[BACK]Return to mfi.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Annotation of src/sys/dev/ic/mfi.c, Revision 1.76

1.76    ! msaitoh     1: /* $NetBSD: mfi.c,v 1.75 2022/05/10 14:13:37 msaitoh Exp $ */
1.1       bouyer      2: /* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */
1.43      bouyer      3:
                      4: /*
                      5:  * Copyright (c) 2012 Manuel Bouyer.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
1.1       bouyer     28: /*
                     29:  * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
                     30:  *
                     31:  * Permission to use, copy, modify, and distribute this software for any
                     32:  * purpose with or without fee is hereby granted, provided that the above
                     33:  * copyright notice and this permission notice appear in all copies.
                     34:  *
                     35:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     36:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     37:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     38:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     39:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     40:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     41:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     42:  */
                     43:
1.43      bouyer     44:  /*-
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  *
                     49:  *            Copyright 1994-2009 The FreeBSD Project.
                     50:  *            All rights reserved.
                     51:  *
                     52:  * 1. Redistributions of source code must retain the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer.
                     54:  * 2. Redistributions in binary form must reproduce the above copyright
                     55:  *    notice, this list of conditions and the following disclaimer in the
                     56:  *    documentation and/or other materials provided with the distribution.
                     57:  *
                     58:  *    THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND
                     59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                     60:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     61:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FREEBSD PROJECT OR
                     62:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     63:  * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     64:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                     65:  * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY
                     66:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     67:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     68:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     69:  *
                     70:  * The views and conclusions contained in the software and documentation
                     71:  * are those of the authors and should not be interpreted as representing
                     72:  * official policies,either expressed or implied, of the FreeBSD Project.
                     73:  */
                     74:
1.2       bouyer     75: #include <sys/cdefs.h>
1.76    ! msaitoh    76: __KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.75 2022/05/10 14:13:37 msaitoh Exp $");
1.2       bouyer     77:
1.4       bouyer     78: #include "bio.h"
1.1       bouyer     79:
                     80: #include <sys/param.h>
                     81: #include <sys/systm.h>
                     82: #include <sys/buf.h>
                     83: #include <sys/ioctl.h>
                     84: #include <sys/device.h>
                     85: #include <sys/kernel.h>
                     86: #include <sys/malloc.h>
                     87: #include <sys/proc.h>
1.43      bouyer     88: #include <sys/cpu.h>
1.47      bouyer     89: #include <sys/conf.h>
                     90: #include <sys/kauth.h>
1.1       bouyer     91:
                     92: #include <uvm/uvm_param.h>
                     93:
1.10      ad         94: #include <sys/bus.h>
1.1       bouyer     95:
                     96: #include <dev/scsipi/scsipi_all.h>
                     97: #include <dev/scsipi/scsi_all.h>
                     98: #include <dev/scsipi/scsi_spc.h>
                     99: #include <dev/scsipi/scsipi_disk.h>
                    100: #include <dev/scsipi/scsi_disk.h>
                    101: #include <dev/scsipi/scsiconf.h>
                    102:
                    103: #include <dev/ic/mfireg.h>
                    104: #include <dev/ic/mfivar.h>
1.47      bouyer    105: #include <dev/ic/mfiio.h>
1.1       bouyer    106:
                    107: #if NBIO > 0
                    108: #include <dev/biovar.h>
                    109: #endif /* NBIO > 0 */
                    110:
1.58      riastrad  111: #include "ioconf.h"
                    112:
1.1       bouyer    113: #ifdef MFI_DEBUG
                    114: uint32_t       mfi_debug = 0
1.73      msaitoh   115: /*                 | MFI_D_CMD */
1.1       bouyer    116: /*                 | MFI_D_INTR */
                    117: /*                 | MFI_D_MISC */
                    118: /*                 | MFI_D_DMA */
1.43      bouyer    119: /*                 | MFI_D_IOCTL */
1.1       bouyer    120: /*                 | MFI_D_RW */
                    121: /*                 | MFI_D_MEM */
                    122: /*                 | MFI_D_CCB */
1.43      bouyer    123: /*                 | MFI_D_SYNC */
1.1       bouyer    124:                ;
                    125: #endif
                    126:
1.13      xtraeme   127: static void            mfi_scsipi_request(struct scsipi_channel *,
                    128:                                scsipi_adapter_req_t, void *);
                    129: static void            mfiminphys(struct buf *bp);
                    130:
                    131: static struct mfi_ccb  *mfi_get_ccb(struct mfi_softc *);
                    132: static void            mfi_put_ccb(struct mfi_ccb *);
                    133: static int             mfi_init_ccb(struct mfi_softc *);
                    134:
                    135: static struct mfi_mem  *mfi_allocmem(struct mfi_softc *, size_t);
1.27      dyoung    136: static void            mfi_freemem(struct mfi_softc *, struct mfi_mem **);
1.13      xtraeme   137:
                    138: static int             mfi_transition_firmware(struct mfi_softc *);
                    139: static int             mfi_initialize_firmware(struct mfi_softc *);
                    140: static int             mfi_get_info(struct mfi_softc *);
1.45      bouyer    141: static int             mfi_get_bbu(struct mfi_softc *,
                    142:                            struct mfi_bbu_status *);
                    143: /* return codes for mfi_get_bbu */
                    144: #define MFI_BBU_GOOD   0
                    145: #define MFI_BBU_BAD    1
                    146: #define MFI_BBU_UNKNOWN        2
1.13      xtraeme   147: static uint32_t                mfi_read(struct mfi_softc *, bus_size_t);
                    148: static void            mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
                    149: static int             mfi_poll(struct mfi_ccb *);
                    150: static int             mfi_create_sgl(struct mfi_ccb *, int);
1.1       bouyer    151:
                    152: /* commands */
1.13      xtraeme   153: static int             mfi_scsi_ld(struct mfi_ccb *, struct scsipi_xfer *);
1.43      bouyer    154: static int             mfi_scsi_ld_io(struct mfi_ccb *, struct scsipi_xfer *,
                    155:                                uint64_t, uint32_t);
                    156: static void            mfi_scsi_ld_done(struct mfi_ccb *);
                    157: static void            mfi_scsi_xs_done(struct mfi_ccb *, int, int);
1.45      bouyer    158: static int             mfi_mgmt_internal(struct mfi_softc *, uint32_t,
1.74      msaitoh   159:                            uint32_t, uint32_t, void *, const union mfi_mbox *,
                    160:                            bool);
1.19      bouyer    161: static int             mfi_mgmt(struct mfi_ccb *,struct scsipi_xfer *,
1.74      msaitoh   162:                            uint32_t, uint32_t, uint32_t, void *,
                    163:                            const union mfi_mbox *);
1.13      xtraeme   164: static void            mfi_mgmt_done(struct mfi_ccb *);
1.1       bouyer    165:
                    166: #if NBIO > 0
1.23      cegger    167: static int             mfi_ioctl(device_t, u_long, void *);
1.13      xtraeme   168: static int             mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *);
                    169: static int             mfi_ioctl_vol(struct mfi_softc *, struct bioc_vol *);
                    170: static int             mfi_ioctl_disk(struct mfi_softc *, struct bioc_disk *);
                    171: static int             mfi_ioctl_alarm(struct mfi_softc *,
                    172:                                struct bioc_alarm *);
                    173: static int             mfi_ioctl_blink(struct mfi_softc *sc,
                    174:                                struct bioc_blink *);
                    175: static int             mfi_ioctl_setstate(struct mfi_softc *,
                    176:                                struct bioc_setstate *);
                    177: static int             mfi_bio_hs(struct mfi_softc *, int, int, void *);
                    178: static int             mfi_create_sensors(struct mfi_softc *);
1.24      dyoung    179: static int             mfi_destroy_sensors(struct mfi_softc *);
1.13      xtraeme   180: static void            mfi_sensor_refresh(struct sysmon_envsys *,
                    181:                                envsys_data_t *);
1.1       bouyer    182: #endif /* NBIO > 0 */
1.45      bouyer    183: static bool            mfi_shutdown(device_t, int);
                    184: static bool            mfi_suspend(device_t, const pmf_qual_t *);
                    185: static bool            mfi_resume(device_t, const pmf_qual_t *);
1.1       bouyer    186:
1.47      bouyer    187: static dev_type_open(mfifopen);
                    188: static dev_type_close(mfifclose);
                    189: static dev_type_ioctl(mfifioctl);
                    190: const struct cdevsw mfi_cdevsw = {
1.52      dholland  191:        .d_open = mfifopen,
                    192:        .d_close = mfifclose,
                    193:        .d_read = noread,
                    194:        .d_write = nowrite,
                    195:        .d_ioctl = mfifioctl,
                    196:        .d_stop = nostop,
                    197:        .d_tty = notty,
                    198:        .d_poll = nopoll,
                    199:        .d_mmap = nommap,
                    200:        .d_kqfilter = nokqfilter,
1.53      dholland  201:        .d_discard = nodiscard,
1.52      dholland  202:        .d_flag = D_OTHER
1.47      bouyer    203: };
                    204:
1.13      xtraeme   205: static uint32_t        mfi_xscale_fw_state(struct mfi_softc *sc);
1.73      msaitoh   206: static void            mfi_xscale_intr_ena(struct mfi_softc *sc);
                    207: static void            mfi_xscale_intr_dis(struct mfi_softc *sc);
                    208: static int             mfi_xscale_intr(struct mfi_softc *sc);
                    209: static void            mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
1.30      dyoung    210:
1.12      xtraeme   211: static const struct mfi_iop_ops mfi_iop_xscale = {
                    212:        mfi_xscale_fw_state,
1.24      dyoung    213:        mfi_xscale_intr_dis,
1.12      xtraeme   214:        mfi_xscale_intr_ena,
                    215:        mfi_xscale_intr,
1.43      bouyer    216:        mfi_xscale_post,
                    217:        mfi_scsi_ld_io,
1.12      xtraeme   218: };
1.30      dyoung    219:
1.13      xtraeme   220: static uint32_t        mfi_ppc_fw_state(struct mfi_softc *sc);
1.73      msaitoh   221: static void            mfi_ppc_intr_ena(struct mfi_softc *sc);
                    222: static void            mfi_ppc_intr_dis(struct mfi_softc *sc);
                    223: static int             mfi_ppc_intr(struct mfi_softc *sc);
                    224: static void            mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
1.30      dyoung    225:
1.12      xtraeme   226: static const struct mfi_iop_ops mfi_iop_ppc = {
                    227:        mfi_ppc_fw_state,
1.24      dyoung    228:        mfi_ppc_intr_dis,
1.12      xtraeme   229:        mfi_ppc_intr_ena,
                    230:        mfi_ppc_intr,
1.43      bouyer    231:        mfi_ppc_post,
                    232:        mfi_scsi_ld_io,
1.12      xtraeme   233: };
1.30      dyoung    234:
1.33      msaitoh   235: uint32_t       mfi_gen2_fw_state(struct mfi_softc *sc);
                    236: void           mfi_gen2_intr_ena(struct mfi_softc *sc);
                    237: void           mfi_gen2_intr_dis(struct mfi_softc *sc);
                    238: int            mfi_gen2_intr(struct mfi_softc *sc);
                    239: void           mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
                    240:
                    241: static const struct mfi_iop_ops mfi_iop_gen2 = {
                    242:        mfi_gen2_fw_state,
                    243:        mfi_gen2_intr_dis,
                    244:        mfi_gen2_intr_ena,
                    245:        mfi_gen2_intr,
1.43      bouyer    246:        mfi_gen2_post,
                    247:        mfi_scsi_ld_io,
1.33      msaitoh   248: };
                    249:
1.38      sborrill  250: u_int32_t      mfi_skinny_fw_state(struct mfi_softc *);
                    251: void           mfi_skinny_intr_dis(struct mfi_softc *);
                    252: void           mfi_skinny_intr_ena(struct mfi_softc *);
                    253: int            mfi_skinny_intr(struct mfi_softc *);
                    254: void           mfi_skinny_post(struct mfi_softc *, struct mfi_ccb *);
                    255:
                    256: static const struct mfi_iop_ops mfi_iop_skinny = {
                    257:        mfi_skinny_fw_state,
                    258:        mfi_skinny_intr_dis,
                    259:        mfi_skinny_intr_ena,
                    260:        mfi_skinny_intr,
1.43      bouyer    261:        mfi_skinny_post,
                    262:        mfi_scsi_ld_io,
                    263: };
                    264:
                    265: static int     mfi_tbolt_init_desc_pool(struct mfi_softc *);
                    266: static int     mfi_tbolt_init_MFI_queue(struct mfi_softc *);
                    267: static void    mfi_tbolt_build_mpt_ccb(struct mfi_ccb *);
                    268: int            mfi_tbolt_scsi_ld_io(struct mfi_ccb *, struct scsipi_xfer *,
                    269:                    uint64_t, uint32_t);
                    270: static void    mfi_tbolt_scsi_ld_done(struct mfi_ccb *);
                    271: static int     mfi_tbolt_create_sgl(struct mfi_ccb *, int);
                    272: void           mfi_tbolt_sync_map_info(struct work *, void *);
                    273: static void    mfi_sync_map_complete(struct mfi_ccb *);
                    274:
                    275: u_int32_t      mfi_tbolt_fw_state(struct mfi_softc *);
                    276: void           mfi_tbolt_intr_dis(struct mfi_softc *);
                    277: void           mfi_tbolt_intr_ena(struct mfi_softc *);
                    278: int            mfi_tbolt_intr(struct mfi_softc *sc);
                    279: void           mfi_tbolt_post(struct mfi_softc *, struct mfi_ccb *);
                    280:
                    281: static const struct mfi_iop_ops mfi_iop_tbolt = {
                    282:        mfi_tbolt_fw_state,
                    283:        mfi_tbolt_intr_dis,
                    284:        mfi_tbolt_intr_ena,
                    285:        mfi_tbolt_intr,
                    286:        mfi_tbolt_post,
                    287:        mfi_tbolt_scsi_ld_io,
1.38      sborrill  288: };
                    289:
1.73      msaitoh   290: #define mfi_fw_state(_s)       ((_s)->sc_iop->mio_fw_state(_s))
                    291: #define mfi_intr_enable(_s)    ((_s)->sc_iop->mio_intr_ena(_s))
                    292: #define mfi_intr_disable(_s)   ((_s)->sc_iop->mio_intr_dis(_s))
                    293: #define mfi_my_intr(_s)                ((_s)->sc_iop->mio_intr(_s))
                    294: #define mfi_post(_s, _c)       ((_s)->sc_iop->mio_post((_s), (_c)))
1.12      xtraeme   295:
1.13      xtraeme   296: static struct mfi_ccb *
1.1       bouyer    297: mfi_get_ccb(struct mfi_softc *sc)
                    298: {
                    299:        struct mfi_ccb          *ccb;
                    300:        int                     s;
                    301:
                    302:        s = splbio();
                    303:        ccb = TAILQ_FIRST(&sc->sc_ccb_freeq);
                    304:        if (ccb) {
                    305:                TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link);
                    306:                ccb->ccb_state = MFI_CCB_READY;
                    307:        }
                    308:        splx(s);
                    309:
                    310:        DNPRINTF(MFI_D_CCB, "%s: mfi_get_ccb: %p\n", DEVNAME(sc), ccb);
1.45      bouyer    311:        if (__predict_false(ccb == NULL && sc->sc_running))
1.43      bouyer    312:                aprint_error_dev(sc->sc_dev, "out of ccb\n");
1.1       bouyer    313:
1.13      xtraeme   314:        return ccb;
1.1       bouyer    315: }
                    316:
1.13      xtraeme   317: static void
1.1       bouyer    318: mfi_put_ccb(struct mfi_ccb *ccb)
                    319: {
                    320:        struct mfi_softc        *sc = ccb->ccb_sc;
1.37      sborrill  321:        struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
1.1       bouyer    322:        int                     s;
                    323:
                    324:        DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb);
                    325:
1.37      sborrill  326:        hdr->mfh_cmd_status = 0x0;
                    327:        hdr->mfh_flags = 0x0;
1.1       bouyer    328:        ccb->ccb_state = MFI_CCB_FREE;
                    329:        ccb->ccb_xs = NULL;
                    330:        ccb->ccb_flags = 0;
                    331:        ccb->ccb_done = NULL;
                    332:        ccb->ccb_direction = 0;
                    333:        ccb->ccb_frame_size = 0;
                    334:        ccb->ccb_extra_frames = 0;
                    335:        ccb->ccb_sgl = NULL;
                    336:        ccb->ccb_data = NULL;
                    337:        ccb->ccb_len = 0;
1.43      bouyer    338:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                    339:                /* erase tb_request_desc but preserve SMID */
                    340:                int index = ccb->ccb_tb_request_desc.header.SMID;
                    341:                ccb->ccb_tb_request_desc.words = 0;
                    342:                ccb->ccb_tb_request_desc.header.SMID = index;
                    343:        }
1.37      sborrill  344:        s = splbio();
1.1       bouyer    345:        TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link);
                    346:        splx(s);
                    347: }
                    348:
1.13      xtraeme   349: static int
1.24      dyoung    350: mfi_destroy_ccb(struct mfi_softc *sc)
                    351: {
                    352:        struct mfi_ccb          *ccb;
                    353:        uint32_t                i;
                    354:
1.43      bouyer    355:        DNPRINTF(MFI_D_CCB, "%s: mfi_destroy_ccb\n", DEVNAME(sc));
1.24      dyoung    356:
                    357:
                    358:        for (i = 0; (ccb = mfi_get_ccb(sc)) != NULL; i++) {
                    359:                /* create a dma map for transfer */
1.43      bouyer    360:                bus_dmamap_destroy(sc->sc_datadmat, ccb->ccb_dmamap);
1.24      dyoung    361:        }
                    362:
                    363:        if (i < sc->sc_max_cmds)
                    364:                return EBUSY;
                    365:
                    366:        free(sc->sc_ccb, M_DEVBUF);
                    367:
                    368:        return 0;
                    369: }
                    370:
                    371: static int
1.1       bouyer    372: mfi_init_ccb(struct mfi_softc *sc)
                    373: {
                    374:        struct mfi_ccb          *ccb;
                    375:        uint32_t                i;
                    376:        int                     error;
1.43      bouyer    377:        bus_addr_t              io_req_base_phys;
                    378:        uint8_t                 *io_req_base;
                    379:        int offset;
1.1       bouyer    380:
                    381:        DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc));
                    382:
                    383:        sc->sc_ccb = malloc(sizeof(struct mfi_ccb) * sc->sc_max_cmds,
1.13      xtraeme   384:            M_DEVBUF, M_WAITOK|M_ZERO);
1.43      bouyer    385:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                    386:                /*
                    387:                 * The first 256 bytes (SMID 0) is not used.
                    388:                 * Don't add to the cmd list.
                    389:                 */
1.54      christos  390:                io_req_base = (uint8_t *)MFIMEM_KVA(sc->sc_tbolt_reqmsgpool) +
                    391:                    MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
                    392:                io_req_base_phys = MFIMEM_DVA(sc->sc_tbolt_reqmsgpool) +
                    393:                    MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
1.55      christos  394:        } else {
                    395:                io_req_base = NULL;     /* XXX: gcc */
                    396:                io_req_base_phys = 0;   /* XXX: gcc */
1.43      bouyer    397:        }
1.1       bouyer    398:
                    399:        for (i = 0; i < sc->sc_max_cmds; i++) {
                    400:                ccb = &sc->sc_ccb[i];
                    401:
                    402:                ccb->ccb_sc = sc;
                    403:
                    404:                /* select i'th frame */
                    405:                ccb->ccb_frame = (union mfi_frame *)
                    406:                    ((char*)MFIMEM_KVA(sc->sc_frames) + sc->sc_frames_size * i);
                    407:                ccb->ccb_pframe =
                    408:                    MFIMEM_DVA(sc->sc_frames) + sc->sc_frames_size * i;
                    409:                ccb->ccb_frame->mfr_header.mfh_context = i;
                    410:
                    411:                /* select i'th sense */
                    412:                ccb->ccb_sense = (struct mfi_sense *)
                    413:                    ((char*)MFIMEM_KVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
                    414:                ccb->ccb_psense =
                    415:                    (MFIMEM_DVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
                    416:
                    417:                /* create a dma map for transfer */
1.43      bouyer    418:                error = bus_dmamap_create(sc->sc_datadmat,
1.1       bouyer    419:                    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
                    420:                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
                    421:                if (error) {
1.43      bouyer    422:                        aprint_error_dev(sc->sc_dev,
                    423:                            "cannot create ccb dmamap (%d)\n", error);
1.1       bouyer    424:                        goto destroy;
                    425:                }
1.43      bouyer    426:                if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                    427:                        offset = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * i;
                    428:                        ccb->ccb_tb_io_request =
                    429:                            (struct mfi_mpi2_request_raid_scsi_io *)
                    430:                            (io_req_base + offset);
                    431:                        ccb->ccb_tb_pio_request =
                    432:                            io_req_base_phys + offset;
                    433:                        offset = MEGASAS_MAX_SZ_CHAIN_FRAME * i;
                    434:                        ccb->ccb_tb_sg_frame =
                    435:                            (mpi2_sge_io_union *)(sc->sc_reply_pool_limit +
                    436:                            offset);
                    437:                        ccb->ccb_tb_psg_frame = sc->sc_sg_frame_busaddr +
                    438:                            offset;
                    439:                        /* SMID 0 is reserved. Set SMID/index from 1 */
                    440:                        ccb->ccb_tb_request_desc.header.SMID = i + 1;
                    441:                }
1.1       bouyer    442:
                    443:                DNPRINTF(MFI_D_CCB,
1.4       bouyer    444:                    "ccb(%d): %p frame: %#lx (%#lx) sense: %#lx (%#lx) map: %#lx\n",
1.1       bouyer    445:                    ccb->ccb_frame->mfr_header.mfh_context, ccb,
1.4       bouyer    446:                    (u_long)ccb->ccb_frame, (u_long)ccb->ccb_pframe,
                    447:                    (u_long)ccb->ccb_sense, (u_long)ccb->ccb_psense,
                    448:                    (u_long)ccb->ccb_dmamap);
1.1       bouyer    449:
                    450:                /* add ccb to queue */
                    451:                mfi_put_ccb(ccb);
                    452:        }
                    453:
1.13      xtraeme   454:        return 0;
1.1       bouyer    455: destroy:
                    456:        /* free dma maps and ccb memory */
1.17      cegger    457:        while (i) {
                    458:                i--;
1.1       bouyer    459:                ccb = &sc->sc_ccb[i];
1.43      bouyer    460:                bus_dmamap_destroy(sc->sc_datadmat, ccb->ccb_dmamap);
1.1       bouyer    461:        }
                    462:
                    463:        free(sc->sc_ccb, M_DEVBUF);
                    464:
1.13      xtraeme   465:        return 1;
1.1       bouyer    466: }
                    467:
1.13      xtraeme   468: static uint32_t
1.1       bouyer    469: mfi_read(struct mfi_softc *sc, bus_size_t r)
                    470: {
                    471:        uint32_t rv;
                    472:
                    473:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                    474:            BUS_SPACE_BARRIER_READ);
                    475:        rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
                    476:
1.4       bouyer    477:        DNPRINTF(MFI_D_RW, "%s: mr 0x%lx 0x08%x ", DEVNAME(sc), (u_long)r, rv);
1.13      xtraeme   478:        return rv;
1.1       bouyer    479: }
                    480:
