TITLE 'sd disk handler' ; CP/M-80 Version 3 -- Modular BIOS dseg ; Disk drive dispatching tables for linked BIOS public sd0,sd1,sd2,sd3 ; Variables containing parameters passed by BDOS extrn @adrv,@rdrv extrn @dma,@trk,@sect extrn @dbnk ; System Control Block variables extrn @ermde ; BDOS error mode ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ up to 00, saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status extrn bnk2phy ; extrn msg.sm ; extrn msg.recv ; extrn add_hla ; Port Address Equates include config.inc include z180reg.inc ; CP/M 3 Disk definition macros include cpm3slr.lib ; Z180 macro library instruction definitions (ignored by slr180) include z180.lib ; common control characters cr equ 13 lf equ 10 bell equ 7 ; Extended Disk Parameter Headers (XPDHs) dw sd$write dw sd$read dw sd$login dw sd$init0 db 0,0 ; relative drive zero sd0: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init1 db 1,0 ; relative drive one sd1: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init0 db 2,0 ; relative drive zero sd2: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init1 db 3,0 ; relative drive one sd3: dph 0,dpbsimhd512 cseg ; DPB must be resident dpbsimhd512: dpb 512,8,2048,4096,1024,6 dseg ; rest is banked ; Disk I/O routines for standardized BIOS interface ; Initialization entry point. ; called for first time initialization. sd$init0: ret sd$init1: sd$init2: sd$init3: ret ; all initialization done by drive 0 ; This entry is called when a logical drive is about to ; be logged into for the purpose of density determination. ; It may adjust the parameters contained in the disk ; parameter header pointed at by sd$login: ld hl,send_msg+1 ld (hl),0 ;login function inc hl ld bc,(@adrv) ld (hl),c ;@adrv inc hl ld (hl),b ;@rdrv inc hl ex de,hl ;xdph to hl xor a ;bank 0 call bnk2phy ;phys. linear address ex de,hl ld (hl),e inc hl ld (hl),d inc hl ld (hl),a ld hl,send_msg ld b,send_msg_login_len call msg.sm ld hl,recv_msg ld b,recv_msg_len ; max receive message len call msg.recv ; ld a,(recv_msg_rc) ; or a ret ; ; disk READ and WRITE entry points. ; these entries are called with the following arguments: ; ; absolute drive number in @adrv (8 bits) +0 ; relative drive number in @rdrv (8 bits) +1 ; multi sector count in @cnt (8 bits) +2 (currently unused) ; disk track address in @trk (16 bits) +3 ; disk sector address in @sect(16 bits) +5 ; disk transfer address in @dma (16 bits) +7 ; disk transfer bank in @dbnk (8 bits) +9 ; pointer to XDPH in ; ; they transfer the appropriate data, perform retries ; if necessary, then return an error code in sd$read: ld hl,read$msg ; point at " Read " ld a,1 jr rw$common sd$write: ld hl,write$msg ; point at " Write " ld a,2 ;fall thru ; compute pysical transfer address ; prepare message ; and send it to AVR. rw$common: ld (operation$name),HL ; save message for errors ld de,send_msg+1 ld (de),a inc de ld hl,@adrv ;address of arguments ld bc,7 ldir push de ld e,(hl) ;dma address inc hl ld d,(hl) inc hl ld a,(hl) ;bank ex de,hl call bnk2phy ;phys. linear address ex de,hl pop hl ld (hl),e inc hl ld (hl),d inc hl ld (hl),a more$retries: ld hl,send_msg ld b,send_msg_rw_len call msg.sm ld hl,recv_msg ld b,recv_msg_len ; max receive message len call msg.recv ld a,(recv_msg_rc) or a ret z ; check status and return to BDOS if no error ; suppress error message if BDOS is returning errors to application... ld a,(@ermde) cp 0ffh jr z,hard$error ; Had permanent error, print message like: ; BIOS Err on d: T-nn, S-mm, , Retry ? call ?pderr ; print message header ld hl,(operation$name) call ?pmsg ; last function (read or write) ld a,(recv_msg_rc) ;TODO: rc errorcode ld a,(recv_msg_rc) tst 080h jr z,fs_end fatfs_err: ld a,(recv_msg_rc+1) cp 20 jr c,fs_err1 xor a fs_err1 ld hl,fr$msg0 ; point at first message ld bc,fr$msg$size ld e,a ; save message number xor a inc e nxt_str: dec e jr z,fs_err_found cpir jr z,nxt_str ld hl,fr$msg0 ; not found, point at first message fs_err_found: call ?pmsg fs_end: ld hl,error$msg call ?pmsg ; print ", Retry (Y/N) ? " call u$conin$echo ; get operator response cp 'y' jr z,more$retries ; Yes, then retry 10 more times hard$error: ; otherwise, ld a,1 ret ; return hard error to BDOS cancel: ; here to abort job jp ?wboot ; leap directly to warmstart vector u$conin$echo: ; get console input, echo it, and shift to upper case call ?const or a jp z,u$c1 ; see if any char already struck call ?conin jp u$conin$echo ; yes, eat it and try again u$c1: call ?conin push af ld c,a call ?cono pop af cp 'a' ret c sub 'a'-'a' ; make upper case ret send_msg: db 2 ; disk command ds 1 ; subcommand (login/read/write) ds 1 ; @adrv ds 1 ; @rdrv ; -read/write- -login- ds 1 ; @cnt 3 byte ds 2 ; @trk xdph address send_msg_login_len equ $ - send_msg ds 2 ; @sect ds 3 ; transfer addr send_msg_rw_len equ $ - send_msg recv_msg: ds 1 ; len ds 1 ; command ds 1 ; subcommand recv_msg_rc: ds 1 ; result code ds 4 ; room for additional parameter recv_msg_len equ $ - recv_msg ; error message components operation$name: dw read$msg read$msg: db ', Read',0 write$msg: db ', Write',0 ; table of pointers to error message strings fr$msg0: db ' Unknown FatFs Error,',0 fr$msg1: db ' DISK_ERR,',0 fr$msg2: db ' INT_ERR,',0 fr$msg3: db ' NOT_READY,',0 fr$msg4: db ' NO_FILE,',0 fr$msg5: db ' NO_PATH,',0 fr$msg6: db ' INVALID_NAME,',0 fr$msg7: db ' DENIED,',0 fr$msg8: db ' EXIST,',0 fr$msg9: db ' INVALID_OBJECT,',0 fr$msg10: db ' WRITE_PROTECTED,',0 fr$msg11: db ' INVALID_DRIVE,',0 fr$msg12: db ' NOT_ENABLED,',0 fr$msg13: db ' NO_FILE_SYSTEM,',0 fr$msg14: db ' MKFS_ABORTED,',0 fr$msg15: db ' TIMEOUT,',0 fr$msg16: db ' LOCKED,',0 fr$msg17: db ' NOT_ENOUGH_CORE,',0 fr$msg18: db ' TOO_MANY_OPEN_FILES,',0 fr$msg19: db ' FR_INVALID_PARAMETER,',0 fr$msg$size equ $ - fr$msg0 error$msg: db ' Retry (Y/N) ? ',0 end /* File function return code (FRESULT) */ FR_OK = 0, /* (0) Succeeded */ FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ FR_EXIST, /* (8) Access denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */