forked from MirrorRepos/RomWBW
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.
1469 lines
29 KiB
1469 lines
29 KiB
;
|
|
;=============================================================================
|
|
; IMM 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/23/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:
|
|
;
|
|
; - TIMEOUT IS INFINITE!!!
|
|
;
|
|
; - ASSIGN DRIVE LETTERS EVEN WHEN NO MEDIA AT BOOT
|
|
;
|
|
; - OPTIMIZE READ/WRITE LOOPS
|
|
;
|
|
; - COMMENT MORE OF THE CODE
|
|
;
|
|
; - THERE ARE CURRENTLY NO BUFFER OVERRUN CHECKS. WE ASSUME SCSI
|
|
; DEVICES WILL SEND/REQUEST THE EXPECTED NUMBER OF BYTES.
|
|
;
|
|
; - MAKE THE MG014 STATUS LED DO SOMETHING USEFUL?
|
|
;
|
|
; NOTES:
|
|
;
|
|
; - THIS DRIVER IS FOR THE ZIP DRIVE EMM INTERFACE. IT WILL SIMPLY
|
|
; FAIL TO EVEN RECOGNIZE A ZIP DRIVE WITH THE OLDER PPA INTERFACE.
|
|
; THERE DOES NOT SEEM TO BE A WAY TO VISUALLY DETERMINE IF A ZIP
|
|
; DRIVE IS EMM OR PPA. SIGH.
|
|
;
|
|
; - THERE ARE SOME HARD CODED TIMEOUT LOOPS IN THE CODE. THEY ARE
|
|
; WORKING OK ON A 7 MHZ Z80. THEY ARE LIKELY TO NEED TWEAKING ON
|
|
; FASTER CPUS.
|
|
;
|
|
; - THIS DRIVER OPERATES PURELY IN NIBBLE MODE. I SUSPECT IT IS
|
|
; POSSIBLE TO USE 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.
|
|
;
|
|
; IMM PORT OFFSETS
|
|
;
|
|
IMM_IODATA .EQU 0 ; PORT A, DATA, OUT
|
|
IMM_IOSTAT .EQU 1 ; PORT B, STATUS, IN
|
|
IMM_IOCTRL .EQU 2 ; PORT C, CTRL, OUT
|
|
IMM_IOSETUP .EQU 3 ; PPI SETUP
|
|
;
|
|
; SCSI UNIT IDS
|
|
;
|
|
IMM_SELF .EQU 7
|
|
IMM_TGT .EQU 6
|
|
;
|
|
; SCSI COMMAND CODES
|
|
;
|
|
SCSI_CMD_READ .EQU $08
|
|
SCSI_CMD_INQ .EQU $12
|
|
SCSI_CMD_TEST .EQU $00
|
|
SCSI_CMD_START .EQU $1B
|
|
SCSI_CMD_SENSE .EQU $03
|
|
SCSI_CMD_WRITE .EQU $0A
|
|
SCSI_CMD_RDCAP .EQU $25
|
|
|
|
;
|
|
; IMM DEVICE STATUS
|
|
;
|
|
IMM_STOK .EQU 0
|
|
IMM_STINVUNIT .EQU -1
|
|
IMM_STNOMEDIA .EQU -2
|
|
IMM_STCMDERR .EQU -3
|
|
IMM_STIOERR .EQU -4
|
|
IMM_STTO .EQU -5
|
|
IMM_STNOTSUP .EQU -6
|
|
;
|
|
; IMM DEVICE CONFIGURATION
|
|
;
|
|
IMM_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
; PER DEVICE DATA OFFSETS IN CONFIG TABLE ENTRIES
|
|
;
|
|
IMM_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
|
|
IMM_MODE .EQU 1 ; OPERATION MODE: IMM MODE (BYTE)
|
|
IMM_STAT .EQU 2 ; LAST STATUS (BYTE)
|
|
IMM_IOBASE .EQU 3 ; IO BASE ADDRESS (BYTE)
|
|
IMM_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD)
|
|
IMM_LBA .EQU 8 ; OFFSET OF LBA (DWORD)
|
|
;
|
|
;=============================================================================
|
|
; INITIALIZATION ENTRY POINT
|
|
;=============================================================================
|
|
;
|
|
IMM_INIT:
|
|
LD IY,IMM_CFG ; POINT TO START OF CONFIG TABLE
|
|
;
|
|
IMM_INIT1:
|
|
LD A,(IY) ; LOAD FIRST BYTE TO CHECK FOR END
|
|
CP $FF ; CHECK FOR END OF TABLE VALUE
|
|
JR NZ,IMM_INIT2 ; IF NOT END OF TABLE, CONTINUE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
IMM_INIT2:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("IMM:$") ; DRIVER LABEL
|
|
;
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,(IY+IMM_IOBASE) ; GET IO BASE ADDRES
|
|
CALL PRTHEXBYTE ; DISPLAY IT
|
|
;
|
|
PRTS(" MODE=$") ; LABEL FOR MODE
|
|
LD A,(IY+IMM_MODE) ; GET MODE BITS
|
|
LD DE,IMM_STR_MODE_NONE ; MODE LABEL
|
|
CP IMMMODE_NONE ; TEST FOR MODE
|
|
JR Z,IMM_INIT3 ; IF SO, DISPLAY IT
|
|
LD DE,IMM_STR_MODE_MG014 ; MODE LABEL
|
|
CP IMMMODE_MG014 ; TEST FOR MODE
|
|
JR Z,IMM_INIT3 ; IF SO, DISPLAY IT
|
|
LD DE,IMM_STR_MODE_UNK ; MODE LABEL
|
|
IMM_INIT3:
|
|
CALL WRITESTR ; DISPLAY MODE
|
|
;
|
|
; CHECK FOR HARDWARE PRESENCE
|
|
CALL IMM_DETECT ; PROBE FOR INTERFACE
|
|
JR Z,IMM_INIT4 ; IF FOUND, CONTINUE
|
|
CALL PC_SPACE ; FORMATTING
|
|
LD DE,IMM_STR_NOHW ; NO IMM MESSAGE
|
|
CALL WRITESTR ; DISPLAY IT
|
|
JR IMM_INIT6 ; SKIP CFG ENTRY
|
|
;
|
|
IMM_INIT4:
|
|
; UPDATE DRIVER RELATIVE UNIT NUMBER IN CONFIG TABLE
|
|
LD A,(IMM_DEVNUM) ; GET NEXT UNIT NUM TO ASSIGN
|
|
LD (IY+IMM_DEV),A ; UPDATE IT
|
|
INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN
|
|
LD (IMM_DEVNUM),A ; SAVE IT
|
|
;
|
|
; ADD UNIT TO GLOBAL DISK UNIT TABLE
|
|
LD BC,IMM_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 IMM_RESET ; RESET/INIT THE INTERFACE
|
|
;
|
|
; START PRINTING DEVICE INFO
|
|
CALL IMM_PRTPREFIX ; PRINT DEVICE PREFIX
|
|
;
|
|
; CHECK FOR BAD STATUS
|
|
LD A,(IY+IMM_STAT) ; GET STATUS
|
|
OR A ; SET FLAGS
|
|
JP Z,IMM_INIT5 ; CONTINUE
|
|
CALL PC_SPACE ; FORMATTING
|
|
CALL IMM_PRTSTATSTR ; PRINT STATUS STRING
|
|
JR IMM_INIT6 ; LOOP TILL DONE
|
|
;
|
|
IMM_INIT5:
|
|
; PRINT STORAGE CAPACITY (BLOCK COUNT)
|
|
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
|
LD A,IMM_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
|
|
;
|
|
IMM_INIT6:
|
|
LD DE,IMM_CFGSIZ ; SIZE OF CFG TABLE ENTRY
|
|
ADD IY,DE ; BUMP POINTER
|
|
JP IMM_INIT1 ; AND LOOP
|
|
;
|
|
;----------------------------------------------------------------------
|
|
; PROBE FOR IMM HARDWARE
|
|
;----------------------------------------------------------------------
|
|
;
|
|
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
|
|
;
|
|
IMM_DETECT:
|
|
; INITIALIZE 8255
|
|
LD A,(IY+IMM_IOBASE) ; BASE PORT
|
|
ADD A,IMM_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_DISCONNECT
|
|
CALL IMM_CONNECT
|
|
CALL IMM_DISCONNECT
|
|
;
|
|
; EXPECTING S1=$B8, S2=$18, S3=$38
|
|
LD A,(IMM_S1)
|
|
CP $B8
|
|
RET NZ
|
|
LD A,(IMM_S2)
|
|
CP $18
|
|
RET NZ
|
|
LD A,(IMM_S3)
|
|
CP $38
|
|
RET NZ
|
|
;
|
|
XOR A
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; DRIVER FUNCTION TABLE
|
|
;=============================================================================
|
|
;
|
|
IMM_FNTBL:
|
|
.DW IMM_STATUS
|
|
.DW IMM_RESET
|
|
.DW IMM_SEEK
|
|
.DW IMM_READ
|
|
.DW IMM_WRITE
|
|
.DW IMM_VERIFY
|
|
.DW IMM_FORMAT
|
|
.DW IMM_DEVICE
|
|
.DW IMM_MEDIA
|
|
.DW IMM_DEFMED
|
|
.DW IMM_CAP
|
|
.DW IMM_GEOM
|
|
#IF (($ - IMM_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID IMM FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
IMM_VERIFY:
|
|
IMM_FORMAT:
|
|
IMM_DEFMED:
|
|
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_READ:
|
|
CALL HB_DSKREAD
|
|
LD A,SCSI_CMD_READ
|
|
LD (IMM_CMD_RW),A
|
|
JP IMM_IO
|
|
;
|
|
;
|
|
;
|
|
IMM_WRITE:
|
|
CALL HB_DSKREAD
|
|
LD A,SCSI_CMD_WRITE
|
|
LD (IMM_CMD_RW),A
|
|
JP IMM_IO
|
|
;
|
|
;
|
|
;
|
|
IMM_IO:
|
|
LD (IMM_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
CALL IMM_CHKERR ; CHECK FOR ERR STATUS AND RESET IF SO
|
|
JR NZ,IMM_IO3 ; BAIL OUT ON ERROR
|
|
;
|
|
; SETUP LBA
|
|
; 3 BYTES, LITTLE ENDIAN -> BIG ENDIAN
|
|
LD HL,IMM_CMD_RW+1 ; START OF LBA FIELD IN CDB (MSB)
|
|
LD A,(IY+IMM_LBA+2) ; THIRD BYTE OF LBA FIELD IN CFG (MSB)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IY+IMM_LBA+1)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(IY+IMM_LBA+0)
|
|
LD (HL),A
|
|
INC HL
|
|
;
|
|
; DO SCSI IO
|
|
LD DE,(IMM_DSKBUF)
|
|
LD BC,512
|
|
LD HL,IMM_CMD_RW
|
|
CALL IMM_RUNCMD
|
|
CALL Z,IMM_CHKCMD
|
|
JR NZ,IMM_IO2 ; IF ERROR, SKIP INCREMENT
|
|
; INCREMENT LBA
|
|
LD A,IMM_LBA ; LBA OFFSET
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL INC32HL ; INCREMENT THE VALUE
|
|
; INCREMENT DMA
|
|
LD HL,IDE_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
XOR A ; SIGNAL SUCCESS
|
|
;
|
|
IMM_IO2:
|
|
IMM_IO3:
|
|
LD HL,(IMM_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
|
|
;
|
|
;
|
|
;
|
|
IMM_STATUS:
|
|
; RETURN UNIT STATUS
|
|
LD A,(IY+IMM_STAT) ; GET STATUS OF SELECTED DEVICE
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
IMM_RESET:
|
|
JP IMM_INITDEV
|
|
;
|
|
;
|
|
;
|
|
IMM_DEVICE:
|
|
LD D,DIODEV_IMM ; D := DEVICE TYPE
|
|
LD E,(IY+IMM_DEV) ; E := PHYSICAL DEVICE NUMBER
|
|
LD C,%01000000 ; C := REMOVABLE HARD DISK
|
|
LD H,(IY+IMM_MODE) ; H := MODE
|
|
LD L,(IY+IMM_IOBASE) ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; IMM_GETMED
|
|
;
|
|
IMM_MEDIA:
|
|
LD A,E ; GET FLAGS
|
|
OR A ; SET FLAGS
|
|
JR Z,IMM_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA
|
|
;
|
|
CALL IMM_RESET ; RESET IMM INTERFACE
|
|
;
|
|
IMM_MEDIA1:
|
|
LD A,(IY+IMM_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
|
|
;
|
|
;
|
|
;
|
|
IMM_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+IMM_LBA+0),L ; SAVE NEW LBA
|
|
LD (IY+IMM_LBA+1),H ; ...
|
|
LD (IY+IMM_LBA+2),E ; ...
|
|
LD (IY+IMM_LBA+3),D ; ...
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
IMM_CAP:
|
|
LD A,(IY+IMM_STAT) ; GET STATUS
|
|
PUSH AF ; SAVE IT
|
|
LD A,IMM_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
|
|
;
|
|
;
|
|
;
|
|
IMM_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 IMM_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 IMM_CAP STATUS
|
|
;
|
|
;=============================================================================
|
|
; FUNCTION SUPPORT ROUTINES
|
|
;=============================================================================
|
|
;
|
|
IMM_WRITEDATA:
|
|
LD C,(IY+IMM_IOBASE)
|
|
OUT (C),A
|
|
CALL DELAY
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_WRITECTRL:
|
|
XOR $0B
|
|
LD C,(IY+IMM_IOBASE)
|
|
INC C
|
|
INC C
|
|
OUT (C),A
|
|
CALL DELAY
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_READSTATUS:
|
|
LD C,(IY+IMM_IOBASE)
|
|
INC C
|
|
IN A,(C)
|
|
LD C,0 ; INIT RESULT
|
|
;
|
|
BIT 0,A ; ACK = $01
|
|
JR Z,IMM_READSTATUS1
|
|
SET 6,C ; $40
|
|
;
|
|
IMM_READSTATUS1:
|
|
;
|
|
BIT 1,A ; BUSY = $02
|
|
JR NZ,IMM_READSTATUS2
|
|
SET 7,C ; $80
|
|
;
|
|
IMM_READSTATUS2:
|
|
;
|
|
BIT 2,A ; PAPER = $04
|
|
JR Z,IMM_READSTATUS3
|
|
SET 5,C ; $20
|
|
;
|
|
IMM_READSTATUS3:
|
|
;
|
|
BIT 3,A ; SELECT = $08
|
|
JR Z,IMM_READSTATUS4
|
|
SET 4,C ; $10
|
|
;
|
|
IMM_READSTATUS4:
|
|
;
|
|
BIT 4,A ; FAULT = $10
|
|
JR Z,IMM_READSTATUS5
|
|
SET 3,C ; $08
|
|
;
|
|
IMM_READSTATUS5:
|
|
LD A,C
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_CPP:
|
|
PUSH AF
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$AA
|
|
CALL IMM_WRITEDATA
|
|
LD A,$55
|
|
CALL IMM_WRITEDATA
|
|
LD A,$00
|
|
CALL IMM_WRITEDATA
|
|
LD A,$FF
|
|
CALL IMM_WRITEDATA
|
|
CALL IMM_READSTATUS
|
|
AND $B8
|
|
LD (IMM_S1),A
|
|
LD A,$87
|
|
CALL IMM_WRITEDATA
|
|
CALL IMM_READSTATUS
|
|
AND $B8
|
|
LD (IMM_S2),A
|
|
LD A,$78
|
|
CALL IMM_WRITEDATA
|
|
CALL IMM_READSTATUS
|
|
AND $38
|
|
LD (IMM_S3),A
|
|
POP AF
|
|
CALL IMM_WRITEDATA
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0D
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$FF
|
|
CALL IMM_WRITEDATA
|
|
;
|
|
; CONNECT: S1=$B8 S2=$18 S3=$30
|
|
; DISCONNECT: S1=$B8 S2=$18 S3=$38
|
|
;
|
|
#IF (IMMTRACE >= 2)
|
|
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
|
|
#ENDIF
|
|
;
|
|
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:
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,$40
|
|
CALL IMM_WRITEDATA
|
|
CALL DELAY ; 16 US, IDEALLY, 1 US
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0D
|
|
CALL IMM_WRITECTRL
|
|
CALL DELAY ; 48 US, IDEALLY, 50 US
|
|
CALL DELAY
|
|
CALL DELAY
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_SELECT:
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nSELECT: $")
|
|
#ENDIF
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
LD HL,500 ; TIMEOUT COUNTER
|
|
;
|
|
IMM_SELECT1:
|
|
CALL IMM_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 IMM_WRITECTRL
|
|
LD A,$80 | (1 << IMM_TGT)
|
|
CALL IMM_WRITEDATA
|
|
CALL DELAY
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL IMM_READSTATUS
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
LD A,$0D
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL IMM_READSTATUS
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
LD HL,500 ; TIMEOUT COUNTER
|
|
;
|
|
IMM_SELECT3:
|
|
CALL IMM_READSTATUS
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
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 IMM_WRITECTRL
|
|
;
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_SENDCMD:
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nSENDCMD:$")
|
|
#ENDIF
|
|
;
|
|
LD HL,0
|
|
IMM_SENDCMD1:
|
|
PUSH HL
|
|
CALL IMM_WAITDONE
|
|
POP HL
|
|
CP $A8
|
|
JR NZ,IMM_SENDCMD2
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,(DE)
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
INC HL
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
LD A,(DE)
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
INC HL
|
|
LD A,$00
|
|
CALL IMM_WRITECTRL
|
|
JR IMM_SENDCMD1
|
|
;
|
|
IMM_SENDCMD2:
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_WAITBUSY:
|
|
LD HL,500 ; NORMAL TIMEOUT COUNTER
|
|
;
|
|
IMM_WAITBUSY_HL: ; VARIABLE TIMEOUT ENTRY
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
IMM_WAITBUSY2:
|
|
CALL IMM_READSTATUS
|
|
BIT 7,A
|
|
RET NZ ; IF SET, MOVE ON
|
|
DEC HL
|
|
LD A,H
|
|
OR L
|
|
; TODO: IMPLEMENT TIMEOUT!!!
|
|
;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 IMM_WRITECTRL
|
|
POP AF
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_NEGOTIATE:
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nNEGO: $")
|
|
#ENDIF
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
CALL DELAY ; 16 US, IDEALLY 5 US
|
|
LD A,$00
|
|
CALL IMM_WRITEDATA
|
|
LD DE,7 ; 112 US, IDEALLY 100 US
|
|
CALL VDELAY
|
|
LD A,$06
|
|
CALL IMM_WRITECTRL
|
|
CALL DELAY ; 16 US, IDEALLY 5 US
|
|
CALL IMM_READSTATUS
|
|
PUSH AF ; SAVE RESULT
|
|
CALL DELAY ; 16 US, IDEALLY 5 US
|
|
LD A,$07
|
|
CALL IMM_WRITECTRL
|
|
CALL DELAY ; 16 US, IDEALLY 5 US
|
|
LD A,$06
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
POP AF
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
AND $20
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PC_GT
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CP $20
|
|
JP NZ,IMM_CMD_IOERR
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_GETBYTE:
|
|
CALL IMM_WAITBUSY
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,$06
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
PUSH AF
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
POP HL
|
|
OR H
|
|
PUSH AF
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
POP AF
|
|
RET
|
|
;
|
|
; DE=BUFFER
|
|
; HL=LENGTH (0 FOR VARIABLE)
|
|
;
|
|
IMM_GETDATA:
|
|
LD A,H
|
|
OR L
|
|
JR NZ,IMM_GETDATALEN
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nGETDATA:$")
|
|
#ENDIF
|
|
;
|
|
IMM_GETDATA1:
|
|
PUSH HL
|
|
CALL IMM_WAITDONE
|
|
POP HL
|
|
CP $98
|
|
JR NZ,IMM_GETDATA2
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,$06
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
PUSH AF
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
POP BC
|
|
OR B
|
|
LD (DE),A
|
|
INC DE
|
|
INC HL
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
JR IMM_GETDATA1
|
|
;
|
|
IMM_GETDATA2:
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
IMM_GETDATALEN:
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nGETDLEN:$")
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
IMM_GETDATALEN1:
|
|
LD A,$06
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
PUSH AF
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
CALL IMM_READSTATUS
|
|
AND $F0
|
|
POP BC
|
|
OR B
|
|
LD (DE),A
|
|
INC DE
|
|
DEC HL
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,H
|
|
OR L
|
|
JR NZ,IMM_GETDATALEN1
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
RET
|
|
;
|
|
; DE=BUFFER
|
|
; HL=LENGTH (0 FOR VARIABLE)
|
|
;
|
|
IMM_PUTDATA:
|
|
LD A,H
|
|
OR L
|
|
JR NZ,IMM_PUTDATALEN
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nPUTDATA:$")
|
|
#ENDIF
|
|
;
|
|
IMM_PUTDATA1:
|
|
PUSH HL
|
|
CALL IMM_WAITDONE
|
|
POP HL
|
|
CP $88
|
|
JR NZ,IMM_PUTDATA2
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,(DE)
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
INC HL
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
LD A,(DE)
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
INC HL
|
|
LD A,$00
|
|
CALL IMM_WRITECTRL
|
|
JR IMM_PUTDATA1
|
|
;
|
|
IMM_PUTDATA2:
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
IMM_PUTDATALEN:
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nPUTDLEN:$")
|
|
CALL PC_SPACE
|
|
CALL PRTHEXWORDHL
|
|
PRTS(" BYTES$")
|
|
#ENDIF
|
|
;
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
IMM_PUTDATALEN1:
|
|
LD A,(DE)
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
DEC HL
|
|
LD A,$05
|
|
CALL IMM_WRITECTRL
|
|
LD A,(DE)
|
|
CALL IMM_WRITEDATA
|
|
INC DE
|
|
DEC HL
|
|
LD A,$00
|
|
CALL IMM_WRITECTRL
|
|
LD A,H
|
|
OR L
|
|
JR NZ,IMM_PUTDATALEN1
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_GETSTATUS:
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nSTATUS:$")
|
|
#ENDIF
|
|
;
|
|
CALL IMM_GETBYTE
|
|
LD (IMM_CMDSTAT),A
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CALL IMM_WAITDONE
|
|
CP $B8
|
|
RET NZ
|
|
CALL IMM_GETBYTE
|
|
LD (IMM_CMDSTAT+1),A
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_ENDREAD:
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0C
|
|
CALL IMM_WRITECTRL
|
|
LD A,$0E
|
|
CALL IMM_WRITECTRL
|
|
LD A,$04
|
|
CALL IMM_WRITECTRL
|
|
RET
|
|
;
|
|
; HL: COMMAND BUFFER
|
|
; DE: TRANSFER BUFFER
|
|
; BC: TRANSFER LENGTH (0=VARIABLE)
|
|
;
|
|
IMM_RUNCMD:
|
|
LD (IMM_CMDSTK),SP ; FOR ERROR ABORTS
|
|
LD (IMM_DSKBUF),DE ; SAVE BUF PTR
|
|
LD (IMM_XFRLEN),BC ; SAVE XFER LEN
|
|
PUSH HL
|
|
CALL IMM_CONNECT
|
|
CALL IMM_SELECT
|
|
CALL IMM_WAITBUSY
|
|
POP DE
|
|
CALL IMM_SENDCMD
|
|
;
|
|
IMM_RUNCMD_PHASE:
|
|
LD HL,50000 ; LONG TIMEOUT HERE
|
|
CALL IMM_WAITDONE_HL
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
PRTS("\r\nPHASE: $")
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
CP $88 ; DEVICE WANTS TO RCV DATA
|
|
JR Z,IMM_RUNCMD_WRITE
|
|
CP $98 ; DEVICE WANTS TO SEND DATA
|
|
JR Z,IMM_RUNCMD_READ
|
|
CP $B8 ; DEVICE WANTS TO BE DONE
|
|
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_PHASE
|
|
;
|
|
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_PHASE
|
|
;
|
|
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,IMM_STIOERR
|
|
JR IMM_CMD_ERR
|
|
;
|
|
IMM_CMD_TIMEOUT:
|
|
LD A,IMM_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???
|
|
LD DE,62
|
|
CALL VDELAY
|
|
CALL IMM_DISCONNECT
|
|
LD DE,62
|
|
CALL VDELAY
|
|
POP AF ; RECOVER STATUS
|
|
JP IMM_ERR ; ERROR EXIT
|
|
;
|
|
;
|
|
;
|
|
IMM_CHKCMD:
|
|
; SCSI COMMAND COMPLETED, CHECK SCSI CMD STATUS
|
|
LD A,(IMM_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,IMM_CHKCMD1 ; IF SO, REQUEST SENSE
|
|
JP IMM_IOERR ; ELSE, GENERAL I/O ERROR
|
|
;
|
|
IMM_CHKCMD1:
|
|
; USE REQUEST SENSE CMD TO GET ERROR DETAILS
|
|
LD DE,HB_WRKBUF ; PUT DATA IN WORK BUF
|
|
LD BC,0 ; VARIABLE LENGTH REQUEST
|
|
LD HL,IMM_CMD_SENSE ; REQUEST SENSE CMD
|
|
CALL IMM_RUNCMD ; DO IT
|
|
JP NZ,IMM_IOERR ; BAIL IF ERROR IN CMD
|
|
;
|
|
; REQ SENSE CMD COMPLETED
|
|
#IF IMMTRACE >= 2)
|
|
LD A,16
|
|
LD DE,HB_WRKBUF
|
|
CALL Z,PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; CHECK SCSI CMD STATUS
|
|
LD A,(IMM_CMDSTAT) ; GET STATUS BYTE
|
|
OR A ; SET FLAGS
|
|
JP NZ,IMM_IOERR ; IF FAILED, GENERAL I/O ERROR
|
|
;
|
|
; RETURN RESULT BASED ON REQ SENSE DATA
|
|
LD A,(HB_WRKBUF+12) ; GET ADDITIONAL SENSE CODE
|
|
CP $3A ; NO MEDIA?
|
|
JP Z,IMM_NOMEDIA ; IF SO, RETURN NO MEDIA ERR
|
|
JP IMM_IOERR ; ELSE GENERAL I/O ERR
|
|
;
|
|
; CHECK CURRENT DEVICE FOR ERROR STATUS AND ATTEMPT TO RECOVER
|
|
; VIA RESET IF DEVICE IS IN ERROR.
|
|
;
|
|
IMM_CHKERR:
|
|
LD A,(IY+IMM_STAT) ; GET STATUS
|
|
OR A ; SET FLAGS
|
|
CALL NZ,IMM_RESET ; IF ERROR STATUS, RESET BUS
|
|
RET
|
|
;
|
|
; (RE)INITIALIZE DEVICE
|
|
;
|
|
IMM_INITDEV:
|
|
; INITIALIZE 8255
|
|
LD A,(IY+IMM_IOBASE) ; BASE PORT
|
|
ADD A,IMM_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_DISCONNECT
|
|
CALL IMM_CONNECT
|
|
CALL IMM_RESETPULSE
|
|
LD DE,62
|
|
CALL VDELAY
|
|
CALL IMM_DISCONNECT
|
|
LD DE,62
|
|
CALL VDELAY
|
|
;
|
|
LD B,4
|
|
IMM_INITDEV1:
|
|
PUSH BC
|
|
;
|
|
; REQUEST SENSE COMMAND
|
|
LD DE,HB_WRKBUF
|
|
LD BC,0
|
|
LD HL,IMM_CMD_SENSE
|
|
CALL IMM_RUNCMD
|
|
JR NZ,IMM_INITDEV2 ; CMD PROC ERROR
|
|
;
|
|
; CHECK CMD STATUS
|
|
LD A,(IMM_CMDSTAT) ; GET STATUS BYTE
|
|
OR A ; SET FLAGS
|
|
JR NZ,IMM_INITDEV2 ; BAD CMD STATUS
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
LD A,16
|
|
LD DE,HB_WRKBUF
|
|
CALL PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; CHECK SENSE KEY
|
|
LD A,(HB_WRKBUF + 2)
|
|
OR A
|
|
;
|
|
IMM_INITDEV2:
|
|
POP BC
|
|
JR Z,IMM_INITDEV3 ; IF NO ERROR, MOVE ON
|
|
DJNZ IMM_INITDEV1 ; TRY UNTIL COUNTER EXHAUSTED
|
|
JP IMM_IOERR ; HANDLE ERROR
|
|
;
|
|
IMM_INITDEV3:
|
|
; READ & RECORD DEVICE CAPACITY
|
|
LD DE,HB_WRKBUF
|
|
LD BC,0
|
|
LD HL,IMM_CMD_RDCAP
|
|
CALL IMM_RUNCMD
|
|
CALL Z,IMM_CHKCMD
|
|
RET NZ ; MEDIA PROBLEM
|
|
;
|
|
#IF IMMTRACE >= 2)
|
|
LD A,8
|
|
LD DE,HB_WRKBUF
|
|
CALL PRTHEXBUF
|
|
#ENDIF
|
|
;
|
|
; INCREMENT, BIG->LITTLE ENDIAN, SAVE
|
|
LD A,IMM_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+IMM_STAT),A ; RECORD IT
|
|
RET
|
|
;;;;
|
|
;;;; *** DEBUG ***
|
|
;;;;
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; LD BC,512
|
|
;;; LD HL,IMM_CMD_READ
|
|
;;; CALL IMM_RUNCMD
|
|
;;; CALL Z,IMM_CHKCMD
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; CALL Z,DUMP_BUFFER
|
|
;;;;
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; LD BC,512
|
|
;;; LD HL,IMM_CMD_READ
|
|
;;; CALL IMM_RUNCMD
|
|
;;; CALL Z,IMM_CHKCMD
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; CALL Z,DUMP_BUFFER
|
|
;;;;
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; LD BC,0
|
|
;;; LD HL,IMM_CMD_INQ
|
|
;;; CALL IMM_RUNCMD
|
|
;;; CALL Z,IMM_CHKCMD
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; CALL Z,DUMP_BUFFER
|
|
;;;;
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; LD BC,512
|
|
;;; LD HL,IMM_CMD_WRITE
|
|
;;; CALL IMM_RUNCMD
|
|
;;; CALL Z,IMM_CHKCMD
|
|
;;;;
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; LD BC,512
|
|
;;; LD HL,IMM_CMD_READ2
|
|
;;; CALL IMM_RUNCMD
|
|
;;; CALL Z,IMM_CHKCMD
|
|
;;; LD DE,HB_WRKBUF
|
|
;;; CALL Z,DUMP_BUFFER
|
|
;;;;
|
|
;;; RET
|
|
;;;;
|
|
;;;IMM_CMD .DB $00, $00, $00, $00, $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_WRITE .DB $0A, $00, $F0, $00, $01, $00 ; READ SECTOR $F000
|
|
;;;IMM_CMD_READ2 .DB $08, $00, $F0, $00, $01, $00 ; READ SECTOR $F000
|
|
;
|
|
;=============================================================================
|
|
; ERROR HANDLING AND DIAGNOSTICS
|
|
;=============================================================================
|
|
;
|
|
; ERROR HANDLERS
|
|
;
|
|
IMM_INVUNIT:
|
|
LD A,IMM_STINVUNIT
|
|
JR IMM_ERR2 ; SPECIAL CASE FOR INVALID UNIT
|
|
;
|
|
IMM_NOMEDIA:
|
|
LD A,IMM_STNOMEDIA
|
|
JR IMM_ERR
|
|
;
|
|
IMM_CMDERR:
|
|
LD A,IMM_STCMDERR
|
|
JR IMM_ERR
|
|
;
|
|
IMM_IOERR:
|
|
LD A,IMM_STIOERR
|
|
JR IMM_ERR
|
|
;
|
|
IMM_TO:
|
|
LD A,IMM_STTO
|
|
JR IMM_ERR
|
|
;
|
|
IMM_NOTSUP:
|
|
LD A,IMM_STNOTSUP
|
|
JR IMM_ERR
|
|
;
|
|
IMM_ERR:
|
|
LD (IY+IMM_STAT),A ; SAVE NEW STATUS
|
|
;
|
|
IMM_ERR2:
|
|
#IF (IMMTRACE >= 2)
|
|
CALL IMM_PRTSTAT
|
|
#ENDIF
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
IMM_PRTERR:
|
|
RET Z ; DONE IF NO ERRORS
|
|
; FALL THRU TO IMM_PRTSTAT
|
|
;
|
|
; PRINT FULL DEVICE STATUS LINE
|
|
;
|
|
IMM_PRTSTAT:
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(IY+IMM_STAT)
|
|
CP IMM_STINVUNIT
|
|
JR Z,IMM_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE
|
|
CALL IMM_PRTPREFIX ; PRINT UNIT PREFIX
|
|
JR IMM_PRTSTAT3
|
|
IMM_PRTSTAT2:
|
|
CALL NEWLINE
|
|
PRTS("IMM:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT
|
|
IMM_PRTSTAT3:
|
|
CALL PC_SPACE ; FORMATTING
|
|
CALL IMM_PRTSTATSTR
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT STATUS STRING
|
|
;
|
|
IMM_PRTSTATSTR:
|
|
PUSH AF
|
|
PUSH DE
|
|
LD A,(IY+IMM_STAT)
|
|
OR A
|
|
LD DE,IMM_STR_STOK
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STINVUNIT
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STNOMEDIA
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STCMDERR
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STIOERR
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STTO
|
|
JR Z,IMM_PRTSTATSTR1
|
|
INC A
|
|
LD DE,IMM_STR_STNOTSUP
|
|
JR Z,IMM_PRTSTATSTR1
|
|
LD DE,IMM_STR_STUNK
|
|
IMM_PRTSTATSTR1:
|
|
CALL WRITESTR
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT DIAGNONSTIC PREFIX
|
|
;
|
|
IMM_PRTPREFIX:
|
|
PUSH AF
|
|
CALL NEWLINE
|
|
PRTS("IMM$")
|
|
LD A,(IY+IMM_DEV) ; GET CURRENT DEVICE NUM
|
|
CP $FE ; NOT YET ASSIGNED?
|
|
JR Z,IMM_PRTPREFIX1 ; SKIP DEV NUM IF SO
|
|
CALL PRTDECB
|
|
IMM_PRTPREFIX1:
|
|
CALL PC_COLON
|
|
POP AF
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; STRING DATA
|
|
;=============================================================================
|
|
;
|
|
IMM_STR_STOK .TEXT "OK$"
|
|
IMM_STR_STINVUNIT .TEXT "INVALID UNIT$"
|
|
IMM_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
|
IMM_STR_STCMDERR .TEXT "COMMAND ERROR$"
|
|
IMM_STR_STIOERR .TEXT "IO ERROR$"
|
|
IMM_STR_STTO .TEXT "TIMEOUT$"
|
|
IMM_STR_STNOTSUP .TEXT "NOT SUPPORTED$"
|
|
IMM_STR_STUNK .TEXT "UNKNOWN ERROR$"
|
|
;
|
|
IMM_STR_NOHW .TEXT "NOT PRESENT$"
|
|
;
|
|
IMM_STR_MODE_NONE .TEXT "NONE$"
|
|
IMM_STR_MODE_MG014 .TEXT "MG014$"
|
|
IMM_STR_MODE_UNK .TEXT "???$"
|
|
;
|
|
;=============================================================================
|
|
; DATA STORAGE
|
|
;=============================================================================
|
|
;
|
|
IMM_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_CMDSTAT .DB 0, 0 ; CMD RESULT STATUS
|
|
;
|
|
IMM_TYPE_MAP:
|
|
.DW IMM_STR_NONE
|
|
.DW IMM_STR_MG014
|
|
;
|
|
IMM_STR_NONE .DB "<NOT PRESENT>$"
|
|
IMM_STR_MG014 .DB "MG014$"
|
|
;
|
|
; SCSI COMMAND TEMPLATES
|
|
;
|
|
IMM_CMD_RW .DB $00, $00, $00, $00, $01, $00 ; READ/WRITE SECTOR
|
|
IMM_CMD_SENSE .DB $03, $00, $00, $00, $FF, $00 ; REQUEST SENSE DATA
|
|
IMM_CMD_RDCAP .DB $25, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; READ CAPACITY
|
|
;
|
|
; IMM DEVICE CONFIGURATION TABLE
|
|
;
|
|
IMM_CFG:
|
|
;
|
|
#IF (IMMCNT >= 1)
|
|
;
|
|
IMM0_CFG: ; DEVICE 0
|
|
.DB 0 ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB IMM0MODE ; DRIVER DEVICE MODE
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB IMM0BASE ; IO BASE ADDRESS
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
#ENDIF
|
|
;
|
|
#IF (IMMCNT >= 2)
|
|
;
|
|
IMM1_CFG: ; DEVICE 1
|
|
.DB 0 ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB IMM1MODE ; DRIVER DEVICE MODE
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB IMM1BASE ; IO BASE ADDRESS
|
|
.DW 0,0 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
#ENDIF
|
|
;
|
|
#IF ($ - IMM_CFG) != (IMMCNT * IMM_CFGSIZ)
|
|
.ECHO "*** INVALID IMM CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END MARKER
|
|
|