1.13      xtraeme   481: static void
1.1       bouyer    482: mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v)
                    483: {
1.4       bouyer    484:        DNPRINTF(MFI_D_RW, "%s: mw 0x%lx 0x%08x", DEVNAME(sc), (u_long)r, v);
1.1       bouyer    485:
                    486:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
                    487:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                    488:            BUS_SPACE_BARRIER_WRITE);
                    489: }
                    490:
1.13      xtraeme   491: static struct mfi_mem *
1.1       bouyer    492: mfi_allocmem(struct mfi_softc *sc, size_t size)
                    493: {
                    494:        struct mfi_mem          *mm;
                    495:        int                     nsegs;
                    496:
1.4       bouyer    497:        DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %ld\n", DEVNAME(sc),
                    498:            (long)size);
1.1       bouyer    499:
1.62      chs       500:        mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_WAITOK|M_ZERO);
1.1       bouyer    501:        mm->am_size = size;
                    502:
                    503:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                    504:            BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0)
1.30      dyoung    505:                goto amfree;
1.1       bouyer    506:
                    507:        if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1,
                    508:            &nsegs, BUS_DMA_NOWAIT) != 0)
                    509:                goto destroy;
                    510:
                    511:        if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva,
                    512:            BUS_DMA_NOWAIT) != 0)
                    513:                goto free;
                    514:
                    515:        if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL,
                    516:            BUS_DMA_NOWAIT) != 0)
                    517:                goto unmap;
                    518:
                    519:        DNPRINTF(MFI_D_MEM, "  kva: %p  dva: %p  map: %p\n",
1.4       bouyer    520:            mm->am_kva, (void *)mm->am_map->dm_segs[0].ds_addr, mm->am_map);
1.1       bouyer    521:
                    522:        memset(mm->am_kva, 0, size);
1.13      xtraeme   523:        return mm;
1.1       bouyer    524:
                    525: unmap:
                    526:        bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size);
                    527: free:
                    528:        bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
                    529: destroy:
                    530:        bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
                    531: amfree:
                    532:        free(mm, M_DEVBUF);
                    533:
1.13      xtraeme   534:        return NULL;
1.1       bouyer    535: }
                    536:
1.13      xtraeme   537: static void
1.27      dyoung    538: mfi_freemem(struct mfi_softc *sc, struct mfi_mem **mmp)
1.1       bouyer    539: {
1.27      dyoung    540:        struct mfi_mem *mm = *mmp;
                    541:
                    542:        if (mm == NULL)
                    543:                return;
                    544:
                    545:        *mmp = NULL;
                    546:
1.1       bouyer    547:        DNPRINTF(MFI_D_MEM, "%s: mfi_freemem: %p\n", DEVNAME(sc), mm);
                    548:
                    549:        bus_dmamap_unload(sc->sc_dmat, mm->am_map);
                    550:        bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size);
                    551:        bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
                    552:        bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
                    553:        free(mm, M_DEVBUF);
                    554: }
                    555:
1.13      xtraeme   556: static int
1.1       bouyer    557: mfi_transition_firmware(struct mfi_softc *sc)
                    558: {
1.18      gmcgarry  559:        uint32_t                fw_state, cur_state;
1.1       bouyer    560:        int                     max_wait, i;
                    561:
1.12      xtraeme   562:        fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
1.1       bouyer    563:
                    564:        DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc),
                    565:            fw_state);
                    566:
                    567:        while (fw_state != MFI_STATE_READY) {
                    568:                DNPRINTF(MFI_D_MISC,
                    569:                    "%s: waiting for firmware to become ready\n",
                    570:                    DEVNAME(sc));
                    571:                cur_state = fw_state;
                    572:                switch (fw_state) {
                    573:                case MFI_STATE_FAULT:
1.43      bouyer    574:                        aprint_error_dev(sc->sc_dev, "firmware fault\n");
1.13      xtraeme   575:                        return 1;
1.1       bouyer    576:                case MFI_STATE_WAIT_HANDSHAKE:
1.43      bouyer    577:                        if (sc->sc_ioptype == MFI_IOP_SKINNY ||
                    578:                            sc->sc_ioptype == MFI_IOP_TBOLT)
1.38      sborrill  579:                                mfi_write(sc, MFI_SKINNY_IDB, MFI_INIT_CLEAR_HANDSHAKE);
                    580:                        else
                    581:                                mfi_write(sc, MFI_IDB, MFI_INIT_CLEAR_HANDSHAKE);
1.1       bouyer    582:                        max_wait = 2;
                    583:                        break;
                    584:                case MFI_STATE_OPERATIONAL:
1.43      bouyer    585:                        if (sc->sc_ioptype == MFI_IOP_SKINNY ||
                    586:                            sc->sc_ioptype == MFI_IOP_TBOLT)
1.69      msaitoh   587:                                mfi_write(sc, MFI_SKINNY_IDB, MFI_RESET_FLAGS);
1.38      sborrill  588:                        else
                    589:                                mfi_write(sc, MFI_IDB, MFI_INIT_READY);
1.1       bouyer    590:                        max_wait = 10;
                    591:                        break;
                    592:                case MFI_STATE_UNDEFINED:
                    593:                case MFI_STATE_BB_INIT:
                    594:                        max_wait = 2;
                    595:                        break;
                    596:                case MFI_STATE_FW_INIT:
                    597:                case MFI_STATE_DEVICE_SCAN:
                    598:                case MFI_STATE_FLUSH_CACHE:
                    599:                        max_wait = 20;
                    600:                        break;
1.43      bouyer    601:                case MFI_STATE_BOOT_MESSAGE_PENDING:
1.48      bouyer    602:                        if (sc->sc_ioptype == MFI_IOP_SKINNY ||
                    603:                            sc->sc_ioptype == MFI_IOP_TBOLT) {
1.43      bouyer    604:                                mfi_write(sc, MFI_SKINNY_IDB, MFI_INIT_HOTPLUG);
1.48      bouyer    605:                        } else {
                    606:                                mfi_write(sc, MFI_IDB, MFI_INIT_HOTPLUG);
1.43      bouyer    607:                        }
1.48      bouyer    608:                        max_wait = 180;
                    609:                        break;
1.1       bouyer    610:                default:
1.43      bouyer    611:                        aprint_error_dev(sc->sc_dev,
                    612:                            "unknown firmware state %d\n", fw_state);
1.13      xtraeme   613:                        return 1;
1.1       bouyer    614:                }
                    615:                for (i = 0; i < (max_wait * 10); i++) {
1.12      xtraeme   616:                        fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
1.1       bouyer    617:                        if (fw_state == cur_state)
                    618:                                DELAY(100000);
                    619:                        else
                    620:                                break;
                    621:                }
                    622:                if (fw_state == cur_state) {
1.43      bouyer    623:                        aprint_error_dev(sc->sc_dev,
                    624:                            "firmware stuck in state %#x\n", fw_state);
1.13      xtraeme   625:                        return 1;
1.1       bouyer    626:                }
                    627:        }
                    628:
1.13      xtraeme   629:        return 0;
1.1       bouyer    630: }
                    631:
1.13      xtraeme   632: static int
1.1       bouyer    633: mfi_initialize_firmware(struct mfi_softc *sc)
                    634: {
                    635:        struct mfi_ccb          *ccb;
                    636:        struct mfi_init_frame   *init;
                    637:        struct mfi_init_qinfo   *qinfo;
                    638:
                    639:        DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc));
                    640:
                    641:        if ((ccb = mfi_get_ccb(sc)) == NULL)
1.13      xtraeme   642:                return 1;
1.1       bouyer    643:
                    644:        init = &ccb->ccb_frame->mfr_init;
                    645:        qinfo = (struct mfi_init_qinfo *)((uint8_t *)init + MFI_FRAME_SIZE);
                    646:
                    647:        memset(qinfo, 0, sizeof *qinfo);
                    648:        qinfo->miq_rq_entries = sc->sc_max_cmds + 1;
                    649:        qinfo->miq_rq_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    650:            offsetof(struct mfi_prod_cons, mpc_reply_q));
                    651:        qinfo->miq_pi_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    652:            offsetof(struct mfi_prod_cons, mpc_producer));
                    653:        qinfo->miq_ci_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
                    654:            offsetof(struct mfi_prod_cons, mpc_consumer));
                    655:
                    656:        init->mif_header.mfh_cmd = MFI_CMD_INIT;
                    657:        init->mif_header.mfh_data_len = sizeof *qinfo;
                    658:        init->mif_qinfo_new_addr_lo = htole32(ccb->ccb_pframe + MFI_FRAME_SIZE);
                    659:
                    660:        DNPRINTF(MFI_D_MISC, "%s: entries: %#x rq: %#x pi: %#x ci: %#x\n",
                    661:            DEVNAME(sc),
                    662:            qinfo->miq_rq_entries, qinfo->miq_rq_addr_lo,
                    663:            qinfo->miq_pi_addr_lo, qinfo->miq_ci_addr_lo);
                    664:
                    665:        if (mfi_poll(ccb)) {
1.43      bouyer    666:                aprint_error_dev(sc->sc_dev,
                    667:                    "mfi_initialize_firmware failed\n");
1.13      xtraeme   668:                return 1;
1.1       bouyer    669:        }
                    670:
                    671:        mfi_put_ccb(ccb);
                    672:
1.13      xtraeme   673:        return 0;
1.1       bouyer    674: }
                    675:
1.13      xtraeme   676: static int
1.1       bouyer    677: mfi_get_info(struct mfi_softc *sc)
                    678: {
                    679: #ifdef MFI_DEBUG
                    680:        int i;
                    681: #endif
                    682:        DNPRINTF(MFI_D_MISC, "%s: mfi_get_info\n", DEVNAME(sc));
                    683:
1.19      bouyer    684:        if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_GET_INFO, MFI_DATA_IN,
1.45      bouyer    685:            sizeof(sc->sc_info), &sc->sc_info, NULL, cold ? true : false))
1.13      xtraeme   686:                return 1;
1.1       bouyer    687:
                    688: #ifdef MFI_DEBUG
                    689:        for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
                    690:                printf("%s: active FW %s Version %s date %s time %s\n",
                    691:                    DEVNAME(sc),
                    692:                    sc->sc_info.mci_image_component[i].mic_name,
                    693:                    sc->sc_info.mci_image_component[i].mic_version,
                    694:                    sc->sc_info.mci_image_component[i].mic_build_date,
                    695:                    sc->sc_info.mci_image_component[i].mic_build_time);
                    696:        }
                    697:
                    698:        for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
                    699:                printf("%s: pending FW %s Version %s date %s time %s\n",
                    700:                    DEVNAME(sc),
                    701:                    sc->sc_info.mci_pending_image_component[i].mic_name,
                    702:                    sc->sc_info.mci_pending_image_component[i].mic_version,
                    703:                    sc->sc_info.mci_pending_image_component[i].mic_build_date,
                    704:                    sc->sc_info.mci_pending_image_component[i].mic_build_time);
                    705:        }
                    706:
                    707:        printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
                    708:            DEVNAME(sc),
                    709:            sc->sc_info.mci_max_arms,
                    710:            sc->sc_info.mci_max_spans,
                    711:            sc->sc_info.mci_max_arrays,
                    712:            sc->sc_info.mci_max_lds,
                    713:            sc->sc_info.mci_product_name);
                    714:
                    715:        printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
                    716:            DEVNAME(sc),
                    717:            sc->sc_info.mci_serial_number,
                    718:            sc->sc_info.mci_hw_present,
                    719:            sc->sc_info.mci_current_fw_time,
                    720:            sc->sc_info.mci_max_cmds,
                    721:            sc->sc_info.mci_max_sg_elements);
                    722:
                    723:        printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
                    724:            DEVNAME(sc),
                    725:            sc->sc_info.mci_max_request_size,
                    726:            sc->sc_info.mci_lds_present,
                    727:            sc->sc_info.mci_lds_degraded,
                    728:            sc->sc_info.mci_lds_offline,
                    729:            sc->sc_info.mci_pd_present);
                    730:
                    731:        printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
                    732:            DEVNAME(sc),
                    733:            sc->sc_info.mci_pd_disks_present,
                    734:            sc->sc_info.mci_pd_disks_pred_failure,
                    735:            sc->sc_info.mci_pd_disks_failed);
                    736:
                    737:        printf("%s: nvram %d mem %d flash %d\n",
                    738:            DEVNAME(sc),
                    739:            sc->sc_info.mci_nvram_size,
                    740:            sc->sc_info.mci_memory_size,
                    741:            sc->sc_info.mci_flash_size);
                    742:
                    743:        printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
                    744:            DEVNAME(sc),
                    745:            sc->sc_info.mci_ram_correctable_errors,
                    746:            sc->sc_info.mci_ram_uncorrectable_errors,
                    747:            sc->sc_info.mci_cluster_allowed,
                    748:            sc->sc_info.mci_cluster_active);
                    749:
                    750:        printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
                    751:            DEVNAME(sc),
                    752:            sc->sc_info.mci_max_strips_per_io,
                    753:            sc->sc_info.mci_raid_levels,
                    754:            sc->sc_info.mci_adapter_ops,
                    755:            sc->sc_info.mci_ld_ops);
                    756:
                    757:        printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
                    758:            DEVNAME(sc),
                    759:            sc->sc_info.mci_stripe_sz_ops.min,
                    760:            sc->sc_info.mci_stripe_sz_ops.max,
                    761:            sc->sc_info.mci_pd_ops,
                    762:            sc->sc_info.mci_pd_mix_support);
                    763:
                    764:        printf("%s: ecc_bucket %d pckg_prop %s\n",
                    765:            DEVNAME(sc),
                    766:            sc->sc_info.mci_ecc_bucket_count,
                    767:            sc->sc_info.mci_package_version);
                    768:
                    769:        printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
                    770:            DEVNAME(sc),
                    771:            sc->sc_info.mci_properties.mcp_seq_num,
                    772:            sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
                    773:            sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
                    774:            sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
                    775:
                    776:        printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
                    777:            DEVNAME(sc),
                    778:            sc->sc_info.mci_properties.mcp_rebuild_rate,
                    779:            sc->sc_info.mci_properties.mcp_patrol_read_rate,
                    780:            sc->sc_info.mci_properties.mcp_bgi_rate,
                    781:            sc->sc_info.mci_properties.mcp_cc_rate);
                    782:
                    783:        printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
                    784:            DEVNAME(sc),
                    785:            sc->sc_info.mci_properties.mcp_recon_rate,
                    786:            sc->sc_info.mci_properties.mcp_cache_flush_interval,
                    787:            sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
                    788:            sc->sc_info.mci_properties.mcp_spinup_delay,
                    789:            sc->sc_info.mci_properties.mcp_cluster_enable);
                    790:
                    791:        printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
                    792:            DEVNAME(sc),
                    793:            sc->sc_info.mci_properties.mcp_coercion_mode,
                    794:            sc->sc_info.mci_properties.mcp_alarm_enable,
                    795:            sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
                    796:            sc->sc_info.mci_properties.mcp_disable_battery_warn,
                    797:            sc->sc_info.mci_properties.mcp_ecc_bucket_size);
                    798:
                    799:        printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
                    800:            DEVNAME(sc),
                    801:            sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
                    802:            sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
                    803:            sc->sc_info.mci_properties.mcp_expose_encl_devices);
                    804:
                    805:        printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
                    806:            DEVNAME(sc),
                    807:            sc->sc_info.mci_pci.mip_vendor,
                    808:            sc->sc_info.mci_pci.mip_device,
                    809:            sc->sc_info.mci_pci.mip_subvendor,
                    810:            sc->sc_info.mci_pci.mip_subdevice);
                    811:
                    812:        printf("%s: type %#x port_count %d port_addr ",
                    813:            DEVNAME(sc),
                    814:            sc->sc_info.mci_host.mih_type,
                    815:            sc->sc_info.mci_host.mih_port_count);
                    816:
                    817:        for (i = 0; i < 8; i++)
1.46      bouyer    818:                printf("%.0" PRIx64 " ", sc->sc_info.mci_host.mih_port_addr[i]);
1.1       bouyer    819:        printf("\n");
                    820:
                    821:        printf("%s: type %.x port_count %d port_addr ",
                    822:            DEVNAME(sc),
                    823:            sc->sc_info.mci_device.mid_type,
                    824:            sc->sc_info.mci_device.mid_port_count);
                    825:
1.46      bouyer    826:        for (i = 0; i < 8; i++) {
                    827:                printf("%.0" PRIx64 " ",
                    828:                    sc->sc_info.mci_device.mid_port_addr[i]);
                    829:        }
1.1       bouyer    830:        printf("\n");
                    831: #endif /* MFI_DEBUG */
                    832:
1.13      xtraeme   833:        return 0;
1.1       bouyer    834: }
                    835:
1.45      bouyer    836: static int
                    837: mfi_get_bbu(struct mfi_softc *sc, struct mfi_bbu_status *stat)
                    838: {
                    839:        DNPRINTF(MFI_D_MISC, "%s: mfi_get_bbu\n", DEVNAME(sc));
                    840:
                    841:        if (mfi_mgmt_internal(sc, MR_DCMD_BBU_GET_STATUS, MFI_DATA_IN,
                    842:            sizeof(*stat), stat, NULL, cold ? true : false))
                    843:                return MFI_BBU_UNKNOWN;
                    844: #ifdef MFI_DEBUG
                    845:        printf("bbu type %d, voltage %d, current %d, temperature %d, "
                    846:            "status 0x%x\n", stat->battery_type, stat->voltage, stat->current,
                    847:            stat->temperature, stat->fw_status);
                    848:        printf("details: ");
1.73      msaitoh   849:        switch (stat->battery_type) {
1.45      bouyer    850:        case MFI_BBU_TYPE_IBBU:
                    851:                printf("guage %d relative charge %d charger state %d "
                    852:                    "charger ctrl %d\n", stat->detail.ibbu.gas_guage_status,
                    853:                    stat->detail.ibbu.relative_charge ,
                    854:                    stat->detail.ibbu.charger_system_state ,
                    855:                    stat->detail.ibbu.charger_system_ctrl);
                    856:                printf("\tcurrent %d abs charge %d max error %d\n",
                    857:                    stat->detail.ibbu.charging_current ,
                    858:                    stat->detail.ibbu.absolute_charge ,
                    859:                    stat->detail.ibbu.max_error);
                    860:                break;
                    861:        case MFI_BBU_TYPE_BBU:
                    862:                printf("guage %d relative charge %d charger state %d\n",
                    863:                    stat->detail.ibbu.gas_guage_status,
                    864:                    stat->detail.bbu.relative_charge ,
                    865:                    stat->detail.bbu.charger_status );
                    866:                printf("\trem capacity %d fyll capacity %d SOH %d\n",
                    867:                    stat->detail.bbu.remaining_capacity ,
                    868:                    stat->detail.bbu.full_charge_capacity ,
                    869:                    stat->detail.bbu.is_SOH_good);
1.61      gdt       870:                break;
1.45      bouyer    871:        default:
                    872:                printf("\n");
                    873:        }
                    874: #endif
1.73      msaitoh   875:        switch (stat->battery_type) {
1.45      bouyer    876:        case MFI_BBU_TYPE_BBU:
1.73      msaitoh   877:                return (stat->detail.bbu.is_SOH_good ?
1.45      bouyer    878:                    MFI_BBU_GOOD : MFI_BBU_BAD);
                    879:        case MFI_BBU_TYPE_NONE:
                    880:                return MFI_BBU_UNKNOWN;
                    881:        default:
                    882:                if (stat->fw_status &
                    883:                    (MFI_BBU_STATE_PACK_MISSING |
                    884:                     MFI_BBU_STATE_VOLTAGE_LOW |
                    885:                     MFI_BBU_STATE_TEMPERATURE_HIGH |
                    886:                     MFI_BBU_STATE_LEARN_CYC_FAIL |
                    887:                     MFI_BBU_STATE_LEARN_CYC_TIMEOUT |
                    888:                     MFI_BBU_STATE_I2C_ERR_DETECT))
                    889:                        return MFI_BBU_BAD;
                    890:                return MFI_BBU_GOOD;
                    891:        }
                    892: }
                    893:
1.13      xtraeme   894: static void
1.1       bouyer    895: mfiminphys(struct buf *bp)
                    896: {
                    897:        DNPRINTF(MFI_D_MISC, "mfiminphys: %d\n", bp->b_bcount);
                    898:
                    899:        /* XXX currently using MFI_MAXFER = MAXPHYS */
                    900:        if (bp->b_bcount > MFI_MAXFER)
                    901:                bp->b_bcount = MFI_MAXFER;
                    902:        minphys(bp);
                    903: }
                    904:
                    905: int
1.27      dyoung    906: mfi_rescan(device_t self, const char *ifattr, const int *locators)
                    907: {
                    908:        struct mfi_softc *sc = device_private(self);
                    909:
                    910:        if (sc->sc_child != NULL)
                    911:                return 0;
                    912:
1.65      thorpej   913:        sc->sc_child = config_found(self, &sc->sc_chan, scsiprint, CFARGS_NONE);
1.27      dyoung    914:
                    915:        return 0;
                    916: }
                    917:
                    918: void
                    919: mfi_childdetached(device_t self, device_t child)
                    920: {
                    921:        struct mfi_softc *sc = device_private(self);
                    922:
                    923:        KASSERT(self == sc->sc_dev);
                    924:        KASSERT(child == sc->sc_child);
                    925:
                    926:        if (child == sc->sc_child)
                    927:                sc->sc_child = NULL;
                    928: }
                    929:
                    930: int
