; 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 @dma,@trk,@sect\r
- extrn @dbnk\r
+ extrn @trk,@sect,@cnt\r
+ extrn @dma,@dbnk\r
\r
; System Control Block variables\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 (hl),0 ;login function\r
inc hl\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
-; multi sector count in @cnt (8 bits) +2 (currently unused)\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
-; disk transfer address in @dma (16 bits) +7\r
-; disk transfer bank in @dbnk (8 bits) +9\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 hl,read$msg ; point at " Read "\r
- ld a,1\r
- jr rw$common\r
-\r
sd$write:\r
- ld hl,write$msg ; point at " Write "\r
- ld a,2\r
- ;fall thru\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
+\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
\r
; compute pysical transfer address\r
; prepare message\r
; and send it to AVR.\r
\r
-rw$common:\r
- ld (operation$name),HL ; save message for errors\r
+rwc_doit:\r
+ ld a,b\r
+ ld hl,@op ;address of arguments\r
ld de,send_msg+1\r
- ld (de),a\r
- inc de\r
- ld hl,@adrv ;address of arguments\r
ld bc,7\r
ldir\r
+ ld (de),a ;number of sectors\r
+ inc de\r
push de\r
ld e,(hl) ;dma address\r
inc hl\r
inc hl\r
ld (hl),a\r
\r
-more$retries:\r
+retry:\r
\r
ld hl,send_msg\r
ld b,send_msg_rw_len\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
-\r
-; suppress error message if BDOS is returning errors to application...\r
+; ret z ; check status and return to BDOS if no error\r
+ jr z,exit\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
-;TODO: rc errorcode\r
-\r
- ld a,(recv_msg_rc)\r
- tst 080h \r
- jr z,fs_end\r
+ ld hl,drvmsg0 ; point at first driver error message\r
+ call pr.idx\r
\r
fatfs_err:\r
+ pop af\r
+ and 080h\r
+ ret z ; no fatfs error\r
\r
- ld a,(recv_msg_rc+1)\r
- cp 20\r
- jr c,fs_err1\r
- xor a\r
-fs_err1\r
- ld hl,fr$msg0 ; point at first message\r
- ld bc,fr$msg$size\r
- ld e,a ; save message number\r
- xor a\r
- inc e\r
-nxt_str:\r
- dec e\r
- jr z,fs_err_found\r
- cpir\r
- jr z,nxt_str\r
- ld hl,fr$msg0 ; not found, point at first message\r
-\r
-fs_err_found:\r
- call ?pmsg\r
-\r
-fs_end:\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,more$retries ; Yes, then retry 10 more times\r
-hard$error:\r
- ; otherwise,\r
- ld a,1\r
- ret ; return hard error to BDOS\r
-\r
-cancel: ; here to abort job\r
- jp ?wboot ; leap directly to warmstart vector\r
-\r
+ call pr.inln\r
+ db 'FatFs: ',0\r
\r
+ ld hl,fr$msg0 ; point at first FatFs message\r
+ ld a,(recv_msg_rc+1)\r
+ jp pr.idx ; return via print routine\r
\r
-u$conin$echo:\r
- ; get console input, echo it, and shift to upper case\r
- call ?const\r
- or a\r
- jp z,u$c1 ; see if any char already struck\r
- call ?conin\r
- jp u$conin$echo ; yes, eat it and try again\r
-u$c1:\r
- call ?conin\r
- push af\r
- ld c,a\r
- call ?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
\r
send_msg:\r
db 2 ; disk command\r
ds 1 ; subcommand (login/read/write)\r
ds 1 ; @adrv\r
ds 1 ; @rdrv\r
- ; -read/write- -login- \r
- ds 1 ; @cnt 3 byte\r
- ds 2 ; @trk xdph address\r
-send_msg_login_len equ $ - send_msg\r
- ds 2 ; @sect\r
+ ; -read/write- -login-\r
+ ds 2 ; @trk xdph address\r
+ ds 2 ; @sect (3 byte)\r
+ ds 1 ; @cnt\r
ds 3 ; transfer addr\r
send_msg_rw_len equ $ - send_msg\r
+send_msg_login_len equ 7\r
\r
\r
recv_msg:\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
-\r
- ; table of pointers to error message strings\r
-\r
-fr$msg0: db ' Unknown FatFs Error,',0\r
-fr$msg1: db ' DISK_ERR,',0\r
-fr$msg2: db ' INT_ERR,',0\r
-fr$msg3: db ' NOT_READY,',0\r
-fr$msg4: db ' NO_FILE,',0\r
-fr$msg5: db ' NO_PATH,',0\r
-fr$msg6: db ' INVALID_NAME,',0\r
-fr$msg7: db ' DENIED,',0\r
-fr$msg8: db ' EXIST,',0\r
-fr$msg9: db ' INVALID_OBJECT,',0\r
-fr$msg10: db ' WRITE_PROTECTED,',0\r
-fr$msg11: db ' INVALID_DRIVE,',0\r
-fr$msg12: db ' NOT_ENABLED,',0\r
-fr$msg13: db ' NO_FILE_SYSTEM,',0\r
-fr$msg14: db ' MKFS_ABORTED,',0\r
-fr$msg15: db ' TIMEOUT,',0\r
-fr$msg16: db ' LOCKED,',0\r
-fr$msg17: db ' NOT_ENOUGH_CORE,',0\r
-fr$msg18: db ' TOO_MANY_OPEN_FILES,',0\r
-fr$msg19: db ' FR_INVALID_PARAMETER,',0\r
-fr$msg$size equ $ - fr$msg0\r
-\r
-\r
-error$msg:\r
- db ' Retry (Y/N) ? ',0\r
-\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
+drvmsg4: db 'Access beyond disk size, ',0\r
+drvmsg5: db 'Write protected, ',0\r
+drvmsg6: db 'No media, ',0\r
+ db 0\r
+\r
+ ; fat file system errors\r
+\r
+fr$msg0: db 'Unknown Error,',0\r
+fr$msg1: db 'DISK_ERR,',0\r
+fr$msg2: db 'INT_ERR,',0\r
+fr$msg3: db 'NOT_READY,',0\r
+fr$msg4: db 'NO_FILE,',0\r
+fr$msg5: db 'NO_PATH,',0\r
+fr$msg6: db 'INVALID_NAME,',0\r
+fr$msg7: db 'DENIED,',0\r
+fr$msg8: db 'EXIST,',0\r
+fr$msg9: db 'INVALID_OBJECT,',0\r
+fr$msg10: db 'WRITE_PROTECTED,',0\r
+fr$msg11: db 'INVALID_DRIVE,',0\r
+fr$msg12: db 'NOT_ENABLED,',0\r
+fr$msg13: db 'NO_FILE_SYSTEM,',0\r
+fr$msg14: db 'MKFS_ABORTED,',0\r
+fr$msg15: db 'TIMEOUT,',0\r
+fr$msg16: db 'LOCKED,',0\r
+fr$msg17: db 'NOT_ENOUGH_CORE,',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
+ db 0\r
+\r
+ rept 80\r
+ db 07CH\r
+ endm\r
+sdstack::\r
+ dw 0\r
\r
end\r
-\r
-/* File function return code (FRESULT) */\r
-\r
-FR_OK = 0, /* (0) Succeeded */\r
-FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */\r
-FR_INT_ERR, /* (2) Assertion failed */\r
-FR_NOT_READY, /* (3) The physical drive cannot work */\r
-FR_NO_FILE, /* (4) Could not find the file */\r
-FR_NO_PATH, /* (5) Could not find the path */\r
-FR_INVALID_NAME, /* (6) The path name format is invalid */\r
-FR_DENIED, /* (7) Access denied due to prohibited access or directory full */\r
-FR_EXIST, /* (8) Access denied due to prohibited access */\r
-FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */\r
-FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */\r
-FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */\r
-FR_NOT_ENABLED, /* (12) The volume has no work area */\r
-FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */\r
-FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */\r
-FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */\r
-FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */\r
-FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */\r
-FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */\r
-FR_INVALID_PARAMETER /* (19) Given parameter is invalid */\r
-\r