From owner-freebsd-stable Tue Apr 29 08:39:05 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id IAA21423 for stable-outgoing; Tue, 29 Apr 1997 08:39:05 -0700 (PDT) Received: from pluto.plutotech.com (root@pluto100.plutotech.com [206.168.67.137]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id IAA21418; Tue, 29 Apr 1997 08:38:59 -0700 (PDT) Received: from narnia.plutotech.com (narnia.plutotech.com [206.168.67.130]) by pluto.plutotech.com (8.8.5/8.8.3) with ESMTP id JAA27224; Tue, 29 Apr 1997 09:38:47 -0600 (MDT) Message-Id: <199704291538.JAA27224@pluto.plutotech.com> X-Mailer: exmh version 2.0beta 12/23/96 To: "David O'Brien" cc: gibbs@freebsd.org, stable@freebsd.org Subject: Re: AHA-2940U problem in -STABLE In-reply-to: Your message of "Tue, 29 Apr 1997 01:49:44 PDT." <19970429014944.36331@dragon.nuxi.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Tue, 29 Apr 1997 10:37:15 -0600 From: "Justin T. Gibbs" Sender: owner-stable@freebsd.org X-Loop: FreeBSD.org Precedence: bulk >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 ----