diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2008-02-11 01:07:03 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2008-02-11 01:07:03 +0000 |
commit | f8582e34cc54670f4253c51444c979cdf2d3e539 (patch) | |
tree | d5055ac0af8e8ef03668fe6cb77b4c5d47dc175c /sys/dev/ic/mfi.c | |
parent | 39557fa39a36446149121d21a3f10223fe5a37fb (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.c | 165 |
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)); +} |