Subject: kern/7252: pcscp timed out on writing to a tape with large blocksize
To: None <gnats-bugs@gnats.netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 03/26/1999 21:34:47
>Number:         7252
>Category:       kern
>Synopsis:       pcscp timed out on writing to a tape with large blocksize
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Mar 26 08:05:02 1999
>Last-Modified:
>Originator:     Izumi Tsutsui
>Organization:
Izumi Tsutsui	Himeji City, Japan
>Release:        NetBSD-current supped on 19990323
>Environment:
System: NetBSD mirage 1.3K NetBSD 1.3K (MIRAGE) #60: Wed Mar 24 20:49:49 JST \
1999 root@:/usr/src/sys/arch/i386/compile/MIRAGE i386

>Description:
This problem was reported by Roger Brooks <R.S.Brooks@liv.ac.uk>.

According to his report, the pscsp driver got time out message
on writing data to the Exabyte tape drive with >4k blocksize,
though reading tapes with large blocks is no problem.

>How-To-Repeat:
Write large blocks to the tape device on pcscp.
(Although I have no tape devices...)

>Fix:
There were two bugs in pcscp.c.

* resid in pcscp_dma_intr() should also be set in the data out phase.
* Don't set up DMA in the transfer pad operations.

I sent a patch to fix these bugs to Roger, and he have comfirmed
that the problem has been fixed. Thanks, Roger!

The following patch also contains other minor fixes.

* Change URL of the PDF technical manual to the index page.
* include <machine/bswap.h> on big endian machines.

--- sys/dev/pci/pcscp.c.orig	Sat Jan  9 21:17:00 1999
+++ sys/dev/pci/pcscp.c	Thu Mar 25 21:40:22 1999
@@ -42,7 +42,7 @@
  * written by Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
  *
  * Technical manual available at
- * http://www.amd.com/products/npd/techdocs/19113a.pdf
+ * http://www.amd.com/products/npd/techdocs/techdocs.html
  */
 
 #include <sys/param.h>
@@ -52,6 +52,9 @@
 
 #include <machine/bus.h>
 #include <machine/intr.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#include <machine/bswap.h>
+#endif
 
 #include <dev/scsipi/scsi_all.h>
 #include <dev/scsipi/scsipi_all.h>
@@ -434,13 +437,20 @@
 				(NCR_READ_REG(sc, NCR_TCM) << 8),
 			NCR_READ_REG(sc, NCR_TCL),
 			NCR_READ_REG(sc, NCR_TCM)));
-		WRITE_DMAREG(esc, DMA_CMD, DMACMD_IDLE |
-			     (datain ? DMACMD_DIR : 0));
-		bus_dmamap_unload(esc->sc_dmat, dmap);
 		return 0;
 	}
 
 	resid = 0;
+	/*
+	 * If a transfer onto the SCSI bus gets interrupted by the device
+	 * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
+	 * as residual since the ESP counter registers get decremented as
+	 * bytes are clocked into the FIFO.
+	 */
+	if (!datain &&
+	    (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
+                NCR_DMA(("pcscp_dma_intr: empty esp FIFO of %d ", resid));
+	}
 
 	if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
 		/*
@@ -555,9 +565,11 @@
 #endif
 
 	/*
-	 * XXX should handle `Transfer Pad' operation?
+	 * No need to set up DMA in `Transfer Pad' operation. 
 	 * (case of *dmasize == 0)
 	 */
+	if (*dmasize == 0)
+		return 0;
 
 	error = bus_dmamap_load(esc->sc_dmat, dmap, *esc->sc_dmaaddr,
 				*esc->sc_dmalen, NULL,
@@ -630,6 +642,10 @@
 	struct pcscp_softc *esc = (struct pcscp_softc *)sc;
 	bus_dmamap_t dmap = esc->sc_xfermap, mdldmap = esc->sc_mdldmap;
 	int datain = esc->sc_datain;
+
+	/* No DMA transfer in Transfer Pad operation */
+	if (esc->sc_dmasize == 0)
+		return;
 
 	/* sync transfer buffer */
 	bus_dmamap_sync(esc->sc_dmat, dmap, 0, dmap->dm_mapsize,

>Audit-Trail:
>Unformatted: