misc/060tsys/t16scsi.s
;----------------------------------------------------------------
;
;	SCSI
;
;----------------------------------------------------------------

	.include	t00iocs.equ
	.include	t02const.equ
	.include	t08debug.equ

;__DEBUG__	equ	1

	.cpu	68060

;----------------------------------------------------------------
;
;	IOCS _SCSIDRV
;
;----------------------------------------------------------------
;----------------------------------------------------------------
;IOCS _SCSIDRV
;	バッファがDMA転送できないとき(バッファの物理アドレスが論理アドレスと
;	異なる場合および物理アドレスがローカルメモリを指している場合)はソフト
;	転送に変更する。
;	_S_REVISIONの返却値が$000A以上のとき(SHARP純正拡張SCSIボード,X68030の
;	内蔵SCSI-BIOSおよびMach-2のSCSI-BIOS)はSRAMのソフト転送フラグを使って
;	ソフト転送に変更する。
;	_S_REVISIONの返却値が$000A未満のとき(SUPERからXVICompactまでのX68000の
;	内蔵SCSI-BIOS)は高レベルの転送コマンド(_S_READ,_S_READEXTなど)を自前で
;	展開して低レベルのソフト転送コマンドを用いる。
	.text
	.align	4,$2048
iocsScsidrv::
	tst.b	patchIocsScsi
	beq	scsicall
	cmp.l	#(scsidrvJumpTableEnd-scsidrvJumpTable)/4,d1
	bcc	scsicall
	jmp	([scsidrvJumpTable,pc,d1.l*4])

	.align	4,$2048
scsidrvJumpTable:
	.dc.l	scsicall		;$00 _S_RESET
	.dc.l	scsicall		;$01 _S_SELECT
	.dc.l	scsicall		;$02 _S_SELECTA
	.dc.l	scsicall		;$03 _S_CMDOUT
	.dc.l	scsidrvDatain		;$04 _S_DATAIN
	.dc.l	scsidrvDataout		;$05 _S_DATAOUT
	.dc.l	scsicall		;$06 _S_STSIN
	.dc.l	scsicall		;$07 _S_MSGIN
	.dc.l	scsicall		;$08 _S_MSGOUT
	.dc.l	scsicall		;$09 _S_PHASE
	.dc.l	scsicall		;$0A _S_REVISION
	.dc.l	scsicall		;$0B _S_DATAIN_P
	.dc.l	scsicall		;$0C _S_DATAOUT_P
	.dc.l	scsicall		;$0D _S_MSGOUTEXT
	.dc.l	scsicall		;$0E 
	.dc.l	scsicall		;$0F 
	.dc.l	scsicall		;$10 
	.dc.l	scsicall		;$11 
	.dc.l	scsicall		;$12 
	.dc.l	scsicall		;$13 
	.dc.l	scsicall		;$14 
	.dc.l	scsicall		;$15 
	.dc.l	scsicall		;$16 
	.dc.l	scsicall		;$17 
	.dc.l	scsicall		;$18 
	.dc.l	scsicall		;$19 
	.dc.l	scsicall		;$1A 
	.dc.l	scsicall		;$1B 
	.dc.l	scsicall		;$1C 
	.dc.l	scsicall		;$1D 
	.dc.l	scsicall		;$1E 
	.dc.l	scsicall		;$1F 
	.dc.l	scsidrvInquiry		;$20 _S_INQUIRY
	.dc.l	scsidrvRead		;$21 _S_READ
	.dc.l	scsidrvWrite		;$22 _S_WRITE
	.dc.l	scsicall		;$23 _S_FORMAT
	.dc.l	scsicall		;$24 _S_TESTUNIT
	.dc.l	scsidrvReadcap		;$25 _S_READCAP
	.dc.l	scsidrvReadext		;$26 _S_READEXT
	.dc.l	scsidrvWriteext		;$27 _S_WRITEEXT
	.dc.l	scsidrvVerifyext	;$28 _S_VERIFYEXT
	.dc.l	scsidrvModesense	;$29 _S_MODESENSE
	.dc.l	scsidrvModeselect	;$2A _S_MODESELECT
	.dc.l	scsicall		;$2B _S_REZEROUNIT
	.dc.l	scsidrvRequest		;$2C _S_REQUEST
	.dc.l	scsicall		;$2D _S_SEEK
	.dc.l	scsidrvReaddma		;$2E _S_READDMA
	.dc.l	scsicall		;$2F _S_STARTSTOP
	.dc.l	scsicall		;$30 _S_SEJECT
	.dc.l	scsidrvReassign		;$31 _S_REASSIGN
	.dc.l	scsicall		;$32 _S_PAMEDIUM
	.dc.l	scsicall		;$33 
	.dc.l	scsicall		;$34 
	.dc.l	scsicall		;$35 
	.dc.l	scsicall		;$36 _S_DSKINI
	.dc.l	scsicall		;$37 _S_FORMATB
	.dc.l	scsicall		;$38 _S_BADFMT
	.dc.l	scsicall		;$39 _S_ASSIGN
