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/>.
25 ; ---------------- Defines for the Filesystem Interface -------
27 ;*****************************************************
28 ;* Disk-Manager constants *
29 ;*****************************************************
33 ; .equ dskType_RAM = 3
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 ; The following 3 variables are copied from DRAM.
73 ndisks: .byte 1 ;Number of CP/M disks
75 ; The following 5 variables are accessed from 8080/z80 via the
76 ; virtual port interface. Don't change order.
79 bcbadr: .byte 2 ;adr of BiosControlBlock
80 seekdsk: .byte 1 ;seek disk number
81 seektrk: .byte 2 ;seek track number
82 seeksec: .byte 2 ;seek sector number
83 dmaadr: .byte 2 ;last dma address
85 unacnt: .byte 1 ;unalloc rec cnt
86 unadsk: .byte 1 ;last unalloc disk
87 unatrk: .byte 2 ;last unalloc track
88 unasec: .byte 1 ;last unalloc sector
90 erflag: .byte 1 ;error reporting
91 wrtype: .byte 1 ;write operation type
93 hostbuf: .byte hostsize ;host buffer (from/to SD-card)
94 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
96 hostdsk: .byte 1 ;host disk number
97 hosttype: .byte 1 ;host disk type (same entry as 1 parition entry)
98 hostlba: .byte 3 ;host sector number (relative to partition start)
101 ; ------------------------------- Start of Code Segment
104 ;---------------------------------------------------------------------
115 printstring "drvtbl ("
142 lds temp2,biosdrvtbl+1
146 lds temp2,biosdirbuf+1
150 lds temp2,biosenddat+1
156 ; ====================================================================
157 ; Function: Get a Pointer to a Partitiontable entry
158 ; ====================================================================
160 ; --------------------------------------------------------------------
161 ; Registers : [w] z Pointer to the Partitionentry
162 ; [r] xl Number of Diskentry to Read
165 ; --------------------------------------------------------------------
167 ; ====================================================================
170 ldi zl,PARTENTRY_SIZE
177 ; ====================================================================
178 ; Function: Virtual Port Interface
179 ; ====================================================================
181 ; --------------------------------------------------------------------
185 ; --------------------------------------------------------------------
187 ; ====================================================================
196 rcall dsk_param_getadr
198 cpi temp3,bcbadr+1-seektrk
202 cpi temp3,bcbadr+1-biospar_base
207 cpi temp3,seekdsk-biospar_base
209 rcall dsk_param_getadr
224 ; rcall dbg_print_biosd
230 ; ====================================================================
231 ; Function: Check if disk exists
232 ; ====================================================================
234 ; --------------------------------------------------------------------
237 ; return 0, if selected disk not exist.
238 ; return !0, if disk exist
239 ; --------------------------------------------------------------------
241 ; ====================================================================
247 printstring "DiskCheck: "
251 brsh dsk_dchrd ;maybe ramdisk
253 ; Check if selected disk # is less then # of disks.
259 ; No disks yet, need to init
261 rcall mgr_init_partitions ;disk chanched?
278 printstring "Select: "
286 rcall dram_readw_pp ;get drive table entry
288 or temp,temp2 ;if !0, drive is allready initialized
310 ldi temp,0 ;error return
317 cpi temp,RAMDISKNR+RAMDISKCNT
320 ldi temp,0xff ;return ok
324 ldi temp,0 ;error return
328 ; ====================================================================
329 ; Function: Return status of last disk i/o function
330 ; ====================================================================
332 ; --------------------------------------------------------------------
335 ; --------------------------------------------------------------------
337 ; ====================================================================
343 ; -------------------------------------------------------------------
351 ; Test DPBs (avrcpm format)
356 .db 0x03,0x07 ;block shift, bock mask
357 .db 0x00,0xF2 ;extent mask, low(disk size -1),
358 .db 0x00,0x3F ;high(disk size -1), low(dir max)
359 .db 0x00,0xC0 ;high(dir max), alloc0
360 .db 0x00,0x10 ;alloc1, low(chk size)
361 .db 0x00,0x02 ;high(chk size), low(offset)
362 .db 0x00,0x00 ;high(offset), fill
365 .db 0x03,0x07 ;block shift, bock mask
366 .db 0x00,0xF2 ;extent mask, low(disk size -1),
367 .db 0x00,0x3F ;high(disk size -1), low(dir max)
368 .db 0x00,0xC0 ;high(dir max), alloc0
369 .db 0x00,0x10 ;alloc1, low(chk size)
370 .db 0x00,0x02 ;high(chk size), low(offset)
371 .db 0x00,0x00 ;high(offset), fill
374 .db 0x03,0x07 ;block shift, bock mask
375 .db 0x00,0xF2 ;extent mask, low(disk size -1),
376 .db 0x00,0x3F ;high(disk size -1), low(dir max)
377 .db 0x00,0xC0 ;high(dir max), alloc0
378 .db 0x00,0x10 ;alloc1, low(chk size)
379 .db 0x00,0x02 ;high(chk size), low(offset)
380 .db 0x00,0x00 ;high(offset), fill
383 .db 0x03,0x07 ;block shift, bock mask
384 .db 0x00,0xF2 ;extent mask, low(disk size -1),
385 .db 0x00,0x3F ;high(disk size -1), low(dir max)
386 .db 0x00,0xC0 ;high(dir max), alloc0
387 .db 0x00,0x10 ;alloc1, low(chk size)
388 .db 0x00,0x02 ;high(chk size), low(offset)
389 .db 0x00,0x00 ;high(offset), fill
393 .db 0x04,0x0F ;block shift, bock mask
394 .db 0x00,0xFB ;extent mask, low(disk size -1),
395 .db 0x01,0xBF ;high(disk size -1), low(dir max)
396 .db 0x00,0xE0 ;high(dir max), alloc0
397 .db 0x00,0x30 ;alloc1, low(chk size)
398 .db 0x00,0x02 ;high(chk size), low(offset)
399 .db 0x00,0x00 ;high(offset), fill
402 .db 0x05,0x1F ;block shift, bock mask
403 .db 0x01,0xFD ;extent mask, low(disk size -1),
404 .db 0x07,0xFF ;high(disk size -1), low(dir max)
405 .db 0x01,0xF0 ;high(dir max), alloc0
406 .db 0x00,0x80 ;alloc1, low(chk size)
407 .db 0x00,0x02 ;high(chk size), low(offset)
408 .db 0x00,0x00 ;high(offset), fill
426 cpi yl,low(tmpdpb + 15)
435 ; for now, only entries 1 - 3 are cleared.
437 ; ====================================================================
438 ; Function: Clear drive table
439 ; ====================================================================
441 ; --------------------------------------------------------------------
445 ; --------------------------------------------------------------------
447 ; ====================================================================
449 ; For now, only entries 1 - 3 are cleared.
463 lds temp2,biosenddat+1
469 ; ----------------------------------------------------------------------
470 ; Init CP/M data structures
478 mov temp3,temp ;save disk #
488 ; -----------------------------------------------------------------
489 ; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
490 ; -----------------------------------------------------------------
491 ;(offset) 0 2 4 6 8 10 12 14
503 rcall dram_writew_pp ;XLT
506 lds temp2,biosdirbuf+1
507 rcall dram_writew_pp ;DIRBUF
510 ; -------------------------------------------------------------
511 ; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
512 ; -------------------------------------------------------------
525 cpi zl,low(tmpdpb + 15)
531 rcall dram_writew_pp ;DPB
533 ; get mem for dir check vector
535 lds temp,tmpdpb+11 ;cks
536 lds temp2,tmpdpb+11+1
543 rcall dram_writew_pp ;CSV
545 ; get mem for alloc vector
547 lds temp,tmpdpb+5 ;dsm
556 ror temp ;(dsm+1+7)/8
559 rcall dram_writew_pp ;ALV
561 ; success, insert DPH into drvtbl
570 ori temp,0xff ;return ok
579 eor temp,temp ;return 0 (+ Z-flag)
583 ; ====================================================================
584 ; Function: Does a Disk interaction
585 ; ====================================================================
587 ; --------------------------------------------------------------------
589 ; Variables : [r] seeksec Sector to read
590 ; [r] seektrk Track to read
591 ; --------------------------------------------------------------------
593 ; ====================================================================
605 printstring "Disk read: "
609 printstring "Disk write: "
614 printstring ": track "
618 printstring ", sector "
621 printstring ", dma-addr "
629 printstring " wrtype "
635 ;See what has to be done.
645 printstring "DISK I/O: Invalid Function code: "
650 sts ndisks,_0 ;no active partitions
652 cbi flags,hostact ;host buffer inactive
653 sts unacnt,_0 ;clear unalloc count
657 sbis flags,hostwrt ;check for pending write
658 cbi flags,hostact ;clear host active flag
663 ; ====================================================================
664 ; Function: Does a Disk read operation
665 ; ====================================================================
667 ; --------------------------------------------------------------------
668 ; Registers : in: temp
669 ; Variables : [r] seekdsk Number of Disk to Read
670 ; [r] seeksec Sector to read
671 ; [r] seektrk Track to read
672 ; --------------------------------------------------------------------
674 ; ====================================================================
677 sbi flags,readop ; Set read operation flag
686 rcall dsk_getpartentry ; Get Paritiontableentry
687 ld temp,z ; Get Partitiontype
690 cpi temp,dskType_None
694 ; It must be a FAT16-Imagefile or CP/M Partition.
696 sbi flags,rsflag ;must read data
697 ldi temp,WRUAL ;write type
698 sts wrtype,temp ;treat as unalloc
699 rjmp dsk_rwoper ;to perform the read
704 ; ====================================================================
705 ; Function: Does a Disk write operation
706 ; ====================================================================
708 ; --------------------------------------------------------------------
709 ; Registers : in: temp Write type
710 ; Variables : [r] seekdsk Number of Disk to Read
711 ; [r] seeksec Sector to read
712 ; [r] seektrk Track to read
713 ; --------------------------------------------------------------------
715 ; ====================================================================
717 ;write the selected sector
719 cbi flags,readop ; not a read operation
727 rcall dsk_getpartentry ; Get Paritiontableentry
728 ld temp2,z ; Get Partitiontype
731 cpi temp2,dskType_None
736 ; It must be a FAT16-Imagefile or CP/M Partition.
738 cbi flags,readop ;not a read operation
741 sts wrtype,temp ;save write type
743 cpi temp,WRUAL ;write unallocated?
744 brne dsk_chkuna ;check for unalloc
746 ; write to unallocated, set parameters
747 ldi temp,blksize/128 ;next unalloc recs
749 lds temp,seekdsk ;disk to seek
750 sts unadsk,temp ;unadsk = sekdsk
752 sts unatrk,temp ;unatrk = sectrk
754 sts unatrk+1,temp ;unatrk = sectrk
756 sts unasec,temp ;unasec = seksec
759 ;check for write to unallocated sector
760 lds temp,unacnt ;any unalloc remain?
762 breq dsk_alloc ;skip if not
764 ; more unallocated records remain
765 dec temp ;unacnt = unacnt-1
767 lds temp,seekdsk ;same disk?
769 cp temp,temp2 ;seekdsk = unadsk?
770 brne dsk_alloc ;skip if not
777 cp temp,temp3 ;seektrk = unatrk?
779 brne dsk_alloc ;skip if not
781 ; tracks are the same
782 lds temp,seeksec ;same sector?
784 cp temp,temp2 ;seeksec = unasec?
785 brne dsk_alloc ;skip if not
787 ; match, move to next sector for future ref
788 inc temp2 ;unasec = unasec+1
790 cpi temp2,CPMSPT ;end of track? (count CP/M sectors)
791 brlo dsk_noovf ;skip if no overflow
793 ; overflow to next track
794 sts unasec,_0 ;unasec = 0
797 subi temp, low(-1) ;unatrk = unatrk+1
803 cbi flags,rsflag ;rsflag = 0
804 rjmp dsk_rwoper ;to perform the write
807 ;not an unallocated record, requires pre-read
808 sts unacnt,_0 ;unacnt = 0
809 sbi flags,rsflag ;rsflag = 1
815 ; ====================================================================
816 ; Function: Does a Disk read/write operation
817 ; ====================================================================
819 ; --------------------------------------------------------------------
821 ; Variables : [r] seekdsk Number of Disk to Read
822 ; [r] seeksec Sector to read
823 ; [r] seektrk Track to read
824 ; --------------------------------------------------------------------
826 ; ====================================================================
828 ;enter here to perform the read/write
830 printstring ", flags: "
834 sts erflag,_0 ;no errors (yet)
836 ;Convert track/sector to an LBA address (in 128byte blocks)
842 lds temp4,seektrk+1 ;
848 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
852 andi temp,SECMSK ;mask buffer number
853 push temp ;save for later
855 ;Convert from CP/M LBA blocks to host LBA blocks
863 ;yl:xh:xl = host block to seek
864 ; active host sector?
865 in _tmp0,flags ;host active flag
866 sbi flags,hostact ;always becomes 1
867 sbrs _tmp0,hostact ;was it already?
868 rjmp dsk_filhst ;fill host if not
870 ; host buffer active, same as seek buffer?
872 lds temp2,hostdsk ;same disk?
873 cp temp,temp2 ;seekdsk = hostdsk?
876 ; same disk, same block?
886 ;proper disk, but not correct sector
887 sbis flags,hostwrt ;host written?
892 rcall dsk_writehost ;clear host buff
898 ;may have to fill the host buffer
905 sbic flags,rsflag ;need to read?
906 rcall dsk_readhost ;yes, if 1
907 cbi flags,hostwrt ;no pending write
911 ;copy data to or from buffer
914 pop temp2 ;get buffer number (which part of hostbuf)
916 add zl,r0 ;offset in hostbuf
922 printstring "; host buf adr: "
930 ldi temp3,128 ;length of move
931 sbic flags,readop ;which way?
932 rjmp dsk_rmove ;skip if read
934 ; mark write operation
935 sbi flags,hostwrt ;hostwrt = 1
951 ; data has been moved to/from host buffer
952 lds temp,wrtype ;write type
953 cpi temp,WRDIR ;to directory?
955 ret ;no further processing
957 ; clear host buffer for directory write
963 rcall dsk_writehost ;clear host buff
964 cbi flags,hostwrt ;buffer written
967 ; ====================================================================
968 ; Function: Does a Disk write operation
969 ; ====================================================================
971 ; --------------------------------------------------------------------
973 ; Variables : [r] seekdsk Number of Disk to Read
974 ; [r] seeksec Sector to read
975 ; [r] seektrk Track to read
976 ; --------------------------------------------------------------------
978 ; ====================================================================
981 rcall dsk_getpartentry
985 ; Is it a FAT16 Diskimage ?
991 ; Is it a CP/M Partition ?
995 ; Disktype not supported -> Return
998 ; ====================================================================
999 ; Function: Does a Disk read operation
1000 ; ====================================================================
1002 ; --------------------------------------------------------------------
1004 ; Variables : [r] seekdsk Number of Disk to Read
1005 ; [r] seeksec Sector to read
1006 ; [r] seektrk Track to read
1007 ; --------------------------------------------------------------------
1009 ; ====================================================================
1012 rcall dsk_getpartentry
1016 ; Is it a FAT16 Diskimage ?
1017 cpi temp,dskType_FAT
1022 ; Is it a CP/M Partition ?
1023 cpi temp,dskType_CPM
1026 ; Disktype not supported -> Return