1.24      dyoung    931: mfi_detach(struct mfi_softc *sc, int flags)
                    932: {
                    933:        int                     error;
                    934:
                    935:        DNPRINTF(MFI_D_MISC, "%s: mfi_detach\n", DEVNAME(sc));
                    936:
1.26      dyoung    937:        if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
1.25      dyoung    938:                return error;
                    939:
1.24      dyoung    940: #if NBIO > 0
                    941:        mfi_destroy_sensors(sc);
1.26      dyoung    942:        bio_unregister(sc->sc_dev);
1.24      dyoung    943: #endif /* NBIO > 0 */
                    944:
                    945:        mfi_intr_disable(sc);
1.45      bouyer    946:        mfi_shutdown(sc->sc_dev, 0);
1.24      dyoung    947:
1.43      bouyer    948:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                    949:                workqueue_destroy(sc->sc_ldsync_wq);
                    950:                mfi_put_ccb(sc->sc_ldsync_ccb);
                    951:                mfi_freemem(sc, &sc->sc_tbolt_reqmsgpool);
                    952:                mfi_freemem(sc, &sc->sc_tbolt_ioc_init);
                    953:                mfi_freemem(sc, &sc->sc_tbolt_verbuf);
                    954:        }
                    955:
1.24      dyoung    956:        if ((error = mfi_destroy_ccb(sc)) != 0)
                    957:                return error;
                    958:
1.27      dyoung    959:        mfi_freemem(sc, &sc->sc_sense);
1.24      dyoung    960:
1.27      dyoung    961:        mfi_freemem(sc, &sc->sc_frames);
1.24      dyoung    962:
1.27      dyoung    963:        mfi_freemem(sc, &sc->sc_pcq);
1.24      dyoung    964:
                    965:        return 0;
                    966: }
                    967:
1.45      bouyer    968: static bool
                    969: mfi_shutdown(device_t dev, int how)
                    970: {
                    971:        struct mfi_softc        *sc = device_private(dev);
1.74      msaitoh   972:        union mfi_mbox          mbox;
1.45      bouyer    973:        int s = splbio();
1.72      msaitoh   974:
1.45      bouyer    975:        DNPRINTF(MFI_D_MISC, "%s: mfi_shutdown\n", DEVNAME(sc));
                    976:        if (sc->sc_running) {
1.74      msaitoh   977:                memset(&mbox, 0, sizeof(mbox));
                    978:                mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
1.45      bouyer    979:                if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_CACHE_FLUSH,
1.74      msaitoh   980:                    MFI_DATA_NONE, 0, NULL, &mbox, true)) {
1.45      bouyer    981:                        aprint_error_dev(dev, "shutdown: cache flush failed\n");
                    982:                        goto fail;
                    983:                }
                    984:
1.74      msaitoh   985:                mbox.b[0] = 0;
1.45      bouyer    986:                if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_SHUTDOWN,
1.74      msaitoh   987:                    MFI_DATA_NONE, 0, NULL, &mbox, true)) {
1.45      bouyer    988:                        aprint_error_dev(dev, "shutdown: "
                    989:                            "firmware shutdown failed\n");
                    990:                        goto fail;
                    991:                }
                    992:                sc->sc_running = false;
                    993:        }
                    994:        splx(s);
                    995:        return true;
                    996: fail:
                    997:        splx(s);
                    998:        return false;
                    999: }
                   1000:
                   1001: static bool
                   1002: mfi_suspend(device_t dev, const pmf_qual_t *q)
                   1003: {
                   1004:        /* XXX to be implemented */
                   1005:        return false;
                   1006: }
                   1007:
                   1008: static bool
                   1009: mfi_resume(device_t dev, const pmf_qual_t *q)
                   1010: {
                   1011:        /* XXX to be implemented */
                   1012:        return false;
                   1013: }
                   1014:
1.24      dyoung   1015: int
1.12      xtraeme  1016: mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
1.1       bouyer   1017: {
                   1018:        struct scsipi_adapter *adapt = &sc->sc_adapt;
                   1019:        struct scsipi_channel *chan = &sc->sc_chan;
1.39      bouyer   1020:        uint32_t                status, frames, max_sgl;
1.1       bouyer   1021:        int                     i;
                   1022:
                   1023:        DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc));
                   1024:
1.42      bouyer   1025:        sc->sc_ioptype = iop;
                   1026:
1.12      xtraeme  1027:        switch (iop) {
                   1028:        case MFI_IOP_XSCALE:
                   1029:                sc->sc_iop = &mfi_iop_xscale;
                   1030:                break;
                   1031:        case MFI_IOP_PPC:
                   1032:                sc->sc_iop = &mfi_iop_ppc;
                   1033:                break;
1.33      msaitoh  1034:        case MFI_IOP_GEN2:
                   1035:                sc->sc_iop = &mfi_iop_gen2;
                   1036:                break;
1.38      sborrill 1037:        case MFI_IOP_SKINNY:
                   1038:                sc->sc_iop = &mfi_iop_skinny;
                   1039:                break;
1.43      bouyer   1040:        case MFI_IOP_TBOLT:
                   1041:                sc->sc_iop = &mfi_iop_tbolt;
                   1042:                break;
1.12      xtraeme  1043:        default:
1.73      msaitoh  1044:                panic("%s: unknown iop %d", DEVNAME(sc), iop);
1.12      xtraeme  1045:        }
                   1046:
1.1       bouyer   1047:        if (mfi_transition_firmware(sc))
1.13      xtraeme  1048:                return 1;
1.1       bouyer   1049:
                   1050:        TAILQ_INIT(&sc->sc_ccb_freeq);
                   1051:
1.12      xtraeme  1052:        status = mfi_fw_state(sc);
1.1       bouyer   1053:        sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
1.39      bouyer   1054:        max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
1.43      bouyer   1055:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
1.59      riastrad 1056:                sc->sc_max_sgl = uimin(max_sgl, (128 * 1024) / PAGE_SIZE + 1);
1.43      bouyer   1057:                sc->sc_sgl_size = sizeof(struct mfi_sg_ieee);
                   1058:        } else if (sc->sc_64bit_dma) {
1.59      riastrad 1059:                sc->sc_max_sgl = uimin(max_sgl, (128 * 1024) / PAGE_SIZE + 1);
1.39      bouyer   1060:                sc->sc_sgl_size = sizeof(struct mfi_sg64);
                   1061:        } else {
                   1062:                sc->sc_max_sgl = max_sgl;
                   1063:                sc->sc_sgl_size = sizeof(struct mfi_sg32);
                   1064:        }
1.69      msaitoh  1065:        if (sc->sc_ioptype == MFI_IOP_SKINNY)
                   1066:                sc->sc_sgl_size = sizeof(struct mfi_sg_ieee);
1.1       bouyer   1067:        DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n",
                   1068:            DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl);
                   1069:
1.43      bouyer   1070:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                   1071:                uint32_t tb_mem_size;
                   1072:                /* for Alignment */
1.66      msaitoh  1073:                tb_mem_size = MEGASAS_THUNDERBOLT_MSG_ALIGNMENT;
1.43      bouyer   1074:
                   1075:                tb_mem_size +=
                   1076:                    MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1);
                   1077:                sc->sc_reply_pool_size =
                   1078:                    ((sc->sc_max_cmds + 1 + 15) / 16) * 16;
                   1079:                tb_mem_size +=
                   1080:                    MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size;
                   1081:
                   1082:                /* this is for SGL's */
                   1083:                tb_mem_size += MEGASAS_MAX_SZ_CHAIN_FRAME * sc->sc_max_cmds;
                   1084:                sc->sc_tbolt_reqmsgpool = mfi_allocmem(sc, tb_mem_size);
                   1085:                if (sc->sc_tbolt_reqmsgpool == NULL) {
                   1086:                        aprint_error_dev(sc->sc_dev,
                   1087:                            "unable to allocate thunderbolt "
                   1088:                            "request message pool\n");
                   1089:                        goto nopcq;
                   1090:                }
                   1091:                if (mfi_tbolt_init_desc_pool(sc)) {
                   1092:                        aprint_error_dev(sc->sc_dev,
                   1093:                            "Thunderbolt pool preparation error\n");
                   1094:                        goto nopcq;
                   1095:                }
                   1096:
                   1097:                /*
                   1098:                 * Allocate DMA memory mapping for MPI2 IOC Init descriptor,
                   1099:                 * we are taking it diffrent from what we have allocated for
                   1100:                 * Request and reply descriptors to avoid confusion later
                   1101:                 */
                   1102:                sc->sc_tbolt_ioc_init = mfi_allocmem(sc,
                   1103:                    sizeof(struct mpi2_ioc_init_request));
                   1104:                if (sc->sc_tbolt_ioc_init == NULL) {
                   1105:                        aprint_error_dev(sc->sc_dev,
                   1106:                            "unable to allocate thunderbolt IOC init memory");
                   1107:                        goto nopcq;
                   1108:                }
                   1109:
                   1110:                sc->sc_tbolt_verbuf = mfi_allocmem(sc,
                   1111:                    MEGASAS_MAX_NAME*sizeof(bus_addr_t));
                   1112:                if (sc->sc_tbolt_verbuf == NULL) {
                   1113:                        aprint_error_dev(sc->sc_dev,
                   1114:                            "unable to allocate thunderbolt version buffer\n");
                   1115:                        goto nopcq;
                   1116:                }
                   1117:
                   1118:        }
1.1       bouyer   1119:        /* consumer/producer and reply queue memory */
                   1120:        sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) +
                   1121:            sizeof(struct mfi_prod_cons));
                   1122:        if (sc->sc_pcq == NULL) {
1.43      bouyer   1123:                aprint_error_dev(sc->sc_dev,
                   1124:                    "unable to allocate reply queue memory\n");
1.1       bouyer   1125:                goto nopcq;
                   1126:        }
                   1127:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0,
                   1128:            sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons),
                   1129:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1130:
                   1131:        /* frame memory */
1.39      bouyer   1132:        frames = (sc->sc_sgl_size * sc->sc_max_sgl + MFI_FRAME_SIZE - 1) /
                   1133:            MFI_FRAME_SIZE + 1;
1.1       bouyer   1134:        sc->sc_frames_size = frames * MFI_FRAME_SIZE;
                   1135:        sc->sc_frames = mfi_allocmem(sc, sc->sc_frames_size * sc->sc_max_cmds);
                   1136:        if (sc->sc_frames == NULL) {
1.43      bouyer   1137:                aprint_error_dev(sc->sc_dev,
                   1138:                    "unable to allocate frame memory\n");
1.1       bouyer   1139:                goto noframe;
                   1140:        }
                   1141:        /* XXX hack, fix this */
                   1142:        if (MFIMEM_DVA(sc->sc_frames) & 0x3f) {
1.43      bouyer   1143:                aprint_error_dev(sc->sc_dev,
                   1144:                    "improper frame alignment (%#llx) FIXME\n",
                   1145:                    (long long int)MFIMEM_DVA(sc->sc_frames));
1.1       bouyer   1146:                goto noframe;
                   1147:        }
                   1148:
                   1149:        /* sense memory */
                   1150:        sc->sc_sense = mfi_allocmem(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
                   1151:        if (sc->sc_sense == NULL) {
1.43      bouyer   1152:                aprint_error_dev(sc->sc_dev,
                   1153:                    "unable to allocate sense memory\n");
1.1       bouyer   1154:                goto nosense;
                   1155:        }
                   1156:
                   1157:        /* now that we have all memory bits go initialize ccbs */
                   1158:        if (mfi_init_ccb(sc)) {
1.43      bouyer   1159:                aprint_error_dev(sc->sc_dev, "could not init ccb list\n");
1.1       bouyer   1160:                goto noinit;
                   1161:        }
                   1162:
                   1163:        /* kickstart firmware with all addresses and pointers */
1.43      bouyer   1164:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                   1165:                if (mfi_tbolt_init_MFI_queue(sc)) {
                   1166:                        aprint_error_dev(sc->sc_dev,
                   1167:                            "could not initialize firmware\n");
                   1168:                        goto noinit;
                   1169:                }
                   1170:        } else {
                   1171:                if (mfi_initialize_firmware(sc)) {
                   1172:                        aprint_error_dev(sc->sc_dev,
                   1173:                            "could not initialize firmware\n");
                   1174:                        goto noinit;
                   1175:                }
1.1       bouyer   1176:        }
1.45      bouyer   1177:        sc->sc_running = true;
1.1       bouyer   1178:
                   1179:        if (mfi_get_info(sc)) {
1.43      bouyer   1180:                aprint_error_dev(sc->sc_dev,
                   1181:                    "could not retrieve controller information\n");
1.1       bouyer   1182:                goto noinit;
                   1183:        }
1.45      bouyer   1184:        aprint_normal_dev(sc->sc_dev,
                   1185:            "%s version %s\n",
                   1186:            sc->sc_info.mci_product_name,
                   1187:            sc->sc_info.mci_package_version);
                   1188:
1.1       bouyer   1189:
1.45      bouyer   1190:        aprint_normal_dev(sc->sc_dev, "logical drives %d, %dMB RAM, ",
1.1       bouyer   1191:            sc->sc_info.mci_lds_present,
                   1192:            sc->sc_info.mci_memory_size);
1.45      bouyer   1193:        sc->sc_bbuok = false;
                   1194:        if (sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU) {
                   1195:                struct mfi_bbu_status   bbu_stat;
                   1196:                int mfi_bbu_status = mfi_get_bbu(sc, &bbu_stat);
                   1197:                aprint_normal("BBU type ");
                   1198:                switch (bbu_stat.battery_type) {
                   1199:                case MFI_BBU_TYPE_BBU:
                   1200:                        aprint_normal("BBU");
                   1201:                        break;
                   1202:                case MFI_BBU_TYPE_IBBU:
                   1203:                        aprint_normal("IBBU");
                   1204:                        break;
                   1205:                default:
                   1206:                        aprint_normal("unknown type %d", bbu_stat.battery_type);
                   1207:                }
                   1208:                aprint_normal(", status ");
1.73      msaitoh  1209:                switch (mfi_bbu_status) {
1.45      bouyer   1210:                case MFI_BBU_GOOD:
                   1211:                        aprint_normal("good\n");
                   1212:                        sc->sc_bbuok = true;
                   1213:                        break;
                   1214:                case MFI_BBU_BAD:
                   1215:                        aprint_normal("bad\n");
                   1216:                        break;
                   1217:                case MFI_BBU_UNKNOWN:
                   1218:                        aprint_normal("unknown\n");
                   1219:                        break;
                   1220:                default:
                   1221:                        panic("mfi_bbu_status");
                   1222:                }
                   1223:        } else {
                   1224:                aprint_normal("BBU not present\n");
                   1225:        }
1.1       bouyer   1226:
                   1227:        sc->sc_ld_cnt = sc->sc_info.mci_lds_present;
                   1228:        sc->sc_max_ld = sc->sc_ld_cnt;
                   1229:        for (i = 0; i < sc->sc_ld_cnt; i++)
                   1230:                sc->sc_ld[i].ld_present = 1;
                   1231:
                   1232:        memset(adapt, 0, sizeof(*adapt));
1.26      dyoung   1233:        adapt->adapt_dev = sc->sc_dev;
1.1       bouyer   1234:        adapt->adapt_nchannels = 1;
1.43      bouyer   1235:        /* keep a few commands for management */
                   1236:        if (sc->sc_max_cmds > 4)
                   1237:                adapt->adapt_openings = sc->sc_max_cmds - 4;
1.1       bouyer   1238:        else
                   1239:                adapt->adapt_openings = sc->sc_max_cmds;
                   1240:        adapt->adapt_max_periph = adapt->adapt_openings;
                   1241:        adapt->adapt_request = mfi_scsipi_request;
                   1242:        adapt->adapt_minphys = mfiminphys;
                   1243:
                   1244:        memset(chan, 0, sizeof(*chan));
                   1245:        chan->chan_adapter = adapt;
1.43      bouyer   1246:        chan->chan_bustype = &scsi_sas_bustype;
1.1       bouyer   1247:        chan->chan_channel = 0;
                   1248:        chan->chan_flags = 0;
                   1249:        chan->chan_nluns = 8;
                   1250:        chan->chan_ntargets = MFI_MAX_LD;
                   1251:        chan->chan_id = MFI_MAX_LD;
                   1252:
1.64      thorpej  1253:        mfi_rescan(sc->sc_dev, NULL, NULL);
1.1       bouyer   1254:
                   1255:        /* enable interrupts */
1.12      xtraeme  1256:        mfi_intr_enable(sc);
1.1       bouyer   1257:
                   1258: #if NBIO > 0
1.26      dyoung   1259:        if (bio_register(sc->sc_dev, mfi_ioctl) != 0)
1.1       bouyer   1260:                panic("%s: controller registration failed", DEVNAME(sc));
                   1261:        if (mfi_create_sensors(sc) != 0)
1.43      bouyer   1262:                aprint_error_dev(sc->sc_dev, "unable to create sensors\n");
1.1       bouyer   1263: #endif /* NBIO > 0 */
1.45      bouyer   1264:        if (!pmf_device_register1(sc->sc_dev, mfi_suspend, mfi_resume,
                   1265:            mfi_shutdown)) {
                   1266:                aprint_error_dev(sc->sc_dev,
                   1267:                    "couldn't establish power handler\n");
                   1268:        }
1.1       bouyer   1269:
1.13      xtraeme  1270:        return 0;
1.1       bouyer   1271: noinit:
1.27      dyoung   1272:        mfi_freemem(sc, &sc->sc_sense);
1.1       bouyer   1273: nosense:
1.27      dyoung   1274:        mfi_freemem(sc, &sc->sc_frames);
1.1       bouyer   1275: noframe:
1.27      dyoung   1276:        mfi_freemem(sc, &sc->sc_pcq);
1.1       bouyer   1277: nopcq:
1.43      bouyer   1278:        if (sc->sc_ioptype == MFI_IOP_TBOLT) {
                   1279:                if (sc->sc_tbolt_reqmsgpool)
                   1280:                        mfi_freemem(sc, &sc->sc_tbolt_reqmsgpool);
                   1281:                if (sc->sc_tbolt_verbuf)
                   1282:                        mfi_freemem(sc, &sc->sc_tbolt_verbuf);
                   1283:        }
1.13      xtraeme  1284:        return 1;
1.1       bouyer   1285: }
                   1286:
1.13      xtraeme  1287: static int
1.1       bouyer   1288: mfi_poll(struct mfi_ccb *ccb)
                   1289: {
                   1290:        struct mfi_softc *sc = ccb->ccb_sc;
                   1291:        struct mfi_frame_header *hdr;
                   1292:        int                     to = 0;
1.43      bouyer   1293:        int                     rv = 0;
1.1       bouyer   1294:
                   1295:        DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc));
                   1296:
                   1297:        hdr = &ccb->ccb_frame->mfr_header;
                   1298:        hdr->mfh_cmd_status = 0xff;
1.43      bouyer   1299:        if (!sc->sc_MFA_enabled)
                   1300:                hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
                   1301:
                   1302:        /* no callback, caller is supposed to do the cleanup */
                   1303:        ccb->ccb_done = NULL;
1.1       bouyer   1304:
1.12      xtraeme  1305:        mfi_post(sc, ccb);
1.43      bouyer   1306:        if (sc->sc_MFA_enabled) {
                   1307:                /*
                   1308:                 * depending on the command type, result may be posted
                   1309:                 * to *hdr, or not. In addition it seems there's
                   1310:                 * no way to avoid posting the SMID to the reply queue.
                   1311:                 * So pool using the interrupt routine.
                   1312:                 */
                   1313:                 while (ccb->ccb_state != MFI_CCB_DONE) {
                   1314:                        delay(1000);
                   1315:                        if (to++ > 5000) { /* XXX 5 seconds busywait sucks */
                   1316:                                rv = 1;
                   1317:                                break;
                   1318:                        }
                   1319:                        mfi_tbolt_intrh(sc);
                   1320:                 }
                   1321:        } else {
1.1       bouyer   1322:                bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
                   1323:                    ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames),
                   1324:                    sc->sc_frames_size, BUS_DMASYNC_POSTREAD);
1.43      bouyer   1325:
                   1326:                while (hdr->mfh_cmd_status == 0xff) {
                   1327:                        delay(1000);
                   1328:                        if (to++ > 5000) { /* XXX 5 seconds busywait sucks */
                   1329:                                rv = 1;
                   1330:                                break;
                   1331:                        }
                   1332:                        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
                   1333:                            ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames),
                   1334:                            sc->sc_frames_size, BUS_DMASYNC_POSTREAD);
                   1335:                }
1.1       bouyer   1336:        }
                   1337:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
                   1338:            ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames),
                   1339:            sc->sc_frames_size, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1340:
                   1341:        if (ccb->ccb_data != NULL) {
                   1342:                DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n",
                   1343:                    DEVNAME(sc));
1.43      bouyer   1344:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
1.1       bouyer   1345:                    ccb->ccb_dmamap->dm_mapsize,
                   1346:                    (ccb->ccb_direction & MFI_DATA_IN) ?
                   1347:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                   1348:
1.43      bouyer   1349:                bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap);
1.1       bouyer   1350:        }
                   1351:
1.43      bouyer   1352:        if (rv != 0) {
                   1353:                aprint_error_dev(sc->sc_dev, "timeout on ccb %d\n",
1.1       bouyer   1354:                    hdr->mfh_context);
                   1355:                ccb->ccb_flags |= MFI_CCB_F_ERR;
1.13      xtraeme  1356:                return 1;
1.1       bouyer   1357:        }
1.30      dyoung   1358:
1.13      xtraeme  1359:        return 0;
1.1       bouyer   1360: }
                   1361:
                   1362: int
                   1363: mfi_intr(void *arg)
                   1364: {
                   1365:        struct mfi_softc        *sc = arg;
                   1366:        struct mfi_prod_cons    *pcq;
                   1367:        struct mfi_ccb          *ccb;
1.12      xtraeme  1368:        uint32_t                producer, consumer, ctx;
1.1       bouyer   1369:        int                     claimed = 0;
                   1370:
1.12      xtraeme  1371:        if (!mfi_my_intr(sc))
                   1372:                return 0;
1.1       bouyer   1373:
1.4       bouyer   1374:        pcq = MFIMEM_KVA(sc->sc_pcq);
                   1375:
                   1376:        DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#lx %#lx\n", DEVNAME(sc),
                   1377:            (u_long)sc, (u_long)pcq);
