mfi_pci.c revision 1.26
1/* $OpenBSD: mfi_pci.c,v 1.26 2012/01/12 06:12:30 dlg Exp $ */ 2/* 3 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include "bio.h" 19 20#include <sys/param.h> 21#include <sys/systm.h> 22#include <sys/kernel.h> 23#include <sys/malloc.h> 24#include <sys/device.h> 25#include <sys/rwlock.h> 26 27#include <dev/pci/pcidevs.h> 28#include <dev/pci/pcivar.h> 29 30#include <machine/bus.h> 31 32#include <scsi/scsi_all.h> 33#include <scsi/scsi_disk.h> 34#include <scsi/scsiconf.h> 35 36#include <dev/ic/mfireg.h> 37#include <dev/ic/mfivar.h> 38 39#define MFI_BAR 0x10 40#define MFI_BAR_GEN2 0x14 41#define MFI_PCI_MEMSIZE 0x2000 /* 8k */ 42 43int mfi_pci_match(struct device *, void *, void *); 44void mfi_pci_attach(struct device *, struct device *, void *); 45 46struct cfattach mfi_pci_ca = { 47 sizeof(struct mfi_softc), mfi_pci_match, mfi_pci_attach 48}; 49 50struct mfi_pci_subtype { 51 pcireg_t st_id; 52 const char *st_string; 53}; 54 55static const struct mfi_pci_subtype mfi_1078_subtypes[] = { 56 { 0x10061000, "SAS 8888ELP" }, 57 { 0x100a1000, "SAS 8708ELP" }, 58 { 0x100f1000, "SAS 8708E" }, 59 { 0x10121000, "SAS 8704ELP" }, 60 { 0x10131000, "SAS 8708EM2" }, 61 { 0x10161000, "SAS 8880EM2" }, 62 { 0x1f0a1028, "Dell PERC 6/e" }, 63 { 0x1f0b1028, "Dell PERC 6/i" }, 64 { 0x1f0d1028, "Dell CERC 6/i" }, 65 { 0x1f0c1028, "Dell PERC 6/i integrated" }, 66 { 0x1f111028, "Dell CERC 6/i integrated" }, 67 { 0x0, "" } 68}; 69 70static const struct mfi_pci_subtype mfi_perc5_subtypes[] = { 71 { 0x1f011028, "Dell PERC 5/e" }, 72 { 0x1f021028, "Dell PERC 5/i" }, 73 { 0x0, "" } 74}; 75 76static const struct mfi_pci_subtype mfi_gen2_subtypes[] = { 77 { 0x1f151028, "Dell PERC H800 Adapter" }, 78 { 0x1f161028, "Dell PERC H700 Adapter" }, 79 { 0x1f171028, "Dell PERC H700 Integrated" }, 80 { 0x1f181028, "Dell PERC H700 Modular" }, 81 { 0x1f191028, "Dell PERC H700" }, 82 { 0x1f1a1028, "Dell PERC H800 Proto Adapter" }, 83 { 0x1f1b1028, "Dell PERC H800" }, 84 { 0x0, "" } 85}; 86 87static const 88struct mfi_pci_device { 89 pcireg_t mpd_vendor; 90 pcireg_t mpd_product; 91 enum mfi_iop mpd_iop; 92 const struct mfi_pci_subtype *mpd_subtype; 93} mfi_pci_devices[] = { 94 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_SAS, 95 MFI_IOP_XSCALE, NULL }, 96 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_VERDE_ZCR, 97 MFI_IOP_XSCALE, NULL }, 98 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078, 99 MFI_IOP_PPC, mfi_1078_subtypes }, 100 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078DE, 101 MFI_IOP_PPC, mfi_1078_subtypes }, 102 { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC5, 103 MFI_IOP_XSCALE, mfi_perc5_subtypes }, 104 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_1, 105 MFI_IOP_GEN2, mfi_gen2_subtypes }, 106 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_2, 107 MFI_IOP_GEN2, mfi_gen2_subtypes }, 108 { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2008_1, 109 MFI_IOP_SKINNY, NULL }, 110}; 111 112const struct mfi_pci_device *mfi_pci_find_device(struct pci_attach_args *); 113 114const struct mfi_pci_device * 115mfi_pci_find_device(struct pci_attach_args *pa) 116{ 117 const struct mfi_pci_device *mpd; 118 int i; 119 120 for (i = 0; i < nitems(mfi_pci_devices); i++) { 121 mpd = &mfi_pci_devices[i]; 122 123 if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) && 124 mpd->mpd_product == PCI_PRODUCT(pa->pa_id)) 125 return (mpd); 126 } 127 128 return (NULL); 129} 130 131int 132mfi_pci_match(struct device *parent, void *match, void *aux) 133{ 134 return ((mfi_pci_find_device(aux) != NULL) ? 1 : 0); 135} 136 137void 138mfi_pci_attach(struct device *parent, struct device *self, void *aux) 139{ 140 struct mfi_softc *sc = (struct mfi_softc *)self; 141 struct pci_attach_args *pa = aux; 142 const struct mfi_pci_device *mpd; 143 const struct mfi_pci_subtype *st; 144 const char *intrstr; 145 pci_intr_handle_t ih; 146 bus_size_t size; 147 pcireg_t reg; 148 int regbar; 149 const char *subtype = NULL; 150 char subid[32]; 151 152 mpd = mfi_pci_find_device(pa); 153 if (mpd == NULL) { 154 printf(": can't find matching pci device\n"); 155 return; 156 } 157 158 sc->sc_flags = mpd->mpd_iop; 159 160 if (mpd->mpd_iop == MFI_IOP_GEN2 || mpd->mpd_iop == MFI_IOP_SKINNY) 161 regbar = MFI_BAR_GEN2; 162 else 163 regbar = MFI_BAR; 164 165 reg = pci_mapreg_type(pa->pa_pc, pa->pa_tag, regbar); 166 if (pci_mapreg_map(pa, regbar, reg, 0, 167 &sc->sc_iot, &sc->sc_ioh, NULL, &size, MFI_PCI_MEMSIZE)) { 168 printf(": can't map controller pci space\n"); 169 return; 170 } 171 172 sc->sc_dmat = pa->pa_dmat; 173 174 if (pci_intr_map(pa, &ih) != 0) { 175 printf(": can't map interrupt\n"); 176 bus_space_unmap(sc->sc_iot, sc->sc_ioh, size); 177 return; 178 } 179 intrstr = pci_intr_string(pa->pa_pc, ih); 180 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, mfi_intr, sc, 181 sc->sc_dev.dv_xname); 182 if (!sc->sc_ih) { 183 printf(": can't establish interrupt"); 184 if (intrstr) 185 printf(" at %s", intrstr); 186 printf("\n"); 187 bus_space_unmap(sc->sc_iot, sc->sc_ioh, size); 188 return; 189 } 190 191 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 192 193 if (mpd->mpd_subtype != NULL) { 194 st = mpd->mpd_subtype; 195 while (st->st_id != 0x0) { 196 if (st->st_id == reg) { 197 subtype = st->st_string; 198 break; 199 } 200 st++; 201 } 202 } 203 if (subtype == NULL) { 204 snprintf(subid, sizeof(subid), "0x%08x", reg); 205 subtype = subid; 206 } 207 208 printf(": %s, %s\n", intrstr, subtype); 209 210 if (mfi_attach(sc, mpd->mpd_iop)) { 211 printf("%s: can't attach\n", DEVNAME(sc)); 212 pci_intr_disestablish(pa->pa_pc, sc->sc_ih); 213 sc->sc_ih = NULL; 214 bus_space_unmap(sc->sc_iot, sc->sc_ioh, size); 215 } 216} 217