; CP/M-80 Version 3 -- Modular BIOS\r
\r
\r
- dseg\r
-\r
; Disk drive dispatching tables for linked BIOS\r
\r
public sd0,sd1,sd2,sd3\r
+ public sd4,sd5,sd6,sd7\r
\r
; Variables containing parameters passed by BDOS\r
\r
+ extrn @xdph,@op\r
extrn @adrv,@rdrv\r
extrn @trk,@sect,@cnt\r
extrn @dma,@dbnk\r
\r
extrn @ermde ; BDOS error mode\r
\r
- ; Utility routines in standard BIOS\r
+ ; Utility routines\r
\r
extrn ?wboot ; warm boot vector\r
- extrn ?pmsg ; print message @<HL> up to 00, saves <BC> & <DE>\r
- extrn ?pdec ; print binary number in <A> from 0 to 99.\r
- extrn ?pderr ; print BIOS disk error header\r
- extrn ?conin,?cono ; con in and out\r
- extrn ?const ; get console status\r
-\r
- extrn bnk2phy ;\r
- extrn msg.sm ;\r
- extrn msg.recv ;\r
- extrn add_hla\r
+ extrn ?pmsg ; print message @<HL>\r
+ extrn pr.idx ; print indexed message\r
+ extrn pr.inln,pr.crlf ; print inline message, print <cr><lf>\r
+ extrn pr.errors ; print BIOS disk error header\r
+ extrn bnk2phy ; translate banked to physical linear address\r
+ extrn msg.sm ; send message to AVR\r
+ extrn msg.recv ; receive message from AVR\r
+ extrn add_hla ; add <A> to <HL>\r
\r
\r
; Port Address Equates\r
\r
; CP/M 3 Disk definition macros\r
\r
- include cpm3slr.lib\r
+ maclib cpm3slr.lib\r
\r
; Z180 macro library instruction definitions (ignored by slr180)\r
\r
bell equ 7\r
\r
\r
+ dseg\r
+\r
; Extended Disk Parameter Headers (XPDHs)\r
\r
+ ; dph translate$table, - disk parameter header\r
+ ; disk$parameter$block,\r
+ ; checksum$size, (optional)\r
+ ; alloc$size (optional)\r
+\r
dw sd$write\r
dw sd$read\r
dw sd$login\r
dw sd$write\r
dw sd$read\r
dw sd$login\r
- dw sd$init0\r
+ dw sd$init2\r
db 2,0 ; relative drive zero\r
sd2: dph 0,dpbsimhd512\r
\r
dw sd$write\r
dw sd$read\r
dw sd$login\r
- dw sd$init1\r
+ dw sd$init3\r
db 3,0 ; relative drive one\r
sd3: dph 0,dpbsimhd512\r
\r
\r
+ dw sd$write\r
+ dw sd$read\r
+ dw sd$login\r
+ dw sd$init4\r
+ db 4,0 ; relative drive zero\r
+sd4: dph 0,dpbsimhd512\r
+\r
+ dw sd$write\r
+ dw sd$read\r
+ dw sd$login\r
+ dw sd$init5\r
+ db 5,0 ; relative drive one\r
+sd5: dph 0,dpbsimhd512\r
+\r
+ dw sd$write\r
+ dw sd$read\r
+ dw sd$login\r
+ dw sd$init6\r
+ db 6,0 ; relative drive zero\r
+sd6: dph 0,dpbsimhd512\r
+\r
+ dw sd$write\r
+ dw sd$read\r
+ dw sd$login\r
+ dw sd$init7\r
+ db 7,0 ; relative drive one\r
+sd7: dph 0,dpbsimhd512\r
+\r
+\r
cseg ; DPB must be resident\r
\r
+ ; dpb physical$sector$size, - disk parameter block\r
+ ; physical$sectors$per$track,\r
+ ; number$tracks,\r
+ ; block$size,\r
+ ; number$dir$entries,\r
+ ; track$offset,\r
+ ; checksum$vec$size (optional)\r
+\r
dpbsimhd512:\r
- dpb 512,8,2048,4096,1024,6\r
+ dpb 512,8,2048,4096,1024,6,8100h\r
\r
\r
dseg ; rest is banked\r
; called for first time initialization.\r
\r
sd$init0:\r
+ call pr.inln ;\r
+ db 'sdio: SD Card driver'cr,lf,0\r
ret\r
\r
sd$init1:\r
sd$init2:\r
sd$init3:\r
+sd$init4:\r
+sd$init5:\r
+sd$init6:\r
+sd$init7:\r
ret ; all initialization done by drive 0\r
\r
\r
-\r
-\r
; This entry is called when a logical drive is about to\r
; be logged into for the purpose of density determination.\r
; It may adjust the parameters contained in the disk\r
; parameter header pointed at by <DE>\r
+;\r
+; absolute drive number in @adrv (8 bits) +0\r
+; relative drive number in @rdrv (8 bits) +1\r
\r
sd$login:\r
+ ld (sdstack),sp\r
+ ld sp,sdstack\r
+\r
xor a\r
ld (residual),a\r
ld hl,send_msg+1\r
ld b,recv_msg_len ; max receive message len\r
call msg.recv\r
\r
-; ld a,(recv_msg_rc)\r
-; or a\r
+ ld a,(recv_msg_rc)\r
+ or a\r
+\r
+ ld sp,(sdstack)\r
+\r
+ ret z\r
+ ld hl,0\r
+ ld (@xdph),hl\r
ret ;\r
\r
\r
; disk READ and WRITE entry points.\r
; these entries are called with the following arguments:\r
;\r
-; absolute drive number in @adrv (8 bits) +0\r
-; relative drive number in @rdrv (8 bits) +1\r
-; disk track address in @trk (16 bits) +2\r
-; disk sector address in @sect(16 bits) +4\r
-; multi sector count in @cnt (8 bits) +6\r
-; disk transfer address in @dma (16 bits) +7\r
-; disk transfer bank in @dbnk (8 bits) +9\r
+; operation type (r/w) in @op (8 bits) +0\r
+; absolute drive number in @adrv (8 bits) +1\r
+; relative drive number in @rdrv (8 bits) +2\r
+; disk track address in @trk (16 bits) +3\r
+; disk sector address in @sect(16 bits) +5\r
+; multi sector count in @cnt (8 bits) +7\r
+; disk transfer address in @dma (16 bits) +8\r
+; disk transfer bank in @dbnk (8 bits) +10\r
; pointer to XDPH in <DE>\r
;\r
; they transfer the appropriate data, perform retries\r
; if necessary, then return an error code in <A>\r
\r
sd$read:\r
- ld de,read$msg ; point at " Read "\r
- ld c,1\r
- jr rw$common\r
sd$write:\r
- ld de,write$msg ; point at " Write "\r
- ld c,2\r
-rw$common:\r
+ ld hl,residual ; remainng sectors from last multi io?\r
+ ld a,(hl)\r
+ sub a,1\r
+ jr c,rwc_new_sectors\r
\r
-; ld hl,residual ; remainng sectors from last multi io?\r
-; ld a,(hl)\r
-; sub a,1\r
-; jr c,rwc_new_sectors\r
-;\r
-; ld (hl),a\r
-; xor a\r
-; ret\r
+ ld (hl),a\r
+ xor a\r
+ ret\r
\r
rwc_new_sectors:\r
+ ld (sdstack),sp\r
+ ld sp,sdstack\r
+\r
ld b,1 ; assume 1 sector to transfer\r
-; ld a,(@cnt)\r
-; or a\r
-; jr z,rwc_doit\r
-;\r
-; ld b,a ; number of sectors to transfer\r
-; dec a ; save remaining\r
-; ld (hl),a\r
-; xor a ; reset multi sector count\r
-; ld (@cnt),a\r
+ ld a,(@cnt)\r
+ or a\r
+ jr z,rwc_doit\r
+\r
+ ld b,a ; number of sectors to transfer\r
+ dec a ; save remaining\r
+ ld (hl),a\r
+ xor a ; reset multi sector count\r
+ ld (@cnt),a\r
\r
; compute pysical transfer address\r
; prepare message\r
; and send it to AVR.\r
\r
rwc_doit:\r
- ld hl,send_msg+1\r
- ld (hl),c\r
- inc hl\r
ld a,b\r
- ex de,hl\r
- ld (operation$name),hl ; save message for errors\r
- ld hl,@adrv ;address of arguments\r
- ld bc,6\r
+ ld hl,@op ;address of arguments\r
+ ld de,send_msg+1\r
+ ld bc,7\r
ldir\r
ld (de),a ;number of sectors\r
inc de\r
call msg.recv\r
ld a,(recv_msg_rc)\r
or a\r
- ret z ; check status and return to BDOS if no error\r
+; ret z ; check status and return to BDOS if no error\r
+ jr z,exit\r
\r
-; suppress error message if BDOS is returning errors to application...\r
-\r
- ld a,(@ermde)\r
- cp 0ffh\r
- jr z,hard$error\r
-\r
- ; Had permanent error, print message like:\r
- ; BIOS Err on d: T-nn, S-mm, <operation> <type>, Retry ?\r
-\r
- call ?pderr ; print message header\r
+ ld hl,print_details\r
+ call pr.errors\r
+ jr z,retry ; Yes, then retry once more\r
+ ; otherwise,\r
+ xor a\r
+ ld (residual),a\r
+ ld a,(recv_msg_rc) ; return hard error to BDOS\r
+ ld c,0ffh\r
+ cp 6 ; media changed?\r
+ jr z,e_exit\r
+ ld c,2\r
+ cp 5 ; disk read only?\r
+ jr z,e_exit\r
+ dec c\r
+e_exit:\r
+ ld a,c\r
+exit:\r
+ ld sp,(sdstack)\r
+ ret\r
\r
- ld hl,(operation$name)\r
- call ?pmsg ; last function (read or write)\r
+;-------------------------------------------------------------------------------\r
\r
+print_details:\r
ld a,(recv_msg_rc)\r
+ push af\r
and a,07fh\r
jr z,fatfs_err\r
\r
ld hl,drvmsg0 ; point at first driver error message\r
- ld c,drvmsg_count\r
- call pdecoded\r
+ call pr.idx\r
\r
fatfs_err:\r
- ld a,(recv_msg_rc)\r
- tst 080h\r
- jr z,prompt ; no fatfs error\r
+ pop af\r
+ and 080h\r
+ ret z ; no fatfs error\r
\r
- ld hl,fsmsg\r
- call ?pmsg\r
+ call pr.inln\r
+ db 'FatFs: ',0\r
\r
ld hl,fr$msg0 ; point at first FatFs message\r
- ld c,fr$msg$count\r
ld a,(recv_msg_rc+1)\r
- call pdecoded\r
-\r
-prompt:\r
- ld hl,error$msg\r
- call ?pmsg ; print "<BEL>, Retry (Y/N) ? "\r
- call u$conin$echo ; get operator response\r
- cp 'Y'\r
- jr z,retry ; Yes, then retry 10 more times\r
+ jp pr.idx ; return via print routine\r
\r
-hard$error:\r
- ; otherwise,\r
- xor a\r
- ld (residual),a\r
-\r
- ld a,1 ; return hard error to BDOS\r
- ret\r
-\r
-cancel: ; here to abort job\r
- jp ?wboot ; leap directly to warmstart vector\r
-\r
-\r
-\r
-; Print message to error code in A\r
-;\r
-\r
-pdecoded:\r
- push bc\r
- push de\r
- push hl ; put pointer to first message on stack\r
- cp c\r
- jr c,pdc_1\r
- xor a\r
-pdc_1:\r
- ld bc,0\r
- ld e,a ; save message number\r
- xor a\r
- inc e\r
-pdc_nxt_str:\r
- dec e\r
- ex (sp),hl\r
- jr z,pdc_found\r
- ex (sp),hl\r
- cpir\r
- jr z,pdc_nxt_str\r
- ; not found (should not happen)\r
-pdc_found:\r
- pop hl\r
- call ?pmsg\r
- pop de\r
- pop bc\r
- ret\r
-\r
-\r
-; get console input, echo it, and shift to upper case\r
-\r
-u$conin$echo:\r
-\r
- call ?const\r
- or a\r
- jr z,u$c1 ; see if any char already struck\r
- call ?conin\r
- jr u$conin$echo ; yes, eat it and try again\r
-u$c1:\r
- call ?conin\r
- push af\r
- ld c,a\r
- cp ' '-1\r
- call nc,?cono\r
- pop af\r
- cp 'a'\r
- ret c\r
- sub 'a'-'A' ; make upper case\r
- ret\r
\r
+;-------------------------------------------------------------------------------\r
\r
residual:\r
db 0\r
recv_msg_len equ $ - recv_msg\r
\r
\r
- ; error message components\r
-\r
-operation$name:\r
- dw read$msg\r
-read$msg:\r
- db ', Read, ',0\r
-write$msg:\r
- db ', Write, ',0\r
+;-------------------------------------------------------------------------------\r
+; error message components\r
+ ; general driver errors\r
\r
drvmsg0: db 'Unknown Error, ',0\r
drvmsg1: db 'Invalid Parameter(s), ',0\r
drvmsg2: db 'Invalid Drive, ',0\r
drvmsg3: db 'Bus Timeout, ',0\r
-drvmsg_size equ $ - drvmsg0\r
-drvmsg_count equ 3\r
+drvmsg4: db 'Access beyond disk size, ',0\r
+drvmsg5: db 'Write protected, ',0\r
+drvmsg6: db 'No media, ',0\r
+ db 0\r
\r
-fsmsg: db 'FatFs: ',0\r
-\r
-; table of pointers to error message strings\r
+ ; fat file system errors\r
\r
fr$msg0: db 'Unknown Error,',0\r
fr$msg1: db 'DISK_ERR,',0\r
fr$msg18: db 'TOO_MANY_OPEN_FILES,',0\r
fr$msg19: db 'FR_INVALID_PARAMETER,',0\r
fr$msg20: db 'short read/write,',0\r
-fr$msg$size equ $ - fr$msg0\r
-fr$msg$count equ 20\r
-\r
-error$msg:\r
- db ' Retry (Y/N) ? ',0\r
+ db 0\r
\r
+ rept 80\r
+ db 07CH\r
+ endm\r
+sdstack::\r
+ dw 0\r
\r
end\r