Browse Source

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.
patch v3.3.0-dev.7
Wayne Warthen 3 years ago
parent
commit
9f71fe05aa
  1. 4
      Source/HBIOS/Config/SCZ180_sc130.asm
  2. 4
      Source/HBIOS/Config/SCZ180_sc140.asm
  3. 4
      Source/HBIOS/Config/SCZ180_sc503.asm
  4. 2
      Source/HBIOS/cfg_scz180.asm
  5. 557
      Source/HBIOS/ide.asm
  6. 503
      Source/HBIOS/ppide.asm
  7. 2
      Source/ver.inc
  8. 2
      Source/ver.lib

4
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)

4
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)

4
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)

2
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

557
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
@ -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
;
; GET CURRENT STATUS
LD A,(IY+IDE_STAT) ; GET STATUS
OR A ; SET FLAGS
JR NZ,IDE_MEDIA1 ; ERROR ACTIVE, GO RIGHT TO RESET
JR Z,IDE_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA
;
; 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
;
;#IF ((IDEMODE != IDEMODE_MK4) & (IDEMODE != IDEMODE_RC))
; SOFT RESET
;
; 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)
;
LD A,(IY+IDE_MODE) ; GET MODE
CP IDEMODE_RC ; RCBUS?
JR Z,IDE_RESET4 ; IF SO, BYPASS
IDE_RESET3:
;
; 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,6 +1249,7 @@ 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
@ -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,24 +1497,44 @@ 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
;
; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY
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
;
IDE_OUT:
EX (SP),HL ; GET PARM POINTER
@ -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

503
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)
;
@ -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
@ -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,14 +1078,14 @@ 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
@ -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
@ -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,9 +1185,15 @@ PPIDE_SELUNIT:
BIT 0,(IY+PPIDE_ACC) ; MASTER?
JR Z,PPIDE_SELUNIT1 ; HANDLE SLAVE
LD A,PPIDE_DRVMASTER ; MASTER
#IF (PPIDETRACE >= 3)
PRTS(" MASTER$")
#ENDIF
JR PPIDE_SELUNIT2
PPIDE_SELUNIT1:
LD A,PPIDE_DRVSLAVE ; SLAVE
#IF (PPIDETRACE >= 3)
PRTS(" SLAVE$")
#ENDIF
PPIDE_SELUNIT2:
LD (PPIDE_DRVHD),A ; SAVE IT
XOR A ; SUCCESS
@ -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,6 +1279,7 @@ 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
@ -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
; 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.
;
; (RE)INITIALIZE DEVICE
;
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,7 +1527,7 @@ 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
;
@ -1412,24 +1535,24 @@ 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,8 +1560,8 @@ 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
; ; -----
; OUTPUT VALUE IN A TO THE DEVICE POINTED TO BY IY ; 204TS
;
PPIDE_OUT:
; *** TODO *** FIX ORDER OF SET/CLEAR WRITE LINE
@ -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

2
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

2
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

Loading…
Cancel
Save