1.1       bouyer   1378:
                   1379:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0,
                   1380:            sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons),
                   1381:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1382:
                   1383:        producer = pcq->mpc_producer;
                   1384:        consumer = pcq->mpc_consumer;
                   1385:
                   1386:        while (consumer != producer) {
                   1387:                DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n",
                   1388:                    DEVNAME(sc), producer, consumer);
                   1389:
                   1390:                ctx = pcq->mpc_reply_q[consumer];
                   1391:                pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX;
                   1392:                if (ctx == MFI_INVALID_CTX)
1.43      bouyer   1393:                        aprint_error_dev(sc->sc_dev,
                   1394:                            "invalid context, p: %d c: %d\n",
                   1395:                            producer, consumer);
1.1       bouyer   1396:                else {
                   1397:                        /* XXX remove from queue and call scsi_done */
                   1398:                        ccb = &sc->sc_ccb[ctx];
                   1399:                        DNPRINTF(MFI_D_INTR, "%s: mfi_intr context %#x\n",
                   1400:                            DEVNAME(sc), ctx);
                   1401:                        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
                   1402:                            ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames),
                   1403:                            sc->sc_frames_size,
                   1404:                            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1405:                        ccb->ccb_done(ccb);
                   1406:
                   1407:                        claimed = 1;
                   1408:                }
                   1409:                consumer++;
                   1410:                if (consumer == (sc->sc_max_cmds + 1))
                   1411:                        consumer = 0;
                   1412:        }
                   1413:
                   1414:        pcq->mpc_consumer = consumer;
                   1415:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0,
                   1416:            sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons),
                   1417:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1418:
1.13      xtraeme  1419:        return claimed;
1.1       bouyer   1420: }
                   1421:
1.13      xtraeme  1422: static int
1.43      bouyer   1423: mfi_scsi_ld_io(struct mfi_ccb *ccb, struct scsipi_xfer *xs, uint64_t blockno,
1.1       bouyer   1424:     uint32_t blockcnt)
                   1425: {
                   1426:        struct scsipi_periph *periph = xs->xs_periph;
                   1427:        struct mfi_io_frame   *io;
                   1428:
1.43      bouyer   1429:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld_io: %d\n",
1.15      cegger   1430:            device_xname(periph->periph_channel->chan_adapter->adapt_dev),
1.1       bouyer   1431:            periph->periph_target);
                   1432:
                   1433:        if (!xs->data)
1.13      xtraeme  1434:                return 1;
1.1       bouyer   1435:
                   1436:        io = &ccb->ccb_frame->mfr_io;
                   1437:        if (xs->xs_control & XS_CTL_DATA_IN) {
                   1438:                io->mif_header.mfh_cmd = MFI_CMD_LD_READ;
                   1439:                ccb->ccb_direction = MFI_DATA_IN;
                   1440:        } else {
                   1441:                io->mif_header.mfh_cmd = MFI_CMD_LD_WRITE;
                   1442:                ccb->ccb_direction = MFI_DATA_OUT;
                   1443:        }
                   1444:        io->mif_header.mfh_target_id = periph->periph_target;
                   1445:        io->mif_header.mfh_timeout = 0;
                   1446:        io->mif_header.mfh_flags = 0;
                   1447:        io->mif_header.mfh_sense_len = MFI_SENSE_SIZE;
                   1448:        io->mif_header.mfh_data_len= blockcnt;
1.43      bouyer   1449:        io->mif_lba_hi = (blockno >> 32);
                   1450:        io->mif_lba_lo = (blockno & 0xffffffff);
1.1       bouyer   1451:        io->mif_sense_addr_lo = htole32(ccb->ccb_psense);
                   1452:        io->mif_sense_addr_hi = 0;
                   1453:
1.43      bouyer   1454:        ccb->ccb_done = mfi_scsi_ld_done;
1.1       bouyer   1455:        ccb->ccb_xs = xs;
                   1456:        ccb->ccb_frame_size = MFI_IO_FRAME_SIZE;
                   1457:        ccb->ccb_sgl = &io->mif_sgl;
                   1458:        ccb->ccb_data = xs->data;
                   1459:        ccb->ccb_len = xs->datalen;
                   1460:
1.14      xtraeme  1461:        if (mfi_create_sgl(ccb, (xs->xs_control & XS_CTL_NOSLEEP) ?
                   1462:            BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
1.13      xtraeme  1463:                return 1;
1.1       bouyer   1464:
1.13      xtraeme  1465:        return 0;
1.1       bouyer   1466: }
                   1467:
1.13      xtraeme  1468: static void
1.43      bouyer   1469: mfi_scsi_ld_done(struct mfi_ccb *ccb)
                   1470: {
                   1471:        struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
                   1472:        mfi_scsi_xs_done(ccb, hdr->mfh_cmd_status, hdr->mfh_scsi_status);
                   1473: }
                   1474:
                   1475: static void
                   1476: mfi_scsi_xs_done(struct mfi_ccb *ccb, int status, int scsi_status)
1.1       bouyer   1477: {
                   1478:        struct scsipi_xfer      *xs = ccb->ccb_xs;
                   1479:        struct mfi_softc        *sc = ccb->ccb_sc;
                   1480:
1.4       bouyer   1481:        DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#lx %#lx\n",
                   1482:            DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame);
1.1       bouyer   1483:
                   1484:        if (xs->data != NULL) {
                   1485:                DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done sync\n",
                   1486:                    DEVNAME(sc));
1.43      bouyer   1487:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
1.1       bouyer   1488:                    ccb->ccb_dmamap->dm_mapsize,
                   1489:                    (xs->xs_control & XS_CTL_DATA_IN) ?
                   1490:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                   1491:
1.43      bouyer   1492:                bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap);
1.1       bouyer   1493:        }
                   1494:
1.43      bouyer   1495:        if (status != MFI_STAT_OK) {
1.1       bouyer   1496:                xs->error = XS_DRIVER_STUFFUP;
                   1497:                DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done stuffup %#x\n",
1.43      bouyer   1498:                    DEVNAME(sc), status);
1.1       bouyer   1499:
1.43      bouyer   1500:                if (scsi_status != 0) {
1.1       bouyer   1501:                        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_sense),
                   1502:                            ccb->ccb_psense - MFIMEM_DVA(sc->sc_sense),
                   1503:                            MFI_SENSE_SIZE, BUS_DMASYNC_POSTREAD);
                   1504:                        DNPRINTF(MFI_D_INTR,
1.4       bouyer   1505:                            "%s: mfi_scsi_xs_done sense %#x %lx %lx\n",
1.43      bouyer   1506:                            DEVNAME(sc), scsi_status,
1.4       bouyer   1507:                            (u_long)&xs->sense, (u_long)ccb->ccb_sense);
1.1       bouyer   1508:                        memset(&xs->sense, 0, sizeof(xs->sense));
                   1509:                        memcpy(&xs->sense, ccb->ccb_sense,
                   1510:                            sizeof(struct scsi_sense_data));
                   1511:                        xs->error = XS_SENSE;
                   1512:                }
                   1513:        } else {
                   1514:                xs->error = XS_NOERROR;
                   1515:                xs->status = SCSI_OK;
                   1516:                xs->resid = 0;
                   1517:        }
                   1518:
                   1519:        mfi_put_ccb(ccb);
                   1520:        scsipi_done(xs);
                   1521: }
                   1522:
1.13      xtraeme  1523: static int
1.1       bouyer   1524: mfi_scsi_ld(struct mfi_ccb *ccb, struct scsipi_xfer *xs)
                   1525: {
                   1526:        struct mfi_pass_frame   *pf;
                   1527:        struct scsipi_periph *periph = xs->xs_periph;
                   1528:
                   1529:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n",
1.15      cegger   1530:            device_xname(periph->periph_channel->chan_adapter->adapt_dev),
1.1       bouyer   1531:            periph->periph_target);
                   1532:
                   1533:        pf = &ccb->ccb_frame->mfr_pass;
                   1534:        pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO;
                   1535:        pf->mpf_header.mfh_target_id = periph->periph_target;
                   1536:        pf->mpf_header.mfh_lun_id = 0;
                   1537:        pf->mpf_header.mfh_cdb_len = xs->cmdlen;
                   1538:        pf->mpf_header.mfh_timeout = 0;
                   1539:        pf->mpf_header.mfh_data_len= xs->datalen; /* XXX */
                   1540:        pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE;
                   1541:
                   1542:        pf->mpf_sense_addr_hi = 0;
                   1543:        pf->mpf_sense_addr_lo = htole32(ccb->ccb_psense);
                   1544:
                   1545:        memset(pf->mpf_cdb, 0, 16);
                   1546:        memcpy(pf->mpf_cdb, &xs->cmdstore, xs->cmdlen);
                   1547:
1.43      bouyer   1548:        ccb->ccb_done = mfi_scsi_ld_done;
1.1       bouyer   1549:        ccb->ccb_xs = xs;
                   1550:        ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
                   1551:        ccb->ccb_sgl = &pf->mpf_sgl;
                   1552:
                   1553:        if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT))
                   1554:                ccb->ccb_direction = (xs->xs_control & XS_CTL_DATA_IN) ?
                   1555:                    MFI_DATA_IN : MFI_DATA_OUT;
                   1556:        else
                   1557:                ccb->ccb_direction = MFI_DATA_NONE;
                   1558:
                   1559:        if (xs->data) {
                   1560:                ccb->ccb_data = xs->data;
                   1561:                ccb->ccb_len = xs->datalen;
                   1562:
1.14      xtraeme  1563:                if (mfi_create_sgl(ccb, (xs->xs_control & XS_CTL_NOSLEEP) ?
                   1564:                    BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
1.13      xtraeme  1565:                        return 1;
1.1       bouyer   1566:        }
                   1567:
1.13      xtraeme  1568:        return 0;
1.1       bouyer   1569: }
                   1570:
1.13      xtraeme  1571: static void
1.1       bouyer   1572: mfi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
                   1573:     void *arg)
                   1574: {
                   1575:        struct scsipi_periph    *periph;
                   1576:        struct scsipi_xfer      *xs;
                   1577:        struct scsipi_adapter   *adapt = chan->chan_adapter;
1.26      dyoung   1578:        struct mfi_softc        *sc = device_private(adapt->adapt_dev);
1.1       bouyer   1579:        struct mfi_ccb          *ccb;
                   1580:        struct scsi_rw_6        *rw;
                   1581:        struct scsipi_rw_10     *rwb;
1.43      bouyer   1582:        struct scsipi_rw_12     *rw12;
                   1583:        struct scsipi_rw_16     *rw16;
1.74      msaitoh  1584:        union mfi_mbox          mbox;
1.43      bouyer   1585:        uint64_t                blockno;
                   1586:        uint32_t                blockcnt;
1.1       bouyer   1587:        uint8_t                 target;
                   1588:        int                     s;
                   1589:
                   1590:        switch (req) {
                   1591:        case ADAPTER_REQ_GROW_RESOURCES:
                   1592:                /* Not supported. */
                   1593:                return;
                   1594:        case ADAPTER_REQ_SET_XFER_MODE:
1.43      bouyer   1595:        {
                   1596:                struct scsipi_xfer_mode *xm = arg;
                   1597:                xm->xm_mode = PERIPH_CAP_TQING;
                   1598:                xm->xm_period = 0;
                   1599:                xm->xm_offset = 0;
                   1600:                scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
1.1       bouyer   1601:                return;
1.43      bouyer   1602:        }
1.1       bouyer   1603:        case ADAPTER_REQ_RUN_XFER:
                   1604:                break;
                   1605:        }
                   1606:
                   1607:        xs = arg;
1.4       bouyer   1608:
1.1       bouyer   1609:        periph = xs->xs_periph;
                   1610:        target = periph->periph_target;
                   1611:
1.43      bouyer   1612:        DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request req %d opcode: %#x "
                   1613:            "target %d lun %d\n", DEVNAME(sc), req, xs->cmd->opcode,
                   1614:            periph->periph_target, periph->periph_lun);
                   1615:
1.1       bouyer   1616:        s = splbio();
                   1617:        if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present ||
                   1618:            periph->periph_lun != 0) {
                   1619:                DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n",
                   1620:                    DEVNAME(sc), target);
                   1621:                xs->error = XS_SELTIMEOUT;
                   1622:                scsipi_done(xs);
                   1623:                splx(s);
                   1624:                return;
                   1625:        }
1.45      bouyer   1626:        if ((xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_10 ||
                   1627:            xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_16) && sc->sc_bbuok) {
                   1628:                /* the cache is stable storage, don't flush */
                   1629:                xs->error = XS_NOERROR;
                   1630:                xs->status = SCSI_OK;
                   1631:                xs->resid = 0;
                   1632:                scsipi_done(xs);
                   1633:                splx(s);
                   1634:                return;
                   1635:        }
1.1       bouyer   1636:
                   1637:        if ((ccb = mfi_get_ccb(sc)) == NULL) {
                   1638:                DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request no ccb\n", DEVNAME(sc));
                   1639:                xs->error = XS_RESOURCE_SHORTAGE;
                   1640:                scsipi_done(xs);
                   1641:                splx(s);
                   1642:                return;
                   1643:        }
                   1644:
                   1645:        switch (xs->cmd->opcode) {
                   1646:        /* IO path */
1.43      bouyer   1647:        case READ_16:
                   1648:        case WRITE_16:
                   1649:                rw16 = (struct scsipi_rw_16 *)xs->cmd;
                   1650:                blockno = _8btol(rw16->addr);
                   1651:                blockcnt = _4btol(rw16->length);
                   1652:                if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) {
                   1653:                        goto stuffup;
                   1654:                }
                   1655:                break;
                   1656:
                   1657:        case READ_12:
                   1658:        case WRITE_12:
                   1659:                rw12 = (struct scsipi_rw_12 *)xs->cmd;
                   1660:                blockno = _4btol(rw12->addr);
                   1661:                blockcnt = _4btol(rw12->length);
                   1662:                if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) {
                   1663:                        goto stuffup;
                   1664:                }
                   1665:                break;
                   1666:
1.1       bouyer   1667:        case READ_10:
                   1668:        case WRITE_10:
                   1669:                rwb = (struct scsipi_rw_10 *)xs->cmd;
                   1670:                blockno = _4btol(rwb->addr);
                   1671:                blockcnt = _2btol(rwb->length);
1.43      bouyer   1672:                if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) {
1.1       bouyer   1673:                        goto stuffup;
                   1674:                }
                   1675:                break;
                   1676:
                   1677:        case SCSI_READ_6_COMMAND:
                   1678:        case SCSI_WRITE_6_COMMAND:
                   1679:                rw = (struct scsi_rw_6 *)xs->cmd;
                   1680:                blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
                   1681:                blockcnt = rw->length ? rw->length : 0x100;
1.43      bouyer   1682:                if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) {
1.1       bouyer   1683:                        goto stuffup;
                   1684:                }
                   1685:                break;
                   1686:
                   1687:        case SCSI_SYNCHRONIZE_CACHE_10:
1.45      bouyer   1688:        case SCSI_SYNCHRONIZE_CACHE_16:
1.74      msaitoh  1689:                memset(&mbox, 0, sizeof(mbox));
                   1690:                mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
1.19      bouyer   1691:                if (mfi_mgmt(ccb, xs,
1.74      msaitoh  1692:                    MR_DCMD_CTRL_CACHE_FLUSH, MFI_DATA_NONE, 0, NULL, &mbox)) {
1.1       bouyer   1693:                        goto stuffup;
1.19      bouyer   1694:                }
                   1695:                break;
1.1       bouyer   1696:
                   1697:        /* hand it of to the firmware and let it deal with it */
                   1698:        case SCSI_TEST_UNIT_READY:
                   1699:                /* save off sd? after autoconf */
                   1700:                if (!cold)      /* XXX bogus */
1.26      dyoung   1701:                        strlcpy(sc->sc_ld[target].ld_dev, device_xname(sc->sc_dev),
1.1       bouyer   1702:                            sizeof(sc->sc_ld[target].ld_dev));
                   1703:                /* FALLTHROUGH */
                   1704:
                   1705:        default:
                   1706:                if (mfi_scsi_ld(ccb, xs)) {
                   1707:                        goto stuffup;
                   1708:                }
                   1709:                break;
                   1710:        }
                   1711:
                   1712:        DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
                   1713:
                   1714:        if (xs->xs_control & XS_CTL_POLL) {
                   1715:                if (mfi_poll(ccb)) {
                   1716:                        /* XXX check for sense in ccb->ccb_sense? */
1.43      bouyer   1717:                        aprint_error_dev(sc->sc_dev,
                   1718:                            "mfi_scsipi_request poll failed\n");
1.22      cegger   1719:                        memset(&xs->sense, 0, sizeof(xs->sense));
1.1       bouyer   1720:                        xs->sense.scsi_sense.response_code =
                   1721:                            SSD_RCODE_VALID | SSD_RCODE_CURRENT;
                   1722:                        xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
                   1723:                        xs->sense.scsi_sense.asc = 0x20; /* invalid opcode */
                   1724:                        xs->error = XS_SENSE;
                   1725:                        xs->status = SCSI_CHECK;
                   1726:                } else {
                   1727:                        DNPRINTF(MFI_D_DMA,
                   1728:                            "%s: mfi_scsipi_request poll complete %d\n",
                   1729:                            DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs);
                   1730:                        xs->error = XS_NOERROR;
                   1731:                        xs->status = SCSI_OK;
                   1732:                        xs->resid = 0;
                   1733:                }
                   1734:                mfi_put_ccb(ccb);
                   1735:                scsipi_done(xs);
                   1736:                splx(s);
                   1737:                return;
                   1738:        }
                   1739:
1.12      xtraeme  1740:        mfi_post(sc, ccb);
1.1       bouyer   1741:
                   1742:        DNPRINTF(MFI_D_DMA, "%s: mfi_scsipi_request queued %d\n", DEVNAME(sc),
                   1743:            ccb->ccb_dmamap->dm_nsegs);
                   1744:
                   1745:        splx(s);
                   1746:        return;
                   1747:
                   1748: stuffup:
1.43      bouyer   1749:        mfi_put_ccb(ccb);
1.1       bouyer   1750:        xs->error = XS_DRIVER_STUFFUP;
                   1751:        scsipi_done(xs);
                   1752:        splx(s);
                   1753: }
                   1754:
1.13      xtraeme  1755: static int
1.1       bouyer   1756: mfi_create_sgl(struct mfi_ccb *ccb, int flags)
                   1757: {
                   1758:        struct mfi_softc        *sc = ccb->ccb_sc;
                   1759:        struct mfi_frame_header *hdr;
                   1760:        bus_dma_segment_t       *sgd;
                   1761:        union mfi_sgl           *sgl;
                   1762:        int                     error, i;
                   1763:
1.4       bouyer   1764:        DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#lx\n", DEVNAME(sc),
                   1765:            (u_long)ccb->ccb_data);
1.1       bouyer   1766:
                   1767:        if (!ccb->ccb_data)
1.13      xtraeme  1768:                return 1;
1.1       bouyer   1769:
1.43      bouyer   1770:        KASSERT(flags == BUS_DMA_NOWAIT || !cpu_intr_p());
                   1771:        error = bus_dmamap_load(sc->sc_datadmat, ccb->ccb_dmamap,
1.1       bouyer   1772:            ccb->ccb_data, ccb->ccb_len, NULL, flags);
                   1773:        if (error) {
1.43      bouyer   1774:                if (error == EFBIG) {
                   1775:                        aprint_error_dev(sc->sc_dev, "more than %d dma segs\n",
1.1       bouyer   1776:                            sc->sc_max_sgl);
1.43      bouyer   1777:                } else {
                   1778:                        aprint_error_dev(sc->sc_dev,
                   1779:                            "error %d loading dma map\n", error);
                   1780:                }
1.13      xtraeme  1781:                return 1;
1.1       bouyer   1782:        }
                   1783:
                   1784:        hdr = &ccb->ccb_frame->mfr_header;
                   1785:        sgl = ccb->ccb_sgl;
                   1786:        sgd = ccb->ccb_dmamap->dm_segs;
                   1787:        for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
1.69      msaitoh  1788:                if (((sc->sc_ioptype == MFI_IOP_SKINNY) ||
                   1789:                        (sc->sc_ioptype == MFI_IOP_TBOLT)) &&
1.43      bouyer   1790:                    (hdr->mfh_cmd == MFI_CMD_PD_SCSI_IO ||
                   1791:                     hdr->mfh_cmd == MFI_CMD_LD_READ ||
                   1792:                     hdr->mfh_cmd == MFI_CMD_LD_WRITE)) {
                   1793:                        sgl->sg_ieee[i].addr = htole64(sgd[i].ds_addr);
                   1794:                        sgl->sg_ieee[i].len = htole32(sgd[i].ds_len);
                   1795:                        sgl->sg_ieee[i].flags = 0;
                   1796:                        DNPRINTF(MFI_D_DMA, "%s: addr: %#" PRIx64 " len: %#"
                   1797:                            PRIx32 "\n",
                   1798:                            DEVNAME(sc), sgl->sg64[i].addr, sgl->sg64[i].len);
                   1799:                        hdr->mfh_flags |= MFI_FRAME_IEEE_SGL | MFI_FRAME_SGL64;
                   1800:                } else if (sc->sc_64bit_dma) {
1.39      bouyer   1801:                        sgl->sg64[i].addr = htole64(sgd[i].ds_addr);
1.41      bouyer   1802:                        sgl->sg64[i].len = htole32(sgd[i].ds_len);
1.39      bouyer   1803:                        DNPRINTF(MFI_D_DMA, "%s: addr: %#" PRIx64 " len: %#"
1.43      bouyer   1804:                            PRIx32 "\n",
1.39      bouyer   1805:                            DEVNAME(sc), sgl->sg64[i].addr, sgl->sg64[i].len);
1.43      bouyer   1806:                        hdr->mfh_flags |= MFI_FRAME_SGL64;
1.39      bouyer   1807:                } else {
                   1808:                        sgl->sg32[i].addr = htole32(sgd[i].ds_addr);
                   1809:                        sgl->sg32[i].len = htole32(sgd[i].ds_len);
                   1810:                        DNPRINTF(MFI_D_DMA, "%s: addr: %#x  len: %#x\n",
                   1811:                            DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len);
1.43      bouyer   1812:                        hdr->mfh_flags |= MFI_FRAME_SGL32;
1.39      bouyer   1813:                }
1.1       bouyer   1814:        }
                   1815:
                   1816:        if (ccb->ccb_direction == MFI_DATA_IN) {
                   1817:                hdr->mfh_flags |= MFI_FRAME_DIR_READ;
1.43      bouyer   1818:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
1.1       bouyer   1819:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   1820:        } else {
                   1821:                hdr->mfh_flags |= MFI_FRAME_DIR_WRITE;
1.43      bouyer   1822:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
1.1       bouyer   1823:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
                   1824:        }
                   1825:
                   1826:        hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs;
