TITLE 'sd disk handler' ; CP/M-80 Version 3 -- Modular BIOS ; Disk drive dispatching tables for linked BIOS public sd0,sd1,sd2,sd3 public sd4,sd5,sd6,sd7 ; Variables containing parameters passed by BDOS extrn @xdph,@op extrn @adrv,@rdrv extrn @trk,@sect,@cnt extrn @dma,@dbnk ; System Control Block variables extrn @ermde ; BDOS error mode ; Utility routines extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ extrn pr.idx ; print indexed message extrn pr.inln,pr.crlf ; print inline message, print extrn pr.errors ; print BIOS disk error header extrn bnk2phy ; translate banked to physical linear address extrn msg.sm ; send message to AVR extrn msg.recv ; receive message from AVR extrn add_hla ; add to ; Port Address Equates include config.inc include z180reg.inc ; CP/M 3 Disk definition macros maclib 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 dseg ; Extended Disk Parameter Headers (XPDHs) ; dph translate$table, - disk parameter header ; disk$parameter$block, ; checksum$size, (optional) ; alloc$size (optional) 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$init2 db 2,0 ; relative drive zero sd2: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init3 db 3,0 ; relative drive one sd3: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init4 db 4,0 ; relative drive zero sd4: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init5 db 5,0 ; relative drive one sd5: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init6 db 6,0 ; relative drive zero sd6: dph 0,dpbsimhd512 dw sd$write dw sd$read dw sd$login dw sd$init7 db 7,0 ; relative drive one sd7: dph 0,dpbsimhd512 cseg ; DPB must be resident ; dpb physical$sector$size, - disk parameter block ; physical$sectors$per$track, ; number$tracks, ; block$size, ; number$dir$entries, ; track$offset, ; checksum$vec$size (optional) dpbsimhd512: dpb 512,8,2048,4096,1024,6,8100h dseg ; rest is banked ; Disk I/O routines for standardized BIOS interface ; Initialization entry point. ; called for first time initialization. sd$init0: call pr.inln ; db 'sdio: SD Card driver'cr,lf,0 ret sd$init1: sd$init2: sd$init3: sd$init4: sd$init5: sd$init6: sd$init7: 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 ; ; absolute drive number in @adrv (8 bits) +0 ; relative drive number in @rdrv (8 bits) +1 sd$login: xor a ld (residual),a 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 z ld hl,0 ld (@xdph),hl ret ; ; disk READ and WRITE entry points. ; these entries are called with the following arguments: ; ; operation type (r/w) in @op (8 bits) +0 ; absolute drive number in @adrv (8 bits) +1 ; relative drive number in @rdrv (8 bits) +2 ; disk track address in @trk (16 bits) +3 ; disk sector address in @sect(16 bits) +5 ; multi sector count in @cnt (8 bits) +7 ; disk transfer address in @dma (16 bits) +8 ; disk transfer bank in @dbnk (8 bits) +10 ; pointer to XDPH in ; ; they transfer the appropriate data, perform retries ; if necessary, then return an error code in sd$read: sd$write: ld hl,residual ; remainng sectors from last multi io? ld a,(hl) sub a,1 jr c,rwc_new_sectors ld (hl),a xor a ret rwc_new_sectors: ld b,1 ; assume 1 sector to transfer ld a,(@cnt) or a jr z,rwc_doit ld b,a ; number of sectors to transfer dec a ; save remaining ld (hl),a xor a ; reset multi sector count ld (@cnt),a ; compute pysical transfer address ; prepare message ; and send it to AVR. rwc_doit: ld a,b ld hl,@op ;address of arguments ld de,send_msg+1 ld bc,7 ldir ld (de),a ;number of sectors inc de 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 retry: 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 ld hl,print_details call pr.errors jr z,retry ; Yes, then retry once more ; otherwise, xor a ld (residual),a ld a,(recv_msg_rc) ; return hard error to BDOS ld c,0ffh cp 6 ; media changed? jr z,e_exit ld c,2 cp 5 ; disk read only? jr z,e_exit dec c e_exit: ld a,c ret ;------------------------------------------------------------------------------- print_details: ld a,(recv_msg_rc) push af and a,07fh jr z,fatfs_err ld hl,drvmsg0 ; point at first driver error message call pr.idx fatfs_err: pop af and 080h ret z ; no fatfs error call pr.inln db 'FatFs: ',0 ld hl,fr$msg0 ; point at first FatFs message ld a,(recv_msg_rc+1) jp pr.idx ; return via print routine ;------------------------------------------------------------------------------- residual: db 0 send_msg: db 2 ; disk command ds 1 ; subcommand (login/read/write) ds 1 ; @adrv ds 1 ; @rdrv ; -read/write- -login- ds 2 ; @trk xdph address ds 2 ; @sect (3 byte) ds 1 ; @cnt ds 3 ; transfer addr send_msg_rw_len equ $ - send_msg send_msg_login_len equ 7 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 ; general driver errors drvmsg0: db 'Unknown Error, ',0 drvmsg1: db 'Invalid Parameter(s), ',0 drvmsg2: db 'Invalid Drive, ',0 drvmsg3: db 'Bus Timeout, ',0 drvmsg4: db 'Access beyond disk size, ',0 drvmsg5: db 'Write protected, ',0 drvmsg6: db 'No media, ',0 db 0 ; fat file system errors fr$msg0: db 'Unknown 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$msg20: db 'short read/write,',0 db 0 end