;
; 
; 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
; 04 Oct 1992 HL	Selection timeout return status added
; 			Normal return status zero added
;			Removal of "15(a1)" accesses
;
	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		SCSIRdWt

SCSIRdWt:
	bset.b	#3,NCR+4	;TM!!! EOP INTERRUPT bit is used for
	bne.s	SCSIRdWt	;TM!!! SCSI BUSY FLAG
	move.b	#$08,NCR+4	;TM!!!
	movem.l	d4-d7/a1-a5,-(sp)	;save regs
	move.l	#CMDBUF,a1		;get CMDBUF add
	move.l	d2,d5		;copy unit#
	moveq	#$0,d2		;LU=0
	lsr.l	#1,d5		;create Target address
	bcc.s	Drive
	moveq	#$20,d2		;LU=1
STILLbsy1:
	btst.b	#6,NCR+8	; TM BUSY check
	bne.s	STILLbsy1	; TM wait if still busy
Drive:
	moveq	#$1,d4
	lsl.l	d5,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

;build the scsi cmd packet
	move.l	d1,d4		;get the start sect #
	move.l	d0,d5		;get the #bytes to transfere
	asr.l	#8,d5		;shift 9 palces to get sectors
	asr.l	#1,d5
	and.l	#$FF,d5		;must be less than 1 byte
;	asl.l	#8,d5		;move to upper byte in word; TM to enable NEC cache
;	move.w	d5,4(a1)	;place in packet           ; TM
	move.b	d5,4(a1)	;place in packet           ; TM don't mask last byte
	asr.l	#8,d4		;convert to sectors
	asr.l	#1,d4
	and.l	#$000FFFFF,d4	;mask out L U #
	move.l	d4,(a1)		;place in packet
;add the logical unit #
	or.b	d2,1(a1)	;put LU# in the packet
	cmp.w	#CMD_READ,IO_COMMAND(a2)	;read ?
	bne	WriteSCSI
	move.b	#$08,(a1)	;set cmd to read

Selection:
	bsr	SELph		;select the target

End:
	bclr.b	#3,NCR+4	;TM!!! clear SCSI BUSY FLAG
	movem.l	(sp)+,d4-d7/a1-a5	;restore regs
	rts			;return to caller

WriteSCSI:	;send data to the SCSI
	move.b   #$0a,(a1)
	bra.s   Selection


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	#$01,15(a1)	;set drive not ready error ; HL
	move.b  #HFERR_SelTimeout,d0 ; 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	#CMDBUF,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
	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 ?
	clr.l	d0		; HL 
	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
	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
;	move.b	#$0,NCR+4	;clear DMAMODE
	bclr.b	#1,NCR+4	;TM!!!
	bra	SendData
   


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
	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)+
;	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
RReq:
	btst.b	#3,NCR+10	;test for phase match
	beq	NextPhase
	bra.s	RecData

CMDBUF	dc.b	$0A,$00,$00,$00,$01,$00,$00,$00,$00,$00 ; TM GENERIC
;CMDBUF	dc.b	$0A,$00,$00,$00,$01,$0c,$00,$00,$00,$00  ; TM for NEC cache
STAT	ds.b	$01		;status word
MSGINBUF	ds.b	$04	;message buffer
ERROR	ds.b	$01		;error flag
;
;
	END
