This adds support for SAS3 (SAS3004, 3008, 3104) chips in mpii(4).
As far as we're concerned, these are the same as the supported SAS2
chips, just with a different sgl layout.  I've tested this on a Lenovo N2215:

mpii0 at pci1 dev 0 function 0 "Symbios Logic SAS3008" rev 0x02: msi
mpii0: N2215, firmware 11.125.0.0, MPI 2.5
scsibus1 at mpii0: 1024 targets
 ..
sd0 at scsibus1 targ 2 lun 0: <ATA, INTEL SSDSCKHB08, EM03> SCSI4 0/direct 
fixed naa.55cd2e404b768d50
sd0: 76319MB, 512 bytes/sector, 156301488 sectors, thin
sd1 at scsibus1 targ 3 lun 0: <ATA, INTEL SSDSCKHB08, EM03> SCSI4 0/direct 
fixed naa.55cd2e404b768eee
sd1: 76319MB, 512 bytes/sector, 156301488 sectors, thin
sd2 at scsibus1 targ 4 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct 
fixed naa.5000c5008528a0af
sd2: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd3 at scsibus1 targ 5 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct 
fixed naa.5000c50085a1199f
sd3: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd4 at scsibus1 targ 6 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct 
fixed naa.5000c50085a114c3
sd4: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd5 at scsibus1 targ 7 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct 
fixed naa.5000c5008549c5a7
sd5: 3815447MB, 512 bytes/sector, 7814037168 sectors

where it works well enough to check out src/sys and build a kernel.

also includes a bonus spelling correction in an error message.

ok?

Index: mpii.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/mpii.c,v
retrieving revision 1.104
diff -u -p -u -p -r1.104 mpii.c
--- mpii.c      17 Aug 2016 01:02:31 -0000      1.104
+++ mpii.c      13 Sep 2016 02:54:55 -0000
@@ -163,6 +163,7 @@ struct mpii_softc {
 
        int                     sc_flags;
 #define MPII_F_RAID            (1<<1)
+#define MPII_F_SAS3            (1<<2)
 
        struct scsibus_softc    *sc_scsibus;
 
@@ -306,6 +307,7 @@ void                mpii_wait_done(struct mpii_ccb *);
 void           mpii_init_queues(struct mpii_softc *);
 
 int            mpii_load_xs(struct mpii_ccb *);
+int            mpii_load_xs_sas3(struct mpii_ccb *);
 
 u_int32_t      mpii_read(struct mpii_softc *, bus_size_t);
 void           mpii_write(struct mpii_softc *, bus_size_t, u_int32_t);
@@ -420,7 +422,13 @@ static const struct pci_matchid mpii_dev
        { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS2208_6 },
        { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS2308_1 },
        { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS2308_2 },
-       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS2308_3 }
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS2308_3 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3004 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3008 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3108_1 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3108_2 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3108_3 },
+       { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_SAS3108_4 }
 };
 
 int
@@ -729,6 +737,63 @@ mpii_intr(void *arg)
 }
 
 int
+mpii_load_xs_sas3(struct mpii_ccb *ccb)
+{
+       struct mpii_softc       *sc = ccb->ccb_sc;
+       struct scsi_xfer        *xs = ccb->ccb_cookie;
+       struct mpii_msg_scsi_io *io = ccb->ccb_cmd;
+       struct mpii_ieee_sge    *csge, *nsge, *sge;
+       bus_dmamap_t            dmap = ccb->ccb_dmamap;
+       int                     i, error;
+
+       /* Request frame structure is described in the mpii_iocfacts */
+       nsge = (struct mpii_ieee_sge *)(io + 1);
+       csge = nsge + sc->sc_chain_sge;
+
+       /* zero length transfer still requires an SGE */
+       if (xs->datalen == 0) {
+               nsge->sg_flags = MPII_IEEE_SGE_END_OF_LIST;
+               return (0);
+       }
+
+       error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
+           (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+       if (error) {
+               printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
+               return (1);
+       }
+
+       for (i = 0; i < dmap->dm_nsegs; i++, nsge++) {
+               if (nsge == csge) {
+                       nsge++;
+                       /* offset to the chain sge from the beginning */
+                       io->chain_offset = ((caddr_t)csge - (caddr_t)io) / 4;
+                       csge->sg_flags = MPII_IEEE_SGE_CHAIN_ELEMENT |
+                           MPII_IEEE_SGE_ADDR_SYSTEM;
+                       /* address of the next sge */
+                       csge->sg_addr = htole64(ccb->ccb_cmd_dva +
+                           ((caddr_t)nsge - (caddr_t)io));
+                       csge->sg_len = htole32((dmap->dm_nsegs - i) *
+                           sizeof(*sge));
+               }
+
+               sge = nsge;
+               sge->sg_flags = MPII_IEEE_SGE_ADDR_SYSTEM;
+               sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
+               sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
+       }
+
+       /* terminate list */
+       sge->sg_flags |= MPII_IEEE_SGE_END_OF_LIST;
+
+       bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
+           (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
+           BUS_DMASYNC_PREWRITE);
+
+       return (0);
+}
+
+int
 mpii_load_xs(struct mpii_ccb *ccb)
 {
        struct mpii_softc       *sc = ccb->ccb_sc;
@@ -1126,6 +1191,7 @@ mpii_iocfacts(struct mpii_softc *sc)
        struct mpii_msg_iocfacts_request        ifq;
        struct mpii_msg_iocfacts_reply          ifp;
        int                                     irs;
+       int                                     sge_size;
        u_int                                   qdepth;
 
        DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
@@ -1160,6 +1226,10 @@ mpii_iocfacts(struct mpii_softc *sc)
        sc->sc_max_cmds = MIN(lemtoh16(&ifp.request_credit),
            MPII_REQUEST_CREDIT);
 
+       /* SAS3 controllers have different sgl layouts */
+       if (ifp.msg_version_maj == 2 && ifp.msg_version_min == 5)
+               SET(sc->sc_flags, MPII_F_SAS3);
+
        /*
         * The host driver must ensure that there is at least one
         * unused entry in the Reply Free Queue. One way to ensure
@@ -1227,9 +1297,15 @@ mpii_iocfacts(struct mpii_softc *sc)
                sc->sc_request_size += 16 - (sc->sc_request_size % 16);
        }
 
+       if (ISSET(sc->sc_flags, MPII_F_SAS3)) {
+               sge_size = sizeof(struct mpii_ieee_sge);
+       } else {
+               sge_size = sizeof(struct mpii_sge);
+       }
+
        /* offset to the chain sge */
        sc->sc_chain_sge = (irs - sizeof(struct mpii_msg_scsi_io)) /
-           sizeof(struct mpii_sge) - 1;
+           sge_size - 1;
 
        /*
         * A number of simple scatter-gather elements we can fit into the
@@ -1237,7 +1313,7 @@ mpii_iocfacts(struct mpii_softc *sc)
         */
        sc->sc_max_sgl = (sc->sc_request_size -
            sizeof(struct mpii_msg_scsi_io) - sizeof(struct scsi_sense_data)) /
-           sizeof(struct mpii_sge) - 1;
+           sge_size - 1;
 
        return (0);
 }
@@ -2704,11 +2780,12 @@ mpii_scsi_cmd(struct scsi_xfer *xs)
        struct mpii_ccb         *ccb = xs->io;
        struct mpii_msg_scsi_io *io;
        struct mpii_device      *dev;
+       int                      ret;
 
        DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd\n", DEVNAME(sc));
 
        if (xs->cmdlen > MPII_CDB_LEN) {
-               DNPRINTF(MPII_D_CMD, "%s: CBD too big %d\n",
+               DNPRINTF(MPII_D_CMD, "%s: CDB too big %d\n",
                    DEVNAME(sc), xs->cmdlen);
                memset(&xs->sense, 0, sizeof(xs->sense));
                xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
@@ -2766,7 +2843,12 @@ mpii_scsi_cmd(struct scsi_xfer *xs)
        htolem32(&io->sense_buffer_low_address, ccb->ccb_cmd_dva +
            sc->sc_request_size - sizeof(struct scsi_sense_data));
 
-       if (mpii_load_xs(ccb) != 0) {
+       if (ISSET(sc->sc_flags, MPII_F_SAS3))
+               ret = mpii_load_xs_sas3(ccb);
+       else
+               ret = mpii_load_xs(ccb);
+
+       if (ret != 0) {
                xs->error = XS_DRIVER_STUFFUP;
                goto done;
        }
Index: mpiireg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/mpiireg.h,v
retrieving revision 1.9
diff -u -p -u -p -r1.9 mpiireg.h
--- mpiireg.h   27 Mar 2014 12:19:55 -0000      1.9
+++ mpiireg.h   13 Sep 2016 02:54:55 -0000
@@ -128,6 +128,26 @@ struct mpii_sge {
        u_int32_t               sg_addr_hi;
 } __packed __aligned(4);
 
+/*
+ * SAS3 (IEEE) Scatter Gather Lists
+ */
+
+#define MPII_IEEE_SGE_ADDR_MASK                (0x03)
+#define MPII_IEEE_SGE_ADDR_SYSTEM      (0x00)
+#define MPII_IEEE_SGE_ADDR_IOCDDR      (0x01)
+#define MPII_IEEE_SGE_ADDR_IOCPLB      (0x02)
+#define MPII_IEEE_SGE_ADDR_IOCPLBNTA   (0x03)
+#define MPII_IEEE_SGE_END_OF_LIST      (0x40)
+#define MPII_IEEE_SGE_CHAIN_ELEMENT    (0x80)
+
+struct mpii_ieee_sge {
+       u_int64_t               sg_addr;
+       u_int32_t               sg_len;
+       u_int16_t               _reserved;
+       u_int8_t                sg_next_chain_offset;
+       u_int8_t                sg_flags;
+} __packed __aligned(4);
+
 struct mpii_fw_tce {
        u_int8_t                reserved1;
        u_int8_t                context_size;
Index: pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1804
diff -u -p -u -p -r1.1804 pcidevs
--- pcidevs     3 Sep 2016 16:05:22 -0000       1.1804
+++ pcidevs     13 Sep 2016 02:54:55 -0000
@@ -5482,6 +5482,12 @@ product SYMBIOS SAS2208_6        0x0085  SAS2208
 product SYMBIOS SAS2308_1      0x0086  SAS2308
 product SYMBIOS SAS2308_2      0x0087  SAS2308
 product SYMBIOS 875J           0x008f  53c875J
+product SYMBIOS SAS3108_1      0x0090  SAS3108
+product SYMBIOS SAS3108_2      0x0091  SAS3108
+product SYMBIOS SAS3108_3      0x0094  SAS3108
+product SYMBIOS SAS3108_4      0x0095  SAS3108
+product SYMBIOS SAS3004                0x0096  SAS3004
+product SYMBIOS SAS3008                0x0097  SAS3008
 product SYMBIOS MEGARAID_320   0x0407  MegaRAID 320
 product SYMBIOS MEGARAID_3202E 0x0408  MegaRAID 320-2E
 product SYMBIOS MEGARAID_SATA  0x0409  MegaRAID SATA 4x/8x

Reply via email to