Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Apr 1997 10:37:15 -0600
From:      "Justin T. Gibbs" <gibbs@plutotech.com>
To:        "David O'Brien" <obrien@NUXI.com>
Cc:        gibbs@freebsd.org, stable@freebsd.org
Subject:   Re: AHA-2940U problem in -STABLE 
Message-ID:  <199704291538.JAA27224@pluto.plutotech.com>
In-Reply-To: Your message of "Tue, 29 Apr 1997 01:49:44 PDT." <19970429014944.36331@dragon.nuxi.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
>Hi Justin,
>
>I'm having a little problem with my AHA-2940.  I can no longer use my
>Exbyte 8505 8mm drive to back up my SCSI hard drive.  Using a 2.2-STABLE
>kernel in single user mode from 4/24 I got:
>
>
>DUMP: 91.33% done, finished in 0:03
>st0(ahc0:4:0): SCB 0x2 - timeed out while idle, LASTPHASE == 0x1, SCSISIGI == 
>0x0
>SEQADDR == 0x8

My guess is that you are using the rewindind device and that the rewind is
taking longer than the st driver allows (5 minutes I think) causing the
initial timeout.  This is the first problem.

>st0(ahc0:4:0): Queueing an Abort SCB
>st0(ahc0:4:0): Abort Mesasge sent
>st0(ahc0:4:0): SCB 2 - Abort Completed
>st0(ahc0:4:0): no longer in timeout
>DUMP: End of tape detected
>sd0(ahc0:0:0): SCB 0x1 - timed out in message out phase, SCSISIGI == 0x0
>SEQADDR == 0x0
>sd0(ahc0:0:0): SCB 1: Yucky Immediate reset. Flags = 0x1
>sd0(ahc0:0:0): no longer in timeout
>sd0(ahc0:0:0): Issued Channel A Bus Reset.  3 SCBs aborted.
>
>
>And then the machine froze (not even a panic).

This is bug #2.  For some reason, the recovery code is botching it.  Can
you try the attached patch and see if the recovery code behaves correctly?
Once I get the recovery code to work for you, you should be able to bump
up the timeout in scsi/st.c:st_rewind and make the problem completly go
away.

>Note, that Dump shouldn't
>have detected EOT as I was dumping a 2gig partition on a tape that should
>hold 5gig minium.  I've used this tape to backup the SCSI drive before,
>even while multiuser.  So I think it has something to do with an aic7xxx
>change.  Maybe?

My guess is that you have more data to dump now, making the rewind take
longer, which is why you are just now running into this problem.

>-- 
>-- David	(obrien@NUXI.com  -or-  obrien@FreeBSD.org)

--
Justin T. Gibbs
===========================================
  FreeBSD: Turning PCs into workstations
===========================================

Index: i386/scsi/aic7xxx.c
===================================================================
RCS file: /usr/cvs/src/sys/i386/scsi/aic7xxx.c,v
retrieving revision 1.118
diff -c -r1.118 aic7xxx.c
*** aic7xxx.c	1997/04/26 05:03:18	1.118
--- aic7xxx.c	1997/04/29 16:31:33
***************
*** 178,191 ****
  					  int unpause_always));
  static inline void restart_sequencer __P((struct ahc_softc *ahc));
  
- static int	timeouts_work;		/*
- 					 * Boolean that lets the driver know
- 					 * that it can safely use timeouts
- 					 * for event scheduling.  Timeouts
- 					 * don't work early in the boot
- 					 * process.
- 					 */
- 
  #define AHC_BUSRESET_DELAY	1000	/* Reset delay in us */
  #define AHC_BUSSETTLE_DELAY (100 * 1000)/* Delay before taking commands
  					 * after a reset in us
--- 178,183 ----
***************
*** 308,314 ****
  static void	ahc_clear_intstat __P((struct ahc_softc *ahc));
  static void	ahc_reset_current_bus __P((struct ahc_softc *ahc));
  static void	ahc_run_done_queue __P((struct ahc_softc *ahc));
- static void	ahc_untimeout_done_queue __P((struct ahc_softc *ahc));
  static void	ahc_scsirate __P((struct ahc_softc* ahc, u_int8_t *scsirate,
  				  u_int8_t *period, u_int8_t *offset,
  				  char channel, int target));
--- 300,305 ----
***************
*** 319,333 ****
  static void	ahc_timeout __P((void *));
  #endif
  
- static timeout_t
- 		ahc_first_timeout;
- 
- static timeout_t
- 		ahc_busreset_complete;
- 
- static timeout_t
- 		ahc_busreset_settle_complete;
- 
  static u_int8_t	ahc_index_busy_target __P((struct ahc_softc *ahc, int target,
  					   char channel, int unbusy));
  
