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

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

1.1       nbrk        1: /* $OpenBSD: mfi.c,v 1.73 2007/06/24 05:34:35 dlg Exp $ */
                      2: /*
                      3:  * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: #include "bio.h"
                     19:
                     20: #include <sys/param.h>
                     21: #include <sys/systm.h>
                     22: #include <sys/buf.h>
                     23: #include <sys/ioctl.h>
                     24: #include <sys/device.h>
                     25: #include <sys/kernel.h>
                     26: #include <sys/malloc.h>
                     27: #include <sys/proc.h>
                     28: #include <sys/rwlock.h>
                     29:
                     30: #include <machine/bus.h>
                     31:
                     32: #include <scsi/scsi_all.h>
                     33: #include <scsi/scsi_disk.h>
                     34: #include <scsi/scsiconf.h>
                     35:
                     36: #include <dev/ic/mfireg.h>
                     37: #include <dev/ic/mfivar.h>
                     38:
                     39: #if NBIO > 0
                     40: #include <dev/biovar.h>
                     41: #include <sys/sensors.h>
                     42: #endif /* NBIO > 0 */
                     43:
                     44: #ifdef MFI_DEBUG
                     45: uint32_t       mfi_debug = 0
                     46: /*                 | MFI_D_CMD */
                     47: /*                 | MFI_D_INTR */
                     48: /*                 | MFI_D_MISC */
                     49: /*                 | MFI_D_DMA */
                     50:                    | MFI_D_IOCTL
                     51: /*                 | MFI_D_RW */
                     52: /*                 | MFI_D_MEM */
                     53: /*                 | MFI_D_CCB */
                     54:                ;
                     55: #endif
                     56:
                     57: struct cfdriver mfi_cd = {
                     58:        NULL, "mfi", DV_DULL
                     59: };
                     60:
                     61: int    mfi_scsi_cmd(struct scsi_xfer *);
                     62: int    mfi_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int, struct proc *);
                     63: void   mfiminphys(struct buf *bp);
                     64:
                     65: struct scsi_adapter mfi_switch = {
                     66:        mfi_scsi_cmd, mfiminphys, 0, 0, mfi_scsi_ioctl
                     67: };
                     68:
                     69: struct scsi_device mfi_dev = {
                     70:        NULL, NULL, NULL, NULL
                     71: };
                     72:
                     73: struct mfi_ccb *mfi_get_ccb(struct mfi_softc *);
                     74: void           mfi_put_ccb(struct mfi_ccb *);
                     75: int            mfi_init_ccb(struct mfi_softc *);
                     76:
                     77: struct mfi_mem *mfi_allocmem(struct mfi_softc *, size_t);
                     78: void           mfi_freemem(struct mfi_softc *, struct mfi_mem *);
                     79:
                     80: int            mfi_transition_firmware(struct mfi_softc *);
                     81: int            mfi_initialize_firmware(struct mfi_softc *);
                     82: int            mfi_get_info(struct mfi_softc *);
                     83: uint32_t       mfi_read(struct mfi_softc *, bus_size_t);
                     84: void           mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
                     85: int            mfi_poll(struct mfi_ccb *);
                     86: int            mfi_despatch_cmd(struct mfi_ccb *);
                     87: int            mfi_create_sgl(struct mfi_ccb *, int);
                     88:
                     89: /* commands */
                     90: int            mfi_scsi_ld(struct mfi_ccb *, struct scsi_xfer *);
                     91: int            mfi_scsi_io(struct mfi_ccb *, struct scsi_xfer *, uint32_t,
                     92:                    uint32_t);
                     93: void           mfi_scsi_xs_done(struct mfi_ccb *);
                     94: int            mfi_mgmt(struct mfi_softc *, uint32_t, uint32_t, uint32_t,
                     95:                    void *, uint8_t *);
                     96: void           mfi_mgmt_done(struct mfi_ccb *);
                     97:
                     98: #if NBIO > 0
                     99: int            mfi_ioctl(struct device *, u_long, caddr_t);
                    100: int            mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *);
                    101: int            mfi_ioctl_vol(struct mfi_softc *, struct bioc_vol *);
                    102: int            mfi_ioctl_disk(struct mfi_softc *, struct bioc_disk *);
                    103: int            mfi_ioctl_alarm(struct mfi_softc *, struct bioc_alarm *);
                    104: int            mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *);
                    105: int            mfi_ioctl_setstate(struct mfi_softc *, struct bioc_setstate *);
                    106: int            mfi_bio_hs(struct mfi_softc *, int, int, void *);
                    107: #ifndef SMALL_KERNEL
                    108: int            mfi_create_sensors(struct mfi_softc *);
                    109: void           mfi_refresh_sensors(void *);
                    110: #endif /* SMALL_KERNEL */
                    111: #endif /* NBIO > 0 */
                    112:
                    113: struct mfi_ccb *
                    114: mfi_get_ccb(struct mfi_softc *sc)
                    115: {
                    116:        struct mfi_ccb          *ccb;
                    117:        int                     s;
                    118:
                    119:        s = splbio();
                    120:        ccb = TAILQ_FIRST(&sc->sc_ccb_freeq);
                    121:        if (ccb) {
                    122:                TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link);
                    123:                ccb->ccb_state = MFI_CCB_READY;
                    124:        }
                    125:        splx(s);
                    126:
                    127:        DNPRINTF(MFI_D_CCB, "%s: mfi_get_ccb: %p\n", DEVNAME(sc), ccb);
                    128:
                    129:        return (ccb);
                    130: }
                    131:
                    132: void
                    133: mfi_put_ccb(struct mfi_ccb *ccb)
                    134: {
                    135:        struct mfi_softc        *sc = ccb->ccb_sc;
                    136:        int                     s;
                    137:
                    138:        DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb);
                    139:
                    140:        s = splbio();
                    141:        ccb->ccb_state = MFI_CCB_FREE;
                    142:        ccb->ccb_xs = NULL;
                    143:        ccb->ccb_flags = 0;
                    144:        ccb->ccb_done = NULL;
                    145:        ccb->ccb_direction = 0;
                    146:        ccb->ccb_frame_size = 0;
                    147:        ccb->ccb_extra_frames = 0;
                    148:        ccb->ccb_sgl = NULL;
                    149:        ccb->ccb_data = NULL;
                    150:        ccb->ccb_len = 0;
                    151:        TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link);
                    152:        splx(s);
                    153: }
                    154:
                    155: int
                    156: mfi_init_ccb(struct mfi_softc *sc)
                    157: {
                    158:        struct mfi_ccb          *ccb;
                    159:        uint32_t                i;
                    160:        int                     error;
                    161:
                    162:        DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc));
                    163:
                    164:        sc->sc_ccb = malloc(sizeof(struct mfi_ccb) * sc->sc_max_cmds,
                    165:            M_DEVBUF, M_WAITOK);
                    166:        memset(sc->sc_ccb, 0, sizeof(struct mfi_ccb) * sc->sc_max_cmds);
                    167:
                    168:        for (i = 0; i < sc->sc_max_cmds; i++) {
                    169:                ccb = &sc->sc_ccb[i];
                    170:
                    171:                ccb->ccb_sc = sc;
                    172:
                    173:                /* select i'th frame */
                    174:                ccb->ccb_frame = (union mfi_frame *)
                    175:                    (MFIMEM_KVA(sc->sc_frames) + sc->sc_frames_size * i);
                    176:                ccb->ccb_pframe =
                    177:                    MFIMEM_DVA(sc->sc_frames) + sc->sc_frames_size * i;
                    178:                ccb->ccb_frame->mfr_header.mfh_context = i;
                    179:
                    180:                /* select i'th sense */
                    181:                ccb->ccb_sense = (struct mfi_sense *)
                    182:                    (MFIMEM_KVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
                    183:                ccb->ccb_psense =
                    184:                    (MFIMEM_DVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
                    185:
                    186:                /* create a dma map for transfer */
                    187:                error = bus_dmamap_create(sc->sc_dmat,
                    188:                    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
                    189:                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
                    190:                if (error) {
                    191:                        printf("%s: cannot create ccb dmamap (%d)\n",
                    192:                            DEVNAME(sc), error);
                    193:                        goto destroy;
                    194:                }
                    195:
                    196:                DNPRINTF(MFI_D_CCB,
                    197:                    "ccb(%d): %p frame: %#x (%#x) sense: %#x (%#x) map: %#x\n",
                    198:                    ccb->ccb_frame->mfr_header.mfh_context, ccb,
                    199:                    ccb->ccb_frame, ccb->ccb_pframe,
                    200:                    ccb->ccb_sense, ccb->ccb_psense,
                    201:                    ccb->ccb_dmamap);
                    202:
                    203:                /* add ccb to queue */
                    204:                mfi_put_ccb(ccb);
                    205:        }
                    206:
                    207:        return (0);
                    208: destroy:
                    209:        /* free dma maps and ccb memory */
                    210:        while (i) {
                    211:                ccb = &sc->sc_ccb[i];
                    212:                bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
                    213:                i--;
                    214:        }
                    215:
                    216:        free(sc->sc_ccb, M_DEVBUF);
                    217:
                    218:        return (1);
                    219: }
                    220:
                    221: uint32_t
                    222: mfi_read(struct mfi_softc *sc, bus_size_t r)
                    223: {
                    224:        uint32_t rv;
                    225:
                    226:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                    227:            BUS_SPACE_BARRIER_READ);
                    228:        rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
                    229:
                    230:        DNPRINTF(MFI_D_RW, "%s: mr 0x%x 0x08%x ", DEVNAME(sc), r, rv);
                    231:        return (rv);
                    232: }
                    233:
                    234: void
                    235: mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v)
                    236: {
                    237:        DNPRINTF(MFI_D_RW, "%s: mw 0x%x 0x%08x", DEVNAME(sc), r, v);
                    238:
                    239:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
                    240:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                    241:            BUS_SPACE_BARRIER_WRITE);
                    242: }
                    243:
                    244: struct mfi_mem *
                    245: mfi_allocmem(struct mfi_softc *sc, size_t size)
                    246: {
                    247:        struct mfi_mem          *mm;
                    248:        int                     nsegs;
                    249:
                    250:        DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %d\n", DEVNAME(sc),
                    251:            size);
                    252:
                    253:        mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT);
                    254:        if (mm == NULL)
                    255:                return (NULL);
                    256:
                    257:        memset(mm, 0, sizeof(struct mfi_mem));
                    258:        mm->am_size = size;
                    259:
                    260:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                    261:            BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0)
                    262:                goto amfree;
                    263:
                    264:        if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1,
                    265:            &nsegs, BUS_DMA_NOWAIT) != 0)
                    266:                goto destroy;
                    267:
                    268:        if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva,
                    269:            BUS_DMA_NOWAIT) != 0)
                    270:                goto free;
                    271:
                    272:        if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL,
                    273:            BUS_DMA_NOWAIT) != 0)
                    274:                goto unmap;
                    275:
                    276:        DNPRINTF(MFI_D_MEM, "  kva: %p  dva: %p  map: %p\n",
                    277:            mm->am_kva, mm->am_map->dm_segs[0].ds_addr, mm->am_map);
                    278:
                    279:        memset(mm->am_kva, 0, size);
                    280:        return (mm);
                    281:
                    282: unmap:
                    283:        bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size);
                    284: free:
                    285:        bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
                    286: destroy:
                    287:        bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
                    288: amfree:
                    289:        free(mm, M_DEVBUF);
                    290:
                    291:        return (NULL);
                    292: }
                    293:
                    294: void
                    295: mfi_freemem(struct mfi_softc *sc, struct mfi_mem *mm)
                    296: {
                    297:        DNPRINTF(MFI_D_MEM, "%s: mfi_freemem: %p\n", DEVNAME(sc), mm);
                    298:
                    299:        bus_dmamap_unload(sc->sc_dmat, mm->am_map);
                    300:        bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size);
                    301:        bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
                    302:        bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
                    303:        free(mm, M_DEVBUF);
                    304: }
                    305:
                    306: int
                    307: mfi_transition_firmware(struct mfi_softc *sc)
                    308: {
                    309:        int32_t                 fw_state, cur_state;
                    310:        int                     max_wait, i;
                    311:
                    312:        fw_state = mfi_read(sc, MFI_OMSG0) & MFI_STATE_MASK;
                    313:
                    314:        DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc),
                    315:            fw_state);
                    316:
                    317:        while (fw_state != MFI_STATE_READY) {
                    318:                DNPRINTF(MFI_D_MISC,
                    319:                    "%s: waiting for firmware to become ready\n",
                    320:                    DEVNAME(sc));
                    321:                cur_state = fw_state;
                    322:                switch (fw_state) {
                    323:                case MFI_STATE_FAULT:
                    324:                        printf("%s: firmware fault\n", DEVNAME(sc));
                    325:                        return (1);
                    326:                case MFI_STATE_WAIT_HANDSHAKE:
                    327:                        mfi_write(sc, MFI_IDB, MFI_INIT_CLEAR_HANDSHAKE);
                    328:                        max_wait = 2;
                    329:                        break;
                    330:                case MFI_STATE_OPERATIONAL:
                    331:                        mfi_write(sc, MFI_IDB, MFI_INIT_READY);
                    332:                        max_wait = 10;
                    333:                        break;
                    334:                case MFI_STATE_UNDEFINED:
                    335:                case MFI_STATE_BB_INIT:
                    336:                        max_wait = 2;
                    337:                        break;
                    338:                case MFI_STATE_FW_INIT:
                    339:                case MFI_STATE_DEVICE_SCAN:
                    340:                case MFI_STATE_FLUSH_CACHE:
                    341:                        max_wait = 20;
                    342:                        break;
                    343:                default:
                    344:                        printf("%s: unknown firmware state %d\n",
                    345:                            DEVNAME(sc), fw_state);
                    346:                        return (1);
                    347:                }
                    348:                for (i = 0; i < (max_wait * 10); i++) {
                    349:                        fw_state = mfi_read(sc, MFI_OMSG0) & MFI_STATE_MASK;
                    350:                        if (fw_state == cur_state)
                    351:                                DELAY(100000);
                    352:                        else
                    353:                                break;
                    354:                }
                    355:                if (fw_state == cur_state) {
                    356:                        printf("%s: firmware stuck in state %#x\n",
                    357:                            DEVNAME(sc), fw_state);
                    358:                        return (1);
                    359:                }
                    360:        }
                    361:
                    362:        return (0);
                    363: }
                    364:
                    365: int
                    366: mfi_initialize_firmware(struct mfi_softc *sc)
                    367: {
                    368:        struct mfi_ccb          *ccb;
                    369:        struct mfi_init_frame   *init;
                    370:        struct mfi_init_qinfo   *qinfo;
                    371:
                    372:        DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc));
                    373:
                    374:        if ((ccb = mfi_get_ccb(sc)) == NULL)
                    375:                return (1);
                    376:
                    377:        init = &ccb->ccb_frame->mfr_init;
                    378:        qinfo = (struct mfi_init_qinfo *)((uint8_t *)init + MFI_FRAME_SIZE);
                    379:
                    380:        memset(qinfo, 0, sizeof *qinfo);
                    381:        qinfo->miq_rq_entries = sc->sc_max_cmds + 1;
                    382:        qinfo->miq_rq_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    383:            offsetof(struct mfi_prod_cons, mpc_reply_q));
                    384:        qinfo->miq_pi_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    385:            offsetof(struct mfi_prod_cons, mpc_producer));
                    386:        qinfo->miq_ci_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    387:            offsetof(struct mfi_prod_cons, mpc_consumer));
                    388:
                    389:        init->mif_header.mfh_cmd = MFI_CMD_INIT;
                    390:        init->mif_header.mfh_data_len = sizeof *qinfo;
                    391:        init->mif_qinfo_new_addr_lo = htole32(ccb->ccb_pframe + MFI_FRAME_SIZE);
                    392:
                    393:        DNPRINTF(MFI_D_MISC, "%s: entries: %#x rq: %#x pi: %#x ci: %#x\n",
                    394:            DEVNAME(sc),
                    395:            qinfo->miq_rq_entries, qinfo->miq_rq_addr_lo,
                    396:            qinfo->miq_pi_addr_lo, qinfo->miq_ci_addr_lo);
                    397:
                    398:        if (mfi_poll(ccb)) {
                    399:                printf("%s: mfi_initialize_firmware failed\n", DEVNAME(sc));
                    400:                return (1);
                    401:        }
                    402:
                    403:        mfi_put_ccb(ccb);
                    404:
                    405:        return (0);
                    406: }
                    407:
                    408: int
                    409: mfi_get_info(struct mfi_softc *sc)
                    410: {
                    411: #ifdef MFI_DEBUG
                    412:        int i;
                    413: #endif
                    414:        DNPRINTF(MFI_D_MISC, "%s: mfi_get_info\n", DEVNAME(sc));
                    415:
                    416:        if (mfi_mgmt(sc, MR_DCMD_CTRL_GET_INFO, MFI_DATA_IN,
                    417:            sizeof(sc->sc_info), &sc->sc_info, NULL))
                    418:                return (1);
                    419:
                    420: #ifdef MFI_DEBUG
                    421:
                    422:        for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
                    423:                printf("%s: active FW %s Version %s date %s time %s\n",
                    424:                    DEVNAME(sc),
                    425:                    sc->sc_info.mci_image_component[i].mic_name,
                    426:                    sc->sc_info.mci_image_component[i].mic_version,
                    427:                    sc->sc_info.mci_image_component[i].mic_build_date,
                    428:                    sc->sc_info.mci_image_component[i].mic_build_time);
                    429:        }
                    430:
                    431:        for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
                    432:                printf("%s: pending FW %s Version %s date %s time %s\n",
                    433:                    DEVNAME(sc),
                    434:                    sc->sc_info.mci_pending_image_component[i].mic_name,
                    435:                    sc->sc_info.mci_pending_image_component[i].mic_version,
                    436:                    sc->sc_info.mci_pending_image_component[i].mic_build_date,
                    437:                    sc->sc_info.mci_pending_image_component[i].mic_build_time);
                    438:        }
                    439:
                    440:        printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
                    441:            DEVNAME(sc),
                    442:            sc->sc_info.mci_max_arms,
                    443:            sc->sc_info.mci_max_spans,
                    444:            sc->sc_info.mci_max_arrays,
                    445:            sc->sc_info.mci_max_lds,
                    446:            sc->sc_info.mci_product_name);
                    447:
                    448:        printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
                    449:            DEVNAME(sc),
                    450:            sc->sc_info.mci_serial_number,
                    451:            sc->sc_info.mci_hw_present,
                    452:            sc->sc_info.mci_current_fw_time,
                    453:            sc->sc_info.mci_max_cmds,
                    454:            sc->sc_info.mci_max_sg_elements);
                    455:
                    456:        printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
                    457:            DEVNAME(sc),
                    458:            sc->sc_info.mci_max_request_size,
                    459:            sc->sc_info.mci_lds_present,
                    460:            sc->sc_info.mci_lds_degraded,
                    461:            sc->sc_info.mci_lds_offline,
                    462:            sc->sc_info.mci_pd_present);
                    463:
                    464:        printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
                    465:            DEVNAME(sc),
                    466:            sc->sc_info.mci_pd_disks_present,
                    467:            sc->sc_info.mci_pd_disks_pred_failure,
                    468:            sc->sc_info.mci_pd_disks_failed);
                    469:
                    470:        printf("%s: nvram %d mem %d flash %d\n",
                    471:            DEVNAME(sc),
                    472:            sc->sc_info.mci_nvram_size,
                    473:            sc->sc_info.mci_memory_size,
                    474:            sc->sc_info.mci_flash_size);
                    475:
                    476:        printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
                    477:            DEVNAME(sc),
                    478:            sc->sc_info.mci_ram_correctable_errors,
                    479:            sc->sc_info.mci_ram_uncorrectable_errors,
                    480:            sc->sc_info.mci_cluster_allowed,
                    481:            sc->sc_info.mci_cluster_active);
                    482:
                    483:        printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
                    484:            DEVNAME(sc),
                    485:            sc->sc_info.mci_max_strips_per_io,
                    486:            sc->sc_info.mci_raid_levels,
                    487:            sc->sc_info.mci_adapter_ops,
                    488:            sc->sc_info.mci_ld_ops);
                    489:
                    490:        printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
                    491:            DEVNAME(sc),
                    492:            sc->sc_info.mci_stripe_sz_ops.min,
                    493:            sc->sc_info.mci_stripe_sz_ops.max,
                    494:            sc->sc_info.mci_pd_ops,
                    495:            sc->sc_info.mci_pd_mix_support);
                    496:
                    497:        printf("%s: ecc_bucket %d pckg_prop %s\n",
                    498:            DEVNAME(sc),
                    499:            sc->sc_info.mci_ecc_bucket_count,
                    500:            sc->sc_info.mci_package_version);
                    501:
                    502:        printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
                    503:            DEVNAME(sc),
                    504:            sc->sc_info.mci_properties.mcp_seq_num,
                    505:            sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
                    506:            sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
                    507:            sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
                    508:
                    509:        printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
                    510:            DEVNAME(sc),
                    511:            sc->sc_info.mci_properties.mcp_rebuild_rate,
                    512:            sc->sc_info.mci_properties.mcp_patrol_read_rate,
                    513:            sc->sc_info.mci_properties.mcp_bgi_rate,
                    514:            sc->sc_info.mci_properties.mcp_cc_rate);
                    515:
                    516:        printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
                    517:            DEVNAME(sc),
                    518:            sc->sc_info.mci_properties.mcp_recon_rate,
                    519:            sc->sc_info.mci_properties.mcp_cache_flush_interval,
                    520:            sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
                    521:            sc->sc_info.mci_properties.mcp_spinup_delay,
                    522:            sc->sc_info.mci_properties.mcp_cluster_enable);
                    523:
                    524:        printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
                    525:            DEVNAME(sc),
                    526:            sc->sc_info.mci_properties.mcp_coercion_mode,
                    527:            sc->sc_info.mci_properties.mcp_alarm_enable,
                    528:            sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
                    529:            sc->sc_info.mci_properties.mcp_disable_battery_warn,
                    530:            sc->sc_info.mci_properties.mcp_ecc_bucket_size);
                    531:
                    532:        printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
                    533:            DEVNAME(sc),
                    534:            sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
                    535:            sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
                    536:            sc->sc_info.mci_properties.mcp_expose_encl_devices);
                    537:
                    538:        printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
                    539:            DEVNAME(sc),
                    540:            sc->sc_info.mci_pci.mip_vendor,
                    541:            sc->sc_info.mci_pci.mip_device,
                    542:            sc->sc_info.mci_pci.mip_subvendor,
                    543:            sc->sc_info.mci_pci.mip_subdevice);
                    544:
                    545:        printf("%s: type %#x port_count %d port_addr ",
                    546:            DEVNAME(sc),
                    547:            sc->sc_info.mci_host.mih_type,
                    548:            sc->sc_info.mci_host.mih_port_count);
                    549:
                    550:        for (i = 0; i < 8; i++)
                    551:                printf("%.0llx ", sc->sc_info.mci_host.mih_port_addr[i]);
                    552:        printf("\n");
                    553:
                    554:        printf("%s: type %.x port_count %d port_addr ",
                    555:            DEVNAME(sc),
                    556:            sc->sc_info.mci_device.mid_type,
                    557:            sc->sc_info.mci_device.mid_port_count);
                    558:
                    559:        for (i = 0; i < 8; i++)
                    560:                printf("%.0llx ", sc->sc_info.mci_device.mid_port_addr[i]);
                    561:        printf("\n");
                    562: #endif /* MFI_DEBUG */
                    563:
                    564:        return (0);
                    565: }
                    566:
                    567: void
                    568: mfiminphys(struct buf *bp)
                    569: {
                    570:        DNPRINTF(MFI_D_MISC, "mfiminphys: %d\n", bp->b_bcount);
                    571:
                    572:        /* XXX currently using MFI_MAXFER = MAXPHYS */
                    573:        if (bp->b_bcount > MFI_MAXFER)
                    574:                bp->b_bcount = MFI_MAXFER;
                    575:        minphys(bp);
                    576: }
                    577:
                    578: int
                    579: mfi_attach(struct mfi_softc *sc)
                    580: {
                    581:        struct scsibus_attach_args saa;
                    582:        uint32_t                status, frames;
                    583:        int                     i;
                    584:
                    585:        DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc));
                    586:
                    587:        if (mfi_transition_firmware(sc))
                    588:                return (1);
                    589:
                    590:        TAILQ_INIT(&sc->sc_ccb_freeq);
                    591:
                    592:        rw_init(&sc->sc_lock, "mfi_lock");
                    593:
                    594:        status = mfi_read(sc, MFI_OMSG0);
                    595:        sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
                    596:        sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
                    597:        DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n",
                    598:            DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl);
                    599:
                    600:        /* consumer/producer and reply queue memory */
                    601:        sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) +
                    602:            sizeof(struct mfi_prod_cons));
                    603:        if (sc->sc_pcq == NULL) {
                    604:                printf("%s: unable to allocate reply queue memory\n",
                    605:                    DEVNAME(sc));
                    606:                goto nopcq;
                    607:        }
                    608:
                    609:        /* frame memory */
                    610:        /* we are not doing 64 bit IO so only calculate # of 32 bit frames */
                    611:        frames = (sizeof(struct mfi_sg32) * sc->sc_max_sgl +
                    612:            MFI_FRAME_SIZE - 1) / MFI_FRAME_SIZE + 1;
                    613:        sc->sc_frames_size = frames * MFI_FRAME_SIZE;
                    614:        sc->sc_frames = mfi_allocmem(sc, sc->sc_frames_size * sc->sc_max_cmds);
                    615:        if (sc->sc_frames == NULL) {
                    616:                printf("%s: unable to allocate frame memory\n", DEVNAME(sc));
                    617:                goto noframe;
                    618:        }
                    619:        /* XXX hack, fix this */
                    620:        if (MFIMEM_DVA(sc->sc_frames) & 0x3f) {
                    621:                printf("%s: improper frame alignment (%#x) FIXME\n",
                    622:                    DEVNAME(sc), MFIMEM_DVA(sc->sc_frames));
                    623:                goto noframe;
                    624:        }
                    625:
                    626:        /* sense memory */
                    627:        sc->sc_sense = mfi_allocmem(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
                    628:        if (sc->sc_sense == NULL) {
                    629:                printf("%s: unable to allocate sense memory\n", DEVNAME(sc));
                    630:                goto nosense;
                    631:        }
                    632:
                    633:        /* now that we have all memory bits go initialize ccbs */
                    634:        if (mfi_init_ccb(sc)) {
                    635:                printf("%s: could not init ccb list\n", DEVNAME(sc));
                    636:                goto noinit;
                    637:        }
                    638:
                    639:        /* kickstart firmware with all addresses and pointers */
                    640:        if (mfi_initialize_firmware(sc)) {
                    641:                printf("%s: could not initialize firmware\n", DEVNAME(sc));
                    642:                goto noinit;
                    643:        }
                    644:
                    645:        if (mfi_get_info(sc)) {
                    646:                printf("%s: could not retrieve controller information\n",
                    647:                    DEVNAME(sc));
                    648:                goto noinit;
                    649:        }
                    650:
                    651:        printf("%s: logical drives %d, version %s, %dMB RAM\n",
                    652:            DEVNAME(sc),
                    653:            sc->sc_info.mci_lds_present,
                    654:            sc->sc_info.mci_package_version,
                    655:            sc->sc_info.mci_memory_size);
                    656:
                    657:        sc->sc_ld_cnt = sc->sc_info.mci_lds_present;
                    658:        sc->sc_max_ld = sc->sc_ld_cnt;
                    659:        for (i = 0; i < sc->sc_ld_cnt; i++)
                    660:                sc->sc_ld[i].ld_present = 1;
                    661:
                    662:        if (sc->sc_ld_cnt)
                    663:                sc->sc_link.openings = sc->sc_max_cmds / sc->sc_ld_cnt;
                    664:        else
                    665:                sc->sc_link.openings = sc->sc_max_cmds;
                    666:
                    667:        sc->sc_link.device = &mfi_dev;
                    668:        sc->sc_link.adapter_softc = sc;
                    669:        sc->sc_link.adapter = &mfi_switch;
                    670:        sc->sc_link.adapter_target = MFI_MAX_LD;
                    671:        sc->sc_link.adapter_buswidth = sc->sc_max_ld;
                    672:
                    673:        bzero(&saa, sizeof(saa));
                    674:        saa.saa_sc_link = &sc->sc_link;
                    675:
                    676:        config_found(&sc->sc_dev, &saa, scsiprint);
                    677:
                    678:        /* enable interrupts */
                    679:        mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
                    680:
                    681: #if NBIO > 0
                    682:        if (bio_register(&sc->sc_dev, mfi_ioctl) != 0)
                    683:                panic("%s: controller registration failed", DEVNAME(sc));
                    684:        else
                    685:                sc->sc_ioctl = mfi_ioctl;
                    686:
                    687: #ifndef SMALL_KERNEL
                    688:        if (mfi_create_sensors(sc) != 0)
                    689:                printf("%s: unable to create sensors\n", DEVNAME(sc));
                    690: #endif
                    691: #endif /* NBIO > 0 */
                    692:
                    693:        return (0);
                    694: noinit:
                    695:        mfi_freemem(sc, sc->sc_sense);
                    696: nosense:
                    697:        mfi_freemem(sc, sc->sc_frames);
                    698: noframe:
                    699:        mfi_freemem(sc, sc->sc_pcq);
                    700: nopcq:
                    701:        return (1);
                    702: }
                    703:
                    704: int
                    705: mfi_despatch_cmd(struct mfi_ccb *ccb)
                    706: {
                    707:        DNPRINTF(MFI_D_CMD, "%s: mfi_despatch_cmd\n",
                    708:            DEVNAME(ccb->ccb_sc));
                    709:
                    710:        mfi_write(ccb->ccb_sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
                    711:            ccb->ccb_extra_frames);
                    712:
                    713:        return(0);
                    714: }
                    715:
                    716: int
                    717: mfi_poll(struct mfi_ccb *ccb)
                    718: {
                    719:        struct mfi_frame_header *hdr;
                    720:        int                     to = 0;
                    721:
                    722:        DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(ccb->ccb_sc));
                    723:
                    724:        hdr = &ccb->ccb_frame->mfr_header;
                    725:        hdr->mfh_cmd_status = 0xff;
                    726:        hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
                    727:
                    728:        mfi_despatch_cmd(ccb);
                    729:
                    730:        while (hdr->mfh_cmd_status == 0xff) {
                    731:                delay(1000);
                    732:                if (to++ > 5000) /* XXX 5 seconds busywait sucks */
                    733:                        break;
                    734:        }
                    735:        if (hdr->mfh_cmd_status == 0xff) {
                    736:                printf("%s: timeout on ccb %d\n", DEVNAME(ccb->ccb_sc),
                    737:                    hdr->mfh_context);
                    738:                ccb->ccb_flags |= MFI_CCB_F_ERR;
                    739:                return (1);
                    740:        }
                    741:
                    742:        return (0);
                    743: }
                    744:
                    745: int
                    746: mfi_intr(void *arg)
                    747: {
                    748:        struct mfi_softc        *sc = arg;
                    749:        struct mfi_prod_cons    *pcq;
                    750:        struct mfi_ccb          *ccb;
                    751:        uint32_t                status, producer, consumer, ctx;
                    752:        int                     claimed = 0;
                    753:
                    754:        status = mfi_read(sc, MFI_OSTS);
                    755:        if ((status & MFI_OSTS_INTR_VALID) == 0)
                    756:                return (claimed);
                    757:        /* write status back to acknowledge interrupt */
                    758:        mfi_write(sc, MFI_OSTS, status);
                    759:
                    760:        DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
                    761:
                    762:        pcq = MFIMEM_KVA(sc->sc_pcq);
                    763:        producer = pcq->mpc_producer;
                    764:        consumer = pcq->mpc_consumer;
                    765:
                    766:        while (consumer != producer) {
                    767:                DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n",
                    768:                    DEVNAME(sc), producer, consumer);
                    769:
                    770:                ctx = pcq->mpc_reply_q[consumer];
                    771:                pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX;
                    772:                if (ctx == MFI_INVALID_CTX)
                    773:                        printf("%s: invalid context, p: %d c: %d\n",
                    774:                            DEVNAME(sc), producer, consumer);
                    775:                else {
                    776:                        /* XXX remove from queue and call scsi_done */
                    777:                        ccb = &sc->sc_ccb[ctx];
                    778:                        DNPRINTF(MFI_D_INTR, "%s: mfi_intr context %#x\n",
                    779:                            DEVNAME(sc), ctx);
                    780:                        ccb->ccb_done(ccb);
                    781:
                    782:                        claimed = 1;
                    783:                }
                    784:                consumer++;
                    785:                if (consumer == (sc->sc_max_cmds + 1))
                    786:                        consumer = 0;
                    787:        }
                    788:
                    789:        pcq->mpc_consumer = consumer;
                    790:
                    791:        return (claimed);
                    792: }
                    793:
                    794: int
                    795: mfi_scsi_io(struct mfi_ccb *ccb, struct scsi_xfer *xs, uint32_t blockno,
                    796:     uint32_t blockcnt)
                    797: {
                    798:        struct scsi_link        *link = xs->sc_link;
                    799:        struct mfi_io_frame     *io;
                    800:
                    801:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_io: %d\n",
                    802:            DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
                    803:
                    804:        if (!xs->data)
                    805:                return (1);
                    806:
                    807:        io = &ccb->ccb_frame->mfr_io;
                    808:        if (xs->flags & SCSI_DATA_IN) {
                    809:                io->mif_header.mfh_cmd = MFI_CMD_LD_READ;
                    810:                ccb->ccb_direction = MFI_DATA_IN;
                    811:        } else {
                    812:                io->mif_header.mfh_cmd = MFI_CMD_LD_WRITE;
                    813:                ccb->ccb_direction = MFI_DATA_OUT;
                    814:        }
                    815:        io->mif_header.mfh_target_id = link->target;
                    816:        io->mif_header.mfh_timeout = 0;
                    817:        io->mif_header.mfh_flags = 0;
                    818:        io->mif_header.mfh_sense_len = MFI_SENSE_SIZE;
                    819:        io->mif_header.mfh_data_len= blockcnt;
                    820:        io->mif_lba_hi = 0;
                    821:        io->mif_lba_lo = blockno;
                    822:        io->mif_sense_addr_lo = htole32(ccb->ccb_psense);
                    823:        io->mif_sense_addr_hi = 0;
                    824:
                    825:        ccb->ccb_done = mfi_scsi_xs_done;
                    826:        ccb->ccb_xs = xs;
                    827:        ccb->ccb_frame_size = MFI_IO_FRAME_SIZE;
                    828:        ccb->ccb_sgl = &io->mif_sgl;
                    829:        ccb->ccb_data = xs->data;
                    830:        ccb->ccb_len = xs->datalen;
                    831:
                    832:        if (mfi_create_sgl(ccb, (xs->flags & SCSI_NOSLEEP) ?
                    833:            BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
                    834:                return (1);
                    835:
                    836:        return (0);
                    837: }
                    838:
                    839: void
                    840: mfi_scsi_xs_done(struct mfi_ccb *ccb)
                    841: {
                    842:        struct scsi_xfer        *xs = ccb->ccb_xs;
                    843:        struct mfi_softc        *sc = ccb->ccb_sc;
                    844:        struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
                    845:
                    846:        DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#x %#x\n",
                    847:            DEVNAME(sc), ccb, ccb->ccb_frame);
                    848:
                    849:        if (xs->data != NULL) {
                    850:                DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done sync\n",
                    851:                    DEVNAME(sc));
                    852:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
                    853:                    ccb->ccb_dmamap->dm_mapsize,
                    854:                    (xs->flags & SCSI_DATA_IN) ?
                    855:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                    856:
                    857:                bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
                    858:        }
                    859:
                    860:        if (hdr->mfh_cmd_status != MFI_STAT_OK) {
                    861:                xs->error = XS_DRIVER_STUFFUP;
                    862:                DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done stuffup %#x\n",
                    863:                    DEVNAME(sc), hdr->mfh_cmd_status);
                    864:
                    865:                if (hdr->mfh_scsi_status != 0) {
                    866:                        DNPRINTF(MFI_D_INTR,
                    867:                            "%s: mfi_scsi_xs_done sense %#x %x %x\n",
                    868:                            DEVNAME(sc), hdr->mfh_scsi_status,
                    869:                            &xs->sense, ccb->ccb_sense);
                    870:                        memset(&xs->sense, 0, sizeof(xs->sense));
                    871:                        memcpy(&xs->sense, ccb->ccb_sense,
                    872:                            sizeof(struct scsi_sense_data));
                    873:                        xs->error = XS_SENSE;
                    874:                }
                    875:        }
                    876:
                    877:        xs->resid = 0;
                    878:        xs->flags |= ITSDONE;
                    879:
                    880:        mfi_put_ccb(ccb);
                    881:        scsi_done(xs);
                    882: }
                    883:
                    884: int
                    885: mfi_scsi_ld(struct mfi_ccb *ccb, struct scsi_xfer *xs)
                    886: {
                    887:        struct scsi_link        *link = xs->sc_link;
                    888:        struct mfi_pass_frame   *pf;
                    889:
                    890:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n",
                    891:            DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
                    892:
                    893:        pf = &ccb->ccb_frame->mfr_pass;
                    894:        pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO;
                    895:        pf->mpf_header.mfh_target_id = link->target;
                    896:        pf->mpf_header.mfh_lun_id = 0;
                    897:        pf->mpf_header.mfh_cdb_len = xs->cmdlen;
                    898:        pf->mpf_header.mfh_timeout = 0;
                    899:        pf->mpf_header.mfh_data_len= xs->datalen; /* XXX */
                    900:        pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE;
                    901:
                    902:        pf->mpf_sense_addr_hi = 0;
                    903:        pf->mpf_sense_addr_lo = htole32(ccb->ccb_psense);
                    904:
                    905:        memset(pf->mpf_cdb, 0, 16);
                    906:        memcpy(pf->mpf_cdb, &xs->cmdstore, xs->cmdlen);
                    907:
                    908:        ccb->ccb_done = mfi_scsi_xs_done;
                    909:        ccb->ccb_xs = xs;
                    910:        ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
                    911:        ccb->ccb_sgl = &pf->mpf_sgl;
                    912:
                    913:        if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
                    914:                ccb->ccb_direction = xs->flags & SCSI_DATA_IN ?
                    915:                    MFI_DATA_IN : MFI_DATA_OUT;
                    916:        else
                    917:                ccb->ccb_direction = MFI_DATA_NONE;
                    918:
                    919:        if (xs->data) {
                    920:                ccb->ccb_data = xs->data;
                    921:                ccb->ccb_len = xs->datalen;
                    922:
                    923:                if (mfi_create_sgl(ccb, (xs->flags & SCSI_NOSLEEP) ?
                    924:                    BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
                    925:                        return (1);
                    926:        }
                    927:
                    928:        return (0);
                    929: }
                    930:
                    931: int
                    932: mfi_scsi_cmd(struct scsi_xfer *xs)
                    933: {
                    934:        struct scsi_link        *link = xs->sc_link;
                    935:        struct mfi_softc        *sc = link->adapter_softc;
                    936:        struct device           *dev = link->device_softc;
                    937:        struct mfi_ccb          *ccb;
                    938:        struct scsi_rw          *rw;
                    939:        struct scsi_rw_big      *rwb;
                    940:        uint32_t                blockno, blockcnt;
                    941:        uint8_t                 target = link->target;
                    942:        uint8_t                 mbox[MFI_MBOX_SIZE];
                    943:
                    944:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd opcode: %#x\n",
                    945:            DEVNAME(sc), xs->cmd->opcode);
                    946:
                    947:        if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present ||
                    948:            link->lun != 0) {
                    949:                DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n",
                    950:                    DEVNAME(sc), target);
                    951:                goto stuffup;
                    952:        }
                    953:
                    954:        if ((ccb = mfi_get_ccb(sc)) == NULL) {
                    955:                DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd no ccb\n", DEVNAME(sc));
                    956:                return (TRY_AGAIN_LATER);
                    957:        }
                    958:
                    959:        xs->error = XS_NOERROR;
                    960:
                    961:        switch (xs->cmd->opcode) {
                    962:        /* IO path */
                    963:        case READ_BIG:
                    964:        case WRITE_BIG:
                    965:                rwb = (struct scsi_rw_big *)xs->cmd;
                    966:                blockno = _4btol(rwb->addr);
                    967:                blockcnt = _2btol(rwb->length);
                    968:                if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
                    969:                        mfi_put_ccb(ccb);
                    970:                        goto stuffup;
                    971:                }
                    972:                break;
                    973:
                    974:        case READ_COMMAND:
                    975:        case WRITE_COMMAND:
                    976:                rw = (struct scsi_rw *)xs->cmd;
                    977:                blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
                    978:                blockcnt = rw->length ? rw->length : 0x100;
                    979:                if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
                    980:                        mfi_put_ccb(ccb);
                    981:                        goto stuffup;
                    982:                }
                    983:                break;
                    984:
                    985:        case SYNCHRONIZE_CACHE:
                    986:                mfi_put_ccb(ccb); /* we don't need this */
                    987:
                    988:                mbox[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
                    989:                if (mfi_mgmt(sc, MR_DCMD_CTRL_CACHE_FLUSH, MFI_DATA_NONE,
                    990:                    0, NULL, mbox))
                    991:                        goto stuffup;
                    992:
                    993:                return (COMPLETE);
                    994:                /* NOTREACHED */
                    995:
                    996:        /* hand it of to the firmware and let it deal with it */
                    997:        case TEST_UNIT_READY:
                    998:                /* save off sd? after autoconf */
                    999:                if (!cold)      /* XXX bogus */
                   1000:                        strlcpy(sc->sc_ld[target].ld_dev, dev->dv_xname,
                   1001:                            sizeof(sc->sc_ld[target].ld_dev));
                   1002:                /* FALLTHROUGH */
                   1003:
                   1004:        default:
                   1005:                if (mfi_scsi_ld(ccb, xs)) {
                   1006:                        mfi_put_ccb(ccb);
                   1007:                        goto stuffup;
                   1008:                }
                   1009:                break;
                   1010:        }
                   1011:
                   1012:        DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
                   1013:
                   1014:        if (xs->flags & SCSI_POLL) {
                   1015:                if (mfi_poll(ccb)) {
                   1016:                        /* XXX check for sense in ccb->ccb_sense? */
                   1017:                        printf("%s: mfi_scsi_cmd poll failed\n",
                   1018:                            DEVNAME(sc));
                   1019:                        mfi_put_ccb(ccb);
                   1020:                        bzero(&xs->sense, sizeof(xs->sense));
                   1021:                        xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
                   1022:                        xs->sense.flags = SKEY_ILLEGAL_REQUEST;
                   1023:                        xs->sense.add_sense_code = 0x20; /* invalid opcode */
                   1024:                        xs->error = XS_SENSE;
                   1025:                        xs->flags |= ITSDONE;
                   1026:                        scsi_done(xs);
                   1027:                        return (COMPLETE);
                   1028:                }
                   1029:                DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd poll complete %d\n",
                   1030:                    DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs);
                   1031:
                   1032:                mfi_put_ccb(ccb);
                   1033:                return (COMPLETE);
                   1034:        }
                   1035:
                   1036:        mfi_despatch_cmd(ccb);
                   1037:
                   1038:        DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd queued %d\n", DEVNAME(sc),
                   1039:            ccb->ccb_dmamap->dm_nsegs);
                   1040:
                   1041:        return (SUCCESSFULLY_QUEUED);
                   1042:
                   1043: stuffup:
                   1044:        xs->error = XS_DRIVER_STUFFUP;
                   1045:        xs->flags |= ITSDONE;
                   1046:        scsi_done(xs);
                   1047:        return (COMPLETE);
                   1048: }
                   1049:
                   1050: int
                   1051: mfi_create_sgl(struct mfi_ccb *ccb, int flags)
                   1052: {
                   1053:        struct mfi_softc        *sc = ccb->ccb_sc;
                   1054:        struct mfi_frame_header *hdr;
                   1055:        bus_dma_segment_t       *sgd;
                   1056:        union mfi_sgl           *sgl;
                   1057:        int                     error, i;
                   1058:
                   1059:        DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#x\n", DEVNAME(sc),
                   1060:            ccb->ccb_data);
                   1061:
                   1062:        if (!ccb->ccb_data)
                   1063:                return (1);
                   1064:
                   1065:        error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap,
                   1066:            ccb->ccb_data, ccb->ccb_len, NULL, flags);
                   1067:        if (error) {
                   1068:                if (error == EFBIG)
                   1069:                        printf("more than %d dma segs\n",
                   1070:                            sc->sc_max_sgl);
                   1071:                else
                   1072:                        printf("error %d loading dma map\n", error);
                   1073:                return (1);
                   1074:        }
                   1075:
                   1076:        hdr = &ccb->ccb_frame->mfr_header;
                   1077:        sgl = ccb->ccb_sgl;
                   1078:        sgd = ccb->ccb_dmamap->dm_segs;
                   1079:        for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
                   1080:                sgl->sg32[i].addr = htole32(sgd[i].ds_addr);
                   1081:                sgl->sg32[i].len = htole32(sgd[i].ds_len);
                   1082:                DNPRINTF(MFI_D_DMA, "%s: addr: %#x  len: %#x\n",
                   1083:                    DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len);
                   1084:        }
                   1085:
                   1086:        if (ccb->ccb_direction == MFI_DATA_IN) {
                   1087:                hdr->mfh_flags |= MFI_FRAME_DIR_READ;
                   1088:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
                   1089:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   1090:        } else {
                   1091:                hdr->mfh_flags |= MFI_FRAME_DIR_WRITE;
                   1092:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
                   1093:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
                   1094:        }
                   1095:
                   1096:        hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs;
                   1097:        /* for 64 bit io make the sizeof a variable to hold whatever sg size */
                   1098:        ccb->ccb_frame_size += sizeof(struct mfi_sg32) *
                   1099:            ccb->ccb_dmamap->dm_nsegs;
                   1100:        ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE;
                   1101:
                   1102:        DNPRINTF(MFI_D_DMA, "%s: sg_count: %d  frame_size: %d  frames_size: %d"
                   1103:            "  dm_nsegs: %d  extra_frames: %d\n",
                   1104:            DEVNAME(sc),
                   1105:            hdr->mfh_sg_count,
                   1106:            ccb->ccb_frame_size,
                   1107:            sc->sc_frames_size,
                   1108:            ccb->ccb_dmamap->dm_nsegs,
                   1109:            ccb->ccb_extra_frames);
                   1110:
                   1111:        return (0);
                   1112: }
                   1113:
                   1114: int
                   1115: mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
                   1116:     void *buf, uint8_t *mbox)
                   1117: {
                   1118:        struct mfi_ccb          *ccb;
                   1119:        struct mfi_dcmd_frame   *dcmd;
                   1120:        int                     rv = 1;
                   1121:
                   1122:        DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(sc), opc);
                   1123:
                   1124:        if ((ccb = mfi_get_ccb(sc)) == NULL)
                   1125:                return (rv);
                   1126:
                   1127:        dcmd = &ccb->ccb_frame->mfr_dcmd;
                   1128:        memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE);
                   1129:        dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD;
                   1130:        dcmd->mdf_header.mfh_timeout = 0;
                   1131:
                   1132:        dcmd->mdf_opcode = opc;
                   1133:        dcmd->mdf_header.mfh_data_len = 0;
                   1134:        ccb->ccb_direction = dir;
                   1135:        ccb->ccb_done = mfi_mgmt_done;
                   1136:
                   1137:        ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE;
                   1138:
                   1139:        /* handle special opcodes */
                   1140:        if (mbox)
                   1141:                memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE);
                   1142:
                   1143:        if (dir != MFI_DATA_NONE) {
                   1144:                dcmd->mdf_header.mfh_data_len = len;
                   1145:                ccb->ccb_data = buf;
                   1146:                ccb->ccb_len = len;
                   1147:                ccb->ccb_sgl = &dcmd->mdf_sgl;
                   1148:
                   1149:                if (mfi_create_sgl(ccb, BUS_DMA_WAITOK))
                   1150:                        goto done;
                   1151:        }
                   1152:
                   1153:        if (cold) {
                   1154:                if (mfi_poll(ccb))
                   1155:                        goto done;
                   1156:        } else {
                   1157:                mfi_despatch_cmd(ccb);
                   1158:
                   1159:                DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt sleeping\n", DEVNAME(sc));
                   1160:                while (ccb->ccb_state != MFI_CCB_DONE)
                   1161:                        tsleep(ccb, PRIBIO, "mfi_mgmt", 0);
                   1162:
                   1163:                if (ccb->ccb_flags & MFI_CCB_F_ERR)
                   1164:                        goto done;
                   1165:        }
                   1166:
                   1167:        rv = 0;
                   1168:
                   1169: done:
                   1170:        mfi_put_ccb(ccb);
                   1171:        return (rv);
                   1172: }
                   1173:
                   1174: void
                   1175: mfi_mgmt_done(struct mfi_ccb *ccb)
                   1176: {
                   1177:        struct mfi_softc        *sc = ccb->ccb_sc;
                   1178:        struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
                   1179:
                   1180:        DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#x %#x\n",
                   1181:            DEVNAME(sc), ccb, ccb->ccb_frame);
                   1182:
                   1183:        if (ccb->ccb_data != NULL) {
                   1184:                DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n",
                   1185:                    DEVNAME(sc));
                   1186:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
                   1187:                    ccb->ccb_dmamap->dm_mapsize,
                   1188:                    (ccb->ccb_direction & MFI_DATA_IN) ?
                   1189:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                   1190:
                   1191:                bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
                   1192:        }
                   1193:
                   1194:        if (hdr->mfh_cmd_status != MFI_STAT_OK)
                   1195:                ccb->ccb_flags |= MFI_CCB_F_ERR;
                   1196:
                   1197:        ccb->ccb_state = MFI_CCB_DONE;
                   1198:
                   1199:        wakeup(ccb);
                   1200: }
                   1201:
                   1202:
                   1203: int
                   1204: mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
                   1205:     struct proc *p)
                   1206: {
                   1207:        struct mfi_softc        *sc = (struct mfi_softc *)link->adapter_softc;
                   1208:
                   1209:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_scsi_ioctl\n", DEVNAME(sc));
                   1210:
                   1211:        if (sc->sc_ioctl)
                   1212:                return (sc->sc_ioctl(link->adapter_softc, cmd, addr));
                   1213:        else
                   1214:                return (ENOTTY);
                   1215: }
                   1216:
                   1217: #if NBIO > 0
                   1218: int
                   1219: mfi_ioctl(struct device *dev, u_long cmd, caddr_t addr)
                   1220: {
                   1221:        struct mfi_softc        *sc = (struct mfi_softc *)dev;
                   1222:        int error = 0;
                   1223:
                   1224:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc));
                   1225:
                   1226:        rw_enter_write(&sc->sc_lock);
                   1227:
                   1228:        switch (cmd) {
                   1229:        case BIOCINQ:
                   1230:                DNPRINTF(MFI_D_IOCTL, "inq\n");
                   1231:                error = mfi_ioctl_inq(sc, (struct bioc_inq *)addr);
                   1232:                break;
                   1233:
                   1234:        case BIOCVOL:
                   1235:                DNPRINTF(MFI_D_IOCTL, "vol\n");
                   1236:                error = mfi_ioctl_vol(sc, (struct bioc_vol *)addr);
                   1237:                break;
                   1238:
                   1239:        case BIOCDISK:
                   1240:                DNPRINTF(MFI_D_IOCTL, "disk\n");
                   1241:                error = mfi_ioctl_disk(sc, (struct bioc_disk *)addr);
                   1242:                break;
                   1243:
                   1244:        case BIOCALARM:
                   1245:                DNPRINTF(MFI_D_IOCTL, "alarm\n");
                   1246:                error = mfi_ioctl_alarm(sc, (struct bioc_alarm *)addr);
                   1247:                break;
                   1248:
                   1249:        case BIOCBLINK:
                   1250:                DNPRINTF(MFI_D_IOCTL, "blink\n");
                   1251:                error = mfi_ioctl_blink(sc, (struct bioc_blink *)addr);
                   1252:                break;
                   1253:
                   1254:        case BIOCSETSTATE:
                   1255:                DNPRINTF(MFI_D_IOCTL, "setstate\n");
                   1256:                error = mfi_ioctl_setstate(sc, (struct bioc_setstate *)addr);
                   1257:                break;
                   1258:
                   1259:        default:
                   1260:                DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n");
                   1261:                error = EINVAL;
                   1262:        }
                   1263:
                   1264:        rw_exit_write(&sc->sc_lock);
                   1265:
                   1266:        return (error);
                   1267: }
                   1268:
                   1269: int
                   1270: mfi_ioctl_inq(struct mfi_softc *sc, struct bioc_inq *bi)
                   1271: {
                   1272:        struct mfi_conf         *cfg;
                   1273:        int                     rv = EINVAL;
                   1274:
                   1275:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq\n", DEVNAME(sc));
                   1276:
                   1277:        if (mfi_get_info(sc)) {
                   1278:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq failed\n",
                   1279:                    DEVNAME(sc));
                   1280:                return (EIO);
                   1281:        }
                   1282:
                   1283:        /* get figures */
                   1284:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
                   1285:        if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
                   1286:                goto freeme;
                   1287:
                   1288:        strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
                   1289:        bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
                   1290:        bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
                   1291:
                   1292:        rv = 0;
                   1293: freeme:
                   1294:        free(cfg, M_DEVBUF);
                   1295:        return (rv);
                   1296: }
                   1297:
                   1298: int
                   1299: mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv)
                   1300: {
                   1301:        int                     i, per, rv = EINVAL;
                   1302:        uint8_t                 mbox[MFI_MBOX_SIZE];
                   1303:
                   1304:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol %#x\n",
                   1305:            DEVNAME(sc), bv->bv_volid);
                   1306:
                   1307:        if (mfi_mgmt(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN,
                   1308:            sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL))
                   1309:                goto done;
                   1310:
                   1311:        i = bv->bv_volid;
                   1312:        mbox[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
                   1313:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol target %#x\n",
                   1314:            DEVNAME(sc), mbox[0]);
                   1315:
                   1316:        if (mfi_mgmt(sc, MR_DCMD_LD_GET_INFO, MFI_DATA_IN,
                   1317:            sizeof(sc->sc_ld_details), &sc->sc_ld_details, mbox))
                   1318:                goto done;
                   1319:
                   1320:        if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
                   1321:                /* go do hotspares */
                   1322:                rv = mfi_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
                   1323:                goto done;
                   1324:        }
                   1325:
                   1326:        strlcpy(bv->bv_dev, sc->sc_ld[i].ld_dev, sizeof(bv->bv_dev));
                   1327:
                   1328:        switch(sc->sc_ld_list.mll_list[i].mll_state) {
                   1329:        case MFI_LD_OFFLINE:
                   1330:                bv->bv_status = BIOC_SVOFFLINE;
                   1331:                break;
                   1332:
                   1333:        case MFI_LD_PART_DEGRADED:
                   1334:        case MFI_LD_DEGRADED:
                   1335:                bv->bv_status = BIOC_SVDEGRADED;
                   1336:                break;
                   1337:
                   1338:        case MFI_LD_ONLINE:
                   1339:                bv->bv_status = BIOC_SVONLINE;
                   1340:                break;
                   1341:
                   1342:        default:
                   1343:                bv->bv_status = BIOC_SVINVALID;
                   1344:                DNPRINTF(MFI_D_IOCTL, "%s: invalid logical disk state %#x\n",
                   1345:                    DEVNAME(sc),
                   1346:                    sc->sc_ld_list.mll_list[i].mll_state);
                   1347:        }
                   1348:
                   1349:        /* additional status can modify MFI status */
                   1350:        switch (sc->sc_ld_details.mld_progress.mlp_in_prog) {
                   1351:        case MFI_LD_PROG_CC:
                   1352:        case MFI_LD_PROG_BGI:
                   1353:                bv->bv_status = BIOC_SVSCRUB;
                   1354:                per = (int)sc->sc_ld_details.mld_progress.mlp_cc.mp_progress;
                   1355:                bv->bv_percent = (per * 100) / 0xffff;
                   1356:                bv->bv_seconds =
                   1357:                    sc->sc_ld_details.mld_progress.mlp_cc.mp_elapsed_seconds;
                   1358:                break;
                   1359:
                   1360:        case MFI_LD_PROG_FGI:
                   1361:        case MFI_LD_PROG_RECONSTRUCT:
                   1362:                /* nothing yet */
                   1363:                break;
                   1364:        }
                   1365:
                   1366:        /*
                   1367:         * The RAID levels are determined per the SNIA DDF spec, this is only
                   1368:         * a subset that is valid for the MFI contrller.
                   1369:         */
                   1370:        bv->bv_level = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_pri_raid;
                   1371:        if (sc->sc_ld_details.mld_cfg.mlc_parm.mpa_sec_raid ==
                   1372:            MFI_DDF_SRL_SPANNED)
                   1373:                bv->bv_level *= 10;
                   1374:
                   1375:        bv->bv_nodisk = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_no_drv_per_span *
                   1376:            sc->sc_ld_details.mld_cfg.mlc_parm.mpa_span_depth;
                   1377:
                   1378:        bv->bv_size = sc->sc_ld_details.mld_size * 512; /* bytes per block */
                   1379:
                   1380:        rv = 0;
                   1381: done:
                   1382:        return (rv);
                   1383: }
                   1384:
                   1385: int
                   1386: mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
                   1387: {
                   1388:        struct mfi_conf         *cfg;
                   1389:        struct mfi_array        *ar;
                   1390:        struct mfi_ld_cfg       *ld;
                   1391:        struct mfi_pd_details   *pd;
                   1392:        struct scsi_inquiry_data *inqbuf;
                   1393:        char                    vend[8+16+4+1];
                   1394:        int                     i, rv = EINVAL;
                   1395:        int                     arr, vol, disk;
                   1396:        uint32_t                size;
                   1397:        uint8_t                 mbox[MFI_MBOX_SIZE];
                   1398:
                   1399:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n",
                   1400:            DEVNAME(sc), bd->bd_diskid);
                   1401:
                   1402:        pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
                   1403:
                   1404:        /* send single element command to retrieve size for full structure */
                   1405:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
                   1406:        if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
                   1407:                goto freeme;
                   1408:
                   1409:        size = cfg->mfc_size;
                   1410:        free(cfg, M_DEVBUF);
                   1411:
                   1412:        /* memory for read config */
                   1413:        cfg = malloc(size, M_DEVBUF, M_WAITOK);
                   1414:        memset(cfg, 0, size);
                   1415:        if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL))
                   1416:                goto freeme;
                   1417:
                   1418:        ar = cfg->mfc_array;
                   1419:
                   1420:        /* calculate offset to ld structure */
                   1421:        ld = (struct mfi_ld_cfg *)(
                   1422:            ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
                   1423:            cfg->mfc_array_size * cfg->mfc_no_array);
                   1424:
                   1425:        vol = bd->bd_volid;
                   1426:
                   1427:        if (vol >= cfg->mfc_no_ld) {
                   1428:                /* do hotspares */
                   1429:                rv = mfi_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
                   1430:                goto freeme;
                   1431:        }
                   1432:
                   1433:        /* find corresponding array for ld */
                   1434:        for (i = 0, arr = 0; i < vol; i++)
                   1435:                arr += ld[i].mlc_parm.mpa_span_depth;
                   1436:
                   1437:        /* offset disk into pd list */
                   1438:        disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
                   1439:
                   1440:        /* offset array index into the next spans */
                   1441:        arr += bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
                   1442:
                   1443:        bd->bd_target = ar[arr].pd[disk].mar_enc_slot;
                   1444:        switch (ar[arr].pd[disk].mar_pd_state){
                   1445:        case MFI_PD_UNCONFIG_GOOD:
                   1446:                bd->bd_status = BIOC_SDUNUSED;
                   1447:                break;
                   1448:
                   1449:        case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
                   1450:                bd->bd_status = BIOC_SDHOTSPARE;
                   1451:                break;
                   1452:
                   1453:        case MFI_PD_OFFLINE:
                   1454:                bd->bd_status = BIOC_SDOFFLINE;
                   1455:                break;
                   1456:
                   1457:        case MFI_PD_FAILED:
                   1458:                bd->bd_status = BIOC_SDFAILED;
                   1459:                break;
                   1460:
                   1461:        case MFI_PD_REBUILD:
                   1462:                bd->bd_status = BIOC_SDREBUILD;
                   1463:                break;
                   1464:
                   1465:        case MFI_PD_ONLINE:
                   1466:                bd->bd_status = BIOC_SDONLINE;
                   1467:                break;
                   1468:
                   1469:        case MFI_PD_UNCONFIG_BAD: /* XXX define new state in bio */
                   1470:        default:
                   1471:                bd->bd_status = BIOC_SDINVALID;
                   1472:                break;
                   1473:
                   1474:        }
                   1475:
                   1476:        /* get the remaining fields */
                   1477:        *((uint16_t *)&mbox) = ar[arr].pd[disk].mar_pd.mfp_id;
                   1478:        if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
                   1479:            sizeof *pd, pd, mbox))
                   1480:                goto freeme;
                   1481:
                   1482:        bd->bd_size = pd->mpd_size * 512; /* bytes per block */
                   1483:
                   1484:        /* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
                   1485:        bd->bd_channel = pd->mpd_enc_idx;
                   1486:
                   1487:        inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
                   1488:        memcpy(vend, inqbuf->vendor, sizeof vend - 1);
                   1489:        vend[sizeof vend - 1] = '\0';
                   1490:        strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
                   1491:
                   1492:        /* XXX find a way to retrieve serial nr from drive */
                   1493:        /* XXX find a way to get bd_procdev */
                   1494:
                   1495:        rv = 0;
                   1496: freeme:
                   1497:        free(pd, M_DEVBUF);
                   1498:        free(cfg, M_DEVBUF);
                   1499:
                   1500:        return (rv);
                   1501: }
                   1502:
                   1503: int
                   1504: mfi_ioctl_alarm(struct mfi_softc *sc, struct bioc_alarm *ba)
                   1505: {
                   1506:        uint32_t                opc, dir = MFI_DATA_NONE;
                   1507:        int                     rv = 0;
                   1508:        int8_t                  ret;
                   1509:
                   1510:        switch(ba->ba_opcode) {
                   1511:        case BIOC_SADISABLE:
                   1512:                opc = MR_DCMD_SPEAKER_DISABLE;
                   1513:                break;
                   1514:
                   1515:        case BIOC_SAENABLE:
                   1516:                opc = MR_DCMD_SPEAKER_ENABLE;
                   1517:                break;
                   1518:
                   1519:        case BIOC_SASILENCE:
                   1520:                opc = MR_DCMD_SPEAKER_SILENCE;
                   1521:                break;
                   1522:
                   1523:        case BIOC_GASTATUS:
                   1524:                opc = MR_DCMD_SPEAKER_GET;
                   1525:                dir = MFI_DATA_IN;
                   1526:                break;
                   1527:
                   1528:        case BIOC_SATEST:
                   1529:                opc = MR_DCMD_SPEAKER_TEST;
                   1530:                break;
                   1531:
                   1532:        default:
                   1533:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_alarm biocalarm invalid "
                   1534:                    "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
                   1535:                return (EINVAL);
                   1536:        }
                   1537:
                   1538:        if (mfi_mgmt(sc, opc, dir, sizeof(ret), &ret, NULL))
                   1539:                rv = EINVAL;
                   1540:        else
                   1541:                if (ba->ba_opcode == BIOC_GASTATUS)
                   1542:                        ba->ba_status = ret;
                   1543:                else
                   1544:                        ba->ba_status = 0;
                   1545:
                   1546:        return (rv);
                   1547: }
                   1548:
                   1549: int
                   1550: mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *bb)
                   1551: {
                   1552:        int                     i, found, rv = EINVAL;
                   1553:        uint8_t                 mbox[MFI_MBOX_SIZE];
                   1554:        uint32_t                cmd;
                   1555:        struct mfi_pd_list      *pd;
                   1556:
                   1557:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc),
                   1558:            bb->bb_status);
                   1559:
                   1560:        /* channel 0 means not in an enclosure so can't be blinked */
                   1561:        if (bb->bb_channel == 0)
                   1562:                return (EINVAL);
                   1563:
                   1564:        pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK);
                   1565:
                   1566:        if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
                   1567:            MFI_PD_LIST_SIZE, pd, NULL))
                   1568:                goto done;
                   1569:
                   1570:        for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
                   1571:                if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
                   1572:                    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
                   1573:                        found = 1;
                   1574:                        break;
                   1575:                }
                   1576:
                   1577:        if (!found)
                   1578:                goto done;
                   1579:
                   1580:        memset(mbox, 0, sizeof mbox);
                   1581:
                   1582:        *((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id;
                   1583:
                   1584:        switch (bb->bb_status) {
                   1585:        case BIOC_SBUNBLINK:
                   1586:                cmd = MR_DCMD_PD_UNBLINK;
                   1587:                break;
                   1588:
                   1589:        case BIOC_SBBLINK:
                   1590:                cmd = MR_DCMD_PD_BLINK;
                   1591:                break;
                   1592:
                   1593:        case BIOC_SBALARM:
                   1594:        default:
                   1595:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink biocblink invalid "
                   1596:                    "opcode %x\n", DEVNAME(sc), bb->bb_status);
                   1597:                goto done;
                   1598:        }
                   1599:
                   1600:
                   1601:        if (mfi_mgmt(sc, cmd, MFI_DATA_NONE, 0, NULL, mbox))
                   1602:                goto done;
                   1603:
                   1604:        rv = 0;
                   1605: done:
                   1606:        free(pd, M_DEVBUF);
                   1607:        return (rv);
                   1608: }
                   1609:
                   1610: int
                   1611: mfi_ioctl_setstate(struct mfi_softc *sc, struct bioc_setstate *bs)
                   1612: {
                   1613:        struct mfi_pd_list      *pd;
                   1614:        int                     i, found, rv = EINVAL;
                   1615:        uint8_t                 mbox[MFI_MBOX_SIZE];
                   1616:        uint32_t                cmd;
                   1617:
                   1618:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc),
                   1619:            bs->bs_status);
                   1620:
                   1621:        pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK);
                   1622:
                   1623:        if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
                   1624:            MFI_PD_LIST_SIZE, pd, NULL))
                   1625:                goto done;
                   1626:
                   1627:        for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
                   1628:                if (bs->bs_channel == pd->mpl_address[i].mpa_enc_index &&
                   1629:                    bs->bs_target == pd->mpl_address[i].mpa_enc_slot) {
                   1630:                        found = 1;
                   1631:                        break;
                   1632:                }
                   1633:
                   1634:        if (!found)
                   1635:                goto done;
                   1636:
                   1637:        memset(mbox, 0, sizeof mbox);
                   1638:
                   1639:        *((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id;
                   1640:
                   1641:        switch (bs->bs_status) {
                   1642:        case BIOC_SSONLINE:
                   1643:                mbox[2] = MFI_PD_ONLINE;
                   1644:                cmd = MD_DCMD_PD_SET_STATE;
                   1645:                break;
                   1646:
                   1647:        case BIOC_SSOFFLINE:
                   1648:                mbox[2] = MFI_PD_OFFLINE;
                   1649:                cmd = MD_DCMD_PD_SET_STATE;
                   1650:                break;
                   1651:
                   1652:        case BIOC_SSHOTSPARE:
                   1653:                mbox[2] = MFI_PD_HOTSPARE;
                   1654:                cmd = MD_DCMD_PD_SET_STATE;
                   1655:                break;
                   1656: /*
                   1657:        case BIOC_SSREBUILD:
                   1658:                cmd = MD_DCMD_PD_REBUILD;
                   1659:                break;
                   1660: */
                   1661:        default:
                   1662:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate invalid "
                   1663:                    "opcode %x\n", DEVNAME(sc), bs->bs_status);
                   1664:                goto done;
                   1665:        }
                   1666:
                   1667:
                   1668:        if (mfi_mgmt(sc, MD_DCMD_PD_SET_STATE, MFI_DATA_NONE, 0, NULL, mbox))
                   1669:                goto done;
                   1670:
                   1671:        rv = 0;
                   1672: done:
                   1673:        free(pd, M_DEVBUF);
                   1674:        return (rv);
                   1675: }
                   1676:
                   1677: int
                   1678: mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
                   1679: {
                   1680:        struct mfi_conf         *cfg;
                   1681:        struct mfi_hotspare     *hs;
                   1682:        struct mfi_pd_details   *pd;
                   1683:        struct bioc_disk        *sdhs;
                   1684:        struct bioc_vol         *vdhs;
                   1685:        struct scsi_inquiry_data *inqbuf;
                   1686:        char                    vend[8+16+4+1];
                   1687:        int                     i, rv = EINVAL;
                   1688:        uint32_t                size;
                   1689:        uint8_t                 mbox[MFI_MBOX_SIZE];
                   1690:
                   1691:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs %d\n", DEVNAME(sc), volid);
                   1692:
                   1693:        if (!bio_hs)
                   1694:                return (EINVAL);
                   1695:
                   1696:        pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
                   1697:
                   1698:        /* send single element command to retrieve size for full structure */
                   1699:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
                   1700:        if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
                   1701:                goto freeme;
                   1702:
                   1703:        size = cfg->mfc_size;
                   1704:        free(cfg, M_DEVBUF);
                   1705:
                   1706:        /* memory for read config */
                   1707:        cfg = malloc(size, M_DEVBUF, M_WAITOK);
                   1708:        memset(cfg, 0, size);
                   1709:        if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL))
                   1710:                goto freeme;
                   1711:
                   1712:        /* calculate offset to hs structure */
                   1713:        hs = (struct mfi_hotspare *)(
                   1714:            ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
                   1715:            cfg->mfc_array_size * cfg->mfc_no_array +
                   1716:            cfg->mfc_ld_size * cfg->mfc_no_ld);
                   1717:
                   1718:        if (volid < cfg->mfc_no_ld)
                   1719:                goto freeme; /* not a hotspare */
                   1720:
                   1721:        if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
                   1722:                goto freeme; /* not a hotspare */
                   1723:
                   1724:        /* offset into hotspare structure */
                   1725:        i = volid - cfg->mfc_no_ld;
                   1726:
                   1727:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d "
                   1728:            "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
                   1729:            cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
                   1730:
                   1731:        /* get pd fields */
                   1732:        memset(mbox, 0, sizeof mbox);
                   1733:        *((uint16_t *)&mbox) = hs[i].mhs_pd.mfp_id;
                   1734:        if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
                   1735:            sizeof *pd, pd, mbox)) {
                   1736:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs illegal PD\n",
                   1737:                    DEVNAME(sc));
                   1738:                goto freeme;
                   1739:        }
                   1740:
                   1741:        switch (type) {
                   1742:        case MFI_MGMT_VD:
                   1743:                vdhs = bio_hs;
                   1744:                vdhs->bv_status = BIOC_SVONLINE;
                   1745:                vdhs->bv_size = pd->mpd_size / 2; /* XXX why? / 2 */
                   1746:                vdhs->bv_level = -1; /* hotspare */
                   1747:                vdhs->bv_nodisk = 1;
                   1748:                break;
                   1749:
                   1750:        case MFI_MGMT_SD:
                   1751:                sdhs = bio_hs;
                   1752:                sdhs->bd_status = BIOC_SDHOTSPARE;
                   1753:                sdhs->bd_size = pd->mpd_size / 2; /* XXX why? / 2 */
                   1754:                sdhs->bd_channel = pd->mpd_enc_idx;
                   1755:                sdhs->bd_target = pd->mpd_enc_slot;
                   1756:                inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
                   1757:                memcpy(vend, inqbuf->vendor, sizeof vend - 1);
                   1758:                vend[sizeof vend - 1] = '\0';
                   1759:                strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
                   1760:                break;
                   1761:
                   1762:        default:
                   1763:                goto freeme;
                   1764:        }
                   1765:
                   1766:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs 6\n", DEVNAME(sc));
                   1767:        rv = 0;
                   1768: freeme:
                   1769:        free(pd, M_DEVBUF);
                   1770:        free(cfg, M_DEVBUF);
                   1771:
                   1772:        return (rv);
                   1773: }
                   1774:
                   1775: #ifndef SMALL_KERNEL
                   1776: int
                   1777: mfi_create_sensors(struct mfi_softc *sc)
                   1778: {
                   1779:        struct device           *dev;
                   1780:        struct scsibus_softc    *ssc;
                   1781:        int                     i;
                   1782:
                   1783:        TAILQ_FOREACH(dev, &alldevs, dv_list) {
                   1784:                if (dev->dv_parent != &sc->sc_dev)
                   1785:                        continue;
                   1786:
                   1787:                /* check if this is the scsibus for the logical disks */
                   1788:                ssc = (struct scsibus_softc *)dev;
                   1789:                if (ssc->adapter_link == &sc->sc_link)
                   1790:                        break;
                   1791:        }
                   1792:
                   1793:        if (ssc == NULL)
                   1794:                return (1);
                   1795:
                   1796:        sc->sc_sensors = malloc(sizeof(struct ksensor) * sc->sc_ld_cnt,
                   1797:            M_DEVBUF, M_WAITOK);
                   1798:        if (sc->sc_sensors == NULL)
                   1799:                return (1);
                   1800:        bzero(sc->sc_sensors, sizeof(struct ksensor) * sc->sc_ld_cnt);
                   1801:
                   1802:        strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
                   1803:            sizeof(sc->sc_sensordev.xname));
                   1804:
                   1805:        for (i = 0; i < sc->sc_ld_cnt; i++) {
                   1806:                if (ssc->sc_link[i][0] == NULL)
                   1807:                        goto bad;
                   1808:
                   1809:                dev = ssc->sc_link[i][0]->device_softc;
                   1810:
                   1811:                sc->sc_sensors[i].type = SENSOR_DRIVE;
                   1812:                sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
                   1813:
                   1814:                strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
                   1815:                    sizeof(sc->sc_sensors[i].desc));
                   1816:
                   1817:                sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
                   1818:        }
                   1819:
                   1820:        if (sensor_task_register(sc, mfi_refresh_sensors, 10) == NULL)
                   1821:                goto bad;
                   1822:
                   1823:        sensordev_install(&sc->sc_sensordev);
                   1824:
                   1825:        return (0);
                   1826:
                   1827: bad:
                   1828:        free(sc->sc_sensors, M_DEVBUF);
                   1829:
                   1830:        return (1);
                   1831: }
                   1832:
                   1833: void
                   1834: mfi_refresh_sensors(void *arg)
                   1835: {
                   1836:        struct mfi_softc        *sc = arg;
                   1837:        int                     i;
                   1838:        struct bioc_vol         bv;
                   1839:
                   1840:
                   1841:        for (i = 0; i < sc->sc_ld_cnt; i++) {
                   1842:                bzero(&bv, sizeof(bv));
                   1843:                bv.bv_volid = i;
                   1844:                if (mfi_ioctl_vol(sc, &bv))
                   1845:                        return;
                   1846:
                   1847:                switch(bv.bv_status) {
                   1848:                case BIOC_SVOFFLINE:
                   1849:                        sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
                   1850:                        sc->sc_sensors[i].status = SENSOR_S_CRIT;
                   1851:                        break;
                   1852:
                   1853:                case BIOC_SVDEGRADED:
                   1854:                        sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
                   1855:                        sc->sc_sensors[i].status = SENSOR_S_WARN;
                   1856:                        break;
                   1857:
                   1858:                case BIOC_SVSCRUB:
                   1859:                case BIOC_SVONLINE:
                   1860:                        sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
                   1861:                        sc->sc_sensors[i].status = SENSOR_S_OK;
                   1862:                        break;
                   1863:
                   1864:                case BIOC_SVINVALID:
                   1865:                        /* FALLTRHOUGH */
                   1866:                default:
                   1867:                        sc->sc_sensors[i].value = 0; /* unknown */
                   1868:                        sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
                   1869:                }
                   1870:
                   1871:        }
                   1872: }
                   1873: #endif /* SMALL_KERNEL */
                   1874: #endif /* NBIO > 0 */

CVSweb