1 /* $OpenBSD: qlw_pci.c,v 1.14 2024/09/04 07:54:52 mglocker Exp $ */ 2 3 /* 4 * Copyright (c) 2011 David Gwynne <dlg@openbsd.org> 5 * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org> 6 * Copyright (c) 2014 Mark Kettenis <kettenis@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/device.h> 24 25 #include <machine/bus.h> 26 27 #include <dev/pci/pcireg.h> 28 #include <dev/pci/pcivar.h> 29 #include <dev/pci/pcidevs.h> 30 31 #ifdef __sparc64__ 32 #include <dev/ofw/openfirm.h> 33 #endif 34 35 #include <scsi/scsi_all.h> 36 #include <scsi/scsiconf.h> 37 38 #include <dev/ic/qlwreg.h> 39 #include <dev/ic/qlwvar.h> 40 41 #ifndef ISP_NOFIRMWARE 42 #include <dev/microcode/isp/asm_1040.h> 43 #include <dev/microcode/isp/asm_1080.h> 44 #include <dev/microcode/isp/asm_12160.h> 45 #endif 46 47 #define QLW_PCI_MEM_BAR 0x14 48 #define QLW_PCI_IO_BAR 0x10 49 50 int qlw_pci_match(struct device *, void *, void *); 51 void qlw_pci_attach(struct device *, struct device *, void *); 52 int qlw_pci_detach(struct device *, int); 53 54 struct qlw_pci_softc { 55 struct qlw_softc psc_qlw; 56 57 pci_chipset_tag_t psc_pc; 58 pcitag_t psc_tag; 59 60 void *psc_ih; 61 }; 62 63 const struct cfattach qlw_pci_ca = { 64 sizeof(struct qlw_pci_softc), 65 qlw_pci_match, 66 qlw_pci_attach 67 }; 68 69 static const struct pci_matchid qlw_devices[] = { 70 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 }, 71 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 }, 72 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 }, 73 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 }, 74 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 }, 75 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 }, 76 }; 77 78 int 79 qlw_pci_match(struct device *parent, void *match, void *aux) 80 { 81 struct pci_attach_args *pa = aux; 82 83 /* Silly AMI MegaRAID exposes its ISP12160 to us. */ 84 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_QLOGIC_ISP12160) { 85 pcireg_t subid; 86 87 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBVEND_0); 88 if (PCI_VENDOR(subid) == PCI_VENDOR_AMI) 89 return (0); 90 } 91 92 return (pci_matchbyid(aux, qlw_devices, nitems(qlw_devices)) * 2); 93 } 94 95 void 96 qlw_pci_attach(struct device *parent, struct device *self, void *aux) 97 { 98 struct qlw_pci_softc *psc = (void *)self; 99 struct qlw_softc *sc = &psc->psc_qlw; 100 struct pci_attach_args *pa = aux; 101 pci_intr_handle_t ih; 102 const char *intrstr; 103 u_int32_t pcictl; 104 #ifdef __sparc64__ 105 int node, initiator; 106 #endif 107 108 pcireg_t bars[] = { QLW_PCI_MEM_BAR, QLW_PCI_IO_BAR }; 109 pcireg_t memtype; 110 int r; 111 112 psc->psc_pc = pa->pa_pc; 113 psc->psc_tag = pa->pa_tag; 114 psc->psc_ih = NULL; 115 sc->sc_dmat = pa->pa_dmat; 116 sc->sc_ios = 0; 117 118 for (r = 0; r < nitems(bars); r++) { 119 memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, bars[r]); 120 if (pci_mapreg_map(pa, bars[r], memtype, 0, 121 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, 0) == 0) 122 break; 123 124 sc->sc_ios = 0; 125 } 126 if (sc->sc_ios == 0) { 127 printf(": unable to map registers\n"); 128 return; 129 } 130 131 if (pci_intr_map(pa, &ih)) { 132 printf(": unable to map interrupt\n"); 133 goto unmap; 134 } 135 intrstr = pci_intr_string(psc->psc_pc, ih); 136 psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO, 137 qlw_intr, sc, DEVNAME(sc)); 138 if (psc->psc_ih == NULL) { 139 printf(": unable to establish interrupt"); 140 if (intrstr != NULL) 141 printf(" at %s", intrstr); 142 printf("\n"); 143 goto deintr; 144 } 145 146 printf(": %s\n", intrstr); 147 148 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 149 pcictl |= PCI_COMMAND_INVALIDATE_ENABLE | 150 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 151 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pcictl); 152 153 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 154 pcictl &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 155 pcictl &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT); 156 pcictl |= (0x80 << PCI_LATTIMER_SHIFT); 157 pcictl |= (0x10 << PCI_CACHELINE_SHIFT); 158 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, pcictl); 159 160 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); 161 pcictl &= ~1; 162 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, pcictl); 163 164 switch (PCI_PRODUCT(pa->pa_id)) { 165 case PCI_PRODUCT_QLOGIC_ISP1020: 166 sc->sc_isp_gen = QLW_GEN_ISP1040; 167 switch (PCI_REVISION(pa->pa_class)) { 168 case 0: 169 sc->sc_isp_type = QLW_ISP1020; 170 break; 171 case 1: 172 sc->sc_isp_type = QLW_ISP1020A; 173 break; 174 case 2: 175 sc->sc_isp_type = QLW_ISP1040; 176 break; 177 case 3: 178 sc->sc_isp_type = QLW_ISP1040A; 179 break; 180 case 4: 181 sc->sc_isp_type = QLW_ISP1040B; 182 break; 183 case 5: 184 default: 185 sc->sc_isp_type = QLW_ISP1040C; 186 break; 187 } 188 sc->sc_numbusses = 1; 189 if (PCI_REVISION(pa->pa_class) < 2) 190 sc->sc_clock = 40; /* ISP1020/1020A */ 191 else 192 sc->sc_clock = 60; /* ISP1040/1040A/1040B/1040C */ 193 break; 194 195 case PCI_PRODUCT_QLOGIC_ISP1240: 196 sc->sc_isp_gen = QLW_GEN_ISP1080; 197 sc->sc_isp_type = QLW_ISP1240; 198 sc->sc_numbusses = 2; 199 sc->sc_clock = 60; 200 break; 201 202 case PCI_PRODUCT_QLOGIC_ISP1080: 203 sc->sc_isp_gen = QLW_GEN_ISP1080; 204 sc->sc_isp_type = QLW_ISP1080; 205 sc->sc_numbusses = 1; 206 sc->sc_clock = 100; 207 break; 208 209 case PCI_PRODUCT_QLOGIC_ISP1280: 210 sc->sc_isp_gen = QLW_GEN_ISP1080; 211 sc->sc_isp_type = QLW_ISP1280; 212 sc->sc_numbusses = 2; 213 sc->sc_clock = 100; 214 break; 215 216 case PCI_PRODUCT_QLOGIC_ISP10160: 217 sc->sc_isp_gen = QLW_GEN_ISP12160; 218 sc->sc_isp_type = QLW_ISP10160; 219 sc->sc_numbusses = 1; 220 sc->sc_clock = 100; 221 break; 222 223 case PCI_PRODUCT_QLOGIC_ISP12160: 224 sc->sc_isp_gen = QLW_GEN_ISP12160; 225 sc->sc_isp_type = QLW_ISP12160; 226 sc->sc_numbusses = 2; 227 sc->sc_clock = 100; 228 break; 229 230 default: 231 printf("unknown pci id %x", pa->pa_id); 232 return; 233 } 234 235 #ifndef ISP_NOFIRMWARE 236 switch (sc->sc_isp_gen) { 237 case QLW_GEN_ISP1040: 238 sc->sc_firmware = isp_1040_risc_code; 239 break; 240 case QLW_GEN_ISP1080: 241 sc->sc_firmware = isp_1080_risc_code; 242 break; 243 case QLW_GEN_ISP12160: 244 sc->sc_firmware = isp_12160_risc_code; 245 break; 246 default: 247 break; 248 } 249 #endif 250 251 /* 252 * The standard SCSI initiator ID is 7. 253 * Add-on cards should have a valid nvram, which will override 254 * these defaults. 255 */ 256 sc->sc_initiator[0] = sc->sc_initiator[1] = 7; 257 258 #ifdef __sparc64__ 259 /* 260 * Walk up the Open Firmware device tree until we find a 261 * "scsi-initiator-id" property. 262 */ 263 node = PCITAG_NODE(pa->pa_tag); 264 while (node) { 265 if (OF_getprop(node, "scsi-initiator-id", 266 &initiator, sizeof(initiator)) == sizeof(initiator)) { 267 /* 268 * Override the SCSI initiator ID provided by 269 * the nvram. 270 */ 271 sc->sc_flags |= QLW_FLAG_INITIATOR; 272 sc->sc_initiator[0] = sc->sc_initiator[1] = initiator; 273 break; 274 } 275 node = OF_parent(node); 276 } 277 #endif 278 279 sc->sc_host_cmd_ctrl = QLW_HOST_CMD_CTRL_PCI; 280 sc->sc_mbox_base = QLW_MBOX_BASE_PCI; 281 282 if (qlw_attach(sc) != 0) { 283 /* error printed by qlw_attach */ 284 goto deintr; 285 } 286 287 return; 288 289 deintr: 290 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 291 psc->psc_ih = NULL; 292 unmap: 293 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 294 sc->sc_ios = 0; 295 } 296 297 int 298 qlw_pci_detach(struct device *self, int flags) 299 { 300 struct qlw_pci_softc *psc = (struct qlw_pci_softc *)self; 301 struct qlw_softc *sc = &psc->psc_qlw; 302 int rv; 303 304 if (psc->psc_ih == NULL) { 305 /* we didn't attach properly, so nothing to detach */ 306 return (0); 307 } 308 309 rv = qlw_detach(sc, flags); 310 if (rv != 0) 311 return (rv); 312 313 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 314 psc->psc_ih = NULL; 315 316 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 317 sc->sc_ios = 0; 318 319 return (0); 320 } 321