1.39      bouyer   1827:        ccb->ccb_frame_size += sc->sc_sgl_size * ccb->ccb_dmamap->dm_nsegs;
1.1       bouyer   1828:        ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE;
                   1829:
                   1830:        DNPRINTF(MFI_D_DMA, "%s: sg_count: %d  frame_size: %d  frames_size: %d"
                   1831:            "  dm_nsegs: %d  extra_frames: %d\n",
                   1832:            DEVNAME(sc),
                   1833:            hdr->mfh_sg_count,
                   1834:            ccb->ccb_frame_size,
                   1835:            sc->sc_frames_size,
                   1836:            ccb->ccb_dmamap->dm_nsegs,
                   1837:            ccb->ccb_extra_frames);
                   1838:
1.13      xtraeme  1839:        return 0;
1.1       bouyer   1840: }
                   1841:
1.13      xtraeme  1842: static int
1.19      bouyer   1843: mfi_mgmt_internal(struct mfi_softc *sc, uint32_t opc, uint32_t dir,
1.74      msaitoh  1844:     uint32_t len, void *buf, const union mfi_mbox *mbox, bool poll)
1.33      msaitoh  1845: {
1.1       bouyer   1846:        struct mfi_ccb          *ccb;
                   1847:        int                     rv = 1;
                   1848:
                   1849:        if ((ccb = mfi_get_ccb(sc)) == NULL)
1.13      xtraeme  1850:                return rv;
1.19      bouyer   1851:        rv = mfi_mgmt(ccb, NULL, opc, dir, len, buf, mbox);
                   1852:        if (rv)
                   1853:                return rv;
                   1854:
1.45      bouyer   1855:        if (poll) {
1.43      bouyer   1856:                rv = 1;
1.19      bouyer   1857:                if (mfi_poll(ccb))
                   1858:                        goto done;
                   1859:        } else {
                   1860:                mfi_post(sc, ccb);
                   1861:
                   1862:                DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt_internal sleeping\n",
                   1863:                    DEVNAME(sc));
                   1864:                while (ccb->ccb_state != MFI_CCB_DONE)
                   1865:                        tsleep(ccb, PRIBIO, "mfi_mgmt", 0);
                   1866:
                   1867:                if (ccb->ccb_flags & MFI_CCB_F_ERR)
                   1868:                        goto done;
                   1869:        }
                   1870:        rv = 0;
                   1871:
                   1872: done:
                   1873:        mfi_put_ccb(ccb);
                   1874:        return rv;
                   1875: }
                   1876:
                   1877: static int
1.74      msaitoh  1878: mfi_mgmt(struct mfi_ccb *ccb, struct scsipi_xfer *xs, uint32_t opc,
                   1879:     uint32_t dir, uint32_t len, void *buf, const union mfi_mbox *mbox)
1.19      bouyer   1880: {
                   1881:        struct mfi_dcmd_frame   *dcmd;
                   1882:
                   1883:        DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(ccb->ccb_sc), opc);
1.1       bouyer   1884:
                   1885:        dcmd = &ccb->ccb_frame->mfr_dcmd;
1.60      bouyer   1886:        memset(dcmd->mdf_mbox.b, 0, MFI_MBOX_SIZE);
1.1       bouyer   1887:        dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD;
                   1888:        dcmd->mdf_header.mfh_timeout = 0;
                   1889:
                   1890:        dcmd->mdf_opcode = opc;
                   1891:        dcmd->mdf_header.mfh_data_len = 0;
                   1892:        ccb->ccb_direction = dir;
1.19      bouyer   1893:        ccb->ccb_xs = xs;
1.1       bouyer   1894:        ccb->ccb_done = mfi_mgmt_done;
                   1895:
                   1896:        ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE;
                   1897:
                   1898:        /* handle special opcodes */
                   1899:        if (mbox)
1.60      bouyer   1900:                memcpy(dcmd->mdf_mbox.b, mbox, MFI_MBOX_SIZE);
1.1       bouyer   1901:
                   1902:        if (dir != MFI_DATA_NONE) {
                   1903:                dcmd->mdf_header.mfh_data_len = len;
                   1904:                ccb->ccb_data = buf;
                   1905:                ccb->ccb_len = len;
                   1906:                ccb->ccb_sgl = &dcmd->mdf_sgl;
                   1907:
                   1908:                if (mfi_create_sgl(ccb, BUS_DMA_WAITOK))
1.19      bouyer   1909:                        return 1;
1.1       bouyer   1910:        }
1.19      bouyer   1911:        return 0;
1.1       bouyer   1912: }
                   1913:
1.13      xtraeme  1914: static void
1.1       bouyer   1915: mfi_mgmt_done(struct mfi_ccb *ccb)
                   1916: {
1.19      bouyer   1917:        struct scsipi_xfer      *xs = ccb->ccb_xs;
1.1       bouyer   1918:        struct mfi_softc        *sc = ccb->ccb_sc;
                   1919:        struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
                   1920:
1.4       bouyer   1921:        DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#lx %#lx\n",
                   1922:            DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame);
1.1       bouyer   1923:
                   1924:        if (ccb->ccb_data != NULL) {
                   1925:                DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n",
                   1926:                    DEVNAME(sc));
1.43      bouyer   1927:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
1.1       bouyer   1928:                    ccb->ccb_dmamap->dm_mapsize,
                   1929:                    (ccb->ccb_direction & MFI_DATA_IN) ?
                   1930:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                   1931:
1.43      bouyer   1932:                bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap);
1.1       bouyer   1933:        }
                   1934:
                   1935:        if (hdr->mfh_cmd_status != MFI_STAT_OK)
                   1936:                ccb->ccb_flags |= MFI_CCB_F_ERR;
                   1937:
                   1938:        ccb->ccb_state = MFI_CCB_DONE;
1.19      bouyer   1939:        if (xs) {
                   1940:                if (hdr->mfh_cmd_status != MFI_STAT_OK) {
                   1941:                        xs->error = XS_DRIVER_STUFFUP;
                   1942:                } else {
                   1943:                        xs->error = XS_NOERROR;
                   1944:                        xs->status = SCSI_OK;
                   1945:                        xs->resid = 0;
                   1946:                }
                   1947:                mfi_put_ccb(ccb);
                   1948:                scsipi_done(xs);
1.30      dyoung   1949:        } else
1.19      bouyer   1950:                wakeup(ccb);
1.1       bouyer   1951: }
                   1952:
                   1953: #if NBIO > 0
                   1954: int
1.23      cegger   1955: mfi_ioctl(device_t dev, u_long cmd, void *addr)
1.1       bouyer   1956: {
1.26      dyoung   1957:        struct mfi_softc *sc = device_private(dev);
1.1       bouyer   1958:        int error = 0;
1.31      bouyer   1959:        int s;
                   1960:
                   1961:        KERNEL_LOCK(1, curlwp);
                   1962:        s = splbio();
1.1       bouyer   1963:
                   1964:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc));
                   1965:
                   1966:        switch (cmd) {
                   1967:        case BIOCINQ:
                   1968:                DNPRINTF(MFI_D_IOCTL, "inq\n");
                   1969:                error = mfi_ioctl_inq(sc, (struct bioc_inq *)addr);
                   1970:                break;
                   1971:
                   1972:        case BIOCVOL:
                   1973:                DNPRINTF(MFI_D_IOCTL, "vol\n");
                   1974:                error = mfi_ioctl_vol(sc, (struct bioc_vol *)addr);
                   1975:                break;
                   1976:
                   1977:        case BIOCDISK:
                   1978:                DNPRINTF(MFI_D_IOCTL, "disk\n");
                   1979:                error = mfi_ioctl_disk(sc, (struct bioc_disk *)addr);
                   1980:                break;
                   1981:
                   1982:        case BIOCALARM:
                   1983:                DNPRINTF(MFI_D_IOCTL, "alarm\n");
                   1984:                error = mfi_ioctl_alarm(sc, (struct bioc_alarm *)addr);
                   1985:                break;
                   1986:
                   1987:        case BIOCBLINK:
                   1988:                DNPRINTF(MFI_D_IOCTL, "blink\n");
                   1989:                error = mfi_ioctl_blink(sc, (struct bioc_blink *)addr);
                   1990:                break;
                   1991:
                   1992:        case BIOCSETSTATE:
                   1993:                DNPRINTF(MFI_D_IOCTL, "setstate\n");
                   1994:                error = mfi_ioctl_setstate(sc, (struct bioc_setstate *)addr);
                   1995:                break;
                   1996:
                   1997:        default:
                   1998:                DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n");
                   1999:                error = EINVAL;
                   2000:        }
1.4       bouyer   2001:        splx(s);
1.31      bouyer   2002:        KERNEL_UNLOCK_ONE(curlwp);
1.13      xtraeme  2003:
1.4       bouyer   2004:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl return %x\n", DEVNAME(sc), error);
1.13      xtraeme  2005:        return error;
1.1       bouyer   2006: }
                   2007:
1.13      xtraeme  2008: static int
1.1       bouyer   2009: mfi_ioctl_inq(struct mfi_softc *sc, struct bioc_inq *bi)
                   2010: {
                   2011:        struct mfi_conf         *cfg;
                   2012:        int                     rv = EINVAL;
                   2013:
                   2014:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq\n", DEVNAME(sc));
                   2015:
                   2016:        if (mfi_get_info(sc)) {
                   2017:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq failed\n",
                   2018:                    DEVNAME(sc));
1.13      xtraeme  2019:                return EIO;
1.1       bouyer   2020:        }
                   2021:
                   2022:        /* get figures */
                   2023:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
1.60      bouyer   2024:        if (mfi_mgmt_internal(sc, MR_DCMD_CONF_GET, MFI_DATA_IN,
1.45      bouyer   2025:            sizeof *cfg, cfg, NULL, false))
1.1       bouyer   2026:                goto freeme;
                   2027:
                   2028:        strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
                   2029:        bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
                   2030:        bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
                   2031:
                   2032:        rv = 0;
                   2033: freeme:
                   2034:        free(cfg, M_DEVBUF);
1.13      xtraeme  2035:        return rv;
1.1       bouyer   2036: }
                   2037:
1.13      xtraeme  2038: static int
1.1       bouyer   2039: mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv)
                   2040: {
                   2041:        int                     i, per, rv = EINVAL;
1.74      msaitoh  2042:        union mfi_mbox          mbox;
1.1       bouyer   2043:
                   2044:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol %#x\n",
                   2045:            DEVNAME(sc), bv->bv_volid);
                   2046:
1.19      bouyer   2047:        if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN,
1.45      bouyer   2048:            sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL, false))
1.1       bouyer   2049:                goto done;
                   2050:
                   2051:        i = bv->bv_volid;
1.74      msaitoh  2052:        memset(&mbox, 0, sizeof(mbox));
                   2053:        mbox.b[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
1.1       bouyer   2054:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol target %#x\n",
1.74      msaitoh  2055:            DEVNAME(sc), mbox.b[0]);
1.1       bouyer   2056:
1.19      bouyer   2057:        if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_INFO, MFI_DATA_IN,
1.74      msaitoh  2058:            sizeof(sc->sc_ld_details), &sc->sc_ld_details, &mbox, false))
1.1       bouyer   2059:                goto done;
                   2060:
                   2061:        if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
                   2062:                /* go do hotspares */
                   2063:                rv = mfi_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
                   2064:                goto done;
                   2065:        }
                   2066:
                   2067:        strlcpy(bv->bv_dev, sc->sc_ld[i].ld_dev, sizeof(bv->bv_dev));
                   2068:
1.73      msaitoh  2069:        switch (sc->sc_ld_list.mll_list[i].mll_state) {
1.1       bouyer   2070:        case MFI_LD_OFFLINE:
                   2071:                bv->bv_status = BIOC_SVOFFLINE;
                   2072:                break;
                   2073:
                   2074:        case MFI_LD_PART_DEGRADED:
                   2075:        case MFI_LD_DEGRADED:
                   2076:                bv->bv_status = BIOC_SVDEGRADED;
                   2077:                break;
                   2078:
                   2079:        case MFI_LD_ONLINE:
                   2080:                bv->bv_status = BIOC_SVONLINE;
                   2081:                break;
                   2082:
                   2083:        default:
                   2084:                bv->bv_status = BIOC_SVINVALID;
                   2085:                DNPRINTF(MFI_D_IOCTL, "%s: invalid logical disk state %#x\n",
                   2086:                    DEVNAME(sc),
                   2087:                    sc->sc_ld_list.mll_list[i].mll_state);
                   2088:        }
                   2089:
                   2090:        /* additional status can modify MFI status */
                   2091:        switch (sc->sc_ld_details.mld_progress.mlp_in_prog) {
                   2092:        case MFI_LD_PROG_CC:
                   2093:                bv->bv_status = BIOC_SVSCRUB;
                   2094:                per = (int)sc->sc_ld_details.mld_progress.mlp_cc.mp_progress;
                   2095:                bv->bv_percent = (per * 100) / 0xffff;
                   2096:                bv->bv_seconds =
                   2097:                    sc->sc_ld_details.mld_progress.mlp_cc.mp_elapsed_seconds;
                   2098:                break;
                   2099:
1.71      msaitoh  2100:        case MFI_LD_PROG_BGI:
                   2101:                bv->bv_status = BIOC_SVSCRUB;
                   2102:                per = (int)sc->sc_ld_details.mld_progress.mlp_bgi.mp_progress;
                   2103:                bv->bv_percent = (per * 100) / 0xffff;
                   2104:                bv->bv_seconds =
                   2105:                    sc->sc_ld_details.mld_progress.mlp_bgi.mp_elapsed_seconds;
                   2106:                break;
                   2107:
1.1       bouyer   2108:        case MFI_LD_PROG_FGI:
                   2109:        case MFI_LD_PROG_RECONSTRUCT:
                   2110:                /* nothing yet */
                   2111:                break;
                   2112:        }
                   2113:
                   2114:        /*
                   2115:         * The RAID levels are determined per the SNIA DDF spec, this is only
1.70      msaitoh  2116:         * a subset that is valid for the MFI controller.
1.1       bouyer   2117:         */
                   2118:        bv->bv_level = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_pri_raid;
                   2119:        if (sc->sc_ld_details.mld_cfg.mlc_parm.mpa_sec_raid ==
                   2120:            MFI_DDF_SRL_SPANNED)
                   2121:                bv->bv_level *= 10;
                   2122:
                   2123:        bv->bv_nodisk = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_no_drv_per_span *
                   2124:            sc->sc_ld_details.mld_cfg.mlc_parm.mpa_span_depth;
                   2125:
                   2126:        bv->bv_size = sc->sc_ld_details.mld_size * 512; /* bytes per block */
1.75      msaitoh  2127:        bv->bv_stripe_size =
                   2128:            (512 << sc->sc_ld_details.mld_cfg.mlc_parm.mpa_stripe_size)
                   2129:            / 1024; /* in KB */
1.1       bouyer   2130:
                   2131:        rv = 0;
                   2132: done:
1.4       bouyer   2133:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol done %x\n",
                   2134:            DEVNAME(sc), rv);
1.13      xtraeme  2135:        return rv;
1.1       bouyer   2136: }
                   2137:
1.13      xtraeme  2138: static int
1.1       bouyer   2139: mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
                   2140: {
                   2141:        struct mfi_conf         *cfg;
                   2142:        struct mfi_array        *ar;
                   2143:        struct mfi_ld_cfg       *ld;
                   2144:        struct mfi_pd_details   *pd;
1.4       bouyer   2145:        struct scsipi_inquiry_data *inqbuf;
1.1       bouyer   2146:        char                    vend[8+16+4+1];
                   2147:        int                     i, rv = EINVAL;
                   2148:        int                     arr, vol, disk;
                   2149:        uint32_t                size;
1.74      msaitoh  2150:        union mfi_mbox          mbox;
1.1       bouyer   2151:
                   2152:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n",
                   2153:            DEVNAME(sc), bd->bd_diskid);
                   2154:
1.4       bouyer   2155:        pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO);
1.1       bouyer   2156:
                   2157:        /* send single element command to retrieve size for full structure */
                   2158:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
1.60      bouyer   2159:        if (mfi_mgmt_internal(sc, MR_DCMD_CONF_GET, MFI_DATA_IN,
1.45      bouyer   2160:            sizeof *cfg, cfg, NULL, false))
1.1       bouyer   2161:                goto freeme;
                   2162:
                   2163:        size = cfg->mfc_size;
                   2164:        free(cfg, M_DEVBUF);
                   2165:
                   2166:        /* memory for read config */
1.13      xtraeme  2167:        cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
1.60      bouyer   2168:        if (mfi_mgmt_internal(sc, MR_DCMD_CONF_GET, MFI_DATA_IN,
1.45      bouyer   2169:            size, cfg, NULL, false))
1.1       bouyer   2170:                goto freeme;
                   2171:
                   2172:        ar = cfg->mfc_array;
                   2173:
                   2174:        /* calculate offset to ld structure */
                   2175:        ld = (struct mfi_ld_cfg *)(
                   2176:            ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
                   2177:            cfg->mfc_array_size * cfg->mfc_no_array);
                   2178:
                   2179:        vol = bd->bd_volid;
                   2180:
                   2181:        if (vol >= cfg->mfc_no_ld) {
                   2182:                /* do hotspares */
                   2183:                rv = mfi_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
                   2184:                goto freeme;
                   2185:        }
                   2186:
                   2187:        /* find corresponding array for ld */
                   2188:        for (i = 0, arr = 0; i < vol; i++)
                   2189:                arr += ld[i].mlc_parm.mpa_span_depth;
                   2190:
                   2191:        /* offset disk into pd list */
                   2192:        disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
                   2193:
                   2194:        /* offset array index into the next spans */
                   2195:        arr += bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
                   2196:
                   2197:        bd->bd_target = ar[arr].pd[disk].mar_enc_slot;
                   2198:        switch (ar[arr].pd[disk].mar_pd_state){
                   2199:        case MFI_PD_UNCONFIG_GOOD:
                   2200:                bd->bd_status = BIOC_SDUNUSED;
                   2201:                break;
                   2202:
                   2203:        case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
                   2204:                bd->bd_status = BIOC_SDHOTSPARE;
                   2205:                break;
                   2206:
                   2207:        case MFI_PD_OFFLINE:
                   2208:                bd->bd_status = BIOC_SDOFFLINE;
                   2209:                break;
                   2210:
                   2211:        case MFI_PD_FAILED:
                   2212:                bd->bd_status = BIOC_SDFAILED;
                   2213:                break;
                   2214:
                   2215:        case MFI_PD_REBUILD:
                   2216:                bd->bd_status = BIOC_SDREBUILD;
                   2217:                break;
                   2218:
                   2219:        case MFI_PD_ONLINE:
                   2220:                bd->bd_status = BIOC_SDONLINE;
                   2221:                break;
                   2222:
                   2223:        case MFI_PD_UNCONFIG_BAD: /* XXX define new state in bio */
                   2224:        default:
                   2225:                bd->bd_status = BIOC_SDINVALID;
                   2226:                break;
                   2227:        }
                   2228:
                   2229:        /* get the remaining fields */
1.74      msaitoh  2230:        memset(&mbox, 0, sizeof(mbox));
                   2231:        mbox.s[0] = ar[arr].pd[disk].mar_pd.mfp_id;
1.4       bouyer   2232:        memset(pd, 0, sizeof(*pd));
1.19      bouyer   2233:        if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
1.74      msaitoh  2234:            sizeof *pd, pd, &mbox, false))
1.1       bouyer   2235:                goto freeme;
                   2236:
                   2237:        bd->bd_size = pd->mpd_size * 512; /* bytes per block */
                   2238:
                   2239:        /* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
                   2240:        bd->bd_channel = pd->mpd_enc_idx;
                   2241:
1.4       bouyer   2242:        inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
1.1       bouyer   2243:        memcpy(vend, inqbuf->vendor, sizeof vend - 1);
                   2244:        vend[sizeof vend - 1] = '\0';
                   2245:        strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
                   2246:
                   2247:        /* XXX find a way to retrieve serial nr from drive */
                   2248:        /* XXX find a way to get bd_procdev */
                   2249:
                   2250:        rv = 0;
                   2251: freeme:
                   2252:        free(pd, M_DEVBUF);
                   2253:        free(cfg, M_DEVBUF);
                   2254:
1.13      xtraeme  2255:        return rv;
1.1       bouyer   2256: }
                   2257:
1.13      xtraeme  2258: static int
1.1       bouyer   2259: mfi_ioctl_alarm(struct mfi_softc *sc, struct bioc_alarm *ba)
                   2260: {
                   2261:        uint32_t                opc, dir = MFI_DATA_NONE;
                   2262:        int                     rv = 0;
                   2263:        int8_t                  ret;
                   2264:
1.73      msaitoh  2265:        switch (ba->ba_opcode) {
1.1       bouyer   2266:        case BIOC_SADISABLE:
                   2267:                opc = MR_DCMD_SPEAKER_DISABLE;
                   2268:                break;
                   2269:
                   2270:        case BIOC_SAENABLE:
                   2271:                opc = MR_DCMD_SPEAKER_ENABLE;
                   2272:                break;
                   2273:
                   2274:        case BIOC_SASILENCE:
                   2275:                opc = MR_DCMD_SPEAKER_SILENCE;
                   2276:                break;
                   2277:
                   2278:        case BIOC_GASTATUS:
                   2279:                opc = MR_DCMD_SPEAKER_GET;
                   2280:                dir = MFI_DATA_IN;
                   2281:                break;
                   2282:
                   2283:        case BIOC_SATEST:
                   2284:                opc = MR_DCMD_SPEAKER_TEST;
                   2285:                break;
                   2286:
                   2287:        default:
                   2288:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_alarm biocalarm invalid "
                   2289:                    "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
1.13      xtraeme  2290:                return EINVAL;
1.1       bouyer   2291:        }
                   2292:
1.45      bouyer   2293:        if (mfi_mgmt_internal(sc, opc, dir, sizeof(ret), &ret, NULL, false))
1.1       bouyer   2294:                rv = EINVAL;
                   2295:        else
                   2296:                if (ba->ba_opcode == BIOC_GASTATUS)
                   2297:                        ba->ba_status = ret;
                   2298:                else
                   2299:                        ba->ba_status = 0;
                   2300:
1.13      xtraeme  2301:        return rv;
1.1       bouyer   2302: }
                   2303:
1.13      xtraeme  2304: static int
1.1       bouyer   2305: mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *bb)
                   2306: {
                   2307:        int                     i, found, rv = EINVAL;
1.74      msaitoh  2308:        union mfi_mbox          mbox;
1.1       bouyer   2309:        uint32_t                cmd;
                   2310:        struct mfi_pd_list      *pd;
                   2311:
                   2312:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc),
                   2313:            bb->bb_status);
                   2314:
                   2315:        /* channel 0 means not in an enclosure so can't be blinked */
                   2316:        if (bb->bb_channel == 0)
1.13      xtraeme  2317:                return EINVAL;
1.1       bouyer   2318:
1.76    ! msaitoh  2319:        pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
1.1       bouyer   2320:
1.19      bouyer   2321:        if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
1.76    ! msaitoh  2322:            sizeof(*pd), pd, NULL, false))
1.1       bouyer   2323:                goto done;
                   2324:
                   2325:        for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
                   2326:                if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
                   2327:                    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
1.73      msaitoh  2328:                        found = 1;
1.1       bouyer   2329:                        break;
                   2330:                }
                   2331:
                   2332:        if (!found)
                   2333:                goto done;
                   2334:
1.74      msaitoh  2335:        memset(&mbox, 0, sizeof(mbox));
                   2336:        mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
1.1       bouyer   2337:
                   2338:        switch (bb->bb_status) {
                   2339:        case BIOC_SBUNBLINK:
                   2340:                cmd = MR_DCMD_PD_UNBLINK;
                   2341:                break;
                   2342:
                   2343:        case BIOC_SBBLINK:
                   2344:                cmd = MR_DCMD_PD_BLINK;
                   2345:                break;
                   2346:
                   2347:        case BIOC_SBALARM:
                   2348:        default:
                   2349:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink biocblink invalid "
                   2350:                    "opcode %x\n", DEVNAME(sc), bb->bb_status);
                   2351:                goto done;
                   2352:        }
                   2353:
                   2354:
1.74      msaitoh  2355:        if (mfi_mgmt_internal(sc, cmd, MFI_DATA_NONE, 0, NULL, &mbox, false))
1.1       bouyer   2356:                goto done;
                   2357:
                   2358:        rv = 0;
                   2359: done:
                   2360:        free(pd, M_DEVBUF);
1.13      xtraeme  2361:        return rv;
1.1       bouyer   2362: }
                   2363:
1.13      xtraeme  2364: static int
1.1       bouyer   2365: mfi_ioctl_setstate(struct mfi_softc *sc, struct bioc_setstate *bs)
                   2366: {
                   2367:        struct mfi_pd_list      *pd;
                   2368:        int                     i, found, rv = EINVAL;
1.74      msaitoh  2369:        union mfi_mbox          mbox;
1.1       bouyer   2370:
                   2371:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc),
                   2372:            bs->bs_status);
                   2373:
1.76    ! msaitoh  2374:        pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
1.1       bouyer   2375:
1.19      bouyer   2376:        if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
1.76    ! msaitoh  2377:            sizeof(*pd), pd, NULL, false))
1.1       bouyer   2378:                goto done;
                   2379:
                   2380:        for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
                   2381:                if (bs->bs_channel == pd->mpl_address[i].mpa_enc_index &&
                   2382:                    bs->bs_target == pd->mpl_address[i].mpa_enc_slot) {
1.73      msaitoh  2383:                        found = 1;
1.1       bouyer   2384:                        break;
                   2385:                }
                   2386:
                   2387:        if (!found)
                   2388:                goto done;
                   2389:
1.74      msaitoh  2390:        memset(&mbox, 0, sizeof(mbox));
                   2391:        mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
1.1       bouyer   2392:
                   2393:        switch (bs->bs_status) {
                   2394:        case BIOC_SSONLINE:
1.74      msaitoh  2395:                mbox.b[4] = MFI_PD_ONLINE;
1.1       bouyer   2396:                break;
                   2397:
                   2398:        case BIOC_SSOFFLINE:
1.74      msaitoh  2399:                mbox.b[4] = MFI_PD_OFFLINE;
1.1       bouyer   2400:                break;
                   2401:
                   2402:        case BIOC_SSHOTSPARE:
1.74      msaitoh  2403:                mbox.b[4] = MFI_PD_HOTSPARE;
1.1       bouyer   2404:                break;
                   2405: /*
                   2406:        case BIOC_SSREBUILD:
                   2407:                break;
                   2408: */
                   2409:        default:
                   2410:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate invalid "
                   2411:                    "opcode %x\n", DEVNAME(sc), bs->bs_status);
                   2412:                goto done;
                   2413:        }
                   2414:
                   2415:
1.60      bouyer   2416:        if (mfi_mgmt_internal(sc, MR_DCMD_PD_SET_STATE, MFI_DATA_NONE,
1.74      msaitoh  2417:            0, NULL, &mbox, false))
1.1       bouyer   2418:                goto done;
                   2419:
                   2420:        rv = 0;
                   2421: done:
                   2422:        free(pd, M_DEVBUF);
1.13      xtraeme  2423:        return rv;
1.1       bouyer   2424: }
                   2425:
1.13      xtraeme  2426: static int
1.1       bouyer   2427: mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
                   2428: {
                   2429:        struct mfi_conf         *cfg;
                   2430:        struct mfi_hotspare     *hs;
                   2431:        struct mfi_pd_details   *pd;
                   2432:        struct bioc_disk        *sdhs;
                   2433:        struct bioc_vol         *vdhs;
1.4       bouyer   2434:        struct scsipi_inquiry_data *inqbuf;
1.1       bouyer   2435:        char                    vend[8+16+4+1];
                   2436:        int                     i, rv = EINVAL;
                   2437:        uint32_t                size;
1.74      msaitoh  2438:        union mfi_mbox          mbox;
1.1       bouyer   2439:
                   2440:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs %d\n", DEVNAME(sc), volid);
                   2441:
                   2442:        if (!bio_hs)
1.13      xtraeme  2443:                return EINVAL;
1.1       bouyer   2444:
1.4       bouyer   2445:        pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO);
1.1       bouyer   2446:
                   2447:        /* send single element command to retrieve size for full structure */
                   2448:        cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
1.60      bouyer   2449:        if (mfi_mgmt_internal(sc, MR_DCMD_CONF_GET, MFI_DATA_IN,
1.45      bouyer   2450:            sizeof *cfg, cfg, NULL, false))
1.1       bouyer   2451:                goto freeme;
                   2452:
                   2453:        size = cfg->mfc_size;
                   2454:        free(cfg, M_DEVBUF);
                   2455:
                   2456:        /* memory for read config */
1.13      xtraeme  2457:        cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
1.60      bouyer   2458:        if (mfi_mgmt_internal(sc, MR_DCMD_CONF_GET, MFI_DATA_IN,
1.45      bouyer   2459:            size, cfg, NULL, false))
1.1       bouyer   2460:                goto freeme;
                   2461:
                   2462:        /* calculate offset to hs structure */
                   2463:        hs = (struct mfi_hotspare *)(
                   2464:            ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
                   2465:            cfg->mfc_array_size * cfg->mfc_no_array +
                   2466:            cfg->mfc_ld_size * cfg->mfc_no_ld);
                   2467:
                   2468:        if (volid < cfg->mfc_no_ld)
                   2469:                goto freeme; /* not a hotspare */
                   2470:
                   2471:        if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
                   2472:                goto freeme; /* not a hotspare */
                   2473:
                   2474:        /* offset into hotspare structure */
                   2475:        i = volid - cfg->mfc_no_ld;
                   2476:
                   2477:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d "
                   2478:            "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
                   2479:            cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
                   2480:
                   2481:        /* get pd fields */
1.74      msaitoh  2482:        memset(&mbox, 0, sizeof(mbox));
                   2483:        mbox.s[0] = hs[i].mhs_pd.mfp_id;
1.19      bouyer   2484:        if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
1.74      msaitoh  2485:            sizeof *pd, pd, &mbox, false)) {
1.1       bouyer   2486:                DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs illegal PD\n",
                   2487:                    DEVNAME(sc));
                   2488:                goto freeme;
                   2489:        }
                   2490:
                   2491:        switch (type) {
                   2492:        case MFI_MGMT_VD:
                   2493:                vdhs = bio_hs;
                   2494:                vdhs->bv_status = BIOC_SVONLINE;
1.14      xtraeme  2495:                vdhs->bv_size = pd->mpd_size * 512; /* bytes per block */
1.1       bouyer   2496:                vdhs->bv_level = -1; /* hotspare */
                   2497:                vdhs->bv_nodisk = 1;
                   2498:                break;
                   2499:
                   2500:        case MFI_MGMT_SD:
                   2501:                sdhs = bio_hs;
                   2502:                sdhs->bd_status = BIOC_SDHOTSPARE;
1.14      xtraeme  2503:                sdhs->bd_size = pd->mpd_size * 512; /* bytes per block */
1.1       bouyer   2504:                sdhs->bd_channel = pd->mpd_enc_idx;
                   2505:                sdhs->bd_target = pd->mpd_enc_slot;
1.4       bouyer   2506:                inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
                   2507:                memcpy(vend, inqbuf->vendor, sizeof(vend) - 1);
1.1       bouyer   2508:                vend[sizeof vend - 1] = '\0';
                   2509:                strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
                   2510:                break;
                   2511:
                   2512:        default:
                   2513:                goto freeme;
                   2514:        }
                   2515:
                   2516:        DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs 6\n", DEVNAME(sc));
                   2517:        rv = 0;
                   2518: freeme:
                   2519:        free(pd, M_DEVBUF);
                   2520:        free(cfg, M_DEVBUF);
                   2521:
1.13      xtraeme  2522:        return rv;
1.1       bouyer   2523: }
                   2524:
1.13      xtraeme  2525: static int
1.24      dyoung   2526: mfi_destroy_sensors(struct mfi_softc *sc)
                   2527: {
1.27      dyoung   2528:        if (sc->sc_sme == NULL)
                   2529:                return 0;
1.24      dyoung   2530:        sysmon_envsys_unregister(sc->sc_sme);
1.27      dyoung   2531:        sc->sc_sme = NULL;
1.24      dyoung   2532:        free(sc->sc_sensor, M_DEVBUF);
                   2533:        return 0;
                   2534: }
                   2535:
                   2536: static int
1.1       bouyer   2537: mfi_create_sensors(struct mfi_softc *sc)
                   2538: {
1.13      xtraeme  2539:        int i;
1.45      bouyer   2540:        int nsensors = sc->sc_ld_cnt + 1;
1.32      msaitoh  2541:        int rv;
1.1       bouyer   2542:
1.11      xtraeme  2543:        sc->sc_sme = sysmon_envsys_create();
                   2544:        sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors,
1.62      chs      2545:            M_DEVBUF, M_WAITOK | M_ZERO);
1.6       xtraeme  2546:
1.45      bouyer   2547:        /* BBU */
                   2548:        sc->sc_sensor[0].units = ENVSYS_INDICATOR;
                   2549:        sc->sc_sensor[0].state = ENVSYS_SINVALID;
                   2550:        sc->sc_sensor[0].value_cur = 0;
                   2551:        /* Enable monitoring for BBU state changes, if present */
                   2552:        if (sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU)
                   2553:                sc->sc_sensor[0].flags |= ENVSYS_FMONCRITICAL;
                   2554:        snprintf(sc->sc_sensor[0].desc,
                   2555:            sizeof(sc->sc_sensor[0].desc), "%s BBU", DEVNAME(sc));
                   2556:        if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[0]))
                   2557:                goto out;
                   2558:
                   2559:        for (i = 1; i < nsensors; i++) {
1.11      xtraeme  2560:                sc->sc_sensor[i].units = ENVSYS_DRIVE;
1.35      pgoyette 2561:                sc->sc_sensor[i].state = ENVSYS_SINVALID;
1.36      pgoyette 2562:                sc->sc_sensor[i].value_cur = ENVSYS_DRIVE_EMPTY;
1.6       xtraeme  2563:                /* Enable monitoring for drive state changes */
1.11      xtraeme  2564:                sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED;
1.4       bouyer   2565:                /* logical drives */
1.11      xtraeme  2566:                snprintf(sc->sc_sensor[i].desc,
                   2567:                    sizeof(sc->sc_sensor[i].desc), "%s:%d",
1.45      bouyer   2568:                    DEVNAME(sc), i - 1);
1.11      xtraeme  2569:                if (sysmon_envsys_sensor_attach(sc->sc_sme,
                   2570:                                                &sc->sc_sensor[i]))
                   2571:                        goto out;
1.4       bouyer   2572:        }
1.6       xtraeme  2573:
1.11      xtraeme  2574:        sc->sc_sme->sme_name = DEVNAME(sc);
                   2575:        sc->sc_sme->sme_cookie = sc;
                   2576:        sc->sc_sme->sme_refresh = mfi_sensor_refresh;
1.32      msaitoh  2577:        rv = sysmon_envsys_register(sc->sc_sme);
                   2578:        if (rv != 0) {
1.43      bouyer   2579:                aprint_error_dev(sc->sc_dev,
                   2580:                    "unable to register with sysmon (rv = %d)\n", rv);
1.11      xtraeme  2581:                goto out;
1.1       bouyer   2582:        }
1.13      xtraeme  2583:        return 0;
1.11      xtraeme  2584:
                   2585: out:
                   2586:        free(sc->sc_sensor, M_DEVBUF);
                   2587:        sysmon_envsys_destroy(sc->sc_sme);
1.32      msaitoh  2588:        sc->sc_sme = NULL;
1.11      xtraeme  2589:        return EINVAL;
1.1       bouyer   2590: }
                   2591:
1.13      xtraeme  2592: static void
1.11      xtraeme  2593: mfi_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
1.1       bouyer   2594: {
1.4       bouyer   2595:        struct mfi_softc        *sc = sme->sme_cookie;
1.1       bouyer   2596:        struct bioc_vol         bv;
1.4       bouyer   2597:        int s;
1.28      bouyer   2598:        int error;
1.1       bouyer   2599:
1.45      bouyer   2600:        if (edata->sensor >= sc->sc_ld_cnt + 1)
                   2601:                return;
                   2602:
                   2603:        if (edata->sensor == 0) {
                   2604:                /* BBU */
                   2605:                struct mfi_bbu_status   bbu_stat;
                   2606:                int bbu_status;
                   2607:                if ((sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU) == 0)
                   2608:                        return;
                   2609:
                   2610:                KERNEL_LOCK(1, curlwp);
                   2611:                s = splbio();
                   2612:                bbu_status = mfi_get_bbu(sc, &bbu_stat);
                   2613:                splx(s);
                   2614:                KERNEL_UNLOCK_ONE(curlwp);
1.73      msaitoh  2615:                switch (bbu_status) {
1.45      bouyer   2616:                case MFI_BBU_GOOD:
                   2617:                        edata->value_cur = 1;
                   2618:                        edata->state = ENVSYS_SVALID;
1.46      bouyer   2619:                        if (!sc->sc_bbuok)
                   2620:                                aprint_normal_dev(sc->sc_dev,
                   2621:                                    "BBU state changed to good\n");
1.45      bouyer   2622:                        sc->sc_bbuok = true;
                   2623:                        break;
                   2624:                case MFI_BBU_BAD:
                   2625:                        edata->value_cur = 0;
                   2626:                        edata->state = ENVSYS_SCRITICAL;
1.46      bouyer   2627:                        if (sc->sc_bbuok)
                   2628:                                aprint_normal_dev(sc->sc_dev,
                   2629:                                    "BBU state changed to bad\n");
1.45      bouyer   2630:                        sc->sc_bbuok = false;
                   2631:                        break;
                   2632:                case MFI_BBU_UNKNOWN:
                   2633:                default:
                   2634:                        edata->value_cur = 0;
                   2635:                        edata->state = ENVSYS_SINVALID;
                   2636:                        sc->sc_bbuok = false;
                   2637:                        break;
                   2638:                }
1.11      xtraeme  2639:                return;
1.45      bouyer   2640:        }
1.1       bouyer   2641:
1.22      cegger   2642:        memset(&bv, 0, sizeof(bv));
1.45      bouyer   2643:        bv.bv_volid = edata->sensor - 1;
1.28      bouyer   2644:        KERNEL_LOCK(1, curlwp);
1.4       bouyer   2645:        s = splbio();
1.28      bouyer   2646:        error = mfi_ioctl_vol(sc, &bv);
1.4       bouyer   2647:        splx(s);
1.28      bouyer   2648:        KERNEL_UNLOCK_ONE(curlwp);
                   2649:        if (error)
1.56      christos 2650:                bv.bv_status = BIOC_SVINVALID;
1.1       bouyer   2651:
1.56      christos 2652:        bio_vol_to_envsys(edata, &bv);
1.4       bouyer   2653: }
                   2654:
1.1       bouyer   2655: #endif /* NBIO > 0 */
1.12      xtraeme  2656:
1.13      xtraeme  2657: static uint32_t
1.12      xtraeme  2658: mfi_xscale_fw_state(struct mfi_softc *sc)
                   2659: {
                   2660:        return mfi_read(sc, MFI_OMSG0);
                   2661: }
1.30      dyoung   2662:
1.13      xtraeme  2663: static void
1.24      dyoung   2664: mfi_xscale_intr_dis(struct mfi_softc *sc)
                   2665: {
                   2666:        mfi_write(sc, MFI_OMSK, 0);
                   2667: }
                   2668:
                   2669: static void
1.12      xtraeme  2670: mfi_xscale_intr_ena(struct mfi_softc *sc)
                   2671: {
                   2672:        mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
                   2673: }
1.30      dyoung   2674:
1.13      xtraeme  2675: static int
1.12      xtraeme  2676: mfi_xscale_intr(struct mfi_softc *sc)
                   2677: {
                   2678:        uint32_t status;
                   2679:
                   2680:        status = mfi_read(sc, MFI_OSTS);
                   2681:        if (!ISSET(status, MFI_OSTS_INTR_VALID))
                   2682:                return 0;
                   2683:
                   2684:        /* write status back to acknowledge interrupt */
                   2685:        mfi_write(sc, MFI_OSTS, status);
                   2686:        return 1;
                   2687: }
1.30      dyoung   2688:
1.13      xtraeme  2689: static void
1.12      xtraeme  2690: mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
                   2691: {
1.14      xtraeme  2692:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
                   2693:            ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames),
                   2694:            sc->sc_frames_size, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   2695:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_sense),
                   2696:            ccb->ccb_psense - MFIMEM_DVA(sc->sc_sense),
                   2697:            MFI_SENSE_SIZE, BUS_DMASYNC_PREREAD);
                   2698:
1.12      xtraeme  2699:        mfi_write(sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
                   2700:            ccb->ccb_extra_frames);
1.43      bouyer   2701:        ccb->ccb_state = MFI_CCB_RUNNING;
1.12      xtraeme  2702: }
1.30      dyoung   2703:
1.13      xtraeme  2704: static uint32_t
1.12      xtraeme  2705: mfi_ppc_fw_state(struct mfi_softc *sc)
                   2706: {
                   2707:        return mfi_read(sc, MFI_OSP);
                   2708: }
1.30      dyoung   2709:
1.13      xtraeme  2710: static void
1.24      dyoung   2711: mfi_ppc_intr_dis(struct mfi_softc *sc)
                   2712: {
                   2713:        /* Taking a wild guess --dyoung */
                   2714:        mfi_write(sc, MFI_OMSK, ~(uint32_t)0x0);
                   2715:        mfi_write(sc, MFI_ODC, 0xffffffff);
                   2716: }
                   2717:
                   2718: static void
1.12      xtraeme  2719: mfi_ppc_intr_ena(struct mfi_softc *sc)
                   2720: {
                   2721:        mfi_write(sc, MFI_ODC, 0xffffffff);
                   2722:        mfi_write(sc, MFI_OMSK, ~0x80000004);
                   2723: }
1.30      dyoung   2724:
1.13      xtraeme  2725: static int
1.12      xtraeme  2726: mfi_ppc_intr(struct mfi_softc *sc)
                   2727: {
                   2728:        uint32_t status;
1.30      dyoung   2729:
1.12      xtraeme  2730:        status = mfi_read(sc, MFI_OSTS);
                   2731:        if (!ISSET(status, MFI_OSTS_PPC_INTR_VALID))
                   2732:                return 0;
1.30      dyoung   2733:
1.12      xtraeme  2734:        /* write status back to acknowledge interrupt */
                   2735:        mfi_write(sc, MFI_ODC, status);
                   2736:        return 1;
                   2737: }
1.30      dyoung   2738:
1.13      xtraeme  2739: static void
1.12      xtraeme  2740: mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
                   2741: {
                   2742:        mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
                   2743:            (ccb->ccb_extra_frames << 1));
1.43      bouyer   2744:        ccb->ccb_state = MFI_CCB_RUNNING;
1.12      xtraeme  2745: }
1.33      msaitoh  2746:
                   2747: u_int32_t
                   2748: mfi_gen2_fw_state(struct mfi_softc *sc)
                   2749: {
                   2750:        return (mfi_read(sc, MFI_OSP));
                   2751: }
                   2752:
                   2753: void
                   2754: mfi_gen2_intr_dis(struct mfi_softc *sc)
                   2755: {
                   2756:        mfi_write(sc, MFI_OMSK, 0xffffffff);
                   2757:        mfi_write(sc, MFI_ODC, 0xffffffff);
                   2758: }
                   2759:
                   2760: void
                   2761: mfi_gen2_intr_ena(struct mfi_softc *sc)
                   2762: {
                   2763:        mfi_write(sc, MFI_ODC, 0xffffffff);
                   2764:        mfi_write(sc, MFI_OMSK, ~MFI_OSTS_GEN2_INTR_VALID);
                   2765: }
                   2766:
                   2767: int
                   2768: mfi_gen2_intr(struct mfi_softc *sc)
                   2769: {
                   2770:        u_int32_t status;
                   2771:
                   2772:        status = mfi_read(sc, MFI_OSTS);
                   2773:        if (!ISSET(status, MFI_OSTS_GEN2_INTR_VALID))
                   2774:                return (0);
                   2775:
                   2776:        /* write status back to acknowledge interrupt */
                   2777:        mfi_write(sc, MFI_ODC, status);
                   2778:
                   2779:        return (1);
                   2780: }
                   2781:
                   2782: void
                   2783: mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
                   2784: {
                   2785:        mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
                   2786:            (ccb->ccb_extra_frames << 1));
