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