scsidrvJumpTableEnd:

;----------------------------------------------------------------
;元の_SCSIDRVを呼び出す
;	Mach-2によるプリンタレディー割り込みベクタの変更をブロックする。
;<d1.l:コマンド
	.text
	.align	4,$2048
scsicall::
	move.l	PRNINT.w,-(sp)		;プリンタレディー割り込みベクタを保存
	pea.l	(@f,pc)
	move.l	vectorOldIocsScsidrv,-(sp)
	rts
@@:	move.l	(sp)+,PRNINT.w		;プリンタレディー割り込みベクタを復元
	rts

;----------------------------------------------------------------
;SRAMのソフト転送フラグをセットした状態で元の_SCSIDRVを呼び出す
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないのでそのまま呼び出す。
;<d1.l:コマンド
	.text
	.align	4,$2048
scsicallSoft::
	cmpi.w	#$000A,scsiRevisionCode
	blo	scsicall		;SRAMのソフト転送フラグに対応していない
	btst.b	#4,$00ED0070
	bne	scsicall		;既にソフト転送になっている
					;以降は終わったら無条件にOFFするので先に確認する
	move.b	#$31,$00E8E00D
	bset.b	#4,$00ED0070		;ソフト転送ON
	move.b	#$00,$00E8E00D
	bsr	scsicall		;元の_SCSIDRVを呼び出す
	move.b	#$31,$00E8E00D
	bclr.b	#4,$00ED0070		;ソフト転送OFF
	move.b	#$00,$00E8E00D
	rts

;----------------------------------------------------------------
;バッファがDMA転送可能かどうか調べる(デバイスからメモリへ転送)
;	以下の条件のいずれか1つでも成立したときDMA転送不可
;		強制ソフト転送が指定されている
;		バッファの物理アドレスが論理アドレスと異なる
;		バッファの物理アドレスがローカルメモリを指している
;<d3.l:バイト数
;<a1.l:バッファの先頭アドレス
;>n-flag:mi=DMA転送不可,pl=DMA転送可能
	.text
	.align	4,$2048
scsiDmaCheckIn::
	tst.b	forceSoftScsi
	bmi	@f
	movem.l	d0-d2,-(sp)
	moveq.l	#0,d0			;デバイスからメモリへ転送
	move.l	a1,d1
	move.l	a1,d2
	add.l	d3,d2
	bsr	dmaAccessCheck
	movem.l	(sp)+,d0-d2
@@:	rts

;----------------------------------------------------------------
;バッファがDMA転送可能かどうか調べる(メモリからデバイスへ転送)
;	以下の条件のいずれか1つでも成立したときDMA転送不可
;		強制ソフト転送が指定されている
;		バッファの物理アドレスが論理アドレスと異なる
;		バッファの物理アドレスがローカルメモリを指している
;<d3.l:バイト数
;<a1.l:バッファの先頭アドレス
;>n-flag:mi=DMA転送不可,pl=DMA転送可能
	.text
	.align	4,$2048
scsiDmaCheckOut::
	tst.b	forceSoftScsi
	bmi	@f
	movem.l	d0-d2,-(sp)
	moveq.l	#1,d0			;メモリからデバイスへ転送
	move.l	a1,d1
	move.l	a1,d2
	add.l	d3,d2
	bsr	dmaAccessCheck
	movem.l	(sp)+,d0-d2
