[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     ! 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