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

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

1.1       nbrk        1: /*     $OpenBSD: twe.c,v 1.27 2006/12/29 13:04:37 pedro Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 2000-2002 Michael Shalayeff.  All rights reserved.
                      5:  *
                      6:  * The SCSI emulation layer is derived from gdt(4) driver,
                      7:  * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     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 OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
                     22:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     23:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     24:  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     26:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     27:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     28:  * THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
                     31: /* #define     TWE_DEBUG */
                     32:
                     33: #include <sys/param.h>
                     34: #include <sys/systm.h>
                     35: #include <sys/buf.h>
                     36: #include <sys/device.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/malloc.h>
                     39: #include <sys/proc.h>
                     40: #include <sys/kthread.h>
                     41:
                     42: #include <machine/bus.h>
                     43:
                     44: #include <scsi/scsi_all.h>
                     45: #include <scsi/scsi_disk.h>
                     46: #include <scsi/scsiconf.h>
                     47:
                     48: #include <dev/ic/twereg.h>
                     49: #include <dev/ic/twevar.h>
                     50:
                     51: #ifdef TWE_DEBUG
                     52: #define        TWE_DPRINTF(m,a)        if (twe_debug & (m)) printf a
                     53: #define        TWE_D_CMD       0x0001
                     54: #define        TWE_D_INTR      0x0002
                     55: #define        TWE_D_MISC      0x0004
                     56: #define        TWE_D_DMA       0x0008
                     57: #define        TWE_D_AEN       0x0010
                     58: int twe_debug = 0;
                     59: #else
                     60: #define        TWE_DPRINTF(m,a)        /* m, a */
                     61: #endif
                     62:
                     63: struct cfdriver twe_cd = {
                     64:        NULL, "twe", DV_DULL
                     65: };
                     66:
                     67: int    twe_scsi_cmd(struct scsi_xfer *);
                     68:
                     69: struct scsi_adapter twe_switch = {
                     70:        twe_scsi_cmd, tweminphys, 0, 0,
                     71: };
                     72:
                     73: struct scsi_device twe_dev = {
                     74:        NULL, NULL, NULL, NULL
                     75: };
                     76:
                     77: static __inline struct twe_ccb *twe_get_ccb(struct twe_softc *sc);
                     78: static __inline void twe_put_ccb(struct twe_ccb *ccb);
                     79: void twe_dispose(struct twe_softc *sc);
                     80: int  twe_cmd(struct twe_ccb *ccb, int flags, int wait);
                     81: int  twe_start(struct twe_ccb *ccb, int wait);
                     82: int  twe_complete(struct twe_ccb *ccb);
                     83: int  twe_done(struct twe_softc *sc, struct twe_ccb *ccb);
                     84: void twe_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size);
                     85: void twe_thread_create(void *v);
                     86: void twe_thread(void *v);
                     87:
                     88:
                     89: static __inline struct twe_ccb *
                     90: twe_get_ccb(sc)
                     91:        struct twe_softc *sc;
                     92: {
                     93:        struct twe_ccb *ccb;
                     94:
                     95:        ccb = TAILQ_LAST(&sc->sc_free_ccb, twe_queue_head);
                     96:        if (ccb)
                     97:                TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
                     98:        return ccb;
                     99: }
                    100:
                    101: static __inline void
                    102: twe_put_ccb(ccb)
                    103:        struct twe_ccb *ccb;
                    104: {
                    105:        struct twe_softc *sc = ccb->ccb_sc;
                    106:
                    107:        ccb->ccb_state = TWE_CCB_FREE;
                    108:        TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
                    109: }
                    110:
                    111: void
                    112: twe_dispose(sc)
                    113:        struct twe_softc *sc;
                    114: {
                    115:        register struct twe_ccb *ccb;
                    116:        if (sc->sc_cmdmap != NULL) {
                    117:                bus_dmamap_destroy(sc->dmat, sc->sc_cmdmap);
                    118:                /* traverse the ccbs and destroy the maps */
                    119:                for (ccb = &sc->sc_ccbs[TWE_MAXCMDS - 1]; ccb >= sc->sc_ccbs; ccb--)
                    120:                        if (ccb->ccb_dmamap)
                    121:                                bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap);
                    122:        }
                    123:        bus_dmamem_unmap(sc->dmat, sc->sc_cmds,
                    124:            sizeof(struct twe_cmd) * TWE_MAXCMDS);
                    125:        bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
                    126: }
                    127:
                    128: int
                    129: twe_attach(sc)
                    130:        struct twe_softc *sc;
                    131: {
                    132:        struct scsibus_attach_args saa;
                    133:        /* this includes a buffer for drive config req, and a capacity req */
                    134:        u_int8_t        param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
                    135:        struct twe_param *pb = (void *)
                    136:            (((u_long)param_buf + TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
                    137:        struct twe_param *cap = (void *)((u_int8_t *)pb + TWE_SECTOR_SIZE);
                    138:        struct twe_ccb  *ccb;
                    139:        struct twe_cmd  *cmd;
                    140:        u_int32_t       status;
                    141:        int             error, i, retry, nunits, nseg;
                    142:        const char      *errstr;
                    143:        twe_lock_t      lock;
                    144:        paddr_t         pa;
                    145:
                    146:        error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS,
                    147:            PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT);
                    148:        if (error) {
                    149:                printf(": cannot allocate commands (%d)\n", error);
                    150:                return (1);
                    151:        }
                    152:
                    153:        error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg,
                    154:            sizeof(struct twe_cmd) * TWE_MAXCMDS,
                    155:            (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT);
                    156:        if (error) {
                    157:                printf(": cannot map commands (%d)\n", error);
                    158:                bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
                    159:                return (1);
                    160:        }
                    161:
                    162:        error = bus_dmamap_create(sc->dmat,
                    163:            sizeof(struct twe_cmd) * TWE_MAXCMDS, TWE_MAXCMDS,
                    164:            sizeof(struct twe_cmd) * TWE_MAXCMDS, 0,
                    165:            BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_cmdmap);
                    166:        if (error) {
                    167:                printf(": cannot create ccb cmd dmamap (%d)\n", error);
                    168:                twe_dispose(sc);
                    169:                return (1);
                    170:        }
                    171:        error = bus_dmamap_load(sc->dmat, sc->sc_cmdmap, sc->sc_cmds,
                    172:            sizeof(struct twe_cmd) * TWE_MAXCMDS, NULL, BUS_DMA_NOWAIT);
                    173:        if (error) {
                    174:                printf(": cannot load command dma map (%d)\n", error);
                    175:                twe_dispose(sc);
                    176:                return (1);
                    177:        }
                    178:
                    179:        TAILQ_INIT(&sc->sc_ccb2q);
                    180:        TAILQ_INIT(&sc->sc_ccbq);
                    181:        TAILQ_INIT(&sc->sc_free_ccb);
                    182:        TAILQ_INIT(&sc->sc_done_ccb);
                    183:
                    184:        lockinit(&sc->sc_lock, PWAIT, "twelk", 0, 0);
                    185:
                    186:        pa = sc->sc_cmdmap->dm_segs[0].ds_addr +
                    187:            sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);
                    188:        for (cmd = (struct twe_cmd *)sc->sc_cmds + TWE_MAXCMDS - 1;
                    189:             cmd >= (struct twe_cmd *)sc->sc_cmds; cmd--, pa -= sizeof(*cmd)) {
                    190:
                    191:                cmd->cmd_index = cmd - (struct twe_cmd *)sc->sc_cmds;
                    192:                ccb = &sc->sc_ccbs[cmd->cmd_index];
                    193:                error = bus_dmamap_create(sc->dmat,
                    194:                    TWE_MAXFER, TWE_MAXOFFSETS, TWE_MAXFER, 0,
                    195:                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
                    196:                if (error) {
                    197:                        printf(": cannot create ccb dmamap (%d)\n", error);
                    198:                        twe_dispose(sc);
                    199:                        return (1);
                    200:                }
                    201:                ccb->ccb_sc = sc;
                    202:                ccb->ccb_cmd = cmd;
                    203:                ccb->ccb_cmdpa = pa;
                    204:                ccb->ccb_state = TWE_CCB_FREE;
                    205:                TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
                    206:        }
                    207:
                    208:        for (errstr = NULL, retry = 3; retry--; ) {
                    209:                int             veseen_srst;
                    210:                u_int16_t       aen;
                    211:
                    212:                if (errstr)
                    213:                        TWE_DPRINTF(TWE_D_MISC, ("%s ", errstr));
                    214:
                    215:                for (i = 350000; i--; DELAY(100)) {
                    216:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    217:                        if (status & TWE_STAT_CPURDY)
                    218:                                break;
                    219:                }
                    220:
                    221:                if (!(status & TWE_STAT_CPURDY)) {
                    222:                        errstr = ": card CPU is not ready\n";
                    223:                        continue;
                    224:                }
                    225:
                    226:                /* soft reset, disable ints */
                    227:                bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    228:                    TWE_CTRL_SRST |
                    229:                    TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR |
                    230:                    TWE_CTRL_MCMDI | TWE_CTRL_MRDYI |
                    231:                    TWE_CTRL_MINT);
                    232:
                    233:                for (i = 350000; i--; DELAY(100)) {
                    234:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    235:                        if (status & TWE_STAT_ATTNI)
                    236:                                break;
                    237:                }
                    238:
                    239:                if (!(status & TWE_STAT_ATTNI)) {
                    240:                        errstr = ": cannot get card's attention\n";
                    241:                        continue;
                    242:                }
                    243:
                    244:                /* drain aen queue */
                    245:                for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY; ) {
                    246:
                    247:                        if ((ccb = twe_get_ccb(sc)) == NULL) {
                    248:                                errstr = ": out of ccbs\n";
                    249:                                continue;
                    250:                        }
                    251:
                    252:                        ccb->ccb_xs = NULL;
                    253:                        ccb->ccb_data = pb;
                    254:                        ccb->ccb_length = TWE_SECTOR_SIZE;
                    255:                        ccb->ccb_state = TWE_CCB_READY;
                    256:                        cmd = ccb->ccb_cmd;
                    257:                        cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
                    258:                        cmd->cmd_op = TWE_CMD_GPARAM;
                    259:                        cmd->cmd_param.count = 1;
                    260:
                    261:                        pb->table_id = TWE_PARAM_AEN;
                    262:                        pb->param_id = 2;
                    263:                        pb->param_size = 2;
                    264:
                    265:                        if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
                    266:                                errstr = ": error draining attention queue\n";
                    267:                                break;
                    268:                        }
                    269:                        aen = *(u_int16_t *)pb->data;
                    270:                        TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
                    271:                        if (aen == TWE_AEN_SRST)
                    272:                                veseen_srst++;
                    273:                }
                    274:
                    275:                if (!veseen_srst) {
                    276:                        errstr = ": we don't get it\n";
                    277:                        continue;
                    278:                }
                    279:
                    280:                if (status & TWE_STAT_CPUERR) {
                    281:                        errstr = ": card CPU error detected\n";
                    282:                        continue;
                    283:                }
                    284:
                    285:                if (status & TWE_STAT_PCIPAR) {
                    286:                        errstr = ": PCI parity error detected\n";
                    287:                        continue;
                    288:                }
                    289:
                    290:                if (status & TWE_STAT_QUEUEE ) {
                    291:                        errstr = ": queuing error detected\n";
                    292:                        continue;
                    293:                }
                    294:
                    295:                if (status & TWE_STAT_PCIABR) {
                    296:                        errstr = ": PCI abort\n";
                    297:                        continue;
                    298:                }
                    299:
                    300:                while (!(status & TWE_STAT_RQE)) {
                    301:                        bus_space_read_4(sc->iot, sc->ioh, TWE_READYQUEUE);
                    302:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    303:                }
                    304:
                    305:                break;
                    306:        }
                    307:
                    308:        if (retry < 0) {
                    309:                printf(errstr);
                    310:                twe_dispose(sc);
                    311:                return 1;
                    312:        }
                    313:
                    314:        if ((ccb = twe_get_ccb(sc)) == NULL) {
                    315:                printf(": out of ccbs\n");
                    316:                twe_dispose(sc);
                    317:                return 1;
                    318:        }
                    319:
                    320:        ccb->ccb_xs = NULL;
                    321:        ccb->ccb_data = pb;
                    322:        ccb->ccb_length = TWE_SECTOR_SIZE;
                    323:        ccb->ccb_state = TWE_CCB_READY;
                    324:        cmd = ccb->ccb_cmd;
                    325:        cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
                    326:        cmd->cmd_op = TWE_CMD_GPARAM;
                    327:        cmd->cmd_param.count = 1;
                    328:
                    329:        pb->table_id = TWE_PARAM_UC;
                    330:        pb->param_id = TWE_PARAM_UC;
                    331:        pb->param_size = TWE_MAX_UNITS;
                    332:        if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
                    333:                printf(": failed to fetch unit parameters\n");
                    334:                twe_dispose(sc);
                    335:                return 1;
                    336:        }
                    337:
                    338:        /* we are assuming last read status was good */
                    339:        printf(": Escalade V%d.%d\n", TWE_MAJV(status), TWE_MINV(status));
                    340:
                    341:        for (nunits = i = 0; i < TWE_MAX_UNITS; i++) {
                    342:                if (pb->data[i] == 0)
                    343:                        continue;
                    344:
                    345:                if ((ccb = twe_get_ccb(sc)) == NULL) {
                    346:                        printf(": out of ccbs\n");
                    347:                        twe_dispose(sc);
                    348:                        return 1;
                    349:                }
                    350:
                    351:                ccb->ccb_xs = NULL;
                    352:                ccb->ccb_data = cap;
                    353:                ccb->ccb_length = TWE_SECTOR_SIZE;
                    354:                ccb->ccb_state = TWE_CCB_READY;
                    355:                cmd = ccb->ccb_cmd;
                    356:                cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
                    357:                cmd->cmd_op = TWE_CMD_GPARAM;
                    358:                cmd->cmd_param.count = 1;
                    359:
                    360:                cap->table_id = TWE_PARAM_UI + i;
                    361:                cap->param_id = 4;
                    362:                cap->param_size = 4;    /* 4 bytes */
                    363:                lock = TWE_LOCK(sc);
                    364:                if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
                    365:                        TWE_UNLOCK(sc, lock);
                    366:                        printf("%s: error fetching capacity for unit %d\n",
                    367:                            sc->sc_dev.dv_xname, i);
                    368:                        continue;
                    369:                }
                    370:                TWE_UNLOCK(sc, lock);
                    371:
                    372:                nunits++;
                    373:                sc->sc_hdr[i].hd_present = 1;
                    374:                sc->sc_hdr[i].hd_devtype = 0;
                    375:                sc->sc_hdr[i].hd_size = letoh32(*(u_int32_t *)cap->data);
                    376:                TWE_DPRINTF(TWE_D_MISC, ("twed%d: size=%d\n",
                    377:                    i, sc->sc_hdr[i].hd_size));
                    378:        }
                    379:
                    380:        if (!nunits)
                    381:                nunits++;
                    382:
                    383:        /* TODO: fetch & print cache params? */
                    384:
                    385:        sc->sc_link.adapter_softc = sc;
                    386:        sc->sc_link.adapter = &twe_switch;
                    387:        sc->sc_link.adapter_target = TWE_MAX_UNITS;
                    388:        sc->sc_link.device = &twe_dev;
                    389:        sc->sc_link.openings = TWE_MAXCMDS / nunits;
                    390:        sc->sc_link.adapter_buswidth = TWE_MAX_UNITS;
                    391:
                    392:        bzero(&saa, sizeof(saa));
                    393:        saa.saa_sc_link = &sc->sc_link;
                    394:
                    395:        config_found(&sc->sc_dev, &saa, scsiprint);
                    396:
                    397:        kthread_create_deferred(twe_thread_create, sc);
                    398:
                    399:        return (0);
                    400: }
                    401:
                    402: void
                    403: twe_thread_create(void *v)
                    404: {
                    405:        struct twe_softc *sc = v;
                    406:
                    407:        if (kthread_create(twe_thread, sc, &sc->sc_thread,
                    408:            "%s", sc->sc_dev.dv_xname)) {
                    409:                /* TODO disable twe */
                    410:                printf("%s: failed to create kernel thread, disabled\n",
                    411:                    sc->sc_dev.dv_xname);
                    412:                return;
                    413:        }
                    414:
                    415:        TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
                    416:            bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
                    417:        /*
                    418:         * ack all before enable, cannot be done in one
                    419:         * operation as it seems clear is not processed
                    420:         * if enable is specified.
                    421:         */
                    422:        bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    423:            TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR);
                    424:        TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
                    425:            bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
                    426:        /* enable interrupts */
                    427:        bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    428:            TWE_CTRL_EINT | TWE_CTRL_ERDYI |
                    429:            /*TWE_CTRL_HOSTI |*/ TWE_CTRL_MCMDI);
                    430: }
                    431:
                    432: void
                    433: twe_thread(v)
                    434:        void *v;
                    435: {
                    436:        struct twe_softc *sc = v;
                    437:        struct twe_ccb *ccb;
                    438:        twe_lock_t lock;
                    439:        u_int32_t status;
                    440:        int err;
                    441:
                    442:        splbio();
                    443:        for (;;) {
                    444:                lock = TWE_LOCK(sc);
                    445:
                    446:                while (!TAILQ_EMPTY(&sc->sc_done_ccb)) {
                    447:                        ccb = TAILQ_FIRST(&sc->sc_done_ccb);
                    448:                        TAILQ_REMOVE(&sc->sc_done_ccb, ccb, ccb_link);
                    449:                        if ((err = twe_done(sc, ccb)))
                    450:                                printf("%s: done failed (%d)\n",
                    451:                                    sc->sc_dev.dv_xname, err);
                    452:                }
                    453:
                    454:                status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    455:                TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
                    456:                    status & TWE_STAT_FLAGS, TWE_STAT_BITS));
                    457:                while (!(status & TWE_STAT_CQF) &&
                    458:                    !TAILQ_EMPTY(&sc->sc_ccb2q)) {
                    459:
                    460:                        ccb = TAILQ_LAST(&sc->sc_ccb2q, twe_queue_head);
                    461:                        TAILQ_REMOVE(&sc->sc_ccb2q, ccb, ccb_link);
                    462:
                    463:                        ccb->ccb_state = TWE_CCB_QUEUED;
                    464:                        TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
                    465:                        bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
                    466:                            ccb->ccb_cmdpa);
                    467:
                    468:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    469:                        TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
                    470:                            status & TWE_STAT_FLAGS, TWE_STAT_BITS));
                    471:                }
                    472:
                    473:                if (!TAILQ_EMPTY(&sc->sc_ccb2q))
                    474:                        bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    475:                            TWE_CTRL_ECMDI);
                    476:
                    477:                TWE_UNLOCK(sc, lock);
                    478:                sc->sc_thread_on = 1;
                    479:                tsleep(sc, PWAIT, "twespank", 0);
                    480:        }
                    481: }
                    482:
                    483: int
                    484: twe_cmd(ccb, flags, wait)
                    485:        struct twe_ccb *ccb;
                    486:        int flags, wait;
                    487: {
                    488:        struct twe_softc *sc = ccb->ccb_sc;
                    489:        bus_dmamap_t dmap;
                    490:        struct twe_cmd *cmd;
                    491:        struct twe_segs *sgp;
                    492:        int error, i;
                    493:
                    494:        if (ccb->ccb_data && ((u_long)ccb->ccb_data & (TWE_ALIGN - 1))) {
                    495:                TWE_DPRINTF(TWE_D_DMA, ("data=%p is unaligned ",ccb->ccb_data));
                    496:                ccb->ccb_realdata = ccb->ccb_data;
                    497:
                    498:                error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, PAGE_SIZE,
                    499:                    0, ccb->ccb_2bseg, TWE_MAXOFFSETS, &ccb->ccb_2nseg,
                    500:                    BUS_DMA_NOWAIT);
                    501:                if (error) {
                    502:                        TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", error));
                    503:                        twe_put_ccb(ccb);
                    504:                        return (ENOMEM);
                    505:                }
                    506:
                    507:                error = bus_dmamem_map(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg,
                    508:                    ccb->ccb_length, (caddr_t *)&ccb->ccb_data, BUS_DMA_NOWAIT);
                    509:                if (error) {
                    510:                        TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error));
                    511:                        bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
                    512:                        twe_put_ccb(ccb);
                    513:                        return (ENOMEM);
                    514:                }
                    515:                bcopy(ccb->ccb_realdata, ccb->ccb_data, ccb->ccb_length);
                    516:        } else
                    517:                ccb->ccb_realdata = NULL;
                    518:
                    519:        dmap = ccb->ccb_dmamap;
                    520:        cmd = ccb->ccb_cmd;
                    521:        cmd->cmd_status = 0;
                    522:
                    523:        if (ccb->ccb_data) {
                    524:                error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,
                    525:                    ccb->ccb_length, NULL, flags);
                    526:                if (error) {
                    527:                        if (error == EFBIG)
                    528:                                printf("more than %d dma segs\n", TWE_MAXOFFSETS);
                    529:                        else
                    530:                                printf("error %d loading dma map\n", error);
                    531:
                    532:                        if (ccb->ccb_realdata) {
                    533:                                bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
                    534:                                    ccb->ccb_length);
                    535:                                bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
                    536:                                    ccb->ccb_2nseg);
                    537:                        }
                    538:                        twe_put_ccb(ccb);
                    539:                        return error;
                    540:                }
                    541:                /* load addresses into command */
                    542:                switch (cmd->cmd_op) {
                    543:                case TWE_CMD_GPARAM:
                    544:                case TWE_CMD_SPARAM:
                    545:                        sgp = cmd->cmd_param.segs;
                    546:                        break;
                    547:                case TWE_CMD_READ:
                    548:                case TWE_CMD_WRITE:
                    549:                        sgp = cmd->cmd_io.segs;
                    550:                        break;
                    551:                default:
                    552:                        /* no data transfer */
                    553:                        TWE_DPRINTF(TWE_D_DMA, ("twe_cmd: unknown sgp op=%x\n",
                    554:                            cmd->cmd_op));
                    555:                        sgp = NULL;
                    556:                        break;
                    557:                }
                    558:                TWE_DPRINTF(TWE_D_DMA, ("data=%p<", ccb->ccb_data));
                    559:                if (sgp) {
                    560:                        /*
                    561:                         * we know that size is in the upper byte,
                    562:                         * and we do not worry about overflow
                    563:                         */
                    564:                        cmd->cmd_op += (2 * dmap->dm_nsegs) << 8;
                    565:                        bzero (sgp, TWE_MAXOFFSETS * sizeof(*sgp));
                    566:                        for (i = 0; i < dmap->dm_nsegs; i++, sgp++) {
                    567:                                sgp->twes_addr = htole32(dmap->dm_segs[i].ds_addr);
                    568:                                sgp->twes_len  = htole32(dmap->dm_segs[i].ds_len);
                    569:                                TWE_DPRINTF(TWE_D_DMA, ("%x[%x] ",
                    570:                                    dmap->dm_segs[i].ds_addr,
                    571:                                    dmap->dm_segs[i].ds_len));
                    572:                        }
                    573:                }
                    574:                TWE_DPRINTF(TWE_D_DMA, ("> "));
                    575:                bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,
                    576:                    BUS_DMASYNC_PREWRITE);
                    577:        }
                    578:        bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sc->sc_cmdmap->dm_mapsize,
                    579:            BUS_DMASYNC_PREWRITE);
                    580:
                    581:        if ((error = twe_start(ccb, wait))) {
                    582:                bus_dmamap_unload(sc->dmat, dmap);
                    583:                if (ccb->ccb_realdata) {
                    584:                        bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
                    585:                            ccb->ccb_length);
                    586:                        bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
                    587:                            ccb->ccb_2nseg);
                    588:                }
                    589:                twe_put_ccb(ccb);
                    590:                return (error);
                    591:        }
                    592:
                    593:        return wait? twe_complete(ccb) : 0;
                    594: }
                    595:
                    596: int
                    597: twe_start(ccb, wait)
                    598:        struct twe_ccb *ccb;
                    599:        int wait;
                    600: {
                    601:        struct twe_softc*sc = ccb->ccb_sc;
                    602:        struct twe_cmd  *cmd = ccb->ccb_cmd;
                    603:        u_int32_t       status;
                    604:        int i;
                    605:
                    606:        cmd->cmd_op = htole16(cmd->cmd_op);
                    607:
                    608:        if (!wait) {
                    609:
                    610:                TWE_DPRINTF(TWE_D_CMD, ("prequeue(%d) ", cmd->cmd_index));
                    611:                ccb->ccb_state = TWE_CCB_PREQUEUED;
                    612:                TAILQ_INSERT_TAIL(&sc->sc_ccb2q, ccb, ccb_link);
                    613:                wakeup(sc);
                    614:                return 0;
                    615:        }
                    616:
                    617:        for (i = 1000; i--; DELAY(10)) {
                    618:
                    619:                status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    620:                if (!(status & TWE_STAT_CQF))
                    621:                        break;
                    622:                TWE_DPRINTF(TWE_D_CMD,  ("twe_start stat=%b ",
                    623:                    status & TWE_STAT_FLAGS, TWE_STAT_BITS));
                    624:        }
                    625:
                    626:        if (!(status & TWE_STAT_CQF)) {
                    627:                bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
                    628:                    ccb->ccb_cmdpa);
                    629:
                    630:                TWE_DPRINTF(TWE_D_CMD, ("queue(%d) ", cmd->cmd_index));
                    631:                ccb->ccb_state = TWE_CCB_QUEUED;
                    632:                TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
                    633:                return 0;
                    634:
                    635:        } else {
                    636:
                    637:                printf("%s: twe_start(%d) timed out\n",
                    638:                    sc->sc_dev.dv_xname, cmd->cmd_index);
                    639:
                    640:                return 1;
                    641:        }
                    642: }
                    643:
                    644: int
                    645: twe_complete(ccb)
                    646:        struct twe_ccb *ccb;
                    647: {
                    648:        struct twe_softc *sc = ccb->ccb_sc;
                    649:        struct scsi_xfer *xs = ccb->ccb_xs;
                    650:        int i;
                    651:
                    652:        for (i = 100 * (xs? xs->timeout : 35000); i--; DELAY(10)) {
                    653:                u_int32_t status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    654:
                    655:                /* TWE_DPRINTF(TWE_D_CMD,  ("twe_intr stat=%b ",
                    656:                    status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
                    657:
                    658:                while (!(status & TWE_STAT_RQE)) {
                    659:                        struct twe_ccb *ccb1;
                    660:                        u_int32_t ready;
                    661:
                    662:                        ready = bus_space_read_4(sc->iot, sc->ioh,
                    663:                            TWE_READYQUEUE);
                    664:
                    665:                        TWE_DPRINTF(TWE_D_CMD, ("ready=%x ", ready));
                    666:
                    667:                        ccb1 = &sc->sc_ccbs[TWE_READYID(ready)];
                    668:                        TAILQ_REMOVE(&sc->sc_ccbq, ccb1, ccb_link);
                    669:                        ccb1->ccb_state = TWE_CCB_DONE;
                    670:                        if (!twe_done(sc, ccb1) && ccb1 == ccb) {
                    671:                                TWE_DPRINTF(TWE_D_CMD, ("complete\n"));
                    672:                                return 0;
                    673:                        }
                    674:
                    675:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    676:                        /* TWE_DPRINTF(TWE_D_CMD,  ("twe_intr stat=%b ",
                    677:                            status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
                    678:                }
                    679:        }
                    680:
                    681:        return 1;
                    682: }
                    683:
                    684: int
                    685: twe_done(sc, ccb)
                    686:        struct twe_softc *sc;
                    687:        struct twe_ccb *ccb;
                    688: {
                    689:        struct twe_cmd *cmd = ccb->ccb_cmd;
                    690:        struct scsi_xfer *xs = ccb->ccb_xs;
                    691:        bus_dmamap_t    dmap;
                    692:        twe_lock_t      lock;
                    693:
                    694:        TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", cmd->cmd_index));
                    695:
                    696:        if (ccb->ccb_state != TWE_CCB_DONE) {
                    697:                printf("%s: undone ccb %d ready\n",
                    698:                     sc->sc_dev.dv_xname, cmd->cmd_index);
                    699:                return 1;
                    700:        }
                    701:
                    702:        dmap = ccb->ccb_dmamap;
                    703:        if (xs) {
                    704:                if (xs->cmd->opcode != PREVENT_ALLOW &&
                    705:                    xs->cmd->opcode != SYNCHRONIZE_CACHE) {
                    706:                        bus_dmamap_sync(sc->dmat, dmap, 0,
                    707:                            dmap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
                    708:                            BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                    709:                        bus_dmamap_unload(sc->dmat, dmap);
                    710:                }
                    711:        } else {
                    712:                switch (letoh16(cmd->cmd_op)) {
                    713:                case TWE_CMD_GPARAM:
                    714:                case TWE_CMD_READ:
                    715:                        bus_dmamap_sync(sc->dmat, dmap, 0,
                    716:                            dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
                    717:                        bus_dmamap_unload(sc->dmat, dmap);
                    718:                        break;
                    719:                case TWE_CMD_SPARAM:
                    720:                case TWE_CMD_WRITE:
                    721:                        bus_dmamap_sync(sc->dmat, dmap, 0,
                    722:                            dmap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                    723:                        bus_dmamap_unload(sc->dmat, dmap);
                    724:                        break;
                    725:                default:
                    726:                        /* no data */
                    727:                        break;
                    728:                }
                    729:        }
                    730:
                    731:        if (ccb->ccb_realdata) {
                    732:                bcopy(ccb->ccb_data, ccb->ccb_realdata, ccb->ccb_length);
                    733:                bus_dmamem_unmap(sc->dmat, ccb->ccb_data, ccb->ccb_length);
                    734:                bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
                    735:        }
                    736:
                    737:        lock = TWE_LOCK(sc);
                    738:        twe_put_ccb(ccb);
                    739:
                    740:        if (xs) {
                    741:                xs->resid = 0;
                    742:                xs->flags |= ITSDONE;
                    743:                scsi_done(xs);
                    744:        }
                    745:        TWE_UNLOCK(sc, lock);
                    746:
                    747:        return 0;
                    748: }
                    749:
                    750: void
                    751: tweminphys(bp)
                    752:        struct buf *bp;
                    753: {
                    754:        if (bp->b_bcount > TWE_MAXFER)
                    755:                bp->b_bcount = TWE_MAXFER;
                    756:        minphys(bp);
                    757: }
                    758:
                    759: void
                    760: twe_copy_internal_data(xs, v, size)
                    761:        struct scsi_xfer *xs;
                    762:        void *v;
                    763:        size_t size;
                    764: {
                    765:        size_t copy_cnt;
                    766:
                    767:        TWE_DPRINTF(TWE_D_MISC, ("twe_copy_internal_data "));
                    768:
                    769:        if (!xs->datalen)
                    770:                printf("uio move is not yet supported\n");
                    771:        else {
                    772:                copy_cnt = MIN(size, xs->datalen);
                    773:                bcopy(v, xs->data, copy_cnt);
                    774:        }
                    775: }
                    776:
                    777: int
                    778: twe_scsi_cmd(xs)
                    779:        struct scsi_xfer *xs;
                    780: {
                    781:        struct scsi_link *link = xs->sc_link;
                    782:        struct twe_softc *sc = link->adapter_softc;
                    783:        struct twe_ccb *ccb;
                    784:        struct twe_cmd *cmd;
                    785:        struct scsi_inquiry_data inq;
                    786:        struct scsi_sense_data sd;
                    787:        struct scsi_read_cap_data rcd;
                    788:        u_int8_t target = link->target;
                    789:        u_int32_t blockno, blockcnt;
                    790:        struct scsi_rw *rw;
                    791:        struct scsi_rw_big *rwb;
                    792:        int error, op, flags, wait;
                    793:        twe_lock_t lock;
                    794:
                    795:
                    796:        if (target >= TWE_MAX_UNITS || !sc->sc_hdr[target].hd_present ||
                    797:            link->lun != 0) {
                    798:                xs->error = XS_DRIVER_STUFFUP;
                    799:                return (COMPLETE);
                    800:        }
                    801:
                    802:        TWE_DPRINTF(TWE_D_CMD, ("twe_scsi_cmd "));
                    803:
                    804:        xs->error = XS_NOERROR;
                    805:
                    806:        switch (xs->cmd->opcode) {
                    807:        case TEST_UNIT_READY:
                    808:        case START_STOP:
                    809: #if 0
                    810:        case VERIFY:
                    811: #endif
                    812:                TWE_DPRINTF(TWE_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
                    813:                    target));
                    814:                break;
                    815:
                    816:        case REQUEST_SENSE:
                    817:                TWE_DPRINTF(TWE_D_CMD, ("REQUEST SENSE tgt %d ", target));
                    818:                bzero(&sd, sizeof sd);
                    819:                sd.error_code = 0x70;
                    820:                sd.segment = 0;
                    821:                sd.flags = SKEY_NO_SENSE;
                    822:                *(u_int32_t*)sd.info = htole32(0);
                    823:                sd.extra_len = 0;
                    824:                twe_copy_internal_data(xs, &sd, sizeof sd);
                    825:                break;
                    826:
                    827:        case INQUIRY:
                    828:                TWE_DPRINTF(TWE_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
                    829:                    sc->sc_hdr[target].hd_devtype));
                    830:                bzero(&inq, sizeof inq);
                    831:                inq.device =
                    832:                    (sc->sc_hdr[target].hd_devtype & 4) ? T_CDROM : T_DIRECT;
                    833:                inq.dev_qual2 =
                    834:                    (sc->sc_hdr[target].hd_devtype & 1) ? SID_REMOVABLE : 0;
                    835:                inq.version = 2;
                    836:                inq.response_format = 2;
                    837:                inq.additional_length = 32;
                    838:                strlcpy(inq.vendor, "3WARE  ", sizeof inq.vendor);
                    839:                snprintf(inq.product, sizeof inq.product, "Host drive  #%02d",
                    840:                    target);
                    841:                strlcpy(inq.revision, "   ", sizeof inq.revision);
                    842:                twe_copy_internal_data(xs, &inq, sizeof inq);
                    843:                break;
                    844:
                    845:        case READ_CAPACITY:
                    846:                TWE_DPRINTF(TWE_D_CMD, ("READ CAPACITY tgt %d ", target));
                    847:                bzero(&rcd, sizeof rcd);
                    848:                _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
                    849:                _lto4b(TWE_SECTOR_SIZE, rcd.length);
                    850:                twe_copy_internal_data(xs, &rcd, sizeof rcd);
                    851:                break;
                    852:
                    853:        case PREVENT_ALLOW:
                    854:                TWE_DPRINTF(TWE_D_CMD, ("PREVENT/ALLOW "));
                    855:                return (COMPLETE);
                    856:
                    857:        case READ_COMMAND:
                    858:        case READ_BIG:
                    859:        case WRITE_COMMAND:
                    860:        case WRITE_BIG:
                    861:        case SYNCHRONIZE_CACHE:
                    862:                lock = TWE_LOCK(sc);
                    863:
                    864:                flags = 0;
                    865:                if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
                    866:                        /* A read or write operation. */
                    867:                        if (xs->cmdlen == 6) {
                    868:                                rw = (struct scsi_rw *)xs->cmd;
                    869:                                blockno = _3btol(rw->addr) &
                    870:                                    (SRW_TOPADDR << 16 | 0xffff);
                    871:                                blockcnt = rw->length ? rw->length : 0x100;
                    872:                        } else {
                    873:                                rwb = (struct scsi_rw_big *)xs->cmd;
                    874:                                blockno = _4btol(rwb->addr);
                    875:                                blockcnt = _2btol(rwb->length);
                    876:                                /* reflect DPO & FUA flags */
                    877:                                if (xs->cmd->opcode == WRITE_BIG &&
                    878:                                    rwb->byte2 & 0x18)
                    879:                                        flags = TWE_FLAGS_CACHEDISABLE;
                    880:                        }
                    881:                        if (blockno >= sc->sc_hdr[target].hd_size ||
                    882:                            blockno + blockcnt > sc->sc_hdr[target].hd_size) {
                    883:                                printf("%s: out of bounds %u-%u >= %u\n",
                    884:                                    sc->sc_dev.dv_xname, blockno, blockcnt,
                    885:                                    sc->sc_hdr[target].hd_size);
                    886:                                xs->error = XS_DRIVER_STUFFUP;
                    887:                                scsi_done(xs);
                    888:                                TWE_UNLOCK(sc, lock);
                    889:                                return (COMPLETE);
                    890:                        }
                    891:                }
                    892:
                    893:                switch (xs->cmd->opcode) {
                    894:                case READ_COMMAND:      op = TWE_CMD_READ;      break;
                    895:                case READ_BIG:          op = TWE_CMD_READ;      break;
                    896:                case WRITE_COMMAND:     op = TWE_CMD_WRITE;     break;
                    897:                case WRITE_BIG:         op = TWE_CMD_WRITE;     break;
                    898:                default:                op = TWE_CMD_NOP;       break;
                    899:                }
                    900:
                    901:                if ((ccb = twe_get_ccb(sc)) == NULL) {
                    902:                        xs->error = XS_DRIVER_STUFFUP;
                    903:                        scsi_done(xs);
                    904:                        TWE_UNLOCK(sc, lock);
                    905:                        return (COMPLETE);
                    906:                }
                    907:
                    908:                ccb->ccb_xs = xs;
                    909:                ccb->ccb_data = xs->data;
                    910:                ccb->ccb_length = xs->datalen;
                    911:                ccb->ccb_state = TWE_CCB_READY;
                    912:                cmd = ccb->ccb_cmd;
                    913:                cmd->cmd_unit_host = TWE_UNITHOST(target, 0); /* XXX why 0? */
                    914:                cmd->cmd_op = op;
                    915:                cmd->cmd_flags = flags;
                    916:                cmd->cmd_io.count = htole16(blockcnt);
                    917:                cmd->cmd_io.lba = htole32(blockno);
                    918:                wait = xs->flags & SCSI_POLL;
                    919:                if (!sc->sc_thread_on)
                    920:                        wait |= SCSI_POLL;
                    921:
                    922:                if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)?
                    923:                    BUS_DMA_NOWAIT : BUS_DMA_WAITOK), wait))) {
                    924:
                    925:                        TWE_UNLOCK(sc, lock);
                    926:                        TWE_DPRINTF(TWE_D_CMD, ("failed %p ", xs));
                    927:                        if (xs->flags & SCSI_POLL) {
                    928:                                return (TRY_AGAIN_LATER);
                    929:                        } else {
                    930:                                xs->error = XS_DRIVER_STUFFUP;
                    931:                                scsi_done(xs);
                    932:                                return (COMPLETE);
                    933:                        }
                    934:                }
                    935:
                    936:                TWE_UNLOCK(sc, lock);
                    937:
                    938:                if (wait & SCSI_POLL)
                    939:                        return (COMPLETE);
                    940:                else
                    941:                        return (SUCCESSFULLY_QUEUED);
                    942:
                    943:        default:
                    944:                TWE_DPRINTF(TWE_D_CMD, ("unsupported scsi command %#x tgt %d ",
                    945:                    xs->cmd->opcode, target));
                    946:                xs->error = XS_DRIVER_STUFFUP;
                    947:        }
                    948:
                    949:        return (COMPLETE);
                    950: }
                    951:
                    952: int
                    953: twe_intr(v)
                    954:        void *v;
                    955: {
                    956:        struct twe_softc *sc = v;
                    957:        struct twe_ccb  *ccb;
                    958:        struct twe_cmd  *cmd;
                    959:        u_int32_t       status;
                    960:        twe_lock_t      lock;
                    961:        int             rv = 0;
                    962:
                    963:        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    964:        TWE_DPRINTF(TWE_D_INTR,  ("twe_intr stat=%b ",
                    965:            status & TWE_STAT_FLAGS, TWE_STAT_BITS));
                    966: #if 0
                    967:        if (status & TWE_STAT_HOSTI) {
                    968:
                    969:                bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                    970:                    TWE_CTRL_CHOSTI);
                    971:        }
                    972: #endif
                    973:
                    974:        if (status & TWE_STAT_RDYI) {
                    975:
                    976:                while (!(status & TWE_STAT_RQE)) {
                    977:
                    978:                        u_int32_t ready;
                    979:
                    980:                        /*
                    981:                         * it seems that reading ready queue
                    982:                         * we get all the status bits in each ready word.
                    983:                         * i wonder if it's legal to use those for
                    984:                         * status and avoid extra read below
                    985:                         */
                    986:                        ready = bus_space_read_4(sc->iot, sc->ioh,
                    987:                            TWE_READYQUEUE);
                    988:
                    989:                        ccb = &sc->sc_ccbs[TWE_READYID(ready)];
                    990:                        TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
                    991:                        ccb->ccb_state = TWE_CCB_DONE;
                    992:                        TAILQ_INSERT_TAIL(&sc->sc_done_ccb, ccb, ccb_link);
                    993:                        rv++;
                    994:
                    995:                        status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
                    996:                        TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
                    997:                            status & TWE_STAT_FLAGS, TWE_STAT_BITS));
                    998:                }
                    999:        }
                   1000:
                   1001:        if (status & TWE_STAT_CMDI) {
                   1002:                rv++;
                   1003:                bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                   1004:                    TWE_CTRL_MCMDI);
                   1005:        }
                   1006:
                   1007:        if (rv)
                   1008:                wakeup(sc);
                   1009:
                   1010:        if (status & TWE_STAT_ATTNI) {
                   1011:                u_int16_t aen;
                   1012:
                   1013:                /*
                   1014:                 * we know no attentions of interest right now.
                   1015:                 * one of those would be mirror degradation i think.
                   1016:                 * or, what else exists in there?
                   1017:                 * maybe 3ware can answer that?
                   1018:                 */
                   1019:                bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
                   1020:                    TWE_CTRL_CATTNI);
                   1021:
                   1022:                lock = TWE_LOCK(sc);
                   1023:                for (aen = -1; aen != TWE_AEN_QEMPTY; ) {
                   1024:                        u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
                   1025:                        struct twe_param *pb = (void *) (((u_long)param_buf +
                   1026:                            TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
                   1027:
                   1028:                        if ((ccb = twe_get_ccb(sc)) == NULL)
                   1029:                                break;
                   1030:
                   1031:                        ccb->ccb_xs = NULL;
                   1032:                        ccb->ccb_data = pb;
                   1033:                        ccb->ccb_length = TWE_SECTOR_SIZE;
                   1034:                        ccb->ccb_state = TWE_CCB_READY;
                   1035:                        cmd = ccb->ccb_cmd;
                   1036:                        cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
                   1037:                        cmd->cmd_op = TWE_CMD_GPARAM;
                   1038:                        cmd->cmd_flags = 0;
                   1039:                        cmd->cmd_param.count = 1;
                   1040:
                   1041:                        pb->table_id = TWE_PARAM_AEN;
                   1042:                        pb->param_id = 2;
                   1043:                        pb->param_size = 2;
                   1044:                        if (twe_cmd(ccb, BUS_DMA_NOWAIT, 1)) {
                   1045:                                printf(": error draining attention queue\n");
                   1046:                                break;
                   1047:                        }
                   1048:                        aen = *(u_int16_t *)pb->data;
                   1049:                        TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
                   1050:                }
                   1051:                TWE_UNLOCK(sc, lock);
                   1052:        }
                   1053:
                   1054:        return rv;
                   1055: }

CVSweb