diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c index ead323b3f73..45ad7935878 100644 --- a/sys/i386/scsi/aic7xxx.c +++ b/sys/i386/scsi/aic7xxx.c @@ -2,7 +2,7 @@ * Generic driver for the aic7xxx based adaptec SCSI controllers * Product specific probe and attach routines can be found in: * i386/eisa/aic7770.c 27/284X and aic7770 motherboard controllers - * pci/aic7870.c 3940, 2940, aic7870 and aic7850 controllers + * pci/aic7870.c 3940, 2940, aic7880, aic7870 and aic7850 controllers * * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs. * All rights reserved. @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx.c,v 1.73 1996/06/08 06:55:01 gibbs Exp $ + * $Id: aic7xxx.c,v 1.74 1996/06/09 17:29:35 gibbs Exp $ */ /* * TODO: @@ -537,11 +537,11 @@ ahc_scsirate(ahc, scsirate, period, offset, channel, target ) continue; } *scsirate = (ahc_syncrates[i].sxfr) | (offset & 0x0f); + /* * Ensure Ultra mode is set properly for * this target. */ - ultra_enb_addr = ULTRA_ENB; if(channel == 'B' || target > 7) ultra_enb_addr++; @@ -792,7 +792,7 @@ ahc_run_waiting_queues(ahc) ahc_send_scb(ahc, scb); /* Mark this as an active command */ - scb->flags = SCB_ACTIVE; + scb->flags ^= SCB_ASSIGNEDQ|SCB_ACTIVE; AHC_OUTB(ahc, QINFIFO, scb->position); if (!(scb->xs->flags & SCSI_NOMASK)) { @@ -815,8 +815,7 @@ ahc_run_waiting_queues(ahc) break; /* - * Advance disc_scb to the next on in the - * list. + * Check the next SCB on in the list. */ AHC_OUTB(ahc, SCBPTR, disc_scb); next_scb = AHC_INB(ahc, SCB_NEXT); @@ -852,7 +851,7 @@ ahc_run_waiting_queues(ahc) ahc_page_scb(ahc, out_scbp, scb); /* Mark this as an active command */ - scb->flags = SCB_ACTIVE; + scb->flags ^= SCB_WAITINGQ|SCB_ACTIVE; /* Queue the command */ AHC_OUTB(ahc, QINFIFO, scb->position); @@ -1019,11 +1018,12 @@ ahc_intr(arg) outscb = ahc->assigned_scbs.stqh_first; STAILQ_REMOVE_HEAD(&ahc->assigned_scbs, links); + outscb->flags ^= SCB_ASSIGNEDQ + |SCB_WAITINGQ; scb->position = outscb->position; outscb->position = SCB_LIST_NULL; STAILQ_INSERT_HEAD(&ahc->waiting_scbs, outscb, links); - outscb->flags = SCB_WAITINGQ; AHC_OUTB(ahc, SCBPTR, scb->position); ahc_send_scb(ahc, scb); scb->flags &= ~SCB_PAGED_OUT; @@ -1110,7 +1110,7 @@ ahc_intr(arg) outscb->position = SCB_LIST_NULL; STAILQ_INSERT_HEAD(&ahc->waiting_scbs, outscb, links); - outscb->flags = SCB_WAITINGQ; + outscb->flags |= SCB_WAITINGQ; ahc_send_scb(ahc, scb); scb->flags &= ~SCB_PAGED_OUT; } @@ -1506,7 +1506,7 @@ pagein_done: */ sc_print_addr(xs->sc_link); printf("Queue Full\n"); - scb->flags = SCB_ASSIGNEDQ; + scb->flags |= SCB_ASSIGNEDQ; STAILQ_INSERT_TAIL(&ahc->assigned_scbs, scb, links); break; @@ -2289,49 +2289,49 @@ static int32_t ahc_scsi_cmd(xs) struct scsi_xfer *xs; { - struct scb *scb; - struct ahc_dma_seg *sg; - int seg; /* scatter gather seg being worked on */ - int thiskv; - physaddr thisphys, nextphys; - int bytes_this_seg, bytes_this_page, datalen, flags; - struct ahc_data *ahc; + struct scb *scb; + struct ahc_dma_seg *sg; + int seg; /* scatter gather seg being worked on */ + int thiskv; + physaddr thisphys, nextphys; + int bytes_this_seg, bytes_this_page, datalen, flags; + struct ahc_data *ahc; u_short mask; - int s; + int s; ahc = (struct ahc_data *)xs->sc_link->adapter_softc; - mask = (0x01 << (xs->sc_link->target + mask = (0x01 << (xs->sc_link->target #if defined(__FreeBSD__) | ((u_long)xs->sc_link->fordriver & 0x08))); #elif defined(__NetBSD__) | (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0) )); #endif - SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n")); - /* - * get an scb to use. If the transfer - * is from a buf (possibly from interrupt time) - * then we can't allow it to sleep - */ - flags = xs->flags; - if (flags & ITSDONE) { - printf("%s: Already done?", ahc_name(ahc)); - xs->flags &= ~ITSDONE; - } - if (!(flags & INUSE)) { - printf("%s: Not in use?", ahc_name(ahc)); - xs->flags |= INUSE; - } - if (!(scb = ahc_get_scb(ahc, flags))) { - xs->error = XS_DRIVER_STUFFUP; - return (TRY_AGAIN_LATER); - } - SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb)); - scb->xs = xs; - if (flags & SCSI_RESET) + SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n")); + /* + * get an scb to use. If the transfer + * is from a buf (possibly from interrupt time) + * then we can't allow it to sleep + */ + flags = xs->flags; + if (flags & ITSDONE) { + printf("%s: Already done?", ahc_name(ahc)); + xs->flags &= ~ITSDONE; + } + if (!(flags & INUSE)) { + printf("%s: Not in use?", ahc_name(ahc)); + xs->flags |= INUSE; + } + if (!(scb = ahc_get_scb(ahc, flags))) { + xs->error = XS_DRIVER_STUFFUP; + return (TRY_AGAIN_LATER); + } + SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb)); + scb->xs = xs; + if (flags & SCSI_RESET) scb->flags |= SCB_DEVICE_RESET|SCB_IMMED; - /* - * Put all the arguments for the xfer in the scb - */ + /* + * Put all the arguments for the xfer in the scb + */ if(ahc->tagenable & mask) { scb->control |= TAG_ENB; @@ -2464,7 +2464,7 @@ ahc_scsi_cmd(xs) AHC_OUTB(ahc, SCBPTR, curscb); AHC_OUTB(ahc, QINFIFO, scb->position); UNPAUSE_SEQUENCER(ahc); - scb->flags = SCB_ACTIVE; + scb->flags |= SCB_ACTIVE; if (!(flags & SCSI_NOMASK)) { timeout(ahc_timeout, (caddr_t)scb, (xs->timeout * hz) / 1000); @@ -2472,7 +2472,7 @@ ahc_scsi_cmd(xs) SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n")); } else { - scb->flags = SCB_WAITINGQ; + scb->flags |= SCB_WAITINGQ; STAILQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links); ahc_run_waiting_queues(ahc); } @@ -2512,7 +2512,11 @@ ahc_free_scb(ahc, scb, flags) opri = splbio(); + /* Clean up for the next user */ scb->flags = SCB_FREE; + scb->control = 0; + scb->status = 0; + if(scb->position == SCB_LIST_NULL) { STAILQ_INSERT_HEAD(&ahc->page_scbs, scb, links); if(!scb->links.stqe_next && !ahc->free_scbs.stqh_first) @@ -2530,10 +2534,10 @@ ahc_free_scb(ahc, scb, flags) * or when we start another command. */ else if((wscb = ahc->waiting_scbs.stqh_first) != NULL) { - wscb->position = scb->position; STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links); + wscb->position = scb->position; STAILQ_INSERT_HEAD(&ahc->assigned_scbs, wscb, links); - wscb->flags = SCB_ASSIGNEDQ; + wscb->flags ^= SCB_WAITINGQ|SCB_ASSIGNEDQ; /* * The "freed" SCB will need to be assigned a slot @@ -2551,9 +2555,6 @@ ahc_free_scb(ahc, scb, flags) } else { STAILQ_INSERT_HEAD(&ahc->free_scbs, scb, links); -#ifdef AHC_DEBUG - ahc->activescbs--; -#endif if(!scb->links.stqe_next && !ahc->page_scbs.stqh_first) /* * If there were no SCBs availible, wake anybody waiting @@ -2561,6 +2562,9 @@ ahc_free_scb(ahc, scb, flags) */ wakeup((caddr_t)&ahc->free_scbs); } +#ifdef AHC_DEBUG + ahc->activescbs--; +#endif splx(opri); } @@ -2590,7 +2594,7 @@ ahc_get_scb(ahc, flags) else if((scbp = ahc->page_scbs.stqh_first)) { STAILQ_REMOVE_HEAD(&ahc->page_scbs, links); } - else if (ahc->numscbs < ahc->maxscbs) { + else if(ahc->numscbs < ahc->maxscbs) { scbp = (struct scb *) malloc(sizeof(struct scb), M_TEMP, M_NOWAIT); if (scbp) { @@ -2622,17 +2626,14 @@ ahc_get_scb(ahc, flags) break; } - if (scbp) { - scbp->control = 0; - scbp->status = 0; - scbp->flags = 0; #ifdef AHC_DEBUG + if (scbp) { ahc->activescbs++; if((ahc_debug & AHC_SHOWSCBCNT) && (ahc->activescbs == ahc->maxhscbs)) printf("%s: Max SCBs active\n", ahc_name(ahc)); -#endif } +#endif splx(opri); @@ -2642,7 +2643,7 @@ ahc_get_scb(ahc, flags) static void ahc_loadseq(ahc) struct ahc_data *ahc; { - static unsigned char seqprog[] = { + static u_char seqprog[] = { # include "aic7xxx_seq.h" };