--- 310,315 ----
***************
*** 489,500 ****
  	ahc->flags = flags;
  	ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
  	ahc->pause = ahc->unpause | PAUSE;
- 
- 	ahc->busreset_args.ahc = ahc;
- 	ahc->busreset_args.bus = 'A';
- 	ahc->busreset_args_b.ahc = ahc;
- 	ahc->busreset_args_b.bus = 'B';
- 
  #if defined(__FreeBSD__)
  	return (ahc);
  #endif
--- 471,476 ----
***************
*** 2326,2334 ****
  
  	unpause_sequencer(ahc, /*unpause_always*/TRUE);
  
- 	/* Notify us when the system can handle timeouts */
- 	timeout(ahc_first_timeout, NULL, 0);
- 
  	/*
  	 * Note that we are going and return (to probe)
  	 */
--- 2302,2307 ----
***************
*** 2377,2399 ****
  	SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
  	flags = xs->flags;
  
- 	if (ahc->in_reset != 0) {
- 		/*
- 		 * If we are still in a reset, send the transaction
- 		 * back indicating that it was aborted due to a
- 		 * reset.
- 		 */
- 		if ((IS_SCSIBUS_B(ahc, xs->sc_link)
- 		  && (ahc->in_reset & CHANNEL_B_RESET) != 0)
- 		 || (!IS_SCSIBUS_B(ahc, xs->sc_link)
- 		  && (ahc->in_reset & CHANNEL_A_RESET) != 0)) {
- 			/* Ick, but I don't want it to abort this */
- 			xs->retries++;
- 		 	xs->error = XS_BUSY;
- 			return(COMPLETE);
- 		}
- 	}
- 
  	/*
  	 * get an scb to use. If the transfer
  	 * is from a buf (possibly from interrupt time)
--- 2350,2355 ----
***************
*** 2893,2911 ****
  	return (0);
  }
  
- /*
-  * Handler to register that the system is capable of
-  * delivering timeouts.  We register this timeout in
-  * ahc_init and it should go off as soon as we're through
-  * the boot process.
-  */
- static void
- ahc_first_timeout(arg)
- 	void	*arg;
- {
- 	timeouts_work = 1;
- }
- 
  static void
  ahc_timeout(arg)
  	void	*arg;
--- 2849,2854 ----
***************
*** 3654,3714 ****
  	ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
  	scsiseq = ahc_inb(ahc, SCSISEQ);
  	ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
! 	if (timeouts_work != 0) {
! 		struct ahc_busreset_args *args;
! 
! 		sblkctl = ahc_inb(ahc, SBLKCTL);
! 		args = (sblkctl & SELBUSB) ? &ahc->busreset_args_b
! 					   : &ahc->busreset_args;
! 		ahc->in_reset |= (args->bus == 'A' ? CHANNEL_A_RESET
! 						   : CHANNEL_B_RESET);
! 		timeout(ahc_busreset_complete, args,
! 			MAX((AHC_BUSRESET_DELAY * hz) / 1000000, 1));
! 	} else {
! 		DELAY(AHC_BUSRESET_DELAY);
! 		/* Turn off the bus reset */
! 		ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
! 
! 		ahc_clear_intstat(ahc);
! 
! 		/* Re-enable reset interrupts */
! 		ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
! 
! 		/* Wait a minimal bus settle delay */
! 		DELAY(AHC_BUSSETTLE_DELAY);
! 
! 		ahc_run_done_queue(ahc);
! 	}
! }
! 
! static void
! ahc_busreset_complete(arg)
! 	void	*arg;
! {
! 	struct	 ahc_busreset_args *args;
! 	struct	 ahc_softc *ahc;
! 	int	 s;
! 	u_int8_t scsiseq;
! 	u_int8_t sblkctl;
! 
! 	args = (struct ahc_busreset_args *)arg;
! 	ahc = (struct ahc_softc *)args->ahc;
! 
! 	s = splbio();
! 	pause_sequencer(ahc);
! 
! 	/* Save the current block control state */
! 	sblkctl = ahc_inb(ahc, SBLKCTL);
! 
! 	/* Switch to the right bus */
! 	if (args->bus == 'A')
! 		ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
! 	else
! 		ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
! 
  	/* Turn off the bus reset */
- 	printf("Clearing bus reset\n");
- 	scsiseq = ahc_inb(ahc, SCSISEQ);
  	ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
  
  	ahc_clear_intstat(ahc);
--- 3597,3604 ----
  	ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
  	scsiseq = ahc_inb(ahc, SCSISEQ);
  	ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
! 	DELAY(AHC_BUSRESET_DELAY);
  	/* Turn off the bus reset */
  	ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
  
  	ahc_clear_intstat(ahc);
***************
*** 3716,3752 ****
  	/* Re-enable reset interrupts */
  	ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
  
! 	/*
! 	 * Set a 100ms timeout to clear our in_reset flag.
! 	 * It will be *at-least* that long before any targets
! 	 * respond to real commands on the bus.
! 	 */
! 	timeout(ahc_busreset_settle_complete, args,
! 		(AHC_BUSSETTLE_DELAY * hz) / 1000000);
! 
! 	/* Restore the original channel */
! 	ahc_outb(ahc, SBLKCTL, sblkctl);
! 	unpause_sequencer(ahc, /*unpause_always*/FALSE);
! 	splx(s);
! }
! 
! static void
! ahc_busreset_settle_complete(arg)
! 	void	*arg;
! {
! 	struct	ahc_busreset_args *args;
! 	struct	ahc_softc *ahc;
! 	int	s;
! 
! 	args = (struct ahc_busreset_args *)arg;
! 	ahc = (struct ahc_softc *)args->ahc;
! 	/* Clear the reset flag */
! 	s = splbio();
! 	printf("Clearing 'in-reset' flag\n");
! 	ahc->in_reset &= (args->bus == 'A' ? ~CHANNEL_A_RESET
! 					   : ~CHANNEL_B_RESET);
! 	ahc_run_done_queue(ahc);
! 	splx(s);
  }
  
  static int
