1aad970f1SDavid E. O'Brien /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 414e084adSAlexander Motin * Copyright (c) 2009-2018 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(ispsoftc_t *, int); 5410365e5aSMatt Jacob static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t); 5510365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int); 5610365e5aSMatt Jacob static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t); 5710365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); 5810365e5aSMatt Jacob static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); 59cd201b7bSAlexander Motin static uint32_t isp_pci_rd_reg_2600(ispsoftc_t *, int); 60cd201b7bSAlexander Motin static void isp_pci_wr_reg_2600(ispsoftc_t *, int, uint32_t); 610e6bc811SAlexander Motin static void isp_pci_run_isr(ispsoftc_t *); 620e6bc811SAlexander Motin static void isp_pci_run_isr_2300(ispsoftc_t *); 630e6bc811SAlexander Motin static void isp_pci_run_isr_2400(ispsoftc_t *); 649cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *); 65a1fa0267SAlexander Motin static void isp_pci_mbxdmafree(ispsoftc_t *); 662df76c16SMatt Jacob static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *); 67a1fa0267SAlexander Motin static int isp_pci_irqsetup(ispsoftc_t *); 689cd7268eSMatt Jacob static void isp_pci_dumpregs(ispsoftc_t *, const char *); 6965adb54cSMatt Jacob 7065adb54cSMatt Jacob static struct ispmdvec mdvec = { 710e6bc811SAlexander Motin isp_pci_run_isr, 7265adb54cSMatt Jacob isp_pci_rd_reg, 7365adb54cSMatt Jacob isp_pci_wr_reg, 7465adb54cSMatt Jacob isp_pci_mbxdma, 7565adb54cSMatt Jacob isp_pci_dmasetup, 760a70657fSMatt Jacob isp_common_dmateardown, 77a1fa0267SAlexander Motin isp_pci_irqsetup, 7865adb54cSMatt Jacob isp_pci_dumpregs, 7956aef503SMatt Jacob NULL, 80d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 8165adb54cSMatt Jacob }; 8265adb54cSMatt Jacob 83d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 840e6bc811SAlexander Motin isp_pci_run_isr, 85d59bd469SMatt Jacob isp_pci_rd_reg_1080, 86d59bd469SMatt Jacob isp_pci_wr_reg_1080, 87d59bd469SMatt Jacob isp_pci_mbxdma, 88d59bd469SMatt Jacob isp_pci_dmasetup, 890a70657fSMatt Jacob isp_common_dmateardown, 90a1fa0267SAlexander Motin isp_pci_irqsetup, 91d59bd469SMatt Jacob isp_pci_dumpregs, 9256aef503SMatt Jacob NULL, 93d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 94d59bd469SMatt Jacob }; 95d59bd469SMatt Jacob 96960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = { 970e6bc811SAlexander Motin isp_pci_run_isr, 98960f6939SMatt Jacob isp_pci_rd_reg_1080, 99960f6939SMatt Jacob isp_pci_wr_reg_1080, 100960f6939SMatt Jacob isp_pci_mbxdma, 101960f6939SMatt Jacob isp_pci_dmasetup, 1020a70657fSMatt Jacob isp_common_dmateardown, 103a1fa0267SAlexander Motin isp_pci_irqsetup, 104960f6939SMatt Jacob isp_pci_dumpregs, 10556aef503SMatt Jacob NULL, 106d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 107960f6939SMatt Jacob }; 108960f6939SMatt Jacob 10965adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 1100e6bc811SAlexander Motin isp_pci_run_isr, 11165adb54cSMatt Jacob isp_pci_rd_reg, 11265adb54cSMatt Jacob isp_pci_wr_reg, 11365adb54cSMatt Jacob isp_pci_mbxdma, 11465adb54cSMatt Jacob isp_pci_dmasetup, 1150a70657fSMatt Jacob isp_common_dmateardown, 116a1fa0267SAlexander Motin isp_pci_irqsetup, 117d02373f1SMatt Jacob isp_pci_dumpregs 11865adb54cSMatt Jacob }; 119222bb542SMatt Jacob 120222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 1210e6bc811SAlexander Motin isp_pci_run_isr, 122126ec864SMatt Jacob isp_pci_rd_reg, 123126ec864SMatt Jacob isp_pci_wr_reg, 124126ec864SMatt Jacob isp_pci_mbxdma, 125126ec864SMatt Jacob isp_pci_dmasetup, 1260a70657fSMatt Jacob isp_common_dmateardown, 127a1fa0267SAlexander Motin isp_pci_irqsetup, 128126ec864SMatt Jacob isp_pci_dumpregs 129126ec864SMatt Jacob }; 130126ec864SMatt Jacob 131126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = { 1320e6bc811SAlexander Motin isp_pci_run_isr_2300, 133222bb542SMatt Jacob isp_pci_rd_reg, 134222bb542SMatt Jacob isp_pci_wr_reg, 135222bb542SMatt Jacob isp_pci_mbxdma, 136222bb542SMatt Jacob isp_pci_dmasetup, 1370a70657fSMatt Jacob isp_common_dmateardown, 138a1fa0267SAlexander Motin isp_pci_irqsetup, 139d02373f1SMatt Jacob isp_pci_dumpregs 140222bb542SMatt Jacob }; 141d951bbcaSMatt Jacob 14210365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = { 1430e6bc811SAlexander Motin isp_pci_run_isr_2400, 14410365e5aSMatt Jacob isp_pci_rd_reg_2400, 14510365e5aSMatt Jacob isp_pci_wr_reg_2400, 14610365e5aSMatt Jacob isp_pci_mbxdma, 14710365e5aSMatt Jacob isp_pci_dmasetup, 1480a70657fSMatt Jacob isp_common_dmateardown, 149a1fa0267SAlexander Motin isp_pci_irqsetup, 15010365e5aSMatt Jacob NULL 15110365e5aSMatt Jacob }; 15210365e5aSMatt Jacob 1532df76c16SMatt Jacob static struct ispmdvec mdvec_2500 = { 1540e6bc811SAlexander Motin isp_pci_run_isr_2400, 1552df76c16SMatt Jacob isp_pci_rd_reg_2400, 1562df76c16SMatt Jacob isp_pci_wr_reg_2400, 1572df76c16SMatt Jacob isp_pci_mbxdma, 1582df76c16SMatt Jacob isp_pci_dmasetup, 1592df76c16SMatt Jacob isp_common_dmateardown, 160a1fa0267SAlexander Motin isp_pci_irqsetup, 1612df76c16SMatt Jacob NULL 1622df76c16SMatt Jacob }; 1632df76c16SMatt Jacob 164218be0b2SAlexander Motin static struct ispmdvec mdvec_2600 = { 1650e6bc811SAlexander Motin isp_pci_run_isr_2400, 166cd201b7bSAlexander Motin isp_pci_rd_reg_2600, 167cd201b7bSAlexander Motin isp_pci_wr_reg_2600, 168218be0b2SAlexander Motin isp_pci_mbxdma, 169218be0b2SAlexander Motin isp_pci_dmasetup, 170218be0b2SAlexander Motin isp_common_dmateardown, 171a1fa0267SAlexander Motin isp_pci_irqsetup, 172218be0b2SAlexander Motin NULL 173218be0b2SAlexander Motin }; 174218be0b2SAlexander Motin 17514e084adSAlexander Motin static struct ispmdvec mdvec_2700 = { 17614e084adSAlexander Motin isp_pci_run_isr_2400, 17714e084adSAlexander Motin isp_pci_rd_reg_2600, 17814e084adSAlexander Motin isp_pci_wr_reg_2600, 17914e084adSAlexander Motin isp_pci_mbxdma, 18014e084adSAlexander Motin isp_pci_dmasetup, 18114e084adSAlexander Motin isp_common_dmateardown, 18214e084adSAlexander Motin isp_pci_irqsetup, 18314e084adSAlexander Motin NULL 18414e084adSAlexander Motin }; 18514e084adSAlexander Motin 18665adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 18765adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 18865adb54cSMatt Jacob #endif 18965adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 19065adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 19165adb54cSMatt Jacob #endif 192d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 193d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 194d951bbcaSMatt Jacob #endif 195d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 196d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 197d951bbcaSMatt Jacob #endif 1988a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 1998a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 2008a97c03aSMatt Jacob #endif 201d951bbcaSMatt Jacob 202d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 203d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 204d951bbcaSMatt Jacob #endif 205d951bbcaSMatt Jacob 206d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 207d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 208d951bbcaSMatt Jacob #endif 209d951bbcaSMatt Jacob 210d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 211d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 212d951bbcaSMatt Jacob #endif 213d951bbcaSMatt Jacob 214ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 215ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 216ab6d0040SMatt Jacob #endif 217ab6d0040SMatt Jacob 21865adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 21965adb54cSMatt Jacob 22065adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 221d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 222f556e83bSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 223960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 224d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 22522e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 22622e1dc85SMatt Jacob 22765adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 228222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 229126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 230126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 231e5265237SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 2328872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 23341675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 2342df76c16SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2532 0x2532 235a959d921SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP5432 0x5432 23614e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 23714e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 238218be0b2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2031 0x2031 23967eeadd2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP8031 0x8031 24014e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2684 0x2171 24114e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2692 0x2b61 24214e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2714 0x2071 24314e084adSAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2722 0x2261 2449a5af410SMatt Jacob 24556aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 24656aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 247d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 248d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 249f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 250f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 251960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 252960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 253d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 254d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 25522e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 25622e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 25722e1dc85SMatt Jacob 25865adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 25965adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 260222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 261222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 262126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 263126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 264126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 265126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 266e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 267e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 2686c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 2696c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 27041675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 27141675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 2722df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 2732df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 27414e084adSAlexander Motin #define PCI_QLOGIC_ISP5432 \ 27514e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC) 276dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 277dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 2789a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 2799a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 280218be0b2SAlexander Motin #define PCI_QLOGIC_ISP2031 \ 281218be0b2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC) 28267eeadd2SAlexander Motin #define PCI_QLOGIC_ISP8031 \ 28367eeadd2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP8031 << 16) | PCI_VENDOR_QLOGIC) 28414e084adSAlexander Motin #define PCI_QLOGIC_ISP2684 \ 28514e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2684 << 16) | PCI_VENDOR_QLOGIC) 28614e084adSAlexander Motin #define PCI_QLOGIC_ISP2692 \ 28714e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2692 << 16) | PCI_VENDOR_QLOGIC) 28814e084adSAlexander Motin #define PCI_QLOGIC_ISP2714 \ 28914e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2714 << 16) | PCI_VENDOR_QLOGIC) 29014e084adSAlexander Motin #define PCI_QLOGIC_ISP2722 \ 29114e084adSAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2722 << 16) | PCI_VENDOR_QLOGIC) 29267eeadd2SAlexander Motin 293e11a1ee8SMatt Jacob /* 294e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 295e11a1ee8SMatt Jacob */ 296e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 297e11a1ee8SMatt Jacob 298d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 299d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 30065adb54cSMatt Jacob 301960f6939SMatt Jacob static int isp_pci_probe (device_t); 302960f6939SMatt Jacob static int isp_pci_attach (device_t); 30310365e5aSMatt Jacob static int isp_pci_detach (device_t); 30465adb54cSMatt Jacob 3051923f739SMatt Jacob 3060230a28bSMatt Jacob #define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev 30765adb54cSMatt Jacob struct isp_pcisoftc { 3089cd7268eSMatt Jacob ispsoftc_t pci_isp; 309960f6939SMatt Jacob device_t pci_dev; 310e95725cbSMatt Jacob struct resource * regs; 311d876d6c3SAlexander Motin struct resource * regs1; 312cd201b7bSAlexander Motin struct resource * regs2; 31308826086SAlexander Motin struct { 314e95725cbSMatt Jacob int iqd; 31508826086SAlexander Motin struct resource * irq; 31608826086SAlexander Motin void * ih; 31708826086SAlexander Motin } irq[ISP_MAX_IRQS]; 318e95725cbSMatt Jacob int rtp; 319e95725cbSMatt Jacob int rgd; 320d876d6c3SAlexander Motin int rtp1; 321d876d6c3SAlexander Motin int rgd1; 322cd201b7bSAlexander Motin int rtp2; 323cd201b7bSAlexander Motin int rgd2; 324d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3251923f739SMatt Jacob bus_dma_tag_t dmat; 3260a70657fSMatt Jacob int msicount; 32765adb54cSMatt Jacob }; 32865adb54cSMatt Jacob 32910365e5aSMatt Jacob 330960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 331960f6939SMatt Jacob /* Device interface */ 332960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 333960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 33410365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 335960f6939SMatt Jacob { 0, 0 } 33665adb54cSMatt Jacob }; 33765adb54cSMatt Jacob 338960f6939SMatt Jacob static driver_t isp_pci_driver = { 339960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 340960f6939SMatt Jacob }; 341960f6939SMatt Jacob static devclass_t isp_devclass; 342960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 343d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1); 344d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1); 3459e7d423dSMatt Jacob static int isp_nvports = 0; 34665adb54cSMatt Jacob 347960f6939SMatt Jacob static int 348960f6939SMatt Jacob isp_pci_probe(device_t dev) 34965adb54cSMatt Jacob { 350960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 35156aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 352960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 35365adb54cSMatt Jacob break; 354d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 355960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 356c6608df3SMatt Jacob break; 357c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 358960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 359d59bd469SMatt Jacob break; 36022e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 361960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 362960f6939SMatt Jacob break; 363f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 364f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 365f556e83bSMatt Jacob break; 366960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 367e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 368e11a1ee8SMatt Jacob return (ENXIO); 369e11a1ee8SMatt Jacob } 370960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 37122e1dc85SMatt Jacob break; 37265adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 373960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 37465adb54cSMatt Jacob break; 3755542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 376960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 3775542fe4bSMatt Jacob break; 378126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 379126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 380126ec864SMatt Jacob break; 381126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 382126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 383126ec864SMatt Jacob break; 384e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 385e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 386e5265237SMatt Jacob break; 3878872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 3888872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 3898872e3d7SMatt Jacob break; 39041675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 39141675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 39241675df0SMatt Jacob break; 3932df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 3942df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 3952df76c16SMatt Jacob break; 396a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 397a959d921SMatt Jacob device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter"); 398a959d921SMatt Jacob break; 399dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 400dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 401dd1419abSMatt Jacob break; 4029a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4039a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4049a5af410SMatt Jacob break; 405218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 406218be0b2SAlexander Motin device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter"); 407218be0b2SAlexander Motin break; 40867eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 40967eeadd2SAlexander Motin device_set_desc(dev, "Qlogic ISP 8031 PCI FCoE Adapter"); 41067eeadd2SAlexander Motin break; 41114e084adSAlexander Motin case PCI_QLOGIC_ISP2684: 41214e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2684 PCI FC Adapter"); 41314e084adSAlexander Motin break; 41414e084adSAlexander Motin case PCI_QLOGIC_ISP2692: 41514e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2692 PCI FC Adapter"); 41614e084adSAlexander Motin break; 41714e084adSAlexander Motin case PCI_QLOGIC_ISP2714: 41814e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2714 PCI FC Adapter"); 41914e084adSAlexander Motin break; 42014e084adSAlexander Motin case PCI_QLOGIC_ISP2722: 42114e084adSAlexander Motin device_set_desc(dev, "Qlogic ISP 2722 PCI FC Adapter"); 42214e084adSAlexander Motin break; 42365adb54cSMatt Jacob default: 424960f6939SMatt Jacob return (ENXIO); 42565adb54cSMatt Jacob } 42673030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 427d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 428a95ae193SMatt Jacob "Core Version %d.%d\n", 429d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 430d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 43173030e03SMatt Jacob isp_announced++; 43265adb54cSMatt Jacob } 43356aef503SMatt Jacob /* 43456aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 43556aef503SMatt Jacob * XXXX: (or increase a reference count to it). 43656aef503SMatt Jacob */ 437b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 43865adb54cSMatt Jacob } 43965adb54cSMatt Jacob 4409cd7268eSMatt Jacob static void 4419e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 4429cd7268eSMatt Jacob { 4439cd7268eSMatt Jacob int tval; 444f7c631bcSMatt Jacob 4459cd7268eSMatt Jacob tval = 0; 4462df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 4479cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4489cd7268eSMatt Jacob } 4499cd7268eSMatt Jacob tval = 0; 4502df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 4519cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 4529cd7268eSMatt Jacob } 453336b5612SMatt Jacob tval = 0; 4542df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 455336b5612SMatt Jacob if (tval) { 456336b5612SMatt Jacob isp->isp_dblev = tval; 457336b5612SMatt Jacob } else { 458336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 459336b5612SMatt Jacob } 460336b5612SMatt Jacob if (bootverbose) { 461336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 462336b5612SMatt Jacob } 4639e7d423dSMatt Jacob tval = -1; 4642df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 465ffe6ea05SAlexander Motin if (tval > 0 && tval <= 254) { 4669e7d423dSMatt Jacob isp_nvports = tval; 4672df76c16SMatt Jacob } 4682df76c16SMatt Jacob tval = 7; 4692df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 4702df76c16SMatt Jacob isp_quickboot_time = tval; 471336b5612SMatt Jacob } 472336b5612SMatt Jacob 473336b5612SMatt Jacob static void 4742df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 475336b5612SMatt Jacob { 476336b5612SMatt Jacob const char *sptr; 4779e7d423dSMatt Jacob int tval = 0; 47807f56f1cSAlexander Motin char prefix[12], name[16]; 479336b5612SMatt Jacob 48007f56f1cSAlexander Motin if (chan == 0) 48107f56f1cSAlexander Motin prefix[0] = 0; 48207f56f1cSAlexander Motin else 48307f56f1cSAlexander Motin snprintf(prefix, sizeof(prefix), "chan%d.", chan); 48407f56f1cSAlexander Motin snprintf(name, sizeof(name), "%siid", prefix); 48507f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 48607f56f1cSAlexander Motin name, &tval)) { 4872df76c16SMatt Jacob if (IS_FC(isp)) { 4882df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 4892df76c16SMatt Jacob } else { 4902df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = 7; 4912df76c16SMatt Jacob } 4922df76c16SMatt Jacob } else { 4932df76c16SMatt Jacob if (IS_FC(isp)) { 4942df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 4952df76c16SMatt Jacob } else { 4962df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = tval; 4972df76c16SMatt Jacob } 498336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 499336b5612SMatt Jacob } 5002df76c16SMatt Jacob 5013e6deb33SAlexander Motin if (IS_SCSI(isp)) 5023e6deb33SAlexander Motin return; 5033e6deb33SAlexander Motin 5042df76c16SMatt Jacob tval = -1; 50507f56f1cSAlexander Motin snprintf(name, sizeof(name), "%srole", prefix); 50607f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 50707f56f1cSAlexander Motin name, &tval) == 0) { 5082df76c16SMatt Jacob switch (tval) { 5092df76c16SMatt Jacob case ISP_ROLE_NONE: 5102df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 5112df76c16SMatt Jacob case ISP_ROLE_TARGET: 51207f56f1cSAlexander Motin case ISP_ROLE_BOTH: 51307f56f1cSAlexander Motin device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval); 5142df76c16SMatt Jacob break; 5152df76c16SMatt Jacob default: 5162df76c16SMatt Jacob tval = -1; 5172df76c16SMatt Jacob break; 518336b5612SMatt Jacob } 519336b5612SMatt Jacob } 5202df76c16SMatt Jacob if (tval == -1) { 5212df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 5222df76c16SMatt Jacob } 5234ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 524336b5612SMatt Jacob 5259cd7268eSMatt Jacob tval = 0; 52607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfullduplex", prefix); 52707f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 52807f56f1cSAlexander Motin name, &tval) == 0 && tval != 0) { 5299cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5309cd7268eSMatt Jacob } 5314d24901aSPedro F. Giffuni sptr = NULL; 53207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%stopology", prefix); 53307f56f1cSAlexander Motin if (resource_string_value(device_get_name(dev), device_get_unit(dev), 5344d24901aSPedro F. Giffuni name, (const char **) &sptr) == 0 && sptr != NULL) { 5359cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 5369cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 5379cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 5389cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5399cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 5409cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 5419cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 5429cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 5439cd7268eSMatt Jacob } 544960f6939SMatt Jacob } 545960f6939SMatt Jacob 54608167db8SKenneth D. Merry #ifdef ISP_FCTAPE_OFF 54708167db8SKenneth D. Merry isp->isp_confopts |= ISP_CFG_NOFCTAPE; 54808167db8SKenneth D. Merry #else 54908167db8SKenneth D. Merry isp->isp_confopts |= ISP_CFG_FCTAPE; 55008167db8SKenneth D. Merry #endif 55108167db8SKenneth D. Merry 552387d8239SMatt Jacob tval = 0; 55307f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snofctape", prefix); 55407f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 55507f56f1cSAlexander Motin name, &tval); 556387d8239SMatt Jacob if (tval) { 55708167db8SKenneth D. Merry isp->isp_confopts &= ~ISP_CFG_FCTAPE; 558387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_NOFCTAPE; 559387d8239SMatt Jacob } 560387d8239SMatt Jacob 561387d8239SMatt Jacob tval = 0; 56207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfctape", prefix); 56307f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 56407f56f1cSAlexander Motin name, &tval); 565387d8239SMatt Jacob if (tval) { 566387d8239SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NOFCTAPE; 567387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_FCTAPE; 568387d8239SMatt Jacob } 569387d8239SMatt Jacob 570387d8239SMatt Jacob 5719ba86737SMatt Jacob /* 5729cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 5739cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 5749cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 5759cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 5769cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 5779cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 5789cd7268eSMatt Jacob */ 5794d24901aSPedro F. Giffuni sptr = NULL; 58007f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sportwwn", prefix); 58107f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 58207f56f1cSAlexander Motin name, (const char **) &sptr); 5834d24901aSPedro F. Giffuni if (tval == 0 && sptr != NULL && *sptr++ == 'w') { 5844d24901aSPedro F. Giffuni char *eptr = NULL; 5852df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 5862df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 5879cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 5882df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 5899cd7268eSMatt Jacob } 5909cd7268eSMatt Jacob } 5919cd7268eSMatt Jacob 5924d24901aSPedro F. Giffuni sptr = NULL; 59307f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snodewwn", prefix); 59407f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 59507f56f1cSAlexander Motin name, (const char **) &sptr); 5964d24901aSPedro F. Giffuni if (tval == 0 && sptr != NULL && *sptr++ == 'w') { 5974d24901aSPedro F. Giffuni char *eptr = NULL; 5982df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 5992df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 6009cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6012df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 6029cd7268eSMatt Jacob } 6039cd7268eSMatt Jacob } 6049cd7268eSMatt Jacob 605f7c631bcSMatt Jacob tval = -1; 60607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sloop_down_limit", prefix); 60707f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 60807f56f1cSAlexander Motin name, &tval); 60910365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6102df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 61110365e5aSMatt Jacob } else { 6122df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 61310365e5aSMatt Jacob } 61410365e5aSMatt Jacob 615f7c631bcSMatt Jacob tval = -1; 61607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sgone_device_time", prefix); 61707f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 61807f56f1cSAlexander Motin name, &tval); 619f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6202df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 621f7c631bcSMatt Jacob } else { 6222df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 623f7c631bcSMatt Jacob } 6249cd7268eSMatt Jacob } 6259cd7268eSMatt Jacob 6269cd7268eSMatt Jacob static int 6279cd7268eSMatt Jacob isp_pci_attach(device_t dev) 6289cd7268eSMatt Jacob { 629a1fa0267SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 630a1fa0267SAlexander Motin ispsoftc_t *isp = &pcs->pci_isp; 631a1fa0267SAlexander Motin int i; 6322df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 6332df76c16SMatt Jacob size_t psize, xsize; 6342df76c16SMatt Jacob char fwname[32]; 6359cd7268eSMatt Jacob 6369cd7268eSMatt Jacob pcs->pci_dev = dev; 6372df76c16SMatt Jacob isp->isp_dev = dev; 6382df76c16SMatt Jacob isp->isp_nchan = 1; 63913d9c921SAlexander Motin mtx_init(&isp->isp_lock, "isp", NULL, MTX_DEF); 6409cd7268eSMatt Jacob 6419cd7268eSMatt Jacob /* 642336b5612SMatt Jacob * Get Generic Options 6439cd7268eSMatt Jacob */ 6449e7d423dSMatt Jacob isp_nvports = 0; 6459e7d423dSMatt Jacob isp_get_generic_options(dev, isp); 6469cd7268eSMatt Jacob 647ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 64808826086SAlexander Motin pcs->regs = pcs->regs2 = NULL; 64908826086SAlexander Motin pcs->rgd = pcs->rtp = 0; 650960f6939SMatt Jacob 6512df76c16SMatt Jacob pcs->pci_dev = dev; 652d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 653d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 654d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 655d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 656d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 6572df76c16SMatt Jacob 6582df76c16SMatt Jacob switch (pci_get_devid(dev)) { 6592df76c16SMatt Jacob case PCI_QLOGIC_ISP1020: 6602df76c16SMatt Jacob did = 0x1040; 6612df76c16SMatt Jacob isp->isp_mdvec = &mdvec; 6622df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 6632df76c16SMatt Jacob break; 6642df76c16SMatt Jacob case PCI_QLOGIC_ISP1080: 6652df76c16SMatt Jacob did = 0x1080; 6662df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 6672df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 6682df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 6692df76c16SMatt Jacob break; 6702df76c16SMatt Jacob case PCI_QLOGIC_ISP1240: 6712df76c16SMatt Jacob did = 0x1080; 6722df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 6732df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1240; 6742df76c16SMatt Jacob isp->isp_nchan = 2; 6752df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 6762df76c16SMatt Jacob break; 6772df76c16SMatt Jacob case PCI_QLOGIC_ISP1280: 6782df76c16SMatt Jacob did = 0x1080; 6792df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 6802df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1280; 6812df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 6822df76c16SMatt Jacob break; 6832df76c16SMatt Jacob case PCI_QLOGIC_ISP10160: 6842df76c16SMatt Jacob did = 0x12160; 6852df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 6862df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_10160; 6872df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 6882df76c16SMatt Jacob break; 6892df76c16SMatt Jacob case PCI_QLOGIC_ISP12160: 6902df76c16SMatt Jacob did = 0x12160; 6912df76c16SMatt Jacob isp->isp_nchan = 2; 6922df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 6932df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_12160; 6942df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 6952df76c16SMatt Jacob break; 6962df76c16SMatt Jacob case PCI_QLOGIC_ISP2100: 6972df76c16SMatt Jacob did = 0x2100; 6982df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2100; 6992df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2100; 7002df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 701960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 702ab6d0040SMatt Jacob /* 703ab6d0040SMatt Jacob * XXX: Need to get the actual revision 704ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 705ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 706ab6d0040SMatt Jacob * XXX; boards. 707ab6d0040SMatt Jacob */ 708ab6d0040SMatt Jacob linesz = 1; 709ab6d0040SMatt Jacob } 7102df76c16SMatt Jacob break; 7112df76c16SMatt Jacob case PCI_QLOGIC_ISP2200: 7122df76c16SMatt Jacob did = 0x2200; 7132df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2200; 7142df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2200; 7152df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 7162df76c16SMatt Jacob break; 7172df76c16SMatt Jacob case PCI_QLOGIC_ISP2300: 7182df76c16SMatt Jacob did = 0x2300; 7192df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7202df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2300; 7212df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7222df76c16SMatt Jacob break; 7232df76c16SMatt Jacob case PCI_QLOGIC_ISP2312: 7242df76c16SMatt Jacob case PCI_QLOGIC_ISP6312: 7252df76c16SMatt Jacob did = 0x2300; 7262df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7272df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2312; 7282df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7292df76c16SMatt Jacob break; 7302df76c16SMatt Jacob case PCI_QLOGIC_ISP2322: 7312df76c16SMatt Jacob case PCI_QLOGIC_ISP6322: 7322df76c16SMatt Jacob did = 0x2322; 7332df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7342df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2322; 7352df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7362df76c16SMatt Jacob break; 7372df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 7382df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 7392df76c16SMatt Jacob did = 0x2400; 7402df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7412df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 7422df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 7432df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 7442df76c16SMatt Jacob break; 7452df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 7462df76c16SMatt Jacob did = 0x2500; 7472df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7482df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 7492df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 7502df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 7512df76c16SMatt Jacob break; 752a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 753a959d921SMatt Jacob did = 0x2500; 754a959d921SMatt Jacob isp->isp_mdvec = &mdvec_2500; 755a959d921SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 756a959d921SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 757a959d921SMatt Jacob break; 758218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 75967eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 760218be0b2SAlexander Motin did = 0x2600; 761218be0b2SAlexander Motin isp->isp_nchan += isp_nvports; 762218be0b2SAlexander Motin isp->isp_mdvec = &mdvec_2600; 763218be0b2SAlexander Motin isp->isp_type = ISP_HA_FC_2600; 764218be0b2SAlexander Motin pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 765218be0b2SAlexander Motin break; 76614e084adSAlexander Motin case PCI_QLOGIC_ISP2684: 76714e084adSAlexander Motin case PCI_QLOGIC_ISP2692: 76814e084adSAlexander Motin case PCI_QLOGIC_ISP2714: 76914e084adSAlexander Motin case PCI_QLOGIC_ISP2722: 77014e084adSAlexander Motin did = 0x2700; 77114e084adSAlexander Motin isp->isp_nchan += isp_nvports; 77214e084adSAlexander Motin isp->isp_mdvec = &mdvec_2700; 77314e084adSAlexander Motin isp->isp_type = ISP_HA_FC_2700; 77414e084adSAlexander Motin pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 77514e084adSAlexander Motin break; 7762df76c16SMatt Jacob default: 7772df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 7782df76c16SMatt Jacob goto bad; 7792df76c16SMatt Jacob break; 78065adb54cSMatt Jacob } 7812df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 7822df76c16SMatt Jacob 783218be0b2SAlexander Motin if (IS_26XX(isp)) { 784218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 785218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 786218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 787218be0b2SAlexander Motin RF_ACTIVE); 788d876d6c3SAlexander Motin pcs->rtp1 = SYS_RES_MEMORY; 789d876d6c3SAlexander Motin pcs->rgd1 = PCIR_BAR(2); 790d876d6c3SAlexander Motin pcs->regs1 = bus_alloc_resource_any(dev, pcs->rtp1, &pcs->rgd1, 791d876d6c3SAlexander Motin RF_ACTIVE); 792cd201b7bSAlexander Motin pcs->rtp2 = SYS_RES_MEMORY; 793cd201b7bSAlexander Motin pcs->rgd2 = PCIR_BAR(4); 794cd201b7bSAlexander Motin pcs->regs2 = bus_alloc_resource_any(dev, pcs->rtp2, &pcs->rgd2, 795cd201b7bSAlexander Motin RF_ACTIVE); 796218be0b2SAlexander Motin } else { 797218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 798218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(1); 799218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 800218be0b2SAlexander Motin RF_ACTIVE); 801218be0b2SAlexander Motin if (pcs->regs == NULL) { 802218be0b2SAlexander Motin pcs->rtp = SYS_RES_IOPORT; 803218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 804218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, 805218be0b2SAlexander Motin &pcs->rgd, RF_ACTIVE); 806218be0b2SAlexander Motin } 807218be0b2SAlexander Motin } 808218be0b2SAlexander Motin if (pcs->regs == NULL) { 809218be0b2SAlexander Motin device_printf(dev, "Unable to map any ports\n"); 810218be0b2SAlexander Motin goto bad; 811218be0b2SAlexander Motin } 812218be0b2SAlexander Motin if (bootverbose) { 813218be0b2SAlexander Motin device_printf(dev, "Using %s space register mapping\n", 814218be0b2SAlexander Motin (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory"); 815218be0b2SAlexander Motin } 816cd201b7bSAlexander Motin isp->isp_regs = pcs->regs; 817cd201b7bSAlexander Motin isp->isp_regs2 = pcs->regs2; 818218be0b2SAlexander Motin 8192df76c16SMatt Jacob if (IS_FC(isp)) { 820222bb542SMatt Jacob psize = sizeof (fcparam); 8212df76c16SMatt Jacob xsize = sizeof (struct isp_fc); 8222df76c16SMatt Jacob } else { 8232df76c16SMatt Jacob psize = sizeof (sdparam); 8242df76c16SMatt Jacob xsize = sizeof (struct isp_spi); 825222bb542SMatt Jacob } 8262df76c16SMatt Jacob psize *= isp->isp_nchan; 8272df76c16SMatt Jacob xsize *= isp->isp_nchan; 8287cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 829c6608df3SMatt Jacob if (isp->isp_param == NULL) { 830960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 831960f6939SMatt Jacob goto bad; 832c6608df3SMatt Jacob } 8332df76c16SMatt Jacob isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 8342df76c16SMatt Jacob if (isp->isp_osinfo.pc.ptr == NULL) { 8352df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 8362df76c16SMatt Jacob goto bad; 8372df76c16SMatt Jacob } 83865adb54cSMatt Jacob 839336b5612SMatt Jacob /* 840336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 841336b5612SMatt Jacob */ 8422df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 8432df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 8449a5af410SMatt Jacob } 8459a5af410SMatt Jacob 8469a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 8479a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 8489a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 8499a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8509a5af410SMatt Jacob } 8519a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 852ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname); 8535f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 8549a5af410SMatt Jacob } 85556aef503SMatt Jacob 85656aef503SMatt Jacob /* 857ad0ab753SMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 858d951bbcaSMatt Jacob */ 859c68534f1SScott Long cmd = pci_read_config(dev, PCIR_COMMAND, 2); 8609e7d423dSMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 86175c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 86275c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 86375c1e828SMatt Jacob } 8648a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 8658a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 8668a97c03aSMatt Jacob } 86706cacb29SMatt Jacob if (IS_24XX(isp)) { 86806cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 86906cacb29SMatt Jacob } 870b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 871ab6d0040SMatt Jacob 872d951bbcaSMatt Jacob /* 873222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 874d951bbcaSMatt Jacob */ 875960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 8766a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 877ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data); 8786a7d12e1SMatt Jacob data = linesz; 879960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 880d951bbcaSMatt Jacob } 881ab6d0040SMatt Jacob 882d951bbcaSMatt Jacob /* 883d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 884d951bbcaSMatt Jacob */ 885960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 886d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 887d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 888ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data); 889960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 890d951bbcaSMatt Jacob } 891ab6d0040SMatt Jacob 892ab6d0040SMatt Jacob /* 893ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 894ab6d0040SMatt Jacob */ 895960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 896ab6d0040SMatt Jacob data &= ~1; 897960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 8982df76c16SMatt Jacob 89905fbcbb0SMatt Jacob /* 90075c1e828SMatt Jacob * Last minute checks... 90175c1e828SMatt Jacob */ 90210365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 90375c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 90475c1e828SMatt Jacob } 90575c1e828SMatt Jacob 90675c1e828SMatt Jacob /* 90705fbcbb0SMatt Jacob * Make sure we're in reset state. 90805fbcbb0SMatt Jacob */ 9093395b056SMatt Jacob ISP_LOCK(isp); 910dfd24649SAlexander Motin if (isp_reinit(isp, 1) != 0) { 9113395b056SMatt Jacob ISP_UNLOCK(isp); 912960f6939SMatt Jacob goto bad; 91365adb54cSMatt Jacob } 9142df76c16SMatt Jacob ISP_UNLOCK(isp); 9152df76c16SMatt Jacob if (isp_attach(isp)) { 9162df76c16SMatt Jacob ISP_LOCK(isp); 917a1fa0267SAlexander Motin isp_shutdown(isp); 9183395b056SMatt Jacob ISP_UNLOCK(isp); 919960f6939SMatt Jacob goto bad; 920d59bd469SMatt Jacob } 921960f6939SMatt Jacob return (0); 922960f6939SMatt Jacob 923960f6939SMatt Jacob bad: 924e52fba21SEdward Tomasz Napierala if (isp->isp_osinfo.fw == NULL && !IS_26XX(isp)) { 925e52fba21SEdward Tomasz Napierala /* 926e52fba21SEdward Tomasz Napierala * Failure to attach at boot time might have been caused 927e52fba21SEdward Tomasz Napierala * by a missing ispfw(4). Except for for 16Gb adapters, 928e52fba21SEdward Tomasz Napierala * there's no loadable firmware for them. 929e52fba21SEdward Tomasz Napierala */ 930e52fba21SEdward Tomasz Napierala isp_prt(isp, ISP_LOGWARN, "See the ispfw(4) man page on " 931e52fba21SEdward Tomasz Napierala "how to load known good firmware at boot time"); 932e52fba21SEdward Tomasz Napierala } 93308826086SAlexander Motin for (i = 0; i < isp->isp_nirq; i++) { 93408826086SAlexander Motin (void) bus_teardown_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih); 93508826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->irq[i].iqd, 93608826086SAlexander Motin pcs->irq[0].irq); 937960f6939SMatt Jacob } 938a035b0afSMatt Jacob if (pcs->msicount) { 9390a70657fSMatt Jacob pci_release_msi(dev); 9400a70657fSMatt Jacob } 941cd201b7bSAlexander Motin if (pcs->regs) 942e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 943d876d6c3SAlexander Motin if (pcs->regs1) 944d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 945cd201b7bSAlexander Motin if (pcs->regs2) 946cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 9479cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 948960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 9492df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 9502df76c16SMatt Jacob } 9512df76c16SMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 9522df76c16SMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 9532df76c16SMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 9549cd7268eSMatt Jacob } 95513d9c921SAlexander Motin mtx_destroy(&isp->isp_lock); 956960f6939SMatt Jacob return (ENXIO); 95765adb54cSMatt Jacob } 95865adb54cSMatt Jacob 95910365e5aSMatt Jacob static int 96010365e5aSMatt Jacob isp_pci_detach(device_t dev) 96110365e5aSMatt Jacob { 962a1fa0267SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 963a1fa0267SAlexander Motin ispsoftc_t *isp = &pcs->pci_isp; 96408826086SAlexander Motin int i, status; 96510365e5aSMatt Jacob 966e95725cbSMatt Jacob status = isp_detach(isp); 967e95725cbSMatt Jacob if (status) 968e95725cbSMatt Jacob return (status); 969e95725cbSMatt Jacob ISP_LOCK(isp); 970a1fa0267SAlexander Motin isp_shutdown(isp); 971e95725cbSMatt Jacob ISP_UNLOCK(isp); 97208826086SAlexander Motin for (i = 0; i < isp->isp_nirq; i++) { 97308826086SAlexander Motin (void) bus_teardown_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih); 97408826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->irq[i].iqd, 97508826086SAlexander Motin pcs->irq[i].irq); 97608826086SAlexander Motin } 977a1fa0267SAlexander Motin if (pcs->msicount) 978e95725cbSMatt Jacob pci_release_msi(dev); 979e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 980d876d6c3SAlexander Motin if (pcs->regs1) 981d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 982cd201b7bSAlexander Motin if (pcs->regs2) 983cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 984a1fa0267SAlexander Motin isp_pci_mbxdmafree(isp); 985e95725cbSMatt Jacob if (pcs->pci_isp.isp_param) { 986e95725cbSMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 987e95725cbSMatt Jacob pcs->pci_isp.isp_param = NULL; 988e95725cbSMatt Jacob } 989e95725cbSMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 990e95725cbSMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 991e95725cbSMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 992e95725cbSMatt Jacob } 99313d9c921SAlexander Motin mtx_destroy(&isp->isp_lock); 99410365e5aSMatt Jacob return (0); 99510365e5aSMatt Jacob } 99610365e5aSMatt Jacob 997126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 998126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 9994cc9e3e7SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xfff)) 1000126ec864SMatt Jacob 1001cd201b7bSAlexander Motin #define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off)) 1002cd201b7bSAlexander Motin #define BXW2(isp, off, v) bus_write_2((isp)->isp_regs, (off), (v)) 1003cd201b7bSAlexander Motin #define BXR4(isp, off) bus_read_4((isp)->isp_regs, (off)) 1004cd201b7bSAlexander Motin #define BXW4(isp, off, v) bus_write_4((isp)->isp_regs, (off), (v)) 1005cd201b7bSAlexander Motin #define B2R4(isp, off) bus_read_4((isp)->isp_regs2, (off)) 1006cd201b7bSAlexander Motin #define B2W4(isp, off, v) bus_write_4((isp)->isp_regs2, (off), (v)) 1007126ec864SMatt Jacob 10080e6bc811SAlexander Motin static ISP_INLINE uint16_t 10090e6bc811SAlexander Motin isp_pci_rd_debounced(ispsoftc_t *isp, int off) 1010126ec864SMatt Jacob { 10110e6bc811SAlexander Motin uint16_t val, prev; 1012126ec864SMatt Jacob 10130e6bc811SAlexander Motin val = BXR2(isp, IspVirt2Off(isp, off)); 1014126ec864SMatt Jacob do { 10150e6bc811SAlexander Motin prev = val; 10160e6bc811SAlexander Motin val = BXR2(isp, IspVirt2Off(isp, off)); 10170e6bc811SAlexander Motin } while (val != prev); 10180e6bc811SAlexander Motin return (val); 1019126ec864SMatt Jacob } 1020126ec864SMatt Jacob 10210e6bc811SAlexander Motin static void 10220e6bc811SAlexander Motin isp_pci_run_isr(ispsoftc_t *isp) 1023126ec864SMatt Jacob { 10240e6bc811SAlexander Motin uint16_t isr, sema, info; 1025126ec864SMatt Jacob 1026126ec864SMatt Jacob if (IS_2100(isp)) { 10270e6bc811SAlexander Motin isr = isp_pci_rd_debounced(isp, BIU_ISR); 10280e6bc811SAlexander Motin sema = isp_pci_rd_debounced(isp, BIU_SEMA); 1029126ec864SMatt Jacob } else { 10306a7d12e1SMatt Jacob isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR)); 10316a7d12e1SMatt Jacob sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA)); 1032126ec864SMatt Jacob } 1033126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 1034126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 1035126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 10360e6bc811SAlexander Motin if (isr == 0 && sema == 0) 10370e6bc811SAlexander Motin return; 10380e6bc811SAlexander Motin if (sema != 0) { 10390e6bc811SAlexander Motin if (IS_2100(isp)) 10400e6bc811SAlexander Motin info = isp_pci_rd_debounced(isp, OUTMAILBOX0); 10410e6bc811SAlexander Motin else 10420e6bc811SAlexander Motin info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 10430e6bc811SAlexander Motin if (info & MBOX_COMMAND_COMPLETE) 10440e6bc811SAlexander Motin isp_intr_mbox(isp, info); 10450e6bc811SAlexander Motin else 10460e6bc811SAlexander Motin isp_intr_async(isp, info); 10470e6bc811SAlexander Motin if (!IS_FC(isp) && isp->isp_state == ISP_RUNSTATE) 10480e6bc811SAlexander Motin isp_intr_respq(isp); 10490e6bc811SAlexander Motin } else 10500e6bc811SAlexander Motin isp_intr_respq(isp); 10510e6bc811SAlexander Motin ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); 10520e6bc811SAlexander Motin if (sema) 10530e6bc811SAlexander Motin ISP_WRITE(isp, BIU_SEMA, 0); 1054126ec864SMatt Jacob } 1055126ec864SMatt Jacob 10560e6bc811SAlexander Motin static void 10570e6bc811SAlexander Motin isp_pci_run_isr_2300(ispsoftc_t *isp) 1058126ec864SMatt Jacob { 10596ce548a1SAlexander Motin uint32_t hccr, r2hisr; 10600e6bc811SAlexander Motin uint16_t isr, info; 1061126ec864SMatt Jacob 10620e6bc811SAlexander Motin if ((BXR2(isp, IspVirt2Off(isp, BIU_ISR)) & BIU2100_ISR_RISC_INT) == 0) 10630e6bc811SAlexander Motin return; 10646a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO)); 1065126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 10660e6bc811SAlexander Motin if ((r2hisr & BIU_R2HST_INTR) == 0) 10670e6bc811SAlexander Motin return; 10680e6bc811SAlexander Motin isr = r2hisr & BIU_R2HST_ISTAT_MASK; 10690e6bc811SAlexander Motin info = r2hisr >> 16; 10700e6bc811SAlexander Motin switch (isr) { 1071126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1072126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1073126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1074126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 10750e6bc811SAlexander Motin isp_intr_mbox(isp, info); 10760e6bc811SAlexander Motin break; 1077126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 10780e6bc811SAlexander Motin isp_intr_async(isp, info); 10796ce548a1SAlexander Motin break; 1080fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 10810e6bc811SAlexander Motin isp_intr_async(isp, ASYNC_RIO16_1); 10820e6bc811SAlexander Motin break; 1083fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 10840e6bc811SAlexander Motin isp_intr_async(isp, ASYNC_CMD_CMPLT); 10850e6bc811SAlexander Motin break; 1086fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 10870e6bc811SAlexander Motin isp_intr_async(isp, ASYNC_CTIO_DONE); 10880e6bc811SAlexander Motin break; 1089126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 10900e6bc811SAlexander Motin isp_intr_respq(isp); 10916ce548a1SAlexander Motin break; 1092126ec864SMatt Jacob default: 10938a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 10948a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 10958a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 1096443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR)); 10975ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 10988a97c03aSMatt Jacob } else { 1099443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 11008a97c03aSMatt Jacob } 1101126ec864SMatt Jacob } 11020e6bc811SAlexander Motin ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); 11030e6bc811SAlexander Motin ISP_WRITE(isp, BIU_SEMA, 0); 1104126ec864SMatt Jacob } 1105126ec864SMatt Jacob 11060e6bc811SAlexander Motin static void 11070e6bc811SAlexander Motin isp_pci_run_isr_2400(ispsoftc_t *isp) 110810365e5aSMatt Jacob { 110910365e5aSMatt Jacob uint32_t r2hisr; 11100e6bc811SAlexander Motin uint16_t isr, info; 111110365e5aSMatt Jacob 11126a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO)); 111310365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 11140e6bc811SAlexander Motin if ((r2hisr & BIU_R2HST_INTR) == 0) 11150e6bc811SAlexander Motin return; 11160e6bc811SAlexander Motin isr = r2hisr & BIU_R2HST_ISTAT_MASK; 11170e6bc811SAlexander Motin info = (r2hisr >> 16); 11180e6bc811SAlexander Motin switch (isr) { 11196ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_OK: 11206ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_FAIL: 11216ce548a1SAlexander Motin case ISPR2HST_MBX_OK: 11226ce548a1SAlexander Motin case ISPR2HST_MBX_FAIL: 11230e6bc811SAlexander Motin isp_intr_mbox(isp, info); 11240e6bc811SAlexander Motin break; 11256ce548a1SAlexander Motin case ISPR2HST_ASYNC_EVENT: 11260e6bc811SAlexander Motin isp_intr_async(isp, info); 11276ce548a1SAlexander Motin break; 11286ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE: 11290e6bc811SAlexander Motin isp_intr_respq(isp); 11300e6bc811SAlexander Motin break; 11316ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE2: 11320e6bc811SAlexander Motin #ifdef ISP_TARGET_MODE 11336ce548a1SAlexander Motin case ISPR2HST_ATIO_RSPQ_UPDATE: 11340e6bc811SAlexander Motin #endif 11350e6bc811SAlexander Motin isp_intr_respq(isp); 11360e6bc811SAlexander Motin /* FALLTHROUGH */ 11370e6bc811SAlexander Motin #ifdef ISP_TARGET_MODE 11380e6bc811SAlexander Motin case ISPR2HST_ATIO_UPDATE: 11396ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE2: 11400e6bc811SAlexander Motin isp_intr_atioq(isp); 11410e6bc811SAlexander Motin #endif 11426ce548a1SAlexander Motin break; 114310365e5aSMatt Jacob default: 114410365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 114510365e5aSMatt Jacob } 11460e6bc811SAlexander Motin ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 114710365e5aSMatt Jacob } 114810365e5aSMatt Jacob 114910365e5aSMatt Jacob static uint32_t 11509cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 115165adb54cSMatt Jacob { 11526a7d12e1SMatt Jacob uint16_t rv; 1153126ec864SMatt Jacob int oldconf = 0; 115465adb54cSMatt Jacob 1155d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 115665adb54cSMatt Jacob /* 115765adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 115865adb54cSMatt Jacob */ 11596a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 1160443e752dSMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); 116137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 116265adb54cSMatt Jacob } 11636a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 1164d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 11656a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 116637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 116765adb54cSMatt Jacob } 116865adb54cSMatt Jacob return (rv); 116965adb54cSMatt Jacob } 117065adb54cSMatt Jacob 117165adb54cSMatt Jacob static void 117210365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 117365adb54cSMatt Jacob { 1174126ec864SMatt Jacob int oldconf = 0; 1175d59bd469SMatt Jacob 1176d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 117765adb54cSMatt Jacob /* 117865adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 117965adb54cSMatt Jacob */ 11806a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 11816a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1182126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 118337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 118465adb54cSMatt Jacob } 11856a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 118637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 1187d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 11886a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 118937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 119065adb54cSMatt Jacob } 11916a7d12e1SMatt Jacob 1192f9734398SMatt Jacob } 119365adb54cSMatt Jacob 119410365e5aSMatt Jacob static uint32_t 11959cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1196d59bd469SMatt Jacob { 119710365e5aSMatt Jacob uint32_t rv, oc = 0; 1198d59bd469SMatt Jacob 119910bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 120010365e5aSMatt Jacob uint32_t tc; 1201d59bd469SMatt Jacob /* 1202d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1203d59bd469SMatt Jacob */ 12046a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 120522e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 120622e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 120722e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 120822e1dc85SMatt Jacob else 120922e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12106a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 121137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1212d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12136a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12146a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1215126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 121637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1217d59bd469SMatt Jacob } 12186a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 121922e1dc85SMatt Jacob if (oc) { 12206a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 122137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1222d59bd469SMatt Jacob } 1223d59bd469SMatt Jacob return (rv); 1224d59bd469SMatt Jacob } 1225d59bd469SMatt Jacob 1226d59bd469SMatt Jacob static void 122710365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1228d59bd469SMatt Jacob { 1229126ec864SMatt Jacob int oc = 0; 1230d59bd469SMatt Jacob 123110bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 123210365e5aSMatt Jacob uint32_t tc; 1233d59bd469SMatt Jacob /* 1234d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1235d59bd469SMatt Jacob */ 12366a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 123722e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 123822e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 123922e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 124022e1dc85SMatt Jacob else 124122e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12426a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 124337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1244d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12456a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12466a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1247126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 124837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1249d59bd469SMatt Jacob } 12506a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 125137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 125222e1dc85SMatt Jacob if (oc) { 12536a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 125437bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 125510365e5aSMatt Jacob } 125610365e5aSMatt Jacob } 125710365e5aSMatt Jacob 125810365e5aSMatt Jacob static uint32_t 125910365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 126010365e5aSMatt Jacob { 126110365e5aSMatt Jacob uint32_t rv; 126210365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 126310365e5aSMatt Jacob 126410365e5aSMatt Jacob switch (block) { 126510365e5aSMatt Jacob case BIU_BLOCK: 126610365e5aSMatt Jacob break; 126710365e5aSMatt Jacob case MBOX_BLOCK: 12686a7d12e1SMatt Jacob return (BXR2(isp, IspVirt2Off(isp, regoff))); 126910365e5aSMatt Jacob case SXP_BLOCK: 1270cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "SXP_BLOCK read at 0x%x", regoff); 127110365e5aSMatt Jacob return (0xffffffff); 127210365e5aSMatt Jacob case RISC_BLOCK: 1273cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "RISC_BLOCK read at 0x%x", regoff); 127410365e5aSMatt Jacob return (0xffffffff); 127510365e5aSMatt Jacob case DMA_BLOCK: 1276cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "DMA_BLOCK read at 0x%x", regoff); 127710365e5aSMatt Jacob return (0xffffffff); 127810365e5aSMatt Jacob default: 1279cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block read at 0x%x", regoff); 128010365e5aSMatt Jacob return (0xffffffff); 128110365e5aSMatt Jacob } 128210365e5aSMatt Jacob 128310365e5aSMatt Jacob switch (regoff) { 128410365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 128510365e5aSMatt Jacob case BIU2400_FLASH_DATA: 128610365e5aSMatt Jacob case BIU2400_ICR: 128710365e5aSMatt Jacob case BIU2400_ISR: 128810365e5aSMatt Jacob case BIU2400_CSR: 128910365e5aSMatt Jacob case BIU2400_REQINP: 129010365e5aSMatt Jacob case BIU2400_REQOUTP: 129110365e5aSMatt Jacob case BIU2400_RSPINP: 129210365e5aSMatt Jacob case BIU2400_RSPOUTP: 12932df76c16SMatt Jacob case BIU2400_PRI_REQINP: 12942df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 129510365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 12962df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 129710365e5aSMatt Jacob case BIU2400_HCCR: 129810365e5aSMatt Jacob case BIU2400_GPIOD: 129910365e5aSMatt Jacob case BIU2400_GPIOE: 130010365e5aSMatt Jacob case BIU2400_HSEMA: 13016a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 130210365e5aSMatt Jacob break; 130310365e5aSMatt Jacob case BIU2400_R2HSTSLO: 13046a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 130510365e5aSMatt Jacob break; 130610365e5aSMatt Jacob case BIU2400_R2HSTSHI: 13076a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16; 130810365e5aSMatt Jacob break; 130910365e5aSMatt Jacob default: 1310cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x", 1311cd201b7bSAlexander Motin regoff); 131210365e5aSMatt Jacob rv = 0xffffffff; 131310365e5aSMatt Jacob break; 131410365e5aSMatt Jacob } 131510365e5aSMatt Jacob return (rv); 131610365e5aSMatt Jacob } 131710365e5aSMatt Jacob 131810365e5aSMatt Jacob static void 131910365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 132010365e5aSMatt Jacob { 132110365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 132210365e5aSMatt Jacob 132310365e5aSMatt Jacob switch (block) { 132410365e5aSMatt Jacob case BIU_BLOCK: 132510365e5aSMatt Jacob break; 132610365e5aSMatt Jacob case MBOX_BLOCK: 13276a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 132837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 132910365e5aSMatt Jacob return; 133010365e5aSMatt Jacob case SXP_BLOCK: 1331cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "SXP_BLOCK write at 0x%x", regoff); 133210365e5aSMatt Jacob return; 133310365e5aSMatt Jacob case RISC_BLOCK: 1334cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "RISC_BLOCK write at 0x%x", regoff); 133510365e5aSMatt Jacob return; 133610365e5aSMatt Jacob case DMA_BLOCK: 1337cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "DMA_BLOCK write at 0x%x", regoff); 133810365e5aSMatt Jacob return; 133910365e5aSMatt Jacob default: 1340cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block write at 0x%x", regoff); 134110365e5aSMatt Jacob break; 134210365e5aSMatt Jacob } 134310365e5aSMatt Jacob 134410365e5aSMatt Jacob switch (regoff) { 134510365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 134610365e5aSMatt Jacob case BIU2400_FLASH_DATA: 134710365e5aSMatt Jacob case BIU2400_ICR: 134810365e5aSMatt Jacob case BIU2400_ISR: 134910365e5aSMatt Jacob case BIU2400_CSR: 135010365e5aSMatt Jacob case BIU2400_REQINP: 135110365e5aSMatt Jacob case BIU2400_REQOUTP: 135210365e5aSMatt Jacob case BIU2400_RSPINP: 135310365e5aSMatt Jacob case BIU2400_RSPOUTP: 13542df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13552df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 135610365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13572df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 135810365e5aSMatt Jacob case BIU2400_HCCR: 135910365e5aSMatt Jacob case BIU2400_GPIOD: 136010365e5aSMatt Jacob case BIU2400_GPIOE: 136110365e5aSMatt Jacob case BIU2400_HSEMA: 13626a7d12e1SMatt Jacob BXW4(isp, IspVirt2Off(isp, regoff), val); 136307d925faSAlexander Motin #ifdef MEMORYBARRIERW 136407d925faSAlexander Motin if (regoff == BIU2400_REQINP || 136507d925faSAlexander Motin regoff == BIU2400_RSPOUTP || 136607d925faSAlexander Motin regoff == BIU2400_PRI_REQINP || 136707d925faSAlexander Motin regoff == BIU2400_ATIO_RSPOUTP) 136807d925faSAlexander Motin MEMORYBARRIERW(isp, SYNC_REG, 136907d925faSAlexander Motin IspVirt2Off(isp, regoff), 4, -1) 137007d925faSAlexander Motin else 137107d925faSAlexander Motin #endif 137237bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1); 137310365e5aSMatt Jacob break; 137410365e5aSMatt Jacob default: 1375cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x", 1376cd201b7bSAlexander Motin regoff); 137710365e5aSMatt Jacob break; 1378d59bd469SMatt Jacob } 1379d59bd469SMatt Jacob } 1380d59bd469SMatt Jacob 1381cd201b7bSAlexander Motin static uint32_t 1382cd201b7bSAlexander Motin isp_pci_rd_reg_2600(ispsoftc_t *isp, int regoff) 1383cd201b7bSAlexander Motin { 1384cd201b7bSAlexander Motin uint32_t rv; 1385cd201b7bSAlexander Motin 1386cd201b7bSAlexander Motin switch (regoff) { 1387cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 1388cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 1389cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x", 1390cd201b7bSAlexander Motin regoff); 1391cd201b7bSAlexander Motin rv = 0xffffffff; 1392cd201b7bSAlexander Motin break; 1393cd201b7bSAlexander Motin case BIU2400_REQINP: 1394cd201b7bSAlexander Motin rv = B2R4(isp, 0x00); 1395cd201b7bSAlexander Motin break; 1396cd201b7bSAlexander Motin case BIU2400_REQOUTP: 1397cd201b7bSAlexander Motin rv = B2R4(isp, 0x04); 1398cd201b7bSAlexander Motin break; 1399cd201b7bSAlexander Motin case BIU2400_RSPINP: 1400cd201b7bSAlexander Motin rv = B2R4(isp, 0x08); 1401cd201b7bSAlexander Motin break; 1402cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 1403cd201b7bSAlexander Motin rv = B2R4(isp, 0x0c); 1404cd201b7bSAlexander Motin break; 1405cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 1406cd201b7bSAlexander Motin rv = B2R4(isp, 0x10); 1407cd201b7bSAlexander Motin break; 1408cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 1409cd201b7bSAlexander Motin rv = B2R4(isp, 0x14); 1410cd201b7bSAlexander Motin break; 1411cd201b7bSAlexander Motin default: 1412cd201b7bSAlexander Motin rv = isp_pci_rd_reg_2400(isp, regoff); 1413cd201b7bSAlexander Motin break; 1414cd201b7bSAlexander Motin } 1415cd201b7bSAlexander Motin return (rv); 1416cd201b7bSAlexander Motin } 1417cd201b7bSAlexander Motin 1418cd201b7bSAlexander Motin static void 1419cd201b7bSAlexander Motin isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val) 1420cd201b7bSAlexander Motin { 1421cd201b7bSAlexander Motin int off; 1422cd201b7bSAlexander Motin 1423cd201b7bSAlexander Motin switch (regoff) { 1424cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 1425cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 1426cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x", 1427cd201b7bSAlexander Motin regoff); 1428cd201b7bSAlexander Motin return; 1429cd201b7bSAlexander Motin case BIU2400_REQINP: 1430cd201b7bSAlexander Motin off = 0x00; 1431cd201b7bSAlexander Motin break; 1432cd201b7bSAlexander Motin case BIU2400_REQOUTP: 1433cd201b7bSAlexander Motin off = 0x04; 1434cd201b7bSAlexander Motin break; 1435cd201b7bSAlexander Motin case BIU2400_RSPINP: 1436cd201b7bSAlexander Motin off = 0x08; 1437cd201b7bSAlexander Motin break; 1438cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 1439cd201b7bSAlexander Motin off = 0x0c; 1440cd201b7bSAlexander Motin break; 1441cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 1442cd201b7bSAlexander Motin off = 0x10; 1443cd201b7bSAlexander Motin break; 1444cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 1445cd201b7bSAlexander Motin off = 0x14; 1446cd201b7bSAlexander Motin break; 1447cd201b7bSAlexander Motin default: 1448cd201b7bSAlexander Motin isp_pci_wr_reg_2400(isp, regoff, val); 1449cd201b7bSAlexander Motin return; 1450cd201b7bSAlexander Motin } 1451cd201b7bSAlexander Motin B2W4(isp, off, val); 1452cd201b7bSAlexander Motin } 1453cd201b7bSAlexander Motin 1454d720e6d5SJustin T. Gibbs 1455222bb542SMatt Jacob struct imush { 145614849e2cSAlexander Motin bus_addr_t maddr; 1457222bb542SMatt Jacob int error; 1458222bb542SMatt Jacob }; 1459222bb542SMatt Jacob 1460d720e6d5SJustin T. Gibbs static void 14611923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1462d720e6d5SJustin T. Gibbs { 1463222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 14642df76c16SMatt Jacob 146514849e2cSAlexander Motin if (!(imushp->error = error)) 146614849e2cSAlexander Motin imushp->maddr = segs[0].ds_addr; 1467d720e6d5SJustin T. Gibbs } 1468d720e6d5SJustin T. Gibbs 1469d720e6d5SJustin T. Gibbs static int 14709cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1471d720e6d5SJustin T. Gibbs { 1472d720e6d5SJustin T. Gibbs caddr_t base; 1473662daaddSMatt Jacob uint32_t len, nsegs; 14748e1b6e7aSMatt Jacob int i, error, cmap = 0; 147553af7d22SMatt Jacob bus_size_t slim; /* segment size */ 14764b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 147751effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1478222bb542SMatt Jacob struct imush im; 1479222bb542SMatt Jacob 1480a1fa0267SAlexander Motin /* Already been here? If so, leave... */ 1481a1fa0267SAlexander Motin if (isp->isp_xflist != NULL) 1482a95ae193SMatt Jacob return (0); 1483a1fa0267SAlexander Motin if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0) 1484a1fa0267SAlexander Motin return (0); 14850a70657fSMatt Jacob ISP_UNLOCK(isp); 1486a1fa0267SAlexander Motin if (isp->isp_rquest != NULL) 1487a1fa0267SAlexander Motin goto gotmaxcmds; 148810365e5aSMatt Jacob 148953af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 14901923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 1491a1fa0267SAlexander Motin if (sizeof (bus_size_t) > 4) 149253af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 1493a1fa0267SAlexander Motin else 14949b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 14951dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 14961923f739SMatt Jacob } else { 14979b434edeSMatt Jacob slim = (1UL << 24); 1498a1fa0267SAlexander Motin llim = BUS_SPACE_MAXADDR_32BIT; 14991923f739SMatt Jacob } 15007e31684eSAlexander Motin if (sizeof (bus_size_t) > 4) 1501662daaddSMatt Jacob nsegs = ISP_NSEG64_MAX; 1502a1fa0267SAlexander Motin else 1503662daaddSMatt Jacob nsegs = ISP_NSEG_MAX; 150409934867SMatt Jacob 150513d9c921SAlexander Motin if (bus_dma_tag_create(bus_get_dma_tag(ISP_PCD(isp)), 1, 1506a1fa0267SAlexander Motin slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, 150713d9c921SAlexander Motin busdma_lock_mutex, &isp->isp_lock, &isp->isp_osinfo.dmat)) { 150872429e49SMatt Jacob ISP_LOCK(isp); 15090a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 15101923f739SMatt Jacob return (1); 15111923f739SMatt Jacob } 15121923f739SMatt Jacob 1513d720e6d5SJustin T. Gibbs /* 1514*cf770ba3SAlexander Motin * Allocate and map the request queue. 1515d720e6d5SJustin T. Gibbs */ 1516d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 151713d9c921SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 151814849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 15199cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.reqdmat)) { 152014849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); 1521a1fa0267SAlexander Motin goto bad; 152214849e2cSAlexander Motin } 152314849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, 152414849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { 152514849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); 152614849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 1527a1fa0267SAlexander Motin goto bad; 152814849e2cSAlexander Motin } 152914849e2cSAlexander Motin isp->isp_rquest = base; 153014849e2cSAlexander Motin im.error = 0; 153114849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, 15329cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 153314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); 1534a1fa0267SAlexander Motin goto bad; 153514849e2cSAlexander Motin } 153614849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", 153714849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 153814849e2cSAlexander Motin isp->isp_rquest_dma = im.maddr; 1539*cf770ba3SAlexander Motin 1540*cf770ba3SAlexander Motin #ifdef ISP_TARGET_MODE 1541*cf770ba3SAlexander Motin /* 1542*cf770ba3SAlexander Motin * Allocate region for external DMA addressable command/status structures. 1543*cf770ba3SAlexander Motin */ 154414849e2cSAlexander Motin if (isp->isp_type >= ISP_HA_FC_2200) { 1545*cf770ba3SAlexander Motin isp_ecmd_t *ecmd; 1546*cf770ba3SAlexander Motin 1547*cf770ba3SAlexander Motin len = N_XCMDS * XCMD_SIZE; 1548*cf770ba3SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, XCMD_SIZE, slim, 1549*cf770ba3SAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1550*cf770ba3SAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.ecmd_dmat)) { 1551*cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create ECMD DMA tag"); 1552*cf770ba3SAlexander Motin goto bad; 1553*cf770ba3SAlexander Motin } 1554*cf770ba3SAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.ecmd_dmat, (void **)&base, 1555*cf770ba3SAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.ecmd_map) != 0) { 1556*cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate ECMD DMA memory"); 1557*cf770ba3SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 1558*cf770ba3SAlexander Motin goto bad; 1559*cf770ba3SAlexander Motin } 1560*cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_base = (isp_ecmd_t *)base; 1561*cf770ba3SAlexander Motin im.error = 0; 1562*cf770ba3SAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.ecmd_dmat, isp->isp_osinfo.ecmd_map, 1563*cf770ba3SAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 1564*cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading ECMD DMA map %d", im.error); 1565*cf770ba3SAlexander Motin goto bad; 1566*cf770ba3SAlexander Motin } 1567*cf770ba3SAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "ecmd area @ 0x%jx/0x%jx", 1568*cf770ba3SAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 1569*cf770ba3SAlexander Motin 157014849e2cSAlexander Motin isp->isp_osinfo.ecmd_dma = im.maddr; 157114849e2cSAlexander Motin isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)base; 157214849e2cSAlexander Motin for (ecmd = isp->isp_osinfo.ecmd_free; 157314849e2cSAlexander Motin ecmd < &isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { 157414849e2cSAlexander Motin if (ecmd == &isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) 157514849e2cSAlexander Motin ecmd->next = NULL; 157614849e2cSAlexander Motin else 157714849e2cSAlexander Motin ecmd->next = ecmd + 1; 157814849e2cSAlexander Motin } 1579387d8239SMatt Jacob } 1580*cf770ba3SAlexander Motin #endif 15812df76c16SMatt Jacob 158253af7d22SMatt Jacob /* 158314849e2cSAlexander Motin * Allocate and map the result queue. 158453af7d22SMatt Jacob */ 158514849e2cSAlexander Motin len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 158613d9c921SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 158714849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 15889cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.respdmat)) { 158914849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); 1590a1fa0267SAlexander Motin goto bad; 1591d720e6d5SJustin T. Gibbs } 159214849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, 159314849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { 159414849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); 159514849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 1596a1fa0267SAlexander Motin goto bad; 1597222bb542SMatt Jacob } 159814849e2cSAlexander Motin isp->isp_result = base; 15992df76c16SMatt Jacob im.error = 0; 160014849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, 16019cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 160214849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); 1603a1fa0267SAlexander Motin goto bad; 160414849e2cSAlexander Motin } 160514849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", 160614849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 160714849e2cSAlexander Motin isp->isp_result_dma = im.maddr; 16082df76c16SMatt Jacob 160914849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 161014849e2cSAlexander Motin /* 161114849e2cSAlexander Motin * Allocate and map ATIO queue on 24xx with target mode. 161214849e2cSAlexander Motin */ 161314849e2cSAlexander Motin if (IS_24XX(isp)) { 161414849e2cSAlexander Motin len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 161513d9c921SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 161614849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 16179cca0e7eSAlexander Motin len, 1, len, 0, NULL, NULL, &isp->isp_osinfo.atiodmat)) { 161814849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag"); 1619a1fa0267SAlexander Motin goto bad; 162014849e2cSAlexander Motin } 162114849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base, 162214849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) { 162314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory"); 162414849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 1625a1fa0267SAlexander Motin goto bad; 162614849e2cSAlexander Motin } 162714849e2cSAlexander Motin isp->isp_atioq = base; 162814849e2cSAlexander Motin im.error = 0; 162914849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap, 16309cca0e7eSAlexander Motin base, len, imc, &im, BUS_DMA_NOWAIT) || im.error) { 163114849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading ATIO DMA map %d", im.error); 16322df76c16SMatt Jacob goto bad; 16332df76c16SMatt Jacob } 163414849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "ATIO area @ 0x%jx/0x%jx", 163514849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 163614849e2cSAlexander Motin isp->isp_atioq_dma = im.maddr; 163714849e2cSAlexander Motin } 163814849e2cSAlexander Motin #endif 16392df76c16SMatt Jacob 16402df76c16SMatt Jacob if (IS_FC(isp)) { 164113d9c921SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, 16427d191fdbSAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 16439cca0e7eSAlexander Motin 2*QENTRY_LEN, 1, 2*QENTRY_LEN, 0, NULL, NULL, 16449cca0e7eSAlexander Motin &isp->isp_osinfo.iocbdmat)) { 16452df76c16SMatt Jacob goto bad; 16462df76c16SMatt Jacob } 16474ff970c4SAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.iocbdmat, 16484ff970c4SAlexander Motin (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.iocbmap) != 0) 16494ff970c4SAlexander Motin goto bad; 16504ff970c4SAlexander Motin isp->isp_iocb = base; 16514ff970c4SAlexander Motin im.error = 0; 16524ff970c4SAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap, 16539cca0e7eSAlexander Motin base, 2*QENTRY_LEN, imc, &im, BUS_DMA_NOWAIT) || im.error) 16544ff970c4SAlexander Motin goto bad; 16554ff970c4SAlexander Motin isp->isp_iocb_dma = im.maddr; 16564ff970c4SAlexander Motin 165713d9c921SAlexander Motin if (bus_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, 16584ff970c4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 16599cca0e7eSAlexander Motin ISP_FC_SCRLEN, 1, ISP_FC_SCRLEN, 0, NULL, NULL, 16609cca0e7eSAlexander Motin &isp->isp_osinfo.scdmat)) 16614ff970c4SAlexander Motin goto bad; 16627d191fdbSAlexander Motin for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 16637d191fdbSAlexander Motin struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16647d191fdbSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.scdmat, 166514849e2cSAlexander Motin (void **)&base, BUS_DMA_COHERENT, &fc->scmap) != 0) 16662df76c16SMatt Jacob goto bad; 166714849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scratch = base; 16682df76c16SMatt Jacob im.error = 0; 166914849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap, 16709cca0e7eSAlexander Motin base, ISP_FC_SCRLEN, imc, &im, BUS_DMA_NOWAIT) || 16719cca0e7eSAlexander Motin im.error) { 16727d191fdbSAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 16737d191fdbSAlexander Motin base, fc->scmap); 1674a1fa0267SAlexander Motin FCPARAM(isp, cmap)->isp_scratch = NULL; 16752df76c16SMatt Jacob goto bad; 16762df76c16SMatt Jacob } 167714849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scdma = im.maddr; 1678a4ccb5d6SAlexander Motin if (!IS_2100(isp)) { 1679387d8239SMatt Jacob for (i = 0; i < INITIAL_NEXUS_COUNT; i++) { 1680387d8239SMatt Jacob struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO); 1681387d8239SMatt Jacob if (n == NULL) { 1682387d8239SMatt Jacob while (fc->nexus_free_list) { 1683387d8239SMatt Jacob n = fc->nexus_free_list; 1684387d8239SMatt Jacob fc->nexus_free_list = n->next; 1685387d8239SMatt Jacob free(n, M_DEVBUF); 1686387d8239SMatt Jacob } 1687387d8239SMatt Jacob goto bad; 1688387d8239SMatt Jacob } 1689387d8239SMatt Jacob n->next = fc->nexus_free_list; 1690387d8239SMatt Jacob fc->nexus_free_list = n; 1691387d8239SMatt Jacob } 16922df76c16SMatt Jacob } 16932df76c16SMatt Jacob } 1694405b7a29SMatt Jacob } 16952df76c16SMatt Jacob 1696a1fa0267SAlexander Motin if (isp->isp_maxcmds == 0) { 1697a1fa0267SAlexander Motin ISP_LOCK(isp); 1698a1fa0267SAlexander Motin return (0); 1699a1fa0267SAlexander Motin } 1700a1fa0267SAlexander Motin 1701a1fa0267SAlexander Motin gotmaxcmds: 1702a1fa0267SAlexander Motin len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 1703a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) 1704a1fa0267SAlexander Motin malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1705a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 17060a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 17070a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1708d720e6d5SJustin T. Gibbs if (error) { 17092df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 17101923f739SMatt Jacob while (--i >= 0) { 1711a1fa0267SAlexander Motin bus_dmamap_destroy(isp->isp_osinfo.dmat, 1712a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool[i].dmap); 17131923f739SMatt Jacob } 17141923f739SMatt Jacob goto bad; 1715d720e6d5SJustin T. Gibbs } 171613d9c921SAlexander Motin callout_init_mtx(&pcmd->wdog, &isp->isp_lock, 0); 1717a1fa0267SAlexander Motin if (i == isp->isp_maxcmds-1) 17180a70657fSMatt Jacob pcmd->next = NULL; 1719a1fa0267SAlexander Motin else 17200a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1721d720e6d5SJustin T. Gibbs } 17220a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 1723a1fa0267SAlexander Motin 1724a1fa0267SAlexander Motin len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1725a1fa0267SAlexander Motin isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1726a1fa0267SAlexander Motin for (len = 0; len < isp->isp_maxcmds - 1; len++) 1727a1fa0267SAlexander Motin isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1728a1fa0267SAlexander Motin isp->isp_xffree = isp->isp_xflist; 1729a1fa0267SAlexander Motin 173072429e49SMatt Jacob ISP_LOCK(isp); 1731d720e6d5SJustin T. Gibbs return (0); 17321923f739SMatt Jacob 17331923f739SMatt Jacob bad: 1734a1fa0267SAlexander Motin isp_pci_mbxdmafree(isp); 1735a1fa0267SAlexander Motin ISP_LOCK(isp); 1736a1fa0267SAlexander Motin return (1); 1737a1fa0267SAlexander Motin } 1738a1fa0267SAlexander Motin 1739a1fa0267SAlexander Motin static void 1740a1fa0267SAlexander Motin isp_pci_mbxdmafree(ispsoftc_t *isp) 1741a1fa0267SAlexander Motin { 1742a1fa0267SAlexander Motin int i; 1743a1fa0267SAlexander Motin 1744a1fa0267SAlexander Motin if (isp->isp_xflist != NULL) { 1745a1fa0267SAlexander Motin free(isp->isp_xflist, M_DEVBUF); 1746a1fa0267SAlexander Motin isp->isp_xflist = NULL; 1747a1fa0267SAlexander Motin } 1748a1fa0267SAlexander Motin if (isp->isp_osinfo.pcmd_pool != NULL) { 1749a1fa0267SAlexander Motin for (i = 0; i < isp->isp_maxcmds; i++) { 1750a1fa0267SAlexander Motin bus_dmamap_destroy(isp->isp_osinfo.dmat, 1751a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool[i].dmap); 1752a1fa0267SAlexander Motin } 1753a1fa0267SAlexander Motin free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1754a1fa0267SAlexander Motin isp->isp_osinfo.pcmd_pool = NULL; 1755a1fa0267SAlexander Motin } 17567d191fdbSAlexander Motin if (IS_FC(isp)) { 1757a1fa0267SAlexander Motin for (i = 0; i < isp->isp_nchan; i++) { 1758a1fa0267SAlexander Motin struct isp_fc *fc = ISP_FC_PC(isp, i); 1759a1fa0267SAlexander Motin if (FCPARAM(isp, i)->isp_scdma != 0) { 1760a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.scdmat, 1761a1fa0267SAlexander Motin fc->scmap); 1762a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scdma = 0; 1763a1fa0267SAlexander Motin } 1764a1fa0267SAlexander Motin if (FCPARAM(isp, i)->isp_scratch != NULL) { 17654ff970c4SAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 1766a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scratch, fc->scmap); 1767a1fa0267SAlexander Motin FCPARAM(isp, i)->isp_scratch = NULL; 1768a1fa0267SAlexander Motin } 1769387d8239SMatt Jacob while (fc->nexus_free_list) { 1770387d8239SMatt Jacob struct isp_nexus *n = fc->nexus_free_list; 1771387d8239SMatt Jacob fc->nexus_free_list = n->next; 1772387d8239SMatt Jacob free(n, M_DEVBUF); 1773387d8239SMatt Jacob } 17742df76c16SMatt Jacob } 1775a1fa0267SAlexander Motin if (isp->isp_iocb_dma != 0) { 17767d191fdbSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.scdmat); 1777a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.iocbdmat, 17784ff970c4SAlexander Motin isp->isp_osinfo.iocbmap); 1779a1fa0267SAlexander Motin isp->isp_iocb_dma = 0; 1780a1fa0267SAlexander Motin } 1781a1fa0267SAlexander Motin if (isp->isp_iocb != NULL) { 1782a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.iocbdmat, 1783a1fa0267SAlexander Motin isp->isp_iocb, isp->isp_osinfo.iocbmap); 17844ff970c4SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat); 17857d191fdbSAlexander Motin } 178614849e2cSAlexander Motin } 178714849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 178814849e2cSAlexander Motin if (IS_24XX(isp)) { 178914849e2cSAlexander Motin if (isp->isp_atioq_dma != 0) { 179014849e2cSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.atiodmat, 179114849e2cSAlexander Motin isp->isp_osinfo.atiomap); 1792a1fa0267SAlexander Motin isp->isp_atioq_dma = 0; 179314849e2cSAlexander Motin } 179414849e2cSAlexander Motin if (isp->isp_atioq != NULL) { 1795a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.atiodmat, isp->isp_atioq, 179614849e2cSAlexander Motin isp->isp_osinfo.atiomap); 179714849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 1798a1fa0267SAlexander Motin isp->isp_atioq = NULL; 179914849e2cSAlexander Motin } 180014849e2cSAlexander Motin } 180114849e2cSAlexander Motin #endif 1802a1fa0267SAlexander Motin if (isp->isp_result_dma != 0) { 1803a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.respdmat, 1804a1fa0267SAlexander Motin isp->isp_osinfo.respmap); 1805a1fa0267SAlexander Motin isp->isp_result_dma = 0; 1806a1fa0267SAlexander Motin } 1807a1fa0267SAlexander Motin if (isp->isp_result != NULL) { 1808a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, 1809a1fa0267SAlexander Motin isp->isp_osinfo.respmap); 1810a1fa0267SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 1811a1fa0267SAlexander Motin isp->isp_result = NULL; 1812a1fa0267SAlexander Motin } 1813*cf770ba3SAlexander Motin #ifdef ISP_TARGET_MODE 1814*cf770ba3SAlexander Motin if (isp->isp_osinfo.ecmd_dma != 0) { 1815*cf770ba3SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.ecmd_dmat, 1816*cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_map); 1817*cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_dma = 0; 1818*cf770ba3SAlexander Motin } 1819*cf770ba3SAlexander Motin if (isp->isp_osinfo.ecmd_base != NULL) { 1820*cf770ba3SAlexander Motin bus_dmamem_free(isp->isp_osinfo.ecmd_dmat, isp->isp_osinfo.ecmd_base, 1821*cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_map); 1822*cf770ba3SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.ecmd_dmat); 1823*cf770ba3SAlexander Motin isp->isp_osinfo.ecmd_base = NULL; 1824*cf770ba3SAlexander Motin } 1825*cf770ba3SAlexander Motin #endif 1826a1fa0267SAlexander Motin if (isp->isp_rquest_dma != 0) { 1827a1fa0267SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.reqdmat, 1828a1fa0267SAlexander Motin isp->isp_osinfo.reqmap); 1829a1fa0267SAlexander Motin isp->isp_rquest_dma = 0; 1830a1fa0267SAlexander Motin } 1831a1fa0267SAlexander Motin if (isp->isp_rquest != NULL) { 1832a1fa0267SAlexander Motin bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, 1833a1fa0267SAlexander Motin isp->isp_osinfo.reqmap); 1834a1fa0267SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 18351923f739SMatt Jacob isp->isp_rquest = NULL; 1836a1fa0267SAlexander Motin } 1837d720e6d5SJustin T. Gibbs } 1838d720e6d5SJustin T. Gibbs 1839d720e6d5SJustin T. Gibbs typedef struct { 18409cd7268eSMatt Jacob ispsoftc_t *isp; 18419e11e5beSMatt Jacob void *cmd_token; 18422df76c16SMatt Jacob void *rq; /* original request */ 18431dae40ebSMatt Jacob int error; 1844d720e6d5SJustin T. Gibbs } mush_t; 1845d720e6d5SJustin T. Gibbs 18464873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 18474873663cSMatt Jacob 18489e11e5beSMatt Jacob static void 18499e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 18509e11e5beSMatt Jacob { 18517e31684eSAlexander Motin mush_t *mp = (mush_t *) arg; 18527e31684eSAlexander Motin ispsoftc_t *isp= mp->isp; 18537e31684eSAlexander Motin struct ccb_scsiio *csio = mp->cmd_token; 18542df76c16SMatt Jacob isp_ddir_t ddir; 18557e31684eSAlexander Motin int sdir; 18569e11e5beSMatt Jacob 18579e11e5beSMatt Jacob if (error) { 18589e11e5beSMatt Jacob mp->error = error; 18599e11e5beSMatt Jacob return; 18609e11e5beSMatt Jacob } 18617e31684eSAlexander Motin if (nseg == 0) { 18627e31684eSAlexander Motin ddir = ISP_NOXFR; 18632df76c16SMatt Jacob } else { 18642df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 18652df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 18667e31684eSAlexander Motin } else { 18672df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 18682df76c16SMatt Jacob } 18697e31684eSAlexander Motin if ((csio->ccb_h.func_code == XPT_CONT_TARGET_IO) ^ 18707e31684eSAlexander Motin ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)) { 18717e31684eSAlexander Motin sdir = BUS_DMASYNC_PREREAD; 18722df76c16SMatt Jacob } else { 18737e31684eSAlexander Motin sdir = BUS_DMASYNC_PREWRITE; 18747e31684eSAlexander Motin } 18757e31684eSAlexander Motin bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, 18767e31684eSAlexander Motin sdir); 1877d720e6d5SJustin T. Gibbs } 1878d720e6d5SJustin T. Gibbs 18797e31684eSAlexander Motin error = isp_send_cmd(isp, mp->rq, dm_segs, nseg, XS_XFRLEN(csio), 18807e31684eSAlexander Motin ddir, (ispds64_t *)csio->req_map); 1881387d8239SMatt Jacob switch (error) { 1882387d8239SMatt Jacob case CMD_EAGAIN: 18832df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1884387d8239SMatt Jacob break; 1885387d8239SMatt Jacob case CMD_QUEUED: 1886387d8239SMatt Jacob break; 1887387d8239SMatt Jacob default: 1888387d8239SMatt Jacob mp->error = EIO; 1889387d8239SMatt Jacob break; 18902df76c16SMatt Jacob } 18912df76c16SMatt Jacob } 18922df76c16SMatt Jacob 1893d720e6d5SJustin T. Gibbs static int 18942df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 1895d720e6d5SJustin T. Gibbs { 1896d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1897dd0b4fb6SKonstantin Belousov int error; 1898d720e6d5SJustin T. Gibbs 18992df76c16SMatt Jacob mp = &mush; 19002df76c16SMatt Jacob mp->isp = isp; 19012df76c16SMatt Jacob mp->cmd_token = csio; 19022df76c16SMatt Jacob mp->rq = ff; 19032df76c16SMatt Jacob mp->error = 0; 19042df76c16SMatt Jacob 1905dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, 19067e31684eSAlexander Motin (union ccb *)csio, dma2, mp, 0); 1907d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 19082df76c16SMatt Jacob bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 1909d720e6d5SJustin T. Gibbs mp->error = EINVAL; 19102df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); 1911d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 19120a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 19132df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 19140a5f7e8bSMatt Jacob #endif 1915d720e6d5SJustin T. Gibbs mp->error = error; 1916d720e6d5SJustin T. Gibbs } 1917d720e6d5SJustin T. Gibbs if (mp->error) { 19184873663cSMatt Jacob int retval = CMD_COMPLETE; 19194873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 19204873663cSMatt Jacob retval = CMD_EAGAIN; 19214873663cSMatt Jacob } else if (mp->error == EFBIG) { 1922387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_TOO_BIG; 1923d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 1924387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_INVALID; 1925d720e6d5SJustin T. Gibbs } else { 1926387d8239SMatt Jacob csio->ccb_h.status = CAM_UNREC_HBA_ERROR; 1927d720e6d5SJustin T. Gibbs } 19284873663cSMatt Jacob return (retval); 19290a5f7e8bSMatt Jacob } 19304873663cSMatt Jacob return (CMD_QUEUED); 1931d720e6d5SJustin T. Gibbs } 1932d720e6d5SJustin T. Gibbs 1933a1fa0267SAlexander Motin static int 1934a1fa0267SAlexander Motin isp_pci_irqsetup(ispsoftc_t *isp) 19353bda7a83SMatt Jacob { 193608826086SAlexander Motin device_t dev = isp->isp_osinfo.dev; 193708826086SAlexander Motin struct isp_pcisoftc *pcs = device_get_softc(dev); 193808826086SAlexander Motin driver_intr_t *f; 193908826086SAlexander Motin int i, max_irq; 19403bda7a83SMatt Jacob 194108826086SAlexander Motin /* Allocate IRQs only once. */ 194208826086SAlexander Motin if (isp->isp_nirq > 0) 1943a1fa0267SAlexander Motin return (0); 194408826086SAlexander Motin 1945abdc2e31SAlexander Motin ISP_UNLOCK(isp); 194608826086SAlexander Motin if (ISP_CAP_MSIX(isp)) { 19471f8c4546SAlexander Motin max_irq = IS_26XX(isp) ? 3 : (IS_25XX(isp) ? 2 : 0); 194817ec7746SAlexander Motin resource_int_value(device_get_name(dev), 194917ec7746SAlexander Motin device_get_unit(dev), "msix", &max_irq); 195017ec7746SAlexander Motin max_irq = imin(ISP_MAX_IRQS, max_irq); 195108826086SAlexander Motin pcs->msicount = imin(pci_msix_count(dev), max_irq); 195208826086SAlexander Motin if (pcs->msicount > 0 && 195308826086SAlexander Motin pci_alloc_msix(dev, &pcs->msicount) != 0) 195408826086SAlexander Motin pcs->msicount = 0; 195508826086SAlexander Motin } 195608826086SAlexander Motin if (pcs->msicount == 0) { 195717ec7746SAlexander Motin max_irq = 1; 195817ec7746SAlexander Motin resource_int_value(device_get_name(dev), 195917ec7746SAlexander Motin device_get_unit(dev), "msi", &max_irq); 196017ec7746SAlexander Motin max_irq = imin(1, max_irq); 196117ec7746SAlexander Motin pcs->msicount = imin(pci_msi_count(dev), max_irq); 196208826086SAlexander Motin if (pcs->msicount > 0 && 196308826086SAlexander Motin pci_alloc_msi(dev, &pcs->msicount) != 0) 196408826086SAlexander Motin pcs->msicount = 0; 196508826086SAlexander Motin } 196608826086SAlexander Motin for (i = 0; i < MAX(1, pcs->msicount); i++) { 196708826086SAlexander Motin pcs->irq[i].iqd = i + (pcs->msicount > 0); 196808826086SAlexander Motin pcs->irq[i].irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 196908826086SAlexander Motin &pcs->irq[i].iqd, RF_ACTIVE | RF_SHAREABLE); 197008826086SAlexander Motin if (pcs->irq[i].irq == NULL) { 197108826086SAlexander Motin device_printf(dev, "could not allocate interrupt\n"); 197208826086SAlexander Motin break; 197308826086SAlexander Motin } 197408826086SAlexander Motin if (i == 0) 197508826086SAlexander Motin f = isp_platform_intr; 197608826086SAlexander Motin else if (i == 1) 197708826086SAlexander Motin f = isp_platform_intr_resp; 197808826086SAlexander Motin else 197908826086SAlexander Motin f = isp_platform_intr_atio; 198008826086SAlexander Motin if (bus_setup_intr(dev, pcs->irq[i].irq, ISP_IFLAGS, NULL, 198108826086SAlexander Motin f, isp, &pcs->irq[i].ih)) { 198208826086SAlexander Motin device_printf(dev, "could not setup interrupt\n"); 198308826086SAlexander Motin (void) bus_release_resource(dev, SYS_RES_IRQ, 198408826086SAlexander Motin pcs->irq[i].iqd, pcs->irq[i].irq); 198508826086SAlexander Motin break; 198608826086SAlexander Motin } 198708826086SAlexander Motin if (pcs->msicount > 1) { 198808826086SAlexander Motin bus_describe_intr(dev, pcs->irq[i].irq, pcs->irq[i].ih, 198908826086SAlexander Motin "%d", i); 199008826086SAlexander Motin } 199108826086SAlexander Motin isp->isp_nirq = i + 1; 199208826086SAlexander Motin } 1993abdc2e31SAlexander Motin ISP_LOCK(isp); 199408826086SAlexander Motin 199508826086SAlexander Motin return (isp->isp_nirq == 0); 199665adb54cSMatt Jacob } 199765adb54cSMatt Jacob 199865adb54cSMatt Jacob static void 19999cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg) 200065adb54cSMatt Jacob { 20011923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 2002d02373f1SMatt Jacob if (msg) 20036e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 20046e5c5328SMatt Jacob else 20056e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 2006d02373f1SMatt Jacob if (IS_SCSI(isp)) 2007d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 2008d02373f1SMatt Jacob else 2009d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 2010d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 2011d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 2012d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 2013d02373f1SMatt Jacob 2014d02373f1SMatt Jacob 2015d02373f1SMatt Jacob if (IS_SCSI(isp)) { 2016d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 2017d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 2018d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 2019d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 2020d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 2021d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 2022d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 2023d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 2024d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 2025d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 2026d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 2027d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 2028d02373f1SMatt Jacob } 2029d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 2030d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 2031d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 2032d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 2033d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 20341923f739SMatt Jacob pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1)); 203565adb54cSMatt Jacob } 2036