summaryrefslogtreecommitdiff
path: root/sys/dev/ic/mfi.c
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 /sys/dev/ic/mfi.c
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@
Diffstat (limited to 'sys/dev/ic/mfi.c')
-rw-r--r--sys/dev/ic/mfi.c165
1 files changed, 127 insertions, 38 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));
+}