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 ;*****************************************************
31 ; Fields in the parttabl
33 .equ MAXDISKS = 8 ;Max number of Disks (partitions)
34 .equ PARTENTRY_SIZE = 9 ;Size of a Partitiontableentry
42 .equ dskType_None = 0 << 4
43 .equ dskType_CPM = 1 << 4
44 .equ dskType_FAT = 2 << 4
45 ; .equ dskType_RAM = 3 << 4
46 .equ dskType_MASK = 0xf << 4
48 ;*****************************************************
49 ;* CP/M to host disk constants *
50 ;*****************************************************
51 ; .equ blksize = 1024 ;CP/M allocation size
54 .equ HOSTSIZE = 512 ;host disk sector size
55 .equ HOSTBLK = HOSTSIZE/128 ;CP/M sects/host buff
56 .equ SECMSK = HOSTBLK-1 ;sector mask
57 .equ SECSHF = log2(HOSTBLK) ;sector shift
59 ;*****************************************************
60 ;* BDOS constants on entry to write *
61 ;*****************************************************
62 .equ WRALL = 0 ;write to allocated
63 .equ WRDIR = 1 ;write to directory
64 .equ WRUAL = 2 ;write to unallocated
65 .equ WRTMSK= 3 ;write type mask
72 ;----------------------------------------------- Start of Data Segment
76 ; The following 3 variables are copied from DRAM.
83 ndisks: .byte 1 ;Number of CP/M disks
85 ; The following 5 variables are accessed from 8080/z80 via the
86 ; virtual port interface. Don't change order.
89 bcbadr: .byte 2 ;adr of BiosControlBlock
90 seekdsk: .byte 1 ;seek disk number
91 seektrk: .byte 2 ;seek track number
92 seeksec: .byte 2 ;seek sector number
93 dmaadr: .byte 2 ;last dma address
95 hdrsize: .byte 1 ;Image header size (offset)
96 cpmspt: .byte 1 ;CP/M sectors per track
97 secpblk: .byte 1 ;sectors per block (alloc size)
98 unacnt: .byte 1 ;unalloc rec cnt
99 unadsk: .byte 1 ;last unalloc disk
100 unatrk: .byte 2 ;last unalloc track
101 unasec: .byte 2 ;last unalloc sector
103 erflag: .byte 1 ;error reporting
104 wrtype: .byte 1 ;write operation type
106 hostdsk: .byte 1 ;host disk number
107 hostlba: .byte 2 ;host sector number (relative to partition start)
108 hostparttbl: .byte PARTENTRY_SIZE*MAXDISKS ;host partition table (type, start sector, sector count)
110 hostbuf: .byte HOSTSIZE ;host buffer (from/to SD-card)
113 ; ------------------------------- Start of Code Segment
116 ;---------------------------------------------------------------------
127 printstring "drvtbl ("
154 lds temp2,biosdrvtbl+1
158 lds temp2,biosdirbuf+1
162 lds temp2,biosenddat+1
168 ; ====================================================================
169 ; ====================================================================
170 ; Function: Get a Pointer to a Partitiontable entry
171 ; ====================================================================
173 ; --------------------------------------------------------------------
174 ; Registers : [w] z Pointer to the Partitionentry
175 ; [r] zl Number of Diskentry to Read
178 ; --------------------------------------------------------------------
180 ; ====================================================================
183 ldi zh,PARTENTRY_SIZE
190 ; ====================================================================
191 ; ====================================================================
192 ; Function: Virtual Port Interface
193 ; ====================================================================
195 ; --------------------------------------------------------------------
199 ; --------------------------------------------------------------------
201 ; ====================================================================
210 rcall dsk_param_getadr
212 cpi temp3,bcbadr+1-biospar_base
217 cpi temp3,seekdsk-biospar_base
219 rcall dsk_param_getadr
234 ; rcall dbg_print_biosd
235 rcall dpb_drvtblclear
240 ; ====================================================================
241 ; Function: Check if disk exists
242 ; ====================================================================
244 ; --------------------------------------------------------------------
247 ; return 0, if selected disk not exist.
248 ; return !0, if disk exist
249 ; --------------------------------------------------------------------
251 ; ====================================================================
257 printstring "DiskCheck: "
261 brsh dsk_dchrd ;maybe ramdisk
266 ; No disks yet, need to init
268 rcall dpb_drvtblclear
274 rcall mgr_init_partitions ;disk chanched?
283 lcall mgr_prnt_parttbl
293 ; Check if selected disk # is less then # of disks.
301 printstring "Select: "
304 rcall dpb_drvtbl_entry_get
305 or temp,temp2 ;if !0, drive is allready initialized
309 rcall dpb_biosdph_get
315 rcall dpb_drvtbl_entry_get
325 ldi temp,0 ;error return
332 cpi temp,RAMDISKNR+RAMDISKCNT
335 ldi temp,0xff ;return ok
339 ldi temp,0 ;error return
343 ; ====================================================================
344 ; Function: Return status of last disk i/o function
345 ; ====================================================================
347 ; --------------------------------------------------------------------
350 ; --------------------------------------------------------------------
352 ; ====================================================================
358 ; ====================================================================
359 ; ====================================================================
367 ; DPBs for varios fixed formats
368 ; dpb data starts at 2. byte
370 dpbdat_avrcpm: ;(dpb243)
371 .db 0x00,0x1A ;sector offset, low(spt)
372 .db 0x00,0x03 ;high (spt), block shift
373 .db 0x07,0x00 ;bock mask, extent mask
374 .db 0xF2,0x00 ;disk size - 1,
375 .db 0x3F,0x00 ;dir max
376 .db 0xC0,0x00 ;alloc0, alloc1
377 .db 0x10,0x00 ;chk size
378 .db 0x02,0x00 ;offset
381 .db 0x02,0x80 ;sector offset, low(spt)
382 .db 0x00,0x05 ;high (spt), block shift
383 .db 0x1F,0x01 ;bock mask, extent mask
384 .db 0xFF,0x07 ;disk size - 1,
385 .db 0xFF,0x03 ;dir max
386 .db 0xFF,0x00 ;alloc0, alloc1
387 .db 0x00,0x01 ;chk size
388 .db 0x00,0x00 ;offset
391 .db 0x00,0x20 ;sector offset, low(spt)
392 .db 0x00,0x05 ;high (spt), block shift
393 .db 0x1F,0x01 ;bock mask, extent mask
394 .db 0xF9,0x07 ;disk size - 1,
395 .db 0xFF,0x03 ;dir max
396 .db 0xFF,0x00 ;alloc0, alloc1
397 .db 0x00,0x01 ;chk size
398 .db 0x06,0x00 ;offset
403 .db 0x04,0x0F ;block shift, bock mask
404 .db 0x00,0xFB ;extent mask, low(disk size -1),
405 .db 0x01,0xBF ;high(disk size -1), low(dir max)
406 .db 0x00,0xE0 ;high(dir max), alloc0
407 .db 0x00,0x30 ;alloc1, low(chk size)
408 .db 0x00,0x02 ;high(chk size), low(offset)
409 .db 0x00,0x00 ;high(offset), fill
412 .db 0x05,0x1F ;block shift, bock mask
413 .db 0x01,0xFD ;extent mask, low(disk size -1),
414 .db 0x07,0xFF ;high(disk size -1), low(dir max)
415 .db 0x01,0xF0 ;high(dir max), alloc0
416 .db 0x00,0x80 ;alloc1, low(chk size)
417 .db 0x00,0x02 ;high(chk size), low(offset)
418 .db 0x00,0x00 ;high(offset), fill
422 ; Copy the dpb data from flash memory, pointed to by Z, to temp ram.
438 ; Copy the dpb data, pointed to by Z to temp ram.
451 ; String compare (z, y), one z-string in flash.
467 ; String compare (x, y, temp2). Max temp2 bytes are compared.
483 ; ====================================================================
484 ; Function: get drive table entry pointer for drive # in temp
485 ; ====================================================================
487 ; --------------------------------------------------------------------
491 ; --------------------------------------------------------------------
493 ; ====================================================================
504 ; ====================================================================
505 ; Function: get drive table entry for drive # in temp
506 ; ====================================================================
508 ; --------------------------------------------------------------------
512 ; --------------------------------------------------------------------
514 ; ====================================================================
516 dpb_drvtbl_entry_get:
518 rcall dpb_drvtbl_entry_p
522 ; ====================================================================
523 ; Function: Clear drive table (entries 0 to 7)
524 ; ====================================================================
526 ; --------------------------------------------------------------------
530 ; --------------------------------------------------------------------
532 ; ====================================================================
551 lds temp2,biosenddat+1
561 ; ====================================================================
562 ; Function: Test disk format: avrcpmhd
563 ; ====================================================================
565 ; --------------------------------------------------------------------
566 ; Registers : temp drive #
568 ; --------------------------------------------------------------------
569 ; Description: Not implemented yet.
570 ; ====================================================================
573 clr temp ; Test, return 'not found' for now.
577 ; ====================================================================
578 ; Function: Test disk format: YAZE
579 ; ====================================================================
581 ; --------------------------------------------------------------------
582 ; Registers : temp drive #
584 ; --------------------------------------------------------------------
585 ; Description: From the YAZE Doc:
587 ; The new disk header occupies the first 128 BYTES of the file and has the
591 ; 10 - 15 a null-terminated ascii comment (may be empty)
592 ; new 16 version (0 = yaze-1.06/1.10, 1 = yaze-ag-2.xx)
593 ; 17 - 31 a null-terminated ascii comment (may be empty)
594 ; 32 - 33 sectors per track
595 ; 34 block shift factor
598 ; 37 - 38 disk size max
599 ; 39 - 40 directory max
602 ; 43 - 44 check size (always zero)
603 ; 45 - 46 track offset
604 ; new 47 psh (used if version=1 and CP/M 3.1 is running)
605 ; new 48 phm ( " " " " " " " " " )
606 ; 49 - 127 unused (zeros)
607 ; ====================================================================
611 .db 10,"<CPM_Disk>",0
618 lpm temp2,z+ ; get length
624 ldi temp,1 ;1 sector header size
631 clr temp ;Not a YAZE disk image.
634 ; ====================================================================
635 ; Function: Test disk format: MyZ80
636 ; ====================================================================
638 ; --------------------------------------------------------------------
639 ; Registers : temp drive #
641 ; --------------------------------------------------------------------
642 ; Description: Test, if first 2 Sectors are filled with 0xE5,
643 ; and Size = 8192KB + 256Bytes.
644 ; ====================================================================
648 rcall dsk_getpartentry ;get partition entry
650 ldd temp2,z+PTAB_SIZE+1 ;check, if size is 16385 phys. sectors
654 brne dsk_tmyz80_not ;wrong size
670 clr temp ;Not a MyZ80 hard disk image.
673 ; ====================================================================
674 ; Function: Test disk format: simhd, simh altair 8800 hard disk format
675 ; ====================================================================
677 ; --------------------------------------------------------------------
678 ; Registers : temp drive #
680 ; --------------------------------------------------------------------
681 ; Description: Test, if first 6 tracks are filled with 0xE5,
682 ; and Size = 8192 KB.
683 ; Actually, only the first phys. sector is tested, since
684 ; the other 47 sectors are not in memory at this time.
685 ; ====================================================================
689 rcall dsk_getpartentry ;get partition entry
691 ldd temp2,z+PTAB_SIZE+1 ;check, if size is 16384 phys. sectors
695 brne dsk_tsimhd_not ;wrong size
714 clr temp ;Not a simhd hard disk image.
717 ; ====================================================================
719 ; ====================================================================
721 ; --------------------------------------------------------------------
722 ; Registers : temp3 drive #
724 ; --------------------------------------------------------------------
726 ; ====================================================================
730 ; Get first sector (512 byte) of current drive into hostbuf.
735 rcall dsk_readhost_lba
737 ; Test for variable format avrcpmhd.
739 rcall dsk_tst_avrcpmhd
742 ; Test for YAZE formats.
747 ; Test for simhd format.
750 ldiw z,dpbdat_simhd*2
753 ; Test for MyZ80 format.
756 ldiw z,dpbdat_myz80*2
759 ; No special image found. Use avrcpm.
761 ldiw z,dpbdat_avrcpm*2
770 ; ====================================================================
771 ; Function: Add CP/M image format data to partition table data
772 ; ====================================================================
774 ; --------------------------------------------------------------------
775 ; Registers : temp3 drive #
777 ; --------------------------------------------------------------------
779 ; ====================================================================
783 ; Test for known CP/M formats
786 breq dpb_imgd_err ;no known format detected
790 rcall dsk_getpartentry ;get partition entry
793 ; std y+12,_0 ;Test: set check size to 0
797 andi temp,~dskType_MASK
798 ldd temp2,z+PTAB_TYPE
799 andi temp2,dskType_MASK
805 tst temp ;more then 256 sectors per track?
806 brne dsk_imgprp_err ;todo: support 16 bit sector numbers
820 printstring ": Format not supported: Too much sectors per track! "
827 ; ====================================================================
829 ; ====================================================================
831 ; --------------------------------------------------------------------
832 ; Registers : temp drive #
836 ; --------------------------------------------------------------------
837 ; Description: Init CP/M data structures
839 ; -----------------------------------------------------------------
840 ; DPH: | XLT | | | |DIRBUF | DPB | CSV | ALV |
841 ; -----------------------------------------------------------------
842 ;offset: 0 2 4 6 8 10 12 14
844 ; -------------------------------------------------------------
845 ; DPB: | SPT |BSH|BLM|EXM| DSM | DRM |AL0|AL1| CKS | OFF |
846 ; -------------------------------------------------------------
848 ; ====================================================================
851 mov temp3,temp ;save disk #
863 rcall heap_get ;returns ptr to dph mem
868 movw y,temp ;save dph pointer
871 rcall dram_writew_pp ;XLT
874 lds temp2,biosdirbuf+1
875 rcall dram_writew_pp ;DIRBUF
885 ldiw z,tmpdpb+1 ;skip sector offset byte
889 cpi zl,low(tmpdpb + 16)
895 rcall dram_writew_pp ;DPB
897 ; get mem for dir check vector
899 lds temp,tmpdpb+12 ;cks
900 lds temp2,tmpdpb+12+1
907 rcall dram_writew_pp ;CSV
909 ; get mem for alloc vector
911 lds temp,tmpdpb+6 ;dsm
920 ror temp ;(dsm+1+7)/8
923 rcall dram_writew_pp ;ALV
925 ; success, insert DPH into drvtbl
928 rcall dpb_drvtbl_entry_p
932 ori temp,0xff ;return ok
941 eor temp,temp ;return 0 (+ Z-flag)
944 ; ====================================================================
946 ; ====================================================================
948 ; --------------------------------------------------------------------
951 ; --------------------------------------------------------------------
953 ; ====================================================================
955 ldd temp2,z+PTAB_TYPE
956 andi temp2,~dskType_MASK ;Lower nibble is image header size
973 ; ====================================================================
974 ; Function: Does a Disk interaction
975 ; ====================================================================
977 ; --------------------------------------------------------------------
979 ; Variables : [r] seeksec Sector to read
980 ; [r] seektrk Track to read
981 ; --------------------------------------------------------------------
983 ; ====================================================================
995 printstring "Disk read: "
999 printstring "Disk write: "
1004 printstring ": track "
1008 printstring ", sector "
1011 printstring ", dma-addr "
1017 sbrs temp,WRITE_FUNC
1019 printstring " wrtype "
1025 ;See what has to be done.
1028 sbrc temp,WRITE_FUNC
1035 printstring "DISK I/O: Invalid Function code: "
1040 sts ndisks,_0 ;no active partitions
1042 cbi flags,hostact ;host buffer inactive
1043 sts unacnt,_0 ;clear unalloc count
1047 sbis flags,hostwrt ;check for pending write
1048 cbi flags,hostact ;clear host active flag
1053 ; ====================================================================
1054 ; Function: Does a Disk read operation
1055 ; ====================================================================
1057 ; --------------------------------------------------------------------
1058 ; Registers : in: temp
1059 ; Variables : [r] seekdsk Number of Disk to Read
1060 ; [r] seeksec Sector to read
1061 ; [r] seektrk Track to read
1062 ; --------------------------------------------------------------------
1064 ; ====================================================================
1067 sbi flags,readop ; Set read operation flag
1076 rcall dsk_getpartentry ; Get Paritiontableentry
1077 ld temp,z ; Get Partitiontype
1078 andi temp,dskType_MASK
1081 cpi temp,dskType_None
1085 ; It must be a FAT16-Imagefile or CP/M Partition.
1087 rcall dsk_setdrvparam ;todo: do this only if needed (disk change)
1090 sbi flags,rsflag ;must read data
1091 ldi temp,WRUAL ;write type
1092 sts wrtype,temp ;treat as unalloc
1094 rjmp dsk_rwoper ;to perform the read
1099 ; ====================================================================
1100 ; Function: Does a Disk write operation
1101 ; ====================================================================
1103 ; --------------------------------------------------------------------
1104 ; Registers : in: temp Write type
1105 ; Variables : [r] seekdsk Number of Disk to Read
1106 ; [r] seeksec Sector to read
1107 ; [r] seektrk Track to read
1108 ; --------------------------------------------------------------------
1110 ; ====================================================================
1112 ;write the selected sector
1114 cbi flags,readop ; not a read operation
1122 rcall dsk_getpartentry ; Get Paritiontableentry
1123 ld temp2,z ; Get Partitiontype
1124 andi temp2,dskType_MASK
1127 cpi temp2,dskType_None
1132 ; It must be a FAT16-Imagefile or CP/M Partition.
1134 rcall dsk_setdrvparam ;todo: do this only if needed (disk change)
1137 sts wrtype,temp ;save write type
1139 cpi temp,WRUAL ;write unallocated?
1140 brne dsk_chkuna ;check for unalloc
1142 ; write to unallocated, set parameters
1143 lds temp,secpblk ;next unalloc recs (blocksize/128)
1145 lds temp,seekdsk ;disk to seek
1146 sts unadsk,temp ;unadsk = sekdsk
1148 sts unatrk,temp ;unatrk = sectrk
1150 sts unatrk+1,temp ;unatrk = sectrk
1152 sts unasec,temp ;unasec = seksec
1155 ;check for write to unallocated sector
1156 lds temp,unacnt ;any unalloc remain?
1158 breq dsk_alloc ;skip if not
1160 ; more unallocated records remain
1161 dec temp ;unacnt = unacnt-1
1163 lds temp,seekdsk ;same disk?
1165 cp temp,temp2 ;seekdsk = unadsk?
1166 brne dsk_alloc ;skip if not
1168 ; disks are the same
1173 cp temp,temp3 ;seektrk = unatrk?
1175 brne dsk_alloc ;skip if not
1177 ; tracks are the same
1178 lds temp,seeksec ;same sector?
1180 cp temp,temp2 ;seeksec = unasec?
1181 brne dsk_alloc ;skip if not
1183 ; match, move to next sector for future ref
1184 inc temp2 ;unasec = unasec+1
1187 cp temp2,_tmp0 ;end of track? (count CP/M sectors)
1188 brlo dsk_noovf ;skip if no overflow
1190 ; overflow to next track
1191 sts unasec,_0 ;unasec = 0
1194 subi temp, low(-1) ;unatrk = unatrk+1
1200 cbi flags,rsflag ;rsflag = 0
1201 rjmp dsk_rwoper ;to perform the write
1204 ;not an unallocated record, requires pre-read
1205 sts unacnt,_0 ;unacnt = 0
1206 sbi flags,rsflag ;rsflag = 1
1212 ; ====================================================================
1213 ; Function: Does a Disk read/write operation
1214 ; ====================================================================
1216 ; --------------------------------------------------------------------
1218 ; Variables : [r] seekdsk Number of Disk to Read
1219 ; [r] seeksec Sector to read
1220 ; [r] seektrk Track to read
1221 ; --------------------------------------------------------------------
1223 ; ====================================================================
1225 ;enter here to perform the read/write
1227 printstring ", flags: "
1231 ;Convert track/sector to an LBA address (in 128byte blocks)
1236 lds temp,hdrsize ;add image header size
1240 lds temp4,seektrk+1 ;
1246 add xh,r0 ;yl:xh:xl := sec + trk * SectorsPerTrack
1250 andi temp,SECMSK ;mask buffer number
1251 push temp ;save for later
1253 ;Convert from CP/M LBA blocks to host LBA blocks
1261 ;todo: yl should be 0 here.
1262 ;xh:xl = host block to seek
1265 rcall dsk_rw_hostbuf
1267 ;copy data to or from buffer
1270 pop temp2 ;get buffer number (which part of hostbuf)
1272 add zl,r0 ;offset in hostbuf
1277 printstring "; host buf adr: "
1283 ldi temp3,128 ;length of move
1284 sbic flags,readop ;which way?
1285 rjmp dsk_rmove ;skip if read
1287 ; mark write operation
1288 sbi flags,hostwrt ;hostwrt = 1
1304 ; data has been moved to/from host buffer
1305 lds temp,wrtype ;write type
1306 cpi temp,WRDIR ;to directory?
1308 ret ;no further processing
1310 ; clear host buffer for directory write
1316 rcall dsk_writehost ;clear host buff
1317 cbi flags,hostwrt ;buffer written
1320 ; ====================================================================
1322 ; ====================================================================
1324 ; --------------------------------------------------------------------
1325 ; Registers : temp2:temp block to read (lba)
1328 ; --------------------------------------------------------------------
1330 ; ====================================================================
1334 printstring "readhst lba"
1336 sbi flags,rsflag ;must read data
1337 rcall dsk_rw_hostbuf
1338 lds temp,erflag ;returns 0, if ok
1342 ; ====================================================================
1343 ; Function: Get physical disk sector in hostbuf.
1344 ; ====================================================================
1346 ; --------------------------------------------------------------------
1347 ; Registers : temp2:temp host block to read/write (lba)
1350 ; --------------------------------------------------------------------
1352 ; ====================================================================
1354 ;xh:xl = host block to seek
1355 sts erflag,_0 ;no errors (yet)
1357 ; active host sector?
1358 in _tmp0,flags ;host active flag
1359 sbi flags,hostact ;always becomes 1
1360 sbrs _tmp0,hostact ;was it already?
1361 rjmp dsk_filhst ;fill host if not
1363 ; host buffer active, same as seek buffer?
1364 lds _tmp0,hostdsk ;same disk?
1365 cp temp3,_tmp0 ;seekdsk = hostdsk?
1368 ; same disk, same block?
1376 ;proper disk, but not correct sector
1377 sbis flags,hostwrt ;host written?
1382 rcall dsk_writehost ;clear host buff
1388 ;may have to fill the host buffer
1393 sbic flags,rsflag ;need to read?
1394 rcall dsk_readhost ;yes, if 1
1395 cbi flags,hostwrt ;no pending write
1400 ; ====================================================================
1401 ; Function: Does a Disk write operation
1402 ; ====================================================================
1404 ; --------------------------------------------------------------------
1406 ; Variables : [r] seekdsk Number of Disk to Read
1407 ; [r] seeksec Sector to read
1408 ; [r] seektrk Track to read
1409 ; --------------------------------------------------------------------
1411 ; ====================================================================
1414 rcall dsk_getpartentry
1416 andi temp,dskType_MASK
1419 ; Is it a FAT16 Diskimage ?
1420 cpi temp,dskType_FAT
1425 ; Is it a CP/M Partition ?
1426 cpi temp,dskType_CPM
1429 ; Disktype not supported -> Return
1432 ; ====================================================================
1433 ; Function: Does a Disk read operation
1434 ; ====================================================================
1436 ; --------------------------------------------------------------------
1438 ; Variables : [r] seekdsk Number of Disk to Read
1439 ; [r] seeksec Sector to read
1440 ; [r] seektrk Track to read
1441 ; --------------------------------------------------------------------
1443 ; ====================================================================
1448 printstring "readhost"
1450 rcall dbg_hexdump_line
1452 rcall dbg_hexdump_line
1456 rcall dsk_getpartentry
1458 andi temp,dskType_MASK
1461 ; Is it a FAT16 Diskimage ?
1462 cpi temp,dskType_FAT
1467 ; Is it a CP/M Partition ?
1468 cpi temp,dskType_CPM
1471 ; Disktype not supported -> Return
1475 ; vim:set ts=8 noet nowrap