Subject: port-mac68k/2921: Some SCSI devices do not work in interrupt driven xfer mode
To: None <gnats-bugs@gnats.netbsd.org>
From: Paul Goyette <paul@pgoyette.bdt.com>
List: netbsd-bugs
Date: 11/07/1996 05:48:51
>Number:         2921
>Category:       port-mac68k
>Synopsis:       Some SCSI devices do not work in interrupt driven xfer mode
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Nov  7 06:05:01 1996
>Last-Modified:
>Originator:     Paul Goyette
>Organization:
>Release:        Nov 5, 1996
>Environment:
System: NetBSD pgoyette.bdt.com 1.2B NetBSD 1.2B (PGOYETTE) #108: 
	Tue Nov 5 06:08:28 PST 1996 
	paul@pgoyette.bdt.com:/home/paul/src/sys/arch/mac68k/compile/PGOYETTE 
	(current as of Tue Nov 5 04:29:12 1996) mac68k
>Description:
	Some devices, such as Exabyte 8200 tape drive, do not work well
	in interrupt-driven transfer mode.  Mine, for example, always ends
	up writing a null (0x00) byte in the next-to-last byte of every
	transfer!  This is obviously a vagary of the mac68k SCSI hardware
	and this using a SCSI "quirk" is not appropriate to fix this, since
	quirks are processed in the MI portions of the SCSI drivers.
>How-To-Repeat:
	Standard mac68k SCSI driver and Exabyte 8200 - just write to the 
	tape, then dump the dump!
>Fix:
	The patch below implements two new kernel compilation options that,
	when defined, force specific SCSI targets to use only the polled
	transfer mode.  If the options are undefined, the driver behaves 
	exactlyu as it does without the patch.  Two separate options are
	defined, one for Reads and one for Writes, since this problem can
	occur for one but not the other.  (My tape drive only exhibits the
	problem on Writes;  Reads work just fine in interrupt mode.)


*** /usr/src/sys/arch/mac68k/dev/mac68k5380.c	Fri Jun  7 04:39:26 1996
--- /home/paul/src/sys/arch/mac68k/dev/mac68k5380.c	Sun Jul 14 10:05:28 1996
***************
*** 123,128 ****
--- 123,148 ----
  static volatile u_char	*ncr_5380_with_drq	= (volatile u_char *)  0x6000;
  static volatile u_char	*ncr_5380_without_drq	= (volatile u_char *) 0x12000;
  
+ /*
+  * Define flags to force use of pio rather than pdma.
+  * We only define the flags if one or the other is needed 
+  * and when we check them in transfer_pdma(), we skip the
+  * check if neither flag is needed.
+  */
+ 
+ #ifdef	NCR_PIO_WRITE
+ #ifdef	NCR_PIO_READ
+ static	u_int8_t	ncr5380_use_pio[2] = { NCR_PIO_WRITE,
+ 					       NCR_PIO_READ };
+ #else	/* def NCR_PIO_READ */
+ static	u_int8_t	ncr5380_use_pio[2] = { NCR_PIO_WRITE, 0 };
+ #endif	/* def NCR_PIO_READ */
+ #else	/* def NCR_PIO_WRITE */
+ #ifdef	NCR_PIO_READ
+ static	u_int8_t	ncr5380_use_pio[2] = { 0, NCR_PIO_READ };
+ #endif	/* def NCR_PIO_READ */
+ #endif	/* def NCR_PIO_WRITE */
+ 
  #define SCSI_5380		((struct scsi_5380 *) ncr)
  #define GET_5380_REG(rnum)	SCSI_5380->scsi_5380[((rnum)<<4)]
  #define SET_5380_REG(rnum,val)	(SCSI_5380->scsi_5380[((rnum)<<4)] = (val))
***************
*** 550,558 ****
  	PID("transfer_pdma0")
  
  	/*
!  	 * Don't bother with PDMA if we can't sleep or for small transfers.
   	 */
! 	if (reqp->dr_flag & DRIVER_NOINT) {
  		PID("pdma, falling back to transfer_pio.")
  		transfer_pio(phasep, data, count, 0);
  		return -1;
--- 570,583 ----
  	PID("transfer_pdma0")
  
  	/*
!  	 * Don't bother with PDMA if we can't sleep or if 
! 	 * target is flagged as needing to use pio.
   	 */
! 	if   ((reqp->dr_flag & DRIVER_NOINT)
! #if	defined(NCR_PIO_READ) || defined(NCR_PIO_WRITE)
! 	  ||  (ncr5380_use_pio[(*phasep == PH_DATAOUT) ?1 : 0] & (1 << reqp->targ_id))
! #endif
! 	      ) {
  		PID("pdma, falling back to transfer_pio.")
  		transfer_pio(phasep, data, count, 0);
  		return -1;
>Audit-Trail:
>Unformatted: