The diff below adds support for "physical disks" to mfii(4).  Just
like with mfi(4) you can configure this hardware (or at least some
models) to expose disks that have not been assigned to a logical volume
to the host.  This diff makes those disks accesable from OpenBSD.

I would appreciate some tests, especially from people who have
configured some logical volumes on their hardware.


Index: mfii.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/mfii.c,v
retrieving revision 1.17
diff -u -p -r1.17 mfii.c
--- mfii.c      13 Jul 2014 23:10:23 -0000      1.17
+++ mfii.c      20 Sep 2014 18:20:30 -0000
@@ -48,6 +48,7 @@
 #define MFII_REQ_TYPE_LDIO     (0x7 << 1)
 #define MFII_REQ_TYPE_MFA      (0x1 << 1)
 #define MFII_REQ_TYPE_NO_LOCK  (0x2 << 1)
+#define MFII_REQ_TYPE_HI_PRI   (0x6 << 1)
 
 #define MFII_REQ_MFA(_a)       htole64((_a) | MFII_REQ_TYPE_MFA)
 
@@ -59,9 +60,11 @@ struct mfii_request_descr {
        u_int16_t       smid;
 
        u_int16_t       lmid;
-       u_int16_t       field;
+       u_int16_t       dev_handle;
 } __packed;
 
+#define MFII_RAID_CTX_IO_TYPE_SYSPD    (0x1 << 4)
+
 struct mfii_raid_context {
        u_int8_t        type_nseg;
        u_int8_t        _reserved1;
@@ -105,6 +108,34 @@ struct mfii_sge {
 
 #define MFII_REQUEST_SIZE      256
 
+#define MR_DCMD_LD_MAP_GET_INFO                        0x0300e101
+
+#define MFII_MAX_ROW           32
+#define MFII_MAX_ARRAY         128
+
+struct mfii_array_map {
+       uint16_t                mam_pd[MFII_MAX_ROW];
+} __packed;
+
+struct mfii_dev_handle {
+       uint16_t                mdh_cur_handle;
+       uint8_t                 mdh_valid;
+       uint8_t                 mdh_reserved;
+       uint16_t                mdh_handle[2];
+} __packed;
+
+struct mfii_ld_map {
+       uint32_t                mlm_total_size;
+       uint32_t                mlm_reserved1[5];
+       uint32_t                mlm_num_lds;
+       uint32_t                mlm_reserved2;
+       uint8_t                 mlm_tgtid_to_ld[2 * MFI_MAX_LD];
+       uint8_t                 mlm_pd_timeout;
+       uint8_t                 mlm_reserved3[7];
+       struct mfii_array_map   mlm_am[MFII_MAX_ARRAY];
+       struct mfii_dev_handle  mlm_dev_handle[MFI_MAX_PD];
+} __packed;
+
 struct mfii_dmamem {
        bus_dmamap_t            mdm_map;
        bus_dma_segment_t       mdm_seg;
@@ -156,6 +187,19 @@ struct mfii_ccb {
 };
 SIMPLEQ_HEAD(mfii_ccb_list, mfii_ccb);
 
+struct mfii_pd_link {
+       u_int16_t               pd_id;
+       struct mfi_pd_details   pd_info;
+       u_int16_t               pd_handle;
+};
+
+struct mfii_pd_softc {
+       struct scsi_link        pd_link;
+       struct scsibus_softc    *pd_scsibus;
+       struct mfii_pd_link     *pd_links[MFI_MAX_PD];
+       uint8_t                 pd_timeout;
+};
+
 struct mfii_softc {
        struct device           sc_dev;
 
@@ -189,6 +233,7 @@ struct mfii_softc {
 
        struct scsi_link        sc_link;
        struct scsibus_softc    *sc_scsibus;
+       struct mfii_pd_softc    *sc_pd;
        struct scsi_iopool      sc_iopool;
 
        struct mfi_ctrl_info    sc_info;
@@ -222,6 +267,15 @@ struct scsi_adapter mfii_switch = {
        NULL  /* ioctl */
 };
 
+void           mfii_pd_scsi_cmd(struct scsi_xfer *);
+int            mfii_pd_scsi_probe(struct scsi_link *);
+
+struct scsi_adapter mfii_pd_switch = {
+       mfii_pd_scsi_cmd,
+       scsi_minphys,
+       mfii_pd_scsi_probe
+};
+
 #define DEVNAME(_sc)           ((_sc)->sc_dev.dv_xname)
 
 u_int32_t              mfii_read(struct mfii_softc *, bus_size_t);
@@ -239,6 +293,7 @@ void                        mfii_scrub_ccb(struct mfii_ccb 
*)
 int                    mfii_transition_firmware(struct mfii_softc *);
 int                    mfii_initialise_firmware(struct mfii_softc *);
 int                    mfii_get_info(struct mfii_softc *);
+int                    mfii_syspd(struct mfii_softc *);
 
 void                   mfii_start(struct mfii_softc *, struct mfii_ccb *);
 void                   mfii_done(struct mfii_softc *, struct mfii_ccb *);
@@ -264,6 +319,8 @@ int                 mfii_scsi_cmd_io(struct mfii_softc
                            struct scsi_xfer *);
 int                    mfii_scsi_cmd_cdb(struct mfii_softc *,
                            struct scsi_xfer *);
+int                    mfii_pd_scsi_cmd_cdb(struct mfii_softc *,
+                           struct scsi_xfer *);
 
 
 #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP)
@@ -388,6 +445,8 @@ mfii_attach(struct device *parent, struc
 
        config_found(&sc->sc_dev, &saa, scsiprint);
 
+       mfii_syspd(sc);
+
        /* enable interrupts */
        mfii_write(sc, MFI_OSTS, 0xffffffff);
        mfii_write(sc, MFI_OMSK, ~MFII_OSTS_INTR_VALID);
@@ -406,6 +465,92 @@ pci_unmap:
 }
 
 int
+mfii_syspd(struct mfii_softc *sc)
+{
+       struct scsibus_attach_args saa;
+       struct scsi_link *link;
+       struct mfii_ld_map *lm;
+       struct mfii_pd_link *pl;
+       struct mfi_pd_list *pd;
+       struct mfii_ccb *ccb;
+       u_int npds, i;
+       int rv;
+
+       sc->sc_pd = malloc(sizeof(*sc->sc_pd), M_DEVBUF, M_WAITOK|M_ZERO);
+       if (sc->sc_pd == NULL)
+               return (1);
+
+       lm = malloc(sizeof(*lm), M_TEMP, M_WAITOK|M_ZERO);
+       if (lm == NULL)
+               goto free_pdsc;
+
+       ccb = scsi_io_get(&sc->sc_iopool, 0);
+       rv = mfii_mgmt(sc, ccb, MR_DCMD_LD_MAP_GET_INFO, NULL,
+           lm, sizeof(*lm), SCSI_DATA_IN|SCSI_NOSLEEP);
+       scsi_io_put(&sc->sc_iopool, ccb);
+       if (rv != 0)
+               goto free_lm;
+
+       sc->sc_pd->pd_timeout = lm->mlm_pd_timeout;
+
+       pd = malloc(sizeof(*pd), M_TEMP, M_WAITOK|M_ZERO);
+       if (pd == NULL)
+               goto free_lm;
+
+       ccb = scsi_io_get(&sc->sc_iopool, 0);
+       rv = mfii_mgmt(sc, ccb, MR_DCMD_PD_GET_LIST, NULL,
+           pd, sizeof(*pd), SCSI_DATA_IN|SCSI_NOSLEEP);
+       scsi_io_put(&sc->sc_iopool, ccb);
+       if (rv != 0)
+               goto free_pd;
+
+       npds = letoh32(pd->mpl_no_pd);
+       for (i = 0; i < npds; i++) {
+               pl = malloc(sizeof(*pl), M_DEVBUF, M_WAITOK|M_ZERO);
+               if (pl == NULL)
+                       goto free_pl;
+
+               pl->pd_id = pd->mpl_address[i].mpa_pd_id;
+               pl->pd_handle = lm->mlm_dev_handle[i].mdh_cur_handle;
+               sc->sc_pd->pd_links[i] = pl;
+       }
+
+       free(pd, M_TEMP, 0);
+       free(lm, M_TEMP, 0);
+
+       link = &sc->sc_pd->pd_link;
+       link->adapter = &mfii_pd_switch;
+       link->adapter_softc = sc;
+       link->adapter_buswidth = MFI_MAX_PD;
+       link->adapter_target = -1;
+       link->openings = sc->sc_max_cmds - 1;
+       link->pool = &sc->sc_iopool;
+
+       bzero(&saa, sizeof(saa));
+       saa.saa_sc_link = link;
+
+       sc->sc_pd->pd_scsibus = (struct scsibus_softc *)
+           config_found(&sc->sc_dev, &saa, scsiprint);
+
+       return (0);
+free_pl:
+       for (i = 0; i < npds; i++) {
+               pl = sc->sc_pd->pd_links[i];
+               if (pl == NULL)
+                       break;
+
+               free(pl, M_DEVBUF, 0);
+       }
+free_pd:
+       free(pd, M_TEMP, 0);
+free_lm:
+       free(lm, M_TEMP, 0);
+free_pdsc:
+       free(sc->sc_pd, M_DEVBUF, 0);
+       return (1);
+}
+
+int
 mfii_detach(struct device *self, int flags)
 {
        struct mfii_softc *sc = (struct mfii_softc *)self;
@@ -1260,6 +1405,120 @@ mfii_scsi_cmd_cdb(struct mfii_softc *sc,
 
        ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
        ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
+
+       return (0);
+}
+
+void
+mfii_pd_scsi_cmd(struct scsi_xfer *xs)
+{
+       struct scsi_link *link = xs->sc_link;
+       struct mfii_softc *sc = link->adapter_softc;
+       struct mfii_ccb *ccb = xs->io;
+
+       mfii_scrub_ccb(ccb);
+       ccb->ccb_cookie = xs;
+       ccb->ccb_done = mfii_scsi_cmd_done;
+       ccb->ccb_data = xs->data;
+       ccb->ccb_len = xs->datalen;
+
+       if (mfii_pd_scsi_cmd_cdb(sc, xs) != 0)
+               goto stuffup;
+
+       xs->error = XS_NOERROR;
+       xs->resid = 0;
+
+       if (ISSET(xs->flags, SCSI_POLL)) {
+               if (mfii_poll(sc, ccb) != 0)
+                       goto stuffup;
+               return;
+       }
+
+       mfii_start(sc, ccb);
+       return;
+
+stuffup:
+       xs->error = XS_DRIVER_STUFFUP;
+       scsi_done(xs);
+}
+
+int
+mfii_pd_scsi_probe(struct scsi_link *link)
+{
+       struct mfii_ccb *ccb;
+       uint8_t mbox[MFI_MBOX_SIZE];
+       struct mfii_softc *sc = link->adapter_softc;
+       struct mfii_pd_link *pl = sc->sc_pd->pd_links[link->target];
+       int rv;
+
+       if (link->lun > 0)
+               return (0);
+
+       if (pl == NULL)
+               return (ENXIO);
+
+       memset(mbox, 0, sizeof(mbox));
+       memcpy(&mbox[0], &pl->pd_id, sizeof(pl->pd_id));
+
+       ccb = scsi_io_get(&sc->sc_iopool, 0);
+       rv = mfii_mgmt(sc, ccb, MR_DCMD_PD_GET_INFO, mbox, &pl->pd_info,
+           sizeof(pl->pd_info), SCSI_DATA_IN|SCSI_NOSLEEP);
+       scsi_io_put(&sc->sc_iopool, ccb);
+       if (rv != 0)
+               return (EIO);
+
+       if (letoh16(pl->pd_info.mpd_fw_state) != MFI_PD_SYSTEM)
+               return (ENXIO);
+
+       return (0);
+}
+
+int
+mfii_pd_scsi_cmd_cdb(struct mfii_softc *sc, struct scsi_xfer *xs)
+{
+       struct scsi_link *link = xs->sc_link;
+       struct mfii_ccb *ccb = xs->io;
+       struct mpii_msg_scsi_io *io = ccb->ccb_request;
+       struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
+
+       io->dev_handle = sc->sc_pd->pd_links[link->target]->pd_handle;
+       io->function = 0;
+       io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
+       io->sgl_flags = htole16(0x02); /* XXX */
+       io->sense_buffer_length = sizeof(xs->sense);
+       io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
+       io->data_length = htole32(xs->datalen);
+       io->io_flags = htole16(xs->cmdlen);
+       io->lun[0] = htobe16(link->lun);
+       switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
+       case SCSI_DATA_IN:
+               ccb->ccb_direction = MFII_DATA_IN;
+               io->direction = MPII_SCSIIO_DIR_READ;
+               break;
+       case SCSI_DATA_OUT:
+               ccb->ccb_direction = MFII_DATA_OUT;
+               io->direction = MPII_SCSIIO_DIR_WRITE;
+               break;
+       default:
+               ccb->ccb_direction = MFII_DATA_NONE;
+               io->direction = MPII_SCSIIO_DIR_NONE;
+               break;
+       }
+       bcopy(xs->cmd, io->cdb, xs->cmdlen);
+
+       ctx->virtual_disk_target_id = htole16(link->target);
+       ctx->raid_flags = MFII_RAID_CTX_IO_TYPE_SYSPD;
+       ctx->timeout_value = sc->sc_pd->pd_timeout;
+
+       if (mfii_load_ccb(sc, ccb, ctx + 1,
+           ISSET(xs->flags, SCSI_NOSLEEP)) != 0)
+               return (1);
+
+       ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap->dm_nsegs;
+
+       ccb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
+       ccb->ccb_req.smid = letoh16(ccb->ccb_smid);
+       ccb->ccb_req.dev_handle = sc->sc_pd->pd_links[link->target]->pd_handle;
 
        return (0);
 }

Reply via email to