1aad970f1SDavid E. O'Brien /*- 22df76c16SMatt Jacob * Copyright (c) 1997-2008 by Matthew Jacob 3e5265237SMatt Jacob * All rights reserved. 465adb54cSMatt Jacob * 565adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 665adb54cSMatt Jacob * modification, are permitted provided that the following conditions 765adb54cSMatt Jacob * are met: 865adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 965adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1065adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 11aa57fd6fSMatt Jacob * 2. The name of the author may not be used to endorse or promote products 12aa57fd6fSMatt Jacob * derived from this software without specific prior written permission. 1365adb54cSMatt Jacob * 1465adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1565adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1665adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1765adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 1865adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1965adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2065adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2165adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2265adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2365adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2465adb54cSMatt Jacob * SUCH DAMAGE. 2565adb54cSMatt Jacob */ 26799881e0SMatt Jacob /* 27799881e0SMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 28799881e0SMatt Jacob * FreeBSD Version. 29799881e0SMatt Jacob */ 30aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 31aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 32aad970f1SDavid E. O'Brien 33960f6939SMatt Jacob #include <sys/param.h> 34960f6939SMatt Jacob #include <sys/systm.h> 35960f6939SMatt Jacob #include <sys/kernel.h> 36960f6939SMatt Jacob #include <sys/module.h> 379a5af410SMatt Jacob #include <sys/linker.h> 389a5af410SMatt Jacob #include <sys/firmware.h> 39960f6939SMatt Jacob #include <sys/bus.h> 4074a96f43SJohn Baldwin #include <sys/stdint.h> 4177e6a3b2SWarner Losh #include <dev/pci/pcireg.h> 4277e6a3b2SWarner Losh #include <dev/pci/pcivar.h> 43d720e6d5SJustin T. Gibbs #include <machine/bus.h> 44960f6939SMatt Jacob #include <machine/resource.h> 45960f6939SMatt Jacob #include <sys/rman.h> 46960f6939SMatt Jacob #include <sys/malloc.h> 472df76c16SMatt Jacob #include <sys/uio.h> 48960f6939SMatt Jacob 4917bc427dSMarius Strobl #ifdef __sparc64__ 5017bc427dSMarius Strobl #include <dev/ofw/openfirm.h> 5117bc427dSMarius Strobl #include <machine/ofw_machdep.h> 5217bc427dSMarius Strobl #endif 5317bc427dSMarius Strobl 54960f6939SMatt Jacob #include <dev/isp/isp_freebsd.h> 55d59bd469SMatt Jacob 5610365e5aSMatt Jacob static uint32_t isp_pci_rd_reg(ispsoftc_t *, int); 5710365e5aSMatt Jacob static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t); 5810365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int); 5910365e5aSMatt Jacob static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t); 6010365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); 6110365e5aSMatt Jacob static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); 62cd201b7bSAlexander Motin static uint32_t isp_pci_rd_reg_2600(ispsoftc_t *, int); 63cd201b7bSAlexander Motin static void isp_pci_wr_reg_2600(ispsoftc_t *, int, uint32_t); 646ce548a1SAlexander Motin static int isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 656ce548a1SAlexander Motin static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 666ce548a1SAlexander Motin static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 679cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *); 682df76c16SMatt Jacob static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *); 699cd7268eSMatt Jacob 709a5af410SMatt Jacob 713bda7a83SMatt Jacob static void isp_pci_reset0(ispsoftc_t *); 729cd7268eSMatt Jacob static void isp_pci_reset1(ispsoftc_t *); 739cd7268eSMatt Jacob static void isp_pci_dumpregs(ispsoftc_t *, const char *); 7465adb54cSMatt Jacob 7565adb54cSMatt Jacob static struct ispmdvec mdvec = { 76126ec864SMatt Jacob isp_pci_rd_isr, 7765adb54cSMatt Jacob isp_pci_rd_reg, 7865adb54cSMatt Jacob isp_pci_wr_reg, 7965adb54cSMatt Jacob isp_pci_mbxdma, 8065adb54cSMatt Jacob isp_pci_dmasetup, 810a70657fSMatt Jacob isp_common_dmateardown, 823bda7a83SMatt Jacob isp_pci_reset0, 8365adb54cSMatt Jacob isp_pci_reset1, 8465adb54cSMatt Jacob isp_pci_dumpregs, 8556aef503SMatt Jacob NULL, 86d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 8765adb54cSMatt Jacob }; 8865adb54cSMatt Jacob 89d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 90126ec864SMatt Jacob isp_pci_rd_isr, 91d59bd469SMatt Jacob isp_pci_rd_reg_1080, 92d59bd469SMatt Jacob isp_pci_wr_reg_1080, 93d59bd469SMatt Jacob isp_pci_mbxdma, 94d59bd469SMatt Jacob isp_pci_dmasetup, 950a70657fSMatt Jacob isp_common_dmateardown, 963bda7a83SMatt Jacob isp_pci_reset0, 97d59bd469SMatt Jacob isp_pci_reset1, 98d59bd469SMatt Jacob isp_pci_dumpregs, 9956aef503SMatt Jacob NULL, 100d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 101d59bd469SMatt Jacob }; 102d59bd469SMatt Jacob 103960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = { 104126ec864SMatt Jacob isp_pci_rd_isr, 105960f6939SMatt Jacob isp_pci_rd_reg_1080, 106960f6939SMatt Jacob isp_pci_wr_reg_1080, 107960f6939SMatt Jacob isp_pci_mbxdma, 108960f6939SMatt Jacob isp_pci_dmasetup, 1090a70657fSMatt Jacob isp_common_dmateardown, 1103bda7a83SMatt Jacob isp_pci_reset0, 111960f6939SMatt Jacob isp_pci_reset1, 112960f6939SMatt Jacob isp_pci_dumpregs, 11356aef503SMatt Jacob NULL, 114d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 115960f6939SMatt Jacob }; 116960f6939SMatt Jacob 11765adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 118126ec864SMatt Jacob isp_pci_rd_isr, 11965adb54cSMatt Jacob isp_pci_rd_reg, 12065adb54cSMatt Jacob isp_pci_wr_reg, 12165adb54cSMatt Jacob isp_pci_mbxdma, 12265adb54cSMatt Jacob isp_pci_dmasetup, 1230a70657fSMatt Jacob isp_common_dmateardown, 1243bda7a83SMatt Jacob isp_pci_reset0, 12565adb54cSMatt Jacob isp_pci_reset1, 126d02373f1SMatt Jacob isp_pci_dumpregs 12765adb54cSMatt Jacob }; 128222bb542SMatt Jacob 129222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 130126ec864SMatt Jacob isp_pci_rd_isr, 131126ec864SMatt Jacob isp_pci_rd_reg, 132126ec864SMatt Jacob isp_pci_wr_reg, 133126ec864SMatt Jacob isp_pci_mbxdma, 134126ec864SMatt Jacob isp_pci_dmasetup, 1350a70657fSMatt Jacob isp_common_dmateardown, 1363bda7a83SMatt Jacob isp_pci_reset0, 137126ec864SMatt Jacob isp_pci_reset1, 138126ec864SMatt Jacob isp_pci_dumpregs 139126ec864SMatt Jacob }; 140126ec864SMatt Jacob 141126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = { 142126ec864SMatt Jacob isp_pci_rd_isr_2300, 143222bb542SMatt Jacob isp_pci_rd_reg, 144222bb542SMatt Jacob isp_pci_wr_reg, 145222bb542SMatt Jacob isp_pci_mbxdma, 146222bb542SMatt Jacob isp_pci_dmasetup, 1470a70657fSMatt Jacob isp_common_dmateardown, 1483bda7a83SMatt Jacob isp_pci_reset0, 149222bb542SMatt Jacob isp_pci_reset1, 150d02373f1SMatt Jacob isp_pci_dumpregs 151222bb542SMatt Jacob }; 152d951bbcaSMatt Jacob 15310365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = { 15410365e5aSMatt Jacob isp_pci_rd_isr_2400, 15510365e5aSMatt Jacob isp_pci_rd_reg_2400, 15610365e5aSMatt Jacob isp_pci_wr_reg_2400, 15710365e5aSMatt Jacob isp_pci_mbxdma, 15810365e5aSMatt Jacob isp_pci_dmasetup, 1590a70657fSMatt Jacob isp_common_dmateardown, 1603bda7a83SMatt Jacob isp_pci_reset0, 16110365e5aSMatt Jacob isp_pci_reset1, 16210365e5aSMatt Jacob NULL 16310365e5aSMatt Jacob }; 16410365e5aSMatt Jacob 1652df76c16SMatt Jacob static struct ispmdvec mdvec_2500 = { 1662df76c16SMatt Jacob isp_pci_rd_isr_2400, 1672df76c16SMatt Jacob isp_pci_rd_reg_2400, 1682df76c16SMatt Jacob isp_pci_wr_reg_2400, 1692df76c16SMatt Jacob isp_pci_mbxdma, 1702df76c16SMatt Jacob isp_pci_dmasetup, 1712df76c16SMatt Jacob isp_common_dmateardown, 1722df76c16SMatt Jacob isp_pci_reset0, 1732df76c16SMatt Jacob isp_pci_reset1, 1742df76c16SMatt Jacob NULL 1752df76c16SMatt Jacob }; 1762df76c16SMatt Jacob 177218be0b2SAlexander Motin static struct ispmdvec mdvec_2600 = { 178218be0b2SAlexander Motin isp_pci_rd_isr_2400, 179cd201b7bSAlexander Motin isp_pci_rd_reg_2600, 180cd201b7bSAlexander Motin isp_pci_wr_reg_2600, 181218be0b2SAlexander Motin isp_pci_mbxdma, 182218be0b2SAlexander Motin isp_pci_dmasetup, 183218be0b2SAlexander Motin isp_common_dmateardown, 184218be0b2SAlexander Motin isp_pci_reset0, 185218be0b2SAlexander Motin isp_pci_reset1, 186218be0b2SAlexander Motin NULL 187218be0b2SAlexander Motin }; 188218be0b2SAlexander Motin 18965adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 19065adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 19165adb54cSMatt Jacob #endif 19265adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 19365adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 19465adb54cSMatt Jacob #endif 195d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 196d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 197d951bbcaSMatt Jacob #endif 198d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 199d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 200d951bbcaSMatt Jacob #endif 2018a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 2028a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 2038a97c03aSMatt Jacob #endif 204d951bbcaSMatt Jacob 205d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 206d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 207d951bbcaSMatt Jacob #endif 208d951bbcaSMatt Jacob 209d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 210d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 211d951bbcaSMatt Jacob #endif 212d951bbcaSMatt Jacob 213d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 214d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 215d951bbcaSMatt Jacob #endif 216d951bbcaSMatt Jacob 217ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 218ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 219ab6d0040SMatt Jacob #endif 220ab6d0040SMatt Jacob 22165adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 22265adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 22365adb54cSMatt Jacob #endif 22465adb54cSMatt Jacob 22565adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 22665adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 22765adb54cSMatt Jacob #endif 22865adb54cSMatt Jacob 229d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 230d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 231d59bd469SMatt Jacob #endif 232d59bd469SMatt Jacob 233f556e83bSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP10160 234f556e83bSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 235f556e83bSMatt Jacob #endif 236f556e83bSMatt Jacob 237960f6939SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP12160 238960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 239960f6939SMatt Jacob #endif 240960f6939SMatt Jacob 241d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 242d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 243d59bd469SMatt Jacob #endif 24465adb54cSMatt Jacob 24522e1dc85SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1280 24622e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 24722e1dc85SMatt Jacob #endif 24822e1dc85SMatt Jacob 24965adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 25065adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 25165adb54cSMatt Jacob #endif 25265adb54cSMatt Jacob 253222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 254222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 255222bb542SMatt Jacob #endif 256222bb542SMatt Jacob 257126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2300 258126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 259126ec864SMatt Jacob #endif 260126ec864SMatt Jacob 261126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2312 262126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 263126ec864SMatt Jacob #endif 264126ec864SMatt Jacob 265e5265237SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2322 266e5265237SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 267e5265237SMatt Jacob #endif 268e5265237SMatt Jacob 2698872e3d7SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2422 2708872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 2718872e3d7SMatt Jacob #endif 2728872e3d7SMatt Jacob 27341675df0SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2432 27441675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 27541675df0SMatt Jacob #endif 27641675df0SMatt Jacob 2772df76c16SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2532 2782df76c16SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2532 0x2532 2792df76c16SMatt Jacob #endif 2802df76c16SMatt Jacob 281dd1419abSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6312 282dd1419abSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 283dd1419abSMatt Jacob #endif 284dd1419abSMatt Jacob 2859a5af410SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6322 2869a5af410SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 2879a5af410SMatt Jacob #endif 2889a5af410SMatt Jacob 289a959d921SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP5432 290a959d921SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP5432 0x5432 291a959d921SMatt Jacob #endif 292a959d921SMatt Jacob 293218be0b2SAlexander Motin #ifndef PCI_PRODUCT_QLOGIC_ISP2031 294218be0b2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2031 0x2031 295218be0b2SAlexander Motin #endif 296218be0b2SAlexander Motin 29767eeadd2SAlexander Motin #ifndef PCI_PRODUCT_QLOGIC_ISP8031 29867eeadd2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP8031 0x8031 29967eeadd2SAlexander Motin #endif 30067eeadd2SAlexander Motin 301a959d921SMatt Jacob #define PCI_QLOGIC_ISP5432 \ 302a959d921SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC) 3039a5af410SMatt Jacob 30456aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 30556aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 306d59bd469SMatt Jacob 307d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 308d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 309d59bd469SMatt Jacob 310f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 311f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 312f556e83bSMatt Jacob 313960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 314960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 315960f6939SMatt Jacob 316d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 317d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 318d59bd469SMatt Jacob 31922e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 32022e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 32122e1dc85SMatt Jacob 32265adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 32365adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 32465adb54cSMatt Jacob 325222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 326222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 327222bb542SMatt Jacob 328126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 329126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 330126ec864SMatt Jacob 331126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 332126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 333126ec864SMatt Jacob 334e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 335e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 336e5265237SMatt Jacob 3376c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 3386c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 3396c426685SMatt Jacob 34041675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 34141675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 34241675df0SMatt Jacob 3432df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 3442df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 3452df76c16SMatt Jacob 346dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 347dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 348dd1419abSMatt Jacob 3499a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 3509a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 3519a5af410SMatt Jacob 352218be0b2SAlexander Motin #define PCI_QLOGIC_ISP2031 \ 353218be0b2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC) 354218be0b2SAlexander Motin 35567eeadd2SAlexander Motin #define PCI_QLOGIC_ISP8031 \ 35667eeadd2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP8031 << 16) | PCI_VENDOR_QLOGIC) 35767eeadd2SAlexander Motin 358e11a1ee8SMatt Jacob /* 359e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 360e11a1ee8SMatt Jacob */ 361e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 362e11a1ee8SMatt Jacob 363d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 364d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 36565adb54cSMatt Jacob 366960f6939SMatt Jacob static int isp_pci_probe (device_t); 367960f6939SMatt Jacob static int isp_pci_attach (device_t); 36810365e5aSMatt Jacob static int isp_pci_detach (device_t); 36965adb54cSMatt Jacob 3701923f739SMatt Jacob 3710230a28bSMatt Jacob #define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev 37265adb54cSMatt Jacob struct isp_pcisoftc { 3739cd7268eSMatt Jacob ispsoftc_t pci_isp; 374960f6939SMatt Jacob device_t pci_dev; 375e95725cbSMatt Jacob struct resource * regs; 376d876d6c3SAlexander Motin struct resource * regs1; 377cd201b7bSAlexander Motin struct resource * regs2; 378e95725cbSMatt Jacob void * irq; 379e95725cbSMatt Jacob int iqd; 380e95725cbSMatt Jacob int rtp; 381e95725cbSMatt Jacob int rgd; 382d876d6c3SAlexander Motin int rtp1; 383d876d6c3SAlexander Motin int rgd1; 384cd201b7bSAlexander Motin int rtp2; 385cd201b7bSAlexander Motin int rgd2; 386960f6939SMatt Jacob void * ih; 387d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3881923f739SMatt Jacob bus_dma_tag_t dmat; 3890a70657fSMatt Jacob int msicount; 39065adb54cSMatt Jacob }; 39165adb54cSMatt Jacob 39210365e5aSMatt Jacob 393960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 394960f6939SMatt Jacob /* Device interface */ 395960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 396960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 39710365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 398960f6939SMatt Jacob { 0, 0 } 39965adb54cSMatt Jacob }; 40065adb54cSMatt Jacob 401960f6939SMatt Jacob static driver_t isp_pci_driver = { 402960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 403960f6939SMatt Jacob }; 404960f6939SMatt Jacob static devclass_t isp_devclass; 405960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 406d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1); 407d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1); 4089e7d423dSMatt Jacob static int isp_nvports = 0; 40965adb54cSMatt Jacob 410960f6939SMatt Jacob static int 411960f6939SMatt Jacob isp_pci_probe(device_t dev) 41265adb54cSMatt Jacob { 413960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 41456aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 415960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 41665adb54cSMatt Jacob break; 417d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 418960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 419c6608df3SMatt Jacob break; 420c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 421960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 422d59bd469SMatt Jacob break; 42322e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 424960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 425960f6939SMatt Jacob break; 426f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 427f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 428f556e83bSMatt Jacob break; 429960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 430e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 431e11a1ee8SMatt Jacob return (ENXIO); 432e11a1ee8SMatt Jacob } 433960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 43422e1dc85SMatt Jacob break; 43565adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 436960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 43765adb54cSMatt Jacob break; 4385542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 439960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 4405542fe4bSMatt Jacob break; 441126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 442126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 443126ec864SMatt Jacob break; 444126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 445126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 446126ec864SMatt Jacob break; 447e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 448e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 449e5265237SMatt Jacob break; 4508872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 4518872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 4528872e3d7SMatt Jacob break; 45341675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 45441675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 45541675df0SMatt Jacob break; 4562df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 4572df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 4582df76c16SMatt Jacob break; 459a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 460a959d921SMatt Jacob device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter"); 461a959d921SMatt Jacob break; 462dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 463dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 464dd1419abSMatt Jacob break; 4659a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4669a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4679a5af410SMatt Jacob break; 468218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 469218be0b2SAlexander Motin device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter"); 470218be0b2SAlexander Motin break; 47167eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 47267eeadd2SAlexander Motin device_set_desc(dev, "Qlogic ISP 8031 PCI FCoE Adapter"); 47367eeadd2SAlexander Motin break; 47465adb54cSMatt Jacob default: 475960f6939SMatt Jacob return (ENXIO); 47665adb54cSMatt Jacob } 47773030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 478d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 479a95ae193SMatt Jacob "Core Version %d.%d\n", 480d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 481d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 48273030e03SMatt Jacob isp_announced++; 48365adb54cSMatt Jacob } 48456aef503SMatt Jacob /* 48556aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 48656aef503SMatt Jacob * XXXX: (or increase a reference count to it). 48756aef503SMatt Jacob */ 488b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 48965adb54cSMatt Jacob } 49065adb54cSMatt Jacob 4919cd7268eSMatt Jacob static void 4929e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 4939cd7268eSMatt Jacob { 4949cd7268eSMatt Jacob int tval; 495f7c631bcSMatt Jacob 4969cd7268eSMatt Jacob tval = 0; 4972df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 4989cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4999cd7268eSMatt Jacob } 5009cd7268eSMatt Jacob tval = 0; 5012df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 5029cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 5039cd7268eSMatt Jacob } 504336b5612SMatt Jacob tval = 0; 5052df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 506336b5612SMatt Jacob if (tval) { 507336b5612SMatt Jacob isp->isp_dblev = tval; 508336b5612SMatt Jacob } else { 509336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 510336b5612SMatt Jacob } 511336b5612SMatt Jacob if (bootverbose) { 512336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 513336b5612SMatt Jacob } 5149e7d423dSMatt Jacob tval = -1; 5152df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 516ffe6ea05SAlexander Motin if (tval > 0 && tval <= 254) { 5179e7d423dSMatt Jacob isp_nvports = tval; 5182df76c16SMatt Jacob } 5192df76c16SMatt Jacob tval = 7; 5202df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 5212df76c16SMatt Jacob isp_quickboot_time = tval; 522336b5612SMatt Jacob } 523336b5612SMatt Jacob 524336b5612SMatt Jacob static void 5252df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 526336b5612SMatt Jacob { 527336b5612SMatt Jacob const char *sptr; 5289e7d423dSMatt Jacob int tval = 0; 52907f56f1cSAlexander Motin char prefix[12], name[16]; 530336b5612SMatt Jacob 53107f56f1cSAlexander Motin if (chan == 0) 53207f56f1cSAlexander Motin prefix[0] = 0; 53307f56f1cSAlexander Motin else 53407f56f1cSAlexander Motin snprintf(prefix, sizeof(prefix), "chan%d.", chan); 53507f56f1cSAlexander Motin snprintf(name, sizeof(name), "%siid", prefix); 53607f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 53707f56f1cSAlexander Motin name, &tval)) { 5382df76c16SMatt Jacob if (IS_FC(isp)) { 5392df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 5402df76c16SMatt Jacob } else { 54117bc427dSMarius Strobl #ifdef __sparc64__ 54217bc427dSMarius Strobl ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev); 54317bc427dSMarius Strobl #else 5442df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = 7; 54517bc427dSMarius Strobl #endif 5462df76c16SMatt Jacob } 5472df76c16SMatt Jacob } else { 5482df76c16SMatt Jacob if (IS_FC(isp)) { 5492df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 5502df76c16SMatt Jacob } else { 5512df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = tval; 5522df76c16SMatt Jacob } 553336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 554336b5612SMatt Jacob } 5552df76c16SMatt Jacob 5563e6deb33SAlexander Motin if (IS_SCSI(isp)) 5573e6deb33SAlexander Motin return; 5583e6deb33SAlexander Motin 5592df76c16SMatt Jacob tval = -1; 56007f56f1cSAlexander Motin snprintf(name, sizeof(name), "%srole", prefix); 56107f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 56207f56f1cSAlexander Motin name, &tval) == 0) { 5632df76c16SMatt Jacob switch (tval) { 5642df76c16SMatt Jacob case ISP_ROLE_NONE: 5652df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 5662df76c16SMatt Jacob case ISP_ROLE_TARGET: 56707f56f1cSAlexander Motin case ISP_ROLE_BOTH: 56807f56f1cSAlexander Motin device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval); 5692df76c16SMatt Jacob break; 5702df76c16SMatt Jacob default: 5712df76c16SMatt Jacob tval = -1; 5722df76c16SMatt Jacob break; 573336b5612SMatt Jacob } 574336b5612SMatt Jacob } 5752df76c16SMatt Jacob if (tval == -1) { 5762df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 5772df76c16SMatt Jacob } 5784ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 579336b5612SMatt Jacob 5809cd7268eSMatt Jacob tval = 0; 58107f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfullduplex", prefix); 58207f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 58307f56f1cSAlexander Motin name, &tval) == 0 && tval != 0) { 5849cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5859cd7268eSMatt Jacob } 5869cd7268eSMatt Jacob sptr = 0; 58707f56f1cSAlexander Motin snprintf(name, sizeof(name), "%stopology", prefix); 58807f56f1cSAlexander Motin if (resource_string_value(device_get_name(dev), device_get_unit(dev), 58907f56f1cSAlexander Motin name, (const char **) &sptr) == 0 && sptr != 0) { 5909cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 5919cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 5929cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 5939cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5949cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 5959cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 5969cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 5979cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 5989cd7268eSMatt Jacob } 599960f6939SMatt Jacob } 600960f6939SMatt Jacob 601387d8239SMatt Jacob tval = 0; 60207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snofctape", prefix); 60307f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 60407f56f1cSAlexander Motin name, &tval); 605387d8239SMatt Jacob if (tval) { 606387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_NOFCTAPE; 607387d8239SMatt Jacob } 608387d8239SMatt Jacob 609387d8239SMatt Jacob tval = 0; 61007f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfctape", prefix); 61107f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 61207f56f1cSAlexander Motin name, &tval); 613387d8239SMatt Jacob if (tval) { 614387d8239SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NOFCTAPE; 615387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_FCTAPE; 616387d8239SMatt Jacob } 617387d8239SMatt Jacob 618387d8239SMatt Jacob 6199ba86737SMatt Jacob /* 6209cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 6219cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 6229cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 6239cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 6249cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 6259cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 6269cd7268eSMatt Jacob */ 6279cd7268eSMatt Jacob sptr = 0; 62807f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sportwwn", prefix); 62907f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 63007f56f1cSAlexander Motin name, (const char **) &sptr); 6319cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6329cd7268eSMatt Jacob char *eptr = 0; 6332df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 6342df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 6359cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 6362df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 6379cd7268eSMatt Jacob } 6389cd7268eSMatt Jacob } 6399cd7268eSMatt Jacob 6409cd7268eSMatt Jacob sptr = 0; 64107f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snodewwn", prefix); 64207f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 64307f56f1cSAlexander Motin name, (const char **) &sptr); 6449cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6459cd7268eSMatt Jacob char *eptr = 0; 6462df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 6472df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 6489cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6492df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 6509cd7268eSMatt Jacob } 6519cd7268eSMatt Jacob } 6529cd7268eSMatt Jacob 653f7c631bcSMatt Jacob tval = -1; 65407f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sloop_down_limit", prefix); 65507f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 65607f56f1cSAlexander Motin name, &tval); 65710365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6582df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 65910365e5aSMatt Jacob } else { 6602df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 66110365e5aSMatt Jacob } 66210365e5aSMatt Jacob 663f7c631bcSMatt Jacob tval = -1; 66407f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sgone_device_time", prefix); 66507f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 66607f56f1cSAlexander Motin name, &tval); 667f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6682df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 669f7c631bcSMatt Jacob } else { 6702df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 671f7c631bcSMatt Jacob } 6729cd7268eSMatt Jacob } 6739cd7268eSMatt Jacob 6749cd7268eSMatt Jacob static int 6759cd7268eSMatt Jacob isp_pci_attach(device_t dev) 6769cd7268eSMatt Jacob { 677218be0b2SAlexander Motin int i, locksetup = 0; 6782df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 6799cd7268eSMatt Jacob struct isp_pcisoftc *pcs; 680a035b0afSMatt Jacob ispsoftc_t *isp; 6812df76c16SMatt Jacob size_t psize, xsize; 6822df76c16SMatt Jacob char fwname[32]; 6839cd7268eSMatt Jacob 6849cd7268eSMatt Jacob pcs = device_get_softc(dev); 6859cd7268eSMatt Jacob if (pcs == NULL) { 6869cd7268eSMatt Jacob device_printf(dev, "cannot get softc\n"); 6879cd7268eSMatt Jacob return (ENOMEM); 6889cd7268eSMatt Jacob } 6899cd7268eSMatt Jacob memset(pcs, 0, sizeof (*pcs)); 6902df76c16SMatt Jacob 6919cd7268eSMatt Jacob pcs->pci_dev = dev; 6929cd7268eSMatt Jacob isp = &pcs->pci_isp; 6932df76c16SMatt Jacob isp->isp_dev = dev; 6942df76c16SMatt Jacob isp->isp_nchan = 1; 695387d8239SMatt Jacob if (sizeof (bus_addr_t) > 4) 696387d8239SMatt Jacob isp->isp_osinfo.sixtyfourbit = 1; 6979cd7268eSMatt Jacob 6989cd7268eSMatt Jacob /* 699336b5612SMatt Jacob * Get Generic Options 7009cd7268eSMatt Jacob */ 7019e7d423dSMatt Jacob isp_nvports = 0; 7029e7d423dSMatt Jacob isp_get_generic_options(dev, isp); 7039cd7268eSMatt Jacob 704ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 705cd201b7bSAlexander Motin pcs->irq = pcs->regs = pcs->regs2 = NULL; 706e95725cbSMatt Jacob pcs->rgd = pcs->rtp = pcs->iqd = 0; 707960f6939SMatt Jacob 7082df76c16SMatt Jacob pcs->pci_dev = dev; 709d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 710d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 711d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 712d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 713d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 7142df76c16SMatt Jacob 7152df76c16SMatt Jacob switch (pci_get_devid(dev)) { 7162df76c16SMatt Jacob case PCI_QLOGIC_ISP1020: 7172df76c16SMatt Jacob did = 0x1040; 7182df76c16SMatt Jacob isp->isp_mdvec = &mdvec; 7192df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 7202df76c16SMatt Jacob break; 7212df76c16SMatt Jacob case PCI_QLOGIC_ISP1080: 7222df76c16SMatt Jacob did = 0x1080; 7232df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7242df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 7252df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7262df76c16SMatt Jacob break; 7272df76c16SMatt Jacob case PCI_QLOGIC_ISP1240: 7282df76c16SMatt Jacob did = 0x1080; 7292df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7302df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1240; 7312df76c16SMatt Jacob isp->isp_nchan = 2; 7322df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7332df76c16SMatt Jacob break; 7342df76c16SMatt Jacob case PCI_QLOGIC_ISP1280: 7352df76c16SMatt Jacob did = 0x1080; 7362df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7372df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1280; 7382df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7392df76c16SMatt Jacob break; 7402df76c16SMatt Jacob case PCI_QLOGIC_ISP10160: 7412df76c16SMatt Jacob did = 0x12160; 7422df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7432df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_10160; 7442df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7452df76c16SMatt Jacob break; 7462df76c16SMatt Jacob case PCI_QLOGIC_ISP12160: 7472df76c16SMatt Jacob did = 0x12160; 7482df76c16SMatt Jacob isp->isp_nchan = 2; 7492df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7502df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_12160; 7512df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7522df76c16SMatt Jacob break; 7532df76c16SMatt Jacob case PCI_QLOGIC_ISP2100: 7542df76c16SMatt Jacob did = 0x2100; 7552df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2100; 7562df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2100; 7572df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 758960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 759ab6d0040SMatt Jacob /* 760ab6d0040SMatt Jacob * XXX: Need to get the actual revision 761ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 762ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 763ab6d0040SMatt Jacob * XXX; boards. 764ab6d0040SMatt Jacob */ 765ab6d0040SMatt Jacob linesz = 1; 766ab6d0040SMatt Jacob } 7672df76c16SMatt Jacob break; 7682df76c16SMatt Jacob case PCI_QLOGIC_ISP2200: 7692df76c16SMatt Jacob did = 0x2200; 7702df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2200; 7712df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2200; 7722df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 7732df76c16SMatt Jacob break; 7742df76c16SMatt Jacob case PCI_QLOGIC_ISP2300: 7752df76c16SMatt Jacob did = 0x2300; 7762df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7772df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2300; 7782df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7792df76c16SMatt Jacob break; 7802df76c16SMatt Jacob case PCI_QLOGIC_ISP2312: 7812df76c16SMatt Jacob case PCI_QLOGIC_ISP6312: 7822df76c16SMatt Jacob did = 0x2300; 7832df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7842df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2312; 7852df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7862df76c16SMatt Jacob break; 7872df76c16SMatt Jacob case PCI_QLOGIC_ISP2322: 7882df76c16SMatt Jacob case PCI_QLOGIC_ISP6322: 7892df76c16SMatt Jacob did = 0x2322; 7902df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7912df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2322; 7922df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7932df76c16SMatt Jacob break; 7942df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 7952df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 7962df76c16SMatt Jacob did = 0x2400; 7972df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7982df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 7992df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 8002df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 8012df76c16SMatt Jacob break; 8022df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 8032df76c16SMatt Jacob did = 0x2500; 8042df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 8052df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 8062df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 8072df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 8082df76c16SMatt Jacob break; 809a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 810a959d921SMatt Jacob did = 0x2500; 811a959d921SMatt Jacob isp->isp_mdvec = &mdvec_2500; 812a959d921SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 813a959d921SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 814a959d921SMatt Jacob break; 815218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 81667eeadd2SAlexander Motin case PCI_QLOGIC_ISP8031: 817218be0b2SAlexander Motin did = 0x2600; 818218be0b2SAlexander Motin isp->isp_nchan += isp_nvports; 819218be0b2SAlexander Motin isp->isp_mdvec = &mdvec_2600; 820218be0b2SAlexander Motin isp->isp_type = ISP_HA_FC_2600; 821218be0b2SAlexander Motin pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 822218be0b2SAlexander Motin break; 8232df76c16SMatt Jacob default: 8242df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 8252df76c16SMatt Jacob goto bad; 8262df76c16SMatt Jacob break; 82765adb54cSMatt Jacob } 8282df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 8292df76c16SMatt Jacob 830218be0b2SAlexander Motin if (IS_26XX(isp)) { 831218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 832218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 833218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 834218be0b2SAlexander Motin RF_ACTIVE); 835d876d6c3SAlexander Motin pcs->rtp1 = SYS_RES_MEMORY; 836d876d6c3SAlexander Motin pcs->rgd1 = PCIR_BAR(2); 837d876d6c3SAlexander Motin pcs->regs1 = bus_alloc_resource_any(dev, pcs->rtp1, &pcs->rgd1, 838d876d6c3SAlexander Motin RF_ACTIVE); 839cd201b7bSAlexander Motin pcs->rtp2 = SYS_RES_MEMORY; 840cd201b7bSAlexander Motin pcs->rgd2 = PCIR_BAR(4); 841cd201b7bSAlexander Motin pcs->regs2 = bus_alloc_resource_any(dev, pcs->rtp2, &pcs->rgd2, 842cd201b7bSAlexander Motin RF_ACTIVE); 843218be0b2SAlexander Motin } else { 844218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 845218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(1); 846218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 847218be0b2SAlexander Motin RF_ACTIVE); 848218be0b2SAlexander Motin if (pcs->regs == NULL) { 849218be0b2SAlexander Motin pcs->rtp = SYS_RES_IOPORT; 850218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 851218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, 852218be0b2SAlexander Motin &pcs->rgd, RF_ACTIVE); 853218be0b2SAlexander Motin } 854218be0b2SAlexander Motin } 855218be0b2SAlexander Motin if (pcs->regs == NULL) { 856218be0b2SAlexander Motin device_printf(dev, "Unable to map any ports\n"); 857218be0b2SAlexander Motin goto bad; 858218be0b2SAlexander Motin } 859218be0b2SAlexander Motin if (bootverbose) { 860218be0b2SAlexander Motin device_printf(dev, "Using %s space register mapping\n", 861218be0b2SAlexander Motin (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory"); 862218be0b2SAlexander Motin } 863cd201b7bSAlexander Motin isp->isp_regs = pcs->regs; 864cd201b7bSAlexander Motin isp->isp_regs2 = pcs->regs2; 865218be0b2SAlexander Motin 8662df76c16SMatt Jacob if (IS_FC(isp)) { 867222bb542SMatt Jacob psize = sizeof (fcparam); 8682df76c16SMatt Jacob xsize = sizeof (struct isp_fc); 8692df76c16SMatt Jacob } else { 8702df76c16SMatt Jacob psize = sizeof (sdparam); 8712df76c16SMatt Jacob xsize = sizeof (struct isp_spi); 872222bb542SMatt Jacob } 8732df76c16SMatt Jacob psize *= isp->isp_nchan; 8742df76c16SMatt Jacob xsize *= isp->isp_nchan; 8757cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 876c6608df3SMatt Jacob if (isp->isp_param == NULL) { 877960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 878960f6939SMatt Jacob goto bad; 879c6608df3SMatt Jacob } 8802df76c16SMatt Jacob isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 8812df76c16SMatt Jacob if (isp->isp_osinfo.pc.ptr == NULL) { 8822df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 8832df76c16SMatt Jacob goto bad; 8842df76c16SMatt Jacob } 88565adb54cSMatt Jacob 886336b5612SMatt Jacob /* 887336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 888336b5612SMatt Jacob */ 8892df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 8902df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 8919a5af410SMatt Jacob } 8929a5af410SMatt Jacob 8939a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 8949a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 8959a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 8969a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8979a5af410SMatt Jacob } 8989a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 899ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname); 9005f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 9019a5af410SMatt Jacob } 90256aef503SMatt Jacob 90356aef503SMatt Jacob /* 904ad0ab753SMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 905d951bbcaSMatt Jacob */ 906c68534f1SScott Long cmd = pci_read_config(dev, PCIR_COMMAND, 2); 9079e7d423dSMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 90875c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 90975c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 91075c1e828SMatt Jacob } 9118a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 9128a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 9138a97c03aSMatt Jacob } 91406cacb29SMatt Jacob if (IS_24XX(isp)) { 91506cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 91606cacb29SMatt Jacob } 917b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 918ab6d0040SMatt Jacob 919d951bbcaSMatt Jacob /* 920222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 921d951bbcaSMatt Jacob */ 922960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 9236a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 924ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data); 9256a7d12e1SMatt Jacob data = linesz; 926960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 927d951bbcaSMatt Jacob } 928ab6d0040SMatt Jacob 929d951bbcaSMatt Jacob /* 930d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 931d951bbcaSMatt Jacob */ 932960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 933d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 934d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 935ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data); 936960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 937d951bbcaSMatt Jacob } 938ab6d0040SMatt Jacob 939ab6d0040SMatt Jacob /* 940ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 941ab6d0040SMatt Jacob */ 942960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 943ab6d0040SMatt Jacob data &= ~1; 944960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 9452df76c16SMatt Jacob 946d876d6c3SAlexander Motin if (IS_26XX(isp)) { 947d876d6c3SAlexander Motin /* 26XX chips support only MSI-X, so start from them. */ 948d876d6c3SAlexander Motin pcs->msicount = imin(pci_msix_count(dev), 1); 949d876d6c3SAlexander Motin if (pcs->msicount > 0 && 950d876d6c3SAlexander Motin (i = pci_alloc_msix(dev, &pcs->msicount)) == 0) { 951e95725cbSMatt Jacob pcs->iqd = 1; 9520a70657fSMatt Jacob } else { 953d876d6c3SAlexander Motin pcs->msicount = 0; 954d876d6c3SAlexander Motin } 955d876d6c3SAlexander Motin } 956d876d6c3SAlexander Motin if (pcs->msicount == 0 && (IS_24XX(isp) || IS_2322(isp))) { 957d876d6c3SAlexander Motin /* 958d876d6c3SAlexander Motin * Older chips support both MSI and MSI-X, but I have 959d876d6c3SAlexander Motin * feeling that older firmware may not support MSI-X, 960d876d6c3SAlexander Motin * but we have no way to check the firmware flag here. 961d876d6c3SAlexander Motin */ 962d876d6c3SAlexander Motin pcs->msicount = imin(pci_msi_count(dev), 1); 963d876d6c3SAlexander Motin if (pcs->msicount > 0 && 964d876d6c3SAlexander Motin pci_alloc_msi(dev, &pcs->msicount) == 0) { 965d876d6c3SAlexander Motin pcs->iqd = 1; 966d876d6c3SAlexander Motin } else { 967d876d6c3SAlexander Motin pcs->msicount = 0; 9680a70657fSMatt Jacob } 9690a70657fSMatt Jacob } 970e95725cbSMatt Jacob pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE); 971e95725cbSMatt Jacob if (pcs->irq == NULL) { 972960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 973960f6939SMatt Jacob goto bad; 974960f6939SMatt Jacob } 975960f6939SMatt Jacob 976f09b1922SMatt Jacob /* Make sure the lock is set up. */ 9776008862bSJohn Baldwin mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); 978f09b1922SMatt Jacob locksetup++; 979f09b1922SMatt Jacob 980e95725cbSMatt Jacob if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { 981f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 982f09b1922SMatt Jacob goto bad; 983f09b1922SMatt Jacob } 984960f6939SMatt Jacob 98505fbcbb0SMatt Jacob /* 98675c1e828SMatt Jacob * Last minute checks... 98775c1e828SMatt Jacob */ 98810365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 98975c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 99075c1e828SMatt Jacob } 99175c1e828SMatt Jacob 99275c1e828SMatt Jacob /* 99305fbcbb0SMatt Jacob * Make sure we're in reset state. 99405fbcbb0SMatt Jacob */ 9953395b056SMatt Jacob ISP_LOCK(isp); 996dfd24649SAlexander Motin if (isp_reinit(isp, 1) != 0) { 9973395b056SMatt Jacob ISP_UNLOCK(isp); 998960f6939SMatt Jacob goto bad; 99965adb54cSMatt Jacob } 10002df76c16SMatt Jacob ISP_UNLOCK(isp); 10012df76c16SMatt Jacob if (isp_attach(isp)) { 10022df76c16SMatt Jacob ISP_LOCK(isp); 100365adb54cSMatt Jacob isp_uninit(isp); 10043395b056SMatt Jacob ISP_UNLOCK(isp); 1005960f6939SMatt Jacob goto bad; 1006d59bd469SMatt Jacob } 1007960f6939SMatt Jacob return (0); 1008960f6939SMatt Jacob 1009960f6939SMatt Jacob bad: 1010a035b0afSMatt Jacob if (pcs->ih) { 1011e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 1012960f6939SMatt Jacob } 1013a035b0afSMatt Jacob if (locksetup) { 10143395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 10153395b056SMatt Jacob } 1016e95725cbSMatt Jacob if (pcs->irq) { 1017e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 1018960f6939SMatt Jacob } 1019a035b0afSMatt Jacob if (pcs->msicount) { 10200a70657fSMatt Jacob pci_release_msi(dev); 10210a70657fSMatt Jacob } 1022cd201b7bSAlexander Motin if (pcs->regs) 1023e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 1024d876d6c3SAlexander Motin if (pcs->regs1) 1025d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 1026cd201b7bSAlexander Motin if (pcs->regs2) 1027cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 10289cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 1029960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 10302df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 10312df76c16SMatt Jacob } 10322df76c16SMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 10332df76c16SMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 10342df76c16SMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 10359cd7268eSMatt Jacob } 1036960f6939SMatt Jacob return (ENXIO); 103765adb54cSMatt Jacob } 103865adb54cSMatt Jacob 103910365e5aSMatt Jacob static int 104010365e5aSMatt Jacob isp_pci_detach(device_t dev) 104110365e5aSMatt Jacob { 104210365e5aSMatt Jacob struct isp_pcisoftc *pcs; 104310365e5aSMatt Jacob ispsoftc_t *isp; 1044e95725cbSMatt Jacob int status; 104510365e5aSMatt Jacob 104610365e5aSMatt Jacob pcs = device_get_softc(dev); 104710365e5aSMatt Jacob if (pcs == NULL) { 104810365e5aSMatt Jacob return (ENXIO); 104910365e5aSMatt Jacob } 105010365e5aSMatt Jacob isp = (ispsoftc_t *) pcs; 1051e95725cbSMatt Jacob status = isp_detach(isp); 1052e95725cbSMatt Jacob if (status) 1053e95725cbSMatt Jacob return (status); 1054e95725cbSMatt Jacob ISP_LOCK(isp); 1055e95725cbSMatt Jacob isp_uninit(isp); 1056e95725cbSMatt Jacob if (pcs->ih) { 1057e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 1058e95725cbSMatt Jacob } 1059e95725cbSMatt Jacob ISP_UNLOCK(isp); 10602df76c16SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 1061e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 1062e95725cbSMatt Jacob if (pcs->msicount) { 1063e95725cbSMatt Jacob pci_release_msi(dev); 1064e95725cbSMatt Jacob } 1065e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 1066d876d6c3SAlexander Motin if (pcs->regs1) 1067d876d6c3SAlexander Motin (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); 1068cd201b7bSAlexander Motin if (pcs->regs2) 1069cd201b7bSAlexander Motin (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); 1070387d8239SMatt Jacob /* 1071387d8239SMatt Jacob * XXX: THERE IS A LOT OF LEAKAGE HERE 1072387d8239SMatt Jacob */ 1073e95725cbSMatt Jacob if (pcs->pci_isp.isp_param) { 1074e95725cbSMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 1075e95725cbSMatt Jacob pcs->pci_isp.isp_param = NULL; 1076e95725cbSMatt Jacob } 1077e95725cbSMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 1078e95725cbSMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 1079e95725cbSMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 1080e95725cbSMatt Jacob } 108110365e5aSMatt Jacob return (0); 108210365e5aSMatt Jacob } 108310365e5aSMatt Jacob 1084126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 1085126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 10864cc9e3e7SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xfff)) 1087126ec864SMatt Jacob 1088cd201b7bSAlexander Motin #define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off)) 1089cd201b7bSAlexander Motin #define BXW2(isp, off, v) bus_write_2((isp)->isp_regs, (off), (v)) 1090cd201b7bSAlexander Motin #define BXR4(isp, off) bus_read_4((isp)->isp_regs, (off)) 1091cd201b7bSAlexander Motin #define BXW4(isp, off, v) bus_write_4((isp)->isp_regs, (off), (v)) 1092cd201b7bSAlexander Motin #define B2R4(isp, off) bus_read_4((isp)->isp_regs2, (off)) 1093cd201b7bSAlexander Motin #define B2W4(isp, off, v) bus_write_4((isp)->isp_regs2, (off), (v)) 1094126ec864SMatt Jacob 10952df76c16SMatt Jacob static ISP_INLINE int 10969cd7268eSMatt Jacob isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) 1097126ec864SMatt Jacob { 109810365e5aSMatt Jacob uint32_t val0, val1; 1099126ec864SMatt Jacob int i = 0; 1100126ec864SMatt Jacob 1101126ec864SMatt Jacob do { 11026a7d12e1SMatt Jacob val0 = BXR2(isp, IspVirt2Off(isp, off)); 11036a7d12e1SMatt Jacob val1 = BXR2(isp, IspVirt2Off(isp, off)); 1104126ec864SMatt Jacob } while (val0 != val1 && ++i < 1000); 1105126ec864SMatt Jacob if (val0 != val1) { 1106126ec864SMatt Jacob return (1); 1107126ec864SMatt Jacob } 1108126ec864SMatt Jacob *rp = val0; 1109126ec864SMatt Jacob return (0); 1110126ec864SMatt Jacob } 1111126ec864SMatt Jacob 1112126ec864SMatt Jacob static int 11136ce548a1SAlexander Motin isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 1114126ec864SMatt Jacob { 11151dae40ebSMatt Jacob uint16_t isr, sema; 1116126ec864SMatt Jacob 1117126ec864SMatt Jacob if (IS_2100(isp)) { 1118126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { 1119126ec864SMatt Jacob return (0); 1120126ec864SMatt Jacob } 1121126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { 1122126ec864SMatt Jacob return (0); 1123126ec864SMatt Jacob } 1124126ec864SMatt Jacob } else { 11256a7d12e1SMatt Jacob isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR)); 11266a7d12e1SMatt Jacob sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA)); 1127126ec864SMatt Jacob } 1128126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 1129126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 1130126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 1131126ec864SMatt Jacob if (isr == 0 && sema == 0) { 1132126ec864SMatt Jacob return (0); 1133126ec864SMatt Jacob } 1134126ec864SMatt Jacob *isrp = isr; 1135126ec864SMatt Jacob if ((*semap = sema) != 0) { 1136126ec864SMatt Jacob if (IS_2100(isp)) { 11376ce548a1SAlexander Motin if (isp_pci_rd_debounced(isp, OUTMAILBOX0, info)) { 1138126ec864SMatt Jacob return (0); 1139126ec864SMatt Jacob } 1140126ec864SMatt Jacob } else { 11416ce548a1SAlexander Motin *info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 1142126ec864SMatt Jacob } 1143126ec864SMatt Jacob } 1144126ec864SMatt Jacob return (1); 1145126ec864SMatt Jacob } 1146126ec864SMatt Jacob 1147126ec864SMatt Jacob static int 11486ce548a1SAlexander Motin isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 1149126ec864SMatt Jacob { 11506ce548a1SAlexander Motin uint32_t hccr, r2hisr; 1151126ec864SMatt Jacob 11526a7d12e1SMatt Jacob if (!(BXR2(isp, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 11533bd40330SMatt Jacob *isrp = 0; 1154db4fa023SMatt Jacob return (0); 11553bd40330SMatt Jacob } 11566a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO)); 1157126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 1158126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 1159126ec864SMatt Jacob *isrp = 0; 1160126ec864SMatt Jacob return (0); 1161126ec864SMatt Jacob } 11626ce548a1SAlexander Motin switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) { 1163126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1164126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1165126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1166126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 1167126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 1168126ec864SMatt Jacob *semap = 1; 11696ce548a1SAlexander Motin break; 1170fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 11716ce548a1SAlexander Motin *info = ASYNC_RIO16_1; 1172fc3bbaaaSMatt Jacob *semap = 1; 1173fc3bbaaaSMatt Jacob return (1); 1174fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 11756ce548a1SAlexander Motin *info = ASYNC_CMD_CMPLT; 1176fc3bbaaaSMatt Jacob *semap = 1; 1177fc3bbaaaSMatt Jacob return (1); 1178fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 11796ce548a1SAlexander Motin *info = ASYNC_CTIO_DONE; 1180fc3bbaaaSMatt Jacob *semap = 1; 1181fc3bbaaaSMatt Jacob return (1); 1182126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 1183126ec864SMatt Jacob *semap = 0; 11846ce548a1SAlexander Motin break; 1185126ec864SMatt Jacob default: 11868a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 11878a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 11888a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 1189443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR)); 11905ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 11918a97c03aSMatt Jacob } else { 1192443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 11938a97c03aSMatt Jacob } 1194126ec864SMatt Jacob return (0); 1195126ec864SMatt Jacob } 11966ce548a1SAlexander Motin *info = (r2hisr >> 16); 11976ce548a1SAlexander Motin return (1); 1198126ec864SMatt Jacob } 1199126ec864SMatt Jacob 120010365e5aSMatt Jacob static int 12016ce548a1SAlexander Motin isp_pci_rd_isr_2400(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 120210365e5aSMatt Jacob { 120310365e5aSMatt Jacob uint32_t r2hisr; 120410365e5aSMatt Jacob 12056a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO)); 120610365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 12076ce548a1SAlexander Motin if ((r2hisr & BIU_R2HST_INTR) == 0) { 120810365e5aSMatt Jacob *isrp = 0; 120910365e5aSMatt Jacob return (0); 121010365e5aSMatt Jacob } 12116ce548a1SAlexander Motin switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) { 12126ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_OK: 12136ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_FAIL: 12146ce548a1SAlexander Motin case ISPR2HST_MBX_OK: 12156ce548a1SAlexander Motin case ISPR2HST_MBX_FAIL: 12166ce548a1SAlexander Motin case ISPR2HST_ASYNC_EVENT: 121710365e5aSMatt Jacob *semap = 1; 12186ce548a1SAlexander Motin break; 12196ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE: 12206ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE2: 12216ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE: 12226ce548a1SAlexander Motin case ISPR2HST_ATIO_RSPQ_UPDATE: 12236ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE2: 122410365e5aSMatt Jacob *semap = 0; 12256ce548a1SAlexander Motin break; 122610365e5aSMatt Jacob default: 122710365e5aSMatt Jacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 122810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 122910365e5aSMatt Jacob return (0); 123010365e5aSMatt Jacob } 12316ce548a1SAlexander Motin *info = (r2hisr >> 16); 12326ce548a1SAlexander Motin return (1); 123310365e5aSMatt Jacob } 123410365e5aSMatt Jacob 123510365e5aSMatt Jacob static uint32_t 12369cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 123765adb54cSMatt Jacob { 12386a7d12e1SMatt Jacob uint16_t rv; 1239126ec864SMatt Jacob int oldconf = 0; 124065adb54cSMatt Jacob 1241d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 124265adb54cSMatt Jacob /* 124365adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 124465adb54cSMatt Jacob */ 12456a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 1246443e752dSMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); 124737bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 124865adb54cSMatt Jacob } 12496a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 1250d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12516a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 125237bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 125365adb54cSMatt Jacob } 125465adb54cSMatt Jacob return (rv); 125565adb54cSMatt Jacob } 125665adb54cSMatt Jacob 125765adb54cSMatt Jacob static void 125810365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 125965adb54cSMatt Jacob { 1260126ec864SMatt Jacob int oldconf = 0; 1261d59bd469SMatt Jacob 1262d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 126365adb54cSMatt Jacob /* 126465adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 126565adb54cSMatt Jacob */ 12666a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12676a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1268126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 126937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 127065adb54cSMatt Jacob } 12716a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 127237bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 1273d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12746a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 127537bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 127665adb54cSMatt Jacob } 12776a7d12e1SMatt Jacob 1278f9734398SMatt Jacob } 127965adb54cSMatt Jacob 128010365e5aSMatt Jacob static uint32_t 12819cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1282d59bd469SMatt Jacob { 128310365e5aSMatt Jacob uint32_t rv, oc = 0; 1284d59bd469SMatt Jacob 128510bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 128610365e5aSMatt Jacob uint32_t tc; 1287d59bd469SMatt Jacob /* 1288d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1289d59bd469SMatt Jacob */ 12906a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 129122e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 129222e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 129322e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 129422e1dc85SMatt Jacob else 129522e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12966a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 129737bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1298d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12996a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 13006a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1301126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 130237bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1303d59bd469SMatt Jacob } 13046a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 130522e1dc85SMatt Jacob if (oc) { 13066a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 130737bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1308d59bd469SMatt Jacob } 1309d59bd469SMatt Jacob return (rv); 1310d59bd469SMatt Jacob } 1311d59bd469SMatt Jacob 1312d59bd469SMatt Jacob static void 131310365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1314d59bd469SMatt Jacob { 1315126ec864SMatt Jacob int oc = 0; 1316d59bd469SMatt Jacob 131710bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 131810365e5aSMatt Jacob uint32_t tc; 1319d59bd469SMatt Jacob /* 1320d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1321d59bd469SMatt Jacob */ 13226a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 132322e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 132422e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 132522e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 132622e1dc85SMatt Jacob else 132722e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 13286a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 132937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1330d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 13316a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 13326a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1333126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 133437bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1335d59bd469SMatt Jacob } 13366a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 133737bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 133822e1dc85SMatt Jacob if (oc) { 13396a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 134037bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 134110365e5aSMatt Jacob } 134210365e5aSMatt Jacob } 134310365e5aSMatt Jacob 134410365e5aSMatt Jacob static uint32_t 134510365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 134610365e5aSMatt Jacob { 134710365e5aSMatt Jacob uint32_t rv; 134810365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 134910365e5aSMatt Jacob 135010365e5aSMatt Jacob switch (block) { 135110365e5aSMatt Jacob case BIU_BLOCK: 135210365e5aSMatt Jacob break; 135310365e5aSMatt Jacob case MBOX_BLOCK: 13546a7d12e1SMatt Jacob return (BXR2(isp, IspVirt2Off(isp, regoff))); 135510365e5aSMatt Jacob case SXP_BLOCK: 1356cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "SXP_BLOCK read at 0x%x", regoff); 135710365e5aSMatt Jacob return (0xffffffff); 135810365e5aSMatt Jacob case RISC_BLOCK: 1359cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "RISC_BLOCK read at 0x%x", regoff); 136010365e5aSMatt Jacob return (0xffffffff); 136110365e5aSMatt Jacob case DMA_BLOCK: 1362cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "DMA_BLOCK read at 0x%x", regoff); 136310365e5aSMatt Jacob return (0xffffffff); 136410365e5aSMatt Jacob default: 1365cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block read at 0x%x", regoff); 136610365e5aSMatt Jacob return (0xffffffff); 136710365e5aSMatt Jacob } 136810365e5aSMatt Jacob 136910365e5aSMatt Jacob switch (regoff) { 137010365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 137110365e5aSMatt Jacob case BIU2400_FLASH_DATA: 137210365e5aSMatt Jacob case BIU2400_ICR: 137310365e5aSMatt Jacob case BIU2400_ISR: 137410365e5aSMatt Jacob case BIU2400_CSR: 137510365e5aSMatt Jacob case BIU2400_REQINP: 137610365e5aSMatt Jacob case BIU2400_REQOUTP: 137710365e5aSMatt Jacob case BIU2400_RSPINP: 137810365e5aSMatt Jacob case BIU2400_RSPOUTP: 13792df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13802df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 138110365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13822df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 138310365e5aSMatt Jacob case BIU2400_HCCR: 138410365e5aSMatt Jacob case BIU2400_GPIOD: 138510365e5aSMatt Jacob case BIU2400_GPIOE: 138610365e5aSMatt Jacob case BIU2400_HSEMA: 13876a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 138810365e5aSMatt Jacob break; 138910365e5aSMatt Jacob case BIU2400_R2HSTSLO: 13906a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 139110365e5aSMatt Jacob break; 139210365e5aSMatt Jacob case BIU2400_R2HSTSHI: 13936a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16; 139410365e5aSMatt Jacob break; 139510365e5aSMatt Jacob default: 1396cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x", 1397cd201b7bSAlexander Motin regoff); 139810365e5aSMatt Jacob rv = 0xffffffff; 139910365e5aSMatt Jacob break; 140010365e5aSMatt Jacob } 140110365e5aSMatt Jacob return (rv); 140210365e5aSMatt Jacob } 140310365e5aSMatt Jacob 140410365e5aSMatt Jacob static void 140510365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 140610365e5aSMatt Jacob { 140710365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 140810365e5aSMatt Jacob 140910365e5aSMatt Jacob switch (block) { 141010365e5aSMatt Jacob case BIU_BLOCK: 141110365e5aSMatt Jacob break; 141210365e5aSMatt Jacob case MBOX_BLOCK: 14136a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 141437bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 141510365e5aSMatt Jacob return; 141610365e5aSMatt Jacob case SXP_BLOCK: 1417cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "SXP_BLOCK write at 0x%x", regoff); 141810365e5aSMatt Jacob return; 141910365e5aSMatt Jacob case RISC_BLOCK: 1420cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "RISC_BLOCK write at 0x%x", regoff); 142110365e5aSMatt Jacob return; 142210365e5aSMatt Jacob case DMA_BLOCK: 1423cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "DMA_BLOCK write at 0x%x", regoff); 142410365e5aSMatt Jacob return; 142510365e5aSMatt Jacob default: 1426cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown block write at 0x%x", regoff); 142710365e5aSMatt Jacob break; 142810365e5aSMatt Jacob } 142910365e5aSMatt Jacob 143010365e5aSMatt Jacob switch (regoff) { 143110365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 143210365e5aSMatt Jacob case BIU2400_FLASH_DATA: 143310365e5aSMatt Jacob case BIU2400_ICR: 143410365e5aSMatt Jacob case BIU2400_ISR: 143510365e5aSMatt Jacob case BIU2400_CSR: 143610365e5aSMatt Jacob case BIU2400_REQINP: 143710365e5aSMatt Jacob case BIU2400_REQOUTP: 143810365e5aSMatt Jacob case BIU2400_RSPINP: 143910365e5aSMatt Jacob case BIU2400_RSPOUTP: 14402df76c16SMatt Jacob case BIU2400_PRI_REQINP: 14412df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 144210365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 14432df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 144410365e5aSMatt Jacob case BIU2400_HCCR: 144510365e5aSMatt Jacob case BIU2400_GPIOD: 144610365e5aSMatt Jacob case BIU2400_GPIOE: 144710365e5aSMatt Jacob case BIU2400_HSEMA: 14486a7d12e1SMatt Jacob BXW4(isp, IspVirt2Off(isp, regoff), val); 144907d925faSAlexander Motin #ifdef MEMORYBARRIERW 145007d925faSAlexander Motin if (regoff == BIU2400_REQINP || 145107d925faSAlexander Motin regoff == BIU2400_RSPOUTP || 145207d925faSAlexander Motin regoff == BIU2400_PRI_REQINP || 145307d925faSAlexander Motin regoff == BIU2400_ATIO_RSPOUTP) 145407d925faSAlexander Motin MEMORYBARRIERW(isp, SYNC_REG, 145507d925faSAlexander Motin IspVirt2Off(isp, regoff), 4, -1) 145607d925faSAlexander Motin else 145707d925faSAlexander Motin #endif 145837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1); 145910365e5aSMatt Jacob break; 146010365e5aSMatt Jacob default: 1461cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x", 1462cd201b7bSAlexander Motin regoff); 146310365e5aSMatt Jacob break; 1464d59bd469SMatt Jacob } 1465d59bd469SMatt Jacob } 1466d59bd469SMatt Jacob 1467cd201b7bSAlexander Motin static uint32_t 1468cd201b7bSAlexander Motin isp_pci_rd_reg_2600(ispsoftc_t *isp, int regoff) 1469cd201b7bSAlexander Motin { 1470cd201b7bSAlexander Motin uint32_t rv; 1471cd201b7bSAlexander Motin 1472cd201b7bSAlexander Motin switch (regoff) { 1473cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 1474cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 1475cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x", 1476cd201b7bSAlexander Motin regoff); 1477cd201b7bSAlexander Motin rv = 0xffffffff; 1478cd201b7bSAlexander Motin break; 1479cd201b7bSAlexander Motin case BIU2400_REQINP: 1480cd201b7bSAlexander Motin rv = B2R4(isp, 0x00); 1481cd201b7bSAlexander Motin break; 1482cd201b7bSAlexander Motin case BIU2400_REQOUTP: 1483cd201b7bSAlexander Motin rv = B2R4(isp, 0x04); 1484cd201b7bSAlexander Motin break; 1485cd201b7bSAlexander Motin case BIU2400_RSPINP: 1486cd201b7bSAlexander Motin rv = B2R4(isp, 0x08); 1487cd201b7bSAlexander Motin break; 1488cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 1489cd201b7bSAlexander Motin rv = B2R4(isp, 0x0c); 1490cd201b7bSAlexander Motin break; 1491cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 1492cd201b7bSAlexander Motin rv = B2R4(isp, 0x10); 1493cd201b7bSAlexander Motin break; 1494cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 1495cd201b7bSAlexander Motin rv = B2R4(isp, 0x14); 1496cd201b7bSAlexander Motin break; 1497cd201b7bSAlexander Motin default: 1498cd201b7bSAlexander Motin rv = isp_pci_rd_reg_2400(isp, regoff); 1499cd201b7bSAlexander Motin break; 1500cd201b7bSAlexander Motin } 1501cd201b7bSAlexander Motin return (rv); 1502cd201b7bSAlexander Motin } 1503cd201b7bSAlexander Motin 1504cd201b7bSAlexander Motin static void 1505cd201b7bSAlexander Motin isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val) 1506cd201b7bSAlexander Motin { 1507cd201b7bSAlexander Motin int off; 1508cd201b7bSAlexander Motin 1509cd201b7bSAlexander Motin switch (regoff) { 1510cd201b7bSAlexander Motin case BIU2400_PRI_REQINP: 1511cd201b7bSAlexander Motin case BIU2400_PRI_REQOUTP: 1512cd201b7bSAlexander Motin isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x", 1513cd201b7bSAlexander Motin regoff); 1514cd201b7bSAlexander Motin return; 1515cd201b7bSAlexander Motin case BIU2400_REQINP: 1516cd201b7bSAlexander Motin off = 0x00; 1517cd201b7bSAlexander Motin break; 1518cd201b7bSAlexander Motin case BIU2400_REQOUTP: 1519cd201b7bSAlexander Motin off = 0x04; 1520cd201b7bSAlexander Motin break; 1521cd201b7bSAlexander Motin case BIU2400_RSPINP: 1522cd201b7bSAlexander Motin off = 0x08; 1523cd201b7bSAlexander Motin break; 1524cd201b7bSAlexander Motin case BIU2400_RSPOUTP: 1525cd201b7bSAlexander Motin off = 0x0c; 1526cd201b7bSAlexander Motin break; 1527cd201b7bSAlexander Motin case BIU2400_ATIO_RSPINP: 1528cd201b7bSAlexander Motin off = 0x10; 1529cd201b7bSAlexander Motin break; 1530cd201b7bSAlexander Motin case BIU2400_ATIO_RSPOUTP: 1531cd201b7bSAlexander Motin off = 0x14; 1532cd201b7bSAlexander Motin break; 1533cd201b7bSAlexander Motin default: 1534cd201b7bSAlexander Motin isp_pci_wr_reg_2400(isp, regoff, val); 1535cd201b7bSAlexander Motin return; 1536cd201b7bSAlexander Motin } 1537cd201b7bSAlexander Motin B2W4(isp, off, val); 1538cd201b7bSAlexander Motin } 1539cd201b7bSAlexander Motin 1540d720e6d5SJustin T. Gibbs 1541222bb542SMatt Jacob struct imush { 154214849e2cSAlexander Motin bus_addr_t maddr; 1543222bb542SMatt Jacob int error; 1544222bb542SMatt Jacob }; 1545222bb542SMatt Jacob 1546d720e6d5SJustin T. Gibbs static void 15471923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1548d720e6d5SJustin T. Gibbs { 1549222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 15502df76c16SMatt Jacob 155114849e2cSAlexander Motin if (!(imushp->error = error)) 155214849e2cSAlexander Motin imushp->maddr = segs[0].ds_addr; 1553d720e6d5SJustin T. Gibbs } 1554d720e6d5SJustin T. Gibbs 1555d720e6d5SJustin T. Gibbs static int 15569cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1557d720e6d5SJustin T. Gibbs { 1558d720e6d5SJustin T. Gibbs caddr_t base; 1559662daaddSMatt Jacob uint32_t len, nsegs; 15608e1b6e7aSMatt Jacob int i, error, cmap = 0; 156153af7d22SMatt Jacob bus_size_t slim; /* segment size */ 15624b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 156351effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1564222bb542SMatt Jacob struct imush im; 156514849e2cSAlexander Motin isp_ecmd_t *ecmd; 1566222bb542SMatt Jacob 1567a95ae193SMatt Jacob /* 1568a95ae193SMatt Jacob * Already been here? If so, leave... 1569a95ae193SMatt Jacob */ 1570a95ae193SMatt Jacob if (isp->isp_rquest) { 1571a95ae193SMatt Jacob return (0); 1572a95ae193SMatt Jacob } 15730a70657fSMatt Jacob ISP_UNLOCK(isp); 1574a95ae193SMatt Jacob 157510365e5aSMatt Jacob if (isp->isp_maxcmds == 0) { 157610365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "maxcmds not set"); 15770a70657fSMatt Jacob ISP_LOCK(isp); 157810365e5aSMatt Jacob return (1); 157910365e5aSMatt Jacob } 158010365e5aSMatt Jacob 158153af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 15821923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 15839b434edeSMatt Jacob if (sizeof (bus_size_t) > 4) { 158453af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 15859b434edeSMatt Jacob } else { 15869b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 15879b434edeSMatt Jacob } 15881dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 15891923f739SMatt Jacob } else { 15901dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR_32BIT; 15919b434edeSMatt Jacob slim = (1UL << 24); 15921923f739SMatt Jacob } 15931923f739SMatt Jacob 15940a70657fSMatt Jacob len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 15952df76c16SMatt Jacob isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 15960a70657fSMatt Jacob if (isp->isp_osinfo.pcmd_pool == NULL) { 15970a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds"); 15980a70657fSMatt Jacob ISP_LOCK(isp); 15990a70657fSMatt Jacob return (1); 16000a70657fSMatt Jacob } 16010a70657fSMatt Jacob 1602662daaddSMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 1603662daaddSMatt Jacob nsegs = ISP_NSEG64_MAX; 1604662daaddSMatt Jacob } else { 1605662daaddSMatt Jacob nsegs = ISP_NSEG_MAX; 1606662daaddSMatt Jacob } 160709934867SMatt Jacob 1608662daaddSMatt Jacob if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, &isp->isp_osinfo.dmat)) { 16090a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 161072429e49SMatt Jacob ISP_LOCK(isp); 16110a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 16121923f739SMatt Jacob return (1); 16131923f739SMatt Jacob } 16141923f739SMatt Jacob 1615c8b8a2c4SMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1616c8b8a2c4SMatt Jacob isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1617a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 16180a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 161972429e49SMatt Jacob ISP_LOCK(isp); 16200a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 1621a95ae193SMatt Jacob return (1); 1622a95ae193SMatt Jacob } 1623c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1624c8b8a2c4SMatt Jacob isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1625c8b8a2c4SMatt Jacob } 1626c8b8a2c4SMatt Jacob isp->isp_xffree = isp->isp_xflist; 1627a95ae193SMatt Jacob 1628d720e6d5SJustin T. Gibbs /* 162914849e2cSAlexander Motin * Allocate and map the request queue and a region for external 163014849e2cSAlexander Motin * DMA addressable command/status structures (22XX and later). 1631d720e6d5SJustin T. Gibbs */ 1632d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 163314849e2cSAlexander Motin if (isp->isp_type >= ISP_HA_FC_2200) 1634387d8239SMatt Jacob len += (N_XCMDS * XCMD_SIZE); 163514849e2cSAlexander Motin if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 163614849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 163714849e2cSAlexander Motin len, 1, len, 0, &isp->isp_osinfo.reqdmat)) { 163814849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); 163914849e2cSAlexander Motin goto bad1; 164014849e2cSAlexander Motin } 164114849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, 164214849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { 164314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); 164414849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 164514849e2cSAlexander Motin goto bad1; 164614849e2cSAlexander Motin } 164714849e2cSAlexander Motin isp->isp_rquest = base; 164814849e2cSAlexander Motin im.error = 0; 164914849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, 165014849e2cSAlexander Motin base, len, imc, &im, 0) || im.error) { 165114849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); 165214849e2cSAlexander Motin goto bad1; 165314849e2cSAlexander Motin } 165414849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", 165514849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 165614849e2cSAlexander Motin isp->isp_rquest_dma = im.maddr; 165714849e2cSAlexander Motin base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 165814849e2cSAlexander Motin im.maddr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 165914849e2cSAlexander Motin if (isp->isp_type >= ISP_HA_FC_2200) { 166014849e2cSAlexander Motin isp->isp_osinfo.ecmd_dma = im.maddr; 166114849e2cSAlexander Motin isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)base; 166214849e2cSAlexander Motin isp->isp_osinfo.ecmd_base = isp->isp_osinfo.ecmd_free; 166314849e2cSAlexander Motin for (ecmd = isp->isp_osinfo.ecmd_free; 166414849e2cSAlexander Motin ecmd < &isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { 166514849e2cSAlexander Motin if (ecmd == &isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) 166614849e2cSAlexander Motin ecmd->next = NULL; 166714849e2cSAlexander Motin else 166814849e2cSAlexander Motin ecmd->next = ecmd + 1; 166914849e2cSAlexander Motin } 1670387d8239SMatt Jacob } 16712df76c16SMatt Jacob 167253af7d22SMatt Jacob /* 167314849e2cSAlexander Motin * Allocate and map the result queue. 167453af7d22SMatt Jacob */ 167514849e2cSAlexander Motin len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 167614849e2cSAlexander Motin if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 167714849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 167814849e2cSAlexander Motin len, 1, len, 0, &isp->isp_osinfo.respdmat)) { 167914849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); 168014849e2cSAlexander Motin goto bad1; 1681d720e6d5SJustin T. Gibbs } 168214849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, 168314849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { 168414849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); 168514849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 168614849e2cSAlexander Motin goto bad1; 1687222bb542SMatt Jacob } 168814849e2cSAlexander Motin isp->isp_result = base; 16892df76c16SMatt Jacob im.error = 0; 169014849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, 169114849e2cSAlexander Motin base, len, imc, &im, 0) || im.error) { 169214849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); 169314849e2cSAlexander Motin goto bad1; 169414849e2cSAlexander Motin } 169514849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", 169614849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 169714849e2cSAlexander Motin isp->isp_result_dma = im.maddr; 16982df76c16SMatt Jacob 169914849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 170014849e2cSAlexander Motin /* 170114849e2cSAlexander Motin * Allocate and map ATIO queue on 24xx with target mode. 170214849e2cSAlexander Motin */ 170314849e2cSAlexander Motin if (IS_24XX(isp)) { 170414849e2cSAlexander Motin len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 170514849e2cSAlexander Motin if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, 170614849e2cSAlexander Motin BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 170714849e2cSAlexander Motin len, 1, len, 0, &isp->isp_osinfo.atiodmat)) { 170814849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag"); 170914849e2cSAlexander Motin goto bad1; 171014849e2cSAlexander Motin } 171114849e2cSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base, 171214849e2cSAlexander Motin BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) { 171314849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory"); 171414849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 171514849e2cSAlexander Motin goto bad1; 171614849e2cSAlexander Motin } 171714849e2cSAlexander Motin isp->isp_atioq = base; 171814849e2cSAlexander Motin im.error = 0; 171914849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap, 172014849e2cSAlexander Motin base, len, imc, &im, 0) || im.error) { 172114849e2cSAlexander Motin isp_prt(isp, ISP_LOGERR, "error loading ATIO DMA map %d", im.error); 17222df76c16SMatt Jacob goto bad; 17232df76c16SMatt Jacob } 172414849e2cSAlexander Motin isp_prt(isp, ISP_LOGDEBUG0, "ATIO area @ 0x%jx/0x%jx", 172514849e2cSAlexander Motin (uintmax_t)im.maddr, (uintmax_t)len); 172614849e2cSAlexander Motin isp->isp_atioq_dma = im.maddr; 172714849e2cSAlexander Motin } 172814849e2cSAlexander Motin #endif 17292df76c16SMatt Jacob 17302df76c16SMatt Jacob if (IS_FC(isp)) { 17317d191fdbSAlexander Motin if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, 17327d191fdbSAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 1733*4ff970c4SAlexander Motin 2*QENTRY_LEN, 1, 2*QENTRY_LEN, 0, &isp->isp_osinfo.iocbdmat)) { 17342df76c16SMatt Jacob goto bad; 17352df76c16SMatt Jacob } 1736*4ff970c4SAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.iocbdmat, 1737*4ff970c4SAlexander Motin (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.iocbmap) != 0) 1738*4ff970c4SAlexander Motin goto bad; 1739*4ff970c4SAlexander Motin isp->isp_iocb = base; 1740*4ff970c4SAlexander Motin im.error = 0; 1741*4ff970c4SAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap, 1742*4ff970c4SAlexander Motin base, 2*QENTRY_LEN, imc, &im, 0) || im.error) 1743*4ff970c4SAlexander Motin goto bad; 1744*4ff970c4SAlexander Motin isp->isp_iocb_dma = im.maddr; 1745*4ff970c4SAlexander Motin 1746*4ff970c4SAlexander Motin if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, 1747*4ff970c4SAlexander Motin BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 1748*4ff970c4SAlexander Motin ISP_FC_SCRLEN, 1, ISP_FC_SCRLEN, 0, &isp->isp_osinfo.scdmat)) 1749*4ff970c4SAlexander Motin goto bad; 17507d191fdbSAlexander Motin for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 17517d191fdbSAlexander Motin struct isp_fc *fc = ISP_FC_PC(isp, cmap); 17527d191fdbSAlexander Motin if (bus_dmamem_alloc(isp->isp_osinfo.scdmat, 175314849e2cSAlexander Motin (void **)&base, BUS_DMA_COHERENT, &fc->scmap) != 0) 17542df76c16SMatt Jacob goto bad; 175514849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scratch = base; 17562df76c16SMatt Jacob im.error = 0; 175714849e2cSAlexander Motin if (bus_dmamap_load(isp->isp_osinfo.scdmat, fc->scmap, 175814849e2cSAlexander Motin base, ISP_FC_SCRLEN, imc, &im, 0) || im.error) { 17597d191fdbSAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 17607d191fdbSAlexander Motin base, fc->scmap); 17612df76c16SMatt Jacob goto bad; 17622df76c16SMatt Jacob } 176314849e2cSAlexander Motin FCPARAM(isp, cmap)->isp_scdma = im.maddr; 1764a4ccb5d6SAlexander Motin if (!IS_2100(isp)) { 1765387d8239SMatt Jacob for (i = 0; i < INITIAL_NEXUS_COUNT; i++) { 1766387d8239SMatt Jacob struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO); 1767387d8239SMatt Jacob if (n == NULL) { 1768387d8239SMatt Jacob while (fc->nexus_free_list) { 1769387d8239SMatt Jacob n = fc->nexus_free_list; 1770387d8239SMatt Jacob fc->nexus_free_list = n->next; 1771387d8239SMatt Jacob free(n, M_DEVBUF); 1772387d8239SMatt Jacob } 1773387d8239SMatt Jacob goto bad; 1774387d8239SMatt Jacob } 1775387d8239SMatt Jacob n->next = fc->nexus_free_list; 1776387d8239SMatt Jacob fc->nexus_free_list = n; 1777387d8239SMatt Jacob } 17782df76c16SMatt Jacob } 17792df76c16SMatt Jacob } 1780405b7a29SMatt Jacob } 17812df76c16SMatt Jacob 1782a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 17830a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 17840a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1785d720e6d5SJustin T. Gibbs if (error) { 17862df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 17871923f739SMatt Jacob while (--i >= 0) { 17882df76c16SMatt Jacob bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap); 17891923f739SMatt Jacob } 17901923f739SMatt Jacob goto bad; 1791d720e6d5SJustin T. Gibbs } 17922df76c16SMatt Jacob callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); 17930a70657fSMatt Jacob if (i == isp->isp_maxcmds-1) { 17940a70657fSMatt Jacob pcmd->next = NULL; 17950a70657fSMatt Jacob } else { 17960a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1797d720e6d5SJustin T. Gibbs } 17980a70657fSMatt Jacob } 17990a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 180072429e49SMatt Jacob ISP_LOCK(isp); 1801d720e6d5SJustin T. Gibbs return (0); 18021923f739SMatt Jacob 18031923f739SMatt Jacob bad: 18047d191fdbSAlexander Motin if (IS_FC(isp)) { 18052df76c16SMatt Jacob while (--cmap >= 0) { 18062df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 18077d191fdbSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.scdmat, fc->scmap); 1808*4ff970c4SAlexander Motin bus_dmamem_free(isp->isp_osinfo.scdmat, 1809*4ff970c4SAlexander Motin FCPARAM(isp, cmap)->isp_scratch, fc->scmap); 1810387d8239SMatt Jacob while (fc->nexus_free_list) { 1811387d8239SMatt Jacob struct isp_nexus *n = fc->nexus_free_list; 1812387d8239SMatt Jacob fc->nexus_free_list = n->next; 1813387d8239SMatt Jacob free(n, M_DEVBUF); 1814387d8239SMatt Jacob } 18152df76c16SMatt Jacob } 18167d191fdbSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.scdmat); 1817*4ff970c4SAlexander Motin bus_dmamap_unload(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap); 1818*4ff970c4SAlexander Motin bus_dmamem_free(isp->isp_osinfo.iocbdmat, isp->isp_iocb, 1819*4ff970c4SAlexander Motin isp->isp_osinfo.iocbmap); 1820*4ff970c4SAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat); 18217d191fdbSAlexander Motin } 182214849e2cSAlexander Motin bad1: 182314849e2cSAlexander Motin if (isp->isp_rquest_dma != 0) { 182414849e2cSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.reqdmat, 182514849e2cSAlexander Motin isp->isp_osinfo.reqmap); 182614849e2cSAlexander Motin } 182714849e2cSAlexander Motin if (isp->isp_rquest != NULL) { 182814849e2cSAlexander Motin bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, 182914849e2cSAlexander Motin isp->isp_osinfo.reqmap); 183014849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); 183114849e2cSAlexander Motin } 183214849e2cSAlexander Motin if (isp->isp_result_dma != 0) { 183314849e2cSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.respdmat, 183414849e2cSAlexander Motin isp->isp_osinfo.respmap); 183514849e2cSAlexander Motin } 183614849e2cSAlexander Motin if (isp->isp_result != NULL) { 183714849e2cSAlexander Motin bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, 183814849e2cSAlexander Motin isp->isp_osinfo.respmap); 183914849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.respdmat); 184014849e2cSAlexander Motin } 184114849e2cSAlexander Motin #ifdef ISP_TARGET_MODE 184214849e2cSAlexander Motin if (IS_24XX(isp)) { 184314849e2cSAlexander Motin if (isp->isp_atioq_dma != 0) { 184414849e2cSAlexander Motin bus_dmamap_unload(isp->isp_osinfo.atiodmat, 184514849e2cSAlexander Motin isp->isp_osinfo.atiomap); 184614849e2cSAlexander Motin } 184714849e2cSAlexander Motin if (isp->isp_atioq != NULL) { 184814849e2cSAlexander Motin bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_atioq, 184914849e2cSAlexander Motin isp->isp_osinfo.atiomap); 185014849e2cSAlexander Motin bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); 185114849e2cSAlexander Motin } 185214849e2cSAlexander Motin } 185314849e2cSAlexander Motin #endif 18541923f739SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 18550a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 18561923f739SMatt Jacob isp->isp_rquest = NULL; 18570a70657fSMatt Jacob ISP_LOCK(isp); 18581923f739SMatt Jacob return (1); 1859d720e6d5SJustin T. Gibbs } 1860d720e6d5SJustin T. Gibbs 1861d720e6d5SJustin T. Gibbs typedef struct { 18629cd7268eSMatt Jacob ispsoftc_t *isp; 18639e11e5beSMatt Jacob void *cmd_token; 18642df76c16SMatt Jacob void *rq; /* original request */ 18651dae40ebSMatt Jacob int error; 18662df76c16SMatt Jacob bus_size_t mapsize; 1867d720e6d5SJustin T. Gibbs } mush_t; 1868d720e6d5SJustin T. Gibbs 18694873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 18704873663cSMatt Jacob 18719e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 18722df76c16SMatt Jacob static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 18732df76c16SMatt Jacob static void tdma2(void *, bus_dma_segment_t *, int, int); 18749e11e5beSMatt Jacob 1875d720e6d5SJustin T. Gibbs static void 18762df76c16SMatt Jacob tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 1877d720e6d5SJustin T. Gibbs { 1878d720e6d5SJustin T. Gibbs mush_t *mp; 18792df76c16SMatt Jacob mp = (mush_t *)arg; 18802df76c16SMatt Jacob mp->mapsize = mapsize; 18812df76c16SMatt Jacob tdma2(arg, dm_segs, nseg, error); 18822df76c16SMatt Jacob } 18832df76c16SMatt Jacob 18842df76c16SMatt Jacob static void 18852df76c16SMatt Jacob tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 18862df76c16SMatt Jacob { 18872df76c16SMatt Jacob mush_t *mp; 18889cd7268eSMatt Jacob ispsoftc_t *isp; 18892df76c16SMatt Jacob struct ccb_scsiio *csio; 18902df76c16SMatt Jacob isp_ddir_t ddir; 18912df76c16SMatt Jacob ispreq_t *rq; 1892d720e6d5SJustin T. Gibbs 1893d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1894d720e6d5SJustin T. Gibbs if (error) { 1895d720e6d5SJustin T. Gibbs mp->error = error; 1896d720e6d5SJustin T. Gibbs return; 1897d720e6d5SJustin T. Gibbs } 18989e11e5beSMatt Jacob csio = mp->cmd_token; 18994fd13c1bSMatt Jacob isp = mp->isp; 19002df76c16SMatt Jacob rq = mp->rq; 19012df76c16SMatt Jacob if (nseg) { 1902387d8239SMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 19032df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 19042df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 19052df76c16SMatt Jacob mp->error = EFAULT; 19069e11e5beSMatt Jacob return; 19079e11e5beSMatt Jacob } 19082df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) { 19092df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_CTIO3; 19102df76c16SMatt Jacob } 191109934867SMatt Jacob } else { 19122df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 19132df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 19142df76c16SMatt Jacob mp->error = EFAULT; 19152df76c16SMatt Jacob return; 191609934867SMatt Jacob } 19172df76c16SMatt Jacob } 19182df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 19192df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 19202df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 19212df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 19222df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 19232df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 192409934867SMatt Jacob } else { 1925a035b0afSMatt Jacob dm_segs = NULL; 1926a035b0afSMatt Jacob nseg = 0; 19272df76c16SMatt Jacob ddir = ISP_NOXFR; 192809934867SMatt Jacob } 19292df76c16SMatt Jacob } else { 19302df76c16SMatt Jacob dm_segs = NULL; 19312df76c16SMatt Jacob nseg = 0; 19322df76c16SMatt Jacob ddir = ISP_NOXFR; 1933fc087171SMatt Jacob } 193465b024e1SMatt Jacob 1935387d8239SMatt Jacob error = isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len); 1936387d8239SMatt Jacob switch (error) { 1937387d8239SMatt Jacob case CMD_EAGAIN: 19382df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1939387d8239SMatt Jacob case CMD_QUEUED: 1940387d8239SMatt Jacob break; 1941387d8239SMatt Jacob default: 1942387d8239SMatt Jacob mp->error = EIO; 194310365e5aSMatt Jacob } 19449e11e5beSMatt Jacob } 19459e11e5beSMatt Jacob #endif 19469e11e5beSMatt Jacob 19472df76c16SMatt Jacob static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 1948126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 19499e11e5beSMatt Jacob 19506de9bf77SMatt Jacob static void 19512df76c16SMatt Jacob dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 195210365e5aSMatt Jacob { 195310365e5aSMatt Jacob mush_t *mp; 195410365e5aSMatt Jacob mp = (mush_t *)arg; 19552df76c16SMatt Jacob mp->mapsize = mapsize; 19562df76c16SMatt Jacob dma2(arg, dm_segs, nseg, error); 19576de9bf77SMatt Jacob } 19581dae40ebSMatt Jacob 19599e11e5beSMatt Jacob static void 19609e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 19619e11e5beSMatt Jacob { 19629e11e5beSMatt Jacob mush_t *mp; 19639cd7268eSMatt Jacob ispsoftc_t *isp; 19649e11e5beSMatt Jacob struct ccb_scsiio *csio; 19652df76c16SMatt Jacob isp_ddir_t ddir; 19669e11e5beSMatt Jacob ispreq_t *rq; 19679e11e5beSMatt Jacob 19689e11e5beSMatt Jacob mp = (mush_t *) arg; 19699e11e5beSMatt Jacob if (error) { 19709e11e5beSMatt Jacob mp->error = error; 19719e11e5beSMatt Jacob return; 19729e11e5beSMatt Jacob } 19739e11e5beSMatt Jacob csio = mp->cmd_token; 19744fd13c1bSMatt Jacob isp = mp->isp; 19759e11e5beSMatt Jacob rq = mp->rq; 19762df76c16SMatt Jacob if (nseg) { 1977387d8239SMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 19782df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 19792df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 19802df76c16SMatt Jacob mp->error = EFAULT; 1981d720e6d5SJustin T. Gibbs return; 1982d720e6d5SJustin T. Gibbs } 19832df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) { 19842df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; 19852df76c16SMatt Jacob } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) { 19862df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_A64; 1987d720e6d5SJustin T. Gibbs } 19882df76c16SMatt Jacob } else { 19892df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 19902df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 19912df76c16SMatt Jacob mp->error = EFAULT; 19922df76c16SMatt Jacob return; 199310365e5aSMatt Jacob } 1994d720e6d5SJustin T. Gibbs } 19952df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 19962df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 19972df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 19982df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 19992df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 20002df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 20012df76c16SMatt Jacob } else { 20022df76c16SMatt Jacob ddir = ISP_NOXFR; 20032df76c16SMatt Jacob } 20042df76c16SMatt Jacob } else { 20052df76c16SMatt Jacob dm_segs = NULL; 20062df76c16SMatt Jacob nseg = 0; 20072df76c16SMatt Jacob ddir = ISP_NOXFR; 2008d720e6d5SJustin T. Gibbs } 2009d720e6d5SJustin T. Gibbs 2010387d8239SMatt Jacob error = isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, (ispds64_t *)csio->req_map); 2011387d8239SMatt Jacob switch (error) { 2012387d8239SMatt Jacob case CMD_EAGAIN: 20132df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 2014387d8239SMatt Jacob break; 2015387d8239SMatt Jacob case CMD_QUEUED: 2016387d8239SMatt Jacob break; 2017387d8239SMatt Jacob default: 2018387d8239SMatt Jacob mp->error = EIO; 2019387d8239SMatt Jacob break; 20202df76c16SMatt Jacob } 20212df76c16SMatt Jacob } 20222df76c16SMatt Jacob 2023d720e6d5SJustin T. Gibbs static int 20242df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 2025d720e6d5SJustin T. Gibbs { 2026d720e6d5SJustin T. Gibbs mush_t mush, *mp; 2027126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 20282df76c16SMatt Jacob void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int); 2029dd0b4fb6SKonstantin Belousov int error; 2030d720e6d5SJustin T. Gibbs 20312df76c16SMatt Jacob mp = &mush; 20322df76c16SMatt Jacob mp->isp = isp; 20332df76c16SMatt Jacob mp->cmd_token = csio; 20342df76c16SMatt Jacob mp->rq = ff; 20352df76c16SMatt Jacob mp->error = 0; 20362df76c16SMatt Jacob mp->mapsize = 0; 20372df76c16SMatt Jacob 203865b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 203965b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 20402df76c16SMatt Jacob eptr = tdma2; 20412df76c16SMatt Jacob eptr2 = tdma2_2; 204265b024e1SMatt Jacob } else 204365b024e1SMatt Jacob #endif 20442df76c16SMatt Jacob { 204565b024e1SMatt Jacob eptr = dma2; 20462df76c16SMatt Jacob eptr2 = dma2_2; 20471dae40ebSMatt Jacob } 204865b024e1SMatt Jacob 20494fd13c1bSMatt Jacob 2050dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, 2051dd0b4fb6SKonstantin Belousov (union ccb *)csio, eptr, mp, 0); 2052d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 20532df76c16SMatt Jacob bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 2054d720e6d5SJustin T. Gibbs mp->error = EINVAL; 20552df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); 2056d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 20570a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 20582df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 20590a5f7e8bSMatt Jacob #endif 2060d720e6d5SJustin T. Gibbs mp->error = error; 2061d720e6d5SJustin T. Gibbs } 2062d720e6d5SJustin T. Gibbs if (mp->error) { 20634873663cSMatt Jacob int retval = CMD_COMPLETE; 20644873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 20654873663cSMatt Jacob retval = CMD_EAGAIN; 20664873663cSMatt Jacob } else if (mp->error == EFBIG) { 2067387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_TOO_BIG; 2068d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 2069387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_INVALID; 2070d720e6d5SJustin T. Gibbs } else { 2071387d8239SMatt Jacob csio->ccb_h.status = CAM_UNREC_HBA_ERROR; 2072d720e6d5SJustin T. Gibbs } 20734873663cSMatt Jacob return (retval); 20740a5f7e8bSMatt Jacob } 20754873663cSMatt Jacob return (CMD_QUEUED); 2076d720e6d5SJustin T. Gibbs } 2077d720e6d5SJustin T. Gibbs 2078d720e6d5SJustin T. Gibbs static void 20793bda7a83SMatt Jacob isp_pci_reset0(ispsoftc_t *isp) 20803bda7a83SMatt Jacob { 20813bda7a83SMatt Jacob ISP_DISABLE_INTS(isp); 20823bda7a83SMatt Jacob } 20833bda7a83SMatt Jacob 20843bda7a83SMatt Jacob static void 20859cd7268eSMatt Jacob isp_pci_reset1(ispsoftc_t *isp) 208665adb54cSMatt Jacob { 208710365e5aSMatt Jacob if (!IS_24XX(isp)) { 208865adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 208965adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 209010365e5aSMatt Jacob } 2091469b6b9eSMatt Jacob /* and enable interrupts */ 209210365e5aSMatt Jacob ISP_ENABLE_INTS(isp); 209365adb54cSMatt Jacob } 209465adb54cSMatt Jacob 209565adb54cSMatt Jacob static void 20969cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg) 209765adb54cSMatt Jacob { 20981923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 2099d02373f1SMatt Jacob if (msg) 21006e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 21016e5c5328SMatt Jacob else 21026e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 2103d02373f1SMatt Jacob if (IS_SCSI(isp)) 2104d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 2105d02373f1SMatt Jacob else 2106d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 2107d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 2108d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 2109d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 2110d02373f1SMatt Jacob 2111d02373f1SMatt Jacob 2112d02373f1SMatt Jacob if (IS_SCSI(isp)) { 2113d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 2114d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 2115d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 2116d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 2117d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 2118d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 2119d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 2120d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 2121d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 2122d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 2123d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 2124d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 2125d02373f1SMatt Jacob } 2126d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 2127d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 2128d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 2129d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 2130d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 21311923f739SMatt Jacob pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1)); 213265adb54cSMatt Jacob } 2133