[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fujitsu MB87030/MB89352 (SPC) manual



<20040814.224538.42042213.oshimaya@sc.starcat.ne.jp>の記事において
oshimaya@sc.starcat.ne.jpさんは書きました。

> rev 1.32のNO_MANUAL_XFERが有効なままのカーネルで試すと
> <PIONEER, CD-ROM DR-U03S, 1.01>のcd1 を認識する時にspc_datain_pio()
> でpanicします(cd0のCW-7501は認識する)。
 :
> NO_MANUAL_XFERを無くしたカーネルだと正常に起動します。

NO_MANUAL_XFER を定義すると、
(1)message in phase の spc_msgin() で DATA XFER コマンドを使う
(2)status phase のとき spc_datain_pio() を呼んで DATA XFER コマンドを使う
の 2つが変わります。定義されていない時はいずれも TEMP register 経由の
マニュアル転送を使います。

NO_MANUAL_XFER を定義した時に CD-ROM の probe で panic するのは
上記(2)のところの話だと思います。以前の変更で同じ問題があった時に
http://www.jp.netbsd.org/ja/JP/ml/tech-misc-ja/200401/msg00001.html
で直ったことからすると、問題が起きるデバイスの場合はステータスを
受け取る前に INTS レジスタがゼロ以外になっている、つまり
ステータスを受け取る前に bus free になっているもしくは phase が
status phase 以外に移行していて、 spc_datain_pio() では
ステータスが受け取れてないんじゃないかという気がします。
(acb->target_stat は spc_scsipi_request() で 0 に初期化されてるので
 エラーが起きない限りは問題にならない)

一方、 NO_MANUAL_XFER を定義しない時に井崎さんの sd0 が
途中で反応しなくなるというのは trace の出力からすると
busy loop で待っているわけではなくて SCSI の転送が終わって
いないのにドライバの状態がおかしくなって終わったものと
扱われてしまっているような感じです。こちらの hp300 でいろいろ
試してみると spc_msgin() を抜ける条件がおかしいとそういうことが
起こり得るということは観測できたので NO_MANUAL_XFER のありなしで
何が違うのか調べたところ、現状の rev 1.32 の NO_MANUAL_XFER なしの
ときのコードだと PSNS register の phase だけを見ていて bus free を
見ていませんでした。
(NO_MANUAL_XFER の時は PCTL register の PCTL_BFINT_ENAB を
 立てているので bus free で INTS レジスタが非ゼロになる)

#本来の規格通りの message が返ってきていればこのへんのコードは
#関係しないと思うんですが、まだいまいち SCSI をわかってないです……

ひとまず (1) の対処で PSNS register の BSY のチェックを追加して、
(2) の対処でそもそも status phase では spc_datain_pio() を
使わないようにしたパッチを作ってみたので、
a) NO_MANUAL_XFER を定義した場合
b) NO_MANUAL_XFER を定義しない場合
のそれぞれで現状問題になっているデバイスでとうなるか
試してもらえないでしょうか。

PSNS register で BSY を見てれば SSTS register の SSTS_INITIATOR を
見る必要はないような気がしますがひとまず両方チェックしてます。
あと、各 busy loop に DELAY(1) が追加されてるのはなんとなくです……。

さらに、現状の spc_intr() では対応する割り込みの処理をしてなくても
無条件に 1 を返していたのを直していますが、 x68k は割り込みハンドラで
割り込みルーチンの返り値を見てないようなのでこれも関係ないですよね……。
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

Index: mb89352.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/mb89352.c,v
retrieving revision 1.32
diff -u -r1.32 mb89352.c
--- mb89352.c	12 Aug 2004 03:39:11 -0000	1.32
+++ mb89352.c	5 Sep 2004 08:31:18 -0000
@@ -1004,19 +1004,18 @@
 		}
 		msg = bus_space_read_1(iot, ioh, DREG);
 #else
-		if ((bus_space_read_1(iot, ioh, PSNS) & PSNS_ATN) != 0)
-			bus_space_write_1(iot, ioh, SCMD, SCMD_RST_ATN);
-
 		while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) == 0) {
-			/* XXX needs timeout */
-			if ((bus_space_read_1(iot, ioh, PSNS) & PH_MASK)
-			     != PH_MSGIN)
+			if ((bus_space_read_1(iot, ioh, PSNS) &
+			    (PSNS_BSY|PH_MASK)) != (PSNS_BSY|PH_MSGIN) ||
+			    (bus_space_read_1(iot, ioh, SSTS) & SSTS_INITIATOR)
+			    == 0)
 				/*
 				 * Target left MESSAGE IN, probably because it
 				 * a) noticed our ATN signal, or
 				 * b) ran out of messages.
 				 */
 				goto out;
+			DELAY(1); /* XXX needs timeout */
 		}
 
 		bus_space_write_1(iot, ioh, PCTL, PH_MSGIN);
