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.
1444 lines
39 KiB
1444 lines
39 KiB
;
|
|
;=============================================================================
|
|
; PPIDE DISK DRIVER
|
|
;=============================================================================
|
|
;
|
|
; TODO:
|
|
; - IMPLEMENT PPIDE_INITDEVICE
|
|
; - IMPLEMENT INTELLIGENT RESET, CHECK IF DEVICE IS ACTUALLY BROKEN BEFORE RESET
|
|
; - FIX SCALER CONSTANT
|
|
;
|
|
;
|
|
#IF (PPIDEMODE == PPIDEMODE_SBC)
|
|
PPIDE_IO_BASE .EQU $60
|
|
#ENDIF
|
|
;
|
|
#IF ((PPIDEMODE == PPIDEMODE_DIO3) | (PPIDEMODE == PPIDEMODE_RC))
|
|
PPIDE_IO_BASE .EQU $20
|
|
#ENDIF
|
|
;
|
|
#IF (PPIDEMODE == PPIDEMODE_MFP)
|
|
PPIDE_IO_BASE .EQU $44
|
|
#ENDIF
|
|
;
|
|
#IF (PPIDEMODE == PPIDEMODE_N8)
|
|
PPIDE_IO_BASE .EQU $80
|
|
#ENDIF
|
|
;
|
|
PPIDE_IO_DATALO .EQU PPIDE_IO_BASE + 0 ; IDE DATA BUS LSB (8255 PORT A)
|
|
PPIDE_IO_DATAHI .EQU PPIDE_IO_BASE + 1 ; IDE DATA BUS MSB (8255 PORT B)
|
|
PPIDE_IO_CTL .EQU PPIDE_IO_BASE + 2 ; IDE ADDRESS BUS AND CONTROL SIGNALS (8255 PORT C)
|
|
PPIDE_IO_PPI .EQU PPIDE_IO_BASE + 3 ; 8255 CONTROL PORT
|
|
;
|
|
; THE CONTROL PORT OF THE 8255 IS PROGRAMMED AS NEEDED TO READ OR WRITE
|
|
; DATA ON THE IDE BUS. PORT C OF THE 8255 IS ALWAYS IN OUTPUT MODE BECAUSE
|
|
; IT IS DRIVING THE ADDRESS BUS AND CONTROL SIGNALS. PORTS A & B WILL BE
|
|
; PLACED IN READ OR WRITE MODE DEPENDING ON THE DIRECTION OF THE DATA BUS.
|
|
;
|
|
PPIDE_DIR_READ .EQU %10010010 ; IDE BUS DATA INPUT MODE
|
|
PPIDE_DIR_WRITE .EQU %10000000 ; IDE BUS DATA OUTPUT MODE
|
|
;
|
|
; PORT C OF THE 8255 IS USED TO DRIVE THE IDE INTERFACE ADDRESS BUS
|
|
; AND VARIOUS CONTROL SIGNALS. THE CONSTANTS BELOW REFLECT THESE
|
|
; ASSIGNMENTS.
|
|
;
|
|
PPIDE_CTL_DA0 .EQU %00000001 ; DRIVE ADDRESS BUS - BIT 0 (DA0)
|
|
PPIDE_CTL_DA1 .EQU %00000010 ; DRIVE ADDRESS BUS - BIT 1 (DA1)
|
|
PPIDE_CTL_DA2 .EQU %00000100 ; DRIVE ADDRESS BUS - BIT 2 (DA2)
|
|
PPIDE_CTL_CS1FX .EQU %00001000 ; DRIVE CHIP SELECT 0 (ACTIVE LOW, INVERTED)
|
|
PPIDE_CTL_CS3FX .EQU %00010000 ; DRIVE CHIP SELECT 1 (ACTIVE LOW, INVERTED)
|
|
PPIDE_CTL_DIOW .EQU %00100000 ; DRIVE I/O WRITE (ACTIVE LOW, INVERTED)
|
|
PPIDE_CTL_DIOR .EQU %01000000 ; DRIVE I/O READ (ACTIVE LOW, INVERTED)
|
|
PPIDE_CTL_RESET .EQU %10000000 ; DRIVE RESET (ACTIVE LOW, INVERTED)
|
|
;
|
|
; +-----------------------------------------------------------------------+
|
|
; | CONTROL BLOCK REGISTERS (CS3FX) |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; | REGISTER | PORT | DIR | DESCRIPTION |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; | PPIDE_REG_ALTSTAT | 0x06 | R | ALTERNATE STATUS REGISTER |
|
|
; | PPIDE_REG_CTRL | 0x06 | W | DEVICE CONTROL REGISTER |
|
|
; | PPIDE_REG_DRVADR | 0x07 | R | DRIVE ADDRESS REGISTER |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
;
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; | COMMAND BLOCK REGISTERS (CS1FX) |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; | REGISTER | PORT | DIR | DESCRIPTION |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; | PPIDE_REG_DATA | 0x00 | R/W | DATA INPUT/OUTPUT |
|
|
; | PPIDE_REG_ERR | 0x01 | R | ERROR REGISTER |
|
|
; | PPIDE_REG_FEAT | 0x01 | W | FEATURES REGISTER |
|
|
; | PPIDE_REG_COUNT | 0x02 | R/W | SECTOR COUNT REGISTER |
|
|
; | PPIDE_REG_SECT | 0x03 | R/W | SECTOR NUMBER REGISTER |
|
|
; | PPIDE_REG_CYLLO | 0x04 | R/W | CYLINDER NUM REGISTER (LSB) |
|
|
; | PPIDE_REG_CYLHI | 0x05 | R/W | CYLINDER NUM REGISTER (MSB) |
|
|
; | PPIDE_REG_DRVHD | 0x06 | R/W | DRIVE/HEAD REGISTER |
|
|
; | PPIDE_REG_LBA0* | 0x03 | R/W | LBA BYTE 0 (BITS 0-7) |
|
|
; | PPIDE_REG_LBA1* | 0x04 | R/W | LBA BYTE 1 (BITS 8-15) |
|
|
; | PPIDE_REG_LBA2* | 0x05 | R/W | LBA BYTE 2 (BITS 16-23) |
|
|
; | PPIDE_REG_LBA3* | 0x06 | R/W | LBA BYTE 3 (BITS 24-27) |
|
|
; | PPIDE_REG_STAT | 0x07 | R | STATUS REGISTER |
|
|
; | PPIDE_REG_CMD | 0x07 | W | COMMAND REGISTER (EXECUTE) |
|
|
; +-----------------------+-------+-------+-------------------------------+
|
|
; * LBA0-4 ARE ALTERNATE DEFINITIONS OF SECT, CYL, AND DRVHD PORTS
|
|
;
|
|
; === STATUS REGISTER ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | BSY | DRDY | DWF | DSC | DRQ | CORR | IDX | ERR |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; BSY: BUSY
|
|
; DRDY: DRIVE READY
|
|
; DWF: DRIVE WRITE FAULT
|
|
; DSC: DRIVE SEEK COMPLETE
|
|
; DRQ: DATA REQUEST
|
|
; CORR: CORRECTED DATA
|
|
; IDX: INDEX
|
|
; ERR: ERROR
|
|
;
|
|
; === ERROR REGISTER ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | BBK | UNC | MC | IDNF | MCR | ABRT | TK0NF | AMNF |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; (VALID WHEN ERR BIT IS SET IN STATUS REGISTER)
|
|
;
|
|
; BBK: BAD BLOCK DETECTED
|
|
; UNC: UNCORRECTABLE DATA ERROR
|
|
; MC: MEDIA CHANGED
|
|
; IDNF: ID NOT FOUND
|
|
; MCR: MEDIA CHANGE REQUESTED
|
|
; ABRT: ABORTED COMMAND
|
|
; TK0NF: TRACK 0 NOT FOUND
|
|
; AMNF: ADDRESS MARK NOT FOUND
|
|
;
|
|
; === DRIVE/HEAD / LBA3 REGISTER ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | 1 | L | 1 | DRV | HS3 | HS2 | HS1 | HS0 |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; L: 0 = CHS ADDRESSING, 1 = LBA ADDRESSING
|
|
; DRV: 0 = DRIVE 0 (PRIMARY) SELECTED, 1 = DRIVE 1 (SLAVE) SELECTED
|
|
; HS: CHS = HEAD ADDRESS (0-15), LBA = BITS 24-27 OF LBA
|
|
;
|
|
; === DEVICE CONTROL REGISTER ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | X | X | X | X | 1 | SRST | ~IEN | 0 |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; SRST: SOFTWARE RESET
|
|
; ~IEN: INTERRUPT ENABLE
|
|
;
|
|
; CONTROL VALUES TO USE WHEN ACCESSING THE VARIOUS IDE DEVICE REGISTERS
|
|
;
|
|
PPIDE_REG_DATA .EQU PPIDE_CTL_CS1FX | $00 ; DATA INPUT/OUTPUT (R/W)
|
|
PPIDE_REG_ERR .EQU PPIDE_CTL_CS1FX | $01 ; ERROR REGISTER (R)
|
|
PPIDE_REG_FEAT .EQU PPIDE_CTL_CS1FX | $01 ; FEATURES REGISTER (W)
|
|
PPIDE_REG_COUNT .EQU PPIDE_CTL_CS1FX | $02 ; SECTOR COUNT REGISTER (R/W)
|
|
PPIDE_REG_SECT .EQU PPIDE_CTL_CS1FX | $03 ; SECTOR NUMBER REGISTER (R/W)
|
|
PPIDE_REG_CYLLO .EQU PPIDE_CTL_CS1FX | $04 ; CYLINDER NUM REGISTER (LSB) (R/W)
|
|
PPIDE_REG_CYLHI .EQU PPIDE_CTL_CS1FX | $05 ; CYLINDER NUM REGISTER (MSB) (R/W)
|
|
PPIDE_REG_DRVHD .EQU PPIDE_CTL_CS1FX | $06 ; DRIVE/HEAD REGISTER (R/W)
|
|
PPIDE_REG_LBA0 .EQU PPIDE_CTL_CS1FX | $03 ; LBA BYTE 0 (BITS 0-7) (R/W)
|
|
PPIDE_REG_LBA1 .EQU PPIDE_CTL_CS1FX | $04 ; LBA BYTE 1 (BITS 8-15) (R/W)
|
|
PPIDE_REG_LBA2 .EQU PPIDE_CTL_CS1FX | $05 ; LBA BYTE 2 (BITS 16-23) (R/W)
|
|
PPIDE_REG_LBA3 .EQU PPIDE_CTL_CS1FX | $06 ; LBA BYTE 3 (BITS 24-27) (R/W)
|
|
PPIDE_REG_STAT .EQU PPIDE_CTL_CS1FX | $07 ; STATUS REGISTER (R)
|
|
PPIDE_REG_CMD .EQU PPIDE_CTL_CS1FX | $07 ; COMMAND REGISTER (EXECUTE) (W)
|
|
PPIDE_REG_ALTSTAT .EQU PPIDE_CTL_CS3FX | $06 ; ALTERNATE STATUS REGISTER (R)
|
|
PPIDE_REG_CTRL .EQU PPIDE_CTL_CS3FX | $06 ; DEVICE CONTROL REGISTER (W)
|
|
PPIDE_REG_DRVADR .EQU PPIDE_CTL_CS3FX | $07 ; DRIVE ADDRESS REGISTER (R)
|
|
;
|
|
#IF (PPIDETRACE >= 3)
|
|
#DEFINE DCALL CALL
|
|
#ELSE
|
|
#DEFINE DCALL \;
|
|
#ENDIF
|
|
;
|
|
; UNIT MAPPING IS AS FOLLOWS:
|
|
; PPIDE0: PRIMARY MASTER
|
|
; PPIDE1: PRIMARY SLAVE
|
|
; PPIDE2: SECONDARY MASTER
|
|
; PPIDE3: SECONDARY SLAVE
|
|
;
|
|
PPIDE_DEVCNT .EQU 2 ; ASSUME ONLY PRIMARY INTERFACE
|
|
;
|
|
; COMMAND BYTES
|
|
;
|
|
PPIDE_CMD_RECAL .EQU $10
|
|
PPIDE_CMD_READ .EQU $20
|
|
PPIDE_CMD_WRITE .EQU $30
|
|
PPIDE_CMD_IDDEV .EQU $EC
|
|
PPIDE_CMD_SETFEAT .EQU $EF
|
|
;
|
|
; FEATURE BYTES
|
|
;
|
|
PPIDE_FEAT_ENABLE8BIT .EQU $01
|
|
PPIDE_FEAT_DISABLE8BIT .EQU $81
|
|
;
|
|
; PPIDE DEVICE TYPES
|
|
;
|
|
PPIDE_TYPEUNK .EQU 0
|
|
PPIDE_TYPEATA .EQU 1
|
|
PPIDE_TYPEATAPI .EQU 2
|
|
;
|
|
; PPIDE DEVICE STATUS
|
|
;
|
|
PPIDE_STOK .EQU 0
|
|
PPIDE_STINVUNIT .EQU -1
|
|
PPIDE_STNOMEDIA .EQU -2
|
|
PPIDE_STCMDERR .EQU -3
|
|
PPIDE_STIOERR .EQU -4
|
|
PPIDE_STRDYTO .EQU -5
|
|
PPIDE_STDRQTO .EQU -6
|
|
PPIDE_STBSYTO .EQU -7
|
|
;
|
|
; DRIVE SELECTION BYTES (FOR USE IN DRIVE/HEAD REGISTER)
|
|
;
|
|
PPIDE_DRVSEL:
|
|
PPIDE_DRVMASTER .DB %11100000 ; LBA, MASTER DEVICE
|
|
PPIDE_DRVSLAVE .DB %11110000 ; LBA, SLAVE DEVICE
|
|
;
|
|
; PPIDE DEVICE CONFIGURATION
|
|
;
|
|
PPIDE_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
; PER DEVICE DATA OFFSETS
|
|
;
|
|
PPIDE_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
|
|
PPIDE_STAT .EQU 1 ; LAST STATUS (BYTE)
|
|
PPIDE_TYPE .EQU 2 ; DEVICE TYPE (BYTE)
|
|
PPIDE_FLAGS .EQU 3 ; FLAG BITS BIT 0=CF, 1=LBA (BYTE)
|
|
PPIDE_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD)
|
|
PPIDE_LBA .EQU 8 ; OFFSET OF LBA (DWORD)
|
|
;
|
|
PPIDE_CFGTBL:
|
|
; DEVICE 0, PRIMARY MASTER
|
|
.DB 0 ; DRIVER DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB 0 ; DEVICE TYPE
|
|
.DB 0 ; FLAGS BYTE
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
; DEVICE 1, PRIMARY SLAVE
|
|
.DB 1 ; DRIVER DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB 0 ; DEVICE TYPE
|
|
.DB 0 ; FLAGS BYTE
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
#IF ($ - PPIDE_CFGTBL) != (PPIDE_DEVCNT * PPIDE_CFGSIZ)
|
|
.ECHO "*** INVALID PPIDE CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END MARKER
|
|
;
|
|
; 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.
|
|
;
|
|
PPIDE_TONORM .EQU 200 ; NORMAL TIMEOUT IS 10 SECS
|
|
PPIDE_TOFAST .EQU 10 ; FAST TIMEOUT IS 0.5 SECS
|
|
;
|
|
;=============================================================================
|
|
; INITIALIZATION ENTRY POINT
|
|
;=============================================================================
|
|
;
|
|
PPIDE_INIT:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("PPIDE:$") ; LABEL FOR IO ADDRESS
|
|
;
|
|
; 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
|
|
LD A,(CB_CPUMHZ) ; LOAD CPU SPEED IN MHZ
|
|
CALL MULT8X16 ; HL := DE * A
|
|
LD (PPIDE_TOSCALER),HL ; SAVE IT
|
|
;
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,PPIDE_IO_BASE
|
|
CALL PRTHEXBYTE
|
|
;
|
|
#IF (PPIDE8BIT)
|
|
PRTS(" 8BIT$")
|
|
#ENDIF
|
|
CALL PPIDE_DETECT ; CHECK FOR HARDWARE
|
|
JR Z,PPIDE_INIT00 ; CONTINUE IF PRESENT
|
|
;
|
|
; HARDWARE NOT PRESENT
|
|
PRTS(" NOT PRESENT$")
|
|
OR $FF ; SIGNAL FAILURE
|
|
RET
|
|
;
|
|
PPIDE_INIT00:
|
|
PRTS(" DEVICES=$")
|
|
LD A,PPIDE_DEVCNT
|
|
CALL PRTDECB
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
;
|
|
LD B,PPIDE_DEVCNT ; LOOP CONTROL
|
|
LD IY,PPIDE_CFGTBL ; START OF CFG TABLE
|
|
PPIDE_INIT0:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
LD BC,PPIDE_FNTBL ; BC := FUNC TABLE ADR
|
|
PUSH IY ; CFG ENTRY POINTER
|
|
POP DE ; COPY TO DE
|
|
CALL DIO_ADDENT ; ADD ENTRY TO GLOBAL DISK DEV TABLE
|
|
LD BC,PPIDE_CFGSIZ ; SIZE OF CFG ENTRY
|
|
ADD IY,BC ; BUMP IY TO NEXT ENTRY
|
|
POP BC ; RESTORE BC
|
|
DJNZ PPIDE_INIT0 ; LOOP AS NEEDED
|
|
;
|
|
; INITIALIZE THE PPIDE INTERFACE NOW
|
|
CALL PPIDE_RESET ; DO HARDWARE SETUP/INIT
|
|
RET NZ ; ABORT IF RESET FAILS
|
|
;
|
|
; DEVICE DISPLAY LOOP
|
|
LD B,PPIDE_DEVCNT ; LOOP ONCE PER DEVICE
|
|
LD IY,PPIDE_CFGTBL ; START OF CFG TABLE
|
|
PPIDE_INIT1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL PPIDE_INIT2 ; DISPLAY UNIT INFO
|
|
LD BC,PPIDE_CFGSIZ ; SIZE OF CFG ENTRY
|
|
ADD IY,BC ; BUMP IY TO NEXT ENTRY
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
DJNZ PPIDE_INIT1 ; LOOP UNTIL DONE
|
|
RET ; DONE
|
|
;
|
|
PPIDE_INIT2:
|
|
; CHECK FOR BAD STATUS
|
|
LD A,(IY+PPIDE_STAT) ; GET STATUS
|
|
OR A ; SET FLAGS
|
|
JP NZ,PPIDE_PRTSTAT ; EXIT VIA PRINT STATUS
|
|
;
|
|
CALL PPIDE_PRTPREFIX ; PRINT DEVICE PREFIX
|
|
;
|
|
#IF (PPIDE8BIT)
|
|
PRTS(" 8BIT$")
|
|
#ENDIF
|
|
;
|
|
; PRINT LBA/NOLBA
|
|
CALL PC_SPACE ; FORMATTING
|
|
BIT 1,(IY+PPIDE_FLAGS) ; TEST LBA FLAG
|
|
LD DE,PPIDE_STR_NO ; POINT TO "NO" STRING
|
|
CALL Z,WRITESTR ; PRINT "NO" BEFORE "LBA" IF LBA NOT SUPPORTED
|
|
PRTS("LBA$") ; PRINT "LBA" REGARDLESS
|
|
;
|
|
; PRINT STORAGE CAPACITY (BLOCK COUNT)
|
|
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
|
LD A,PPIDE_MEDCAP ; OFFSET TO CAPACITY FIELD
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL LD32 ; GET THE CAPACITY VALUE
|
|
CALL PRTHEX32 ; PRINT HEX VALUE
|
|
;
|
|
; PRINT STORAGE SIZE IN MB
|
|
PRTS(" SIZE=$") ; PRINT FIELD LABEL
|
|
LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
|
|
CALL SRL32 ; RIGHT SHIFT
|
|
CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED)
|
|
PRTS("MB$") ; PRINT SUFFIX
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; RETURN WITH A=0, AND Z SET
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; PROBE FOR PPIDE HARDWARE
|
|
;----------------------------------------------------------------------
|
|
;
|
|
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
|
|
;
|
|
PPIDE_DETECT:
|
|
;
|
|
; TEST FOR PPI EXISTENCE
|
|
; WE SETUP THE PPI TO WRITE, THEN WRITE A VALUE OF ZERO
|
|
; TO PORT A (DATALO), THEN READ IT BACK. IF THE PPI IS THERE
|
|
; THEN THE BUS HOLD CIRCUITRY WILL READ BACK THE ZERO. SINCE
|
|
; WE ARE IN WRITE MODE, AN IDE CONTROLLER WILL NOT BE ABLE TO
|
|
; INTERFERE WITH THE VALUE BEING READ.
|
|
LD A,PPIDE_DIR_WRITE ; SET DATA BUS DIRECTION TO WRITE
|
|
OUT (PPIDE_IO_PPI),A ; OUTPUT TO CONTROL WORD
|
|
LD C,PPIDE_IO_DATALO ; PPI PORT A
|
|
XOR A ; VALUE ZERO
|
|
OUT (C),A ; PUSH VALUE TO PORT
|
|
IN A,(C) ; GET PORT VALUE
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;=============================================================================
|
|
; DRIVER FUNCTION TABLE
|
|
;=============================================================================
|
|
;
|
|
PPIDE_FNTBL:
|
|
.DW PPIDE_STATUS
|
|
.DW PPIDE_RESET
|
|
.DW PPIDE_SEEK
|
|
.DW PPIDE_READ
|
|
.DW PPIDE_WRITE
|
|
.DW PPIDE_VERIFY
|
|
.DW PPIDE_FORMAT
|
|
.DW PPIDE_DEVICE
|
|
.DW PPIDE_MEDIA
|
|
.DW PPIDE_DEFMED
|
|
.DW PPIDE_CAP
|
|
.DW PPIDE_GEOM
|
|
#IF (($ - PPIDE_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID PPIDE FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
PPIDE_VERIFY:
|
|
PPIDE_FORMAT:
|
|
PPIDE_DEFMED:
|
|
CALL PANIC ; NOT IMPLEMENTED
|
|
;
|
|
;
|
|
;
|
|
PPIDE_READ:
|
|
LD BC,PPIDE_RDSEC ; GET ADR OF SECTOR READ FUNC
|
|
LD (PPIDE_IOFNADR),BC ; SAVE IT AS PENDING IO FUNC
|
|
JR PPIDE_IO ; CONTINUE TO GENERIC IO ROUTINE
|
|
;
|
|
;
|
|
;
|
|
PPIDE_WRITE:
|
|
LD BC,PPIDE_WRSEC ; GET ADR OF SECTOR WRITE FUNC
|
|
LD (PPIDE_IOFNADR),BC ; SAVE IT AS PENDING IO FUNC
|
|
JR PPIDE_IO ; CONTINUE TO GENERIC IO ROUTINE
|
|
;
|
|
;
|
|
;
|
|
PPIDE_IO:
|
|
LD (PPIDE_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,E ; BLOCK COUNT TO A
|
|
OR A ; SET FLAGS
|
|
RET Z ; ZERO SECTOR I/O, RETURN W/ E=0 & A=0
|
|
LD B,A ; INIT SECTOR DOWNCOUNTER
|
|
LD C,0 ; INIT SECTOR READ/WRITE COUNT
|
|
#IF (PPIDETRACE == 1)
|
|
LD HL,PPIDE_PRTERR ; SET UP PPIDE_PRTERR
|
|
PUSH HL ; ... TO FILTER ALL EXITS
|
|
#ENDIF
|
|
PUSH BC ; SAVE COUNTERS
|
|
CALL PPIDE_SELUNIT ; HARDWARE SELECTION OF TARGET UNIT
|
|
CALL PPIDE_CHKDEVICE ; CHECK DEVICE AND CLEAR STATUS
|
|
POP BC ; RESTORE COUNTERS
|
|
JR NZ,PPIDE_IO3 ; BAIL OUT ON ERROR
|
|
PPIDE_IO1:
|
|
PUSH BC ; SAVE COUNTERS
|
|
LD HL,(PPIDE_IOFNADR) ; GET PENDING IO FUNCTION ADDRESS
|
|
CALL JPHL ; ... AND CALL IT
|
|
JR NZ,PPIDE_IO2 ; IF ERROR, SKIP INCREMENT
|
|
; INCREMENT LBA
|
|
LD A,PPIDE_LBA ; LBA OFFSET
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL INC32HL ; INCREMENT THE VALUE
|
|
; INCREMENT DMA
|
|
LD HL,PPIDE_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
XOR A ; SIGNAL SUCCESS
|
|
PPIDE_IO2:
|
|
POP BC ; RECOVER COUNTERS
|
|
JR NZ,PPIDE_IO3 ; IF ERROR, BAIL OUT
|
|
INC C ; BUMP COUNT OF SECTORS READ
|
|
DJNZ PPIDE_IO1 ; LOOP AS NEEDED
|
|
PPIDE_IO3:
|
|
LD E,C ; SECTOR READ COUNT TO E
|
|
LD HL,(PPIDE_DSKBUF) ; CURRENT DMA TO HL
|
|
OR A ; SET FLAGS BASED ON RETURN CODE
|
|
RET ; AND RETURN, A HAS RETURN CODE
|
|
;
|
|
;
|
|
;
|
|
PPIDE_STATUS:
|
|
; RETURN UNIT STATUS
|
|
LD A,(IY+PPIDE_STAT) ; GET STATUS OF SELECTED DEVICE
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPIDE_DEVICE:
|
|
LD D,DIODEV_PPIDE ; D := DEVICE TYPE
|
|
LD E,(IY+PPIDE_DEV) ; E := PHYSICAL DEVICE NUMBER
|
|
BIT 0,(IY+PPIDE_FLAGS) ; TEST CF BIT IN FLAGS
|
|
LD C,%00000000 ; ASSUME NON-REMOVABLE HARD DISK
|
|
JR Z,PPIDE_DEVICE1 ; IF Z, WE ARE DONE
|
|
LD C,%01001000 ; OTHERWISE REMOVABLE COMPACT FLASH
|
|
PPIDE_DEVICE1:
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; IDE_GETMED
|
|
;
|
|
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
|
|
;
|
|
; 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
|
|
;
|
|
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
|
|
LD E,MID_HD ; ASSUME WE ARE OK
|
|
RET Z ; RETURN IF GOOD INIT
|
|
LD E,MID_NONE ; SIGNAL NO MEDIA
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPIDE_SEEK:
|
|
BIT 7,D ; CHECK FOR LBA FLAG
|
|
CALL Z,HB_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA
|
|
RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA)
|
|
LD (IY+PPIDE_LBA+0),L ; SAVE NEW LBA
|
|
LD (IY+PPIDE_LBA+1),H ; ...
|
|
LD (IY+PPIDE_LBA+2),E ; ...
|
|
LD (IY+PPIDE_LBA+3),D ; ...
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPIDE_CAP:
|
|
LD A,(IY+PPIDE_STAT) ; GET STATUS
|
|
PUSH AF ; SAVE IT
|
|
LD A,PPIDE_MEDCAP ; OFFSET TO CAPACITY FIELD
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL LD32 ; GET THE CURRENT CAPACITY INTO DE:HL
|
|
LD BC,512 ; 512 BYTES PER BLOCK
|
|
POP AF ; RECOVER STATUS
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_GEOM:
|
|
; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS
|
|
; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE
|
|
CALL PPIDE_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC
|
|
LD L,H ; DIVPPIDE BY 256 FOR # TRACKS
|
|
LD H,E ; ... HIGH BYTE DISCARDED, RESULT IN HL
|
|
LD D,16 | $80 ; HEADS / CYL = 16, SET LBA CAPABILITY BIT
|
|
LD E,16 ; SECTORS / TRACK = 16
|
|
RET ; DONE, A STILL HAS PPIDE_CAP STATUS
|
|
;
|
|
;=============================================================================
|
|
; FUNCTION SUPPORT ROUTINES
|
|
;=============================================================================
|
|
;
|
|
;
|
|
;
|
|
PPIDE_SETFEAT:
|
|
PUSH AF
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" SETFEAT$")
|
|
#ENDIF
|
|
LD A,(PPIDE_DRVHD)
|
|
;OUT (PPIDE_REG_DRVHD),A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_DRVHD
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
POP AF
|
|
;OUT (PPIDE_REG_FEAT),A ; SET THE FEATURE VALUE
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_FEAT
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
LD A,PPIDE_CMD_SETFEAT ; CMD = SETFEAT
|
|
LD (PPIDE_CMD),A ; SAVE IT
|
|
JP PPIDE_RUNCMD ; RUN COMMAND AND EXIT
|
|
;
|
|
;
|
|
;
|
|
PPIDE_IDENTIFY:
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" IDDEV$")
|
|
#ENDIF
|
|
LD A,(PPIDE_DRVHD)
|
|
;OUT (PPIDE_REG_DRVHD),A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_DRVHD
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
LD A,PPIDE_CMD_IDDEV
|
|
LD (PPIDE_CMD),A
|
|
CALL PPIDE_RUNCMD
|
|
RET NZ
|
|
LD HL,HB_WRKBUF
|
|
JP PPIDE_GETBUF ; EXIT THRU BUFRD
|
|
;
|
|
;
|
|
;
|
|
PPIDE_RDSEC:
|
|
;
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" READ$")
|
|
#ENDIF
|
|
LD A,(PPIDE_DRVHD)
|
|
;OUT (PPIDE_REG_DRVHD),A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_DRVHD
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_SETADDR ; SETUP CYL, TRK, HEAD
|
|
LD A,PPIDE_CMD_READ
|
|
LD (PPIDE_CMD),A
|
|
CALL PPIDE_RUNCMD
|
|
RET NZ
|
|
LD HL,(PPIDE_DSKBUF)
|
|
JP PPIDE_GETBUF
|
|
;
|
|
;
|
|
;
|
|
PPIDE_WRSEC:
|
|
;
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" WRITE$")
|
|
#ENDIF
|
|
LD A,(PPIDE_DRVHD)
|
|
;OUT (PPIDE_REG_DRVHD),A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_DRVHD
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_SETADDR ; SETUP CYL, TRK, HEAD
|
|
LD A,PPIDE_CMD_WRITE
|
|
LD (PPIDE_CMD),A
|
|
CALL PPIDE_RUNCMD
|
|
RET NZ
|
|
LD HL,(PPIDE_DSKBUF)
|
|
JP PPIDE_PUTBUF
|
|
;
|
|
;
|
|
;
|
|
PPIDE_SETADDR:
|
|
; XXX
|
|
; SEND 3 LOWEST BYTES OF LBA IN REVERSE ORDER
|
|
; IDE_IO_LBA3 HAS ALREADY BEEN SET
|
|
; HSTLBA2-0 --> IDE_IO_LBA2-0
|
|
LD A,(IY+PPIDE_LBA+2)
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_LBA2
|
|
|
|
LD A,(IY+PPIDE_LBA+1)
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_LBA1
|
|
|
|
LD A,(IY+PPIDE_LBA+0)
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_LBA0
|
|
|
|
LD A,1
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_COUNT
|
|
;
|
|
#IF (DSKYENABLE)
|
|
CALL PPIDE_DSKY
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; COMMAND PROCESSING
|
|
;=============================================================================
|
|
;
|
|
PPIDE_RUNCMD:
|
|
CALL PPIDE_WAITRDY ; WAIT FOR DRIVE READY
|
|
RET NZ ; BAIL OUT ON TIMEOUT
|
|
;
|
|
LD A,(PPIDE_CMD) ; GET THE COMMAND
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
;OUT (PPIDE_REG_CMD),A ; SEND IT (STARTS EXECUTION)
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_CMD
|
|
#IF (PPIDETRACE >= 3)
|
|
PRTS(" -->$")
|
|
#ENDIF
|
|
;
|
|
CALL PPIDE_WAITBSY ; WAIT FOR DRIVE READY (COMMAND DONE)
|
|
RET NZ ; BAIL OUT ON TIMEOUT
|
|
;
|
|
CALL PPIDE_GETRES
|
|
JP NZ,PPIDE_CMDERR
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_GETBUF:
|
|
#IF (PPIDETRACE >= 3)
|
|
PRTS(" GETBUF$")
|
|
#ENDIF
|
|
;
|
|
; WAIT FOR BUFFER
|
|
CALL PPIDE_WAITDRQ ; WAIT FOR BUFFER READY
|
|
RET NZ ; BAIL OUT IF TIMEOUT
|
|
;
|
|
; SETUP PPI TO READ
|
|
LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ
|
|
OUT (PPIDE_IO_PPI),A ; DO IT
|
|
;
|
|
; SELECT READ/WRITE IDE REGISTER
|
|
LD A,PPIDE_REG_DATA ; DATA REGISTER
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
LD E,A ; E := READ UNASSERTED
|
|
XOR PPIDE_CTL_DIOR ; SWAP THE READ LINE BIT
|
|
LD D,A ; D := READ ASSERTED
|
|
;
|
|
; LOOP SETUP
|
|
LD B,0 ; 256 ITERATIONS
|
|
LD C,PPIDE_IO_DATALO ; SETUP C WITH IO PORT (LSB)
|
|
;
|
|
#IF (!PPIDE8BIT)
|
|
INC C ; PRE-INCREMENT C
|
|
#ENDIF
|
|
;
|
|
CALL PPIDE_GETBUF1 ; FIRST PASS (FIRST 256 BYTES)
|
|
CALL PPIDE_GETBUF1 ; SECOND PASS (LAST 256 BYTES)
|
|
;
|
|
;; CLEAN UP
|
|
;XOR A ; ZERO A
|
|
;OUT (PPIDE_IO_CTL),A ; RELEASE ALL BUS SIGNALS
|
|
;
|
|
CALL PPIDE_WAITRDY ; PROBLEMS IF THIS IS REMOVED!
|
|
RET NZ
|
|
CALL PPIDE_GETRES
|
|
JP NZ,PPIDE_IOERR
|
|
RET
|
|
;
|
|
PPIDE_GETBUF1: ; START OF READ LOOP
|
|
LD A,D ; ASSERT READ
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
#IF (!PPIDE8BIT)
|
|
DEC C
|
|
INI ; GET AND SAVE NEXT BYTE
|
|
INC C ; LSB -> MSB
|
|
#ENDIF
|
|
INI ; GET AND SAVE NEXT BYTE
|
|
LD A,E ; DEASSERT READ
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
;
|
|
JR NZ,PPIDE_GETBUF1 ; LOOP UNTIL DONE
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_PUTBUF:
|
|
#IF (PPIDETRACE >= 3)
|
|
PRTS(" PUTBUF$")
|
|
#ENDIF
|
|
|
|
; WAIT FOR BUFFER
|
|
CALL PPIDE_WAITDRQ ; WAIT FOR BUFFER READY
|
|
RET NZ ; BAIL OUT IF TIMEOUT
|
|
;
|
|
; SETUP PPI TO WRITE
|
|
LD A,PPIDE_DIR_WRITE ; SET DATA BUS DIRECTION TO WRITE
|
|
OUT (PPIDE_IO_PPI),A ; DO IT
|
|
;
|
|
; SELECT READ/WRITE IDE REGISTER
|
|
LD A,PPIDE_REG_DATA ; DATA REGISTER
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
LD E,A ; E := WRITE UNASSERTED
|
|
XOR PPIDE_CTL_DIOW ; SWAP THE READ LINE BIT
|
|
LD D,A ; D := WRITE ASSERTED
|
|
;
|
|
; LOOP SETUP
|
|
LD B,0 ; 256 ITERATIONS
|
|
LD C,PPIDE_IO_DATALO ; SETUP C WITH IO PORT (LSB)
|
|
;
|
|
#IF (!PPIDE8BIT)
|
|
INC C ; PRE-INCREMENT C
|
|
#ENDIF
|
|
;
|
|
CALL PPIDE_PUTBUF1 ; FIRST PASS (FIRST 256 BYTES)
|
|
CALL PPIDE_PUTBUF1 ; SECOND PASS (LAST 256 BYTES)
|
|
;
|
|
;; CLEAN UP
|
|
;XOR A ; ZERO A
|
|
;OUT (PPIDE_IO_CTL),A ; RELEASE ALL BUS SIGNALS
|
|
;
|
|
CALL PPIDE_WAITRDY ; PROBLEMS IF THIS IS REMOVED!
|
|
RET NZ
|
|
CALL PPIDE_GETRES
|
|
JP NZ,PPIDE_IOERR
|
|
RET
|
|
;
|
|
PPIDE_PUTBUF1: ; START OF READ LOOP
|
|
#IF (!PPIDE8BIT)
|
|
DEC C
|
|
OUTI ; PUT NEXT BYTE ON THE BUS (LSB)
|
|
INC C
|
|
#ENDIF
|
|
OUTI
|
|
LD A,D ; ASSERT WRITE
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
LD A,E ; DEASSERT WRITE
|
|
OUT (PPIDE_IO_CTL),A ; DO IT
|
|
;
|
|
JR NZ,PPIDE_PUTBUF1 ; LOOP UNTIL DONE
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_GETRES:
|
|
;IN A,(PPIDE_REG_STAT) ; READ STATUS
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_STAT
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
AND %00000001 ; ERROR BIT SET?
|
|
RET Z ; NOPE, RETURN WITH ZF
|
|
;
|
|
;IN A,(PPIDE_REG_ERR) ; READ ERROR REGISTER
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_ERR
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
OR $FF ; FORCE NZ TO SIGNAL ERROR
|
|
RET ; RETURN
|
|
;
|
|
;=============================================================================
|
|
; HARDWARE INTERFACE ROUTINES
|
|
;=============================================================================
|
|
;
|
|
; SOFT RESET OF ALL DEVICES ON BUS
|
|
;
|
|
PPIDE_RESET:
|
|
;
|
|
; SETUP PPI TO READ
|
|
LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ
|
|
OUT (PPIDE_IO_PPI),A ; DO IT
|
|
;
|
|
; PULSE IDE RESET LINE
|
|
LD A,PPIDE_CTL_RESET
|
|
OUT (PPIDE_IO_CTL),A
|
|
LD DE,20
|
|
CALL VDELAY
|
|
XOR A
|
|
OUT (PPIDE_IO_CTL),A
|
|
LD DE,20
|
|
CALL VDELAY
|
|
;
|
|
LD A,%00001010 ; SET ~IEN, 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
|
|
CALL VDELAY
|
|
;
|
|
;; CLEAR OUT ALL DATA (FOR ALL UNITS)
|
|
;LD HL,PPIDE_UDATA
|
|
;LD BC,PPIDE_UDLEN
|
|
;XOR A
|
|
;CALL FILL
|
|
;
|
|
PUSH IY ; SAVE CURRENT DEVICE CFG PTR
|
|
;
|
|
; PROBE / INITIALIZE ALL UNITS
|
|
LD B,PPIDE_DEVCNT ; NUMBER OF UNITS TO TRY
|
|
LD IY,PPIDE_CFGTBL ; START OF CFG TABLE
|
|
PPIDE_RESET1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL PPIDE_INITUNIT ; PROBE/INIT UNIT
|
|
LD BC,PPIDE_CFGSIZ ; SIZE OF CFG ENTRY
|
|
ADD IY,BC ; BUMP IY TO NEXT ENTRY
|
|
POP BC ; RESTORE BC
|
|
DJNZ PPIDE_RESET1 ; LOOP AS NEEDED
|
|
;
|
|
POP IY ; RECOVER DEVICE CFG PTR
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND DONE
|
|
;
|
|
;
|
|
;
|
|
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
|
|
CALL Z,PPIDE_INITDEV ; IF FOUND, ATTEMPT TO INIT DEVICE
|
|
|
|
RET
|
|
;
|
|
; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT
|
|
;
|
|
PPIDE_SELUNIT:
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" SELUNIT$")
|
|
#ENDIF
|
|
PUSH HL ; SAVE HL, IT IS DESTROYED BELOW
|
|
PUSH IY
|
|
POP BC
|
|
LD A,(IY+PPIDE_DEV) ; GET DEVICE
|
|
AND $01 ; LS BIT DETERMINES MASTER/SLAVE
|
|
LD HL,PPIDE_DRVSEL
|
|
CALL ADDHLA
|
|
LD A,(HL) ; LOAD DRIVE/HEAD VALUE
|
|
POP HL ; RECOVER HL
|
|
LD (PPIDE_DRVHD),A ; SAVE IT
|
|
;
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_PROBE:
|
|
#IF (PPIDETRACE >= 3)
|
|
CALL PPIDE_PRTPREFIX
|
|
PRTS(" PROBE$") ; LABEL FOR IO ADDRESS
|
|
#ENDIF
|
|
;
|
|
LD A,(PPIDE_DRVHD)
|
|
;OUT (IDE_IO_DRVHD),A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_DRVHD
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
|
|
CALL DELAY ; DELAY ~16US
|
|
;
|
|
; IN A,(PPIDE_REG_STAT) ; GET STATUS
|
|
; BELOW TESTS FOR EXISTENCE OF AN IDE CONTROLLER ON THE
|
|
; PPIDE INTERFACE. WE WRITE A VALUE OF ZERO FIRST SO THAT
|
|
; THE PPI BUS HOLD WILL RETURN A VALUE OF ZERO IF THERE IS
|
|
; NOTHING CONNECTED TO PPI PORT A. THEN WE READ THE STATUS
|
|
; REGISTER. IF AN IDE CONTROLLER IS THERE, IT SHOULD ALWAYS
|
|
; RETURN SOMETHING OTHER THAN ZERO. NOTE THAT REG_STAT IS
|
|
; ALSO THE COMMAND REGISTER FOR THE IDE CONTOLLER, BUT A
|
|
; COMMAND VALUE OF ZERO IS A NOP, SO IT DOES NO HARM IF AN
|
|
; IDE CONTOLLER IS THERE AND SEES IT.
|
|
XOR A
|
|
CALL PPIDE_OUT
|
|
.DB PPIDE_REG_STAT
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_STAT
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE
|
|
OR A
|
|
JP Z,PPIDE_NOMEDIA
|
|
;
|
|
DCALL PPIDE_REGDUMP
|
|
;
|
|
;JR PPIDE_PROBE1 ; *DEBUG*
|
|
;
|
|
PPIDE_PROBE0:
|
|
CALL PPIDE_WAITBSY ; WAIT FOR BUSY TO CLEAR
|
|
JP NZ,PPIDE_NOMEDIA ; CONVERT TIMEOUT TO NO MEDIA AND RETURN
|
|
;
|
|
DCALL PPIDE_REGDUMP
|
|
;
|
|
; CHECK STATUS
|
|
; IN A,(PPIDE_REG_STAT) ; GET STATUS
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_STAT
|
|
DCALL PC_SPACE
|
|
DCALL PRTHEXBYTE ; IF DEBUG, PRINT STATUS
|
|
OR A ; SET FLAGS TO TEST FOR ZERO
|
|
JP Z,PPIDE_NOMEDIA ; CONTINUE IF NON-ZERO
|
|
;
|
|
; CHECK SIGNATURE
|
|
DCALL PC_SPACE
|
|
;IN A,(PPIDE_REG_COUNT)
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_COUNT
|
|
DCALL PRTHEXBYTE
|
|
CP $01
|
|
JP NZ,PPIDE_NOMEDIA
|
|
DCALL PC_SPACE
|
|
;IN A,(PPIDE_REG_SECT)
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_SECT
|
|
DCALL PRTHEXBYTE
|
|
CP $01
|
|
JP NZ,PPIDE_NOMEDIA
|
|
DCALL PC_SPACE
|
|
;IN A,(PPIDE_REG_CYLLO)
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_CYLLO
|
|
DCALL PRTHEXBYTE
|
|
CP $00
|
|
JP NZ,PPIDE_NOMEDIA
|
|
DCALL PC_SPACE
|
|
;IN A,(PPIDE_REG_CYLHI)
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_CYLHI
|
|
DCALL PRTHEXBYTE
|
|
CP $00
|
|
JP NZ,PPIDE_NOMEDIA
|
|
;
|
|
PPIDE_PROBE1:
|
|
; SIGNATURE MATCHES ATA DEVICE, RECORD TYPE AND RETURN SUCCESS
|
|
LD A,PPIDE_TYPEATA ; TYPE = ATA
|
|
LD (IY+PPIDE_TYPE),A ; SET IT IN INSTANCE DATA
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE, NOTE THAT A=0 AND Z IS SET
|
|
;
|
|
; (RE)INITIALIZE DEVICE
|
|
;
|
|
PPIDE_INITDEV:
|
|
;
|
|
LD A,(IY+PPIDE_TYPE) ; GET THE DEVICE TYPE
|
|
OR A ; SET FLAGS
|
|
JP Z,PPIDE_NOMEDIA ; EXIT SETTING NO MEDIA STATUS
|
|
;
|
|
; CLEAR OUT UNIT SPECIFIC DATA, BUT PRESERVE THE EXISTING
|
|
; VALUE OF THE UNIT TYPE WHICH WAS ESTABLISHED BY THE DEVICE
|
|
; PROBES WHEN THE PPIDE BUS WAS RESET
|
|
;PUSH AF ; SAVE UNIT TYPE VALUE FROM ABOVE
|
|
;LD A,(IY+PPIDE_DEV) ; GET CURRENT DEVICE NUMBER
|
|
;PUSH AF ; ... AND SAVE IT
|
|
;;PUSH HL ; SAVE UNIT TYPE FIELD POINTER
|
|
;;PPIDE_DPTR(0) ; SET HL TO START OF UNIT DATA
|
|
;;LD BC,PPIDE_UDLEN
|
|
;;XOR A
|
|
;;CALL FILL
|
|
;;POP HL ; RECOVER UNIT TYPE FIELD POINTER
|
|
;;POP AF ; RECOVER UNIT TYPE VALUE
|
|
;PUSH IY ; SET HL TO
|
|
;POP HL ; ... START OF DEVICE INSTANCE DATA
|
|
;LD BC,PPIDE_CFGSIZ ; SIZE OF CONFGI DATA TO CLEAR
|
|
;XOR A ; FILL WITH ZERO
|
|
;CALL FILL ; DO IT
|
|
;POP AF ; RECOVER DEVICE NUMBER VALUE
|
|
;LD (IY+PPIDE_DEV),A ; ... AND PUT IT BACK
|
|
;POP AF ; RECOVER DEVICE TYPE VALUE
|
|
;LD (IY+PPIDE_TYPE),A ; ... AND PUT IT BACK
|
|
;
|
|
#IF (PPIDE8BIT)
|
|
LD A,PPIDE_FEAT_ENABLE8BIT ; FEATURE VALUE = ENABLE 8-BIT PIO
|
|
#ELSE
|
|
LD A,PPIDE_FEAT_DISABLE8BIT ; FEATURE VALUE = DISABLE 8-BIT PIO
|
|
#ENDIF
|
|
CALL PPIDE_SETFEAT ; SET FEATURE
|
|
|
|
#IF (PPIDE8BIT)
|
|
; "REAL" IDE DRIVES MAY NOT ACCEPT THE DISABLE8BIT FEATURE COMMAND,
|
|
; SO IT IS ONLY AN ERROR IF WE ARE ATTEMPTING TO ENABLE8BIT.
|
|
; CREDIT TO ED BRINDLEY FOR THIS CORRECTION.
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
#ENDIF
|
|
;
|
|
CALL PPIDE_IDENTIFY ; EXECUTE PPIDENTIFY COMMAND
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
;
|
|
LD DE,HB_WRKBUF ; POINT TO BUFFER
|
|
DCALL DUMP_BUFFER ; DUMP IT IF DEBUGGING
|
|
;
|
|
XOR A
|
|
LD (IY+PPIDE_FLAGS),0 ; CLEAR FLAGS
|
|
|
|
; DETERMINE IF CF DEVICE
|
|
LD HL,HB_WRKBUF ; FIRST WORD OF IDENTIFY DATA HAS CF FLAG
|
|
LD A,$8A ; FIRST BYTE OF MARKER IS $8A
|
|
CP (HL) ; COMPARE
|
|
JR NZ,PPIDE_INITDEV1 ; IF NO MATCH, NOT CF
|
|
INC HL
|
|
LD A,$84 ; SECOND BYTE OF MARKER IS $84
|
|
CP (HL) ; COMPARE
|
|
JR NZ,PPIDE_INITDEV1 ; IF NOT MATCH, NOT CF
|
|
SET 0,(IY+PPIDE_FLAGS) ; SET FLAGS BIT FOR CF MEDIA
|
|
;
|
|
PPIDE_INITDEV1:
|
|
; DETERMINE IF LBA CAPABLE
|
|
LD A,(HB_WRKBUF+98+1) ; GET BYTE WITH LBA BIT FROM BUFFER
|
|
BIT 1,A ; CHECK THE LBA BIT
|
|
JR Z,PPIDE_INITDEV2 ; NOT SET, BYPASS
|
|
SET 1,(IY+PPIDE_FLAGS) ; SET FLAGS BIT FOR LBA
|
|
;
|
|
PPIDE_INITDEV2:
|
|
; GET DEVICE CAPACITY AND SAVE IT
|
|
LD A,PPIDE_MEDCAP ; OFFSET TO CAPACITY FIELD
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
PUSH HL ; SAVE POINTER
|
|
LD HL,HB_WRKBUF ; POINT TO BUFFER START
|
|
LD A,120 ; OFFSET OF SECTOR COUNT
|
|
CALL ADDHLA ; POINT TO ADDRESS OF SECTOR COUNT
|
|
CALL LD32 ; LOAD IT TO DE:HL
|
|
POP BC ; RECOVER POINTER TO CAPACITY ENTRY
|
|
CALL ST32 ; SAVE CAPACITY
|
|
;
|
|
; RESET CARD STATUS TO 0 (OK)
|
|
XOR A ; A := 0 (STATUS = OK)
|
|
LD (IY+PPIDE_STAT),A ; SAVE IT
|
|
;
|
|
RET ; RETURN, A=0, Z SET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_CHKDEVICE:
|
|
LD A,(IY+PPIDE_STAT) ; GET STATUS
|
|
OR A ; SET FLAGS
|
|
RET Z ; RETURN IF ALL IS WELL
|
|
;
|
|
; ATTEMPT TO REINITIALIZE HERE???
|
|
JP PPIDE_ERR
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_WAITRDY:
|
|
LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS
|
|
LD B,A ; PUT IN OUTER LOOP VAR
|
|
PPIDE_WAITRDY1:
|
|
LD DE,(PPIDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR
|
|
PPIDE_WAITRDY2:
|
|
;IN A,(PPIDE_REG_STAT) ; READ STATUS
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_STAT
|
|
LD C,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
|
|
RET Z ; ALL SET, RETURN WITH Z SET
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JR NZ,PPIDE_WAITRDY2 ; INNER LOOP RETURN
|
|
DJNZ PPIDE_WAITRDY1 ; OUTER LOOP RETURN
|
|
JP PPIDE_RDYTO ; EXIT WITH RDYTO ERR
|
|
;
|
|
;
|
|
;
|
|
PPIDE_WAITDRQ:
|
|
LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS
|
|
LD B,A ; PUT IN OUTER LOOP VAR
|
|
PPIDE_WAITDRQ1:
|
|
LD DE,(PPIDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR
|
|
PPIDE_WAITDRQ2:
|
|
;IN A,(PPIDE_REG_STAT) ; READ STATUS
|
|
CALL PPIDE_IN
|
|
.DB PPIDE_REG_STAT
|
|
LD C,A ; SAVE IT
|
|
AND %10001000 ; TO FILL (OR READY TO FILL)
|
|
XOR %00001000
|
|
RET Z
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JR NZ,PPIDE_WAITDRQ2
|
|
DJNZ PPIDE_WAITDRQ1
|
|
JP PPIDE_DRQTO ; EXIT WITH BUFTO ERR
|
|
;
|
|
;
|
|
;
|
|
PPIDE_WAITBSY:
|
|
LD A,(PPIDE_TIMEOUT) ; GET TIMEOUT IN 0.05 SECS
|
|
LD B,A ; PUT IN OUTER LOOP VAR
|
|
PPIDE_WAITBSY1:
|
|
LD DE,(PPIDE_TOSCALER) ; CPU SPPED SCALER TO INNER LOOP VAR
|
|
PPIDE_WAITBSY2:
|
|
;IN A,(PPIDE_REG_STAT) ; READ STATUS
|
|
CALL PPIDE_IN ; 17TS + 170TS
|
|
.DB PPIDE_REG_STAT ; 0TS
|
|
LD C,A ; SAVE IT ; 4TS
|
|
AND %10000000 ; TO FILL (OR READY TO FILL) ; 7TS
|
|
RET Z ; 5TS
|
|
DEC DE ; 6TS
|
|
LD A,D ; 4TS
|
|
OR E ; 4TS
|
|
JR NZ,PPIDE_WAITBSY2 ; 12TS
|
|
DJNZ PPIDE_WAITBSY1 ; -----
|
|
JP PPIDE_BSYTO ; EXIT WITH BSYTO ERR ; 229TS
|
|
;
|
|
;
|
|
;
|
|
PPIDE_IN:
|
|
LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ ; 7TS
|
|
OUT (PPIDE_IO_PPI),A ; DO IT ; 11TS
|
|
EX (SP),HL ; GET PARM POINTER ; 19TS
|
|
PUSH BC ; SAVE INCOMING BC ; 11TS
|
|
LD B,(HL) ; GET CTL PORT VALUE ; 7TS
|
|
LD C,PPIDE_IO_CTL ; SETUP PORT TO WRITE ; 7TS
|
|
OUT (C),B ; SET ADDRESS LINES ; 12TS
|
|
SET 6,B ; TURN ON WRITE BIT ; 8TS
|
|
OUT (C),B ; ASSERT WRITE LINE ; 12TS
|
|
;NOP
|
|
;NOP
|
|
IN A,(PPIDE_IO_DATALO) ; GET DATA VALUE FROM DEVICE ; 11TS
|
|
;NOP
|
|
;NOP
|
|
RES 6,B ; CLEAR WRITE BIT ; 8TS
|
|
OUT (C),B ; DEASSERT WRITE LINE ; 12TS
|
|
POP BC ; RECOVER INCOMING BC ; 10TS
|
|
INC HL ; POINT PAST PARM ; 6TS
|
|
EX (SP),HL ; RESTORE STACK ; 19TS
|
|
RET ; 10TS
|
|
; ; -----
|
|
; ; 170TS
|
|
;
|
|
PPIDE_OUT:
|
|
PUSH AF ; PRESERVE INCOMING VALUE
|
|
LD A,PPIDE_DIR_WRITE ; SET DATA BUS DIRECTION TO WRITE
|
|
OUT (PPIDE_IO_PPI),A ; DO IT
|
|
POP AF ; RECOVER VALUE TO WRITE
|
|
EX (SP),HL ; GET PARM POINTER
|
|
PUSH BC ; SAVE INCOMING BC
|
|
LD B,(HL) ; GET IDE ADDRESS VALUE
|
|
LD C,PPIDE_IO_CTL ; SETUP PORT TO WRITE
|
|
OUT (C),B ; SET ADDRESS LINES
|
|
SET 5,B ; TURN ON WRITE BIT
|
|
OUT (C),B ; ASSERT WRITE LINE
|
|
;NOP
|
|
;NOP
|
|
OUT (PPIDE_IO_DATALO),A ; SEND DATA VALUE TO DEVICE
|
|
;NOP
|
|
;NOP
|
|
RES 5,B ; CLEAR WRITE BIT
|
|
OUT (C),B ; DEASSERT WRITE LINE
|
|
POP BC ; RECOVER INCOMING BC
|
|
INC HL ; POINT PAST PARM
|
|
EX (SP),HL ; RESTORE STACK
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; ERROR HANDLING AND DIAGNOSTICS
|
|
;=============================================================================
|
|
;
|
|
; ERROR HANDLERS
|
|
;
|
|
PPIDE_INVUNIT:
|
|
LD A,PPIDE_STINVUNIT
|
|
JR PPIDE_ERR2 ; SPECIAL CASE FOR INVALID UNIT
|
|
;
|
|
PPIDE_NOMEDIA:
|
|
LD A,PPIDE_STNOMEDIA
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_CMDERR:
|
|
LD A,PPIDE_STCMDERR
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_IOERR:
|
|
LD A,PPIDE_STIOERR
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_RDYTO:
|
|
LD A,PPIDE_STRDYTO
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_DRQTO:
|
|
LD A,PPIDE_STDRQTO
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_BSYTO:
|
|
LD A,PPIDE_STBSYTO
|
|
JR PPIDE_ERR
|
|
;
|
|
PPIDE_ERR:
|
|
LD (IY+PPIDE_STAT),A ; SAVE NEW STATUS
|
|
;
|
|
PPIDE_ERR2:
|
|
#IF (PPIDETRACE >= 2)
|
|
CALL PPIDE_PRTSTAT
|
|
CALL PPIDE_REGDUMP
|
|
#ENDIF
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPIDE_PRTERR:
|
|
RET Z ; DONE IF NO ERRORS
|
|
; FALL THRU TO PPIDE_PRTSTAT
|
|
;
|
|
; PRINT STATUS STRING (STATUS NUM IN A)
|
|
;
|
|
PPIDE_PRTSTAT:
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
OR A
|
|
LD DE,PPIDE_STR_STOK
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STINVUNIT
|
|
JR Z,PPIDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE
|
|
INC A
|
|
LD DE,PPIDE_STR_STNOMEDIA
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STCMDERR
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STIOERR
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STRDYTO
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STDRQTO
|
|
JR Z,PPIDE_PRTSTAT1
|
|
INC A
|
|
LD DE,PPIDE_STR_STBSYTO
|
|
JR Z,PPIDE_PRTSTAT1
|
|
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
|
|
CALL WRITESTR
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT ALL REGISTERS DIRECTLY FROM DEVICE
|
|
; DEVICE MUST BE SELECTED PRIOR TO CALL
|
|
;
|
|
PPIDE_REGDUMP:
|
|
PUSH AF
|
|
PUSH BC
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,PPIDE_DIR_READ ; SET DATA BUS DIRECTION TO READ
|
|
OUT (PPIDE_IO_PPI),A ; DO IT
|
|
LD C,PPIDE_REG_CMD
|
|
LD B,7
|
|
PPIDE_REGDUMP1:
|
|
LD A,C ; REGISTER ADDRESS
|
|
OUT (PPIDE_IO_CTL),A ; SET IT
|
|
XOR PPIDE_CTL_DIOR ; SET BIT TO ASSERT READ LINE
|
|
OUT (PPIDE_IO_CTL),A ; ASSERT READ
|
|
IN A,(PPIDE_IO_DATALO) ; GET VALUE
|
|
CALL PRTHEXBYTE ; DISPLAY IT
|
|
LD A,C ; RELOAD ADDRESS W/ READ UNASSERTED
|
|
OUT (PPIDE_IO_CTL),A ; AND SET IT
|
|
DEC C ; NEXT LOWER REGISTER
|
|
DEC B ; DEC LOOP COUNTER
|
|
CALL NZ,PC_SPACE ; FORMATTING
|
|
JR NZ,PPIDE_REGDUMP1 ; LOOP AS NEEDED
|
|
CALL PC_RBKT ; FORMATTING
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT DIAGNONSTIC PREFIX
|
|
;
|
|
PPIDE_PRTPREFIX:
|
|
PUSH AF
|
|
CALL NEWLINE
|
|
PRTS("PPIDE$")
|
|
LD A,(IY+PPIDE_DEV) ; GET CURRENT DEVICE NUM
|
|
ADD A,'0'
|
|
CALL COUT
|
|
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
|
|
;=============================================================================
|
|
;
|
|
PPIDE_STR_STOK .TEXT "OK$"
|
|
PPIDE_STR_STINVUNIT .TEXT "INVALID UNIT$"
|
|
PPIDE_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
|
PPIDE_STR_STCMDERR .TEXT "COMMAND ERROR$"
|
|
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_STUNK .TEXT "UNKNOWN ERROR$"
|
|
;
|
|
PPIDE_STR_NO .TEXT "NO$"
|
|
;
|
|
;=============================================================================
|
|
; 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_CMD .DB 0 ; PENDING COMMAND TO PROCESS
|
|
PPIDE_IOFNADR .DW 0 ; PENDING IO FUNCTION ADDRESS
|
|
PPIDE_DRVHD .DB 0 ; CURRENT DRIVE/HEAD MASK
|
|
;
|
|
PPIDE_DSKBUF .DW 0 ; ACTIVE DISK BUFFER
|
|
|