mirror of https://github.com/wwarthen/RomWBW.git
Browse Source
Thanks and credit to Jay Cotton for providing the SCSI transport code upon which this driver is based.pull/639/head v3.6.0-dev.44
48 changed files with 922 additions and 12 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,808 @@ |
|||
; |
|||
;============================================================================= |
|||
; SCSI DISK DRIVER FOR 5380 |
|||
;============================================================================= |
|||
; |
|||
; DISK DEVICE DRIVER FOR THE 5380 SCSI CHIP. |
|||
; DERIVED FROM CODE PROVIDED BY JAY COTTON. |
|||
; |
|||
; TODO: |
|||
; - IMPLEMENT INQUIRY COMMAND AND DISPLAY DATA AT INIT |
|||
; - IMPLEMENT CAPACITY COMMAND |
|||
; - DO SOMETHING IN INITDEV TO CONFIRM LUN EXISTS |
|||
; |
|||
; NOTES: |
|||
; - CAPACITY IS CURRENTLY HARD-CODED TO 200000 BLOCKS (1GB OF DATA) |
|||
; |
|||
SCSIBASE .EQU $40 |
|||
; |
|||
; SCSI DEVICE STATUS CODES |
|||
; |
|||
SCSI_STOK .EQU 0 |
|||
SCSI_STNOMEDIA .EQU -1 |
|||
SCSI_STIOERR .EQU -2 |
|||
SCSI_STTO .EQU -3 |
|||
SCSI_STNOTRDY .EQU -4 |
|||
; |
|||
; NCR 5380 I/O REGISTERS |
|||
; |
|||
SCSI_SR_CSD .EQU SCSIBASE ; CURRENT SCSI DATA |
|||
SCSI_SR_ICR .EQU SCSIBASE + $01 ; INITIATOR COMMAND |
|||
SCSI_SR_MR .EQU SCSIBASE + $02 ; MODE |
|||
SCSI_SR_TCR .EQU SCSIBASE + $03 ; TARGET COMMAND |
|||
SCSI_SR_CSBS .EQU SCSIBASE + $04 ; CURRENT SCSI BUS STAT. |
|||
SCSI_SR_BSR .EQU SCSIBASE + $05 ; BUS STATUS |
|||
SCSI_SR_IDR .EQU SCSIBASE + $06 ; INITIATOR DMA RECV. |
|||
SCSI_SR_RPI .EQU SCSIBASE + $07 ; RESET PARITY/IRQ |
|||
; |
|||
; NCR 5380 OUTPUT ONLY REGISTERS |
|||
; |
|||
SCSI_SR_ODR .EQU SCSIBASE ; OUTPUT DATA |
|||
SCSI_SR_SER .EQU SCSIBASE + $04 ; SELECT ENABLE |
|||
SCSI_SR_SDS .EQU SCSIBASE + $05 ; START DMA SEND |
|||
SCSI_SR_SDTR .EQU SCSIBASE + $06 ; START TARGET DMA RECV. |
|||
SCSI_SR_SDIR .EQU SCSIBASE + $07 ; START INITIATOR DMA RECV. |
|||
; |
|||
; SCSI CURRENT BUS STATUS BIT MASKS |
|||
; |
|||
SCSI_SM_RST .EQU $80 ; RESET |
|||
SCSI_SM_BSY .EQU $40 ; BUSY |
|||
SCSI_SM_REQ .EQU $20 ; REQUEST |
|||
SCSI_SM_MSG .EQU $10 ; MESSAGE |
|||
SCSI_SM_CD .EQU $08 ; CMD/DATA |
|||
SCSI_SM_IO .EQU $04 ; IN/OUT |
|||
SCSI_SM_SEL .EQU $02 ; SELECT |
|||
SCSI_SM_DBP .EQU $01 ; PARITY BIT |
|||
; |
|||
SCSI_SM_PHM .EQU $08 ; PHASE MATCH BIT |
|||
; |
|||
; SDCI DEVICE CONFIGURATION |
|||
; |
|||
; PER DEVICE DATA OFFSETS IN CFG BLOCK |
|||
; |
|||
SCSI_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE) |
|||
SCSI_IOBASE .EQU 1 ; IO BASE ADDRESS (BYTE) |
|||
SCSI_LUN .EQU 2 ; TARGET LUN |
|||
SCSI_STAT .EQU 3 ; LAST STATUS (BYTE) |
|||
SCSI_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD) |
|||
SCSI_LBA .EQU 8 ; OFFSET OF LBA (DWORD) |
|||
; |
|||
SCSI_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES |
|||
; |
|||
SCSI_CFGTBL: |
|||
; |
|||
#IF (SCSICNT >= 1) |
|||
; |
|||
SCSI0_CFG: |
|||
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY) |
|||
.DB SCSIBASE ; IO BASE ADDRESS |
|||
.DB SCSI0_LUN ; SCSI TARGET LUN |
|||
.DB SCSI_STNOTRDY ; DEVICE STATUS |
|||
.DW $0000,$0020 ; DEVICE CAPACITY (BLOCKS) |
|||
.DW 0,0 ; CURRENT LBA |
|||
; |
|||
DEVECHO "SCSI: IO=" |
|||
DEVECHO SCSIBASE |
|||
DEVECHO ", LUN=" |
|||
DEVECHO SCSI0_LUN |
|||
DEVECHO "\n" |
|||
#ENDIF |
|||
; |
|||
#IF (SCSICNT >= 2) |
|||
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY) |
|||
.DB SCSIBASE ; IO BASE ADDRESS |
|||
.DB SCSI1_LUN ; SCSI TARGET LUN |
|||
.DB SCSI_STNOTRDY ; DEVICE STATUS |
|||
.DW $0000,$0020 ; DEVICE CAPACITY (BLOCKS) |
|||
.DW 0,0 ; CURRENT LBA |
|||
; |
|||
DEVECHO "SCSI: IO=" |
|||
DEVECHO SCSIBASE |
|||
DEVECHO ", LUN=" |
|||
DEVECHO SCSI1_LUN |
|||
DEVECHO "\n" |
|||
#ENDIF |
|||
; |
|||
#IF ($ - SCSI_CFGTBL) != (SCSICNT * 2 * SCSI_CFGSIZ) |
|||
.ECHO "*** INVALID SCSI CONFIG TABLE ***\n" |
|||
#ENDIF |
|||
; |
|||
.DB $FF ; END OF TABLE MARKER |
|||
; |
|||
;============================================================================= |
|||
; INITIALIZATION ENTRY POINT |
|||
;============================================================================= |
|||
; |
|||
SCSI_INIT: |
|||
CALL NEWLINE ; FORMATTING |
|||
PRTS("SCSI:$") ; TAG |
|||
; |
|||
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS |
|||
LD A,SCSIBASE ; GET IO BASE ADDRES |
|||
CALL PRTHEXBYTE ; DISPLAY IT |
|||
; |
|||
CALL SCSI_DETECT ; DETECT THE SCSI INTERFACE |
|||
JR Z,SCSI_INIT1 ; IF FOUND CONTINUE |
|||
PRTS(" NOT PRESENT$") ; SHOW NOT PRESENT |
|||
XOR A ; SUCCESS |
|||
RET ; AND BAIL OUT |
|||
; |
|||
SCSI_INIT1: |
|||
XOR A ; ZERO ACCUM |
|||
LD (SCSI_DEVNUM),A ; INIT DEV UNIT NUM FOR DYNAMIC ASSIGNMENT |
|||
LD IY,SCSI_CFGTBL ; POINT TO START OF CONFIG TABLE |
|||
; |
|||
SCSI_INIT2: |
|||
LD A,(IY) ; LOAD FIRST BYTE TO CHECK FOR END |
|||
CP $FF ; CHECK FOR END OF TABLE VALUE |
|||
RET Z ; RETURN IF DONE |
|||
; |
|||
CALL SCSI_INIT3 ; REGISTER & INIT DEVICE |
|||
; |
|||
LD DE,SCSI_CFGSIZ ; SIZE OF CFG TABLE ENTRY |
|||
ADD IY,DE ; BUMP POINTER |
|||
JP SCSI_INIT2 ; AND LOOP |
|||
; |
|||
SCSI_INIT3: |
|||
; UPDATE DRIVER RELATIVE UNIT NUMBER IN CONFIG TABLE |
|||
LD A,(SCSI_DEVNUM) ; GET NEXT UNIT NUM TO ASSIGN |
|||
LD (IY+SCSI_DEV),A ; UPDATE IT |
|||
INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN |
|||
LD (SCSI_DEVNUM),A ; SAVE IT |
|||
; |
|||
; ADD UNIT TO GLOBAL DISK UNIT TABLE |
|||
LD BC,SCSI_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 SCSI_PRTPREFIX ; TAG FOR ACTIVE DEVICE |
|||
; |
|||
PRTS(" LUN=$") ; LUN LABEL |
|||
LD A,(IY+SCSI_LUN) ; LOAD LUN |
|||
CALL PRTDEC8 ; DISPLAY IT |
|||
; |
|||
CALL SCSI_INITDEV ; INITIALIZE DEVICE |
|||
#IF (SCSITRACE < 2) |
|||
JP NZ,SCSI_PRTSTAT |
|||
#ENDIF |
|||
RET NZ |
|||
; |
|||
; PRINT STORAGE CAPACITY (BLOCK COUNT) |
|||
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL |
|||
LD A,SCSI_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 |
|||
; |
|||
XOR A ; SUCCESS |
|||
RET |
|||
; |
|||
;============================================================================= |
|||
; DRIVER FUNCTION TABLE |
|||
;============================================================================= |
|||
; |
|||
SCSI_FNTBL: |
|||
.DW SCSI_STATUS |
|||
.DW SCSI_RESET |
|||
.DW SCSI_SEEK |
|||
.DW SCSI_READ |
|||
.DW SCSI_WRITE |
|||
.DW SCSI_VERIFY |
|||
.DW SCSI_FORMAT |
|||
.DW SCSI_DEVICE |
|||
.DW SCSI_MEDIA |
|||
.DW SCSI_DEFMED |
|||
.DW SCSI_CAP |
|||
.DW SCSI_GEOM |
|||
#IF (($ - SCSI_FNTBL) != (DIO_FNCNT * 2)) |
|||
.ECHO "*** INVALID SCSI FUNCTION TABLE ***\n" |
|||
#ENDIF |
|||
; |
|||
SCSI_VERIFY: |
|||
SCSI_FORMAT: |
|||
SCSI_DEFMED: |
|||
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED |
|||
RET |
|||
; |
|||
; |
|||
; |
|||
SCSI_READ: |
|||
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR |
|||
LD A,$08 ; SETUP READ COMMAND |
|||
JR SCSI_IO ; DO THE IO |
|||
; |
|||
; |
|||
; |
|||
SCSI_WRITE: |
|||
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR |
|||
LD A,$0A ; SETUP WRITE COMMAND |
|||
JR SCSI_IO ; DO THE IO |
|||
; |
|||
; |
|||
; |
|||
SCSI_IO: |
|||
LD (SCSI_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS |
|||
; SETUP SCSI COMMAND |
|||
LD (SCSI_S_CDB),A ; SET SCSI COMMAND |
|||
; SETUP DISK BUFFER POINTERS |
|||
LD (SCSI_BUF_OUT),HL ; INPUT BUFFER |
|||
LD (SCSI_BUF_IN),HL ; OUTPUT BUFFER |
|||
; SETUP LUN/LBA |
|||
LD A,(IY+SCSI_LUN) ; PUT LUN IN ACCUM |
|||
RRCA ; MOVE TO TOP 3 BITS |
|||
RRCA ; ... |
|||
RRCA ; ... |
|||
OR (IY+SCSI_LBA+2) ; MERGE WITH TOP OF LBA |
|||
LD (SCSI_CUR_LUN),A ; PUT IN CDB |
|||
LD A,(IY+SCSI_LBA+1) ; LBA MID |
|||
LD (SCSI_CUR_LBN),A ; PUT IN CDB |
|||
LD A,(IY+SCSI_LBA+0) ; LBA MID |
|||
LD (SCSI_CUR_LBN+1),A ; PUT IN CDB |
|||
PUSH IX ; SAVE IX |
|||
LD IX,SCSI_S_IOT ; SET POINTER |
|||
CALL SCSI_GO ; DO THE SCSI TRANSACTION |
|||
POP IX ; RESTORE IX |
|||
JR NZ,SCSI_IO1 ; IF ERROR, SKIP INCREMENT |
|||
; INCREMENT LBA |
|||
LD A,SCSI_LBA ; LBA OFFSET |
|||
CALL LDHLIYA ; HL := IY + A, REG A TRASHED |
|||
CALL INC32HL ; INCREMENT THE VALUE |
|||
; INCREMENT DMA |
|||
LD HL,SCSI_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR |
|||
INC (HL) ; BUMP DMA BY |
|||
INC (HL) ; ... 512 BYTES |
|||
XOR A ; SIGNAL SUCCESS |
|||
SCSI_IO1: |
|||
LD HL,(SCSI_DSKBUF) ; CURRENT DMA TO HL |
|||
OR A ; SET FLAGS |
|||
RET Z ; DONE IF NO ERROR |
|||
LD A,ERR_IO ; SIGNAL IO ERROR |
|||
OR A ; SET FLAGS |
|||
RET ; AND DONE |
|||
; |
|||
; |
|||
; |
|||
SCSI_STATUS: |
|||
LD A,(IY+SCSI_STAT) ; GET STATUS OF SELECTED DEVICE |
|||
OR A ; SET FLAGS |
|||
RET ; AND RETURN |
|||
; |
|||
; |
|||
; |
|||
SCSI_RESET: |
|||
CALL SCSI_INITDEV ; REINITIALIZE UNIT |
|||
OR A ; SET RESULT FLAGS |
|||
RET |
|||
; |
|||
; |
|||
; |
|||
SCSI_DEVICE: |
|||
LD D,DIODEV_SCSI ; D := DEVICE TYPE |
|||
LD E,(IY+SCSI_DEV) ; E := PHYSICAL DEVICE NUMBER |
|||
LD C,%00110000 ; C := GENERIC HARD DISK ATTRIBUTES |
|||
LD H,0 ; H := MODE |
|||
LD L,(SCSI_IOBASE) ; L := BASE I/O ADDRESS |
|||
XOR A ; SIGNAL SUCCESS |
|||
RET |
|||
; |
|||
; |
|||
; |
|||
SCSI_MEDIA: |
|||
LD A,E ; GET FLAGS |
|||
OR A ; SET FLAGS |
|||
JR Z,SCSI_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA |
|||
CALL SCSI_INITDEV ; REINITIALIZE DEVICE |
|||
; |
|||
SCSI_MEDIA1: |
|||
LD A,(IY+SCSI_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 |
|||
; |
|||
; |
|||
; |
|||
SCSI_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+SCSI_LBA+0),L ; SAVE NEW LBA |
|||
LD (IY+SCSI_LBA+1),H ; ... |
|||
LD (IY+SCSI_LBA+2),E ; ... |
|||
LD (IY+SCSI_LBA+3),D ; ... |
|||
XOR A ; SIGNAL SUCCESS |
|||
RET ; AND RETURN |
|||
; |
|||
; |
|||
; |
|||
SCSI_CAP: |
|||
LD A,(IY+SCSI_STAT) ; GET STATUS |
|||
PUSH AF ; SAVE IT |
|||
LD A,SCSI_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 |
|||
; |
|||
; |
|||
; |
|||
SCSI_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 SCSI_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 SCSI_CAP STATUS |
|||
; |
|||
;============================================================================= |
|||
; FUNCTION SUPPORT ROUTINES |
|||
;============================================================================= |
|||
; |
|||
; ON RETURN, ZF SET INDICATES HARDWARE FOUND |
|||
; |
|||
SCSI_DETECT: |
|||
LD A,$05 |
|||
OUT (SCSIBASE+3),A |
|||
IN A,(SCSIBASE+3) |
|||
CP $05 |
|||
RET NZ |
|||
LD A,$0A |
|||
OUT (SCSIBASE+3),A |
|||
IN A,(SCSIBASE+3) |
|||
CP $0A |
|||
RET |
|||
; |
|||
; INITIALIZE DEVICE |
|||
; |
|||
SCSI_INITDEV: |
|||
XOR A |
|||
LD (IY+SCSI_STAT),A |
|||
RET |
|||
; |
|||
;============================================================================= |
|||
; COMMAND PROCESSING |
|||
;============================================================================= |
|||
; |
|||
;---------------------------------------------------------------- |
|||
;WRITE LOGICAL BLOCK TO DISK |
|||
;CUR_TID,CUR_LUN,CUR_LBN ALREADY SET |
|||
;EXIT WITH ZERO STATUS IF OK |
|||
;---------------------------------------------------------------- |
|||
; |
|||
WR_PHY: |
|||
LD A,0AH ;WRITE COMMAND |
|||
JR PHY_COM ;FINISH SAME AS READ |
|||
|
|||
;---------------------------------------------------------------- |
|||
;READ LOGICAL BLOCK FROM DISK |
|||
;CUR_TID,CUR_LUN,CUR_LBN ALREADY SET |
|||
;EXIT WITH ZERO STATUS IF OK |
|||
;---------------------------------------------------------------- |
|||
; |
|||
RD_PHY: |
|||
LD A,8 ;READ COMMAND |
|||
PHY_COM: |
|||
LD (SCSI_S_CDB),A ;SET IN COMMAND BLOCK |
|||
LD IX,SCSI_S_IOT ;POINT TO IO TABLE |
|||
CALL SCSI_GO |
|||
AND 02H ;MASK TO ERROR BIT |
|||
RET |
|||
;------------------------------------------------------------------------------- |
|||
;DO SCSI TRANSACTION |
|||
; IX=SCSI IO BLOCK |
|||
;------------------------------------------------------------------------------- |
|||
SCSI_GO: |
|||
LD A,$FF ;PRESET ERROR STATUS |
|||
LD L,(IX+4) ;POINT TO STATUS ADDRESS |
|||
LD H,(IX+5) ;POINT TO STATUS ADDRESS |
|||
LD (HL),A ;SET ERROR |
|||
; |
|||
XOR A ; |
|||
OUT (SCSI_SR_MR),A ;RESET CONTROL REG |
|||
OUT (SCSI_SR_TCR),A ;CLEAR COMMAND REG. |
|||
OUT (SCSI_SR_ICR),A ; |
|||
LD A,(IX) ;GET TID |
|||
BIT 7,A ; TURN ON MY ID |
|||
OUT (SCSI_SR_ODR),A ;SET TARGET ID |
|||
LD A,$01 ;DRIVE BUS |
|||
OUT (SCSI_SR_ICR),A ; |
|||
LD A,$05 ;SET SEL AND DRIVE BUS |
|||
OUT (SCSI_SR_ICR),A ; |
|||
; |
|||
;WAIT FOR SCSI BUSY |
|||
LD BC,0 ;INIT TIMEOUT |
|||
S_SWT: |
|||
IN A,(SCSI_SR_CSBS) ;GET BUS STATUS |
|||
AND SCSI_SM_BSY ;MASK TO BUSY BIT |
|||
JR NZ,S_BSYA ;JMP IF BUSY ACTIVE |
|||
NOP ;KILL A LITTLE TIME |
|||
NOP |
|||
NOP |
|||
NOP |
|||
DEC BC ;DEC TIMEOUT |
|||
LD A,B ;TEST TIMEOUT=0 |
|||
OR C |
|||
JR NZ,S_SWT ;JMP IF NO TIMEOUT |
|||
XOR A ;CLEAR A |
|||
OUT (SCSI_SR_ICR),A ;CLEAR SEL AND DATA |
|||
JR S_EXIT ;ERROR EXIT |
|||
; |
|||
;BUSY IS ACTIVE |
|||
S_BSYA: |
|||
XOR A ;CLEAR A |
|||
OUT (SCSI_SR_ICR),A ;CLEAR SEL AND DATA |
|||
|
|||
;------------------------------------------------------------------------------- |
|||
; |
|||
;TARGET IS SELECTED SO TEST BSY AND REQ |
|||
;THEN DECODE REQUESTED PHASE |
|||
; |
|||
;------------------------------------------------------------------------------- |
|||
PHASE: |
|||
XOR A |
|||
OUT (SCSI_SR_ICR),A ;RESET INITIATOR |
|||
; |
|||
S_WTREQ: |
|||
IN A,(SCSI_SR_CSBS) ;GET BUS STATUS |
|||
LD B,A ;SAVE COPY |
|||
AND SCSI_SM_BSY ;MASK TO BUSY BIT |
|||
JR NZ,S_WTRQ1 ;STILL BUSY SO CONT. |
|||
|
|||
;------------------------------------------------------------------------------- |
|||
;BUSY LOST SO EXIT |
|||
;------------------------------------------------------------------------------- |
|||
S_EXIT: |
|||
LD L,(IX+4) ;GET STATUS POINTER |
|||
LD H,(IX+5) ;GET STATUS POINTER |
|||
LD A,(HL) |
|||
RET ;BUSY LOST? WERE DONE |
|||
; |
|||
S_WTRQ1: |
|||
LD A,B ;RECOVER STATUS |
|||
AND SCSI_SM_REQ ;REQUEST ACTIVE? |
|||
JR Z,S_WTREQ ;LOOP TILL REQUEST |
|||
|
|||
;------------------------------------------------------------------------------- |
|||
;REQUEST IS ACTIVE SO SET 5380 TO REQUESTED PHASE |
|||
;------------------------------------------------------------------------------- |
|||
LD A,B ;RECOVER BUS STATUS |
|||
RR A ;SHIFT STATUS TO PHASE BITS |
|||
RR A |
|||
AND $07 ;MASK TO PHASE BITS |
|||
OUT (SCSI_SR_TCR),A ;SET PHASE |
|||
; |
|||
;JUMP TO PHASE HANDLER |
|||
; |
|||
LD A,B ;RECOVER BUS STATUS |
|||
RR A |
|||
AND $0E ;MASK TO PHASE BITS |
|||
LD E,A ; |
|||
LD D,0 |
|||
LD HL,PHTABL ;POINT TO TABLE |
|||
ADD HL,DE ;OFFSET INTO TABLE |
|||
LD E,(HL) ;GET EXECUTION ADDRESS |
|||
INC HL |
|||
LD D,(HL) |
|||
PUSH DE |
|||
RET ;EXECUTE PHASE |
|||
|
|||
;------------------------------------------------------------------------------- |
|||
;PHASE TABLE |
|||
;------------------------------------------------------------------------------- |
|||
PHTABL: |
|||
.WORD PHASE0 ;DATA OUT |
|||
.WORD PHASE1 ;DATA IN |
|||
.WORD PHASE2 ;CMD OUT |
|||
.WORD PHASE3 ;STATUS IN |
|||
.WORD S_EXIT ;UNUSED |
|||
.WORD S_EXIT ;UNUSED |
|||
.WORD PHASE6 ;MESSAGE OUT |
|||
.WORD PHASE7 ;MESSAGE IN |
|||
|
|||
;------------------------------------------------------------------------------- |
|||
;PHASE HANDLERS |
|||
;------------------------------------------------------------------------------- |
|||
; |
|||
;DATA OUT |
|||
PHASE0: |
|||
LD L,(IX+6) ;GET POINTER |
|||
LD H,(IX+7) |
|||
JP S_WRIT ;WRITE BYTES |
|||
; |
|||
;DATA IN |
|||
PHASE1: |
|||
LD L,(IX+8) ;GET POINTER |
|||
LD H,(IX+9) |
|||
JP S_READ ;READ BYTES |
|||
; |
|||
;CMD OUT |
|||
PHASE2: |
|||
LD L,(IX+2) |
|||
LD H,(IX+3) |
|||
JP S_WRIT |
|||
; |
|||
;STATUS IN |
|||
PHASE3: |
|||
LD L,(IX+4) |
|||
LD H,(IX+5) |
|||
JP S_READ |
|||
; |
|||
;MSG OUT |
|||
PHASE6: |
|||
LD L,(IX+10) |
|||
LD H,(IX+11) |
|||
JP S_WRIT |
|||
; |
|||
;MSG IN |
|||
PHASE7: |
|||
LD L,(IX+12) |
|||
LD H,(IX+13) |
|||
JP S_READ |
|||
;------------------------------------------------------------------------------- |
|||
;SCSI WRITE ROUTINE (SEND BYTES TO TARGET) |
|||
;BUS PHASE ALREADY SET. RETURN ON PHASE MISMATCH |
|||
;------------------------------------------------------------------------------- |
|||
S_WRIT: |
|||
LD A,1 ;DRIVE SCSI DATA BUS |
|||
OUT (SCSI_SR_ICR),A |
|||
; |
|||
;WAIT FOR REQ WHILE CHECKING BUSY |
|||
; |
|||
S_WWREQ: |
|||
IN A,(SCSI_SR_CSBS) ;GET CURRENT BUS STAT |
|||
LD B,A ;SAVE IT |
|||
AND SCSI_SM_REQ ;REQUEST ACTIVE? |
|||
JR NZ,S_WNXT ; |
|||
; |
|||
LD A,B ;RECOVER CURRENT BUS STAT |
|||
AND SCSI_SM_BSY ;STILL BUSY? |
|||
JP NZ,S_WWREQ ;LOOP IF STILL BUSY |
|||
JP PHASE ; |
|||
; |
|||
;REQUEST ACTIVE SO CHECK PHASE |
|||
; |
|||
S_WNXT: |
|||
IN A,(SCSI_SR_BSR) ;GET STATUS |
|||
AND SCSI_SM_PHM ;MASK TO PHASE MATCH |
|||
JP Z,PHASE ;JMP IF PHASE MISMATCH |
|||
; |
|||
;REQUEST ACTIVE AND PHASE MATCH SO SEND DATA |
|||
; |
|||
LD A,(HL) ;GET BYTE |
|||
OUT (SCSI_SR_ODR),A ;SEND DATA |
|||
LD A,$11 ;ACK + DRIVE BUS |
|||
OUT (SCSI_SR_ICR),A ;SET ACK,DRIVE SCSI BUS |
|||
INC HL ;ADVANCE BUF POINTER |
|||
; |
|||
;WAIT FOR REQUEST TO DROP |
|||
; |
|||
S_WNREQ: |
|||
IN A,(SCSI_SR_CSBS) ;GET CURRENT STATUS |
|||
AND SCSI_SM_REQ |
|||
JR NZ,S_WNREQ ;LOOP TILL REQ DROPS |
|||
; |
|||
LD A,$1 ;DROP ACK,ASSERT DATA |
|||
OUT (SCSI_SR_ICR),A ;DROP ACK |
|||
JP S_WWREQ ;LOOP FOR NEXT BYTE/PHASE |
|||
;------------------------------------------------------------------------------- |
|||
;SCSI READ ROUTINE (GET BYTES FROM TARGET) |
|||
;BUS PHASE ALREADY SET. RETURN ON PHASE MISMATCH |
|||
;------------------------------------------------------------------------------- |
|||
; |
|||
S_READ: |
|||
; |
|||
;WAIT FOR REQ WHILE CHECKING BUSY |
|||
; |
|||
S_RWREQ: |
|||
IN A,(SCSI_SR_CSBS) ;GET CURRENT BUS STAT |
|||
LD B,A ;SAVE IT |
|||
AND SCSI_SM_REQ ;REQUEST ACTIVE? |
|||
JR NZ,S_RNXT ; |
|||
; |
|||
LD A,B ;RECOVER CURRENT BUS STAT |
|||
AND SCSI_SM_BSY ;STILL BUSY? |
|||
JP NZ,S_RWREQ ;LOOP IF STIL BUSY |
|||
JP PHASE ; |
|||
; |
|||
;REQUEST ACTIVE SO CHECK PHASE |
|||
S_RNXT: |
|||
IN A,(SCSI_SR_BSR) ;GET STATUS |
|||
AND SCSI_SM_PHM ;MASK TO PHASE MATCH |
|||
JP Z,PHASE ;JMP IF PHASE MISMATCH |
|||
|
|||
;REQUEST ACTIVE AND PHASE MATCH SO GET DATA |
|||
; |
|||
IN A, (SCSI_SR_CSD) ;GET DATA |
|||
LD (HL),A ;SAVE DATA |
|||
LD A,$10 |
|||
OUT (SCSI_SR_ICR),A ;SET ACK |
|||
INC HL ;ADVANCE BUF POINTER |
|||
; |
|||
;WAIT FOR REQUEST TO DROP |
|||
; |
|||
S_RNREQ: |
|||
IN A,(SCSI_SR_CSBS) ;GET CURRENT STATUS |
|||
AND SCSI_SM_REQ |
|||
JR NZ,S_RNREQ ;LOOP TILL REQ DROPS |
|||
XOR A |
|||
OUT (SCSI_SR_ICR),A ;DROP ACK |
|||
JP S_READ ;LOOP FOR NEXT BYTE/PHASE |
|||
|
|||
; |
|||
;============================================================================= |
|||
; HARDWARE INTERFACE ROUTINES |
|||
;============================================================================= |
|||
; |
|||
;============================================================================= |
|||
; ERROR HANDLING AND DIAGNOSTICS |
|||
;============================================================================= |
|||
; |
|||
; ERROR HANDLERS |
|||
; |
|||
SCSI_NOMEDIA: |
|||
LD A,SCSI_STNOMEDIA |
|||
JR SCSI_ERR |
|||
; |
|||
SCSI_IOERR: |
|||
LD A,SCSI_STIOERR |
|||
JR SCSI_ERR |
|||
; |
|||
SCSI_TO: |
|||
LD A,SCSI_STTO |
|||
JR SCSI_ERR |
|||
; |
|||
SCSI_NOTRDY: |
|||
LD A,SCSI_STNOTRDY |
|||
JR SCSI_ERR |
|||
; |
|||
SCSI_ERR: |
|||
LD (IY+SCSI_STAT),A ; SAVE NEW STATUS |
|||
; |
|||
#IF (SCSITRACE >= 2) |
|||
CALL SCSI_PRTSTAT |
|||
#ENDIF |
|||
OR A ; SET FLAGS |
|||
RET |
|||
; |
|||
; |
|||
; |
|||
SCSI_PRTERR: |
|||
RET Z ; DONE IF NO ERRORS |
|||
; FALL THRU TO SCSI_PRTSTAT |
|||
; |
|||
; PRINT FULL DEVICE STATUS LINE |
|||
; |
|||
SCSI_PRTSTAT: |
|||
PUSH AF |
|||
PUSH DE |
|||
PUSH HL |
|||
LD A,(IY+SCSI_STAT) |
|||
CALL SCSI_PRTPREFIX ; PRINT UNIT PREFIX |
|||
JR SCSI_PRTSTAT3 |
|||
SCSI_PRTSTAT2: |
|||
CALL NEWLINE |
|||
PRTS("SCSI:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT |
|||
SCSI_PRTSTAT3: |
|||
CALL PC_SPACE ; FORMATTING |
|||
CALL SCSI_PRTSTATSTR |
|||
POP HL |
|||
POP DE |
|||
POP AF |
|||
RET |
|||
; |
|||
; PRINT STATUS STRING |
|||
; |
|||
SCSI_PRTSTATSTR: |
|||
PUSH AF |
|||
PUSH DE |
|||
LD A,(IY+SCSI_STAT) |
|||
OR A |
|||
LD DE,SCSI_STR_STOK |
|||
JR Z,SCSI_PRTSTATSTR1 |
|||
INC A |
|||
LD DE,SCSI_STR_STNOMEDIA |
|||
JR Z,SCSI_PRTSTATSTR1 |
|||
INC A |
|||
LD DE,SCSI_STR_STIOERR |
|||
JR Z,SCSI_PRTSTATSTR1 |
|||
INC A |
|||
LD DE,SCSI_STR_STTO |
|||
JR Z,SCSI_PRTSTATSTR1 |
|||
INC A |
|||
LD DE,SCSI_STR_STNOTRDY |
|||
JR Z,SCSI_PRTSTATSTR1 |
|||
LD DE,SCSI_STR_STUNK |
|||
SCSI_PRTSTATSTR1: |
|||
CALL WRITESTR |
|||
POP DE |
|||
POP AF |
|||
RET |
|||
; |
|||
; PRINT DIAGNONSTIC PREFIX |
|||
; |
|||
SCSI_PRTPREFIX: |
|||
PUSH AF |
|||
CALL NEWLINE |
|||
PRTS("SCSI$") |
|||
LD A,(IY+SCSI_DEV) ; GET CURRENT DEVICE NUM |
|||
CP $FE ; NOT YET ASSIGNED? |
|||
JR Z,SCSI_PRTPREFIX1 ; SKIP DEV NUM IF SO |
|||
CALL PRTDECB |
|||
SCSI_PRTPREFIX1: |
|||
CALL PC_COLON |
|||
POP AF |
|||
RET |
|||
; |
|||
;============================================================================= |
|||
; STRING DATA |
|||
;============================================================================= |
|||
; |
|||
SCSI_STR_STOK .TEXT "OK$" |
|||
SCSI_STR_STNOMEDIA .TEXT "NO MEDIA$" |
|||
SCSI_STR_STIOERR .TEXT "IO ERROR$" |
|||
SCSI_STR_STTO .TEXT "TIMEOUT$" |
|||
SCSI_STR_STNOTRDY .TEXT "NOT READY$" |
|||
SCSI_STR_STUNK .TEXT "UNKNOWN ERROR$" |
|||
; |
|||
;============================================================================= |
|||
; DATA STORAGE |
|||
;============================================================================= |
|||
; |
|||
SCSI_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT |
|||
SCSI_DSKBUF .DW 0 ; ACTIVE DISK BUFFER |
|||
; |
|||
;---------------------------------------------------------------- |
|||
;SCSI COMMAND DESCRIPTOR FOR READ/WRITE |
|||
;DO NOT USE THIS FOR DIRECT SCSI I/O |
|||
;YOU WILL MESS UP BLOCK/DEBLOCK |
|||
; |
|||
SCSI_S_CDB: |
|||
.DB 8 ; COMMAND |
|||
SCSI_CUR_LUN: |
|||
.DB 0 << 5 ; LUN/LBA HI |
|||
SCSI_CUR_LBN: |
|||
.DB 0 ; LBA MID |
|||
.DB 0 ; LBA LOW |
|||
.DB 1 ; COUNT |
|||
.DB 0 ; FLAGS |
|||
; |
|||
;---------------------------------------------------------------- |
|||
;SCSI I/O ADDRESS TABLE FOR READ/WRITE |
|||
;DONT MESS WITH THIS EITHER |
|||
SCSI_S_IOT: |
|||
SCSI_CUR_TID .DB 1 << SCSI_TID ;TARGET |
|||
.DB 0 ;UNUSED |
|||
.DW SCSI_S_CDB ;CDB POINTER |
|||
.DW SCSI_S_STAT ;STATUS POINTER |
|||
SCSI_BUF_OUT .DW HB_WRKBUF ;DATA OUT POINTER |
|||
SCSI_BUF_IN .DW HB_WRKBUF ;DATA IN POINTER |
|||
.DW SCSI_S_MSG ;MSG OUT POINTER |
|||
.DW SCSI_S_MSG ;MSG IN POINTER |
|||
; |
|||
;---------------------------------------------------------------- |
|||
;THIS IS THE END OF INITIALIZED DATA |
|||
;EVERYTHING FOLLOWING MUST HAVE MEMORY SPACE AVAILABLE |
|||
;BUT IS NOT PART OF THE BOOT IMAGE |
|||
;---------------------------------------------------------------- |
|||
; |
|||
; UNINITIALIZED DATA AREA |
|||
; |
|||
SCSI_S_STAT .DW 0 ;SCSI ENDING STATUS |
|||
SCSI_S_MSG .DW 0 ;SCSI MESSAGE |
|||
; |
|||
Loading…
Reference in new issue