Subject: IMPORTANT: bug in asc driver in 1.2 release
To: None <port-pmax@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: port-pmax
Date: 10/03/1996 21:06:44
The 1.2 release of the ASC driver for the NCR 53c94 chip used in
TurboChannel DECstations has a bug.

The following patch should be applied to the 1.2 source tree before
re-building a kernel.  I am not sure what the official stance on
building an updated kernel, with this patch applied, is, given
that the release is   now stepping  out the door...


following 
Index: src/sys/dev/tc/asc.c

*** 1.1	1996/08/03 11:42:43
--- asc.c	1996/09/29 01:22:04
***************
*** 128,133 ****
--- 128,134 ----
  #include <sys/buf.h>
  #include <sys/conf.h>
  #include <sys/errno.h>
+ #include <sys/kernel.h>
  #include <sys/device.h>
  #include <sys/reboot.h>
  
***************
*** 198,203 ****
--- 199,205 ----
   */
  static void asc_reset();
  static void asc_startcmd();
+ static void asc_timeout();
  
  #ifdef DEBUG
  int	asc_debug = 1;
***************
*** 734,739 ****
--- 736,747 ----
  		splx(s);
  	}
  	asc->cmd[sdp->sd_drive] = scsicmd;
+ 	/*
+ 	 * Kludge: use a 60 second timeout if data is being transfered,
+ 	 * otherwise use a 30 minute timeout.
+ 	 */
+ 	timeout(asc_timeout, scsicmd, hz * (scsicmd->buflen == 0 ?
+ 	    1800 : 60));
  	asc_startcmd(asc, sdp->sd_drive);
  	splx(s);
  }
***************
*** 1451,1456 ****
--- 1459,1465 ----
  	scsicmd = asc->cmd[target];
  	asc->cmd[target] = (ScsiCmd *)0;
  	state = &asc->st[target];
+ 	untimeout(asc_timeout, scsicmd);
  
  #ifdef DEBUG
  	if (asc_debug > 1) {
***************
*** 1544,1556 ****
  		state->buflen -= len;
  	}
  
- #ifdef DEBUG
  	if (!(state->flags & DMA_IN_PROGRESS) &&
  	    (regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 0) {
! 		printf("asc_dma_in: FIFO count %x flags %x\n",
! 		    regs->asc_flags, state->flags);
  	}
- #endif
  	/* setup to start reading the next chunk */
  	len = state->buflen;
  #ifdef DEBUG
--- 1553,1588 ----
  		state->buflen -= len;
  	}
  
  	if (!(state->flags & DMA_IN_PROGRESS) &&
  	    (regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 0) {
! 	  	volatile int async_fifo_junk = 0;
! 
! 		/*
! 		 * If the target is asynchronous, the FIFO contains
! 		 * a byte of garbage. (see the Mach mk84 53c94 driver,
! 		 * where this occurs on tk-50s and exabytes.)
! 		 * It also occurs on  asynch disks like SCSI-1 disks.
! 		 * Recover by reading the byte of junk from the fifo if,
! 		 * and only if, the target is async. If the target is
! 		 * synch, there is no junk, and reading the fifo
! 		 * deadlocks our SCSI state machine.
! 		 */
! 		 if (state->sync_offset == 0)
! 			async_fifo_junk = regs->asc_fifo;
! #ifdef DEBUG
! 		printf("%s: asc_dma_in: FIFO count %x flags %x sync_offset %d",
! 		    asc->sc_dev.dv_xname, regs->asc_flags,
! 		       state->flags, state->sync_offset);
! 		if (state->sync_offset != 0)
! 			printf("\n");
! 		else
! 			printf(" unexpected fifo data %x\n", async_fifo_junk);
! #ifdef DIAGNOSTIC
! 		asc_DumpLog("asc_dma_in");
! #endif	/* DIAGNOSTIC */
! #endif	/* DEBUG */
! 
  	}
  	/* setup to start reading the next chunk */
  	len = state->buflen;
  #ifdef DEBUG
***************
*** 2245,2250 ****
--- 2277,2300 ----
  			}
  		}
  	}
+ }
+ 
+ void
+ asc_timeout(arg)
+ 	void *arg;
+ {
+ 	int s = splbio();
+ 	ScsiCmd *scsicmd = (ScsiCmd *) arg;
+ 
+ 	printf("asc_timeout: cmd %p drive %d\n", scsicmd, scsicmd->sd->sd_drive);
+ #ifdef DEBUG
+ 	asc_DumpLog("asc_timeout");
+ #endif
+ #if 0
+ 	panic("asc_timeout");
+ #else
+ 	boot(4); /* XXX */
+ #endif
  }
  
  #ifdef notdef