@@:	rts

;----------------------------------------------------------------
;_S_DATAIN
;	データインフェーズの実行(DMA転送)
;	DMA転送不可のとき_S_DATAIN_Pに変更する
;<d3.l:バイト数
;<a1.l:バッファの先頭アドレス
	.text
	.align	4,$2048
scsidrvDatain::
	bsr	scsiDmaCheckIn
	bpl	scsicall		;DMA転送可能なのでこのまま実行する
	move.l	d1,-(sp)
	moveq.l	#_S_DATAIN_P,d1		;DMA転送不可なので_S_DATAIN_Pに変更する
	bsr	scsicall
	move.l	(sp)+,d1
	rts

;----------------------------------------------------------------
;_S_DATAOUT
;	データアウトフェーズの実行(DMA転送)
;	DMA転送不可のとき_S_DATAOUT_Pに変更する
;<d3.l:バイト数
;<a1.l:バッファの先頭アドレス
	.text
	.align	4,$2048
scsidrvDataout::
	bsr	scsiDmaCheckOut
	bpl	scsicall		;DMA転送可能なのでこのまま実行する
	move.l	d1,-(sp)
	moveq.l	#_S_DATAOUT_P,d1	;DMA転送不可なので_S_DATAOUT_Pに変更する
	bsr	scsicall
	move.l	(sp)+,d1
	rts

;----------------------------------------------------------------
;_S_INQUIRY
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d3.l:バイト数
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
	.text
	.align	4,$2048
scsidrvInquiry::
	bsr	scsiDmaCheckIn
	bpl	scsicall		;DMA転送可能
	bra	scsicallSoft

;----------------------------------------------------------------
;_S_READ
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号($001FFFFF=2097151以下)
;<d3.l:ブロック数($0001=1~$0100=256)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データインフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
	.text
	.align	4,$2048
scsidrvRead::
	move.l	d3,-(sp)
	lsl.l	#8,d3
	lsl.l	d5,d3			;バイト数
	bsr	scsiDmaCheckIn
	movem.l	(sp)+,d3		;フラグ保存
	bpl	scsicall		;バッファはDMA転送可能
	cmpi.w	#$000A,scsiRevisionCode
	bhs	scsicallSoft		;SRAMのソフト転送フラグが使える
	movem.l	d1-d4/a1,-(sp)		;スタック注意
	moveq.l	#_S_SELECT,d1		;セレクションフェーズ
	bsr	scsicall
	tst.l	d0
	beq	1f
	moveq.l	#_S_SELECT,d1		;リトライ
	bsr	scsicall
	tst.l	d0
	bne	8f
1:	lsl.l	#8,d3			;ブロック数<<8
	and.l	#$001FFFFF,d2		;ブロック番号
	and.l	#$00070000,d4		;LUN<<16
	lsl.l	#5,d4			;LUN<<21
	or.l	d4,d2			;(LUN<<21)|ブロック番号
	or.l	#$08000000,d2		;($08<<24)|(LUN<<21)|ブロック番号
	move.w	d3,-(sp)		;ブロック数 0(256のときは0 0)
	move.l	d2,-(sp)		;$08 LUN|ブロック番号H M L
	movea.l	sp,a1
	moveq.l	#_S_CMDOUT,d1		;コマンドアウトフェーズ
	bsr	scsicall
	addq.l	#6,sp
	tst.l	d0
	bne	8f
	lsl.l	d5,d3			;バイト数
	movea.l	(4*4,sp),a1		;バッファの先頭アドレス(スタック注意)
	moveq.l	#_S_DATAIN_P,d1		;データインフェーズ
	bsr	scsicall
	cmp.l	#-1,d0			;データインフェーズが-1を返したときは続行不可
	beq	9f
	move.l	d0,d2
	clr.l	-(sp)
	moveq.l	#_S_STSIN,d1		;ステータスインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	moveq.l	#_S_MSGIN,d1		;メッセージインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	move.l	(sp)+,d0
	bne	9f
	cmp.l	#-2,d2			;データインフェーズが転送未完了のときは-2を返す
	bne	9f
	moveq.l	#-2,d0
9:	movem.l	(sp)+,d1-d4/a1
	rts

7:	addq.l	#4,sp
8:	moveq.l	#-1,d0
	bra	9b

;----------------------------------------------------------------
;_S_WRITE
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号($001FFFFF=2097151以下)
;<d3.l:ブロック数($0001=1~$0100=256)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データアウトフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
	.text
	.align	4,$2048
scsidrvWrite::
	move.l	d3,-(sp)
	lsl.l	#8,d3
	lsl.l	d5,d3			;バイト数
	bsr	scsiDmaCheckOut
	movem.l	(sp)+,d3		;フラグ保存
	bpl	scsicall		;バッファはDMA転送可能
	cmpi.w	#$000A,scsiRevisionCode
	bhs	scsicallSoft		;SRAMのソフト転送フラグが使える
	movem.l	d1-d4/a1,-(sp)		;スタック注意
	moveq.l	#_S_SELECT,d1		;セレクションフェーズ
	bsr	scsicall
	tst.l	d0
	beq	1f
	moveq.l	#_S_SELECT,d1		;リトライ
	bsr	scsicall
	tst.l	d0
	bne	8f
1:	lsl.l	#8,d3			;ブロック数<<8
	and.l	#$001FFFFF,d2		;ブロック番号
	and.l	#$00070000,d4		;LUN<<16
	lsl.l	#5,d4			;LUN<<21
	or.l	d4,d2			;(LUN<<21)|ブロック番号
	or.l	#$0A000000,d2		;($0A<<24)|(LUN<<21)|ブロック番号
	move.w	d3,-(sp)		;ブロック数 0(256のときは0 0)
	move.l	d2,-(sp)		;$0A LUN|ブロック番号H M L
	movea.l	sp,a1
	moveq.l	#_S_CMDOUT,d1		;コマンドアウトフェーズ
	bsr	scsicall
	addq.l	#6,sp
	tst.l	d0
	bne	8f
	lsl.l	d5,d3			;バイト数
	movea.l	(4*4,sp),a1		;バッファの先頭アドレス(スタック注意)
	moveq.l	#_S_DATAOUT_P,d1	;データアウトフェーズ
	bsr	scsicall
	cmp.l	#-1,d0			;データアウトフェーズが-1を返したときは続行不可
	beq	9f
	move.l	d0,d2
	clr.l	-(sp)
	moveq.l	#_S_STSIN,d1		;ステータスインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	moveq.l	#_S_MSGIN,d1		;メッセージインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	move.l	(sp)+,d0
	bne	9f
	cmp.l	#-2,d2			;データアウトフェーズが転送未完了のときは-2を返す
	bne	9f
	moveq.l	#-2,d0
9:	movem.l	(sp)+,d1-d4/a1
	rts

7:	addq.l	#4,sp
8:	moveq.l	#-1,d0
	bra	9b

;----------------------------------------------------------------
;_S_READCAP
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
	.text
	.align	4,$2048
scsidrvReadcap::
	move.l	d3,-(sp)
	moveq.l	#8,d3			;8バイト固定
	bsr	scsiDmaCheckIn
	movem.l	(sp)+,d3		;ccr保存
	bpl	scsicall		;DMA転送可能
	bra	scsicallSoft

;----------------------------------------------------------------
;_S_READEXT,_S_WRITEEXT,_S_VERIFYEXTの分割処理ルーチン
;	16MB以上のデータを分割する。
;	_S_READEXT,_S_WRITEEXT,_S_VERIFYEXTはブロック数を65535まで指定できるが
;	実際には16MB以上を一度に転送することができない。すなわちブロックのサイズが
;	512バイトならば32767ブロックが上限となっている。
;	これはソフトウェアの都合ではなくてSPCの転送バイト数カウンタが24ビットしか
;	ないため。
;<d2.l:ブロック番号
;<d3.l:ブロック数
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;<(4,sp).l:転送処理ルーチンのアドレス
;<(8,sp).l:復帰アドレス
	.text
	.align	4,$2048
