[BACK]Return to osiop.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/osiop.c, Revision 1.1.1.1

1.1       nbrk        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

CVSweb