1aad970f1SDavid E. O'Brien /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 41b760be4SAlexander Motin * Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org> 52df76c16SMatt Jacob * Copyright (c) 1997-2008 by Matthew Jacob 6e5265237SMatt Jacob * All rights reserved. 765adb54cSMatt Jacob * 865adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 965adb54cSMatt Jacob * modification, are permitted provided that the following conditions 1065adb54cSMatt Jacob * are met: 1165adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 1265adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1365adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 14aa57fd6fSMatt Jacob * 2. The name of the author may not be used to endorse or promote products 15aa57fd6fSMatt Jacob * derived from this software without specific prior written permission. 1665adb54cSMatt Jacob * 1765adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1865adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1965adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2065adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2165adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2265adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2365adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2465adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2565adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2665adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2765adb54cSMatt Jacob * SUCH DAMAGE. 2865adb54cSMatt Jacob */ 29799881e0SMatt Jacob /* 30799881e0SMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 31799881e0SMatt Jacob * FreeBSD Version. 32799881e0SMatt Jacob */ 33aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 34aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 35aad970f1SDavid E. O'Brien 36960f6939SMatt Jacob #include <sys/param.h> 37960f6939SMatt Jacob #include <sys/systm.h> 38960f6939SMatt Jacob #include <sys/kernel.h> 39960f6939SMatt Jacob #include <sys/module.h> 409a5af410SMatt Jacob #include <sys/linker.h> 419a5af410SMatt Jacob #include <sys/firmware.h> 42960f6939SMatt Jacob #include <sys/bus.h> 4374a96f43SJohn Baldwin #include <sys/stdint.h> 4477e6a3b2SWarner Losh #include <dev/pci/pcireg.h> 4577e6a3b2SWarner Losh #include <dev/pci/pcivar.h> 46d720e6d5SJustin T. Gibbs #include <machine/bus.h> 47960f6939SMatt Jacob #include <machine/resource.h> 48960f6939SMatt Jacob #include <sys/rman.h> 49960f6939SMatt Jacob #include <sys/malloc.h> 502df76c16SMatt Jacob #include <sys/uio.h> 51960f6939SMatt Jacob #include <dev/isp/isp_freebsd.h> 52d59bd469SMatt Jacob 5310365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); 5410365e5aSMatt Jacob static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); 55cd201b7bSAlexander Motin static uint32_t isp_pci_rd_reg_2600(ispsoftc_t *, int); 56cd201b7bSAlexander Motin static void isp_pci_wr_reg_2600(ispsoftc_t *, int, uint32_t); 570e6bc811SAlexander Motin static void isp_pci_run_isr_2400(ispsoftc_t *); 589cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *); 59a1fa0267SAlexander Motin static void isp_pci_mbxdmafree(ispsoftc_t *); 60a1fa0267SAlexander Motin static int isp_pci_irqsetup(ispsoftc_t *); 61d951bbcaSMatt Jacob 6210365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = { 630e6bc811SAlexander Motin isp_pci_run_isr_2400, 6410365e5aSMatt Jacob isp_pci_rd_reg_2400, 6510365e5aSMatt Jacob isp_pci_wr_reg_2400, 6610365e5aSMatt Jacob isp_pci_mbxdma, 67f6854a0cSAlexander Motin isp_send_cmd, 68a1fa0267SAlexander Motin isp_pci_irqsetup, 6910365e5aSMatt Jacob NULL 7010365e5aSMatt Jacob }; 7110365e5aSMatt Jacob 722df76c16SMatt Jacob static struct ispmdvec mdvec_2500 = { 730e6bc811SAlexander Motin isp_pci_run_isr_2400, 742df76c16SMatt Jacob isp_pci_rd_reg_2400, 752df76c16SMatt Jacob isp_pci_wr_reg_2400, 762df76c16SMatt Jacob isp_pci_mbxdma, 77f6854a0cSAlexander Motin isp_send_cmd, 78a1fa0267SAlexander Motin isp_pci_irqsetup, 792df76c16SMatt Jacob NULL 802df76c16SMatt Jacob }; 812df76c16SMatt Jacob 82218be0b2SAlexander Motin static struct ispmdvec mdvec_2600 = { 830e6bc811SAlexander Motin isp_pci_run_isr_2400, 84cd201b7bSAlexander Motin isp_pci_rd_reg_2600, 85cd201b7bSAlexander Motin isp_pci_wr_reg_2600, 86218be0b2SAlexander Motin isp_pci_mbxdma, 87f6854a0cSAlexander Motin isp_send_cmd, 88a1fa0267SAlexander Motin isp_pci_irqsetup, 89218be0b2SAlexander Motin NULL 90218be0b2SAlexander Motin }; 91218be0b2SAlexander Motin 9214e084adSAlexander Motin static struct ispmdvec mdvec_2700 = { 9314e084adSAlexander Motin isp_pci_run_isr_2400, 9414e084adSAlexander Motin isp_pci_rd_reg_2600, 9514e084adSAlexander Motin isp_pci_wr_reg_2600, 9614e084adSAlexander Motin isp_pci_mbxdma, 97f6854a0cSAlexander Motin isp_send_cmd, 9814e084adSAlexander Motin isp_pci_irqsetup, 9914e084adSAlexander Motin NULL 10014e084adSAlexander Motin }; 10114e084adSAlexander Motin 102*407abff6SJoerg Pulz static struct ispmdvec mdvec_2800 = { 103*407abff6SJoerg Pulz isp_pci_run_isr_2400, 104*407abff6SJoerg Pulz isp_pci_rd_reg_2600, 105*407abff6SJoerg Pulz isp_pci_wr_reg_2600, 106*407abff6SJoerg Pulz isp_pci_mbxdma, 107*407abff6SJoerg Pulz isp_send_cmd, 108*407abff6SJoerg Pulz isp_pci_irqsetup, 109*407abff6SJoerg Pulz NULL 110*407abff6SJoerg Pulz }; 111*407abff6SJoerg Pulz 11265adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 11365adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 11465adb54cSMatt Jacob #endif 11565adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 11665adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 11765adb54cSMatt Jacob #endif 118d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 119d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 120d951bbcaSMatt Jacob #endif 121d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 122d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 123d951bbcaSMatt Jacob #endif 1248a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 1258a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 1268a97c03aSMatt Jacob #endif 127d951bbcaSMatt Jacob 128d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 129d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 130d951bbcaSMatt Jacob #endif 131d951bbcaSMatt Jacob 132d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 133d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 134d951bbcaSMatt Jacob #endif 135d951bbcaSMatt Jacob 136d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 137d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 138d951bbcaSMatt Jacob #endif 139d951bbcaSMatt Jacob 140ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 141ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 142ab6d0040SMatt Jacob #endif 143ab6d0040SMatt Jacob 14465adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 14565adb54cSMatt Jacob 1468872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 14741675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 1482df76c16SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2532 0x2532 149a959d921SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP5432 0x5432 150218be0b2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2031 0x2031 15167eeadd2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP8031 0x8031 15214e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2684 0x2171 15314e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2692 0x2b61 15414e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2714 0x2071 15514e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2722 0x2261 156*407abff6SJoerg Pulz #define PCI_PRODUCT_QLOGIC_ISP2812 0x2281 157*407abff6SJoerg Pulz #define PCI_PRODUCT_QLOGIC_ISP2814 0x2081 1589a5af410SMatt Jacob 1596c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 1606c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 16141675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 16241675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 1632df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 1642df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 16514e084adSAlexander Motin #define PCI_QLOGIC_ISP5432 \ 16614e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC) 167218be0b2SAlexander Motin #define PCI_QLOGIC_ISP2031 \ 168218be0b2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC) 16967eeadd2SAlexander Motin #define PCI_QLOGIC_ISP8031 \ 17067eeadd2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP8031 << 16) | PCI_VENDOR_QLOGIC) 17114e084adSAlexander Motin #define PCI_QLOGIC_ISP2684 \ 17214e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2684 << 16) | PCI_VENDOR_QLOGIC) 17314e084adSAlexander Motin #define PCI_QLOGIC_ISP2692 \ 17414e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2692 << 16) | PCI_VENDOR_QLOGIC) 17514e084adSAlexander Motin #define PCI_QLOGIC_ISP2714 \ 17614e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2714 << 16) | PCI_VENDOR_QLOGIC) 17714e084adSAlexander Motin #define PCI_QLOGIC_ISP2722 \ 17814e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2722 << 16) | PCI_VENDOR_QLOGIC) 179*407abff6SJoerg Pulz #define PCI_QLOGIC_ISP2812 \ 180*407abff6SJoerg Pulz ((PCI_PRODUCT_QLOGIC_ISP2812 << 16) | PCI_VENDOR_QLOGIC) 181*407abff6SJoerg Pulz #define PCI_QLOGIC_ISP2814 \ 182*407abff6SJoerg Pulz ((PCI_PRODUCT_QLOGIC_ISP2814 << 16) | PCI_VENDOR_QLOGIC) 18367eeadd2SAlexander Motin 184d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 185d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 18665adb54cSMatt Jacob 187960f6939SMatt Jacob static int isp_pci_probe (device_t); 188960f6939SMatt Jacob static int isp_pci_attach (device_t); 18910365e5aSMatt Jacob static int isp_pci_detach (device_t); 19065adb54cSMatt Jacob 1911923f739SMatt Jacob 19265adb54cSMatt Jacob struct isp_pcisoftc { 1939cd7268eSMatt Jacob ispsoftc_t pci_isp; 194e95725cbSMatt Jacob struct resource * regs; 195d876d6c3SAlexander Motin struct resource * regs1; 196cd201b7bSAlexander Motin struct resource * regs2; 19708826086SAlexander Motin struct { 198e95725cbSMatt Jacob int iqd; 19908826086SAlexander Motin struct resource * irq; 20008826086SAlexander Motin void * ih; 20108826086SAlexander Motin } irq[ISP_MAX_IRQS]; 202e95725cbSMatt Jacob int rtp; 203e95725cbSMatt Jacob int rgd; 204d876d6c3SAlexander Motin int rtp1; 205d876d6c3SAlexander Motin int rgd1; 206cd201b7bSAlexander Motin int rtp2; 207cd201b7bSAlexander Motin int rgd2; 2081923f739SMatt Jacob bus_dma_tag_t dmat; 2090a70657fSMatt Jacob int msicount; 21065adb54cSMatt Jacob }; 21165adb54cSMatt Jacob 21210365e5aSMatt Jacob 213960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 214960f6939SMatt Jacob /* Device interface */ 215960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 216960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 21710365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 218960f6939SMatt Jacob { 0, 0 } 21965adb54cSMatt Jacob }; 22065adb54cSMatt Jacob 221960f6939SMatt Jacob static driver_t isp_pci_driver = { 222960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 223960f6939SMatt Jacob }; 224d1a9e9b9SJohn Baldwin 225d1a9e9b9SJohn Baldwin DRIVER_MODULE(isp, pci, isp_pci_driver, 0, 0); 226d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1); 227d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1); 2289e7d423dSMatt Jacob static int isp_nvports = 0; 22965adb54cSMatt Jacob 230960f6939SMatt Jacob static int 231960f6939SMatt Jacob isp_pci_probe(device_t dev) 23265adb54cSMatt Jacob { 233960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 2348872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 2358872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 2368872e3d7SMatt Jacob break; 23741675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 23841675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 23941675df0SMatt Jacob break; 2402df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 2412df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 2422df76c16SMatt Jacob break; 243a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 244a959d921SMatt Jacob device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter"); 245a959d921SMatt Jacob break; 246218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 247218be0b2SAlexander Motin device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter"); 248218be0b2SAlexander Motin break; 24967eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 25067eeadd2SAlexander Motin device_set_desc(dev, "Qlogic ISP 8031 PCI FCoE Adapter"); 25167eeadd2SAlexander Motin break; 25214e084adSAlexander Motin case PCI_QLOGIC_ISP2684: 25314e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2684 PCI FC Adapter"); 25414e084adSAlexander Motin break; 25514e084adSAlexander Motin case PCI_QLOGIC_ISP2692: 25614e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2692 PCI FC Adapter"); 25714e084adSAlexander Motin break; 25814e084adSAlexander Motin case PCI_QLOGIC_ISP2714: 25914e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2714 PCI FC Adapter"); 26014e084adSAlexander Motin break; 26114e084adSAlexander Motin case PCI_QLOGIC_ISP2722: 26214e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2722 PCI FC Adapter"); 26314e084adSAlexander Motin break; 264*407abff6SJoerg Pulz case PCI_QLOGIC_ISP2812: 265*407abff6SJoerg Pulz device_set_desc(dev, "Qlogic ISP 2812 PCI FC Adapter"); 266*407abff6SJoerg Pulz break; 267*407abff6SJoerg Pulz case PCI_QLOGIC_ISP2814: 268*407abff6SJoerg Pulz device_set_desc(dev, "Qlogic ISP 2814 PCI FC Adapter"); 269*407abff6SJoerg Pulz break; 27065adb54cSMatt Jacob default: 271960f6939SMatt Jacob return (ENXIO); 27265adb54cSMatt Jacob } 27373030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 274d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 275a95ae193SMatt Jacob "Core Version %d.%d\n", 276d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 277d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 27873030e03SMatt Jacob isp_announced++; 27965adb54cSMatt Jacob } 28056aef503SMatt Jacob /* 28156aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 28256aef503SMatt Jacob * XXXX: (or increase a reference count to it). 28356aef503SMatt Jacob */ 284b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 28565adb54cSMatt Jacob } 28665adb54cSMatt Jacob 2879cd7268eSMatt Jacob static void 2889e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 2899cd7268eSMatt Jacob { 2909cd7268eSMatt Jacob int tval; 291f7c631bcSMatt Jacob 2929cd7268eSMatt Jacob tval = 0; 2932df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 2949cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 2959cd7268eSMatt Jacob } 2969cd7268eSMatt Jacob tval = 0; 2972df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 2989cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 2999cd7268eSMatt Jacob } 300336b5612SMatt Jacob tval = 0; 3012df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 302336b5612SMatt Jacob if (tval) { 303336b5612SMatt Jacob isp->isp_dblev = tval; 304336b5612SMatt Jacob } else { 305336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 306336b5612SMatt Jacob } 307336b5612SMatt Jacob if (bootverbose) { 308336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 309336b5612SMatt Jacob } 3109e7d423dSMatt Jacob tval = -1; 3112df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 312ffe6ea05SAlexander Motin if (tval > 0 && tval <= 254) { 3139e7d423dSMatt Jacob isp_nvports = tval; 3142df76c16SMatt Jacob } 3152df76c16SMatt Jacob tval = 7; 3162df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 3172df76c16SMatt Jacob isp_quickboot_time = tval; 318336b5612SMatt Jacob } 319336b5612SMatt Jacob 320336b5612SMatt Jacob static void 3212df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 322336b5612SMatt Jacob { 323336b5612SMatt Jacob const char *sptr; 3249e7d423dSMatt Jacob int tval = 0; 32507f56f1cSAlexander Motin char prefix[12], name[16]; 326336b5612SMatt Jacob 32707f56f1cSAlexander Motin if (chan == 0) 32807f56f1cSAlexander Motin prefix[0] = 0; 32907f56f1cSAlexander Motin else 33007f56f1cSAlexander Motin snprintf(prefix, sizeof(prefix), "chan%d.", chan); 33107f56f1cSAlexander Motin snprintf(name, sizeof(name), "%siid", prefix); 33207f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 33307f56f1cSAlexander Motin name, &tval)) { 3342df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 3352df76c16SMatt Jacob } else { 3362df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 337336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 338336b5612SMatt Jacob } 3392df76c16SMatt Jacob 3402df76c16SMatt Jacob tval = -1; 34107f56f1cSAlexander Motin snprintf(name, sizeof(name), "%srole", prefix); 34207f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 34307f56f1cSAlexander Motin name, &tval) == 0) { 3442df76c16SMatt Jacob switch (tval) { 3452df76c16SMatt Jacob case ISP_ROLE_NONE: 3462df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 3472df76c16SMatt Jacob case ISP_ROLE_TARGET: 34807f56f1cSAlexander Motin case ISP_ROLE_BOTH: 34907f56f1cSAlexander Motin device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval); 3502df76c16SMatt Jacob break; 3512df76c16SMatt Jacob default: 3522df76c16SMatt Jacob tval = -1; 3532df76c16SMatt Jacob break; 354336b5612SMatt Jacob } 355336b5612SMatt Jacob } 3562df76c16SMatt Jacob if (tval == -1) { 3572df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 3582df76c16SMatt Jacob } 3594ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 360336b5612SMatt Jacob 3619cd7268eSMatt Jacob tval = 0; 36207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfullduplex", prefix); 36307f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 36407f56f1cSAlexander Motin name, &tval) == 0 && tval != 0) { 3659cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 3669cd7268eSMatt Jacob } 3674d24901aSPedro F. Giffuni sptr = NULL; 36807f56f1cSAlexander Motin snprintf(name, sizeof(name), "%stopology", prefix); 36907f56f1cSAlexander Motin if (resource_string_value(device_get_name(dev), device_get_unit(dev), 3704d24901aSPedro F. Giffuni name, (const char **) &sptr) == 0 && sptr != NULL) { 3719cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 3729cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 3739cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 3749cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 3759cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 3769cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 3779cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 3789cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 3799cd7268eSMatt Jacob } 380960f6939SMatt Jacob } 381960f6939SMatt Jacob 38208167db8SKenneth D. Merry #ifdef ISP_FCTAPE_OFF 38308167db8SKenneth D. Merry isp->isp_confopts |= ISP_CFG_NOFCTAPE; 38408167db8SKenneth D. Merry #else 38508167db8SKenneth D. Merry isp->isp_confopts |= ISP_CFG_FCTAPE; 38608167db8SKenneth D. Merry #endif 38708167db8SKenneth D. Merry 388387d8239SMatt Jacob tval = 0; 38907f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snofctape", prefix); 39007f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 39107f56f1cSAlexander Motin name, &tval); 392387d8239SMatt Jacob if (tval) { 39308167db8SKenneth D. Merry isp->isp_confopts &= ~ISP_CFG_FCTAPE; 394387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_NOFCTAPE; 395387d8239SMatt Jacob } 396387d8239SMatt Jacob 397387d8239SMatt Jacob tval = 0; 39807f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfctape", prefix); 39907f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 40007f56f1cSAlexander Motin name, &tval); 401387d8239SMatt Jacob if (tval) { 402387d8239SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NOFCTAPE; 403387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_FCTAPE; 404387d8239SMatt Jacob } 405387d8239SMatt Jacob 406387d8239SMatt Jacob 4079ba86737SMatt Jacob /* 4089cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 4099cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 4109cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 4119cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 4129cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 4139cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 4149cd7268eSMatt Jacob */ 4154d24901aSPedro F. Giffuni sptr = NULL; 41607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sportwwn", prefix); 41707f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 41807f56f1cSAlexander Motin name, (const char **) &sptr); 4194d24901aSPedro F. Giffuni if (tval == 0 && sptr != NULL && *sptr++ == 'w') { 4204d24901aSPedro F. Giffuni char *eptr = NULL; 4212df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 4222df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 4239cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 4242df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 4259cd7268eSMatt Jacob } 4269cd7268eSMatt Jacob } 4279cd7268eSMatt Jacob 4284d24901aSPedro F. Giffuni sptr = NULL; 42907f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snodewwn", prefix); 43007f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 43107f56f1cSAlexander Motin name, (const char **) &sptr); 4324d24901aSPedro F. Giffuni if (tval == 0 && sptr != NULL && *sptr++ == 'w') { 4334d24901aSPedro F. Giffuni char *eptr = NULL; 4342df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 4352df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 4369cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 4372df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 4389cd7268eSMatt Jacob } 4399cd7268eSMatt Jacob } 4409cd7268eSMatt Jacob 441f7c631bcSMatt Jacob tval = -1; 44207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sloop_down_limit", prefix); 44307f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 44407f56f1cSAlexander Motin name, &tval); 44510365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 4462df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 44710365e5aSMatt Jacob } else { 4482df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 44910365e5aSMatt Jacob } 45010365e5aSMatt Jacob 451f7c631bcSMatt Jacob tval = -1; 45207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sgone_device_time", prefix); 45307f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 45407f56f1cSAlexander Motin name, &tval); 455f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 4562df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 457f7c631bcSMatt Jacob } else { 4582df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 459f7c631bcSMatt Jacob } 4609cd7268eSMatt Jacob } 4619cd7268eSMatt Jacob 4629cd7268eSMatt Jacob static int 4639cd7268eSMatt Jacob isp_pci_attach(device_t dev) 4649cd7268eSMatt Jacob { 465a1fa0267SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 466a1fa0267SAlexander Motin ispsoftc_t *isp = &pcs->pci_isp; 467a1fa0267SAlexander Motin int i; 4682df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 4692df76c16SMatt Jacob size_t psize, xsize; 4702df76c16SMatt Jacob char fwname[32]; 4719cd7268eSMatt Jacob 4722df76c16SMatt Jacob isp->isp_dev = dev; 4732df76c16SMatt Jacob isp->isp_nchan = 1; 47413d9c921SAlexander Motin mtx_init(&isp->isp_lock, "isp", NULL, MTX_DEF); 4759cd7268eSMatt Jacob 4769cd7268eSMatt Jacob /* 477336b5612SMatt Jacob * Get Generic Options 4789cd7268eSMatt Jacob */ 4799e7d423dSMatt Jacob isp_nvports = 0; 4809e7d423dSMatt Jacob isp_get_generic_options(dev, isp); 4819cd7268eSMatt Jacob 482ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 48308826086SAlexander Motin pcs->regs = pcs->regs2 = NULL; 48408826086SAlexander Motin pcs->rgd = pcs->rtp = 0; 485960f6939SMatt Jacob 4861b760be4SAlexander Motin isp->isp_nchan += isp_nvports; 4872df76c16SMatt Jacob switch (pci_get_devid(dev)) { 4882df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 4892df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 4902df76c16SMatt Jacob did = 0x2400; 4912df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 4922df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 4932df76c16SMatt Jacob break; 4942df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 4952df76c16SMatt Jacob did = 0x2500; 4962df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 4972df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 4982df76c16SMatt Jacob break; 499a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 500a959d921SMatt Jacob did = 0x2500; 501a959d921SMatt Jacob isp->isp_mdvec = &mdvec_2500; 502a959d921SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 503a959d921SMatt Jacob break; 504218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 50567eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 506218be0b2SAlexander Motin did = 0x2600; 507218be0b2SAlexander Motin isp->isp_mdvec = &mdvec_2600; 508218be0b2SAlexander Motin isp->isp_type = ISP_HA_FC_2600; 509218be0b2SAlexander Motin break; 51014e084adSAlexander Motin case PCI_QLOGIC_ISP2684: 51114e084adSAlexander Motin case PCI_QLOGIC_ISP2692: 51214e084adSAlexander Motin case PCI_QLOGIC_ISP2714: 51314e084adSAlexander Motin case PCI_QLOGIC_ISP2722: 51414e084adSAlexander Motin did = 0x2700; 51514e084adSAlexander Motin isp->isp_mdvec = &mdvec_2700; 51614e084adSAlexander Motin isp->isp_type = ISP_HA_FC_2700; 51714e084adSAlexander Motin break; 518*407abff6SJoerg Pulz case PCI_QLOGIC_ISP2812: 519*407abff6SJoerg Pulz case PCI_QLOGIC_ISP2814: 520*407abff6SJoerg Pulz did = 0x2800; 521*407abff6SJoerg Pulz isp->isp_mdvec = &mdvec_2800; 522*407abff6SJoerg Pulz isp->isp_type = ISP_HA_FC_2800; 523*407abff6SJoerg Pulz break; 5242df76c16SMatt Jacob default: 5252df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 5262df76c16SMatt Jacob goto bad; 5272df76c16SMatt Jacob break; 52865adb54cSMatt Jacob } 5292df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 5302df76c16SMatt Jacob 531218be0b2SAlexander Motin if (IS_26XX(isp)) { 532218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 533218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 534218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 535218be0b2SAlexander Motin RF_ACTIVE); 536d876d6c3SAlexander Motin pcs->rtp1 = SYS_RES_MEMORY; 537d876d6c3SAlexander Motin pcs->rgd1 = PCIR_BAR(2); 538d876d6c3SAlexander Motin pcs->regs1 = bus_alloc_resource_any(dev, pcs->rtp1, &pcs->rgd1, 539d876d6c3SAlexander Motin RF_ACTIVE); 540cd201b7bSAlexander Motin pcs->rtp2 = SYS_RES_MEMORY; 541cd201b7bSAlexander Motin pcs->rgd2 = PCIR_BAR(4); 542cd201b7bSAlexander Motin pcs->regs2 = bus_alloc_resource_any(dev, pcs->rtp2, &pcs->rgd2, 543cd201b7bSAlexander Motin RF_ACTIVE); 544218be0b2SAlexander Motin } else { 545218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 546218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(1); 547218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 548218be0b2SAlexander Motin RF_ACTIVE); 549218be0b2SAlexander Motin if (pcs->regs == NULL) { 550218be0b2SAlexander Motin pcs->rtp = SYS_RES_IOPORT; 551218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 552218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, 553218be0b2SAlexander Motin &pcs->rgd, RF_ACTIVE); 554218be0b2SAlexander Motin } 555218be0b2SAlexander Motin } 556218be0b2SAlexander Motin if (pcs->regs == NULL) { 557218be0b2SAlexander Motin device_printf(dev, "Unable to map any ports\n"); 558218be0b2SAlexander Motin goto bad; 559218be0b2SAlexander Motin } 560218be0b2SAlexander Motin if (bootverbose) { 561218be0b2SAlexander Motin device_printf(dev, "Using %s space register mapping\n", 562218be0b2SAlexander Motin (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory"); 563218be0b2SAlexander Motin } 564cd201b7bSAlexander Motin isp->isp_regs = pcs->regs; 565cd201b7bSAlexander Motin isp->isp_regs2 = pcs->regs2; 566218be0b2SAlexander Motin 5671b760be4SAlexander Motin psize = sizeof(fcparam) * isp->isp_nchan; 5681b760be4SAlexander Motin xsize = sizeof(struct isp_fc) * isp->isp_nchan; 5697cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 570c6608df3SMatt Jacob if (isp->isp_param == NULL) { 571960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 572960f6939SMatt Jacob goto bad; 573c6608df3SMatt Jacob } 574a6222dd7SAlexander Motin isp->isp_osinfo.fc = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 575a6222dd7SAlexander Motin if (isp->isp_osinfo.fc == NULL) { 5762df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 5772df76c16SMatt Jacob goto bad; 5782df76c16SMatt Jacob } 57965adb54cSMatt Jacob 580336b5612SMatt Jacob /* 581336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 582336b5612SMatt Jacob */ 5832df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 5842df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 5859a5af410SMatt Jacob } 5869a5af410SMatt Jacob 5879a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 5889a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 5899a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 5909a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 5919a5af410SMatt Jacob } 5929a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 593ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname); 5945f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 5959a5af410SMatt Jacob } 59656aef503SMatt Jacob 59756aef503SMatt Jacob /* 598ad0ab753SMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 599d951bbcaSMatt Jacob */ 600c68534f1SScott Long cmd = pci_read_config(dev, PCIR_COMMAND, 2); 6019e7d423dSMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 6028a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 603b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 604ab6d0040SMatt Jacob 605d951bbcaSMatt Jacob /* 606222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 607d951bbcaSMatt Jacob */ 608960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 6096a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 610ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data); 6116a7d12e1SMatt Jacob data = linesz; 612960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 613d951bbcaSMatt Jacob } 614ab6d0040SMatt Jacob 615d951bbcaSMatt Jacob /* 616d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 617d951bbcaSMatt Jacob */ 618960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 619d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 620d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 621ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data); 622960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 623d951bbcaSMatt Jacob } 624ab6d0040SMatt Jacob 625ab6d0040SMatt Jacob /* 626ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 627ab6d0040SMatt Jacob */ 628960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 629ab6d0040SMatt Jacob data &= ~1; 630960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 6312df76c16SMatt Jacob 63205fbcbb0SMatt Jacob /* 63375c1e828SMatt Jacob * Last minute checks... 63475c1e828SMatt Jacob */ 63575c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 63675c1e828SMatt Jacob 63775c1e828SMatt Jacob /* 63805fbcbb0SMatt Jacob * Make sure we're in reset state. 63905fbcbb0SMatt Jacob */ 6403395b056SMatt Jacob ISP_LOCK(isp); 641dfd24649SAlexander Motin if (isp_reinit(isp, 1) != 0) { 6423395b056SMatt Jacob ISP_UNLOCK(isp); 643960f6939SMatt Jacob goto bad; 64465adb54cSMatt Jacob } 6452df76c16SMatt Jacob ISP_UNLOCK(isp); 6462df76c16SMatt Jacob if (isp_attach(isp)) { 6472df76c16SMatt Jacob ISP_LOCK(isp); 648a1fa0267SAlexander Motin isp_shutdown(isp); 6493395b056SMatt Jacob ISP_UNLOCK(isp); 650960f6939SMatt Jacob goto bad; 651d59bd469SMatt Jacob } 652960f6939SMatt Jacob return (0); 653960f6939SMatt Jacob 654960f6939SMatt Jacob bad: 655e52fba21SEdward Tomasz Napierala if (isp->isp_osinfo.fw == NULL && !IS_26XX(isp)) { 656e52fba21SEdward Tomasz Napierala /* 657e52fba21SEdward Tomasz Napierala * Failure to attach at boot time might have been caused 658bafe4ceeSGordon Bergling * by a missing ispfw(4). Except for 16Gb adapters, 659e52fba21SEdward Tomasz Napierala * there's no loadable firmware for them. 660e52fba21SEdward Tomasz Napierala */ 661e52fba21SEdward Tomasz Napierala isp_prt(isp, ISP_LOGWARN, "See the ispfw(4) man page on " 662e52fba21SEdward Tomasz Napierala "how to load known good firmware at boot time"); 663e52fba21SEdward Tomasz Napierala } 66408826086SAlexander Motin for (i = 0; i < isp->isp_nirq; i++) { 66508826086SAlexander Motin (void) bus_teardown_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih); 66608826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->irq[i].iqd, 66708826086SAlexander Motin pcs->irq[0].irq); 668960f6939SMatt Jacob } 669a035b0afSMatt Jacob if (pcs->msicount) { 6700a70657fSMatt Jacob pci_release_msi(dev); 6710a70657fSMatt Jacob } 672cd201b7bSAlexander Motin if (pcs->regs) 673e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 674d876d6c3SAlexander Motin if (pcs->regs1) 675d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 676cd201b7bSAlexander Motin if (pcs->regs2) 677cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 6789cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 679960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 6802df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 6812df76c16SMatt Jacob } 682a6222dd7SAlexander Motin if (pcs->pci_isp.isp_osinfo.fc) { 683a6222dd7SAlexander Motin free(pcs->pci_isp.isp_osinfo.fc, M_DEVBUF); 684a6222dd7SAlexander Motin pcs->pci_isp.isp_osinfo.fc = NULL; 6859cd7268eSMatt Jacob } 68613d9c921SAlexander Motin mtx_destroy(&isp->isp_lock); 687960f6939SMatt Jacob return (ENXIO); 68865adb54cSMatt Jacob } 68965adb54cSMatt Jacob 69010365e5aSMatt Jacob static int 69110365e5aSMatt Jacob isp_pci_detach(device_t dev) 69210365e5aSMatt Jacob { 693a1fa0267SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 694a1fa0267SAlexander Motin ispsoftc_t *isp = &pcs->pci_isp; 69508826086SAlexander Motin int i, status; 69610365e5aSMatt Jacob 697e95725cbSMatt Jacob status = isp_detach(isp); 698e95725cbSMatt Jacob if (status) 699e95725cbSMatt Jacob return (status); 700e95725cbSMatt Jacob ISP_LOCK(isp); 701a1fa0267SAlexander Motin isp_shutdown(isp); 702e95725cbSMatt Jacob ISP_UNLOCK(isp); 70308826086SAlexander Motin for (i = 0; i < isp->isp_nirq; i++) { 70408826086SAlexander Motin (void) bus_teardown_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih); 70508826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->irq[i].iqd, 70608826086SAlexander Motin pcs->irq[i].irq); 70708826086SAlexander Motin } 708a1fa0267SAlexander Motin if (pcs->msicount) 709e95725cbSMatt Jacob pci_release_msi(dev); 710e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 711d876d6c3SAlexander Motin if (pcs->regs1) 712d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 713cd201b7bSAlexander Motin if (pcs->regs2) 714cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 715a1fa0267SAlexander Motin isp_pci_mbxdmafree(isp); 716e95725cbSMatt Jacob if (pcs->pci_isp.isp_param) { 717e95725cbSMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 718e95725cbSMatt Jacob pcs->pci_isp.isp_param = NULL; 719e95725cbSMatt Jacob } 720a6222dd7SAlexander Motin if (pcs->pci_isp.isp_osinfo.fc) { 721a6222dd7SAlexander Motin free(pcs->pci_isp.isp_osinfo.fc, M_DEVBUF); 722a6222dd7SAlexander Motin pcs->pci_isp.isp_osinfo.fc = NULL; 723e95725cbSMatt Jacob } 72413d9c921SAlexander Motin mtx_destroy(&isp->isp_lock); 72510365e5aSMatt Jacob return (0); 72610365e5aSMatt Jacob } 72710365e5aSMatt Jacob 728cd201b7bSAlexander Motin #define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off)) 729cd201b7bSAlexander Motin #define BXW2(isp, off, v) bus_write_2((isp)->isp_regs, (off), (v)) 730cd201b7bSAlexander Motin #define BXR4(isp, off) bus_read_4((isp)->isp_regs, (off)) 731cd201b7bSAlexander Motin #define BXW4(isp, off, v) bus_write_4((isp)->isp_regs, (off), (v)) 732cd201b7bSAlexander Motin #define B2R4(isp, off) bus_read_4((isp)->isp_regs2, (off)) 733cd201b7bSAlexander Motin #define B2W4(isp, off, v) bus_write_4((isp)->isp_regs2, (off), (v)) 734126ec864SMatt Jacob 7350e6bc811SAlexander Motin static void 7360e6bc811SAlexander Motin isp_pci_run_isr_2400(ispsoftc_t *isp) 73710365e5aSMatt Jacob { 73810365e5aSMatt Jacob uint32_t r2hisr; 7390e6bc811SAlexander Motin uint16_t isr, info; 74010365e5aSMatt Jacob 7411b760be4SAlexander Motin r2hisr = BXR4(isp, BIU2400_R2HSTS); 74210365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 7430e6bc811SAlexander Motin if ((r2hisr & BIU_R2HST_INTR) == 0) 7440e6bc811SAlexander Motin return; 7450e6bc811SAlexander Motin isr = r2hisr & BIU_R2HST_ISTAT_MASK; 7460e6bc811SAlexander Motin info = (r2hisr >> 16); 7470e6bc811SAlexander Motin switch (isr) { 7486ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_OK: 7496ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_FAIL: 7506ce548a1SAlexander Motin case ISPR2HST_MBX_OK: 7516ce548a1SAlexander Motin case ISPR2HST_MBX_FAIL: 7520e6bc811SAlexander Motin isp_intr_mbox(isp, info); 7530e6bc811SAlexander Motin break; 7546ce548a1SAlexander Motin case ISPR2HST_ASYNC_EVENT: 7550e6bc811SAlexander Motin isp_intr_async(isp, info); 7566ce548a1SAlexander Motin break; 7576ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE: 7580e6bc811SAlexander Motin isp_intr_respq(isp); 7590e6bc811SAlexander Motin break; 7606ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE2: 7610e6bc811SAlexander Motin #ifdef ISP_TARGET_MODE 7626ce548a1SAlexander Motin case ISPR2HST_ATIO_RSPQ_UPDATE: 7630e6bc811SAlexander Motin #endif 7640e6bc811SAlexander Motin isp_intr_respq(isp); 7650e6bc811SAlexander Motin /* FALLTHROUGH */ 7660e6bc811SAlexander Motin #ifdef ISP_TARGET_MODE 7670e6bc811SAlexander Motin case ISPR2HST_ATIO_UPDATE: 7686ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE2: 7690e6bc811SAlexander Motin isp_intr_atioq(isp); 7700e6bc811SAlexander Motin #endif 7716ce548a1SAlexander Motin break; 77210365e5aSMatt Jacob default: 77310365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 77410365e5aSMatt Jacob } 7750e6bc811SAlexander Motin ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 77610365e5aSMatt Jacob } 77710365e5aSMatt Jacob 77810365e5aSMatt Jacob static uint32_t 77910365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 78010365e5aSMatt Jacob { 78110365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 78210365e5aSMatt Jacob 78310365e5aSMatt Jacob switch (block) { 78410365e5aSMatt Jacob case BIU_BLOCK: 7851b760be4SAlexander Motin return (BXR4(isp, regoff)); 78610365e5aSMatt Jacob case MBOX_BLOCK: 7871b760be4SAlexander Motin return (BXR2(isp, regoff)); 7881b760be4SAlexander Motin } 789cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block read at 0x%x", regoff); 79010365e5aSMatt Jacob return (0xffffffff); 79110365e5aSMatt Jacob } 79210365e5aSMatt Jacob 79310365e5aSMatt Jacob static void 79410365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 79510365e5aSMatt Jacob { 79610365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 79710365e5aSMatt Jacob 79810365e5aSMatt Jacob switch (block) { 79910365e5aSMatt Jacob case BIU_BLOCK: 8001b760be4SAlexander Motin BXW4(isp, regoff, val); 80107d925faSAlexander Motin #ifdef MEMORYBARRIERW 80207d925faSAlexander Motin if (regoff == BIU2400_REQINP || 80307d925faSAlexander Motin regoff == BIU2400_RSPOUTP || 80407d925faSAlexander Motin regoff == BIU2400_PRI_REQINP || 80507d925faSAlexander Motin regoff == BIU2400_ATIO_RSPOUTP) 8061b760be4SAlexander Motin MEMORYBARRIERW(isp, SYNC_REG, regoff, 4, -1) 80707d925faSAlexander Motin else 80807d925faSAlexander Motin #endif 8091b760be4SAlexander Motin MEMORYBARRIER(isp, SYNC_REG, regoff, 4, -1); 8101b760be4SAlexander Motin return; 8111b760be4SAlexander Motin case MBOX_BLOCK: 8121b760be4SAlexander Motin BXW2(isp, regoff, val); 8131b760be4SAlexander Motin MEMORYBARRIER(isp, SYNC_REG, regoff, 2, -1); 8141b760be4SAlexander Motin return; 815d59bd469SMatt Jacob } 8161b760be4SAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block write at 0x%x", regoff); 817d59bd469SMatt Jacob } 818d59bd469SMatt Jacob 819cd201b7bSAlexander Motin static uint32_t 820cd201b7bSAlexander Motin isp_pci_rd_reg_2600(ispsoftc_t *isp, int regoff) 821cd201b7bSAlexander Motin { 822cd201b7bSAlexander Motin uint32_t rv; 823cd201b7bSAlexander Motin 824cd201b7bSAlexander Motin switch (regoff) { 825cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 826cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 827cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x", 828cd201b7bSAlexander Motin regoff); 829cd201b7bSAlexander Motin rv = 0xffffffff; 830cd201b7bSAlexander Motin break; 831cd201b7bSAlexander Motin case BIU2400_REQINP: 832cd201b7bSAlexander Motin rv = B2R4(isp, 0x00); 833cd201b7bSAlexander Motin break; 834cd201b7bSAlexander Motin case BIU2400_REQOUTP: 835cd201b7bSAlexander Motin rv = B2R4(isp, 0x04); 836cd201b7bSAlexander Motin break; 837cd201b7bSAlexander Motin case BIU2400_RSPINP: 838cd201b7bSAlexander Motin rv = B2R4(isp, 0x08); 839cd201b7bSAlexander Motin break; 840cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 841cd201b7bSAlexander Motin rv = B2R4(isp, 0x0c); 842cd201b7bSAlexander Motin break; 843cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 844cd201b7bSAlexander Motin rv = B2R4(isp, 0x10); 845cd201b7bSAlexander Motin break; 846cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 847cd201b7bSAlexander Motin rv = B2R4(isp, 0x14); 848cd201b7bSAlexander Motin break; 849cd201b7bSAlexander Motin default: 850cd201b7bSAlexander Motin rv = isp_pci_rd_reg_2400(isp, regoff); 851cd201b7bSAlexander Motin break; 852cd201b7bSAlexander Motin } 853cd201b7bSAlexander Motin return (rv); 854cd201b7bSAlexander Motin } 855cd201b7bSAlexander Motin 856cd201b7bSAlexander Motin static void 857cd201b7bSAlexander Motin isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val) 858cd201b7bSAlexander Motin { 859cd201b7bSAlexander Motin int off; 860cd201b7bSAlexander Motin 861cd201b7bSAlexander Motin switch (regoff) { 862cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 863cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 864cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x", 865cd201b7bSAlexander Motin regoff); 866cd201b7bSAlexander Motin return; 867cd201b7bSAlexander Motin case BIU2400_REQINP: 868cd201b7bSAlexander Motin off = 0x00; 869cd201b7bSAlexander Motin break; 870cd201b7bSAlexander Motin case BIU2400_REQOUTP: 871cd201b7bSAlexander Motin off = 0x04; 872cd201b7bSAlexander Motin break; 873cd201b7bSAlexander Motin case BIU2400_RSPINP: 874cd201b7bSAlexander Motin off = 0x08; 875cd201b7bSAlexander Motin break; 876cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 877cd201b7bSAlexander Motin off = 0x0c; 878cd201b7bSAlexander Motin break; 879cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 880cd201b7bSAlexander Motin off = 0x10; 881cd201b7bSAlexander Motin break; 882cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 883cd201b7bSAlexander Motin off = 0x14; 884cd201b7bSAlexander Motin break; 885cd201b7bSAlexander Motin default: 886cd201b7bSAlexander Motin isp_pci_wr_reg_2400(isp, regoff, val); 887cd201b7bSAlexander Motin return; 888cd201b7bSAlexander Motin } 889cd201b7bSAlexander Motin B2W4(isp, off, val); 890cd201b7bSAlexander Motin } 891cd201b7bSAlexander Motin 892d720e6d5SJustin T. Gibbs 893222bb542SMatt Jacob struct imush { 89414849e2cSAlexander Motin bus_addr_t maddr; 895222bb542SMatt Jacob int error; 896222bb542SMatt Jacob }; 897222bb542SMatt Jacob 898d720e6d5SJustin T. Gibbs static void 8991923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 900d720e6d5SJustin T. Gibbs { 901222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 9022df76c16SMatt Jacob 90314849e2cSAlexander Motin if (!(imushp->error = error)) 90414849e2cSAlexander Motin imushp->maddr = segs[0].ds_addr; 905d720e6d5SJustin T. Gibbs } 906d720e6d5SJustin T. Gibbs 907d720e6d5SJustin T. Gibbs static int 9089cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 909d720e6d5SJustin T. Gibbs { 910254c652bSAlexander Motin bus_dma_tag_t ptag; 911d720e6d5SJustin T. Gibbs caddr_t base; 9121b760be4SAlexander Motin uint32_t len; 913254c652bSAlexander Motin int i, error, cmap; 91453af7d22SMatt Jacob bus_size_t slim; /* segment size */ 915222bb542SMatt Jacob struct imush im; 916dae0ba75SAlexander Motin #ifdef ISP_TARGET_MODE 9171b760be4SAlexander Motin isp_ecmd_t *ecmd; 918dae0ba75SAlexander Motin #endif 919222bb542SMatt Jacob 920a1fa0267SAlexander Motin /* Already been here? If so, leave... */ 921a1fa0267SAlexander Motin if (isp->isp_xflist != NULL) 922a95ae193SMatt Jacob return (0); 923a1fa0267SAlexander Motin if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0) 924a1fa0267SAlexander Motin return (0); 9250a70657fSMatt Jacob ISP_UNLOCK(isp); 92610365e5aSMatt Jacob 927254c652bSAlexander Motin ptag = bus_get_dma_tag(isp->isp_osinfo.dev); 928a1fa0267SAlexander Motin if (sizeof (bus_size_t) > 4) 92953af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 930a1fa0267SAlexander Motin else 9319b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 932254c652bSAlexander Motin 933254c652bSAlexander Motin if (isp->isp_rquest != NULL) 934254c652bSAlexander Motin goto gotmaxcmds; 9351923f739SMatt Jacob 936d720e6d5SJustin T. Gibbs /* 937cf770ba3SAlexander Motin * Allocate and map the request queue. 938d720e6d5SJustin T. Gibbs */ 939d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 940254c652bSAlexander Motin if (bus_dma_tag_create(ptag, QENTRY_LEN, slim, 9411b760be4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 9429cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.reqdmat)) { 94314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); 944a1fa0267SAlexander Motin goto bad; 94514849e2cSAlexander Motin } 94614849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, 94714849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { 94814849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); 94914849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 950a1fa0267SAlexander Motin goto bad; 95114849e2cSAlexander Motin } 95214849e2cSAlexander Motin isp->isp_rquest = base; 95314849e2cSAlexander Motin im.error = 0; 95414849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, 9559cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 95614849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); 957a1fa0267SAlexander Motin goto bad; 95814849e2cSAlexander Motin } 95914849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", 96014849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 96114849e2cSAlexander Motin isp->isp_rquest_dma = im.maddr; 962cf770ba3SAlexander Motin 963cf770ba3SAlexander Motin #ifdef ISP_TARGET_MODE 964cf770ba3SAlexander Motin /* 965cf770ba3SAlexander Motin * Allocate region for external DMA addressable command/status structures. 966cf770ba3SAlexander Motin */ 967cf770ba3SAlexander Motin len = N_XCMDS * XCMD_SIZE; 968254c652bSAlexander Motin if (bus_dma_tag_create(ptag, XCMD_SIZE, slim, 9691b760be4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 970cf770ba3SAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.ecmd_dmat)) { 971cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create ECMD DMA tag"); 972cf770ba3SAlexander Motin goto bad; 973cf770ba3SAlexander Motin } 974cf770ba3SAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.ecmd_dmat, (void **)&base, 975cf770ba3SAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.ecmd_map) != 0) { 976cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate ECMD DMA memory"); 977254c652bSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.ecmd_dmat); 978cf770ba3SAlexander Motin goto bad; 979cf770ba3SAlexander Motin } 980cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_base = (isp_ecmd_t *)base; 981cf770ba3SAlexander Motin im.error = 0; 982cf770ba3SAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.ecmd_dmat, isp->isp_osinfo.ecmd_map, 983cf770ba3SAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 984cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading ECMD DMA map %d", im.error); 985cf770ba3SAlexander Motin goto bad; 986cf770ba3SAlexander Motin } 987cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "ecmd area @ 0x%jx/0x%jx", 988cf770ba3SAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 989cf770ba3SAlexander Motin 99014849e2cSAlexander Motin isp->isp_osinfo.ecmd_dma = im.maddr; 99114849e2cSAlexander Motin isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)base; 99214849e2cSAlexander Motin for (ecmd = isp->isp_osinfo.ecmd_free; 99314849e2cSAlexander Motin ecmd < &isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { 99414849e2cSAlexander Motin if (ecmd == &isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) 99514849e2cSAlexander Motin ecmd->next = NULL; 99614849e2cSAlexander Motin else 99714849e2cSAlexander Motin ecmd->next = ecmd + 1; 99814849e2cSAlexander Motin } 999cf770ba3SAlexander Motin #endif 10002df76c16SMatt Jacob 100153af7d22SMatt Jacob /* 100214849e2cSAlexander Motin * Allocate and map the result queue. 100353af7d22SMatt Jacob */ 100414849e2cSAlexander Motin len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1005254c652bSAlexander Motin if (bus_dma_tag_create(ptag, QENTRY_LEN, slim, 10061b760be4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 10079cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.respdmat)) { 100814849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); 1009a1fa0267SAlexander Motin goto bad; 1010d720e6d5SJustin T. Gibbs } 101114849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, 101214849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { 101314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); 101414849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 1015a1fa0267SAlexander Motin goto bad; 1016222bb542SMatt Jacob } 101714849e2cSAlexander Motin isp->isp_result = base; 10182df76c16SMatt Jacob im.error = 0; 101914849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, 10209cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 102114849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); 1022a1fa0267SAlexander Motin goto bad; 102314849e2cSAlexander Motin } 102414849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", 102514849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 102614849e2cSAlexander Motin isp->isp_result_dma = im.maddr; 10272df76c16SMatt Jacob 102814849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 102914849e2cSAlexander Motin /* 1030b8e2395eSAlexander Motin * Allocate and map ATIO queue. 103114849e2cSAlexander Motin */ 1032b8e2395eSAlexander Motin len = ISP_QUEUE_SIZE(ATIO_QUEUE_LEN(isp)); 1033254c652bSAlexander Motin if (bus_dma_tag_create(ptag, QENTRY_LEN, slim, 10341b760be4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 10359cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.atiodmat)) { 103614849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag"); 1037a1fa0267SAlexander Motin goto bad; 103814849e2cSAlexander Motin } 103914849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base, 104014849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) { 104114849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory"); 104214849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 1043a1fa0267SAlexander Motin goto bad; 104414849e2cSAlexander Motin } 104514849e2cSAlexander Motin isp->isp_atioq = base; 104614849e2cSAlexander Motin im.error = 0; 104714849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap, 10489cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 104914849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading ATIO DMA map %d", im.error); 10502df76c16SMatt Jacob goto bad; 10512df76c16SMatt Jacob } 105214849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "ATIO area @ 0x%jx/0x%jx", 105314849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 105414849e2cSAlexander Motin isp->isp_atioq_dma = im.maddr; 105514849e2cSAlexander Motin #endif 10562df76c16SMatt Jacob 1057254c652bSAlexander Motin if (bus_dma_tag_create(ptag, 64, slim, 10587d191fdbSAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 10599cca0e7eSAlexander Motin 2*QENTRY_LEN, 1, 2*QENTRY_LEN, 0, NULL, NULL, 10609cca0e7eSAlexander Motin &isp->isp_osinfo.iocbdmat)) { 10612df76c16SMatt Jacob goto bad; 10622df76c16SMatt Jacob } 10634ff970c4SAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.iocbdmat, 10644ff970c4SAlexander Motin (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.iocbmap) != 0) 10654ff970c4SAlexander Motin goto bad; 10664ff970c4SAlexander Motin isp->isp_iocb = base; 10674ff970c4SAlexander Motin im.error = 0; 10684ff970c4SAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap, 10699cca0e7eSAlexander Motin base, 2*QENTRY_LEN, imc, &im, BUS_DMA_NOWAIT) || im.error) 10704ff970c4SAlexander Motin goto bad; 10714ff970c4SAlexander Motin isp->isp_iocb_dma = im.maddr; 10724ff970c4SAlexander Motin 1073254c652bSAlexander Motin if (bus_dma_tag_create(ptag, 64, slim, 10744ff970c4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 10759cca0e7eSAlexander Motin ISP_FC_SCRLEN, 1, ISP_FC_SCRLEN, 0, NULL, NULL, 10769cca0e7eSAlexander Motin &isp->isp_osinfo.scdmat)) 10774ff970c4SAlexander Motin goto bad; 10787d191fdbSAlexander Motin for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 10797d191fdbSAlexander Motin struct isp_fc *fc = ISP_FC_PC(isp, cmap); 10807d191fdbSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.scdmat, 108114849e2cSAlexander Motin (void **)&base, BUS_DMA_COHERENT, &fc->scmap) != 0) 10822df76c16SMatt Jacob goto bad; 108314849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scratch = base; 10842df76c16SMatt Jacob im.error = 0; 108514849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap, 10869cca0e7eSAlexander Motin base, ISP_FC_SCRLEN, imc, &im, BUS_DMA_NOWAIT) || 10879cca0e7eSAlexander Motin im.error) { 10887d191fdbSAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 10897d191fdbSAlexander Motin base, fc->scmap); 1090a1fa0267SAlexander Motin FCPARAM(isp, cmap)->isp_scratch = NULL; 10912df76c16SMatt Jacob goto bad; 10922df76c16SMatt Jacob } 109314849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scdma = im.maddr; 1094387d8239SMatt Jacob for (i = 0; i < INITIAL_NEXUS_COUNT; i++) { 1095387d8239SMatt Jacob struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO); 1096387d8239SMatt Jacob if (n == NULL) { 1097387d8239SMatt Jacob while (fc->nexus_free_list) { 1098387d8239SMatt Jacob n = fc->nexus_free_list; 1099387d8239SMatt Jacob fc->nexus_free_list = n->next; 1100387d8239SMatt Jacob free(n, M_DEVBUF); 1101387d8239SMatt Jacob } 1102387d8239SMatt Jacob goto bad; 1103387d8239SMatt Jacob } 1104387d8239SMatt Jacob n->next = fc->nexus_free_list; 1105387d8239SMatt Jacob fc->nexus_free_list = n; 1106387d8239SMatt Jacob } 11072df76c16SMatt Jacob } 11082df76c16SMatt Jacob 1109a1fa0267SAlexander Motin if (isp->isp_maxcmds == 0) { 1110a1fa0267SAlexander Motin ISP_LOCK(isp); 1111a1fa0267SAlexander Motin return (0); 1112a1fa0267SAlexander Motin } 1113a1fa0267SAlexander Motin 1114a1fa0267SAlexander Motin gotmaxcmds: 1115254c652bSAlexander Motin if (bus_dma_tag_create(ptag, 1, slim, 1116254c652bSAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 1117254c652bSAlexander Motin (ISP_NSEG64_MAX - 1) * PAGE_SIZE, ISP_NSEG64_MAX, 1118254c652bSAlexander Motin (ISP_NSEG64_MAX - 1) * PAGE_SIZE, 0, 1119254c652bSAlexander Motin busdma_lock_mutex, &isp->isp_lock, &isp->isp_osinfo.dmat)) 1120254c652bSAlexander Motin goto bad; 1121a1fa0267SAlexander Motin len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 1122a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) 1123a1fa0267SAlexander Motin malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1124a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 11250a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 11260a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1127d720e6d5SJustin T. Gibbs if (error) { 11282df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 11291923f739SMatt Jacob while (--i >= 0) { 1130a1fa0267SAlexander Motin bus_dmamap_destroy(isp->isp_osinfo.dmat, 1131a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool[i].dmap); 11321923f739SMatt Jacob } 11331923f739SMatt Jacob goto bad; 1134d720e6d5SJustin T. Gibbs } 113513d9c921SAlexander Motin callout_init_mtx(&pcmd->wdog, &isp->isp_lock, 0); 1136a1fa0267SAlexander Motin if (i == isp->isp_maxcmds-1) 11370a70657fSMatt Jacob pcmd->next = NULL; 1138a1fa0267SAlexander Motin else 11390a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1140d720e6d5SJustin T. Gibbs } 11410a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 1142a1fa0267SAlexander Motin 11430b19f90aSAlexander Motin len = sizeof(isp_hdl_t) * ISP_HANDLE_NUM(isp); 1144a1fa0267SAlexander Motin isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 11450b19f90aSAlexander Motin for (len = 0; len < ISP_HANDLE_NUM(isp) - 1; len++) 1146a1fa0267SAlexander Motin isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1147a1fa0267SAlexander Motin isp->isp_xffree = isp->isp_xflist; 1148a1fa0267SAlexander Motin 114972429e49SMatt Jacob ISP_LOCK(isp); 1150d720e6d5SJustin T. Gibbs return (0); 11511923f739SMatt Jacob 11521923f739SMatt Jacob bad: 1153a1fa0267SAlexander Motin isp_pci_mbxdmafree(isp); 1154a1fa0267SAlexander Motin ISP_LOCK(isp); 1155a1fa0267SAlexander Motin return (1); 1156a1fa0267SAlexander Motin } 1157a1fa0267SAlexander Motin 1158a1fa0267SAlexander Motin static void 1159a1fa0267SAlexander Motin isp_pci_mbxdmafree(ispsoftc_t *isp) 1160a1fa0267SAlexander Motin { 1161a1fa0267SAlexander Motin int i; 1162a1fa0267SAlexander Motin 1163a1fa0267SAlexander Motin if (isp->isp_xflist != NULL) { 1164a1fa0267SAlexander Motin free(isp->isp_xflist, M_DEVBUF); 1165a1fa0267SAlexander Motin isp->isp_xflist = NULL; 1166a1fa0267SAlexander Motin } 1167a1fa0267SAlexander Motin if (isp->isp_osinfo.pcmd_pool != NULL) { 1168a1fa0267SAlexander Motin for (i = 0; i < isp->isp_maxcmds; i++) { 1169a1fa0267SAlexander Motin bus_dmamap_destroy(isp->isp_osinfo.dmat, 1170a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool[i].dmap); 1171a1fa0267SAlexander Motin } 1172a1fa0267SAlexander Motin free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1173a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool = NULL; 1174a1fa0267SAlexander Motin } 1175254c652bSAlexander Motin if (isp->isp_osinfo.dmat) { 1176254c652bSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.dmat); 1177254c652bSAlexander Motin isp->isp_osinfo.dmat = NULL; 1178254c652bSAlexander Motin } 1179a1fa0267SAlexander Motin for (i = 0; i < isp->isp_nchan; i++) { 1180a1fa0267SAlexander Motin struct isp_fc *fc = ISP_FC_PC(isp, i); 1181a1fa0267SAlexander Motin if (FCPARAM(isp, i)->isp_scdma != 0) { 1182a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.scdmat, 1183a1fa0267SAlexander Motin fc->scmap); 1184a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scdma = 0; 1185a1fa0267SAlexander Motin } 1186a1fa0267SAlexander Motin if (FCPARAM(isp, i)->isp_scratch != NULL) { 11874ff970c4SAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 1188a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scratch, fc->scmap); 1189a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scratch = NULL; 1190a1fa0267SAlexander Motin } 1191387d8239SMatt Jacob while (fc->nexus_free_list) { 1192387d8239SMatt Jacob struct isp_nexus *n = fc->nexus_free_list; 1193387d8239SMatt Jacob fc->nexus_free_list = n->next; 1194387d8239SMatt Jacob free(n, M_DEVBUF); 1195387d8239SMatt Jacob } 11962df76c16SMatt Jacob } 1197254c652bSAlexander Motin if (isp->isp_osinfo.scdmat) { 11987d191fdbSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.scdmat); 1199254c652bSAlexander Motin isp->isp_osinfo.scdmat = NULL; 1200254c652bSAlexander Motin } 1201254c652bSAlexander Motin if (isp->isp_iocb_dma != 0) { 1202a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.iocbdmat, 12034ff970c4SAlexander Motin isp->isp_osinfo.iocbmap); 1204a1fa0267SAlexander Motin isp->isp_iocb_dma = 0; 1205a1fa0267SAlexander Motin } 1206a1fa0267SAlexander Motin if (isp->isp_iocb != NULL) { 1207a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.iocbdmat, 1208a1fa0267SAlexander Motin isp->isp_iocb, isp->isp_osinfo.iocbmap); 12094ff970c4SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat); 12107d191fdbSAlexander Motin } 121114849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 121214849e2cSAlexander Motin if (isp->isp_atioq_dma != 0) { 121314849e2cSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.atiodmat, 121414849e2cSAlexander Motin isp->isp_osinfo.atiomap); 1215a1fa0267SAlexander Motin isp->isp_atioq_dma = 0; 121614849e2cSAlexander Motin } 121714849e2cSAlexander Motin if (isp->isp_atioq != NULL) { 1218a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.atiodmat, isp->isp_atioq, 121914849e2cSAlexander Motin isp->isp_osinfo.atiomap); 122014849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 1221a1fa0267SAlexander Motin isp->isp_atioq = NULL; 122214849e2cSAlexander Motin } 122314849e2cSAlexander Motin #endif 1224a1fa0267SAlexander Motin if (isp->isp_result_dma != 0) { 1225a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.respdmat, 1226a1fa0267SAlexander Motin isp->isp_osinfo.respmap); 1227a1fa0267SAlexander Motin isp->isp_result_dma = 0; 1228a1fa0267SAlexander Motin } 1229a1fa0267SAlexander Motin if (isp->isp_result != NULL) { 1230a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, 1231a1fa0267SAlexander Motin isp->isp_osinfo.respmap); 1232a1fa0267SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 1233a1fa0267SAlexander Motin isp->isp_result = NULL; 1234a1fa0267SAlexander Motin } 1235cf770ba3SAlexander Motin #ifdef ISP_TARGET_MODE 1236cf770ba3SAlexander Motin if (isp->isp_osinfo.ecmd_dma != 0) { 1237cf770ba3SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.ecmd_dmat, 1238cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_map); 1239cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_dma = 0; 1240cf770ba3SAlexander Motin } 1241cf770ba3SAlexander Motin if (isp->isp_osinfo.ecmd_base != NULL) { 1242cf770ba3SAlexander Motin bus_dmamem_free(isp->isp_osinfo.ecmd_dmat, isp->isp_osinfo.ecmd_base, 1243cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_map); 1244cf770ba3SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.ecmd_dmat); 1245cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_base = NULL; 1246cf770ba3SAlexander Motin } 1247cf770ba3SAlexander Motin #endif 1248a1fa0267SAlexander Motin if (isp->isp_rquest_dma != 0) { 1249a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.reqdmat, 1250a1fa0267SAlexander Motin isp->isp_osinfo.reqmap); 1251a1fa0267SAlexander Motin isp->isp_rquest_dma = 0; 1252a1fa0267SAlexander Motin } 1253a1fa0267SAlexander Motin if (isp->isp_rquest != NULL) { 1254a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, 1255a1fa0267SAlexander Motin isp->isp_osinfo.reqmap); 1256a1fa0267SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 12571923f739SMatt Jacob isp->isp_rquest = NULL; 1258a1fa0267SAlexander Motin } 1259d720e6d5SJustin T. Gibbs } 1260d720e6d5SJustin T. Gibbs 1261a1fa0267SAlexander Motin static int 1262a1fa0267SAlexander Motin isp_pci_irqsetup(ispsoftc_t *isp) 12633bda7a83SMatt Jacob { 126408826086SAlexander Motin device_t dev = isp->isp_osinfo.dev; 126508826086SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 126608826086SAlexander Motin driver_intr_t *f; 126708826086SAlexander Motin int i, max_irq; 12683bda7a83SMatt Jacob 126908826086SAlexander Motin /* Allocate IRQs only once. */ 127008826086SAlexander Motin if (isp->isp_nirq > 0) 1271a1fa0267SAlexander Motin return (0); 127208826086SAlexander Motin 1273abdc2e31SAlexander Motin ISP_UNLOCK(isp); 127408826086SAlexander Motin if (ISP_CAP_MSIX(isp)) { 12751f8c4546SAlexander Motin max_irq = IS_26XX(isp) ? 3 : (IS_25XX(isp) ? 2 : 0); 127617ec7746SAlexander Motin resource_int_value(device_get_name(dev), 127717ec7746SAlexander Motin device_get_unit(dev), "msix", &max_irq); 127817ec7746SAlexander Motin max_irq = imin(ISP_MAX_IRQS, max_irq); 127908826086SAlexander Motin pcs->msicount = imin(pci_msix_count(dev), max_irq); 128008826086SAlexander Motin if (pcs->msicount > 0 && 128108826086SAlexander Motin pci_alloc_msix(dev, &pcs->msicount) != 0) 128208826086SAlexander Motin pcs->msicount = 0; 128308826086SAlexander Motin } 128408826086SAlexander Motin if (pcs->msicount == 0) { 128517ec7746SAlexander Motin max_irq = 1; 128617ec7746SAlexander Motin resource_int_value(device_get_name(dev), 128717ec7746SAlexander Motin device_get_unit(dev), "msi", &max_irq); 128817ec7746SAlexander Motin max_irq = imin(1, max_irq); 128917ec7746SAlexander Motin pcs->msicount = imin(pci_msi_count(dev), max_irq); 129008826086SAlexander Motin if (pcs->msicount > 0 && 129108826086SAlexander Motin pci_alloc_msi(dev, &pcs->msicount) != 0) 129208826086SAlexander Motin pcs->msicount = 0; 129308826086SAlexander Motin } 129408826086SAlexander Motin for (i = 0; i < MAX(1, pcs->msicount); i++) { 129508826086SAlexander Motin pcs->irq[i].iqd = i + (pcs->msicount > 0); 129608826086SAlexander Motin pcs->irq[i].irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 129708826086SAlexander Motin &pcs->irq[i].iqd, RF_ACTIVE | RF_SHAREABLE); 129808826086SAlexander Motin if (pcs->irq[i].irq == NULL) { 129908826086SAlexander Motin device_printf(dev, "could not allocate interrupt\n"); 130008826086SAlexander Motin break; 130108826086SAlexander Motin } 130208826086SAlexander Motin if (i == 0) 130308826086SAlexander Motin f = isp_platform_intr; 130408826086SAlexander Motin else if (i == 1) 130508826086SAlexander Motin f = isp_platform_intr_resp; 130608826086SAlexander Motin else 130708826086SAlexander Motin f = isp_platform_intr_atio; 130808826086SAlexander Motin if (bus_setup_intr(dev, pcs->irq[i].irq, ISP_IFLAGS, NULL, 130908826086SAlexander Motin f, isp, &pcs->irq[i].ih)) { 131008826086SAlexander Motin device_printf(dev, "could not setup interrupt\n"); 131108826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, 131208826086SAlexander Motin pcs->irq[i].iqd, pcs->irq[i].irq); 131308826086SAlexander Motin break; 131408826086SAlexander Motin } 131508826086SAlexander Motin if (pcs->msicount > 1) { 131608826086SAlexander Motin bus_describe_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih, 131708826086SAlexander Motin "%d", i); 131808826086SAlexander Motin } 131908826086SAlexander Motin isp->isp_nirq = i + 1; 132008826086SAlexander Motin } 1321abdc2e31SAlexander Motin ISP_LOCK(isp); 132208826086SAlexander Motin 132308826086SAlexander Motin return (isp->isp_nirq == 0); 132465adb54cSMatt Jacob } 1325