scsiCommandSplitter::
	movem.l	d1-d5/a1,-(sp)
	lsl.l	d5,d3			;バイト数>>8
	cmp.l	#$00FFFFFF>>8,d3	;サイズが小さければそのまま転送処理を行う
	bls	9f
	lsr.l	d5,d3			;ブロック数
	movem.l	d2-d3/a1,-(sp)
;<(sp):今回のブロック番号
;<(4,sp):今回の残りブロック数
;<(8,sp):今回のバッファの先頭アドレス
1:	movem.l	(12+12,sp),d4-d5	;スタック注意
	move.l	#$00FFFFFF>>8,d3
	lsr.l	d5,d3			;今回のブロック数
	sub.l	d3,(4,sp)		;次回の残りブロック数
	bpl	2f
	add.l	(4,sp),d3		;最後のブロック数
	clr.l	(4,sp)			;残りなし
2:	move.l	(sp),d2			;今回のブロック番号
	add.l	d3,(sp)			;次回のブロック番号
	movea.l	(8,sp),a1		;今回のバッファの先頭アドレス
	lsl.l	#8,d3
	lsl.l	d5,d3
	add.l	d3,(8,sp)		;次回のバッファの先頭アドレス
	lsr.l	#8,d3
	lsr.l	d5,d3
;<d2.l:今回のブロック番号
;<d3.l:今回のブロック数
;<a1.l:今回のバッファの先頭アドレス
;<(sp).l:次回のブロック番号
;<(4,sp).l:次回の残りブロック数
;<(8,sp).l:次回のバッファの先頭アドレス
  debug 'splitted(d2,d3,d4,d5,a1)=',5,d2,d3,d4,d5,a1
	jsr	([12+24,sp])		;転送実行,スタック注意
	tst.l	d0
	bne	3f			;エラー終了
	tst.l	(4,sp)			;残り転送ブロック数
	bne	1b			;残りあり
3:	lea.l	(12,sp),sp
	movem.l	(sp)+,d1-d5/a1
	addq.l	#4,sp			;転送ルーチンをスキップする
					;レジスタを復元するため最後までループの中で行う
	rts

9:	movem.l	(sp)+,d1-d5/a1
	rts

;----------------------------------------------------------------
;_S_READEXT
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号
;<d3.l:ブロック数($0000=0~$FFFF=65535)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データインフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
	.text
	.align	4,$2048
scsidrvReadext::
	bsr	scsiCommandSplitter	;分割処理
;分割処理ルーチンによって以降の処理は複数回に分けて行われることがある
	move.l	d3,-(sp)
	lsl.l	#8,d3
	lsl.l	d5,d3			;バイト数
	bsr	scsiDmaCheckIn
	movem.l	(sp)+,d3		;ccr保存
	bpl	scsicall		;バッファはDMA転送可能
	cmpi.w	#$000A,scsiRevisionCode
	bhs	scsicallSoft		;SRAMのソフト転送フラグが使える
	movem.l	d1-d4/a1,-(sp)		;スタック注意
	and.l	#$0000FFFF,d3
	beq	8f
	moveq.l	#_S_SELECT,d1		;セレクションフェーズ
	bsr	scsicall
	tst.l	d0
	beq	1f
	moveq.l	#_S_SELECT,d1		;リトライ
	bsr	scsicall
	tst.l	d0
	bne	8f
1:	lsl.l	#8,d3			;ブロック数<<8
	swap.w	d4
	and.w	#$0007,d4		;LUN
	lsl.w	#5,d4			;LUN<<5
	or.w	#$2800,d4		;($28<<8)|(LUN<<5)
	move.l	d3,-(sp)		;0 ブロック数H L 0
	move.l	d2,-(sp)		;ブロック番号HH HL LH LL
	move.w	d4,-(sp)		;($28<<8)|(LUN<<5)
	movea.l	sp,a1
	moveq.l	#_S_CMDOUT,d1		;コマンドアウトフェーズ
	bsr	scsicall
	lea.l	(10,sp),sp
	tst.l	d0
	bne	8f
	lsl.l	d5,d3			;バイト数
	movea.l	(4*4,sp),a1		;バッファの先頭アドレス(スタック注意)
	moveq.l	#_S_DATAIN_P,d1		;データインフェーズ
	bsr	scsicall
	cmp.l	#-1,d0			;データインフェーズが-1を返したときは続行不可
	beq	9f
	move.l	d0,d2
	clr.l	-(sp)
	moveq.l	#_S_STSIN,d1		;ステータスインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	moveq.l	#_S_MSGIN,d1		;メッセージインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	move.l	(sp)+,d0
	bne	9f
	cmp.l	#-2,d2			;データインフェーズが転送未完了のときは-2を返す
	bne	9f
	moveq.l	#-2,d0
