; ;================================================================================================== ; PROPIO DRIVER ;================================================================================================== ; ; TODO: ; PRP_IOBASE .EQU $A8 ; DEVECHO "PRP: IO=" DEVECHO PRP_IOBASE DEVECHO "\n" ; ; GLOBAL PROPIO INITIALIZATION ; PRP_INIT: ; CALL NEWLINE ; FORMATTING PRTS("PRP: IO=0x$") LD A,PRP_IOBASE CALL PRTHEXBYTE ; CALL PRP_DETECT ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXWORD ; *DEBUG* LD DE,PRP_STR_NOHW JP NZ,WRITESTR ; ; RESET INTERFACE, RETURN WITH NZ ON FAILURE #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" RESET$") #ENDIF ; ; REQUEST INTERFACE RESET, RESULT IN A, Z/NZ SET LD A,PRPSD_CMDRESET ; CLEAR ANY ERRORS ON PROPIO CALL PRPSD_SNDCMD RET NZ ; NZ SET, A HAS RESULT CODE ; CALL PRPSD_GETVER RET NZ ; ; PRINT FIRMWARE VERSION PRTS(" F/W=$") LD HL,PRP_FWVER CALL LD32 LD A,D CALL PRTDECB CALL PC_PERIOD LD A,E CALL PRTDECB CALL PC_PERIOD CALL PRTDEC ; ; CHECK F/W VERSION & NOTIFY USER IF UPGRADE REQUIRED LD HL,PRP_FWVER CALL LD32 XOR A CP D JR NZ,PRP_INIT1 CP E JR NZ,PRP_INIT1 LD DE,PRP_STR_UPGRADE CALL WRITESTR ; PRP_INIT1: CALL PRPCON_INIT ; CONSOLE INITIALIZATION CALL PRPSD_INIT ; SD CARD INITIALIZATION ; RET ; ; ; PRP_DETECT: LD BC,2048 ; TRY FOR ABOUT 4 SECONDS PRP_DETECT1: CALL PRP_DETECT2 RET Z DEC BC LD A,B OR C JR NZ,PRP_DETECT1 OR $FF RET ; PRP_DETECT2: LD A,PRPSD_CMDRESET OUT (PRPSD_DSKCMD),A LD DE,64 ; 1MS CALL VDELAY LD A,$A5 OUT (PRPSD_DSKIO),A LD A,$5A OUT (PRPSD_DSKIO),A LD A,PRPSD_CMDNOP OUT (PRPSD_DSKCMD),A LD DE,64 ; 1MS CALL VDELAY IN A,(PRPSD_DSKIO) CP $A5 RET NZ IN A,(PRPSD_DSKIO) CP $5A RET ; ; ; PRP_STR_NOHW .TEXT " NOT PRESENT$" PRP_STR_UPGRADE .TEXT " !!!UPGRADE REQUIRED!!!$" ; ;================================================================================================== ; PROPIO CONSOLE DRIVER ;================================================================================================== ; PRPCON_CMD .EQU PRP_IOBASE + 0 ; PROPIO CONSOLE COMMAND PORT (WHEN WRITTEN) PRPCON_STATUS .EQU PRP_IOBASE + 0 ; PROPIO CONSOLE STATUS PORT (WHEN READ) PRPCON_DATA .EQU PRP_IOBASE + 1 ; PROPIO CONSOLE DATA PORT (READ=KBD, WRITE=DISPLAY) ; PRPCON_BUSY .EQU $80 ; BIT SET WHEN PROPIO CONSOLE INTERFACE IS BUSY PRPCON_ERR .EQU $40 ; BIT SET WHEN PROPIO CONSOLE ERROR HAS OCCURRED PRPCON_KBDRDY .EQU $20 ; BIT SET WHEN KEYBOARD BUF HAS A BYTE READY (BUF FULL) PRPCON_DSPRDY .EQU $10 ; BIT SET WHEN DISPLAY BUF IS READY FOR A BYTE (BUF EMPTY) ; PRPCON_ROWS .EQU 29 ; PROPELLER VGA DISPLAY ROWS (30 - 1 STATUS LINES) PRPCON_COLS .EQU 80 ; PROPELLER VGA DISPLAY COLS ; DEVECHO "PRPCON: ENABLED\n" ; ; ; PRPCON_INIT: ; CALL NEWLINE PRTS("PRPCON:$") ; ; DISPLAY CONSOLE DIMENSIONS CALL PC_SPACE LD A,PRPCON_COLS CALL PRTDECB LD A,'X' CALL COUT LD A,PRPCON_ROWS CALL PRTDECB CALL PRTSTRD .TEXT " TEXT (ANSI)$" ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; LD D,0 ; PHYSICAL UNIT IS ZERO LD E,CIODEV_PRPCON ; DEVICE TYPE LD BC,PRPCON_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ;;;LD (HCB + HCB_CRTDEV),A ; SET OURSELVES AS THE CRT DEVICE CALL CIO_SETCRT ; SET OURSELVES AS THE CRT DEVICE ; XOR A ; SIGNAL SUCCESS RET ; ; DRIVER FUNCTION TABLE ; PRPCON_FNTBL: .DW PRPCON_IN .DW PRPCON_OUT .DW PRPCON_IST .DW PRPCON_OST .DW PRPCON_INITDEV .DW PRPCON_QUERY .DW PRPCON_DEVICE #IF (($ - PRPCON_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID PRPCON FUNCTION TABLE ***\n" #ENDIF ; ; ; PRPCON_IN: CALL PRPCON_IST ; CHECK FOR CHAR PENDING JR Z,PRPCON_IN ; WAIT FOR IT IF NECESSARY IN A,(PRPCON_DATA) ; READ THE CHAR FROM PROPIO LD E,A RET ; ; ; PRPCON_IST: IN A,(PRPCON_STATUS) ; READ LINE STATUS REGISTER AND PRPCON_KBDRDY | PRPCON_BUSY ; ISOLATE KBDRDY AND BUSY SUB PRPCON_KBDRDY ; KBD RDY BUT NOT BUSY? JR Z,PRPCON_IST1 ; YES, GO TO READY LOGIC XOR A ; SIGNAL NO CHARS WAITING JP CIO_IDLE ; RETURN VIA IDLE PROCESSING PRPCON_IST1: DEC A ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; PRPCON_OUT: CALL PRPCON_OST ; CHECK FOR OUTPUT READY JR Z,PRPCON_OUT ; WAIT IF NECESSARY LD A,E ; RECOVER THE CHAR TO WRITE OUT (PRPCON_DATA),A ; WRITE THE CHAR TO PROPIO RET ; ; ; PRPCON_OST: IN A,(PRPCON_STATUS) ; READ LINE STATUS REGISTER AND PRPCON_DSPRDY | PRPCON_BUSY ; ISOLATE DSPRDY AND BUSY SUB PRPCON_DSPRDY ; DSP RDY BUT NOT BUSY? JR Z,PRPCON_OST1 ; YES, GO TO READY LOGIC XOR A ; SIGNAL NO CHARS WAITING JP CIO_IDLE ; RETURN VIA IDLE PROCESSING PRPCON_OST1: DEC A ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; PRPCON_INITDEV: SYSCHKERR(ERR_NOTIMPL) RET ; ; ; PRPCON_QUERY: LD DE,0 LD HL,0 XOR A RET ; ; ; PRPCON_DEVICE: LD D,CIODEV_PRPCON ; D := DEVICE TYPE LD E,0 ; E := DEVICE NUM, ALWAYS 0 LD C,$BF ; C := DEVICE TYPE, 0xBF IS PROP TERM LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,PRP_IOBASE ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ;================================================================================================== ; PROPIO SD CARD DRIVER ;================================================================================================== ; ; IO PORT ADDRESSES ; PRPSD_DSKCMD .EQU PRP_IOBASE + 2 PRPSD_DSKST .EQU PRP_IOBASE + 2 PRPSD_DSKIO .EQU PRP_IOBASE + 3 ; PRPSD_CMDNOP .EQU $00 PRPSD_CMDSTAT .EQU $01 PRPSD_CMDTYPE .EQU $02 PRPSD_CMDCAP .EQU $03 PRPSD_CMDCSD .EQU $04 PRPSD_CMDRESET .EQU $10 PRPSD_CMDINIT .EQU $20 PRPSD_CMDREAD .EQU $30 PRPSD_CMDPREP .EQU $40 PRPSD_CMDWRITE .EQU $50 ; PRPSD_CMDVER .EQU $F0 ; PRPSD_DSKSTBSY .EQU $80 PRPSD_DSKSTERR .EQU $40 PRPSD_DSKSTOVR .EQU $20 PRPSD_DSKSTTO .EQU $10 ; ; SD CARD TYPE ; PRPSD_TYPEUNK .EQU 0 ; CARD TYPE UNKNOWN/UNDETERMINED PRPSD_TYPEMMC .EQU 1 ; MULTIMEDIA CARD (MMC STANDARD) PRPSD_TYPESDSC .EQU 2 ; SDSC CARD (V1) PRPSD_TYPESDHC .EQU 3 ; SDHC CARD (V2) PRPSD_TYPESDXC .EQU 4 ; SDXC CARD (V3) ; ; SD CARD STATUS (PRPSD_STAT) ; PRPSD_STOK .EQU 0 ; OK PRPSD_STINVUNIT .EQU -1 ; INVALID UNIT PRPSD_STRDYTO .EQU -2 ; TIMEOUT WAITING FOR CARD TO BE READY PRPSD_STINITTO .EQU -3 ; INITIALIZATION TIMEOUT PRPSD_STCMDTO .EQU -4 ; TIMEOUT WAITING FOR COMMAND RESPONSE PRPSD_STCMDERR .EQU -5 ; COMMAND ERROR OCCURRED (REF PRPSD_RC) PRPSD_STDATAERR .EQU -6 ; DATA ERROR OCCURRED (REF PRPSD_TOK) PRPSD_STDATATO .EQU -7 ; DATA TRANSFER TIMEOUT PRPSD_STCRCERR .EQU -8 ; CRC ERROR ON RECEIVED DATA PACKET PRPSD_STNOMEDIA .EQU -9 ; NO MEDIA IN CONNECTOR PRPSD_STWRTPROT .EQU -10 ; ATTEMPT TO WRITE TO WRITE PROTECTED MEDIA ; ; PRPSD DEVICE CONFIGURATION ; PRPSD_DEVCNT .EQU 1 ; ONE DEVICE SUPPORTED PRPSD_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES ; ; PER DEVICE DATA OFFSETS ; PRPSD_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE) PRPSD_STAT .EQU 1 ; LAST STATUS (BYTE) PRPSD_TYPE .EQU 2 ; DEVICE TYPE (BYTE) PRPSD_FLAGS .EQU 3 ; FLAG BITS BIT 0=CF, 1=LBA (BYTE) PRPSD_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD) PRPSD_LBA .EQU 8 ; OFFSET OF LBA (DWORD) ; PRPSD_CFGTBL: ; DEVICE 0 .DB 0 ; DRIVER DEVICE NUMBER .DB 0 ; DEVICE STATUS .DB 0 ; DEVICE TYPE .DB 0 ; FLAGS BYTE .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA ; #IF ($ - PRPSD_CFGTBL) != (PRPSD_DEVCNT * PRPSD_CFGSIZ) .ECHO "*** INVALID PRPSD CONFIG TABLE ***\n" #ENDIF ; .DB $FF ; END MARKER ; DEVECHO "PRPSD: ENABLED\n" ; ; SD CARD INITIALIZATION ; PRPSD_INIT: ; ; SETUP THE DISPATCH TABLE ENTRIES ; LD B,PRPSD_DEVCNT ; LOOP CONTROL LD IY,PRPSD_CFGTBL ; START OF CFG TABLE PRPSD_INIT0: PUSH BC ; SAVE LOOP CONTROL LD BC,PRPSD_FNTBL ; BC := FUNC TABLE ADR PUSH IY ; CFG ENTRY POINTER POP DE ; COPY TO DE CALL DIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED LD BC,PRPSD_CFGSIZ ; SIZE OF CFG ENTRY ADD IY,BC ; BUMP IY TO NEXT ENTRY POP BC ; RESTORE BC DJNZ PRPSD_INIT0 ; LOOP AS NEEDED ; ; INITIALIZE INDIVIDUAL UNIT(S) AND DISPLAY DEVICE INVENTORY LD B,PRPSD_DEVCNT ; INIT LOOP COUNTER TO DEVICE COUNT LD IY,PRPSD_CFGTBL ; START OF CFG TABLE PRPSD_INIT1: PUSH BC ; SAVE LOOP COUNTER/INDEX CALL PRPSD_INITUNIT ; INITIALIZE IT #IF (PRPSDTRACE < 2) CALL NZ,PRPSD_PRTSTAT ; IF ERROR, SHOW IT #ENDIF LD BC,PRPSD_CFGSIZ ; SIZE OF CFG ENTRY ADD IY,BC ; BUMP IY TO NEXT ENTRY POP BC ; RESTORE LOOP CONTROL DJNZ PRPSD_INIT1 ; DECREMENT LOOP COUNTER AND LOOP AS NEEDED ; RET ; DONE ; ; ; PRPSD_INITUNIT: ; REINITIALIZE THE CARD HERE CALL PRPSD_INITCARD RET NZ ; CALL PRPSD_PRTPREFIX ; ; PRINT CARD TYPE PRTS(" TYPE=$") CALL PRPSD_PRTTYPE ; ; PRINT STORAGE CAPACITY (BLOCK COUNT) PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL LD A,PRPSD_MEDCAP ; OFFSET TO CAPACITY FIELD CALL LDHLIYA ; HL := IY + A, REG A TRASHED CALL LD32 ; GET THE CAPACITY VALUE CALL PRTHEX32 ; PRINT HEX VALUE ; ; PRINT STORAGE SIZE IN MB PRTS(" SIZE=$") ; PRINT FIELD LABEL LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB CALL SRL32 ; RIGHT SHIFT ;CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) CALL PRTDEC32 ; PRINT DWORD IN DECIMAL PRTS("MB$") ; PRINT SUFFIX ; XOR A ; SIGNAL SUCCESS RET ; ; ; PRPSD_FNTBL: .DW PRPSD_STATUS .DW PRPSD_RESET .DW PRPSD_SEEK .DW PRPSD_READ .DW PRPSD_WRITE .DW PRPSD_VERIFY .DW PRPSD_FORMAT .DW PRPSD_DEVICE .DW PRPSD_MEDIA .DW PRPSD_DEFMED .DW PRPSD_CAP .DW PRPSD_GEOM #IF (($ - PRPSD_FNTBL) != (DIO_FNCNT * 2)) .ECHO "*** INVALID PRPSD FUNCTION TABLE ***\n" #ENDIF ; PRPSD_VERIFY: PRPSD_FORMAT: PRPSD_DEFMED: SYSCHKERR(ERR_NOTIMPL) ; INVALID SUB-FUNCTION RET ; ; ; PRPSD_READ: CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR LD BC,PRPSD_RDSEC ; GET ADR OF SECTOR READ FUNC LD (PRPSD_IOFNADR),BC ; SAVE IT AS PENDING IO FUNC JR PRPSD_IO ; CONTINUE TO GENERIC IO ROUTINE ; ; ; PRPSD_WRITE: CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR LD BC,PRPSD_WRSEC ; GET ADR OF SECTOR READ FUNC LD (PRPSD_IOFNADR),BC ; SAVE IT AS PENDING IO FUNC JR PRPSD_IO ; CONTINUE TO GENERIC IO ROUTINE ; ; ; PRPSD_IO: LD (PRPSD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS LD A,E ; BLOCK COUNT TO A OR A ; SET FLAGS RET Z ; ZERO SECTOR I/O, RETURN W/ E=0 & A=0 LD B,A ; INIT SECTOR DOWNCOUNTER LD C,0 ; INIT SECTOR R/W COUNTER #IF (PRPSDTRACE == 1) LD HL,PRPSD_PRTERR ; SET UP PRPSD_PRTERR PUSH HL ; ... TO FILTER ALL EXITS #ENDIF PUSH BC ; SAVE COUNTERS CALL PRPSD_CHKCARD ; CHECK / REINIT CARD AS NEEDED POP BC ; RESTORE COUNTERS JR NZ,PRPSD_IO3 ; BAIL OUT ON ERROR PRPSD_IO1: PUSH BC ; SAVE COUNTERS #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX #ENDIF LD HL,(PRPSD_IOFNADR) ; GET PENDING IO FUNCTION ADDRESS CALL JPHL ; ... AND CALL IT JR NZ,PRPSD_IO2 ; BAIL OUT ON ERROR ; INCREMENT LBA LD A,PRPSD_LBA ; LBA OFFSET CALL LDHLIYA ; HL := IY + A, REG A TRASHED CALL INC32HL ; INCREMENT THE VALUE ; INCREMENT DMA LD HL,PRPSD_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR INC (HL) ; BUMP DMA BY INC (HL) ; ... 512 BYTES XOR A ; SIGNAL SUCCESS PRPSD_IO2: POP BC ; RECOVER COUNTERS JR NZ,PRPSD_IO3 ; IF ERROR PENDING, BAIL OUT INC C ; BUMP COUNT OF SECTORS READ DJNZ PRPSD_IO1 ; LOOP AS NEEDED PRPSD_IO3: LD E,C ; SECTOR READ COUNT TO E LD HL,(PRPSD_DSKBUF) ; CURRENT BUF ADR TO HL OR A ; SET FLAGS BASED ON RETURN CODE RET Z ; RETURN IF SUCCESS LD A,ERR_IO ; SIGNAL IO ERROR OR A ; SET FLAGS RET ; AND DONE ; ; ; PRPSD_RDSEC: ; CALL PRPSD_SETBLK ; SEND BLOCK ADDRESS #IF (PRPSDTRACE >= 3) PRTS(" READ$") #ENDIF LD A,PRPSD_CMDREAD ; READ COMMAND CALL PRPSD_SNDCMD ; ... AND SEND COMMAND RET NZ ; BAIL OUT ON ERROR LD C,PRPSD_DSKIO ; SET PORT LD B,0 ; SET LOOP COUNTER FOR 256 ITER LD HL,(PRPSD_DSKBUF) ; SET BUF ADR INIR ; READ 256 BYTES INIR ; ... AND AGAIN FOR 512 TOTAL XOR A ; SIGNAL SUCCESS RET ; ; ; PRPSD_WRSEC: ; CALL PRPSD_SETBLK #IF (PRPSDTRACE >= 3) PRTS(" PREP$") #ENDIF LD A,PRPSD_CMDPREP ; PREPARE COMMAND CALL PRPSD_SNDCMD ; SEND IT RET NZ ; BAIL OUT ON ERROR LD C,PRPSD_DSKIO ; SET PORT LD B,0 ; SET LOOP COUNTER FOR 256 ITER LD HL,(PRPSD_DSKBUF) ; SET BUF ADR OTIR ; WRITE 256 BYTES OTIR ; ... AND AGAIN FOR 512 TOTAL #IF (PRPSDTRACE >= 3) PRTS(" WRITE$") #ENDIF LD A,PRPSD_CMDWRITE ; WRITE COMMAND CALL PRPSD_SNDCMD ; SEND IT RET NZ ; BAIL OUT ON ERROR XOR A ; SIGNAL SUCCESS RET ; RETURN ; ; ; PRPSD_STATUS: LD A,(IY+PRPSD_STAT) ; GET STATUS OF SELECTED DEVICE OR A RET ; ; ; PRPSD_RESET: XOR A ; ALWAYS OK RET ; ; ; PRPSD_DEVICE: LD D,DIODEV_PRPSD ; D := DEVICE TYPE LD E,(IY+PRPSD_DEV) ; E := PHYSICAL DEVICE NUMBER LD C,%00110010 ; C := ATTRIBUTES, REMOVABLE, SD CARD LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,PRP_IOBASE ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; PRPSD_SENSE ; PRPSD_MEDIA: ; REINITIALIZE THE CARD HERE CALL PRPSD_INITCARD #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTERR ; PRINT ANY ERRORS #ENDIF LD E,MID_HD ; ASSUME WE ARE OK RET Z ; RETURN IF GOOD INIT LD E,MID_NONE ; SIGNAL NO MEDA LD A,ERR_NOMEDIA ; NO MEDIA ERROR OR A ; SET FLAGS RET ; AND RETURN ; ; ; PRPSD_SEEK: BIT 7,D ; CHECK FOR LBA FLAG CALL Z,HB_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA) LD (IY+PRPSD_LBA+0),L ; SAVE NEW LBA LD (IY+PRPSD_LBA+1),H ; ... LD (IY+PRPSD_LBA+2),E ; ... LD (IY+PRPSD_LBA+3),D ; ... XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; ; PRPSD_CAP: LD A,PRPSD_MEDCAP ; OFFSET TO CAPACITY FIELD CALL LDHLIYA ; HL := IY + A, REG A TRASHED CALL LD32 ; GET THE CURRENT CAPACITY INTO DE:HL LD BC,512 ; 512 BYTES PER BLOCK LD A,(IY+PRPSD_STAT) ; GET STATUS OR A ; SET FLAGS RET ; ; ; PRPSD_GEOM: ; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS ; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE CALL PRPSD_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC LD L,H ; DIVIDE BY 256 FOR # TRACKS LD H,E ; ... HIGH BYTE DISCARDED, RESULT IN HL LD D,16 | $80 ; HEADS / CYL = 16, SET LBA CAPABILITY BIT LD E,16 ; SECTORS / TRACK = 16 RET ; DONE, A STILL HAS PRPSD_CAP STATUS ; ; ; PRPSD_INITCARD: ;; CLEAR ALL STATUS DATA ;LD HL,PRPSD_UNITDATA ;LD BC,PRPSD_UNITDATALEN ;XOR A ;CALL FILL ; ; RESET INTERFACE, RETURN WITH NZ ON FAILURE #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" RESET$") #ENDIF ; REQUEST INTERFACE RESET, RESULT IN A, Z/NZ SET LD A,PRPSD_CMDRESET ; CLEAR ANY ERRORS ON PROPIO CALL PRPSD_SNDCMD RET NZ ; NZ SET, A HAS RESULT CODE ; ; (RE)INITIALIZE THE CARD, RETURN WITH NZ ON FAILURE #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" INIT$") #ENDIF ; REQUEST HARDWARE INIT, RESULT IN A, Z/NZ SET LD A,PRPSD_CMDINIT CALL PRPSD_SNDCMD ;RET NZ ; NZ SET, A HAS RESULT CODE JP NZ,PRPSD_NOMEDIA ; RETURN W/ NO MEDIA ERROR #IF (PRPSDTRACE >= 3) ; GET CSD IF DEBUGGING CALL PRPSD_GETCSD RET NZ #ENDIF ; GET CARD TYPE CALL PRPSD_GETTYPE RET NZ ; GET CAPACITY CALL PRPSD_GETCAP RET NZ RET ; N/NZ SET, A HAS RESULT CODE ; ; CHECK THE SD CARD, ATTEMPT TO REINITIALIZE IF NEEDED ; PRPSD_CHKCARD: LD A,(IY+PRPSD_STAT) ; GET CURRENT STATUS OR A ; SET FLAGS RET Z ; IF ALL GOOD, DONE JP PRPSD_INITCARD ; OTHERWISE, REINIT ; ; ; PRPSD_GETVER: #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX #ENDIF ; #IF (PRPSDTRACE >= 3) PRTS(" PREP$") #ENDIF ; ; ZEROES BUFFER IN CASE F/W DOES NOT KNOW VER COMMAND LD A,PRPSD_CMDPREP CALL PRPSD_SNDCMD RET NZ ; RETURN ON FAILURE, A = STATUS ; #IF (PRPSDTRACE >= 3) PRTS(" VER$") #ENDIF LD A,PRPSD_CMDVER CALL PRPSD_SNDCMD RET NZ LD C,PRPSD_DSKIO ; FROM PROPIO DISK PORT LD B,4 ; 4 BYTES LD HL,PRP_FWVER ; TO PRP_FWVER INIR #IF (PRPSDTRACE >= 3) CALL PC_SPACE LD HL,PRP_FWVER CALL LD32 CALL PRTHEX32 #ENDIF XOR A RET ; ; ; PRPSD_GETTYPE: #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" TYPE$") #ENDIF LD A,PRPSD_CMDTYPE CALL PRPSD_SNDCMD RET NZ IN A,(PRPSD_DSKIO) LD (IY+PRPSD_TYPE),A #IF (PRPSDTRACE >= 3) CALL PC_SPACE CALL PRTHEXBYTE #ENDIF XOR A RET ; ; ; PRPSD_GETCAP: #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" CAP$") #ENDIF LD A,PRPSD_CMDCAP CALL PRPSD_SNDCMD RET NZ LD C,PRPSD_DSKIO ; FROM PROPIO DISK PORT LD B,4 ; 4 BYTES LD A,PRPSD_MEDCAP ; ... OF CAPACITY CALL LDHLIYA ; HL := IY + A, REG A TRASHED INIR #IF (PRPSDTRACE >= 3) CALL PC_SPACE LD A,PRPSD_MEDCAP ; ... OF CAPACITY CALL LDHLIYA ; HL := IY + A, REG A TRASHED CALL LD32 CALL PRTHEX32 #ENDIF XOR A RET ; ; ; PRPSD_GETCSD: #IF (PRPSDTRACE >= 3) CALL PRPSD_PRTPREFIX PRTS(" CSD$") #ENDIF LD A,PRPSD_CMDCSD CALL PRPSD_SNDCMD RET NZ LD C,PRPSD_DSKIO LD B,16 LD HL,PRPSD_CSDBUF INIR #IF (PRPSDTRACE >= 3) CALL PC_SPACE LD DE,PRPSD_CSDBUF LD A,16 CALL PRTHEXBUF #ENDIF XOR A RET ; ; ; PRPSD_SNDCMD: LD (PRPSD_CMD),A ; SAVE INCOMING COMMAND CALL PRPSD_WAITBSY ; WAIT FOR BUSY TO BE CLEAR LD (PRPSD_DSKSTAT),A ; SAVE STATUS #IF (PRPSDTRACE >= 3) CALL PC_SPACE CALL PRTHEXBYTE #ENDIF BIT 7,A ; STILL BUSY JP NZ,PRPSD_ERRRDYTO ; HANDLE TIMEOUT ;CALL PC_PERIOD LD A,(PRPSD_CMD) ; RECOVER INCOMING COMMAND OUT (PRPSD_DSKCMD),A ; SEND THE COMMAND CALL PRPSD_WAITBSY ; WAIT FOR BUSY TO CLEAR (CMD COMPLETE) LD (PRPSD_DSKSTAT),A ; SAVE STATUS #IF (PRPSDTRACE >= 3) CALL PC_SPACE CALL PRTHEXBYTE #ENDIF OR A ; SET FLAGS RET Z ; RETURN W/ NO ERRORS ; BIT 7,A ; STILL BUSY JP NZ,PRPSD_ERRRDYTO ; HANDLE TIMEOUT ; ; ASSUMES A COMMAND ERROR AT THIS POINT ; GET DETAIL ERROR CODE LD C,PRPSD_DSKIO ; FROM PROPIO DISK PORT LD B,4 ; 4 BYTES LD HL,PRPSD_ERRCODE ; TO PRPSD_ERRCODE INIR #IF (PRPSDTRACE >= 3) CALL PC_SPACE LD HL,PRPSD_ERRCODE CALL LD32 CALL PRTHEX32 #ENDIF JP PRPSD_ERRCMD ; RETURN VIA ERROR HANDLER ; ; ; PRPSD_WAITBSY: LD BC,(PRPSD_TIMEOUT) PRPSD_WAITBSY1: IN A,(PRPSD_DSKST) ; GET STATUS LD E,A ; SAVE IT IN E BIT 7,A ; ISLOATE BUSY BIT JR Z,PRPSD_WAITBSY2 ; DONE, JUMP TO HAPPY EXIT CALL DELAY CALL DELAY DEC BC LD A,B OR C JR NZ,PRPSD_WAITBSY1 ; TIMEOUT RETURN LD A,E ; RECOVER LAST STATUS OR A ; SET FLAGS RET ; PRPSD_WAITBSY2: #IF (PRPSDTRACE >= 3) ; DUMP LOOP COUNT PUSH AF CALL PC_SPACE CALL PC_LBKT OR A ; CLEAR CARRY LD HL,(PRPSD_TIMEOUT) SBC HL,BC LD B,H LD C,L CALL PRTHEXWORD CALL PC_RBKT POP AF #ENDIF OR A ; SET FLAGS RET ; AND RETURN WITH STATUS IN A ; ; SEND INDEX OF BLOCK TO READ/WRITE FROM SD CARD ; 32 BIT VALUE (4 BYTES) ; PRPSD_SETBLK: #IF (PRPSDTRACE >= 3) PRTS(" BLK$") #ENDIF ; A NOP COMMAND IS A QUICK WAY TO ENSURE THE DISK BUFFER ; POINTER ON THE PROPIO IS RESET TO ZERO LD A,PRPSD_CMDNOP OUT (PRPSD_DSKCMD),A ; SEND THE COMMAND (NO WAIT) #IF (PRPSDTRACE >= 3) CALL PC_SPACE LD A,PRPSD_LBA ; OFFSET OF LBA CALL LDHLIYA ; HL := IY + A, REG A TRASHED CALL LD32 CALL PRTHEX32 #ENDIF LD C,PRPSD_DSKIO ; SEND TO DISK I/O PORT LD B,4 ; 4 BYTES LD A,PRPSD_LBA ; OFFSET OF LBA CALL LDHLIYA ; HL := IY + A, REG A TRASHED ;;;#IF (DSKYENABLE) ;;; #IF (DSKYDSKACT) CALL HB_DSKACT ; SHOW ACTIVITY ;;; #ENDIF ;;;#ENDIF OTIR RET ; ;============================================================================= ; ERROR HANDLING AND DIAGNOSTICS ;============================================================================= ; ; ERROR HANDLERS ; PRPSD_INVUNIT: LD A,PRPSD_STINVUNIT JR PRPSD_ERR2 ; SPECIAL CASE FOR INVALID UNIT ; PRPSD_ERRRDYTO: LD A,PRPSD_STRDYTO JR PRPSD_ERR ; PRPSD_ERRINITTO: LD A,PRPSD_STINITTO JR PRPSD_ERR ; PRPSD_ERRCMDTO: LD A,PRPSD_STCMDTO JR PRPSD_ERR ; PRPSD_ERRCMD: LD A,PRPSD_STCMDERR JR PRPSD_ERR ; PRPSD_ERRDATA: LD A,PRPSD_STDATAERR JR PRPSD_ERR ; PRPSD_ERRDATATO: LD A,PRPSD_STDATATO JR PRPSD_ERR ; PRPSD_ERRCRC: LD A,PRPSD_STCRCERR JR PRPSD_ERR ; PRPSD_NOMEDIA: LD A,PRPSD_STNOMEDIA JR PRPSD_ERR ; PRPSD_WRTPROT: LD A,PRPSD_STWRTPROT JR PRPSD_ERR2 ; DO NOT UPDATE UNIT STATUS! ; PRPSD_ERR: LD (IY+PRPSD_STAT),A ; UPDATE STATUS ; PRPSD_ERR2: #IF (PRPSDTRACE >= 2) CALL PRPSD_PRTSTAT #ENDIF OR A ; SET FLAGS RET ; ; ; PRPSD_PRTERR: RET Z ; DONE IF NO ERRORS ; FALL THRU TO PRPSD_PRTSTAT ; ; PRINT STATUS STRING ; PRPSD_PRTSTAT: PUSH AF PUSH DE PUSH HL LD A,(IY+PRPSD_STAT) OR A LD DE,PRPSD_STR_STOK JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STINVUNIT JR Z,PRPSD_PRTSTAT1 ; INVALID UNIT IS SPECIAL CASE INC A LD DE,PRPSD_STR_STRDYTO JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STINITTO JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STCMDTO JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STCMDERR JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STDATAERR JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STDATATO JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STCRCERR JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STNOMEDIA JR Z,PRPSD_PRTSTAT1 INC A LD DE,PRPSD_STR_STWRTPROT JR Z,PRPSD_PRTSTAT1 LD DE,PRPSD_STR_STUNK PRPSD_PRTSTAT1: CALL PRPSD_PRTPREFIX ; PRINT UNIT PREFIX CALL PC_SPACE ; FORMATTING CALL WRITESTR LD A,(IY+PRPSD_STAT) CP PRPSD_STCMDERR CALL Z,PRPSD_PRTSTAT2 POP HL POP DE POP AF RET PRPSD_PRTSTAT2: CALL PC_SPACE LD A,(PRPSD_DSKSTAT) CALL PRTHEXBYTE CALL PC_SPACE JP PRPSD_PRTERRCODE RET ; ; ; PRPSD_PRTERRCODE: PUSH HL PUSH DE LD HL,PRPSD_ERRCODE CALL LD32 CALL PRTHEX32 POP DE POP HL RET ; ; PRINT DIAGNONSTIC PREFIX ; PRPSD_PRTPREFIX: PUSH AF CALL NEWLINE PRTS("PRPSD$") LD A,(IY+PRPSD_DEV) ; GET CURRENT DEVICE NUM ADD A,'0' CALL COUT CALL PC_COLON POP AF RET ; ; PRINT THE CARD TYPE ; PRPSD_PRTTYPE: LD A,(IY+PRPSD_TYPE) LD DE,PRPSD_STR_TYPEMMC CP PRPSD_TYPEMMC JR Z,PRPSD_PRTTYPE1 LD DE,PRPSD_STR_TYPESDSC CP PRPSD_TYPESDSC JR Z,PRPSD_PRTTYPE1 LD DE,PRPSD_STR_TYPESDHC CP PRPSD_TYPESDHC JR Z,PRPSD_PRTTYPE1 LD DE,PRPSD_STR_TYPESDXC CP PRPSD_TYPESDXC JR Z,PRPSD_PRTTYPE1 LD DE,PRPSD_STR_TYPEUNK PRPSD_PRTTYPE1: JP WRITESTR ; ;============================================================================= ; STRING DATA ;============================================================================= ; PRPSD_STR_ARROW .TEXT " -->$" PRPSD_STR_RC .TEXT " RC=$" PRPSD_STR_TOK .TEXT " TOK=$" PRPSD_STR_CSD .TEXT " CSD =$" PRPSD_STR_CID .TEXT " CID =$" PRPSD_STR_SCR .TEXT " SCR =$" PRPSD_STR_SDTYPE .TEXT " SD CARD TYPE ID=$" ; PRPSD_STR_STOK .TEXT "OK$" PRPSD_STR_STINVUNIT .TEXT "INVALID UNIT$" PRPSD_STR_STRDYTO .TEXT "READY TIMEOUT$" PRPSD_STR_STINITTO .TEXT "INITIALIZATION TIMEOUT$" PRPSD_STR_STCMDTO .TEXT "COMMAND TIMEOUT$" PRPSD_STR_STCMDERR .TEXT "COMMAND ERROR$" PRPSD_STR_STDATAERR .TEXT "DATA ERROR$" PRPSD_STR_STDATATO .TEXT "DATA TIMEOUT$" PRPSD_STR_STCRCERR .TEXT "CRC ERROR$" PRPSD_STR_STNOMEDIA .TEXT "NO MEDIA$" PRPSD_STR_STWRTPROT .TEXT "WRITE PROTECTED$" PRPSD_STR_STUNK .TEXT "UNKNOWN$" ; PRPSD_STR_TYPEUNK .TEXT "UNK$" PRPSD_STR_TYPEMMC .TEXT "MMC$" PRPSD_STR_TYPESDSC .TEXT "SDSC$" PRPSD_STR_TYPESDHC .TEXT "SDHC$" PRPSD_STR_TYPESDXC .TEXT "SDXC$" ; ;============================================================================= ; DATA STORAGE ;============================================================================= ; PRP_FWVER .DW 0,0 ; MMNNBBB (M=MAJOR, N=MINOR, B=BUILD) ; PRPSD_IOFNADR .DW 0 ; PENDING IO FUNCTION ADDRESS ; PRPSD_DSKBUF .DW 0 ; PRPSD_DSKSTAT .DB 0 PRPSD_ERRCODE .DW 0,0 PRPSD_CSDBUF .FILL 16,0 ; PRPSD_CMD .DB 0 ; PRPSD_TIMEOUT .DW $0000 ; FIX: MAKE THIS CPU SPEED RELATIVE