@@ -1056,7 +1055,7 @@
 		/* Ack the last byte read. */
 		bus_space_write_1(iot, ioh, SCMD, SCMD_SET_ACK);
 		while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) != 0)
-			continue;	/* XXX needs timeout */
+			DELAY(1);	/* XXX needs timeout */
 		bus_space_write_1(iot, ioh, SCMD, SCMD_RST_ACK);
 #endif
 	}
@@ -1233,7 +1232,7 @@
 	/* Ack the last message byte. */
 	bus_space_write_1(iot, ioh, SCMD, SCMD_SET_ACK);
 	while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) != 0)
-		continue;	/* XXX needs timeout */
+		DELAY(1);	/* XXX needs timeout */
 	bus_space_write_1(iot, ioh, SCMD, SCMD_RST_ACK);
 #endif
 
@@ -1425,7 +1424,7 @@
 #endif
 
 		while ((bus_space_read_1(iot, ioh, SSTS) & SSTS_DREG_FULL) != 0)
-			;
+			DELAY(1);
 		/* Send message byte. */
 		bus_space_write_1(iot, ioh, DREG, *--sc->sc_omp);
 		--n;
@@ -1497,6 +1496,7 @@
 			break;
 		if (bus_space_read_1(iot, ioh, INTS) != 0)
 			break;
+		DELAY(1);
 	}
 
 	/*
@@ -1516,6 +1516,7 @@
 			/* Break on interrupt. */
 			if (intstat != 0)
 				goto phasechange;
+			DELAY(1);
 		}
 
 		xfer = min(DOUTAMOUNT, n);
@@ -1546,6 +1547,7 @@
 			/* Break on interrupt. */
 			if (intstat != 0)
 				goto phasechange;
+			DELAY(1);
 		}
 	}
 
@@ -1643,6 +1645,7 @@
 					goto phasechange;
 				intstat = bus_space_read_1(iot, ioh, INTS);
 			}
+			DELAY(1);
 		}
 		SPC_MISC(("extra data  "));
 	}
@@ -1674,18 +1677,18 @@
 	struct spc_tinfo *ti;
 	int n;
 
+	SPC_TRACE(("spc_intr  "));
+
+	ints = bus_space_read_1(iot, ioh, INTS);
+	if (ints == 0)
+		return 0;
+
 	/*
 	 * Disable interrupt.
 	 */
 	bus_space_write_1(iot, ioh, SCTL,
 	    bus_space_read_1(iot, ioh, SCTL) & ~SCTL_INTR_ENAB);
 
-	SPC_TRACE(("spc_intr  "));
-
-	ints = bus_space_read_1(iot, ioh, INTS);
-	if (ints == 0)
-		goto out;
-
 	if (sc->sc_dma_done != NULL &&
 	    sc->sc_state == SPC_CONNECTED &&
 	    (sc->sc_flags & SPC_DOINGDMA) != 0 &&
@@ -1943,7 +1946,7 @@
 	bus_space_write_1(iot, ioh, INTS, ints);
 	ints = 0;
 	while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) == 0)
-		delay(1);	/* need timeout XXX */
+		DELAY(1);	/* need timeout XXX */
 #endif
 
 	/*
@@ -2027,20 +2030,16 @@
 		SPC_ASSERT(sc->sc_nexus != NULL);
 		acb = sc->sc_nexus;
 
-#ifdef NO_MANUAL_XFER
-		spc_datain_pio(sc, &acb->target_stat, 1);
-#else
 		if ((bus_space_read_1(iot, ioh, PSNS) & PSNS_ATN) != 0)
 			bus_space_write_1(iot, ioh, SCMD, SCMD_RST_ATN);
 		while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) == 0)
-			continue;	/* XXX needs timeout */
+			DELAY(1);	/* XXX needs timeout */
 		bus_space_write_1(iot, ioh, PCTL, PH_STAT);
 		acb->target_stat = bus_space_read_1(iot, ioh, TEMP);
 		bus_space_write_1(iot, ioh, SCMD, SCMD_SET_ACK);
 		while ((bus_space_read_1(iot, ioh, PSNS) & PSNS_REQ) != 0)
-			continue;	/* XXX needs timeout */
+			DELAY(1);	/* XXX needs timeout */
 		bus_space_write_1(iot, ioh, SCMD, SCMD_RST_ACK);
-#endif
 
 		SPC_MISC(("target_stat=0x%02x  ", acb->target_stat));
 		sc->sc_prevphase = PH_STAT;