9:	movem.l	(sp)+,d1-d4/a1
	rts

7:	addq.l	#4,sp
8:	moveq.l	#-1,d0
	bra	9b

;----------------------------------------------------------------
;_S_WRITEEXT
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号
;<d3.l:ブロック数($0000=0~$FFFF=65535)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データアウトフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
	.text
	.align	4,$2048
scsidrvWriteext::
	bsr	scsiCommandSplitter	;分割処理
;分割処理ルーチンによって以降の処理は複数回に分けて行われることがある
	move.l	d3,-(sp)
	lsl.l	#8,d3
	lsl.l	d5,d3			;バイト数
	bsr	scsiDmaCheckOut
	movem.l	(sp)+,d3		;ccr保存
	bpl	scsicall		;バッファはDMA転送可能
	cmpi.w	#$000A,scsiRevisionCode
	bhs	scsicallSoft		;SRAMのソフト転送フラグが使える
	movem.l	d1-d4/a1,-(sp)		;スタック注意
	and.l	#$0000FFFF,d3
	beq	8f
	moveq.l	#_S_SELECT,d1		;セレクションフェーズ
	bsr	scsicall
	tst.l	d0
	beq	1f
	moveq.l	#_S_SELECT,d1		;リトライ
	bsr	scsicall
	tst.l	d0
	bne	8f
1:	lsl.l	#8,d3			;ブロック数<<8
	swap.w	d4
	and.w	#$0007,d4		;LUN
	lsl.w	#5,d4			;LUN<<5
	or.w	#$2A00,d4		;($2A<<8)|(LUN<<5)
	move.l	d3,-(sp)		;0 ブロック数H L 0
	move.l	d2,-(sp)		;ブロック番号HH HL LH LL
	move.w	d4,-(sp)		;($2A<<8)|(LUN<<5)
	movea.l	sp,a1
	moveq.l	#_S_CMDOUT,d1		;コマンドアウトフェーズ
	bsr	scsicall
	lea.l	(10,sp),sp
	tst.l	d0
	bne	8f
	lsl.l	d5,d3			;バイト数
	movea.l	(4*4,sp),a1		;バッファの先頭アドレス(スタック注意)
	moveq.l	#_S_DATAOUT_P,d1	;データアウトフェーズ
	bsr	scsicall
	cmp.l	#-1,d0			;データアウトフェーズが-1を返したときは続行不可
	beq	9f
	move.l	d0,d2
	clr.l	-(sp)
	moveq.l	#_S_STSIN,d1		;ステータスインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	moveq.l	#_S_MSGIN,d1		;メッセージインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	move.l	(sp)+,d0
	bne	9f
	cmp.l	#-2,d2			;データアウトフェーズが転送未完了のときは-2を返す
	bne	9f
	moveq.l	#-2,d0
9:	movem.l	(sp)+,d1-d4/a1
	rts

7:	addq.l	#4,sp
8:	moveq.l	#-1,d0
	bra	9b

;----------------------------------------------------------------
;_S_VERIFYEXT
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号
;<d3.l:ブロック数($0000=0~$FFFF=65535)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データアウトフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
	.text
	.align	4,$2048
scsidrvVerifyext::
	bsr	scsiCommandSplitter	;分割処理
;分割処理ルーチンによって以降の処理は複数回に分けて行われることがある
	move.l	d3,-(sp)
	lsl.l	#8,d3
	lsl.l	d5,d3			;バイト数
	bsr	scsiDmaCheckOut
	movem.l	(sp)+,d3		;ccr保存
	bpl	scsicall		;バッファはDMA転送可能
	cmpi.w	#$000A,scsiRevisionCode
	bhs	scsicallSoft		;SRAMのソフト転送フラグが使える
	movem.l	d1-d4/a1,-(sp)		;スタック注意
	and.l	#$0000FFFF,d3
	beq	8f
	moveq.l	#_S_SELECT,d1		;セレクションフェーズ
	bsr	scsicall
	tst.l	d0
	beq	1f
	moveq.l	#_S_SELECT,d1		;リトライ
	bsr	scsicall
	tst.l	d0
	bne	8f
