mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
Added a new driver category for DSKY (Display/Keypad) devices. Existing DSKY devices were converted into drivers ICM and PKD. These devices were previously DSKY and DSKYNG. This removes substantial code duplication and recovers significant space in romldr and dbgmon.
1406 lines
33 KiB
NASM
1406 lines
33 KiB
NASM
;
|
|
;=============================================================================
|
|
; PPA DISK DRIVER
|
|
;=============================================================================
|
|
;
|
|
; PARALLEL PORT INTERFACE FOR SCSI DISK DEVICES USING A PARALLEL PORT
|
|
; ADAPTER. PRIMARILY TARGETS PARALLEL PORT IOMEGA ZIP DRIVES.
|
|
;
|
|
; INTENDED TO CO-EXIST WITH LPT DRIVER.
|
|
;
|
|
; CREATED BY WAYNE WARTHEN FOR ROMWBW HBIOS.
|
|
; MUCH OF THE CODE IS DERIVED FROM LINUX AND FUZIX (ALAN COX).
|
|
; - https://github.com/EtchedPixels/FUZIX
|
|
; - https://github.com/torvalds/linux
|
|
;
|
|
; 05/23/2023 WBW - INITIAL RELEASE
|
|
; 05/26/3023 WBW - CLEAN UP, LED ACTIVITY
|
|
; 05/27/2023 WBW - ADDED SPP MODE
|
|
; 06/06/2023 WBW - OPTIMIZE BLOCK READ AND WRITE
|
|
;
|
|
;=============================================================================
|
|
;
|
|
; IBM PC STANDARD PARALLEL PORT (SPP):
|
|
; - NHYODYNE PRINT MODULE
|
|
;
|
|
; PORT 0 (OUTPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; PORT 1 (INPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | /BUSY | /ACK | POUT | SEL | /ERR | 0 | 0 | 0 |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; PORT 2 (OUTPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | STAT1 | STAT0 | ENBL | PINT | SEL | RES | LF | STB |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
;=============================================================================
|
|
;
|
|
; MG014 STYLE INTERFACE:
|
|
; - RCBUS MG014 MODULE
|
|
;
|
|
; PORT 0 (OUTPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; PORT 1 (INPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | | | | /ERR | SEL | POUT | BUSY | /ACK |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; PORT 2 (OUTPUT):
|
|
;
|
|
; D7 D6 D5 D4 D3 D2 D1 D0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | LED | | | | /SEL | /RES | /LF | /STB |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
;=============================================================================
|
|
;
|
|
; TODO:
|
|
;
|
|
; NOTES:
|
|
;
|
|
; - THIS DRIVER IS FOR THE ZIP DRIVE PPA INTERFACE. IT WILL SIMPLY
|
|
; FAIL TO EVEN RECOGNIZE A ZIP DRIVE WITH THE NEWER IMM INTERFACE.
|
|
; THERE DOES NOT SEEM TO BE A WAY TO VISUALLY DETERMINE IF A ZIP
|
|
; DRIVE IS PPA OR IMM. SIGH.
|
|
;
|
|
; - THIS DRIVER OPERATES USES NIBBLE READ MODE. ALTHOUGH THE 8255
|
|
; (MG014) CAN READ OR WRITE TO PORT A (DATA), IT "GLITCHES" WHEN
|
|
; THE MODE IS CHANGED CAUSING THE CONTROL LINES TO CHANGE AND
|
|
; BREAKS THE PROTOCOL. I SUSPECT THE MBC SPP CAN SUPPORT FULL BYTE
|
|
; MODE, (PS2 STYLE), BUT I HAVE NOT ATTEMPTED IT.
|
|
;
|
|
; - RELATIVE TO ABOVE, THIS BEAST IS SLOW. IN ADDITION TO THE
|
|
; NIBBLE MODE READS, THE MG014 ASSIGNS SIGNALS DIFFERENTLY THAN
|
|
; THE STANDARD IBM PARALLEL PORT WHICH NECESSITATES A BUNCH OF EXTRA
|
|
; BIT FIDDLING ON EVERY READ.
|
|
;
|
|
; - SOME OF THE DATA TRANSFERS HAVE NO BUFFER OVERRUN CHECKS. IT IS
|
|
; ASSUMED SCSI DEVICES WILL SEND/REQUEST THE EXPECTED NUMBER OF BYTES.
|
|
;
|
|
; PPA PORT OFFSETS
|
|
;
|
|
PPA_IODATA .EQU 0 ; PORT A, DATA, OUT
|
|
PPA_IOSTAT .EQU 1 ; PORT B, STATUS, IN
|
|
PPA_IOCTRL .EQU 2 ; PORT C, CTRL, OUT
|
|
PPA_IOSETUP .EQU 3 ; PPI SETUP
|
|
;
|
|
; SCSI UNIT IDS
|
|
;
|
|
PPA_SELF .EQU 7
|
|
PPA_TGT .EQU 6
|
|
;
|
|
; PPA DEVICE STATUS
|
|
;
|
|
PPA_STOK .EQU 0
|
|
PPA_STNOMEDIA .EQU -1
|
|
PPA_STCMDERR .EQU -2
|
|
PPA_STIOERR .EQU -3
|
|
PPA_STTO .EQU -4
|
|
PPA_STNOTSUP .EQU -5
|
|
;
|
|
; PPA DEVICE CONFIGURATION
|
|
;
|
|
PPA_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
; PER DEVICE DATA OFFSETS IN CONFIG TABLE ENTRIES
|
|
;
|
|
PPA_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
|
|
PPA_MODE .EQU 1 ; OPERATION MODE: PPA MODE (BYTE)
|
|
PPA_STAT .EQU 2 ; LAST STATUS (BYTE)
|
|
PPA_IOBASE .EQU 3 ; IO BASE ADDRESS (BYTE)
|
|
PPA_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD)
|
|
PPA_LBA .EQU 8 ; OFFSET OF LBA (DWORD)
|
|
;
|
|
; MACROS
|
|
;
|
|
#DEFINE PPA_WCTL(VAL) LD A,VAL \ CALL PPA_WRITECTRL
|
|
#DEFINE PPA_WDATA(VAL) LD A,VAL \ CALL PPA_WRITEDATA
|
|
;
|
|
#DEFINE PPA_DPUL(VAL) LD A,VAL \ CALL PPA_DPULSE
|
|
#DEFINE PPA_CPUL(VAL) LD A,VAL \ CALL PPA_CPULSE
|
|
;
|
|
; INCLUDE MG014 NIBBLE MAP FOR MG014 MODE
|
|
;
|
|
#IF (IMMMODE == IMMMODE_MG014)
|
|
#DEFINE MG014_MAP
|
|
#ENDIF
|
|
;
|
|
;=============================================================================
|
|
; INITIALIZATION ENTRY POINT
|
|
;=============================================================================
|
|
;
|
|
PPA_INIT:
|
|
LD IY,PPA_CFG ; POINT TO START OF CONFIG TABLE
|
|
;
|
|
PPA_INIT1:
|
|
LD A,(IY) ; LOAD FIRST BYTE TO CHECK FOR END
|
|
CP $FF ; CHECK FOR END OF TABLE VALUE
|
|
JR NZ,PPA_INIT2 ; IF NOT END OF TABLE, CONTINUE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
PPA_INIT2:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("PPA:$") ; DRIVER LABEL
|
|
;
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,(IY+PPA_IOBASE) ; GET IO BASE ADDRES
|
|
CALL PRTHEXBYTE ; DISPLAY IT
|
|
;
|
|
PRTS(" MODE=$") ; LABEL FOR MODE
|
|
LD A,(IY+PPA_MODE) ; GET MODE BITS
|
|
|
|
LD HL,PPA_STR_MODE_MAP
|
|
ADD A,A
|
|
CALL ADDHLA
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
CALL WRITESTR
|
|
;
|
|
; CHECK FOR HARDWARE PRESENCE
|
|
CALL PPA_DETECT ; PROBE FOR INTERFACE
|
|
JR Z,PPA_INIT4 ; IF FOUND, CONTINUE
|
|
CALL PC_SPACE ; FORMATTING
|
|
LD DE,PPA_STR_NOHW ; NO PPA MESSAGE
|
|
CALL WRITESTR ; DISPLAY IT
|
|
JR PPA_INIT6 ; SKIP CFG ENTRY
|
|
;
|
|
PPA_INIT4:
|
|
; UPDATE DRIVER RELATIVE UNIT NUMBER IN CONFIG TABLE
|
|
LD A,(PPA_DEVNUM) ; GET NEXT UNIT NUM TO ASSIGN
|
|
LD (IY+PPA_DEV),A ; UPDATE IT
|
|
INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN
|
|
LD (PPA_DEVNUM),A ; SAVE IT
|
|
;
|
|
; ADD UNIT TO GLOBAL DISK UNIT TABLE
|
|
LD BC,PPA_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
|
|
;
|
|
CALL PPA_RESET ; RESET/INIT THE INTERFACE
|
|
#IF (PPATRACE <= 1)
|
|
CALL NZ,PPA_PRTSTAT
|
|
#ENDIF
|
|
JR NZ,PPA_INIT6
|
|
;
|
|
; START PRINTING DEVICE INFO
|
|
CALL PPA_PRTPREFIX ; PRINT DEVICE PREFIX
|
|
;
|
|
PPA_INIT5:
|
|
; PRINT STORAGE CAPACITY (BLOCK COUNT)
|
|
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
|
LD A,PPA_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 PRTDEC32 ; PRINT DWORD IN DECIMAL
|
|
PRTS("MB$") ; PRINT SUFFIX
|
|
;
|
|
PPA_INIT6:
|
|
LD DE,PPA_CFGSIZ ; SIZE OF CFG TABLE ENTRY
|
|
ADD IY,DE ; BUMP POINTER
|
|
JP PPA_INIT1 ; AND LOOP
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; PROBE FOR PPA HARDWARE
|
|
;----------------------------------------------------------------------
|
|
;
|
|
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
|
|
;
|
|
PPA_DETECT:
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nDETECT:$")
|
|
#ENDIF
|
|
;
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
; INITIALIZE 8255
|
|
LD A,(IY+PPA_IOBASE) ; BASE PORT
|
|
ADD A,PPA_IOSETUP ; BUMP TO SETUP PORT
|
|
LD C,A ; MOVE TO C FOR I/O
|
|
LD A,$82 ; CONFIG A OUT, B IN, C OUT
|
|
OUT (C),A ; DO IT
|
|
CALL DELAY ; BRIEF DELAY FOR GOOD MEASURE
|
|
#ENDIF
|
|
;
|
|
PPA_WDATA($AA)
|
|
CALL PPA_DISCONNECT
|
|
CALL PPA_CONNECT
|
|
PPA_WCTL($0E)
|
|
CALL PPA_READSTATUS
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
AND $08
|
|
CP $08
|
|
JR NZ,PPA_DETECT_FAIL
|
|
;
|
|
PPA_WCTL($0C)
|
|
CALL PPA_READSTATUS
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
AND $08
|
|
CP $00
|
|
JR NZ,PPA_DETECT_FAIL
|
|
;
|
|
CALL PPA_DISCONNECT
|
|
;
|
|
PPA_WDATA($AA)
|
|
PPA_WCTL($0C)
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
PPA_DETECT_FAIL:
|
|
OR $FF ; SIGNAL FAILURE
|
|
RET NZ
|
|
;
|
|
;=============================================================================
|
|
; DRIVER FUNCTION TABLE
|
|
;=============================================================================
|
|
;
|
|
PPA_FNTBL:
|
|
.DW PPA_STATUS
|
|
.DW PPA_RESET
|
|
.DW PPA_SEEK
|
|
.DW PPA_READ
|
|
.DW PPA_WRITE
|
|
.DW PPA_VERIFY
|
|
.DW PPA_FORMAT
|
|
.DW PPA_DEVICE
|
|
.DW PPA_MEDIA
|
|
.DW PPA_DEFMED
|
|
.DW PPA_CAP
|
|
.DW PPA_GEOM
|
|
#IF (($ - PPA_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID PPA FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
PPA_VERIFY:
|
|
PPA_FORMAT:
|
|
PPA_DEFMED:
|
|
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_READ:
|
|
CALL HB_DSKREAD ; HOOK DISK READ CONTROLLER
|
|
LD A,SCSI_CMD_READ ; SETUP SCSI READ
|
|
LD (PPA_CMD_RW),A ; AND SAVE IT IN SCSI CMD
|
|
JP PPA_IO ; DO THE I/O
|
|
;
|
|
;
|
|
;
|
|
PPA_WRITE:
|
|
CALL HB_DSKWRITE ; HOOK DISK WRITE CONTROLLER
|
|
LD A,SCSI_CMD_WRITE ; SETUP SCSI WRITE
|
|
LD (PPA_CMD_RW),A ; AND SAVE IT IN SCSI CMD
|
|
JP PPA_IO ; DO THE I/O
|
|
;
|
|
;
|
|
;
|
|
PPA_IO:
|
|
PUSH HL
|
|
CALL PPA_CHKERR ; CHECK FOR ERR STATUS AND RESET IF SO
|
|
POP HL
|
|
JR NZ,PPA_IO3 ; BAIL OUT ON ERROR
|
|
;
|
|
LD (PPA_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
;
|
|
#IF (DSKYENABLE)
|
|
#IF (DSKYDSKACT)
|
|
LD A,PPA_LBA
|
|
CALL LDHLIYA
|
|
CALL HB_DSKACT ; SHOW ACTIVITY
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
; SETUP LBA
|
|
; 3 BYTES, LITTLE ENDIAN -> BIG ENDIAN
|
|
LD HL,PPA_CMD_RW+1 ; START OF LBA FIELD IN CDB (MSB)
|
|
LD A,(IY+PPA_LBA+2) ; THIRD BYTE OF LBA FIELD IN CFG (MSB)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IY+PPA_LBA+1)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IY+PPA_LBA+0)
|
|
LD (HL),A
|
|
INC HL
|
|
;
|
|
; DO SCSI IO
|
|
LD DE,(PPA_DSKBUF) ; DISK BUFFER TO DE
|
|
LD A,1 ; BLOCK I/O, ONE SECTOR
|
|
LD HL,PPA_CMD_RW ; POINT TO READ/WRITE CMD TEMPLATE
|
|
CALL PPA_RUNCMD ; RUN THE SCSI ENGINE
|
|
CALL Z,PPA_CHKCMD ; IF EXIT OK, CHECK SCSI RESULTS
|
|
JR NZ,PPA_IO2 ; IF ERROR, SKIP INCREMENT
|
|
; INCREMENT LBA
|
|
LD A,PPA_LBA ; LBA OFFSET
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL INC32HL ; INCREMENT THE VALUE
|
|
; INCREMENT DMA
|
|
LD HL,PPA_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
XOR A ; SIGNAL SUCCESS
|
|
;
|
|
PPA_IO2:
|
|
PPA_IO3:
|
|
LD HL,(PPA_DSKBUF) ; CURRENT DMA TO HL
|
|
OR A ; SET FLAGS BASED ON RETURN CODE
|
|
RET Z ; RETURN IF SUCCESS
|
|
LD A,ERR_IO ; SIGNAL IO ERROR
|
|
OR A ; SET FLAGS
|
|
RET ; AND DONE
|
|
;
|
|
;
|
|
;
|
|
PPA_STATUS:
|
|
; RETURN UNIT STATUS
|
|
LD A,(IY+PPA_STAT) ; GET STATUS OF SELECTED DEVICE
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPA_RESET:
|
|
JP PPA_INITDEV ; JUST (RE)INIT DEVICE
|
|
;
|
|
;
|
|
;
|
|
PPA_DEVICE:
|
|
LD D,DIODEV_PPA ; D := DEVICE TYPE
|
|
LD E,(IY+PPA_DEV) ; E := PHYSICAL DEVICE NUMBER
|
|
LD C,%01111001 ; C := REMOVABLE HARD DISK
|
|
LD H,(IY+PPA_MODE) ; H := MODE
|
|
LD L,(IY+PPA_IOBASE) ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; PPA_GETMED
|
|
;
|
|
PPA_MEDIA:
|
|
LD A,E ; GET FLAGS
|
|
OR A ; SET FLAGS
|
|
JR Z,PPA_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA
|
|
;
|
|
CALL PPA_RESET ; RESET INCLUDES MEDIA CHECK
|
|
;
|
|
PPA_MEDIA1:
|
|
LD A,(IY+PPA_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
|
|
LD A,ERR_NOMEDIA ; NO MEDIA ERROR
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPA_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+PPA_LBA+0),L ; SAVE NEW LBA
|
|
LD (IY+PPA_LBA+1),H ; ...
|
|
LD (IY+PPA_LBA+2),E ; ...
|
|
LD (IY+PPA_LBA+3),D ; ...
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
PPA_CAP:
|
|
LD A,(IY+PPA_STAT) ; GET STATUS
|
|
PUSH AF ; SAVE IT
|
|
LD A,PPA_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
|
|
;
|
|
;
|
|
;
|
|
PPA_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 PPA_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC
|
|
LD L,H ; DIVIDE 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 PPA_CAP STATUS
|
|
;
|
|
;=============================================================================
|
|
; FUNCTION SUPPORT ROUTINES
|
|
;=============================================================================
|
|
;
|
|
; OUTPUT BYTE IN A TO THE DATA PORT
|
|
;
|
|
PPA_WRITEDATA:
|
|
LD C,(IY+PPA_IOBASE) ; DATA PORT IS AT IOBASE
|
|
OUT (C),A ; WRITE THE BYTE
|
|
;CALL DELAY ; IS THIS NEEDED???
|
|
RET ; DONE
|
|
;
|
|
;
|
|
;
|
|
PPA_WRITECTRL:
|
|
; IBM PC INVERTS ALL BUT C2 ON THE BUS, MG014 DOES NOT.
|
|
; BELOW TRANSLATES FROM IBM -> MG014. IT ALSO INVERTS THE
|
|
; MG014 LED SIMPLY TO MAKE IT EASY TO KEEP LED ON DURING
|
|
; ALL ACTIVITY.
|
|
#IF (PPAMODE == PPAMODE_MG014
|
|
XOR $0B | $80 ; HIGH BIT IS MG014 LED
|
|
#ENDIF
|
|
LD C,(IY+PPA_IOBASE) ; GET BASE IO ADDRESS
|
|
INC C ; BUMP TO CONTROL PORT
|
|
INC C
|
|
OUT (C),A ; WRITE TO CONTROL PORT
|
|
;CALL DELAY ; IS THIS NEEDED?
|
|
RET ; DONE
|
|
;
|
|
; READ THE PARALLEL PORT INPUT LINES (STATUS) AND MAP SIGNALS FROM
|
|
; MG014 TO IBM STANDARD. NOTE POLARITY CHANGE REQUIRED FOR BUSY.
|
|
;
|
|
; MG014 IBM PC
|
|
; -------- --------
|
|
; 0: /ACK 6: /ACK
|
|
; 1: BUSY 7: /BUSY
|
|
; 2: POUT 5: POUT
|
|
; 3: SEL 4: SEL
|
|
; 4: /ERR 3: /ERR
|
|
;
|
|
PPA_READSTATUS:
|
|
LD C,(IY+PPA_IOBASE) ; IOBASE TO C
|
|
INC C ; BUMP TO STATUS PORT
|
|
IN A,(C) ; READ IT
|
|
;
|
|
#IF (PPAMODE == PPAMODE_MG014
|
|
;
|
|
; SHUFFLE BITS ON MG014
|
|
LD C,0 ; INIT RESULT
|
|
BIT 0,A ; 0: /ACK
|
|
JR Z,PPA_READSTATUS1
|
|
SET 6,C ; 6: /ACK
|
|
PPA_READSTATUS1:
|
|
BIT 1,A ; 1: BUSY
|
|
JR NZ,PPA_READSTATUS2 ; POLARITY CHANGE!
|
|
SET 7,C ; 7: /BUSY
|
|
PPA_READSTATUS2:
|
|
BIT 2,A ; 2: POUT
|
|
JR Z,PPA_READSTATUS3
|
|
SET 5,C ; 5: POUT
|
|
PPA_READSTATUS3:
|
|
BIT 3,A ; 3: SEL
|
|
JR Z,PPA_READSTATUS4
|
|
SET 4,C ; 4: SEL
|
|
PPA_READSTATUS4:
|
|
BIT 4,A ; 4: /ERR
|
|
JR Z,PPA_READSTATUS5
|
|
SET 3,C ; 3: /ERR
|
|
PPA_READSTATUS5:
|
|
LD A,C ; RESULT TO A
|
|
;
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_DPULSE:
|
|
CALL PPA_WRITEDATA
|
|
PPA_WCTL($0C)
|
|
PPA_WCTL($0E)
|
|
PPA_WCTL($0C)
|
|
PPA_WCTL($04)
|
|
PPA_WCTL($0C)
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_CPULSE:
|
|
CALL PPA_WRITEDATA
|
|
PPA_WCTL($04)
|
|
PPA_WCTL($06)
|
|
PPA_WCTL($04)
|
|
PPA_WCTL($0C)
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_CONNECT:
|
|
PPA_CPUL($00)
|
|
PPA_CPUL($3C)
|
|
PPA_CPUL($20)
|
|
PPA_CPUL($8F)
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_DISCONNECT:
|
|
PPA_DPUL($00)
|
|
PPA_DPUL($3C)
|
|
PPA_DPUL($20)
|
|
PPA_DPUL($0F)
|
|
;
|
|
; TURNS OFF MG014 LED
|
|
PPA_WCTL($8C)
|
|
;
|
|
RET
|
|
;
|
|
; INITIATE A SCSI BUS RESET.
|
|
;
|
|
PPA_RESETPULSE:
|
|
PPA_WDATA($40)
|
|
PPA_WCTL($08)
|
|
CALL DELAY ; 32 US, IDEALLY 30 US
|
|
PPA_WCTL($0C)
|
|
RET
|
|
;
|
|
; SCSI SELECT PROCESS
|
|
;
|
|
PPA_SELECT:
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nSELECT: $")
|
|
#ENDIF
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PPA_READSTATUS
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
LD A,1 << PPA_TGT
|
|
CALL PPA_WRITEDATA
|
|
PPA_WCTL($0E)
|
|
PPA_WCTL($0C)
|
|
LD A,1 << PPA_SELF
|
|
CALL PPA_WRITEDATA
|
|
PPA_WCTL($08)
|
|
;
|
|
LD B,0 ; TIMEOUT COUNTER
|
|
PPA_SELECT1:
|
|
CALL PPA_READSTATUS
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
AND $40
|
|
CP $40
|
|
RET Z
|
|
DJNZ PPA_SELECT1
|
|
JP PPA_CMD_TIMEOUT
|
|
;
|
|
; SEND SCSI CMD BYTE STRING. AT ENTRY, HL POINTS TO START OF
|
|
; COMMAND BYTES. THE LENGTH OF THE COMMAND STRING MUST PRECEED
|
|
; THE COMMAND BYTES (HL - 1).
|
|
;
|
|
; NOTE THAT DATA IS SENT AS BYTE PAIRS! EACH LOOP SENDS 2 BYTES.
|
|
; DATA OUTPOUT IS BURSTED (NO CHECK FOR BUSY). SEEMS TO WORK FINE.
|
|
;
|
|
PPA_SENDCMD:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nSENDCMD:$")
|
|
#ENDIF
|
|
;
|
|
DEC HL ; BACKUP TO LENGTH BYTE
|
|
LD B,(HL) ; PUT IN B FOR LOOP COUNTER
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
LD A,B
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
INC HL ; BACK TO FIRST CMD BYTE
|
|
;
|
|
PPA_SENDCMD1:
|
|
;PPA_WCTL($0C)
|
|
LD A,(HL) ; LOAD CMD BYTE
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CALL PPA_WRITEDATA ; PUT IT ON THE BUS
|
|
INC HL ; BUMP TO NEXT BYTE
|
|
PPA_WCTL($0E)
|
|
PPA_WCTL($0C)
|
|
DJNZ PPA_SENDCMD1 ; LOOP TILL DONE
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
; WAIT FOR SCSI BUS TO BECOME READY WITH A TIMEOUT.
|
|
;
|
|
PPA_WAITLOOP:
|
|
CALL PPA_READSTATUS
|
|
BIT 7,A
|
|
RET NZ ; DONE, STATUS IN A
|
|
DEC HL
|
|
LD A,H
|
|
OR L
|
|
RET Z ; TIMEOUT
|
|
JR PPA_WAITLOOP
|
|
;
|
|
PPA_WAIT:
|
|
LD HL,500 ; GOOD VALUE???
|
|
PPA_WCTL($0C)
|
|
CALL PPA_WAITLOOP
|
|
JP Z,PPA_CMD_TIMEOUT ; HANDLE TIMEOUT
|
|
;PUSH AF
|
|
;IMM_WCTL($04)
|
|
;POP AF
|
|
AND $F0
|
|
RET ; RETURN W/ RESULT IN A
|
|
;
|
|
; MAX OBSERVED WAITLOOP ITERATIONS IS $0116B3 @ 7.372 MHZ ON MG014
|
|
; MAX OBSERVED WAITLOOP ITERATIONS IS $028EFE @ 8.000 MHZ ON MBC SPP
|
|
;
|
|
PPA_LONGWAIT:
|
|
LD A,(CB_CPUMHZ) ; LOAD CPU SPEED IN MHZ
|
|
SRL A ; DIVIDE BY 2, GOOD ENOUGH
|
|
LD B,A ; USE FOR OUTER LOOP COUNT
|
|
PPA_WCTL($0C)
|
|
PPA_LONGWAIT1:
|
|
LD HL,0
|
|
CALL PPA_WAITLOOP
|
|
JR NZ,PPA_LONGWAIT2 ; HANDLE SUCCESS
|
|
DJNZ PPA_LONGWAIT1 ; LOOP TILL COUNTER EXHAUSTED
|
|
JP PPA_CMD_TIMEOUT ; HANDLE TIMEOUT
|
|
;
|
|
PPA_LONGWAIT2:
|
|
;PUSH AF
|
|
;PPA_WCTL($04)
|
|
;
|
|
#IF 0
|
|
PUSH AF
|
|
CALL PC_GT
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
CALL PRTHEXWORDHL
|
|
POP AF
|
|
#ENDIF
|
|
;
|
|
;POP AF
|
|
AND $F0
|
|
RET ; RETURN W/ RESULT IN A
|
|
;
|
|
; GET A BYTE OF DATA FROM THE SCSI DEVICE. THIS IS A NIBBLE READ.
|
|
; BYTE RETURNED IN A.
|
|
;
|
|
PPA_GETBYTE:
|
|
CALL PPA_WAIT
|
|
PPA_WCTL($04)
|
|
CALL PPA_READSTATUS
|
|
AND $F0
|
|
PUSH AF
|
|
PPA_WCTL($06)
|
|
CALL PPA_READSTATUS
|
|
AND $F0
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
POP HL
|
|
OR H
|
|
PUSH AF
|
|
PPA_WCTL($0C)
|
|
POP AF
|
|
RET
|
|
;
|
|
; GET A CHUNK OF DATA FROM SCSI BUS. THIS IS SPECIFICALLY FOR
|
|
; READ PHASE. IF TRANSFER MODE IS NON-ZERO, THEN A BLOCK (512 BYTES)
|
|
; OF DATA WILL BE READ. OTHERWISE, DATA IS WRITTEN AS
|
|
; LONG AS SCSI DEVICE WANTS TO CONTINUE RECEIVING (NO OVERRUN
|
|
; CHECK IN THIS CASE).
|
|
;
|
|
; THIS IS A NIBBLE READ.
|
|
;
|
|
; DE=BUFFER
|
|
; A=TRANSFER MODE (0=VARIABLE, 1=BLOCK)
|
|
;
|
|
PPA_GETDATA:
|
|
; BRANCH TO CORRECT ROUTINE
|
|
OR A
|
|
JR NZ,PPA_GETBLOCK ; DO BLOCK READ
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nGETDATA:$")
|
|
#ENDIF
|
|
;
|
|
PPA_GETDATA1:
|
|
PUSH HL ; SAVE BYTE COUNTER
|
|
CALL PPA_WAIT ; WAIT FOR BUS READY
|
|
POP HL ; RESTORE BYTE COUNTER
|
|
CP $D0 ; CHECK FOR READ PHASE
|
|
JR NZ,PPA_GETDATA2 ; IF NOT, ASSUME WE ARE DONE
|
|
PPA_WCTL($04)
|
|
CALL PPA_READSTATUS ; GET FIRST NIBBLE
|
|
AND $F0 ; ISOLATE BITS
|
|
PUSH AF ; SAVE WORKING VALUE
|
|
PPA_WCTL($06)
|
|
CALL PPA_READSTATUS ; GET SECOND NIBBLE
|
|
AND $F0 ; ISOLATE BITS
|
|
RRCA ; AND SHIFT TO LOW NIBBLE
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
POP BC ; RECOVER LOW NIBBLE
|
|
OR B ; COMBINE
|
|
LD (DE),A ; AND SAVE THE FULL BYTE VALUE
|
|
INC DE ; NEXT BUFFER POS
|
|
INC HL ; INCREMENT BYTES COUNTER
|
|
JR PPA_GETDATA1 ; LOOP TILL DONE
|
|
;
|
|
PPA_GETDATA2:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
PPA_WCTL($0C)
|
|
RET
|
|
;
|
|
PPA_GETBLOCK:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nGETBLK:$")
|
|
#ENDIF
|
|
LD B,0 ; LOOP COUNTER
|
|
EXX ; SWITCH TO ALT
|
|
EX AF,AF' ; SWITCH TO ALT AF
|
|
; SAVE ALT REGS
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
; C: PORT C
|
|
LD A,(IY+PPA_IOBASE) ; BASE PORT
|
|
INC A ; STATUS PORT
|
|
LD (PPA_GETBLOCK_A),A ; FILL IN
|
|
LD (PPA_GETBLOCK_B),A ; ... DYNAMIC BITS OF CODE
|
|
INC A ; CONTROL PORT
|
|
LD C,A ; ... TO C
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
; DE: CLOCK VALUES
|
|
LD D,$04 ^ ($0B | $80)
|
|
LD E,$06 ^ ($0B | $80)
|
|
; HL: STATMAP
|
|
LD H,MG014_STATMAPLO >> 8
|
|
#ENDIF
|
|
#IF (PPAMODE == PPAMODE_SPP)
|
|
; DE: CLOCK VALUES
|
|
LD D,$04
|
|
LD E,$06
|
|
#ENDIF
|
|
EXX ; SWITCH TO PRI
|
|
CALL PPA_GETBLOCK1 ; LOOP TWICE
|
|
CALL PPA_GETBLOCK1 ; ... FOR 512 BYTES
|
|
; RESTORE ALT REGS
|
|
EXX ; SWITCH TO ALT REGS
|
|
EX AF,AF' ; SWITCH TO ALT AF
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
EXX ; SWITCH TO PRI REGS
|
|
EX AF,AF' ; SWITCH TO PRI AF
|
|
RET
|
|
;
|
|
;
|
|
PPA_GETBLOCK1:
|
|
EXX ; ALT REGS
|
|
OUT (C),D ; SEND FIRST CLOCK
|
|
PPA_GETBLOCK_A .EQU $+1
|
|
IN A,($FF) ; GET HIGH NIBBLE
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
AND $0F ; RELEVANT BITS ONLY
|
|
ADD A,MG014_STATMAPHI & $FF ; HIGH BYTE OF MAP PTR
|
|
LD L,A ; PUT IN L
|
|
LD A,(HL) ; LOOKUP HIGH NIBBLE VALUE
|
|
EX AF,AF' ; SAVE NIBBLE
|
|
#ENDIF
|
|
#IF (PPAMODE == PPAMODE_SPP)
|
|
AND $F0 ; RELEVANT BITS ONLY
|
|
LD L,A ; SAVE NIBBLE IN L
|
|
#ENDIF
|
|
OUT (C),E ; SEND SECOND CLOCK
|
|
PPA_GETBLOCK_B .EQU $+1
|
|
IN A,($FF) ; GET LOW NIBBLE
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
AND $0F ; RELEVANT BITS ONLY
|
|
ADD A,MG014_STATMAPLO & $FF ; LOW BYTE OF MAP PTR
|
|
LD L,A ; PUT IN L
|
|
EX AF,AF' ; RECOVER HIGH NIBBLE VALUE
|
|
OR (HL) ; COMBINE WITH LOW NIB VALUE
|
|
#ENDIF
|
|
#IF (PPAMODE == PPAMODE_SPP)
|
|
AND $F0 ; RELEVANT BITS ONLY
|
|
RLCA ; MOVE TO LOW NIBBLE
|
|
RLCA ; MOVE TO LOW NIBBLE
|
|
RLCA ; MOVE TO LOW NIBBLE
|
|
RLCA ; MOVE TO LOW NIBBLE
|
|
OR L ; COMBINE WITH HIGH NIB VALUE
|
|
#ENDIF
|
|
EXX ; SWITCH TO PRI
|
|
LD (DE),A ; SAVE BYTE
|
|
INC DE ; BUMP BUF PTR
|
|
DJNZ PPA_GETBLOCK1 ; LOOP
|
|
RET ; DONE
|
|
;
|
|
; PUT A CHUNK OF DATA TO THE SCSI BUS. THIS IS SPECIFICALLY FOR
|
|
; WRITE PHASE. IF TRANSFER MODE IS NON-ZERO, THEN A BLOCK (512 BYTES)
|
|
; OF DATA WILL BE WRITTEN. OTHERWISE, DATA IS WRITTEN AS
|
|
; LONG AS SCSI DEVICE WANTS TO CONTINUE RECEIVING (NO OVERRUN
|
|
; CHECK IN THIS CASE).
|
|
;
|
|
; DE=BUFFER
|
|
; A=TRANSFER MODE (0=VARIABLE, 1=BLOCK)
|
|
;
|
|
PPA_PUTDATA:
|
|
; BRANCH TO CORRECT ROUTINE
|
|
OR A
|
|
JR NZ,PPA_PUTBLOCK ; DO BLOCK WRITE
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nPUTDATA:$")
|
|
#ENDIF
|
|
;
|
|
PPA_PUTDATA1:
|
|
PUSH HL ; SAVE BYTE COUNTER
|
|
CALL PPA_WAIT ; WAIT FOR BUS READY
|
|
POP HL ; RESTORE BYTE COUNTER
|
|
CP $C0 ; CHECK FOR WRITE PHASE
|
|
JR NZ,PPA_PUTDATA2 ; IF NOT, ASSUME WE ARE DONE
|
|
LD A,(DE) ; GET NEXT BYTE TO WRITE (FIRST OF PAIR)
|
|
CALL PPA_WRITEDATA ; PUT ON BUS
|
|
INC DE ; BUMP TO NEXT BUF POS
|
|
INC HL ; INCREMENT COUNTER
|
|
PPA_WCTL($0E)
|
|
PPA_WCTL($0C)
|
|
LD A,(DE) ; GET NEXT BYTE TO WRITE (SECOND OF PAIR)
|
|
JR PPA_PUTDATA1 ; LOOP TILL DONE
|
|
;
|
|
PPA_PUTDATA2:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
PPA_PUTBLOCK:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nPUTBLK:$")
|
|
#ENDIF
|
|
;
|
|
LD B,0 ; LOOP COUNTER
|
|
LD A,(IY+PPA_IOBASE) ; GET BASE IO ADR
|
|
LD (PPA_PUTBLOCK_A),A ; FILL IN
|
|
INC A ; STATUS PORT
|
|
INC A ; CONTROL PORT
|
|
LD C,A ; ... TO C
|
|
; HL: CLOCK VALUES
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
LD H,$0E ^ ($0B | $80)
|
|
LD L,$0C ^ ($0B | $80)
|
|
#ENDIF
|
|
#IF (PPAMODE == PPAMODE_SPP)
|
|
LD H,$0E
|
|
LD L,$0C
|
|
#ENDIF
|
|
CALL PPA_PUTBLOCK1 ; DO BELOW TWICE
|
|
CALL PPA_PUTBLOCK1 ; ... FOR 512 BYTES
|
|
RET
|
|
;
|
|
PPA_PUTBLOCK1:
|
|
LD A,(DE) ; GET NEXT BYTE
|
|
PPA_PUTBLOCK_A .EQU $+1
|
|
OUT ($FF),A ; PUT ON BUS
|
|
INC DE ; INCREMENT BUF POS
|
|
OUT (C),H ; FIRST CLOCK
|
|
OUT (C),L ; SECOND CLOCK
|
|
DJNZ PPA_PUTBLOCK1 ; LOOP
|
|
RET ; DONE
|
|
;
|
|
; READ SCSI COMMAND STATUS
|
|
;
|
|
PPA_GETSTATUS:
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nSTATUS:$")
|
|
#ENDIF
|
|
;
|
|
CALL PPA_GETBYTE ; GET ONE BYTE
|
|
LD (PPA_CMDSTAT),A ; SAVE AS FIRST STATUS BYTE
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CALL PPA_WAIT ; CHECK FOR OPTIONAL SECOND BYTE
|
|
CP $F0 ; STILL IN STATUS PHASE?
|
|
RET NZ ; IF NOT, DONE
|
|
CALL PPA_GETBYTE ; ELSE, GET THE SECOND BYTE
|
|
LD (PPA_CMDSTAT+1),A ; AND SAVE IT
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
; THIS IS THE MAIN SCSI ENGINE. BASICALLY, IT SELECTS THE DEVICE
|
|
; ON THE BUS, SENDS THE COMMAND, THEN PROCESSES THE RESULT.
|
|
;
|
|
; HL: COMMAND BUFFER
|
|
; DE: TRANSFER BUFFER
|
|
; A: TRANSFER MODE (0=VARIABLE, 1=BLOCK)
|
|
;
|
|
PPA_RUNCMD:
|
|
; THERE ARE MANY PLACES NESTED WITHIN THE ROUTINES THAT
|
|
; ARE CALLED HERE. HERE WE SAVE THE STACK SO THAT WE CAN
|
|
; EASILY AND QUICKLY ABORT OUT OF ANY NESTED ROUTINE.
|
|
; SEE PPA_CMD_ERR BELOW.
|
|
LD (PPA_CMDSTK),SP ; FOR ERROR ABORTS
|
|
LD (PPA_DSKBUF),DE ; SAVE BUF PTR
|
|
LD (PPA_XFRMODE),A ; SAVE XFER LEN
|
|
PUSH HL
|
|
CALL PPA_CONNECT ; PARALLEL PORT BUS CONNECT
|
|
CALL PPA_SELECT ; SELECT TARGET DEVICE
|
|
CALL PPA_WAIT ; WAIT TILL READY
|
|
POP HL
|
|
CALL PPA_SENDCMD ; SEND THE COMMAND
|
|
;
|
|
PPA_RUNCMD_PHASE:
|
|
; WAIT FOR THE BUS TO BE READY. WE USE AN EXTRA LONG WAIT
|
|
; TIMEOUT HERE BECAUSE THIS IS WHERE WE WILL WAIT FOR LONG
|
|
; OPERATIONS TO COMPLETE. IT CAN TAKE SOME TIME IF THE
|
|
; DEVICE HAS GONE TO SLEEP BECAUSE IT WILL NEED TO WAKE UP
|
|
; AND SPIN UP BEFORE PROCESSING AN I/O COMMAND.
|
|
CALL PPA_LONGWAIT ; WAIT TILL READY
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nPHASE: $")
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CP $C0 ; DEVICE WANTS TO RCV DATA
|
|
JR Z,PPA_RUNCMD_WRITE
|
|
CP $D0 ; DEVICE WANTS TO SEND DATA
|
|
JR Z,PPA_RUNCMD_READ
|
|
CP $F0 ; DEVICE WANTS TO BE DONE
|
|
JR Z,PPA_RUNCMD_END
|
|
JR PPA_CMD_IOERR
|
|
;
|
|
PPA_RUNCMD_WRITE:
|
|
LD DE,(PPA_DSKBUF) ; XFER BUFFER
|
|
LD A,(PPA_XFRMODE) ; XFER MODE
|
|
CALL PPA_PUTDATA ; SEND DATA NOW
|
|
JR PPA_RUNCMD_PHASE ; BACK TO DISPATCH
|
|
;
|
|
PPA_RUNCMD_READ:
|
|
LD DE,(PPA_DSKBUF) ; XFER BUFFER
|
|
LD A,(PPA_XFRMODE) ; XFER MODE
|
|
CALL PPA_GETDATA ; GET THE DATA NOW
|
|
JR PPA_RUNCMD_PHASE ; BACK TO DISPATCH
|
|
;
|
|
PPA_RUNCMD_END:
|
|
CALL PPA_GETSTATUS ; READ STATUS BYTES
|
|
CALL PPA_DISCONNECT ; PARALLEL PORT BUS DISCONNECT
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
PPA_CMD_IOERR:
|
|
LD A,PPA_STIOERR ; ERROR VALUE TO A
|
|
JR PPA_CMD_ERR ; CONTINUE
|
|
;
|
|
PPA_CMD_TIMEOUT:
|
|
LD A,PPA_STTO ; ERROR VALUE TO A
|
|
JR PPA_CMD_ERR ; CONTINUE
|
|
;
|
|
PPA_CMD_ERR:
|
|
LD SP,(PPA_CMDSTK) ; UNWIND STACK
|
|
PUSH AF ; SAVE STATUS
|
|
;CALL PPA_RESETPULSE ; CLEAN UP THE MESS???
|
|
LD DE,62 ; DELAY AFTER RESET PULSE
|
|
CALL VDELAY
|
|
CALL PPA_DISCONNECT ; PARALLEL PORT BUS DISCONNECT
|
|
LD DE,62 ; DELAY AFTER DISCONNECT
|
|
CALL VDELAY
|
|
POP AF ; RECOVER STATUS
|
|
JP PPA_ERR ; NOW DO STANDARD ERR PROCESSING
|
|
;
|
|
; ERRORS SHOULD GENERALLY NOT CAUSE SCSI PROCESSING TO FAIL. IF A
|
|
; DEVICE ERROR (I.E., READ ERROR) OCCURS, THEN THE SCSI PROTOCOL WILL
|
|
; PROVIDE ERROR INFORMATION. THE STATUS RESULT OF THE SCSI COMMAND
|
|
; WILL INDICATE IF AN ERROR OCCURRED. ADDITIONALLY, IF THE ERROR IS
|
|
; A CHECK CONDITION ERROR, THEN IT IS MANDATORY TO ISSUE A SENSE
|
|
; REQUEST SCSI COMMAND TO CLEAR THE ERROR AND RETRIEVE DETAILED ERROR
|
|
; INFO.
|
|
;
|
|
PPA_CHKCMD:
|
|
; SCSI COMMAND COMPLETED, CHECK SCSI CMD STATUS
|
|
LD A,(PPA_CMDSTAT) ; GET STATUS BYTE
|
|
OR A ; SET FLAGS
|
|
RET Z ; IF ZERO, ALL GOOD, DONE
|
|
;
|
|
; DO WE HAVE A CHECK CONDITION?
|
|
CP 2 ; CHECK CONDITION RESULT?
|
|
JR Z,PPA_CHKCMD1 ; IF SO, REQUEST SENSE
|
|
JP PPA_IOERR ; ELSE, GENERAL I/O ERROR
|
|
;
|
|
PPA_CHKCMD1:
|
|
; USE REQUEST SENSE CMD TO GET ERROR DETAILS
|
|
LD DE,HB_WRKBUF ; PUT DATA IN WORK BUF
|
|
LD A,0 ; VARIABLE LENGTH READ
|
|
LD HL,PPA_CMD_SENSE ; REQUEST SENSE CMD
|
|
CALL PPA_RUNCMD ; DO IT
|
|
JP NZ,PPA_IOERR ; BAIL IF ERROR IN CMD
|
|
;
|
|
; REQ SENSE CMD COMPLETED
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nSENSE:$")
|
|
LD A,$19
|
|
LD DE,HB_WRKBUF
|
|
CALL Z,PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; CHECK SCSI CMD STATUS
|
|
LD A,(PPA_CMDSTAT) ; GET STATUS BYTE
|
|
OR A ; SET FLAGS
|
|
JP NZ,PPA_IOERR ; IF FAILED, GENERAL I/O ERROR
|
|
;
|
|
; RETURN RESULT BASED ON REQ SENSE DATA
|
|
; TODO: WE NEED TO CHECK THE SENSE KEY FIRST!!!
|
|
LD A,(HB_WRKBUF+12) ; GET ADDITIONAL SENSE CODE
|
|
CP $3A ; NO MEDIA?
|
|
JP Z,PPA_NOMEDIA ; IF SO, RETURN NO MEDIA ERR
|
|
JP PPA_IOERR ; ELSE GENERAL I/O ERR
|
|
;
|
|
; CHECK CURRENT DEVICE FOR ERROR STATUS AND ATTEMPT TO RECOVER
|
|
; VIA RESET IF DEVICE IS IN ERROR.
|
|
;
|
|
PPA_CHKERR:
|
|
LD A,(IY+PPA_STAT) ; GET STATUS
|
|
OR A ; SET FLAGS
|
|
CALL NZ,PPA_RESET ; IF ERROR STATUS, RESET BUS
|
|
RET
|
|
;
|
|
; (RE)INITIALIZE DEVICE
|
|
;
|
|
PPA_INITDEV:
|
|
;
|
|
#IF (PPAMODE == PPAMODE_MG014)
|
|
; INITIALIZE 8255
|
|
LD A,(IY+PPA_IOBASE) ; BASE PORT
|
|
ADD A,PPA_IOSETUP ; BUMP TO SETUP PORT
|
|
LD C,A ; MOVE TO C FOR I/O
|
|
LD A,$82 ; CONFIG A OUT, B IN, C OUT
|
|
OUT (C),A ; DO IT
|
|
CALL DELAY ; SHORT DELAY FOR BUS SETTLE
|
|
#ENDIF
|
|
;
|
|
; BUS RESET
|
|
CALL PPA_CONNECT
|
|
CALL PPA_RESETPULSE
|
|
LD DE,62 ; 1000 US
|
|
CALL VDELAY
|
|
CALL PPA_DISCONNECT
|
|
LD DE,62 ; 1000 US
|
|
CALL VDELAY
|
|
;
|
|
; INITIALLY, THE DEVICE MAY REQUIRE MULTIPLE REQUEST SENSE
|
|
; COMMANDS BEFORE IT WILL ACCEPT I/O COMMANDS. THIS IS DUE
|
|
; TO THINGS LIKE BUS RESET NOTIFICATION, MEDIA CHANGE, ETC.
|
|
; HERE, WE RUN A FEW REQUEST SENSE COMMANDS. AS SOON AS ONE
|
|
; INDICATES NO ERRORS, WE CAN CONTINUE.
|
|
LD B,4 ; TRY UP TO 4 TIMES
|
|
PPA_INITDEV1:
|
|
PUSH BC ; SAVE LOOP COUNTER
|
|
;
|
|
; REQUEST SENSE COMMAND
|
|
LD DE,HB_WRKBUF ; BUFFER FOR SENSE DATA
|
|
LD A,0 ; READ WHATEVER IS SENT
|
|
LD HL,PPA_CMD_SENSE ; POINT TO CMD BUFFER
|
|
CALL PPA_RUNCMD ; RUN THE SCSI ENGINE
|
|
JR NZ,PPA_INITDEV2 ; CMD PROC ERROR
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nSENSE:$")
|
|
LD A,$19
|
|
LD DE,HB_WRKBUF
|
|
CALL PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; CHECK SENSE KEY
|
|
LD A,(HB_WRKBUF + 2) ; GET SENSE KEY
|
|
OR A ; SET FLAGS
|
|
;
|
|
PPA_INITDEV2:
|
|
POP BC ; RESTORE LOOP COUNTER
|
|
JR Z,PPA_INITDEV3 ; IF NO ERROR, MOVE ON
|
|
DJNZ PPA_INITDEV1 ; TRY UNTIL COUNTER EXHAUSTED
|
|
JP PPA_IOERR ; BAIL OUT WITH ERROR
|
|
;
|
|
PPA_INITDEV3:
|
|
; READ & RECORD DEVICE CAPACITY
|
|
LD DE,HB_WRKBUF ; BUFFER TO CAPACITY RESPONSE
|
|
LD A,0 ; READ WHATEVER IS SENT
|
|
LD HL,PPA_CMD_RDCAP ; POINT TO READ CAPACITY CMD
|
|
CALL PPA_RUNCMD ; RUN THE SCSI ENGINE
|
|
CALL Z,PPA_CHKCMD ; CHECK AND RECORD ANY ERRORS
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
;
|
|
#IF (PPATRACE >= 3)
|
|
PRTS("\r\nRDCAP:$")
|
|
LD A,8
|
|
LD DE,HB_WRKBUF
|
|
CALL PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; CAPACITY IS RETURNED IN A 4 BYTE, BIG ENDIAN FIELD AND
|
|
; INDICATES THE LAST LBA VALUE. WE NEED TO CONVERT THIS TO
|
|
; LITTLE ENDIAN AND INCREMENT THE VALUE TO MAKE IT A CAPACITY
|
|
; COUNT INSTEAD OF A LAST LBA VALUE.
|
|
LD A,PPA_MEDCAP ; OFFSET IN CFG FOR CAPACITY
|
|
CALL LDHLIYA ; POINTER TO HL
|
|
PUSH HL ; SAVE IT
|
|
LD HL,HB_WRKBUF ; POINT TO VALUE IN CMD RESULT
|
|
CALL LD32 ; LOAD IT TO DE:HL
|
|
LD A,L ; FLIP BYTES
|
|
LD L,D ; ... BIG ENDIAN
|
|
LD D,A ; ... TO LITTLE ENDIAN
|
|
LD A,H
|
|
LD H,E
|
|
LD E,A
|
|
CALL INC32 ; INCREMENT TO FINAL VALUE
|
|
POP BC ; RECOVER SAVE LOCATION
|
|
CALL ST32 ; STORE VALUE
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
LD (IY+PPA_STAT),A ; RECORD IT
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; ERROR HANDLING AND DIAGNOSTICS
|
|
;=============================================================================
|
|
;
|
|
; ERROR HANDLERS
|
|
;
|
|
;
|
|
PPA_NOMEDIA:
|
|
LD A,PPA_STNOMEDIA
|
|
JR PPA_ERR
|
|
;
|
|
PPA_CMDERR:
|
|
LD A,PPA_STCMDERR
|
|
JR PPA_ERR
|
|
;
|
|
PPA_IOERR:
|
|
LD A,PPA_STIOERR
|
|
JR PPA_ERR
|
|
;
|
|
PPA_TO:
|
|
LD A,PPA_STTO
|
|
JR PPA_ERR
|
|
;
|
|
PPA_NOTSUP:
|
|
LD A,PPA_STNOTSUP
|
|
JR PPA_ERR
|
|
;
|
|
PPA_ERR:
|
|
LD (IY+PPA_STAT),A ; SAVE NEW STATUS
|
|
;
|
|
PPA_ERR2:
|
|
#IF (PPATRACE >= 2)
|
|
CALL PPA_PRTSTAT
|
|
#ENDIF
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
PPA_PRTERR:
|
|
RET Z ; DONE IF NO ERRORS
|
|
; FALL THRU TO PPA_PRTSTAT
|
|
;
|
|
; PRINT FULL DEVICE STATUS LINE
|
|
;
|
|
PPA_PRTSTAT:
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(IY+PPA_STAT)
|
|
CALL PPA_PRTPREFIX ; PRINT UNIT PREFIX
|
|
CALL PC_SPACE ; FORMATTING
|
|
CALL PPA_PRTSTATSTR
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT STATUS STRING
|
|
;
|
|
PPA_PRTSTATSTR:
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(IY+PPA_STAT)
|
|
NEG
|
|
LD HL,PPA_STR_ST_MAP
|
|
ADD A,A
|
|
CALL ADDHLA
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
CALL WRITESTR
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT DIAGNONSTIC PREFIX
|
|
;
|
|
PPA_PRTPREFIX:
|
|
PUSH AF
|
|
CALL NEWLINE
|
|
PRTS("PPA$")
|
|
LD A,(IY+PPA_DEV) ; GET CURRENT DEVICE NUM
|
|
CALL PRTDECB
|
|
CALL PC_COLON
|
|
POP AF
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; STRING DATA
|
|
;=============================================================================
|
|
;
|
|
PPA_STR_ST_MAP:
|
|
.DW PPA_STR_STOK
|
|
.DW PPA_STR_STNOMEDIA
|
|
.DW PPA_STR_STCMDERR
|
|
.DW PPA_STR_STIOERR
|
|
.DW PPA_STR_STTO
|
|
.DW PPA_STR_STNOTSUP
|
|
;
|
|
PPA_STR_STOK .TEXT "OK$"
|
|
PPA_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
|
PPA_STR_STCMDERR .TEXT "COMMAND ERROR$"
|
|
PPA_STR_STIOERR .TEXT "IO ERROR$"
|
|
PPA_STR_STTO .TEXT "TIMEOUT$"
|
|
PPA_STR_STNOTSUP .TEXT "NOT SUPPORTED$"
|
|
PPA_STR_STUNK .TEXT "UNKNOWN ERROR$"
|
|
;
|
|
PPA_STR_MODE_MAP:
|
|
.DW PPA_STR_MODE_NONE
|
|
.DW PPA_STR_MODE_SPP
|
|
.DW PPA_STR_MODE_MG014
|
|
;
|
|
PPA_STR_MODE_NONE .DB "NONE$"
|
|
PPA_STR_MODE_SPP .DB "SPP$"
|
|
PPA_STR_MODE_MG014 .DB "MG014$"
|
|
;
|
|
PPA_STR_NOHW .TEXT "NOT PRESENT$"
|
|
;
|
|
;=============================================================================
|
|
; DATA STORAGE
|
|
;=============================================================================
|
|
;
|
|
PPA_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT
|
|
PPA_CMDSTK .DW 0 ; STACK PTR FOR CMD ABORTING
|
|
PPA_DSKBUF .DW 0 ; WORKING DISK BUFFER POINTER
|
|
PPA_XFRMODE .DB 0 ; 0=VARIABLE, 1=BLOCK (512 BYTES)
|
|
PPA_CMDSTAT .DB 0, 0 ; CMD RESULT STATUS
|
|
;
|
|
; SCSI COMMAND TEMPLATES (LENGTH PREFIXED)
|
|
;
|
|
.DB 6
|
|
PPA_CMD_RW .DB $00, $00, $00, $00, $01, $00 ; READ/WRITE SECTOR
|
|
.DB 6
|
|
PPA_CMD_SENSE .DB $03, $00, $00, $00, $FF, $00 ; REQUEST SENSE DATA
|
|
.DB 10
|
|
PPA_CMD_RDCAP .DB $25, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; READ CAPACITY
|
|
;
|
|
; PPA DEVICE CONFIGURATION TABLE
|
|
;
|
|
PPA_CFG:
|
|
;
|
|
#IF (PPACNT >= 1)
|
|
;
|
|
PPA0_CFG: ; DEVICE 0
|
|
.DB 0 ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB PPAMODE ; DRIVER DEVICE MODE
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB PPA0BASE ; IO BASE ADDRESS
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
#ENDIF
|
|
;
|
|
#IF (PPACNT >= 2)
|
|
;
|
|
PPA1_CFG: ; DEVICE 1
|
|
.DB 0 ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB PPAMODE ; DRIVER DEVICE MODE
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB PPA1BASE ; IO BASE ADDRESS
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
#ENDIF
|
|
;
|
|
#IF ($ - PPA_CFG) != (PPACNT * PPA_CFGSIZ)
|
|
.ECHO "*** INVALID PPA CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END MARKER
|