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.
 
 
 
 
 
 

1454 lines
26 KiB

;
;=============================================================================
; PPA DISK DRIVER
;=============================================================================
;
; PARALLEL PORT INTERFACE FOR SCSI DISK DEVICES USING A PARALLEL PORT
; ADAPTER. PRIMARILY TARGETS PARALLEL PORT IOMEGA ZIP DRIVES.
;
; CURRENTLY CODED SPECIFICALLY FOR RCBUS MG014 PARALLEL PORT HARDWARE.
; INTENDED TO CO-EXIST WITH LPT DRIVER.
;
; CREATED BY WAYNE WARTHEN FOR ROMWBW HBIOS.
; MUCH OF THE CODE IS DERIVED FROM FUZIX (ALAN COX).
;
; 5/19/2023 WBW - INITIAL RELEASE
;
;=============================================================================
;
; MG014 STYLE INTERFACE (USED BY RCBUS MG014 MODULE):
;
; PORT 0 (INPUT/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 (INPUT/OUTPUT):
;
; D7 D6 D5 D4 D3 D2 D1 D0
; +-------+-------+-------+-------+-------+-------+-------+-------+
; | LED | | | | /SEL | /RES | /LF | /STB |
; +-------+-------+-------+-------+-------+-------+-------+-------+
;
;=============================================================================
;
; TODO:
;
; NOTES:
;
;;;;
;;;; COMMAND BYTES
;;;;
;;;PPA_CPPA_NOP .EQU $00
;;;PPA_CPPA_DEVRES .EQU $08
;;;PPA_CPPA_RECAL .EQU $10
;;;PPA_CPPA_READ .EQU $20
;;;PPA_CPPA_WRITE .EQU $30
;;;PPA_CPPA_DEVDIAG .EQU $90
;;;PPA_CPPA_IDPKTDEV .EQU $A1
;;;PPA_CPPA_IDDEV .EQU $EC
;;;PPA_CPPA_SETFEAT .EQU $EF
;
; 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
;
; PPA DEVICE STATUS
;
PPA_STOK .EQU 0
PPA_STINVUNIT .EQU -1
PPA_STNOMEDIA .EQU -2
PPA_STCMDERR .EQU -3
PPA_STIOERR .EQU -4
PPA_STTO .EQU -5
PPA_STNOTSUP .EQU -6
;
; 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)
;
;=============================================================================
; 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:
; CHECK FOR HARDWARE PRESENCE
CALL PPA_DETECT ; PROBE FOR INTERFACE
JP NZ,PPA_INIT6 ; SKIP CFG ENTRY
;
; 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
;
CALL PPA_PRTPREFIX ; PRINT DEVICE PREFIX
;
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 DE,PPA_STR_MODE_NONE ; MODE LABEL
CP PPAMODE_NONE ; TEST FOR MODE
JR Z,PPA_INIT3 ; IF SO, DISPLAY IT
LD DE,PPA_STR_MODE_MG014 ; MODE LABEL
CP PPAMODE_MG014 ; TEST FOR MODE
JR Z,PPA_INIT3 ; IF SO, DISPLAY IT
LD DE,PPA_STR_MODE_UNK ; MODE LABEL
PPA_INIT3:
CALL WRITESTR ; DISPLAY MODE
;
PPA_INIT4:
CALL PPA_RESET ; RESET THE INTERFACE
;
; 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
;
; CHECK FOR BAD STATUS
LD A,(IY+PPA_STAT) ; GET STATUS
OR A ; SET FLAGS
JP Z,PPA_INIT5 ; CONTINUE
CALL PC_SPACE ; FORMATTING
CALL PPA_PRTSTATSTR ; PRINT STATUS STRING
JR PPA_INIT6 ; LOOP TILL DONE
;
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:
XOR A ; SIGNAL SUCCESS
RET ; AND RETURN
;
;=============================================================================
; 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:
JP PPA_STNOTSUP ; NOT SUPPORTED
;
;
;
PPA_WRITE:
JP PPA_STNOTSUP ; NOT SUPPORTED
;
;
;
PPA_STATUS:
; RETURN UNIT STATUS
LD A,(IY+PPA_STAT) ; GET STATUS OF SELECTED DEVICE
OR A ; SET FLAGS
RET ; AND RETURN
;
;
;
PPA_DEVICE:
LD D,DIODEV_PPA ; D := DEVICE TYPE
LD E,(IY+PPA_DEV) ; E := PHYSICAL DEVICE NUMBER
LD C,%01000000 ; 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 PPA INTERFACE
CALL PPA_INITUNIT ; RE-INITIALIZE UNIT
;
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
;=============================================================================
;
PPA_SELF .EQU 7
PPA_TGT .EQU 6
;
IMM_TGT .EQU 6
;
;
;
PPA_DELAY:
PUSH AF
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
POP AF
RET
;
;
;
PPA_WRITEDATA:
;PRTS(" D-$")
;CALL PRTHEXBYTE
LD C,(IY+PPA_IOBASE)
OUT (C),A
CALL PPA_DELAY
RET
;
;
;
PPA_WRITECTRL:
;PRTS(" C-$")
;CALL PRTHEXBYTE
XOR $0B
;PRTS(">$")
;CALL PRTHEXBYTE
LD C,(IY+PPA_IOBASE)
INC C
INC C
OUT (C),A
CALL PPA_DELAY
RET
;
;
;
PPA_READSTATUS:
LD C,(IY+PPA_IOBASE)
INC C
IN A,(C)
;PRTS(" I-$")
;CALL PRTHEXBYTE
LD C,0 ; INIT RESULT
;
BIT 0,A ; ACK = $01
JR Z,PPA_READSTATUS1
SET 6,C ; $40
;
PPA_READSTATUS1:
;
BIT 1,A ; BUSY = $02
JR NZ,PPA_READSTATUS2
SET 7,C ; $80
;
PPA_READSTATUS2:
;
BIT 2,A ; PAPER = $04
JR Z,PPA_READSTATUS3
SET 5,C ; $20
;
PPA_READSTATUS3:
;
BIT 3,A ; SELECT = $08
JR Z,PPA_READSTATUS4
SET 4,C ; $10
;
PPA_READSTATUS4:
;
BIT 4,A ; FAULT = $10
JR Z,PPA_READSTATUS5
SET 3,C ; $08
;
PPA_READSTATUS5:
LD A,C
;PRTS(">$")
;CALL PRTHEXBYTE
RET
;
;
;
PPA_DPULSE:
CALL PPA_WRITEDATA
LD A,$0C
CALL PPA_WRITECTRL
LD A,$0E
CALL PPA_WRITECTRL
LD A,$0C ;?
CALL PPA_WRITECTRL ;?
LD A,$04
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
RET
;
;
;
PPA_CPULSE:
CALL PPA_WRITEDATA
LD A,$04
CALL PPA_WRITECTRL
LD A,$06
CALL PPA_WRITECTRL
LD A,$04
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
RET
;
;
;
PPA_CONNECT:
CALL NEWLINE
LD A,$00
CALL PPA_CPULSE
LD A,$3C
CALL PPA_CPULSE
LD A,$20
CALL PPA_CPULSE
LD A,$8F
CALL PPA_CPULSE
RET
;
;
;
IMM_CPP:
;CALL NEWLINE
PUSH AF
LD A,$0C
CALL PPA_WRITECTRL
LD A,$AA
CALL PPA_WRITEDATA
LD A,$55
CALL PPA_WRITEDATA
LD A,$00
CALL PPA_WRITEDATA
LD A,$FF
CALL PPA_WRITEDATA
CALL PPA_READSTATUS
AND $B8
LD (IMM_S1),A
LD A,$87
CALL PPA_WRITEDATA
CALL PPA_READSTATUS
AND $B8
LD (IMM_S2),A
LD A,$78
CALL PPA_WRITEDATA
CALL PPA_READSTATUS
AND $38
LD (IMM_S3),A
POP AF
CALL PPA_WRITEDATA
LD A,$0C
CALL PPA_WRITECTRL
LD A,$0D
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
LD A,$FF
CALL PPA_WRITEDATA
; CONNECT: S1=$B8 S2=$18 S3=$30
; DISCONNECT: S1=$B8 S2=$18 S3=$38
PRTS("\r\nCPP: S1=$")
LD A,(IMM_S1)
CALL PRTHEXBYTE
PRTS(" S2=$")
LD A,(IMM_S2)
CALL PRTHEXBYTE
PRTS(" S3=$")
LD A,(IMM_S3)
CALL PRTHEXBYTE
XOR A ; ASSUME SUCCESS FOR NOW
RET
;
IMM_S1 .DB 0
IMM_S2 .DB 0
IMM_S3 .DB 0
;
;
;
IMM_CONNECT:
LD A,$E0
CALL IMM_CPP
LD A,$30
CALL IMM_CPP
LD A,$E0
CALL IMM_CPP
RET
;
;
;
IMM_DISCONNECT:
LD A,$30
CALL IMM_CPP
RET
;
;
;
IMM_RESETPULSE:
;CALL NEWLINE
LD A,$04
CALL PPA_WRITECTRL
LD A,$40
CALL PPA_WRITEDATA
CALL DELAY
LD A,$0C
CALL PPA_WRITECTRL
LD A,$0D
CALL PPA_WRITECTRL
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
LD A,$0C
CALL PPA_WRITECTRL
LD A,$04
CALL PPA_WRITECTRL
RET
;
;
;
PPA_DISCONNECT:
;CALL NEWLINE
LD A,$00
CALL PPA_DPULSE
LD A,$3C
CALL PPA_DPULSE
LD A,$20
CALL PPA_DPULSE
LD A,$0F
CALL PPA_DPULSE
RET
;
;
;
PPA_SELECT:
LD A,1 << PPA_TGT
CALL PPA_WRITEDATA
LD A,$0E
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
LD A,1 << PPA_SELF
CALL PPA_WRITEDATA
LD A,$08
CALL PPA_WRITECTRL
;
LD HL,0 ; TIMEOUT COUNTER
;
PPA_SELECT1:
CALL PPA_READSTATUS
OR $F0
RET NZ
DEC HL
LD A,H
OR L
RET Z ; TIMEOUT
JR PPA_SELECT1
;
;
;
IMM_SELECT:
PRTS("\r\nSELECT: $")
LD A,$0C
CALL PPA_WRITECTRL
;
LD HL,500 ; TIMEOUT COUNTER
;
IMM_SELECT1:
CALL PPA_READSTATUS
AND $08
JR Z,IMM_SELECT2 ; IF CLEAR, MOVE ON
DEC HL
LD A,H
OR L
JP Z,IMM_CMD_TIMEOUT ; TIMEOUT
JR IMM_SELECT1
;
IMM_SELECT2:
LD A,$04
CALL PPA_WRITECTRL
LD A,$80 | (1 << IMM_TGT)
CALL PPA_WRITEDATA
CALL DELAY
LD A,$0C
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
CALL PC_SPACE
CALL PRTHEXBYTE
LD A,$0D
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
CALL PC_SPACE
CALL PRTHEXBYTE
;
LD HL,500 ; TIMEOUT COUNTER
;
IMM_SELECT3:
CALL PPA_READSTATUS
CALL PC_SPACE
CALL PRTHEXBYTE
AND $08
JR NZ,IMM_SELECT4 ; IF CLEAR, MOVE ON
DEC HL
LD A,H
OR L
JP Z,IMM_CMD_TIMEOUT ; TIMEOUT
JR IMM_SELECT3
;
IMM_SELECT4:
LD A,$0C
CALL PPA_WRITECTRL
;
XOR A
RET
;
;
;
IMM_SENDCMD:
; TODO: USE PUTDATA ROUTINE???
; TODO: CHECK BUSY???
PRTS("\r\nSENDCMD:$")
LD A,$04
CALL PPA_WRITECTRL
;
LD HL,IMM_CMD
LD B,6
;
IMM_SENDCMD1:
LD A,(HL)
CALL PC_SPACE
CALL PRTHEXBYTE
CALL PPA_WRITEDATA
INC HL
DEC B
LD A,$05
CALL PPA_WRITECTRL
LD A,(HL)
CALL PC_SPACE
CALL PRTHEXBYTE
CALL PPA_WRITEDATA
INC HL
LD A,$00
CALL PPA_WRITECTRL
DJNZ IMM_SENDCMD1
LD A,$04
CALL PPA_WRITECTRL
;
CALL PPA_READSTATUS
CALL PC_SPACE
CALL PC_GT
CALL PRTHEXBYTE
RET
;
;
;
IMM_WAITBUSY:
LD HL,500 ; NORMAL TIMEOUT COUNTER
;
IMM_WAITBUSY_HL: ; VARIABLE TIMEOUT ENTRY
;PRTS("\r\nWAITB: $")
LD A,$0C
CALL PPA_WRITECTRL
;
IMM_WAITBUSY2:
CALL PPA_READSTATUS
BIT 7,A
RET NZ ; IF SET, MOVE ON
DEC HL
LD A,H
OR L
JP Z,IMM_CMD_TIMEOUT ; TIMEOUT
JR IMM_WAITBUSY2
;
;
;
IMM_WAITDONE:
LD HL,500 ; NORMAL TIMEOUT COUNTER
;
IMM_WAITDONE_HL: ; VARIABLE TIMEOUT ENTRY
CALL IMM_WAITBUSY_HL
AND $B8
PUSH AF
LD A,$04
CALL PPA_WRITECTRL
POP AF
RET
;
;
;
IMM_NEGOTIATE:
; TODO: REVIEW TIMING DELAYS!!!
PRTS("\r\nNEGO: $")
LD A,$04
CALL PPA_WRITECTRL
CALL DELAY
LD A,$00
CALL PPA_WRITEDATA
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
LD A,$06
CALL PPA_WRITECTRL
CALL DELAY
CALL PPA_READSTATUS
PUSH AF ; SAVE RESULT
CALL DELAY
LD A,$07
CALL PPA_WRITECTRL
CALL DELAY
LD A,$06
CALL PPA_WRITECTRL
;
POP AF
CALL PC_SPACE
CALL PRTHEXBYTE
AND $20
CALL PC_SPACE
CALL PC_GT
CALL PRTHEXBYTE
CP $20
JP NZ,IMM_CMD_IOERR
RET
;
;
;
PPA_WAITDONE:
LD HL,0 ; TIMEOUT COUNTER
PPA_WAITDONE1:
CALL PPA_READSTATUS
AND $F0
BIT 7,A
RET NZ
DEC HL
LD A,H
OR L
JP Z,IMM_CMD_TIMEOUT ; TIMEOUT
JR PPA_WAITDONE1
;
;
;
IMM_GETBYTE:
CALL IMM_WAITBUSY
LD A,$04
CALL PPA_WRITECTRL
LD A,$06
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
RRCA
RRCA
RRCA
RRCA
PUSH AF
LD A,$05
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
POP HL
OR H
PUSH AF
LD A,$04
CALL PPA_WRITECTRL
POP AF
RET
;
; DE=BUFFER
; HL=LENGTH (0 FOR VARIABLE)
;
IMM_GETDATA:
LD A,H
OR L
JR NZ,IMM_GETDATALEN
PRTS("\r\nGETDATA:$")
IMM_GETDATA1:
PUSH HL
CALL IMM_WAITDONE
POP HL
CP $98
JR NZ,IMM_GETDATA2
LD A,$04
CALL PPA_WRITECTRL
LD A,$06
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
RRCA
RRCA
RRCA
RRCA
PUSH AF
LD A,$05
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
POP BC
OR B
LD (DE),A
INC DE
INC HL
LD A,$04
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
JR IMM_GETDATA1
;
IMM_GETDATA2:
CALL PC_SPACE
CALL PRTHEXWORDHL
PRTS(" BYTES$")
RET
;
IMM_GETDATALEN:
PRTS("\r\nGETDLEN:$")
CALL PC_SPACE
CALL PRTHEXWORDHL
PRTS(" BYTES$")
LD A,$04
CALL PPA_WRITECTRL
IMM_GETDATALEN1:
LD A,$06
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
RRCA
RRCA
RRCA
RRCA
PUSH AF
LD A,$05
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
POP BC
OR B
LD (DE),A
INC DE
DEC HL
LD A,$04
CALL PPA_WRITECTRL
LD A,H
OR L
JR NZ,IMM_GETDATALEN1
LD A,$0C
CALL PPA_WRITECTRL
RET
;
; DE=BUFFER
; HL=LENGTH (0 FOR VARIABLE)
;
IMM_PUTDATA:
LD A,H
OR L
JR NZ,IMM_PUTDATALEN
PRTS("\r\nPUTDATA:$")
IMM_PUTDATA1:
PUSH HL
CALL IMM_WAITDONE
POP HL
CP $88
JR NZ,IMM_PUTDATA2
LD A,$04
CALL PPA_WRITECTRL
LD A,(DE)
CALL PPA_WRITEDATA
INC DE
INC HL
LD A,$05
CALL PPA_WRITECTRL
LD A,(DE)
CALL PPA_WRITEDATA
INC DE
INC HL
LD A,$00
CALL PPA_WRITECTRL
JR IMM_PUTDATA1
;
IMM_PUTDATA2:
LD A,$04
CALL PPA_WRITECTRL
CALL PC_SPACE
CALL PRTHEXWORDHL
PRTS(" BYTES$")
RET
;
IMM_PUTDATALEN:
PRTS("\r\nPUTDLEN:$")
CALL PC_SPACE
CALL PRTHEXWORDHL
PRTS(" BYTES$")
LD A,$04
CALL PPA_WRITECTRL
IMM_PUTDATALEN1:
LD A,(DE)
CALL PPA_WRITEDATA
INC DE
DEC HL
LD A,$05
CALL PPA_WRITECTRL
LD A,(DE)
CALL PPA_WRITEDATA
INC DE
DEC HL
LD A,$00
CALL PPA_WRITECTRL
LD A,H
OR L
JR NZ,IMM_PUTDATALEN1
LD A,$04
CALL PPA_WRITECTRL
RET
;
;
;
IMM_GETSTATUS:
PRTS("\r\nSTATUS:$")
CALL IMM_GETBYTE
LD (IMM_STATUS),A
CALL PC_SPACE
CALL PRTHEXBYTE
CALL IMM_WAITDONE
CP $B8
RET NZ
CALL IMM_GETBYTE
LD (IMM_STATUS+1),A
CALL PC_SPACE
CALL PRTHEXBYTE
RET
;
;
;
IMM_ENDREAD:
LD A,$04
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
LD A,$0E
CALL PPA_WRITECTRL
LD A,$04
CALL PPA_WRITECTRL
RET
;
;
;
IMM_RUNCMDX:
; COPY CMD BYTES FROM (HL)
PUSH BC
PUSH DE
LD BC,6
LD DE,IMM_CMD
LDIR
POP DE
POP BC
;
IMM_RUNCMD:
LD (IMM_CMDSTK),SP ; FOR ERROR ABORTS
LD (IMM_DSKBUF),DE ; SAVE BUF PTR
LD (IMM_XFRLEN),BC ; SAVE XFER LEN
CALL IMM_CONNECT
CALL IMM_SELECT
CALL IMM_WAITBUSY
CALL IMM_SENDCMD
;
IMM_RUNCMD_LOOP:
LD HL,50000 ; LONG TIMEOUT HERE
CALL IMM_WAITDONE_HL
;
PRTS("\r\nCMD$")
PRTS("LOOP: $")
CALL PRTHEXBYTE
;
CP $88
JR Z,IMM_RUNCMD_WRITE
CP $98
JR Z,IMM_RUNCMD_READ
CP $B8
JR Z,IMM_RUNCMD_END
JR IMM_CMD_IOERR
;
IMM_RUNCMD_WRITE:
LD DE,(IMM_DSKBUF)
LD HL,(IMM_XFRLEN) ; XFER LENGTH
CALL IMM_PUTDATA ; SEND DATA NOW
JR IMM_RUNCMD_LOOP
;
IMM_RUNCMD_READ:
CALL IMM_NEGOTIATE
CALL IMM_WAITDONE
; CHECK FOR STATUS $98???
LD DE,(IMM_DSKBUF)
LD HL,(IMM_XFRLEN) ; XFER LENGTH
CALL IMM_GETDATA ; GET THE DATA NOW
CALL IMM_ENDREAD
JR IMM_RUNCMD_LOOP
;
IMM_RUNCMD_END:
CALL IMM_NEGOTIATE
CALL IMM_WAITDONE
; CHECK FOR STATUS $B8???
CALL IMM_GETSTATUS
CALL IMM_ENDREAD
CALL IMM_DISCONNECT
XOR A ; SIGNAL SUCCESS
RET
;
IMM_CMD_IOERR:
LD A,PPA_STIOERR
JR IMM_CMD_ERR
;
IMM_CMD_TIMEOUT:
LD A,PPA_STTO
JR IMM_CMD_ERR
;
IMM_CMD_ERR:
LD SP,(IMM_CMDSTK) ; UNWIND STACK
PUSH AF ; SAVE STATUS
CALL IMM_RESETPULSE ; CLEAN UP THE MESS
CALL IMM_DISCONNECT ; MAKE SURE WE ARE OFF THE BUS
POP AF ; RECOVER STATUS
JP PPA_ERR ; ERROR EXIT
;
;=============================================================================
; HARDWARE INTERFACE ROUTINES
;=============================================================================
;
; RESET ALL DEVICES ON BUS
;
PPA_RESET:
JP PPA_INITUNIT
;
;
;
PPA_INITUNIT:
;JP PPA_INITDEV
JP IMM_INITDEV
;
; (RE)INITIALIZE DEVICE
;
PPA_INITDEV:
; 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
CALL NEWLINE
LD A,$0C
CALL PPA_WRITECTRL
CALL DELAY
;
; INITIALIZE PPA INTERFACE
CALL PPA_READSTATUS
CALL NEWLINE
LD A,$AA
CALL PPA_WRITEDATA
CALL PPA_DISCONNECT
CALL PPA_CONNECT
CALL NEWLINE
;LD A,$06
LD A,$0E
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
;... CHECK VALUE=$F0
CALL PC_SPACE
CALL PRTHEXBYTE
CALL NEWLINE
;LD A,$04
LD A,$0C
CALL PPA_WRITECTRL
CALL PPA_READSTATUS
AND $F0
;... CHECK VALUE=$80
CALL PC_SPACE
CALL PRTHEXBYTE
CALL PPA_DISCONNECT
CALL NEWLINE
LD A,$AA
CALL PPA_WRITEDATA
LD A,$0C ; ???
CALL NEWLINE
CALL PPA_WRITECTRL
CALL PPA_CONNECT
CALL NEWLINE
LD A,$40
CALL PPA_WRITEDATA
LD A,$08
CALL PPA_WRITECTRL
LD A,$0C
CALL PPA_WRITECTRL
CALL PPA_DISCONNECT
;
JP PPA_NOMEDIA
;
; RECORD STATUS OK
XOR A ; A := 0 (STATUS = OK)
LD (IY+PPA_STAT),A ; SAVE IT
;
RET ; RETURN, A=0, Z SET
;
;
;
IMM_INITDEV:
; 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
;
CALL IMM_CONNECT
CALL IMM_RESETPULSE
LD DE,62
CALL VDELAY
CALL IMM_DISCONNECT
LD DE,62
CALL VDELAY
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
LD BC,512
LD HL,IMM_CMD_READ
CALL IMM_RUNCMDX
LD DE,HB_WRKBUF
CALL Z,DUMP_BUFFER
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
LD BC,512
LD HL,IMM_CMD_READ
CALL IMM_RUNCMDX
LD DE,HB_WRKBUF
CALL Z,DUMP_BUFFER
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_INQ
CALL IMM_RUNCMDX
LD DE,HB_WRKBUF
CALL Z,DUMP_BUFFER
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
;LD BC,512
LD BC,0
LD HL,IMM_CMD_WRITE
CALL IMM_RUNCMDX
LD DE,HB_WRKBUF
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL Z,PRTHEXBUF
;
LD DE,HB_WRKBUF
LD BC,512
LD HL,IMM_CMD_READ2
CALL IMM_RUNCMDX
LD DE,HB_WRKBUF
CALL DUMP_BUFFER
;
LD DE,HB_WRKBUF
LD BC,0
LD HL,IMM_CMD_SENSE
CALL IMM_RUNCMDX
LD A,16
LD DE,HB_WRKBUF
CALL PRTHEXBUF
;
JP PPA_NOMEDIA
;
IMM_CMD .DB $00, $00, $00, $00, $00, $00 ; TEMPLATE
IMM_CMD_READ .DB $08, $00, $00, $00, $01, $00 ; READ SECTOR $0000
IMM_CMD_INQ .DB $12, $00, $00, $00, $FF, $00 ; INQUIRY
IMM_CMD_TEST .DB $00, $00, $00, $00, $00, $00 ; TEST UNIT READY
IMM_CMD_START .DB $1B, $00, $00, $00, $01, $00 ; START UNIT
IMM_CMD_SENSE .DB $03, $00, $00, $00, $FF, $00 ; REQUEST SENSE DATA
IMM_CMD_WRITE .DB $0A, $00, $F0, $00, $01, $00 ; READ SECTOR $F000
IMM_CMD_READ2 .DB $08, $00, $F0, $00, $01, $00 ; READ SECTOR $F000
;
; 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
;
;=============================================================================
; ERROR HANDLING AND DIAGNOSTICS
;=============================================================================
;
; ERROR HANDLERS
;
PPA_INVUNIT:
LD A,PPA_STINVUNIT
JR PPA_ERR2 ; SPECIAL CASE FOR INVALID UNIT
;
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)
CP PPA_STINVUNIT
JR Z,PPA_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE
CALL PPA_PRTPREFIX ; PRINT UNIT PREFIX
JR PPA_PRTSTAT3
PPA_PRTSTAT2:
CALL NEWLINE
PRTS("PPA:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT
PPA_PRTSTAT3:
CALL PC_SPACE ; FORMATTING
CALL PPA_PRTSTATSTR
POP HL
POP DE
POP AF
RET
;
; PRINT STATUS STRING
;
PPA_PRTSTATSTR:
PUSH AF
PUSH DE
LD A,(IY+PPA_STAT)
OR A
LD DE,PPA_STR_STOK
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STINVUNIT
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STNOMEDIA
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STCMDERR
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STIOERR
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STTO
JR Z,PPA_PRTSTATSTR1
INC A
LD DE,PPA_STR_STNOTSUP
JR Z,PPA_PRTSTATSTR1
LD DE,PPA_STR_STUNK
PPA_PRTSTATSTR1:
CALL WRITESTR
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
CP $FE ; NOT YET ASSIGNED?
JR Z,PPA_PRTPREFIX1 ; SKIP DEV NUM IF SO
CALL PRTDECB
PPA_PRTPREFIX1:
CALL PC_COLON
POP AF
RET
;
;=============================================================================
; STRING DATA
;=============================================================================
;
PPA_STR_STOK .TEXT "OK$"
PPA_STR_STINVUNIT .TEXT "INVALID UNIT$"
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_NO .TEXT "NO$"
PPA_STR_NOHW .TEXT "NOT PRESENT$"
;
PPA_STR_MODE_NONE .TEXT "NONE$"
PPA_STR_MODE_MG014 .TEXT "MG014$"
PPA_STR_MODE_UNK .TEXT "???$"
;
;=============================================================================
; DATA STORAGE
;=============================================================================
;
;;;PPA_DSKBUF .DW 0 ; ACTIVE DISK BUFFER
;
PPA_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT
IMM_CMDSTK .DW 0 ; STACK PTR FOR CMD ABORTING
IMM_DSKBUF .DW 0 ; WORKING DISK BUFFER POINTER
IMM_XFRLEN .DW 0 ; WORKING TRANSFER LENGTH
IMM_STATUS .DB 0, 0 ; CMD RESULT STATUS
;
PPA_TYPE_MAP:
.DW PPA_STR_NONE
.DW PPA_STR_MG014
;
PPA_STR_NONE .DB "<NOT PRESENT>$"
PPA_STR_MG014 .DB "MG014$"
;
; PPA DEVICE CONFIGURATION TABLE
;
PPA_CFG:
;
#IF (PPACNT >= 1)
;
PPA0_CFG: ; DEVICE 0
.DB 0 ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
.DB PPA0MODE ; 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 PPA1MODE ; 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