--- 3606,3613 ----
  	/* Re-enable reset interrupts */
  	ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
  
! 	/* Wait a minimal bus settle delay */
! 	DELAY(AHC_BUSSETTLE_DELAY);
  }
  
  static int
***************
*** 3831,3848 ****
  		ahc_clear_intstat(ahc);
  		restart_sequencer(ahc);
  	}
! 	/*
! 	 * Untimeout our scbs now in case we have to delay our done
! 	 * processing.
! 	 */
! 	ahc_untimeout_done_queue(ahc);
! 	if (initiate_reset == 0) {
! 		/*
! 		 * If we initiated the reset, we'll run the queue
! 		 * once our bus-settle delay has expired.
! 		 */
! 		ahc_run_done_queue(ahc);
! 	}
  	return found;
  }
  
--- 3692,3698 ----
  		ahc_clear_intstat(ahc);
  		restart_sequencer(ahc);
  	}
! 	ahc_run_done_queue(ahc);
  	return found;
  }
  
***************
*** 3860,3879 ****
  	}
  }
  	
- static void
- ahc_untimeout_done_queue(ahc)
- 	struct ahc_softc *ahc;
- {
- 	int i;
- 	struct scb *scbp;
- 	
- 	for (i = 0; i < ahc->scb_data->numscbs; i++) {
- 		scbp = ahc->scb_data->scbarray[i];
- 		if (scbp->flags & SCB_QUEUED_FOR_DONE) 
- 			untimeout(ahc_timeout, (caddr_t)scbp);
- 	}
- }
- 
  static int
  ahc_match_scb (scb, target, channel, lun, tag)
  	struct	 scb *scb;
--- 3710,3715 ----
Index: i386/scsi/aic7xxx.h
===================================================================
RCS file: /usr/cvs/src/sys/i386/scsi/aic7xxx.h,v
retrieving revision 1.40
diff -c -r1.40 aic7xxx.h
*** aic7xxx.h	1997/02/25 03:05:35	1.40
--- aic7xxx.h	1997/04/29 16:28:40
***************
*** 228,238 ****
  					 */
  };
  
- struct ahc_busreset_args {
- 	struct	ahc_softc *ahc;
- 	char	bus;
- };
- 
  struct ahc_softc {
  #if defined(__FreeBSD__)
  	int	unit;
--- 228,233 ----
***************
*** 249,256 ****
  #endif
  	volatile u_int8_t *maddr;
  	struct	scb_data *scb_data;
- 	struct	ahc_busreset_args	busreset_args;
- 	struct	ahc_busreset_args	busreset_args_b;
  	struct	scsi_link sc_link;
  	struct	scsi_link sc_link_b;	/* Second bus for Twin channel cards */
  	STAILQ_HEAD(, scb) waiting_scbs;/*
--- 244,249 ----
***************
*** 289,297 ****
  	u_int8_t	unpause;
  	u_int8_t	pause;
  	u_int8_t	in_timeout;
- 	u_int8_t	in_reset;
- #define	CHANNEL_A_RESET		0x01
- #define	CHANNEL_B_RESET		0x02
  };
  
  struct full_ahc_softc {
--- 282,287 ----





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199704291538.JAA27224>