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

Annotation of sys/dev/ic/oosiop.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: oosiop.c,v 1.5 2006/11/28 23:59:45 dlg Exp $  */
        !             2: /*     $NetBSD: oosiop.c,v 1.4 2003/10/29 17:45:55 tsutsui Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2001 Shuichiro URATA.  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:  * NCR53C700 SCSI I/O processor (OOSIOP) driver
        !            32:  *
        !            33:  * TODO:
        !            34:  *   - Better error handling.
        !            35:  *   - Implement tagged queuing.
        !            36:  */
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/timeout.h>
        !            41: #include <sys/kernel.h>
        !            42: #include <sys/device.h>
        !            43: #include <sys/buf.h>
        !            44: #include <sys/malloc.h>
        !            45: #include <sys/queue.h>
        !            46:
        !            47: #include <uvm/uvm_extern.h>
        !            48:
        !            49: #include <scsi/scsi_all.h>
        !            50: #include <scsi/scsiconf.h>
        !            51: #include <scsi/scsi_message.h>
        !            52:
        !            53: #include <machine/cpu.h>
        !            54: #include <machine/bus.h>
        !            55:
        !            56: #include <dev/ic/oosiopreg.h>
        !            57: #include <dev/ic/oosiopvar.h>
        !            58:
        !            59: /* 53C700 script */
        !            60: #include <dev/microcode/siop/oosiop.out>
        !            61:
        !            62: int    oosiop_alloc_cb(struct oosiop_softc *, int);
        !            63:
        !            64: static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
        !            65: static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
        !            66: static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
        !            67:                         int);
        !            68: static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
        !            69:                         bus_addr_t);
        !            70: static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
        !            71:                         bus_size_t, bus_addr_t);
        !            72:
        !            73: void   oosiop_load_script(struct oosiop_softc *);
        !            74: void   oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
        !            75: void   oosiop_setup_dma(struct oosiop_softc *);
        !            76: void   oosiop_flush_fifo(struct oosiop_softc *);
        !            77: void   oosiop_clear_fifo(struct oosiop_softc *);
        !            78: void   oosiop_phasemismatch(struct oosiop_softc *);
        !            79: void   oosiop_setup_syncxfer(struct oosiop_softc *);
        !            80: void   oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
        !            81: void   oosiop_minphys(struct buf *);
        !            82: int    oosiop_scsicmd(struct scsi_xfer *);
        !            83: void   oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
        !            84: void   oosiop_timeout(void *);
        !            85: void   oosiop_reset(struct oosiop_softc *);
        !            86: void   oosiop_reset_bus(struct oosiop_softc *);
        !            87: void   oosiop_scriptintr(struct oosiop_softc *);
        !            88: void   oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
        !            89: void   oosiop_setup(struct oosiop_softc *, struct oosiop_cb *);
        !            90: void   oosiop_poll(struct oosiop_softc *, struct oosiop_cb *);
        !            91: void   oosiop_processintr(struct oosiop_softc *, u_int8_t);
        !            92:
        !            93: /* Trap interrupt code for unexpected data I/O */
        !            94: #define        DATAIN_TRAP     0xdead0001
        !            95: #define        DATAOUT_TRAP    0xdead0002
        !            96:
        !            97: /* Possible TP and SCF conbination */
        !            98: static const struct {
        !            99:        u_int8_t        tp;
        !           100:        u_int8_t        scf;
        !           101: } synctbl[] = {
        !           102:        {0, 1},         /* SCLK /  4.0 */
        !           103:        {1, 1},         /* SCLK /  5.0 */
        !           104:        {2, 1},         /* SCLK /  6.0 */
        !           105:        {3, 1},         /* SCLK /  7.0 */
        !           106:        {1, 2},         /* SCLK /  7.5 */
        !           107:        {4, 1},         /* SCLK /  8.0 */
        !           108:        {5, 1},         /* SCLK /  9.0 */
        !           109:        {6, 1},         /* SCLK / 10.0 */
        !           110:        {3, 2},         /* SCLK / 10.5 */
        !           111:        {7, 1},         /* SCLK / 11.0 */
        !           112:        {4, 2},         /* SCLK / 12.0 */
        !           113:        {5, 2},         /* SCLK / 13.5 */
        !           114:        {3, 3},         /* SCLK / 14.0 */
        !           115:        {6, 2},         /* SCLK / 15.0 */
        !           116:        {4, 3},         /* SCLK / 16.0 */
        !           117:        {7, 2},         /* SCLK / 16.5 */
        !           118:        {5, 3},         /* SCLK / 18.0 */
        !           119:        {6, 3},         /* SCLK / 20.0 */
        !           120:        {7, 3}          /* SCLK / 22.0 */
        !           121: };
        !           122: #define        NSYNCTBL        (sizeof(synctbl) / sizeof(synctbl[0]))
        !           123:
        !           124: #define        oosiop_period(sc, tp, scf)                                      \
        !           125:            (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
        !           126:
        !           127: struct cfdriver oosiop_cd = {
        !           128:        NULL, "oosiop", DV_DULL
        !           129: };
        !           130:
        !           131: struct scsi_adapter oosiop_adapter = {
        !           132:        oosiop_scsicmd,
        !           133:        oosiop_minphys,
        !           134:        NULL,
        !           135:        NULL
        !           136: };
        !           137:
        !           138: struct scsi_device oosiop_dev = {
        !           139:        NULL,
        !           140:        NULL,
        !           141:        NULL,
        !           142:        NULL
        !           143: };
        !           144:
        !           145: void
        !           146: oosiop_attach(struct oosiop_softc *sc)
        !           147: {
        !           148:        struct scsibus_attach_args saa;
        !           149:        bus_size_t scrsize;
        !           150:        bus_dma_segment_t seg;
        !           151:        struct oosiop_cb *cb;
        !           152:        int err, i, nseg;
        !           153:
        !           154:        /*
        !           155:         * Allocate DMA-safe memory for the script and map it.
        !           156:         */
        !           157:        scrsize = round_page(sizeof(oosiop_script));
        !           158:        err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
        !           159:            &nseg, BUS_DMA_NOWAIT);
        !           160:        if (err) {
        !           161:                printf(": failed to allocate script memory, err=%d\n", err);
        !           162:                return;
        !           163:        }
        !           164:        err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
        !           165:            (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
        !           166:        if (err) {
        !           167:                printf(": failed to map script memory, err=%d\n", err);
        !           168:                return;
        !           169:        }
        !           170:        err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
        !           171:            BUS_DMA_NOWAIT, &sc->sc_scrdma);
        !           172:        if (err) {
        !           173:                printf(": failed to create script map, err=%d\n", err);
        !           174:                return;
        !           175:        }
        !           176:        err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma,
        !           177:            &seg, nseg, scrsize, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
        !           178:        if (err) {
        !           179:                printf(": failed to load script map, err=%d\n", err);
        !           180:                return;
        !           181:        }
        !           182:        bzero(sc->sc_scr, scrsize);
        !           183:        sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
        !           184:
        !           185:        /* Initialize command block array */
        !           186:        TAILQ_INIT(&sc->sc_free_cb);
        !           187:        TAILQ_INIT(&sc->sc_cbq);
        !           188:        if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
        !           189:                return;
        !           190:
        !           191:        /* Use first cb to reselection msgin buffer */
        !           192:        cb = TAILQ_FIRST(&sc->sc_free_cb);
        !           193:        sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
        !           194:            offsetof(struct oosiop_xfer, msgin[0]);
        !           195:
        !           196:        for (i = 0; i < OOSIOP_NTGT; i++) {
        !           197:                sc->sc_tgt[i].nexus = NULL;
        !           198:                sc->sc_tgt[i].flags = 0;
        !           199:        }
        !           200:
        !           201:        /* Setup asynchronous clock divisor parameters */
        !           202:        if (sc->sc_freq <= 25000000) {
        !           203:                sc->sc_ccf = 10;
        !           204:                sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
        !           205:        } else if (sc->sc_freq <= 37500000) {
        !           206:                sc->sc_ccf = 15;
        !           207:                sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
        !           208:        } else if (sc->sc_freq <= 50000000) {
        !           209:                sc->sc_ccf = 20;
        !           210:                sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
        !           211:        } else {
        !           212:                sc->sc_ccf = 30;
        !           213:                sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
        !           214:        }
        !           215:
        !           216:        if (sc->sc_chip == OOSIOP_700)
        !           217:                sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
        !           218:        else
        !           219:                sc->sc_minperiod = oosiop_period(sc, 4, 10);
        !           220:
        !           221:        if (sc->sc_minperiod < 25)
        !           222:                sc->sc_minperiod = 25;  /* limit to 10MB/s */
        !           223:
        !           224:        printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
        !           225:            sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
        !           226:            oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
        !           227:            sc->sc_freq / 1000000, sc->sc_id);
        !           228:        /*
        !           229:         * Reset all
        !           230:         */
        !           231:        oosiop_reset(sc);
        !           232:        oosiop_reset_bus(sc);
        !           233:
        !           234:        /*
        !           235:         * Start SCRIPTS processor
        !           236:         */
        !           237:        oosiop_load_script(sc);
        !           238:        sc->sc_active = 0;
        !           239:        oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
        !           240:
        !           241:        /*
        !           242:         * Fill in the sc_link.
        !           243:         */
        !           244:        sc->sc_link.adapter = &oosiop_adapter;
        !           245:        sc->sc_link.adapter_softc = sc;
        !           246:        sc->sc_link.device = &oosiop_dev;
        !           247:        sc->sc_link.openings = 1;       /* XXX */
        !           248:        sc->sc_link.adapter_buswidth = OOSIOP_NTGT;
        !           249:        sc->sc_link.adapter_target = sc->sc_id;
        !           250:        sc->sc_link.quirks = ADEV_NODOORLOCK;
        !           251:
        !           252:        bzero(&saa, sizeof(saa));
        !           253:        saa.saa_sc_link = &sc->sc_link;
        !           254:
        !           255:        /*
        !           256:         * Now try to attach all the sub devices.
        !           257:         */
        !           258:        config_found(&sc->sc_dev, &saa, scsiprint);
        !           259: }
        !           260:
        !           261: int
        !           262: oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
        !           263: {
        !           264:        struct oosiop_cb *cb;
        !           265:        struct oosiop_xfer *xfer;
        !           266:        bus_size_t xfersize;
        !           267:        bus_dma_segment_t seg;
        !           268:        int i, s, err, nseg;
        !           269:
        !           270:        /*
        !           271:         * Allocate oosiop_cb.
        !           272:         */
        !           273:        cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT);
        !           274:        if (cb == NULL) {
        !           275:                printf(": failed to allocate cb memory\n");
        !           276:                return (ENOMEM);
        !           277:        }
        !           278:        bzero(cb, sizeof(struct oosiop_cb) * ncb);
        !           279:
        !           280:        /*
        !           281:         * Allocate DMA-safe memory for the oosiop_xfer and map it.
        !           282:         */
        !           283:        xfersize = sizeof(struct oosiop_xfer) * ncb;
        !           284:        err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
        !           285:            &nseg, BUS_DMA_NOWAIT);
        !           286:        if (err) {
        !           287:                printf(": failed to allocate xfer block memory, err=%d\n", err);
        !           288:                return (err);
        !           289:        }
        !           290:        err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
        !           291:            (caddr_t *)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
        !           292:        if (err) {
        !           293:                printf(": failed to map xfer block memory, err=%d\n", err);
        !           294:                return (err);
        !           295:        }
        !           296:
        !           297:        /* Initialize each command block */
        !           298:        for (i = 0; i < ncb; i++) {
        !           299:                err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
        !           300:                    0, BUS_DMA_NOWAIT, &cb->cmddma);
        !           301:                if (err) {
        !           302:                        printf(": failed to create cmddma map, err=%d\n", err);
        !           303:                        return (err);
        !           304:                }
        !           305:
        !           306:                err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
        !           307:                    OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
        !           308:                    &cb->datadma);
        !           309:                if (err) {
        !           310:                        printf(": failed to create datadma map, err=%d\n", err);
        !           311:                        return (err);
        !           312:                }
        !           313:
        !           314:                err = bus_dmamap_create(sc->sc_dmat,
        !           315:                    sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
        !           316:                    0, BUS_DMA_NOWAIT, &cb->xferdma);
        !           317:                if (err) {
        !           318:                        printf(": failed to create xfer block map, err=%d\n",
        !           319:                            err);
        !           320:                        return (err);
        !           321:                }
        !           322:                err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
        !           323:                    sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
        !           324:                if (err) {
        !           325:                        printf(": failed to load xfer block, err=%d\n", err);
        !           326:                        return (err);
        !           327:                }
        !           328:
        !           329:                cb->xfer = xfer;
        !           330:
        !           331:                s = splbio();
        !           332:                TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
        !           333:                splx(s);
        !           334:
        !           335:                cb++;
        !           336:                xfer++;
        !           337:        }
        !           338:
        !           339:        return (0);
        !           340: }
        !           341:
        !           342: static __inline void
        !           343: oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr)
        !           344: {
        !           345:        u_int32_t dcmd;
        !           346:        int32_t dsps;
        !           347:
        !           348:        dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
        !           349:        dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
        !           350:
        !           351:        /* convert relative to absolute */
        !           352:        if (dcmd & 0x04000000) {
        !           353:                dcmd &= ~0x04000000;
        !           354: #if 0
        !           355:                /*
        !           356:                 * sign extension isn't needed here because
        !           357:                 * ncr53cxxx.c generates 32 bit dsps.
        !           358:                 */
        !           359:                dsps <<= 8;
        !           360:                dsps >>= 8;
        !           361: #endif
        !           362:                sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
        !           363:                dsps += addr + 8;
        !           364:        }
        !           365:
        !           366:        sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
        !           367: }
        !           368:
        !           369: static __inline void
        !           370: oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr)
        !           371: {
        !           372:        u_int32_t dcmd;
        !           373:        int32_t dsps;
        !           374:
        !           375:        dcmd = letoh32(sc->sc_scr[addr / 4 + 0]);
        !           376:        dsps = letoh32(sc->sc_scr[addr / 4 + 1]);
        !           377:
        !           378:        /* convert relative to absolute */
        !           379:        if (dcmd & 0x00800000) {
        !           380:                dcmd &= ~0x00800000;
        !           381:                sc->sc_scr[addr / 4] = htole32(dcmd);
        !           382: #if 0
        !           383:                /*
        !           384:                 * sign extension isn't needed here because
        !           385:                 * ncr53cxxx.c generates 32 bit dsps.
        !           386:                 */
        !           387:                dsps <<= 8;
        !           388:                dsps >>= 8;
        !           389: #endif
        !           390:                dsps += addr + 8;
        !           391:        }
        !           392:
        !           393:        sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
        !           394: }
        !           395:
        !           396: static __inline void
        !           397: oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id)
        !           398: {
        !           399:        u_int32_t dcmd;
        !           400:
        !           401:        dcmd = letoh32(sc->sc_scr[addr / 4]);
        !           402:        dcmd &= 0xff00ffff;
        !           403:        dcmd |= 0x00010000 << id;
        !           404:        sc->sc_scr[addr / 4] = htole32(dcmd);
        !           405: }
        !           406:
        !           407: static __inline void
        !           408: oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst)
        !           409: {
        !           410:
        !           411:        sc->sc_scr[addr / 4 + 1] = htole32(dst);
        !           412: }
        !           413:
        !           414: static __inline void
        !           415: oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc,
        !           416:     bus_addr_t dsps)
        !           417: {
        !           418:        u_int32_t dcmd;
        !           419:
        !           420:        dcmd = letoh32(sc->sc_scr[addr / 4]);
        !           421:        dcmd &= 0xff000000;
        !           422:        dcmd |= dbc & 0x00ffffff;
        !           423:        sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
        !           424:        sc->sc_scr[addr / 4 + 1] = htole32(dsps);
        !           425: }
        !           426:
        !           427: void
        !           428: oosiop_load_script(struct oosiop_softc *sc)
        !           429: {
        !           430:        int i;
        !           431:
        !           432:        /* load script */
        !           433:        for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++)
        !           434:                sc->sc_scr[i] = htole32(oosiop_script[i]);
        !           435:
        !           436:        /* relocate script */
        !           437:        for (i = 0; i < (sizeof(oosiop_script) / 8); i++) {
        !           438:                switch (oosiop_script[i * 2] >> 27) {
        !           439:                case 0x08:      /* select */
        !           440:                case 0x0a:      /* wait reselect */
        !           441:                        oosiop_relocate_io(sc, i * 8);
        !           442:                        break;
        !           443:                case 0x10:      /* jump */
        !           444:                case 0x11:      /* call */
        !           445:                        oosiop_relocate_tc(sc, i * 8);
        !           446:                        break;
        !           447:                }
        !           448:        }
        !           449:
        !           450:        oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf);
        !           451:        OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
        !           452: }
        !           453:
        !           454: void
        !           455: oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb)
        !           456: {
        !           457:        struct oosiop_xfer *xfer = cb->xfer;
        !           458:        struct scsi_xfer *xs = cb->xs;
        !           459:        int i, n, off;
        !           460:
        !           461:        OOSIOP_XFERSCR_SYNC(sc, cb,
        !           462:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !           463:
        !           464:        off = cb->curdp;
        !           465:
        !           466:        if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
        !           467:                /* Find start segment */
        !           468:                for (i = 0; i < cb->datadma->dm_nsegs; i++) {
        !           469:                        if (off < cb->datadma->dm_segs[i].ds_len)
        !           470:                                break;
        !           471:                        off -= cb->datadma->dm_segs[i].ds_len;
        !           472:                }
        !           473:
        !           474:                /* build MOVE block */
        !           475:                if (xs->flags & SCSI_DATA_IN) {
        !           476:                        n = 0;
        !           477:                        while (i < cb->datadma->dm_nsegs) {
        !           478:                                xfer->datain_scr[n * 2 + 0] =
        !           479:                                    htole32(0x09000000 |
        !           480:                                    (cb->datadma->dm_segs[i].ds_len - off));
        !           481:                                xfer->datain_scr[n * 2 + 1] =
        !           482:                                    htole32(cb->datadma->dm_segs[i].ds_addr +
        !           483:                                    off);
        !           484:                                n++;
        !           485:                                i++;
        !           486:                                off = 0;
        !           487:                        }
        !           488:                        xfer->datain_scr[n * 2 + 0] = htole32(0x80080000);
        !           489:                        xfer->datain_scr[n * 2 + 1] =
        !           490:                            htole32(sc->sc_scrbase + Ent_phasedispatch);
        !           491:                }
        !           492:                if (xs->flags & SCSI_DATA_OUT) {
        !           493:                        n = 0;
        !           494:                        while (i < cb->datadma->dm_nsegs) {
        !           495:                                xfer->dataout_scr[n * 2 + 0] =
        !           496:                                    htole32(0x08000000 |
        !           497:                                    (cb->datadma->dm_segs[i].ds_len - off));
        !           498:                                xfer->dataout_scr[n * 2 + 1] =
        !           499:                                    htole32(cb->datadma->dm_segs[i].ds_addr +
        !           500:                                    off);
        !           501:                                n++;
        !           502:                                i++;
        !           503:                                off = 0;
        !           504:                        }
        !           505:                        xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000);
        !           506:                        xfer->dataout_scr[n * 2 + 1] =
        !           507:                            htole32(sc->sc_scrbase + Ent_phasedispatch);
        !           508:                }
        !           509:        }
        !           510:        if ((xs->flags & SCSI_DATA_IN) == 0) {
        !           511:                xfer->datain_scr[0] = htole32(0x98080000);
        !           512:                xfer->datain_scr[1] = htole32(DATAIN_TRAP);
        !           513:        }
        !           514:        if ((xs->flags & SCSI_DATA_OUT) == 0) {
        !           515:                xfer->dataout_scr[0] = htole32(0x98080000);
        !           516:                xfer->dataout_scr[1] = htole32(DATAOUT_TRAP);
        !           517:        }
        !           518:        OOSIOP_XFERSCR_SYNC(sc, cb,
        !           519:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           520: }
        !           521:
        !           522: /*
        !           523:  * Setup DMA pointer into script.
        !           524:  */
        !           525: void
        !           526: oosiop_setup_dma(struct oosiop_softc *sc)
        !           527: {
        !           528:        struct oosiop_cb *cb;
        !           529:        bus_addr_t xferbase;
        !           530:
        !           531:        cb = sc->sc_curcb;
        !           532:        xferbase = cb->xferdma->dm_segs[0].ds_addr;
        !           533:
        !           534:        OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
        !           535:
        !           536:        oosiop_fixup_select(sc, Ent_p_select, cb->id);
        !           537:        oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase +
        !           538:            offsetof(struct oosiop_xfer, datain_scr[0]));
        !           539:        oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase +
        !           540:            offsetof(struct oosiop_xfer, dataout_scr[0]));
        !           541:        oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase +
        !           542:            offsetof(struct oosiop_xfer, msgin[0]));
        !           543:        oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase +
        !           544:            offsetof(struct oosiop_xfer, msgin[1]));
        !           545:        oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase +
        !           546:            offsetof(struct oosiop_xfer, msgout[0]));
        !           547:        oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase +
        !           548:            offsetof(struct oosiop_xfer, status));
        !           549:        oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->cmdlen,
        !           550:            cb->cmddma->dm_segs[0].ds_addr);
        !           551:
        !           552:        OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
        !           553: }
        !           554:
        !           555: void
        !           556: oosiop_flush_fifo(struct oosiop_softc *sc)
        !           557: {
        !           558:
        !           559:        oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
        !           560:            OOSIOP_DFIFO_FLF);
        !           561:        while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
        !           562:            OOSIOP_CTEST1_FMT)
        !           563:                ;
        !           564:        oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
        !           565:            ~OOSIOP_DFIFO_FLF);
        !           566: }
        !           567:
        !           568: void
        !           569: oosiop_clear_fifo(struct oosiop_softc *sc)
        !           570: {
        !           571:
        !           572:        oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
        !           573:            OOSIOP_DFIFO_CLF);
        !           574:        while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
        !           575:            OOSIOP_CTEST1_FMT)
        !           576:                ;
        !           577:        oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
        !           578:            ~OOSIOP_DFIFO_CLF);
        !           579: }
        !           580:
        !           581: void
        !           582: oosiop_phasemismatch(struct oosiop_softc *sc)
        !           583: {
        !           584:        struct oosiop_cb *cb;
        !           585:        u_int32_t dsp, dbc, n, i, len;
        !           586:        u_int8_t dfifo, sstat1;
        !           587:
        !           588:        cb = sc->sc_curcb;
        !           589:        if (cb == NULL)
        !           590:                return;
        !           591:
        !           592:        dsp = oosiop_read_4(sc, OOSIOP_DSP);
        !           593:        dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX;
        !           594:        len = 0;
        !           595:
        !           596:        n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8;
        !           597:        if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) &&
        !           598:            n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) {
        !           599:                n -= offsetof(struct oosiop_xfer, datain_scr[0]);
        !           600:                n >>= 3;
        !           601:                OOSIOP_DINSCR_SYNC(sc, cb,
        !           602:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !           603:                for (i = 0; i <= n; i++)
        !           604:                        len += letoh32(cb->xfer->datain_scr[i * 2]) &
        !           605:                            0x00ffffff;
        !           606:                OOSIOP_DINSCR_SYNC(sc, cb,
        !           607:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           608:                /* All data in the chip are already flushed */
        !           609:        } else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) &&
        !           610:            n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) {
        !           611:                n -= offsetof(struct oosiop_xfer, dataout_scr[0]);
        !           612:                n >>= 3;
        !           613:                OOSIOP_DOUTSCR_SYNC(sc, cb,
        !           614:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !           615:                for (i = 0; i <= n; i++)
        !           616:                        len += letoh32(cb->xfer->dataout_scr[i * 2]) &
        !           617:                            0x00ffffff;
        !           618:                OOSIOP_DOUTSCR_SYNC(sc, cb,
        !           619:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           620:
        !           621:                dfifo = oosiop_read_1(sc, OOSIOP_DFIFO);
        !           622:                dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) &
        !           623:                    OOSIOP_DFIFO_BO;
        !           624:
        !           625:                sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1);
        !           626:                if (sstat1 & OOSIOP_SSTAT1_OLF)
        !           627:                        dbc++;
        !           628:                if ((sc->sc_tgt[cb->id].sxfer != 0) &&
        !           629:                    (sstat1 & OOSIOP_SSTAT1_ORF) != 0)
        !           630:                        dbc++;
        !           631:
        !           632:                oosiop_clear_fifo(sc);
        !           633:        } else {
        !           634:                printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname,
        !           635:                    oosiop_read_4(sc, OOSIOP_DSP) - 8);
        !           636:                oosiop_clear_fifo(sc);
        !           637:                return;
        !           638:        }
        !           639:
        !           640:        len -= dbc;
        !           641:        if (len) {
        !           642:                cb->curdp += len;
        !           643:                oosiop_setup_sgdma(sc, cb);
        !           644:        }
        !           645: }
        !           646:
        !           647: void
        !           648: oosiop_setup_syncxfer(struct oosiop_softc *sc)
        !           649: {
        !           650:        int id;
        !           651:
        !           652:        id = sc->sc_curcb->id;
        !           653:        if (sc->sc_chip != OOSIOP_700)
        !           654:                oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf);
        !           655:
        !           656:        oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer);
        !           657: }
        !           658:
        !           659: void
        !           660: oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset)
        !           661: {
        !           662:        int i, p;
        !           663:
        !           664:        printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, id);
        !           665:
        !           666:        if (offset == 0) {
        !           667:                /* Asynchronous */
        !           668:                sc->sc_tgt[id].scf = 0;
        !           669:                sc->sc_tgt[id].sxfer = 0;
        !           670:                printf("asynchronous");
        !           671:        } else {
        !           672:                /* Synchronous */
        !           673:                if (sc->sc_chip == OOSIOP_700) {
        !           674:                        for (i = 4; i < 12; i++) {
        !           675:                                p = oosiop_period(sc, i, sc->sc_ccf);
        !           676:                                if (p >= period)
        !           677:                                        break;
        !           678:                        }
        !           679:                        if (i == 12) {
        !           680:                                printf("%s: target %d period too large\n",
        !           681:                                    sc->sc_dev.dv_xname, id);
        !           682:                                i = 11; /* XXX */
        !           683:                        }
        !           684:                        sc->sc_tgt[id].scf = 0;
        !           685:                        sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset;
        !           686:                } else {
        !           687:                        for (i = 0; i < NSYNCTBL; i++) {
        !           688:                                p = oosiop_period(sc, synctbl[i].tp + 4,
        !           689:                                    (synctbl[i].scf + 1) * 5);
        !           690:                                if (p >= period)
        !           691:                                        break;
        !           692:                        }
        !           693:                        if (i == NSYNCTBL) {
        !           694:                                printf("%s: target %d period too large\n",
        !           695:                                    sc->sc_dev.dv_xname, id);
        !           696:                                i = NSYNCTBL - 1;       /* XXX */
        !           697:                        }
        !           698:                        sc->sc_tgt[id].scf = synctbl[i].scf;
        !           699:                        sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset;
        !           700:                }
        !           701:                /* XXX print actual ns period... */
        !           702:                printf(" synchronous");
        !           703:        }
        !           704:        printf(" xfers\n");
        !           705: }
        !           706:
        !           707: void
        !           708: oosiop_minphys(struct buf *bp)
        !           709: {
        !           710:
        !           711:        if (bp->b_bcount > OOSIOP_MAX_XFER)
        !           712:                bp->b_bcount = OOSIOP_MAX_XFER;
        !           713:        minphys(bp);
        !           714: }
        !           715:
        !           716: int
        !           717: oosiop_scsicmd(struct scsi_xfer *xs)
        !           718: {
        !           719:        struct oosiop_softc *sc;
        !           720:        struct oosiop_cb *cb;
        !           721:        struct oosiop_xfer *xfer;
        !           722:        int s, err;
        !           723:
        !           724:        sc = (struct oosiop_softc *)xs->sc_link->adapter_softc;
        !           725:
        !           726:        s = splbio();
        !           727:        cb = TAILQ_FIRST(&sc->sc_free_cb);
        !           728:        TAILQ_REMOVE(&sc->sc_free_cb, cb, chain);
        !           729:        splx(s);
        !           730:
        !           731:        cb->xs = xs;
        !           732:        cb->xsflags = xs->flags;
        !           733:        cb->cmdlen = xs->cmdlen;
        !           734:        cb->datalen = 0;
        !           735:        cb->flags = 0;
        !           736:        cb->id = xs->sc_link->target;
        !           737:        cb->lun = xs->sc_link->lun;
        !           738:        xfer = cb->xfer;
        !           739:
        !           740:        /* Setup SCSI command buffer DMA */
        !           741:        err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd,
        !           742:            xs->cmdlen, NULL, ((xs->flags & SCSI_NOSLEEP) ?
        !           743:            BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
        !           744:            BUS_DMA_STREAMING | BUS_DMA_WRITE);
        !           745:        if (err) {
        !           746:                printf("%s: unable to load cmd DMA map: %d",
        !           747:                    sc->sc_dev.dv_xname, err);
        !           748:                xs->error = XS_DRIVER_STUFFUP;
        !           749:                scsi_done(xs);
        !           750:                TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
        !           751:                return (COMPLETE);
        !           752:        }
        !           753:        bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
        !           754:            BUS_DMASYNC_PREWRITE);
        !           755:
        !           756:        /* Setup data buffer DMA */
        !           757:        if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
        !           758:                cb->datalen = xs->datalen;
        !           759:                err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
        !           760:                    xs->data, xs->datalen, NULL,
        !           761:                    ((xs->flags & SCSI_NOSLEEP) ?
        !           762:                    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
        !           763:                    BUS_DMA_STREAMING |
        !           764:                    ((xs->flags & SCSI_DATA_IN) ? BUS_DMA_READ :
        !           765:                    BUS_DMA_WRITE));
        !           766:                if (err) {
        !           767:                        printf("%s: unable to load data DMA map: %d",
        !           768:                            sc->sc_dev.dv_xname, err);
        !           769:                        xs->error = XS_DRIVER_STUFFUP;
        !           770:                        bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
        !           771:                        scsi_done(xs);
        !           772:                        TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
        !           773:                        return (COMPLETE);
        !           774:                }
        !           775:                bus_dmamap_sync(sc->sc_dmat, cb->datadma,
        !           776:                    0, xs->datalen,
        !           777:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           778:        }
        !           779:
        !           780:        xfer->status = SCSI_OOSIOP_NOSTATUS;
        !           781:
        !           782:        oosiop_setup(sc, cb);
        !           783:
        !           784:        s = splbio();
        !           785:
        !           786:        /*
        !           787:         * Always initialize timeout so it does not contain trash
        !           788:         * that could confuse timeout_del().
        !           789:         */
        !           790:        timeout_set(&xs->stimeout, oosiop_timeout, cb);
        !           791:
        !           792:        TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain);
        !           793:
        !           794:        if (!sc->sc_active) {
        !           795:                /* Abort script to start selection */
        !           796:                oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
        !           797:        }
        !           798:        if (xs->flags & SCSI_POLL)
        !           799:                oosiop_poll(sc, cb);
        !           800:        else {
        !           801:                /* start expire timer */
        !           802:                timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
        !           803:        }
        !           804:
        !           805:        splx(s);
        !           806:
        !           807:        if ((xs->flags & ITSDONE) == 0)
        !           808:                return (SUCCESSFULLY_QUEUED);
        !           809:        else
        !           810:                return (COMPLETE);
        !           811: }
        !           812:
        !           813: void
        !           814: oosiop_poll(struct oosiop_softc *sc, struct oosiop_cb *cb)
        !           815: {
        !           816:        struct scsi_xfer *xs = cb->xs;
        !           817:        int i, s, to;
        !           818:        u_int8_t istat;
        !           819:
        !           820:        s = splbio();
        !           821:        to = xs->timeout / 1000;
        !           822:        for (;;) {
        !           823:                i = 1000;
        !           824:                while (((istat = oosiop_read_1(sc, OOSIOP_ISTAT)) &
        !           825:                    (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0) {
        !           826:                        if (i <= 0) {
        !           827:                                i = 1000;
        !           828:                                to--;
        !           829:                                if (to <= 0) {
        !           830:                                        oosiop_reset(sc);
        !           831:                                        splx(s);
        !           832:                                        return;
        !           833:                                }
        !           834:                        }
        !           835:                        delay(1000);
        !           836:                        i--;
        !           837:                }
        !           838:                oosiop_processintr(sc, istat);
        !           839:
        !           840:                if (xs->flags & ITSDONE)
        !           841:                        break;
        !           842:        }
        !           843:
        !           844:        splx(s);
        !           845: }
        !           846:
        !           847: void
        !           848: oosiop_setup(struct oosiop_softc *sc, struct oosiop_cb *cb)
        !           849: {
        !           850:        struct oosiop_xfer *xfer = cb->xfer;
        !           851:
        !           852:        cb->curdp = 0;
        !           853:        cb->savedp = 0;
        !           854:
        !           855:        oosiop_setup_sgdma(sc, cb);
        !           856:
        !           857:        /* Setup msgout buffer */
        !           858:        OOSIOP_XFERMSG_SYNC(sc, cb,
        !           859:           BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !           860:        xfer->msgout[0] = MSG_IDENTIFY(cb->lun,
        !           861:            (cb->xs->cmd->opcode != REQUEST_SENSE));
        !           862:        cb->msgoutlen = 1;
        !           863:
        !           864:        if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) {
        !           865:                /* Send SDTR */
        !           866:                xfer->msgout[1] = MSG_EXTENDED;
        !           867:                xfer->msgout[2] = MSG_EXT_SDTR_LEN;
        !           868:                xfer->msgout[3] = MSG_EXT_SDTR;
        !           869:                xfer->msgout[4] = sc->sc_minperiod;
        !           870:                xfer->msgout[5] = OOSIOP_MAX_OFFSET;
        !           871:                cb->msgoutlen = 6;
        !           872:                sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG;
        !           873:                sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR;
        !           874:        }
        !           875:
        !           876:        OOSIOP_XFERMSG_SYNC(sc, cb,
        !           877:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !           878: }
        !           879:
        !           880: void
        !           881: oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb)
        !           882: {
        !           883:        struct scsi_xfer *xs;
        !           884:        struct scsi_link *periph;
        !           885:        int autosense;
        !           886:
        !           887:        xs = cb->xs;
        !           888:        periph = xs->sc_link;
        !           889:
        !           890:        /*
        !           891:         * Record if this is the completion of an auto sense
        !           892:         * scsi command, and then reset the flag so we don't loop
        !           893:         * when such a command fails or times out.
        !           894:         */
        !           895:        autosense = cb->flags & CBF_AUTOSENSE;
        !           896:        cb->flags &= ~CBF_AUTOSENSE;
        !           897:
        !           898:        bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, cb->cmdlen,
        !           899:            BUS_DMASYNC_POSTWRITE);
        !           900:        bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
        !           901:
        !           902:        if (cb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
        !           903:                bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, cb->datalen,
        !           904:                    (cb->xsflags & SCSI_DATA_IN) ?
        !           905:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
        !           906:                bus_dmamap_unload(sc->sc_dmat, cb->datadma);
        !           907:        }
        !           908:
        !           909:        timeout_del(&xs->stimeout);
        !           910:
        !           911:        xs->status = cb->xfer->status;
        !           912:
        !           913:        if (cb->flags & CBF_SELTOUT)
        !           914:                xs->error = XS_SELTIMEOUT;
        !           915:        else if (cb->flags & CBF_TIMEOUT)
        !           916:                xs->error = XS_TIMEOUT;
        !           917:        else switch (xs->status) {
        !           918:        case SCSI_OK:
        !           919:                if (autosense == 0)
        !           920:                        xs->error = XS_NOERROR;
        !           921:                else
        !           922:                        xs->error = XS_SENSE;
        !           923:                break;
        !           924:
        !           925:        case SCSI_BUSY:
        !           926:                xs->error = XS_BUSY;
        !           927:                break;
        !           928:        case SCSI_CHECK:
        !           929: #ifdef notyet
        !           930:                if (autosense == 0)
        !           931:                        cb->flags |= CBF_AUTOSENSE;
        !           932:                else
        !           933: #endif
        !           934:                        xs->error = XS_DRIVER_STUFFUP;
        !           935:                break;
        !           936:        case SCSI_OOSIOP_NOSTATUS:
        !           937:                /* the status byte was not updated, cmd was aborted. */
        !           938:                xs->error = XS_SELTIMEOUT;
        !           939:                break;
        !           940:
        !           941:        default:
        !           942:                xs->error = XS_RESET;
        !           943:                break;
        !           944:        }
        !           945:
        !           946:        if ((cb->flags & CBF_AUTOSENSE) == 0) {
        !           947:                /* Put it on the free list. */
        !           948: FREE:
        !           949:                xs->resid = 0;
        !           950:                xs->flags |= ITSDONE;
        !           951:                scsi_done(xs);
        !           952:                TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
        !           953:
        !           954:                if (cb == sc->sc_curcb)
        !           955:                        sc->sc_curcb = NULL;
        !           956:                if (cb == sc->sc_lastcb)
        !           957:                        sc->sc_lastcb = NULL;
        !           958:                sc->sc_tgt[cb->id].nexus = NULL;
        !           959:        } else {
        !           960:                /* Set up REQUEST_SENSE command */
        !           961:                struct scsi_sense *cmd = (struct scsi_sense *)xs->cmd;
        !           962:                int err;
        !           963:
        !           964:                bzero(cmd, sizeof(*cmd));
        !           965:                cmd->opcode = REQUEST_SENSE;
        !           966:                cmd->byte2 = xs->sc_link->lun << 5;
        !           967:                cb->cmdlen = cmd->length = sizeof(xs->sense);
        !           968:
        !           969:                cb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
        !           970:                cb->xsflags |= SCSI_DATA_IN;
        !           971:                cb->datalen = sizeof xs->sense;
        !           972:
        !           973:                /* Setup SCSI command buffer DMA */
        !           974:                err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, cmd,
        !           975:                    cb->cmdlen, NULL,
        !           976:                    BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_WRITE);
        !           977:                if (err) {
        !           978:                        printf("%s: unable to load REQUEST_SENSE cmd DMA map: %d",
        !           979:                            sc->sc_dev.dv_xname, err);
        !           980:                        xs->error = XS_DRIVER_STUFFUP;
        !           981:                        goto FREE;
        !           982:                }
        !           983:                bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, cb->cmdlen,
        !           984:                    BUS_DMASYNC_PREWRITE);
        !           985:
        !           986:                /* Setup data buffer DMA */
        !           987:                err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
        !           988:                    &xs->sense, sizeof(xs->sense), NULL,
        !           989:                    BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
        !           990:                if (err) {
        !           991:                        printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
        !           992:                            sc->sc_dev.dv_xname, err);
        !           993:                        xs->error = XS_DRIVER_STUFFUP;
        !           994:                        bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
        !           995:                        goto FREE;
        !           996:                }
        !           997:                bus_dmamap_sync(sc->sc_dmat, cb->datadma,
        !           998:                    0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
        !           999:
        !          1000:                oosiop_setup(sc, cb);
        !          1001:
        !          1002:                TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
        !          1003:                if ((cb->xs->flags & SCSI_POLL) == 0) {
        !          1004:                        /* start expire timer */
        !          1005:                        timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz);
        !          1006:                }
        !          1007:        }
        !          1008: }
        !          1009:
        !          1010: void
        !          1011: oosiop_timeout(void *arg)
        !          1012: {
        !          1013:        struct oosiop_cb *cb = arg;
        !          1014:        struct scsi_xfer *xs = cb->xs;
        !          1015:        struct oosiop_softc *sc = xs->sc_link->adapter_softc;
        !          1016:        int s;
        !          1017:
        !          1018:        sc_print_addr(xs->sc_link);
        !          1019:        printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
        !          1020:
        !          1021:        s = splbio();
        !          1022:
        !          1023:        oosiop_reset_bus(sc);
        !          1024:
        !          1025:        cb->flags |= CBF_TIMEOUT;
        !          1026:        oosiop_done(sc, cb);
        !          1027:
        !          1028:        splx(s);
        !          1029: }
        !          1030:
        !          1031: void
        !          1032: oosiop_reset(struct oosiop_softc *sc)
        !          1033: {
        !          1034:        int i, s;
        !          1035:
        !          1036:        s = splbio();
        !          1037:
        !          1038:        /* Stop SCRIPTS processor */
        !          1039:        oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
        !          1040:        delay(100);
        !          1041:        oosiop_write_1(sc, OOSIOP_ISTAT, 0);
        !          1042:
        !          1043:        /* Reset the chip */
        !          1044:        oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST);
        !          1045:        delay(100);
        !          1046:        oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
        !          1047:        delay(10000);
        !          1048:
        !          1049:        /* Set up various chip parameters */
        !          1050:        oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG);
        !          1051:        oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR);
        !          1052:        oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
        !          1053:        oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8);
        !          1054:        oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id));
        !          1055:        oosiop_write_1(sc, OOSIOP_DWT, 0xff);   /* Enable DMA timeout */
        !          1056:        oosiop_write_1(sc, OOSIOP_CTEST7, 0);
        !          1057:        oosiop_write_1(sc, OOSIOP_SXFER, 0);
        !          1058:
        !          1059:        /* Clear all interrupts */
        !          1060:        (void)oosiop_read_1(sc, OOSIOP_SSTAT0);
        !          1061:        (void)oosiop_read_1(sc, OOSIOP_SSTAT1);
        !          1062:        (void)oosiop_read_1(sc, OOSIOP_DSTAT);
        !          1063:
        !          1064:        /* Enable interrupts */
        !          1065:        oosiop_write_1(sc, OOSIOP_SIEN,
        !          1066:            OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE |
        !          1067:            OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR);
        !          1068:        oosiop_write_1(sc, OOSIOP_DIEN,
        !          1069:            OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR |
        !          1070:            OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID);
        !          1071:
        !          1072:        /* Set target state to asynchronous */
        !          1073:        for (i = 0; i < OOSIOP_NTGT; i++) {
        !          1074:                sc->sc_tgt[i].flags = 0;
        !          1075:                sc->sc_tgt[i].scf = 0;
        !          1076:                sc->sc_tgt[i].sxfer = 0;
        !          1077:        }
        !          1078:
        !          1079:        splx(s);
        !          1080: }
        !          1081:
        !          1082: void
        !          1083: oosiop_reset_bus(struct oosiop_softc *sc)
        !          1084: {
        !          1085:        int s, i;
        !          1086:
        !          1087:        s = splbio();
        !          1088:
        !          1089:        /* Assert SCSI RST */
        !          1090:        oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST);
        !          1091:        delay(25);      /* Reset hold time (25us) */
        !          1092:        oosiop_write_1(sc, OOSIOP_SCNTL1, 0);
        !          1093:
        !          1094:        /* Remove all nexuses */
        !          1095:        for (i = 0; i < OOSIOP_NTGT; i++) {
        !          1096:                if (sc->sc_tgt[i].nexus) {
        !          1097:                        sc->sc_tgt[i].nexus->xfer->status =
        !          1098:                            SCSI_OOSIOP_NOSTATUS; /* XXX */
        !          1099:                        oosiop_done(sc, sc->sc_tgt[i].nexus);
        !          1100:                }
        !          1101:        }
        !          1102:
        !          1103:        sc->sc_curcb = NULL;
        !          1104:
        !          1105:        delay(250000);  /* Reset to selection (250ms) */
        !          1106:
        !          1107:        splx(s);
        !          1108: }
        !          1109:
        !          1110: /*
        !          1111:  * interrupt handler
        !          1112:  */
        !          1113: int
        !          1114: oosiop_intr(struct oosiop_softc *sc)
        !          1115: {
        !          1116:        u_int8_t istat;
        !          1117:
        !          1118:        istat = oosiop_read_1(sc, OOSIOP_ISTAT);
        !          1119:
        !          1120:        if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0)
        !          1121:                return (0);
        !          1122:
        !          1123:        oosiop_processintr(sc, istat);
        !          1124:        return (1);
        !          1125: }
        !          1126:
        !          1127: void
        !          1128: oosiop_processintr(struct oosiop_softc *sc, u_int8_t istat)
        !          1129: {
        !          1130:        struct oosiop_cb *cb;
        !          1131:        u_int32_t dcmd;
        !          1132:        u_int8_t dstat, sstat0;
        !          1133:
        !          1134:        sc->sc_nextdsp = Ent_wait_reselect;
        !          1135:
        !          1136:        /* DMA interrupts */
        !          1137:        if (istat & OOSIOP_ISTAT_DIP) {
        !          1138:                oosiop_write_1(sc, OOSIOP_ISTAT, 0);
        !          1139:
        !          1140:                dstat = oosiop_read_1(sc, OOSIOP_DSTAT);
        !          1141:
        !          1142:                if (dstat & OOSIOP_DSTAT_ABRT) {
        !          1143:                        sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
        !          1144:                            sc->sc_scrbase - 8;
        !          1145:
        !          1146:                        if (sc->sc_nextdsp == Ent_p_resel_msgin_move &&
        !          1147:                            (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) {
        !          1148:                                if ((dstat & OOSIOP_DSTAT_DFE) == 0)
        !          1149:                                        oosiop_flush_fifo(sc);
        !          1150:                                sc->sc_nextdsp += 8;
        !          1151:                        }
        !          1152:                }
        !          1153:
        !          1154:                if (dstat & OOSIOP_DSTAT_SSI) {
        !          1155:                        sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
        !          1156:                            sc->sc_scrbase;
        !          1157:                        printf("%s: single step %08x\n", sc->sc_dev.dv_xname,
        !          1158:                            sc->sc_nextdsp);
        !          1159:                }
        !          1160:
        !          1161:                if (dstat & OOSIOP_DSTAT_SIR) {
        !          1162:                        if ((dstat & OOSIOP_DSTAT_DFE) == 0)
        !          1163:                                oosiop_flush_fifo(sc);
        !          1164:                        oosiop_scriptintr(sc);
        !          1165:                }
        !          1166:
        !          1167:                if (dstat & OOSIOP_DSTAT_WTD) {
        !          1168:                        printf("%s: DMA time out\n", sc->sc_dev.dv_xname);
        !          1169:                        oosiop_reset(sc);
        !          1170:                }
        !          1171:
        !          1172:                if (dstat & OOSIOP_DSTAT_IID) {
        !          1173:                        dcmd = oosiop_read_4(sc, OOSIOP_DBC);
        !          1174:                        if ((dcmd & 0xf8000000) == 0x48000000) {
        !          1175:                                printf("%s: REQ asserted on WAIT DISCONNECT\n",
        !          1176:                                    sc->sc_dev.dv_xname);
        !          1177:                                sc->sc_nextdsp = Ent_phasedispatch; /* XXX */
        !          1178:                        } else {
        !          1179:                                printf("%s: invalid SCRIPTS instruction "
        !          1180:                                    "addr=%08x dcmd=%08x dsps=%08x\n",
        !          1181:                                    sc->sc_dev.dv_xname,
        !          1182:                                    oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd,
        !          1183:                                    oosiop_read_4(sc, OOSIOP_DSPS));
        !          1184:                                oosiop_reset(sc);
        !          1185:                                OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
        !          1186:                                oosiop_load_script(sc);
        !          1187:                        }
        !          1188:                }
        !          1189:
        !          1190:                if ((dstat & OOSIOP_DSTAT_DFE) == 0)
        !          1191:                        oosiop_clear_fifo(sc);
        !          1192:        }
        !          1193:
        !          1194:        /* SCSI interrupts */
        !          1195:        if (istat & OOSIOP_ISTAT_SIP) {
        !          1196:                if (istat & OOSIOP_ISTAT_DIP)
        !          1197:                        delay(1);
        !          1198:                sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0);
        !          1199:
        !          1200:                if (sstat0 & OOSIOP_SSTAT0_M_A) {
        !          1201:                        /* SCSI phase mismatch during MOVE operation */
        !          1202:                        oosiop_phasemismatch(sc);
        !          1203:                        sc->sc_nextdsp = Ent_phasedispatch;
        !          1204:                }
        !          1205:
        !          1206:                if (sstat0 & OOSIOP_SSTAT0_STO) {
        !          1207:                        if (sc->sc_curcb) {
        !          1208:                                sc->sc_curcb->flags |= CBF_SELTOUT;
        !          1209:                                oosiop_done(sc, sc->sc_curcb);
        !          1210:                        }
        !          1211:                }
        !          1212:
        !          1213:                if (sstat0 & OOSIOP_SSTAT0_SGE) {
        !          1214:                        printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname);
        !          1215:                        oosiop_reset(sc);
        !          1216:                }
        !          1217:
        !          1218:                if (sstat0 & OOSIOP_SSTAT0_UDC) {
        !          1219:                        /* XXX */
        !          1220:                        if (sc->sc_curcb) {
        !          1221:                                printf("%s: unexpected disconnect\n",
        !          1222:                                    sc->sc_dev.dv_xname);
        !          1223:                                oosiop_done(sc, sc->sc_curcb);
        !          1224:                        }
        !          1225:                }
        !          1226:
        !          1227:                if (sstat0 & OOSIOP_SSTAT0_RST)
        !          1228:                        oosiop_reset(sc);
        !          1229:
        !          1230:                if (sstat0 & OOSIOP_SSTAT0_PAR)
        !          1231:                        printf("%s: parity error\n", sc->sc_dev.dv_xname);
        !          1232:        }
        !          1233:
        !          1234:        /* Start next command if available */
        !          1235:        if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) {
        !          1236:                cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq);
        !          1237:                TAILQ_REMOVE(&sc->sc_cbq, cb, chain);
        !          1238:                sc->sc_tgt[cb->id].nexus = cb;
        !          1239:
        !          1240:                oosiop_setup_dma(sc);
        !          1241:                oosiop_setup_syncxfer(sc);
        !          1242:                sc->sc_lastcb = cb;
        !          1243:                sc->sc_nextdsp = Ent_start_select;
        !          1244:
        !          1245:                /* Schedule timeout */
        !          1246:                if ((cb->xs->flags & SCSI_POLL) == 0) {
        !          1247:                        /* start expire timer */
        !          1248:                        timeout_add(&cb->xs->stimeout,
        !          1249:                            (cb->xs->timeout / 1000) * hz);
        !          1250:                }
        !          1251:        }
        !          1252:
        !          1253:        sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect);
        !          1254:
        !          1255:        /* Restart script */
        !          1256:        oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase);
        !          1257: }
        !          1258:
        !          1259: void
        !          1260: oosiop_scriptintr(struct oosiop_softc *sc)
        !          1261: {
        !          1262:        struct oosiop_cb *cb;
        !          1263:        u_int32_t icode;
        !          1264:        u_int32_t dsp;
        !          1265:        int i;
        !          1266:        u_int8_t sfbr, resid, resmsg;
        !          1267:
        !          1268:        cb = sc->sc_curcb;
        !          1269:        icode = oosiop_read_4(sc, OOSIOP_DSPS);
        !          1270:
        !          1271:        switch (icode) {
        !          1272:        case A_int_done:
        !          1273:                if (cb)
        !          1274:                        oosiop_done(sc, cb);
        !          1275:                break;
        !          1276:
        !          1277:        case A_int_msgin:
        !          1278:                if (cb)
        !          1279:                        oosiop_msgin(sc, cb);
        !          1280:                break;
        !          1281:
        !          1282:        case A_int_extmsg:
        !          1283:                /* extended message in DMA setup request */
        !          1284:                sfbr = oosiop_read_1(sc, OOSIOP_SFBR);
        !          1285:                OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
        !          1286:                oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr,
        !          1287:                    cb->xferdma->dm_segs[0].ds_addr +
        !          1288:                    offsetof(struct oosiop_xfer, msgin[2]));
        !          1289:                OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
        !          1290:                sc->sc_nextdsp = Ent_rcv_extmsg;
        !          1291:                break;
        !          1292:
        !          1293:        case A_int_resel:
        !          1294:                /* reselected */
        !          1295:                resid = oosiop_read_1(sc, OOSIOP_SFBR);
        !          1296:                for (i = 0; i < OOSIOP_NTGT; i++)
        !          1297:                        if (resid & (1 << i))
        !          1298:                                break;
        !          1299:                if (i == OOSIOP_NTGT) {
        !          1300:                        printf("%s: missing reselection target id\n",
        !          1301:                            sc->sc_dev.dv_xname);
        !          1302:                        break;
        !          1303:                }
        !          1304:                sc->sc_resid = i;
        !          1305:                sc->sc_nextdsp = Ent_wait_resel_identify;
        !          1306:
        !          1307:                if (cb) {
        !          1308:                        /* Current command was lost arbitration */
        !          1309:                        sc->sc_tgt[cb->id].nexus = NULL;
        !          1310:                        TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
        !          1311:                        sc->sc_curcb = NULL;
        !          1312:                }
        !          1313:
        !          1314:                break;
        !          1315:
        !          1316:        case A_int_res_id:
        !          1317:                cb = sc->sc_tgt[sc->sc_resid].nexus;
        !          1318:                resmsg = oosiop_read_1(sc, OOSIOP_SFBR);
        !          1319:                if (MSG_ISIDENTIFY(resmsg) && cb &&
        !          1320:                    (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) {
        !          1321:                        sc->sc_curcb = cb;
        !          1322:                        if (cb != sc->sc_lastcb) {
        !          1323:                                oosiop_setup_dma(sc);
        !          1324:                                oosiop_setup_syncxfer(sc);
        !          1325:                                sc->sc_lastcb = cb;
        !          1326:                        }
        !          1327:                        if (cb->curdp != cb->savedp) {
        !          1328:                                cb->curdp = cb->savedp;
        !          1329:                                oosiop_setup_sgdma(sc, cb);
        !          1330:                        }
        !          1331:                        sc->sc_nextdsp = Ent_ack_msgin;
        !          1332:                } else {
        !          1333:                        /* Reselection from invalid target */
        !          1334:                        oosiop_reset_bus(sc);
        !          1335:                }
        !          1336:                break;
        !          1337:
        !          1338:        case A_int_resfail:
        !          1339:                /* reselect failed */
        !          1340:                break;
        !          1341:
        !          1342:        case A_int_disc:
        !          1343:                /* disconnected */
        !          1344:                sc->sc_curcb = NULL;
        !          1345:                break;
        !          1346:
        !          1347:        case A_int_err:
        !          1348:                /* generic error */
        !          1349:                dsp = oosiop_read_4(sc, OOSIOP_DSP);
        !          1350:                printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname,
        !          1351:                    dsp - 8);
        !          1352:                sc->sc_curcb = NULL;
        !          1353:                break;
        !          1354:
        !          1355:        case DATAIN_TRAP:
        !          1356:                printf("%s: unexpected datain\n", sc->sc_dev.dv_xname);
        !          1357:                /* XXX: need to reset? */
        !          1358:                break;
        !          1359:
        !          1360:        case DATAOUT_TRAP:
        !          1361:                printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname);
        !          1362:                /* XXX: need to reset? */
        !          1363:                break;
        !          1364:
        !          1365:        default:
        !          1366:                printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname,
        !          1367:                    icode);
        !          1368:                break;
        !          1369:        }
        !          1370: }
        !          1371:
        !          1372: void
        !          1373: oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb)
        !          1374: {
        !          1375:        struct oosiop_xfer *xfer;
        !          1376:        int msgout;
        !          1377:
        !          1378:        xfer = cb->xfer;
        !          1379:        sc->sc_nextdsp = Ent_ack_msgin;
        !          1380:        msgout = 0;
        !          1381:
        !          1382:        OOSIOP_XFERMSG_SYNC(sc, cb,
        !          1383:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !          1384:
        !          1385:        switch (xfer->msgin[0]) {
        !          1386:        case MSG_EXTENDED:
        !          1387:                switch (xfer->msgin[2]) {
        !          1388:                case MSG_EXT_SDTR:
        !          1389:                        if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
        !          1390:                                /* Host initiated SDTR */
        !          1391:                                sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
        !          1392:                        } else {
        !          1393:                                /* Target initiated SDTR */
        !          1394:                                if (xfer->msgin[3] < sc->sc_minperiod)
        !          1395:                                        xfer->msgin[3] = sc->sc_minperiod;
        !          1396:                                if (xfer->msgin[4] > OOSIOP_MAX_OFFSET)
        !          1397:                                        xfer->msgin[4] = OOSIOP_MAX_OFFSET;
        !          1398:                                xfer->msgout[0] = MSG_EXTENDED;
        !          1399:                                xfer->msgout[1] = MSG_EXT_SDTR_LEN;
        !          1400:                                xfer->msgout[2] = MSG_EXT_SDTR;
        !          1401:                                xfer->msgout[3] = xfer->msgin[3];
        !          1402:                                xfer->msgout[4] = xfer->msgin[4];
        !          1403:                                cb->msgoutlen = 5;
        !          1404:                                msgout = 1;
        !          1405:                        }
        !          1406:                        oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3],
        !          1407:                            (int)xfer->msgin[4]);
        !          1408:                        oosiop_setup_syncxfer(sc);
        !          1409:                        break;
        !          1410:
        !          1411:                default:
        !          1412:                        /* Reject message */
        !          1413:                        xfer->msgout[0] = MSG_MESSAGE_REJECT;
        !          1414:                        cb->msgoutlen = 1;
        !          1415:                        msgout = 1;
        !          1416:                        break;
        !          1417:                }
        !          1418:                break;
        !          1419:
        !          1420:        case MSG_SAVEDATAPOINTER:
        !          1421:                cb->savedp = cb->curdp;
        !          1422:                break;
        !          1423:
        !          1424:        case MSG_RESTOREPOINTERS:
        !          1425:                if (cb->curdp != cb->savedp) {
        !          1426:                        cb->curdp = cb->savedp;
        !          1427:                        oosiop_setup_sgdma(sc, cb);
        !          1428:                }
        !          1429:                break;
        !          1430:
        !          1431:        case MSG_MESSAGE_REJECT:
        !          1432:                if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
        !          1433:                        /* SDTR rejected */
        !          1434:                        sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
        !          1435:                        oosiop_set_syncparam(sc, cb->id, 0, 0);
        !          1436:                        oosiop_setup_syncxfer(sc);
        !          1437:                }
        !          1438:                break;
        !          1439:
        !          1440:        default:
        !          1441:                /* Reject message */
        !          1442:                xfer->msgout[0] = MSG_MESSAGE_REJECT;
        !          1443:                cb->msgoutlen = 1;
        !          1444:                msgout = 1;
        !          1445:        }
        !          1446:
        !          1447:        OOSIOP_XFERMSG_SYNC(sc, cb,
        !          1448:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !          1449:
        !          1450:        if (msgout) {
        !          1451:                OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
        !          1452:                oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen,
        !          1453:                    cb->xferdma->dm_segs[0].ds_addr +
        !          1454:                    offsetof(struct oosiop_xfer, msgout[0]));
        !          1455:                OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
        !          1456:                sc->sc_nextdsp = Ent_sendmsg;
        !          1457:        }
        !          1458: }

CVSweb