1.43      bouyer   2787:        ccb->ccb_state = MFI_CCB_RUNNING;
1.33      msaitoh  2788: }
1.38      sborrill 2789:
                   2790: u_int32_t
                   2791: mfi_skinny_fw_state(struct mfi_softc *sc)
                   2792: {
                   2793:        return (mfi_read(sc, MFI_OSP));
                   2794: }
                   2795:
                   2796: void
                   2797: mfi_skinny_intr_dis(struct mfi_softc *sc)
                   2798: {
                   2799:        mfi_write(sc, MFI_OMSK, 0);
                   2800: }
                   2801:
                   2802: void
                   2803: mfi_skinny_intr_ena(struct mfi_softc *sc)
                   2804: {
                   2805:        mfi_write(sc, MFI_OMSK, ~0x00000001);
                   2806: }
                   2807:
                   2808: int
                   2809: mfi_skinny_intr(struct mfi_softc *sc)
                   2810: {
                   2811:        u_int32_t status;
                   2812:
                   2813:        status = mfi_read(sc, MFI_OSTS);
                   2814:        if (!ISSET(status, MFI_OSTS_SKINNY_INTR_VALID))
                   2815:                return (0);
                   2816:
                   2817:        /* write status back to acknowledge interrupt */
                   2818:        mfi_write(sc, MFI_OSTS, status);
                   2819:
                   2820:        return (1);
                   2821: }
                   2822:
                   2823: void
                   2824: mfi_skinny_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
                   2825: {
                   2826:        mfi_write(sc, MFI_IQPL, 0x1 | ccb->ccb_pframe |
                   2827:            (ccb->ccb_extra_frames << 1));
                   2828:        mfi_write(sc, MFI_IQPH, 0x00000000);
1.43      bouyer   2829:        ccb->ccb_state = MFI_CCB_RUNNING;
                   2830: }
                   2831:
                   2832: #define MFI_FUSION_ENABLE_INTERRUPT_MASK       (0x00000008)
                   2833:
                   2834: void
                   2835: mfi_tbolt_intr_ena(struct mfi_softc *sc)
                   2836: {
                   2837:        mfi_write(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK);
                   2838:        mfi_read(sc, MFI_OMSK);
                   2839: }
                   2840:
                   2841: void
                   2842: mfi_tbolt_intr_dis(struct mfi_softc *sc)
                   2843: {
                   2844:        mfi_write(sc, MFI_OMSK, 0xFFFFFFFF);
                   2845:        mfi_read(sc, MFI_OMSK);
                   2846: }
                   2847:
                   2848: int
                   2849: mfi_tbolt_intr(struct mfi_softc *sc)
                   2850: {
                   2851:        int32_t status;
                   2852:
                   2853:        status = mfi_read(sc, MFI_OSTS);
                   2854:
                   2855:        if (ISSET(status, 0x1)) {
                   2856:                mfi_write(sc, MFI_OSTS, status);
                   2857:                mfi_read(sc, MFI_OSTS);
                   2858:                if (ISSET(status, MFI_STATE_CHANGE_INTERRUPT))
                   2859:                        return 0;
                   2860:                return 1;
                   2861:        }
                   2862:        if (!ISSET(status, MFI_FUSION_ENABLE_INTERRUPT_MASK))
                   2863:                return 0;
                   2864:        mfi_read(sc, MFI_OSTS);
                   2865:        return 1;
                   2866: }
                   2867:
                   2868: u_int32_t
                   2869: mfi_tbolt_fw_state(struct mfi_softc *sc)
                   2870: {
                   2871:        return mfi_read(sc, MFI_OSP);
                   2872: }
                   2873:
                   2874: void
                   2875: mfi_tbolt_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
                   2876: {
                   2877:        if (sc->sc_MFA_enabled) {
                   2878:                if ((ccb->ccb_flags & MFI_CCB_F_TBOLT) == 0)
                   2879:                        mfi_tbolt_build_mpt_ccb(ccb);
                   2880:                mfi_write(sc, MFI_IQPL,
                   2881:                    ccb->ccb_tb_request_desc.words & 0xFFFFFFFF);
1.73      msaitoh  2882:                mfi_write(sc, MFI_IQPH,
1.43      bouyer   2883:                    ccb->ccb_tb_request_desc.words >> 32);
                   2884:                ccb->ccb_state = MFI_CCB_RUNNING;
                   2885:                return;
                   2886:        }
                   2887:        uint64_t bus_add = ccb->ccb_pframe;
                   2888:        bus_add |= (MFI_REQ_DESCRIPT_FLAGS_MFA
                   2889:            << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
                   2890:        mfi_write(sc, MFI_IQPL, bus_add);
                   2891:        mfi_write(sc, MFI_IQPH, bus_add >> 32);
                   2892:        ccb->ccb_state = MFI_CCB_RUNNING;
                   2893: }
                   2894:
                   2895: static void
                   2896: mfi_tbolt_build_mpt_ccb(struct mfi_ccb *ccb)
                   2897: {
                   2898:        union mfi_mpi2_request_descriptor *req_desc = &ccb->ccb_tb_request_desc;
                   2899:        struct mfi_mpi2_request_raid_scsi_io *io_req = ccb->ccb_tb_io_request;
                   2900:        struct mpi25_ieee_sge_chain64 *mpi25_ieee_chain;
                   2901:
                   2902:        io_req->Function = MPI2_FUNCTION_PASSTHRU_IO_REQUEST;
                   2903:        io_req->SGLOffset0 =
                   2904:            offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 4;
                   2905:        io_req->ChainOffset =
                   2906:            offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 16;
                   2907:
                   2908:        mpi25_ieee_chain =
                   2909:            (struct mpi25_ieee_sge_chain64 *)&io_req->SGL.IeeeChain;
                   2910:        mpi25_ieee_chain->Address = ccb->ccb_pframe;
                   2911:
                   2912:        /*
                   2913:          In MFI pass thru, nextChainOffset will always be zero to
                   2914:          indicate the end of the chain.
                   2915:        */
                   2916:        mpi25_ieee_chain->Flags= MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT
                   2917:                | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
                   2918:
                   2919:        /* setting the length to the maximum length */
                   2920:        mpi25_ieee_chain->Length = 1024;
                   2921:
                   2922:        req_desc->header.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
                   2923:            MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
                   2924:        ccb->ccb_flags |= MFI_CCB_F_TBOLT;
                   2925:        bus_dmamap_sync(ccb->ccb_sc->sc_dmat,
1.73      msaitoh  2926:            MFIMEM_MAP(ccb->ccb_sc->sc_tbolt_reqmsgpool),
1.43      bouyer   2927:            ccb->ccb_tb_pio_request -
                   2928:             MFIMEM_DVA(ccb->ccb_sc->sc_tbolt_reqmsgpool),
                   2929:            MEGASAS_THUNDERBOLT_NEW_MSG_SIZE,
                   2930:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   2931: }
                   2932:
                   2933: /*
                   2934:  * Description:
                   2935:  *      This function will prepare message pools for the Thunderbolt controller
                   2936:  */
                   2937: static int
                   2938: mfi_tbolt_init_desc_pool(struct mfi_softc *sc)
                   2939: {
                   2940:        uint32_t     offset = 0;
                   2941:        uint8_t      *addr = MFIMEM_KVA(sc->sc_tbolt_reqmsgpool);
                   2942:
1.67      msaitoh  2943:        /* Request Descriptors alignment restrictions */
1.43      bouyer   2944:        KASSERT(((uintptr_t)addr & 0xFF) == 0);
                   2945:
                   2946:        /* Skip request message pool */
                   2947:        addr = &addr[MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1)];
                   2948:
                   2949:        /* Reply Frame Pool is initialized */
                   2950:        sc->sc_reply_frame_pool = (struct mfi_mpi2_reply_header *) addr;
                   2951:        KASSERT(((uintptr_t)addr & 0xFF) == 0);
                   2952:
                   2953:        offset = (uintptr_t)sc->sc_reply_frame_pool
                   2954:            - (uintptr_t)MFIMEM_KVA(sc->sc_tbolt_reqmsgpool);
                   2955:        sc->sc_reply_frame_busaddr =
                   2956:            MFIMEM_DVA(sc->sc_tbolt_reqmsgpool) + offset;
                   2957:
                   2958:        /* initializing reply address to 0xFFFFFFFF */
                   2959:        memset((uint8_t *)sc->sc_reply_frame_pool, 0xFF,
                   2960:               (MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size));
                   2961:
                   2962:        /* Skip Reply Frame Pool */
                   2963:        addr += MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size;
                   2964:        sc->sc_reply_pool_limit = (void *)addr;
                   2965:
                   2966:        offset = MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size;
                   2967:        sc->sc_sg_frame_busaddr = sc->sc_reply_frame_busaddr + offset;
                   2968:
                   2969:        /* initialize the last_reply_idx to 0 */
                   2970:        sc->sc_last_reply_idx = 0;
                   2971:        offset = (sc->sc_sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME *
                   2972:            sc->sc_max_cmds)) - MFIMEM_DVA(sc->sc_tbolt_reqmsgpool);
1.44      bouyer   2973:        KASSERT(offset <= sc->sc_tbolt_reqmsgpool->am_size);
1.43      bouyer   2974:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 0,
                   2975:            MFIMEM_MAP(sc->sc_tbolt_reqmsgpool)->dm_mapsize,
                   2976:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   2977:        return 0;
                   2978: }
                   2979:
                   2980: /*
                   2981:  * This routine prepare and issue INIT2 frame to the Firmware
                   2982:  */
                   2983:
                   2984: static int
                   2985: mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
                   2986: {
                   2987:        struct mpi2_ioc_init_request   *mpi2IocInit;
                   2988:        struct mfi_init_frame           *mfi_init;
                   2989:        struct mfi_ccb                  *ccb;
                   2990:        bus_addr_t                      phyAddress;
                   2991:        mfi_address                     *mfiAddressTemp;
                   2992:        int                             s;
                   2993:        char                            *verbuf;
                   2994:        char                            wqbuf[10];
                   2995:
                   2996:        /* Check if initialization is already completed */
                   2997:        if (sc->sc_MFA_enabled) {
                   2998:                return 1;
                   2999:        }
                   3000:
                   3001:        mpi2IocInit =
                   3002:            (struct mpi2_ioc_init_request *)MFIMEM_KVA(sc->sc_tbolt_ioc_init);
                   3003:
                   3004:        s = splbio();
                   3005:        if ((ccb = mfi_get_ccb(sc)) == NULL) {
                   3006:                splx(s);
                   3007:                return (EBUSY);
                   3008:        }
                   3009:
                   3010:
                   3011:        mfi_init = &ccb->ccb_frame->mfr_init;
                   3012:
                   3013:        memset(mpi2IocInit, 0, sizeof(struct mpi2_ioc_init_request));
                   3014:        mpi2IocInit->Function  = MPI2_FUNCTION_IOC_INIT;
                   3015:        mpi2IocInit->WhoInit   = MPI2_WHOINIT_HOST_DRIVER;
                   3016:
                   3017:        /* set MsgVersion and HeaderVersion host driver was built with */
                   3018:        mpi2IocInit->MsgVersion = MPI2_VERSION;
                   3019:        mpi2IocInit->HeaderVersion = MPI2_HEADER_VERSION;
                   3020:        mpi2IocInit->SystemRequestFrameSize = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE/4;
                   3021:        mpi2IocInit->ReplyDescriptorPostQueueDepth =
                   3022:            (uint16_t)sc->sc_reply_pool_size;
                   3023:        mpi2IocInit->ReplyFreeQueueDepth = 0; /* Not supported by MR. */
                   3024:
                   3025:        /* Get physical address of reply frame pool */
                   3026:        phyAddress = sc->sc_reply_frame_busaddr;
                   3027:        mfiAddressTemp =
                   3028:            (mfi_address *)&mpi2IocInit->ReplyDescriptorPostQueueAddress;
                   3029:        mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
                   3030:        mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
                   3031:
                   3032:        /* Get physical address of request message pool */
                   3033:        phyAddress =  MFIMEM_DVA(sc->sc_tbolt_reqmsgpool);
                   3034:        mfiAddressTemp = (mfi_address *)&mpi2IocInit->SystemRequestFrameBaseAddress;
                   3035:        mfiAddressTemp->u.addressLow = (uint32_t)phyAddress;
                   3036:        mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32);
                   3037:
                   3038:        mpi2IocInit->ReplyFreeQueueAddress =  0; /* Not supported by MR. */
                   3039:        mpi2IocInit->TimeStamp = time_uptime;
                   3040:
                   3041:        verbuf = MFIMEM_KVA(sc->sc_tbolt_verbuf);
                   3042:        snprintf(verbuf, strlen(MEGASAS_VERSION) + 2, "%s\n",
1.73      msaitoh  3043:            MEGASAS_VERSION);
1.43      bouyer   3044:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_verbuf), 0,
                   3045:            MFIMEM_MAP(sc->sc_tbolt_verbuf)->dm_mapsize, BUS_DMASYNC_PREWRITE);
                   3046:        mfi_init->driver_ver_lo = htole32(MFIMEM_DVA(sc->sc_tbolt_verbuf));
                   3047:        mfi_init->driver_ver_hi =
                   3048:                    htole32((uint64_t)MFIMEM_DVA(sc->sc_tbolt_verbuf) >> 32);
                   3049:
                   3050:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_ioc_init), 0,
                   3051:            MFIMEM_MAP(sc->sc_tbolt_ioc_init)->dm_mapsize,
                   3052:            BUS_DMASYNC_PREWRITE);
                   3053:        /* Get the physical address of the mpi2 ioc init command */
                   3054:        phyAddress =  MFIMEM_DVA(sc->sc_tbolt_ioc_init);
                   3055:        mfi_init->mif_qinfo_new_addr_lo = htole32(phyAddress);
                   3056:        mfi_init->mif_qinfo_new_addr_hi = htole32((uint64_t)phyAddress >> 32);
                   3057:
                   3058:        mfi_init->mif_header.mfh_cmd = MFI_CMD_INIT;
                   3059:        mfi_init->mif_header.mfh_data_len = sizeof(struct mpi2_ioc_init_request);
                   3060:        if (mfi_poll(ccb) != 0) {
                   3061:                aprint_error_dev(sc->sc_dev, "failed to send IOC init2 "
                   3062:                    "command at 0x%" PRIx64 "\n",
                   3063:                    (uint64_t)ccb->ccb_pframe);
                   3064:                splx(s);
                   3065:                return 1;
                   3066:        }
                   3067:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_verbuf), 0,
                   3068:            MFIMEM_MAP(sc->sc_tbolt_verbuf)->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                   3069:        bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_ioc_init), 0,
                   3070:            MFIMEM_MAP(sc->sc_tbolt_ioc_init)->dm_mapsize,
                   3071:            BUS_DMASYNC_POSTWRITE);
                   3072:        mfi_put_ccb(ccb);
                   3073:        splx(s);
                   3074:
                   3075:        if (mfi_init->mif_header.mfh_cmd_status == 0) {
                   3076:                sc->sc_MFA_enabled = 1;
                   3077:        }
                   3078:        else {
                   3079:                aprint_error_dev(sc->sc_dev, "Init command Failed %x\n",
                   3080:                    mfi_init->mif_header.mfh_cmd_status);
                   3081:                return 1;
                   3082:        }
                   3083:
                   3084:        snprintf(wqbuf, sizeof(wqbuf), "%swq", DEVNAME(sc));
                   3085:        if (workqueue_create(&sc->sc_ldsync_wq, wqbuf, mfi_tbolt_sync_map_info,
                   3086:            sc, PRIBIO, IPL_BIO, 0) != 0) {
                   3087:                aprint_error_dev(sc->sc_dev, "workqueue_create failed\n");
                   3088:                return 1;
                   3089:        }
                   3090:        workqueue_enqueue(sc->sc_ldsync_wq, &sc->sc_ldsync_wk, NULL);
                   3091:        return 0;
                   3092: }
                   3093:
                   3094: int
                   3095: mfi_tbolt_intrh(void *arg)
                   3096: {
                   3097:        struct mfi_softc        *sc = arg;
                   3098:        struct mfi_ccb          *ccb;
                   3099:        union mfi_mpi2_reply_descriptor *desc;
                   3100:        int smid, num_completed;
                   3101:
                   3102:        if (!mfi_tbolt_intr(sc))
                   3103:                return 0;
                   3104:
                   3105:        DNPRINTF(MFI_D_INTR, "%s: mfi_tbolt_intrh %#lx %#lx\n", DEVNAME(sc),
                   3106:            (u_long)sc, (u_long)sc->sc_last_reply_idx);
                   3107:
                   3108:        KASSERT(sc->sc_last_reply_idx < sc->sc_reply_pool_size);
                   3109:
                   3110:        desc = (union mfi_mpi2_reply_descriptor *)
                   3111:            ((uintptr_t)sc->sc_reply_frame_pool +
                   3112:             sc->sc_last_reply_idx * MEGASAS_THUNDERBOLT_REPLY_SIZE);
                   3113:
                   3114:        bus_dmamap_sync(sc->sc_dmat,
1.73      msaitoh  3115:            MFIMEM_MAP(sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3116:            MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1),
                   3117:            MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size,
                   3118:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   3119:        num_completed = 0;
                   3120:        while ((desc->header.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK) !=
                   3121:            MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
                   3122:                smid = desc->header.SMID;
                   3123:                KASSERT(smid > 0 && smid <= sc->sc_max_cmds);
                   3124:                ccb = &sc->sc_ccb[smid - 1];
                   3125:                DNPRINTF(MFI_D_INTR,
                   3126:                    "%s: mfi_tbolt_intr SMID %#x reply_idx %#x "
                   3127:                    "desc %#" PRIx64 " ccb %p\n", DEVNAME(sc), smid,
                   3128:                    sc->sc_last_reply_idx, desc->words, ccb);
                   3129:                KASSERT(ccb->ccb_state == MFI_CCB_RUNNING);
                   3130:                if (ccb->ccb_flags & MFI_CCB_F_TBOLT_IO &&
                   3131:                    ccb->ccb_tb_io_request->ChainOffset != 0) {
                   3132:                        bus_dmamap_sync(sc->sc_dmat,
1.73      msaitoh  3133:                            MFIMEM_MAP(sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3134:                            ccb->ccb_tb_psg_frame -
                   3135:                                MFIMEM_DVA(sc->sc_tbolt_reqmsgpool),
                   3136:                            MEGASAS_MAX_SZ_CHAIN_FRAME,  BUS_DMASYNC_POSTREAD);
                   3137:                }
                   3138:                if (ccb->ccb_flags & MFI_CCB_F_TBOLT_IO) {
                   3139:                        bus_dmamap_sync(sc->sc_dmat,
1.73      msaitoh  3140:                            MFIMEM_MAP(sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3141:                            ccb->ccb_tb_pio_request -
                   3142:                                MFIMEM_DVA(sc->sc_tbolt_reqmsgpool),
                   3143:                            MEGASAS_THUNDERBOLT_NEW_MSG_SIZE,
                   3144:                            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   3145:                }
                   3146:                if (ccb->ccb_done)
                   3147:                        ccb->ccb_done(ccb);
                   3148:                else
                   3149:                        ccb->ccb_state = MFI_CCB_DONE;
                   3150:                sc->sc_last_reply_idx++;
                   3151:                if (sc->sc_last_reply_idx >= sc->sc_reply_pool_size) {
                   3152:                        sc->sc_last_reply_idx = 0;
                   3153:                }
                   3154:                desc->words = ~0x0;
                   3155:                /* Get the next reply descriptor */
                   3156:                desc = (union mfi_mpi2_reply_descriptor *)
                   3157:                    ((uintptr_t)sc->sc_reply_frame_pool +
                   3158:                     sc->sc_last_reply_idx * MEGASAS_THUNDERBOLT_REPLY_SIZE);
                   3159:                num_completed++;
                   3160:        }
                   3161:        if (num_completed == 0)
                   3162:                return 0;
                   3163:
                   3164:        bus_dmamap_sync(sc->sc_dmat,
1.73      msaitoh  3165:            MFIMEM_MAP(sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3166:            MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1),
                   3167:            MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size,
                   3168:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   3169:        mfi_write(sc, MFI_RPI, sc->sc_last_reply_idx);
                   3170:        return 1;
                   3171: }
                   3172:
                   3173:
                   3174: int
                   3175: mfi_tbolt_scsi_ld_io(struct mfi_ccb *ccb, struct scsipi_xfer *xs,
                   3176:     uint64_t blockno, uint32_t blockcnt)
                   3177: {
                   3178:        struct scsipi_periph *periph = xs->xs_periph;
                   3179:        struct mfi_mpi2_request_raid_scsi_io    *io_req;
                   3180:        int sge_count;
                   3181:
                   3182:        DNPRINTF(MFI_D_CMD, "%s: mfi_tbolt_scsi_ld_io: %d\n",
                   3183:            device_xname(periph->periph_channel->chan_adapter->adapt_dev),
                   3184:            periph->periph_target);
                   3185:
                   3186:        if (!xs->data)
                   3187:                return 1;
                   3188:
                   3189:        ccb->ccb_done = mfi_tbolt_scsi_ld_done;
                   3190:        ccb->ccb_xs = xs;
                   3191:        ccb->ccb_data = xs->data;
                   3192:        ccb->ccb_len = xs->datalen;
                   3193:
                   3194:        io_req = ccb->ccb_tb_io_request;
                   3195:
                   3196:        /* Just the CDB length,rest of the Flags are zero */
                   3197:        io_req->IoFlags = xs->cmdlen;
                   3198:        memset(io_req->CDB.CDB32, 0, 32);
                   3199:        memcpy(io_req->CDB.CDB32, &xs->cmdstore, xs->cmdlen);
                   3200:
                   3201:        io_req->RaidContext.TargetID = periph->periph_target;
                   3202:        io_req->RaidContext.Status = 0;
                   3203:        io_req->RaidContext.exStatus = 0;
                   3204:        io_req->RaidContext.timeoutValue = MFI_FUSION_FP_DEFAULT_TIMEOUT;
                   3205:        io_req->Function = MPI2_FUNCTION_LD_IO_REQUEST;
                   3206:        io_req->DevHandle = periph->periph_target;
                   3207:
                   3208:        ccb->ccb_tb_request_desc.header.RequestFlags =
                   3209:            (MFI_REQ_DESCRIPT_FLAGS_LD_IO << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
                   3210:        io_req->DataLength = blockcnt * MFI_SECTOR_LEN;
                   3211:
                   3212:        if (xs->xs_control & XS_CTL_DATA_IN) {
                   3213:                io_req->Control = MPI2_SCSIIO_CONTROL_READ;
                   3214:                ccb->ccb_direction = MFI_DATA_IN;
                   3215:        } else {
                   3216:                io_req->Control = MPI2_SCSIIO_CONTROL_WRITE;
                   3217:                ccb->ccb_direction = MFI_DATA_OUT;
                   3218:        }
                   3219:
                   3220:        sge_count = mfi_tbolt_create_sgl(ccb,
                   3221:            (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK
                   3222:            );
                   3223:        if (sge_count < 0)
                   3224:                return 1;
                   3225:        KASSERT(sge_count <= ccb->ccb_sc->sc_max_sgl);
                   3226:        io_req->RaidContext.numSGE = sge_count;
                   3227:        io_req->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING;
                   3228:        io_req->SGLOffset0 =
                   3229:            offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 4;
                   3230:
                   3231:        io_req->SenseBufferLowAddress = htole32(ccb->ccb_psense);
                   3232:        io_req->SenseBufferLength = MFI_SENSE_SIZE;
                   3233:
                   3234:        ccb->ccb_flags |= MFI_CCB_F_TBOLT | MFI_CCB_F_TBOLT_IO;
                   3235:        bus_dmamap_sync(ccb->ccb_sc->sc_dmat,
1.73      msaitoh  3236:            MFIMEM_MAP(ccb->ccb_sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3237:            ccb->ccb_tb_pio_request -
                   3238:             MFIMEM_DVA(ccb->ccb_sc->sc_tbolt_reqmsgpool),
                   3239:            MEGASAS_THUNDERBOLT_NEW_MSG_SIZE,
                   3240:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   3241:
                   3242:        return 0;
                   3243: }
                   3244:
                   3245:
                   3246: static void
                   3247: mfi_tbolt_scsi_ld_done(struct mfi_ccb *ccb)
                   3248: {
                   3249:        struct mfi_mpi2_request_raid_scsi_io *io_req = ccb->ccb_tb_io_request;
                   3250:        mfi_scsi_xs_done(ccb, io_req->RaidContext.Status,
                   3251:            io_req->RaidContext.exStatus);
                   3252: }
                   3253:
                   3254: static int
                   3255: mfi_tbolt_create_sgl(struct mfi_ccb *ccb, int flags)
                   3256: {
                   3257:        struct mfi_softc        *sc = ccb->ccb_sc;
                   3258:        bus_dma_segment_t       *sgd;
                   3259:        int                     error, i, sge_idx, sge_count;
                   3260:        struct mfi_mpi2_request_raid_scsi_io *io_req;
                   3261:        struct mpi25_ieee_sge_chain64 *sgl_ptr;
                   3262:
                   3263:        DNPRINTF(MFI_D_DMA, "%s: mfi_tbolt_create_sgl %#lx\n", DEVNAME(sc),
                   3264:            (u_long)ccb->ccb_data);
                   3265:
                   3266:        if (!ccb->ccb_data)
                   3267:                return -1;
                   3268:
                   3269:        KASSERT(flags == BUS_DMA_NOWAIT || !cpu_intr_p());
                   3270:        error = bus_dmamap_load(sc->sc_datadmat, ccb->ccb_dmamap,
                   3271:            ccb->ccb_data, ccb->ccb_len, NULL, flags);
                   3272:        if (error) {
                   3273:                if (error == EFBIG)
                   3274:                        aprint_error_dev(sc->sc_dev, "more than %d dma segs\n",
                   3275:                            sc->sc_max_sgl);
                   3276:                else
                   3277:                        aprint_error_dev(sc->sc_dev,
                   3278:                            "error %d loading dma map\n", error);
                   3279:                return -1;
                   3280:        }
                   3281:
                   3282:        io_req = ccb->ccb_tb_io_request;
                   3283:        sgl_ptr = &io_req->SGL.IeeeChain.Chain64;
                   3284:        sge_count = ccb->ccb_dmamap->dm_nsegs;
                   3285:        sgd = ccb->ccb_dmamap->dm_segs;
                   3286:        KASSERT(sge_count <= sc->sc_max_sgl);
                   3287:        KASSERT(sge_count <=
                   3288:            (MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG - 1 +
                   3289:             MEGASAS_THUNDERBOLT_MAX_SGE_IN_CHAINMSG));
                   3290:
                   3291:        if (sge_count > MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG) {
                   3292:                /* One element to store the chain info */
                   3293:                sge_idx = MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG - 1;
                   3294:                DNPRINTF(MFI_D_DMA,
                   3295:                    "mfi sge_idx %d sge_count %d io_req paddr 0x%" PRIx64 "\n",
                   3296:                    sge_idx, sge_count, ccb->ccb_tb_pio_request);
                   3297:        } else {
                   3298:                sge_idx = sge_count;
                   3299:        }
                   3300:
                   3301:        for (i = 0; i < sge_idx; i++) {
                   3302:                sgl_ptr->Address = htole64(sgd[i].ds_addr);
                   3303:                sgl_ptr->Length = htole32(sgd[i].ds_len);
                   3304:                sgl_ptr->Flags = 0;
                   3305:                if (sge_idx < sge_count) {
                   3306:                        DNPRINTF(MFI_D_DMA,
                   3307:                            "sgl %p %d 0x%" PRIx64 " len 0x%" PRIx32
                   3308:                            " flags 0x%x\n", sgl_ptr, i,
                   3309:                            sgl_ptr->Address, sgl_ptr->Length,
                   3310:                            sgl_ptr->Flags);
                   3311:                }
                   3312:                sgl_ptr++;
                   3313:        }
                   3314:        io_req->ChainOffset = 0;
                   3315:        if (sge_idx < sge_count) {
                   3316:                struct mpi25_ieee_sge_chain64 *sg_chain;
                   3317:                io_req->ChainOffset = MEGASAS_THUNDERBOLT_CHAIN_OFF_MAINMSG;
                   3318:                sg_chain = sgl_ptr;
                   3319:                /* Prepare chain element */
                   3320:                sg_chain->NextChainOffset = 0;
                   3321:                sg_chain->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
                   3322:                    MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR);
                   3323:                sg_chain->Length =  (sizeof(mpi2_sge_io_union) *
                   3324:                    (sge_count - sge_idx));
                   3325:                sg_chain->Address = ccb->ccb_tb_psg_frame;
                   3326:                DNPRINTF(MFI_D_DMA,
                   3327:                    "sgl %p chain 0x%" PRIx64 " len 0x%" PRIx32
                   3328:                    " flags 0x%x\n", sg_chain, sg_chain->Address,
                   3329:                    sg_chain->Length, sg_chain->Flags);
                   3330:                sgl_ptr = &ccb->ccb_tb_sg_frame->IeeeChain.Chain64;
                   3331:                for (; i < sge_count; i++) {
                   3332:                        sgl_ptr->Address = htole64(sgd[i].ds_addr);
                   3333:                        sgl_ptr->Length = htole32(sgd[i].ds_len);
                   3334:                        sgl_ptr->Flags = 0;
                   3335:                        DNPRINTF(MFI_D_DMA,
                   3336:                            "sgl %p %d 0x%" PRIx64 " len 0x%" PRIx32
                   3337:                            " flags 0x%x\n", sgl_ptr, i, sgl_ptr->Address,
                   3338:                            sgl_ptr->Length, sgl_ptr->Flags);
                   3339:                        sgl_ptr++;
                   3340:                }
                   3341:                bus_dmamap_sync(sc->sc_dmat,
1.73      msaitoh  3342:                    MFIMEM_MAP(sc->sc_tbolt_reqmsgpool),
1.43      bouyer   3343:                    ccb->ccb_tb_psg_frame - MFIMEM_DVA(sc->sc_tbolt_reqmsgpool),
                   3344:                    MEGASAS_MAX_SZ_CHAIN_FRAME,  BUS_DMASYNC_PREREAD);
                   3345:        }
                   3346:
                   3347:        if (ccb->ccb_direction == MFI_DATA_IN) {
                   3348:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
                   3349:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   3350:        } else {
                   3351:                bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0,
                   3352:                    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
                   3353:        }
                   3354:        return sge_count;
                   3355: }
                   3356:
                   3357: /*
                   3358:  * The ThunderBolt HW has an option for the driver to directly
                   3359:  * access the underlying disks and operate on the RAID.  To
                   3360:  * do this there needs to be a capability to keep the RAID controller
                   3361:  * and driver in sync.  The FreeBSD driver does not take advantage
                   3362:  * of this feature since it adds a lot of complexity and slows down
                   3363:  * performance.  Performance is gained by using the controller's
                   3364:  * cache etc.
                   3365:  *
                   3366:  * Even though this driver doesn't access the disks directly, an
                   3367:  * AEN like command is used to inform the RAID firmware to "sync"
                   3368:  * with all LD's via the MFI_DCMD_LD_MAP_GET_INFO command.  This
                   3369:  * command in write mode will return when the RAID firmware has
                   3370:  * detected a change to the RAID state.  Examples of this type
                   3371:  * of change are removing a disk.  Once the command returns then
                   3372:  * the driver needs to acknowledge this and "sync" all LD's again.
                   3373:  * This repeats until we shutdown.  Then we need to cancel this
                   3374:  * pending command.
                   3375:  *
                   3376:  * If this is not done right the RAID firmware will not remove a
                   3377:  * pulled drive and the RAID won't go degraded etc.  Effectively,
                   3378:  * stopping any RAID mangement to functions.
                   3379:  *
                   3380:  * Doing another LD sync, requires the use of an event since the
                   3381:  * driver needs to do a mfi_wait_command and can't do that in an
                   3382:  * interrupt thread.
                   3383:  *
                   3384:  * The driver could get the RAID state via the MFI_DCMD_LD_MAP_GET_INFO
1.68      andvar   3385:  * That requires a bunch of structure and it is simpler to just do
1.43      bouyer   3386:  * the MFI_DCMD_LD_GET_LIST versus walking the RAID map.
                   3387:  */
                   3388:
                   3389: void
                   3390: mfi_tbolt_sync_map_info(struct work *w, void *v)
                   3391: {
                   3392:        struct mfi_softc *sc = v;
                   3393:        int i;
                   3394:        struct mfi_ccb *ccb = NULL;
1.74      msaitoh  3395:        union mfi_mbox mbox;
1.63      maxv     3396:        struct mfi_ld *ld_sync;
1.43      bouyer   3397:        size_t ld_size;
                   3398:        int s;
                   3399:
                   3400:        DNPRINTF(MFI_D_SYNC, "%s: mfi_tbolt_sync_map_info\n", DEVNAME(sc));
                   3401: again:
1.63      maxv     3402:        ld_sync = NULL;
1.43      bouyer   3403:        s = splbio();
                   3404:        if (sc->sc_ldsync_ccb != NULL) {
                   3405:                splx(s);
                   3406:                return;
                   3407:        }
                   3408:
                   3409:        if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN,
1.45      bouyer   3410:            sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL, false)) {
1.43      bouyer   3411:                aprint_error_dev(sc->sc_dev, "MR_DCMD_LD_GET_LIST failed\n");
                   3412:                goto err;
                   3413:        }
                   3414:
                   3415:        ld_size = sizeof(*ld_sync) * sc->sc_ld_list.mll_no_ld;
1.73      msaitoh  3416:
1.57      christos 3417:        ld_sync = malloc(ld_size, M_DEVBUF, M_WAITOK | M_ZERO);
1.43      bouyer   3418:        if (ld_sync == NULL) {
                   3419:                aprint_error_dev(sc->sc_dev, "Failed to allocate sync\n");
                   3420:                goto err;
                   3421:        }
                   3422:        for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
                   3423:                ld_sync[i] = sc->sc_ld_list.mll_list[i].mll_ld;
                   3424:        }
                   3425:
                   3426:        if ((ccb = mfi_get_ccb(sc)) == NULL) {
                   3427:                aprint_error_dev(sc->sc_dev, "Failed to get sync command\n");
                   3428:                goto err;
                   3429:        }
                   3430:        sc->sc_ldsync_ccb = ccb;
1.73      msaitoh  3431:
1.74      msaitoh  3432:        memset(&mbox, 0, sizeof(mbox));
                   3433:        mbox.b[0] = sc->sc_ld_list.mll_no_ld;
                   3434:        mbox.b[1] = MFI_DCMD_MBOX_PEND_FLAG;
1.43      bouyer   3435:        if (mfi_mgmt(ccb, NULL, MR_DCMD_LD_MAP_GET_INFO, MFI_DATA_OUT,
1.74      msaitoh  3436:            ld_size, ld_sync, &mbox)) {
1.43      bouyer   3437:                aprint_error_dev(sc->sc_dev, "Failed to create sync command\n");
                   3438:                goto err;
                   3439:        }
                   3440:        /*
                   3441:         * we won't sleep on this command, so we have to override
                   3442:         * the callback set up by mfi_mgmt()
                   3443:         */
                   3444:        ccb->ccb_done = mfi_sync_map_complete;
                   3445:
                   3446:        mfi_post(sc, ccb);
                   3447:        splx(s);
                   3448:        return;
                   3449:
                   3450: err:
                   3451:        if (ld_sync)
                   3452:                free(ld_sync, M_DEVBUF);
                   3453:        if (ccb)
                   3454:                mfi_put_ccb(ccb);
                   3455:        sc->sc_ldsync_ccb = NULL;
                   3456:        splx(s);
                   3457:        kpause("ldsyncp", 0, hz, NULL);
                   3458:        goto again;
                   3459: }
                   3460:
                   3461: static void
                   3462: mfi_sync_map_complete(struct mfi_ccb *ccb)
                   3463: {
                   3464:        struct mfi_softc *sc = ccb->ccb_sc;
1.45      bouyer   3465:        bool aborted = !sc->sc_running;
1.43      bouyer   3466:
                   3467:        DNPRINTF(MFI_D_SYNC, "%s: mfi_sync_map_complete\n",
                   3468:            DEVNAME(ccb->ccb_sc));
                   3469:        KASSERT(sc->sc_ldsync_ccb == ccb);
                   3470:        mfi_mgmt_done(ccb);
                   3471:        free(ccb->ccb_data, M_DEVBUF);
                   3472:        if (ccb->ccb_flags & MFI_CCB_F_ERR) {
                   3473:                aprint_error_dev(sc->sc_dev, "sync command failed\n");
1.45      bouyer   3474:                aborted = true;
1.43      bouyer   3475:        }
                   3476:        mfi_put_ccb(ccb);
                   3477:        sc->sc_ldsync_ccb = NULL;
                   3478:
                   3479:        /* set it up again so the driver can catch more events */
                   3480:        if (!aborted) {
                   3481:                workqueue_enqueue(sc->sc_ldsync_wq, &sc->sc_ldsync_wk, NULL);
                   3482:        }
1.38      sborrill 3483: }
1.47      bouyer   3484:
                   3485: static int
                   3486: mfifopen(dev_t dev, int flag, int mode, struct lwp *l)
                   3487: {
                   3488:        struct mfi_softc *sc;
                   3489:
                   3490:        if ((sc = device_lookup_private(&mfi_cd, minor(dev))) == NULL)
                   3491:                return (ENXIO);
                   3492:        return (0);
                   3493: }
                   3494:
                   3495: static int
                   3496: mfifclose(dev_t dev, int flag, int mode, struct lwp *l)
                   3497: {
                   3498:        return (0);
                   3499: }
                   3500:
                   3501: static int
                   3502: mfifioctl(dev_t dev, u_long cmd, void *data, int flag,
                   3503:     struct lwp *l)
                   3504: {
                   3505:        struct mfi_softc *sc;
                   3506:        struct mfi_ioc_packet *ioc = data;
                   3507:        uint8_t *udata;
                   3508:        struct mfi_ccb *ccb = NULL;
                   3509:        int ctx, i, s, error;
                   3510:        union mfi_sense_ptr sense_ptr;
                   3511:
1.73      msaitoh  3512:        switch (cmd) {
1.47      bouyer   3513:        case MFI_CMD:
                   3514:                sc = device_lookup_private(&mfi_cd, ioc->mfi_adapter_no);
                   3515:                break;
                   3516:        default:
                   3517:                return ENOTTY;
                   3518:        }
                   3519:        if (sc == NULL)
                   3520:                return (ENXIO);
                   3521:        if (sc->sc_opened)
                   3522:                return (EBUSY);
                   3523:
1.73      msaitoh  3524:        switch (cmd) {
1.47      bouyer   3525:        case MFI_CMD:
                   3526:                error = kauth_authorize_device_passthru(l->l_cred, dev,
                   3527:                    KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
                   3528:                if (error)
                   3529:                        return error;
                   3530:                if (ioc->mfi_sge_count > MAX_IOCTL_SGE)
                   3531:                        return EINVAL;
                   3532:                s = splbio();
                   3533:                if ((ccb = mfi_get_ccb(sc)) == NULL)
                   3534:                        return ENOMEM;
                   3535:                ccb->ccb_data = NULL;
                   3536:                ctx = ccb->ccb_frame->mfr_header.mfh_context;
                   3537:                memcpy(ccb->ccb_frame, ioc->mfi_frame.raw,
                   3538:                   sizeof(*ccb->ccb_frame));
                   3539:                ccb->ccb_frame->mfr_header.mfh_context = ctx;
                   3540:                ccb->ccb_frame->mfr_header.mfh_scsi_status = 0;
                   3541:                ccb->ccb_frame->mfr_header.mfh_pad0 = 0;
                   3542:                ccb->ccb_frame_size =
                   3543:                    (sizeof(union mfi_sgl) * ioc->mfi_sge_count) +
                   3544:                    ioc->mfi_sgl_off;
                   3545:                if (ioc->mfi_sge_count > 0) {
                   3546:                        ccb->ccb_sgl = (union mfi_sgl *)
                   3547:                            &ccb->ccb_frame->mfr_bytes[ioc->mfi_sgl_off];
                   3548:                }
                   3549:                if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_READ)
                   3550:                        ccb->ccb_direction = MFI_DATA_IN;
                   3551:                if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_WRITE)
                   3552:                        ccb->ccb_direction = MFI_DATA_OUT;
                   3553:                ccb->ccb_len = ccb->ccb_frame->mfr_header.mfh_data_len;
                   3554:                if (ccb->ccb_len > MAXPHYS) {
                   3555:                        error = ENOMEM;
                   3556:                        goto out;
                   3557:                }
                   3558:                if (ccb->ccb_len &&
                   3559:                    (ccb->ccb_direction & (MFI_DATA_IN | MFI_DATA_OUT)) != 0) {
                   3560:                        udata = malloc(ccb->ccb_len, M_DEVBUF, M_WAITOK|M_ZERO);
                   3561:                        if (udata == NULL) {
                   3562:                                error = ENOMEM;
                   3563:                                goto out;
                   3564:                        }
                   3565:                        ccb->ccb_data = udata;
                   3566:                        if (ccb->ccb_direction & MFI_DATA_OUT) {
                   3567:                                for (i = 0; i < ioc->mfi_sge_count; i++) {
                   3568:                                        error = copyin(ioc->mfi_sgl[i].iov_base,
                   3569:                                            udata, ioc->mfi_sgl[i].iov_len);
                   3570:                                        if (error)
                   3571:                                                goto out;
                   3572:                                        udata = &udata[
                   3573:                                            ioc->mfi_sgl[i].iov_len];
                   3574:                                }
                   3575:                        }
                   3576:                        if (mfi_create_sgl(ccb, BUS_DMA_WAITOK)) {
                   3577:                                error = EIO;
                   3578:                                goto out;
                   3579:                        }
                   3580:                }
                   3581:                if (ccb->ccb_frame->mfr_header.mfh_cmd == MFI_CMD_PD_SCSI_IO) {
                   3582:                        ccb->ccb_frame->mfr_io.mif_sense_addr_lo =
                   3583:                            htole32(ccb->ccb_psense);
                   3584:                        ccb->ccb_frame->mfr_io.mif_sense_addr_hi = 0;
                   3585:                }
                   3586:                ccb->ccb_done = mfi_mgmt_done;
                   3587:                mfi_post(sc, ccb);
                   3588:                while (ccb->ccb_state != MFI_CCB_DONE)
                   3589:                        tsleep(ccb, PRIBIO, "mfi_fioc", 0);
                   3590:
                   3591:                if (ccb->ccb_direction & MFI_DATA_IN) {
                   3592:                        udata = ccb->ccb_data;
                   3593:                        for (i = 0; i < ioc->mfi_sge_count; i++) {
                   3594:                                error = copyout(udata,
                   3595:                                    ioc->mfi_sgl[i].iov_base,
                   3596:                                    ioc->mfi_sgl[i].iov_len);
                   3597:                                if (error)
                   3598:                                        goto out;
                   3599:                                udata = &udata[
                   3600:                                    ioc->mfi_sgl[i].iov_len];
                   3601:                        }
                   3602:                }
                   3603:                if (ioc->mfi_sense_len) {
                   3604:                        memcpy(&sense_ptr.sense_ptr_data[0],
                   3605:                        &ioc->mfi_frame.raw[ioc->mfi_sense_off],
                   3606:                        sizeof(sense_ptr.sense_ptr_data));
                   3607:                        error = copyout(ccb->ccb_sense,
                   3608:                            sense_ptr.user_space,
                   3609:                            sizeof(sense_ptr.sense_ptr_data));
                   3610:                        if (error)
                   3611:                                goto out;
                   3612:                }
                   3613:                memcpy(ioc->mfi_frame.raw, ccb->ccb_frame,
                   3614:                   sizeof(*ccb->ccb_frame));
                   3615:                break;
                   3616:        default:
                   3617:                printf("mfifioctl unhandled cmd 0x%lx\n", cmd);
                   3618:                return ENOTTY;
                   3619:        }
                   3620:
                   3621: out:
                   3622:        if (ccb->ccb_data)
                   3623:                free(ccb->ccb_data, M_DEVBUF);
                   3624:        if (ccb)
                   3625:                mfi_put_ccb(ccb);
                   3626:        splx(s);
                   3627:        return error;
                   3628: }

CVSweb <webmaster@jp.NetBSD.org>