From 9f71fe05aadafdc88a02c5a5c35648e7be0e0c05 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sun, 30 Apr 2023 12:03:16 -0700 Subject: [PATCH] Cleanup IDE and PPIDE drivers - The use of hardware reset has been improved such that it is generally only used at initial boot up. - Minor improvements to CF card detection and initialization. - Implement a simple wait mechanism to accommodate the startup time of the RC2014 SD Pico module. - Front panel I/O port for SC series of systems has been moved to 0x00 which is consistent with all other systems and avoids some I/O conflicts. --- Source/HBIOS/Config/SCZ180_sc130.asm | 4 +- Source/HBIOS/Config/SCZ180_sc140.asm | 4 +- Source/HBIOS/Config/SCZ180_sc503.asm | 4 +- Source/HBIOS/cfg_scz180.asm | 2 +- Source/HBIOS/ide.asm | 565 +++++++++++++++++---------- Source/HBIOS/ppide.asm | 535 +++++++++++++++---------- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 8 files changed, 697 insertions(+), 421 deletions(-) diff --git a/Source/HBIOS/Config/SCZ180_sc130.asm b/Source/HBIOS/Config/SCZ180_sc130.asm index ed6e7284..59203b42 100644 --- a/Source/HBIOS/Config/SCZ180_sc130.asm +++ b/Source/HBIOS/Config/SCZ180_sc130.asm @@ -35,8 +35,10 @@ Z180_CLKDIV .SET 1 ; Z180: CHK DIV: 0=OSC/2, 1=OSC, 2=OSC*2 Z180_MEMWAIT .SET 0 ; Z180: MEMORY WAIT STATES (0-3) Z180_IOWAIT .SET 1 ; Z180: I/O WAIT STATES TO ADD ABOVE 1 W/S BUILT-IN (0-3) ; +FPENABLE .SET TRUE ; ENABLES FRONT PANEL SWITCHES +DIAGENABLE .SET TRUE ; ENABLES OUTPUT TO 8 BIT LED DIAGNOSTIC PORT +DIAGPORT .SET $00 ; DIAGNOSTIC PORT ADDRESS LEDENABLE .SET TRUE ; ENABLE STATUS LED (SINGLE LED) -DIAGENABLE .SET FALSE ; ENABLES OUTPUT TO 8 BIT LED DIAGNOSTIC PORT ; DSRTCENABLE .SET TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) INTRTCENABLE .SET TRUE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) diff --git a/Source/HBIOS/Config/SCZ180_sc140.asm b/Source/HBIOS/Config/SCZ180_sc140.asm index ad3d953e..131d3b34 100644 --- a/Source/HBIOS/Config/SCZ180_sc140.asm +++ b/Source/HBIOS/Config/SCZ180_sc140.asm @@ -35,10 +35,10 @@ Z180_MEMWAIT .SET 0 ; Z180: MEMORY WAIT STATES (0-3) Z180_IOWAIT .SET 1 ; Z180: I/O WAIT STATES TO ADD ABOVE 1 W/S BUILT-IN (0-3) ; FPENABLE .SET TRUE ; ENABLES FRONT PANEL SWITCHES -FPBASE .SET $A0 ; FRONT PANEL I/O PORT BASE ADDRESS +FPBASE .SET $00 ; FRONT PANEL I/O PORT BASE ADDRESS LEDENABLE .SET TRUE ; ENABLE STATUS LED (SINGLE LED) DIAGENABLE .SET TRUE ; ENABLES OUTPUT TO 8 BIT LED DIAGNOSTIC PORT -DIAGPORT .SET $A0 ; DIAGNOSTIC PORT ADDRESS +DIAGPORT .SET $00 ; DIAGNOSTIC PORT ADDRESS ; DSRTCENABLE .SET TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) INTRTCENABLE .SET TRUE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) diff --git a/Source/HBIOS/Config/SCZ180_sc503.asm b/Source/HBIOS/Config/SCZ180_sc503.asm index 29e741e2..edc7de7f 100644 --- a/Source/HBIOS/Config/SCZ180_sc503.asm +++ b/Source/HBIOS/Config/SCZ180_sc503.asm @@ -35,10 +35,10 @@ Z180_MEMWAIT .SET 0 ; Z180: MEMORY WAIT STATES (0-3) Z180_IOWAIT .SET 1 ; Z180: I/O WAIT STATES TO ADD ABOVE 1 W/S BUILT-IN (0-3) ; FPENABLE .SET TRUE ; ENABLES FRONT PANEL SWITCHES -FPBASE .SET $A0 ; FRONT PANEL I/O PORT BASE ADDRESS +FPBASE .SET $00 ; FRONT PANEL I/O PORT BASE ADDRESS LEDENABLE .SET TRUE ; ENABLE STATUS LED (SINGLE LED) DIAGENABLE .SET TRUE ; ENABLES OUTPUT TO 8 BIT LED DIAGNOSTIC PORT -DIAGPORT .SET $A0 ; DIAGNOSTIC PORT ADDRESS +DIAGPORT .SET $00 ; DIAGNOSTIC PORT ADDRESS ; DSRTCENABLE .SET TRUE ; DSRTC: ENABLE DS-1302 CLOCK DRIVER (DSRTC.ASM) INTRTCENABLE .SET TRUE ; ENABLE PERIODIC INTERRUPT CLOCK DRIVER (INTRTC.ASM) diff --git a/Source/HBIOS/cfg_scz180.asm b/Source/HBIOS/cfg_scz180.asm index 3af748d8..f534ccd4 100644 --- a/Source/HBIOS/cfg_scz180.asm +++ b/Source/HBIOS/cfg_scz180.asm @@ -67,7 +67,7 @@ SKZENABLE .EQU FALSE ; ENABLE SERGEY'S Z80-512K FEATURES WDOGMODE .EQU WDOG_NONE ; WATCHDOG MODE: WDOG_[NONE|EZZ80|SKZ] ; FPENABLE .EQU FALSE ; ENABLES FRONT PANEL SWITCHES -FPBASE .EQU $0D ; FRONT PANEL I/O PORT BASE ADDRESS +FPBASE .EQU $00 ; FRONT PANEL I/O PORT BASE ADDRESS DIAGENABLE .EQU TRUE ; ENABLES OUTPUT TO 8 BIT LED DIAGNOSTIC PORT DIAGPORT .EQU $0D ; DIAGNOSTIC PORT ADDRESS DIAGDISKIO .EQU TRUE ; ENABLES DISK I/O ACTIVITY ON DIAGNOSTIC LEDS diff --git a/Source/HBIOS/ide.asm b/Source/HBIOS/ide.asm index 5268b447..7bda2401 100644 --- a/Source/HBIOS/ide.asm +++ b/Source/HBIOS/ide.asm @@ -4,7 +4,6 @@ ;============================================================================= ; ; TODO: -; - FIX SCALER CONSTANT ; - GOPARTNER NEEDS TO HANDLE "NO PARTNER" CONDITION ; - IMPLEMENT H/W PROBES FOR DIO AND DIDE ; @@ -126,9 +125,13 @@ IDE_REG_DRVADR .EQU $0F ; DRIVE ADDRESS REGISTER (R) ; ; COMMAND BYTES ; +IDE_CIDE_NOP .EQU $00 +IDE_CIDE_DEVRES .EQU $08 IDE_CIDE_RECAL .EQU $10 IDE_CIDE_READ .EQU $20 IDE_CIDE_WRITE .EQU $30 +IDE_CIDE_DEVDIAG .EQU $90 +IDE_CIDE_IDPKTDEV .EQU $A1 IDE_CIDE_IDDEV .EQU $EC IDE_CIDE_SETFEAT .EQU $EF ; @@ -153,6 +156,7 @@ IDE_STIOERR .EQU -4 IDE_STRDYTO .EQU -5 IDE_STDRQTO .EQU -6 IDE_STBSYTO .EQU -7 +IDE_STNOTSUP .EQU -8 ; ; DRIVE SELECTION BYTES (FOR USE IN DRIVE/HEAD REGISTER) ; @@ -290,15 +294,18 @@ IDE_DEV2S: ; DEVICE 2, SLAVE ; ; THE IDE_WAITXXX FUNCTIONS ARE BUILT TO TIMEOUT AS NEEDED SO DRIVER WILL ; NOT HANG IF DEVICE IS UNRESPONSIVE. DIFFERENT TIMEOUTS ARE USED DEPENDING -; ON THE SITUATION. GENERALLY, THE FAST TIMEOUT IS USED TO PROBE FOR DEVICES -; USING FUNCTIONS THAT PERFORM NO I/O. OTHERWISE THE NORMAL TIMEOUT IS USED. -; IDE SPEC ALLOWS FOR UP TO 30 SECS MAX TO RESPOND. IN PRACTICE, THIS IS WAY -; TOO LONG, BUT IF YOU ARE USING A VERY OLD DEVICE, THESE TIMEOUTS MAY NEED TO -; BE ADJUSTED. NOTE THAT THESE ARE BYTE VALUES, SO YOU CANNOT EXCEED 255. -; THE TIMEOUTS ARE IN UNITS OF .05 SECONDS. -; -IDE_TONORM .EQU 200 ; NORMAL TIMEOUT IS 10 SECS -IDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS +; ON THE SITUATION. THE SLOW TIMEOUT IS USED TO WAIT FOR A DEVICE TO +; BECOME READY AFTER A HARD RESET (SPIN UP, ETC.). THE NORMAL TIMEOUT +; IS USED DURING NORMAL OPERATION FOR ALL I/O OPERATIONS WHICH SHOULD +; OCCUR PRETTY FAST. NOTE THAT THE ATA SPEC ALLOWS UP TO 30 SECONDS +; FOR DEVICES TO RESPOND. WE ARE USING MUCH MORE AGGRESSIVE VALUES +; BASED ON REAL WORLD EXPERIENCE. +; THE PICO TIMEOUT (TOPICO) IS A SPECIAL TIMEOUT FOR THE RC2014 SD +; PICO TO WAIT FOR THE PICO DEVICE TO INITIALIZE. +; +IDE_TOSLOW .EQU 200 ; SLOW TIMEOUT IS 20 SECS +IDE_TONORM .EQU 5 ; NORMAL TIMEOUT IS 0.55 SECS +IDE_TOPICO .EQU 50 ; RC2014 SD PICO (5 SECONDS) ; ;============================================================================= ; INITIALIZATION ENTRY POINT @@ -306,9 +313,12 @@ IDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS ; IDE_INIT: ; COMPUTE CPU SPEED COMPENSATED TIMEOUT SCALER - ; AT 1MHZ, THE SCALER IS 218 (50000US / 229TS = 218) - ; SCALER IS THEREFORE 218 * CPU SPEED IN MHZ - LD DE,961 ; LOAD SCALER FOR 1MHZ + ; ONE INTERNAL LOOP IN WAITBSY IS 180TS. ON A 1 MHZ CPU, 1 TS + ; TAKES 1NS. SO 1/10 SECOND IS 100000 TS ON A 1 MHZ CPU. + ; SINCE 1 INTERNAL LOOP IS 180 TS, IT TAKES 100000 / 180 = 556 + ; INTERNAL LOOPS FOR 1/10 SECOND. SO, WE WANT TO USE + ; 523 * CPU MHZ FOR INTERNAL LOOP COUNT. + LD DE,556 ; LOAD SCALER FOR 1MHZ LD A,(CB_CPUMHZ) ; LOAD CPU SPEED IN MHZ CALL MULT8X16 ; HL := DE * A LD (IDE_TOSCALER),HL ; SAVE IT @@ -359,7 +369,7 @@ IDE_INIT2A: LD DE,IDE_STR_NOHW ; NOT PRESENT MESSAGE CALL WRITESTR ; DISPLAY IT JR IDE_INIT4 ; SKIP CFG ENTRY -; +; IDE_INIT3: CALL IDE_RESET ; RESET THE BUS CALL IDE_INIT5 ; DETECT/INIT MASTER @@ -367,7 +377,7 @@ IDE_INIT3: CALL IDE_GOPARTNER ; SWITCH IY TO PARTNER CFG CALL IDE_INIT5 ; DETECT/INIT SLAVE POP IY ; RESTORE CFG PTR -; +; IDE_INIT4: LD DE,IDE_CFGSIZ ; SIZE OF CFG TABLE ENTRY ADD IY,DE ; BUMP POINTER @@ -385,13 +395,28 @@ IDE_INIT5: PUSH IY ; CFG ENTRY POINTER POP DE ; COPY TO DE CALL DIO_ADDENT ; ADD ENTRY TO GLOBAL DISK DEV TABLE +; + ; START PRINTING DEVICE INFO + CALL IDE_PRTPREFIX ; PRINT DEVICE PREFIX + LD A,(IY+IDE_TYPE) + LD DE,IDE_STR_TYPEATA + CP IDE_TYPEATA + CALL Z,WRITESTR + LD DE,IDE_STR_TYPEATAPI + CP IDE_TYPEATAPI + CALL Z,WRITESTR ; ; CHECK FOR BAD STATUS LD A,(IY+IDE_STAT) ; GET STATUS OR A ; SET FLAGS - JP NZ,IDE_PRTSTAT ; EXIT VIA PRINT STATUS + JP Z,IDE_INIT6 + CALL PC_SPACE + JP NZ,IDE_PRTSTATSTR ; EXIT VIA PRINT STATUS STRING ; - CALL IDE_PRTPREFIX ; PRINT DEVICE PREFIX +IDE_INIT6: + LD A,(IY+IDE_TYPE) ; GET DEVICE TYPE + CP IDE_TYPEATA ; ATA? + RET NZ ; IF NOT, THEN DONE ; LD DE,IDE_STR_8BIT BIT 1,(IY+IDE_ACC) ; 8 BIT ACCESS? @@ -555,26 +580,12 @@ IDE_DEVICE1: IDE_MEDIA: LD A,E ; GET FLAGS OR A ; SET FLAGS - JR Z,IDE_MEDIA2 ; JUST REPORT CURRENT STATUS AND MEDIA + JR Z,IDE_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA ; - ; GET CURRENT STATUS - LD A,(IY+IDE_STAT) ; GET STATUS - OR A ; SET FLAGS - JR NZ,IDE_MEDIA1 ; ERROR ACTIVE, GO RIGHT TO RESET -; - ; USE IDENTIFY COMMAND TO CHECK DEVICE - LD HL,IDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),IDE_TOFAST ; USE FAST TIMEOUT DURING IDENTIFY COMMAND - CALL IDE_SELUNIT ; HARDWARE SELECTION OF TARGET UNIT - CALL IDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND - LD HL,IDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),IDE_TONORM ; BACK TO NORMAL TIMEOUT - JR Z,IDE_MEDIA2 ; IF SUCCESS, BYPASS RESET + ;CALL IDE_RESET ; RESET IDE INTERFACE + CALL IDE_INITUNIT ; RE-INITIALIZE UNIT ; IDE_MEDIA1: - CALL IDE_RESET ; RESET IDE INTERFACE -; -IDE_MEDIA2: LD A,(IY+IDE_STAT) ; GET STATUS OR A ; SET FLAGS LD D,0 ; NO MEDIA CHANGE DETECTED @@ -655,6 +666,32 @@ IDE_SETFEAT: ; ; ; +IDE_NOP: +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" NOP$") +#ENDIF + LD A,(IDE_DRVHD) + ;OUT (IDE_IO_DRVHD),A + CALL IDE_OUT + .DB IDE_REG_DRVHD +#IF (IDETRACE >= 3) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF +; + ; EXECUTE THE NOP COMMAND, BUT DON'T WAIT FOR DRDY, JUST + ; MAKE SURE BUSY IS CLEAR. THIS COMMAND IS USED DURING + ; DEVICE DETECTION/INITIALIZATION AND ATAPI DEVICES WILL + ; NOT ASSERT DRDY AFTER RESET. + LD A,IDE_CIDE_NOP ; CMD = NOP + LD (IDE_CMD),A ; SAVE IT + CALL IDE_WAITBSY + RET NZ + JP IDE_RUNCMD1 ; RUN COMMAND AND EXIT +; +; +; IDE_IDENTIFY: #IF (IDETRACE >= 3) CALL IDE_PRTPREFIX @@ -672,6 +709,40 @@ IDE_IDENTIFY: LD (IDE_CMD),A CALL IDE_RUNCMD RET NZ + + CALL IDE_IN + .DB IDE_REG_STAT + BIT 3,A ; IS DRQ SET? + JP Z,IDE_NOMEDIA +; + LD HL,HB_WRKBUF + JP IDE_GETBUF ; EXIT THRU BUFRD +; +; +; +IDE_IDENTIFYPACKET: +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" IDPKTDEV$") +#ENDIF + LD A,(IDE_DRVHD) + ;OUT (IDE_IO_DRVHD),A + CALL IDE_OUT + .DB IDE_REG_DRVHD +#IF (IDETRACE >= 3) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF + LD A,IDE_CIDE_IDPKTDEV + LD (IDE_CMD),A + CALL IDE_RUNCMD + RET NZ +; + CALL IDE_IN + .DB IDE_REG_STAT + BIT 3,A ; IS DRQ SET? + JP Z,IDE_NOMEDIA +; LD HL,HB_WRKBUF JP IDE_GETBUF ; EXIT THRU BUFRD ; @@ -766,10 +837,6 @@ IDE_SETADDR: #ENDIF CALL IDE_OUT .DB IDE_REG_COUNT -;;; -;;#IF (DSKYENABLE) -;; CALL IDE_DSKY -;;#ENDIF ; RET ; @@ -781,6 +848,7 @@ IDE_RUNCMD: CALL IDE_WAITRDY ; WAIT FOR DRIVE READY RET NZ ; BAIL OUT ON TIMEOUT ; +IDE_RUNCMD1: LD A,(IDE_CMD) ; GET THE COMMAND #IF (IDETRACE >= 3) CALL PC_SPACE @@ -937,11 +1005,14 @@ IDE_RESET: PRTS(" RESET$") #ENDIF ; -;#IF (IDEMODE == IDEMODE_MK4) +; HARD RESET +; +; RESET LINE IS NORMALLY PULSED AT POWER ON. HOWEVER, THIS IS NOT +; DONE FOR MK4 BUILT-IN IDE PORT, SO WE DO IT NOW. ; LD A,(IY+IDE_MODE) ; GET MODE CP IDEMODE_MK4 ; MK4? - JR NZ,IDE_RESET1 ; IF NOT, BYPASS + JR NZ,IDE_RESET2 ; IF NOT, BYPASS ; ; USE HARDWARE RESET LINE #IF (IDETRACE >= 3) @@ -960,66 +1031,59 @@ IDE_RESET: LD DE,20 CALL VDELAY ; -IDE_RESET1: +; SOME CF CARDS AND CF CARD EMULATORS NEED A LITTLE TIME TO +; "BOOT" THEIR INTERNAL ELECTRONICS, SO THEY CANNOT ASSERT BUSY +; IMMEDIATELY. A SMALL WAIT IS PERFORMED HERE TO GIVE SUCH DEVICES +; A BETTER CHANCE TO SUCCEED LATER. ; -;#ENDIF +;;; CALL LDELAY ; DELAY FOR SLAVE INIT + LD DE,150000 / 16 ; + CALL VDELAY ; SMALL DELAY +; + JR IDE_RESET3 ; SKIP SOFT RESET +; +; SOFT RESET ; -;#IF ((IDEMODE != IDEMODE_MK4) & (IDEMODE != IDEMODE_RC)) +; RC CANNOT ACCESS DEVICE CONTROL REG, SO SKIP THIS ; +IDE_RESET2: LD A,(IY+IDE_MODE) ; GET MODE - CP IDEMODE_MK4 ; MK4? - JR Z,IDE_RESET3 ; IF SO, BYPASS CP IDEMODE_RC ; RCBUS? - JR Z,IDE_RESET3 ; IF SO, BYPASS + JR Z,IDE_RESET4 ; IF SO, BYPASS ; ; INITIATE SOFT RESET #IF (IDETRACE >= 3) PRTS(" SOFT$") #ENDIF - LD A,%00001110 ; NO INTERRUPTS, ASSERT RESET BOTH DRIVES + LD A,%00001110 ; ASSERT RESET, NO INTERRUPTS ;OUT (IDE_IO_CTRL),A CALL IDE_OUT .DB IDE_REG_CTRL -; -IDE_RESET3: -; -;#ENDIF -; - LD DE,2 ; DELAY 32US (SPEC IS >= 25US) + LD DE,20 ; DELAY 320US (SPEC IS >= 25US) CALL VDELAY ; -;#IF (IDEMODE != IDEMODE_RC) +IDE_RESET3: ; - LD A,(IY+IDE_MODE) ; GET MODE - CP IDEMODE_RC ; RCBUS? - JR Z,IDE_RESET4 ; IF SO, BYPASS +; CONFIGURE OPERATION AND END SOFT RESET ; - ; CONFIGURE OPERATION AND END SOFT RESET #IF (IDETRACE >= 3) PRTS(" CONFIG$") #ENDIF - LD A,%00001010 ; NO INTERRUPTS, DEASSERT RESET + LD DE,20 ; DELAY 320US (SPEC IS >= 25US) + CALL VDELAY + LD A,%00001010 ; DEASSERT RESET, NO INTERRUPTS ;OUT (IDE_IO_CTRL),A ; PUSH TO REGISTER CALL IDE_OUT .DB IDE_REG_CTRL ; IDE_RESET4: -; -;#ENDIF -; -; SPEC ALLOWS UP TO 450MS FOR DEVICES TO ASSERT THEIR PRESENCE -; VIA -DASP. I ENCOUNTER PROBLEMS LATER ON IF I DON'T WAIT HERE -; FOR THAT TO OCCUR. THUS FAR, IT APPEARS THAT 150MS IS SUFFICIENT -; FOR ANY DEVICE ENCOUNTERED. MAY NEED TO EXTEND BACK TO 500MS -; IF A SLOWER DEVICE IS ENCOUNTERED. -; - ;LD DE,500000/16 ; ~500MS - LD DE,150000/16 ; ~???MS - CALL VDELAY + LD HL,IDE_TONORM ; NORMAL TIMEOUT NOW + LD (IDE_TIMEOUT),HL ; AND RESTORE IT ; ; INITIALIZE THE INDIVIDUAL UNITS (MASTER AND SLAVE). ; BASED ON TESTING, IT APPEARS THAT THE MASTER UNIT MUST ; BE DONE FIRST OR THIS BEHAVES BADLY. +; PUSH IY ; SAVE CFG PTR BIT 0,(IY+IDE_ACC) ; MASTER? CALL Z,IDE_GOPARTNER ; IF NOT, SWITCH TO MASTER @@ -1037,14 +1101,10 @@ IDE_INITUNIT: CALL IDE_SELUNIT ; SELECT UNIT RET NZ ; ABORT IF ERROR - LD HL,IDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),IDE_TONORM ; SET NORMAL TIMEOUT - CALL IDE_PROBE ; DO PROBE RET NZ ; JUST RETURN IF NOTHING THERE - CALL IDE_INITDEV ; IF FOUND, ATTEMPT TO INIT DEVICE - RET ; DONE + JP IDE_INITDEV ; EXIT VIA INITDEV ; ; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT ; UNIT IS SPECIFIED IN IDE_UNIT @@ -1059,9 +1119,15 @@ IDE_SELUNIT: BIT 0,(IY+IDE_ACC) ; MASTER? JR Z,IDE_SELUNIT1 ; HANDLE SLAVE LD A,IDE_DRVMASTER ; MASTER +#IF (IDETRACE >= 3) + PRTS(" MASTER$") +#ENDIF JR IDE_SELUNIT2 IDE_SELUNIT1: LD A,IDE_DRVSLAVE ; SLAVE +#IF (IDETRACE >= 3) + PRTS(" SLAVE$") +#ENDIF IDE_SELUNIT2: LD (IDE_DRVHD),A ; SAVE IT XOR A ; SUCCESS @@ -1082,6 +1148,13 @@ IDE_PROBE: CALL IDE_PRTPREFIX PRTS(" PROBE$") ; LABEL FOR IO ADDRESS #ENDIF +; +#IF (IDETRACE >= 3) + CALL IDE_IN + .DB IDE_REG_STAT + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF ; ; SELECT DEVICE (MASTER/SLAVE) LD A,(IDE_DRVHD) @@ -1094,14 +1167,20 @@ IDE_PROBE: #ENDIF CALL DELAY ; DELAY ~16US ; -; IF WE GET HERE AND THE INTERFACE IS STILL INITIALIZING, WE NEED TO -; WAIT UNTIL THE INTERFACE IS READY. PER SPEC, THE STATUS REGISTER -; WILL BE EXACTLY $80 IN THIS SCENARIO. SINCE $80 IS UNLIKELY -; FOR A FLOATING PORT VALUE, WE INTERPRET THIS VALUE TO MEAN HARDWARE -; IS THERE AND INIT IS IN PROGRESS, SO IT WILL BE IMPOSSIBLE TO -; INTERROGATE REGISTERS YET. SINCE WE NOW BELIEVE THAT SOME HARDWARE -; IS RESPONDING, IT IS SAFE (AND NECESSARY) TO WAIT FOR BUSY TO -; CLEAR. +; THE RC2014 SD PICO TAKES A FEW SECONDS TO INITIALIZE. DURING THIS +; TIME IT APPEARS TO RETURN $00. BELOW IS A SPECIAL CASE FOR RC2014 +; TO WAIT FOR THIS DEVICE TO INITIALIZE. WE ONLY DO THIS IF THE +; MASTER DEVICE IS BEING PROBED. WHEN THE SLAVE DEVICE IS +; SELECTED, THE SD PICO WILL ALWAYS RETURN ZERO AND CAUSE AN +; UNNECESSARY DELAY. +; + LD A,(IY+IDE_MODE) ; GET MODE BITS + CP IDEMODE_RC ; RCBUS? + JR NZ,IDE_PROBE0 ; IF NOT, BYPASS +; + LD A,(IDE_DRVHD) ; GET CURRENT SETTING + BIT 4,A ; TEST SLAVE BIT + JR NZ,IDE_PROBE0 ; IF SO, BYPASS ; CALL IDE_IN .DB IDE_REG_STAT @@ -1109,8 +1188,60 @@ IDE_PROBE: CALL PC_SPACE CALL PRTHEXBYTE #ENDIF + OR A ; SET FLAGS + JR NZ,IDE_PROBE0 ; SKIP IF NOT $00 +; +#IF (IDETRACE >= 3) + PRTS(" WAIT$") +#ENDIF + LD HL,(IDE_TIMEOUT) ; GET CURRENT TIMEOUT + PUSH HL ; SAVE IT + LD HL,IDE_TOPICO ; SLOW TIMEOUT FOR THIS + LD (IDE_TIMEOUT),HL ; SET IT + CALL IDE_WAIT00 ; WAIT FOR $00 TO CLEAR + POP HL ; RECOVER TIMEOUT + LD (IDE_TIMEOUT),HL ; SET IT +; +; IF WE GET HERE AND THE DRIVE IS STILL INITIALIZING, WE NEED TO +; WAIT UNTIL THE DRIVE IS READY. IN THIS CASE BUSY *WILL* BE HIGH. +; BASED ON TESTING, DRDY AND DSC VALUES VARY. EVERYTHING ELSE SEEMS +; TO BE ZERO. SO, WE FILTER OUT DRDY & DSC, THEN LOOK FOR BUSY=1 +; AND ALL ELSE ZERO. THIS GENERALLY AVOIDS VALUES THAT ARE TYPICAL +; FOR FLOATING PORTS AND SO CAN BE USED TO DETERMINE IF WE NEED TO +; WAIT FOR THE DEVICE TO BE READY. THIS WAIT IS MANDATORY BECAUSE +; SOME (IF NOT ALL) DEVICES WILL NOT PERSIST REGISTER VALUES UNTIL +; THE DRIVE IS READY. +; +IDE_PROBE0: + CALL IDE_IN + .DB IDE_REG_STAT +#IF (IDETRACE >= 3) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF +; + AND %10101111 ; FILTER OUT DRDY & DSC CP $80 ; INIT IN PROGRESS? - CALL Z,IDE_WAITBSY ; WAIT FOR BUSY TO CLEAR + JR NZ,IDE_PROBE1 ; IF NOT, SKIP AHEAD +; +#IF (IDETRACE >= 3) + PRTS(" WAIT$") +#ENDIF +; + LD HL,(IDE_TIMEOUT) ; GET CURRENT TIMEOUT + PUSH HL ; SAVE IT + LD HL,IDE_TOSLOW ; SLOW TIMEOUT FOR THIS + LD (IDE_TIMEOUT),HL ; SET IT + CALL IDE_WAITBSY ; WAIT FOR BUSY TO CLEAR + POP HL ; RECOVER TIMEOUT + LD (IDE_TIMEOUT),HL ; SET IT +; +#IF (IDETRACE >= 3) + CALL IDE_IN + .DB IDE_REG_STAT + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF ; ; TEST FOR PRESENCE OF IDE REGISTERS. USE LBA0/1 TO SEE ; IF VALUE CAN BE PERSISTED. THE USE OF BOTH LBA0 AND LBA1 @@ -1118,11 +1249,12 @@ IDE_PROBE: ; PPI ITSELF WILL PERSIST THE LAST VALUE WRITTEN, SO WE USE ; MULTIPLE REGISTERS TO WORK AROUND THIS. ; +IDE_PROBE1: ; $AA -> LBA0 LD A,$AA CALL IDE_OUT .DB IDE_REG_LBA0 -; +; ; $55 => LBA1 LD A,$55 CALL IDE_OUT @@ -1152,43 +1284,34 @@ IDE_PROBE: CALL IDE_REGDUMP #ENDIF ; - CALL IDE_WAITBSY ; WAIT FOR BUSY TO CLEAR - JP NZ,IDE_NOMEDIA ; CONVERT TIMEOUT TO NO MEDIA AND RETURN + XOR A + RET +; +; (RE)INITIALIZE DEVICE +; +IDE_INITDEV: ; #IF (IDETRACE >= 3) - CALL IDE_REGDUMP + CALL IDE_PRTPREFIX + PRTS(" INITDEV$") ; LABEL FOR IO ADDRESS #ENDIF ; -; IF THE INTERFACE HAS A MASTER AND NO SLAVE, THEN THE ABOVE CHECKS -; MAY ALL SUCCEED WHEN PROBING FOR THE SLAVE. HOWEVER, THE STATUS -; BYTE FOR THE SLAVE WILL REMAIN $00, SO WE LOOK FOR THAT VALUE AS A -; FINAL WAY TO DETECT NO MEDIA. +; IF THE IDE STATUS BYTE IS $00, WE HAVE EITHER A NON-PRESENT SLAVE +; OR AN ATAPI DEVICE. TO DIFFERENTIATE THESE POSSIBILITIES, WE RUN +; A NOP COMMAND. IF WE HAVE AN ATAPI DEVICE, THIS WILL CAUSE THE +; STATUS BYTE TO BE "NORMAL" (NON-ZERO). IF THE STATUS IS STILL +; ZERO, WE ABORT WITH A NO MEDIA STATUS. NOTE THAT THE NOP COMMAND +; RETURNS A COMMAND ERROR BY DESIGN. WE JUST IGNORE THE ERROR. ; - ; CHECK STATUS - ;IN A,(IDE_IO_STAT) ; GET STATUS + CALL IDE_NOP CALL IDE_IN .DB IDE_REG_STAT -#IF (IDETRACE >= 3) - CALL PC_SPACE - CALL PRTHEXBYTE ; IF DEBUG, PRINT STATUS -#ENDIF - OR A ; SET FLAGS TO TEST FOR ZERO + OR A JP Z,IDE_NOMEDIA ; - ; ASSUME ATA DEVICE FOR NOW, RECORD TYPE AND RETURN SUCCESS - LD A,IDE_TYPEATA ; TYPE = ATA - LD (IY+IDE_TYPE),A ; SET IT IN INSTANCE DATA - XOR A ; SIGNAL SUCCESS - RET ; DONE, NOTE THAT A=0 AND Z IS SET -; -; (RE)INITIALIZE DEVICE -; -IDE_INITDEV: -; - LD A,(IY+IDE_TYPE) ; GET THE DEVICE TYPE - OR A ; SET FLAGS - JP Z,IDE_NOMEDIA ; EXIT SETTING NO MEDIA STATUS +; WE NEED TO SETUP 8-BIT MODE BEFORE DOING ANYTHING ELSE ; +IDE_INITDEV0A: BIT 1,(IY+IDE_ACC) ; 8 BIT ACCESS? JR Z,IDE_INITDEV0 ; NO, DO 16 BIT INIT LD A,IDE_FEAT_ENABLE8BIT ; FEATURE VALUE = ENABLE 8-BIT PIO @@ -1206,10 +1329,14 @@ IDE_INITDEV0: IDE_INITDEV00: ; CALL IDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND - RET NZ ; BAIL OUT ON ERROR + JR NZ,IDE_INITDEVP ; ON ERROR, TRY PACKET DEVICE +; + ; DECLARE WE ARE ATA + LD A,IDE_TYPEATA ; OTHERWISE TYPE=ATA + LD (IY+IDE_TYPE),A ; SET IT IN INSTANCE DATA ; LD DE,HB_WRKBUF ; POINT TO BUFFER -#IF (IDETRACE >= 3) +#IF (IDETRACE >= 4) CALL DUMP_BUFFER ; DUMP IT IF DEBUGGING #ENDIF ; @@ -1229,38 +1356,15 @@ IDE_INITDEV00: CALL PRTHEXWORD #ENDIF ; -; SEE PAGE 114 OF CF+ & CF SPECIFICATION REV. 3.0 FOR CF CARD -; SIGNATURE VALUES. ALL OF THE BELOW ARE DOCUMENTED THERE EXCEPT -; $045A WHICH IS A VALUE DISCOVERED ON A CF<->SD CARD ADAPTER. -; -; SIGNATURE $045A IS NOT LISTED IN THE CF SPEC. IT WAS ADDED BECAUSE -; IT WAS SEEN IN THE WILD ON A CF-SD ADAPTER. HOWEVER IT HAS NOW -; ALSO BEEN SEEN ON A SPINNING HARD DISK. SINCE IT IS AMBIGUOUS, I -; WILL CONSIDER IT TO BE A HARD DISK. -; - LD BC,$848A ; STANDARD CF CARD SIGNATURE %1000 1111 1000 1010 - CALL IDE_INITDEV000 ; TEST & SET - LD BC,$044A ; ALT SIG FOR CF NON-REMOVABLE %0000 0100 0100 1010 - CALL IDE_INITDEV000 ; TEST & SET - ;LD BC,$045A ; ?ALT SIG FOR CF NON-REMOVABLE %0000 0100 0101 1010 - ;CALL IDE_INITDEV000 ; TEST & SET - LD BC,$0040 ; ALT SIG FOR CF NON-REMOVABLE %0000 0000 0100 0000 - CALL IDE_INITDEV000 ; TEST & SET - JR IDE_INITDEV1 ; CONTINUE INIT -; -IDE_INITDEV000: - ; CHECK IF FIRST WORD OF IDENTIFY DATA MATCHES VALUE IN BC - ; AND SET CF FLAG IF SO - LD HL,(HB_WRKBUF) ; FIRST WORD OF IDENTIFY DATA - OR A ; CLEAR CARRY - SBC HL,BC ; COMPARE - RET NZ ; ABORT IF NOT EQUAL + ; DETERMINE IF COMPACTFLASH MEDIA + LD A,(HB_WRKBUF+(83*2)) ; LOW BYTE OF WORD 83 + BIT 2,A ; TEST CFA FEATURE SET BIT + JR Z,IDE_INITDEV1 ; IF NOT, SKIP SET 0,(IY+IDE_MED) ; ELSE SET FLAGS BIT FOR CF MEDIA - RET ; AND RETURN ; IDE_INITDEV1: ; DETERMINE IF LBA CAPABLE - LD A,(HB_WRKBUF+98+1) ; GET BYTE WITH LBA BIT FROM BUFFER + LD A,(HB_WRKBUF+98+1) ; HIGH BYTE OF WORD 49 BIT 1,A ; CHECK THE LBA BIT JR Z,IDE_INITDEV2 ; NOT SET, BYPASS SET 1,(IY+IDE_MED) ; SET FLAGS BIT FOR LBA @@ -1277,12 +1381,39 @@ IDE_INITDEV2: POP BC ; RECOVER POINTER TO CAPACITY ENTRY CALL ST32 ; SAVE CAPACITY ; - ; RESET CARD STATUS TO 0 (OK) + ; RECORD STATUS OK XOR A ; A := 0 (STATUS = OK) LD (IY+IDE_STAT),A ; SAVE IT ; RET ; RETURN, A=0, Z SET ; +; +; +IDE_INITDEVP: + CALL IDE_IDENTIFYPACKET ; EXECUTE IDENTIFY COMMAND + RET NZ ; BAIL OUT ON ERROR +; + ; DECLARE WE ARE ATAPI + LD A,IDE_TYPEATAPI ; OTHERWISE TYPE=ATAPI + LD (IY+IDE_TYPE),A ; SET IT IN INSTANCE DATA +; + LD DE,HB_WRKBUF ; POINT TO BUFFER +#IF (IDETRACE >= 4) + CALL DUMP_BUFFER ; DUMP IT IF DEBUGGING +#ENDIF +; + LD (IY+IDE_MED),0 ; CLEAR FLAGS +; + ; DONE FOR NOW, ATAPI NOT INPLEMENTED +; + ; RETURN NOT SUPPORTED STATUS + JP IDE_NOTSUP ; NOT SUPPORTED +; +; ; RECORD STATUS OK +; XOR A ; A := 0 (STATUS = OK) +; LD (IY+IDE_STAT),A ; SAVE IT +; RET +; ; SWITCH IY POINTER FROM CURRENT UNIT CFG TO PARTNER UNIT CFG ; IDE_GOPARTNER: @@ -1328,7 +1459,7 @@ IDE_WAITRDY2: ; ; IDE_WAITDRQ: - LD A,(IDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS + LD A,(IDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS LD B,A ; PUT IN OUTER LOOP VAR IDE_WAITDRQ1: LD DE,(IDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR @@ -1350,14 +1481,14 @@ IDE_WAITDRQ2: ; ; IDE_WAITBSY: - LD A,(IDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS + LD A,(IDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS LD B,A ; PUT IN OUTER LOOP VAR IDE_WAITBSY1: LD DE,(IDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR IDE_WAITBSY2: - ;IN A,(IDE_IO_STAT) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER ; 11TS - CALL IDE_IN ; 17TS + ???TS - .DB IDE_REG_STAT ; 0TS + ;IN A,(IDE_IO_STAT) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER + CALL IDE_IN ; 17TS + 121TS + .DB IDE_REG_STAT LD C,A ; SAVE IT ; 4TS AND %10000000 ; TO FILL (OR READY TO FILL) ; 7TS RET Z ; 5TS @@ -1366,25 +1497,45 @@ IDE_WAITBSY2: OR E ; 4TS JR NZ,IDE_WAITBSY2 ; 12TS DJNZ IDE_WAITBSY1 ; ----- - JP IDE_BSYTO ; EXIT WITH BSYTO ERR ; ??TS + JP IDE_BSYTO ; EXIT WITH BSYTO ERR ; 180 +; +; +; +IDE_WAIT00: + LD A,(IDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS + LD B,A ; PUT IN OUTER LOOP VAR +IDE_WAIT001: + LD DE,(IDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR +IDE_WAIT002: + ;IN A,(IDE_IO_STAT) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER + CALL IDE_IN + .DB IDE_REG_STAT + OR A ; SET FLAGS + RET NZ ; DONE IF NOT ZERO + DEC DE + LD A,D + OR E + JR NZ,IDE_WAIT002 + DJNZ IDE_WAIT001 + RET ; DONE ; ; READ A VALUE FROM THE DEVICE POINTED TO BY IY AND RETURN IT IN A -; +; IDE_IN: - EX (SP),HL ; GET PARM POINTER - PUSH BC - LD A,(HL) - INC HL - LD C,(IY+IDE_IOBASE) - ADD A,C - LD C,A - IN A,(C) - POP BC - EX (SP),HL ; RESTORE STACK - RET + EX (SP),HL ; GET PARM POINTER ; 19TS + PUSH BC ; 11TS + LD A,(HL) ; 7TS + INC HL ; 6TS + LD C,(IY+IDE_IOBASE) ; 19TS + ADD A,C ; 4TS + LD C,A ; 4TS + IN A,(C) ; 12TS + POP BC ; 10TS + EX (SP),HL ; RESTORE STACK ; 19TS + RET ; 10TS +; ; ---- +; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY ; 121TS ; -; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY -; IDE_OUT: EX (SP),HL ; GET PARM POINTER PUSH BC @@ -1434,6 +1585,10 @@ IDE_BSYTO: LD A,IDE_STBSYTO JR IDE_ERR ; +IDE_NOTSUP: + LD A,IDE_STNOTSUP + JR IDE_ERR +; IDE_ERR: LD (IY+IDE_STAT),A ; SAVE NEW STATUS ; @@ -1451,48 +1606,64 @@ IDE_PRTERR: RET Z ; DONE IF NO ERRORS ; FALL THRU TO IDE_PRTSTAT ; -; PRINT STATUS STRING (STATUS NUM IN A) +; PRINT FULL DEVICE STATUS LINE ; IDE_PRTSTAT: PUSH AF PUSH DE PUSH HL LD A,(IY+IDE_STAT) + CP IDE_STINVUNIT + JR Z,IDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE + CALL IDE_PRTPREFIX ; PRINT UNIT PREFIX + JR IDE_PRTSTAT3 +IDE_PRTSTAT2: + CALL NEWLINE + PRTS("IDE:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT +IDE_PRTSTAT3: + CALL PC_SPACE ; FORMATTING + CALL IDE_PRTSTATSTR + POP HL + POP DE + POP AF + RET +; +; PRINT STATUS STRING +; +IDE_PRTSTATSTR: + PUSH AF + PUSH DE + LD A,(IY+IDE_STAT) OR A LD DE,IDE_STR_STOK - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STINVUNIT - JR Z,IDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STNOMEDIA - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STCMDERR - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STIOERR - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STRDYTO - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STDRQTO - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 INC A LD DE,IDE_STR_STBSYTO - JR Z,IDE_PRTSTAT1 + JR Z,IDE_PRTSTATSTR1 + INC A + LD DE,IDE_STR_STNOTSUP + JR Z,IDE_PRTSTATSTR1 LD DE,IDE_STR_STUNK -IDE_PRTSTAT1: - CALL IDE_PRTPREFIX ; PRINT UNIT PREFIX - JR IDE_PRTSTAT3 -IDE_PRTSTAT2: - CALL NEWLINE - PRTS("IDE:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT -IDE_PRTSTAT3: - CALL PC_SPACE ; FORMATTING +IDE_PRTSTATSTR1: CALL WRITESTR - POP HL POP DE POP AF RET @@ -1536,30 +1707,6 @@ IDE_PRTPREFIX1: CALL PC_COLON POP AF RET -;;; -;;; -;;; -;;#IF (DSKYENABLE) -;;IDE_DSKY: -;; LD HL,DSKY_HEXBUF ; POINT TO DSKY BUFFER -;; CALL IDE_IN -;; .DB IDE_REG_DRVHD -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL IDE_IN -;; .DB IDE_REG_CYLHI -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL IDE_IN -;; .DB IDE_REG_CYLLO -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL IDE_IN -;; .DB IDE_REG_SECT -;; LD (HL),A ; SAVE IN BUFFER -;; CALL DSKY_HEXOUT ; SEND IT TO DSKY -;; RET -;;#ENDIF ; ;============================================================================= ; STRING DATA @@ -1573,6 +1720,7 @@ IDE_STR_STIOERR .TEXT "IO ERROR$" IDE_STR_STRDYTO .TEXT "READY TIMEOUT$" IDE_STR_STDRQTO .TEXT "DRQ TIMEOUT$" IDE_STR_STBSYTO .TEXT "BUSY TIMEOUT$" +IDE_STR_STNOTSUP .TEXT "NOT SUPPORTED$" IDE_STR_STUNK .TEXT "UNKNOWN ERROR$" ; IDE_STR_NO .TEXT "NO$" @@ -1584,12 +1732,15 @@ IDE_STR_MODE_DIDE .TEXT "DIDE$" IDE_STR_MODE_MK4 .TEXT "MK4$" IDE_STR_MODE_RC .TEXT "RC$" ; +IDE_STR_TYPEATA .TEXT " ATA$" +IDE_STR_TYPEATAPI .TEXT " ATAPI$" +; ;============================================================================= ; DATA STORAGE ;============================================================================= ; IDE_TIMEOUT .DB IDE_TONORM ; WAIT FUNCS TIMEOUT IN TENTHS OF SEC -IDE_TOSCALER .DW CPUMHZ * 961 ; WAIT FUNCS SCALER FOR CPU SPEED +IDE_TOSCALER .DW CPUMHZ * 556 ; WAIT FUNCS SCALER FOR CPU SPEED ; IDE_CMD .DB 0 ; PENDING COMMAND TO PROCESS IDE_IOFNADR .DW 0 ; PENDING IO FUNCTION ADDRESS diff --git a/Source/HBIOS/ppide.asm b/Source/HBIOS/ppide.asm index f3f2fe6a..2894f891 100644 --- a/Source/HBIOS/ppide.asm +++ b/Source/HBIOS/ppide.asm @@ -4,7 +4,6 @@ ;============================================================================= ; ; TODO: -; - FIX SCALER CONSTANT ; - GOPARTNER NEEDS TO HANDLE "NO PARTNER" CONDITION ; ; NOTES: @@ -144,9 +143,13 @@ PPIDE_REG_DRVADR .EQU PPIDE_CTL_CS3 | $07 ; DRIVE ADDRESS REGISTER (R) ; ; COMMAND BYTES ; +PPIDE_CIDE_NOP .EQU $00 +PPIDE_CIDE_DEVRES .EQU $08 PPIDE_CMD_RECAL .EQU $10 PPIDE_CMD_READ .EQU $20 PPIDE_CMD_WRITE .EQU $30 +PPIDE_CIDE_DEVDIAG .EQU $90 +PPIDE_CIDE_IDPKTDEV .EQU $A1 PPIDE_CMD_IDDEV .EQU $EC PPIDE_CMD_SETFEAT .EQU $EF ; @@ -171,6 +174,7 @@ PPIDE_STIOERR .EQU -4 PPIDE_STRDYTO .EQU -5 PPIDE_STDRQTO .EQU -6 PPIDE_STBSYTO .EQU -7 +PPIDE_STNOTSUP .EQU -8 ; ; DRIVE SELECTION BYTES (FOR USE IN DRIVE/HEAD REGISTER) ; @@ -217,7 +221,7 @@ PPIDE_DEV0M: ; DEVICE 0, MASTER .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE0BASE ; DATALO - .DB PPIDE0BASE+2 ; CTL + .DB PPIDE0BASE+2 ; CTL .DB PPIDE0BASE+3 ; PPI .DW PPIDE_DEV0S ; PARTNER ; @@ -230,7 +234,7 @@ PPIDE_DEV0S: ; DEVICE 0, SLAVE .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE0BASE ; DATALO - .DB PPIDE0BASE+2 ; CTL + .DB PPIDE0BASE+2 ; CTL .DB PPIDE0BASE+3 ; PPI .DW PPIDE_DEV0M ; PARTNER ; @@ -247,7 +251,7 @@ PPIDE_DEV1M: ; DEVICE 1, MASTER .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE1BASE ; DATALO - .DB PPIDE1BASE+2 ; CTL + .DB PPIDE1BASE+2 ; CTL .DB PPIDE1BASE+3 ; PPI .DW PPIDE_DEV1S ; PARTNER ; @@ -260,7 +264,7 @@ PPIDE_DEV1S: ; DEVICE 1, SLAVE .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE1BASE ; DATALO - .DB PPIDE1BASE+2 ; CTL + .DB PPIDE1BASE+2 ; CTL .DB PPIDE1BASE+3 ; PPI .DW PPIDE_DEV1M ; PARTNER ; @@ -277,10 +281,10 @@ PPIDE_DEV2M: ; DEVICE 2, MASTER .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE2BASE ; DATALO - .DB PPIDE2BASE+2 ; CTL + .DB PPIDE2BASE+2 ; CTL .DB PPIDE2BASE+3 ; PPI .DW PPIDE_DEV2S ; PARTNER -; +; PPIDE_DEV2S: ; DEVICE 2, SLAVE .DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY) .DB 0 ; DEVICE STATUS @@ -290,7 +294,7 @@ PPIDE_DEV2S: ; DEVICE 2, SLAVE .DW 0,0 ; DEVICE CAPACITY .DW 0,0 ; CURRENT LBA .DB PPIDE2BASE ; DATALO - .DB PPIDE2BASE+2 ; CTL + .DB PPIDE2BASE+2 ; CTL .DB PPIDE2BASE+3 ; PPI .DW PPIDE_DEV2M ; PARTNER ; @@ -302,17 +306,17 @@ PPIDE_DEV2S: ; DEVICE 2, SLAVE ; .DB $FF ; END OF TABLE MARKER ; -; THE IDE_WAITXXX FUNCTIONS ARE BUILT TO TIMEOUT AS NEEDED SO DRIVER WILL +; THE PPIDE_WAITXXX FUNCTIONS ARE BUILT TO TIMEOUT AS NEEDED SO DRIVER WILL ; NOT HANG IF DEVICE IS UNRESPONSIVE. DIFFERENT TIMEOUTS ARE USED DEPENDING -; ON THE SITUATION. GENERALLY, THE FAST TIMEOUT IS USED TO PROBE FOR DEVICES -; USING FUNCTIONS THAT PERFORM NO I/O. OTHERWISE THE NORMAL TIMEOUT IS USED. -; IDE SPEC ALLOWS FOR UP TO 30 SECS MAX TO RESPOND. IN PRACTICE, THIS IS WAY -; TOO LONG, BUT IF YOU ARE USING A VERY OLD DEVICE, THESE TIMEOUTS MAY NEED TO -; BE ADJUSTED. NOTE THAT THESE ARE BYTE VALUES, SO YOU CANNOT EXCEED 255. -; THE TIMEOUTS ARE IN UNITS OF .05 SECONDS. +; ON THE SITUATION. THE SLOW TIMEOUT IS USED TO WAIT FOR A DEVICE TO +; BECOME READY AFTER A HARD RESET (SPIN UP, ETC.). THE NORMAL TIMEOUT +; IS USED DURING NORMAL OPERATION FOR ALL I/O OPERATIONS WHICH SHOULD +; OCCUR PRETTY FAST. NOTE THAT THE ATA SPEC ALLOWS UP TO 30 SECONDS +; FOR DEVICES TO RESPOND. WE ARE USING MUCH MORE AGGRESSIVE VALUES +; BASED ON REAL WORLD EXPERIENCE. ; -PPIDE_TONORM .EQU 200 ; NORMAL TIMEOUT IS 10 SECS -PPIDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS +PPIDE_TOSLOW .EQU 200 ; SLOW TIMEOUT IS 20 SECS +PPIDE_TONORM .EQU 5 ; NORMAL TIMEOUT IS 0.5 SECS ; ;============================================================================= ; INITIALIZATION ENTRY POINT @@ -320,9 +324,12 @@ PPIDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS ; PPIDE_INIT: ; COMPUTE CPU SPEED COMPENSATED TIMEOUT SCALER - ; AT 1MHZ, THE SCALER IS 218 (50000US / 229TS = 218) - ; SCALER IS THEREFORE 218 * CPU SPEED IN MHZ - LD DE,218 ; LOAD SCALER FOR 1MHZ + ; ONE INTERNAL LOOP IN WAITBSY IS 263TS. ON A 1 MHZ CPU, 1 TS + ; TAKES 1NS. SO 1/10 SECOND IS 100000 TS ON A 1 MHZ CPU. + ; SINCE 1 INTERNAL LOOP IS 263 TS, IT TAKES 100000 / 263 = 356 + ; INTERNAL LOOPS FOR 1/10 SECOND. SO, WE WANT TO USE + ; 356 * CPU MHZ FOR INTERNAL LOOP COUNT. + LD DE,380 ; LOAD SCALER FOR 1MHZ LD A,(CB_CPUMHZ) ; LOAD CPU SPEED IN MHZ CALL MULT8X16 ; HL := DE * A LD (PPIDE_TOSCALER),HL ; SAVE IT @@ -355,7 +362,7 @@ PPIDE_INIT2: LD DE,PPIDE_STR_NOPPI ; NO PPI MESSAGE CALL WRITESTR ; DISPLAY IT JR PPIDE_INIT4 ; SKIP CFG ENTRY -; +; PPIDE_INIT3: CALL PPIDE_RESET ; RESET THE BUS CALL PPIDE_INIT5 ; DETECT/INIT MASTER @@ -363,7 +370,7 @@ PPIDE_INIT3: CALL PPIDE_GOPARTNER ; SWITCH IY TO PARTNER CFG CALL PPIDE_INIT5 ; DETECT/INIT SLAVE POP IY ; RESTORE CFG PTR -; +; PPIDE_INIT4: LD DE,PPIDE_CFGSIZ ; SIZE OF CFG TABLE ENTRY ADD IY,DE ; BUMP POINTER @@ -381,13 +388,28 @@ PPIDE_INIT5: PUSH IY ; CFG ENTRY POINTER POP DE ; COPY TO DE CALL DIO_ADDENT ; ADD ENTRY TO GLOBAL DISK DEV TABLE +; + ; START PRINTING DEVICE INFO + CALL PPIDE_PRTPREFIX ; PRINT DEVICE PREFIX + LD A,(IY+PPIDE_TYPE) + LD DE,PPIDE_STR_TYPEATA + CP PPIDE_TYPEATA + CALL Z,WRITESTR + LD DE,PPIDE_STR_TYPEATAPI + CP PPIDE_TYPEATAPI + CALL Z,WRITESTR ; ; CHECK FOR BAD STATUS LD A,(IY+PPIDE_STAT) ; GET STATUS OR A ; SET FLAGS - JP NZ,PPIDE_PRTSTAT ; EXIT VIA PRINT STATUS + JP Z,PPIDE_INIT6 + CALL PC_SPACE + JP NZ,PPIDE_PRTSTATSTR ; EXIT VIA PRINT STATUS STRING ; - CALL PPIDE_PRTPREFIX ; PRINT DEVICE PREFIX +PPIDE_INIT6: + LD A,(IY+PPIDE_TYPE) ; GET DEVICE TYPE + CP PPIDE_TYPEATA ; ATA? + RET NZ ; IF NOT, THEN DONE ; LD DE,PPIDE_STR_8BIT BIT 1,(IY+PPIDE_ACC) ; 8 BIT ACCESS? @@ -426,9 +448,9 @@ PPIDE_INIT5: PPIDE_DETECT: ; ; TEST FOR PPI EXISTENCE - ; WE SETUP THE PPI TO WRITE, THEN WRITE A VALUE OF ZERO + ; WE SETUP THE PPI TO WRITE, THEN WRITE A VALUE OF $A5 ; TO PORT A (DATALO), THEN READ IT BACK. IF THE PPI IS THERE - ; THEN THE BUS HOLD CIRCUITRY WILL READ BACK THE ZERO. SINCE + ; THEN THE BUS HOLD CIRCUITRY WILL READ BACK THE $A5. SINCE ; WE ARE IN WRITE MODE, AN IDE CONTROLLER WILL NOT BE ABLE TO ; INTERFERE WITH THE VALUE BEING READ. ; @@ -437,14 +459,14 @@ PPIDE_DETECT: OUT (C),A ; WRITE IT ; LD C,(IY+PPIDE_DATALO) ; PPI PORT A, DATALO - XOR A ; VALUE ZERO + LD A,$A5 ; TEST VALUE OUT (C),A ; PUSH VALUE TO PORT IN A,(C) ; GET PORT VALUE #IF (PPIDETRACE >= 3) CALL PC_SPACE CALL PRTHEXBYTE #ENDIF - OR A ; SET FLAGS + CP $A5 ; CHECK FOR TEST VALUE RET ; AND RETURN ; ;============================================================================= @@ -564,26 +586,12 @@ PPIDE_DEVICE1: PPIDE_MEDIA: LD A,E ; GET FLAGS OR A ; SET FLAGS - JR Z,PPIDE_MEDIA2 ; JUST REPORT CURRENT STATUS AND MEDIA -; - ; GET CURRENT STATUS - LD A,(IY+PPIDE_STAT) ; GET STATUS - OR A ; SET FLAGS - JR NZ,PPIDE_MEDIA1 ; ERROR ACTIVE, GO RIGHT TO RESET + JR Z,PPIDE_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA ; - ; USE IDENTIFY COMMAND TO CHECK DEVICE - LD HL,PPIDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),PPIDE_TOFAST ; USE FAST TIMEOUT DURING IDENTIFY COMMAND - CALL PPIDE_SELUNIT ; HARDWARE SELECTION OF TARGET UNIT - CALL PPIDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND - LD HL,PPIDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),PPIDE_TONORM ; BACK TO NORMAL TIMEOUT - JR Z,PPIDE_MEDIA2 ; IF SUCCESS, BYPASS RESET + ;CALL PPIDE_RESET ; RESET IDE INTERFACE + CALL PPIDE_INITUNIT ; RE-INITIALIZE UNIT ; PPIDE_MEDIA1: - CALL PPIDE_RESET ; RESET IDE INTERFACE -; -PPIDE_MEDIA2: LD A,(IY+PPIDE_STAT) ; GET STATUS OR A ; SET FLAGS LD D,0 ; NO MEDIA CHANGE DETECTED @@ -666,6 +674,32 @@ PPIDE_SETFEAT: ; ; ; +PPIDE_NOP: +#IF (PPIDETRACE >= 3) + CALL PPIDE_PRTPREFIX + PRTS(" NOP$") +#ENDIF + LD A,(PPIDE_DRVHD) + ;OUT (PPIDE_IO_DRVHD),A + CALL PPIDE_OUT + .DB PPIDE_REG_DRVHD +#IF (PPIDETRACE >= 3) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF +; + ; EXECUTE THE NOP COMMAND, BUT DON'T WAIT FOR DRDY, JUST + ; MAKE SURE BUSY IS CLEAR. THIS COMMAND IS USED DURING + ; DEVICE DETECTION/INITIALIZATION AND ATAPI DEVICES WILL + ; NOT ASSERT DRDY AFTER RESET. + LD A,PPIDE_CIDE_NOP ; CMD = NOP + LD (PPIDE_CMD),A ; SAVE IT + CALL PPIDE_WAITBSY + RET NZ + JP PPIDE_RUNCMD1 ; RUN COMMAND AND EXIT +; +; +; PPIDE_IDENTIFY: #IF (PPIDETRACE >= 3) CALL PPIDE_PRTPREFIX @@ -683,6 +717,35 @@ PPIDE_IDENTIFY: LD (PPIDE_CMD),A CALL PPIDE_RUNCMD RET NZ +; + LD HL,HB_WRKBUF + JP PPIDE_GETBUF ; EXIT THRU BUFRD +; +; +; +PPIDE_IDENTIFYPACKET: +#IF (PPIDETRACE >= 3) + CALL PPIDE_PRTPREFIX + PRTS(" IDPKTDEV$") +#ENDIF + LD A,(PPIDE_DRVHD) + ;OUT (PPIDE_IO_DRVHD),A + CALL PPIDE_OUT + .DB PPIDE_REG_DRVHD +#IF (PPIDETRACE >= 3) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF + LD A,PPIDE_CIDE_IDPKTDEV + LD (PPIDE_CMD),A + CALL PPIDE_RUNCMD + RET NZ +; + CALL PPIDE_IN + .DB PPIDE_REG_STAT + BIT 6,A ; IS DRQ SET? + JP Z,PPIDE_NOMEDIA +; LD HL,HB_WRKBUF JP PPIDE_GETBUF ; EXIT THRU BUFRD ; @@ -777,10 +840,6 @@ PPIDE_SETADDR: #ENDIF CALL PPIDE_OUT .DB PPIDE_REG_COUNT -; -;;#IF (DSKYENABLE) -;; CALL PPIDE_DSKY -;;#ENDIF ; RET ; @@ -792,6 +851,7 @@ PPIDE_RUNCMD: CALL PPIDE_WAITRDY ; WAIT FOR DRIVE READY RET NZ ; BAIL OUT ON TIMEOUT ; +PPIDE_RUNCMD1: LD A,(PPIDE_CMD) ; GET THE COMMAND #IF (PPIDETRACE >= 3) CALL PC_SPACE @@ -982,13 +1042,18 @@ PPIDE_GETRES: ; HARDWARE INTERFACE ROUTINES ;============================================================================= ; -; SOFT RESET OF ALL DEVICES ON BUS +; RESET ALL DEVICES ON BUS ; PPIDE_RESET: #IF (PPIDETRACE >= 3) CALL PPIDE_PRTPREFIX PRTS(" RESET$") #ENDIF +; +; HARD RESET +; +; RESET LINE IS NORMALLY PULSED AT POWER ON. HOWEVER, THIS IS NOT +; DONE FOR PPIDE DEVICES, SO WE DO IT NOW. ; ; SETUP PPI TO READ LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ @@ -1013,21 +1078,21 @@ PPIDE_RESET: #ENDIF ; ; PULSE IDE RESET LINE -#IF (IDETRACE >= 3) +#IF (PPIDETRACE >= 3) PRTS(" HARD$") #ENDIF LD A,PPIDE_CTL_RESET ;OUT (PPIDE_IO_CTL),A LD C,(IY+PPIDE_CTL) ; SET IDE ADDRESS OUT (C),A - LD DE,20 + LD DE,20 ; DELAY 320US (SPEC IS >= 25US) CALL VDELAY XOR A ;OUT (PPIDE_IO_CTL),A OUT (C),A LD DE,20 CALL VDELAY -; +; #IF (DSKYENABLE) #IF (DSKYMODE == DSKYMODE_NG) ; REININT DSKY AND RESTORE CONTENTS @@ -1039,28 +1104,55 @@ PPIDE_RESET: #ENDIF #ENDIF ; - ; CONFIGURE OPERATION +; SOME CF CARDS AND CF CARD EMULATORS NEED A LITTLE TIME TO +; "BOOT" THEIR INTERNAL ELECTRONICS, SO THEY CANNOT ASSERT BUSY +; IMMEDIATELY. A SMALL WAIT IS PERFORMED HERE TO GIVE SUCH DEVICES +; A BETTER CHANCE TO SUCCEED LATER. +; +;;; CALL LDELAY ; DELAY FOR SLAVE INIT + LD DE,150000 / 16 ; + CALL VDELAY ; SMALL DELAY +; + JR PPIDE_RESET3 ; SKIP SOFT RESET +; +; SOFT RESET +; +; RC CANNOT ACCESS DEVICE CONTROL REG, SO SKIP THIS +; +PPIDE_RESET2: + ; INITIATE SOFT RESET +#IF (IDETRACE >= 3) + PRTS(" SOFT$") +#ENDIF + LD A,%00001110 ; ASSERT RESET, NO INTERRUPTS + ;OUT (PPIDE_IO_CTRL),A + CALL PPIDE_OUT + .DB PPIDE_REG_CTRL + LD DE,20 ; DELAY 320US (SPEC IS >= 25US) + CALL VDELAY +; +PPIDE_RESET3: +; +; CONFIGURE OPERATION AND END SOFT RESET +; #IF (PPIDETRACE >= 3) PRTS(" CONFIG$") #ENDIF - LD A,%00001010 ; SET ~IEN, NO INTERRUPTS + LD A,%00001010 ; DEASSERT RESET, NO INTERRUPTS ;OUT (PPIDE_REG_CTRL),A CALL PPIDE_OUT .DB PPIDE_REG_CTRL -; -; SPEC ALLOWS UP TO 450MS FOR DEVICES TO ASSERT THEIR PRESENCE -; VIA -DASP. I ENCOUNTER PROBLEMS LATER ON IF I DON'T WAIT HERE -; FOR THAT TO OCCUR. THUS FAR, IT APPEARS THAT 150MS IS SUFFICIENT -; FOR ANY DEVICE ENCOUNTERED. MAY NEED TO EXTEND BACK TO 500MS -; IF A SLOWER DEVICE IS ENCOUNTERED. -; - ;LD DE,500000/16 ; ~500MS - LD DE,150000/16 ; ~???MS + LD DE,20 ; DELAY 320US (SPEC IS >= 25US) CALL VDELAY +; +PPIDE_RESET5: + LD HL,PPIDE_TONORM ; NORMAL TIMEOUT NOW + LD (PPIDE_TIMEOUT),HL ; AND RESTORE IT ; ; INITIALIZE THE INDIVIDUAL UNITS (MASTER AND SLAVE). ; BASED ON TESTING, IT APPEARS THAT THE MASTER UNIT MUST ; BE DONE FIRST OR THIS BEHAVES BADLY. +; PUSH IY ; SAVE CFG PTR BIT 0,(IY+PPIDE_ACC) ; MASTER? CALL Z,PPIDE_GOPARTNER ; IF NOT, SWITCH TO MASTER @@ -1068,7 +1160,7 @@ PPIDE_RESET: CALL PPIDE_GOPARTNER ; POINT TO SLAVE CALL PPIDE_INITUNIT ; INIT PARTNER UNIT POP IY ; RECOVER ORIG CFG PTR -; +; XOR A ; SIGNAL SUCCESS RET ; AND DONE ; @@ -1078,14 +1170,10 @@ PPIDE_INITUNIT: CALL PPIDE_SELUNIT ; SELECT UNIT RET NZ ; ABORT IF ERROR - LD HL,PPIDE_TIMEOUT ; POINT TO TIMEOUT - LD (HL),PPIDE_TONORM ; SET NORMAL TIMEOUT - CALL PPIDE_PROBE ; DO PROBE RET NZ ; JUST RETURN IF NOTHING THERE - CALL PPIDE_INITDEV ; IF FOUND, ATTEMPT TO INIT DEVICE - RET ; DONE + JP PPIDE_INITDEV ; EXIT VIA INITDEV ; ; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT ; @@ -1097,10 +1185,16 @@ PPIDE_SELUNIT: BIT 0,(IY+PPIDE_ACC) ; MASTER? JR Z,PPIDE_SELUNIT1 ; HANDLE SLAVE LD A,PPIDE_DRVMASTER ; MASTER - JR PPIDE_SELUNIT2 -PPIDE_SELUNIT1: +#IF (PPIDETRACE >= 3) + PRTS(" MASTER$") +#ENDIF + JR PPIDE_SELUNIT2 +PPIDE_SELUNIT1: LD A,PPIDE_DRVSLAVE ; SLAVE -PPIDE_SELUNIT2: +#IF (PPIDETRACE >= 3) + PRTS(" SLAVE$") +#ENDIF +PPIDE_SELUNIT2: LD (PPIDE_DRVHD),A ; SAVE IT XOR A ; SUCCESS RET @@ -1112,7 +1206,7 @@ PPIDE_PROBE: ; PROBE FOR A DRIVE ON THE INTERFACE (EITHER MASTER OR SLAVE). ; IDEALLY, THIS IS BEING CALLED IMMEDIATELY AFTER A HARD OR SOFT ; INTERFACE RESET. HOWEVER, THERE ARE SOME HARDWARE IMPLEMENTATTIONS -; WHICH ARE NOT CAPABLE OF EITHER A HARD NOR SOFT RESET. SO THIS +; WHICH ARE CAPABLE OF NEITHER A HARD NOR SOFT RESET. SO THIS ; CODE SHOULD TRY TO HANDLE THE SCENARIO WHERE NO INTERFACE RESET ; HAS OCCURRED. ; @@ -1120,6 +1214,13 @@ PPIDE_PROBE: CALL PPIDE_PRTPREFIX PRTS(" PROBE$") ; LABEL FOR IO ADDRESS #ENDIF +; +#IF (PPIDETRACE >= 3) + CALL PPIDE_IN + .DB PPIDE_REG_STAT + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF ; ; SELECT DEVICE (MASTER/SLAVE) LD A,(PPIDE_DRVHD) @@ -1132,14 +1233,15 @@ PPIDE_PROBE: #ENDIF CALL DELAY ; DELAY ~16US ; -; IF WE GET HERE AND THE INTERFACE IS STILL INITIALIZING, WE NEED TO -; WAIT UNTIL THE INTERFACE IS READY. PER SPEC, THE STATUS REGISTER -; WILL BE EXACTLY $80 IN THIS SCENARIO. SINCE $80 IS UNLIKELY -; FOR A FLOATING PORT VALUE, WE INTERPRET THIS VALUE TO MEAN HARDWARE -; IS THERE AND INIT IS IN PROGRESS, SO IT WILL BE IMPOSSIBLE TO -; INTERROGATE REGISTERS YET. SINCE WE NOW BELIEVE THAT SOME HARDWARE -; IS RESPONDING, IT IS SAFE (AND NECESSARY) TO WAIT FOR BUSY TO -; CLEAR. +; IF WE GET HERE AND THE DRIVE IS STILL INITIALIZING, WE NEED TO +; WAIT UNTIL THE DRIVE IS READY. IN THIS CASE BUSY *WILL* BE HIGH. +; BASED ON TESTING, DRDY AND DSC VALUES VARY. EVERYTHING ELSE SEEMS +; TO BE ZERO. SO, WE FILTER OUT DRDY & DSC, THEN LOOK FOR BUSY=1 +; AND ALL ELSE ZERO. THIS GENERALLY AVOIDS VALUES THAT ARE TYPICAL +; FOR FLOATING PORTS AND SO CAN BE USED TO DETERMINE IF WE NEED TO +; WAIT FOR THE DEVICE TO BE READY. THIS WAIT IS MANDATORY BECAUSE +; SOME (IF NOT ALL) DEVICES WILL NOT PERSIST REGISTER VALUES UNTIL +; THE DRIVE IS READY. ; CALL PPIDE_IN .DB PPIDE_REG_STAT @@ -1147,8 +1249,29 @@ PPIDE_PROBE: CALL PC_SPACE CALL PRTHEXBYTE #ENDIF +; + AND %10101111 ; FILTER OUT DRDY & DSC CP $80 ; INIT IN PROGRESS? - CALL Z,PPIDE_WAITBSY ; WAIT FOR BUSY TO CLEAR + JR NZ,PPIDE_PROBE1 ; IF NOT, SKIP AHEAD +; +#IF (PPIDETRACE >= 3) + PRTS(" WAIT$") +#ENDIF +; + LD HL,(PPIDE_TIMEOUT) ; GET CURRENT TIMEOUT + PUSH HL ; SAVE IT + LD HL,PPIDE_TOSLOW ; SLOW TIMEOUT FOR THIS + LD (PPIDE_TIMEOUT),HL ; SET IT + CALL PPIDE_WAITBSY ; WAIT FOR BUSY TO CLEAR + POP HL ; RECOVER TIMEOUT + LD (PPIDE_TIMEOUT),HL ; SET IT +; +#IF (PPIDETRACE >= 3) + CALL PPIDE_IN + .DB PPIDE_REG_STAT + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF ; ; TEST FOR PRESENCE OF IDE REGISTERS. USE LBA0/1 TO SEE ; IF VALUE CAN BE PERSISTED. THE USE OF BOTH LBA0 AND LBA1 @@ -1156,11 +1279,12 @@ PPIDE_PROBE: ; PPI ITSELF WILL PERSIST THE LAST VALUE WRITTEN, SO WE USE ; MULTIPLE REGISTERS TO WORK AROUND THIS FALSE POSITIVE. ; +PPIDE_PROBE1: ; $AA -> LBA0 LD A,$AA CALL PPIDE_OUT .DB PPIDE_REG_LBA0 -; +; ; $55 => LBA1 LD A,$55 CALL PPIDE_OUT @@ -1190,43 +1314,34 @@ PPIDE_PROBE: CALL PPIDE_REGDUMP #ENDIF ; - CALL PPIDE_WAITBSY ; WAIT FOR BUSY TO CLEAR - JP NZ,PPIDE_NOMEDIA ; CONVERT TIMEOUT TO NO MEDIA AND RETURN + XOR A + RET ; -#IF (PPIDETRACE >= 3) - CALL PPIDE_REGDUMP -#ENDIF +; (RE)INITIALIZE DEVICE ; -; IF THE INTERFACE HAS A MASTER AND NO SLAVE, THEN THE ABOVE CHECKS -; MAY ALL SUCCEED WHEN PROBING FOR THE SLAVE. HOWEVER, THE STATUS -; BYTE FOR THE SLAVE WILL REMAIN $00, SO WE LOOK FOR THAT VALUE AS A -; FINAL WAY TO DETECT NO MEDIA. +PPIDE_INITDEV: ; - ; CHECK STATUS -; IN A,(PPIDE_REG_STAT) ; GET STATUS - CALL PPIDE_IN - .DB PPIDE_REG_STAT #IF (PPIDETRACE >= 3) - CALL PC_SPACE - CALL PRTHEXBYTE ; IF DEBUG, PRINT STATUS + CALL PPIDE_PRTPREFIX + PRTS(" INITDEV$") ; LABEL FOR IO ADDRESS #ENDIF - OR A ; SET FLAGS TO TEST FOR ZERO - JP Z,PPIDE_NOMEDIA ; CONTINUE IF NON-ZERO ; - ; ASSUME ATA DEVICE FOR NOW, RECORD TYPE AND RETURN SUCCESS - LD A,PPIDE_TYPEATA ; TYPE = ATA - LD (IY+PPIDE_TYPE),A ; SET IT IN INSTANCE DATA - XOR A ; SIGNAL SUCCESS - RET ; DONE, NOTE THAT A=0 AND Z IS SET -; -; (RE)INITIALIZE DEVICE +; IF THE IDE STATUS BYTE IS $00, WE HAVE EITHER A NON-PRESENT SLAVE +; OR AN ATAPI DEVICE. TO DIFFERENTIATE THESE POSSIBILITIES, WE RUN +; A NOP COMMAND. IF WE HAVE AN ATAPI DEVICE, THIS WILL CAUSE THE +; STATUS BYTE TO BE "NORMAL" (NON-ZERO). IF THE STATUS IS STILL +; ZERO, WE ABORT WITH A NO MEDIA STATUS. NOTE THAT THE NOP COMMAND +; RETURNS A COMMAND ERROR BY DESIGN. WE JUST IGNORE THE ERROR. ; -PPIDE_INITDEV: + CALL PPIDE_NOP + CALL PPIDE_IN + .DB PPIDE_REG_STAT + OR A + JP Z,PPIDE_NOMEDIA ; - LD A,(IY+PPIDE_TYPE) ; GET THE DEVICE TYPE - OR A ; SET FLAGS - JP Z,PPIDE_NOMEDIA ; EXIT SETTING NO MEDIA STATUS +; WE NEED TO SETUP 8-BIT MODE BEFORE DOING ANYTHING ELSE ; +PPIDE_INITDEV0A: BIT 1,(IY+PPIDE_ACC) ; 8 BIT ACCESS? JR Z,PPIDE_INITDEV0 ; NO, DO 16 BIT INIT LD A,PPIDE_FEAT_ENABLE8BIT ; FEATURE VALUE = ENABLE 8-BIT PIO @@ -1244,10 +1359,14 @@ PPIDE_INITDEV0: PPIDE_INITDEV00: ; CALL PPIDE_IDENTIFY ; EXECUTE PPIDENTIFY COMMAND - RET NZ ; BAIL OUT ON ERROR + JR NZ,PPIDE_INITDEVP ; ON ERROR, TRY PACKET DEVICE +; + ; DECLARE WE ARE ATA + LD A,PPIDE_TYPEATA ; OTHERWISE TYPE=ATA + LD (IY+PPIDE_TYPE),A ; SET IT IN INSTANCE DATA ; LD DE,HB_WRKBUF ; POINT TO BUFFER -#IF (PPIDETRACE >= 3) +#IF (PPIDETRACE >= 4) CALL DUMP_BUFFER ; DUMP IT IF DEBUGGING #ENDIF ; @@ -1267,38 +1386,15 @@ PPIDE_INITDEV00: CALL PRTHEXWORD #ENDIF ; -; SEE PAGE 114 OF CF+ & CF SPECIFICATION REV. 3.0 FOR CF CARD -; SIGNATURE VALUES. ALL OF THE BELOW ARE DOCUMENTED THERE EXCEPT -; $045A WHICH IS A VALUE DISCOVERED ON A CF<->SD CARD ADAPTER. -; -; SIGNATURE $045A IS NOT LISTED IN THE CF SPEC. IT WAS ADDED BECAUSE -; IT WAS SEEN IN THE WILD ON A CF-SD ADAPTER. HOWEVER IT HAS NOW -; ALSO BEEN SEEN ON A SPINNING HARD DISK. SINCE IT IS AMBIGUOUS, I -; WILL CONSIDER IT TO BE A HARD DISK. -; - LD BC,$848A ; STANDARD CF CARD SIGNATURE %1000 1111 1000 1010 - CALL PPIDE_INITDEV000 ; TEST & SET - LD BC,$044A ; ALT SIG FOR CF NON-REMOVABLE %0000 0100 0100 1010 - CALL PPIDE_INITDEV000 ; TEST & SET - ;LD BC,$045A ; ?ALT SIG FOR CF NON-REMOVABLE %0000 0100 0101 1010 - ;CALL PPIDE_INITDEV000 ; TEST & SET - LD BC,$0040 ; ALT SIG FOR CF NON-REMOVABLE %0000 0000 0100 0000 - CALL PPIDE_INITDEV000 ; TEST & SET - JR PPIDE_INITDEV1 ; CONTINUE INIT -; -PPIDE_INITDEV000: - ; CHECK IF FIRST WORD OF IDENTIFY DATA MATCHES VALUE IN BC - ; AND SET CF FLAG IF SO - LD HL,(HB_WRKBUF) ; FIRST WORD OF IDENTIFY DATA - OR A ; CLEAR CARRY - SBC HL,BC ; COMPARE - RET NZ ; ABORT IF NOT EQUAL + ; DETERMINE IF COMPACTFLASH MEDIA + LD A,(HB_WRKBUF+(83*2)) ; LOW BYTE OF WORD 83 + BIT 2,A ; TEST CFA FEATURE SET BIT + JR Z,PPIDE_INITDEV1 ; IF NOT, SKIP SET 0,(IY+PPIDE_MED) ; ELSE SET FLAGS BIT FOR CF MEDIA - RET ; AND RETURN ; PPIDE_INITDEV1: ; DETERMINE IF LBA CAPABLE - LD A,(HB_WRKBUF+98+1) ; GET BYTE WITH LBA BIT FROM BUFFER + LD A,(HB_WRKBUF+98+1) ; HIGH BYTE OF WORD 49 BIT 1,A ; CHECK THE LBA BIT JR Z,PPIDE_INITDEV2 ; NOT SET, BYPASS SET 1,(IY+PPIDE_MED) ; SET FLAGS BIT FOR LBA @@ -1315,12 +1411,39 @@ PPIDE_INITDEV2: POP BC ; RECOVER POINTER TO CAPACITY ENTRY CALL ST32 ; SAVE CAPACITY ; - ; RESET CARD STATUS TO 0 (OK) + ; RECORD STATUS OK XOR A ; A := 0 (STATUS = OK) LD (IY+PPIDE_STAT),A ; SAVE IT ; RET ; RETURN, A=0, Z SET ; +; +; +PPIDE_INITDEVP: + CALL PPIDE_IDENTIFYPACKET ; EXECUTE IDENTIFY COMMAND + RET NZ ; BAIL OUT ON ERROR +; + ; DECLARE WE ARE ATAPI + LD A,PPIDE_TYPEATAPI ; OTHERWISE TYPE=ATAPI + LD (IY+PPIDE_TYPE),A ; SET IT IN INSTANCE DATA +; + LD DE,HB_WRKBUF ; POINT TO BUFFER +#IF (PPIDETRACE >= 4) + CALL DUMP_BUFFER ; DUMP IT IF DEBUGGING +#ENDIF +; + LD (IY+PPIDE_MED),0 ; CLEAR FLAGS +; + ; DONE FOR NOW, ATAPI NOT INPLEMENTED +; + ; RETURN NOT SUPPORTED STATUS + JP PPIDE_NOTSUP ; NOT SUPPORTED +; +; ; RECORD STATUS OK +; XOR A ; A := 0 (STATUS = OK) +; LD (IY+PPIDE_STAT),A ; SAVE IT +; RET +; ; SWITCH IY POINTER FROM CURRENT UNIT CFG TO PARTNER UNIT CFG ; PPIDE_GOPARTNER: @@ -1344,7 +1467,7 @@ PPIDE_CHKERR: ; ; PPIDE_WAITRDY: - LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS + LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS LD B,A ; PUT IN OUTER LOOP VAR PPIDE_WAITRDY1: LD DE,(PPIDE_TOSCALER) ; CPU SPEED SCALER TO INNER LOOP VAR @@ -1366,7 +1489,7 @@ PPIDE_WAITRDY2: ; ; PPIDE_WAITDRQ: - LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS + LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS LD B,A ; PUT IN OUTER LOOP VAR PPIDE_WAITDRQ1: LD DE,(PPIDE_TOSCALER) ; CPU SPEED SCALER TO INNER LOOP VAR @@ -1388,14 +1511,14 @@ PPIDE_WAITDRQ2: ; ; PPIDE_WAITBSY: - LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS + LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.1 SECS LD B,A ; PUT IN OUTER LOOP VAR PPIDE_WAITBSY1: LD DE,(PPIDE_TOSCALER) ; CPU SPEED SCALER TO INNER LOOP VAR PPIDE_WAITBSY2: ;IN A,(PPIDE_REG_STAT) ; READ STATUS - CALL PPIDE_IN ; 17TS + 170TS - .DB PPIDE_REG_STAT ; 0TS + CALL PPIDE_IN ; 17TS + 204TS + .DB PPIDE_REG_STAT LD C,A ; SAVE IT ; 4TS AND %10000000 ; TO FILL (OR READY TO FILL) ; 7TS RET Z ; 5TS @@ -1404,32 +1527,32 @@ PPIDE_WAITBSY2: OR E ; 4TS JR NZ,PPIDE_WAITBSY2 ; 12TS DJNZ PPIDE_WAITBSY1 ; ----- - JP PPIDE_BSYTO ; EXIT WITH BSYTO ERR ; 229TS + JP PPIDE_BSYTO ; EXIT WITH BSYTO ERR ; 263TS ; ; READ A VALUE FROM THE DEVICE POINTED TO BY IY AND RETURN IT IN A -; +; PPIDE_IN: EX (SP),HL ; GET PARM POINTER ; 19TS PUSH BC ; SAVE INCOMING BC ; 11TS LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ ; 7TS - ;OUT (PPIDE_IO_PPI),A ; DO IT ; 11TS - LD C,(IY+PPIDE_PPI) ; PPI CONTROL WORD - OUT (C),A ; WRITE IT + ;OUT (PPIDE_IO_PPI),A ; DO IT + LD C,(IY+PPIDE_PPI) ; PPI CONTROL WORD ; 19TS + OUT (C),A ; WRITE IT ; 12TS ; LD B,(HL) ; GET CTL PORT VALUE ; 7TS - ;LD C,PPIDE_IO_CTL ; SETUP PORT TO WRITE ; 7TS + ;LD C,PPIDE_IO_CTL ; SETUP PORT TO WRITE ;LD C,(IY+PPIDE_CTL) ; SET IDE ADDRESS - DEC C ; SET IDE ADDRESS + DEC C ; SET IDE ADDRESS ; 4TS OUT (C),B ; SET ADDRESS LINES ; 12TS SET 6,B ; TURN ON READ BIT ; 8TS OUT (C),B ; ASSERT READ LINE ; 12TS ; - ;IN A,(PPIDE_IO_DATALO) ; GET DATA VALUE FROM DEVICE ; 11TS - DEC C - DEC C - IN A,(C) ; GET DATA VALUE FROM DEVICE - INC C - INC C + ;IN A,(PPIDE_IO_DATALO) ; GET DATA VALUE FROM DEVICE + DEC C ; 4TS + DEC C ; 4TS + IN A,(C) ; GET DATA VALUE FROM DEVICE ; 12 + INC C ; 4TS + INC C ; 4TS ; RES 6,B ; CLEAR READ BIT ; 8TS OUT (C),B ; DEASSERT READ LINE ; 12TS @@ -1437,9 +1560,9 @@ PPIDE_IN: INC HL ; POINT PAST PARM ; 6TS EX (SP),HL ; RESTORE STACK ; 19TS RET ; 10TS +; ; ----- +; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY ; 204TS ; -; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY -; PPIDE_OUT: ; *** TODO *** FIX ORDER OF SET/CLEAR WRITE LINE EX (SP),HL ; GET PARM POINTER @@ -1507,6 +1630,10 @@ PPIDE_BSYTO: LD A,PPIDE_STBSYTO JR PPIDE_ERR ; +PPIDE_NOTSUP: + LD A,PPIDE_STNOTSUP + JR PPIDE_ERR +; PPIDE_ERR: LD (IY+PPIDE_STAT),A ; SAVE NEW STATUS ; @@ -1524,48 +1651,64 @@ PPIDE_PRTERR: RET Z ; DONE IF NO ERRORS ; FALL THRU TO PPIDE_PRTSTAT ; -; PRINT STATUS STRING (STATUS NUM IN A) +; PRINT FULL DEVICE STATUS LINE ; PPIDE_PRTSTAT: PUSH AF PUSH DE PUSH HL LD A,(IY+PPIDE_STAT) + CP PPIDE_STINVUNIT + JR Z,PPIDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE + CALL PPIDE_PRTPREFIX ; PRINT UNIT PREFIX + JR PPIDE_PRTSTAT3 +PPIDE_PRTSTAT2: + CALL NEWLINE + PRTS("PPIDE:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT +PPIDE_PRTSTAT3: + CALL PC_SPACE ; FORMATTING + CALL PPIDE_PRTSTATSTR + POP HL + POP DE + POP AF + RET +; +; PRINT STATUS STRING +; +PPIDE_PRTSTATSTR: + PUSH AF + PUSH DE + LD A,(IY+PPIDE_STAT) OR A LD DE,PPIDE_STR_STOK - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STINVUNIT - JR Z,PPIDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STNOMEDIA - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STCMDERR - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STIOERR - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STRDYTO - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STDRQTO - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 INC A LD DE,PPIDE_STR_STBSYTO - JR Z,PPIDE_PRTSTAT1 + JR Z,PPIDE_PRTSTATSTR1 + INC A + LD DE,PPIDE_STR_STNOTSUP + JR Z,PPIDE_PRTSTATSTR1 LD DE,PPIDE_STR_STUNK -PPIDE_PRTSTAT1: - CALL PPIDE_PRTPREFIX ; PRINT UNIT PREFIX - JR PPIDE_PRTSTAT3 -PPIDE_PRTSTAT2: - CALL NEWLINE - PRTS("PPIDE:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT -PPIDE_PRTSTAT3: - CALL PC_SPACE ; FORMATTING +PPIDE_PRTSTATSTR1: CALL WRITESTR - POP HL POP DE POP AF RET @@ -1628,30 +1771,6 @@ PPIDE_PRTPREFIX1: CALL PC_COLON POP AF RET -;;; -;;; -;;; -;;#IF (DSKYENABLE) -;;PPIDE_DSKY: -;; LD HL,DSKY_HEXBUF ; POINT TO DSKY BUFFER -;; CALL PPIDE_IN -;; .DB PPIDE_REG_DRVHD -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL PPIDE_IN -;; .DB PPIDE_REG_CYLHI -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL PPIDE_IN -;; .DB PPIDE_REG_CYLLO -;; LD (HL),A ; SAVE IN BUFFER -;; INC HL ; INCREMENT BUFFER POINTER -;; CALL PPIDE_IN -;; .DB PPIDE_REG_SECT -;; LD (HL),A ; SAVE IN BUFFER -;; CALL DSKY_HEXOUT ; SEND IT TO DSKY -;; RET -;;#ENDIF ; ;============================================================================= ; STRING DATA @@ -1665,18 +1784,22 @@ PPIDE_STR_STIOERR .TEXT "IO ERROR$" PPIDE_STR_STRDYTO .TEXT "READY TIMEOUT$" PPIDE_STR_STDRQTO .TEXT "DRQ TIMEOUT$" PPIDE_STR_STBSYTO .TEXT "BUSY TIMEOUT$" +PPIDE_STR_STNOTSUP .TEXT "NOT SUPPORTED$" PPIDE_STR_STUNK .TEXT "UNKNOWN ERROR$" ; PPIDE_STR_NO .TEXT "NO$" PPIDE_STR_NOPPI .TEXT "PPI NOT PRESENT$" PPIDE_STR_8BIT .TEXT " 8-BIT$" ; +PPIDE_STR_TYPEATA .TEXT " ATA$" +PPIDE_STR_TYPEATAPI .TEXT " ATAPI$" +; ;============================================================================= ; DATA STORAGE ;============================================================================= ; PPIDE_TIMEOUT .DB PPIDE_TONORM ; WAIT FUNCS TIMEOUT IN TENTHS OF SEC -PPIDE_TOSCALER .DW CPUMHZ * 218 ; WAIT FUNCS SCALER FOR CPU SPEED +PPIDE_TOSCALER .DW CPUMHZ * 380 ; WAIT FUNCS SCALER FOR CPU SPEED ; PPIDE_CMD .DB 0 ; PENDING COMMAND TO PROCESS PPIDE_IOFNADR .DW 0 ; PENDING IO FUNCTION ADDRESS diff --git a/Source/ver.inc b/Source/ver.inc index 1abda088..e90eda31 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,7 +2,7 @@ #DEFINE RMN 3 #DEFINE RUP 0 #DEFINE RTP 0 -#DEFINE BIOSVER "3.3.0-dev.6" +#DEFINE BIOSVER "3.3.0-dev.7" #define rmj RMJ #define rmn RMN #define rup RUP diff --git a/Source/ver.lib b/Source/ver.lib index 65d94bf3..96dcd00e 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 3 rup equ 0 rtp equ 0 biosver macro - db "3.3.0-dev.6" + db "3.3.0-dev.7" endm