@ -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 PP 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 .
; 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 1 0 SECS
PPIDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS
PPIDE_TOSLOW .EQU 200 ; SLOW TIMEOUT IS 2 0 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 DI O_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 ( PP IDETRACE > = 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 N EITHER 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 STATU S
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 , $ 848 A ; STANDARD CF CARD SIGNATURE %1000 1111 1000 1010
CALL PPIDE_INITDEV000 ; TEST & SET
LD BC , $ 044 A ; 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 ST3 2 ; 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 + 170 TS
.DB PPIDE_REG_STAT ; 0TS
CALL PPIDE_IN ; 17TS + 204 TS
.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 ; 229 TS
JP PPIDE_BSYTO ; EXIT WITH BSYTO ERR ; 263 TS
;
; 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_PRTSTATSTR 1
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_PRTSTATSTR 1
INC A
LD DE , PPIDE_STR_STCMDERR
JR Z , PPIDE_PRTSTAT1
JR Z , PPIDE_PRTSTATSTR 1
INC A
LD DE , PPIDE_STR_STIOERR
JR Z , PPIDE_PRTSTAT1
JR Z , PPIDE_PRTSTATSTR 1
INC A
LD DE , PPIDE_STR_STRDYTO
JR Z , PPIDE_PRTSTAT1
JR Z , PPIDE_PRTSTATSTR 1
INC A
LD DE , PPIDE_STR_STDRQTO
JR Z , PPIDE_PRTSTAT1
JR Z , PPIDE_PRTSTATSTR 1
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