LCOV - code coverage report
Current view: top level - dev/ic - mfi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1183 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: mfi.c,v 1.169 2018/08/14 05:22:21 jmatthew Exp $ */
       2             : /*
       3             :  * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include "bio.h"
      19             : 
      20             : #include <sys/param.h>
      21             : #include <sys/systm.h>
      22             : #include <sys/buf.h>
      23             : #include <sys/device.h>
      24             : #include <sys/kernel.h>
      25             : #include <sys/malloc.h>
      26             : #include <sys/rwlock.h>
      27             : #include <sys/sensors.h>
      28             : #include <sys/dkio.h>
      29             : #include <sys/pool.h>
      30             : 
      31             : #include <machine/bus.h>
      32             : 
      33             : #include <scsi/scsi_all.h>
      34             : #include <scsi/scsi_disk.h>
      35             : #include <scsi/scsiconf.h>
      36             : 
      37             : #include <dev/biovar.h>
      38             : #include <dev/ic/mfireg.h>
      39             : #include <dev/ic/mfivar.h>
      40             : 
      41             : #ifdef MFI_DEBUG
      42             : uint32_t        mfi_debug = 0
      43             : /*                  | MFI_D_CMD */
      44             : /*                  | MFI_D_INTR */
      45             : /*                  | MFI_D_MISC */
      46             : /*                  | MFI_D_DMA */
      47             : /*                  | MFI_D_IOCTL */
      48             : /*                  | MFI_D_RW */
      49             : /*                  | MFI_D_MEM */
      50             : /*                  | MFI_D_CCB */
      51             :                 ;
      52             : #endif
      53             : 
      54             : struct cfdriver mfi_cd = {
      55             :         NULL, "mfi", DV_DULL
      56             : };
      57             : 
      58             : void    mfi_scsi_cmd(struct scsi_xfer *);
      59             : int     mfi_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int);
      60             : int     mfi_ioctl_cache(struct scsi_link *, u_long,  struct dk_cache *);
      61             : void    mfiminphys(struct buf *bp, struct scsi_link *sl);
      62             : 
      63             : void    mfi_pd_scsi_cmd(struct scsi_xfer *);
      64             : int     mfi_pd_scsi_probe(struct scsi_link *);
      65             : 
      66             : struct scsi_adapter mfi_switch = {
      67             :         mfi_scsi_cmd, mfiminphys, 0, 0, mfi_scsi_ioctl
      68             : };
      69             : 
      70             : struct scsi_adapter mfi_pd_switch = {
      71             :         mfi_pd_scsi_cmd,
      72             :         mfiminphys,
      73             :         mfi_pd_scsi_probe,
      74             :         0,
      75             :         mfi_scsi_ioctl
      76             : };
      77             : 
      78             : void *          mfi_get_ccb(void *);
      79             : void            mfi_put_ccb(void *, void *);
      80             : void            mfi_scrub_ccb(struct mfi_ccb *);
      81             : int             mfi_init_ccb(struct mfi_softc *);
      82             : 
      83             : struct mfi_mem  *mfi_allocmem(struct mfi_softc *, size_t);
      84             : void            mfi_freemem(struct mfi_softc *, struct mfi_mem *);
      85             : 
      86             : int             mfi_transition_firmware(struct mfi_softc *);
      87             : int             mfi_initialize_firmware(struct mfi_softc *);
      88             : int             mfi_get_info(struct mfi_softc *);
      89             : uint32_t        mfi_read(struct mfi_softc *, bus_size_t);
      90             : void            mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
      91             : void            mfi_poll(struct mfi_softc *, struct mfi_ccb *);
      92             : void            mfi_exec(struct mfi_softc *, struct mfi_ccb *);
      93             : void            mfi_exec_done(struct mfi_softc *, struct mfi_ccb *);
      94             : int             mfi_create_sgl(struct mfi_softc *, struct mfi_ccb *, int);
      95             : u_int           mfi_default_sgd_load(struct mfi_softc *, struct mfi_ccb *);
      96             : int             mfi_syspd(struct mfi_softc *);
      97             : 
      98             : /* commands */
      99             : int             mfi_scsi_ld(struct mfi_softc *sc, struct mfi_ccb *,
     100             :                     struct scsi_xfer *);
     101             : int             mfi_scsi_io(struct mfi_softc *sc, struct mfi_ccb *,
     102             :                     struct scsi_xfer *, uint64_t, uint32_t);
     103             : void            mfi_scsi_xs_done(struct mfi_softc *sc, struct mfi_ccb *);
     104             : int             mfi_mgmt(struct mfi_softc *, uint32_t, uint32_t, uint32_t,
     105             :                     void *, const union mfi_mbox *);
     106             : int             mfi_do_mgmt(struct mfi_softc *, struct mfi_ccb * , uint32_t,
     107             :                     uint32_t, uint32_t, void *, const union mfi_mbox *);
     108             : void            mfi_empty_done(struct mfi_softc *, struct mfi_ccb *);
     109             : 
     110             : #if NBIO > 0
     111             : int             mfi_ioctl(struct device *, u_long, caddr_t);
     112             : int             mfi_bio_getitall(struct mfi_softc *);
     113             : int             mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *);
     114             : int             mfi_ioctl_vol(struct mfi_softc *, struct bioc_vol *);
     115             : int             mfi_ioctl_disk(struct mfi_softc *, struct bioc_disk *);
     116             : int             mfi_ioctl_alarm(struct mfi_softc *, struct bioc_alarm *);
     117             : int             mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *);
     118             : int             mfi_ioctl_setstate(struct mfi_softc *, struct bioc_setstate *);
     119             : int             mfi_ioctl_patrol(struct mfi_softc *sc, struct bioc_patrol *);
     120             : int             mfi_bio_hs(struct mfi_softc *, int, int, void *);
     121             : #ifndef SMALL_KERNEL
     122             : int             mfi_create_sensors(struct mfi_softc *);
     123             : void            mfi_refresh_sensors(void *);
     124             : int             mfi_bbu(struct mfi_softc *);
     125             : #endif /* SMALL_KERNEL */
     126             : #endif /* NBIO > 0 */
     127             : 
     128             : void            mfi_start(struct mfi_softc *, struct mfi_ccb *);
     129             : void            mfi_done(struct mfi_softc *, struct mfi_ccb *);
     130             : u_int32_t       mfi_xscale_fw_state(struct mfi_softc *);
     131             : void            mfi_xscale_intr_ena(struct mfi_softc *);
     132             : int             mfi_xscale_intr(struct mfi_softc *);
     133             : void            mfi_xscale_post(struct mfi_softc *, struct mfi_ccb *);
     134             : 
     135             : static const struct mfi_iop_ops mfi_iop_xscale = {
     136             :         mfi_xscale_fw_state,
     137             :         mfi_xscale_intr_ena,
     138             :         mfi_xscale_intr,
     139             :         mfi_xscale_post,
     140             :         mfi_default_sgd_load,
     141             :         0,
     142             : };
     143             : 
     144             : u_int32_t       mfi_ppc_fw_state(struct mfi_softc *);
     145             : void            mfi_ppc_intr_ena(struct mfi_softc *);
     146             : int             mfi_ppc_intr(struct mfi_softc *);
     147             : void            mfi_ppc_post(struct mfi_softc *, struct mfi_ccb *);
     148             : 
     149             : static const struct mfi_iop_ops mfi_iop_ppc = {
     150             :         mfi_ppc_fw_state,
     151             :         mfi_ppc_intr_ena,
     152             :         mfi_ppc_intr,
     153             :         mfi_ppc_post,
     154             :         mfi_default_sgd_load,
     155             :         MFI_IDB,
     156             :         0
     157             : };
     158             : 
     159             : u_int32_t       mfi_gen2_fw_state(struct mfi_softc *);
     160             : void            mfi_gen2_intr_ena(struct mfi_softc *);
     161             : int             mfi_gen2_intr(struct mfi_softc *);
     162             : void            mfi_gen2_post(struct mfi_softc *, struct mfi_ccb *);
     163             : 
     164             : static const struct mfi_iop_ops mfi_iop_gen2 = {
     165             :         mfi_gen2_fw_state,
     166             :         mfi_gen2_intr_ena,
     167             :         mfi_gen2_intr,
     168             :         mfi_gen2_post,
     169             :         mfi_default_sgd_load,
     170             :         MFI_IDB,
     171             :         0
     172             : };
     173             : 
     174             : u_int32_t       mfi_skinny_fw_state(struct mfi_softc *);
     175             : void            mfi_skinny_intr_ena(struct mfi_softc *);
     176             : int             mfi_skinny_intr(struct mfi_softc *);
     177             : void            mfi_skinny_post(struct mfi_softc *, struct mfi_ccb *);
     178             : u_int           mfi_skinny_sgd_load(struct mfi_softc *, struct mfi_ccb *);
     179             : 
     180             : static const struct mfi_iop_ops mfi_iop_skinny = {
     181             :         mfi_skinny_fw_state,
     182             :         mfi_skinny_intr_ena,
     183             :         mfi_skinny_intr,
     184             :         mfi_skinny_post,
     185             :         mfi_skinny_sgd_load,
     186             :         MFI_SKINNY_IDB,
     187             :         MFI_IOP_F_SYSPD
     188             : };
     189             : 
     190             : #define mfi_fw_state(_s)        ((_s)->sc_iop->mio_fw_state(_s))
     191             : #define mfi_intr_enable(_s)     ((_s)->sc_iop->mio_intr_ena(_s))
     192             : #define mfi_my_intr(_s)         ((_s)->sc_iop->mio_intr(_s))
     193             : #define mfi_post(_s, _c)        ((_s)->sc_iop->mio_post((_s), (_c)))
     194             : #define mfi_sgd_load(_s, _c)    ((_s)->sc_iop->mio_sgd_load((_s), (_c)))
     195             : 
     196             : void *
     197           0 : mfi_get_ccb(void *cookie)
     198             : {
     199           0 :         struct mfi_softc        *sc = cookie;
     200             :         struct mfi_ccb          *ccb;
     201             : 
     202           0 :         KERNEL_UNLOCK();
     203             : 
     204           0 :         mtx_enter(&sc->sc_ccb_mtx);
     205           0 :         ccb = SLIST_FIRST(&sc->sc_ccb_freeq);
     206           0 :         if (ccb != NULL) {
     207           0 :                 SLIST_REMOVE_HEAD(&sc->sc_ccb_freeq, ccb_link);
     208           0 :                 ccb->ccb_state = MFI_CCB_READY;
     209           0 :         }
     210           0 :         mtx_leave(&sc->sc_ccb_mtx);
     211             : 
     212             :         DNPRINTF(MFI_D_CCB, "%s: mfi_get_ccb: %p\n", DEVNAME(sc), ccb);
     213           0 :         KERNEL_LOCK();
     214             : 
     215           0 :         return (ccb);
     216             : }
     217             : 
     218             : void
     219           0 : mfi_put_ccb(void *cookie, void *io)
     220             : {
     221           0 :         struct mfi_softc        *sc = cookie;
     222           0 :         struct mfi_ccb          *ccb = io;
     223             : 
     224             :         DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb);
     225             : 
     226           0 :         KERNEL_UNLOCK();
     227           0 :         mtx_enter(&sc->sc_ccb_mtx);
     228           0 :         SLIST_INSERT_HEAD(&sc->sc_ccb_freeq, ccb, ccb_link);
     229           0 :         mtx_leave(&sc->sc_ccb_mtx);
     230           0 :         KERNEL_LOCK();
     231           0 : }
     232             : 
     233             : void
     234           0 : mfi_scrub_ccb(struct mfi_ccb *ccb)
     235             : {
     236           0 :         struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
     237             : 
     238           0 :         hdr->mfh_cmd_status = 0x0;
     239           0 :         hdr->mfh_flags = 0x0;
     240           0 :         ccb->ccb_state = MFI_CCB_FREE;
     241           0 :         ccb->ccb_cookie = NULL;
     242           0 :         ccb->ccb_flags = 0;
     243           0 :         ccb->ccb_done = NULL;
     244           0 :         ccb->ccb_direction = 0;
     245           0 :         ccb->ccb_frame_size = 0;
     246           0 :         ccb->ccb_extra_frames = 0;
     247           0 :         ccb->ccb_sgl = NULL;
     248           0 :         ccb->ccb_data = NULL;
     249           0 :         ccb->ccb_len = 0;
     250           0 : }
     251             : 
     252             : int
     253           0 : mfi_init_ccb(struct mfi_softc *sc)
     254             : {
     255             :         struct mfi_ccb          *ccb;
     256             :         uint32_t                i;
     257             :         int                     error;
     258             : 
     259             :         DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc));
     260             : 
     261           0 :         sc->sc_ccb = mallocarray(sc->sc_max_cmds, sizeof(struct mfi_ccb),
     262             :             M_DEVBUF, M_WAITOK|M_ZERO);
     263             : 
     264           0 :         for (i = 0; i < sc->sc_max_cmds; i++) {
     265           0 :                 ccb = &sc->sc_ccb[i];
     266             : 
     267             :                 /* select i'th frame */
     268           0 :                 ccb->ccb_frame = (union mfi_frame *)
     269           0 :                     (MFIMEM_KVA(sc->sc_frames) + sc->sc_frames_size * i);
     270           0 :                 ccb->ccb_pframe =
     271           0 :                     MFIMEM_DVA(sc->sc_frames) + sc->sc_frames_size * i;
     272           0 :                 ccb->ccb_pframe_offset = sc->sc_frames_size * i;
     273           0 :                 ccb->ccb_frame->mfr_header.mfh_context = i;
     274             : 
     275             :                 /* select i'th sense */
     276           0 :                 ccb->ccb_sense = (struct mfi_sense *)
     277           0 :                     (MFIMEM_KVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
     278           0 :                 ccb->ccb_psense =
     279           0 :                     (MFIMEM_DVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
     280             : 
     281             :                 /* create a dma map for transfer */
     282           0 :                 error = bus_dmamap_create(sc->sc_dmat,
     283             :                     MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
     284             :                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
     285           0 :                 if (error) {
     286           0 :                         printf("%s: cannot create ccb dmamap (%d)\n",
     287           0 :                             DEVNAME(sc), error);
     288             :                         goto destroy;
     289             :                 }
     290             : 
     291             :                 DNPRINTF(MFI_D_CCB,
     292             :                     "ccb(%d): %p frame: %#x (%#x) sense: %#x (%#x) map: %#x\n",
     293             :                     ccb->ccb_frame->mfr_header.mfh_context, ccb,
     294             :                     ccb->ccb_frame, ccb->ccb_pframe,
     295             :                     ccb->ccb_sense, ccb->ccb_psense,
     296             :                     ccb->ccb_dmamap);
     297             : 
     298             :                 /* add ccb to queue */
     299           0 :                 mfi_put_ccb(sc, ccb);
     300             :         }
     301             : 
     302           0 :         return (0);
     303             : destroy:
     304             :         /* free dma maps and ccb memory */
     305           0 :         while ((ccb = mfi_get_ccb(sc)) != NULL)
     306           0 :                 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
     307             : 
     308           0 :         free(sc->sc_ccb, M_DEVBUF, 0);
     309             : 
     310           0 :         return (1);
     311           0 : }
     312             : 
     313             : uint32_t
     314           0 : mfi_read(struct mfi_softc *sc, bus_size_t r)
     315             : {
     316             :         uint32_t rv;
     317             : 
     318           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
     319             :             BUS_SPACE_BARRIER_READ);
     320           0 :         rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
     321             : 
     322             :         DNPRINTF(MFI_D_RW, "%s: mr 0x%x 0x08%x ", DEVNAME(sc), r, rv);
     323           0 :         return (rv);
     324             : }
     325             : 
     326             : void
     327           0 : mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v)
     328             : {
     329             :         DNPRINTF(MFI_D_RW, "%s: mw 0x%x 0x%08x", DEVNAME(sc), r, v);
     330             : 
     331           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
     332           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
     333             :             BUS_SPACE_BARRIER_WRITE);
     334           0 : }
     335             : 
     336             : struct mfi_mem *
     337           0 : mfi_allocmem(struct mfi_softc *sc, size_t size)
     338             : {
     339             :         struct mfi_mem          *mm;
     340           0 :         int                     nsegs;
     341             : 
     342             :         DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %d\n", DEVNAME(sc),
     343             :             size);
     344             : 
     345           0 :         mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT|M_ZERO);
     346           0 :         if (mm == NULL)
     347           0 :                 return (NULL);
     348             : 
     349           0 :         mm->am_size = size;
     350             : 
     351           0 :         if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
     352           0 :             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0)
     353             :                 goto amfree;
     354             : 
     355           0 :         if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1,
     356           0 :             &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
     357             :                 goto destroy;
     358             : 
     359           0 :         if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva,
     360           0 :             BUS_DMA_NOWAIT) != 0)
     361             :                 goto free;
     362             : 
     363           0 :         if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL,
     364           0 :             BUS_DMA_NOWAIT) != 0)
     365             :                 goto unmap;
     366             : 
     367             :         DNPRINTF(MFI_D_MEM, "  kva: %p  dva: %p  map: %p\n",
     368             :             mm->am_kva, mm->am_map->dm_segs[0].ds_addr, mm->am_map);
     369             : 
     370           0 :         return (mm);
     371             : 
     372             : unmap:
     373           0 :         bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size);
     374             : free:
     375           0 :         bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
     376             : destroy:
     377           0 :         bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
     378             : amfree:
     379           0 :         free(mm, M_DEVBUF, sizeof *mm);
     380             : 
     381           0 :         return (NULL);
     382           0 : }
     383             : 
     384             : void
     385           0 : mfi_freemem(struct mfi_softc *sc, struct mfi_mem *mm)
     386             : {
     387             :         DNPRINTF(MFI_D_MEM, "%s: mfi_freemem: %p\n", DEVNAME(sc), mm);
     388             : 
     389           0 :         bus_dmamap_unload(sc->sc_dmat, mm->am_map);
     390           0 :         bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size);
     391           0 :         bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
     392           0 :         bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
     393           0 :         free(mm, M_DEVBUF, sizeof *mm);
     394           0 : }
     395             : 
     396             : int
     397           0 : mfi_transition_firmware(struct mfi_softc *sc)
     398             : {
     399             :         int32_t                 fw_state, cur_state;
     400           0 :         u_int32_t               idb = sc->sc_iop->mio_idb;
     401             :         int                     max_wait, i;
     402             : 
     403           0 :         fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
     404             : 
     405             :         DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc),
     406             :             fw_state);
     407             : 
     408           0 :         while (fw_state != MFI_STATE_READY) {
     409             :                 DNPRINTF(MFI_D_MISC,
     410             :                     "%s: waiting for firmware to become ready\n",
     411             :                     DEVNAME(sc));
     412             :                 cur_state = fw_state;
     413           0 :                 switch (fw_state) {
     414             :                 case MFI_STATE_FAULT:
     415           0 :                         printf("%s: firmware fault\n", DEVNAME(sc));
     416           0 :                         return (1);
     417             :                 case MFI_STATE_WAIT_HANDSHAKE:
     418           0 :                         mfi_write(sc, idb, MFI_INIT_CLEAR_HANDSHAKE);
     419             :                         max_wait = 2;
     420           0 :                         break;
     421             :                 case MFI_STATE_OPERATIONAL:
     422           0 :                         mfi_write(sc, idb, MFI_INIT_READY);
     423             :                         max_wait = 10;
     424           0 :                         break;
     425             :                 case MFI_STATE_UNDEFINED:
     426             :                 case MFI_STATE_BB_INIT:
     427             :                         max_wait = 2;
     428           0 :                         break;
     429             :                 case MFI_STATE_FW_INIT:
     430             :                 case MFI_STATE_DEVICE_SCAN:
     431             :                 case MFI_STATE_FLUSH_CACHE:
     432             :                         max_wait = 20;
     433           0 :                         break;
     434             :                 default:
     435           0 :                         printf("%s: unknown firmware state %d\n",
     436           0 :                             DEVNAME(sc), fw_state);
     437           0 :                         return (1);
     438             :                 }
     439           0 :                 for (i = 0; i < (max_wait * 10); i++) {
     440           0 :                         fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
     441           0 :                         if (fw_state == cur_state)
     442           0 :                                 DELAY(100000);
     443             :                         else
     444             :                                 break;
     445             :                 }
     446           0 :                 if (fw_state == cur_state) {
     447           0 :                         printf("%s: firmware stuck in state %#x\n",
     448           0 :                             DEVNAME(sc), fw_state);
     449           0 :                         return (1);
     450             :                 }
     451             :         }
     452             : 
     453           0 :         return (0);
     454           0 : }
     455             : 
     456             : int
     457           0 : mfi_initialize_firmware(struct mfi_softc *sc)
     458             : {
     459             :         struct mfi_ccb          *ccb;
     460             :         struct mfi_init_frame   *init;
     461             :         struct mfi_init_qinfo   *qinfo;
     462             :         int                     rv = 0;
     463             : 
     464             :         DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc));
     465             : 
     466           0 :         ccb = scsi_io_get(&sc->sc_iopool, 0);
     467           0 :         mfi_scrub_ccb(ccb);
     468             : 
     469           0 :         init = &ccb->ccb_frame->mfr_init;
     470           0 :         qinfo = (struct mfi_init_qinfo *)((uint8_t *)init + MFI_FRAME_SIZE);
     471             : 
     472           0 :         memset(qinfo, 0, sizeof(*qinfo));
     473           0 :         qinfo->miq_rq_entries = htole32(sc->sc_max_cmds + 1);
     474             : 
     475           0 :         qinfo->miq_rq_addr = htole64(MFIMEM_DVA(sc->sc_pcq) +
     476             :             offsetof(struct mfi_prod_cons, mpc_reply_q));
     477             : 
     478           0 :         qinfo->miq_pi_addr = htole64(MFIMEM_DVA(sc->sc_pcq) +
     479             :             offsetof(struct mfi_prod_cons, mpc_producer));
     480             : 
     481           0 :         qinfo->miq_ci_addr = htole64(MFIMEM_DVA(sc->sc_pcq) +
     482             :             offsetof(struct mfi_prod_cons, mpc_consumer));
     483             : 
     484           0 :         init->mif_header.mfh_cmd = MFI_CMD_INIT;
     485           0 :         init->mif_header.mfh_data_len = htole32(sizeof(*qinfo));
     486           0 :         init->mif_qinfo_new_addr = htole64(ccb->ccb_pframe + MFI_FRAME_SIZE);
     487             : 
     488           0 :         bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq),
     489             :             0, MFIMEM_LEN(sc->sc_pcq),
     490             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
     491             : 
     492           0 :         ccb->ccb_done = mfi_empty_done;
     493           0 :         mfi_poll(sc, ccb);
     494           0 :         if (init->mif_header.mfh_cmd_status != MFI_STAT_OK)
     495           0 :                 rv = 1;
     496             : 
     497           0 :         mfi_put_ccb(sc, ccb);
     498             : 
     499           0 :         return (rv);
     500             : }
     501             : 
     502             : void
     503           0 : mfi_empty_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
     504             : {
     505             :         /* nop */
     506           0 : }
     507             : 
     508             : int
     509           0 : mfi_get_info(struct mfi_softc *sc)
     510             : {
     511             : #ifdef MFI_DEBUG
     512             :         int i;
     513             : #endif
     514             :         DNPRINTF(MFI_D_MISC, "%s: mfi_get_info\n", DEVNAME(sc));
     515             : 
     516           0 :         if (mfi_mgmt(sc, MR_DCMD_CTRL_GET_INFO, MFI_DATA_IN,
     517           0 :             sizeof(sc->sc_info), &sc->sc_info, NULL))
     518           0 :                 return (1);
     519             : 
     520             : #ifdef MFI_DEBUG
     521             :         for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
     522             :                 printf("%s: active FW %s Version %s date %s time %s\n",
     523             :                     DEVNAME(sc),
     524             :                     sc->sc_info.mci_image_component[i].mic_name,
     525             :                     sc->sc_info.mci_image_component[i].mic_version,
     526             :                     sc->sc_info.mci_image_component[i].mic_build_date,
     527             :                     sc->sc_info.mci_image_component[i].mic_build_time);
     528             :         }
     529             : 
     530             :         for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
     531             :                 printf("%s: pending FW %s Version %s date %s time %s\n",
     532             :                     DEVNAME(sc),
     533             :                     sc->sc_info.mci_pending_image_component[i].mic_name,
     534             :                     sc->sc_info.mci_pending_image_component[i].mic_version,
     535             :                     sc->sc_info.mci_pending_image_component[i].mic_build_date,
     536             :                     sc->sc_info.mci_pending_image_component[i].mic_build_time);
     537             :         }
     538             : 
     539             :         printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
     540             :             DEVNAME(sc),
     541             :             sc->sc_info.mci_max_arms,
     542             :             sc->sc_info.mci_max_spans,
     543             :             sc->sc_info.mci_max_arrays,
     544             :             sc->sc_info.mci_max_lds,
     545             :             sc->sc_info.mci_product_name);
     546             : 
     547             :         printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
     548             :             DEVNAME(sc),
     549             :             sc->sc_info.mci_serial_number,
     550             :             sc->sc_info.mci_hw_present,
     551             :             sc->sc_info.mci_current_fw_time,
     552             :             sc->sc_info.mci_max_cmds,
     553             :             sc->sc_info.mci_max_sg_elements);
     554             : 
     555             :         printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
     556             :             DEVNAME(sc),
     557             :             sc->sc_info.mci_max_request_size,
     558             :             sc->sc_info.mci_lds_present,
     559             :             sc->sc_info.mci_lds_degraded,
     560             :             sc->sc_info.mci_lds_offline,
     561             :             sc->sc_info.mci_pd_present);
     562             : 
     563             :         printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
     564             :             DEVNAME(sc),
     565             :             sc->sc_info.mci_pd_disks_present,
     566             :             sc->sc_info.mci_pd_disks_pred_failure,
     567             :             sc->sc_info.mci_pd_disks_failed);
     568             : 
     569             :         printf("%s: nvram %d mem %d flash %d\n",
     570             :             DEVNAME(sc),
     571             :             sc->sc_info.mci_nvram_size,
     572             :             sc->sc_info.mci_memory_size,
     573             :             sc->sc_info.mci_flash_size);
     574             : 
     575             :         printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
     576             :             DEVNAME(sc),
     577             :             sc->sc_info.mci_ram_correctable_errors,
     578             :             sc->sc_info.mci_ram_uncorrectable_errors,
     579             :             sc->sc_info.mci_cluster_allowed,
     580             :             sc->sc_info.mci_cluster_active);
     581             : 
     582             :         printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
     583             :             DEVNAME(sc),
     584             :             sc->sc_info.mci_max_strips_per_io,
     585             :             sc->sc_info.mci_raid_levels,
     586             :             sc->sc_info.mci_adapter_ops,
     587             :             sc->sc_info.mci_ld_ops);
     588             : 
     589             :         printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
     590             :             DEVNAME(sc),
     591             :             sc->sc_info.mci_stripe_sz_ops.min,
     592             :             sc->sc_info.mci_stripe_sz_ops.max,
     593             :             sc->sc_info.mci_pd_ops,
     594             :             sc->sc_info.mci_pd_mix_support);
     595             : 
     596             :         printf("%s: ecc_bucket %d pckg_prop %s\n",
     597             :             DEVNAME(sc),
     598             :             sc->sc_info.mci_ecc_bucket_count,
     599             :             sc->sc_info.mci_package_version);
     600             : 
     601             :         printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
     602             :             DEVNAME(sc),
     603             :             sc->sc_info.mci_properties.mcp_seq_num,
     604             :             sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
     605             :             sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
     606             :             sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
     607             : 
     608             :         printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
     609             :             DEVNAME(sc),
     610             :             sc->sc_info.mci_properties.mcp_rebuild_rate,
     611             :             sc->sc_info.mci_properties.mcp_patrol_read_rate,
     612             :             sc->sc_info.mci_properties.mcp_bgi_rate,
     613             :             sc->sc_info.mci_properties.mcp_cc_rate);
     614             : 
     615             :         printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
     616             :             DEVNAME(sc),
     617             :             sc->sc_info.mci_properties.mcp_recon_rate,
     618             :             sc->sc_info.mci_properties.mcp_cache_flush_interval,
     619             :             sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
     620             :             sc->sc_info.mci_properties.mcp_spinup_delay,
     621             :             sc->sc_info.mci_properties.mcp_cluster_enable);
     622             : 
     623             :         printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
     624             :             DEVNAME(sc),
     625             :             sc->sc_info.mci_properties.mcp_coercion_mode,
     626             :             sc->sc_info.mci_properties.mcp_alarm_enable,
     627             :             sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
     628             :             sc->sc_info.mci_properties.mcp_disable_battery_warn,
     629             :             sc->sc_info.mci_properties.mcp_ecc_bucket_size);
     630             : 
     631             :         printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
     632             :             DEVNAME(sc),
     633             :             sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
     634             :             sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
     635             :             sc->sc_info.mci_properties.mcp_expose_encl_devices);
     636             : 
     637             :         printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
     638             :             DEVNAME(sc),
     639             :             sc->sc_info.mci_pci.mip_vendor,
     640             :             sc->sc_info.mci_pci.mip_device,
     641             :             sc->sc_info.mci_pci.mip_subvendor,
     642             :             sc->sc_info.mci_pci.mip_subdevice);
     643             : 
     644             :         printf("%s: type %#x port_count %d port_addr ",
     645             :             DEVNAME(sc),
     646             :             sc->sc_info.mci_host.mih_type,
     647             :             sc->sc_info.mci_host.mih_port_count);
     648             : 
     649             :         for (i = 0; i < 8; i++)
     650             :                 printf("%.0llx ", sc->sc_info.mci_host.mih_port_addr[i]);
     651             :         printf("\n");
     652             : 
     653             :         printf("%s: type %.x port_count %d port_addr ",
     654             :             DEVNAME(sc),
     655             :             sc->sc_info.mci_device.mid_type,
     656             :             sc->sc_info.mci_device.mid_port_count);
     657             : 
     658             :         for (i = 0; i < 8; i++)
     659             :                 printf("%.0llx ", sc->sc_info.mci_device.mid_port_addr[i]);
     660             :         printf("\n");
     661             : #endif /* MFI_DEBUG */
     662             : 
     663           0 :         return (0);
     664           0 : }
     665             : 
     666             : void
     667           0 : mfiminphys(struct buf *bp, struct scsi_link *sl)
     668             : {
     669             :         DNPRINTF(MFI_D_MISC, "mfiminphys: %d\n", bp->b_bcount);
     670             : 
     671             :         /* XXX currently using MFI_MAXFER = MAXPHYS */
     672           0 :         if (bp->b_bcount > MFI_MAXFER)
     673           0 :                 bp->b_bcount = MFI_MAXFER;
     674           0 :         minphys(bp);
     675           0 : }
     676             : 
     677             : int
     678           0 : mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
     679             : {
     680           0 :         struct scsibus_attach_args saa;
     681             :         uint32_t                status, frames, max_sgl;
     682             :         int                     i;
     683             : 
     684           0 :         switch (iop) {
     685             :         case MFI_IOP_XSCALE:
     686           0 :                 sc->sc_iop = &mfi_iop_xscale;
     687           0 :                 break;
     688             :         case MFI_IOP_PPC:
     689           0 :                 sc->sc_iop = &mfi_iop_ppc;
     690           0 :                 break;
     691             :         case MFI_IOP_GEN2:
     692           0 :                 sc->sc_iop = &mfi_iop_gen2;
     693           0 :                 break;
     694             :         case MFI_IOP_SKINNY:
     695           0 :                 sc->sc_iop = &mfi_iop_skinny;
     696           0 :                 break;
     697             :         default:
     698           0 :                 panic("%s: unknown iop %d", DEVNAME(sc), iop);
     699             :         }
     700             : 
     701             :         DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc));
     702             : 
     703           0 :         if (mfi_transition_firmware(sc))
     704           0 :                 return (1);
     705             : 
     706           0 :         SLIST_INIT(&sc->sc_ccb_freeq);
     707           0 :         mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
     708           0 :         scsi_iopool_init(&sc->sc_iopool, sc, mfi_get_ccb, mfi_put_ccb);
     709             : 
     710           0 :         rw_init(&sc->sc_lock, "mfi_lock");
     711             : 
     712           0 :         status = mfi_fw_state(sc);
     713           0 :         sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
     714           0 :         max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
     715           0 :         if (sc->sc_64bit_dma) {
     716           0 :                 sc->sc_max_sgl = min(max_sgl, (128 * 1024) / PAGE_SIZE + 1);
     717           0 :                 sc->sc_sgl_size = sizeof(struct mfi_sg64);
     718           0 :                 sc->sc_sgl_flags = MFI_FRAME_SGL64;
     719           0 :         } else {
     720           0 :                 sc->sc_max_sgl = max_sgl;
     721           0 :                 sc->sc_sgl_size = sizeof(struct mfi_sg32);
     722           0 :                 sc->sc_sgl_flags = MFI_FRAME_SGL32;
     723             :         }
     724           0 :         if (iop == MFI_IOP_SKINNY)
     725           0 :                 sc->sc_sgl_size = sizeof(struct mfi_sg_skinny);
     726             :         DNPRINTF(MFI_D_MISC, "%s: 64bit: %d max commands: %u, max sgl: %u\n",
     727             :             DEVNAME(sc), sc->sc_64bit_dma, sc->sc_max_cmds, sc->sc_max_sgl);
     728             : 
     729             :         /* consumer/producer and reply queue memory */
     730           0 :         sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) +
     731             :             sizeof(struct mfi_prod_cons));
     732           0 :         if (sc->sc_pcq == NULL) {
     733           0 :                 printf("%s: unable to allocate reply queue memory\n",
     734           0 :                     DEVNAME(sc));
     735           0 :                 goto nopcq;
     736             :         }
     737             : 
     738             :         /* frame memory */
     739             :         /* we are not doing 64 bit IO so only calculate # of 32 bit frames */
     740           0 :         frames = (sc->sc_sgl_size * sc->sc_max_sgl + MFI_FRAME_SIZE - 1) /
     741           0 :             MFI_FRAME_SIZE + 1;
     742           0 :         sc->sc_frames_size = frames * MFI_FRAME_SIZE;
     743           0 :         sc->sc_frames = mfi_allocmem(sc, sc->sc_frames_size * sc->sc_max_cmds);
     744           0 :         if (sc->sc_frames == NULL) {
     745           0 :                 printf("%s: unable to allocate frame memory\n", DEVNAME(sc));
     746           0 :                 goto noframe;
     747             :         }
     748             :         /* XXX hack, fix this */
     749           0 :         if (MFIMEM_DVA(sc->sc_frames) & 0x3f) {
     750           0 :                 printf("%s: improper frame alignment (%#lx) FIXME\n",
     751           0 :                     DEVNAME(sc), MFIMEM_DVA(sc->sc_frames));
     752           0 :                 goto noframe;
     753             :         }
     754             : 
     755             :         /* sense memory */
     756           0 :         sc->sc_sense = mfi_allocmem(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
     757           0 :         if (sc->sc_sense == NULL) {
     758           0 :                 printf("%s: unable to allocate sense memory\n", DEVNAME(sc));
     759           0 :                 goto nosense;
     760             :         }
     761             : 
     762             :         /* now that we have all memory bits go initialize ccbs */
     763           0 :         if (mfi_init_ccb(sc)) {
     764           0 :                 printf("%s: could not init ccb list\n", DEVNAME(sc));
     765           0 :                 goto noinit;
     766             :         }
     767             : 
     768             :         /* kickstart firmware with all addresses and pointers */
     769           0 :         if (mfi_initialize_firmware(sc)) {
     770           0 :                 printf("%s: could not initialize firmware\n", DEVNAME(sc));
     771           0 :                 goto noinit;
     772             :         }
     773             : 
     774           0 :         if (mfi_get_info(sc)) {
     775           0 :                 printf("%s: could not retrieve controller information\n",
     776             :                     DEVNAME(sc));
     777           0 :                 goto noinit;
     778             :         }
     779             : 
     780           0 :         printf("%s: \"%s\", firmware %s", DEVNAME(sc),
     781           0 :             sc->sc_info.mci_product_name, sc->sc_info.mci_package_version);
     782           0 :         if (letoh16(sc->sc_info.mci_memory_size) > 0)
     783           0 :                 printf(", %uMB cache", letoh16(sc->sc_info.mci_memory_size));
     784           0 :         printf("\n");
     785             : 
     786           0 :         sc->sc_ld_cnt = sc->sc_info.mci_lds_present;
     787           0 :         for (i = 0; i < sc->sc_ld_cnt; i++)
     788           0 :                 sc->sc_ld[i].ld_present = 1;
     789             : 
     790           0 :         sc->sc_link.adapter = &mfi_switch;
     791           0 :         sc->sc_link.adapter_softc = sc;
     792           0 :         sc->sc_link.adapter_buswidth = sc->sc_info.mci_max_lds;
     793           0 :         sc->sc_link.adapter_target = -1;
     794           0 :         sc->sc_link.luns = 1;
     795           0 :         sc->sc_link.openings = sc->sc_max_cmds - 1;
     796           0 :         sc->sc_link.pool = &sc->sc_iopool;
     797             : 
     798           0 :         bzero(&saa, sizeof(saa));
     799           0 :         saa.saa_sc_link = &sc->sc_link;
     800             : 
     801           0 :         sc->sc_scsibus = (struct scsibus_softc *)
     802           0 :             config_found(&sc->sc_dev, &saa, scsiprint);
     803             : 
     804           0 :         if (ISSET(sc->sc_iop->mio_flags, MFI_IOP_F_SYSPD))
     805           0 :                 mfi_syspd(sc);
     806             : 
     807             :         /* enable interrupts */
     808           0 :         mfi_intr_enable(sc);
     809             : 
     810             : #if NBIO > 0
     811           0 :         if (bio_register(&sc->sc_dev, mfi_ioctl) != 0)
     812           0 :                 panic("%s: controller registration failed", DEVNAME(sc));
     813             :         else
     814           0 :                 sc->sc_ioctl = mfi_ioctl;
     815             : 
     816             : #ifndef SMALL_KERNEL
     817           0 :         if (mfi_create_sensors(sc) != 0)
     818           0 :                 printf("%s: unable to create sensors\n", DEVNAME(sc));
     819             : #endif
     820             : #endif /* NBIO > 0 */
     821             : 
     822           0 :         return (0);
     823             : noinit:
     824           0 :         mfi_freemem(sc, sc->sc_sense);
     825             : nosense:
     826           0 :         mfi_freemem(sc, sc->sc_frames);
     827             : noframe:
     828           0 :         mfi_freemem(sc, sc->sc_pcq);
     829             : nopcq:
     830           0 :         return (1);
     831           0 : }
     832             : 
     833             : int
     834           0 : mfi_syspd(struct mfi_softc *sc)
     835             : {
     836           0 :         struct scsibus_attach_args saa;
     837             :         struct scsi_link *link;
     838             :         struct mfi_pd_link *pl;
     839             :         struct mfi_pd_list *pd;
     840             :         u_int npds, i;
     841             : 
     842           0 :         sc->sc_pd = malloc(sizeof(*sc->sc_pd), M_DEVBUF, M_WAITOK|M_ZERO);
     843           0 :         if (sc->sc_pd == NULL)
     844           0 :                 return (1);
     845             : 
     846           0 :         pd = malloc(sizeof(*pd), M_TEMP, M_WAITOK|M_ZERO);
     847           0 :         if (pd == NULL)
     848             :                 goto nopdsc;
     849             : 
     850           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
     851           0 :             sizeof(*pd), pd, NULL) != 0)
     852             :                 goto nopd;
     853             : 
     854           0 :         npds = letoh32(pd->mpl_no_pd);
     855           0 :         for (i = 0; i < npds; i++) {
     856           0 :                 pl = malloc(sizeof(*pl), M_DEVBUF, M_WAITOK|M_ZERO);
     857           0 :                 if (pl == NULL)
     858             :                         goto nopl;
     859             : 
     860           0 :                 pl->pd_id = pd->mpl_address[i].mpa_pd_id;
     861           0 :                 sc->sc_pd->pd_links[i] = pl;
     862             :         }
     863             : 
     864           0 :         free(pd, M_TEMP, sizeof *pd);
     865             : 
     866           0 :         link = &sc->sc_pd->pd_link;
     867           0 :         link->adapter = &mfi_pd_switch;
     868           0 :         link->adapter_softc = sc;
     869           0 :         link->adapter_buswidth = MFI_MAX_PD;
     870           0 :         link->adapter_target = -1;
     871           0 :         link->openings = sc->sc_max_cmds - 1;
     872           0 :         link->pool = &sc->sc_iopool;
     873             : 
     874           0 :         bzero(&saa, sizeof(saa));
     875           0 :         saa.saa_sc_link = link;
     876             : 
     877           0 :         sc->sc_pd->pd_scsibus = (struct scsibus_softc *)
     878           0 :             config_found(&sc->sc_dev, &saa, scsiprint);
     879             : 
     880           0 :         return (0);
     881             : nopl:
     882           0 :         for (i = 0; i < npds; i++) {
     883           0 :                 pl = sc->sc_pd->pd_links[i];
     884           0 :                 if (pl == NULL)
     885             :                         break;
     886             : 
     887           0 :                 free(pl, M_DEVBUF, sizeof *pl);
     888             :         }
     889             : nopd:
     890           0 :         free(pd, M_TEMP, sizeof *pd);
     891             : nopdsc:
     892           0 :         free(sc->sc_pd, M_DEVBUF, sizeof *sc->sc_pd);
     893           0 :         return (1);
     894           0 : }
     895             : 
     896             : void
     897           0 : mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
     898             : {
     899             :         struct mfi_frame_header *hdr;
     900             :         int to = 0;
     901             : 
     902             :         DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc));
     903             : 
     904           0 :         hdr = &ccb->ccb_frame->mfr_header;
     905           0 :         hdr->mfh_cmd_status = 0xff;
     906           0 :         hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
     907             : 
     908           0 :         mfi_start(sc, ccb);
     909             : 
     910           0 :         for (;;) {
     911           0 :                 delay(1000);
     912             : 
     913           0 :                 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
     914             :                     ccb->ccb_pframe_offset, sc->sc_frames_size,
     915             :                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
     916             : 
     917           0 :                 if (hdr->mfh_cmd_status != 0xff)
     918             :                         break;
     919             : 
     920           0 :                 if (to++ > 5000) {
     921           0 :                         printf("%s: timeout on ccb %d\n", DEVNAME(sc),
     922           0 :                             hdr->mfh_context);
     923           0 :                         ccb->ccb_flags |= MFI_CCB_F_ERR;
     924           0 :                         break;
     925             :                 }
     926             : 
     927           0 :                 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
     928             :                     ccb->ccb_pframe_offset, sc->sc_frames_size,
     929             :                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
     930             :         }
     931             : 
     932           0 :         if (ccb->ccb_len > 0) {
     933           0 :                 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
     934             :                     ccb->ccb_dmamap->dm_mapsize,
     935             :                     (ccb->ccb_direction & MFI_DATA_IN) ?
     936             :                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
     937             : 
     938           0 :                 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
     939           0 :         }
     940             : 
     941           0 :         ccb->ccb_done(sc, ccb);
     942           0 : }
     943             : 
     944             : void
     945           0 : mfi_exec(struct mfi_softc *sc, struct mfi_ccb *ccb)
     946             : {
     947           0 :         struct mutex m = MUTEX_INITIALIZER(IPL_BIO);
     948             : 
     949             : #ifdef DIAGNOSTIC
     950           0 :         if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
     951           0 :                 panic("mfi_exec called with cookie or done set");
     952             : #endif
     953             : 
     954           0 :         ccb->ccb_cookie = &m;
     955           0 :         ccb->ccb_done = mfi_exec_done;
     956             : 
     957           0 :         mfi_start(sc, ccb);
     958             : 
     959           0 :         mtx_enter(&m);
     960           0 :         while (ccb->ccb_cookie != NULL)
     961           0 :                 msleep(ccb, &m, PRIBIO, "mfiexec", 0);
     962           0 :         mtx_leave(&m);
     963           0 : }
     964             : 
     965             : void
     966           0 : mfi_exec_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
     967             : {
     968           0 :         struct mutex *m = ccb->ccb_cookie;
     969             : 
     970           0 :         mtx_enter(m);
     971           0 :         ccb->ccb_cookie = NULL;
     972           0 :         wakeup_one(ccb);
     973           0 :         mtx_leave(m);
     974           0 : }
     975             : 
     976             : int
     977           0 : mfi_intr(void *arg)
     978             : {
     979           0 :         struct mfi_softc        *sc = arg;
     980           0 :         struct mfi_prod_cons    *pcq = MFIMEM_KVA(sc->sc_pcq);
     981             :         struct mfi_ccb          *ccb;
     982             :         uint32_t                producer, consumer, ctx;
     983             :         int                     claimed = 0;
     984             : 
     985           0 :         if (!mfi_my_intr(sc))
     986           0 :                 return (0);
     987             : 
     988           0 :         bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq),
     989             :             0, MFIMEM_LEN(sc->sc_pcq),
     990             :             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
     991             : 
     992           0 :         producer = letoh32(pcq->mpc_producer);
     993           0 :         consumer = letoh32(pcq->mpc_consumer);
     994             : 
     995             :         DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
     996             : 
     997           0 :         while (consumer != producer) {
     998             :                 DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n",
     999             :                     DEVNAME(sc), producer, consumer);
    1000             : 
    1001           0 :                 ctx = pcq->mpc_reply_q[consumer];
    1002           0 :                 pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX;
    1003           0 :                 if (ctx == MFI_INVALID_CTX)
    1004           0 :                         printf("%s: invalid context, p: %d c: %d\n",
    1005           0 :                             DEVNAME(sc), producer, consumer);
    1006             :                 else {
    1007             :                         /* XXX remove from queue and call scsi_done */
    1008           0 :                         ccb = &sc->sc_ccb[ctx];
    1009             :                         DNPRINTF(MFI_D_INTR, "%s: mfi_intr context %#x\n",
    1010             :                             DEVNAME(sc), ctx);
    1011           0 :                         mfi_done(sc, ccb);
    1012             : 
    1013             :                         claimed = 1;
    1014             :                 }
    1015           0 :                 consumer++;
    1016           0 :                 if (consumer == (sc->sc_max_cmds + 1))
    1017             :                         consumer = 0;
    1018             :         }
    1019             : 
    1020           0 :         pcq->mpc_consumer = htole32(consumer);
    1021             : 
    1022           0 :         bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq),
    1023             :             0, MFIMEM_LEN(sc->sc_pcq),
    1024             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1025             : 
    1026           0 :         return (claimed);
    1027           0 : }
    1028             : 
    1029             : int
    1030           0 : mfi_scsi_io(struct mfi_softc *sc, struct mfi_ccb *ccb,
    1031             :     struct scsi_xfer *xs, uint64_t blockno, uint32_t blockcnt)
    1032             : {
    1033           0 :         struct scsi_link        *link = xs->sc_link;
    1034             :         struct mfi_io_frame     *io;
    1035             : 
    1036             :         DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_io: %d\n",
    1037             :             DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
    1038             : 
    1039           0 :         if (!xs->data)
    1040           0 :                 return (1);
    1041             : 
    1042           0 :         io = &ccb->ccb_frame->mfr_io;
    1043           0 :         if (xs->flags & SCSI_DATA_IN) {
    1044           0 :                 io->mif_header.mfh_cmd = MFI_CMD_LD_READ;
    1045           0 :                 ccb->ccb_direction = MFI_DATA_IN;
    1046           0 :         } else {
    1047           0 :                 io->mif_header.mfh_cmd = MFI_CMD_LD_WRITE;
    1048           0 :                 ccb->ccb_direction = MFI_DATA_OUT;
    1049             :         }
    1050           0 :         io->mif_header.mfh_target_id = link->target;
    1051           0 :         io->mif_header.mfh_timeout = 0;
    1052           0 :         io->mif_header.mfh_flags = 0;
    1053           0 :         io->mif_header.mfh_sense_len = MFI_SENSE_SIZE;
    1054           0 :         io->mif_header.mfh_data_len = htole32(blockcnt);
    1055           0 :         io->mif_lba = htole64(blockno);
    1056           0 :         io->mif_sense_addr = htole64(ccb->ccb_psense);
    1057             : 
    1058           0 :         ccb->ccb_done = mfi_scsi_xs_done;
    1059           0 :         ccb->ccb_cookie = xs;
    1060           0 :         ccb->ccb_frame_size = MFI_IO_FRAME_SIZE;
    1061           0 :         ccb->ccb_sgl = &io->mif_sgl;
    1062           0 :         ccb->ccb_data = xs->data;
    1063           0 :         ccb->ccb_len = xs->datalen;
    1064             : 
    1065           0 :         if (mfi_create_sgl(sc, ccb, (xs->flags & SCSI_NOSLEEP) ?
    1066             :             BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
    1067           0 :                 return (1);
    1068             : 
    1069           0 :         return (0);
    1070           0 : }
    1071             : 
    1072             : void
    1073           0 : mfi_scsi_xs_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
    1074             : {
    1075           0 :         struct scsi_xfer        *xs = ccb->ccb_cookie;
    1076           0 :         struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
    1077             : 
    1078             :         DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#x %#x\n",
    1079             :             DEVNAME(sc), ccb, ccb->ccb_frame);
    1080             : 
    1081           0 :         switch (hdr->mfh_cmd_status) {
    1082             :         case MFI_STAT_OK:
    1083           0 :                 xs->resid = 0;
    1084           0 :                 break;
    1085             : 
    1086             :         case MFI_STAT_SCSI_DONE_WITH_ERROR:
    1087           0 :                 xs->error = XS_SENSE;
    1088           0 :                 xs->resid = 0;
    1089           0 :                 memset(&xs->sense, 0, sizeof(xs->sense));
    1090           0 :                 memcpy(&xs->sense, ccb->ccb_sense, sizeof(xs->sense));
    1091           0 :                 break;
    1092             : 
    1093             :         case MFI_STAT_DEVICE_NOT_FOUND:
    1094           0 :                 xs->error = XS_SELTIMEOUT;
    1095           0 :                 break;
    1096             : 
    1097             :         default:
    1098           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1099             :                 DPRINTF(MFI_D_CMD,
    1100             :                     "%s: mfi_scsi_xs_done stuffup %02x on %02x\n",
    1101             :                     DEVNAME(sc), hdr->mfh_cmd_status, xs->cmd->opcode);
    1102             : 
    1103           0 :                 if (hdr->mfh_scsi_status != 0) {
    1104             :                         DNPRINTF(MFI_D_INTR,
    1105             :                             "%s: mfi_scsi_xs_done sense %#x %x %x\n",
    1106             :                             DEVNAME(sc), hdr->mfh_scsi_status,
    1107             :                             &xs->sense, ccb->ccb_sense);
    1108           0 :                         memset(&xs->sense, 0, sizeof(xs->sense));
    1109           0 :                         memcpy(&xs->sense, ccb->ccb_sense,
    1110             :                             sizeof(struct scsi_sense_data));
    1111           0 :                         xs->error = XS_SENSE;
    1112           0 :                 }
    1113             :                 break;
    1114             :         }
    1115             : 
    1116           0 :         KERNEL_LOCK();
    1117           0 :         scsi_done(xs);
    1118           0 :         KERNEL_UNLOCK();
    1119           0 : }
    1120             : 
    1121             : int
    1122           0 : mfi_scsi_ld(struct mfi_softc *sc, struct mfi_ccb *ccb, struct scsi_xfer *xs)
    1123             : {
    1124           0 :         struct scsi_link        *link = xs->sc_link;
    1125             :         struct mfi_pass_frame   *pf;
    1126             : 
    1127             :         DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n",
    1128             :             DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
    1129             : 
    1130           0 :         pf = &ccb->ccb_frame->mfr_pass;
    1131           0 :         pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO;
    1132           0 :         pf->mpf_header.mfh_target_id = link->target;
    1133           0 :         pf->mpf_header.mfh_lun_id = 0;
    1134           0 :         pf->mpf_header.mfh_cdb_len = xs->cmdlen;
    1135           0 :         pf->mpf_header.mfh_timeout = 0;
    1136           0 :         pf->mpf_header.mfh_data_len = htole32(xs->datalen); /* XXX */
    1137           0 :         pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE;
    1138             : 
    1139           0 :         pf->mpf_sense_addr = htole64(ccb->ccb_psense);
    1140             : 
    1141           0 :         memset(pf->mpf_cdb, 0, 16);
    1142           0 :         memcpy(pf->mpf_cdb, xs->cmd, xs->cmdlen);
    1143             : 
    1144           0 :         ccb->ccb_done = mfi_scsi_xs_done;
    1145           0 :         ccb->ccb_cookie = xs;
    1146           0 :         ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
    1147           0 :         ccb->ccb_sgl = &pf->mpf_sgl;
    1148             : 
    1149           0 :         if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
    1150           0 :                 ccb->ccb_direction = xs->flags & SCSI_DATA_IN ?
    1151             :                     MFI_DATA_IN : MFI_DATA_OUT;
    1152             :         else
    1153           0 :                 ccb->ccb_direction = MFI_DATA_NONE;
    1154             : 
    1155           0 :         if (xs->data) {
    1156           0 :                 ccb->ccb_data = xs->data;
    1157           0 :                 ccb->ccb_len = xs->datalen;
    1158             : 
    1159           0 :                 if (mfi_create_sgl(sc, ccb, (xs->flags & SCSI_NOSLEEP) ?
    1160             :                     BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
    1161           0 :                         return (1);
    1162             :         }
    1163             : 
    1164           0 :         return (0);
    1165           0 : }
    1166             : 
    1167             : void
    1168           0 : mfi_scsi_cmd(struct scsi_xfer *xs)
    1169             : {
    1170           0 :         struct scsi_link        *link = xs->sc_link;
    1171           0 :         struct mfi_softc        *sc = link->adapter_softc;
    1172           0 :         struct mfi_ccb          *ccb = xs->io;
    1173             :         struct scsi_rw          *rw;
    1174             :         struct scsi_rw_big      *rwb;
    1175             :         struct scsi_rw_16       *rw16;
    1176             :         uint64_t                blockno;
    1177             :         uint32_t                blockcnt;
    1178           0 :         uint8_t                 target = link->target;
    1179           0 :         union mfi_mbox          mbox;
    1180             : 
    1181             :         DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd opcode: %#x\n",
    1182             :             DEVNAME(sc), xs->cmd->opcode);
    1183             : 
    1184           0 :         KERNEL_UNLOCK();
    1185             : 
    1186           0 :         if (!sc->sc_ld[target].ld_present) {
    1187             :                 DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n",
    1188             :                     DEVNAME(sc), target);
    1189             :                 goto stuffup;
    1190             :         }
    1191             : 
    1192           0 :         mfi_scrub_ccb(ccb);
    1193             : 
    1194           0 :         xs->error = XS_NOERROR;
    1195             : 
    1196           0 :         switch (xs->cmd->opcode) {
    1197             :         /* IO path */
    1198             :         case READ_BIG:
    1199             :         case WRITE_BIG:
    1200           0 :                 rwb = (struct scsi_rw_big *)xs->cmd;
    1201           0 :                 blockno = (uint64_t)_4btol(rwb->addr);
    1202           0 :                 blockcnt = _2btol(rwb->length);
    1203           0 :                 if (mfi_scsi_io(sc, ccb, xs, blockno, blockcnt))
    1204             :                         goto stuffup;
    1205             :                 break;
    1206             : 
    1207             :         case READ_COMMAND:
    1208             :         case WRITE_COMMAND:
    1209           0 :                 rw = (struct scsi_rw *)xs->cmd;
    1210             :                 blockno =
    1211           0 :                     (uint64_t)(_3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff));
    1212           0 :                 blockcnt = rw->length ? rw->length : 0x100;
    1213           0 :                 if (mfi_scsi_io(sc, ccb, xs, blockno, blockcnt))
    1214             :                         goto stuffup;
    1215             :                 break;
    1216             : 
    1217             :         case READ_16:
    1218             :         case WRITE_16:
    1219           0 :                 rw16 = (struct scsi_rw_16 *)xs->cmd;
    1220           0 :                 blockno = _8btol(rw16->addr);
    1221           0 :                 blockcnt = _4btol(rw16->length);
    1222           0 :                 if (mfi_scsi_io(sc, ccb, xs, blockno, blockcnt))
    1223             :                         goto stuffup;
    1224             :                 break;
    1225             : 
    1226             :         case SYNCHRONIZE_CACHE:
    1227           0 :                 mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
    1228           0 :                 if (mfi_do_mgmt(sc, ccb, MR_DCMD_CTRL_CACHE_FLUSH,
    1229             :                     MFI_DATA_NONE, 0, NULL, &mbox))
    1230             :                         goto stuffup;
    1231             : 
    1232             :                 goto complete;
    1233             :                 /* NOTREACHED */
    1234             : 
    1235             :         default:
    1236           0 :                 if (mfi_scsi_ld(sc, ccb, xs))
    1237             :                         goto stuffup;
    1238             :                 break;
    1239             :         }
    1240             : 
    1241             :         DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
    1242             : 
    1243           0 :         if (xs->flags & SCSI_POLL)
    1244           0 :                 mfi_poll(sc, ccb);
    1245             :         else 
    1246           0 :                 mfi_start(sc, ccb);
    1247             : 
    1248           0 :         KERNEL_LOCK();
    1249           0 :         return;
    1250             : 
    1251             : stuffup:
    1252           0 :         xs->error = XS_DRIVER_STUFFUP;
    1253             : complete:
    1254           0 :         KERNEL_LOCK();
    1255           0 :         scsi_done(xs);
    1256           0 : }
    1257             : 
    1258             : u_int
    1259           0 : mfi_default_sgd_load(struct mfi_softc *sc, struct mfi_ccb *ccb)
    1260             : {
    1261           0 :         struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
    1262           0 :         union mfi_sgl           *sgl = ccb->ccb_sgl;
    1263           0 :         bus_dma_segment_t       *sgd = ccb->ccb_dmamap->dm_segs;
    1264             :         int                      i;
    1265             : 
    1266           0 :         hdr->mfh_flags |= sc->sc_sgl_flags;
    1267             : 
    1268           0 :         for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
    1269           0 :                 if (sc->sc_64bit_dma) {
    1270           0 :                         sgl->sg64[i].addr = htole64(sgd[i].ds_addr);
    1271           0 :                         sgl->sg64[i].len = htole32(sgd[i].ds_len);
    1272             :                         DNPRINTF(MFI_D_DMA, "%s: addr: %#x  len: %#x\n",
    1273             :                             DEVNAME(sc), sgl->sg64[i].addr, sgl->sg64[i].len);
    1274           0 :                 } else {
    1275           0 :                         sgl->sg32[i].addr = htole32(sgd[i].ds_addr);
    1276           0 :                         sgl->sg32[i].len = htole32(sgd[i].ds_len);
    1277             :                         DNPRINTF(MFI_D_DMA, "%s: addr: %#x  len: %#x\n",
    1278             :                             DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len);
    1279             :                 }
    1280             :         }
    1281             : 
    1282           0 :         return (ccb->ccb_dmamap->dm_nsegs *
    1283           0 :             (sc->sc_64bit_dma ? sizeof(sgl->sg64) : sizeof(sgl->sg32)));
    1284             : }
    1285             : 
    1286             : int
    1287           0 : mfi_create_sgl(struct mfi_softc *sc, struct mfi_ccb *ccb, int flags)
    1288             : {
    1289           0 :         struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
    1290             :         int                     error;
    1291             : 
    1292             :         DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#x\n", DEVNAME(sc),
    1293             :             ccb->ccb_data);
    1294             : 
    1295           0 :         if (!ccb->ccb_data) {
    1296           0 :                 hdr->mfh_sg_count = 0;
    1297           0 :                 return (1);
    1298             :         }
    1299             : 
    1300           0 :         error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap,
    1301             :             ccb->ccb_data, ccb->ccb_len, NULL, flags);
    1302           0 :         if (error) {
    1303           0 :                 if (error == EFBIG)
    1304           0 :                         printf("more than %d dma segs\n",
    1305           0 :                             sc->sc_max_sgl);
    1306             :                 else
    1307           0 :                         printf("error %d loading dma map\n", error);
    1308           0 :                 return (1);
    1309             :         }
    1310             : 
    1311           0 :         ccb->ccb_frame_size += mfi_sgd_load(sc, ccb);
    1312             : 
    1313           0 :         if (ccb->ccb_direction == MFI_DATA_IN) {
    1314           0 :                 hdr->mfh_flags |= MFI_FRAME_DIR_READ;
    1315           0 :                 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    1316             :                     ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
    1317           0 :         } else {
    1318           0 :                 hdr->mfh_flags |= MFI_FRAME_DIR_WRITE;
    1319           0 :                 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    1320             :                     ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    1321             :         }
    1322             : 
    1323           0 :         hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs;
    1324           0 :         ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE;
    1325             : 
    1326             :         DNPRINTF(MFI_D_DMA, "%s: sg_count: %d  frame_size: %d  frames_size: %d"
    1327             :             "  dm_nsegs: %d  extra_frames: %d\n",
    1328             :             DEVNAME(sc),
    1329             :             hdr->mfh_sg_count,
    1330             :             ccb->ccb_frame_size,
    1331             :             sc->sc_frames_size,
    1332             :             ccb->ccb_dmamap->dm_nsegs,
    1333             :             ccb->ccb_extra_frames);
    1334             : 
    1335           0 :         return (0);
    1336           0 : }
    1337             : 
    1338             : int
    1339           0 : mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
    1340             :     void *buf, const union mfi_mbox *mbox)
    1341             : {
    1342             :         struct mfi_ccb *ccb;
    1343             :         int rv;
    1344             : 
    1345           0 :         ccb = scsi_io_get(&sc->sc_iopool, 0);
    1346           0 :         mfi_scrub_ccb(ccb);
    1347           0 :         rv = mfi_do_mgmt(sc, ccb, opc, dir, len, buf, mbox);
    1348           0 :         scsi_io_put(&sc->sc_iopool, ccb);
    1349             : 
    1350           0 :         return (rv);
    1351             : }
    1352             : 
    1353             : int
    1354           0 : mfi_do_mgmt(struct mfi_softc *sc, struct mfi_ccb *ccb, uint32_t opc,
    1355             :     uint32_t dir, uint32_t len, void *buf, const union mfi_mbox *mbox)
    1356             : {
    1357             :         struct mfi_dcmd_frame *dcmd;
    1358             :         uint8_t *dma_buf = NULL;
    1359             :         int rv = EINVAL;
    1360             : 
    1361             :         DNPRINTF(MFI_D_MISC, "%s: mfi_do_mgmt %#x\n", DEVNAME(sc), opc);
    1362             : 
    1363           0 :         dma_buf = dma_alloc(len, cold ? PR_NOWAIT : PR_WAITOK);
    1364           0 :         if (dma_buf == NULL)
    1365             :                 goto done;
    1366             : 
    1367           0 :         dcmd = &ccb->ccb_frame->mfr_dcmd;
    1368           0 :         memset(&dcmd->mdf_mbox, 0, sizeof(dcmd->mdf_mbox));
    1369           0 :         dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD;
    1370           0 :         dcmd->mdf_header.mfh_timeout = 0;
    1371             : 
    1372           0 :         dcmd->mdf_opcode = opc;
    1373           0 :         dcmd->mdf_header.mfh_data_len = 0;
    1374           0 :         ccb->ccb_direction = dir;
    1375             : 
    1376           0 :         ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE;
    1377             : 
    1378             :         /* handle special opcodes */
    1379           0 :         if (mbox != NULL)
    1380           0 :                 memcpy(&dcmd->mdf_mbox, mbox, sizeof(dcmd->mdf_mbox));
    1381             : 
    1382           0 :         if (dir != MFI_DATA_NONE) {
    1383           0 :                 if (dir == MFI_DATA_OUT)
    1384           0 :                         memcpy(dma_buf, buf, len);
    1385           0 :                 dcmd->mdf_header.mfh_data_len = len;
    1386           0 :                 ccb->ccb_data = dma_buf;
    1387           0 :                 ccb->ccb_len = len;
    1388           0 :                 ccb->ccb_sgl = &dcmd->mdf_sgl;
    1389             : 
    1390           0 :                 if (mfi_create_sgl(sc, ccb, cold ? BUS_DMA_NOWAIT :
    1391             :                     BUS_DMA_WAITOK)) {
    1392             :                         rv = EINVAL;
    1393           0 :                         goto done;
    1394             :                 }
    1395             :         }
    1396             : 
    1397           0 :         if (cold) {
    1398           0 :                 ccb->ccb_done = mfi_empty_done;
    1399           0 :                 mfi_poll(sc, ccb);
    1400           0 :         } else
    1401           0 :                 mfi_exec(sc, ccb);
    1402             : 
    1403           0 :         if (dcmd->mdf_header.mfh_cmd_status != MFI_STAT_OK) {
    1404           0 :                 if (dcmd->mdf_header.mfh_cmd_status == MFI_STAT_WRONG_STATE)
    1405           0 :                         rv = ENXIO;
    1406             :                 else
    1407             :                         rv = EIO;
    1408             :                 goto done;
    1409             :         }
    1410             : 
    1411           0 :         if (dir == MFI_DATA_IN)
    1412           0 :                 memcpy(buf, dma_buf, len);
    1413             : 
    1414           0 :         rv = 0;
    1415             : done:
    1416           0 :         if (dma_buf)
    1417           0 :                 dma_free(dma_buf, len);
    1418             : 
    1419           0 :         return (rv);
    1420             : }
    1421             : 
    1422             : int
    1423           0 : mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
    1424             : {
    1425           0 :         struct mfi_softc        *sc = (struct mfi_softc *)link->adapter_softc;
    1426             : 
    1427             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_scsi_ioctl\n", DEVNAME(sc));
    1428             : 
    1429           0 :         switch (cmd) {
    1430             :         case DIOCGCACHE:
    1431             :         case DIOCSCACHE:
    1432           0 :                 return (mfi_ioctl_cache(link, cmd, (struct dk_cache *)addr));
    1433             :                 break;
    1434             : 
    1435             :         default:
    1436           0 :                 if (sc->sc_ioctl)
    1437           0 :                         return (sc->sc_ioctl(link->adapter_softc, cmd, addr));
    1438             :                 break;
    1439             :         }
    1440             : 
    1441           0 :         return (ENOTTY);
    1442           0 : }
    1443             : 
    1444             : int
    1445           0 : mfi_ioctl_cache(struct scsi_link *link, u_long cmd,  struct dk_cache *dc)
    1446             : {
    1447           0 :         struct mfi_softc        *sc = (struct mfi_softc *)link->adapter_softc;
    1448             :         int                      rv, wrenable, rdenable;
    1449           0 :         struct mfi_ld_prop       ldp;
    1450           0 :         union mfi_mbox           mbox;
    1451             : 
    1452           0 :         if (mfi_get_info(sc)) {
    1453             :                 rv = EIO;
    1454           0 :                 goto done;
    1455             :         }
    1456             : 
    1457           0 :         if (!sc->sc_ld[link->target].ld_present) {
    1458             :                 rv = EIO;
    1459           0 :                 goto done;
    1460             :         }
    1461             : 
    1462           0 :         memset(&mbox, 0, sizeof(mbox));
    1463           0 :         mbox.b[0] = link->target;
    1464           0 :         if ((rv = mfi_mgmt(sc, MR_DCMD_LD_GET_PROPERTIES, MFI_DATA_IN,
    1465           0 :             sizeof(ldp), &ldp, &mbox)) != 0)
    1466             :                 goto done;
    1467             : 
    1468           0 :         if (sc->sc_info.mci_memory_size > 0) {
    1469           0 :                 wrenable = ISSET(ldp.mlp_cur_cache_policy,
    1470             :                     MR_LD_CACHE_ALLOW_WRITE_CACHE)? 1 : 0;
    1471           0 :                 rdenable = ISSET(ldp.mlp_cur_cache_policy,
    1472             :                     MR_LD_CACHE_ALLOW_READ_CACHE)? 1 : 0;
    1473           0 :         } else {
    1474           0 :                 wrenable = ISSET(ldp.mlp_diskcache_policy,
    1475             :                     MR_LD_DISK_CACHE_ENABLE)? 1 : 0;
    1476             :                 rdenable = 0;
    1477             :         }
    1478             : 
    1479           0 :         if (cmd == DIOCGCACHE) {
    1480           0 :                 dc->wrcache = wrenable;
    1481           0 :                 dc->rdcache = rdenable;
    1482           0 :                 goto done;
    1483             :         } /* else DIOCSCACHE */
    1484             : 
    1485           0 :         if (((dc->wrcache) ? 1 : 0) == wrenable &&
    1486           0 :             ((dc->rdcache) ? 1 : 0) == rdenable)
    1487             :                 goto done;
    1488             : 
    1489           0 :         memset(&mbox, 0, sizeof(mbox));
    1490           0 :         mbox.b[0] = ldp.mlp_ld.mld_target;
    1491           0 :         mbox.b[1] = ldp.mlp_ld.mld_res;
    1492           0 :         mbox.s[1] = ldp.mlp_ld.mld_seq;
    1493             : 
    1494           0 :         if (sc->sc_info.mci_memory_size > 0) {
    1495           0 :                 if (dc->rdcache)
    1496           0 :                         SET(ldp.mlp_cur_cache_policy,
    1497             :                             MR_LD_CACHE_ALLOW_READ_CACHE);
    1498             :                 else
    1499           0 :                         CLR(ldp.mlp_cur_cache_policy,
    1500             :                             MR_LD_CACHE_ALLOW_READ_CACHE);
    1501           0 :                 if (dc->wrcache)
    1502           0 :                         SET(ldp.mlp_cur_cache_policy,
    1503             :                             MR_LD_CACHE_ALLOW_WRITE_CACHE);
    1504             :                 else
    1505           0 :                         CLR(ldp.mlp_cur_cache_policy,
    1506             :                             MR_LD_CACHE_ALLOW_WRITE_CACHE);
    1507             :         } else {
    1508           0 :                 if (dc->rdcache) {
    1509             :                         rv = EOPNOTSUPP;
    1510           0 :                         goto done;
    1511             :                 }
    1512           0 :                 if (dc->wrcache)
    1513           0 :                         ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_ENABLE;
    1514             :                 else
    1515           0 :                         ldp.mlp_diskcache_policy = MR_LD_DISK_CACHE_DISABLE;
    1516             :         }
    1517             : 
    1518           0 :         if ((rv = mfi_mgmt(sc, MR_DCMD_LD_SET_PROPERTIES, MFI_DATA_OUT,
    1519             :             sizeof(ldp), &ldp, &mbox)) != 0)
    1520           0 :                 goto done;
    1521             : done:
    1522           0 :         return (rv);
    1523           0 : }
    1524             : 
    1525             : #if NBIO > 0
    1526             : int
    1527           0 : mfi_ioctl(struct device *dev, u_long cmd, caddr_t addr)
    1528             : {
    1529           0 :         struct mfi_softc        *sc = (struct mfi_softc *)dev;
    1530             :         int error = 0;
    1531             : 
    1532             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc));
    1533             : 
    1534           0 :         rw_enter_write(&sc->sc_lock);
    1535             : 
    1536           0 :         switch (cmd) {
    1537             :         case BIOCINQ:
    1538             :                 DNPRINTF(MFI_D_IOCTL, "inq\n");
    1539           0 :                 error = mfi_ioctl_inq(sc, (struct bioc_inq *)addr);
    1540           0 :                 break;
    1541             : 
    1542             :         case BIOCVOL:
    1543             :                 DNPRINTF(MFI_D_IOCTL, "vol\n");
    1544           0 :                 error = mfi_ioctl_vol(sc, (struct bioc_vol *)addr);
    1545           0 :                 break;
    1546             : 
    1547             :         case BIOCDISK:
    1548             :                 DNPRINTF(MFI_D_IOCTL, "disk\n");
    1549           0 :                 error = mfi_ioctl_disk(sc, (struct bioc_disk *)addr);
    1550           0 :                 break;
    1551             : 
    1552             :         case BIOCALARM:
    1553             :                 DNPRINTF(MFI_D_IOCTL, "alarm\n");
    1554           0 :                 error = mfi_ioctl_alarm(sc, (struct bioc_alarm *)addr);
    1555           0 :                 break;
    1556             : 
    1557             :         case BIOCBLINK:
    1558             :                 DNPRINTF(MFI_D_IOCTL, "blink\n");
    1559           0 :                 error = mfi_ioctl_blink(sc, (struct bioc_blink *)addr);
    1560           0 :                 break;
    1561             : 
    1562             :         case BIOCSETSTATE:
    1563             :                 DNPRINTF(MFI_D_IOCTL, "setstate\n");
    1564           0 :                 error = mfi_ioctl_setstate(sc, (struct bioc_setstate *)addr);
    1565           0 :                 break;
    1566             : 
    1567             :         case BIOCPATROL:
    1568             :                 DNPRINTF(MFI_D_IOCTL, "patrol\n");
    1569           0 :                 error = mfi_ioctl_patrol(sc, (struct bioc_patrol *)addr);
    1570           0 :                 break;
    1571             : 
    1572             :         default:
    1573             :                 DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n");
    1574             :                 error = ENOTTY;
    1575           0 :         }
    1576             : 
    1577           0 :         rw_exit_write(&sc->sc_lock);
    1578             : 
    1579           0 :         return (error);
    1580             : }
    1581             : 
    1582             : int
    1583           0 : mfi_bio_getitall(struct mfi_softc *sc)
    1584             : {
    1585             :         int                     i, d, size, rv = EINVAL;
    1586           0 :         union mfi_mbox          mbox;
    1587             :         struct mfi_conf         *cfg = NULL;
    1588             :         struct mfi_ld_details   *ld_det = NULL;
    1589             : 
    1590             :         /* get info */
    1591           0 :         if (mfi_get_info(sc)) {
    1592             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_get_info failed\n",
    1593             :                     DEVNAME(sc));
    1594             :                 goto done;
    1595             :         }
    1596             : 
    1597             :         /* send single element command to retrieve size for full structure */
    1598           0 :         cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
    1599           0 :         if (cfg == NULL)
    1600             :                 goto done;
    1601           0 :         if (mfi_mgmt(sc, MR_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg,
    1602             :             NULL)) {
    1603           0 :                 free(cfg, M_DEVBUF, sizeof *cfg);
    1604           0 :                 goto done;
    1605             :         }
    1606             : 
    1607           0 :         size = cfg->mfc_size;
    1608           0 :         free(cfg, M_DEVBUF, sizeof *cfg);
    1609             : 
    1610             :         /* memory for read config */
    1611           0 :         cfg = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
    1612           0 :         if (cfg == NULL)
    1613             :                 goto done;
    1614           0 :         if (mfi_mgmt(sc, MR_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL)) {
    1615           0 :                 free(cfg, M_DEVBUF, size);
    1616           0 :                 goto done;
    1617             :         }
    1618             : 
    1619             :         /* replace current pointer with new one */
    1620           0 :         if (sc->sc_cfg)
    1621           0 :                 free(sc->sc_cfg, M_DEVBUF, 0);
    1622           0 :         sc->sc_cfg = cfg;
    1623             : 
    1624             :         /* get all ld info */
    1625           0 :         if (mfi_mgmt(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN,
    1626           0 :             sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL))
    1627             :                 goto done;
    1628             : 
    1629             :         /* get memory for all ld structures */
    1630           0 :         size = cfg->mfc_no_ld * sizeof(struct mfi_ld_details);
    1631           0 :         if (sc->sc_ld_sz != size) {
    1632           0 :                 if (sc->sc_ld_details)
    1633           0 :                         free(sc->sc_ld_details, M_DEVBUF, 0);
    1634             : 
    1635           0 :                 ld_det = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
    1636           0 :                 if (ld_det == NULL)
    1637             :                         goto done;
    1638           0 :                 sc->sc_ld_sz = size;
    1639           0 :                 sc->sc_ld_details = ld_det;
    1640           0 :         }
    1641             : 
    1642             :         /* find used physical disks */
    1643             :         size = sizeof(struct mfi_ld_details);
    1644           0 :         for (i = 0, d = 0; i < cfg->mfc_no_ld; i++) {
    1645           0 :                 memset(&mbox, 0, sizeof(mbox));
    1646           0 :                 mbox.b[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
    1647           0 :                 if (mfi_mgmt(sc, MR_DCMD_LD_GET_INFO, MFI_DATA_IN, size,
    1648           0 :                     &sc->sc_ld_details[i], &mbox))
    1649             :                         goto done;
    1650             : 
    1651           0 :                 d += sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
    1652           0 :                     sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
    1653             :         }
    1654           0 :         sc->sc_no_pd = d;
    1655             : 
    1656           0 :         rv = 0;
    1657             : done:
    1658           0 :         return (rv);
    1659           0 : }
    1660             : 
    1661             : int
    1662           0 : mfi_ioctl_inq(struct mfi_softc *sc, struct bioc_inq *bi)
    1663             : {
    1664             :         int                     rv = EINVAL;
    1665             :         struct mfi_conf         *cfg = NULL;
    1666             : 
    1667             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq\n", DEVNAME(sc));
    1668             : 
    1669           0 :         if (mfi_bio_getitall(sc)) {
    1670             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
    1671             :                     DEVNAME(sc));
    1672             :                 goto done;
    1673             :         }
    1674             : 
    1675             :         /* count unused disks as volumes */
    1676           0 :         if (sc->sc_cfg == NULL)
    1677             :                 goto done;
    1678             :         cfg = sc->sc_cfg;
    1679             : 
    1680           0 :         bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
    1681           0 :         bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
    1682             : #if notyet
    1683             :         bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs +
    1684             :             (bi->bi_nodisk - sc->sc_no_pd);
    1685             : #endif
    1686             :         /* tell bio who we are */
    1687           0 :         strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
    1688             : 
    1689           0 :         rv = 0;
    1690             : done:
    1691           0 :         return (rv);
    1692             : }
    1693             : 
    1694             : int
    1695           0 : mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv)
    1696             : {
    1697             :         int                     i, per, rv = EINVAL;
    1698             :         struct scsi_link        *link;
    1699             :         struct device           *dev;
    1700             : 
    1701             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol %#x\n",
    1702             :             DEVNAME(sc), bv->bv_volid);
    1703             : 
    1704             :         /* we really could skip and expect that inq took care of it */
    1705           0 :         if (mfi_bio_getitall(sc)) {
    1706             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
    1707             :                     DEVNAME(sc));
    1708             :                 goto done;
    1709             :         }
    1710             : 
    1711           0 :         if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
    1712             :                 /* go do hotspares & unused disks */
    1713           0 :                 rv = mfi_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
    1714           0 :                 goto done;
    1715             :         }
    1716             : 
    1717             :         i = bv->bv_volid;
    1718           0 :         link = scsi_get_link(sc->sc_scsibus, i, 0);
    1719           0 :         if (link != NULL && link->device_softc != NULL) {
    1720           0 :                 dev = link->device_softc;
    1721           0 :                 strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
    1722           0 :         }
    1723             : 
    1724           0 :         switch(sc->sc_ld_list.mll_list[i].mll_state) {
    1725             :         case MFI_LD_OFFLINE:
    1726           0 :                 bv->bv_status = BIOC_SVOFFLINE;
    1727           0 :                 break;
    1728             : 
    1729             :         case MFI_LD_PART_DEGRADED:
    1730             :         case MFI_LD_DEGRADED:
    1731           0 :                 bv->bv_status = BIOC_SVDEGRADED;
    1732           0 :                 break;
    1733             : 
    1734             :         case MFI_LD_ONLINE:
    1735           0 :                 bv->bv_status = BIOC_SVONLINE;
    1736           0 :                 break;
    1737             : 
    1738             :         default:
    1739           0 :                 bv->bv_status = BIOC_SVINVALID;
    1740             :                 DNPRINTF(MFI_D_IOCTL, "%s: invalid logical disk state %#x\n",
    1741             :                     DEVNAME(sc),
    1742             :                     sc->sc_ld_list.mll_list[i].mll_state);
    1743           0 :         }
    1744             : 
    1745             :         /* additional status can modify MFI status */
    1746           0 :         switch (sc->sc_ld_details[i].mld_progress.mlp_in_prog) {
    1747             :         case MFI_LD_PROG_CC:
    1748             :         case MFI_LD_PROG_BGI:
    1749           0 :                 bv->bv_status = BIOC_SVSCRUB;
    1750           0 :                 per = (int)sc->sc_ld_details[i].mld_progress.mlp_cc.mp_progress;
    1751           0 :                 bv->bv_percent = (per * 100) / 0xffff;
    1752           0 :                 bv->bv_seconds =
    1753           0 :                     sc->sc_ld_details[i].mld_progress.mlp_cc.mp_elapsed_seconds;
    1754           0 :                 break;
    1755             : 
    1756             :         case MFI_LD_PROG_FGI:
    1757             :         case MFI_LD_PROG_RECONSTRUCT:
    1758             :                 /* nothing yet */
    1759             :                 break;
    1760             :         }
    1761             : 
    1762           0 :         if (sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_cur_cache_policy & 0x01)
    1763           0 :                 bv->bv_cache = BIOC_CVWRITEBACK;
    1764             :         else
    1765           0 :                 bv->bv_cache = BIOC_CVWRITETHROUGH;
    1766             : 
    1767             :         /*
    1768             :          * The RAID levels are determined per the SNIA DDF spec, this is only
    1769             :          * a subset that is valid for the MFI controller.
    1770             :          */
    1771           0 :         bv->bv_level = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_pri_raid;
    1772           0 :         if (sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_sec_raid ==
    1773             :             MFI_DDF_SRL_SPANNED)
    1774           0 :                 bv->bv_level *= 10;
    1775             : 
    1776           0 :         bv->bv_nodisk = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
    1777           0 :             sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
    1778             : 
    1779           0 :         bv->bv_size = sc->sc_ld_details[i].mld_size * 512; /* bytes per block */
    1780             : 
    1781           0 :         rv = 0;
    1782             : done:
    1783           0 :         return (rv);
    1784             : }
    1785             : 
    1786             : int
    1787           0 : mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
    1788             : {
    1789             :         struct mfi_conf         *cfg;
    1790             :         struct mfi_array        *ar;
    1791             :         struct mfi_ld_cfg       *ld;
    1792             :         struct mfi_pd_details   *pd;
    1793             :         struct mfi_pd_progress  *mfp;
    1794             :         struct mfi_progress     *mp;
    1795             :         struct scsi_inquiry_data *inqbuf;
    1796           0 :         char                    vend[8+16+4+1], *vendp;
    1797             :         int                     rv = EINVAL;
    1798             :         int                     arr, vol, disk, span;
    1799           0 :         union mfi_mbox          mbox;
    1800             : 
    1801             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n",
    1802             :             DEVNAME(sc), bd->bd_diskid);
    1803             : 
    1804             :         /* we really could skip and expect that inq took care of it */
    1805           0 :         if (mfi_bio_getitall(sc)) {
    1806             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
    1807             :                     DEVNAME(sc));
    1808           0 :                 return (rv);
    1809             :         }
    1810           0 :         cfg = sc->sc_cfg;
    1811             : 
    1812           0 :         pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
    1813             : 
    1814           0 :         ar = cfg->mfc_array;
    1815           0 :         vol = bd->bd_volid;
    1816           0 :         if (vol >= cfg->mfc_no_ld) {
    1817             :                 /* do hotspares */
    1818           0 :                 rv = mfi_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
    1819           0 :                 goto freeme;
    1820             :         }
    1821             : 
    1822             :         /* calculate offset to ld structure */
    1823           0 :         ld = (struct mfi_ld_cfg *)(
    1824           0 :             ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
    1825           0 :             cfg->mfc_array_size * cfg->mfc_no_array);
    1826             : 
    1827             :         /* use span 0 only when raid group is not spanned */
    1828           0 :         if (ld[vol].mlc_parm.mpa_span_depth > 1)
    1829           0 :                 span = bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
    1830             :         else
    1831             :                 span = 0;
    1832           0 :         arr = ld[vol].mlc_span[span].mls_index;
    1833             : 
    1834             :         /* offset disk into pd list */
    1835           0 :         disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
    1836           0 :         bd->bd_target = ar[arr].pd[disk].mar_enc_slot;
    1837             : 
    1838             :         /* get status */
    1839           0 :         switch (ar[arr].pd[disk].mar_pd_state){
    1840             :         case MFI_PD_UNCONFIG_GOOD:
    1841             :         case MFI_PD_FAILED:
    1842           0 :                 bd->bd_status = BIOC_SDFAILED;
    1843           0 :                 break;
    1844             : 
    1845             :         case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
    1846           0 :                 bd->bd_status = BIOC_SDHOTSPARE;
    1847           0 :                 break;
    1848             : 
    1849             :         case MFI_PD_OFFLINE:
    1850           0 :                 bd->bd_status = BIOC_SDOFFLINE;
    1851           0 :                 break;
    1852             : 
    1853             :         case MFI_PD_REBUILD:
    1854           0 :                 bd->bd_status = BIOC_SDREBUILD;
    1855           0 :                 break;
    1856             : 
    1857             :         case MFI_PD_ONLINE:
    1858           0 :                 bd->bd_status = BIOC_SDONLINE;
    1859           0 :                 break;
    1860             : 
    1861             :         case MFI_PD_UNCONFIG_BAD: /* XXX define new state in bio */
    1862             :         default:
    1863           0 :                 bd->bd_status = BIOC_SDINVALID;
    1864           0 :                 break;
    1865             :         }
    1866             : 
    1867             :         /* get the remaining fields */
    1868           0 :         memset(&mbox, 0, sizeof(mbox));
    1869           0 :         mbox.s[0] = ar[arr].pd[disk].mar_pd.mfp_id;
    1870           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
    1871             :             sizeof *pd, pd, &mbox)) {
    1872             :                 /* disk is missing but succeed command */
    1873             :                 rv = 0;
    1874           0 :                 goto freeme;
    1875             :         }
    1876             : 
    1877           0 :         bd->bd_size = pd->mpd_size * 512; /* bytes per block */
    1878             : 
    1879             :         /* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
    1880           0 :         bd->bd_channel = pd->mpd_enc_idx;
    1881             : 
    1882           0 :         inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
    1883           0 :         vendp = inqbuf->vendor;
    1884           0 :         memcpy(vend, vendp, sizeof vend - 1);
    1885           0 :         vend[sizeof vend - 1] = '\0';
    1886           0 :         strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
    1887             : 
    1888             :         /* XXX find a way to retrieve serial nr from drive */
    1889             :         /* XXX find a way to get bd_procdev */
    1890             : 
    1891           0 :         mfp = &pd->mpd_progress;
    1892           0 :         if (mfp->mfp_in_prog & MFI_PD_PROG_PR) {
    1893           0 :                 mp = &mfp->mfp_patrol_read;
    1894           0 :                 bd->bd_patrol.bdp_percent = (mp->mp_progress * 100) / 0xffff;
    1895           0 :                 bd->bd_patrol.bdp_seconds = mp->mp_elapsed_seconds;
    1896           0 :         }
    1897             : 
    1898           0 :         rv = 0;
    1899             : freeme:
    1900           0 :         free(pd, M_DEVBUF, sizeof *pd);
    1901             : 
    1902           0 :         return (rv);
    1903           0 : }
    1904             : 
    1905             : int
    1906           0 : mfi_ioctl_alarm(struct mfi_softc *sc, struct bioc_alarm *ba)
    1907             : {
    1908             :         uint32_t                opc, dir = MFI_DATA_NONE;
    1909             :         int                     rv = 0;
    1910           0 :         int8_t                  ret;
    1911             : 
    1912           0 :         switch(ba->ba_opcode) {
    1913             :         case BIOC_SADISABLE:
    1914             :                 opc = MR_DCMD_SPEAKER_DISABLE;
    1915           0 :                 break;
    1916             : 
    1917             :         case BIOC_SAENABLE:
    1918             :                 opc = MR_DCMD_SPEAKER_ENABLE;
    1919           0 :                 break;
    1920             : 
    1921             :         case BIOC_SASILENCE:
    1922             :                 opc = MR_DCMD_SPEAKER_SILENCE;
    1923           0 :                 break;
    1924             : 
    1925             :         case BIOC_GASTATUS:
    1926             :                 opc = MR_DCMD_SPEAKER_GET;
    1927             :                 dir = MFI_DATA_IN;
    1928           0 :                 break;
    1929             : 
    1930             :         case BIOC_SATEST:
    1931             :                 opc = MR_DCMD_SPEAKER_TEST;
    1932           0 :                 break;
    1933             : 
    1934             :         default:
    1935             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_alarm biocalarm invalid "
    1936             :                     "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
    1937           0 :                 return (EINVAL);
    1938             :         }
    1939             : 
    1940           0 :         if (mfi_mgmt(sc, opc, dir, sizeof(ret), &ret, NULL))
    1941           0 :                 rv = EINVAL;
    1942             :         else
    1943           0 :                 if (ba->ba_opcode == BIOC_GASTATUS)
    1944           0 :                         ba->ba_status = ret;
    1945             :                 else
    1946           0 :                         ba->ba_status = 0;
    1947             : 
    1948           0 :         return (rv);
    1949           0 : }
    1950             : 
    1951             : int
    1952           0 : mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *bb)
    1953             : {
    1954             :         int                     i, found, rv = EINVAL;
    1955           0 :         union mfi_mbox          mbox;
    1956             :         uint32_t                cmd;
    1957             :         struct mfi_pd_list      *pd;
    1958             : 
    1959             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc),
    1960             :             bb->bb_status);
    1961             : 
    1962             :         /* channel 0 means not in an enclosure so can't be blinked */
    1963           0 :         if (bb->bb_channel == 0)
    1964           0 :                 return (EINVAL);
    1965             : 
    1966           0 :         pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
    1967             : 
    1968           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
    1969             :             sizeof(*pd), pd, NULL))
    1970             :                 goto done;
    1971             : 
    1972           0 :         for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
    1973           0 :                 if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
    1974           0 :                     bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
    1975             :                         found = 1;
    1976           0 :                         break;
    1977             :                 }
    1978             : 
    1979           0 :         if (!found)
    1980             :                 goto done;
    1981             : 
    1982           0 :         memset(&mbox, 0, sizeof(mbox));
    1983           0 :         mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
    1984             : 
    1985           0 :         switch (bb->bb_status) {
    1986             :         case BIOC_SBUNBLINK:
    1987             :                 cmd = MR_DCMD_PD_UNBLINK;
    1988           0 :                 break;
    1989             : 
    1990             :         case BIOC_SBBLINK:
    1991             :                 cmd = MR_DCMD_PD_BLINK;
    1992           0 :                 break;
    1993             : 
    1994             :         case BIOC_SBALARM:
    1995             :         default:
    1996             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink biocblink invalid "
    1997             :                     "opcode %x\n", DEVNAME(sc), bb->bb_status);
    1998             :                 goto done;
    1999             :         }
    2000             : 
    2001             : 
    2002           0 :         if (mfi_mgmt(sc, cmd, MFI_DATA_NONE, 0, NULL, &mbox))
    2003             :                 goto done;
    2004             : 
    2005           0 :         rv = 0;
    2006             : done:
    2007           0 :         free(pd, M_DEVBUF, sizeof *pd);
    2008           0 :         return (rv);
    2009           0 : }
    2010             : 
    2011             : int
    2012           0 : mfi_ioctl_setstate(struct mfi_softc *sc, struct bioc_setstate *bs)
    2013             : {
    2014             :         struct mfi_pd_list      *pd;
    2015             :         struct mfi_pd_details   *info;
    2016             :         int                     i, found, rv = EINVAL;
    2017           0 :         union mfi_mbox          mbox;
    2018             : 
    2019             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc),
    2020             :             bs->bs_status);
    2021             : 
    2022           0 :         pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
    2023           0 :         info = malloc(sizeof *info, M_DEVBUF, M_WAITOK);
    2024             : 
    2025           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
    2026             :             sizeof(*pd), pd, NULL))
    2027             :                 goto done;
    2028             : 
    2029           0 :         for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
    2030           0 :                 if (bs->bs_channel == pd->mpl_address[i].mpa_enc_index &&
    2031           0 :                     bs->bs_target == pd->mpl_address[i].mpa_enc_slot) {
    2032             :                         found = 1;
    2033           0 :                         break;
    2034             :                 }
    2035             : 
    2036           0 :         if (!found)
    2037             :                 goto done;
    2038             : 
    2039           0 :         memset(&mbox, 0, sizeof(mbox));
    2040           0 :         mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
    2041             : 
    2042           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
    2043             :             sizeof *info, info, &mbox))
    2044             :                 goto done;
    2045             : 
    2046           0 :         mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
    2047           0 :         mbox.s[1] = info->mpd_pd.mfp_seq;
    2048             : 
    2049           0 :         switch (bs->bs_status) {
    2050             :         case BIOC_SSONLINE:
    2051           0 :                 mbox.b[4] = MFI_PD_ONLINE;
    2052           0 :                 break;
    2053             : 
    2054             :         case BIOC_SSOFFLINE:
    2055           0 :                 mbox.b[4] = MFI_PD_OFFLINE;
    2056           0 :                 break;
    2057             : 
    2058             :         case BIOC_SSHOTSPARE:
    2059           0 :                 mbox.b[4] = MFI_PD_HOTSPARE;
    2060           0 :                 break;
    2061             : 
    2062             :         case BIOC_SSREBUILD:
    2063           0 :                 mbox.b[4] = MFI_PD_REBUILD;
    2064           0 :                 break;
    2065             : 
    2066             :         default:
    2067             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate invalid "
    2068             :                     "opcode %x\n", DEVNAME(sc), bs->bs_status);
    2069             :                 goto done;
    2070             :         }
    2071             : 
    2072             : 
    2073           0 :         if ((rv = mfi_mgmt(sc, MR_DCMD_PD_SET_STATE, MFI_DATA_NONE, 0, NULL,
    2074             :             &mbox)))
    2075             :                 goto done;
    2076             : 
    2077             :         rv = 0;
    2078             : done:
    2079           0 :         free(pd, M_DEVBUF, sizeof *pd);
    2080           0 :         free(info, M_DEVBUF, sizeof *info);
    2081           0 :         return (rv);
    2082           0 : }
    2083             : 
    2084             : int
    2085           0 : mfi_ioctl_patrol(struct mfi_softc *sc, struct bioc_patrol *bp)
    2086             : {
    2087             :         uint32_t                opc, dir = MFI_DATA_NONE;
    2088             :         int                     rv = 0;
    2089           0 :         struct mfi_pr_properties prop;
    2090           0 :         struct mfi_pr_status    status;
    2091           0 :         uint32_t                time, exec_freq;
    2092             : 
    2093           0 :         switch (bp->bp_opcode) {
    2094             :         case BIOC_SPSTOP:
    2095             :         case BIOC_SPSTART:
    2096           0 :                 if (bp->bp_opcode == BIOC_SPSTART)
    2097           0 :                         opc = MR_DCMD_PR_START;
    2098             :                 else
    2099             :                         opc = MR_DCMD_PR_STOP;
    2100             :                 dir = MFI_DATA_IN;
    2101           0 :                 if (mfi_mgmt(sc, opc, dir, 0, NULL, NULL))
    2102           0 :                         return (EINVAL);
    2103             :                 break;
    2104             : 
    2105             :         case BIOC_SPMANUAL:
    2106             :         case BIOC_SPDISABLE:
    2107             :         case BIOC_SPAUTO:
    2108             :                 /* Get device's time. */
    2109             :                 opc = MR_DCMD_TIME_SECS_GET;
    2110             :                 dir = MFI_DATA_IN;
    2111           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(time), &time, NULL))
    2112           0 :                         return (EINVAL);
    2113             : 
    2114             :                 opc = MR_DCMD_PR_GET_PROPERTIES;
    2115             :                 dir = MFI_DATA_IN;
    2116           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(prop), &prop, NULL))
    2117           0 :                         return (EINVAL);
    2118             : 
    2119           0 :                 switch (bp->bp_opcode) {
    2120             :                 case BIOC_SPMANUAL:
    2121           0 :                         prop.op_mode = MFI_PR_OPMODE_MANUAL;
    2122           0 :                         break;
    2123             :                 case BIOC_SPDISABLE:
    2124           0 :                         prop.op_mode = MFI_PR_OPMODE_DISABLED;
    2125           0 :                         break;
    2126             :                 case BIOC_SPAUTO:
    2127           0 :                         if (bp->bp_autoival != 0) {
    2128           0 :                                 if (bp->bp_autoival == -1)
    2129             :                                         /* continuously */
    2130           0 :                                         exec_freq = 0xffffffffU;
    2131           0 :                                 else if (bp->bp_autoival > 0)
    2132             :                                         exec_freq = bp->bp_autoival;
    2133             :                                 else
    2134           0 :                                         return (EINVAL);
    2135           0 :                                 prop.exec_freq = exec_freq;
    2136           0 :                         }
    2137           0 :                         if (bp->bp_autonext != 0) {
    2138           0 :                                 if (bp->bp_autonext < 0)
    2139           0 :                                         return (EINVAL);
    2140             :                                 else
    2141           0 :                                         prop.next_exec = time + bp->bp_autonext;
    2142           0 :                         }
    2143           0 :                         prop.op_mode = MFI_PR_OPMODE_AUTO;
    2144           0 :                         break;
    2145             :                 }
    2146             : 
    2147             :                 opc = MR_DCMD_PR_SET_PROPERTIES;
    2148             :                 dir = MFI_DATA_OUT;
    2149           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(prop), &prop, NULL))
    2150           0 :                         return (EINVAL);
    2151             : 
    2152             :                 break;
    2153             : 
    2154             :         case BIOC_GPSTATUS:
    2155             :                 opc = MR_DCMD_PR_GET_PROPERTIES;
    2156             :                 dir = MFI_DATA_IN;
    2157           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(prop), &prop, NULL))
    2158           0 :                         return (EINVAL);
    2159             : 
    2160             :                 opc = MR_DCMD_PR_GET_STATUS;
    2161             :                 dir = MFI_DATA_IN;
    2162           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(status), &status, NULL))
    2163           0 :                         return (EINVAL);
    2164             : 
    2165             :                 /* Get device's time. */
    2166             :                 opc = MR_DCMD_TIME_SECS_GET;
    2167             :                 dir = MFI_DATA_IN;
    2168           0 :                 if (mfi_mgmt(sc, opc, dir, sizeof(time), &time, NULL))
    2169           0 :                         return (EINVAL);
    2170             : 
    2171           0 :                 switch (prop.op_mode) {
    2172             :                 case MFI_PR_OPMODE_AUTO:
    2173           0 :                         bp->bp_mode = BIOC_SPMAUTO;
    2174           0 :                         bp->bp_autoival = prop.exec_freq;
    2175           0 :                         bp->bp_autonext = prop.next_exec;
    2176           0 :                         bp->bp_autonow = time;
    2177           0 :                         break;
    2178             :                 case MFI_PR_OPMODE_MANUAL:
    2179           0 :                         bp->bp_mode = BIOC_SPMMANUAL;
    2180           0 :                         break;
    2181             :                 case MFI_PR_OPMODE_DISABLED:
    2182           0 :                         bp->bp_mode = BIOC_SPMDISABLED;
    2183           0 :                         break;
    2184             :                 default:
    2185           0 :                         printf("%s: unknown patrol mode %d\n",
    2186           0 :                             DEVNAME(sc), prop.op_mode);
    2187           0 :                         break;
    2188             :                 }
    2189             : 
    2190           0 :                 switch (status.state) {
    2191             :                 case MFI_PR_STATE_STOPPED:
    2192           0 :                         bp->bp_status = BIOC_SPSSTOPPED;
    2193           0 :                         break;
    2194             :                 case MFI_PR_STATE_READY:
    2195           0 :                         bp->bp_status = BIOC_SPSREADY;
    2196           0 :                         break;
    2197             :                 case MFI_PR_STATE_ACTIVE:
    2198           0 :                         bp->bp_status = BIOC_SPSACTIVE;
    2199           0 :                         break;
    2200             :                 case MFI_PR_STATE_ABORTED:
    2201           0 :                         bp->bp_status = BIOC_SPSABORTED;
    2202           0 :                         break;
    2203             :                 default:
    2204           0 :                         printf("%s: unknown patrol state %d\n",
    2205           0 :                             DEVNAME(sc), status.state);
    2206           0 :                         break;
    2207             :                 }
    2208             : 
    2209             :                 break;
    2210             : 
    2211             :         default:
    2212             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_patrol biocpatrol invalid "
    2213             :                     "opcode %x\n", DEVNAME(sc), bp->bp_opcode);
    2214           0 :                 return (EINVAL);
    2215             :         }
    2216             : 
    2217           0 :         return (rv);
    2218           0 : }
    2219             : 
    2220             : int
    2221           0 : mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
    2222             : {
    2223             :         struct mfi_conf         *cfg;
    2224             :         struct mfi_hotspare     *hs;
    2225             :         struct mfi_pd_details   *pd;
    2226             :         struct bioc_disk        *sdhs;
    2227             :         struct bioc_vol         *vdhs;
    2228             :         struct scsi_inquiry_data *inqbuf;
    2229           0 :         char                    vend[8+16+4+1], *vendp;
    2230             :         int                     i, rv = EINVAL;
    2231             :         uint32_t                size;
    2232           0 :         union mfi_mbox          mbox;
    2233             : 
    2234             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs %d\n", DEVNAME(sc), volid);
    2235             : 
    2236           0 :         if (!bio_hs)
    2237           0 :                 return (EINVAL);
    2238             : 
    2239           0 :         pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
    2240             : 
    2241             :         /* send single element command to retrieve size for full structure */
    2242           0 :         cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
    2243           0 :         if (mfi_mgmt(sc, MR_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
    2244             :                 goto freeme;
    2245             : 
    2246           0 :         size = cfg->mfc_size;
    2247           0 :         free(cfg, M_DEVBUF, sizeof *cfg);
    2248             : 
    2249             :         /* memory for read config */
    2250           0 :         cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
    2251           0 :         if (mfi_mgmt(sc, MR_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL))
    2252             :                 goto freeme;
    2253             : 
    2254             :         /* calculate offset to hs structure */
    2255           0 :         hs = (struct mfi_hotspare *)(
    2256           0 :             ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
    2257           0 :             cfg->mfc_array_size * cfg->mfc_no_array +
    2258           0 :             cfg->mfc_ld_size * cfg->mfc_no_ld);
    2259             : 
    2260           0 :         if (volid < cfg->mfc_no_ld)
    2261             :                 goto freeme; /* not a hotspare */
    2262             : 
    2263           0 :         if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
    2264             :                 goto freeme; /* not a hotspare */
    2265             : 
    2266             :         /* offset into hotspare structure */
    2267           0 :         i = volid - cfg->mfc_no_ld;
    2268             : 
    2269             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d "
    2270             :             "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
    2271             :             cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
    2272             : 
    2273             :         /* get pd fields */
    2274           0 :         memset(&mbox, 0, sizeof(mbox));
    2275           0 :         mbox.s[0] = hs[i].mhs_pd.mfp_id;
    2276           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
    2277             :             sizeof *pd, pd, &mbox)) {
    2278             :                 DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs illegal PD\n",
    2279             :                     DEVNAME(sc));
    2280             :                 goto freeme;
    2281             :         }
    2282             : 
    2283           0 :         switch (type) {
    2284             :         case MFI_MGMT_VD:
    2285           0 :                 vdhs = bio_hs;
    2286           0 :                 vdhs->bv_status = BIOC_SVONLINE;
    2287           0 :                 vdhs->bv_size = pd->mpd_size / 2 * 1024; /* XXX why? */
    2288           0 :                 vdhs->bv_level = -1; /* hotspare */
    2289           0 :                 vdhs->bv_nodisk = 1;
    2290           0 :                 break;
    2291             : 
    2292             :         case MFI_MGMT_SD:
    2293           0 :                 sdhs = bio_hs;
    2294           0 :                 sdhs->bd_status = BIOC_SDHOTSPARE;
    2295           0 :                 sdhs->bd_size = pd->mpd_size / 2 * 1024; /* XXX why? */
    2296           0 :                 sdhs->bd_channel = pd->mpd_enc_idx;
    2297           0 :                 sdhs->bd_target = pd->mpd_enc_slot;
    2298           0 :                 inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
    2299           0 :                 vendp = inqbuf->vendor;
    2300           0 :                 memcpy(vend, vendp, sizeof vend - 1);
    2301           0 :                 vend[sizeof vend - 1] = '\0';
    2302           0 :                 strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
    2303           0 :                 break;
    2304             : 
    2305             :         default:
    2306             :                 goto freeme;
    2307             :         }
    2308             : 
    2309             :         DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs 6\n", DEVNAME(sc));
    2310           0 :         rv = 0;
    2311             : freeme:
    2312           0 :         free(pd, M_DEVBUF, sizeof *pd);
    2313           0 :         free(cfg, M_DEVBUF, 0);
    2314             : 
    2315           0 :         return (rv);
    2316           0 : }
    2317             : 
    2318             : #ifndef SMALL_KERNEL
    2319             : 
    2320             : static const char *mfi_bbu_indicators[] = {
    2321             :         "pack missing",
    2322             :         "voltage low",
    2323             :         "temp high",
    2324             :         "charge active",
    2325             :         "discharge active",
    2326             :         "learn cycle req'd",
    2327             :         "learn cycle active",
    2328             :         "learn cycle failed",
    2329             :         "learn cycle timeout",
    2330             :         "I2C errors",
    2331             :         "replace pack",
    2332             :         "low capacity",
    2333             :         "periodic learn req'd"
    2334             : };
    2335             : 
    2336             : #define MFI_BBU_SENSORS 4
    2337             : 
    2338             : int
    2339           0 : mfi_bbu(struct mfi_softc *sc)
    2340             : {
    2341           0 :         struct mfi_bbu_status bbu;
    2342             :         u_int32_t status;
    2343             :         u_int32_t mask;
    2344             :         u_int32_t soh_bad;
    2345             :         int i;
    2346             : 
    2347           0 :         if (mfi_mgmt(sc, MR_DCMD_BBU_GET_STATUS, MFI_DATA_IN,
    2348           0 :             sizeof(bbu), &bbu, NULL) != 0) {
    2349           0 :                 for (i = 0; i < MFI_BBU_SENSORS; i++) {
    2350           0 :                         sc->sc_bbu[i].value = 0;
    2351           0 :                         sc->sc_bbu[i].status = SENSOR_S_UNKNOWN;
    2352             :                 }
    2353           0 :                 for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
    2354           0 :                         sc->sc_bbu_status[i].value = 0;
    2355           0 :                         sc->sc_bbu_status[i].status = SENSOR_S_UNKNOWN;
    2356             :                 }
    2357           0 :                 return (-1);
    2358             :         }
    2359             : 
    2360           0 :         switch (bbu.battery_type) {
    2361             :         case MFI_BBU_TYPE_IBBU:
    2362             :                 mask = MFI_BBU_STATE_BAD_IBBU;
    2363             :                 soh_bad = 0;
    2364           0 :                 break;
    2365             :         case MFI_BBU_TYPE_BBU:
    2366             :                 mask = MFI_BBU_STATE_BAD_BBU;
    2367           0 :                 soh_bad = (bbu.detail.bbu.is_SOH_good == 0);
    2368           0 :                 break;
    2369             : 
    2370             :         case MFI_BBU_TYPE_NONE:
    2371             :         default:
    2372           0 :                 sc->sc_bbu[0].value = 0;
    2373           0 :                 sc->sc_bbu[0].status = SENSOR_S_CRIT;
    2374           0 :                 for (i = 1; i < MFI_BBU_SENSORS; i++) {
    2375           0 :                         sc->sc_bbu[i].value = 0;
    2376           0 :                         sc->sc_bbu[i].status = SENSOR_S_UNKNOWN;
    2377             :                 }
    2378           0 :                 for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
    2379           0 :                         sc->sc_bbu_status[i].value = 0;
    2380           0 :                         sc->sc_bbu_status[i].status = SENSOR_S_UNKNOWN;
    2381             :                 }
    2382           0 :                 return (0);
    2383             :         }
    2384             : 
    2385           0 :         status = letoh32(bbu.fw_status);
    2386             : 
    2387           0 :         sc->sc_bbu[0].value = ((status & mask) || soh_bad) ? 0 : 1;
    2388           0 :         sc->sc_bbu[0].status = ((status & mask) || soh_bad) ? SENSOR_S_CRIT :
    2389             :             SENSOR_S_OK;
    2390             : 
    2391           0 :         sc->sc_bbu[1].value = letoh16(bbu.voltage) * 1000;
    2392           0 :         sc->sc_bbu[2].value = (int16_t)letoh16(bbu.current) * 1000;
    2393           0 :         sc->sc_bbu[3].value = letoh16(bbu.temperature) * 1000000 + 273150000;
    2394           0 :         for (i = 1; i < MFI_BBU_SENSORS; i++)
    2395           0 :                 sc->sc_bbu[i].status = SENSOR_S_UNSPEC;
    2396             : 
    2397           0 :         for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
    2398           0 :                 sc->sc_bbu_status[i].value = (status & (1 << i)) ? 1 : 0;
    2399           0 :                 sc->sc_bbu_status[i].status = SENSOR_S_UNSPEC;
    2400             :         }
    2401             : 
    2402           0 :         return (0);
    2403           0 : }
    2404             : 
    2405             : int
    2406           0 : mfi_create_sensors(struct mfi_softc *sc)
    2407             : {
    2408             :         struct device           *dev;
    2409             :         struct scsi_link        *link;
    2410             :         int                     i;
    2411             : 
    2412           0 :         strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
    2413             :             sizeof(sc->sc_sensordev.xname));
    2414             : 
    2415           0 :         if (ISSET(letoh32(sc->sc_info.mci_adapter_ops ), MFI_INFO_AOPS_BBU)) {
    2416           0 :                 sc->sc_bbu = mallocarray(4, sizeof(*sc->sc_bbu),
    2417             :                     M_DEVBUF, M_WAITOK | M_ZERO);
    2418             : 
    2419           0 :                 sc->sc_bbu[0].type = SENSOR_INDICATOR;
    2420           0 :                 sc->sc_bbu[0].status = SENSOR_S_UNKNOWN;
    2421           0 :                 strlcpy(sc->sc_bbu[0].desc, "bbu ok",
    2422             :                     sizeof(sc->sc_bbu[0].desc));
    2423           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_bbu[0]);
    2424             : 
    2425           0 :                 sc->sc_bbu[1].type = SENSOR_VOLTS_DC;
    2426           0 :                 sc->sc_bbu[1].status = SENSOR_S_UNSPEC;
    2427           0 :                 sc->sc_bbu[2].type = SENSOR_AMPS;
    2428           0 :                 sc->sc_bbu[2].status = SENSOR_S_UNSPEC;
    2429           0 :                 sc->sc_bbu[3].type = SENSOR_TEMP;
    2430           0 :                 sc->sc_bbu[3].status = SENSOR_S_UNSPEC;
    2431           0 :                 for (i = 1; i < MFI_BBU_SENSORS; i++) {
    2432           0 :                         strlcpy(sc->sc_bbu[i].desc, "bbu",
    2433             :                             sizeof(sc->sc_bbu[i].desc));
    2434           0 :                         sensor_attach(&sc->sc_sensordev, &sc->sc_bbu[i]);
    2435             :                 }
    2436             : 
    2437           0 :                 sc->sc_bbu_status = malloc(sizeof(*sc->sc_bbu_status) *
    2438             :                     sizeof(mfi_bbu_indicators), M_DEVBUF, M_WAITOK | M_ZERO);
    2439             : 
    2440           0 :                 for (i = 0; i < nitems(mfi_bbu_indicators); i++) {
    2441           0 :                         sc->sc_bbu_status[i].type = SENSOR_INDICATOR;
    2442           0 :                         sc->sc_bbu_status[i].status = SENSOR_S_UNSPEC;
    2443           0 :                         strlcpy(sc->sc_bbu_status[i].desc,
    2444           0 :                             mfi_bbu_indicators[i],
    2445             :                             sizeof(sc->sc_bbu_status[i].desc));
    2446             : 
    2447           0 :                         sensor_attach(&sc->sc_sensordev, &sc->sc_bbu_status[i]);
    2448             :                 }
    2449             :         }
    2450             : 
    2451           0 :         sc->sc_sensors = mallocarray(sc->sc_ld_cnt, sizeof(struct ksensor),
    2452             :             M_DEVBUF, M_NOWAIT | M_ZERO);
    2453           0 :         if (sc->sc_sensors == NULL)
    2454           0 :                 return (1);
    2455             : 
    2456           0 :         for (i = 0; i < sc->sc_ld_cnt; i++) {
    2457           0 :                 link = scsi_get_link(sc->sc_scsibus, i, 0);
    2458           0 :                 if (link == NULL)
    2459             :                         goto bad;
    2460             : 
    2461           0 :                 dev = link->device_softc;
    2462             : 
    2463           0 :                 sc->sc_sensors[i].type = SENSOR_DRIVE;
    2464           0 :                 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
    2465             : 
    2466           0 :                 strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
    2467             :                     sizeof(sc->sc_sensors[i].desc));
    2468             : 
    2469           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
    2470             :         }
    2471             : 
    2472           0 :         if (sensor_task_register(sc, mfi_refresh_sensors, 10) == NULL)
    2473             :                 goto bad;
    2474             : 
    2475           0 :         sensordev_install(&sc->sc_sensordev);
    2476             : 
    2477           0 :         return (0);
    2478             : 
    2479             : bad:
    2480           0 :         free(sc->sc_sensors, M_DEVBUF,
    2481           0 :             sc->sc_ld_cnt * sizeof(struct ksensor));
    2482             : 
    2483           0 :         return (1);
    2484           0 : }
    2485             : 
    2486             : void
    2487           0 : mfi_refresh_sensors(void *arg)
    2488             : {
    2489           0 :         struct mfi_softc        *sc = arg;
    2490             :         int                     i, rv;
    2491           0 :         struct bioc_vol         bv;
    2492             : 
    2493           0 :         if (sc->sc_bbu != NULL && mfi_bbu(sc) != 0)
    2494           0 :                 return;
    2495             : 
    2496           0 :         for (i = 0; i < sc->sc_ld_cnt; i++) {
    2497           0 :                 bzero(&bv, sizeof(bv));
    2498           0 :                 bv.bv_volid = i;
    2499             : 
    2500           0 :                 rw_enter_write(&sc->sc_lock);
    2501           0 :                 rv = mfi_ioctl_vol(sc, &bv);
    2502           0 :                 rw_exit_write(&sc->sc_lock);
    2503             : 
    2504           0 :                 if (rv != 0)
    2505           0 :                         return;
    2506             : 
    2507           0 :                 switch(bv.bv_status) {
    2508             :                 case BIOC_SVOFFLINE:
    2509           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
    2510           0 :                         sc->sc_sensors[i].status = SENSOR_S_CRIT;
    2511           0 :                         break;
    2512             : 
    2513             :                 case BIOC_SVDEGRADED:
    2514           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
    2515           0 :                         sc->sc_sensors[i].status = SENSOR_S_WARN;
    2516           0 :                         break;
    2517             : 
    2518             :                 case BIOC_SVSCRUB:
    2519             :                 case BIOC_SVONLINE:
    2520           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
    2521           0 :                         sc->sc_sensors[i].status = SENSOR_S_OK;
    2522           0 :                         break;
    2523             : 
    2524             :                 case BIOC_SVINVALID:
    2525             :                         /* FALLTRHOUGH */
    2526             :                 default:
    2527           0 :                         sc->sc_sensors[i].value = 0; /* unknown */
    2528           0 :                         sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
    2529           0 :                         break;
    2530             :                 }
    2531             :         }
    2532           0 : }
    2533             : #endif /* SMALL_KERNEL */
    2534             : #endif /* NBIO > 0 */
    2535             : 
    2536             : void
    2537           0 : mfi_start(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2538             : {
    2539           0 :         bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
    2540             :             ccb->ccb_pframe_offset, sc->sc_frames_size,
    2541             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    2542             : 
    2543           0 :         mfi_post(sc, ccb);
    2544           0 : }
    2545             : 
    2546             : void
    2547           0 : mfi_done(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2548             : {
    2549           0 :         bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames),
    2550             :             ccb->ccb_pframe_offset, sc->sc_frames_size,
    2551             :             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    2552             : 
    2553           0 :         if (ccb->ccb_len > 0) {
    2554           0 :                 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap,
    2555             :                     0, ccb->ccb_dmamap->dm_mapsize,
    2556             :                     (ccb->ccb_direction == MFI_DATA_IN) ?
    2557             :                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    2558             : 
    2559           0 :                 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    2560           0 :         }
    2561             : 
    2562           0 :         ccb->ccb_done(sc, ccb);
    2563           0 : }
    2564             : 
    2565             : u_int32_t
    2566           0 : mfi_xscale_fw_state(struct mfi_softc *sc)
    2567             : {
    2568           0 :         return (mfi_read(sc, MFI_OMSG0));
    2569             : }
    2570             : 
    2571             : void
    2572           0 : mfi_xscale_intr_ena(struct mfi_softc *sc)
    2573             : {
    2574           0 :         mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
    2575           0 : }
    2576             : 
    2577             : int
    2578           0 : mfi_xscale_intr(struct mfi_softc *sc)
    2579             : {
    2580             :         u_int32_t status;
    2581             : 
    2582           0 :         status = mfi_read(sc, MFI_OSTS);
    2583           0 :         if (!ISSET(status, MFI_OSTS_INTR_VALID))
    2584           0 :                 return (0);
    2585             : 
    2586             :         /* write status back to acknowledge interrupt */
    2587           0 :         mfi_write(sc, MFI_OSTS, status);
    2588             : 
    2589           0 :         return (1);
    2590           0 : }
    2591             : 
    2592             : void
    2593           0 : mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2594             : {
    2595           0 :         mfi_write(sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
    2596           0 :             ccb->ccb_extra_frames);
    2597           0 : }
    2598             : 
    2599             : u_int32_t
    2600           0 : mfi_ppc_fw_state(struct mfi_softc *sc)
    2601             : {
    2602           0 :         return (mfi_read(sc, MFI_OSP));
    2603             : }
    2604             : 
    2605             : void
    2606           0 : mfi_ppc_intr_ena(struct mfi_softc *sc)
    2607             : {
    2608           0 :         mfi_write(sc, MFI_ODC, 0xffffffff);
    2609           0 :         mfi_write(sc, MFI_OMSK, ~0x80000004);
    2610           0 : }
    2611             : 
    2612             : int
    2613           0 : mfi_ppc_intr(struct mfi_softc *sc)
    2614             : {
    2615             :         u_int32_t status;
    2616             : 
    2617           0 :         status = mfi_read(sc, MFI_OSTS);
    2618           0 :         if (!ISSET(status, MFI_OSTS_PPC_INTR_VALID))
    2619           0 :                 return (0);
    2620             : 
    2621             :         /* write status back to acknowledge interrupt */
    2622           0 :         mfi_write(sc, MFI_ODC, status);
    2623             : 
    2624           0 :         return (1);
    2625           0 : }
    2626             : 
    2627             : void
    2628           0 : mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2629             : {
    2630           0 :         mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
    2631           0 :             (ccb->ccb_extra_frames << 1));
    2632           0 : }
    2633             : 
    2634             : u_int32_t
    2635           0 : mfi_gen2_fw_state(struct mfi_softc *sc)
    2636             : {
    2637           0 :         return (mfi_read(sc, MFI_OSP));
    2638             : }
    2639             : 
    2640             : void
    2641           0 : mfi_gen2_intr_ena(struct mfi_softc *sc)
    2642             : {
    2643           0 :         mfi_write(sc, MFI_ODC, 0xffffffff);
    2644           0 :         mfi_write(sc, MFI_OMSK, ~MFI_OSTS_GEN2_INTR_VALID);
    2645           0 : }
    2646             : 
    2647             : int
    2648           0 : mfi_gen2_intr(struct mfi_softc *sc)
    2649             : {
    2650             :         u_int32_t status;
    2651             : 
    2652           0 :         status = mfi_read(sc, MFI_OSTS);
    2653           0 :         if (!ISSET(status, MFI_OSTS_GEN2_INTR_VALID))
    2654           0 :                 return (0);
    2655             : 
    2656             :         /* write status back to acknowledge interrupt */
    2657           0 :         mfi_write(sc, MFI_ODC, status);
    2658             : 
    2659           0 :         return (1);
    2660           0 : }
    2661             : 
    2662             : void
    2663           0 : mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2664             : {
    2665           0 :         mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
    2666           0 :             (ccb->ccb_extra_frames << 1));
    2667           0 : }
    2668             : 
    2669             : u_int32_t
    2670           0 : mfi_skinny_fw_state(struct mfi_softc *sc)
    2671             : {
    2672           0 :         return (mfi_read(sc, MFI_OSP));
    2673             : }
    2674             : 
    2675             : void
    2676           0 : mfi_skinny_intr_ena(struct mfi_softc *sc)
    2677             : {
    2678           0 :         mfi_write(sc, MFI_OMSK, ~0x00000001);
    2679           0 : }
    2680             : 
    2681             : int
    2682           0 : mfi_skinny_intr(struct mfi_softc *sc)
    2683             : {
    2684             :         u_int32_t status;
    2685             : 
    2686           0 :         status = mfi_read(sc, MFI_OSTS);
    2687           0 :         if (!ISSET(status, MFI_OSTS_SKINNY_INTR_VALID))
    2688           0 :                 return (0);
    2689             : 
    2690             :         /* write status back to acknowledge interrupt */
    2691           0 :         mfi_write(sc, MFI_OSTS, status);
    2692             : 
    2693           0 :         return (1);
    2694           0 : }
    2695             : 
    2696             : void
    2697           0 : mfi_skinny_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2698             : {
    2699           0 :         mfi_write(sc, MFI_IQPL, 0x1 | ccb->ccb_pframe |
    2700           0 :             (ccb->ccb_extra_frames << 1));
    2701           0 :         mfi_write(sc, MFI_IQPH, 0x00000000);
    2702           0 : }
    2703             : 
    2704             : u_int
    2705           0 : mfi_skinny_sgd_load(struct mfi_softc *sc, struct mfi_ccb *ccb)
    2706             : {
    2707           0 :         struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header;
    2708           0 :         union mfi_sgl           *sgl = ccb->ccb_sgl;
    2709           0 :         bus_dma_segment_t       *sgd = ccb->ccb_dmamap->dm_segs;
    2710             :         int                      i;
    2711             : 
    2712           0 :         switch (hdr->mfh_cmd) {
    2713             :         case MFI_CMD_LD_READ:
    2714             :         case MFI_CMD_LD_WRITE:
    2715             :         case MFI_CMD_PD_SCSI_IO:
    2716             :                 /* Use MF_FRAME_IEEE for some IO commands on skinny adapters */
    2717           0 :                 for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
    2718           0 :                         sgl->sg_skinny[i].addr = htole64(sgd[i].ds_addr);
    2719           0 :                         sgl->sg_skinny[i].len = htole32(sgd[i].ds_len);
    2720           0 :                         sgl->sg_skinny[i].flag = 0;
    2721             :                 }
    2722           0 :                 hdr->mfh_flags |= MFI_FRAME_IEEE | MFI_FRAME_SGL64;
    2723             : 
    2724           0 :                 return (ccb->ccb_dmamap->dm_nsegs * sizeof(sgl->sg_skinny));
    2725             :         default:
    2726           0 :                 return (mfi_default_sgd_load(sc, ccb));
    2727             :         }
    2728           0 : }
    2729             : 
    2730             : int
    2731           0 : mfi_pd_scsi_probe(struct scsi_link *link)
    2732             : {
    2733           0 :         union mfi_mbox mbox;
    2734           0 :         struct mfi_softc *sc = link->adapter_softc;
    2735           0 :         struct mfi_pd_link *pl = sc->sc_pd->pd_links[link->target];
    2736             : 
    2737           0 :         if (link->lun > 0)
    2738           0 :                 return (0);
    2739             : 
    2740           0 :         if (pl == NULL)
    2741           0 :                 return (ENXIO);
    2742             : 
    2743           0 :         memset(&mbox, 0, sizeof(mbox));
    2744           0 :         mbox.s[0] = pl->pd_id;
    2745             : 
    2746           0 :         if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
    2747           0 :             sizeof(pl->pd_info), &pl->pd_info, &mbox))
    2748           0 :                 return (EIO);
    2749             : 
    2750           0 :         if (letoh16(pl->pd_info.mpd_fw_state) != MFI_PD_SYSTEM)
    2751           0 :                 return (ENXIO);
    2752             : 
    2753           0 :         return (0);
    2754           0 : }
    2755             : 
    2756             : void
    2757           0 : mfi_pd_scsi_cmd(struct scsi_xfer *xs)
    2758             : {
    2759           0 :         struct scsi_link *link = xs->sc_link;
    2760           0 :         struct mfi_softc *sc = link->adapter_softc;
    2761           0 :         struct mfi_ccb *ccb = xs->io;
    2762           0 :         struct mfi_pass_frame *pf = &ccb->ccb_frame->mfr_pass;
    2763           0 :         struct mfi_pd_link *pl = sc->sc_pd->pd_links[link->target];
    2764             : 
    2765           0 :         KERNEL_UNLOCK();
    2766             : 
    2767           0 :         mfi_scrub_ccb(ccb);
    2768           0 :         xs->error = XS_NOERROR;
    2769             : 
    2770           0 :         pf->mpf_header.mfh_cmd = MFI_CMD_PD_SCSI_IO;
    2771           0 :         pf->mpf_header.mfh_target_id = pl->pd_id;
    2772           0 :         pf->mpf_header.mfh_lun_id = link->lun;
    2773           0 :         pf->mpf_header.mfh_cdb_len = xs->cmdlen;
    2774           0 :         pf->mpf_header.mfh_timeout = 0;
    2775           0 :         pf->mpf_header.mfh_data_len = htole32(xs->datalen); /* XXX */
    2776           0 :         pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE;
    2777           0 :         pf->mpf_sense_addr = htole64(ccb->ccb_psense);
    2778             : 
    2779           0 :         memset(pf->mpf_cdb, 0, sizeof(pf->mpf_cdb));
    2780           0 :         memcpy(pf->mpf_cdb, xs->cmd, xs->cmdlen);
    2781             : 
    2782           0 :         ccb->ccb_done = mfi_scsi_xs_done;
    2783           0 :         ccb->ccb_cookie = xs;
    2784           0 :         ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
    2785           0 :         ccb->ccb_sgl = &pf->mpf_sgl;
    2786             : 
    2787           0 :         if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
    2788           0 :                 ccb->ccb_direction = xs->flags & SCSI_DATA_IN ?
    2789             :                     MFI_DATA_IN : MFI_DATA_OUT;
    2790             :         else
    2791           0 :                 ccb->ccb_direction = MFI_DATA_NONE;
    2792             : 
    2793           0 :         if (xs->data) {
    2794           0 :                 ccb->ccb_data = xs->data;
    2795           0 :                 ccb->ccb_len = xs->datalen;
    2796             : 
    2797           0 :                 if (mfi_create_sgl(sc, ccb, (xs->flags & SCSI_NOSLEEP) ?
    2798             :                     BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
    2799             :                         goto stuffup;
    2800             :         }
    2801             : 
    2802           0 :         if (xs->flags & SCSI_POLL)
    2803           0 :                 mfi_poll(sc, ccb);
    2804             :         else
    2805           0 :                 mfi_start(sc, ccb);
    2806             : 
    2807           0 :         KERNEL_LOCK();
    2808           0 :         return;
    2809             : 
    2810             : stuffup:
    2811           0 :         xs->error = XS_DRIVER_STUFFUP;
    2812           0 :         KERNEL_LOCK();
    2813           0 :         scsi_done(xs);
    2814           0 : }

Generated by: LCOV version 1.13