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 | |
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@
-rw-r--r-- | sys/dev/ic/mfi.c | 165 | ||||
-rw-r--r-- | sys/dev/ic/mfireg.h | 5 | ||||
-rw-r--r-- | sys/dev/ic/mfivar.h | 18 | ||||
-rw-r--r-- | sys/dev/pci/mfi_pci.c | 95 |
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; |