HuBASICでSCSI制御をしたときのプログラムの一部です。
まず、セレクション。
変数TARGETに、セレクションしたいデバイスのIDを設定します。
1440 OUT PCTL,&H0 'START Selection Phase"INRS"はMB89352のINTSです。BASICの予約語とぶつかり"INTS"に出来ないため。
1450 WAIT SSTS,&B11110000,&B11111111
1460 OUT SCTL,(INP(SCTL) OR &B10000) 'Arbitration Enable
1470 OUT TEMP,(INP(BDID) OR 2^TARGET)
1480 OUT TCH,&HF
1490 OUT TCM,&H46
1500 OUT TCL,&H4
1510 OUT INRS,INP(INRS)
1520 OUT SCMD,&B100000 'Command Code = Select
1530 WAIT INRS,&B10100
1540 R=INP(INRS):OUT INRS,INP(INRS)
1550 IF R<>&B10000 THEN PRINT"Selection Error[";BIN$(R);"]":GOTO"ERR"
バス制御は全てMB89352がやってくれるので、BASICではその結果を見ているだけです。
データイン動作は、変数TLENに転送バイト数、変数MBASEに読み込むメモリのアドレスを入れます。
1810 OUT TCH,0SSTSを見て、FIFOバッファが空でなければDREGからデータを受け取ります。 この1バイト受け取るために、SSTSを監視する方法は非常に遅く、『まずい!ぶっ壊れたか?』と思わせるくらいのインパクトがあります。
1820 OUT TCM,(TLEN AND &HFF00)\&H100
1830 OUT TCL,TLEN AND &HFF
1840 WAIT PSNS,&B10000000 'REQ待ち
1850 IF (INP(PSNS) AND &B111)<>&B1 THEN PRINT"Data In Phase Error":GOTO"ERR"
1860 OUT PCTL,&B1 'Set Data In Phase
1870 OUT INRS,INP(INRS)
1880 OUT SCMD,&B10000100 'Command Code = Transfer
1890 WHILE (INP(SSTS) AND &B11110000)<>&B10110000
1900 WEND
1910 FOR X=1 TO TLEN
1920 WAIT SSTS,&B1,&B1
1930 POKE MBASE+X-1,INP(DREG)
1940 NEXT
1950 WAIT INRS,&HFF
1960 R=INP(INRS):OUT INRS,INP(INRS)
1970 IF R<>&B10000 THEN PRINT"Data In Error[";BIN$(r);"]":GOTO"ERR"
高速化したい場合には、SSTSのバッファフルを見て8バイト毎転送するようにすると良いです…とは言うものの、BASICでの高速化は意味がありません…素直にマシン語かDMAで。