home *** CD-ROM | disk | FTP | other *** search
- ;
- ; SCSIDirectCmd, based on "SCSIRdWt"
- ;
- ; Original version by Paul Harker
- ; BUSY check on SELECT
- ; improved handshake on MSGIN, CMDOUT
- ; 26 May 1992 TM
- ; 17 Jun 1992 TM SCSI BUSY FLAG ADDED for simaltaneous copy bug
- ; 15 Sep 1992 TM GENERIC version
- ; 05 Oct 1992 HL SCSI-Direct version
- ; New selection of unit
- ; Return status when sel. timed out
- ; Return status zero on normal return
- ; Buffers not on 512 b boundaries are treated with
- ; their actual length
- ; 22 Oct 1992 HL Return status bug fixed
- ; 25 Oct 1992 HL Bug introduced above fixed
- ;
- include "exec/types.i"
- include "exec/io.i"
- include "exec/devices.i"
- include "exec/tasks.i"
- include "exec/interrupts.i
- include "devices/scsidisk.i"
- include "mydev.i"
- include "scsi.i"
-
- Public SCSIDirectCmd
-
- ; In params:
- ; LU in d2
- ; Cmd ptr in a2
- ; Buffer ptr in a0
- ; Buffer length in d0
- ;
- ; Out params:
- ; IO_Status in d0
- ; SCSI_Status in d7
-
- SCSIDirectCmd:
- bset.b #3,NCR+4 ;TM!!! EOP INTERRUPT bit is used for
- bne.s SCSIDirectCmd ;TM!!! SCSI BUSY FLAG
- move.b #$08,NCR+4 ;TM!!!
- movem.l d4-d6/a3-a5,-(sp) ;save regs
- clr.b d7 ;clear error flag ; HL
- STILLbsy1:
- btst.b #6,NCR+8 ; TM BUSY check
- bne.s STILLbsy1 ; TM wait if still busy
- Drive:
- moveq #$1,d4
- lsl.l d2,d4 ;shift to address bit
- or.b #$80,d4 ;add addresses
- move.b d4,NCR ;load addresses
- move.b #$5,NCR+2 ;assert BUS with address
-
- Selection:
- bsr SELph ;select the target
-
- End:
- bclr.b #3,NCR+4 ;TM!!! clear SCSI BUSY FLAG
- movem.l (sp)+,d4-d6/a3-a5 ;restore regs
- rts ;return to caller
-
- SELph: ;select the target
- move.l #M250,d5 ;load timer
-
- loop1: btst.b #6,NCR+8 ;test BSY
- bne.s SLECT ;if busy , selected
- subq #1,d5 ;dec timer
- bne.s loop1 ;loop
- move.b #HFERR_SelTimeout,d0 ;set drive not ready error ; HL
- rts
-
- SLECT:
- and.b #$FB,NCR+2 ;clr SEL
-
- NextPhase: ;Check the SCSI bus phase
- move.b #$0,NCR
- move.b #$0,NCR+6 ;clear TCR
- btst.b #5,NCR+8 ;test REQ
- bne.s GotREQ ;if REQ it must be busy...
- btst.b #6,NCR+8 ;check BUSY
- beq Done ;bus free
- bra NextPhase ; still waiting for REQ
- GotREQ:
- btst.b #3,NCR+8 ;check C/D
- beq.s Dat ;data in/out phase
- btst.b #4,NCR+8 ;check MSG
- bne.s Message ;Message in/out phase
- btst.b #2,NCR+8 ;check I/O
- bne.s STATph ;stat phase
- bra.s CMDph ;command phase
- Message: ;check to see if it is message in or out
- btst.b #2,NCR+8 ;check I/O
- ; bne.s MSGINph
- bne MSGINph ;TM
- ; bra.s MSGOUTph ;TM
- bra MSGOUTph ;TM
- Dat: ;check to see if it is data in or out
- btst.b #2,NCR+8 ;check I/O
- ; bne.s RDATph
- bne RDATph ;TM
- ; bra.s SDATph ;TM
- bra SDATph ;TM
- CMDph: ;send command
- move.l a2,a4 ;set the cmd buffer add
- move.b #$02,NCR+6 ;set TCR to command phase
- Send: ;send x characters to the target
- btst.b #6,NCR+8 ;TM busy check
- beq Done ;TM busy check
- btst.b #5,NCR+8 ;test for REQ
- beq.s Send ;wait for REQ
- btst.b #3,NCR+10 ;test phase match
- ; beq.s NextPhase
- beq NextPhase ;TM
- move.b (a4)+,NCR ;set the byte
- ori.b #$10,NCR+2 ;set ACK
- CMDReq:
- btst.b #6,NCR+8 ;TM busy check
- beq Done ;TM busy check
- btst.b #5,NCR+8 ; TM test for REQ
- bne.s CMDReq ; TM wait for REQ deasserted
- andi.b #$EF,NCR+2 ;clr ACK
- bra Send
-
- STATph: ;get status byte
- move.b NCR,d7 ;move STATUS into Stat temp
- ori.b #$10,NCR+2 ;set ACK
- STATReq:
- btst.b #6,NCR+8 ;TM busy check
- beq Done ;TM busy check
- btst.b #5,NCR+8 ; TM test for REQ
- bne.s STATReq ; TM wait for REQ deasserted
- andi.b #$ef,NCR+2 ;clr ACK
- bra NextPhase
-
- MSGINph: ;only msg supported is COMPLETE..so we just ack it
- ori.b #$10,NCR+2 ;set ACK
- MSGINReq:
- btst.b #6,NCR+8 ;TM busy check
- beq Done ;TM busy check
- btst.b #5,NCR+8 ; TM test for REQ
- bne.s MSGINReq ; TM wait for REQ deasserted
- and.b #$EF,NCR+2 ;clr ACK
- STILLbsy:
- btst.b #6,NCR+8 ; TM BUSY check
- bne.s STILLbsy ; TM wait if still busy
- Done: ;did we end normally ?
- move.b d7,d6
- and.b #$0e,d6 ; For normal SCSI devices, use this ; HL
- ;;; and.b #$0c,d6 ; For (older) adaptec cards, use this ; HL
- cmp.b #$00,d6
- beq StatOk
- cmp.b #$04,d6
- beq StatOk
- move.b #HFERR_BadStatus,d0
- rts ;do a clean end
- StatOk:
- move.b #0,d0
- rts ;do a clean end
-
- MSGOUTph: ;send message to target
- bra NextPhase ;error try again
-
- SDATph: ;send data to target
- move.l a0,a4 ;set the data buffer add
- move.b #$00,NCR+6 ;set TCR to send data
- SendData: ;send x characters to the target
- btst.b #6,NCR+8 ;TM busy check
- beq Done ;TM busy check
- btst.b #5,NCR+8 ;test for REQ
- beq.s SendData ;wait for REQ
- btst.b #3,NCR+10 ;test phase match
- ; beq.s NextPhase
- beq NextPhase ;TM
- ; move.b #$02,NCR+4 ;Set DMAMODE
- bset.b #1,NCR+4 ;TM!!!
- move.b #$00,NCR+12 ;start DMA recieve
- move.l d0,d4
- and.l #511,d4 ;Check if length is even 512b
- bne UnevenSend
- moveq #64,d4 ;load counter..we do 512 byte blocks
- LoopTop:
- move.b (a4)+,DMA ;set byte 0
- move.b (a4)+,DMA ;set byte 1
- move.b (a4)+,DMA ;set byte 2
- move.b (a4)+,DMA ;set byte 3
- move.b (a4)+,DMA ;set byte 4
- move.b (a4)+,DMA ;set byte 5
- move.b (a4)+,DMA ;set byte 6
- move.b (a4)+,DMA ;set byte 7
- subq #1,d4
- bne.s LoopTop
- SendLast:
- ; move.b #$0,NCR+4 ;clear DMAMODE
- bclr.b #1,NCR+4 ;TM!!!
- bra SendData
-
- UnevenSend:
- move.l d0,d4 ;load counter.. we do bufsize bytes
- UnevenSendLoop:
- move.b (a4)+,DMA ;set byte
- subq #1,d4 ;decrement counter
- bne.s UnevenSendLoop ;done with block?
- bra.s SendLast
-
- RDATph: ;receive data fron target
- move.l a0,a4 ;set the data buffer add
- lea DMA+12,a5 ;set DMA recieve Base
- move.b #$01,NCR+6 ;set TCR to receive data
- RecData:
- ; move.b #$02,NCR+4 ;Set DMAMODE
- bset.b #1,NCR+4 ;TM!!!
- move.b #$00,NCR+14 ;start DMA recieve
- move.l d0,d4
- and.l #511,d4 ;Check if length is even 512b
- bne UnevenRec
- moveq #63,d4 ;load counter..we do 512 byte blocks
- RecLoop:
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- subq #1,d4 ;decrement counter
- bne.s RecLoop ;done with block?
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- move.b (a5),(a4)+
- RecLast:
- ; move.b #$0,NCR+4 ;disable ack/req
- bclr.b #1,NCR+4 ;TM!!!
- move.b (a5),(a4)+ ;read last byte of block
- WRec:
- btst.b #5,NCR+8 ;test REQ
- bne.s RReq ;Got it
- btst.b #6,NCR+8 ;check BUSY
- beq Done ;Not Busy? must be Done.
- bra.s WRec ;wait for REQ
-
- UnevenRec:
- move.l d0,d4 ;load counter.. we do bufsize bytes
- subq #1,d4 ;decrement counter
- UnevenRecLoop:
- move.b (a5),(a4)+
- subq #1,d4 ;decrement counter
- bne.s UnevenRecLoop ;done with block?
- bra.s RecLast
-
- RReq:
- btst.b #3,NCR+10 ;test for phase match
- beq NextPhase
- bra.s RecData
- ;
- END
-