1 ; Filesystem functions for the Interaction with BIOS and Disks
3 ; Copyright (C) 2010 Frank Zoll
5 ; This file is part of avrcpm.
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.
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.
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/>.
24 ; ---------------- Defines for the Filesystem Interface -------
27 ;*****************************************************
28 ;* Disk-Manager constants *
29 ;*****************************************************
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
46 .equ SECMSK = hostblk-1 ;sector mask
47 .equ SECSHF = log2(hostblk) ;sector shift
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
62 ;----------------------------------------------- Start of Data Segment
66 ndisks: .byte 1 ;Number of CP/M disks
68 seekdsk: .byte 1 ;seek disk number
69 seektrk: .byte 2 ;seek track number
70 seeksec: .byte 1 ;seek sector number
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
77 erflag: .byte 1 ;error reporting
78 wrtype: .byte 1 ;write operation type
79 dmaadr: .byte 2 ;last dma address
81 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
82 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
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)
89 ; ------------------------------- Start of Code Segment
92 ; ====================================================================
93 ; Function: Get a Pointer to a Partitiontable entry
94 ; ====================================================================
96 ; --------------------------------------------------------------------
97 ; Registers : [w] z Pointer to the Partitionentry
98 ; [r] xl Number of Diskentry to Read
99 ; --------------------------------------------------------------------
101 ; ====================================================================
104 ldi zl,PARTENTRY_SIZE
111 ; ====================================================================
113 ; ====================================================================
115 ; --------------------------------------------------------------------
117 ; Variables : [r] seeksec Sector to read
118 ; [r] seektrk Track to read
119 ; --------------------------------------------------------------------
121 ; ====================================================================
125 brsh dsk_dchrd ;maybe ramdisk
127 ; Check if selected disk # is less then # of disks.
133 ; No disks yet, need to init
135 rcall mgr_init_partitions
149 cpi temp,RAMDISKNR+RAMDISKCNT
153 ldi temp,0xff ;error return
185 ; ====================================================================
186 ; Function: Does a Disk interaction
187 ; ====================================================================
189 ; --------------------------------------------------------------------
191 ; Variables : [r] seeksec Sector to read
192 ; [r] seektrk Track to read
193 ; --------------------------------------------------------------------
195 ; ====================================================================
207 printstring "Disk read: "
211 printstring "Disk write: "
216 printstring ": track "
220 printstring ", sector "
223 printstring ", dma-addr "
231 printstring " wrtype "
237 ;See what has to be done.
247 printstring "DISK I/O: Invalid Function code: "
252 sts ndisks,_0 ;no active partitions
254 cbi flags,hostact ;host buffer inactive
255 sts unacnt,_0 ;clear unalloc count
259 sbis flags,hostwrt ;check for pending write
260 cbi flags,hostact ;clear host active flag
265 ; ====================================================================
266 ; Function: Does a Disk read operation
267 ; ====================================================================
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 ; --------------------------------------------------------------------
276 ; ====================================================================
279 sbi flags,readop ; Set read operation flag
287 rcall dsk_getpartentry ; Get Paritiontableentry
288 ld temp,z ; Get Partitiontype
291 cpi temp,dskType_None
294 ; It must be a FAT16-Imagefile or CP/M Partition.
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
304 ; ====================================================================
305 ; Function: Does a Disk write operation
306 ; ====================================================================
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 ; --------------------------------------------------------------------
315 ; ====================================================================
317 ;write the selected sector
319 cbi flags,readop ; not a read operation
327 rcall dsk_getpartentry ; Get Paritiontableentry
328 ld temp2,z ; Get Partitiontype
331 cpi temp2,dskType_None
336 ; It must be a FAT16-Imagefile or CP/M Partition.
338 cbi flags,readop ;not a read operation
341 sts wrtype,temp ;save write type
343 cpi temp,WRUAL ;write unallocated?
344 brne dsk_chkuna ;check for unalloc
346 ; write to unallocated, set parameters
347 ldi temp,blksize/128 ;next unalloc recs
349 lds temp,seekdsk ;disk to seek
350 sts unadsk,temp ;unadsk = sekdsk
352 sts unatrk,temp ;unatrk = sectrk
354 sts unatrk+1,temp ;unatrk = sectrk
356 sts unasec,temp ;unasec = seksec
359 ;check for write to unallocated sector
360 lds temp,unacnt ;any unalloc remain?
362 breq dsk_alloc ;skip if not
364 ; more unallocated records remain
365 dec temp ;unacnt = unacnt-1
367 lds temp,seekdsk ;same disk?
369 cp temp,temp2 ;seekdsk = unadsk?
370 brne dsk_alloc ;skip if not
377 cp temp,temp3 ;seektrk = unatrk?
379 brne dsk_alloc ;skip if not
381 ; tracks are the same
382 lds temp,seeksec ;same sector?
384 cp temp,temp2 ;seeksec = unasec?
385 brne dsk_alloc ;skip if not
387 ; match, move to next sector for future ref
388 inc temp2 ;unasec = unasec+1
390 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
391 brlo dsk_noovf ;skip if no overflow
393 ; overflow to next track
394 sts unasec,_0 ;unasec = 0
397 subi temp, low(-1) ;unatrk = unatrk+1
403 cbi flags,rsflag ;rsflag = 0
404 rjmp dsk_rwoper ;to perform the write
407 ;not an unallocated record, requires pre-read
408 sts unacnt,_0 ;unacnt = 0
409 sbi flags,rsflag ;rsflag = 1
415 ; ====================================================================
416 ; Function: Does a Disk read/write operation
417 ; ====================================================================
419 ; --------------------------------------------------------------------
421 ; Variables : [r] seekdsk Number of Disk to Read
422 ; [r] seeksec Sector to read
423 ; [r] seektrk Track to read
424 ; --------------------------------------------------------------------
426 ; ====================================================================
428 ;enter here to perform the read/write
430 printstring ", flags: "
434 sts erflag,_0 ;no errors (yet)
436 ;Convert track/sector to an LBA address (in 128byte blocks)
442 lds temp4,seektrk+1 ;
448 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
452 andi temp,SECMSK ;mask buffer number
453 push temp ;save for later
455 ;Convert from CP/M LBA blocks to host LBA blocks
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
470 ; host buffer active, same as seek buffer?
472 lds temp2,hostdsk ;same disk?
473 cp temp,temp2 ;seekdsk = hostdsk?
476 ; same disk, same block?
486 ;proper disk, but not correct sector
487 sbis flags,hostwrt ;host written?
492 rcall dsk_writehost ;clear host buff
498 ;may have to fill the host buffer
505 sbic flags,rsflag ;need to read?
506 rcall dsk_readhost ;yes, if 1
507 cbi flags,hostwrt ;no pending write
511 ;copy data to or from buffer
514 pop temp2 ;get buffer number (which part of hostbuf)
516 add zl,r0 ;offset in hostbuf
522 printstring "; host buf adr: "
530 ldi temp3,128 ;length of move
531 sbic flags,readop ;which way?
532 rjmp dsk_rmove ;skip if read
534 ; mark write operation
535 sbi flags,hostwrt ;hostwrt = 1
551 ; data has been moved to/from host buffer
552 lds temp,wrtype ;write type
553 cpi temp,WRDIR ;to directory?
555 ret ;no further processing
557 ; clear host buffer for directory write
563 rcall dsk_writehost ;clear host buff
564 cbi flags,hostwrt ;buffer written
567 ; ====================================================================
568 ; Function: Does a Disk write operation
569 ; ====================================================================
571 ; --------------------------------------------------------------------
573 ; Variables : [r] seekdsk Number of Disk to Read
574 ; [r] seeksec Sector to read
575 ; [r] seektrk Track to read
576 ; --------------------------------------------------------------------
578 ; ====================================================================
581 rcall dsk_getpartentry
585 ; Is it a FAT16 Diskimage ?
591 ; Is it a CP/M Partition ?
595 ; Disktype not supported -> Return
598 ; ====================================================================
599 ; Function: Does a Disk read operation
600 ; ====================================================================
602 ; --------------------------------------------------------------------
604 ; Variables : [r] seekdsk Number of Disk to Read
605 ; [r] seeksec Sector to read
606 ; [r] seektrk Track to read
607 ; --------------------------------------------------------------------
609 ; ====================================================================
612 rcall dsk_getpartentry
616 ; Is it a FAT16 Diskimage ?
622 ; Is it a CP/M Partition ?
626 ; Disktype not supported -> Return