1 /* $OpenBSD: qla_pci.c,v 1.11 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 * 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 USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * 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/device.h> 23 24 #include <machine/bus.h> 25 26 #include <dev/pci/pcireg.h> 27 #include <dev/pci/pcivar.h> 28 #include <dev/pci/pcidevs.h> 29 30 #ifdef __sparc64__ 31 #include <dev/ofw/openfirm.h> 32 #endif 33 34 #include <scsi/scsi_all.h> 35 #include <scsi/scsiconf.h> 36 37 #include <dev/ic/qlareg.h> 38 #include <dev/ic/qlavar.h> 39 40 #define QLA_PCI_MEM_BAR 0x14 41 #define QLA_PCI_IO_BAR 0x10 42 43 int qla_pci_match(struct device *, void *, void *); 44 void qla_pci_attach(struct device *, struct device *, void *); 45 int qla_pci_detach(struct device *, int); 46 47 struct qla_pci_softc { 48 struct qla_softc psc_qla; 49 50 pci_chipset_tag_t psc_pc; 51 pcitag_t psc_tag; 52 53 void *psc_ih; 54 }; 55 56 const struct cfattach qla_pci_ca = { 57 sizeof(struct qla_pci_softc), 58 qla_pci_match, 59 qla_pci_attach 60 }; 61 62 #define PREAD(s, r) pci_conf_read((s)->psc_pc, (s)->psc_tag, (r)) 63 #define PWRITE(s, r, v) pci_conf_write((s)->psc_pc, (s)->psc_tag, (r), (v)) 64 65 static const struct pci_matchid qla_devices[] = { 66 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100 }, 67 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2200 }, 68 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2300 }, 69 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2312 }, 70 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2322 }, 71 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6312 }, 72 { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6322 }, 73 }; 74 75 int 76 qla_pci_match(struct device *parent, void *match, void *aux) 77 { 78 return (pci_matchbyid(aux, qla_devices, nitems(qla_devices)) * 2); 79 } 80 81 void 82 qla_pci_attach(struct device *parent, struct device *self, void *aux) 83 { 84 struct qla_pci_softc *psc = (void *)self; 85 struct qla_softc *sc = &psc->psc_qla; 86 struct pci_attach_args *pa = aux; 87 pci_intr_handle_t ih; 88 const char *intrstr; 89 u_int32_t pcictl; 90 #ifdef __sparc64__ 91 u_int64_t wwn; 92 int node; 93 #endif 94 95 pcireg_t bars[] = { QLA_PCI_MEM_BAR, QLA_PCI_IO_BAR }; 96 pcireg_t memtype; 97 int r; 98 99 psc->psc_pc = pa->pa_pc; 100 psc->psc_tag = pa->pa_tag; 101 psc->psc_ih = NULL; 102 sc->sc_dmat = pa->pa_dmat; 103 sc->sc_ios = 0; 104 105 for (r = 0; r < nitems(bars); r++) { 106 memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, bars[r]); 107 if (pci_mapreg_map(pa, bars[r], memtype, 0, 108 &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, 0) == 0) 109 break; 110 111 sc->sc_ios = 0; 112 } 113 if (sc->sc_ios == 0) { 114 printf(": unable to map registers\n"); 115 return; 116 } 117 118 if (pci_intr_map(pa, &ih)) { 119 printf(": unable to map interrupt\n"); 120 goto unmap; 121 } 122 intrstr = pci_intr_string(psc->psc_pc, ih); 123 psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO, 124 qla_intr, sc, DEVNAME(sc)); 125 if (psc->psc_ih == NULL) { 126 printf(": unable to establish interrupt"); 127 if (intrstr != NULL) 128 printf(" at %s", intrstr); 129 printf("\n"); 130 goto deintr; 131 } 132 133 printf(": %s\n", intrstr); 134 135 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 136 pcictl |= PCI_COMMAND_INVALIDATE_ENABLE | 137 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 138 /* fw manual says to enable bus master here, then disable it while 139 * resetting.. hm. 140 */ 141 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pcictl); 142 143 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 144 pcictl &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 145 pcictl &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT); 146 pcictl |= (0x80 << PCI_LATTIMER_SHIFT); 147 pcictl |= (0x10 << PCI_CACHELINE_SHIFT); 148 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, pcictl); 149 150 pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG); 151 pcictl &= ~1; 152 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, pcictl); 153 154 switch (PCI_PRODUCT(pa->pa_id)) { 155 case PCI_PRODUCT_QLOGIC_ISP2100: 156 sc->sc_isp_gen = QLA_GEN_ISP2100; 157 sc->sc_isp_type = QLA_ISP2100; 158 break; 159 160 case PCI_PRODUCT_QLOGIC_ISP2200: 161 sc->sc_isp_gen = QLA_GEN_ISP2200; 162 sc->sc_isp_type = QLA_ISP2200; 163 break; 164 165 case PCI_PRODUCT_QLOGIC_ISP2300: 166 sc->sc_isp_type = QLA_ISP2300; 167 sc->sc_isp_gen = QLA_GEN_ISP23XX; 168 break; 169 170 case PCI_PRODUCT_QLOGIC_ISP2312: 171 case PCI_PRODUCT_QLOGIC_ISP6312: 172 sc->sc_isp_type = QLA_ISP2312; 173 sc->sc_isp_gen = QLA_GEN_ISP23XX; 174 break; 175 176 case PCI_PRODUCT_QLOGIC_ISP2322: 177 case PCI_PRODUCT_QLOGIC_ISP6322: 178 sc->sc_isp_type = QLA_ISP2322; 179 sc->sc_isp_gen = QLA_GEN_ISP23XX; 180 break; 181 182 default: 183 printf("unknown pci id %x", pa->pa_id); 184 return; 185 } 186 187 #ifdef __sparc64__ 188 node = PCITAG_NODE(pa->pa_tag); 189 if (OF_getprop(node, "port-wwn", &wwn, sizeof(wwn)) == sizeof(wwn)) 190 sc->sc_port_name = wwn; 191 if (OF_getprop(node, "node-wwn", &wwn, sizeof(wwn)) == sizeof(wwn)) 192 sc->sc_node_name = wwn; 193 #endif 194 195 sc->sc_port = pa->pa_function; 196 197 if (qla_attach(sc) != 0) { 198 /* error printed by qla_attach */ 199 goto deintr; 200 } 201 202 return; 203 204 deintr: 205 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 206 psc->psc_ih = NULL; 207 unmap: 208 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 209 sc->sc_ios = 0; 210 } 211 212 int 213 qla_pci_detach(struct device *self, int flags) 214 { 215 struct qla_pci_softc *psc = (struct qla_pci_softc *)self; 216 struct qla_softc *sc = &psc->psc_qla; 217 int rv; 218 219 if (psc->psc_ih == NULL) { 220 /* we didn't attach properly, so nothing to detach */ 221 return (0); 222 } 223 224 rv = qla_detach(sc, flags); 225 if (rv != 0) 226 return (rv); 227 228 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 229 psc->psc_ih = NULL; 230 231 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 232 sc->sc_ios = 0; 233 234 return (0); 235 } 236