1 /* $OpenBSD: ciss_pci.c,v 1.21 2020/01/05 01:07:58 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 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 26 #include <dev/pci/pcidevs.h> 27 #include <dev/pci/pcivar.h> 28 29 #include <machine/bus.h> 30 31 #include <scsi/scsi_all.h> 32 #include <scsi/scsi_disk.h> 33 #include <scsi/scsiconf.h> 34 35 #include <dev/ic/cissreg.h> 36 #include <dev/ic/cissvar.h> 37 38 #define CISS_BAR 0x10 39 40 int ciss_pci_match(struct device *, void *, void *); 41 void ciss_pci_attach(struct device *, struct device *, void *); 42 int ciss_activate(struct device *, int); 43 44 struct cfattach ciss_pci_ca = { 45 sizeof(struct ciss_softc), ciss_pci_match, ciss_pci_attach, 46 NULL, ciss_activate 47 }; 48 49 const struct pci_matchid ciss_pci_devices[] = { 50 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA532 }, 51 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA5300 }, 52 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA5300_2 }, 53 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA5312 }, 54 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA5I }, 55 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA5I_2 }, 56 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA6I }, 57 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA641 }, 58 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA642 }, 59 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA6400 }, 60 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA6400EM }, 61 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA6422 }, 62 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_CSA64XX }, 63 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE200 }, 64 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE200I_1 }, 65 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE200I_2 }, 66 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE200I_3 }, 67 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE200I_4 }, 68 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE500_1 }, 69 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAE500_2 }, 70 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAH240 }, 71 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAH240AR }, 72 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAH240TR }, 73 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAH241 }, 74 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAH244BR }, 75 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP212 }, 76 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP220I }, 77 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP222 }, 78 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP224BR }, 79 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP230I }, 80 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP240TR }, 81 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP246BR }, 82 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP410 }, 83 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP410I }, 84 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP411 }, 85 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP420 }, 86 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP420I }, 87 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP421 }, 88 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP430 }, 89 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP430I }, 90 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP431 }, 91 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP440 }, 92 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP440AR }, 93 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP441 }, 94 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP530 }, 95 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP531 }, 96 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP542T }, 97 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP600 }, 98 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP700M }, 99 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP711M }, 100 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP712M }, 101 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP721M }, 102 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP731M }, 103 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP741M }, 104 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP800 }, 105 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP812 }, 106 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP822 }, 107 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP830 }, 108 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP830I }, 109 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP840 }, 110 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAP841 }, 111 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSAV100 }, 112 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_1 }, 113 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_2 }, 114 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_3 }, 115 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_4 }, 116 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_5 }, 117 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_6 }, 118 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_7 }, 119 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_8 }, 120 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_9 }, 121 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_10 }, 122 { PCI_VENDOR_HP, PCI_PRODUCT_HP_HPSA_11 } 123 }; 124 125 int 126 ciss_pci_match(struct device *parent, void *match, void *aux) 127 { 128 struct pci_attach_args *pa = aux; 129 130 return pci_matchbyid(pa, ciss_pci_devices, nitems(ciss_pci_devices)); 131 } 132 133 void 134 ciss_pci_attach(struct device *parent, struct device *self, void *aux) 135 { 136 struct ciss_softc *sc = (struct ciss_softc *)self; 137 struct pci_attach_args *pa = aux; 138 bus_size_t size, cfgsz; 139 pci_intr_handle_t ih; 140 const char *intrstr; 141 int cfg_bar, memtype; 142 pcireg_t reg; 143 144 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, CISS_BAR); 145 if (pci_mapreg_map(pa, CISS_BAR, memtype, 0, 146 &sc->iot, &sc->ioh, NULL, &size, 0)) { 147 printf(": can't map controller mem space\n"); 148 return; 149 } 150 sc->dmat = pa->pa_dmat; 151 152 sc->iem = CISS_READYENA; 153 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 154 if (PCI_VENDOR(reg) == PCI_VENDOR_COMPAQ && 155 (PCI_PRODUCT(reg) == PCI_PRODUCT_COMPAQ_CSA5I || 156 PCI_PRODUCT(reg) == PCI_PRODUCT_COMPAQ_CSA532 || 157 PCI_PRODUCT(reg) == PCI_PRODUCT_COMPAQ_CSA5312)) 158 sc->iem = CISS_READYENAB; 159 160 cfg_bar = bus_space_read_2(sc->iot, sc->ioh, CISS_CFG_BAR); 161 sc->cfgoff = bus_space_read_4(sc->iot, sc->ioh, CISS_CFG_OFF); 162 if (cfg_bar != CISS_BAR) { 163 if (pci_mapreg_map(pa, cfg_bar, PCI_MAPREG_TYPE_MEM, 0, 164 NULL, &sc->cfg_ioh, NULL, &cfgsz, 0)) { 165 printf(": can't map controller config space\n"); 166 bus_space_unmap(sc->iot, sc->ioh, size); 167 return; 168 } 169 } else { 170 sc->cfg_ioh = sc->ioh; 171 cfgsz = size; 172 } 173 174 if (sc->cfgoff + sizeof(struct ciss_config) > cfgsz) { 175 printf(": unfit config space\n"); 176 bus_space_unmap(sc->iot, sc->ioh, size); 177 if (cfg_bar != CISS_BAR) 178 bus_space_unmap(sc->iot, sc->cfg_ioh, cfgsz); 179 return; 180 } 181 182 /* disable interrupts until ready */ 183 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR, 184 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) | sc->iem); 185 186 if (pci_intr_map(pa, &ih)) { 187 printf(": can't map interrupt\n"); 188 bus_space_unmap(sc->iot, sc->ioh, size); 189 if (cfg_bar != CISS_BAR) 190 bus_space_unmap(sc->iot, sc->cfg_ioh, cfgsz); 191 return; 192 } 193 intrstr = pci_intr_string(pa->pa_pc, ih); 194 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ciss_intr, sc, 195 sc->sc_dev.dv_xname); 196 if (!sc->sc_ih) { 197 printf(": can't establish interrupt"); 198 if (intrstr) 199 printf(" at %s", intrstr); 200 printf("\n"); 201 bus_space_unmap(sc->iot, sc->ioh, size); 202 if (cfg_bar != CISS_BAR) 203 bus_space_unmap(sc->iot, sc->cfg_ioh, cfgsz); 204 return; 205 } 206 207 printf(": %s\n%s", intrstr, sc->sc_dev.dv_xname); 208 209 if (ciss_attach(sc)) { 210 pci_intr_disestablish(pa->pa_pc, sc->sc_ih); 211 sc->sc_ih = NULL; 212 bus_space_unmap(sc->iot, sc->ioh, size); 213 if (cfg_bar != CISS_BAR) 214 bus_space_unmap(sc->iot, sc->cfg_ioh, cfgsz); 215 return; 216 } 217 218 /* enable interrupts now */ 219 bus_space_write_4(sc->iot, sc->ioh, CISS_IMR, 220 bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) & ~sc->iem); 221 } 222 223 int 224 ciss_activate(struct device *self, int act) 225 { 226 int ret = 0; 227 228 ret = config_activate_children(self, act); 229 230 switch (act) { 231 case DVACT_POWERDOWN: 232 ciss_shutdown(self); 233 break; 234 } 235 236 return (ret); 237 } 238