The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/osiop.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a323854a9109595f169bffe978599b58


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.