1:	lsl.l	#8,d3			;ブロック数<<8
	swap.w	d4
	and.w	#$0007,d4		;LUN
	lsl.w	#5,d4			;LUN<<5
	or.w	#$2F00,d4		;($2F<<8)|(LUN<<5)
	move.l	d3,-(sp)		;0 ブロック数H L 0
	move.l	d2,-(sp)		;ブロック番号HH HL LH LL
	move.w	d4,-(sp)		;($2F<<8)|(LUN<<5)
	movea.l	sp,a1
	moveq.l	#_S_CMDOUT,d1		;コマンドアウトフェーズ
	bsr	scsicall
	lea.l	(10,sp),sp
	tst.l	d0
	bne	8f
	lsl.l	d5,d3			;バイト数
	movea.l	(4*4,sp),a1		;バッファの先頭アドレス(スタック注意)
	moveq.l	#_S_DATAOUT_P,d1	;データアウトフェーズ
	bsr	scsicall
	cmp.l	#-1,d0			;データアウトフェーズが-1を返したときは続行不可
	beq	9f
	move.l	d0,d2
	clr.l	-(sp)
	moveq.l	#_S_STSIN,d1		;ステータスインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	moveq.l	#_S_MSGIN,d1		;メッセージインフェーズ
	lea.l	(1,sp),a1
	bsr	scsicall
	tst.l	d0
	bne	7f
	move.l	(sp)+,d0
	bne	9f
	cmp.l	#-2,d2			;データアウトフェーズが転送未完了のときは-2を返す
	bne	9f
	moveq.l	#-2,d0
9:	movem.l	(sp)+,d1-d4/a1
	rts

7:	addq.l	#4,sp
8:	moveq.l	#-1,d0
	bra	9b

;----------------------------------------------------------------
;_S_MODESENSE
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d2.l:bit0-5=ページコード
;	bit6-7=ページコントロール(0=カレント,1=変更可能,2=デフォルト,3=セーブ)
;<d3.l:バイト数($00=0~$FF=255)
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
scsidrvModesense	equ	scsidrvInquiry

;----------------------------------------------------------------
;_S_MODESELECT
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d2.l:bit0=SP(0=保存しない,1=保存する),bit4=PF(0=SCSI-1,1=SCSI-2)
;<d3.l:バイト数($00=0~$FF=255)
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
	.text
	.align	4,$2048
scsidrvModeselect::
	bsr	scsiDmaCheckOut
	bpl	scsicall		;DMA転送可能
	bra	scsicallSoft

;----------------------------------------------------------------
;_S_REQUEST
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d3.l:バイト数($00=0~$FF=255,0のときの挙動がSCSI-1とSCSI-2で異なる)
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
scsidrvRequest	equ	scsidrvInquiry

;----------------------------------------------------------------
;_S_REASSIGN
;	内蔵SCSI-BIOSは問題ないがMach-2がDMA転送を使おうとするのでパッチが必要
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないがDMA転送も使っていないのでそのままでよい
;<d3.l:バイト数($00=0~$FF=255)
;<d4.l:ターゲット
;<a1.l:バッファの先頭アドレス
scsidrvReassign	equ	scsidrvModeselect

;----------------------------------------------------------------
;_S_READDMA
;	DMA転送不可のときソフト転送に変更する
;	SUPERからXVICompactまでのX68000の内蔵SCSI-BIOSはSRAMのソフト転送フラグに
;	対応していないので自前で展開する
;<d2.l:ブロック番号($001FFFFF=2097151以下)
;<d3.l:ブロック数($0001=1~$0100=256)
;<d4.l:ターゲット
;<d5.l:ブロックのサイズ(0=256,1=512,2=1024)
;<a1.l:バッファの先頭アドレス
;>d0.l:
;	-1		エラー
;	-2		エラー(データインフェーズにおけるDMA転送未完了)
;	下位ワード	ステータスインフェーズの結果
;	上位ワード	メッセージインフェーズの結果
scsidrvReaddma	equ	scsidrvRead



