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); 626ce548a1SAlexander Motin static int isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 636ce548a1SAlexander Motin static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 646ce548a1SAlexander Motin static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); 659cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *); 662df76c16SMatt Jacob static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *); 679cd7268eSMatt Jacob 689a5af410SMatt Jacob 693bda7a83SMatt Jacob static void isp_pci_reset0(ispsoftc_t *); 709cd7268eSMatt Jacob static void isp_pci_reset1(ispsoftc_t *); 719cd7268eSMatt Jacob static void isp_pci_dumpregs(ispsoftc_t *, const char *); 7265adb54cSMatt Jacob 7365adb54cSMatt Jacob static struct ispmdvec mdvec = { 74126ec864SMatt Jacob isp_pci_rd_isr, 7565adb54cSMatt Jacob isp_pci_rd_reg, 7665adb54cSMatt Jacob isp_pci_wr_reg, 7765adb54cSMatt Jacob isp_pci_mbxdma, 7865adb54cSMatt Jacob isp_pci_dmasetup, 790a70657fSMatt Jacob isp_common_dmateardown, 803bda7a83SMatt Jacob isp_pci_reset0, 8165adb54cSMatt Jacob isp_pci_reset1, 8265adb54cSMatt Jacob isp_pci_dumpregs, 8356aef503SMatt Jacob NULL, 84d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 8565adb54cSMatt Jacob }; 8665adb54cSMatt Jacob 87d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 88126ec864SMatt Jacob isp_pci_rd_isr, 89d59bd469SMatt Jacob isp_pci_rd_reg_1080, 90d59bd469SMatt Jacob isp_pci_wr_reg_1080, 91d59bd469SMatt Jacob isp_pci_mbxdma, 92d59bd469SMatt Jacob isp_pci_dmasetup, 930a70657fSMatt Jacob isp_common_dmateardown, 943bda7a83SMatt Jacob isp_pci_reset0, 95d59bd469SMatt Jacob isp_pci_reset1, 96d59bd469SMatt Jacob isp_pci_dumpregs, 9756aef503SMatt Jacob NULL, 98d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 99d59bd469SMatt Jacob }; 100d59bd469SMatt Jacob 101960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = { 102126ec864SMatt Jacob isp_pci_rd_isr, 103960f6939SMatt Jacob isp_pci_rd_reg_1080, 104960f6939SMatt Jacob isp_pci_wr_reg_1080, 105960f6939SMatt Jacob isp_pci_mbxdma, 106960f6939SMatt Jacob isp_pci_dmasetup, 1070a70657fSMatt Jacob isp_common_dmateardown, 1083bda7a83SMatt Jacob isp_pci_reset0, 109960f6939SMatt Jacob isp_pci_reset1, 110960f6939SMatt Jacob isp_pci_dumpregs, 11156aef503SMatt Jacob NULL, 112d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 113960f6939SMatt Jacob }; 114960f6939SMatt Jacob 11565adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 116126ec864SMatt Jacob isp_pci_rd_isr, 11765adb54cSMatt Jacob isp_pci_rd_reg, 11865adb54cSMatt Jacob isp_pci_wr_reg, 11965adb54cSMatt Jacob isp_pci_mbxdma, 12065adb54cSMatt Jacob isp_pci_dmasetup, 1210a70657fSMatt Jacob isp_common_dmateardown, 1223bda7a83SMatt Jacob isp_pci_reset0, 12365adb54cSMatt Jacob isp_pci_reset1, 124d02373f1SMatt Jacob isp_pci_dumpregs 12565adb54cSMatt Jacob }; 126222bb542SMatt Jacob 127222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 128126ec864SMatt Jacob isp_pci_rd_isr, 129126ec864SMatt Jacob isp_pci_rd_reg, 130126ec864SMatt Jacob isp_pci_wr_reg, 131126ec864SMatt Jacob isp_pci_mbxdma, 132126ec864SMatt Jacob isp_pci_dmasetup, 1330a70657fSMatt Jacob isp_common_dmateardown, 1343bda7a83SMatt Jacob isp_pci_reset0, 135126ec864SMatt Jacob isp_pci_reset1, 136126ec864SMatt Jacob isp_pci_dumpregs 137126ec864SMatt Jacob }; 138126ec864SMatt Jacob 139126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = { 140126ec864SMatt Jacob isp_pci_rd_isr_2300, 141222bb542SMatt Jacob isp_pci_rd_reg, 142222bb542SMatt Jacob isp_pci_wr_reg, 143222bb542SMatt Jacob isp_pci_mbxdma, 144222bb542SMatt Jacob isp_pci_dmasetup, 1450a70657fSMatt Jacob isp_common_dmateardown, 1463bda7a83SMatt Jacob isp_pci_reset0, 147222bb542SMatt Jacob isp_pci_reset1, 148d02373f1SMatt Jacob isp_pci_dumpregs 149222bb542SMatt Jacob }; 150d951bbcaSMatt Jacob 15110365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = { 15210365e5aSMatt Jacob isp_pci_rd_isr_2400, 15310365e5aSMatt Jacob isp_pci_rd_reg_2400, 15410365e5aSMatt Jacob isp_pci_wr_reg_2400, 15510365e5aSMatt Jacob isp_pci_mbxdma, 15610365e5aSMatt Jacob isp_pci_dmasetup, 1570a70657fSMatt Jacob isp_common_dmateardown, 1583bda7a83SMatt Jacob isp_pci_reset0, 15910365e5aSMatt Jacob isp_pci_reset1, 16010365e5aSMatt Jacob NULL 16110365e5aSMatt Jacob }; 16210365e5aSMatt Jacob 1632df76c16SMatt Jacob static struct ispmdvec mdvec_2500 = { 1642df76c16SMatt Jacob isp_pci_rd_isr_2400, 1652df76c16SMatt Jacob isp_pci_rd_reg_2400, 1662df76c16SMatt Jacob isp_pci_wr_reg_2400, 1672df76c16SMatt Jacob isp_pci_mbxdma, 1682df76c16SMatt Jacob isp_pci_dmasetup, 1692df76c16SMatt Jacob isp_common_dmateardown, 1702df76c16SMatt Jacob isp_pci_reset0, 1712df76c16SMatt Jacob isp_pci_reset1, 1722df76c16SMatt Jacob NULL 1732df76c16SMatt Jacob }; 1742df76c16SMatt Jacob 175*218be0b2SAlexander Motin static struct ispmdvec mdvec_2600 = { 176*218be0b2SAlexander Motin isp_pci_rd_isr_2400, 177*218be0b2SAlexander Motin isp_pci_rd_reg_2400, 178*218be0b2SAlexander Motin isp_pci_wr_reg_2400, 179*218be0b2SAlexander Motin isp_pci_mbxdma, 180*218be0b2SAlexander Motin isp_pci_dmasetup, 181*218be0b2SAlexander Motin isp_common_dmateardown, 182*218be0b2SAlexander Motin isp_pci_reset0, 183*218be0b2SAlexander Motin isp_pci_reset1, 184*218be0b2SAlexander Motin NULL 185*218be0b2SAlexander Motin }; 186*218be0b2SAlexander Motin 18765adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 18865adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 18965adb54cSMatt Jacob #endif 19065adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 19165adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 19265adb54cSMatt Jacob #endif 193d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 194d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 195d951bbcaSMatt Jacob #endif 196d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 197d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 198d951bbcaSMatt Jacob #endif 1998a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 2008a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 2018a97c03aSMatt Jacob #endif 202d951bbcaSMatt Jacob 203d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 204d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 205d951bbcaSMatt Jacob #endif 206d951bbcaSMatt Jacob 207d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 208d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 209d951bbcaSMatt Jacob #endif 210d951bbcaSMatt Jacob 211d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 212d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 213d951bbcaSMatt Jacob #endif 214d951bbcaSMatt Jacob 215ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 216ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 217ab6d0040SMatt Jacob #endif 218ab6d0040SMatt Jacob 21965adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 22065adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 22165adb54cSMatt Jacob #endif 22265adb54cSMatt Jacob 22365adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 22465adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 22565adb54cSMatt Jacob #endif 22665adb54cSMatt Jacob 227d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 228d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 229d59bd469SMatt Jacob #endif 230d59bd469SMatt Jacob 231f556e83bSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP10160 232f556e83bSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 233f556e83bSMatt Jacob #endif 234f556e83bSMatt Jacob 235960f6939SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP12160 236960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 237960f6939SMatt Jacob #endif 238960f6939SMatt Jacob 239d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 240d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 241d59bd469SMatt Jacob #endif 24265adb54cSMatt Jacob 24322e1dc85SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1280 24422e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 24522e1dc85SMatt Jacob #endif 24622e1dc85SMatt Jacob 24765adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 24865adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 24965adb54cSMatt Jacob #endif 25065adb54cSMatt Jacob 251222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 252222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 253222bb542SMatt Jacob #endif 254222bb542SMatt Jacob 255126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2300 256126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 257126ec864SMatt Jacob #endif 258126ec864SMatt Jacob 259126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2312 260126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 261126ec864SMatt Jacob #endif 262126ec864SMatt Jacob 263e5265237SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2322 264e5265237SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 265e5265237SMatt Jacob #endif 266e5265237SMatt Jacob 2678872e3d7SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2422 2688872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 2698872e3d7SMatt Jacob #endif 2708872e3d7SMatt Jacob 27141675df0SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2432 27241675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 27341675df0SMatt Jacob #endif 27441675df0SMatt Jacob 2752df76c16SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2532 2762df76c16SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2532 0x2532 2772df76c16SMatt Jacob #endif 2782df76c16SMatt Jacob 279dd1419abSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6312 280dd1419abSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 281dd1419abSMatt Jacob #endif 282dd1419abSMatt Jacob 2839a5af410SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6322 2849a5af410SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 2859a5af410SMatt Jacob #endif 2869a5af410SMatt Jacob 287a959d921SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP5432 288a959d921SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP5432 0x5432 289a959d921SMatt Jacob #endif 290a959d921SMatt Jacob 291*218be0b2SAlexander Motin #ifndef PCI_PRODUCT_QLOGIC_ISP2031 292*218be0b2SAlexander Motin #define PCI_PRODUCT_QLOGIC_ISP2031 0x2031 293*218be0b2SAlexander Motin #endif 294*218be0b2SAlexander Motin 295a959d921SMatt Jacob #define PCI_QLOGIC_ISP5432 \ 296a959d921SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC) 2979a5af410SMatt Jacob 29856aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 29956aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 300d59bd469SMatt Jacob 301d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 302d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 303d59bd469SMatt Jacob 304f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 305f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 306f556e83bSMatt Jacob 307960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 308960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 309960f6939SMatt Jacob 310d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 311d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 312d59bd469SMatt Jacob 31322e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 31422e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 31522e1dc85SMatt Jacob 31665adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 31765adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 31865adb54cSMatt Jacob 319222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 320222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 321222bb542SMatt Jacob 322126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 323126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 324126ec864SMatt Jacob 325126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 326126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 327126ec864SMatt Jacob 328e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 329e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 330e5265237SMatt Jacob 3316c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 3326c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 3336c426685SMatt Jacob 33441675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 33541675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 33641675df0SMatt Jacob 3372df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 3382df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 3392df76c16SMatt Jacob 340dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 341dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 342dd1419abSMatt Jacob 3439a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 3449a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 3459a5af410SMatt Jacob 346*218be0b2SAlexander Motin #define PCI_QLOGIC_ISP2031 \ 347*218be0b2SAlexander Motin ((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC) 348*218be0b2SAlexander Motin 349e11a1ee8SMatt Jacob /* 350e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 351e11a1ee8SMatt Jacob */ 352e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 353e11a1ee8SMatt Jacob 354d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 355d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 35665adb54cSMatt Jacob 357960f6939SMatt Jacob static int isp_pci_probe (device_t); 358960f6939SMatt Jacob static int isp_pci_attach (device_t); 35910365e5aSMatt Jacob static int isp_pci_detach (device_t); 36065adb54cSMatt Jacob 3611923f739SMatt Jacob 3620230a28bSMatt Jacob #define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev 36365adb54cSMatt Jacob struct isp_pcisoftc { 3649cd7268eSMatt Jacob ispsoftc_t pci_isp; 365960f6939SMatt Jacob device_t pci_dev; 366e95725cbSMatt Jacob struct resource * regs; 367e95725cbSMatt Jacob void * irq; 368e95725cbSMatt Jacob int iqd; 369e95725cbSMatt Jacob int rtp; 370e95725cbSMatt Jacob int rgd; 371960f6939SMatt Jacob void * ih; 372d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3731923f739SMatt Jacob bus_dma_tag_t dmat; 3740a70657fSMatt Jacob int msicount; 37565adb54cSMatt Jacob }; 37665adb54cSMatt Jacob 37710365e5aSMatt Jacob 378960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 379960f6939SMatt Jacob /* Device interface */ 380960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 381960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 38210365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 383960f6939SMatt Jacob { 0, 0 } 38465adb54cSMatt Jacob }; 38565adb54cSMatt Jacob 386960f6939SMatt Jacob static driver_t isp_pci_driver = { 387960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 388960f6939SMatt Jacob }; 389960f6939SMatt Jacob static devclass_t isp_devclass; 390960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 391d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1); 392d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1); 3939e7d423dSMatt Jacob static int isp_nvports = 0; 39465adb54cSMatt Jacob 395960f6939SMatt Jacob static int 396960f6939SMatt Jacob isp_pci_probe(device_t dev) 39765adb54cSMatt Jacob { 398960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 39956aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 400960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 40165adb54cSMatt Jacob break; 402d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 403960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 404c6608df3SMatt Jacob break; 405c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 406960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 407d59bd469SMatt Jacob break; 40822e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 409960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 410960f6939SMatt Jacob break; 411f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 412f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 413f556e83bSMatt Jacob break; 414960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 415e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 416e11a1ee8SMatt Jacob return (ENXIO); 417e11a1ee8SMatt Jacob } 418960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 41922e1dc85SMatt Jacob break; 42065adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 421960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 42265adb54cSMatt Jacob break; 4235542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 424960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 4255542fe4bSMatt Jacob break; 426126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 427126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 428126ec864SMatt Jacob break; 429126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 430126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 431126ec864SMatt Jacob break; 432e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 433e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 434e5265237SMatt Jacob break; 4358872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 4368872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 4378872e3d7SMatt Jacob break; 43841675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 43941675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 44041675df0SMatt Jacob break; 4412df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 4422df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 4432df76c16SMatt Jacob break; 444a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 445a959d921SMatt Jacob device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter"); 446a959d921SMatt Jacob break; 447dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 448dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 449dd1419abSMatt Jacob break; 4509a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4519a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4529a5af410SMatt Jacob break; 453*218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 454*218be0b2SAlexander Motin device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter"); 455*218be0b2SAlexander Motin break; 45665adb54cSMatt Jacob default: 457960f6939SMatt Jacob return (ENXIO); 45865adb54cSMatt Jacob } 45973030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 460d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 461a95ae193SMatt Jacob "Core Version %d.%d\n", 462d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 463d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 46473030e03SMatt Jacob isp_announced++; 46565adb54cSMatt Jacob } 46656aef503SMatt Jacob /* 46756aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 46856aef503SMatt Jacob * XXXX: (or increase a reference count to it). 46956aef503SMatt Jacob */ 470b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 47165adb54cSMatt Jacob } 47265adb54cSMatt Jacob 4739cd7268eSMatt Jacob static void 4749e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 4759cd7268eSMatt Jacob { 4769cd7268eSMatt Jacob int tval; 477f7c631bcSMatt Jacob 4789cd7268eSMatt Jacob tval = 0; 4792df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 4809cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4819cd7268eSMatt Jacob } 4829cd7268eSMatt Jacob tval = 0; 4832df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 4849cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 4859cd7268eSMatt Jacob } 486336b5612SMatt Jacob tval = 0; 4872df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 488336b5612SMatt Jacob if (tval) { 489336b5612SMatt Jacob isp->isp_dblev = tval; 490336b5612SMatt Jacob } else { 491336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 492336b5612SMatt Jacob } 493336b5612SMatt Jacob if (bootverbose) { 494336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 495336b5612SMatt Jacob } 4969e7d423dSMatt Jacob tval = -1; 4972df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 498ffe6ea05SAlexander Motin if (tval > 0 && tval <= 254) { 4999e7d423dSMatt Jacob isp_nvports = tval; 5002df76c16SMatt Jacob } 5012df76c16SMatt Jacob tval = 7; 5022df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 5032df76c16SMatt Jacob isp_quickboot_time = tval; 504336b5612SMatt Jacob } 505336b5612SMatt Jacob 506336b5612SMatt Jacob static void 5072df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 508336b5612SMatt Jacob { 509336b5612SMatt Jacob const char *sptr; 5109e7d423dSMatt Jacob int tval = 0; 51107f56f1cSAlexander Motin char prefix[12], name[16]; 512336b5612SMatt Jacob 51307f56f1cSAlexander Motin if (chan == 0) 51407f56f1cSAlexander Motin prefix[0] = 0; 51507f56f1cSAlexander Motin else 51607f56f1cSAlexander Motin snprintf(prefix, sizeof(prefix), "chan%d.", chan); 51707f56f1cSAlexander Motin snprintf(name, sizeof(name), "%siid", prefix); 51807f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 51907f56f1cSAlexander Motin name, &tval)) { 5202df76c16SMatt Jacob if (IS_FC(isp)) { 5212df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 5222df76c16SMatt Jacob } else { 52317bc427dSMarius Strobl #ifdef __sparc64__ 52417bc427dSMarius Strobl ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev); 52517bc427dSMarius Strobl #else 5262df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = 7; 52717bc427dSMarius Strobl #endif 5282df76c16SMatt Jacob } 5292df76c16SMatt Jacob } else { 5302df76c16SMatt Jacob if (IS_FC(isp)) { 5312df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 5322df76c16SMatt Jacob } else { 5332df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = tval; 5342df76c16SMatt Jacob } 535336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 536336b5612SMatt Jacob } 5372df76c16SMatt Jacob 5383e6deb33SAlexander Motin if (IS_SCSI(isp)) 5393e6deb33SAlexander Motin return; 5403e6deb33SAlexander Motin 5412df76c16SMatt Jacob tval = -1; 54207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%srole", prefix); 54307f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 54407f56f1cSAlexander Motin name, &tval) == 0) { 5452df76c16SMatt Jacob switch (tval) { 5462df76c16SMatt Jacob case ISP_ROLE_NONE: 5472df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 5482df76c16SMatt Jacob case ISP_ROLE_TARGET: 54907f56f1cSAlexander Motin case ISP_ROLE_BOTH: 55007f56f1cSAlexander Motin device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval); 5512df76c16SMatt Jacob break; 5522df76c16SMatt Jacob default: 5532df76c16SMatt Jacob tval = -1; 5542df76c16SMatt Jacob break; 555336b5612SMatt Jacob } 556336b5612SMatt Jacob } 5572df76c16SMatt Jacob if (tval == -1) { 5582df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 5592df76c16SMatt Jacob } 5604ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 561336b5612SMatt Jacob 5629cd7268eSMatt Jacob tval = 0; 56307f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfullduplex", prefix); 56407f56f1cSAlexander Motin if (resource_int_value(device_get_name(dev), device_get_unit(dev), 56507f56f1cSAlexander Motin name, &tval) == 0 && tval != 0) { 5669cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5679cd7268eSMatt Jacob } 5689cd7268eSMatt Jacob sptr = 0; 56907f56f1cSAlexander Motin snprintf(name, sizeof(name), "%stopology", prefix); 57007f56f1cSAlexander Motin if (resource_string_value(device_get_name(dev), device_get_unit(dev), 57107f56f1cSAlexander Motin name, (const char **) &sptr) == 0 && sptr != 0) { 5729cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 5739cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 5749cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 5759cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5769cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 5779cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 5789cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 5799cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 5809cd7268eSMatt Jacob } 581960f6939SMatt Jacob } 582960f6939SMatt Jacob 583387d8239SMatt Jacob tval = 0; 58407f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snofctape", prefix); 58507f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 58607f56f1cSAlexander Motin name, &tval); 587387d8239SMatt Jacob if (tval) { 588387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_NOFCTAPE; 589387d8239SMatt Jacob } 590387d8239SMatt Jacob 591387d8239SMatt Jacob tval = 0; 59207f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sfctape", prefix); 59307f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 59407f56f1cSAlexander Motin name, &tval); 595387d8239SMatt Jacob if (tval) { 596387d8239SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NOFCTAPE; 597387d8239SMatt Jacob isp->isp_confopts |= ISP_CFG_FCTAPE; 598387d8239SMatt Jacob } 599387d8239SMatt Jacob 600387d8239SMatt Jacob 6019ba86737SMatt Jacob /* 6029cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 6039cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 6049cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 6059cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 6069cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 6079cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 6089cd7268eSMatt Jacob */ 6099cd7268eSMatt Jacob sptr = 0; 61007f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sportwwn", prefix); 61107f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 61207f56f1cSAlexander Motin name, (const char **) &sptr); 6139cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6149cd7268eSMatt Jacob char *eptr = 0; 6152df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 6162df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 6179cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 6182df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 6199cd7268eSMatt Jacob } 6209cd7268eSMatt Jacob } 6219cd7268eSMatt Jacob 6229cd7268eSMatt Jacob sptr = 0; 62307f56f1cSAlexander Motin snprintf(name, sizeof(name), "%snodewwn", prefix); 62407f56f1cSAlexander Motin tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 62507f56f1cSAlexander Motin name, (const char **) &sptr); 6269cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6279cd7268eSMatt Jacob char *eptr = 0; 6282df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 6292df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 6309cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6312df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 6329cd7268eSMatt Jacob } 6339cd7268eSMatt Jacob } 6349cd7268eSMatt Jacob 635f7c631bcSMatt Jacob tval = -1; 63607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sloop_down_limit", prefix); 63707f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 63807f56f1cSAlexander Motin name, &tval); 63910365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6402df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 64110365e5aSMatt Jacob } else { 6422df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 64310365e5aSMatt Jacob } 64410365e5aSMatt Jacob 645f7c631bcSMatt Jacob tval = -1; 64607f56f1cSAlexander Motin snprintf(name, sizeof(name), "%sgone_device_time", prefix); 64707f56f1cSAlexander Motin (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 64807f56f1cSAlexander Motin name, &tval); 649f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6502df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 651f7c631bcSMatt Jacob } else { 6522df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 653f7c631bcSMatt Jacob } 6549cd7268eSMatt Jacob } 6559cd7268eSMatt Jacob 6569cd7268eSMatt Jacob static int 6579cd7268eSMatt Jacob isp_pci_attach(device_t dev) 6589cd7268eSMatt Jacob { 659*218be0b2SAlexander Motin int i, locksetup = 0; 6602df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 6619cd7268eSMatt Jacob struct isp_pcisoftc *pcs; 662a035b0afSMatt Jacob ispsoftc_t *isp; 6632df76c16SMatt Jacob size_t psize, xsize; 6642df76c16SMatt Jacob char fwname[32]; 6659cd7268eSMatt Jacob 6669cd7268eSMatt Jacob pcs = device_get_softc(dev); 6679cd7268eSMatt Jacob if (pcs == NULL) { 6689cd7268eSMatt Jacob device_printf(dev, "cannot get softc\n"); 6699cd7268eSMatt Jacob return (ENOMEM); 6709cd7268eSMatt Jacob } 6719cd7268eSMatt Jacob memset(pcs, 0, sizeof (*pcs)); 6722df76c16SMatt Jacob 6739cd7268eSMatt Jacob pcs->pci_dev = dev; 6749cd7268eSMatt Jacob isp = &pcs->pci_isp; 6752df76c16SMatt Jacob isp->isp_dev = dev; 6762df76c16SMatt Jacob isp->isp_nchan = 1; 677387d8239SMatt Jacob if (sizeof (bus_addr_t) > 4) 678387d8239SMatt Jacob isp->isp_osinfo.sixtyfourbit = 1; 6799cd7268eSMatt Jacob 6809cd7268eSMatt Jacob /* 681336b5612SMatt Jacob * Get Generic Options 6829cd7268eSMatt Jacob */ 6839e7d423dSMatt Jacob isp_nvports = 0; 6849e7d423dSMatt Jacob isp_get_generic_options(dev, isp); 6859cd7268eSMatt Jacob 686ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 687e95725cbSMatt Jacob pcs->irq = pcs->regs = NULL; 688e95725cbSMatt Jacob pcs->rgd = pcs->rtp = pcs->iqd = 0; 689960f6939SMatt Jacob 6902df76c16SMatt Jacob pcs->pci_dev = dev; 691d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 692d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 693d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 694d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 695d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 6962df76c16SMatt Jacob 6972df76c16SMatt Jacob switch (pci_get_devid(dev)) { 6982df76c16SMatt Jacob case PCI_QLOGIC_ISP1020: 6992df76c16SMatt Jacob did = 0x1040; 7002df76c16SMatt Jacob isp->isp_mdvec = &mdvec; 7012df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 7022df76c16SMatt Jacob break; 7032df76c16SMatt Jacob case PCI_QLOGIC_ISP1080: 7042df76c16SMatt Jacob did = 0x1080; 7052df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7062df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 7072df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7082df76c16SMatt Jacob break; 7092df76c16SMatt Jacob case PCI_QLOGIC_ISP1240: 7102df76c16SMatt Jacob did = 0x1080; 7112df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7122df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1240; 7132df76c16SMatt Jacob isp->isp_nchan = 2; 7142df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7152df76c16SMatt Jacob break; 7162df76c16SMatt Jacob case PCI_QLOGIC_ISP1280: 7172df76c16SMatt Jacob did = 0x1080; 7182df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7192df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1280; 7202df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7212df76c16SMatt Jacob break; 7222df76c16SMatt Jacob case PCI_QLOGIC_ISP10160: 7232df76c16SMatt Jacob did = 0x12160; 7242df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7252df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_10160; 7262df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7272df76c16SMatt Jacob break; 7282df76c16SMatt Jacob case PCI_QLOGIC_ISP12160: 7292df76c16SMatt Jacob did = 0x12160; 7302df76c16SMatt Jacob isp->isp_nchan = 2; 7312df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7322df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_12160; 7332df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7342df76c16SMatt Jacob break; 7352df76c16SMatt Jacob case PCI_QLOGIC_ISP2100: 7362df76c16SMatt Jacob did = 0x2100; 7372df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2100; 7382df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2100; 7392df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 740960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 741ab6d0040SMatt Jacob /* 742ab6d0040SMatt Jacob * XXX: Need to get the actual revision 743ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 744ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 745ab6d0040SMatt Jacob * XXX; boards. 746ab6d0040SMatt Jacob */ 747ab6d0040SMatt Jacob linesz = 1; 748ab6d0040SMatt Jacob } 7492df76c16SMatt Jacob break; 7502df76c16SMatt Jacob case PCI_QLOGIC_ISP2200: 7512df76c16SMatt Jacob did = 0x2200; 7522df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2200; 7532df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2200; 7542df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 7552df76c16SMatt Jacob break; 7562df76c16SMatt Jacob case PCI_QLOGIC_ISP2300: 7572df76c16SMatt Jacob did = 0x2300; 7582df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7592df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2300; 7602df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7612df76c16SMatt Jacob break; 7622df76c16SMatt Jacob case PCI_QLOGIC_ISP2312: 7632df76c16SMatt Jacob case PCI_QLOGIC_ISP6312: 7642df76c16SMatt Jacob did = 0x2300; 7652df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7662df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2312; 7672df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7682df76c16SMatt Jacob break; 7692df76c16SMatt Jacob case PCI_QLOGIC_ISP2322: 7702df76c16SMatt Jacob case PCI_QLOGIC_ISP6322: 7712df76c16SMatt Jacob did = 0x2322; 7722df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7732df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2322; 7742df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7752df76c16SMatt Jacob break; 7762df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 7772df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 7782df76c16SMatt Jacob did = 0x2400; 7792df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7802df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 7812df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 7822df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 7832df76c16SMatt Jacob break; 7842df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 7852df76c16SMatt Jacob did = 0x2500; 7862df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7872df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 7882df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 7892df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 7902df76c16SMatt Jacob break; 791a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 792a959d921SMatt Jacob did = 0x2500; 793a959d921SMatt Jacob isp->isp_mdvec = &mdvec_2500; 794a959d921SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 795a959d921SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 796a959d921SMatt Jacob break; 797*218be0b2SAlexander Motin case PCI_QLOGIC_ISP2031: 798*218be0b2SAlexander Motin did = 0x2600; 799*218be0b2SAlexander Motin isp->isp_nchan += isp_nvports; 800*218be0b2SAlexander Motin isp->isp_mdvec = &mdvec_2600; 801*218be0b2SAlexander Motin isp->isp_type = ISP_HA_FC_2600; 802*218be0b2SAlexander Motin pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 803*218be0b2SAlexander Motin break; 8042df76c16SMatt Jacob default: 8052df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 8062df76c16SMatt Jacob goto bad; 8072df76c16SMatt Jacob break; 80865adb54cSMatt Jacob } 8092df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 8102df76c16SMatt Jacob 811*218be0b2SAlexander Motin if (IS_26XX(isp)) { 812*218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 813*218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 814*218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 815*218be0b2SAlexander Motin RF_ACTIVE); 816*218be0b2SAlexander Motin } else { 817*218be0b2SAlexander Motin pcs->rtp = SYS_RES_MEMORY; 818*218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(1); 819*218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, 820*218be0b2SAlexander Motin RF_ACTIVE); 821*218be0b2SAlexander Motin if (pcs->regs == NULL) { 822*218be0b2SAlexander Motin pcs->rtp = SYS_RES_IOPORT; 823*218be0b2SAlexander Motin pcs->rgd = PCIR_BAR(0); 824*218be0b2SAlexander Motin pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, 825*218be0b2SAlexander Motin &pcs->rgd, RF_ACTIVE); 826*218be0b2SAlexander Motin } 827*218be0b2SAlexander Motin } 828*218be0b2SAlexander Motin if (pcs->regs == NULL) { 829*218be0b2SAlexander Motin device_printf(dev, "Unable to map any ports\n"); 830*218be0b2SAlexander Motin goto bad; 831*218be0b2SAlexander Motin } 832*218be0b2SAlexander Motin if (bootverbose) { 833*218be0b2SAlexander Motin device_printf(dev, "Using %s space register mapping\n", 834*218be0b2SAlexander Motin (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory"); 835*218be0b2SAlexander Motin } 836*218be0b2SAlexander Motin isp->isp_bus_tag = rman_get_bustag(pcs->regs); 837*218be0b2SAlexander Motin isp->isp_bus_handle = rman_get_bushandle(pcs->regs); 838*218be0b2SAlexander Motin 8392df76c16SMatt Jacob if (IS_FC(isp)) { 840222bb542SMatt Jacob psize = sizeof (fcparam); 8412df76c16SMatt Jacob xsize = sizeof (struct isp_fc); 8422df76c16SMatt Jacob } else { 8432df76c16SMatt Jacob psize = sizeof (sdparam); 8442df76c16SMatt Jacob xsize = sizeof (struct isp_spi); 845222bb542SMatt Jacob } 8462df76c16SMatt Jacob psize *= isp->isp_nchan; 8472df76c16SMatt Jacob xsize *= isp->isp_nchan; 8487cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 849c6608df3SMatt Jacob if (isp->isp_param == NULL) { 850960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 851960f6939SMatt Jacob goto bad; 852c6608df3SMatt Jacob } 8532df76c16SMatt Jacob isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 8542df76c16SMatt Jacob if (isp->isp_osinfo.pc.ptr == NULL) { 8552df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 8562df76c16SMatt Jacob goto bad; 8572df76c16SMatt Jacob } 85865adb54cSMatt Jacob 859336b5612SMatt Jacob /* 860336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 861336b5612SMatt Jacob */ 8622df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 8632df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 8649a5af410SMatt Jacob } 8659a5af410SMatt Jacob 8669a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 8679a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 8689a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 8699a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8709a5af410SMatt Jacob } 8719a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 872ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname); 8735f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 8749a5af410SMatt Jacob } 87556aef503SMatt Jacob 87656aef503SMatt Jacob /* 877ad0ab753SMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 878d951bbcaSMatt Jacob */ 879c68534f1SScott Long cmd = pci_read_config(dev, PCIR_COMMAND, 2); 8809e7d423dSMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 88175c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 88275c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 88375c1e828SMatt Jacob } 8848a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 8858a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 8868a97c03aSMatt Jacob } 88706cacb29SMatt Jacob if (IS_24XX(isp)) { 88806cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 88906cacb29SMatt Jacob } 890b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 891ab6d0040SMatt Jacob 892d951bbcaSMatt Jacob /* 893222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 894d951bbcaSMatt Jacob */ 895960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 8966a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 897ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data); 8986a7d12e1SMatt Jacob data = linesz; 899960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 900d951bbcaSMatt Jacob } 901ab6d0040SMatt Jacob 902d951bbcaSMatt Jacob /* 903d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 904d951bbcaSMatt Jacob */ 905960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 906d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 907d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 908ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data); 909960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 910d951bbcaSMatt Jacob } 911ab6d0040SMatt Jacob 912ab6d0040SMatt Jacob /* 913ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 914ab6d0040SMatt Jacob */ 915960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 916ab6d0040SMatt Jacob data &= ~1; 917960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 9182df76c16SMatt Jacob 9192df76c16SMatt Jacob /* 9202df76c16SMatt Jacob * Do MSI 9212df76c16SMatt Jacob * 9222df76c16SMatt Jacob * NB: MSI-X needs to be disabled for the 2432 (PCI-Express) 9232df76c16SMatt Jacob */ 9240a70657fSMatt Jacob if (IS_24XX(isp) || IS_2322(isp)) { 9250a70657fSMatt Jacob pcs->msicount = pci_msi_count(dev); 9260a70657fSMatt Jacob if (pcs->msicount > 1) { 9270a70657fSMatt Jacob pcs->msicount = 1; 9280a70657fSMatt Jacob } 9290a70657fSMatt Jacob if (pci_alloc_msi(dev, &pcs->msicount) == 0) { 930e95725cbSMatt Jacob pcs->iqd = 1; 9310a70657fSMatt Jacob } else { 932e95725cbSMatt Jacob pcs->iqd = 0; 9330a70657fSMatt Jacob } 9340a70657fSMatt Jacob } 935e95725cbSMatt Jacob pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE); 936e95725cbSMatt Jacob if (pcs->irq == NULL) { 937960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 938960f6939SMatt Jacob goto bad; 939960f6939SMatt Jacob } 940960f6939SMatt Jacob 941f09b1922SMatt Jacob /* Make sure the lock is set up. */ 9426008862bSJohn Baldwin mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); 943f09b1922SMatt Jacob locksetup++; 944f09b1922SMatt Jacob 945e95725cbSMatt Jacob if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { 946f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 947f09b1922SMatt Jacob goto bad; 948f09b1922SMatt Jacob } 949960f6939SMatt Jacob 95005fbcbb0SMatt Jacob /* 95175c1e828SMatt Jacob * Last minute checks... 95275c1e828SMatt Jacob */ 95310365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 95475c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 95575c1e828SMatt Jacob } 95675c1e828SMatt Jacob 95775c1e828SMatt Jacob /* 95805fbcbb0SMatt Jacob * Make sure we're in reset state. 95905fbcbb0SMatt Jacob */ 9603395b056SMatt Jacob ISP_LOCK(isp); 961dfd24649SAlexander Motin if (isp_reinit(isp, 1) != 0) { 9623395b056SMatt Jacob ISP_UNLOCK(isp); 963960f6939SMatt Jacob goto bad; 96465adb54cSMatt Jacob } 9652df76c16SMatt Jacob ISP_UNLOCK(isp); 9662df76c16SMatt Jacob if (isp_attach(isp)) { 9672df76c16SMatt Jacob ISP_LOCK(isp); 96865adb54cSMatt Jacob isp_uninit(isp); 9693395b056SMatt Jacob ISP_UNLOCK(isp); 970960f6939SMatt Jacob goto bad; 971d59bd469SMatt Jacob } 972960f6939SMatt Jacob return (0); 973960f6939SMatt Jacob 974960f6939SMatt Jacob bad: 975a035b0afSMatt Jacob if (pcs->ih) { 976e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 977960f6939SMatt Jacob } 978a035b0afSMatt Jacob if (locksetup) { 9793395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 9803395b056SMatt Jacob } 981e95725cbSMatt Jacob if (pcs->irq) { 982e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 983960f6939SMatt Jacob } 984a035b0afSMatt Jacob if (pcs->msicount) { 9850a70657fSMatt Jacob pci_release_msi(dev); 9860a70657fSMatt Jacob } 987e95725cbSMatt Jacob if (pcs->regs) { 988e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 989960f6939SMatt Jacob } 9909cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 991960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 9922df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 9932df76c16SMatt Jacob } 9942df76c16SMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 9952df76c16SMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 9962df76c16SMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 9979cd7268eSMatt Jacob } 998960f6939SMatt Jacob return (ENXIO); 99965adb54cSMatt Jacob } 100065adb54cSMatt Jacob 100110365e5aSMatt Jacob static int 100210365e5aSMatt Jacob isp_pci_detach(device_t dev) 100310365e5aSMatt Jacob { 100410365e5aSMatt Jacob struct isp_pcisoftc *pcs; 100510365e5aSMatt Jacob ispsoftc_t *isp; 1006e95725cbSMatt Jacob int status; 100710365e5aSMatt Jacob 100810365e5aSMatt Jacob pcs = device_get_softc(dev); 100910365e5aSMatt Jacob if (pcs == NULL) { 101010365e5aSMatt Jacob return (ENXIO); 101110365e5aSMatt Jacob } 101210365e5aSMatt Jacob isp = (ispsoftc_t *) pcs; 1013e95725cbSMatt Jacob status = isp_detach(isp); 1014e95725cbSMatt Jacob if (status) 1015e95725cbSMatt Jacob return (status); 1016e95725cbSMatt Jacob ISP_LOCK(isp); 1017e95725cbSMatt Jacob isp_uninit(isp); 1018e95725cbSMatt Jacob if (pcs->ih) { 1019e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 1020e95725cbSMatt Jacob } 1021e95725cbSMatt Jacob ISP_UNLOCK(isp); 10222df76c16SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 1023e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 1024e95725cbSMatt Jacob if (pcs->msicount) { 1025e95725cbSMatt Jacob pci_release_msi(dev); 1026e95725cbSMatt Jacob } 1027e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 1028387d8239SMatt Jacob /* 1029387d8239SMatt Jacob * XXX: THERE IS A LOT OF LEAKAGE HERE 1030387d8239SMatt Jacob */ 1031e95725cbSMatt Jacob if (pcs->pci_isp.isp_param) { 1032e95725cbSMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 1033e95725cbSMatt Jacob pcs->pci_isp.isp_param = NULL; 1034e95725cbSMatt Jacob } 1035e95725cbSMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 1036e95725cbSMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 1037e95725cbSMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 1038e95725cbSMatt Jacob } 103910365e5aSMatt Jacob return (0); 104010365e5aSMatt Jacob } 104110365e5aSMatt Jacob 1042126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 1043126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 10444cc9e3e7SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xfff)) 1045126ec864SMatt Jacob 10466a7d12e1SMatt Jacob #define BXR2(isp, off) \ 10476a7d12e1SMatt Jacob bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off) 10486a7d12e1SMatt Jacob #define BXW2(isp, off, v) \ 10496a7d12e1SMatt Jacob bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, off, v) 10506a7d12e1SMatt Jacob #define BXR4(isp, off) \ 10516a7d12e1SMatt Jacob bus_space_read_4(isp->isp_bus_tag, isp->isp_bus_handle, off) 10526a7d12e1SMatt Jacob #define BXW4(isp, off, v) \ 10536a7d12e1SMatt Jacob bus_space_write_4(isp->isp_bus_tag, isp->isp_bus_handle, off, v) 1054126ec864SMatt Jacob 1055126ec864SMatt Jacob 10562df76c16SMatt Jacob static ISP_INLINE int 10579cd7268eSMatt Jacob isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) 1058126ec864SMatt Jacob { 105910365e5aSMatt Jacob uint32_t val0, val1; 1060126ec864SMatt Jacob int i = 0; 1061126ec864SMatt Jacob 1062126ec864SMatt Jacob do { 10636a7d12e1SMatt Jacob val0 = BXR2(isp, IspVirt2Off(isp, off)); 10646a7d12e1SMatt Jacob val1 = BXR2(isp, IspVirt2Off(isp, off)); 1065126ec864SMatt Jacob } while (val0 != val1 && ++i < 1000); 1066126ec864SMatt Jacob if (val0 != val1) { 1067126ec864SMatt Jacob return (1); 1068126ec864SMatt Jacob } 1069126ec864SMatt Jacob *rp = val0; 1070126ec864SMatt Jacob return (0); 1071126ec864SMatt Jacob } 1072126ec864SMatt Jacob 1073126ec864SMatt Jacob static int 10746ce548a1SAlexander Motin isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 1075126ec864SMatt Jacob { 10761dae40ebSMatt Jacob uint16_t isr, sema; 1077126ec864SMatt Jacob 1078126ec864SMatt Jacob if (IS_2100(isp)) { 1079126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { 1080126ec864SMatt Jacob return (0); 1081126ec864SMatt Jacob } 1082126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { 1083126ec864SMatt Jacob return (0); 1084126ec864SMatt Jacob } 1085126ec864SMatt Jacob } else { 10866a7d12e1SMatt Jacob isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR)); 10876a7d12e1SMatt Jacob sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA)); 1088126ec864SMatt Jacob } 1089126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 1090126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 1091126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 1092126ec864SMatt Jacob if (isr == 0 && sema == 0) { 1093126ec864SMatt Jacob return (0); 1094126ec864SMatt Jacob } 1095126ec864SMatt Jacob *isrp = isr; 1096126ec864SMatt Jacob if ((*semap = sema) != 0) { 1097126ec864SMatt Jacob if (IS_2100(isp)) { 10986ce548a1SAlexander Motin if (isp_pci_rd_debounced(isp, OUTMAILBOX0, info)) { 1099126ec864SMatt Jacob return (0); 1100126ec864SMatt Jacob } 1101126ec864SMatt Jacob } else { 11026ce548a1SAlexander Motin *info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 1103126ec864SMatt Jacob } 1104126ec864SMatt Jacob } 1105126ec864SMatt Jacob return (1); 1106126ec864SMatt Jacob } 1107126ec864SMatt Jacob 1108126ec864SMatt Jacob static int 11096ce548a1SAlexander Motin isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 1110126ec864SMatt Jacob { 11116ce548a1SAlexander Motin uint32_t hccr, r2hisr; 1112126ec864SMatt Jacob 11136a7d12e1SMatt Jacob if (!(BXR2(isp, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 11143bd40330SMatt Jacob *isrp = 0; 1115db4fa023SMatt Jacob return (0); 11163bd40330SMatt Jacob } 11176a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO)); 1118126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 1119126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 1120126ec864SMatt Jacob *isrp = 0; 1121126ec864SMatt Jacob return (0); 1122126ec864SMatt Jacob } 11236ce548a1SAlexander Motin switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) { 1124126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1125126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1126126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1127126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 1128126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 1129126ec864SMatt Jacob *semap = 1; 11306ce548a1SAlexander Motin break; 1131fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 11326ce548a1SAlexander Motin *info = ASYNC_RIO16_1; 1133fc3bbaaaSMatt Jacob *semap = 1; 1134fc3bbaaaSMatt Jacob return (1); 1135fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 11366ce548a1SAlexander Motin *info = ASYNC_CMD_CMPLT; 1137fc3bbaaaSMatt Jacob *semap = 1; 1138fc3bbaaaSMatt Jacob return (1); 1139fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 11406ce548a1SAlexander Motin *info = ASYNC_CTIO_DONE; 1141fc3bbaaaSMatt Jacob *semap = 1; 1142fc3bbaaaSMatt Jacob return (1); 1143126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 1144126ec864SMatt Jacob *semap = 0; 11456ce548a1SAlexander Motin break; 1146126ec864SMatt Jacob default: 11478a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 11488a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 11498a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 1150443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR)); 11515ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 11528a97c03aSMatt Jacob } else { 1153443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 11548a97c03aSMatt Jacob } 1155126ec864SMatt Jacob return (0); 1156126ec864SMatt Jacob } 11576ce548a1SAlexander Motin *info = (r2hisr >> 16); 11586ce548a1SAlexander Motin return (1); 1159126ec864SMatt Jacob } 1160126ec864SMatt Jacob 116110365e5aSMatt Jacob static int 11626ce548a1SAlexander Motin isp_pci_rd_isr_2400(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info) 116310365e5aSMatt Jacob { 116410365e5aSMatt Jacob uint32_t r2hisr; 116510365e5aSMatt Jacob 11666a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO)); 116710365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 11686ce548a1SAlexander Motin if ((r2hisr & BIU_R2HST_INTR) == 0) { 116910365e5aSMatt Jacob *isrp = 0; 117010365e5aSMatt Jacob return (0); 117110365e5aSMatt Jacob } 11726ce548a1SAlexander Motin switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) { 11736ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_OK: 11746ce548a1SAlexander Motin case ISPR2HST_ROM_MBX_FAIL: 11756ce548a1SAlexander Motin case ISPR2HST_MBX_OK: 11766ce548a1SAlexander Motin case ISPR2HST_MBX_FAIL: 11776ce548a1SAlexander Motin case ISPR2HST_ASYNC_EVENT: 117810365e5aSMatt Jacob *semap = 1; 11796ce548a1SAlexander Motin break; 11806ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE: 11816ce548a1SAlexander Motin case ISPR2HST_RSPQ_UPDATE2: 11826ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE: 11836ce548a1SAlexander Motin case ISPR2HST_ATIO_RSPQ_UPDATE: 11846ce548a1SAlexander Motin case ISPR2HST_ATIO_UPDATE2: 118510365e5aSMatt Jacob *semap = 0; 11866ce548a1SAlexander Motin break; 118710365e5aSMatt Jacob default: 118810365e5aSMatt Jacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 118910365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 119010365e5aSMatt Jacob return (0); 119110365e5aSMatt Jacob } 11926ce548a1SAlexander Motin *info = (r2hisr >> 16); 11936ce548a1SAlexander Motin return (1); 119410365e5aSMatt Jacob } 119510365e5aSMatt Jacob 119610365e5aSMatt Jacob static uint32_t 11979cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 119865adb54cSMatt Jacob { 11996a7d12e1SMatt Jacob uint16_t rv; 1200126ec864SMatt Jacob int oldconf = 0; 120165adb54cSMatt Jacob 1202d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 120365adb54cSMatt Jacob /* 120465adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 120565adb54cSMatt Jacob */ 12066a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 1207443e752dSMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); 120837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 120965adb54cSMatt Jacob } 12106a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 1211d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12126a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 121337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 121465adb54cSMatt Jacob } 121565adb54cSMatt Jacob return (rv); 121665adb54cSMatt Jacob } 121765adb54cSMatt Jacob 121865adb54cSMatt Jacob static void 121910365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 122065adb54cSMatt Jacob { 1221126ec864SMatt Jacob int oldconf = 0; 1222d59bd469SMatt Jacob 1223d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 122465adb54cSMatt Jacob /* 122565adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 122665adb54cSMatt Jacob */ 12276a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12286a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1229126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 123037bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 123165adb54cSMatt Jacob } 12326a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 123337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 1234d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12356a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 123637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 123765adb54cSMatt Jacob } 12386a7d12e1SMatt Jacob 1239f9734398SMatt Jacob } 124065adb54cSMatt Jacob 124110365e5aSMatt Jacob static uint32_t 12429cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1243d59bd469SMatt Jacob { 124410365e5aSMatt Jacob uint32_t rv, oc = 0; 1245d59bd469SMatt Jacob 124610bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 124710365e5aSMatt Jacob uint32_t tc; 1248d59bd469SMatt Jacob /* 1249d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1250d59bd469SMatt Jacob */ 12516a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 125222e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 125322e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 125422e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 125522e1dc85SMatt Jacob else 125622e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12576a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 125837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1259d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12606a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12616a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1262126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 126337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1264d59bd469SMatt Jacob } 12656a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 126622e1dc85SMatt Jacob if (oc) { 12676a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 126837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1269d59bd469SMatt Jacob } 1270d59bd469SMatt Jacob return (rv); 1271d59bd469SMatt Jacob } 1272d59bd469SMatt Jacob 1273d59bd469SMatt Jacob static void 127410365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1275d59bd469SMatt Jacob { 1276126ec864SMatt Jacob int oc = 0; 1277d59bd469SMatt Jacob 127810bf42c2SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 127910365e5aSMatt Jacob uint32_t tc; 1280d59bd469SMatt Jacob /* 1281d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1282d59bd469SMatt Jacob */ 12836a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 128422e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 128522e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 128622e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 128722e1dc85SMatt Jacob else 128822e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12896a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 129037bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1291d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12926a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12936a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1294126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 129537bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1296d59bd469SMatt Jacob } 12976a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 129837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 129922e1dc85SMatt Jacob if (oc) { 13006a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 130137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 130210365e5aSMatt Jacob } 130310365e5aSMatt Jacob } 130410365e5aSMatt Jacob 130510365e5aSMatt Jacob static uint32_t 130610365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 130710365e5aSMatt Jacob { 130810365e5aSMatt Jacob uint32_t rv; 130910365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 131010365e5aSMatt Jacob 131110365e5aSMatt Jacob switch (block) { 131210365e5aSMatt Jacob case BIU_BLOCK: 131310365e5aSMatt Jacob break; 131410365e5aSMatt Jacob case MBOX_BLOCK: 13156a7d12e1SMatt Jacob return (BXR2(isp, IspVirt2Off(isp, regoff))); 131610365e5aSMatt Jacob case SXP_BLOCK: 131710365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); 131810365e5aSMatt Jacob return (0xffffffff); 131910365e5aSMatt Jacob case RISC_BLOCK: 132010365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); 132110365e5aSMatt Jacob return (0xffffffff); 132210365e5aSMatt Jacob case DMA_BLOCK: 132310365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); 132410365e5aSMatt Jacob return (0xffffffff); 132510365e5aSMatt Jacob default: 132610365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); 132710365e5aSMatt Jacob return (0xffffffff); 132810365e5aSMatt Jacob } 132910365e5aSMatt Jacob 133010365e5aSMatt Jacob 133110365e5aSMatt Jacob switch (regoff) { 133210365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 133310365e5aSMatt Jacob case BIU2400_FLASH_DATA: 133410365e5aSMatt Jacob case BIU2400_ICR: 133510365e5aSMatt Jacob case BIU2400_ISR: 133610365e5aSMatt Jacob case BIU2400_CSR: 133710365e5aSMatt Jacob case BIU2400_REQINP: 133810365e5aSMatt Jacob case BIU2400_REQOUTP: 133910365e5aSMatt Jacob case BIU2400_RSPINP: 134010365e5aSMatt Jacob case BIU2400_RSPOUTP: 13412df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13422df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 134310365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13442df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 134510365e5aSMatt Jacob case BIU2400_HCCR: 134610365e5aSMatt Jacob case BIU2400_GPIOD: 134710365e5aSMatt Jacob case BIU2400_GPIOE: 134810365e5aSMatt Jacob case BIU2400_HSEMA: 13496a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 135010365e5aSMatt Jacob break; 135110365e5aSMatt Jacob case BIU2400_R2HSTSLO: 13526a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 135310365e5aSMatt Jacob break; 135410365e5aSMatt Jacob case BIU2400_R2HSTSHI: 13556a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16; 135610365e5aSMatt Jacob break; 135710365e5aSMatt Jacob default: 135810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 135910365e5aSMatt Jacob "isp_pci_rd_reg_2400: unknown offset %x", regoff); 136010365e5aSMatt Jacob rv = 0xffffffff; 136110365e5aSMatt Jacob break; 136210365e5aSMatt Jacob } 136310365e5aSMatt Jacob return (rv); 136410365e5aSMatt Jacob } 136510365e5aSMatt Jacob 136610365e5aSMatt Jacob static void 136710365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 136810365e5aSMatt Jacob { 136910365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 137010365e5aSMatt Jacob 137110365e5aSMatt Jacob switch (block) { 137210365e5aSMatt Jacob case BIU_BLOCK: 137310365e5aSMatt Jacob break; 137410365e5aSMatt Jacob case MBOX_BLOCK: 13756a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 137637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 137710365e5aSMatt Jacob return; 137810365e5aSMatt Jacob case SXP_BLOCK: 137910365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); 138010365e5aSMatt Jacob return; 138110365e5aSMatt Jacob case RISC_BLOCK: 138210365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); 138310365e5aSMatt Jacob return; 138410365e5aSMatt Jacob case DMA_BLOCK: 138510365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); 138610365e5aSMatt Jacob return; 138710365e5aSMatt Jacob default: 138810365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", 138910365e5aSMatt Jacob regoff); 139010365e5aSMatt Jacob break; 139110365e5aSMatt Jacob } 139210365e5aSMatt Jacob 139310365e5aSMatt Jacob switch (regoff) { 139410365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 139510365e5aSMatt Jacob case BIU2400_FLASH_DATA: 139610365e5aSMatt Jacob case BIU2400_ICR: 139710365e5aSMatt Jacob case BIU2400_ISR: 139810365e5aSMatt Jacob case BIU2400_CSR: 139910365e5aSMatt Jacob case BIU2400_REQINP: 140010365e5aSMatt Jacob case BIU2400_REQOUTP: 140110365e5aSMatt Jacob case BIU2400_RSPINP: 140210365e5aSMatt Jacob case BIU2400_RSPOUTP: 14032df76c16SMatt Jacob case BIU2400_PRI_REQINP: 14042df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 140510365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 14062df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 140710365e5aSMatt Jacob case BIU2400_HCCR: 140810365e5aSMatt Jacob case BIU2400_GPIOD: 140910365e5aSMatt Jacob case BIU2400_GPIOE: 141010365e5aSMatt Jacob case BIU2400_HSEMA: 14116a7d12e1SMatt Jacob BXW4(isp, IspVirt2Off(isp, regoff), val); 141207d925faSAlexander Motin #ifdef MEMORYBARRIERW 141307d925faSAlexander Motin if (regoff == BIU2400_REQINP || 141407d925faSAlexander Motin regoff == BIU2400_RSPOUTP || 141507d925faSAlexander Motin regoff == BIU2400_PRI_REQINP || 141607d925faSAlexander Motin regoff == BIU2400_ATIO_RSPOUTP) 141707d925faSAlexander Motin MEMORYBARRIERW(isp, SYNC_REG, 141807d925faSAlexander Motin IspVirt2Off(isp, regoff), 4, -1) 141907d925faSAlexander Motin else 142007d925faSAlexander Motin #endif 142137bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1); 142210365e5aSMatt Jacob break; 142310365e5aSMatt Jacob default: 142410365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 142510365e5aSMatt Jacob "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); 142610365e5aSMatt Jacob break; 1427d59bd469SMatt Jacob } 1428d59bd469SMatt Jacob } 1429d59bd469SMatt Jacob 1430d720e6d5SJustin T. Gibbs 1431222bb542SMatt Jacob struct imush { 14329cd7268eSMatt Jacob ispsoftc_t *isp; 14332df76c16SMatt Jacob caddr_t vbase; 14342df76c16SMatt Jacob int chan; 1435222bb542SMatt Jacob int error; 1436222bb542SMatt Jacob }; 1437222bb542SMatt Jacob 14381923f739SMatt Jacob static void imc(void *, bus_dma_segment_t *, int, int); 14392df76c16SMatt Jacob static void imc1(void *, bus_dma_segment_t *, int, int); 14401923f739SMatt Jacob 1441d720e6d5SJustin T. Gibbs static void 14421923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1443d720e6d5SJustin T. Gibbs { 1444222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 1445387d8239SMatt Jacob isp_ecmd_t *ecmd; 14462df76c16SMatt Jacob 1447222bb542SMatt Jacob if (error) { 1448222bb542SMatt Jacob imushp->error = error; 14492df76c16SMatt Jacob return; 14502df76c16SMatt Jacob } 14512df76c16SMatt Jacob if (nseg != 1) { 14522df76c16SMatt Jacob imushp->error = EINVAL; 14532df76c16SMatt Jacob return; 14542df76c16SMatt Jacob } 14557d3cea31SMatt Jacob isp_prt(imushp->isp, ISP_LOGDEBUG0, "request/result area @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); 1456387d8239SMatt Jacob 14572df76c16SMatt Jacob imushp->isp->isp_rquest = imushp->vbase; 14582df76c16SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 14592df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 14602df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 1461387d8239SMatt Jacob 14622df76c16SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 14632df76c16SMatt Jacob imushp->isp->isp_result = imushp->vbase; 14642df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 14652df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 1466387d8239SMatt Jacob 1467a4ccb5d6SAlexander Motin if (imushp->isp->isp_type >= ISP_HA_FC_2200) { 1468387d8239SMatt Jacob imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr; 1469387d8239SMatt Jacob imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase; 1470387d8239SMatt Jacob imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free; 1471387d8239SMatt Jacob for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) { 1472387d8239SMatt Jacob if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) { 1473387d8239SMatt Jacob ecmd->next = NULL; 1474387d8239SMatt Jacob } else { 1475387d8239SMatt Jacob ecmd->next = ecmd + 1; 1476387d8239SMatt Jacob } 1477387d8239SMatt Jacob } 1478de0627d0SMatt Jacob } 1479387d8239SMatt Jacob #ifdef ISP_TARGET_MODE 1480387d8239SMatt Jacob segs->ds_addr += (N_XCMDS * XCMD_SIZE); 1481387d8239SMatt Jacob imushp->vbase += (N_XCMDS * XCMD_SIZE); 1482387d8239SMatt Jacob if (IS_24XX(imushp->isp)) { 14832df76c16SMatt Jacob imushp->isp->isp_atioq_dma = segs->ds_addr; 14842df76c16SMatt Jacob imushp->isp->isp_atioq = imushp->vbase; 14851923f739SMatt Jacob } 14862df76c16SMatt Jacob #endif 1487222bb542SMatt Jacob } 14882df76c16SMatt Jacob 14892df76c16SMatt Jacob static void 14902df76c16SMatt Jacob imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error) 14912df76c16SMatt Jacob { 14922df76c16SMatt Jacob struct imush *imushp = (struct imush *) arg; 14932df76c16SMatt Jacob if (error) { 14942df76c16SMatt Jacob imushp->error = error; 14952df76c16SMatt Jacob return; 14962df76c16SMatt Jacob } 14972df76c16SMatt Jacob if (nseg != 1) { 14982df76c16SMatt Jacob imushp->error = EINVAL; 14992df76c16SMatt Jacob return; 15002df76c16SMatt Jacob } 15017d3cea31SMatt Jacob isp_prt(imushp->isp, ISP_LOGDEBUG0, "scdma @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); 15022df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr; 15032df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase; 1504d720e6d5SJustin T. Gibbs } 1505d720e6d5SJustin T. Gibbs 1506d720e6d5SJustin T. Gibbs static int 15079cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1508d720e6d5SJustin T. Gibbs { 1509d720e6d5SJustin T. Gibbs caddr_t base; 1510662daaddSMatt Jacob uint32_t len, nsegs; 15118e1b6e7aSMatt Jacob int i, error, cmap = 0; 151253af7d22SMatt Jacob bus_size_t slim; /* segment size */ 15134b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 151451effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1515222bb542SMatt Jacob struct imush im; 1516222bb542SMatt Jacob 1517a95ae193SMatt Jacob /* 1518a95ae193SMatt Jacob * Already been here? If so, leave... 1519a95ae193SMatt Jacob */ 1520a95ae193SMatt Jacob if (isp->isp_rquest) { 1521a95ae193SMatt Jacob return (0); 1522a95ae193SMatt Jacob } 15230a70657fSMatt Jacob ISP_UNLOCK(isp); 1524a95ae193SMatt Jacob 152510365e5aSMatt Jacob if (isp->isp_maxcmds == 0) { 152610365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "maxcmds not set"); 15270a70657fSMatt Jacob ISP_LOCK(isp); 152810365e5aSMatt Jacob return (1); 152910365e5aSMatt Jacob } 153010365e5aSMatt Jacob 153153af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 15321923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 15339b434edeSMatt Jacob if (sizeof (bus_size_t) > 4) { 153453af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 15359b434edeSMatt Jacob } else { 15369b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 15379b434edeSMatt Jacob } 15381dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 15391923f739SMatt Jacob } else { 15401dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR_32BIT; 15419b434edeSMatt Jacob slim = (1UL << 24); 15421923f739SMatt Jacob } 15431923f739SMatt Jacob 15440a70657fSMatt Jacob len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 15452df76c16SMatt Jacob isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 15460a70657fSMatt Jacob if (isp->isp_osinfo.pcmd_pool == NULL) { 15470a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds"); 15480a70657fSMatt Jacob ISP_LOCK(isp); 15490a70657fSMatt Jacob return (1); 15500a70657fSMatt Jacob } 15510a70657fSMatt Jacob 1552662daaddSMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 1553662daaddSMatt Jacob nsegs = ISP_NSEG64_MAX; 1554662daaddSMatt Jacob } else { 1555662daaddSMatt Jacob nsegs = ISP_NSEG_MAX; 1556662daaddSMatt Jacob } 155709934867SMatt Jacob 1558662daaddSMatt 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)) { 15590a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 156072429e49SMatt Jacob ISP_LOCK(isp); 15610a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 15621923f739SMatt Jacob return (1); 15631923f739SMatt Jacob } 15641923f739SMatt Jacob 1565c8b8a2c4SMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1566c8b8a2c4SMatt Jacob isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1567a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 15680a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 156972429e49SMatt Jacob ISP_LOCK(isp); 15700a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 1571a95ae193SMatt Jacob return (1); 1572a95ae193SMatt Jacob } 1573c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1574c8b8a2c4SMatt Jacob isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1575c8b8a2c4SMatt Jacob } 1576c8b8a2c4SMatt Jacob isp->isp_xffree = isp->isp_xflist; 157751e23558SNate Lawson #ifdef ISP_TARGET_MODE 157832b3ec7dSMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1579c8b8a2c4SMatt Jacob isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 158051e23558SNate Lawson if (isp->isp_tgtlist == NULL) { 15810a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1582a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 158372429e49SMatt Jacob ISP_LOCK(isp); 15840a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); 1585a95ae193SMatt Jacob return (1); 1586a95ae193SMatt Jacob } 1587c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1588c8b8a2c4SMatt Jacob isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1]; 1589c8b8a2c4SMatt Jacob } 1590c8b8a2c4SMatt Jacob isp->isp_tgtfree = isp->isp_tgtlist; 15910a70657fSMatt Jacob #endif 1592a95ae193SMatt Jacob 1593d720e6d5SJustin T. Gibbs /* 15942df76c16SMatt Jacob * Allocate and map the request and result queues (and ATIO queue 1595387d8239SMatt Jacob * if we're a 2400 supporting target mode), and a region for 1596387d8239SMatt Jacob * external dma addressable command/status structures (23XX and 1597387d8239SMatt Jacob * later). 1598d720e6d5SJustin T. Gibbs */ 1599d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1600d02373f1SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 16012df76c16SMatt Jacob #ifdef ISP_TARGET_MODE 16022df76c16SMatt Jacob if (IS_24XX(isp)) { 16032df76c16SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1604d720e6d5SJustin T. Gibbs } 16052df76c16SMatt Jacob #endif 1606a4ccb5d6SAlexander Motin if (isp->isp_type >= ISP_HA_FC_2200) { 1607387d8239SMatt Jacob len += (N_XCMDS * XCMD_SIZE); 1608387d8239SMatt Jacob } 16092df76c16SMatt Jacob 161053af7d22SMatt Jacob /* 16112df76c16SMatt Jacob * Create a tag for the control spaces. We don't always need this 16122df76c16SMatt Jacob * to be 32 bits, but we do this for simplicity and speed's sake. 161353af7d22SMatt Jacob */ 16148e1b6e7aSMatt Jacob if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, slim, 0, &isp->isp_osinfo.cdmat)) { 16152df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces"); 16160a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1617a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 161851e23558SNate Lawson #ifdef ISP_TARGET_MODE 161951e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 162051e23558SNate Lawson #endif 162172429e49SMatt Jacob ISP_LOCK(isp); 1622d720e6d5SJustin T. Gibbs return (1); 1623d720e6d5SJustin T. Gibbs } 1624d720e6d5SJustin T. Gibbs 162537bb79f1SMarius Strobl if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &isp->isp_osinfo.cdmap) != 0) { 16262df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); 16272df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 16280a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1629a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 163051e23558SNate Lawson #ifdef ISP_TARGET_MODE 163151e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 163251e23558SNate Lawson #endif 163372429e49SMatt Jacob ISP_LOCK(isp); 1634222bb542SMatt Jacob return (1); 1635222bb542SMatt Jacob } 1636d720e6d5SJustin T. Gibbs 16372df76c16SMatt Jacob im.isp = isp; 16382df76c16SMatt Jacob im.chan = 0; 16392df76c16SMatt Jacob im.vbase = base; 16402df76c16SMatt Jacob im.error = 0; 16412df76c16SMatt Jacob 16422df76c16SMatt Jacob bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0); 16432df76c16SMatt Jacob if (im.error) { 16442df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error); 16452df76c16SMatt Jacob goto bad; 16462df76c16SMatt Jacob } 16472df76c16SMatt Jacob 16482df76c16SMatt Jacob if (IS_FC(isp)) { 16492df76c16SMatt Jacob for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 16502df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16512df76c16SMatt Jacob if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, ISP_FC_SCRLEN, 1, slim, 0, &fc->tdmat)) { 16522df76c16SMatt Jacob goto bad; 16532df76c16SMatt Jacob } 165437bb79f1SMarius Strobl if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &fc->tdmap) != 0) { 16552df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16562df76c16SMatt Jacob goto bad; 16572df76c16SMatt Jacob } 16582df76c16SMatt Jacob im.isp = isp; 16592df76c16SMatt Jacob im.chan = cmap; 16602df76c16SMatt Jacob im.vbase = base; 16612df76c16SMatt Jacob im.error = 0; 16622df76c16SMatt Jacob bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0); 16632df76c16SMatt Jacob if (im.error) { 16642df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 16652df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16662df76c16SMatt Jacob goto bad; 16672df76c16SMatt Jacob } 1668a4ccb5d6SAlexander Motin if (!IS_2100(isp)) { 1669387d8239SMatt Jacob for (i = 0; i < INITIAL_NEXUS_COUNT; i++) { 1670387d8239SMatt Jacob struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO); 1671387d8239SMatt Jacob if (n == NULL) { 1672387d8239SMatt Jacob while (fc->nexus_free_list) { 1673387d8239SMatt Jacob n = fc->nexus_free_list; 1674387d8239SMatt Jacob fc->nexus_free_list = n->next; 1675387d8239SMatt Jacob free(n, M_DEVBUF); 1676387d8239SMatt Jacob } 1677387d8239SMatt Jacob goto bad; 1678387d8239SMatt Jacob } 1679387d8239SMatt Jacob n->next = fc->nexus_free_list; 1680387d8239SMatt Jacob fc->nexus_free_list = n; 1681387d8239SMatt Jacob } 16822df76c16SMatt Jacob } 16832df76c16SMatt Jacob } 1684405b7a29SMatt Jacob } 16852df76c16SMatt Jacob 1686a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 16870a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 16880a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1689d720e6d5SJustin T. Gibbs if (error) { 16902df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 16911923f739SMatt Jacob while (--i >= 0) { 16922df76c16SMatt Jacob bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap); 16931923f739SMatt Jacob } 16941923f739SMatt Jacob goto bad; 1695d720e6d5SJustin T. Gibbs } 16962df76c16SMatt Jacob callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); 16970a70657fSMatt Jacob if (i == isp->isp_maxcmds-1) { 16980a70657fSMatt Jacob pcmd->next = NULL; 16990a70657fSMatt Jacob } else { 17000a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1701d720e6d5SJustin T. Gibbs } 17020a70657fSMatt Jacob } 17030a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 170472429e49SMatt Jacob ISP_LOCK(isp); 1705d720e6d5SJustin T. Gibbs return (0); 17061923f739SMatt Jacob 17071923f739SMatt Jacob bad: 17082df76c16SMatt Jacob while (--cmap >= 0) { 17092df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 1710aced5239SJohn Baldwin bus_dmamap_unload(fc->tdmat, fc->tdmap); 17112df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 17122df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 1713387d8239SMatt Jacob while (fc->nexus_free_list) { 1714387d8239SMatt Jacob struct isp_nexus *n = fc->nexus_free_list; 1715387d8239SMatt Jacob fc->nexus_free_list = n->next; 1716387d8239SMatt Jacob free(n, M_DEVBUF); 1717387d8239SMatt Jacob } 17182df76c16SMatt Jacob } 1719aced5239SJohn Baldwin if (isp->isp_rquest_dma != 0) 1720aced5239SJohn Baldwin bus_dmamap_unload(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap); 17212df76c16SMatt Jacob bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); 17222df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 17231923f739SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 172451e23558SNate Lawson #ifdef ISP_TARGET_MODE 172551e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 172651e23558SNate Lawson #endif 17270a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 17281923f739SMatt Jacob isp->isp_rquest = NULL; 17290a70657fSMatt Jacob ISP_LOCK(isp); 17301923f739SMatt Jacob return (1); 1731d720e6d5SJustin T. Gibbs } 1732d720e6d5SJustin T. Gibbs 1733d720e6d5SJustin T. Gibbs typedef struct { 17349cd7268eSMatt Jacob ispsoftc_t *isp; 17359e11e5beSMatt Jacob void *cmd_token; 17362df76c16SMatt Jacob void *rq; /* original request */ 17371dae40ebSMatt Jacob int error; 17382df76c16SMatt Jacob bus_size_t mapsize; 1739d720e6d5SJustin T. Gibbs } mush_t; 1740d720e6d5SJustin T. Gibbs 17414873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 17424873663cSMatt Jacob 17439e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 17442df76c16SMatt Jacob static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 17452df76c16SMatt Jacob static void tdma2(void *, bus_dma_segment_t *, int, int); 17469e11e5beSMatt Jacob 1747d720e6d5SJustin T. Gibbs static void 17482df76c16SMatt Jacob tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 1749d720e6d5SJustin T. Gibbs { 1750d720e6d5SJustin T. Gibbs mush_t *mp; 17512df76c16SMatt Jacob mp = (mush_t *)arg; 17522df76c16SMatt Jacob mp->mapsize = mapsize; 17532df76c16SMatt Jacob tdma2(arg, dm_segs, nseg, error); 17542df76c16SMatt Jacob } 17552df76c16SMatt Jacob 17562df76c16SMatt Jacob static void 17572df76c16SMatt Jacob tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 17582df76c16SMatt Jacob { 17592df76c16SMatt Jacob mush_t *mp; 17609cd7268eSMatt Jacob ispsoftc_t *isp; 17612df76c16SMatt Jacob struct ccb_scsiio *csio; 17622df76c16SMatt Jacob isp_ddir_t ddir; 17632df76c16SMatt Jacob ispreq_t *rq; 1764d720e6d5SJustin T. Gibbs 1765d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1766d720e6d5SJustin T. Gibbs if (error) { 1767d720e6d5SJustin T. Gibbs mp->error = error; 1768d720e6d5SJustin T. Gibbs return; 1769d720e6d5SJustin T. Gibbs } 17709e11e5beSMatt Jacob csio = mp->cmd_token; 17714fd13c1bSMatt Jacob isp = mp->isp; 17722df76c16SMatt Jacob rq = mp->rq; 17732df76c16SMatt Jacob if (nseg) { 1774387d8239SMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 17752df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 17762df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 17772df76c16SMatt Jacob mp->error = EFAULT; 17789e11e5beSMatt Jacob return; 17799e11e5beSMatt Jacob } 17802df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) { 17812df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_CTIO3; 17822df76c16SMatt Jacob } 178309934867SMatt Jacob } else { 17842df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 17852df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 17862df76c16SMatt Jacob mp->error = EFAULT; 17872df76c16SMatt Jacob return; 178809934867SMatt Jacob } 17892df76c16SMatt Jacob } 17902df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 17912df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 17922df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 17932df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 17942df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 17952df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 179609934867SMatt Jacob } else { 1797a035b0afSMatt Jacob dm_segs = NULL; 1798a035b0afSMatt Jacob nseg = 0; 17992df76c16SMatt Jacob ddir = ISP_NOXFR; 180009934867SMatt Jacob } 18012df76c16SMatt Jacob } else { 18022df76c16SMatt Jacob dm_segs = NULL; 18032df76c16SMatt Jacob nseg = 0; 18042df76c16SMatt Jacob ddir = ISP_NOXFR; 1805fc087171SMatt Jacob } 180665b024e1SMatt Jacob 1807387d8239SMatt Jacob error = isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len); 1808387d8239SMatt Jacob switch (error) { 1809387d8239SMatt Jacob case CMD_EAGAIN: 18102df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1811387d8239SMatt Jacob case CMD_QUEUED: 1812387d8239SMatt Jacob break; 1813387d8239SMatt Jacob default: 1814387d8239SMatt Jacob mp->error = EIO; 181510365e5aSMatt Jacob } 18169e11e5beSMatt Jacob } 18179e11e5beSMatt Jacob #endif 18189e11e5beSMatt Jacob 18192df76c16SMatt Jacob static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 1820126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 18219e11e5beSMatt Jacob 18226de9bf77SMatt Jacob static void 18232df76c16SMatt Jacob dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 182410365e5aSMatt Jacob { 182510365e5aSMatt Jacob mush_t *mp; 182610365e5aSMatt Jacob mp = (mush_t *)arg; 18272df76c16SMatt Jacob mp->mapsize = mapsize; 18282df76c16SMatt Jacob dma2(arg, dm_segs, nseg, error); 18296de9bf77SMatt Jacob } 18301dae40ebSMatt Jacob 18319e11e5beSMatt Jacob static void 18329e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 18339e11e5beSMatt Jacob { 18349e11e5beSMatt Jacob mush_t *mp; 18359cd7268eSMatt Jacob ispsoftc_t *isp; 18369e11e5beSMatt Jacob struct ccb_scsiio *csio; 18372df76c16SMatt Jacob isp_ddir_t ddir; 18389e11e5beSMatt Jacob ispreq_t *rq; 18399e11e5beSMatt Jacob 18409e11e5beSMatt Jacob mp = (mush_t *) arg; 18419e11e5beSMatt Jacob if (error) { 18429e11e5beSMatt Jacob mp->error = error; 18439e11e5beSMatt Jacob return; 18449e11e5beSMatt Jacob } 18459e11e5beSMatt Jacob csio = mp->cmd_token; 18464fd13c1bSMatt Jacob isp = mp->isp; 18479e11e5beSMatt Jacob rq = mp->rq; 18482df76c16SMatt Jacob if (nseg) { 1849387d8239SMatt Jacob if (isp->isp_osinfo.sixtyfourbit) { 18502df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 18512df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 18522df76c16SMatt Jacob mp->error = EFAULT; 1853d720e6d5SJustin T. Gibbs return; 1854d720e6d5SJustin T. Gibbs } 18552df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) { 18562df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; 18572df76c16SMatt Jacob } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) { 18582df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_A64; 1859d720e6d5SJustin T. Gibbs } 18602df76c16SMatt Jacob } else { 18612df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 18622df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 18632df76c16SMatt Jacob mp->error = EFAULT; 18642df76c16SMatt Jacob return; 186510365e5aSMatt Jacob } 1866d720e6d5SJustin T. Gibbs } 18672df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 18682df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 18692df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 18702df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 18712df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 18722df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 18732df76c16SMatt Jacob } else { 18742df76c16SMatt Jacob ddir = ISP_NOXFR; 18752df76c16SMatt Jacob } 18762df76c16SMatt Jacob } else { 18772df76c16SMatt Jacob dm_segs = NULL; 18782df76c16SMatt Jacob nseg = 0; 18792df76c16SMatt Jacob ddir = ISP_NOXFR; 1880d720e6d5SJustin T. Gibbs } 1881d720e6d5SJustin T. Gibbs 1882387d8239SMatt Jacob error = isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, (ispds64_t *)csio->req_map); 1883387d8239SMatt Jacob switch (error) { 1884387d8239SMatt Jacob case CMD_EAGAIN: 18852df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1886387d8239SMatt Jacob break; 1887387d8239SMatt Jacob case CMD_QUEUED: 1888387d8239SMatt Jacob break; 1889387d8239SMatt Jacob default: 1890387d8239SMatt Jacob mp->error = EIO; 1891387d8239SMatt Jacob break; 18922df76c16SMatt Jacob } 18932df76c16SMatt Jacob } 18942df76c16SMatt Jacob 1895d720e6d5SJustin T. Gibbs static int 18962df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 1897d720e6d5SJustin T. Gibbs { 1898d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1899126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 19002df76c16SMatt Jacob void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int); 1901dd0b4fb6SKonstantin Belousov int error; 1902d720e6d5SJustin T. Gibbs 19032df76c16SMatt Jacob mp = &mush; 19042df76c16SMatt Jacob mp->isp = isp; 19052df76c16SMatt Jacob mp->cmd_token = csio; 19062df76c16SMatt Jacob mp->rq = ff; 19072df76c16SMatt Jacob mp->error = 0; 19082df76c16SMatt Jacob mp->mapsize = 0; 19092df76c16SMatt Jacob 191065b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 191165b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 19122df76c16SMatt Jacob eptr = tdma2; 19132df76c16SMatt Jacob eptr2 = tdma2_2; 191465b024e1SMatt Jacob } else 191565b024e1SMatt Jacob #endif 19162df76c16SMatt Jacob { 191765b024e1SMatt Jacob eptr = dma2; 19182df76c16SMatt Jacob eptr2 = dma2_2; 19191dae40ebSMatt Jacob } 192065b024e1SMatt Jacob 19214fd13c1bSMatt Jacob 1922dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, 1923dd0b4fb6SKonstantin Belousov (union ccb *)csio, eptr, mp, 0); 1924d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 19252df76c16SMatt Jacob bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 1926d720e6d5SJustin T. Gibbs mp->error = EINVAL; 19272df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); 1928d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 19290a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 19302df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 19310a5f7e8bSMatt Jacob #endif 1932d720e6d5SJustin T. Gibbs mp->error = error; 1933d720e6d5SJustin T. Gibbs } 1934d720e6d5SJustin T. Gibbs if (mp->error) { 19354873663cSMatt Jacob int retval = CMD_COMPLETE; 19364873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 19374873663cSMatt Jacob retval = CMD_EAGAIN; 19384873663cSMatt Jacob } else if (mp->error == EFBIG) { 1939387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_TOO_BIG; 1940d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 1941387d8239SMatt Jacob csio->ccb_h.status = CAM_REQ_INVALID; 1942d720e6d5SJustin T. Gibbs } else { 1943387d8239SMatt Jacob csio->ccb_h.status = CAM_UNREC_HBA_ERROR; 1944d720e6d5SJustin T. Gibbs } 19454873663cSMatt Jacob return (retval); 19460a5f7e8bSMatt Jacob } 19474873663cSMatt Jacob return (CMD_QUEUED); 1948d720e6d5SJustin T. Gibbs } 1949d720e6d5SJustin T. Gibbs 1950d720e6d5SJustin T. Gibbs static void 19513bda7a83SMatt Jacob isp_pci_reset0(ispsoftc_t *isp) 19523bda7a83SMatt Jacob { 19533bda7a83SMatt Jacob ISP_DISABLE_INTS(isp); 19543bda7a83SMatt Jacob } 19553bda7a83SMatt Jacob 19563bda7a83SMatt Jacob static void 19579cd7268eSMatt Jacob isp_pci_reset1(ispsoftc_t *isp) 195865adb54cSMatt Jacob { 195910365e5aSMatt Jacob if (!IS_24XX(isp)) { 196065adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 196165adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 196210365e5aSMatt Jacob } 1963469b6b9eSMatt Jacob /* and enable interrupts */ 196410365e5aSMatt Jacob ISP_ENABLE_INTS(isp); 196565adb54cSMatt Jacob } 196665adb54cSMatt Jacob 196765adb54cSMatt Jacob static void 19689cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg) 196965adb54cSMatt Jacob { 19701923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 1971d02373f1SMatt Jacob if (msg) 19726e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 19736e5c5328SMatt Jacob else 19746e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 1975d02373f1SMatt Jacob if (IS_SCSI(isp)) 1976d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 1977d02373f1SMatt Jacob else 1978d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 1979d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 1980d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 1981d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 1982d02373f1SMatt Jacob 1983d02373f1SMatt Jacob 1984d02373f1SMatt Jacob if (IS_SCSI(isp)) { 1985d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 1986d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 1987d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 1988d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 1989d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 1990d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 1991d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 1992d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 1993d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 1994d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 1995d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 1996d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 1997d02373f1SMatt Jacob } 1998d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 1999d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 2000d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 2001d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 2002d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 20031923f739SMatt Jacob pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1)); 200465adb54cSMatt Jacob } 2005