root/dev/ic/osiop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. osiop_attach
  2. osiop_minphys
  3. osiop_scsicmd
  4. osiop_poll
  5. osiop_sched
  6. osiop_scsidone
  7. osiop_abort
  8. osiop_init
  9. osiop_reset
  10. osiop_resetbus
  11. osiop_start
  12. osiop_checkintr
  13. osiop_select
  14. osiop_intr
  15. osiop_update_xfer_mode
  16. scsi_period_to_osiop
  17. osiop_timeout
  18. osiop_dump_trace
  19. osiop_dump_acb
  20. osiop_dump

    1 /*      $OpenBSD: osiop.c,v 1.29 2007/06/20 18:02:39 miod Exp $ */
    2 /*      $NetBSD: osiop.c,v 1.9 2002/04/05 18:27:54 bouyer Exp $ */
    3 
    4 /*
    5  * Copyright (c) 2001 Izumi Tsutsui.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Copyright (c) 1994 Michael L. Hitch
   32  * Copyright (c) 1990 The Regents of the University of California.
   33  * All rights reserved.
   34  *
   35  * This code is derived from software contributed to Berkeley by
   36  * Van Jacobson of Lawrence Berkeley Laboratory.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  *      @(#)siop.c      7.5 (Berkeley) 5/4/91
   63  */
   64 
   65 /*
   66  * MI NCR53C710 scsi adaptor driver; based on arch/amiga/dev/siop.c:
   67  *      NetBSD: siop.c,v 1.43 1999/09/30 22:59:53 thorpej Exp
   68  *
   69  * bus_space/bus_dma'fied by Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
   70  */
   71 
   72 #include <sys/cdefs.h>
   73 /* __KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.9 2002/04/05 18:27:54 bouyer Exp $"); */
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/device.h>
   78 #include <sys/malloc.h>
   79 #include <sys/buf.h>
   80 #include <sys/kernel.h>
   81 
   82 #include <scsi/scsi_all.h>
   83 #include <scsi/scsiconf.h>
   84 #include <scsi/scsi_message.h>
   85 
   86 #include <machine/cpu.h>
   87 #include <machine/bus.h>
   88 
   89 #include <dev/ic/osiopreg.h>
   90 #include <dev/ic/osiopvar.h>
   91 
   92 /* 53C710 script */
   93 #include <dev/microcode/siop/osiop.out>
   94 
   95 void osiop_attach(struct osiop_softc *);
   96 void osiop_minphys(struct buf *);
   97 int osiop_scsicmd(struct scsi_xfer *xs);
   98 void osiop_poll(struct osiop_softc *, struct osiop_acb *);
   99 void osiop_sched(struct osiop_softc *);
  100 void osiop_scsidone(struct osiop_acb *, int);
  101 void osiop_abort(struct osiop_softc *, const char *);
  102 void osiop_init(struct osiop_softc *);
  103 void osiop_reset(struct osiop_softc *);
  104 void osiop_resetbus(struct osiop_softc *);
  105 void osiop_start(struct osiop_softc *);
  106 int osiop_checkintr(struct osiop_softc *, u_int8_t, u_int8_t, u_int8_t, int *);
  107 void osiop_select(struct osiop_softc *);
  108 void osiop_update_xfer_mode(struct osiop_softc *, int);
  109 void scsi_period_to_osiop(struct osiop_softc *, int);
  110 void osiop_timeout(void *);
  111 
  112 int osiop_reset_delay = 250;    /* delay after reset, in milliseconds */
  113 
  114 /* #define OSIOP_DEBUG */
  115 #ifdef OSIOP_DEBUG
  116 #define DEBUG_DMA       0x0001
  117 #define DEBUG_INT       0x0002
  118 #define DEBUG_PHASE     0x0004
  119 #define DEBUG_DISC      0x0008
  120 #define DEBUG_CMD       0x0010
  121 #define DEBUG_SYNC      0x0020
  122 #define DEBUG_SCHED     0x0040
  123 #define DEBUG_ALL       0xffff
  124 int osiop_debug = 0; /*DEBUG_ALL;*/
  125 int osiopstarts = 0;
  126 int osiopints = 0;
  127 int osiopphmm = 0;
  128 int osiop_trix = 0;
  129 #define OSIOP_TRACE_SIZE        128
  130 #define OSIOP_TRACE(a,b,c,d)    do {                            \
  131         osiop_trbuf[osiop_trix + 0] = (a);                      \
  132         osiop_trbuf[osiop_trix + 1] = (b);                      \
  133         osiop_trbuf[osiop_trix + 2] = (c);                      \
  134         osiop_trbuf[osiop_trix + 3] = (d);                      \
  135         osiop_trix = (osiop_trix + 4) & (OSIOP_TRACE_SIZE - 1); \
  136 } while (0)
  137 u_int8_t osiop_trbuf[OSIOP_TRACE_SIZE];
  138 void osiop_dump_trace(void);
  139 void osiop_dump_acb(struct osiop_acb *);
  140 void osiop_dump(struct osiop_softc *);
  141 #else
  142 #define OSIOP_TRACE(a,b,c,d)
  143 #endif
  144 
  145 #ifdef OSIOP_DEBUG
  146 /*
  147  * sync period transfer lookup - only valid for 66MHz clock
  148  */
  149 static struct {
  150         u_int8_t p;     /* period from sync request message */
  151         u_int8_t r;     /* siop_period << 4 | sbcl */
  152 } sync_tab[] = {
  153         { 60/4, 0<<4 | 1},
  154         { 76/4, 1<<4 | 1},
  155         { 92/4, 2<<4 | 1},
  156         { 92/4, 0<<4 | 2},
  157         {108/4, 3<<4 | 1},
  158         {116/4, 1<<4 | 2},
  159         {120/4, 4<<4 | 1},
  160         {120/4, 0<<4 | 3},
  161         {136/4, 5<<4 | 1},
  162         {140/4, 2<<4 | 2},
  163         {152/4, 6<<4 | 1},
  164         {152/4, 1<<4 | 3},
  165         {164/4, 3<<4 | 2},
  166         {168/4, 7<<4 | 1},
  167         {180/4, 2<<4 | 3},
  168         {184/4, 4<<4 | 2},
  169         {208/4, 5<<4 | 2},
  170         {212/4, 3<<4 | 3},
  171         {232/4, 6<<4 | 2},
  172         {240/4, 4<<4 | 3},
  173         {256/4, 7<<4 | 2},
  174         {272/4, 5<<4 | 3},
  175         {300/4, 6<<4 | 3},
  176         {332/4, 7<<4 | 3}
  177 };
  178 #endif
  179 
  180 struct cfdriver osiop_cd = {
  181         NULL, "osiop", DV_DULL
  182 };
  183 
  184 struct scsi_adapter osiop_adapter = {
  185         osiop_scsicmd,
  186         osiop_minphys,
  187         NULL,
  188         NULL,
  189 };
  190 
  191 struct scsi_device osiop_dev = {
  192         NULL,
  193         NULL,
  194         NULL,
  195         NULL,
  196 };
  197 
  198 void
  199 osiop_attach(sc)
  200         struct osiop_softc *sc;
  201 {
  202         struct scsibus_attach_args saa;
  203         struct osiop_acb *acb;
  204         bus_dma_segment_t seg;
  205         int nseg;
  206         int i, err;
  207 
  208         /*
  209          * Allocate and map DMA-safe memory for the script.
  210          */
  211         err = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
  212             &seg, 1, &nseg, BUS_DMA_NOWAIT);
  213         if (err) {
  214                 printf(": failed to allocate script memory, err=%d\n", err);
  215                 return;
  216         }
  217         err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, PAGE_SIZE,
  218             (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
  219         if (err) {
  220                 printf(": failed to map script memory, err=%d\n", err);
  221                 return;
  222         }
  223         err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
  224             BUS_DMA_NOWAIT, &sc->sc_scrdma);
  225         if (err) {
  226                 printf(": failed to create script map, err=%d\n", err);
  227                 return;
  228         }
  229         err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma,
  230             &seg, nseg, PAGE_SIZE, BUS_DMA_NOWAIT);
  231         if (err) {
  232                 printf(": failed to load script map, err=%d\n", err);
  233                 return;
  234         }
  235         bzero(sc->sc_script, PAGE_SIZE);
  236 
  237         /*
  238          * Copy and sync script
  239          */
  240         memcpy(sc->sc_script, osiop_script, sizeof(osiop_script));
  241         bus_dmamap_sync(sc->sc_dmat, sc->sc_scrdma, 0, sizeof(osiop_script),
  242             BUS_DMASYNC_PREWRITE);
  243 
  244         /*
  245          * Allocate and map DMA-safe memory for the script data structure.
  246          */
  247         err = bus_dmamem_alloc(sc->sc_dmat,
  248             sizeof(struct osiop_ds) * OSIOP_NACB, PAGE_SIZE, 0,
  249             &seg, 1, &nseg, BUS_DMA_NOWAIT);
  250         if (err) {
  251                 printf(": failed to allocate ds memory, err=%d\n", err);
  252                 return;
  253         }
  254         err = bus_dmamem_map(sc->sc_dmat, &seg, nseg,
  255             sizeof(struct osiop_ds) * OSIOP_NACB, (caddr_t *)&sc->sc_ds,
  256             BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
  257         if (err) {
  258                 printf(": failed to map ds memory, err=%d\n", err);
  259                 return;
  260         }
  261         err = bus_dmamap_create(sc->sc_dmat,
  262             sizeof(struct osiop_ds) * OSIOP_NACB, 1,
  263             sizeof(struct osiop_ds) * OSIOP_NACB, 0,
  264             BUS_DMA_NOWAIT, &sc->sc_dsdma);
  265         if (err) {
  266                 printf(": failed to create ds map, err=%d\n", err);
  267                 return;
  268         }
  269         err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_dsdma,
  270             &seg, nseg, sizeof(struct osiop_ds) * OSIOP_NACB, BUS_DMA_NOWAIT);
  271         if (err) {
  272                 printf(": failed to load ds map, err=%d\n", err);
  273                 return;
  274         }
  275         bzero(sc->sc_ds, sizeof(struct osiop_ds) * OSIOP_NACB);
  276 
  277         /*
  278          * Allocate (malloc) memory for acb's.
  279          */
  280         acb = malloc(sizeof(struct osiop_acb) * OSIOP_NACB,
  281             M_DEVBUF, M_NOWAIT);
  282         if (acb == NULL) {
  283                 printf(": can't allocate memory for acb\n");
  284                 return;
  285         }
  286         bzero(acb, sizeof(struct osiop_acb) * OSIOP_NACB);
  287         sc->sc_acb = acb;
  288 
  289         sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
  290         sc->sc_nexus = NULL;
  291         sc->sc_active = 0;
  292 
  293         bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
  294 
  295         /* Initialize command block queue */
  296         TAILQ_INIT(&sc->ready_list);
  297         TAILQ_INIT(&sc->nexus_list);
  298         TAILQ_INIT(&sc->free_list);
  299 
  300         /* Initialize each command block */
  301         for (i = 0; i < OSIOP_NACB; i++, acb++) {
  302                 bus_addr_t dsa;
  303 
  304                 err = bus_dmamap_create(sc->sc_dmat, OSIOP_MAX_XFER, OSIOP_NSG,
  305                     OSIOP_MAX_XFER, 0, BUS_DMA_NOWAIT, &acb->datadma);
  306                 if (err) {
  307                         printf(": failed to create datadma map, err=%d\n",
  308                             err);
  309                         return;
  310                 }
  311 
  312                 acb->sc = sc;
  313                 acb->ds = &sc->sc_ds[i];
  314                 acb->dsoffset = sizeof(struct osiop_ds) * i;
  315 
  316                 dsa = sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset;
  317                 acb->ds->id.addr = dsa + OSIOP_DSIDOFF;
  318                 acb->ds->cmd.addr = dsa + OSIOP_DSCMDOFF;
  319                 acb->ds->status.count = 1;
  320                 acb->ds->status.addr = dsa + OSIOP_DSSTATOFF;
  321                 acb->ds->msg.count = 1;
  322                 acb->ds->msg.addr = dsa + OSIOP_DSMSGOFF;
  323                 acb->ds->msgin.count = 1;
  324                 acb->ds->msgin.addr = dsa + OSIOP_DSMSGINOFF;
  325                 acb->ds->extmsg.count = 1;
  326                 acb->ds->extmsg.addr = dsa + OSIOP_DSEXTMSGOFF;
  327                 acb->ds->synmsg.count = 3;
  328                 acb->ds->synmsg.addr = dsa + OSIOP_DSSYNMSGOFF;
  329                 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
  330         }
  331 
  332         printf(": NCR53C710 rev %d, %dMHz, SCSI ID %d\n",
  333             osiop_read_1(sc, OSIOP_CTEST8) >> 4, sc->sc_clock_freq, sc->sc_id);
  334 
  335         /*
  336          * Initialize all
  337          */
  338         osiop_init(sc);
  339 
  340         /*
  341          * Fill in the sc_link.
  342          */
  343         sc->sc_link.adapter = &osiop_adapter;
  344         sc->sc_link.adapter_softc = sc;
  345         sc->sc_link.device = &osiop_dev;
  346         sc->sc_link.openings = 4;
  347         sc->sc_link.adapter_buswidth = OSIOP_NTGT;
  348         sc->sc_link.adapter_target = sc->sc_id;
  349 
  350         bzero(&saa, sizeof(saa));
  351         saa.saa_sc_link = &sc->sc_link;
  352 
  353         /*
  354          * Now try to attach all the sub devices.
  355          */
  356         config_found(&sc->sc_dev, &saa, scsiprint);
  357 }
  358 
  359 /*
  360  * default minphys routine for osiop based controllers
  361  */
  362 void
  363 osiop_minphys(bp)
  364         struct buf *bp;
  365 {
  366 
  367         if (bp->b_bcount > OSIOP_MAX_XFER)
  368                 bp->b_bcount = OSIOP_MAX_XFER;
  369         minphys(bp);
  370 }
  371 
  372 /*
  373  * used by specific osiop controller
  374  *
  375  */
  376 int
  377 osiop_scsicmd(xs)
  378         struct scsi_xfer *xs;
  379 {
  380         struct scsi_link *periph = xs->sc_link;
  381         struct osiop_acb *acb;
  382         struct osiop_softc *sc = periph->adapter_softc;
  383         int err, s;
  384 
  385         /* XXXX ?? */
  386         if (xs->flags & SCSI_DATA_UIO)
  387                 panic("osiop: scsi data uio requested");
  388 
  389         /* XXXX ?? */
  390         if (sc->sc_nexus && (xs->flags & SCSI_POLL))
  391 #if 0
  392                 panic("osiop_scsicmd: busy");
  393 #else
  394                 printf("osiop_scsicmd: busy\n");
  395 #endif
  396 
  397         s = splbio();
  398         acb = TAILQ_FIRST(&sc->free_list);
  399         if (acb != NULL) {
  400                 TAILQ_REMOVE(&sc->free_list, acb, chain);
  401         }
  402         else {
  403 #ifdef DIAGNOSTIC
  404                 sc_print_addr(periph);
  405                 printf("unable to allocate acb\n");
  406                 panic("osiop_scsipi_request");
  407 #endif
  408                 splx(s);
  409                 return (TRY_AGAIN_LATER);
  410         }
  411 
  412         acb->flags = 0;
  413         acb->status = ACB_S_READY;
  414         acb->xs = xs;
  415         acb->xsflags = xs->flags;
  416         bcopy(xs->cmd, &acb->ds->scsi_cmd, xs->cmdlen);
  417         acb->ds->cmd.count = xs->cmdlen;
  418         acb->datalen = 0;
  419 #ifdef OSIOP_DEBUG
  420         acb->data = xs->data;
  421 #endif
  422 
  423         /* Setup DMA map for data buffer */
  424         if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  425                 acb->datalen = xs->datalen;
  426                 err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
  427                     xs->data, acb->datalen, NULL,
  428                     BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
  429                     ((acb->xsflags & SCSI_DATA_IN) ?
  430                      BUS_DMA_READ : BUS_DMA_WRITE));
  431                 if (err) {
  432                         printf("%s: unable to load data DMA map: %d",
  433                             sc->sc_dev.dv_xname, err);
  434                         xs->error = XS_DRIVER_STUFFUP;
  435                         scsi_done(xs);
  436                         TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
  437                         splx(s);
  438                         return (COMPLETE);
  439                 }
  440                 bus_dmamap_sync(sc->sc_dmat, acb->datadma,
  441                     0, acb->datalen, (acb->xsflags & SCSI_DATA_IN) ?
  442                     BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  443         }
  444 
  445         /*
  446          * Always initialize timeout so it does not contain trash
  447          * that could confuse timeout_del().
  448          */
  449         timeout_set(&xs->stimeout, osiop_timeout, acb);
  450 
  451         TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
  452 
  453         osiop_sched(sc);
  454 
  455         splx(s);
  456 
  457         if ((acb->xsflags & SCSI_POLL) || (sc->sc_flags & OSIOP_NODMA))
  458                 osiop_poll(sc, acb);
  459         else
  460                 /* start expire timer */
  461                 timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
  462 
  463         if ((xs->flags & ITSDONE) == 0)
  464                 return (SUCCESSFULLY_QUEUED);
  465         else
  466                 return (COMPLETE);
  467 }
  468 
  469 void
  470 osiop_poll(sc, acb)
  471         struct osiop_softc *sc;
  472         struct osiop_acb *acb;
  473 {
  474         struct scsi_xfer *xs = acb->xs;
  475         int status, i, s, to;
  476         u_int8_t istat, dstat, sstat0;
  477 
  478         s = splbio();
  479         to = xs->timeout / 1000;
  480         if (!TAILQ_EMPTY(&sc->nexus_list))
  481                 printf("%s: osiop_poll called with disconnected device\n",
  482                     sc->sc_dev.dv_xname);
  483         for (;;) {
  484                 i = 1000;
  485                 while (((istat = osiop_read_1(sc, OSIOP_ISTAT)) &
  486                     (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
  487                         if (i <= 0) {
  488 #ifdef OSIOP_DEBUG
  489                                 printf("waiting: tgt %d cmd %02x sbcl %02x"
  490                                     " dsp %x (+%lx) dcmd %x"
  491                                     " ds %p timeout %d\n",
  492                                     xs->sc_link->target,
  493                                     acb->ds->scsi_cmd.opcode,
  494                                     osiop_read_1(sc, OSIOP_SBCL),
  495                                     osiop_read_4(sc, OSIOP_DSP),
  496                                     osiop_read_4(sc, OSIOP_DSP) -
  497                                         sc->sc_scrdma->dm_segs[0].ds_addr,
  498                                     osiop_read_1(sc, OSIOP_DCMD),
  499                                     acb->ds, acb->xs->timeout);
  500 #endif
  501                                 i = 1000;
  502                                 to--;
  503                                 if (to <= 0) {
  504                                         osiop_reset(sc);
  505                                         splx(s);
  506                                         return;
  507                                 }
  508                         }
  509                         delay(1000);
  510                         i--;
  511                 }
  512                 sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
  513                 delay(25); /* Need delay between SSTAT0 and DSTAT reads */
  514                 dstat = osiop_read_1(sc, OSIOP_DSTAT);
  515                 if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
  516                         if (acb != sc->sc_nexus)
  517                                 printf("%s: osiop_poll disconnected device"
  518                                     " completed\n", sc->sc_dev.dv_xname);
  519                         else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
  520                                 sc->sc_flags &= ~OSIOP_INTSOFF;
  521                                 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
  522                                 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
  523                         }
  524                         osiop_scsidone(sc->sc_nexus, status);
  525                 }
  526 
  527                 if (xs->flags & ITSDONE)
  528                         break;
  529         }
  530 
  531         splx(s);
  532         return;
  533 }
  534 
  535 /*
  536  * start next command that's ready
  537  */
  538 void
  539 osiop_sched(sc)
  540         struct osiop_softc *sc;
  541 {
  542         struct osiop_tinfo *ti;
  543         struct scsi_link *periph;
  544         struct osiop_acb *acb;
  545 
  546         if ((sc->sc_nexus != NULL) || TAILQ_EMPTY(&sc->ready_list)) {
  547 #ifdef OSIOP_DEBUG
  548                 if (osiop_debug & DEBUG_SCHED)
  549                         printf("%s: osiop_sched->nexus %p/%d ready %p/%d\n",
  550                             sc->sc_dev.dv_xname, sc->sc_nexus,
  551                             sc->sc_nexus != NULL ?
  552                              sc->sc_nexus->xs->sc_link->target : 0,
  553                             TAILQ_FIRST(&sc->ready_list),
  554                             TAILQ_FIRST(&sc->ready_list) != NULL ?
  555                              TAILQ_FIRST(&sc->ready_list)->xs->sc_link->target :
  556                              0);
  557 #endif
  558                 return;
  559         }
  560         TAILQ_FOREACH(acb, &sc->ready_list, chain) {
  561                 periph = acb->xs->sc_link;
  562                 ti = &sc->sc_tinfo[periph->target];
  563                 if ((ti->lubusy & (1 << periph->lun)) == 0) {
  564                         TAILQ_REMOVE(&sc->ready_list, acb, chain);
  565                         sc->sc_nexus = acb;
  566                         ti->lubusy |= (1 << periph->lun);
  567                         break;
  568                 }
  569         }
  570 
  571         if (acb == NULL) {
  572 #ifdef OSIOP_DEBUG
  573                 if (osiop_debug & DEBUG_SCHED)
  574                         printf("%s: osiop_sched didn't find ready command\n",
  575                             sc->sc_dev.dv_xname);
  576 #endif
  577                 return;
  578         }
  579 
  580         if (acb->xsflags & SCSI_RESET)
  581                 osiop_reset(sc);
  582 
  583         sc->sc_active++;
  584         osiop_select(sc);
  585 }
  586 
  587 void
  588 osiop_scsidone(acb, status)
  589         struct osiop_acb *acb;
  590         int status;
  591 {
  592         struct scsi_xfer *xs;
  593         struct scsi_link *periph;
  594         struct osiop_softc *sc;
  595         int autosense;
  596 
  597 #ifdef DIAGNOSTIC
  598         if (acb == NULL || acb->xs == NULL) {
  599                 printf("osiop_scsidone: NULL acb or scsi_xfer\n");
  600 #if defined(OSIOP_DEBUG) && defined(DDB)
  601                 Debugger();
  602 #endif
  603                 return;
  604         }
  605 #endif
  606         xs = acb->xs;
  607         sc = acb->sc;
  608         periph = xs->sc_link;
  609 
  610         /*
  611          * Record if this is the completion of an auto sense
  612          * scsi command, and then reset the flag so we don't loop
  613          * when such a command fails or times out.
  614          */
  615         autosense = acb->flags & ACB_F_AUTOSENSE;
  616         acb->flags &= ~ACB_F_AUTOSENSE;
  617 
  618 #ifdef OSIOP_DEBUG
  619         if (acb->status != ACB_S_DONE)
  620                 printf("%s: acb not done (status %d)\n",
  621                     sc->sc_dev.dv_xname, acb->status);
  622 #endif
  623 
  624         if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  625                 bus_dmamap_sync(sc->sc_dmat, acb->datadma, 0, acb->datalen,
  626                     (acb->xsflags & SCSI_DATA_IN) ?
  627                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  628                 bus_dmamap_unload(sc->sc_dmat, acb->datadma);
  629         }
  630 
  631         timeout_del(&xs->stimeout);
  632         xs->status = status;
  633 
  634         switch (status) {
  635         case SCSI_OK:
  636                 if (autosense == 0)
  637                         xs->error = XS_NOERROR;
  638                 else
  639                         xs->error = XS_SENSE;
  640                 break;
  641         case SCSI_BUSY:
  642                 xs->error = XS_BUSY;
  643                 break;
  644         case SCSI_CHECK:
  645                 if (autosense == 0)
  646                         acb->flags |= ACB_F_AUTOSENSE;
  647                 else
  648                         xs->error = XS_DRIVER_STUFFUP;
  649                 break;
  650         case SCSI_OSIOP_NOCHECK:
  651                 /*
  652                  * don't check status, xs->error is already valid
  653                  */
  654                 break;
  655         case SCSI_OSIOP_NOSTATUS:
  656                 /*
  657                  * the status byte was not updated, cmd was
  658                  * aborted
  659                  */
  660                 xs->error = XS_SELTIMEOUT;
  661                 break;
  662         default:
  663 #ifdef OSIOP_DEBUG
  664                 printf("%s: osiop_scsidone: unknown status code (0x%02x)\n",
  665                     sc->sc_dev.dv_xname, status);
  666 #endif
  667                 xs->error = XS_DRIVER_STUFFUP;
  668                 break;
  669         }
  670 
  671         /*
  672          * Remove the ACB from whatever queue it's on.  We have to do a bit of
  673          * a hack to figure out which queue it's on.  Note that it is *not*
  674          * necessary to cdr down the ready queue, but we must cdr down the
  675          * nexus queue and see if it's there, so we can mark the unit as no
  676          * longer busy.  This code is sickening, but it works.
  677          */
  678         if (acb == sc->sc_nexus) {
  679                 sc->sc_nexus = NULL;
  680                 sc->sc_tinfo[periph->target].lubusy &=
  681                     ~(1 << periph->lun);
  682                 sc->sc_active--;
  683                 OSIOP_TRACE('d', 'a', status, 0);
  684         } else if (sc->ready_list.tqh_last == &TAILQ_NEXT(acb, chain)) {
  685                 TAILQ_REMOVE(&sc->ready_list, acb, chain);
  686                 OSIOP_TRACE('d', 'r', status, 0);
  687         } else {
  688                 struct osiop_acb *acb2;
  689                 TAILQ_FOREACH(acb2, &sc->nexus_list, chain) {
  690                         if (acb2 == acb) {
  691                                 TAILQ_REMOVE(&sc->nexus_list, acb, chain);
  692                                 sc->sc_tinfo[periph->target].lubusy &=
  693                                     ~(1 << periph->lun);
  694                                 sc->sc_active--;
  695                                 break;
  696                         }
  697                 }
  698                 if (acb2 == NULL) {
  699                         if (TAILQ_NEXT(acb, chain) != NULL) {
  700                                 TAILQ_REMOVE(&sc->ready_list, acb, chain);
  701                                 sc->sc_active--;
  702                         } else {
  703                                 printf("%s: can't find matching acb\n",
  704                                     sc->sc_dev.dv_xname);
  705 #ifdef DDB
  706 #if 0
  707                                 Debugger();
  708 #endif
  709 #endif
  710                         }
  711                 }
  712                 OSIOP_TRACE('d', 'n', status, 0);
  713         }
  714 
  715         if ((acb->flags & ACB_F_AUTOSENSE) == 0) {
  716                 /* Put it on the free list. */
  717 FREE:
  718                 acb->status = ACB_S_FREE;
  719                 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
  720                 sc->sc_tinfo[periph->target].cmds++;
  721 
  722                 xs->resid = 0;
  723                 xs->flags |= ITSDONE;
  724                 scsi_done(xs);
  725         } else {
  726                 /* Set up REQUEST_SENSE command */
  727                 struct scsi_sense *cmd = (struct scsi_sense *)&acb->ds->scsi_cmd;
  728                 int err;
  729 
  730                 bzero(cmd, sizeof(*cmd));
  731                 acb->ds->cmd.count = sizeof(*cmd);
  732                 cmd->opcode = REQUEST_SENSE;
  733                 cmd->byte2  = xs->sc_link->lun << 5;
  734                 cmd->length = sizeof(xs->sense);
  735 
  736                 /* Setup DMA map for data buffer */
  737                 acb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
  738                 acb->xsflags |= SCSI_DATA_IN;
  739                 acb->datalen  = sizeof xs->sense;
  740 #ifdef OSIOP_DEBUG
  741                 acb->data = &xs->sense;
  742 #endif
  743                 err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
  744                     &xs->sense, sizeof(xs->sense), NULL,
  745                     BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
  746                 if (err) {
  747                         printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
  748                             sc->sc_dev.dv_xname, err);
  749                         xs->error = XS_DRIVER_STUFFUP;
  750                         goto FREE;
  751                 }
  752                 bus_dmamap_sync(sc->sc_dmat, acb->datadma,
  753                     0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
  754 
  755                 sc->sc_tinfo[periph->target].senses++;
  756                 acb->status  = ACB_S_READY;
  757                 TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
  758                 if (((acb->xsflags & SCSI_POLL) == 0) && ((sc->sc_flags & OSIOP_NODMA) == 0))
  759                         /* start expire timer */
  760                         timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
  761         }
  762 
  763         osiop_sched(sc);
  764 }
  765 
  766 void
  767 osiop_abort(sc, where)
  768         struct osiop_softc *sc;
  769         const char *where;
  770 {
  771         u_int8_t dstat, sstat0;
  772 
  773         sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
  774         delay(25); /* Need delay between SSTAT0 and DSTAT reads */
  775         dstat = osiop_read_1(sc, OSIOP_DSTAT);
  776 
  777         printf("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
  778             sc->sc_dev.dv_xname, where,
  779             dstat, sstat0,
  780             osiop_read_1(sc, OSIOP_SBCL));
  781 
  782         /* XXX XXX XXX */
  783         if (sc->sc_active > 0) {
  784                 sc->sc_active = 0;
  785         }
  786 }
  787 
  788 void
  789 osiop_init(sc)
  790         struct osiop_softc *sc;
  791 {
  792         int i, inhibit_sync, inhibit_disc;
  793 
  794         sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
  795         sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
  796         sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
  797         sc->sc_minsync = sc->sc_tcp[1];         /* in 4ns units */
  798 
  799         if (sc->sc_minsync < 25)
  800                 sc->sc_minsync = 25;
  801 
  802         if (sc->sc_clock_freq <= 25) {
  803                 sc->sc_dcntl |= OSIOP_DCNTL_CF_1;       /* SCLK/1 */
  804                 sc->sc_tcp[0] = sc->sc_tcp[1];
  805         } else if (sc->sc_clock_freq <= 37) {
  806                 sc->sc_dcntl |= OSIOP_DCNTL_CF_1_5;     /* SCLK/1.5 */
  807                 sc->sc_tcp[0] = sc->sc_tcp[2];
  808         } else if (sc->sc_clock_freq <= 50) {
  809                 sc->sc_dcntl |= OSIOP_DCNTL_CF_2;       /* SCLK/2 */
  810                 sc->sc_tcp[0] = sc->sc_tcp[3];
  811         } else {
  812                 sc->sc_dcntl |= OSIOP_DCNTL_CF_3;       /* SCLK/3 */
  813                 sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
  814         }
  815 
  816         if ((sc->sc_cfflags & 0x10000) != 0) {
  817                 sc->sc_flags |= OSIOP_NODMA;
  818 #ifdef OSIOP_DEBUG
  819                 printf("%s: DMA disabled; use polling\n",
  820                     sc->sc_dev.dv_xname);
  821 #endif
  822         }
  823 
  824         inhibit_sync = (sc->sc_cfflags & 0xff00) >> 8;  /* XXX */
  825         inhibit_disc =  sc->sc_cfflags & 0x00ff;        /* XXX */
  826 #ifdef OSIOP_DEBUG
  827         if (inhibit_sync != 0)
  828                 printf("%s: Inhibiting synchronous transfer: 0x%02x\n",
  829                     sc->sc_dev.dv_xname, inhibit_sync);
  830         if (inhibit_disc != 0)
  831                 printf("%s: Inhibiting disconnect: 0x%02x\n",
  832                     sc->sc_dev.dv_xname, inhibit_disc);
  833 #endif
  834         for (i = 0; i < OSIOP_NTGT; i++) {
  835                 if (inhibit_sync & (1 << i))
  836                         sc->sc_tinfo[i].flags |= TI_NOSYNC;
  837                 if (inhibit_disc & (1 << i))
  838                         sc->sc_tinfo[i].flags |= TI_NODISC;
  839         }
  840 
  841         osiop_resetbus(sc);
  842         osiop_reset(sc);
  843 }
  844 
  845 void
  846 osiop_reset(sc)
  847         struct osiop_softc *sc;
  848 {
  849         struct osiop_acb *acb;
  850         int i, s;
  851         u_int8_t stat;
  852 
  853 #ifdef OSIOP_DEBUG
  854         printf("%s: resetting chip\n", sc->sc_dev.dv_xname);
  855 #endif
  856         if (sc->sc_flags & OSIOP_ALIVE)
  857                 osiop_abort(sc, "reset");
  858 
  859         s = splbio();
  860 
  861         /*
  862          * Reset the chip
  863          * XXX - is this really needed?
  864          */
  865 
  866         /* abort current script */
  867         osiop_write_1(sc, OSIOP_ISTAT,
  868             osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_ABRT);
  869         /* reset chip */
  870         osiop_write_1(sc, OSIOP_ISTAT,
  871             osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_RST);
  872         delay(100);
  873         osiop_write_1(sc, OSIOP_ISTAT,
  874             osiop_read_1(sc, OSIOP_ISTAT) & ~OSIOP_ISTAT_RST);
  875         delay(100);
  876 
  877         /*
  878          * Set up various chip parameters
  879          */
  880         osiop_write_1(sc, OSIOP_SCNTL0,
  881             OSIOP_ARB_FULL | OSIOP_SCNTL0_EPC | OSIOP_SCNTL0_EPG);
  882         osiop_write_1(sc, OSIOP_SCNTL1, OSIOP_SCNTL1_ESR);
  883         osiop_write_1(sc, OSIOP_DCNTL, sc->sc_dcntl);
  884         osiop_write_1(sc, OSIOP_DMODE, sc->sc_dmode);
  885         /* don't enable interrupts yet */
  886         osiop_write_1(sc, OSIOP_SIEN, 0x00);
  887         osiop_write_1(sc, OSIOP_DIEN, 0x00);
  888         osiop_write_1(sc, OSIOP_SCID, OSIOP_SCID_VALUE(sc->sc_id));
  889         osiop_write_1(sc, OSIOP_DWT, 0x00);
  890         osiop_write_1(sc, OSIOP_CTEST0, osiop_read_1(sc, OSIOP_CTEST0)
  891             | OSIOP_CTEST0_BTD | OSIOP_CTEST0_EAN);
  892         osiop_write_1(sc, OSIOP_CTEST7,
  893             osiop_read_1(sc, OSIOP_CTEST7) | sc->sc_ctest7);
  894 
  895         /* will need to re-negotiate sync xfers */
  896         for (i = 0; i < OSIOP_NTGT; i++) {
  897                 sc->sc_tinfo[i].state = NEG_INIT;
  898                 sc->sc_tinfo[i].period = 0;
  899                 sc->sc_tinfo[i].offset = 0;
  900         }
  901 
  902         stat = osiop_read_1(sc, OSIOP_ISTAT);
  903         if (stat & OSIOP_ISTAT_SIP)
  904                 osiop_read_1(sc, OSIOP_SSTAT0);
  905         if (stat & OSIOP_ISTAT_DIP) {
  906                 if (stat & OSIOP_ISTAT_SIP)
  907                         /* Need delay between SSTAT0 and DSTAT reads */
  908                         delay(25);
  909                 osiop_read_1(sc, OSIOP_DSTAT);
  910         }
  911 
  912         splx(s);
  913 
  914         delay(osiop_reset_delay * 1000);
  915 
  916         s = splbio();
  917         if (sc->sc_nexus != NULL) {
  918                 sc->sc_nexus->xs->error =
  919                     (sc->sc_nexus->flags & ACB_F_TIMEOUT) ?
  920                     XS_TIMEOUT : XS_RESET;
  921                 sc->sc_nexus->status = ACB_S_DONE;
  922                 osiop_scsidone(sc->sc_nexus, SCSI_OSIOP_NOCHECK);
  923         }
  924         while ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
  925                 acb->xs->error = (acb->flags & ACB_F_TIMEOUT) ?
  926                     XS_TIMEOUT : XS_RESET;
  927                 acb->status = ACB_S_DONE;
  928                 osiop_scsidone(acb, SCSI_OSIOP_NOCHECK);
  929         }
  930         splx(s);
  931 
  932         sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
  933         /* enable SCSI and DMA interrupts */
  934         sc->sc_sien = OSIOP_SIEN_M_A | OSIOP_SIEN_STO | /*OSIOP_SIEN_SEL |*/
  935             OSIOP_SIEN_SGE | OSIOP_SIEN_UDC | OSIOP_SIEN_RST | OSIOP_SIEN_PAR;
  936         sc->sc_dien = OSIOP_DIEN_BF | OSIOP_DIEN_ABRT | OSIOP_DIEN_SIR |
  937             /*OSIOP_DIEN_WTD |*/ OSIOP_DIEN_IID;
  938         osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
  939         osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
  940 }
  941 
  942 void
  943 osiop_resetbus(sc)
  944         struct osiop_softc *sc;
  945 {
  946 
  947         osiop_write_1(sc, OSIOP_SIEN, 0);
  948         osiop_write_1(sc, OSIOP_SCNTL1,
  949             osiop_read_1(sc, OSIOP_SCNTL1) | OSIOP_SCNTL1_RST);
  950         delay(25);
  951         osiop_write_1(sc, OSIOP_SCNTL1,
  952             osiop_read_1(sc, OSIOP_SCNTL1) & ~OSIOP_SCNTL1_RST);
  953 }
  954 
  955 /*
  956  * Setup Data Storage for 53C710 and start SCRIPTS processing
  957  */
  958 
  959 void
  960 osiop_start(sc)
  961         struct osiop_softc *sc;
  962 {
  963         struct osiop_acb *acb = sc->sc_nexus;
  964         struct osiop_ds *ds = acb->ds;
  965         struct scsi_xfer *xs = acb->xs;
  966         bus_dmamap_t dsdma = sc->sc_dsdma, datadma = acb->datadma;
  967         struct osiop_tinfo *ti;
  968         int target = xs->sc_link->target;
  969         int lun = xs->sc_link->lun;
  970         int disconnect, i;
  971 
  972 #ifdef OSIOP_DEBUG
  973         if (osiop_debug & DEBUG_DISC &&
  974             osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
  975                 printf("ACK! osiop was busy: script %p dsa %p active %d\n",
  976                     sc->sc_script, acb->ds, sc->sc_active);
  977                 printf("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n",
  978                     osiop_read_1(sc, OSIOP_ISTAT),
  979                     osiop_read_1(sc, OSIOP_SFBR),
  980                     osiop_read_1(sc, OSIOP_LCRC),
  981                     osiop_read_1(sc, OSIOP_SIEN),
  982                     osiop_read_1(sc, OSIOP_DIEN));
  983 #ifdef DDB
  984 #if 0
  985                 Debugger();
  986 #endif
  987 #endif
  988         }
  989 #endif
  990 
  991 #ifdef OSIOP_DEBUG
  992         if (acb->status != ACB_S_READY)
  993                 panic("osiop_start: non-ready cmd in acb");
  994 #endif
  995 
  996         acb->intstat = 0;
  997 
  998         ti = &sc->sc_tinfo[target];
  999         ds->scsi_addr = ((1 << 16) << target) | (ti->sxfer << 8);
 1000 
 1001         disconnect = (ds->scsi_cmd.opcode != REQUEST_SENSE) &&
 1002             (ti->flags & TI_NODISC) == 0;
 1003 
 1004         ds->msgout[0] = MSG_IDENTIFY(lun, disconnect);
 1005         ds->id.count = 1;
 1006         ds->stat[0] = SCSI_OSIOP_NOSTATUS;      /* set invalid status */
 1007         ds->msgbuf[0] = ds->msgbuf[1] = MSG_INVALID;
 1008         bzero(&ds->data, sizeof(ds->data));
 1009 
 1010         /*
 1011          * Negotiate wide is the initial negotiation state;  since the 53c710
 1012          * doesn't do wide transfers, just begin the synchronous transfer
 1013          * negotiation here.
 1014          */
 1015         if (ti->state == NEG_INIT) {
 1016                 if ((ti->flags & TI_NOSYNC) != 0) {
 1017                         ti->state = NEG_DONE;
 1018                         ti->period = 0;
 1019                         ti->offset = 0;
 1020                         osiop_update_xfer_mode(sc, target);
 1021 #ifdef OSIOP_DEBUG
 1022                         if (osiop_debug & DEBUG_SYNC)
 1023                                 printf("Forcing target %d asynchronous\n",
 1024                                     target);
 1025 #endif
 1026                 } else {
 1027                         ds->msgbuf[2] = MSG_INVALID;
 1028                         ds->msgout[1] = MSG_EXTENDED;
 1029                         ds->msgout[2] = MSG_EXT_SDTR_LEN;
 1030                         ds->msgout[3] = MSG_EXT_SDTR;
 1031                         ds->msgout[4] = sc->sc_minsync;
 1032                         ds->msgout[5] = OSIOP_MAX_OFFSET;
 1033                         ds->id.count = MSG_EXT_SDTR_LEN + 3;
 1034                         ti->state = NEG_WAITS;
 1035 #ifdef OSIOP_DEBUG
 1036                         if (osiop_debug & DEBUG_SYNC)
 1037                                 printf("Sending sync request to target %d\n",
 1038                                     target);
 1039 #endif
 1040                 }
 1041         }
 1042 
 1043         acb->curaddr = 0;
 1044         acb->curlen = 0;
 1045 
 1046         /*
 1047          * Build physical DMA addresses for scatter/gather I/O
 1048          */
 1049         if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
 1050                 for (i = 0; i < datadma->dm_nsegs; i++) {
 1051                         ds->data[i].count = datadma->dm_segs[i].ds_len;
 1052                         ds->data[i].addr  = datadma->dm_segs[i].ds_addr;
 1053                 }
 1054         }
 1055 
 1056         /* sync script data structure */
 1057         bus_dmamap_sync(sc->sc_dmat, dsdma,
 1058             acb->dsoffset, sizeof(struct osiop_ds),
 1059             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1060 
 1061         acb->status = ACB_S_ACTIVE;
 1062 
 1063 #ifdef OSIOP_DEBUG
 1064         if (osiop_debug & DEBUG_DISC &&
 1065             osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
 1066                 printf("ACK! osiop was busy at start: "
 1067                     "script %p dsa %p active %d\n",
 1068                     sc->sc_script, acb->ds, sc->sc_active);
 1069 #ifdef DDB
 1070 #if 0
 1071                 Debugger();
 1072 #endif
 1073 #endif
 1074         }
 1075 #endif
 1076         if (TAILQ_EMPTY(&sc->nexus_list)) {
 1077                 if (osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON)
 1078                         printf("%s: osiop_select while connected?\n",
 1079                             sc->sc_dev.dv_xname);
 1080                 osiop_write_4(sc, OSIOP_TEMP, 0);
 1081                 osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
 1082                 osiop_write_4(sc, OSIOP_DSA,
 1083                     dsdma->dm_segs[0].ds_addr + acb->dsoffset);
 1084                 osiop_write_4(sc, OSIOP_DSP,
 1085                     sc->sc_scrdma->dm_segs[0].ds_addr + Ent_scripts);
 1086                 OSIOP_TRACE('s', 1, 0, 0);
 1087         } else {
 1088                 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
 1089                         osiop_write_1(sc, OSIOP_ISTAT, OSIOP_ISTAT_SIGP);
 1090                         OSIOP_TRACE('s', 2, 0, 0);
 1091                 } else {
 1092                         OSIOP_TRACE('s', 3,
 1093                             osiop_read_1(sc, OSIOP_ISTAT), 0);
 1094                 }
 1095         }
 1096 #ifdef OSIOP_DEBUG
 1097         osiopstarts++;
 1098 #endif
 1099 }
 1100 
 1101 /*
 1102  * Process a DMA or SCSI interrupt from the 53C710 SIOP
 1103  */
 1104 
 1105 int
 1106 osiop_checkintr(sc, istat, dstat, sstat0, status)
 1107         struct  osiop_softc *sc;
 1108         u_int8_t istat;
 1109         u_int8_t dstat;
 1110         u_int8_t sstat0;
 1111         int *status;
 1112 {
 1113         struct osiop_acb *acb = sc->sc_nexus;
 1114         struct osiop_ds *ds;
 1115         bus_dmamap_t dsdma = sc->sc_dsdma;
 1116         bus_addr_t scraddr = sc->sc_scrdma->dm_segs[0].ds_addr;
 1117         int target = 0;
 1118         int dfifo, dbc, intcode, sstat1;
 1119 
 1120         dfifo = osiop_read_1(sc, OSIOP_DFIFO);
 1121         dbc = osiop_read_4(sc, OSIOP_DBC) & 0x00ffffff;
 1122         sstat1 = osiop_read_1(sc, OSIOP_SSTAT1);
 1123         osiop_write_1(sc, OSIOP_CTEST8,
 1124             osiop_read_1(sc, OSIOP_CTEST8) | OSIOP_CTEST8_CLF);
 1125         while ((osiop_read_1(sc, OSIOP_CTEST1) & OSIOP_CTEST1_FMT) !=
 1126             OSIOP_CTEST1_FMT)
 1127                 ;
 1128         osiop_write_1(sc, OSIOP_CTEST8,
 1129             osiop_read_1(sc, OSIOP_CTEST8) & ~OSIOP_CTEST8_CLF);
 1130         intcode = osiop_read_4(sc, OSIOP_DSPS);
 1131 #ifdef OSIOP_DEBUG
 1132         osiopints++;
 1133         if (osiop_read_4(sc, OSIOP_DSP) != 0 &&
 1134             (osiop_read_4(sc, OSIOP_DSP) < scraddr ||
 1135             osiop_read_4(sc, OSIOP_DSP) >= scraddr + sizeof(osiop_script))) {
 1136                 printf("%s: dsp not within script dsp %x scripts %lx:%lx",
 1137                     sc->sc_dev.dv_xname,
 1138                     osiop_read_4(sc, OSIOP_DSP),
 1139                     scraddr, scraddr + sizeof(osiop_script));
 1140                 printf(" istat %x dstat %x sstat0 %x\n", istat, dstat, sstat0);
 1141 #ifdef DDB
 1142                 Debugger();
 1143 #endif
 1144         }
 1145 #endif
 1146         OSIOP_TRACE('i', dstat, istat, (istat & OSIOP_ISTAT_DIP) ?
 1147             intcode & 0xff : sstat0);
 1148 
 1149         ds = NULL;
 1150         if (acb != NULL) { /* XXX */
 1151                 ds = acb->ds;
 1152                 bus_dmamap_sync(sc->sc_dmat, dsdma,
 1153                     acb->dsoffset, sizeof(struct osiop_ds),
 1154                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1155 #ifdef OSIOP_DEBUG
 1156                 if (acb->status != ACB_S_ACTIVE)
 1157                         printf("osiop_checkintr: acb not active (status %d)\n",
 1158                             acb->status);
 1159 #endif
 1160         }
 1161 
 1162         if (dstat & OSIOP_DSTAT_SIR && intcode == A_ok) {
 1163                 /* Normal completion status, or check condition */
 1164                 struct osiop_tinfo *ti;
 1165                 if (acb == NULL) {
 1166                         printf("%s: COMPLETE with no active command?\n",
 1167                             sc->sc_dev.dv_xname);
 1168                         return (0);
 1169                 }
 1170 #ifdef OSIOP_DEBUG
 1171                 if (osiop_read_4(sc, OSIOP_DSA) !=
 1172                     dsdma->dm_segs[0].ds_addr + acb->dsoffset) {
 1173                         printf("osiop: invalid dsa: %x %lx\n",
 1174                             osiop_read_4(sc, OSIOP_DSA),
 1175                             dsdma->dm_segs[0].ds_addr + acb->dsoffset);
 1176                         panic("*** osiop DSA invalid ***");
 1177                 }
 1178 #endif
 1179                 target = acb->xs->sc_link->target;
 1180                 ti = &sc->sc_tinfo[target];
 1181                 if (ti->state == NEG_WAITS) {
 1182                         if (ds->msgbuf[1] == MSG_INVALID)
 1183                                 printf("%s: target %d ignored sync request\n",
 1184                                     sc->sc_dev.dv_xname, target);
 1185                         else if (ds->msgbuf[1] == MSG_MESSAGE_REJECT)
 1186                                 printf("%s: target %d rejected sync request\n",
 1187                                     sc->sc_dev.dv_xname, target);
 1188                         ti->period = 0;
 1189                         ti->offset = 0;
 1190                         osiop_update_xfer_mode(sc, target);
 1191                         ti->state = NEG_DONE;
 1192                 }
 1193 #ifdef OSIOP_DEBUG
 1194                 if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
 1195 #if 0
 1196                         printf("ACK! osiop was busy at end: "
 1197                             "script %p dsa %p\n", &osiop_script, ds);
 1198 #ifdef DDB
 1199                         Debugger();
 1200 #endif
 1201 #endif
 1202                 }
 1203                 if (ds->msgbuf[0] != MSG_CMDCOMPLETE)
 1204                         printf("%s: message was not COMMAND COMPLETE: %02x\n",
 1205                             sc->sc_dev.dv_xname, ds->msgbuf[0]);
 1206 #endif
 1207                 if (!TAILQ_EMPTY(&sc->nexus_list))
 1208                         osiop_write_1(sc, OSIOP_DCNTL,
 1209                             osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1210                 *status = ds->stat[0];
 1211                 acb->status = ACB_S_DONE;
 1212                 return (1);
 1213         }
 1214         if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_syncmsg) {
 1215                 if (acb == NULL) {
 1216                         printf("%s: Sync message with no active command?\n",
 1217                             sc->sc_dev.dv_xname);
 1218                         return (0);
 1219                 }
 1220                 target = acb->xs->sc_link->target;
 1221                 if (ds->msgbuf[1] == MSG_EXTENDED &&
 1222                     ds->msgbuf[2] == MSG_EXT_SDTR_LEN &&
 1223                     ds->msgbuf[3] == MSG_EXT_SDTR) {
 1224                         struct osiop_tinfo *ti = &sc->sc_tinfo[target];
 1225 #ifdef OSIOP_DEBUG
 1226                         if (osiop_debug & DEBUG_SYNC)
 1227                                 printf("sync msg in: "
 1228                                     "%02x %02x %02x %02x %02x %02x\n",
 1229                                     ds->msgbuf[0], ds->msgbuf[1],
 1230                                     ds->msgbuf[2], ds->msgbuf[3],
 1231                                     ds->msgbuf[4], ds->msgbuf[5]);
 1232 #endif
 1233                         ti->period = ds->msgbuf[4];
 1234                         ti->offset = ds->msgbuf[5];
 1235                         osiop_update_xfer_mode(sc, target);
 1236 
 1237                         bus_dmamap_sync(sc->sc_dmat, dsdma,
 1238                             acb->dsoffset, sizeof(struct osiop_ds),
 1239                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1240                         osiop_write_1(sc, OSIOP_SXFER, ti->sxfer);
 1241                         osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
 1242                         if (ti->state == NEG_WAITS) {
 1243                                 ti->state = NEG_DONE;
 1244                                 osiop_write_4(sc, OSIOP_DSP,
 1245                                     scraddr + Ent_clear_ack);
 1246                                 return (0);
 1247                         }
 1248                         osiop_write_1(sc, OSIOP_DCNTL,
 1249                             osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1250                         ti->state = NEG_DONE;
 1251                         return (0);
 1252                 }
 1253                 /* XXX - not SDTR message */
 1254         }
 1255         if (sstat0 & OSIOP_SSTAT0_M_A) {
 1256                 /* Phase mismatch */
 1257 #ifdef OSIOP_DEBUG
 1258                 osiopphmm++;
 1259 #endif
 1260                 if (acb == NULL) {
 1261                         printf("%s: Phase mismatch with no active command?\n",
 1262                             sc->sc_dev.dv_xname);
 1263                         return (0);
 1264                 }
 1265                 if (acb->datalen > 0) {
 1266                         int adjust = (dfifo - (dbc & 0x7f)) & 0x7f;
 1267                         if (sstat1 & OSIOP_SSTAT1_ORF)
 1268                                 adjust++;
 1269                         if (sstat1 & OSIOP_SSTAT1_OLF)
 1270                                 adjust++;
 1271                         acb->curaddr = osiop_read_4(sc, OSIOP_DNAD) - adjust;
 1272                         acb->curlen = dbc + adjust;
 1273 #ifdef OSIOP_DEBUG
 1274                         if (osiop_debug & DEBUG_DISC) {
 1275                                 printf("Phase mismatch: curaddr %lx "
 1276                                     "curlen %lx dfifo %x dbc %x sstat1 %x "
 1277                                     "adjust %x sbcl %x starts %d acb %p\n",
 1278                                     acb->curaddr, acb->curlen, dfifo,
 1279                                     dbc, sstat1, adjust,
 1280                                     osiop_read_1(sc, OSIOP_SBCL),
 1281                                     osiopstarts, acb);
 1282                                 if (ds->data[1].count != 0) {
 1283                                         int i;
 1284                                         for (i = 0; ds->data[i].count != 0; i++)
 1285                                                 printf("chain[%d] "
 1286                                                     "addr %x len %x\n", i,
 1287                                                     ds->data[i].addr,
 1288                                                     ds->data[i].count);
 1289                                 }
 1290                                 bus_dmamap_sync(sc->sc_dmat, dsdma,
 1291                                     acb->dsoffset, sizeof(struct osiop_ds),
 1292                                     BUS_DMASYNC_PREREAD |
 1293                                     BUS_DMASYNC_PREWRITE);
 1294                         }
 1295 #endif
 1296                 }
 1297 #ifdef OSIOP_DEBUG
 1298                 OSIOP_TRACE('m', osiop_read_1(sc, OSIOP_SBCL),
 1299                     osiop_read_4(sc, OSIOP_DSP) >> 8,
 1300                     osiop_read_4(sc, OSIOP_DSP));
 1301                 if (osiop_debug & DEBUG_PHASE)
 1302                         printf("Phase mismatch: %x dsp +%lx dcmd %x\n",
 1303                             osiop_read_1(sc, OSIOP_SBCL),
 1304                             osiop_read_4(sc, OSIOP_DSP) - scraddr,
 1305                             osiop_read_4(sc, OSIOP_DBC));
 1306 #endif
 1307                 if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_REQ) == 0) {
 1308                         printf("Phase mismatch: "
 1309                             "REQ not asserted! %02x dsp %x\n",
 1310                             osiop_read_1(sc, OSIOP_SBCL),
 1311                             osiop_read_4(sc, OSIOP_DSP));
 1312 #if defined(OSIOP_DEBUG) && defined(DDB)
 1313                         /*Debugger(); XXX is*/
 1314 #endif
 1315                 }
 1316                 switch (OSIOP_PHASE(osiop_read_1(sc, OSIOP_SBCL))) {
 1317                 case DATA_OUT_PHASE:
 1318                 case DATA_IN_PHASE:
 1319                 case STATUS_PHASE:
 1320                 case COMMAND_PHASE:
 1321                 case MSG_IN_PHASE:
 1322                 case MSG_OUT_PHASE:
 1323                         osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
 1324                         break;
 1325                 default:
 1326                         printf("%s: invalid phase\n", sc->sc_dev.dv_xname);
 1327                         goto bad_phase;
 1328                 }
 1329                 return (0);
 1330         }
 1331         if (sstat0 & OSIOP_SSTAT0_STO) {
 1332                 /* Select timed out */
 1333                 if (acb == NULL) {
 1334                         printf("%s: Select timeout with no active command?\n",
 1335                             sc->sc_dev.dv_xname);
 1336 #if 0
 1337                         return (0);
 1338 #else
 1339                         goto bad_phase;
 1340 #endif
 1341                 }
 1342 #ifdef OSIOP_DEBUG
 1343                 if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
 1344                         printf("ACK! osiop was busy at timeout: "
 1345                             "script %p dsa %lx\n", sc->sc_script,
 1346                             dsdma->dm_segs[0].ds_addr + acb->dsoffset);
 1347                         printf(" sbcl %x sdid %x "
 1348                             "istat %x dstat %x sstat0 %x\n",
 1349                             osiop_read_1(sc, OSIOP_SBCL),
 1350                             osiop_read_1(sc, OSIOP_SDID),
 1351                             istat, dstat, sstat0);
 1352                         if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) == 0) {
 1353                                 printf("Yikes, it's not busy now!\n");
 1354 #if 0
 1355                                 *status = SCSI_OSIOP_NOSTATUS;
 1356                                 if (!TAILQ_EMPTY(&sc->nexus_list))
 1357                                         osiop_write_4(sc, OSIOP_DSP,
 1358                                             scraddr + Ent_wait_reselect);
 1359                                 return (1);
 1360 #endif
 1361                         }
 1362 #if 0
 1363                         osiop_write_1(sc, OSIOP_DCNTL,
 1364                             osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1365 #endif
 1366 #ifdef DDB
 1367                         Debugger();
 1368 #endif
 1369                         return (0);
 1370                 }
 1371 #endif
 1372                 acb->status = ACB_S_DONE;
 1373                 *status = SCSI_OSIOP_NOSTATUS;
 1374                 acb->xs->error = XS_SELTIMEOUT;
 1375                 if (!TAILQ_EMPTY(&sc->nexus_list))
 1376                         osiop_write_4(sc, OSIOP_DSP,
 1377                             scraddr + Ent_wait_reselect);
 1378                 return (1);
 1379         }
 1380         if (acb != NULL)
 1381                 target = acb->xs->sc_link->target;
 1382         else
 1383                 target = sc->sc_id;
 1384         if (sstat0 & OSIOP_SSTAT0_UDC) {
 1385 #ifdef OSIOP_DEBUG
 1386                 if (acb == NULL)
 1387                         printf("%s: Unexpected disconnect "
 1388                             "with no active command?\n", sc->sc_dev.dv_xname);
 1389                 printf("%s: target %d disconnected unexpectedly\n",
 1390                     sc->sc_dev.dv_xname, target);
 1391 #endif
 1392 #if 0
 1393                 osiop_abort(sc, "osiop_chkintr");
 1394 #endif
 1395                 *status = SCSI_CHECK;
 1396                 if (!TAILQ_EMPTY(&sc->nexus_list))
 1397                         osiop_write_4(sc, OSIOP_DSP,
 1398                             scraddr + Ent_wait_reselect);
 1399                 return (acb != NULL);
 1400         }
 1401         if (dstat & OSIOP_DSTAT_SIR &&
 1402             (intcode == A_int_disc || intcode == A_int_disc_wodp)) {
 1403                 /* Disconnect */
 1404                 if (acb == NULL) {
 1405                         printf("%s: Disconnect with no active command?\n",
 1406                             sc->sc_dev.dv_xname);
 1407                         return (0);
 1408                 }
 1409 #ifdef OSIOP_DEBUG
 1410                 if (osiop_debug & DEBUG_DISC) {
 1411                         printf("%s: ID %02x disconnected TEMP %x (+%lx) "
 1412                             "curaddr %lx curlen %lx buf %x len %x dfifo %x "
 1413                             "dbc %x sstat1 %x starts %d acb %p\n",
 1414                             sc->sc_dev.dv_xname, 1 << target,
 1415                             osiop_read_4(sc, OSIOP_TEMP),
 1416                             (osiop_read_4(sc, OSIOP_TEMP) != 0) ?
 1417                                 osiop_read_4(sc, OSIOP_TEMP) - scraddr : 0,
 1418                             acb->curaddr, acb->curlen,
 1419                             ds->data[0].addr, ds->data[0].count,
 1420                             dfifo, dbc, sstat1, osiopstarts, acb);
 1421                         bus_dmamap_sync(sc->sc_dmat, dsdma,
 1422                             acb->dsoffset, sizeof(struct osiop_ds),
 1423                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1424                 }
 1425 #endif
 1426                 /*
 1427                  * XXXX need to update curaddr/curlen to reflect
 1428                  * current data transferred.  If device disconnected in
 1429                  * the middle of a DMA block, they should already be set
 1430                  * by the phase change interrupt.  If the disconnect
 1431                  * occurs on a DMA block boundary, we have to figure out
 1432                  * which DMA block it was.
 1433                  */
 1434                 if (acb->datalen > 0 &&
 1435                     osiop_read_4(sc, OSIOP_TEMP) != 0) {
 1436                         long n = osiop_read_4(sc, OSIOP_TEMP) - scraddr;
 1437 
 1438                         if (acb->curlen != 0 &&
 1439                             acb->curlen != ds->data[0].count)
 1440                                 printf("%s: curaddr/curlen already set? "
 1441                                     "n %lx iob %lx/%lx chain[0] %x/%x\n",
 1442                                     sc->sc_dev.dv_xname, n,
 1443                                     acb->curaddr, acb->curlen,
 1444                                     ds->data[0].addr, ds->data[0].count);
 1445                         if (n < Ent_datain)
 1446                                 n = (n - Ent_dataout) / 16;
 1447                         else
 1448                                 n = (n - Ent_datain) / 16;
 1449                         if (n < 0 || n >= OSIOP_NSG)
 1450                                 printf("TEMP invalid %ld\n", n);
 1451                         else {
 1452                                 acb->curaddr = ds->data[n].addr;
 1453                                 acb->curlen = ds->data[n].count;
 1454                         }
 1455 #ifdef OSIOP_DEBUG
 1456                         if (osiop_debug & DEBUG_DISC) {
 1457                                 printf("%s: TEMP offset %ld",
 1458                                     sc->sc_dev.dv_xname, n);
 1459                                 printf(" curaddr %lx curlen %lx\n",
 1460                                     acb->curaddr, acb->curlen);
 1461                         }
 1462 #endif
 1463                 }
 1464                 /*
 1465                  * If data transfer was interrupted by disconnect, curaddr
 1466                  * and curlen should reflect the point of interruption.
 1467                  * Adjust the DMA chain so that the data transfer begins
 1468                  * at the appropriate place upon reselection.
 1469                  * XXX This should only be done on save data pointer message?
 1470                  */
 1471                 if (acb->curlen > 0) {
 1472                         int i, j;
 1473 #ifdef OSIOP_DEBUG
 1474                         if (osiop_debug & DEBUG_DISC)
 1475                                 printf("%s: adjusting DMA chain\n",
 1476                                     sc->sc_dev.dv_xname);
 1477                         if (intcode == A_int_disc_wodp)
 1478                                 printf("%s: ID %02x disconnected "
 1479                                     "without Save Data Pointers\n",
 1480                                     sc->sc_dev.dv_xname, 1 << target);
 1481 #endif
 1482                         for (i = 0; i < OSIOP_NSG; i++) {
 1483                                 if (ds->data[i].count == 0)
 1484                                         break;
 1485                                 if (acb->curaddr >= ds->data[i].addr &&
 1486                                     acb->curaddr <
 1487                                     (ds->data[i].addr + ds->data[i].count))
 1488                                         break;
 1489                         }
 1490                         if (i >= OSIOP_NSG || ds->data[i].count == 0) {
 1491                                 printf("couldn't find saved data pointer: "
 1492                                     "curaddr %lx curlen %lx i %d\n",
 1493                                     acb->curaddr, acb->curlen, i);
 1494 #if defined(OSIOP_DEBUG) && defined(DDB)
 1495                                 Debugger();
 1496 #endif
 1497                         }
 1498 #ifdef OSIOP_DEBUG
 1499                         if (osiop_debug & DEBUG_DISC)
 1500                                 printf(" chain[0]: %x/%x -> %lx/%lx\n",
 1501                                     ds->data[0].addr, ds->data[0].count,
 1502                                     acb->curaddr, acb->curlen);
 1503 #endif
 1504                         ds->data[0].addr = acb->curaddr;
 1505                         ds->data[0].count = acb->curlen;
 1506                         for (j = 1, i = i + 1;
 1507                             i < OSIOP_NSG && ds->data[i].count > 0;
 1508                             i++, j++) {
 1509 #ifdef OSIOP_DEBUG
 1510                                 if (osiop_debug & DEBUG_DISC)
 1511                                         printf("  chain[%d]: %x/%x -> %x/%x\n",
 1512                                             j,
 1513                                             ds->data[j].addr, ds->data[j].count,
 1514                                             ds->data[i].addr, ds->data[i].count);
 1515 #endif
 1516                                 ds->data[j].addr  = ds->data[i].addr;
 1517                                 ds->data[j].count = ds->data[i].count;
 1518                         }
 1519                         if (j < OSIOP_NSG) {
 1520                                 ds->data[j].addr  = 0;
 1521                                 ds->data[j].count = 0;
 1522                         }
 1523                         bus_dmamap_sync(sc->sc_dmat, dsdma,
 1524                             acb->dsoffset, sizeof(struct osiop_ds),
 1525                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1526                 }
 1527                 sc->sc_tinfo[target].dconns++;
 1528                 /*
 1529                  * add nexus to waiting list
 1530                  * clear nexus
 1531                  * try to start another command for another target/lun
 1532                  */
 1533                 acb->intstat = sc->sc_flags & OSIOP_INTSOFF;
 1534                 TAILQ_INSERT_TAIL(&sc->nexus_list, acb, chain);
 1535                 sc->sc_nexus = NULL;            /* no current device */
 1536                 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_wait_reselect);
 1537                 /* XXXX start another command ? */
 1538                 osiop_sched(sc);
 1539                 return (0);
 1540         }
 1541         if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_reconnect) {
 1542                 int reselid = ffs(osiop_read_4(sc, OSIOP_SCRATCH) & 0xff) - 1;
 1543                 int reselun = osiop_read_1(sc, OSIOP_SFBR) & 0x07;
 1544 #ifdef OSIOP_DEBUG
 1545                 u_int8_t resmsg;
 1546 #endif
 1547 
 1548                 /* Reconnect */
 1549                 /* XXXX save current SBCL */
 1550                 sc->sc_sstat1 = osiop_read_1(sc, OSIOP_SBCL);
 1551 #ifdef OSIOP_DEBUG
 1552                 if (osiop_debug & DEBUG_DISC)
 1553                         printf("%s: target ID %02x reselected dsps %x\n",
 1554                             sc->sc_dev.dv_xname, reselid, intcode);
 1555                 resmsg = osiop_read_1(sc, OSIOP_SFBR);
 1556                 if (!MSG_ISIDENTIFY(resmsg))
 1557                         printf("%s: Reselect message in was not identify: "
 1558                             "%02x\n", sc->sc_dev.dv_xname, resmsg);
 1559 #endif
 1560                 if (sc->sc_nexus != NULL) {
 1561                         struct scsi_link *periph =
 1562                             sc->sc_nexus->xs->sc_link;
 1563 #ifdef OSIOP_DEBUG
 1564                         if (osiop_debug & DEBUG_DISC)
 1565                                 printf("%s: reselect ID %02x w/active\n",
 1566                                     sc->sc_dev.dv_xname, reselid);
 1567 #endif
 1568                         TAILQ_INSERT_HEAD(&sc->ready_list,
 1569                             sc->sc_nexus, chain);
 1570                         sc->sc_tinfo[periph->target].lubusy
 1571                             &= ~(1 << periph->lun);
 1572                         sc->sc_active--;
 1573                 }
 1574                 /*
 1575                  * locate acb of reselecting device
 1576                  * set sc->sc_nexus to acb
 1577                  */
 1578                 TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
 1579                         struct scsi_link *periph = acb->xs->sc_link;
 1580                         if (reselid != periph->target ||
 1581                             reselun != periph->lun) {
 1582                                 continue;
 1583                         }
 1584                         TAILQ_REMOVE(&sc->nexus_list, acb, chain);
 1585                         sc->sc_nexus = acb;
 1586                         sc->sc_flags |= acb->intstat;
 1587                         acb->intstat = 0;
 1588                         osiop_write_4(sc, OSIOP_DSA,
 1589                             dsdma->dm_segs[0].ds_addr + acb->dsoffset);
 1590                         osiop_write_1(sc, OSIOP_SXFER,
 1591                             sc->sc_tinfo[reselid].sxfer);
 1592                         osiop_write_1(sc, OSIOP_SBCL,
 1593                             sc->sc_tinfo[reselid].sbcl);
 1594                         break;
 1595                 }
 1596                 if (acb == NULL) {
 1597                         printf("%s: target ID %02x reselect nexus_list %p\n",
 1598                             sc->sc_dev.dv_xname, reselid,
 1599                             TAILQ_FIRST(&sc->nexus_list));
 1600                         panic("unable to find reselecting device");
 1601                 }
 1602 
 1603                 osiop_write_4(sc, OSIOP_TEMP, 0);
 1604                 osiop_write_1(sc, OSIOP_DCNTL,
 1605                     osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1606                 return (0);
 1607         }
 1608         if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_connect) {
 1609 #ifdef OSIOP_DEBUG
 1610                 u_int8_t ctest2 = osiop_read_1(sc, OSIOP_CTEST2);
 1611 
 1612                 /* reselect was interrupted (by Sig_P or select) */
 1613                 if (osiop_debug & DEBUG_DISC ||
 1614                     (ctest2 & OSIOP_CTEST2_SIGP) == 0)
 1615                         printf("%s: reselect interrupted (Sig_P?) "
 1616                             "scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
 1617                             sc->sc_dev.dv_xname,
 1618                             osiop_read_1(sc, OSIOP_SCNTL1), ctest2,
 1619                             osiop_read_1(sc, OSIOP_SFBR), istat,
 1620                             osiop_read_1(sc, OSIOP_ISTAT));
 1621 #endif
 1622                 /* XXX assumes it was not select */
 1623                 if (sc->sc_nexus == NULL) {
 1624 #ifdef OSIOP_DEBUG
 1625                         printf("%s: reselect interrupted, sc_nexus == NULL\n",
 1626                             sc->sc_dev.dv_xname);
 1627 #if 0
 1628                         osiop_dump(sc);
 1629 #ifdef DDB
 1630                         Debugger();
 1631 #endif
 1632 #endif
 1633 #endif
 1634                         osiop_write_1(sc, OSIOP_DCNTL,
 1635                             osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1636                         return (0);
 1637                 }
 1638                 target = sc->sc_nexus->xs->sc_link->target;
 1639                 osiop_write_4(sc, OSIOP_TEMP, 0);
 1640                 osiop_write_4(sc, OSIOP_DSA,
 1641                     dsdma->dm_segs[0].ds_addr + sc->sc_nexus->dsoffset);
 1642                 osiop_write_1(sc, OSIOP_SXFER, sc->sc_tinfo[target].sxfer);
 1643                 osiop_write_1(sc, OSIOP_SBCL, sc->sc_tinfo[target].sbcl);
 1644                 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_scripts);
 1645                 return (0);
 1646         }
 1647         if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_msgin) {
 1648                 /* Unrecognized message in byte */
 1649                 if (acb == NULL) {
 1650                         printf("%s: Bad message-in with no active command?\n",
 1651                             sc->sc_dev.dv_xname);
 1652                         return (0);
 1653                 }
 1654                 printf("%s: Unrecognized message in data "
 1655                     "sfbr %x msg %x sbcl %x\n", sc->sc_dev.dv_xname,
 1656                     osiop_read_1(sc, OSIOP_SFBR), ds->msgbuf[1],
 1657                     osiop_read_1(sc, OSIOP_SBCL));
 1658                 /* what should be done here? */
 1659                 osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
 1660                 bus_dmamap_sync(sc->sc_dmat, dsdma,
 1661                     acb->dsoffset, sizeof(struct osiop_ds),
 1662                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1663                 return (0);
 1664         }
 1665         if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_status) {
 1666                 /* Status phase wasn't followed by message in phase? */
 1667                 printf("%s: Status phase not followed by message in phase? "
 1668                     "sbcl %x sbdl %x\n", sc->sc_dev.dv_xname,
 1669                     osiop_read_1(sc, OSIOP_SBCL),
 1670                     osiop_read_1(sc, OSIOP_SBDL));
 1671                 if (osiop_read_1(sc, OSIOP_SBCL) == 0xa7) {
 1672                         /* It is now, just continue the script? */
 1673                         osiop_write_1(sc, OSIOP_DCNTL,
 1674                             osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
 1675                         return (0);
 1676                 }
 1677         }
 1678         if (dstat & OSIOP_DSTAT_SIR && sstat0 == 0) {
 1679                 printf("OSIOP interrupt: %x sts %x msg %x %x sbcl %x\n",
 1680                     intcode, ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
 1681                     osiop_read_1(sc, OSIOP_SBCL));
 1682                 osiop_reset(sc);
 1683                 *status = SCSI_OSIOP_NOSTATUS;
 1684                 return (0);     /* osiop_reset has cleaned up */
 1685         }
 1686         if (sstat0 & OSIOP_SSTAT0_SGE)
 1687                 printf("%s: SCSI Gross Error\n", sc->sc_dev.dv_xname);
 1688         if (sstat0 & OSIOP_SSTAT0_PAR)
 1689                 printf("%s: Parity Error\n", sc->sc_dev.dv_xname);
 1690         if (dstat & OSIOP_DSTAT_IID)
 1691                 printf("%s: Invalid instruction detected\n",
 1692                     sc->sc_dev.dv_xname);
 1693  bad_phase:
 1694         /*
 1695          * temporary panic for unhandled conditions
 1696          * displays various things about the 53C710 status and registers
 1697          * then panics.
 1698          * XXXX need to clean this up to print out the info, reset, and continue
 1699          */
 1700         printf("osiop_chkintr: target %x ds %p\n", target, ds);
 1701         printf("scripts %lx ds %lx dsp %x dcmd %x\n", scraddr,
 1702             sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset,
 1703             osiop_read_4(sc, OSIOP_DSP),
 1704             osiop_read_4(sc, OSIOP_DBC));
 1705         printf("osiop_chkintr: istat %x dstat %x sstat0 %x "
 1706             "dsps %x dsa %x sbcl %x sts %x msg %x %x sfbr %x\n",
 1707             istat, dstat, sstat0, intcode,
 1708             osiop_read_4(sc, OSIOP_DSA),
 1709             osiop_read_1(sc, OSIOP_SBCL),
 1710             ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
 1711             osiop_read_1(sc, OSIOP_SFBR));
 1712 #ifdef OSIOP_DEBUG
 1713         if (osiop_debug & DEBUG_DMA)
 1714                 panic("osiop_chkintr: **** temp ****");
 1715 #if 0
 1716 #ifdef DDB
 1717         Debugger();
 1718 #endif
 1719 #endif
 1720 #endif
 1721         osiop_reset(sc);        /* hard reset */
 1722         *status = SCSI_OSIOP_NOSTATUS;
 1723         if (acb != NULL)
 1724                 acb->status = ACB_S_DONE;
 1725         return (0);             /* osiop_reset cleaned up */
 1726 }
 1727 
 1728 void
 1729 osiop_select(sc)
 1730         struct osiop_softc *sc;
 1731 {
 1732         struct osiop_acb *acb = sc->sc_nexus;
 1733 
 1734 #ifdef OSIOP_DEBUG
 1735         if (osiop_debug & DEBUG_CMD)
 1736                 printf("%s: select ", sc->sc_dev.dv_xname);
 1737 #endif
 1738 
 1739         if (acb->xsflags & SCSI_POLL || sc->sc_flags & OSIOP_NODMA) {
 1740                 sc->sc_flags |= OSIOP_INTSOFF;
 1741                 sc->sc_flags &= ~OSIOP_INTDEFER;
 1742                 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
 1743                         osiop_write_1(sc, OSIOP_SIEN, 0);
 1744                         osiop_write_1(sc, OSIOP_DIEN, 0);
 1745                 }
 1746 #if 0
 1747         } else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
 1748                 sc->sc_flags &= ~OSIOP_INTSOFF;
 1749                 if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
 1750                         osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
 1751                         osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
 1752                 }
 1753 #endif
 1754         }
 1755 #ifdef OSIOP_DEBUG
 1756         if (osiop_debug & DEBUG_CMD)
 1757                 printf("osiop_select: target %x cmd %02x ds %p\n",
 1758                     acb->xs->sc_link->target,
 1759                     acb->ds->scsi_cmd.opcode, sc->sc_nexus->ds);
 1760 #endif
 1761 
 1762         osiop_start(sc);
 1763 
 1764         return;
 1765 }
 1766 
 1767 /*
 1768  * 53C710 interrupt handler
 1769  */
 1770 
 1771 void
 1772 osiop_intr(sc)
 1773         struct osiop_softc *sc;
 1774 {
 1775         int status, s;
 1776         u_int8_t istat, dstat, sstat0;
 1777 
 1778         s = splbio();
 1779 
 1780         istat = sc->sc_istat;
 1781         if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
 1782                 splx(s);
 1783                 return;
 1784         }
 1785 
 1786         /* Got a valid interrupt on this device; set by MD handler */
 1787         dstat = sc->sc_dstat;
 1788         sstat0 = sc->sc_sstat0;
 1789         sc->sc_istat = 0;
 1790 #ifdef OSIOP_DEBUG
 1791         if (!sc->sc_active) {
 1792                 /* XXX needs sync */
 1793                 printf("%s: spurious interrupt? "
 1794                     "istat %x dstat %x sstat0 %x nexus %p status %x\n",
 1795                     sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus,
 1796                     (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0);
 1797         }
 1798 #endif
 1799 
 1800 #ifdef OSIOP_DEBUG
 1801         if (osiop_debug & (DEBUG_INT|DEBUG_CMD)) {
 1802                 /* XXX needs sync */
 1803                 printf("%s: intr istat %x dstat %x sstat0 %x dsps %x "
 1804                     "sbcl %x dsp %x dcmd %x sts %x msg %x\n",
 1805                     sc->sc_dev.dv_xname,
 1806                     istat, dstat, sstat0,
 1807                     osiop_read_4(sc, OSIOP_DSPS),
 1808                     osiop_read_1(sc, OSIOP_SBCL),
 1809                     osiop_read_4(sc, OSIOP_DSP),
 1810                     osiop_read_4(sc, OSIOP_DBC),
 1811                     (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0,
 1812                     (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->msgbuf[0] : 0);
 1813         }
 1814 #endif
 1815         if (sc->sc_flags & OSIOP_INTDEFER) {
 1816                 sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
 1817                 osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
 1818                 osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
 1819         }
 1820         if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
 1821 #if 0
 1822                 if (status == SCSI_OSIOP_NOSTATUS)
 1823                         printf("osiop_intr: no valid status \n");
 1824 #endif
 1825                 if ((sc->sc_flags & (OSIOP_INTSOFF | OSIOP_INTDEFER)) !=
 1826                     OSIOP_INTSOFF) {
 1827 #if 0
 1828                         if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
 1829                                 struct scsi_link *periph;
 1830 
 1831                                 periph = sc->sc_nexus->xs->sc_link;
 1832                                 printf("%s: SCSI bus busy at completion"
 1833                                     " targ %d sbcl %02x sfbr %x lcrc "
 1834                                     "%02x dsp +%x\n", sc->sc_dev.dv_xname,
 1835                                     periph->periphtarget,
 1836                                     osiop_read_1(sc, OSIOP_SBCL),
 1837                                     osiop_read_1(sc, OSIOP_SFBR),
 1838                                     osiop_read_1(sc, OSIOP_LCRC),
 1839                                     osiop_read_4(sc, OSIOP_DSP) -
 1840                                         sc->sc_scrdma->dm_segs[0].ds_addr);
 1841                         }
 1842 #endif
 1843                         osiop_scsidone(sc->sc_nexus, status);
 1844                 }
 1845         }
 1846         splx(s);
 1847 }
 1848 
 1849 void
 1850 osiop_update_xfer_mode(sc, target)
 1851         struct osiop_softc *sc;
 1852         int target;
 1853 {
 1854         struct osiop_tinfo *ti = &sc->sc_tinfo[target];
 1855 
 1856         printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, target);
 1857 
 1858         ti->sxfer = 0;
 1859         ti->sbcl = 0;
 1860         if (ti->offset != 0) {
 1861                 scsi_period_to_osiop(sc, target);
 1862                 switch (ti->period) {
 1863                 case 0x00:
 1864                 case 0x01:
 1865                 case 0x02:
 1866                 case 0x03:
 1867                 case 0x04:
 1868                 case 0x05:
 1869                 case 0x06:
 1870                 case 0x07:
 1871                 case 0x08:
 1872                         /* Reserved transfer period factor */
 1873                         printf("??");
 1874                         break;
 1875                 case 0x09:
 1876                         /* Transfer period = 12.5 ns */
 1877                         printf("80");
 1878                         break;
 1879                 case 0x0a:
 1880                         /* Transfer period = 25 ns */
 1881                         printf("40");
 1882                         break;
 1883                 case 0x0b:
 1884                         /* Transfer period = 30.3 ns */
 1885                         printf("33");
 1886                         break;
 1887                 case 0x0c:
 1888                         /* Transfer period = 50 ns */
 1889                         printf("20");
 1890                         break;
 1891                 default:
 1892                         /* Transfer period = ti->period*4 ns */
 1893                         printf("%d", 1000/(ti->period*4));
 1894                         break;
 1895                 }
 1896                 printf(" MHz %d REQ/ACK offset", ti->offset);
 1897         } else
 1898                 printf("asynch");
 1899 
 1900         printf(" xfers\n");
 1901 }
 1902 
 1903 /*
 1904  * This is based on the Progressive Peripherals 33MHz Zeus driver and will
 1905  * not be correct for other 53c710 boards.
 1906  *
 1907  */
 1908 void
 1909 scsi_period_to_osiop(sc, target)
 1910         struct osiop_softc *sc;
 1911         int target;
 1912 {
 1913         int period, offset, sxfer, sbcl;
 1914 #ifdef OSIOP_DEBUG
 1915         int i;
 1916 #endif
 1917 
 1918         period = sc->sc_tinfo[target].period;
 1919         offset = sc->sc_tinfo[target].offset;
 1920 #ifdef OSIOP_DEBUG
 1921         if (osiop_debug & DEBUG_SYNC) {
 1922                 sxfer = 0;
 1923                 if (offset <= OSIOP_MAX_OFFSET)
 1924                         sxfer = offset;
 1925                 for (i = 0; i < sizeof(sync_tab) / sizeof(sync_tab[0]); i++) {
 1926                         if (period <= sync_tab[i].p) {
 1927                                 sxfer |= sync_tab[i].r & 0x70;
 1928                                 sbcl = sync_tab[i].r & 0x03;
 1929                                 break;
 1930                         }
 1931                 }
 1932                 printf("osiop sync old: osiop_sxfr %02x, osiop_sbcl %02x\n",
 1933                     sxfer, sbcl);
 1934         }
 1935 #endif
 1936         for (sbcl = 1; sbcl < 4; sbcl++) {
 1937                 sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3;
 1938                 if (sxfer >= 0 && sxfer <= 7)
 1939                         break;
 1940         }
 1941         if (sbcl > 3) {
 1942                 printf("osiop sync: unable to compute sync params "
 1943                     "for period %d ns\n", period * 4);
 1944                 /*
 1945                  * XXX need to pick a value we can do and renegotiate
 1946                  */
 1947                 sxfer = sbcl = 0;
 1948         } else {
 1949                 sxfer = (sxfer << 4) | ((offset <= OSIOP_MAX_OFFSET) ?
 1950                     offset : OSIOP_MAX_OFFSET);
 1951 #ifdef OSIOP_DEBUG
 1952                 if (osiop_debug & DEBUG_SYNC) {
 1953                         printf("osiop sync: params for period %dns: sxfer %x sbcl %x",
 1954                             period * 4, sxfer, sbcl);
 1955                         printf(" actual period %dns\n",
 1956                             sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4));
 1957                 }
 1958 #endif
 1959         }
 1960         sc->sc_tinfo[target].sxfer = sxfer;
 1961         sc->sc_tinfo[target].sbcl = sbcl;
 1962 #ifdef OSIOP_DEBUG
 1963         if (osiop_debug & DEBUG_SYNC)
 1964                 printf("osiop sync: osiop_sxfr %02x, osiop_sbcl %02x\n",
 1965                     sxfer, sbcl);
 1966 #endif
 1967 }
 1968 
 1969 void
 1970 osiop_timeout(arg)
 1971         void *arg;
 1972 {
 1973         struct osiop_acb *acb = arg;
 1974         struct scsi_xfer *xs = acb->xs;
 1975         struct osiop_softc *sc = acb->sc;
 1976         int s;
 1977 
 1978         sc_print_addr(xs->sc_link);
 1979         printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
 1980 
 1981         s = splbio();
 1982         /* reset the scsi bus */
 1983         osiop_resetbus(sc);
 1984 
 1985         acb->flags |= ACB_F_TIMEOUT;
 1986         osiop_reset(sc);
 1987         splx(s);
 1988         return;
 1989 }
 1990 
 1991 #ifdef OSIOP_DEBUG
 1992 
 1993 #if OSIOP_TRACE_SIZE
 1994 void
 1995 osiop_dump_trace()
 1996 {
 1997         int i;
 1998 
 1999         printf("osiop trace: next index %d\n", osiop_trix);
 2000         i = osiop_trix;
 2001         do {
 2002                 printf("%3d: '%c' %02x %02x %02x\n", i,
 2003                     osiop_trbuf[i], osiop_trbuf[i + 1],
 2004                     osiop_trbuf[i + 2], osiop_trbuf[i + 3]);
 2005                 i = (i + 4) & (OSIOP_TRACE_SIZE - 1);
 2006         } while (i != osiop_trix);
 2007 }
 2008 #endif
 2009 
 2010 void
 2011 osiop_dump_acb(acb)
 2012         struct osiop_acb *acb;
 2013 {
 2014         u_int8_t *b;
 2015         int i;
 2016 
 2017         printf("acb@%p ", acb);
 2018         if (acb->xs == NULL) {
 2019                 printf("<unused>\n");
 2020                 return;
 2021         }
 2022 
 2023         b = (u_int8_t *)&acb->ds->scsi_cmd;
 2024         printf("(%d:%d) status %2x cmdlen %2ld cmd ",
 2025             acb->xs->sc_link->target,
 2026             acb->xs->sc_link->lun,
 2027             acb->status,
 2028             acb->ds->cmd.count);
 2029         for (i = acb->ds->cmd.count; i > 0; i--)
 2030                 printf(" %02x", *b++);
 2031         printf("\n");
 2032         printf("  xs: %p data %p:%04x ", acb->xs, acb->data,
 2033             acb->datalen);
 2034         printf("cur %lx:%lx\n", acb->curaddr, acb->curlen);
 2035 }
 2036 
 2037 void
 2038 osiop_dump(sc)
 2039         struct osiop_softc *sc;
 2040 {
 2041         struct osiop_acb *acb;
 2042         int i, s;
 2043 
 2044         s = splbio();
 2045 #if OSIOP_TRACE_SIZE
 2046         osiop_dump_trace();
 2047 #endif
 2048         printf("%s@%p istat %02x\n",
 2049             sc->sc_dev.dv_xname, sc, osiop_read_1(sc, OSIOP_ISTAT));
 2050         if ((acb = TAILQ_FIRST(&sc->free_list)) != NULL) {
 2051                 printf("Free list:\n");
 2052                 while (acb) {
 2053                         osiop_dump_acb(acb);
 2054                         acb = TAILQ_NEXT(acb, chain);
 2055                 }
 2056         }
 2057         if ((acb = TAILQ_FIRST(&sc->ready_list)) != NULL) {
 2058                 printf("Ready list:\n");
 2059                 while (acb) {
 2060                         osiop_dump_acb(acb);
 2061                         acb = TAILQ_NEXT(acb, chain);
 2062                 }
 2063         }
 2064         if ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
 2065                 printf("Nexus list:\n");
 2066                 while (acb) {
 2067                         osiop_dump_acb(acb);
 2068                         acb = TAILQ_NEXT(acb, chain);
 2069                 }
 2070         }
 2071         if (sc->sc_nexus) {
 2072                 printf("Nexus:\n");
 2073                 osiop_dump_acb(sc->sc_nexus);
 2074         }
 2075         for (i = 0; i < OSIOP_NTGT; i++) {
 2076                 if (sc->sc_tinfo[i].cmds > 2) {
 2077                         printf("tgt %d: cmds %d disc %d lubusy %x\n",
 2078                             i, sc->sc_tinfo[i].cmds,
 2079                             sc->sc_tinfo[i].dconns,
 2080                             sc->sc_tinfo[i].lubusy);
 2081                 }
 2082         }
 2083         splx(s);
 2084 }
 2085 #endif

/* [<][>][^][v][top][bottom][index][help] */