misc/060tsys/t16scsi.s- Source code ソースコード - XEiJ - STUDIO KAMADA
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

STUDIO KAMADA
Copyright © 1999-2026 Makoto Kamada