]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/dsk_fsys.asm
6645bf989eb5f7d71762a457cfc5fae38b139fa6
[avrcpm.git] / avrcpm / avr / dsk_fsys.asm
1 ; Filesystem functions for the Interaction with BIOS and Disks
2 ;
3 ; Copyright (C) 2010 Frank Zoll
4 ;
5 ; This file is part of avrcpm.
6 ;
7 ; avrcpm is free software: you can redistribute it and/or modify it
8 ; under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
11 ;
12 ; avrcpm is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
16 ;
17 ; You should have received a copy of the GNU General Public License
18 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
19 ;
20 ; $Id$
21 ;
22
23
24 ; ---------------- Defines for the Filesystem Interface -------
25
26
27 ;*****************************************************
28 ;* Disk-Manager constants *
29 ;*****************************************************
30 .equ dskType_None = 0
31 .equ dskType_CPM = 1
32 .equ dskType_FAT = 2
33 .equ dskType_RAM = 3
34
35 ;*****************************************************
36 ;* CP/M to host disk constants *
37 ;*****************************************************
38 .equ MAXDISKS = 6 ;Max number of Disks (partitions)
39 .equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
40 .equ blksize = 1024 ;CP/M allocation size
41 .equ hostsize = 512 ;host disk sector size
42 ; .equ hostspt = 20 ;host disk sectors/trk
43 .equ hostblk = hostsize/128 ;CP/M sects/host buff
44 ; .equ CPMSPT = hostblk*hostspt ;CP/M sectors/track
45 .equ CPMSPT = 26 ;
46 .equ SECMSK = hostblk-1 ;sector mask
47 .equ SECSHF = log2(hostblk) ;sector shift
48
49 ;*****************************************************
50 ;* BDOS constants on entry to write *
51 ;*****************************************************
52 .equ WRALL = 0 ;write to allocated
53 .equ WRDIR = 1 ;write to directory
54 .equ WRUAL = 2 ;write to unallocated
55 .equ WRTMSK= 3 ;write type mask
56
57 .equ READ_FUNC = 7
58 .equ WRITE_FUNC = 6
59 .equ BOOT_FUNC = 5
60 .equ HOME_FUNC = 4
61
62 ;----------------------------------------------- Start of Data Segment
63
64 .dseg
65
66 ndisks: .byte 1 ;Number of CP/M disks
67
68 seekdsk: .byte 1 ;seek disk number
69 seektrk: .byte 2 ;seek track number
70 seeksec: .byte 1 ;seek sector number
71
72 unacnt: .byte 1 ;unalloc rec cnt
73 unadsk: .byte 1 ;last unalloc disk
74 unatrk: .byte 2 ;last unalloc track
75 unasec: .byte 1 ;last unalloc sector
76
77 erflag: .byte 1 ;error reporting
78 wrtype: .byte 1 ;write operation type
79 dmaadr: .byte 2 ;last dma address
80
81 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
82 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
83 hostparttbltop:
84 hostdsk: .byte 1 ;host disk number
85 hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
86 hostlba: .byte 3 ;host sector number (relative to partition start)
87
88
89 ; ------------------------------- Start of Code Segment
90 .cseg
91
92 ; ====================================================================
93 ; Function: Get a Pointer to a Partitiontable entry
94 ; ====================================================================
95 ; Parameters
96 ; --------------------------------------------------------------------
97 ; Registers : [w] z Pointer to the Partitionentry
98 ; [r] xl Number of Diskentry to Read
99 ; --------------------------------------------------------------------
100 ; Description:
101 ; ====================================================================
102 dsk_getpartentry:
103
104 ldi zl,PARTENTRY_SIZE
105 mul xl,zl
106 ldiw z,hostparttbl
107 add zl,_tmp0
108 add zh,_tmp1
109 ret
110
111 ; ====================================================================
112 ; Function:
113 ; ====================================================================
114 ; Parameters
115 ; --------------------------------------------------------------------
116 ; Registers : none
117 ; Variables : [r] seeksec Sector to read
118 ; [r] seektrk Track to read
119 ; --------------------------------------------------------------------
120 ; Description:
121 ; ====================================================================
122 dskDiskCheck:
123 lds temp2,seekdsk
124 cpi temp2,RAMDISKNR
125 brsh dsk_dchrd ;maybe ramdisk
126
127 ; Check if selected disk # is less then # of disks.
128
129 lds temp,ndisks
130 tst temp
131 brne dsk_dchpart1
132
133 ; No disks yet, need to init
134
135 rcall mgr_init_partitions
136 cbr temp,0x80
137 lds temp2,seekdsk
138
139 dsk_dchpart1:
140 cp temp2,temp
141 brsh dsk_dcher
142
143 dsk_dchend:
144 ldi temp,0
145 ret
146
147 dsk_dchrd:
148 #if RAMDISKCNT
149 cpi temp,RAMDISKNR+RAMDISKCNT
150 brlo dsk_dchend
151 #endif
152 dsk_dcher:
153 ldi temp,0xff ;error return
154 ret
155
156 dskErrorRet:
157 lds temp,erflag
158 ret
159
160 dskDiskSel:
161 sts seekdsk,temp
162 ret
163
164 dskTrackSel_l:
165 sts seektrk,temp
166 sts seektrk+1,_0
167 ret
168
169 dskTrackSel_h:
170 sts seektrk+1,temp
171 ret
172
173 dskSecSel:
174 sts seeksec,temp
175 ret
176
177 dskDmal:
178 sts dmaadr,temp
179 ret
180
181 dskDmah:
182 sts dmaadr+1,temp
183 ret
184
185 ; ====================================================================
186 ; Function: Does a Disk interaction
187 ; ====================================================================
188 ; Parameters
189 ; --------------------------------------------------------------------
190 ; Registers : none
191 ; Variables : [r] seeksec Sector to read
192 ; [r] seektrk Track to read
193 ; --------------------------------------------------------------------
194 ; Description:
195 ; ====================================================================
196 dskDoIt:
197 .if DISK_DEBUG
198 push temp
199 sbrc temp,READ_FUNC
200 rjmp dskdbgr
201 sbrc temp,WRITE_FUNC
202 rjmp dskdbgw
203 rjmp dskdbge
204
205 dskdbgr:
206 printnewline
207 printstring "Disk read: "
208 rjmp dskdbg1
209 dskdbgw:
210 printnewline
211 printstring "Disk write: "
212 dskdbg1:
213 lds temp,seekdsk
214 subi temp,-('A')
215 rcall uartputc
216 printstring ": track "
217 lds temp2,seektrk+1
218 lds temp,seektrk
219 rcall printhexw
220 printstring ", sector "
221 lds temp,seeksec
222 rcall printhex
223 printstring ", dma-addr "
224 lds temp2,dmaadr+1
225 lds temp,dmaadr
226 rcall printhexw
227 pop temp
228 push temp
229 sbrs temp,WRITE_FUNC
230 rjmp dskdbge
231 printstring " wrtype "
232 andi temp,3
233 rcall printhex
234 dskdbge:
235 pop temp
236 .endif
237 ;See what has to be done.
238 sbrc temp,READ_FUNC
239 rjmp dsk_read
240 sbrc temp,WRITE_FUNC
241 rjmp dsk_write
242 sbrc temp,HOME_FUNC
243 rjmp dsk_home
244 sbrc temp,BOOT_FUNC
245 rjmp dsk_boot
246
247 printstring "DISK I/O: Invalid Function code: "
248 rcall printhex
249 rjmp haltinv
250
251 dsk_boot:
252 sts ndisks,_0 ;no active partitions
253 dsk_cboot:
254 cbi flags,hostact ;host buffer inactive
255 sts unacnt,_0 ;clear unalloc count
256 ret
257
258 dsk_home:
259 sbis flags,hostwrt ;check for pending write
260 cbi flags,hostact ;clear host active flag
261 ret
262
263
264
265 ; ====================================================================
266 ; Function: Does a Disk read operation
267 ; ====================================================================
268 ; Parameters
269 ; --------------------------------------------------------------------
270 ; Registers : in: temp
271 ; Variables : [r] seekdsk Number of Disk to Read
272 ; [r] seeksec Sector to read
273 ; [r] seektrk Track to read
274 ; --------------------------------------------------------------------
275 ; Description:
276 ; ====================================================================
277 dsk_read:
278 sts erflag,_0
279 sbi flags,readop ; Set read operation flag
280 ;RAM disk?
281 lds xl,seekdsk
282 #if RAMDISKCNT
283 cpi xl,RAMDISKNR
284 brlt PC+2
285 rjmp rdsk_read
286 #endif
287 rcall dsk_getpartentry ; Get Paritiontableentry
288 ld temp,z ; Get Partitiontype
289
290 ; Isn't it a Disk ?
291 cpi temp,dskType_None
292 brne PC+2
293 rjmp dsk_read_err
294 ; It must be a FAT16-Imagefile or CP/M Partition.
295 sts unacnt,_0
296 sbi flags,rsflag ;must read data
297 ldi temp,WRUAL ;write type
298 sts wrtype,temp ;treat as unalloc
299 rjmp dsk_rwoper ;to perform the read
300
301 dsk_read_err:
302 ret
303
304 ; ====================================================================
305 ; Function: Does a Disk write operation
306 ; ====================================================================
307 ; Parameters
308 ; --------------------------------------------------------------------
309 ; Registers : in: temp Write type
310 ; Variables : [r] seekdsk Number of Disk to Read
311 ; [r] seeksec Sector to read
312 ; [r] seektrk Track to read
313 ; --------------------------------------------------------------------
314 ; Description:
315 ; ====================================================================
316 dsk_write:
317 ;write the selected sector
318 sts erflag,_0
319 cbi flags,readop ; not a read operation
320 ;RAM disk?
321 lds xl,seekdsk
322 #if RAMDISKCNT
323 cpi xl,RAMDISKNR
324 brlt PC+2
325 rjmp rdsk_write
326 #endif
327 rcall dsk_getpartentry ; Get Paritiontableentry
328 ld temp2,z ; Get Partitiontype
329
330 ; Isn't it a Disk ?
331 cpi temp2,dskType_None
332 brne PC+2
333 rjmp dsk_write_err
334
335
336 ; It must be a FAT16-Imagefile or CP/M Partition.
337
338 cbi flags,readop ;not a read operation
339
340 andi temp,WRTMSK
341 sts wrtype,temp ;save write type
342
343 cpi temp,WRUAL ;write unallocated?
344 brne dsk_chkuna ;check for unalloc
345
346 ; write to unallocated, set parameters
347 ldi temp,blksize/128 ;next unalloc recs
348 sts unacnt,temp
349 lds temp,seekdsk ;disk to seek
350 sts unadsk,temp ;unadsk = sekdsk
351 lds temp,seektrk
352 sts unatrk,temp ;unatrk = sectrk
353 lds temp,seektrk+1
354 sts unatrk+1,temp ;unatrk = sectrk
355 lds temp,seeksec
356 sts unasec,temp ;unasec = seksec
357 ;
358 dsk_chkuna:
359 ;check for write to unallocated sector
360 lds temp,unacnt ;any unalloc remain?
361 tst temp
362 breq dsk_alloc ;skip if not
363
364 ; more unallocated records remain
365 dec temp ;unacnt = unacnt-1
366 sts unacnt,temp
367 lds temp,seekdsk ;same disk?
368 lds temp2,unadsk
369 cp temp,temp2 ;seekdsk = unadsk?
370 brne dsk_alloc ;skip if not
371
372 ; disks are the same
373 lds temp,unatrk
374 lds temp2,unatrk+1
375 lds temp3,seektrk
376 lds temp4,seektrk+1
377 cp temp,temp3 ;seektrk = unatrk?
378 cpc temp2,temp4
379 brne dsk_alloc ;skip if not
380
381 ; tracks are the same
382 lds temp,seeksec ;same sector?
383 lds temp2,unasec
384 cp temp,temp2 ;seeksec = unasec?
385 brne dsk_alloc ;skip if not
386
387 ; match, move to next sector for future ref
388 inc temp2 ;unasec = unasec+1
389 sts unasec,temp2
390 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
391 brlo dsk_noovf ;skip if no overflow
392
393 ; overflow to next track
394 sts unasec,_0 ;unasec = 0
395 lds temp,unatrk
396 lds temp2,unatrk+1
397 subi temp, low(-1) ;unatrk = unatrk+1
398 sbci temp2,high(-1)
399 sts unatrk,temp
400 sts unatrk+1,temp2
401 ;
402 dsk_noovf:
403 cbi flags,rsflag ;rsflag = 0
404 rjmp dsk_rwoper ;to perform the write
405 ;
406 dsk_alloc:
407 ;not an unallocated record, requires pre-read
408 sts unacnt,_0 ;unacnt = 0
409 sbi flags,rsflag ;rsflag = 1
410 rjmp dsk_rwoper
411
412 dsk_write_err:
413 ret
414
415 ; ====================================================================
416 ; Function: Does a Disk read/write operation
417 ; ====================================================================
418 ; Parameters
419 ; --------------------------------------------------------------------
420 ; Registers : none
421 ; Variables : [r] seekdsk Number of Disk to Read
422 ; [r] seeksec Sector to read
423 ; [r] seektrk Track to read
424 ; --------------------------------------------------------------------
425 ; Description:
426 ; ====================================================================
427 dsk_rwoper:
428 ;enter here to perform the read/write
429 .if DISK_DEBUG
430 printstring ", flags: "
431 in temp,flags
432 rcall printhex
433 .endif
434 sts erflag,_0 ;no errors (yet)
435
436 ;Convert track/sector to an LBA address (in 128byte blocks)
437
438 lds xl,seeksec ;
439 ldi xh,0 ;
440 ldi yl,0 ;
441 lds temp3,seektrk ;
442 lds temp4,seektrk+1 ;
443 ldi temp,CPMSPT ;
444 mul temp3,temp ;
445 add xl,r0 ;
446 adc xh,r1 ;
447 mul temp4,temp ;
448 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
449 adc yl,r1 ;
450
451 mov temp,xl
452 andi temp,SECMSK ;mask buffer number
453 push temp ;save for later
454
455 ;Convert from CP/M LBA blocks to host LBA blocks
456 ldi temp,SECSHF
457 dsk_sh1:
458 lsr yl
459 ror xh
460 ror xl
461 dec temp
462 brne dsk_sh1
463 ;yl:xh:xl = host block to seek
464 ; active host sector?
465 in _tmp0,flags ;host active flag
466 sbi flags,hostact ;always becomes 1
467 sbrs _tmp0,hostact ;was it already?
468 rjmp dsk_filhst ;fill host if not
469
470 ; host buffer active, same as seek buffer?
471 lds temp,seekdsk
472 lds temp2,hostdsk ;same disk?
473 cp temp,temp2 ;seekdsk = hostdsk?
474 brne dsk_nomatch
475
476 ; same disk, same block?
477 lds temp,hostlba
478 lds temp2,hostlba+1
479 lds temp3,hostlba+2
480 cp xl,temp
481 cpc xh,temp2
482 cpc yl,temp3
483 breq dsk_match
484 ;
485 dsk_nomatch:
486 ;proper disk, but not correct sector
487 sbis flags,hostwrt ;host written?
488 rjmp dsk_filhst
489 push xl
490 push xh
491 push yl
492 rcall dsk_writehost ;clear host buff
493 pop yl
494 pop xh
495 pop xl
496
497 dsk_filhst:
498 ;may have to fill the host buffer
499 lds temp,seekdsk
500 sts hostdsk,temp
501 sts hostlba,xl
502 sts hostlba+1,xh
503 sts hostlba+2,yl
504
505 sbic flags,rsflag ;need to read?
506 rcall dsk_readhost ;yes, if 1
507 cbi flags,hostwrt ;no pending write
508
509 dsk_match:
510
511 ;copy data to or from buffer
512 ldiw z,hostbuf
513 ldi temp,128
514 pop temp2 ;get buffer number (which part of hostbuf)
515 mul temp2,temp
516 add zl,r0 ;offset in hostbuf
517 adc zh,r1
518
519 .if DISK_DEBUG > 2
520 push r0
521 push r1
522 printstring "; host buf adr: "
523 pop temp2
524 pop temp
525 rcall printhexw
526 .endif
527
528 lds xl,dmaadr
529 lds xh,dmaadr+1
530 ldi temp3,128 ;length of move
531 sbic flags,readop ;which way?
532 rjmp dsk_rmove ;skip if read
533
534 ; mark write operation
535 sbi flags,hostwrt ;hostwrt = 1
536 dsk_wmove:
537 mem_read
538 st z+,temp
539 adiw xl,1
540 dec temp3
541 brne dsk_wmove
542 rjmp dsk_rwmfin
543
544 dsk_rmove:
545 ld temp,z+
546 mem_write
547 adiw xl,1
548 dec temp3
549 brne dsk_rmove
550 dsk_rwmfin:
551 ; data has been moved to/from host buffer
552 lds temp,wrtype ;write type
553 cpi temp,WRDIR ;to directory?
554 breq dsk_wdir
555 ret ;no further processing
556 dsk_wdir:
557 ; clear host buffer for directory write
558 lds temp,erflag
559 tst temp ;errors?
560 breq dsk_wdir1
561 ret ;skip if so
562 dsk_wdir1:
563 rcall dsk_writehost ;clear host buff
564 cbi flags,hostwrt ;buffer written
565 ret
566
567 ; ====================================================================
568 ; Function: Does a Disk write operation
569 ; ====================================================================
570 ; Parameters
571 ; --------------------------------------------------------------------
572 ; Registers : none
573 ; Variables : [r] seekdsk Number of Disk to Read
574 ; [r] seeksec Sector to read
575 ; [r] seektrk Track to read
576 ; --------------------------------------------------------------------
577 ; Description:
578 ; ====================================================================
579 dsk_writehost:
580 lds xl,hostdsk
581 rcall dsk_getpartentry
582 ld temp,z
583
584 #if FAT16_SUPPORT
585 ; Is it a FAT16 Diskimage ?
586 cpi temp,dskType_FAT
587 brne PC+2
588 rjmp fat_writehost
589 #endif
590
591 ; Is it a CP/M Partition ?
592 cpi temp,dskType_CPM
593 brne PC+2
594 rjmp cpm_writehost
595 ; Disktype not supported -> Return
596 ret
597
598 ; ====================================================================
599 ; Function: Does a Disk read operation
600 ; ====================================================================
601 ; Parameters
602 ; --------------------------------------------------------------------
603 ; Registers : none
604 ; Variables : [r] seekdsk Number of Disk to Read
605 ; [r] seeksec Sector to read
606 ; [r] seektrk Track to read
607 ; --------------------------------------------------------------------
608 ; Description:
609 ; ====================================================================
610 dsk_readhost:
611 lds xl,hostdsk
612 rcall dsk_getpartentry
613 ld temp,z
614
615 #if FAT16_SUPPORT
616 ; Is it a FAT16 Diskimage ?
617 cpi temp,dskType_FAT
618 brne PC+2
619 rjmp fat_readhost
620 #endif
621
622 ; Is it a CP/M Partition ?
623 cpi temp,dskType_CPM
624 brne PC+2
625 rjmp cpm_readhost
626 ; Disktype not supported -> Return
627 ret
628