1 TITLE 'compactflash disk handler'
3 ; CP/M-80 Version 3 -- Modular BIOS
6 ; Disk drive dispatching tables for linked BIOS
10 ; Variables containing parameters passed by BDOS
17 ; System Control Block variables
19 extrn @ermde ; BDOS error mode
23 extrn ?wboot ; warm boot vector
24 extrn ?pmsg ; print message @<HL>
25 extrn pr.idx ; print indexed message
26 extrn pr.inln ; print inline message
27 extrn pr.decl ; print 32 bit decimal number
28 extrn pr.errors ; print BIOS disk error header
29 extrn ?cono ; console out
30 extrn bnk2phy ; translate banked to physical linear address
31 extrn add_hla ; add <A> to <HL>
32 extrn gstimer ; get timer short (16 bit)
34 ; Port Address Equates
39 ; CP/M 3 Disk definition macros
43 ; Z180 macro library instruction definitions (ignored by slr180)
47 DEBUG equ false ; not used
48 MULTIIO equ true ; Multi I/O currently not fully implemented.
50 ; IDE Task File Register Definitions
52 ;IdeDOR equ IDEBASE+6 ; Digital Output Register
53 IDEDat equ IDEBASE+0 ; Data Register
54 IDEErr equ IDEBASE+1 ; Error Register
55 IDEFeat equ IDEBASE+1 ; Feature Register
56 IDESCnt equ IDEBASE+2 ; Sector Count
57 IDESNum equ IDEBASE+3 ; Sector Number
58 IDECLo equ IDEBASE+4 ; Cylinder Low
59 IDECHi equ IDEBASE+5 ; Cylinder High
60 IDESDH equ IDEBASE+6 ; Drive and Head
61 IDECmd equ IDEBASE+7 ; Command / Status
63 ; IDE Hard disk commands:
65 CmdHome equ 10h ; Recalibrate
66 CmdRd equ 20h ; Read Sector
67 CmdWr equ 30h ; Write Sector
68 CmdInit equ 91h ; Initialize Drive Params
69 CmdId equ 0ECh ; Read ID
70 CmdSF equ 0EFh ; Set Feature
72 ; Partition Table Structures
79 ; (see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html)
81 PARTID1_FAT16 equ 00EH
82 PARTID2_FAT16 equ 006H
88 PTAB_TYPE equ 0 ; 1 byte
89 PTAB_START equ 1 ; 4 byte (28 bit, max 128 GiB)
90 PTAB_SIZE equ 5 ; 4 byte (3 needed, 20 bit, max 512 MiB)
91 PTAB_SPT equ 9 ; 1 byte
92 PTAB_BSH equ 10 ; 1 byte
97 ; common control characters
103 ;-------------------------------------------------------------------------------
105 ; Macro: wait while device is busy
114 ; Macro: wait until device is ready
124 ; Macro: wait for DRQ signal
133 ;-------------------------------------------------------------------------------
137 ; Extended Disk Parameter Headers (XPDHs)
139 ; dph translate$table, - disk parameter header
140 ; disk$parameter$block,
141 ; checksum$size, (optional)
142 ; alloc$size (optional)
148 db 0,0 ; relative drive zero
149 cf0: dph 0,dpbsimhd512,0
155 db 1,0 ; relative drive one
156 cf1: dph 0,dpbsimhd512,0
162 db 2,0 ; relative drive zero
163 cf2: dph 0,dpbsimhd512,0
169 db 3,0 ; relative drive one
170 cf3: dph 0,dpbsimhd512,0
172 cseg ; DPB must be resident
174 ; dpb physical$sector$size, - disk parameter block
175 ; physical$sectors$per$track,
178 ; number$dir$entries,
180 ; checksum$vec$size (optional)
183 dpb 512,8,2048,4096,1024,6,8000h
185 ;-------------------------------------------------------------------------------
187 dseg ; rest is banked
189 ; Disk I/O routines for standardized BIOS interface
191 ; Initialization entry point.
192 ; called for first time initialization.
196 db 'cfio: CompactFlash Memory Card driver',0
198 ld hl,parttbl ; Clear partition table
199 ld b,PARTENTRY_SIZE*MAXDISKS
205 call cf_init ; init ide interface / cf card
207 call ident_read ; identify drive
210 call prnt_info ; print device information
211 call ptab_read ; read the partition table
214 ld c,0 ; number of found disks (paritions)
217 ld hl,tmpsecbuf+512-1 ; Point to first byte of partition table
218 ld a,(hl) ; Test, if it has a valid MBR
226 ; Search for valid Partitions
228 ld hl,tmpsecbuf+512-2-64+PART_TYPE ; Point to partition type of first first partition table entry
230 ld b,4 ; Max # of partition table entries
232 ld a,(hl) ; Get Partitiontype
233 cp PARTID_CPM ; Test for CP/M Partition
234 ld a,16 ; Offset to next entry
237 ld a,(hl) ; (Re)get Partitiontype
238 ld (de),a ; Save paritition type
240 inc hl ; Point to partition start (lba)
244 ld bc,8 ; Copy partition start and size
246 rept PARTENTRY_SIZE-8-1
250 inc c ; One more found
259 ;TODO: variable disk format: sectors per track, ...
261 call prnt_ptab ; Print partition table info
266 db ": No Card",cr,lf,0
273 ret ; all initialization done by drive 0
275 ; Read ID from Hard Disk
279 ld a,0E0h ; assume unit 0,
282 out (IdeCmd),a ; command: read sector data
284 ld bc,IdeDat ; B = 0 (counter), C = I/O address
285 WAITDRQ ; wait for DRQ to become active
287 inir ; read 512 data bytes (2 x 256)
289 in a,(IdeCmd) ; check final drive status
290 and 10001001b ; Busy, DRQ, or Error?
291 ret z ; no: everything is ok
292 ld a,1 ; return with A=1 on error
296 ; Read partition table
300 ld a,0E0h ; assume unit 0, lba mode
302 xor a ; sector 0 (lba)
306 inc a ; one sector to read
307 out (IdeSCnt),a ; set sector count
310 out (IdeCmd),a ; command: read sector data
312 ld bc,IdeDat ; B = 0 (counter), C = I/O address
313 WAITDRQ ; wait for DRQ to become active
315 inir ; read 512 data bytes (2 x 256)
317 in a,(IdeCmd) ; check final drive status
318 and 10001001b ; Busy, DRQ, or Error?
319 ret z ; no: everything is ok
320 ld a,1 ; return with A=1 on error
324 ld hl,25600 ; 32000/1.25 ms
325 call wait_nbsy_to ; wait for BSY == 0
326 jr c,cfi_error ; return error on timeout
328 ld hl,25600 ; 32000/1.25 ms
329 call wait_rdy_to ; wait for RDY == 1
330 jr c,cfi_error ; return error on timeout
332 ld a,0E0h ; assume unit 0, lba mode
335 xor a ; execute NOP command
341 cp 01010001b ; should return error
343 ld a,10h ; execute RECALIBRATE command
348 cp 01010000b ; should return ok
351 ld a,1 ; Enable 8-bit data transfer.
353 ld a,CmdSF ; Set feature command
356 in a,(IdeCmd) ; check final drive status
357 and 10001001b ; Busy, DRQ, or Error?
358 ret z ; no: everything is ok
360 ld a,1 ; return with A=1 on error
363 ;-------------------------------------------------------------------------------
364 ; print char, skipping leading blanks
374 ; print character, saving hl, de, bc
387 ;-------------------------------------------------------------------------------
414 ; Wait while device is busy with time out
415 ; hl: timer tics (1.25ms) to wait
417 ; a: IDE status register
418 ; carry flag set, if time out
434 ; Wait for ready signal with time out
435 ; hl: timer tics (1.25ms) to wait
437 ; a: IDE status register
438 ; carry flag set, if time out
446 and 11000000b ; clears carry
455 ;-------------------------------------------------------------------------------
458 ; Remove leading and trailing spaces
461 push hl ; Save string address
464 dec hl ; Point to last char.
466 prn_el: ; Reduce string len by number of trailing spaces
469 jr nz,prn_el1 ; No more spaces
470 jp po,prn_el2 ; No more characters
479 pop hl ; Restore beginning of string
481 or a ; Test number of remaining chars
482 ret z ; Done, if string was spaces only
484 ld b,1 ; Flag, skip spaces
486 inc hl ;Text is low byte high byte format
501 ; Print divice information
505 db cr,lf,' Model: ',0
506 ld hl,tmpsecbuf + 27*2 ; Model number
507 ld c,20*2 ; max character count
511 ld hl,tmpsecbuf + 10*2 ; Serial number
516 ld hl,tmpsecbuf + 23*2 ; Firmware revision
522 ld hl,(tmpsecbuf+60*2) ;Total Sectors Addressable in LBA Mode
523 ld de,(tmpsecbuf+61*2) ;
542 ; Print partition table info
563 db ': CP/M partition at: ',0
564 ld l,(ix+PTAB_START+0)
565 ld h,(ix+PTAB_START+1)
566 ld e,(ix+PTAB_START+2)
567 ld d,(ix+PTAB_START+3)
572 ld l,(ix+PTAB_SIZE+0)
573 ld h,(ix+PTAB_SIZE+1)
574 ld e,(ix+PTAB_SIZE+2)
575 ld d,(ix+PTAB_SIZE+3)
590 ;-------------------------------------------------------------------------------
592 ; This entry is called when a logical drive is about to
593 ; be logged into for the purpose of density determination.
594 ; It may adjust the parameters contained in the disk
595 ; parameter header pointed at by <DE>
597 ; absolute drive number in @adrv (8 bits) +0
598 ; relative drive number in @rdrv (8 bits) +1
602 ld (residual),a ; just in case
617 ; disk READ and WRITE entry points.
618 ; these entries are called with the following arguments:
620 ; operation type (r/w) in @op (8 bits) +0
621 ; absolute drive number in @adrv (8 bits) +1
622 ; relative drive number in @rdrv (8 bits) +2
623 ; disk track address in @trk (16 bits) +3
624 ; disk sector address in @sect(16 bits) +5
625 ; multi sector count in @cnt (8 bits) +7
626 ; disk transfer address in @dma (16 bits) +8
627 ; disk transfer bank in @dbnk (8 bits) +10
628 ; pointer to XDPH in <DE>
630 ; they transfer the appropriate data, perform retries
631 ; if necessary, then return an error code in <A>
634 ld bc,M_DIM1*256 + CmdRd ; Transfermode: i/o to memory++
637 ld bc,0*256 + CmdWr ; Transfermode: memory++ to i/o
641 ld hl,residual ; remainng sectors from last multi io?
653 and a,~(M_DMS1+M_DIM1+M_DIM0)
657 ld b,1 ; assume 1 sector to transfer
663 ld b,a ; number of sectors to transfer
664 dec a ; save remaining
666 xor a ; reset multi sector count
680 out (IdeSCnt),a ; set sector count
682 ; compute logical block number (lba) --> cf-controller
684 ; TODO: sectors per track from dpb
685 ; lba = track * 8 + sector
699 push hl ; check, if block# fits in partition
700 ld e,(iy+PTAB_SIZE+0)
701 ld d,(iy+PTAB_SIZE+1)
704 sbc a,(iy+PTAB_SIZE+2)
707 ld a,1 ; block# >= partition size, return error
712 ld a,(iy+PTAB_START+0) ; add partition start
715 ld a,(iy+PTAB_START+1)
718 ld a,(iy+PTAB_START+2)
721 ld a,(iy+PTAB_START+3)
730 ; compute pysical transfer address --> DMA
732 call bnk2phy ; phys. linear address
757 in a,(IdeCmd) ; check final drive status
764 and 10001001b ; Busy, DRQ, or Error?
765 ret z ; Return to BDOS if no error
769 jp z,retry ; Yes, then retry once more
774 ld a,1 ; return hard error to BDOS
777 ;-------------------------------------------------------------------------------
790 ld hl,b0$msg ; point at message[0]
791 dec e ; index of next message
792 add a,a ; shift left and push residual bits with status
795 call c,pr.idx ; print it, if bit is set.
797 jr nz,errm1 ; if any more bits left, continue
800 ;-------------------------------------------------------------------------------
801 ; error message components
806 b7$msg: db ' Bad Block detected,',0
807 b6$msg: db ' Uncorrectable Data Error,',0
808 b5$msg: db ' Media Changed,',0
809 b4$msg: db ' Sector ID Not Found,',0
810 b3$msg: db ' Media Change Requst,',0
811 b2$msg: db ' Aborted Command,',0
812 b1$msg: db ' Track 0 Not Found,',0
813 b0$msg: db ' AM Not Found (or general error),',0
816 ;-------------------------------------------------------------------------------
822 ds PARTENTRY_SIZE*MAXDISKS
824 tmpsecbuf: ;temporary sector buffer