Subject: port-sun3/2168: sun3: xd driver dies on boot
To: None <gnats-bugs@NetBSD.ORG>
From: Don Koch <aardvark@poirot.krl.com>
List: netbsd-bugs
Date: 03/03/1996 18:47:53
>Number:         2168
>Category:       port-sun3
>Synopsis:       Xylogics 753 (xd) driver dies during boot
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Mar  3 19:05:03 1996
>Last-Modified:
>Originator:     Don Koch
>Organization:
	Koch Research Labs
>Release:        NetBSD-current-960302
>Environment:
	Sun 3/280, NetBSD-current, sun3, na
System: NetBSD poirot 1.1A NetBSD 1.1A (SMD_DMK) #2: Sun Mar 3 17:32:02 EST 1996 aardvark@poirot:/usr/src/sys/arch/sun3/compile/SMD_DMK sun3


>Description:
	xd driver dies with bad dvma_kvtopa() call:
Jan 30 19:09:26 poirot /netbsd: xdc0 at vmel0 addr 0xffffee80 level 2 vector 0x44panic: dvma_kvtopa: bad dmva addr=0x0
Jan 30 19:09:26 poirot /netbsd: 
Jan 30 19:09:26 poirot /netbsd: trap type=0x0, code=0x145, v=0x37006442
Jan 30 19:09:26 poirot /netbsd: kernel: Bus error trap
Jan 30 19:09:26 poirot /netbsd: syncing disks... trap type=0x8, code=0x145, v=0x0
Jan 30 19:09:27 poirot /netbsd: kernel: MMU fault trap
Jan 30 19:09:27 poirot /netbsd: trap during panic!

	Problem stems from (a) not checking pointers for null before using
	them (twice!) and (b) trying to |= into a virtual write only address
	(the control and status register is status when read, control when
	written; |= reads the status, ors in a bit and then writes it back
	out as a control code with semi-meaningless results).

>How-To-Repeat:
	Configure with xd driver, add one Xylogics 753/7053, boot well.
>Fix:
	Apply following patch:
--- xd.c.org	Thu Feb 22 07:42:00 1996
+++ xd.c	Sun Mar  3 18:31:49 1996
@@ -143,7 +143,7 @@
 	(ADDR) = ((ADDR) >> 8); \
 	(XDC)->xdc_iopbaddr3 = (ADDR); \
 	(XDC)->xdc_iopbamod = XDC_ADDRMOD; \
-	(XDC)->xdc_csr |= XDC_ADDIOPB; /* go! */ \
+	(XDC)->xdc_csr = XDC_ADDIOPB; /* go! */ \
 }
 
 /*
@@ -402,9 +402,9 @@
 		dvma_kvtopa((long) xdc->iopbase, BUS_VME32);
 	xdc->reqs = (struct xd_iorq *)
 	    malloc(XDC_MAXIOPB * sizeof(struct xd_iorq), M_DEVBUF, M_NOWAIT);
-	bzero(xdc->reqs, XDC_MAXIOPB * sizeof(struct xd_iorq));
 	if (xdc->reqs == NULL)
 		panic("xdc malloc");
+	bzero(xdc->reqs, XDC_MAXIOPB * sizeof(struct xd_iorq));
 
 	/* init free list, iorq to iopb pointers, and non-zero fields in the
 	 * iopb which never change. */
@@ -1257,8 +1257,8 @@
 			block = block / iorq->xd->nhead;
 			iopb->cylno = block;
 		}
-		dp = dvma_kvtopa((long)iorq->dbuf, BUS_VME32);
-		iopb->daddr = dp = (iorq->dbuf == NULL) ? 0 : dp;
+		iopb->daddr = dp = (iorq->dbuf == NULL) ? 0 :
+		  dvma_kvtopa((long)iorq->dbuf, BUS_VME32);
 		iopb->addrmod = XDC_ADDRMOD;
 	}
 }
@@ -1646,7 +1646,7 @@
 		if (del <= 0)
 			panic("xdc_reset");
 	} else {
-		xdcsc->xdc->xdc_csr |= XDC_CLRRIO;	/* clear RIO */
+		xdcsc->xdc->xdc_csr = XDC_CLRRIO;	/* clear RIO */
 	}
 	bcopy(&tmpiopb, xdcsc->iopbase, sizeof(tmpiopb));
 }
@@ -1815,7 +1815,7 @@
 	 * done bit.
 	 */
 	if (xdc->xdc_csr & XDC_REMIOPB) {
-		xdc->xdc_csr |= XDC_CLRRIO;
+		xdc->xdc_csr = XDC_CLRRIO;
 	}
 
 	for (rqno = 0; rqno < XDC_MAXIOPB; rqno++) {

>Audit-Trail:
>Unformatted: