summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2008-02-11 01:07:03 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2008-02-11 01:07:03 +0000
commitf8582e34cc54670f4253c51444c979cdf2d3e539 (patch)
treed5055ac0af8e8ef03668fe6cb77b4c5d47dc175c
parent39557fa39a36446149121d21a3f10223fe5a37fb (diff)
add support for the mfi controllers with the ppc iops, aka, LSI SAS1078 or
Dell PERC6. committed off a machine booting and rooting off a perc6. tested on a perc5 by marco@ ok marco@
-rw-r--r--sys/dev/ic/mfi.c165
-rw-r--r--sys/dev/ic/mfireg.h5
-rw-r--r--sys/dev/ic/mfivar.h18
-rw-r--r--sys/dev/pci/mfi_pci.c95
4 files changed, 175 insertions, 108 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index c3a68ca949a..b207ae8d09d 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.78 2008/01/26 08:57:31 brad Exp $ */
+/* $OpenBSD: mfi.c,v 1.79 2008/02/11 01:07:02 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -83,7 +83,6 @@ int mfi_get_info(struct mfi_softc *);
uint32_t mfi_read(struct mfi_softc *, bus_size_t);
void mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
int mfi_poll(struct mfi_ccb *);
-int mfi_dispatch_cmd(struct mfi_ccb *);
int mfi_create_sgl(struct mfi_ccb *, int);
/* commands */
@@ -110,6 +109,35 @@ void mfi_refresh_sensors(void *);
#endif /* SMALL_KERNEL */
#endif /* NBIO > 0 */
+u_int32_t mfi_xscale_fw_state(struct mfi_softc *sc);
+void mfi_xscale_intr_ena(struct mfi_softc *sc);
+int mfi_xscale_intr(struct mfi_softc *sc);
+void mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
+
+static const struct mfi_iop_ops mfi_iop_xscale = {
+ mfi_xscale_fw_state,
+ mfi_xscale_intr_ena,
+ mfi_xscale_intr,
+ mfi_xscale_post
+};
+
+u_int32_t mfi_ppc_fw_state(struct mfi_softc *sc);
+void mfi_ppc_intr_ena(struct mfi_softc *sc);
+int mfi_ppc_intr(struct mfi_softc *sc);
+void mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
+
+static const struct mfi_iop_ops mfi_iop_ppc = {
+ mfi_ppc_fw_state,
+ mfi_ppc_intr_ena,
+ mfi_ppc_intr,
+ mfi_ppc_post
+};
+
+#define mfi_fw_state(_s) ((_s)->sc_iop->mio_fw_state(_s))
+#define mfi_intr_enable(_s) ((_s)->sc_iop->mio_intr_ena(_s))
+#define mfi_my_intr(_s) ((_s)->sc_iop->mio_intr(_s))
+#define mfi_post(_s, _c) ((_s)->sc_iop->mio_post((_s), (_c)))
+
struct mfi_ccb *
mfi_get_ccb(struct mfi_softc *sc)
{
@@ -307,7 +335,7 @@ mfi_transition_firmware(struct mfi_softc *sc)
int32_t fw_state, cur_state;
int max_wait, i;
- fw_state = mfi_read(sc, MFI_OMSG0) & MFI_STATE_MASK;
+ fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc),
fw_state);
@@ -344,7 +372,7 @@ mfi_transition_firmware(struct mfi_softc *sc)
return (1);
}
for (i = 0; i < (max_wait * 10); i++) {
- fw_state = mfi_read(sc, MFI_OMSG0) & MFI_STATE_MASK;
+ fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
if (fw_state == cur_state)
DELAY(100000);
else
@@ -574,12 +602,23 @@ mfiminphys(struct buf *bp)
}
int
-mfi_attach(struct mfi_softc *sc)
+mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
{
struct scsibus_attach_args saa;
uint32_t status, frames;
int i;
+ switch (iop) {
+ case MFI_IOP_XSCALE:
+ sc->sc_iop = &mfi_iop_xscale;
+ break;
+ case MFI_IOP_PPC:
+ sc->sc_iop = &mfi_iop_ppc;
+ break;
+ default:
+ panic("%s: unknown iop %d", DEVNAME(sc), iop);
+ }
+
DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc));
if (mfi_transition_firmware(sc))
@@ -589,7 +628,7 @@ mfi_attach(struct mfi_softc *sc)
rw_init(&sc->sc_lock, "mfi_lock");
- status = mfi_read(sc, MFI_OMSG0);
+ status = mfi_fw_state(sc);
sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n",
@@ -674,7 +713,7 @@ mfi_attach(struct mfi_softc *sc)
config_found(&sc->sc_dev, &saa, scsiprint);
/* enable interrupts */
- mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
+ mfi_intr_enable(sc);
#if NBIO > 0
if (bio_register(&sc->sc_dev, mfi_ioctl) != 0)
@@ -700,18 +739,6 @@ nopcq:
}
int
-mfi_dispatch_cmd(struct mfi_ccb *ccb)
-{
- DNPRINTF(MFI_D_CMD, "%s: mfi_dispatch_cmd\n",
- DEVNAME(ccb->ccb_sc));
-
- mfi_write(ccb->ccb_sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
- ccb->ccb_extra_frames);
-
- return(0);
-}
-
-int
mfi_poll(struct mfi_ccb *ccb)
{
struct mfi_softc *sc = ccb->ccb_sc;
@@ -724,7 +751,7 @@ mfi_poll(struct mfi_ccb *ccb)
hdr->mfh_cmd_status = 0xff;
hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
- mfi_dispatch_cmd(ccb);
+ mfi_post(sc, ccb);
while (hdr->mfh_cmd_status == 0xff) {
delay(1000);
@@ -756,21 +783,18 @@ mfi_intr(void *arg)
struct mfi_softc *sc = arg;
struct mfi_prod_cons *pcq;
struct mfi_ccb *ccb;
- uint32_t status, producer, consumer, ctx;
+ uint32_t producer, consumer, ctx;
int claimed = 0;
- status = mfi_read(sc, MFI_OSTS);
- if ((status & MFI_OSTS_INTR_VALID) == 0)
- return (claimed);
- /* write status back to acknowledge interrupt */
- mfi_write(sc, MFI_OSTS, status);
-
- DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
+ if (!mfi_my_intr(sc))
+ return (0);
pcq = MFIMEM_KVA(sc->sc_pcq);
producer = pcq->mpc_producer;
consumer = pcq->mpc_consumer;
+ DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
+
while (consumer != producer) {
DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n",
DEVNAME(sc), producer, consumer);
@@ -1025,26 +1049,22 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
/* XXX check for sense in ccb->ccb_sense? */
printf("%s: mfi_scsi_cmd poll failed\n",
DEVNAME(sc));
- mfi_put_ccb(ccb);
bzero(&xs->sense, sizeof(xs->sense));
xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
xs->sense.flags = SKEY_ILLEGAL_REQUEST;
xs->sense.add_sense_code = 0x20; /* invalid opcode */
xs->error = XS_SENSE;
- xs->flags |= ITSDONE;
- s = splbio();
- scsi_done(xs);
- splx(s);
- return (COMPLETE);
}
- DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd poll complete %d\n",
- DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs);
mfi_put_ccb(ccb);
+ xs->flags |= ITSDONE;
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
return (COMPLETE);
}
- mfi_dispatch_cmd(ccb);
+ mfi_post(sc, ccb);
DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd queued %d\n", DEVNAME(sc),
ccb->ccb_dmamap->dm_nsegs);
@@ -1167,7 +1187,7 @@ mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
if (mfi_poll(ccb))
goto done;
} else {
- mfi_dispatch_cmd(ccb);
+ mfi_post(sc, ccb);
DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt sleeping\n", DEVNAME(sc));
while (ccb->ccb_state != MFI_CCB_DONE)
@@ -1882,3 +1902,72 @@ mfi_refresh_sensors(void *arg)
}
#endif /* SMALL_KERNEL */
#endif /* NBIO > 0 */
+
+u_int32_t
+mfi_xscale_fw_state(struct mfi_softc *sc)
+{
+ return (mfi_read(sc, MFI_OMSG0));
+}
+
+void
+mfi_xscale_intr_ena(struct mfi_softc *sc)
+{
+ mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
+}
+
+int
+mfi_xscale_intr(struct mfi_softc *sc)
+{
+ u_int32_t status;
+
+ status = mfi_read(sc, MFI_OSTS);
+ if (!ISSET(status, MFI_OSTS_INTR_VALID))
+ return (0);
+
+ /* write status back to acknowledge interrupt */
+ mfi_write(sc, MFI_OSTS, status);
+
+ return (1);
+}
+
+void
+mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
+{
+ mfi_write(sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
+ ccb->ccb_extra_frames);
+}
+
+u_int32_t
+mfi_ppc_fw_state(struct mfi_softc *sc)
+{
+ return (mfi_read(sc, MFI_OSP));
+}
+
+void
+mfi_ppc_intr_ena(struct mfi_softc *sc)
+{
+ mfi_write(sc, MFI_ODC, 0xffffffff);
+ mfi_write(sc, MFI_OMSK, ~0x80000004);
+}
+
+int
+mfi_ppc_intr(struct mfi_softc *sc)
+{
+ u_int32_t status;
+
+ status = mfi_read(sc, MFI_OSTS);
+ if (!ISSET(status, MFI_OSTS_PPC_INTR_VALID))
+ return (0);
+
+ /* write status back to acknowledge interrupt */
+ mfi_write(sc, MFI_ODC, status);
+
+ return (1);
+}
+
+void
+mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
+{
+ mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
+ (ccb->ccb_extra_frames << 1));
+}
diff --git a/sys/dev/ic/mfireg.h b/sys/dev/ic/mfireg.h
index d5654783263..54248bcadac 100644
--- a/sys/dev/ic/mfireg.h
+++ b/sys/dev/ic/mfireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfireg.h,v 1.24 2006/06/19 19:05:45 marco Exp $ */
+/* $OpenBSD: mfireg.h,v 1.25 2008/02/11 01:07:02 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -23,6 +23,7 @@
#define MFI_FRAME_SIZE 64
#define MFI_SENSE_SIZE 128
#define MFI_OSTS_INTR_VALID 0x00000002 /* valid interrupt */
+#define MFI_OSTS_PPC_INTR_VALID 0x80000000
#define MFI_INVALID_CTX 0xffffffff
#define MFI_ENABLE_INTR 0x01
#define MFI_MAXFER MAXPHYS /* XXX bogus */
@@ -40,6 +41,8 @@
#define MFI_OMSK 0x34 /* outbound inter mask */
#define MFI_IQP 0x40 /* inbound queue port */
#define MFI_OQP 0x44 /* outbound queue port */
+#define MFI_ODC 0xa0 /* outbound doorbell clr */
+#define MFI_OSP 0xb0 /* outbound scratch pad */
/* * firmware states */
#define MFI_STATE_MASK 0xf0000000
diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h
index de88877a4fc..b1aa37c4dfe 100644
--- a/sys/dev/ic/mfivar.h
+++ b/sys/dev/ic/mfivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfivar.h,v 1.30 2007/03/22 16:55:31 deraadt Exp $ */
+/* $OpenBSD: mfivar.h,v 1.31 2008/02/11 01:07:02 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -94,11 +94,25 @@ struct mfi_ccb {
TAILQ_HEAD(mfi_ccb_list, mfi_ccb);
+enum mfi_iop {
+ MFI_IOP_XSCALE,
+ MFI_IOP_PPC
+};
+
+struct mfi_iop_ops {
+ u_int32_t (*mio_fw_state)(struct mfi_softc *);
+ void (*mio_intr_ena)(struct mfi_softc *);
+ int (*mio_intr)(struct mfi_softc *);
+ void (*mio_post)(struct mfi_softc *, struct mfi_ccb *);
+};
+
struct mfi_softc {
struct device sc_dev;
void *sc_ih;
struct scsi_link sc_link;
+ const struct mfi_iop_ops *sc_iop;
+
u_int32_t sc_flags;
bus_space_tag_t sc_iot;
@@ -148,5 +162,5 @@ struct mfi_softc {
struct ksensordev sc_sensordev;
};
-int mfi_attach(struct mfi_softc *sc);
+int mfi_attach(struct mfi_softc *sc, enum mfi_iop);
int mfi_intr(void *);
diff --git a/sys/dev/pci/mfi_pci.c b/sys/dev/pci/mfi_pci.c
index 0ff6daa3409..cc5125efb6a 100644
--- a/sys/dev/pci/mfi_pci.c
+++ b/sys/dev/pci/mfi_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi_pci.c,v 1.14 2008/01/26 05:43:03 dlg Exp $ */
+/* $OpenBSD: mfi_pci.c,v 1.15 2008/02/11 01:07:02 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -37,7 +37,6 @@
#define MFI_BAR 0x10
#define MFI_PCI_MEMSIZE 0x2000 /* 8k */
-int mfi_pci_find_device(void *);
int mfi_pci_match(struct device *, void *, void *);
void mfi_pci_attach(struct device *, struct device *, void *);
@@ -49,75 +48,44 @@ static const
struct mfi_pci_device {
pcireg_t mpd_vendor;
pcireg_t mpd_product;
- pcireg_t mpd_subvendor;
- pcireg_t mpd_subproduct;
- char *mpd_model;
- uint32_t mpd_flags;
+ enum mfi_iop mpd_iop;
} mfi_pci_devices[] = {
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_SAS,
- 0, 0, "", 0 },
+ MFI_IOP_XSCALE },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_VERDE_ZCR,
- 0, 0, "", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x1006, "LSI 8888elp", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x100a, "LSI 8708elp", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x100f, "LSI 8708E", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x1012, "LSI 8704ELP", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x1013, "LSI 8708em2", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 ,
- PCI_VENDOR_SYMBIOS, 0x1016, "LSI 8880em2", 0 },
+ MFI_IOP_XSCALE },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078,
+ MFI_IOP_PPC },
{ PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC5,
- PCI_VENDOR_DELL, 0x1f01, "Dell PERC 5/e", 0 },
- { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC5,
- PCI_VENDOR_DELL, 0x1f02, "Dell PERC 5/i", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_DELL_PERC6,
- PCI_VENDOR_DELL, 0x1f0a, "Dell PERC 6/e", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_DELL_PERC6,
- PCI_VENDOR_DELL, 0x1f0b, "Dell PERC 6/i", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_DELL_PERC6,
- PCI_VENDOR_DELL, 0x1f0d, "Dell CERC 6/i", 0 },
+ MFI_IOP_XSCALE },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_DELL_PERC6,
- PCI_VENDOR_DELL, 0x1f0c, "Dell PERC 6/i integrated", 0 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_DELL_PERC6,
- PCI_VENDOR_DELL, 0x1f11, "Dell CERC 6/i integrated", 0 },
- { 0 }
+ MFI_IOP_PPC }
};
-int
-mfi_pci_find_device(void *aux) {
- struct pci_attach_args *pa = aux;
- int i;
-
- for (i = 0; mfi_pci_devices[i].mpd_vendor; i++) {
- if (mfi_pci_devices[i].mpd_vendor == PCI_VENDOR(pa->pa_id) &&
- mfi_pci_devices[i].mpd_product == PCI_PRODUCT(pa->pa_id)) {
- DNPRINTF(MFI_D_MISC, "mfi_pci_find_device: %i\n", i);
- return (i);
- }
+#define sizeofa(_a) (sizeof(_a) / sizeof((_a)[0]))
+const struct mfi_pci_device *mfi_pci_find_device(struct pci_attach_args *);
+
+const struct mfi_pci_device *
+mfi_pci_find_device(struct pci_attach_args *pa)
+{
+ const struct mfi_pci_device *mpd;
+ int i;
+
+ for (i = 0; i < sizeofa(mfi_pci_devices); i++) {
+ mpd = &mfi_pci_devices[i];
+
+ if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
+ mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
+ return (mpd);
}
- return (-1);
+ return (NULL);
}
int
mfi_pci_match(struct device *parent, void *match, void *aux)
{
- int i;
-
- if ((i = mfi_pci_find_device(aux)) != -1) {
- DNPRINTF(MFI_D_MISC,
- "mfi_pci_match: vendor: %04x product: %04x\n",
- mfi_pci_devices[i].mpd_vendor,
- mfi_pci_devices[i].mpd_product);
-
- return (1);
- }
-
- return (0);
+ return ((mfi_pci_find_device(aux) != NULL) ? 1 : 0);
}
void
@@ -125,22 +93,15 @@ mfi_pci_attach(struct device *parent, struct device *self, void *aux)
{
struct mfi_softc *sc = (struct mfi_softc *)self;
struct pci_attach_args *pa = aux;
+ const struct mfi_pci_device *mpd;
const char *intrstr;
pci_intr_handle_t ih;
bus_size_t size;
pcireg_t csr;
- uint32_t subsysid, i;
- subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
- for (i = 0; mfi_pci_devices[i].mpd_vendor; i++)
- if (mfi_pci_devices[i].mpd_subvendor == PCI_VENDOR(subsysid) &&
- mfi_pci_devices[i].mpd_subproduct == PCI_PRODUCT(subsysid)){
- printf(", %s", mfi_pci_devices[i].mpd_model);
- break;
- }
+ mpd = mfi_pci_find_device(pa);
csr = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MFI_BAR);
- csr |= PCI_MAPREG_MEM_TYPE_32BIT;
if (pci_mapreg_map(pa, MFI_BAR, csr, 0,
&sc->sc_iot, &sc->sc_ioh, NULL, &size, MFI_PCI_MEMSIZE)) {
printf(": can't map controller pci space\n");
@@ -168,7 +129,7 @@ mfi_pci_attach(struct device *parent, struct device *self, void *aux)
printf(": %s\n", intrstr);
- if (mfi_attach(sc)) {
+ if (mfi_attach(sc, mpd->mpd_iop)) {
printf("%s: can't attach\n", DEVNAME(sc));
pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
sc->sc_ih = NULL;