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

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

1.1       nbrk        1: /*     $OpenBSD: mpi.c,v 1.86 2007/06/12 19:29:23 thib Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org>
                      5:  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: #include <sys/param.h>
                     21: #include <sys/systm.h>
                     22: #include <sys/buf.h>
                     23: #include <sys/device.h>
                     24: #include <sys/proc.h>
                     25: #include <sys/malloc.h>
                     26: #include <sys/kernel.h>
                     27:
                     28: #include <machine/bus.h>
                     29:
                     30: #include <scsi/scsi_all.h>
                     31: #include <scsi/scsiconf.h>
                     32:
                     33: #include <dev/ic/mpireg.h>
                     34: #include <dev/ic/mpivar.h>
                     35:
                     36: #ifdef MPI_DEBUG
                     37: uint32_t       mpi_debug = 0
                     38: /*                 | MPI_D_CMD */
                     39: /*                 | MPI_D_INTR */
                     40: /*                 | MPI_D_MISC */
                     41: /*                 | MPI_D_DMA */
                     42: /*                 | MPI_D_IOCTL */
                     43: /*                 | MPI_D_RW */
                     44: /*                 | MPI_D_MEM */
                     45: /*                 | MPI_D_CCB */
                     46: /*                 | MPI_D_PPR */
                     47: /*                 | MPI_D_RAID */
                     48: /*                 | MPI_D_EVT */
                     49:                ;
                     50: #endif
                     51:
                     52: struct cfdriver mpi_cd = {
                     53:        NULL, "mpi", DV_DULL
                     54: };
                     55:
                     56: int                    mpi_scsi_cmd(struct scsi_xfer *);
                     57: void                   mpi_scsi_cmd_done(struct mpi_ccb *);
                     58: void                   mpi_minphys(struct buf *bp);
                     59: int                    mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t,
                     60:                            int, struct proc *);
                     61:
                     62: struct scsi_adapter mpi_switch = {
                     63:        mpi_scsi_cmd, mpi_minphys, NULL, NULL, mpi_scsi_ioctl
                     64: };
                     65:
                     66: struct scsi_device mpi_dev = {
                     67:        NULL, NULL, NULL, NULL
                     68: };
                     69:
                     70: struct mpi_dmamem      *mpi_dmamem_alloc(struct mpi_softc *, size_t);
                     71: void                   mpi_dmamem_free(struct mpi_softc *,
                     72:                            struct mpi_dmamem *);
                     73: int                    mpi_alloc_ccbs(struct mpi_softc *);
                     74: struct mpi_ccb         *mpi_get_ccb(struct mpi_softc *);
                     75: void                   mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *);
                     76: int                    mpi_alloc_replies(struct mpi_softc *);
                     77: void                   mpi_push_replies(struct mpi_softc *);
                     78:
                     79: void                   mpi_start(struct mpi_softc *, struct mpi_ccb *);
                     80: int                    mpi_complete(struct mpi_softc *, struct mpi_ccb *, int);
                     81: int                    mpi_poll(struct mpi_softc *, struct mpi_ccb *, int);
                     82: int                    mpi_reply(struct mpi_softc *, u_int32_t);
                     83:
                     84: void                   mpi_squash_ppr(struct mpi_softc *);
                     85: void                   mpi_run_ppr(struct mpi_softc *);
                     86: int                    mpi_ppr(struct mpi_softc *, struct scsi_link *,
                     87:                            struct mpi_cfg_raid_physdisk *, int, int, int);
                     88: int                    mpi_inq(struct mpi_softc *, u_int16_t, int);
                     89:
                     90: void                   mpi_timeout_xs(void *);
                     91: int                    mpi_load_xs(struct mpi_ccb *);
                     92:
                     93: u_int32_t              mpi_read(struct mpi_softc *, bus_size_t);
                     94: void                   mpi_write(struct mpi_softc *, bus_size_t, u_int32_t);
                     95: int                    mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t,
                     96:                            u_int32_t);
                     97: int                    mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t,
                     98:                            u_int32_t);
                     99:
                    100: int                    mpi_init(struct mpi_softc *);
                    101: int                    mpi_reset_soft(struct mpi_softc *);
                    102: int                    mpi_reset_hard(struct mpi_softc *);
                    103:
                    104: int                    mpi_handshake_send(struct mpi_softc *, void *, size_t);
                    105: int                    mpi_handshake_recv_dword(struct mpi_softc *,
                    106:                            u_int32_t *);
                    107: int                    mpi_handshake_recv(struct mpi_softc *, void *, size_t);
                    108:
                    109: void                   mpi_empty_done(struct mpi_ccb *);
                    110:
                    111: int                    mpi_iocinit(struct mpi_softc *);
                    112: int                    mpi_iocfacts(struct mpi_softc *);
                    113: int                    mpi_portfacts(struct mpi_softc *);
                    114: int                    mpi_portenable(struct mpi_softc *);
                    115: void                   mpi_get_raid(struct mpi_softc *);
                    116: int                    mpi_fwupload(struct mpi_softc *);
                    117:
                    118: int                    mpi_eventnotify(struct mpi_softc *);
                    119: void                   mpi_eventnotify_done(struct mpi_ccb *);
                    120: void                   mpi_eventack(struct mpi_softc *,
                    121:                            struct mpi_msg_event_reply *);
                    122: void                   mpi_eventack_done(struct mpi_ccb *);
                    123: void                   mpi_evt_sas(void *, void *);
                    124:
                    125: int                    mpi_cfg_header(struct mpi_softc *, u_int8_t, u_int8_t,
                    126:                            u_int32_t, struct mpi_cfg_hdr *);
                    127: int                    mpi_cfg_page(struct mpi_softc *, u_int32_t,
                    128:                            struct mpi_cfg_hdr *, int, void *, size_t);
                    129:
                    130: #define DEVNAME(s)             ((s)->sc_dev.dv_xname)
                    131:
                    132: #define        dwordsof(s)             (sizeof(s) / sizeof(u_int32_t))
                    133: #define        sizeofa(s)              (sizeof(s) / sizeof((s)[0]))
                    134:
                    135: #define mpi_read_db(s)         mpi_read((s), MPI_DOORBELL)
                    136: #define mpi_write_db(s, v)     mpi_write((s), MPI_DOORBELL, (v))
                    137: #define mpi_read_intr(s)       mpi_read((s), MPI_INTR_STATUS)
                    138: #define mpi_write_intr(s, v)   mpi_write((s), MPI_INTR_STATUS, (v))
                    139: #define mpi_pop_reply(s)       mpi_read((s), MPI_REPLY_QUEUE)
                    140: #define mpi_push_reply(s, v)   mpi_write((s), MPI_REPLY_QUEUE, (v))
                    141:
                    142: #define mpi_wait_db_int(s)     mpi_wait_ne((s), MPI_INTR_STATUS, \
                    143:                                    MPI_INTR_STATUS_DOORBELL, 0)
                    144: #define mpi_wait_db_ack(s)     mpi_wait_eq((s), MPI_INTR_STATUS, \
                    145:                                    MPI_INTR_STATUS_IOCDOORBELL, 0)
                    146:
                    147: int
                    148: mpi_attach(struct mpi_softc *sc)
                    149: {
                    150:        struct scsibus_attach_args      saa;
                    151:        struct mpi_ccb                  *ccb;
                    152:
                    153:        printf("\n");
                    154:
                    155:        /* disable interrupts */
                    156:        mpi_write(sc, MPI_INTR_MASK,
                    157:            MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL);
                    158:
                    159:        if (mpi_init(sc) != 0) {
                    160:                printf("%s: unable to initialise\n", DEVNAME(sc));
                    161:                return (1);
                    162:        }
                    163:
                    164:        if (mpi_iocfacts(sc) != 0) {
                    165:                printf("%s: unable to get iocfacts\n", DEVNAME(sc));
                    166:                return (1);
                    167:        }
                    168:
                    169:        if (mpi_alloc_ccbs(sc) != 0) {
                    170:                /* error already printed */
                    171:                return (1);
                    172:        }
                    173:
                    174:        if (mpi_alloc_replies(sc) != 0) {
                    175:                printf("%s: unable to allocate reply space\n", DEVNAME(sc));
                    176:                goto free_ccbs;
                    177:        }
                    178:
                    179:        if (mpi_iocinit(sc) != 0) {
                    180:                printf("%s: unable to send iocinit\n", DEVNAME(sc));
                    181:                goto free_ccbs;
                    182:        }
                    183:
                    184:        /* spin until we're operational */
                    185:        if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
                    186:            MPI_DOORBELL_STATE_OPER) != 0) {
                    187:                printf("%s: state: 0x%08x\n", DEVNAME(sc),
                    188:                    mpi_read_db(sc) & MPI_DOORBELL_STATE);
                    189:                printf("%s: operational state timeout\n", DEVNAME(sc));
                    190:                goto free_ccbs;
                    191:        }
                    192:
                    193:        mpi_push_replies(sc);
                    194:
                    195:        if (mpi_portfacts(sc) != 0) {
                    196:                printf("%s: unable to get portfacts\n", DEVNAME(sc));
                    197:                goto free_replies;
                    198:        }
                    199:
                    200: #ifdef notyet
                    201:        if (mpi_eventnotify(sc) != 0) {
                    202:                printf("%s: unable to get portfacts\n", DEVNAME(sc));
                    203:                goto free_replies;
                    204:        }
                    205: #endif
                    206:
                    207:        if (mpi_portenable(sc) != 0) {
                    208:                printf("%s: unable to enable port\n", DEVNAME(sc));
                    209:                goto free_replies;
                    210:        }
                    211:
                    212:        if (mpi_fwupload(sc) != 0) {
                    213:                printf("%s: unable to upload firmware\n", DEVNAME(sc));
                    214:                goto free_replies;
                    215:        }
                    216:
                    217:        if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI)
                    218:                mpi_squash_ppr(sc);
                    219:
                    220:        /* we should be good to go now, attach scsibus */
                    221:        sc->sc_link.device = &mpi_dev;
                    222:        sc->sc_link.adapter = &mpi_switch;
                    223:        sc->sc_link.adapter_softc = sc;
                    224:        sc->sc_link.adapter_target = sc->sc_target;
                    225:        sc->sc_link.adapter_buswidth = sc->sc_buswidth;
                    226:        sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth;
                    227:
                    228:        bzero(&saa, sizeof(saa));
                    229:        saa.saa_sc_link = &sc->sc_link;
                    230:
                    231:        /* config_found() returns the scsibus attached to us */
                    232:        sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev,
                    233:            &saa, scsiprint);
                    234:
                    235:        /* get raid pages */
                    236:        mpi_get_raid(sc);
                    237:
                    238:        /* do domain validation */
                    239:        if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI)
                    240:                mpi_run_ppr(sc);
                    241:
                    242:        /* enable interrupts */
                    243:        mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL);
                    244:
                    245:        return (0);
                    246:
                    247: free_replies:
                    248:        bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
                    249:            0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
                    250:        mpi_dmamem_free(sc, sc->sc_replies);
                    251: free_ccbs:
                    252:        while ((ccb = mpi_get_ccb(sc)) != NULL)
                    253:                bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
                    254:        mpi_dmamem_free(sc, sc->sc_requests);
                    255:        free(sc->sc_ccbs, M_DEVBUF);
                    256:
                    257:        return(1);
                    258: }
                    259:
                    260: void
                    261: mpi_squash_ppr(struct mpi_softc *sc)
                    262: {
                    263:        struct mpi_cfg_hdr              hdr;
                    264:        struct mpi_cfg_spi_dev_pg1      page;
                    265:        int                             i;
                    266:
                    267:        DNPRINTF(MPI_D_PPR, "%s: mpi_squash_ppr\n", DEVNAME(sc));
                    268:
                    269:        for (i = 0; i < sc->sc_buswidth; i++) {
                    270:                if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV,
                    271:                    1, i, &hdr) != 0)
                    272:                        return;
                    273:
                    274:                if (mpi_cfg_page(sc, i, &hdr, 1, &page, sizeof(page)) != 0)
                    275:                        return;
                    276:
                    277:                DNPRINTF(MPI_D_PPR, "%s:  target: %d req_params1: 0x%02x "
                    278:                    "req_offset: 0x%02x req_period: 0x%02x "
                    279:                    "req_params2: 0x%02x conf: 0x%08x\n", DEVNAME(sc), i,
                    280:                    page.req_params1, page.req_offset, page.req_period,
                    281:                    page.req_params2, letoh32(page.configuration));
                    282:
                    283:                page.req_params1 = 0x0;
                    284:                page.req_offset = 0x0;
                    285:                page.req_period = 0x0;
                    286:                page.req_params2 = 0x0;
                    287:                page.configuration = htole32(0x0);
                    288:
                    289:                if (mpi_cfg_page(sc, i, &hdr, 0, &page, sizeof(page)) != 0)
                    290:                        return;
                    291:        }
                    292: }
                    293:
                    294: void
                    295: mpi_run_ppr(struct mpi_softc *sc)
                    296: {
                    297:        struct mpi_cfg_hdr              hdr;
                    298:        struct mpi_cfg_spi_port_pg0     port_pg;
                    299:        struct mpi_cfg_ioc_pg3          *physdisk_pg;
                    300:        struct mpi_cfg_raid_physdisk    *physdisk_list, *physdisk;
                    301:        size_t                          pagelen;
                    302:        struct scsi_link                *link;
                    303:        int                             i, tries;
                    304:
                    305:        if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_PORT, 0, 0x0,
                    306:            &hdr) != 0) {
                    307:                DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch header\n",
                    308:                    DEVNAME(sc));
                    309:                return;
                    310:        }
                    311:
                    312:        if (mpi_cfg_page(sc, 0x0, &hdr, 1, &port_pg, sizeof(port_pg)) != 0) {
                    313:                DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch page\n",
                    314:                    DEVNAME(sc));
                    315:                return;
                    316:        }
                    317:
                    318:        for (i = 0; i < sc->sc_buswidth; i++) {
                    319:                link = sc->sc_scsibus->sc_link[i][0];
                    320:                if (link == NULL)
                    321:                        continue;
                    322:
                    323:                /* do not ppr volumes */
                    324:                if (link->flags & SDEV_VIRTUAL)
                    325:                        continue;
                    326:
                    327:                tries = 0;
                    328:                while (mpi_ppr(sc, link, NULL, port_pg.min_period,
                    329:                    port_pg.max_offset, tries) == EAGAIN)
                    330:                        tries++;
                    331:        }
                    332:
                    333:        if ((sc->sc_flags & MPI_F_RAID) == 0)
                    334:                return;
                    335:
                    336:        if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 3, 0x0,
                    337:            &hdr) != 0) {
                    338:                DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
                    339:                    "fetch ioc pg 3 header\n", DEVNAME(sc));
                    340:                return;
                    341:        }
                    342:
                    343:        pagelen = hdr.page_length * 4; /* dwords to bytes */
                    344:        physdisk_pg = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
                    345:        if (physdisk_pg == NULL) {
                    346:                DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
                    347:                    "allocate ioc pg 3\n", DEVNAME(sc));
                    348:                return;
                    349:        }
                    350:        physdisk_list = (struct mpi_cfg_raid_physdisk *)(physdisk_pg + 1);
                    351:
                    352:        if (mpi_cfg_page(sc, 0, &hdr, 1, physdisk_pg, pagelen) != 0) {
                    353:                DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: mpi_run_ppr unable to "
                    354:                    "fetch ioc page 3\n", DEVNAME(sc));
                    355:                goto out;
                    356:        }
                    357:
                    358:        DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s:  no_phys_disks: %d\n", DEVNAME(sc),
                    359:            physdisk_pg->no_phys_disks);
                    360:
                    361:        for (i = 0; i < physdisk_pg->no_phys_disks; i++) {
                    362:                physdisk = &physdisk_list[i];
                    363:
                    364:                DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s:  id: %d bus: %d ioc: %d "
                    365:                    "num: %d\n", DEVNAME(sc), physdisk->phys_disk_id,
                    366:                    physdisk->phys_disk_bus, physdisk->phys_disk_ioc,
                    367:                    physdisk->phys_disk_num);
                    368:
                    369:                if (physdisk->phys_disk_ioc != sc->sc_ioc_number)
                    370:                        continue;
                    371:
                    372:                tries = 0;
                    373:                while (mpi_ppr(sc, NULL, physdisk, port_pg.min_period,
                    374:                    port_pg.max_offset, tries) == EAGAIN)
                    375:                        tries++;
                    376:        }
                    377:
                    378: out:
                    379:        free(physdisk_pg, M_TEMP);
                    380: }
                    381:
                    382: int
                    383: mpi_ppr(struct mpi_softc *sc, struct scsi_link *link,
                    384:     struct mpi_cfg_raid_physdisk *physdisk, int period, int offset, int try)
                    385: {
                    386:        struct mpi_cfg_hdr              hdr0, hdr1;
                    387:        struct mpi_cfg_spi_dev_pg0      pg0;
                    388:        struct mpi_cfg_spi_dev_pg1      pg1;
                    389:        u_int32_t                       address;
                    390:        int                             id;
                    391:        int                             raid = 0;
                    392:
                    393:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr period: %d offset: %d try: %d "
                    394:            "link quirks: 0x%x\n", DEVNAME(sc), period, offset, try,
                    395:            link->quirks);
                    396:
                    397:        if (try >= 3)
                    398:                return (EIO);
                    399:
                    400:        if (physdisk == NULL) {
                    401:                if ((link->inqdata.device & SID_TYPE) == T_PROCESSOR)
                    402:                        return (EIO);
                    403:
                    404:                address = link->target;
                    405:                id = link->target;
                    406:        } else {
                    407:                raid = 1;
                    408:                address = (physdisk->phys_disk_bus << 8) |
                    409:                    (physdisk->phys_disk_id);
                    410:                id = physdisk->phys_disk_num;
                    411:        }
                    412:
                    413:        if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 0,
                    414:            address, &hdr0) != 0) {
                    415:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 0\n",
                    416:                    DEVNAME(sc));
                    417:                return (EIO);
                    418:        }
                    419:
                    420:        if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 1,
                    421:            address, &hdr1) != 0) {
                    422:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 1\n",
                    423:                    DEVNAME(sc));
                    424:                return (EIO);
                    425:        }
                    426:
                    427: #ifdef MPI_DEBUG
                    428:        if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
                    429:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 0\n",
                    430:                    DEVNAME(sc));
                    431:                return (EIO);
                    432:        }
                    433:
                    434:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
                    435:            "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
                    436:            "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
                    437:            pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
                    438: #endif
                    439:
                    440:        if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
                    441:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 1\n",
                    442:                    DEVNAME(sc));
                    443:                return (EIO);
                    444:        }
                    445:
                    446:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
                    447:            "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
                    448:            "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
                    449:            pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
                    450:
                    451:        pg1.req_params1 = 0;
                    452:        pg1.req_offset = offset;
                    453:        pg1.req_period = period;
                    454:        pg1.req_params2 &= ~MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH;
                    455:
                    456:        if (raid || !(link->quirks & SDEV_NOSYNC)) {
                    457:                pg1.req_params2 |= MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH_WIDE;
                    458:
                    459:                switch (try) {
                    460:                case 0: /* U320 */
                    461:                        break;
                    462:                case 1: /* U160 */
                    463:                        pg1.req_period = 0x09;
                    464:                        break;
                    465:                case 2: /* U80 */
                    466:                        pg1.req_period = 0x0a;
                    467:                        break;
                    468:                }
                    469:
                    470:                if (pg1.req_period < 0x09) {
                    471:                        /* Ultra320: enable QAS & PACKETIZED */
                    472:                        pg1.req_params1 |= MPI_CFG_SPI_DEV_1_REQPARAMS_QAS |
                    473:                            MPI_CFG_SPI_DEV_1_REQPARAMS_PACKETIZED;
                    474:                }
                    475:                if (pg1.req_period < 0xa) {
                    476:                        /* >= Ultra160: enable dual xfers */
                    477:                        pg1.req_params1 |=
                    478:                            MPI_CFG_SPI_DEV_1_REQPARAMS_DUALXFERS;
                    479:                }
                    480:        }
                    481:
                    482:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
                    483:            "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
                    484:            "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
                    485:            pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
                    486:
                    487:        if (mpi_cfg_page(sc, address, &hdr1, 0, &pg1, sizeof(pg1)) != 0) {
                    488:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to write page 1\n",
                    489:                    DEVNAME(sc));
                    490:                return (EIO);
                    491:        }
                    492:
                    493:        if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
                    494:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 1\n",
                    495:                    DEVNAME(sc));
                    496:                return (EIO);
                    497:        }
                    498:
                    499:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
                    500:            "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
                    501:            "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
                    502:            pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
                    503:
                    504:        if (mpi_inq(sc, id, raid) != 0) {
                    505:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to do inquiry against "
                    506:                    "target %d\n", DEVNAME(sc), link->target);
                    507:                return (EIO);
                    508:        }
                    509:
                    510:        if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
                    511:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 0 after "
                    512:                    "inquiry\n", DEVNAME(sc));
                    513:                return (EIO);
                    514:        }
                    515:
                    516:        DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
                    517:            "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
                    518:            "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
                    519:            pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
                    520:
                    521:        if (!(letoh32(pg0.information) & 0x07) && (try == 0)) {
                    522:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U320 ppr rejected\n",
                    523:                    DEVNAME(sc));
                    524:                return (EAGAIN);
                    525:        }
                    526:
                    527:        if ((((letoh32(pg0.information) >> 8) & 0xff) > 0x09) && (try == 1)) {
                    528:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U160 ppr rejected\n",
                    529:                    DEVNAME(sc));
                    530:                return (EAGAIN);
                    531:        }
                    532:
                    533:        if (letoh32(pg0.information) & 0x0e) {
                    534:                DNPRINTF(MPI_D_PPR, "%s: mpi_ppr ppr rejected: %0x\n",
                    535:                    DEVNAME(sc), letoh32(pg0.information));
                    536:                return (EAGAIN);
                    537:        }
                    538:
                    539:        switch(pg0.neg_period) {
                    540:        case 0x08:
                    541:                period = 160;
                    542:                break;
                    543:        case 0x09:
                    544:                period = 80;
                    545:                break;
                    546:        case 0x0a:
                    547:                period = 40;
                    548:                break;
                    549:        case 0x0b:
                    550:                period = 20;
                    551:                break;
                    552:        case 0x0c:
                    553:                period = 10;
                    554:                break;
                    555:        default:
                    556:                period = 0;
                    557:                break;
                    558:        }
                    559:
                    560:        printf("%s: %s %d %s at %dMHz width %dbit offset %d "
                    561:            "QAS %d DT %d IU %d\n", DEVNAME(sc), raid ? "phys disk" : "target",
                    562:            id, period ? "Sync" : "Async", period,
                    563:            (pg0.neg_params2 & MPI_CFG_SPI_DEV_0_NEGPARAMS_WIDTH_WIDE) ? 16 : 8,
                    564:            pg0.neg_offset,
                    565:            (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_QAS) ? 1 : 0,
                    566:            (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_DUALXFERS) ? 1 : 0,
                    567:            (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_PACKETIZED) ? 1 : 0);
                    568:
                    569:        return (0);
                    570: }
                    571:
                    572: int
                    573: mpi_inq(struct mpi_softc *sc, u_int16_t target, int physdisk)
                    574: {
                    575:        struct mpi_ccb                  *ccb;
                    576:        struct scsi_inquiry             inq;
                    577:        struct {
                    578:                struct mpi_msg_scsi_io          io;
                    579:                struct mpi_sge                  sge;
                    580:                struct scsi_inquiry_data        inqbuf;
                    581:                struct scsi_sense_data          sense;
                    582:        } __packed                      *bundle;
                    583:        struct mpi_msg_scsi_io          *io;
                    584:        struct mpi_sge                  *sge;
                    585:        u_int64_t                       addr;
                    586:
                    587:        DNPRINTF(MPI_D_PPR, "%s: mpi_inq\n", DEVNAME(sc));
                    588:
                    589:        bzero(&inq, sizeof(inq));
                    590:        inq.opcode = INQUIRY;
                    591:        _lto2b(sizeof(struct scsi_inquiry_data), inq.length);
                    592:
                    593:        ccb = mpi_get_ccb(sc);
                    594:        if (ccb == NULL)
                    595:                return (1);
                    596:
                    597:        ccb->ccb_done = mpi_empty_done;
                    598:
                    599:        bundle = ccb->ccb_cmd;
                    600:        io = &bundle->io;
                    601:        sge = &bundle->sge;
                    602:
                    603:        io->function = physdisk ? MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH :
                    604:            MPI_FUNCTION_SCSI_IO_REQUEST;
                    605:        /*
                    606:         * bus is always 0
                    607:         * io->bus = htole16(sc->sc_bus);
                    608:         */
                    609:        io->target_id = target;
                    610:
                    611:        io->cdb_length = sizeof(inq);
                    612:        io->sense_buf_len = sizeof(struct scsi_sense_data);
                    613:        io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
                    614:
                    615:        io->msg_context = htole32(ccb->ccb_id);
                    616:
                    617:        /*
                    618:         * always lun 0
                    619:         * io->lun[0] = htobe16(link->lun);
                    620:         */
                    621:
                    622:        io->direction = MPI_SCSIIO_DIR_READ;
                    623:        io->tagging = MPI_SCSIIO_ATTR_NO_DISCONNECT;
                    624:
                    625:        bcopy(&inq, io->cdb, sizeof(inq));
                    626:
                    627:        io->data_length = htole32(sizeof(struct scsi_inquiry_data));
                    628:
                    629:        io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
                    630:            ((u_int8_t *)&bundle->sense - (u_int8_t *)bundle));
                    631:
                    632:        sge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64 |
                    633:            MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
                    634:            (u_int32_t)sizeof(inq));
                    635:
                    636:        addr = ccb->ccb_cmd_dva +
                    637:            ((u_int8_t *)&bundle->inqbuf - (u_int8_t *)bundle);
                    638:        sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
                    639:        sge->sg_lo_addr = htole32((u_int32_t)addr);
                    640:
                    641:        if (mpi_poll(sc, ccb, 5000) != 0)
                    642:                return (1);
                    643:
                    644:        if (ccb->ccb_rcb != NULL)
                    645:                mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                    646:
                    647:        mpi_put_ccb(sc, ccb);
                    648:
                    649:        return (0);
                    650: }
                    651:
                    652: void
                    653: mpi_detach(struct mpi_softc *sc)
                    654: {
                    655:
                    656: }
                    657:
                    658: int
                    659: mpi_intr(void *arg)
                    660: {
                    661:        struct mpi_softc                *sc = arg;
                    662:        u_int32_t                       reg;
                    663:        int                             rv = 0;
                    664:
                    665:        while ((reg = mpi_pop_reply(sc)) != 0xffffffff) {
                    666:                mpi_reply(sc, reg);
                    667:                rv = 1;
                    668:        }
                    669:
                    670:        return (rv);
                    671: }
                    672:
                    673: int
                    674: mpi_reply(struct mpi_softc *sc, u_int32_t reg)
                    675: {
                    676:        struct mpi_ccb                  *ccb;
                    677:        struct mpi_rcb                  *rcb = NULL;
                    678:        struct mpi_msg_reply            *reply = NULL;
                    679:        u_int32_t                       reply_dva;
                    680:        int                             id;
                    681:        int                             i;
                    682:
                    683:        DNPRINTF(MPI_D_INTR, "%s: mpi_reply reg: 0x%08x\n", DEVNAME(sc), reg);
                    684:
                    685:        if (reg & MPI_REPLY_QUEUE_ADDRESS) {
                    686:                bus_dmamap_sync(sc->sc_dmat,
                    687:                    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
                    688:                    BUS_DMASYNC_POSTREAD);
                    689:
                    690:                reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1;
                    691:
                    692:                i = (reply_dva - (u_int32_t)MPI_DMA_DVA(sc->sc_replies)) /
                    693:                    MPI_REPLY_SIZE;
                    694:                rcb = &sc->sc_rcbs[i];
                    695:                reply = rcb->rcb_reply;
                    696:
                    697:                id = letoh32(reply->msg_context);
                    698:
                    699:                bus_dmamap_sync(sc->sc_dmat,
                    700:                    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
                    701:                    BUS_DMASYNC_PREREAD);
                    702:        } else {
                    703:                switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) {
                    704:                case MPI_REPLY_QUEUE_TYPE_INIT:
                    705:                        id = reg & MPI_REPLY_QUEUE_CONTEXT;
                    706:                        break;
                    707:
                    708:                default:
                    709:                        panic("%s: unsupported context reply\n",
                    710:                            DEVNAME(sc));
                    711:                }
                    712:        }
                    713:
                    714:        DNPRINTF(MPI_D_INTR, "%s: mpi_reply id: %d reply: %p\n",
                    715:            DEVNAME(sc), id, reply);
                    716:
                    717:        ccb = &sc->sc_ccbs[id];
                    718:
                    719:        bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
                    720:            ccb->ccb_offset, MPI_REQUEST_SIZE,
                    721:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    722:        ccb->ccb_state = MPI_CCB_READY;
                    723:        ccb->ccb_rcb = rcb;
                    724:
                    725:        ccb->ccb_done(ccb);
                    726:
                    727:        return (id);
                    728: }
                    729:
                    730: struct mpi_dmamem *
                    731: mpi_dmamem_alloc(struct mpi_softc *sc, size_t size)
                    732: {
                    733:        struct mpi_dmamem               *mdm;
                    734:        int                             nsegs;
                    735:
                    736:        mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT);
                    737:        if (mdm == NULL)
                    738:                return (NULL);
                    739:
                    740:        bzero(mdm, sizeof(struct mpi_dmamem));
                    741:        mdm->mdm_size = size;
                    742:
                    743:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                    744:            BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
                    745:                goto mdmfree;
                    746:
                    747:        if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
                    748:            1, &nsegs, BUS_DMA_NOWAIT) != 0)
                    749:                goto destroy;
                    750:
                    751:        if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
                    752:            &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
                    753:                goto free;
                    754:
                    755:        if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
                    756:            NULL, BUS_DMA_NOWAIT) != 0)
                    757:                goto unmap;
                    758:
                    759:        bzero(mdm->mdm_kva, size);
                    760:
                    761:        DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_alloc size: %d mdm: %#x "
                    762:            "map: %#x nsegs: %d segs: %#x kva: %x\n",
                    763:            DEVNAME(sc), size, mdm->mdm_map, nsegs, mdm->mdm_seg, mdm->mdm_kva);
                    764:
                    765:        return (mdm);
                    766:
                    767: unmap:
                    768:        bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
                    769: free:
                    770:        bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
                    771: destroy:
                    772:        bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
                    773: mdmfree:
                    774:        free(mdm, M_DEVBUF);
                    775:
                    776:        return (NULL);
                    777: }
                    778:
                    779: void
                    780: mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm)
                    781: {
                    782:        DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_free %#x\n", DEVNAME(sc), mdm);
                    783:
                    784:        bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
                    785:        bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
                    786:        bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
                    787:        bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
                    788:        free(mdm, M_DEVBUF);
                    789: }
                    790:
                    791: int
                    792: mpi_alloc_ccbs(struct mpi_softc *sc)
                    793: {
                    794:        struct mpi_ccb                  *ccb;
                    795:        u_int8_t                        *cmd;
                    796:        int                             i;
                    797:
                    798:        TAILQ_INIT(&sc->sc_ccb_free);
                    799:
                    800:        sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds,
                    801:            M_DEVBUF, M_WAITOK|M_CANFAIL);
                    802:        if (sc->sc_ccbs == NULL) {
                    803:                printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
                    804:                return (1);
                    805:        }
                    806:        bzero(sc->sc_ccbs, sizeof(struct mpi_ccb) * sc->sc_maxcmds);
                    807:
                    808:        sc->sc_requests = mpi_dmamem_alloc(sc,
                    809:            MPI_REQUEST_SIZE * sc->sc_maxcmds);
                    810:        if (sc->sc_requests == NULL) {
                    811:                printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
                    812:                goto free_ccbs;
                    813:        }
                    814:        cmd = MPI_DMA_KVA(sc->sc_requests);
                    815:        bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds);
                    816:
                    817:        for (i = 0; i < sc->sc_maxcmds; i++) {
                    818:                ccb = &sc->sc_ccbs[i];
                    819:
                    820:                if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
                    821:                    sc->sc_max_sgl_len, MAXPHYS, 0, 0,
                    822:                    &ccb->ccb_dmamap) != 0) {
                    823:                        printf("%s: unable to create dma map\n", DEVNAME(sc));
                    824:                        goto free_maps;
                    825:                }
                    826:
                    827:                ccb->ccb_sc = sc;
                    828:                ccb->ccb_id = i;
                    829:                ccb->ccb_offset = MPI_REQUEST_SIZE * i;
                    830:
                    831:                ccb->ccb_cmd = &cmd[ccb->ccb_offset];
                    832:                ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) +
                    833:                    ccb->ccb_offset;
                    834:
                    835:                DNPRINTF(MPI_D_CCB, "%s: mpi_alloc_ccbs(%d) ccb: %#x map: %#x "
                    836:                    "sc: %#x id: %#x offs: %#x cmd: %#x dva: %#x\n",
                    837:                    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
                    838:                    ccb->ccb_id, ccb->ccb_offset, ccb->ccb_cmd,
                    839:                    ccb->ccb_cmd_dva);
                    840:
                    841:                mpi_put_ccb(sc, ccb);
                    842:        }
                    843:
                    844:        return (0);
                    845:
                    846: free_maps:
                    847:        while ((ccb = mpi_get_ccb(sc)) != NULL)
                    848:                bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
                    849:
                    850:        mpi_dmamem_free(sc, sc->sc_requests);
                    851: free_ccbs:
                    852:        free(sc->sc_ccbs, M_DEVBUF);
                    853:
                    854:        return (1);
                    855: }
                    856:
                    857: struct mpi_ccb *
                    858: mpi_get_ccb(struct mpi_softc *sc)
                    859: {
                    860:        struct mpi_ccb                  *ccb;
                    861:
                    862:        ccb = TAILQ_FIRST(&sc->sc_ccb_free);
                    863:        if (ccb == NULL) {
                    864:                DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb == NULL\n", DEVNAME(sc));
                    865:                return (NULL);
                    866:        }
                    867:
                    868:        TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
                    869:
                    870:        ccb->ccb_state = MPI_CCB_READY;
                    871:
                    872:        DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb %#x\n", DEVNAME(sc), ccb);
                    873:
                    874:        return (ccb);
                    875: }
                    876:
                    877: void
                    878: mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb)
                    879: {
                    880:        DNPRINTF(MPI_D_CCB, "%s: mpi_put_ccb %#x\n", DEVNAME(sc), ccb);
                    881:
                    882:        ccb->ccb_state = MPI_CCB_FREE;
                    883:        ccb->ccb_xs = NULL;
                    884:        ccb->ccb_done = NULL;
                    885:        bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE);
                    886:        TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
                    887: }
                    888:
                    889: int
                    890: mpi_alloc_replies(struct mpi_softc *sc)
                    891: {
                    892:        DNPRINTF(MPI_D_MISC, "%s: mpi_alloc_replies\n", DEVNAME(sc));
                    893:
                    894:        sc->sc_rcbs = malloc(MPI_REPLY_COUNT * sizeof(struct mpi_rcb),
                    895:            M_DEVBUF, M_WAITOK|M_CANFAIL);
                    896:        if (sc->sc_rcbs == NULL)
                    897:                return (1);
                    898:
                    899:        sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE);
                    900:        if (sc->sc_replies == NULL) {
                    901:                free(sc->sc_rcbs, M_DEVBUF);
                    902:                return (1);
                    903:        }
                    904:
                    905:        return (0);
                    906: }
                    907:
                    908: void
                    909: mpi_push_replies(struct mpi_softc *sc)
                    910: {
                    911:        struct mpi_rcb                  *rcb;
                    912:        char                            *kva = MPI_DMA_KVA(sc->sc_replies);
                    913:        int                             i;
                    914:
                    915:        bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
                    916:            0, PAGE_SIZE, BUS_DMASYNC_PREREAD);
                    917:
                    918:        for (i = 0; i < MPI_REPLY_COUNT; i++) {
                    919:                rcb = &sc->sc_rcbs[i];
                    920:
                    921:                rcb->rcb_reply = kva + MPI_REPLY_SIZE * i;
                    922:                rcb->rcb_reply_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) +
                    923:                    MPI_REPLY_SIZE * i;
                    924:                mpi_push_reply(sc, rcb->rcb_reply_dva);
                    925:        }
                    926: }
                    927:
                    928: void
                    929: mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb)
                    930: {
                    931:        DNPRINTF(MPI_D_RW, "%s: mpi_start %#x\n", DEVNAME(sc),
                    932:            ccb->ccb_cmd_dva);
                    933:
                    934:        bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
                    935:            ccb->ccb_offset, MPI_REQUEST_SIZE,
                    936:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    937:
                    938:        ccb->ccb_state = MPI_CCB_QUEUED;
                    939:        mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva);
                    940: }
                    941:
                    942: int
                    943: mpi_complete(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
                    944: {
                    945:        u_int32_t                       reg;
                    946:        int                             id = -1;
                    947:
                    948:        DNPRINTF(MPI_D_INTR, "%s: mpi_complete timeout %d\n", DEVNAME(sc),
                    949:            timeout);
                    950:
                    951:        do {
                    952:                reg = mpi_pop_reply(sc);
                    953:                if (reg == 0xffffffff) {
                    954:                        if (timeout-- == 0)
                    955:                                return (1);
                    956:
                    957:                        delay(1000);
                    958:                        continue;
                    959:                }
                    960:
                    961:                id = mpi_reply(sc, reg);
                    962:
                    963:        } while (ccb->ccb_id != id);
                    964:
                    965:        return (0);
                    966: }
                    967:
                    968: int
                    969: mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
                    970: {
                    971:        int                             error;
                    972:        int                             s;
                    973:
                    974:        DNPRINTF(MPI_D_CMD, "%s: mpi_poll\n", DEVNAME(sc));
                    975:
                    976:        s = splbio();
                    977:        mpi_start(sc, ccb);
                    978:        error = mpi_complete(sc, ccb, timeout);
                    979:        splx(s);
                    980:
                    981:        return (error);
                    982: }
                    983:
                    984: int
                    985: mpi_scsi_cmd(struct scsi_xfer *xs)
                    986: {
                    987:        struct scsi_link                *link = xs->sc_link;
                    988:        struct mpi_softc                *sc = link->adapter_softc;
                    989:        struct mpi_ccb                  *ccb;
                    990:        struct mpi_ccb_bundle           *mcb;
                    991:        struct mpi_msg_scsi_io          *io;
                    992:        int                             s;
                    993:
                    994:        DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd\n", DEVNAME(sc));
                    995:
                    996:        if (xs->cmdlen > MPI_CDB_LEN) {
                    997:                DNPRINTF(MPI_D_CMD, "%s: CBD too big %d\n",
                    998:                    DEVNAME(sc), xs->cmdlen);
                    999:                bzero(&xs->sense, sizeof(xs->sense));
                   1000:                xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
                   1001:                xs->sense.flags = SKEY_ILLEGAL_REQUEST;
                   1002:                xs->sense.add_sense_code = 0x20;
                   1003:                xs->error = XS_SENSE;
                   1004:                s = splbio();
                   1005:                scsi_done(xs);
                   1006:                splx(s);
                   1007:                return (COMPLETE);
                   1008:        }
                   1009:
                   1010:        s = splbio();
                   1011:        ccb = mpi_get_ccb(sc);
                   1012:        splx(s);
                   1013:        if (ccb == NULL) {
                   1014:                xs->error = XS_DRIVER_STUFFUP;
                   1015:                s = splbio();
                   1016:                scsi_done(xs);
                   1017:                splx(s);
                   1018:                return (COMPLETE);
                   1019:        }
                   1020:        DNPRINTF(MPI_D_CMD, "%s: ccb_id: %d xs->flags: 0x%x\n",
                   1021:            DEVNAME(sc), ccb->ccb_id, xs->flags);
                   1022:
                   1023:        ccb->ccb_xs = xs;
                   1024:        ccb->ccb_done = mpi_scsi_cmd_done;
                   1025:
                   1026:        mcb = ccb->ccb_cmd;
                   1027:        io = &mcb->mcb_io;
                   1028:
                   1029:        io->function = MPI_FUNCTION_SCSI_IO_REQUEST;
                   1030:        /*
                   1031:         * bus is always 0
                   1032:         * io->bus = htole16(sc->sc_bus);
                   1033:         */
                   1034:        io->target_id = link->target;
                   1035:
                   1036:        io->cdb_length = xs->cmdlen;
                   1037:        io->sense_buf_len = sizeof(xs->sense);
                   1038:        io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
                   1039:
                   1040:        io->msg_context = htole32(ccb->ccb_id);
                   1041:
                   1042:        io->lun[0] = htobe16(link->lun);
                   1043:
                   1044:        switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
                   1045:        case SCSI_DATA_IN:
                   1046:                io->direction = MPI_SCSIIO_DIR_READ;
                   1047:                break;
                   1048:        case SCSI_DATA_OUT:
                   1049:                io->direction = MPI_SCSIIO_DIR_WRITE;
                   1050:                break;
                   1051:        default:
                   1052:                io->direction = MPI_SCSIIO_DIR_NONE;
                   1053:                break;
                   1054:        }
                   1055:
                   1056:        if (link->quirks & SDEV_NOTAGS)
                   1057:                io->tagging = MPI_SCSIIO_ATTR_UNTAGGED;
                   1058:        else
                   1059:                io->tagging = MPI_SCSIIO_ATTR_SIMPLE_Q;
                   1060:
                   1061:        bcopy(xs->cmd, io->cdb, xs->cmdlen);
                   1062:
                   1063:        io->data_length = htole32(xs->datalen);
                   1064:
                   1065:        io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
                   1066:            ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
                   1067:
                   1068:        if (mpi_load_xs(ccb) != 0) {
                   1069:                xs->error = XS_DRIVER_STUFFUP;
                   1070:                s = splbio();
                   1071:                mpi_put_ccb(sc, ccb);
                   1072:                scsi_done(xs);
                   1073:                splx(s);
                   1074:                return (COMPLETE);
                   1075:        }
                   1076:
                   1077:        timeout_set(&xs->stimeout, mpi_timeout_xs, ccb);
                   1078:
                   1079:        if (xs->flags & SCSI_POLL) {
                   1080:                if (mpi_poll(sc, ccb, xs->timeout) != 0)
                   1081:                        xs->error = XS_DRIVER_STUFFUP;
                   1082:                return (COMPLETE);
                   1083:        }
                   1084:
                   1085:        s = splbio();
                   1086:        mpi_start(sc, ccb);
                   1087:        splx(s);
                   1088:        return (SUCCESSFULLY_QUEUED);
                   1089: }
                   1090:
                   1091: void
                   1092: mpi_scsi_cmd_done(struct mpi_ccb *ccb)
                   1093: {
                   1094:        struct mpi_softc                *sc = ccb->ccb_sc;
                   1095:        struct scsi_xfer                *xs = ccb->ccb_xs;
                   1096:        struct mpi_ccb_bundle           *mcb = ccb->ccb_cmd;
                   1097:        bus_dmamap_t                    dmap = ccb->ccb_dmamap;
                   1098:        struct mpi_msg_scsi_io_error    *sie;
                   1099:
                   1100:        if (xs->datalen != 0) {
                   1101:                bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
                   1102:                    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
                   1103:                    BUS_DMASYNC_POSTWRITE);
                   1104:
                   1105:                bus_dmamap_unload(sc->sc_dmat, dmap);
                   1106:        }
                   1107:
                   1108:        /* timeout_del */
                   1109:        xs->error = XS_NOERROR;
                   1110:        xs->resid = 0;
                   1111:        xs->flags |= ITSDONE;
                   1112:
                   1113:        if (ccb->ccb_rcb == NULL) {
                   1114:                /* no scsi error, we're ok so drop out early */
                   1115:                xs->status = SCSI_OK;
                   1116:                mpi_put_ccb(sc, ccb);
                   1117:                scsi_done(xs);
                   1118:                return;
                   1119:        }
                   1120:
                   1121:        sie = ccb->ccb_rcb->rcb_reply;
                   1122:
                   1123:        DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd_done xs cmd: 0x%02x len: %d "
                   1124:            "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
                   1125:            xs->flags);
                   1126:        DNPRINTF(MPI_D_CMD, "%s:  target_id: %d bus: %d msg_length: %d "
                   1127:            "function: 0x%02x\n", DEVNAME(sc), sie->target_id, sie->bus,
                   1128:            sie->msg_length, sie->function);
                   1129:        DNPRINTF(MPI_D_CMD, "%s:  cdb_length: %d sense_buf_length: %d "
                   1130:            "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length,
                   1131:            sie->sense_buf_len, sie->msg_flags);
                   1132:        DNPRINTF(MPI_D_CMD, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   1133:            letoh32(sie->msg_context));
                   1134:        DNPRINTF(MPI_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
                   1135:            "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
                   1136:            sie->scsi_state, letoh16(sie->ioc_status));
                   1137:        DNPRINTF(MPI_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   1138:            letoh32(sie->ioc_loginfo));
                   1139:        DNPRINTF(MPI_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
                   1140:            letoh32(sie->transfer_count));
                   1141:        DNPRINTF(MPI_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
                   1142:            letoh32(sie->sense_count));
                   1143:        DNPRINTF(MPI_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
                   1144:            letoh32(sie->response_info));
                   1145:        DNPRINTF(MPI_D_CMD, "%s:  tag: 0x%04x\n", DEVNAME(sc),
                   1146:            letoh16(sie->tag));
                   1147:
                   1148:        xs->status = sie->scsi_status;
                   1149:        switch (letoh16(sie->ioc_status)) {
                   1150:        case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
                   1151:                xs->resid = xs->datalen - letoh32(sie->transfer_count);
                   1152:                if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) {
                   1153:                        xs->error = XS_DRIVER_STUFFUP;
                   1154:                        break;
                   1155:                }
                   1156:                /* FALLTHROUGH */
                   1157:        case MPI_IOCSTATUS_SUCCESS:
                   1158:        case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
                   1159:                switch (xs->status) {
                   1160:                case SCSI_OK:
                   1161:                        xs->resid = 0;
                   1162:                        break;
                   1163:
                   1164:                case SCSI_CHECK:
                   1165:                        xs->error = XS_SENSE;
                   1166:                        break;
                   1167:
                   1168:                case SCSI_BUSY:
                   1169:                case SCSI_QUEUE_FULL:
                   1170:                        xs->error = XS_BUSY;
                   1171:                        break;
                   1172:
                   1173:                default:
                   1174:                        xs->error = XS_DRIVER_STUFFUP;
                   1175:                        break;
                   1176:                }
                   1177:                break;
                   1178:
                   1179:        case MPI_IOCSTATUS_BUSY:
                   1180:        case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
                   1181:                xs->error = XS_BUSY;
                   1182:                break;
                   1183:
                   1184:        case MPI_IOCSTATUS_SCSI_INVALID_BUS:
                   1185:        case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
                   1186:        case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
                   1187:                xs->error = XS_SELTIMEOUT;
                   1188:                break;
                   1189:
                   1190:        default:
                   1191:                xs->error = XS_DRIVER_STUFFUP;
                   1192:                break;
                   1193:        }
                   1194:
                   1195:        if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
                   1196:                bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense));
                   1197:
                   1198:        DNPRINTF(MPI_D_CMD, "%s:  xs err: 0x%02x status: %d\n", DEVNAME(sc),
                   1199:            xs->error, xs->status);
                   1200:
                   1201:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   1202:        mpi_put_ccb(sc, ccb);
                   1203:        scsi_done(xs);
                   1204: }
                   1205:
                   1206: void
                   1207: mpi_timeout_xs(void *arg)
                   1208: {
                   1209:        /* XXX */
                   1210: }
                   1211:
                   1212: int
                   1213: mpi_load_xs(struct mpi_ccb *ccb)
                   1214: {
                   1215:        struct mpi_softc                *sc = ccb->ccb_sc;
                   1216:        struct scsi_xfer                *xs = ccb->ccb_xs;
                   1217:        struct mpi_ccb_bundle           *mcb = ccb->ccb_cmd;
                   1218:        struct mpi_msg_scsi_io          *io = &mcb->mcb_io;
                   1219:        struct mpi_sge                  *sge, *nsge = &mcb->mcb_sgl[0];
                   1220:        struct mpi_sge                  *ce = NULL, *nce;
                   1221:        u_int64_t                       ce_dva;
                   1222:        bus_dmamap_t                    dmap = ccb->ccb_dmamap;
                   1223:        u_int32_t                       addr, flags;
                   1224:        int                             i, error;
                   1225:
                   1226:        if (xs->datalen == 0) {
                   1227:                nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
                   1228:                    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
                   1229:                return (0);
                   1230:        }
                   1231:
                   1232:        error = bus_dmamap_load(sc->sc_dmat, dmap,
                   1233:            xs->data, xs->datalen, NULL,
                   1234:            (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
                   1235:        if (error) {
                   1236:                printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
                   1237:                return (1);
                   1238:        }
                   1239:
                   1240:        flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64;
                   1241:        if (xs->flags & SCSI_DATA_OUT)
                   1242:                flags |= MPI_SGE_FL_DIR_OUT;
                   1243:
                   1244:        if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
                   1245:                ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
                   1246:                io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
                   1247:        }
                   1248:
                   1249:        for (i = 0; i < dmap->dm_nsegs; i++) {
                   1250:
                   1251:                if (nsge == ce) {
                   1252:                        nsge++;
                   1253:                        sge->sg_hdr |= htole32(MPI_SGE_FL_LAST);
                   1254:
                   1255:                        DNPRINTF(MPI_D_DMA, "%s:   - 0x%08x 0x%08x 0x%08x\n",
                   1256:                            DEVNAME(sc), sge->sg_hdr,
                   1257:                            sge->sg_hi_addr, sge->sg_lo_addr);
                   1258:
                   1259:                        if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
                   1260:                                nce = &nsge[sc->sc_chain_len - 1];
                   1261:                                addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
                   1262:                                addr = addr << 16 |
                   1263:                                    sizeof(struct mpi_sge) * sc->sc_chain_len;
                   1264:                        } else {
                   1265:                                nce = NULL;
                   1266:                                addr = sizeof(struct mpi_sge) *
                   1267:                                    (dmap->dm_nsegs - i);
                   1268:                        }
                   1269:
                   1270:                        ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN |
                   1271:                            MPI_SGE_FL_SIZE_64 | addr);
                   1272:
                   1273:                        ce_dva = ccb->ccb_cmd_dva +
                   1274:                            ((u_int8_t *)nsge - (u_int8_t *)mcb);
                   1275:
                   1276:                        addr = (u_int32_t)(ce_dva >> 32);
                   1277:                        ce->sg_hi_addr = htole32(addr);
                   1278:                        addr = (u_int32_t)ce_dva;
                   1279:                        ce->sg_lo_addr = htole32(addr);
                   1280:
                   1281:                        DNPRINTF(MPI_D_DMA, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
                   1282:                            DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
                   1283:                            ce->sg_lo_addr);
                   1284:
                   1285:                        ce = nce;
                   1286:                }
                   1287:
                   1288:                DNPRINTF(MPI_D_DMA, "%s:  %d: %d 0x%016llx\n", DEVNAME(sc),
                   1289:                    i, dmap->dm_segs[i].ds_len,
                   1290:                    (u_int64_t)dmap->dm_segs[i].ds_addr);
                   1291:
                   1292:                sge = nsge;
                   1293:
                   1294:                sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
                   1295:                addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
                   1296:                sge->sg_hi_addr = htole32(addr);
                   1297:                addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
                   1298:                sge->sg_lo_addr = htole32(addr);
                   1299:
                   1300:                DNPRINTF(MPI_D_DMA, "%s:  %d: 0x%08x 0x%08x 0x%08x\n",
                   1301:                    DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
                   1302:                    sge->sg_lo_addr);
                   1303:
                   1304:                nsge = sge + 1;
                   1305:        }
                   1306:
                   1307:        /* terminate list */
                   1308:        sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
                   1309:            MPI_SGE_FL_EOL);
                   1310:
                   1311:        bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
                   1312:            (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
                   1313:            BUS_DMASYNC_PREWRITE);
                   1314:
                   1315:        return (0);
                   1316: }
                   1317:
                   1318: void
                   1319: mpi_minphys(struct buf *bp)
                   1320: {
                   1321:        /* XXX */
                   1322:        if (bp->b_bcount > MAXPHYS)
                   1323:                bp->b_bcount = MAXPHYS;
                   1324:        minphys(bp);
                   1325: }
                   1326:
                   1327: int
                   1328: mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e)
                   1329: {
                   1330:        return (ENOTTY);
                   1331: }
                   1332:
                   1333: u_int32_t
                   1334: mpi_read(struct mpi_softc *sc, bus_size_t r)
                   1335: {
                   1336:        u_int32_t                       rv;
                   1337:
                   1338:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1339:            BUS_SPACE_BARRIER_READ);
                   1340:        rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
                   1341:
                   1342:        DNPRINTF(MPI_D_RW, "%s: mpi_read %#x %#x\n", DEVNAME(sc), r, rv);
                   1343:
                   1344:        return (rv);
                   1345: }
                   1346:
                   1347: void
                   1348: mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v)
                   1349: {
                   1350:        DNPRINTF(MPI_D_RW, "%s: mpi_write %#x %#x\n", DEVNAME(sc), r, v);
                   1351:
                   1352:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
                   1353:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1354:            BUS_SPACE_BARRIER_WRITE);
                   1355: }
                   1356:
                   1357: int
                   1358: mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
                   1359:     u_int32_t target)
                   1360: {
                   1361:        int                             i;
                   1362:
                   1363:        DNPRINTF(MPI_D_RW, "%s: mpi_wait_eq %#x %#x %#x\n", DEVNAME(sc), r,
                   1364:            mask, target);
                   1365:
                   1366:        for (i = 0; i < 10000; i++) {
                   1367:                if ((mpi_read(sc, r) & mask) == target)
                   1368:                        return (0);
                   1369:                delay(1000);
                   1370:        }
                   1371:
                   1372:        return (1);
                   1373: }
                   1374:
                   1375: int
                   1376: mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
                   1377:     u_int32_t target)
                   1378: {
                   1379:        int                             i;
                   1380:
                   1381:        DNPRINTF(MPI_D_RW, "%s: mpi_wait_ne %#x %#x %#x\n", DEVNAME(sc), r,
                   1382:            mask, target);
                   1383:
                   1384:        for (i = 0; i < 10000; i++) {
                   1385:                if ((mpi_read(sc, r) & mask) != target)
                   1386:                        return (0);
                   1387:                delay(1000);
                   1388:        }
                   1389:
                   1390:        return (1);
                   1391: }
                   1392:
                   1393: int
                   1394: mpi_init(struct mpi_softc *sc)
                   1395: {
                   1396:        u_int32_t                       db;
                   1397:        int                             i;
                   1398:
                   1399:        /* spin until the IOC leaves the RESET state */
                   1400:        if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
                   1401:            MPI_DOORBELL_STATE_RESET) != 0) {
                   1402:                DNPRINTF(MPI_D_MISC, "%s: mpi_init timeout waiting to leave "
                   1403:                    "reset state\n", DEVNAME(sc));
                   1404:                return (1);
                   1405:        }
                   1406:
                   1407:        /* check current ownership */
                   1408:        db = mpi_read_db(sc);
                   1409:        if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) {
                   1410:                DNPRINTF(MPI_D_MISC, "%s: mpi_init initialised by pci peer\n",
                   1411:                    DEVNAME(sc));
                   1412:                return (0);
                   1413:        }
                   1414:
                   1415:        for (i = 0; i < 5; i++) {
                   1416:                switch (db & MPI_DOORBELL_STATE) {
                   1417:                case MPI_DOORBELL_STATE_READY:
                   1418:                        DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is ready\n",
                   1419:                            DEVNAME(sc));
                   1420:                        return (0);
                   1421:
                   1422:                case MPI_DOORBELL_STATE_OPER:
                   1423:                case MPI_DOORBELL_STATE_FAULT:
                   1424:                        DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is being "
                   1425:                            "reset\n" , DEVNAME(sc));
                   1426:                        if (mpi_reset_soft(sc) != 0)
                   1427:                                mpi_reset_hard(sc);
                   1428:                        break;
                   1429:
                   1430:                case MPI_DOORBELL_STATE_RESET:
                   1431:                        DNPRINTF(MPI_D_MISC, "%s: mpi_init waiting to come "
                   1432:                            "out of reset\n", DEVNAME(sc));
                   1433:                        if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
                   1434:                            MPI_DOORBELL_STATE_RESET) != 0)
                   1435:                                return (1);
                   1436:                        break;
                   1437:                }
                   1438:                db = mpi_read_db(sc);
                   1439:        }
                   1440:
                   1441:        return (1);
                   1442: }
                   1443:
                   1444: int
                   1445: mpi_reset_soft(struct mpi_softc *sc)
                   1446: {
                   1447:        DNPRINTF(MPI_D_MISC, "%s: mpi_reset_soft\n", DEVNAME(sc));
                   1448:
                   1449:        if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
                   1450:                return (1);
                   1451:
                   1452:        mpi_write_db(sc,
                   1453:            MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET));
                   1454:        if (mpi_wait_eq(sc, MPI_INTR_STATUS,
                   1455:            MPI_INTR_STATUS_IOCDOORBELL, 0) != 0)
                   1456:                return (1);
                   1457:
                   1458:        if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
                   1459:            MPI_DOORBELL_STATE_READY) != 0)
                   1460:                return (1);
                   1461:
                   1462:        return (0);
                   1463: }
                   1464:
                   1465: int
                   1466: mpi_reset_hard(struct mpi_softc *sc)
                   1467: {
                   1468:        DNPRINTF(MPI_D_MISC, "%s: mpi_reset_hard\n", DEVNAME(sc));
                   1469:
                   1470:        /* enable diagnostic register */
                   1471:        mpi_write(sc, MPI_WRITESEQ, 0xff);
                   1472:        mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1);
                   1473:        mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2);
                   1474:        mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3);
                   1475:        mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4);
                   1476:        mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5);
                   1477:
                   1478:        /* reset ioc */
                   1479:        mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER);
                   1480:
                   1481:        delay(10000);
                   1482:
                   1483:        /* disable diagnostic register */
                   1484:        mpi_write(sc, MPI_WRITESEQ, 0xff);
                   1485:
                   1486:        /* restore pci bits? */
                   1487:
                   1488:        /* firmware bits? */
                   1489:        return (0);
                   1490: }
                   1491:
                   1492: int
                   1493: mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords)
                   1494: {
                   1495:        u_int32_t                               *query = buf;
                   1496:        int                                     i;
                   1497:
                   1498:        /* make sure the doorbell is not in use. */
                   1499:        if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
                   1500:                return (1);
                   1501:
                   1502:        /* clear pending doorbell interrupts */
                   1503:        if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL)
                   1504:                mpi_write_intr(sc, 0);
                   1505:
                   1506:        /*
                   1507:         * first write the doorbell with the handshake function and the
                   1508:         * dword count.
                   1509:         */
                   1510:        mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) |
                   1511:            MPI_DOORBELL_DWORDS(dwords));
                   1512:
                   1513:        /*
                   1514:         * the doorbell used bit will be set because a doorbell function has
                   1515:         * started. Wait for the interrupt and then ack it.
                   1516:         */
                   1517:        if (mpi_wait_db_int(sc) != 0)
                   1518:                return (1);
                   1519:        mpi_write_intr(sc, 0);
                   1520:
                   1521:        /* poll for the acknowledgement. */
                   1522:        if (mpi_wait_db_ack(sc) != 0)
                   1523:                return (1);
                   1524:
                   1525:        /* write the query through the doorbell. */
                   1526:        for (i = 0; i < dwords; i++) {
                   1527:                mpi_write_db(sc, htole32(query[i]));
                   1528:                if (mpi_wait_db_ack(sc) != 0)
                   1529:                        return (1);
                   1530:        }
                   1531:
                   1532:        return (0);
                   1533: }
                   1534:
                   1535: int
                   1536: mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword)
                   1537: {
                   1538:        u_int16_t                               *words = (u_int16_t *)dword;
                   1539:        int                                     i;
                   1540:
                   1541:        for (i = 0; i < 2; i++) {
                   1542:                if (mpi_wait_db_int(sc) != 0)
                   1543:                        return (1);
                   1544:                words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK);
                   1545:                mpi_write_intr(sc, 0);
                   1546:        }
                   1547:
                   1548:        return (0);
                   1549: }
                   1550:
                   1551: int
                   1552: mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords)
                   1553: {
                   1554:        struct mpi_msg_reply                    *reply = buf;
                   1555:        u_int32_t                               *dbuf = buf, dummy;
                   1556:        int                                     i;
                   1557:
                   1558:        /* get the first dword so we can read the length out of the header. */
                   1559:        if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0)
                   1560:                return (1);
                   1561:
                   1562:        DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dwords: %d reply: %d\n",
                   1563:            DEVNAME(sc), dwords, reply->msg_length);
                   1564:
                   1565:        /*
                   1566:         * the total length, in dwords, is in the message length field of the
                   1567:         * reply header.
                   1568:         */
                   1569:        for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
                   1570:                if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0)
                   1571:                        return (1);
                   1572:        }
                   1573:
                   1574:        /* if there's extra stuff to come off the ioc, discard it */
                   1575:        while (i++ < reply->msg_length) {
                   1576:                if (mpi_handshake_recv_dword(sc, &dummy) != 0)
                   1577:                        return (1);
                   1578:                DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dummy read: "
                   1579:                    "0x%08x\n", DEVNAME(sc), dummy);
                   1580:        }
                   1581:
                   1582:        /* wait for the doorbell used bit to be reset and clear the intr */
                   1583:        if (mpi_wait_db_int(sc) != 0)
                   1584:                return (1);
                   1585:        mpi_write_intr(sc, 0);
                   1586:
                   1587:        return (0);
                   1588: }
                   1589:
                   1590: void
                   1591: mpi_empty_done(struct mpi_ccb *ccb)
                   1592: {
                   1593:        /* nothing to do */
                   1594: }
                   1595:
                   1596: int
                   1597: mpi_iocfacts(struct mpi_softc *sc)
                   1598: {
                   1599:        struct mpi_msg_iocfacts_request         ifq;
                   1600:        struct mpi_msg_iocfacts_reply           ifp;
                   1601:
                   1602:        DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts\n", DEVNAME(sc));
                   1603:
                   1604:        bzero(&ifq, sizeof(ifq));
                   1605:        bzero(&ifp, sizeof(ifp));
                   1606:
                   1607:        ifq.function = MPI_FUNCTION_IOC_FACTS;
                   1608:        ifq.chain_offset = 0;
                   1609:        ifq.msg_flags = 0;
                   1610:        ifq.msg_context = htole32(0xdeadbeef);
                   1611:
                   1612:        if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
                   1613:                DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts send failed\n",
                   1614:                    DEVNAME(sc));
                   1615:                return (1);
                   1616:        }
                   1617:
                   1618:        if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
                   1619:                DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts recv failed\n",
                   1620:                    DEVNAME(sc));
                   1621:                return (1);
                   1622:        }
                   1623:
                   1624:        DNPRINTF(MPI_D_MISC, "%s:  func: 0x%02x len: %d msgver: %d.%d\n",
                   1625:            DEVNAME(sc), ifp.function, ifp.msg_length,
                   1626:            ifp.msg_version_maj, ifp.msg_version_min);
                   1627:        DNPRINTF(MPI_D_MISC, "%s:  msgflags: 0x%02x iocnumber: 0x%02x "
                   1628:            "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
                   1629:            ifp.ioc_number, ifp.header_version_maj,
                   1630:            ifp.header_version_min);
                   1631:        DNPRINTF(MPI_D_MISC, "%s:  message context: 0x%08x\n", DEVNAME(sc),
                   1632:            letoh32(ifp.msg_context));
                   1633:        DNPRINTF(MPI_D_MISC, "%s:  iocstatus: 0x%04x ioexcept: 0x%04x\n",
                   1634:            DEVNAME(sc), letoh16(ifp.ioc_status),
                   1635:            letoh16(ifp.ioc_exceptions));
                   1636:        DNPRINTF(MPI_D_MISC, "%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
                   1637:            letoh32(ifp.ioc_loginfo));
                   1638:        DNPRINTF(MPI_D_MISC, "%s:  flags: 0x%02x blocksize: %d whoinit: 0x%02x "
                   1639:            "maxchdepth: %d\n", DEVNAME(sc), ifp.flags,
                   1640:            ifp.block_size, ifp.whoinit, ifp.max_chain_depth);
                   1641:        DNPRINTF(MPI_D_MISC, "%s:  reqfrsize: %d replyqdepth: %d\n",
                   1642:            DEVNAME(sc), letoh16(ifp.request_frame_size),
                   1643:            letoh16(ifp.reply_queue_depth));
                   1644:        DNPRINTF(MPI_D_MISC, "%s:  productid: 0x%04x\n", DEVNAME(sc),
                   1645:            letoh16(ifp.product_id));
                   1646:        DNPRINTF(MPI_D_MISC, "%s:  hostmfahiaddr: 0x%08x\n", DEVNAME(sc),
                   1647:            letoh32(ifp.current_host_mfa_hi_addr));
                   1648:        DNPRINTF(MPI_D_MISC, "%s:  event_state: 0x%02x number_of_ports: %d "
                   1649:            "global_credits: %d\n",
                   1650:            DEVNAME(sc), ifp.event_state, ifp.number_of_ports,
                   1651:            letoh16(ifp.global_credits));
                   1652:        DNPRINTF(MPI_D_MISC, "%s:  sensebufhiaddr: 0x%08x\n", DEVNAME(sc),
                   1653:            letoh32(ifp.current_sense_buffer_hi_addr));
                   1654:        DNPRINTF(MPI_D_MISC, "%s:  maxbus: %d maxdev: %d replyfrsize: %d\n",
                   1655:            DEVNAME(sc), ifp.max_buses, ifp.max_devices,
                   1656:            letoh16(ifp.current_reply_frame_size));
                   1657:        DNPRINTF(MPI_D_MISC, "%s:  fw_image_size: %d\n", DEVNAME(sc),
                   1658:            letoh32(ifp.fw_image_size));
                   1659:        DNPRINTF(MPI_D_MISC, "%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
                   1660:            letoh32(ifp.ioc_capabilities));
                   1661:        DNPRINTF(MPI_D_MISC, "%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
                   1662:            "fw_version_dev: 0x%02x\n", DEVNAME(sc),
                   1663:            ifp.fw_version_maj, ifp.fw_version_min,
                   1664:            ifp.fw_version_unit, ifp.fw_version_dev);
                   1665:        DNPRINTF(MPI_D_MISC, "%s:  hi_priority_queue_depth: 0x%04x\n",
                   1666:            DEVNAME(sc), letoh16(ifp.hi_priority_queue_depth));
                   1667:        DNPRINTF(MPI_D_MISC, "%s:  host_page_buffer_sge: hdr: 0x%08x "
                   1668:            "addr 0x%08x %08x\n", DEVNAME(sc),
                   1669:            letoh32(ifp.host_page_buffer_sge.sg_hdr),
                   1670:            letoh32(ifp.host_page_buffer_sge.sg_hi_addr),
                   1671:            letoh32(ifp.host_page_buffer_sge.sg_lo_addr));
                   1672:
                   1673:        sc->sc_maxcmds = letoh16(ifp.global_credits);
                   1674:        sc->sc_maxchdepth = ifp.max_chain_depth;
                   1675:        sc->sc_ioc_number = ifp.ioc_number;
                   1676:        if (sc->sc_flags & MPI_F_SPI)
                   1677:                sc->sc_buswidth = 16;
                   1678:        else
                   1679:                sc->sc_buswidth =
                   1680:                    (ifp.max_devices == 0) ? 256 : ifp.max_devices;
                   1681:        if (ifp.flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
                   1682:                sc->sc_fw_len = letoh32(ifp.fw_image_size);
                   1683:
                   1684:        /*
                   1685:         * you can fit sg elements on the end of the io cmd if they fit in the
                   1686:         * request frame size.
                   1687:         */
                   1688:        sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) -
                   1689:            sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge);
                   1690:        DNPRINTF(MPI_D_MISC, "%s:   first sgl len: %d\n", DEVNAME(sc),
                   1691:            sc->sc_first_sgl_len);
                   1692:
                   1693:        sc->sc_chain_len = (letoh16(ifp.request_frame_size) * 4) /
                   1694:            sizeof(struct mpi_sge);
                   1695:        DNPRINTF(MPI_D_MISC, "%s:   chain len: %d\n", DEVNAME(sc),
                   1696:            sc->sc_chain_len);
                   1697:
                   1698:        /* the sgl tailing the io cmd loses an entry to the chain element. */
                   1699:        sc->sc_max_sgl_len = MPI_MAX_SGL - 1;
                   1700:        /* the sgl chains lose an entry for each chain element */
                   1701:        sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) /
                   1702:            sc->sc_chain_len;
                   1703:        DNPRINTF(MPI_D_MISC, "%s:   max sgl len: %d\n", DEVNAME(sc),
                   1704:            sc->sc_max_sgl_len);
                   1705:
                   1706:        /* XXX we're ignoring the max chain depth */
                   1707:
                   1708:        return (0);
                   1709: }
                   1710:
                   1711: int
                   1712: mpi_iocinit(struct mpi_softc *sc)
                   1713: {
                   1714:        struct mpi_msg_iocinit_request          iiq;
                   1715:        struct mpi_msg_iocinit_reply            iip;
                   1716:        u_int32_t                               hi_addr;
                   1717:
                   1718:        DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit\n", DEVNAME(sc));
                   1719:
                   1720:        bzero(&iiq, sizeof(iiq));
                   1721:        bzero(&iip, sizeof(iip));
                   1722:
                   1723:        iiq.function = MPI_FUNCTION_IOC_INIT;
                   1724:        iiq.whoinit = MPI_WHOINIT_HOST_DRIVER;
                   1725:
                   1726:        iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth;
                   1727:        iiq.max_buses = 1;
                   1728:
                   1729:        iiq.msg_context = htole32(0xd00fd00f);
                   1730:
                   1731:        iiq.reply_frame_size = htole16(MPI_REPLY_SIZE);
                   1732:
                   1733:        hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32);
                   1734:        iiq.host_mfa_hi_addr = htole32(hi_addr);
                   1735:        iiq.sense_buffer_hi_addr = htole32(hi_addr);
                   1736:
                   1737:        hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32);
                   1738:        iiq.reply_fifo_host_signalling_addr = htole32(hi_addr);
                   1739:
                   1740:        iiq.msg_version_maj = 0x01;
                   1741:        iiq.msg_version_min = 0x02;
                   1742:
                   1743:        iiq.hdr_version_unit = 0x0d;
                   1744:        iiq.hdr_version_dev = 0x00;
                   1745:
                   1746:        if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
                   1747:                DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit send failed\n",
                   1748:                    DEVNAME(sc));
                   1749:                return (1);
                   1750:        }
                   1751:
                   1752:        if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
                   1753:                DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit recv failed\n",
                   1754:                    DEVNAME(sc));
                   1755:                return (1);
                   1756:        }
                   1757:
                   1758:        DNPRINTF(MPI_D_MISC, "%s:  function: 0x%02x msg_length: %d "
                   1759:            "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
                   1760:            iip.msg_length, iip.whoinit);
                   1761:        DNPRINTF(MPI_D_MISC, "%s:  msg_flags: 0x%02x max_buses: %d "
                   1762:            "max_devices: %d flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags,
                   1763:            iip.max_buses, iip.max_devices, iip.flags);
                   1764:        DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   1765:            letoh32(iip.msg_context));
                   1766:        DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
                   1767:            letoh16(iip.ioc_status));
                   1768:        DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   1769:            letoh32(iip.ioc_loginfo));
                   1770:
                   1771:        return (0);
                   1772: }
                   1773:
                   1774: int
                   1775: mpi_portfacts(struct mpi_softc *sc)
                   1776: {
                   1777:        struct mpi_ccb                          *ccb;
                   1778:        struct mpi_msg_portfacts_request        *pfq;
                   1779:        volatile struct mpi_msg_portfacts_reply *pfp;
                   1780:        int                                     s, rv = 1;
                   1781:
                   1782:        DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts\n", DEVNAME(sc));
                   1783:
                   1784:        s = splbio();
                   1785:        ccb = mpi_get_ccb(sc);
                   1786:        splx(s);
                   1787:        if (ccb == NULL) {
                   1788:                DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts ccb_get\n",
                   1789:                    DEVNAME(sc));
                   1790:                return (rv);
                   1791:        }
                   1792:
                   1793:        ccb->ccb_done = mpi_empty_done;
                   1794:        pfq = ccb->ccb_cmd;
                   1795:
                   1796:        pfq->function = MPI_FUNCTION_PORT_FACTS;
                   1797:        pfq->chain_offset = 0;
                   1798:        pfq->msg_flags = 0;
                   1799:        pfq->port_number = 0;
                   1800:        pfq->msg_context = htole32(ccb->ccb_id);
                   1801:
                   1802:        if (mpi_poll(sc, ccb, 50000) != 0) {
                   1803:                DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts poll\n", DEVNAME(sc));
                   1804:                goto err;
                   1805:        }
                   1806:
                   1807:        if (ccb->ccb_rcb == NULL) {
                   1808:                DNPRINTF(MPI_D_MISC, "%s: empty portfacts reply\n",
                   1809:                    DEVNAME(sc));
                   1810:                goto err;
                   1811:        }
                   1812:        pfp = ccb->ccb_rcb->rcb_reply;
                   1813:
                   1814:        DNPRINTF(MPI_D_MISC, "%s:  function: 0x%02x msg_length: %d\n",
                   1815:            DEVNAME(sc), pfp->function, pfp->msg_length);
                   1816:        DNPRINTF(MPI_D_MISC, "%s:  msg_flags: 0x%02x port_number: %d\n",
                   1817:            DEVNAME(sc), pfp->msg_flags, pfp->port_number);
                   1818:        DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   1819:            letoh32(pfp->msg_context));
                   1820:        DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
                   1821:            letoh16(pfp->ioc_status));
                   1822:        DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   1823:            letoh32(pfp->ioc_loginfo));
                   1824:        DNPRINTF(MPI_D_MISC, "%s:  max_devices: %d port_type: 0x%02x\n",
                   1825:            DEVNAME(sc), letoh16(pfp->max_devices), pfp->port_type);
                   1826:        DNPRINTF(MPI_D_MISC, "%s:  protocol_flags: 0x%04x port_scsi_id: %d\n",
                   1827:            DEVNAME(sc), letoh16(pfp->protocol_flags),
                   1828:            letoh16(pfp->port_scsi_id));
                   1829:        DNPRINTF(MPI_D_MISC, "%s:  max_persistent_ids: %d "
                   1830:            "max_posted_cmd_buffers: %d\n", DEVNAME(sc),
                   1831:            letoh16(pfp->max_persistent_ids),
                   1832:            letoh16(pfp->max_posted_cmd_buffers));
                   1833:        DNPRINTF(MPI_D_MISC, "%s:  max_lan_buckets: %d\n", DEVNAME(sc),
                   1834:            letoh16(pfp->max_lan_buckets));
                   1835:
                   1836:        sc->sc_porttype = pfp->port_type;
                   1837:        sc->sc_target = letoh16(pfp->port_scsi_id);
                   1838:
                   1839:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   1840:        rv = 0;
                   1841: err:
                   1842:        mpi_put_ccb(sc, ccb);
                   1843:
                   1844:        return (rv);
                   1845: }
                   1846:
                   1847: int
                   1848: mpi_eventnotify(struct mpi_softc *sc)
                   1849: {
                   1850:        struct mpi_ccb                          *ccb;
                   1851:        struct mpi_msg_event_request            *enq;
                   1852:        int                                     s;
                   1853:
                   1854:        s = splbio();
                   1855:        ccb = mpi_get_ccb(sc);
                   1856:        splx(s);
                   1857:        if (ccb == NULL) {
                   1858:                DNPRINTF(MPI_D_MISC, "%s: mpi_eventnotify ccb_get\n",
                   1859:                    DEVNAME(sc));
                   1860:                return (1);
                   1861:        }
                   1862:
                   1863:        ccb->ccb_done = mpi_eventnotify_done;
                   1864:        enq = ccb->ccb_cmd;
                   1865:
                   1866:        enq->function = MPI_FUNCTION_EVENT_NOTIFICATION;
                   1867:        enq->chain_offset = 0;
                   1868:        enq->event_switch = MPI_EVENT_SWITCH_ON;
                   1869:        enq->msg_context = htole32(ccb->ccb_id);
                   1870:
                   1871:        mpi_start(sc, ccb);
                   1872:        return (0);
                   1873: }
                   1874:
                   1875: void
                   1876: mpi_eventnotify_done(struct mpi_ccb *ccb)
                   1877: {
                   1878:        struct mpi_softc                        *sc = ccb->ccb_sc;
                   1879:        struct mpi_msg_event_reply              *enp = ccb->ccb_rcb->rcb_reply;
                   1880:        int                                     deferred = 0;
                   1881:
                   1882:        DNPRINTF(MPI_D_EVT, "%s: mpi_eventnotify_done\n", DEVNAME(sc));
                   1883:
                   1884:        DNPRINTF(MPI_D_EVT, "%s:  function: 0x%02x msg_length: %d "
                   1885:            "data_length: %d\n", DEVNAME(sc), enp->function, enp->msg_length,
                   1886:            letoh16(enp->data_length));
                   1887:        DNPRINTF(MPI_D_EVT, "%s:  ack_required: %d msg_flags 0x%02x\n",
                   1888:            DEVNAME(sc), enp->ack_required, enp->msg_flags);
                   1889:        DNPRINTF(MPI_D_EVT, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   1890:            letoh32(enp->msg_context));
                   1891:        DNPRINTF(MPI_D_EVT, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
                   1892:            letoh16(enp->ioc_status));
                   1893:        DNPRINTF(MPI_D_EVT, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   1894:            letoh32(enp->ioc_loginfo));
                   1895:        DNPRINTF(MPI_D_EVT, "%s:  event: 0x%08x\n", DEVNAME(sc),
                   1896:            letoh32(enp->event));
                   1897:        DNPRINTF(MPI_D_EVT, "%s:  event_context: 0x%08x\n", DEVNAME(sc),
                   1898:            letoh32(enp->event_context));
                   1899:
                   1900:        switch (letoh32(enp->event)) {
                   1901:        /* ignore these */
                   1902:        case MPI_EVENT_EVENT_CHANGE:
                   1903:        case MPI_EVENT_SAS_PHY_LINK_STATUS:
                   1904:                break;
                   1905:
                   1906:        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
                   1907:                if (sc->sc_scsibus == NULL)
                   1908:                        break;
                   1909:
                   1910:                if (scsi_task(mpi_evt_sas, sc, ccb->ccb_rcb, 0) != 0) {
                   1911:                        printf("%s: unable to run SAS device status change\n",
                   1912:                            DEVNAME(sc));
                   1913:                        break;
                   1914:                }
                   1915:                deferred = 1;
                   1916:                break;
                   1917:
                   1918:        default:
                   1919:                printf("%s: unhandled event 0x%02x\n", DEVNAME(sc),
                   1920:                    letoh32(enp->event));
                   1921:                break;
                   1922:        }
                   1923:
                   1924:        if (!deferred) {
                   1925:                if (enp->ack_required)
                   1926:                        mpi_eventack(sc, enp);
                   1927:                mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   1928:        }
                   1929:
                   1930:        if ((enp->msg_flags & MPI_EVENT_FLAGS_REPLY_KEPT) == 0) {
                   1931:                /* XXX this shouldnt happen till shutdown */
                   1932:                mpi_put_ccb(sc, ccb);
                   1933:        }
                   1934: }
                   1935:
                   1936: void
                   1937: mpi_evt_sas(void *xsc, void *arg)
                   1938: {
                   1939:        struct mpi_softc                        *sc = xsc;
                   1940:        struct mpi_rcb                          *rcb = arg;
                   1941:        struct mpi_msg_event_reply              *enp = rcb->rcb_reply;
                   1942:        struct mpi_evt_sas_change               *ch;
                   1943:        u_int8_t                                *data;
                   1944:        int                                     s;
                   1945:
                   1946:        data = rcb->rcb_reply;
                   1947:        data += sizeof(struct mpi_msg_event_reply);
                   1948:        ch = (struct mpi_evt_sas_change *)data;
                   1949:
                   1950:        if (ch->bus != 0)
                   1951:                return;
                   1952:
                   1953:        switch (ch->reason) {
                   1954:        case MPI_EVT_SASCH_REASON_ADDED:
                   1955:        case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED:
                   1956:                scsi_probe_target(sc->sc_scsibus, ch->target);
                   1957:                break;
                   1958:
                   1959:        case MPI_EVT_SASCH_REASON_NOT_RESPONDING:
                   1960:                scsi_detach_target(sc->sc_scsibus, ch->target, DETACH_FORCE);
                   1961:                break;
                   1962:
                   1963:        case MPI_EVT_SASCH_REASON_SMART_DATA:
                   1964:        case MPI_EVT_SASCH_REASON_UNSUPPORTED:
                   1965:        case MPI_EVT_SASCH_REASON_INTERNAL_RESET:
                   1966:                break;
                   1967:        default:
                   1968:                printf("%s: unknown reason for SAS device status change: "
                   1969:                    "0x%02x\n", DEVNAME(sc), ch->reason);
                   1970:                break;
                   1971:        }
                   1972:
                   1973:        s = splbio();
                   1974:        mpi_push_reply(sc, rcb->rcb_reply_dva);
                   1975:        if (enp->ack_required)
                   1976:                mpi_eventack(sc, enp);
                   1977:        splx(s);
                   1978: }
                   1979:
                   1980: void
                   1981: mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp)
                   1982: {
                   1983:        struct mpi_ccb                          *ccb;
                   1984:        struct mpi_msg_eventack_request         *eaq;
                   1985:
                   1986:        ccb = mpi_get_ccb(sc);
                   1987:        if (ccb == NULL) {
                   1988:                DNPRINTF(MPI_D_EVT, "%s: mpi_eventack ccb_get\n", DEVNAME(sc));
                   1989:                return;
                   1990:        }
                   1991:
                   1992:        ccb->ccb_done = mpi_eventack_done;
                   1993:        eaq = ccb->ccb_cmd;
                   1994:
                   1995:        eaq->function = MPI_FUNCTION_EVENT_ACK;
                   1996:        eaq->msg_context = htole32(ccb->ccb_id);
                   1997:
                   1998:        eaq->event = enp->event;
                   1999:        eaq->event_context = enp->event_context;
                   2000:
                   2001:        mpi_start(sc, ccb);
                   2002:        return;
                   2003: }
                   2004:
                   2005: void
                   2006: mpi_eventack_done(struct mpi_ccb *ccb)
                   2007: {
                   2008:        struct mpi_softc                        *sc = ccb->ccb_sc;
                   2009:
                   2010:        DNPRINTF(MPI_D_EVT, "%s: event ack done\n", DEVNAME(sc));
                   2011:
                   2012:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   2013:        mpi_put_ccb(sc, ccb);
                   2014: }
                   2015:
                   2016: int
                   2017: mpi_portenable(struct mpi_softc *sc)
                   2018: {
                   2019:        struct mpi_ccb                          *ccb;
                   2020:        struct mpi_msg_portenable_request       *peq;
                   2021:        struct mpi_msg_portenable_repy          *pep;
                   2022:        int                                     s;
                   2023:
                   2024:        DNPRINTF(MPI_D_MISC, "%s: mpi_portenable\n", DEVNAME(sc));
                   2025:
                   2026:        s = splbio();
                   2027:        ccb = mpi_get_ccb(sc);
                   2028:        splx(s);
                   2029:        if (ccb == NULL) {
                   2030:                DNPRINTF(MPI_D_MISC, "%s: mpi_portenable ccb_get\n",
                   2031:                    DEVNAME(sc));
                   2032:                return (1);
                   2033:        }
                   2034:
                   2035:        ccb->ccb_done = mpi_empty_done;
                   2036:        peq = ccb->ccb_cmd;
                   2037:
                   2038:        peq->function = MPI_FUNCTION_PORT_ENABLE;
                   2039:        peq->port_number = 0;
                   2040:        peq->msg_context = htole32(ccb->ccb_id);
                   2041:
                   2042:        if (mpi_poll(sc, ccb, 50000) != 0) {
                   2043:                DNPRINTF(MPI_D_MISC, "%s: mpi_portenable poll\n", DEVNAME(sc));
                   2044:                return (1);
                   2045:        }
                   2046:
                   2047:        if (ccb->ccb_rcb == NULL) {
                   2048:                DNPRINTF(MPI_D_MISC, "%s: empty portenable reply\n",
                   2049:                    DEVNAME(sc));
                   2050:                return (1);
                   2051:        }
                   2052:        pep = ccb->ccb_rcb->rcb_reply;
                   2053:
                   2054:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   2055:        mpi_put_ccb(sc, ccb);
                   2056:
                   2057:        return (0);
                   2058: }
                   2059:
                   2060: int
                   2061: mpi_fwupload(struct mpi_softc *sc)
                   2062: {
                   2063:        struct mpi_ccb                          *ccb;
                   2064:        struct {
                   2065:                struct mpi_msg_fwupload_request         req;
                   2066:                struct mpi_sge                          sge;
                   2067:        } __packed                              *bundle;
                   2068:        struct mpi_msg_fwupload_reply           *upp;
                   2069:        u_int64_t                               addr;
                   2070:        int                                     s;
                   2071:        int                                     rv = 0;
                   2072:
                   2073:        if (sc->sc_fw_len == 0)
                   2074:                return (0);
                   2075:
                   2076:        DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload\n", DEVNAME(sc));
                   2077:
                   2078:        sc->sc_fw = mpi_dmamem_alloc(sc, sc->sc_fw_len);
                   2079:        if (sc->sc_fw == NULL) {
                   2080:                DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload unable to allocate %d\n",
                   2081:                    DEVNAME(sc), sc->sc_fw_len);
                   2082:                return (1);
                   2083:        }
                   2084:
                   2085:        s = splbio();
                   2086:        ccb = mpi_get_ccb(sc);
                   2087:        splx(s);
                   2088:        if (ccb == NULL) {
                   2089:                DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload ccb_get\n",
                   2090:                    DEVNAME(sc));
                   2091:                goto err;
                   2092:        }
                   2093:
                   2094:        ccb->ccb_done = mpi_empty_done;
                   2095:        bundle = ccb->ccb_cmd;
                   2096:
                   2097:        bundle->req.function = MPI_FUNCTION_FW_UPLOAD;
                   2098:        bundle->req.msg_context = htole32(ccb->ccb_id);
                   2099:
                   2100:        bundle->req.image_type = MPI_FWUPLOAD_IMAGETYPE_IOC_FW;
                   2101:
                   2102:        bundle->req.tce.details_length = 12;
                   2103:        bundle->req.tce.image_size = htole32(sc->sc_fw_len);
                   2104:
                   2105:        bundle->sge.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
                   2106:            MPI_SGE_FL_SIZE_64 | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
                   2107:            MPI_SGE_FL_EOL | (u_int32_t)sc->sc_fw_len);
                   2108:        addr = MPI_DMA_DVA(sc->sc_fw);
                   2109:        bundle->sge.sg_hi_addr = htole32((u_int32_t)(addr >> 32));
                   2110:        bundle->sge.sg_lo_addr = htole32((u_int32_t)addr);
                   2111:
                   2112:        if (mpi_poll(sc, ccb, 50000) != 0) {
                   2113:                DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
                   2114:                goto err;
                   2115:        }
                   2116:
                   2117:        if (ccb->ccb_rcb == NULL)
                   2118:                panic("%s: unable to do fw upload\n", DEVNAME(sc));
                   2119:        upp = ccb->ccb_rcb->rcb_reply;
                   2120:
                   2121:        if (letoh16(upp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
                   2122:                rv = 1;
                   2123:
                   2124:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   2125:        mpi_put_ccb(sc, ccb);
                   2126:
                   2127:        return (rv);
                   2128:
                   2129: err:
                   2130:        mpi_dmamem_free(sc, sc->sc_fw);
                   2131:        return (1);
                   2132: }
                   2133:
                   2134: void
                   2135: mpi_get_raid(struct mpi_softc *sc)
                   2136: {
                   2137:        struct mpi_cfg_hdr              hdr;
                   2138:        struct mpi_cfg_ioc_pg2          *vol_page;
                   2139:        struct mpi_cfg_raid_vol         *vol_list, *vol;
                   2140:        size_t                          pagelen;
                   2141:        u_int32_t                       capabilities;
                   2142:        struct scsi_link                *link;
                   2143:        int                             i;
                   2144:
                   2145:        DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid\n", DEVNAME(sc));
                   2146:
                   2147:        if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0, &hdr) != 0) {
                   2148:                DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch header"
                   2149:                    "for IOC page 2\n", DEVNAME(sc));
                   2150:                return;
                   2151:        }
                   2152:
                   2153:        pagelen = hdr.page_length * 4; /* dwords to bytes */
                   2154:        vol_page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
                   2155:        if (vol_page == NULL) {
                   2156:                DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to allocate "
                   2157:                    "space for ioc config page 2\n", DEVNAME(sc));
                   2158:                return;
                   2159:        }
                   2160:        vol_list = (struct mpi_cfg_raid_vol *)(vol_page + 1);
                   2161:
                   2162:        if (mpi_cfg_page(sc, 0, &hdr, 1, vol_page, pagelen) != 0) {
                   2163:                DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch IOC "
                   2164:                    "page 2\n", DEVNAME(sc));
                   2165:                goto out;
                   2166:        }
                   2167:
                   2168:        capabilities = letoh32(vol_page->capabilities);
                   2169:
                   2170:        DNPRINTF(MPI_D_RAID, "%s:  capabilities: 0x08%x\n", DEVNAME(sc),
                   2171:            letoh32(vol_page->capabilities));
                   2172:        DNPRINTF(MPI_D_RAID, "%s:  active_vols: %d max_vols: %d "
                   2173:            "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc),
                   2174:            vol_page->active_vols, vol_page->max_vols,
                   2175:            vol_page->active_physdisks, vol_page->max_physdisks);
                   2176:
                   2177:        /* don't walk list if there are no RAID capability */
                   2178:        if (capabilities == 0xdeadbeef) {
                   2179:                printf("%s: deadbeef in raid configuration\n", DEVNAME(sc));
                   2180:                goto out;
                   2181:        }
                   2182:
                   2183:        if ((capabilities & MPI_CFG_IOC_2_CAPABILITIES_RAID) == 0 ||
                   2184:            (vol_page->active_vols == 0))
                   2185:                goto out;
                   2186:
                   2187:        sc->sc_flags |= MPI_F_RAID;
                   2188:
                   2189:        for (i = 0; i < vol_page->active_vols; i++) {
                   2190:                vol = &vol_list[i];
                   2191:
                   2192:                DNPRINTF(MPI_D_RAID, "%s:   id: %d bus: %d ioc: %d pg: %d\n",
                   2193:                    DEVNAME(sc), vol->vol_id, vol->vol_bus, vol->vol_ioc,
                   2194:                    vol->vol_page);
                   2195:                DNPRINTF(MPI_D_RAID, "%s:   type: 0x%02x flags: 0x%02x\n",
                   2196:                    DEVNAME(sc), vol->vol_type, vol->flags);
                   2197:
                   2198:                if (vol->vol_ioc != sc->sc_ioc_number || vol->vol_bus != 0)
                   2199:                        continue;
                   2200:
                   2201:                link = sc->sc_scsibus->sc_link[vol->vol_id][0];
                   2202:                if (link == NULL)
                   2203:                        continue;
                   2204:
                   2205:                link->flags |= SDEV_VIRTUAL;
                   2206:        }
                   2207:
                   2208: out:
                   2209:        free(vol_page, M_TEMP);
                   2210: }
                   2211:
                   2212: int
                   2213: mpi_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number,
                   2214:     u_int32_t address, struct mpi_cfg_hdr *hdr)
                   2215: {
                   2216:        struct mpi_ccb                          *ccb;
                   2217:        struct mpi_msg_config_request           *cq;
                   2218:        struct mpi_msg_config_reply             *cp;
                   2219:        int                                     rv = 0;
                   2220:        int                                     s;
                   2221:
                   2222:        DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header type: %#x number: %x "
                   2223:            "address: %d\n", DEVNAME(sc), type, number, address);
                   2224:
                   2225:        s = splbio();
                   2226:        ccb = mpi_get_ccb(sc);
                   2227:        splx(s);
                   2228:        if (ccb == NULL) {
                   2229:                DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header ccb_get\n",
                   2230:                    DEVNAME(sc));
                   2231:                return (1);
                   2232:        }
                   2233:
                   2234:        ccb->ccb_done = mpi_empty_done;
                   2235:        cq = ccb->ccb_cmd;
                   2236:
                   2237:        cq->function = MPI_FUNCTION_CONFIG;
                   2238:        cq->msg_context = htole32(ccb->ccb_id);
                   2239:
                   2240:        cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER;
                   2241:
                   2242:        cq->config_header.page_number = number;
                   2243:        cq->config_header.page_type = type;
                   2244:        cq->page_address = htole32(address);
                   2245:        cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
                   2246:            MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
                   2247:
                   2248:        if (mpi_poll(sc, ccb, 50000) != 0) {
                   2249:                DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
                   2250:                return (1);
                   2251:        }
                   2252:
                   2253:        if (ccb->ccb_rcb == NULL)
                   2254:                panic("%s: unable to fetch config header\n", DEVNAME(sc));
                   2255:        cp = ccb->ccb_rcb->rcb_reply;
                   2256:
                   2257:        DNPRINTF(MPI_D_MISC, "%s:  action: 0x%02x msg_length: %d function: "
                   2258:            "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
                   2259:        DNPRINTF(MPI_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
                   2260:            "msg_flags: 0x%02x\n", DEVNAME(sc),
                   2261:            letoh16(cp->ext_page_length), cp->ext_page_type,
                   2262:            cp->msg_flags);
                   2263:        DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   2264:            letoh32(cp->msg_context));
                   2265:        DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
                   2266:            letoh16(cp->ioc_status));
                   2267:        DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   2268:            letoh32(cp->ioc_loginfo));
                   2269:        DNPRINTF(MPI_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
                   2270:            "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
                   2271:            cp->config_header.page_version,
                   2272:            cp->config_header.page_length,
                   2273:            cp->config_header.page_number,
                   2274:            cp->config_header.page_type);
                   2275:
                   2276:        if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
                   2277:                rv = 1;
                   2278:        else
                   2279:                *hdr = cp->config_header;
                   2280:
                   2281:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   2282:        mpi_put_ccb(sc, ccb);
                   2283:
                   2284:        return (rv);
                   2285: }
                   2286:
                   2287: int
                   2288: mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr,
                   2289:     int read, void *page, size_t len)
                   2290: {
                   2291:        struct mpi_ccb                          *ccb;
                   2292:        struct mpi_msg_config_request           *cq;
                   2293:        struct mpi_msg_config_reply             *cp;
                   2294:        u_int64_t                               dva;
                   2295:        char                                    *kva;
                   2296:        int                                     rv = 0;
                   2297:        int                                     s;
                   2298:
                   2299:        DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page address: %d read: %d type: %x\n",
                   2300:            DEVNAME(sc), address, read, hdr->page_type);
                   2301:
                   2302:        if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) ||
                   2303:            len < hdr->page_length * 4)
                   2304:                return (1);
                   2305:
                   2306:        s = splbio();
                   2307:        ccb = mpi_get_ccb(sc);
                   2308:        splx(s);
                   2309:        if (ccb == NULL) {
                   2310:                DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page ccb_get\n", DEVNAME(sc));
                   2311:                return (1);
                   2312:        }
                   2313:
                   2314:        ccb->ccb_done = mpi_empty_done;
                   2315:        cq = ccb->ccb_cmd;
                   2316:
                   2317:        cq->function = MPI_FUNCTION_CONFIG;
                   2318:        cq->msg_context = htole32(ccb->ccb_id);
                   2319:
                   2320:        cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
                   2321:            MPI_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
                   2322:
                   2323:        cq->config_header = *hdr;
                   2324:        cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK;
                   2325:        cq->page_address = htole32(address);
                   2326:        cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
                   2327:            MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
                   2328:            (hdr->page_length * 4) |
                   2329:            (read ? MPI_SGE_FL_DIR_IN : MPI_SGE_FL_DIR_OUT));
                   2330:
                   2331:        /* bounce the page via the request space to avoid more bus_dma games */
                   2332:        dva = ccb->ccb_cmd_dva + sizeof(struct mpi_msg_config_request);
                   2333:
                   2334:        cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
                   2335:        cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
                   2336:
                   2337:        kva = ccb->ccb_cmd;
                   2338:        kva += sizeof(struct mpi_msg_config_request);
                   2339:        if (!read)
                   2340:                bcopy(page, kva, len);
                   2341:
                   2342:        if (mpi_poll(sc, ccb, 50000) != 0) {
                   2343:                DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page poll\n", DEVNAME(sc));
                   2344:                return (1);
                   2345:        }
                   2346:
                   2347:        if (ccb->ccb_rcb == NULL) {
                   2348:                mpi_put_ccb(sc, ccb);
                   2349:                return (1);
                   2350:        }
                   2351:        cp = ccb->ccb_rcb->rcb_reply;
                   2352:
                   2353:        DNPRINTF(MPI_D_MISC, "%s:  action: 0x%02x msg_length: %d function: "
                   2354:            "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
                   2355:        DNPRINTF(MPI_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
                   2356:            "msg_flags: 0x%02x\n", DEVNAME(sc),
                   2357:            letoh16(cp->ext_page_length), cp->ext_page_type,
                   2358:            cp->msg_flags);
                   2359:        DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
                   2360:            letoh32(cp->msg_context));
                   2361:        DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
                   2362:            letoh16(cp->ioc_status));
                   2363:        DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
                   2364:            letoh32(cp->ioc_loginfo));
                   2365:        DNPRINTF(MPI_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
                   2366:            "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
                   2367:            cp->config_header.page_version,
                   2368:            cp->config_header.page_length,
                   2369:            cp->config_header.page_number,
                   2370:            cp->config_header.page_type);
                   2371:
                   2372:        if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
                   2373:                rv = 1;
                   2374:        else if (read)
                   2375:                bcopy(kva, page, len);
                   2376:
                   2377:        mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
                   2378:        mpi_put_ccb(sc, ccb);
                   2379:
                   2380:        return (rv);
                   2381: }

CVSweb