Subject: Re: CVS commit: syssrc/sys/dev/ic
To: Chuck Silvers <chuq@chuq.com>
From: Charles Hannum <abuse@spamalicious.com>
List: source-changes
Date: 09/24/2002 13:40:51
> this change causes my ultra2 to panic:

I didn't realize quite how broken the driver was.  Could you try the
following patch?

I had to do a hack for the config flags, because there aren't enough
bits, but I figure most people just turn them on or off for all
devices anyway...


Index: ncr53c9x.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/ncr53c9x.c,v
retrieving revision 1.99
diff -u -r1.99 ncr53c9x.c
--- ncr53c9x.c	2002/09/24 13:29:44	1.99
+++ ncr53c9x.c	2002/09/24 13:38:50
@@ -200,7 +200,20 @@
 	struct scsipi_adapter *adapt = &sc->sc_adapter;
 	struct scsipi_channel *chan = &sc->sc_channel;
 
-	callout_init(&sc->sc_watchdog);
+	/*
+	 * Note, the front-end has set us up to print the chip variation.
+	 */
+	if (sc->sc_rev >= NCR_VARIANT_MAX) {
+		printf("\n%s: unknown variant %d, devices not attached\n",
+		    sc->sc_dev.dv_xname, sc->sc_rev);
+		return;
+	}
+
+	printf(": %s, %dMHz, SCSI ID %d\n",
+	    ncr53c9x_variant_names[sc->sc_rev], sc->sc_freq, sc->sc_id);
+
+	sc->sc_ntarg = (sc->sc_rev == NCR_VARIANT_FAS366) ? 16 : 8;
+
 	/*
 	 * Allocate SCSI message buffers.
 	 * Front-ends can override allocation to avoid alignment
@@ -213,22 +226,14 @@
 	if (sc->sc_imess == NULL)
 		sc->sc_imess = malloc(NCR_MAX_MSG_LEN + 1, M_DEVBUF, M_NOWAIT);
 
-	if (sc->sc_omess == NULL || sc->sc_imess == NULL) {
-		printf("out of memory\n");
-		return;
-	}
+	sc->sc_tinfo = malloc(sc->sc_ntarg * sizeof(sc->sc_tinfo[0]));
 
-	/*
-	 * Note, the front-end has set us up to print the chip variation.
-	 */
-	if (sc->sc_rev >= NCR_VARIANT_MAX) {
-		printf("\n%s: unknown variant %d, devices not attached\n",
-		    sc->sc_dev.dv_xname, sc->sc_rev);
+	if (!sc->sc_omess || !sc->sc_imess || !sc->sc_tinfo) {
+		printf("out of memory\n");
 		return;
 	}
 
-	printf(": %s, %dMHz, SCSI ID %d\n",
-	    ncr53c9x_variant_names[sc->sc_rev], sc->sc_freq, sc->sc_id);
+	callout_init(&sc->sc_watchdog);
 
 	/*
 	 * Treat NCR53C90 with the 86C01 DMA chip exactly as ESP100
@@ -277,11 +282,7 @@
 	chan->chan_adapter = adapt;
 	chan->chan_bustype = &scsi_bustype;
 	chan->chan_channel = 0;
-#if 0 /* XXX */
-	chan->chan_ntargets = (sc->sc_rev == NCR_VARIANT_FAS366) ? 16 : 8;
-#else
-	chan->chan_ntargets = 8;
-#endif
+	chan->chan_ntargets = sc->sc_ntarg;
 	chan->chan_nluns = 8;
 	chan->chan_id = sc->sc_id;
 
@@ -449,7 +450,7 @@
 		TAILQ_INIT(&sc->ready_list);
 		sc->sc_nexus = NULL;
 		memset(sc->sc_tinfo, 0, sizeof(sc->sc_tinfo));
-		for (r = 0; r < NCR_NTARG; r++) {
+		for (r = 0; r < sc->sc_ntarg; r++) {
 			LIST_INIT(&sc->sc_tinfo[r].luns);
 		}
 	} else {
@@ -461,7 +462,7 @@
 			ncr53c9x_done(sc, ecb);
 		}
 		/* Cancel outstanding disconnected commands on each LUN */
-		for (r = 0; r < 8; r++) {
+		for (r = 0; r < sc->sc_ntarg; r++) {
 			LIST_FOREACH(li, &sc->sc_tinfo[r].luns, link) {
 				if ((ecb = li->untagged) != NULL) {
 					li->untagged = NULL;
@@ -492,13 +493,13 @@
 	ncr53c9x_reset(sc);
 
 	sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
-	for (r = 0; r < 8; r++) {
+	for (r = 0; r < sc->sc_ntarg; r++) {
 		struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[r];
 /* XXX - config flags per target: low bits: no reselect; high bits: no synch */
 
-		ti->flags = ((sc->sc_minsync && !(sc->sc_cfflags & (1<<(r+8))))
+		ti->flags = ((sc->sc_minsync && !(sc->sc_cfflags & (1<<((r&7)+8))))
 		    ? 0 : T_SYNCHOFF) |
-		    ((sc->sc_cfflags & (1<<r)) ? T_RSELECTOFF : 0);
+		    ((sc->sc_cfflags & (1<<(r&7))) ? T_RSELECTOFF : 0);
 #ifdef DEBUG
 		if (ncr53c9x_notag)
 			ti->flags &= ~T_TAG;
@@ -905,7 +906,7 @@
 		ti->period = 0;
 		ti->offset = 0;
 
-		if ((sc->sc_cfflags & (1<<(xm->xm_target+16))) == 0 &&
+		if ((sc->sc_cfflags & (1<<((xm->xm_target&7)+16))) == 0 &&
 		    (xm->xm_mode & PERIPH_CAP_TQING)) {
 			NCR_MISC(("%s: target %d: tagged queuing\n",
 			    sc->sc_dev.dv_xname, xm->xm_target));
@@ -2921,7 +2922,8 @@
 			/* XXX ASYNC CALLBACK! */
 			scsipi_printaddr(periph);
 			printf("sync negotiation disabled\n");
-			sc->sc_cfflags |= (1 << (periph->periph_target + 8));
+			sc->sc_cfflags |=
+			    (1 << ((periph->periph_target & 7) + 8));
 			ncr53c9x_update_xfer_mode(sc, periph->periph_target);
 		}
 	}
@@ -2941,7 +2943,7 @@
 	time_t old = time.tv_sec - (10 * 60);
 
 	s = splbio();
-	for (t = 0; t < NCR_NTARG; t++) {
+	for (t = 0; t < sc->sc_ntarg; t++) {
 		ti = &sc->sc_tinfo[t];
 		li = LIST_FIRST(&ti->luns);
 		while (li) {
Index: ncr53c9xvar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/ncr53c9xvar.h,v
retrieving revision 1.37
diff -u -r1.37 ncr53c9xvar.h
--- ncr53c9xvar.h	2002/08/26 06:23:32	1.37
+++ ncr53c9xvar.h	2002/09/24 13:38:50
@@ -70,7 +70,6 @@
 /* #define NCR53C9X_DEBUG		1 */
 
 /* Wide or differential can have 16 targets */
-#define NCR_NTARG		8
 #define NCR_NLUN		8
 
 #define	NCR_ABORT_TIMEOUT	2000	/* time to wait for abort */
@@ -299,7 +298,8 @@
 		ready_list;
 
 	struct ncr53c9x_ecb *sc_nexus;		/* Current command */
-	struct ncr53c9x_tinfo sc_tinfo[NCR_NTARG];
+	int	sc_ntarg;
+	struct ncr53c9x_tinfo *sc_tinfo;
 
 	/* Data about the current nexus (updated for every cmd switch) */
 	caddr_t	sc_dp;		/* Current data pointer */