mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
730 lines
16 KiB
730 lines
16 KiB
;
|
|
;==================================================================================================
|
|
; IDE DISK DRIVER
|
|
;==================================================================================================
|
|
;
|
|
#IF (IDETRACE >= 2)
|
|
#DEFINE DCALL CALL
|
|
#ELSE
|
|
#DEFINE DCALL \;
|
|
#ENDIF
|
|
;
|
|
; IO PORT ADDRESSES
|
|
;
|
|
#IF (IDEMODE == IDEMODE_MK4)
|
|
IDEBASE .EQU MK4_IDE
|
|
#ELSE
|
|
IDEBASE .EQU $20
|
|
#ENDIF
|
|
|
|
#IF ((IDEMODE == IDEMODE_DIO) | (IDEMODE == IDEMODE_MK4))
|
|
#IF (IDE8BIT)
|
|
IDEDATA .EQU $IDEBASE + $00 ; DATA PORT (8 BIT)
|
|
#ELSE
|
|
IDEDATALO .EQU $IDEBASE + $00 ; DATA PORT (16 BIT LO BYTE)
|
|
IDEDATAHI .EQU $IDEBASE + $08 ; DATA PORT (16 BIT HI BYTE)
|
|
IDEDATA .EQU IDEDATALO
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
#IF (IDEMODE == IDEMODE_DIDE)
|
|
#IF (IDE8BIT)
|
|
IDEDATA .EQU $IDEBASE + $00 ; DATA PORT (8 BIT OR 16 BIT PIO LO/HI BYTES)
|
|
#ELSE
|
|
IDEDATA .EQU $IDEBASE + $08 ; DATA PORT (16 BIT PIO LO/HI BYTES)
|
|
IDEDMA .EQU $IDEBASE + $09 ; DATA PORT (16 BIT DMA LO/HI BYTES)
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
IDEERR .EQU $IDEBASE + $01 ; READ: ERROR REGISTER; WRITE: PRECOMP
|
|
IDESECTC .EQU $IDEBASE + $02 ; SECTOR COUNT
|
|
IDESECTN .EQU $IDEBASE + $03 ; SECTOR NUMBER
|
|
IDECYLLO .EQU $IDEBASE + $04 ; CYLINDER LOW
|
|
IDECYLHI .EQU $IDEBASE + $05 ; CYLINDER HIGH
|
|
IDEDEVICE .EQU $IDEBASE + $06 ; DRIVE/HEAD
|
|
IDESTTS .EQU $IDEBASE + $07 ; READ: STATUS; WRITE: COMMAND
|
|
IDECTRL .EQU $IDEBASE + $0E ; READ: ALTERNATIVE STATUS; WRITE; DEVICE CONTROL
|
|
IDEADDR .EQU $IDEBASE + $0F ; DRIVE ADDRESS (READ ONLY)
|
|
;
|
|
;
|
|
;
|
|
IDECMD_RECAL .EQU $10
|
|
IDECMD_READ .EQU $20
|
|
IDECMD_WRITE .EQU $30
|
|
IDECMD_IDDEV .EQU $EC
|
|
IDECMD_SETFEAT .EQU $EF
|
|
;
|
|
IDE_RCOK .EQU 0
|
|
IDE_RCCMDERR .EQU 1
|
|
IDE_RCRDYTO .EQU 2
|
|
IDE_RCBUFTO .EQU 3
|
|
IDE_RCBSYTO .EQU 4
|
|
;
|
|
; UNIT CONFIGURATION
|
|
;
|
|
IDE_DEVICES:
|
|
IDE_DEVICE0 .DB %11100000 ; LBA, MASTER DEVICE
|
|
IDE_DEVICE1 .DB %11110000 ; LBA, SLAVE DEVICE
|
|
;
|
|
;
|
|
;
|
|
IDE_INIT:
|
|
PRTS("IDE:$") ; LABEL FOR IO ADDRESS
|
|
;
|
|
#IF (IDEMODE == IDEMODE_DIO)
|
|
PRTS(" MODE=DIO$")
|
|
#ENDIF
|
|
#IF (IDEMODE == IDEMODE_DIDE)
|
|
PRTS(" MODE=DIDE$")
|
|
#ENDIF
|
|
#IF (IDEMODE == IDEMODE_MK4)
|
|
PRTS(" MODE=MK4$")
|
|
#ENDIF
|
|
; PRINT IDE INTERFACE PORT ADDRESS
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,IDEDATA ; GET IO ADDRESS
|
|
CALL PRTHEXBYTE ; PRINT IT
|
|
;
|
|
; RESET INTERFACE
|
|
CALL IDE_RESET ; INTERFACE RESET
|
|
CALL DELAY ; SMALL DELAY
|
|
;
|
|
; SET GLOBAL STATUS TO OK (ZERO)
|
|
XOR A ; STATUS OK
|
|
LD (IDE_STAT),A ; INITIALIZE IT
|
|
;
|
|
; PROBE FOR DEVICE(S)
|
|
LD A,(IDE_DEVICE0) ; DEVICE 0
|
|
DCALL PC_SPACE ; IF DEBUGGING, PRINT A SPACE
|
|
DCALL PC_LBKT ; IF DEBUGGING, PRINT LEFT BRACKET
|
|
CALL IDE_PROBE ; PROBE FOR DEVICE 0 PRESENCE
|
|
DCALL PC_RBKT ; IF DEBUGGING, PRINT A RIGHT BRACKET
|
|
JR NZ,IDE_INIT1 ; IF DEVCIE 0 NOT PRESENT, SKIP DEVICE 1 PROBE
|
|
LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT
|
|
INC (HL) ; INCREMENT IT
|
|
LD A,(IDE_DEVICE1) ; DEVICE 1
|
|
DCALL PC_SPACE ; IF DEBUGGING, PRINT A SPACE
|
|
DCALL PC_LBKT ; IF DEBUGGING, PRINT A LEFT BRACKET
|
|
CALL IDE_PROBE ; PROBE FOR DEVICE 1 PRESENT
|
|
DCALL PC_RBKT ; IF DEBUGGING, PRINT A RIGHT BRACKET
|
|
JR NZ,IDE_INIT1 ; IF DEVICE 1 NOT PRESENT, SKIP
|
|
LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT
|
|
INC (HL) ; INCREMENT IT
|
|
;
|
|
IDE_INIT1:
|
|
; RESTORE DEFAULT DEVICE SELECTION (DEVICE 0)
|
|
LD A,(IDE_DEVICE0) ; DEVICE 0
|
|
OUT (IDEDEVICE),A ; SELECT IT
|
|
CALL DELAY ; SMALL DELAY AFTER SELECT
|
|
;
|
|
; PRINT UNIT COUNT
|
|
PRTS(" UNITS=$") ; PRINT LABEL FOR UNIT COUNT
|
|
LD A,(IDE_UNITCNT) ; GET UNIT COUNT
|
|
CALL PRTDECB ; PRINT IT IN DECIMAL
|
|
;
|
|
; CHECK FOR ZERO DEVICES AND BAIL OUT IF SO
|
|
LD A,(IDE_UNITCNT) ; GET UNIT COUNT
|
|
OR A ; SET FLAGS
|
|
RET Z ; IF ZERO, WE ARE DONE
|
|
;
|
|
; DEVICE SETUP LOOP
|
|
LD B,A ; LOOP ONCE PER UNIT
|
|
LD C,0 ; C IS UNIT INDEX
|
|
IDE_INIT2:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL IDE_INIT3 ; HANDLE THE NEXT UNIT
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; INCREMENT UNIT INDEX
|
|
DJNZ IDE_INIT2 ; LOOP UNTIL DONE
|
|
RET ; INIT FINISHED
|
|
;
|
|
IDE_INIT3: ; SUBROUTINE TO QUERY A DEVICE
|
|
|
|
; PRINT PREFIX FOR UNIT INFO "IDE#:"
|
|
CALL NEWLINE ; FORMATTING: START A NEW LINE
|
|
LD DE,IDESTR_PREFIX ; POINT TO STRING "IDE"
|
|
CALL WRITESTR ; PRINT STRING
|
|
LD A,C ; UNIT NUMBER TO ACCUM
|
|
LD (IDE_CURUNIT),A ; SAVE THE CURRENT UNIT
|
|
CALL PRTDECB ; PRINT IT IN DECIMAL
|
|
CALL PC_COLON ; PRINT THE ENDING COLON
|
|
;
|
|
LD A,C ; UNIT NUMBER TO ACCUM
|
|
CALL IDE_SELECT ; SELECT THE CORRECT DEVICE
|
|
;
|
|
#IF (IDE8BIT)
|
|
PRTS(" 8BIT$")
|
|
CALL IDE_SET8BIT ; SET 8BIT TRANSFER FEATURE
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
#ENDIF
|
|
;
|
|
CALL IDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
;
|
|
LD DE,(DIOBUF) ; POINT TO BUFFER
|
|
DCALL DUMP_BUFFER ; DUMP IT IF DEBUGGING
|
|
;
|
|
; PRINT LBA/NOLBA
|
|
CALL PC_SPACE ; SPACING
|
|
LD HL,(DIOBUF) ; POINT TO BUFFER START
|
|
LD DE,98+1 ; OFFSET OF BYTE CONTAINING LBA FLAG
|
|
ADD HL,DE ; POINT TO FINAL BUFFER ADDRESS
|
|
LD A,(HL) ; GET THE BYTE
|
|
BIT 1,A ; CHECK THE LBA BIT
|
|
LD DE,IDESTR_NO ; POINT TO "NO" STRING
|
|
CALL Z,WRITESTR ; PRINT "NO" BEFORE "LBA" IF LBA NOT SUPPORTED
|
|
PRTS("LBA$") ; PRINT "LBA" REGARDLESS
|
|
;
|
|
; PRECOMPUTE LOC TO STORE 32-BIT CAPACITY
|
|
LD HL,IDE_CAPLIST ; POINT TO CAPACITY ARRAY
|
|
LD A,(IDE_CURUNIT) ; GET CUR UNIT NUM
|
|
RLCA ; MULTIPLY BY 4
|
|
RLCA ; ... TO OFFSET BY DWORDS
|
|
CALL ADDHLA ; ADD OFFSET TO POINTER
|
|
PUSH HL ; SAVE POINTER
|
|
;
|
|
; GET, SAVE, AND PRINT STORAGE CAPACITY (BLOCK COUNT)
|
|
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
|
LD HL,(DIOBUF) ; POINT TO BUFFER START
|
|
LD DE,120 ; OFFSET OF SECGTOR COUNT
|
|
ADD HL,DE ; POINT TO ADDRESS OF SECTOR COUNT
|
|
CALL LD32 ; LOAD IT TO DE:HL
|
|
POP BC ; RECOVER POINTER TO CAPACITY ARRAY ENTRY
|
|
CALL ST32 ; SAVE CAPACITY
|
|
CALL PRTHEX32 ; PRINT HEX VALUE
|
|
;
|
|
; PRINT STORAGE SIZE IN MB
|
|
PRTS(" SIZE=$") ; PRINT FIELD LABEL
|
|
LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
|
|
CALL SRL32 ; RIGHT SHIFT
|
|
CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED)
|
|
PRTS("MB$") ; PRINT SUFFIX
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_DISPATCH:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F
|
|
JR Z,IDE_READ
|
|
DEC A
|
|
JR Z,IDE_WRITE
|
|
DEC A
|
|
JR Z,IDE_STATUS
|
|
DEC A
|
|
JR Z,IDE_MEDIA
|
|
CALL PANIC
|
|
;
|
|
;
|
|
;
|
|
IDE_READ:
|
|
LD A,IDECMD_READ
|
|
LD (IDE_CMD),A
|
|
CALL IDE_RW
|
|
RET NZ
|
|
CALL IDE_BUFRD
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_WRITE:
|
|
LD A,IDECMD_WRITE
|
|
LD (IDE_CMD),A
|
|
CALL IDE_RW
|
|
RET NZ
|
|
CALL IDE_BUFWR
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_STATUS:
|
|
LD A,(IDE_STAT) ; LOAD STATUS
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; IDE_MEDIA
|
|
;
|
|
IDE_MEDIA:
|
|
LD A,C ; GET THE DEVICE/UNIT
|
|
AND $0F ; ISOLATE UNIT
|
|
LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT
|
|
CP (HL) ; COMPARE TO UNIT COUNT
|
|
LD A,MID_HD ; ASSUME WE ARE OK
|
|
RET C ; RETURN
|
|
XOR A ; NO MEDIA
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
IDE_RW:
|
|
; SELECT DEVICE
|
|
LD A,(HSTDSK) ; HSTDSK -> HEAD BIT 4 TO SELECT UNIT
|
|
AND $0F
|
|
CALL IDE_SELECT
|
|
CALL IDE_SETUP ; SETUP CYL, TRK, HEAD
|
|
JR IDE_RUNCMD ; RETURN THRU RUNCMD
|
|
;
|
|
;
|
|
;
|
|
IDE_RUNCMD:
|
|
; CLEAR RESULTS
|
|
XOR A ; A = 0
|
|
LD (IDE_STAT),A ; CLEAR DRIVER STATUS CODE
|
|
LD (IDE_STTS),A ; CLEAR SAVED STTS
|
|
LD (IDE_ERRS),A ; CLEAR SAVED ERR
|
|
CALL IDE_WAITRDY ; WAIT FOR DRIVE READY
|
|
RET NZ ; BAIL OUT ON TIMEOUT
|
|
LD A,(IDE_CMD) ; GET THE COMMAND
|
|
OUT (IDESTTS),A ; SEND IT (STARTS EXECUTION)
|
|
CALL IDE_WAITRDY ; WAIT FOR DRIVE READY (COMMAND DONE)
|
|
RET NZ ; BAIL OUT ON TIMEOUT
|
|
CALL IDE_CHKERR ; CHECK FOR ERRORS
|
|
RET NZ ; BAIL OUT ON TIMEOUT
|
|
DCALL IDE_PRT ; PRINT COMMAND IF DEBUG ENABLED
|
|
XOR A ; SET RESULT
|
|
RET ; DONE
|
|
;
|
|
;
|
|
;
|
|
IDE_ERRCMD:
|
|
LD A,IDE_RCCMDERR
|
|
JR IDE_ERR
|
|
;
|
|
IDE_ERRRDYTO:
|
|
LD A,IDE_RCRDYTO
|
|
JR IDE_ERR
|
|
;
|
|
IDE_ERRBUFTO:
|
|
LD A,IDE_RCBUFTO
|
|
JR IDE_ERR
|
|
;
|
|
IDE_ERRBSYTO:
|
|
LD A,IDE_RCBSYTO
|
|
JR IDE_ERR
|
|
;
|
|
IDE_ERR:
|
|
LD (IDE_STAT),A ; SAVE ERROR AS STATUS
|
|
#IF (IDETRACE >= 1)
|
|
PUSH AF ; SAVE ACCUM
|
|
CALL IDE_PRT ; PRINT COMMAND SUMMARY
|
|
POP AF ; RESTORE ACCUM
|
|
#ENDIF
|
|
OR A ; MAKE SURE FLAGS ARE SET
|
|
RET ; DONE
|
|
;
|
|
; SOFT RESET OF ALL DEVICES
|
|
;
|
|
IDE_RESET:
|
|
LD A,%00001110 ; NO INTERRUPTS, ASSERT RESET BOTH DRIVES
|
|
OUT (IDECTRL),A
|
|
LD DE,16 ; DELAY ~250US
|
|
CALL VDELAY
|
|
LD A,%00001010 ; NO INTERRUPTS, DEASSERT RESET
|
|
OUT (IDECTRL),A
|
|
XOR A
|
|
LD (IDE_STAT),A ; STATUS OK
|
|
RET ; SAVE IT
|
|
;
|
|
; SELECT DEVICE IN A
|
|
;
|
|
IDE_SELECT:
|
|
LD HL,IDE_DEVICES
|
|
CALL ADDHLA
|
|
LD A,(HL) ; LOAD DEVICE
|
|
LD (IDE_DEVICE),A ; SHADOW REGISTER
|
|
|
|
CALL IDE_WAITBSY
|
|
RET NZ
|
|
|
|
LD A,(IDE_DEVICE) ; RECOVER DEVICE VALUE
|
|
OUT (IDEDEVICE),A ; SELECT DEVICE
|
|
; DELAY???
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_PROBE:
|
|
OUT (IDEDEVICE),A ; SELECT IT
|
|
CALL DELAY
|
|
IN A,(IDESECTC)
|
|
DCALL PRTHEXBYTE
|
|
CP $01
|
|
RET NZ
|
|
DCALL PC_SPACE
|
|
IN A,(IDESECTN)
|
|
DCALL PRTHEXBYTE
|
|
CP $01
|
|
RET NZ
|
|
DCALL PC_SPACE
|
|
IN A,(IDECYLLO)
|
|
DCALL PRTHEXBYTE
|
|
CP $00
|
|
RET NZ
|
|
DCALL PC_SPACE
|
|
IN A,(IDECYLHI)
|
|
DCALL PRTHEXBYTE
|
|
CP $00
|
|
RET NZ
|
|
DCALL PC_SPACE
|
|
IN A,(IDESTTS)
|
|
DCALL PRTHEXBYTE ; PRINT STATUS
|
|
CP 0
|
|
JR NZ,IDE_PROBE1
|
|
OR $FF ; SIGNAL ERROR
|
|
RET
|
|
|
|
IDE_PROBE1:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_SET8BIT:
|
|
; DEVICE *MUST* ALREADY BE SELECTED!
|
|
LD A,IDECMD_SETFEAT
|
|
LD (IDE_CMD),A
|
|
LD A,$01 ; $01 ENABLES 8-BIT XFR FEATURE
|
|
OUT (IDEERR),A ; SET FEATURS VALUE
|
|
JP IDE_RUNCMD ; EXIT THRU RUNCMD
|
|
;
|
|
;
|
|
;
|
|
IDE_IDENTIFY:
|
|
; DEVICE *MUST* ALREADY BE SELECTED!
|
|
LD A,IDECMD_IDDEV
|
|
LD (IDE_CMD),A
|
|
CALL IDE_RUNCMD
|
|
RET NZ
|
|
JP IDE_BUFRD ; EXIT THRU BUFRD
|
|
;
|
|
;
|
|
;
|
|
IDE_WAITRDY:
|
|
LD B,15 ; ~15 SECOND TIMEOUT?
|
|
IDE_WAITRDY1:
|
|
LD DE,-1 ; ~1 SECOND INNER LOOP
|
|
IDE_WAITRDY2:
|
|
IN A,(IDESTTS) ; READ STATUS
|
|
LD (IDE_STTS),A ; SAVE IT
|
|
AND %11000000 ; ISOLATE BUSY AND RDY BITS
|
|
XOR %01000000 ; WE WANT BUSY(7) TO BE 0 AND RDY(6) TO BE 1
|
|
;JR Z,IDE_WAITRPT ; DIAGNOSTIC
|
|
RET Z ; ALL SET, RETURN WITH Z SET
|
|
CALL DELAY ; DELAY 16US
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JR NZ,IDE_WAITRDY2 ; INNER LOOP RETURN
|
|
DJNZ IDE_WAITRDY1 ; OUTER LOOP RETURN
|
|
JP IDE_ERRRDYTO ; EXIT WITH RDYTO ERR
|
|
;
|
|
;
|
|
;
|
|
IDE_WAITBUF:
|
|
LD B,3 ; ~3 SECOND TIMEOUT???
|
|
IDE_WAITBUF1:
|
|
LD DE,-1 ; ~1 SECOND INNER LOOP
|
|
IDE_WAITBUF2:
|
|
IN A,(IDESTTS) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER
|
|
LD (IDE_STTS),A ; SAVE IT
|
|
AND %10001000 ; TO FILL (OR READY TO FILL)
|
|
XOR %00001000
|
|
;JR Z,IDE_WAITRPT ; DIAGNOSTIC
|
|
RET Z
|
|
CALL DELAY ; DELAY 16US
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JR NZ,IDE_WAITBUF2
|
|
DJNZ IDE_WAITBUF1
|
|
JP IDE_ERRBUFTO ; EXIT WITH BUFTO ERR
|
|
;
|
|
;
|
|
;
|
|
IDE_WAITBSY:
|
|
LD B,3 ; ~3 SECOND TIMEOUT???
|
|
IDE_WAITBSY1:
|
|
LD DE,-1 ; ~1 SECOND INNER LOOP
|
|
IDE_WAITBSY2:
|
|
IN A,(IDESTTS) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER
|
|
LD (IDE_STTS),A ; SAVE IT
|
|
AND %10000000 ; TO FILL (OR READY TO FILL)
|
|
;JR Z,IDE_WAITRPT ; DIAGNOSTIC
|
|
RET Z
|
|
CALL DELAY ; DELAY 16US
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JR NZ,IDE_WAITBSY2
|
|
DJNZ IDE_WAITBSY1
|
|
JP IDE_ERRBSYTO ; EXIT WITH BSYTO ERR
|
|
;
|
|
;
|
|
;
|
|
IDE_WAITRPT:
|
|
PUSH AF
|
|
CALL PC_SPACE
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
LD A,D
|
|
CALL PRTHEXBYTE
|
|
LD A,E
|
|
CALL PRTHEXBYTE
|
|
POP AF
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDE_CHKERR:
|
|
IN A,(IDESTTS) ; GET STATUS
|
|
LD (IDE_STTS),A ; SAVE IT
|
|
AND %00000001 ; ERROR BIT SET?
|
|
RET Z ; NOPE, RETURN WITH ZF
|
|
;
|
|
IN A,(IDEERR) ; READ ERROR REGISTER
|
|
LD (IDE_ERRS),A ; SAVE IT
|
|
JP IDE_ERRCMD ; EXIT VIA ERRCMD
|
|
;
|
|
;
|
|
;
|
|
IDE_BUFRD:
|
|
CALL IDE_WAITBUF ; WAIT FOR BUFFER READY
|
|
RET NZ ; BAIL OUT IF TIMEOUT
|
|
|
|
LD HL,(DIOBUF)
|
|
LD B,0
|
|
|
|
#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE))
|
|
LD C,IDEDATA
|
|
INIR
|
|
INIR
|
|
#ELSE
|
|
LD C,IDEDATAHI
|
|
IDE_BUFRD1:
|
|
IN A,(IDEDATALO) ; READ THE LO BYTE
|
|
LD (HL),A ; SAVE IN BUFFER
|
|
INC HL ; INC BUFFER POINTER
|
|
INI ; READ AND SAVE HI BYTE, INC HL, DEC B
|
|
JP NZ,IDE_BUFRD1 ; LOOP AS NEEDED
|
|
#ENDIF
|
|
JP IDE_CHKERR ; RETURN THRU CHKERR
|
|
;
|
|
;
|
|
;
|
|
IDE_BUFWR:
|
|
CALL IDE_WAITBUF ; WAIT FOR BUFFER READY
|
|
RET NZ ; BAIL OUT IF TIMEOUT
|
|
|
|
LD HL,(DIOBUF)
|
|
LD B,0
|
|
|
|
#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE))
|
|
LD C,IDEDATA
|
|
OTIR
|
|
OTIR
|
|
#ELSE
|
|
LD C,IDEDATAHI
|
|
IDE_BUFWR1:
|
|
LD A,(HL) ; GET THE LO BYTE AND KEEP IT IN A FOR LATER
|
|
INC HL ; BUMP TO NEXT BYTE IN BUFFER
|
|
OUTI ; WRITE HI BYTE, INC HL, DEC B
|
|
OUT (IDEDATALO),A ; NOW WRITE THE SAVED LO BYTE TO LO BYTE
|
|
JP NZ,IDE_BUFWR1 ; LOOP AS NEEDED
|
|
#ENDIF
|
|
JP IDE_CHKERR ; RETURN THRU CHKERR
|
|
;
|
|
;
|
|
;
|
|
IDE_SETUP:
|
|
LD A,1
|
|
OUT (IDESECTC),A
|
|
|
|
; SEND 3 BYTES OF LBA T:SS -> CYL:SEC (CC:S)
|
|
LD A,(HSTLBAHI) ; LBA HIGH LSB
|
|
LD (IDE_CYLHI),A ; SAVE IT
|
|
OUT (IDECYLHI),A ; -> CYLINDER HI
|
|
LD A,(HSTLBALO + 1) ; LBA LOW MSB
|
|
LD (IDE_CYLLO),A ; SAVE IT
|
|
OUT (IDECYLLO),A ; -> CYLINDER LO
|
|
LD A,(HSTLBALO) ; LBA LOW LSB
|
|
LD (IDE_SEC),A ; SAVE IT
|
|
OUT (IDESECTN),A ; -> SECTOR NUM
|
|
#IF (DSKYENABLE)
|
|
CALL IDE_DSKY
|
|
#ENDIF
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
#IF (DSKYENABLE)
|
|
IDE_DSKY:
|
|
LD HL,DSKY_HEXBUF
|
|
LD A,(IDE_DEVICE)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IDE_CYLHI)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IDE_CYLLO)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IDE_SEC)
|
|
LD (HL),A
|
|
CALL DSKY_HEXOUT
|
|
RET
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
IDE_PRT:
|
|
CALL NEWLINE
|
|
|
|
LD DE,IDESTR_PREFIX
|
|
CALL WRITESTR
|
|
CALL PC_COLON
|
|
|
|
CALL PC_SPACE
|
|
LD DE,IDESTR_CMD
|
|
CALL WRITESTR
|
|
LD A,(IDE_CMD)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,(IDE_CMD)
|
|
LD DE,IDESTR_READ
|
|
CP IDECMD_READ
|
|
JP Z,IDE_PRTCMD
|
|
LD DE,IDESTR_WRITE
|
|
CP IDECMD_WRITE
|
|
JP Z,IDE_PRTCMD
|
|
LD DE,IDESTR_SETFEAT
|
|
CP IDECMD_SETFEAT
|
|
JP Z,IDE_PRTCMD
|
|
LD DE,IDESTR_IDDEV
|
|
CP IDECMD_IDDEV
|
|
JP Z,IDE_PRTCMD
|
|
LD DE,IDESTR_RECAL
|
|
CP IDECMD_RECAL
|
|
JP Z,IDE_PRTCMD
|
|
LD DE,IDESTR_UNKCMD
|
|
IDE_PRTCMD:
|
|
CALL WRITESTR
|
|
CALL PC_RBKT
|
|
|
|
CALL PC_SPACE
|
|
LD A,(IDE_DEVICE)
|
|
CALL PRTHEXBYTE
|
|
LD A,(IDE_CYLHI)
|
|
CALL PRTHEXBYTE
|
|
LD A,(IDE_CYLLO)
|
|
CALL PRTHEXBYTE
|
|
LD A,(IDE_SEC)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
LD DE,IDESTR_ARROW
|
|
CALL WRITESTR
|
|
|
|
CALL PC_SPACE
|
|
IN A,(IDESTTS)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
IN A,(IDEERR)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
LD DE,IDESTR_RC
|
|
CALL WRITESTR
|
|
LD A,(IDE_STAT)
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,(IDE_STAT)
|
|
LD DE,IDESTR_RCOK
|
|
CP IDE_RCOK
|
|
JP Z,IDE_PRTRC
|
|
LD DE,IDESTR_RCCMDERR
|
|
CP IDE_RCCMDERR
|
|
JP Z,IDE_PRTRC
|
|
LD DE,IDESTR_RCRDYTO
|
|
CP IDE_RCRDYTO
|
|
JP Z,IDE_PRTRC
|
|
LD DE,IDESTR_RCBUFTO
|
|
CP IDE_RCBUFTO
|
|
JP Z,IDE_PRTRC
|
|
LD DE,IDESTR_RCBSYTO
|
|
CP IDE_RCBSYTO
|
|
JP Z,IDE_PRTRC
|
|
LD DE,IDESTR_RCUNK
|
|
IDE_PRTRC:
|
|
CALL WRITESTR
|
|
CALL PC_RBKT
|
|
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IDESTR_PREFIX .TEXT "IDE$"
|
|
IDESTR_CMD .TEXT "CMD=$"
|
|
IDESTR_RC .TEXT "RC=$"
|
|
IDESTR_ARROW .TEXT "-->$"
|
|
IDESTR_READ .TEXT "READ$"
|
|
IDESTR_WRITE .TEXT "WRITE$"
|
|
IDESTR_SETFEAT .TEXT "SETFEAT$"
|
|
IDESTR_IDDEV .TEXT "IDDEV$"
|
|
IDESTR_RECAL .TEXT "RECAL$"
|
|
IDESTR_UNKCMD .TEXT "UNKCMD$"
|
|
IDESTR_RCOK .TEXT "OK$"
|
|
IDESTR_RCCMDERR .TEXT "COMMAND ERROR$"
|
|
IDESTR_RCRDYTO .TEXT "READY TIMEOUT$"
|
|
IDESTR_RCBUFTO .TEXT "BUFFER TIMEOUT$"
|
|
IDESTR_RCBSYTO .TEXT "BUSY TIMEOUT$"
|
|
IDESTR_RCUNK .TEXT "UNKNOWN ERROR$"
|
|
IDESTR_NO .TEXT "NO$"
|
|
;
|
|
;==================================================================================================
|
|
; IDE DISK DRIVER - DATA
|
|
;==================================================================================================
|
|
;
|
|
IDE_UNITCNT .DB 0
|
|
IDE_CURUNIT .DB 0
|
|
IDE_STAT .DB 0
|
|
;
|
|
IDE_CMD .DB 0
|
|
IDE_DEVICE .DB 0
|
|
IDE_CYLHI .DB 0
|
|
IDE_CYLLO .DB 0
|
|
IDE_SEC .DB 0
|
|
IDE_STTS .DB 0
|
|
IDE_ERRS .DB 0
|
|
;
|
|
IDE_CAPLIST .FILL 2 * 4,0 ; CAPACITY OF EACH UNIT IN BLOCKS, 1 DWORD PER UNIT
|
|
;
|
|
;
|
|
;
|
|
;
|
|
; Error Register (ERR bit being set in the Status Register)
|
|
;
|
|
; Bit 7: BBK (Bad Block Detected) Set when a Bad Block is detected.
|
|
; Bit 6: UNC (Uncorrectable Data Error) Set when Uncorrectable Error is encountered.
|
|
; Bit 5: MC (Media Changed) Set to 0.
|
|
; Bit 4: IDNF (ID Not Found) Set when Sector ID not found.
|
|
; Bit 3: MCR (Media Change Request) Set to 0.
|
|
; Bit 2: ABRT (Aborted Command) Set when Command Aborted due to drive error.
|
|
; Bit 1: TKONF (Track 0 Not Found) Set when Executive Drive Diagnostic Command.
|
|
; Bit 0: AMNF (Address mark Not Found) Set in case of a general error.
|
|
;
|
|
; Status Register (When the contents of this register are read by the host, the IREQ# bit is cleared)
|
|
;
|
|
; Bit 7: BSY (Busy) Set when the drive is busy and unable to process any new ATA commands.
|
|
; Bit 6: DRDY (Data Ready) Set when the device is ready to accept ATA commands from the host.
|
|
; Bit 5: DWF (Drive Write Fault) Always set to 0.
|
|
; Bit 4: DSC (Drive Seek Complete) Set when the drive heads have been positioned over a specific track.
|
|
; Bit 3: DRQ (Data Request) Set when device is ready to transfer a word or byte of data to or from the host and the device.
|
|
; Bit 2: CORR (Corrected Data) Always set to 0.
|
|
; Bit 1: IDX (Index) Always set to 0.
|
|
; Bit 0: ERR (Error) Set when an error occurred during the previous ATA command.
|