;----------------------------------------------------------------
;
;	IOCS _PRNINTST(Mach-2対策)
;
;----------------------------------------------------------------
;----------------------------------------------------------------
;IOCS _PRNINTST
;	内蔵SCSIインタフェイスのMB89352のリセットコンディション割り込みがなぜか
;	$6Cではなく$63で入ってくることがあり、Mach-2と内蔵SCSIポートを繋いだ状態で
;	SCSIバスリセットをかけると白帯が出てしまう。そこで、Mach-2のSCSI-BIOSは
;	SCSIバスリセットの際にプリンタレディー割り込みベクタを変更して白帯が出ない
;	ように細工されている。変更されたベクタは$63EAxxxxとなって、次のようなコード
;	を指す。
;		move.b	$00E96029,$00E96029	;13F9 00E9 6029 00E9 6029
;		rte				;4E73
;	このコードは内蔵SCSIインタフェイスのMB89352のINTS(Interrupt Sense)レジスタを
;	クリアしているだけで、内蔵SCSI-BIOSのSCSI割り込みルーチンと同じ処理である。
;
;	X68030のROMはプリンタレディー割り込みベクタの使用状態を最上位バイトが0か
;	どうかで判別するので、書き換えられたベクタを未使用と認識する。しかし、
;	060turboのROMでは割り込みルーチンをハイメモリ領域に配置できるようにするために
;	ベクタの使用状態を32ビット全体でチェックするように変更されているため、
;	書き換えられたベクタを使用中と認識してしまう。その結果、060turboとMach-2を
;	併用するとプリンタレディー割り込みベクタを変更できなくなり、TeXシステムの
;	print.xなどが動作しなくなる。
;
;	$63はハイメモリのアドレスの最上位バイトと一致しないので、ベクタの最上位バイト
;	が$63かどうかで使用状態を判別するように変更することでMath-2を併用した場合に
;	_PRNINTSTが機能しなくなる問題を回避する。
;	これだけでは既にプリンタレディー割り込みを使用している状態でSCSIバスリセット
;	を行うとプリンタレディー割り込みベクタが破壊されてしまうが、それは_SCSIDRV側
;	で対処する。
;
;<a1.l:プリンタのレディー割り込み処理ルーチンのアドレス(0=解除)
;>d0.l:結果
;	0	正常終了
;	その他	使用中なので設定できない(現在の処理ルーチンのアドレス)
	.text
	.align	4,$2048
iocsPrnintst::
	move.l	a0,-(sp)
	move.w	sr,-(sp)
	ori.w	#$0700,sr		;割り込み禁止
	moveq.l	#PRNINT>>2,d0
	lea.l	PRNINT.w,a0
	cmpa.w	#0,a1			;tst.l a1
	beq	1f			;解除する
	cmp.b	(a0),d0			;最上位バイトだけ比較する
	bne	2f			;使用中なので設定できない
;未使用なので設定する
	move.l	a1,(a0)			;設定する
	bset.b	#0,$00E9C001		;プリンタ割り込み許可
8:	moveq.l	#0,d0
9:	move.w	(sp)+,sr
	movea.l	(sp)+,a0
	rts

;解除する
1:	bclr.b	#0,$00E9C001		;プリンタ割り込み禁止
	move.l	#((PRNINT>>2)<<24)+defaultPrnint,(a0)	;解除する
	bra	8b

;使用中なので設定できない
2:	move.l	(a0),d0			;取得する
	bra	9b

;----------------------------------------------------------------
;デフォルトのプリンタレディー割り込み処理ルーチン
;	$00xxxxxxのアドレスに配置して$63000000を加えたベクタを設定する
	.text
	.align	4,$2048
defaultPrnint::
	rte				;何もしない

;白帯を出すとき
;	moveq.l	#$63,d7			;ベクタ番号
;	movea.l	sp,a6
;	trap	#14
;@@:	IOCS	_ABORTJOB
;	bra	@b