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); 622df76c16SMatt Jacob static int isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); 632df76c16SMatt Jacob static int isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); 642df76c16SMatt Jacob static int isp_pci_rd_isr_2400(ispsoftc_t *, uint32_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 17565adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 17665adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 17765adb54cSMatt Jacob #endif 17865adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 17965adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 18065adb54cSMatt Jacob #endif 181d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 182d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 183d951bbcaSMatt Jacob #endif 184d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 185d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 186d951bbcaSMatt Jacob #endif 1878a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 1888a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 1898a97c03aSMatt Jacob #endif 190d951bbcaSMatt Jacob 191d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 192d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 193d951bbcaSMatt Jacob #endif 194d951bbcaSMatt Jacob 195d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 196d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 197d951bbcaSMatt Jacob #endif 198d951bbcaSMatt Jacob 199d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 200d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 201d951bbcaSMatt Jacob #endif 202d951bbcaSMatt Jacob 203ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 204ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 205ab6d0040SMatt Jacob #endif 206ab6d0040SMatt Jacob 20765adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 20865adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 20965adb54cSMatt Jacob #endif 21065adb54cSMatt Jacob 21165adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 21265adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 21365adb54cSMatt Jacob #endif 21465adb54cSMatt Jacob 215d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 216d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 217d59bd469SMatt Jacob #endif 218d59bd469SMatt Jacob 219f556e83bSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP10160 220f556e83bSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 221f556e83bSMatt Jacob #endif 222f556e83bSMatt Jacob 223960f6939SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP12160 224960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 225960f6939SMatt Jacob #endif 226960f6939SMatt Jacob 227d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 228d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 229d59bd469SMatt Jacob #endif 23065adb54cSMatt Jacob 23122e1dc85SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1280 23222e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 23322e1dc85SMatt Jacob #endif 23422e1dc85SMatt Jacob 23565adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 23665adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 23765adb54cSMatt Jacob #endif 23865adb54cSMatt Jacob 239222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 240222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 241222bb542SMatt Jacob #endif 242222bb542SMatt Jacob 243126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2300 244126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 245126ec864SMatt Jacob #endif 246126ec864SMatt Jacob 247126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2312 248126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 249126ec864SMatt Jacob #endif 250126ec864SMatt Jacob 251e5265237SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2322 252e5265237SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 253e5265237SMatt Jacob #endif 254e5265237SMatt Jacob 2558872e3d7SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2422 2568872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 2578872e3d7SMatt Jacob #endif 2588872e3d7SMatt Jacob 25941675df0SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2432 26041675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 26141675df0SMatt Jacob #endif 26241675df0SMatt Jacob 2632df76c16SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2532 2642df76c16SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2532 0x2532 2652df76c16SMatt Jacob #endif 2662df76c16SMatt Jacob 267dd1419abSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6312 268dd1419abSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 269dd1419abSMatt Jacob #endif 270dd1419abSMatt Jacob 2719a5af410SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6322 2729a5af410SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 2739a5af410SMatt Jacob #endif 2749a5af410SMatt Jacob 275a959d921SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP5432 276a959d921SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP5432 0x5432 277a959d921SMatt Jacob #endif 278a959d921SMatt Jacob 279a959d921SMatt Jacob #define PCI_QLOGIC_ISP5432 \ 280a959d921SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC) 2819a5af410SMatt Jacob 28256aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 28356aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 284d59bd469SMatt Jacob 285d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 286d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 287d59bd469SMatt Jacob 288f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 289f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 290f556e83bSMatt Jacob 291960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 292960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 293960f6939SMatt Jacob 294d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 295d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 296d59bd469SMatt Jacob 29722e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 29822e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 29922e1dc85SMatt Jacob 30065adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 30165adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 30265adb54cSMatt Jacob 303222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 304222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 305222bb542SMatt Jacob 306126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 307126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 308126ec864SMatt Jacob 309126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 310126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 311126ec864SMatt Jacob 312e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 313e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 314e5265237SMatt Jacob 3156c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 3166c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 3176c426685SMatt Jacob 31841675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 31941675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 32041675df0SMatt Jacob 3212df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 3222df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 3232df76c16SMatt Jacob 324dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 325dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 326dd1419abSMatt Jacob 3279a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 3289a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 3299a5af410SMatt Jacob 330e11a1ee8SMatt Jacob /* 331e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 332e11a1ee8SMatt Jacob */ 333e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 334e11a1ee8SMatt Jacob 33565adb54cSMatt Jacob #define IO_MAP_REG 0x10 33665adb54cSMatt Jacob #define MEM_MAP_REG 0x14 33765adb54cSMatt Jacob 338d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 339d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 34065adb54cSMatt Jacob 341960f6939SMatt Jacob static int isp_pci_probe (device_t); 342960f6939SMatt Jacob static int isp_pci_attach (device_t); 34310365e5aSMatt Jacob static int isp_pci_detach (device_t); 34465adb54cSMatt Jacob 3451923f739SMatt Jacob 3460230a28bSMatt Jacob #define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev 34765adb54cSMatt Jacob struct isp_pcisoftc { 3489cd7268eSMatt Jacob ispsoftc_t pci_isp; 349960f6939SMatt Jacob device_t pci_dev; 350e95725cbSMatt Jacob struct resource * regs; 351e95725cbSMatt Jacob void * irq; 352e95725cbSMatt Jacob int iqd; 353e95725cbSMatt Jacob int rtp; 354e95725cbSMatt Jacob int rgd; 355960f6939SMatt Jacob void * ih; 356d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3571923f739SMatt Jacob bus_dma_tag_t dmat; 3580a70657fSMatt Jacob int msicount; 35965adb54cSMatt Jacob }; 36065adb54cSMatt Jacob 36110365e5aSMatt Jacob 362960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 363960f6939SMatt Jacob /* Device interface */ 364960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 365960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 36610365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 367960f6939SMatt Jacob { 0, 0 } 36865adb54cSMatt Jacob }; 36965adb54cSMatt Jacob 370960f6939SMatt Jacob static driver_t isp_pci_driver = { 371960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 372960f6939SMatt Jacob }; 373960f6939SMatt Jacob static devclass_t isp_devclass; 374960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 375d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1); 376d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1); 377*9e7d423dSMatt Jacob static int isp_nvports = 0; 37865adb54cSMatt Jacob 379960f6939SMatt Jacob static int 380960f6939SMatt Jacob isp_pci_probe(device_t dev) 38165adb54cSMatt Jacob { 382960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 38356aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 384960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 38565adb54cSMatt Jacob break; 386d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 387960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 388c6608df3SMatt Jacob break; 389c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 390960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 391d59bd469SMatt Jacob break; 39222e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 393960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 394960f6939SMatt Jacob break; 395f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 396f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 397f556e83bSMatt Jacob break; 398960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 399e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 400e11a1ee8SMatt Jacob return (ENXIO); 401e11a1ee8SMatt Jacob } 402960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 40322e1dc85SMatt Jacob break; 40465adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 405960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 40665adb54cSMatt Jacob break; 4075542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 408960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 4095542fe4bSMatt Jacob break; 410126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 411126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 412126ec864SMatt Jacob break; 413126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 414126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 415126ec864SMatt Jacob break; 416e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 417e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 418e5265237SMatt Jacob break; 4198872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 4208872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 4218872e3d7SMatt Jacob break; 42241675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 42341675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 42441675df0SMatt Jacob break; 4252df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 4262df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 4272df76c16SMatt Jacob break; 428a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 429a959d921SMatt Jacob device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter"); 430a959d921SMatt Jacob break; 431dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 432dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 433dd1419abSMatt Jacob break; 4349a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4359a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4369a5af410SMatt Jacob break; 43765adb54cSMatt Jacob default: 438960f6939SMatt Jacob return (ENXIO); 43965adb54cSMatt Jacob } 44073030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 441d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 442a95ae193SMatt Jacob "Core Version %d.%d\n", 443d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 444d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 44573030e03SMatt Jacob isp_announced++; 44665adb54cSMatt Jacob } 44756aef503SMatt Jacob /* 44856aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 44956aef503SMatt Jacob * XXXX: (or increase a reference count to it). 45056aef503SMatt Jacob */ 451b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 45265adb54cSMatt Jacob } 45365adb54cSMatt Jacob 4549cd7268eSMatt Jacob static void 455*9e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 4569cd7268eSMatt Jacob { 4579cd7268eSMatt Jacob int tval; 458f7c631bcSMatt Jacob 459222bb542SMatt Jacob /* 4609ba86737SMatt Jacob * Figure out if we're supposed to skip this one. 4619ba86737SMatt Jacob */ 4626e5c5328SMatt Jacob tval = 0; 4632df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "disable", &tval) == 0 && tval) { 4649cd7268eSMatt Jacob device_printf(dev, "disabled at user request\n"); 4659cd7268eSMatt Jacob isp->isp_osinfo.disabled = 1; 4669cd7268eSMatt Jacob return; 467b9b599feSMatt Jacob } 4686e5c5328SMatt Jacob 4699cd7268eSMatt Jacob tval = 0; 4702df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 4719cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4729cd7268eSMatt Jacob } 4739cd7268eSMatt Jacob tval = 0; 4742df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 4759cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 4769cd7268eSMatt Jacob } 477336b5612SMatt Jacob tval = 0; 4782df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 479336b5612SMatt Jacob if (tval) { 480336b5612SMatt Jacob isp->isp_dblev = tval; 481336b5612SMatt Jacob } else { 482336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 483336b5612SMatt Jacob } 484336b5612SMatt Jacob if (bootverbose) { 485336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 486336b5612SMatt Jacob } 487*9e7d423dSMatt Jacob tval = -1; 4882df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 4892df76c16SMatt Jacob if (tval > 0 && tval < 127) { 490*9e7d423dSMatt Jacob isp_nvports = tval; 4912df76c16SMatt Jacob } 4922df76c16SMatt Jacob tval = 1; 4932df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "autoconfig", &tval); 4942df76c16SMatt Jacob isp_autoconfig = tval; 4952df76c16SMatt Jacob tval = 7; 4962df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 4972df76c16SMatt Jacob isp_quickboot_time = tval; 498336b5612SMatt Jacob } 499336b5612SMatt Jacob 500336b5612SMatt Jacob static void 501336b5612SMatt Jacob isp_get_pci_options(device_t dev, int *m1, int *m2) 502336b5612SMatt Jacob { 503336b5612SMatt Jacob int tval; 504336b5612SMatt Jacob /* 505336b5612SMatt Jacob * Which we should try first - memory mapping or i/o mapping? 506336b5612SMatt Jacob * 507336b5612SMatt Jacob * We used to try memory first followed by i/o on alpha, otherwise 508336b5612SMatt Jacob * the reverse, but we should just try memory first all the time now. 509336b5612SMatt Jacob */ 510336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 511336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 512336b5612SMatt Jacob 513336b5612SMatt Jacob tval = 0; 5142df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_iomap", &tval) == 0 && tval != 0) { 515336b5612SMatt Jacob *m1 = PCIM_CMD_PORTEN; 516336b5612SMatt Jacob *m2 = PCIM_CMD_MEMEN; 517336b5612SMatt Jacob } 518336b5612SMatt Jacob tval = 0; 5192df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_memmap", &tval) == 0 && tval != 0) { 520336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 521336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 522336b5612SMatt Jacob } 523336b5612SMatt Jacob } 524336b5612SMatt Jacob 525336b5612SMatt Jacob static void 5262df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 527336b5612SMatt Jacob { 528336b5612SMatt Jacob const char *sptr; 529*9e7d423dSMatt Jacob int tval = 0; 530336b5612SMatt Jacob 5312df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "iid", &tval)) { 5322df76c16SMatt Jacob if (IS_FC(isp)) { 5332df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 5342df76c16SMatt Jacob } else { 53517bc427dSMarius Strobl #ifdef __sparc64__ 53617bc427dSMarius Strobl ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev); 53717bc427dSMarius Strobl #else 5382df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = 7; 53917bc427dSMarius Strobl #endif 5402df76c16SMatt Jacob } 5412df76c16SMatt Jacob } else { 5422df76c16SMatt Jacob if (IS_FC(isp)) { 5432df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 5442df76c16SMatt Jacob } else { 5452df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = tval; 5462df76c16SMatt Jacob } 547336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 548336b5612SMatt Jacob } 5492df76c16SMatt Jacob 5502df76c16SMatt Jacob tval = -1; 5512df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "role", &tval) == 0) { 5522df76c16SMatt Jacob switch (tval) { 5532df76c16SMatt Jacob case ISP_ROLE_NONE: 5542df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 5552df76c16SMatt Jacob case ISP_ROLE_TARGET: 5562df76c16SMatt Jacob case ISP_ROLE_INITIATOR|ISP_ROLE_TARGET: 5572df76c16SMatt Jacob device_printf(dev, "setting role to 0x%x\n", tval); 5582df76c16SMatt Jacob break; 5592df76c16SMatt Jacob default: 5602df76c16SMatt Jacob tval = -1; 5612df76c16SMatt Jacob break; 562336b5612SMatt Jacob } 563336b5612SMatt Jacob } 5642df76c16SMatt Jacob if (tval == -1) { 5652df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 5662df76c16SMatt Jacob } 567336b5612SMatt Jacob 568336b5612SMatt Jacob if (IS_SCSI(isp)) { 5694ecb1d4aSMatt Jacob ISP_SPI_PC(isp, chan)->def_role = tval; 570336b5612SMatt Jacob return; 571336b5612SMatt Jacob } 5724ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 573336b5612SMatt Jacob 5749cd7268eSMatt Jacob tval = 0; 5752df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fullduplex", &tval) == 0 && tval != 0) { 5769cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5779cd7268eSMatt Jacob } 5789cd7268eSMatt Jacob sptr = 0; 5792df76c16SMatt Jacob if (resource_string_value(device_get_name(dev), device_get_unit(dev), "topology", (const char **) &sptr) == 0 && sptr != 0) { 5809cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 5819cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 5829cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 5839cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5849cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 5859cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 5869cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 5879cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 5889cd7268eSMatt Jacob } 589960f6939SMatt Jacob } 590960f6939SMatt Jacob 5919ba86737SMatt Jacob /* 5929cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 5939cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 5949cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 5959cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 5969cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 5979cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 5989cd7268eSMatt Jacob */ 5999cd7268eSMatt Jacob sptr = 0; 6002df76c16SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "portwwn", (const char **) &sptr); 6019cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6029cd7268eSMatt Jacob char *eptr = 0; 6032df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 6042df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 6059cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 6062df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 6079cd7268eSMatt Jacob } 6089cd7268eSMatt Jacob } 6099cd7268eSMatt Jacob 6109cd7268eSMatt Jacob sptr = 0; 6112df76c16SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "nodewwn", (const char **) &sptr); 6129cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6139cd7268eSMatt Jacob char *eptr = 0; 6142df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 6152df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 6169cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6172df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 6189cd7268eSMatt Jacob } 6199cd7268eSMatt Jacob } 6209cd7268eSMatt Jacob 62110365e5aSMatt Jacob tval = 0; 6222df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "hysteresis", &tval); 62310365e5aSMatt Jacob if (tval >= 0 && tval < 256) { 6242df76c16SMatt Jacob ISP_FC_PC(isp, chan)->hysteresis = tval; 62510365e5aSMatt Jacob } else { 6262df76c16SMatt Jacob ISP_FC_PC(isp, chan)->hysteresis = isp_fabric_hysteresis; 62710365e5aSMatt Jacob } 62810365e5aSMatt Jacob 629f7c631bcSMatt Jacob tval = -1; 6302df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "loop_down_limit", &tval); 63110365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6322df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 63310365e5aSMatt Jacob } else { 6342df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 63510365e5aSMatt Jacob } 63610365e5aSMatt Jacob 637f7c631bcSMatt Jacob tval = -1; 6382df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "gone_device_time", &tval); 639f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6402df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 641f7c631bcSMatt Jacob } else { 6422df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 643f7c631bcSMatt Jacob } 6449cd7268eSMatt Jacob } 6459cd7268eSMatt Jacob 6469cd7268eSMatt Jacob static int 6479cd7268eSMatt Jacob isp_pci_attach(device_t dev) 6489cd7268eSMatt Jacob { 649e95725cbSMatt Jacob int i, m1, m2, locksetup = 0; 6502df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 6519cd7268eSMatt Jacob struct isp_pcisoftc *pcs; 652a035b0afSMatt Jacob ispsoftc_t *isp; 6532df76c16SMatt Jacob size_t psize, xsize; 6542df76c16SMatt Jacob char fwname[32]; 6559cd7268eSMatt Jacob 6569cd7268eSMatt Jacob pcs = device_get_softc(dev); 6579cd7268eSMatt Jacob if (pcs == NULL) { 6589cd7268eSMatt Jacob device_printf(dev, "cannot get softc\n"); 6599cd7268eSMatt Jacob return (ENOMEM); 6609cd7268eSMatt Jacob } 6619cd7268eSMatt Jacob memset(pcs, 0, sizeof (*pcs)); 6622df76c16SMatt Jacob 6639cd7268eSMatt Jacob pcs->pci_dev = dev; 6649cd7268eSMatt Jacob isp = &pcs->pci_isp; 6652df76c16SMatt Jacob isp->isp_dev = dev; 6662df76c16SMatt Jacob isp->isp_nchan = 1; 6679cd7268eSMatt Jacob 6689cd7268eSMatt Jacob /* 669336b5612SMatt Jacob * Get Generic Options 6709cd7268eSMatt Jacob */ 671*9e7d423dSMatt Jacob isp_nvports = 0; 672*9e7d423dSMatt Jacob isp_get_generic_options(dev, isp); 6739cd7268eSMatt Jacob 6749cd7268eSMatt Jacob /* 6759cd7268eSMatt Jacob * Check to see if options have us disabled 6769cd7268eSMatt Jacob */ 6779cd7268eSMatt Jacob if (isp->isp_osinfo.disabled) { 6789cd7268eSMatt Jacob /* 6799cd7268eSMatt Jacob * But return zero to preserve unit numbering 6809cd7268eSMatt Jacob */ 6819cd7268eSMatt Jacob return (0); 6829cd7268eSMatt Jacob } 6839cd7268eSMatt Jacob 6849cd7268eSMatt Jacob /* 6859cd7268eSMatt Jacob * Get PCI options- which in this case are just mapping preferences. 6869cd7268eSMatt Jacob */ 6879cd7268eSMatt Jacob isp_get_pci_options(dev, &m1, &m2); 6889cd7268eSMatt Jacob 689ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 690e95725cbSMatt Jacob pcs->irq = pcs->regs = NULL; 691e95725cbSMatt Jacob pcs->rgd = pcs->rtp = pcs->iqd = 0; 692960f6939SMatt Jacob 693b49c4674SMatt Jacob cmd = pci_read_config(dev, PCIR_COMMAND, 2); 694960f6939SMatt Jacob if (cmd & m1) { 695e95725cbSMatt Jacob pcs->rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 696e95725cbSMatt Jacob pcs->rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 697e95725cbSMatt Jacob pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE); 69865adb54cSMatt Jacob } 699e95725cbSMatt Jacob if (pcs->regs == NULL && (cmd & m2)) { 700e95725cbSMatt Jacob pcs->rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 701e95725cbSMatt Jacob pcs->rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 702e95725cbSMatt Jacob pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE); 70365adb54cSMatt Jacob } 704e95725cbSMatt Jacob if (pcs->regs == NULL) { 705960f6939SMatt Jacob device_printf(dev, "unable to map any ports\n"); 706960f6939SMatt Jacob goto bad; 70765adb54cSMatt Jacob } 7089cd7268eSMatt Jacob if (bootverbose) { 709e95725cbSMatt Jacob device_printf(dev, "using %s space register mapping\n", (pcs->rgd == IO_MAP_REG)? "I/O" : "Memory"); 7109cd7268eSMatt Jacob } 711e95725cbSMatt Jacob isp->isp_bus_tag = rman_get_bustag(pcs->regs); 712e95725cbSMatt Jacob isp->isp_bus_handle = rman_get_bushandle(pcs->regs); 71365adb54cSMatt Jacob 7142df76c16SMatt Jacob pcs->pci_dev = dev; 715d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 716d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 717d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 718d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 719d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 7202df76c16SMatt Jacob 7212df76c16SMatt Jacob switch (pci_get_devid(dev)) { 7222df76c16SMatt Jacob case PCI_QLOGIC_ISP1020: 7232df76c16SMatt Jacob did = 0x1040; 7242df76c16SMatt Jacob isp->isp_mdvec = &mdvec; 7252df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 7262df76c16SMatt Jacob break; 7272df76c16SMatt Jacob case PCI_QLOGIC_ISP1080: 7282df76c16SMatt Jacob did = 0x1080; 7292df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7302df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 7312df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7322df76c16SMatt Jacob break; 7332df76c16SMatt Jacob case PCI_QLOGIC_ISP1240: 7342df76c16SMatt Jacob did = 0x1080; 7352df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7362df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1240; 7372df76c16SMatt Jacob isp->isp_nchan = 2; 7382df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7392df76c16SMatt Jacob break; 7402df76c16SMatt Jacob case PCI_QLOGIC_ISP1280: 7412df76c16SMatt Jacob did = 0x1080; 7422df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7432df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1280; 7442df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7452df76c16SMatt Jacob break; 7462df76c16SMatt Jacob case PCI_QLOGIC_ISP10160: 7472df76c16SMatt Jacob did = 0x12160; 7482df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7492df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_10160; 7502df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7512df76c16SMatt Jacob break; 7522df76c16SMatt Jacob case PCI_QLOGIC_ISP12160: 7532df76c16SMatt Jacob did = 0x12160; 7542df76c16SMatt Jacob isp->isp_nchan = 2; 7552df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7562df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_12160; 7572df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7582df76c16SMatt Jacob break; 7592df76c16SMatt Jacob case PCI_QLOGIC_ISP2100: 7602df76c16SMatt Jacob did = 0x2100; 7612df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2100; 7622df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2100; 7632df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 764960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 765ab6d0040SMatt Jacob /* 766ab6d0040SMatt Jacob * XXX: Need to get the actual revision 767ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 768ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 769ab6d0040SMatt Jacob * XXX; boards. 770ab6d0040SMatt Jacob */ 771ab6d0040SMatt Jacob linesz = 1; 772ab6d0040SMatt Jacob } 7732df76c16SMatt Jacob break; 7742df76c16SMatt Jacob case PCI_QLOGIC_ISP2200: 7752df76c16SMatt Jacob did = 0x2200; 7762df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2200; 7772df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2200; 7782df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 7792df76c16SMatt Jacob break; 7802df76c16SMatt Jacob case PCI_QLOGIC_ISP2300: 7812df76c16SMatt Jacob did = 0x2300; 7822df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7832df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2300; 7842df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7852df76c16SMatt Jacob break; 7862df76c16SMatt Jacob case PCI_QLOGIC_ISP2312: 7872df76c16SMatt Jacob case PCI_QLOGIC_ISP6312: 7882df76c16SMatt Jacob did = 0x2300; 7892df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7902df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2312; 7912df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7922df76c16SMatt Jacob break; 7932df76c16SMatt Jacob case PCI_QLOGIC_ISP2322: 7942df76c16SMatt Jacob case PCI_QLOGIC_ISP6322: 7952df76c16SMatt Jacob did = 0x2322; 7962df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7972df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2322; 7982df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7992df76c16SMatt Jacob break; 8002df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 8012df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 8022df76c16SMatt Jacob did = 0x2400; 8032df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 8042df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 8052df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 8062df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 8072df76c16SMatt Jacob break; 8082df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 8092df76c16SMatt Jacob did = 0x2500; 8102df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 8112df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 8122df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 8132df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 8142df76c16SMatt Jacob break; 815a959d921SMatt Jacob case PCI_QLOGIC_ISP5432: 816a959d921SMatt Jacob did = 0x2500; 817a959d921SMatt Jacob isp->isp_mdvec = &mdvec_2500; 818a959d921SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 819a959d921SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 820a959d921SMatt Jacob break; 8212df76c16SMatt Jacob default: 8222df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 8232df76c16SMatt Jacob goto bad; 8242df76c16SMatt Jacob break; 82565adb54cSMatt Jacob } 8262df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 8272df76c16SMatt Jacob 8282df76c16SMatt Jacob if (IS_FC(isp)) { 829222bb542SMatt Jacob psize = sizeof (fcparam); 8302df76c16SMatt Jacob xsize = sizeof (struct isp_fc); 8312df76c16SMatt Jacob } else { 8322df76c16SMatt Jacob psize = sizeof (sdparam); 8332df76c16SMatt Jacob xsize = sizeof (struct isp_spi); 834222bb542SMatt Jacob } 8352df76c16SMatt Jacob psize *= isp->isp_nchan; 8362df76c16SMatt Jacob xsize *= isp->isp_nchan; 8377cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 838c6608df3SMatt Jacob if (isp->isp_param == NULL) { 839960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 840960f6939SMatt Jacob goto bad; 841c6608df3SMatt Jacob } 8422df76c16SMatt Jacob isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 8432df76c16SMatt Jacob if (isp->isp_osinfo.pc.ptr == NULL) { 8442df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 8452df76c16SMatt Jacob goto bad; 8462df76c16SMatt Jacob } 84765adb54cSMatt Jacob 848336b5612SMatt Jacob /* 849336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 850336b5612SMatt Jacob */ 8512df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 8522df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 8539a5af410SMatt Jacob } 8549a5af410SMatt Jacob 8552df76c16SMatt Jacob /* 8562df76c16SMatt Jacob * The 'it' suffix really only matters for SCSI cards in target mode. 8572df76c16SMatt Jacob */ 8589a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 8594ecb1d4aSMatt Jacob if (IS_SCSI(isp) && (ISP_SPI_PC(isp, 0)->def_role & ISP_ROLE_TARGET)) { 8609a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x_it", did); 8619a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 862ad0ab753SMatt Jacob } else if (IS_24XX(isp)) { 8632df76c16SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x_multi", did); 8642df76c16SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8659a5af410SMatt Jacob } 8669a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 8679a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 8689a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8699a5af410SMatt Jacob } 8709a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 871ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname); 8725f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 8739a5af410SMatt Jacob } 87456aef503SMatt Jacob 87556aef503SMatt Jacob /* 876ad0ab753SMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 877d951bbcaSMatt Jacob */ 878*9e7d423dSMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 87975c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 88075c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 88175c1e828SMatt Jacob } 8828a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 8838a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 8848a97c03aSMatt Jacob } 88506cacb29SMatt Jacob if (IS_24XX(isp)) { 88606cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 88706cacb29SMatt Jacob } 888b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 889ab6d0040SMatt Jacob 890d951bbcaSMatt Jacob /* 891222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 892d951bbcaSMatt Jacob */ 893960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 8946a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 895ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data); 8966a7d12e1SMatt Jacob data = linesz; 897960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 898d951bbcaSMatt Jacob } 899ab6d0040SMatt Jacob 900d951bbcaSMatt Jacob /* 901d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 902d951bbcaSMatt Jacob */ 903960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 904d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 905d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 906ad0ab753SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data); 907960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 908d951bbcaSMatt Jacob } 909ab6d0040SMatt Jacob 910ab6d0040SMatt Jacob /* 911ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 912ab6d0040SMatt Jacob */ 913960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 914ab6d0040SMatt Jacob data &= ~1; 915960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 9162df76c16SMatt Jacob 9172df76c16SMatt Jacob /* 9182df76c16SMatt Jacob * Do MSI 9192df76c16SMatt Jacob * 9202df76c16SMatt Jacob * NB: MSI-X needs to be disabled for the 2432 (PCI-Express) 9212df76c16SMatt Jacob */ 9220a70657fSMatt Jacob if (IS_24XX(isp) || IS_2322(isp)) { 9230a70657fSMatt Jacob pcs->msicount = pci_msi_count(dev); 9240a70657fSMatt Jacob if (pcs->msicount > 1) { 9250a70657fSMatt Jacob pcs->msicount = 1; 9260a70657fSMatt Jacob } 9270a70657fSMatt Jacob if (pci_alloc_msi(dev, &pcs->msicount) == 0) { 928e95725cbSMatt Jacob pcs->iqd = 1; 9290a70657fSMatt Jacob } else { 930e95725cbSMatt Jacob pcs->iqd = 0; 9310a70657fSMatt Jacob } 9320a70657fSMatt Jacob } 933e95725cbSMatt Jacob pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE); 934e95725cbSMatt Jacob if (pcs->irq == NULL) { 935960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 936960f6939SMatt Jacob goto bad; 937960f6939SMatt Jacob } 938960f6939SMatt Jacob 939f09b1922SMatt Jacob /* Make sure the lock is set up. */ 9406008862bSJohn Baldwin mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); 941f09b1922SMatt Jacob locksetup++; 942f09b1922SMatt Jacob 943e95725cbSMatt Jacob if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { 944f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 945f09b1922SMatt Jacob goto bad; 946f09b1922SMatt Jacob } 947960f6939SMatt Jacob 94805fbcbb0SMatt Jacob /* 94975c1e828SMatt Jacob * Last minute checks... 95075c1e828SMatt Jacob */ 95110365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 95275c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 95375c1e828SMatt Jacob } 95475c1e828SMatt Jacob 95575c1e828SMatt Jacob /* 95605fbcbb0SMatt Jacob * Make sure we're in reset state. 95705fbcbb0SMatt Jacob */ 9583395b056SMatt Jacob ISP_LOCK(isp); 9592df76c16SMatt Jacob isp_reset(isp, 1); 96065adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 9613395b056SMatt Jacob ISP_UNLOCK(isp); 962960f6939SMatt Jacob goto bad; 96365adb54cSMatt Jacob } 96465adb54cSMatt Jacob isp_init(isp); 9652df76c16SMatt Jacob if (isp->isp_state == ISP_INITSTATE) { 9662df76c16SMatt Jacob isp->isp_state = ISP_RUNSTATE; 9672df76c16SMatt Jacob } 9682df76c16SMatt Jacob ISP_UNLOCK(isp); 9692df76c16SMatt Jacob if (isp_attach(isp)) { 9702df76c16SMatt Jacob ISP_LOCK(isp); 97165adb54cSMatt Jacob isp_uninit(isp); 9723395b056SMatt Jacob ISP_UNLOCK(isp); 973960f6939SMatt Jacob goto bad; 974d59bd469SMatt Jacob } 975960f6939SMatt Jacob return (0); 976960f6939SMatt Jacob 977960f6939SMatt Jacob bad: 978a035b0afSMatt Jacob if (pcs->ih) { 979e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 980960f6939SMatt Jacob } 981a035b0afSMatt Jacob if (locksetup) { 9823395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 9833395b056SMatt Jacob } 984e95725cbSMatt Jacob if (pcs->irq) { 985e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 986960f6939SMatt Jacob } 987a035b0afSMatt Jacob if (pcs->msicount) { 9880a70657fSMatt Jacob pci_release_msi(dev); 9890a70657fSMatt Jacob } 990e95725cbSMatt Jacob if (pcs->regs) { 991e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 992960f6939SMatt Jacob } 9939cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 994960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 9952df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 9962df76c16SMatt Jacob } 9972df76c16SMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 9982df76c16SMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 9992df76c16SMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 10009cd7268eSMatt Jacob } 1001960f6939SMatt Jacob return (ENXIO); 100265adb54cSMatt Jacob } 100365adb54cSMatt Jacob 100410365e5aSMatt Jacob static int 100510365e5aSMatt Jacob isp_pci_detach(device_t dev) 100610365e5aSMatt Jacob { 100710365e5aSMatt Jacob struct isp_pcisoftc *pcs; 100810365e5aSMatt Jacob ispsoftc_t *isp; 1009e95725cbSMatt Jacob int status; 101010365e5aSMatt Jacob 101110365e5aSMatt Jacob pcs = device_get_softc(dev); 101210365e5aSMatt Jacob if (pcs == NULL) { 101310365e5aSMatt Jacob return (ENXIO); 101410365e5aSMatt Jacob } 101510365e5aSMatt Jacob isp = (ispsoftc_t *) pcs; 1016e95725cbSMatt Jacob status = isp_detach(isp); 1017e95725cbSMatt Jacob if (status) 1018e95725cbSMatt Jacob return (status); 1019e95725cbSMatt Jacob ISP_LOCK(isp); 1020e95725cbSMatt Jacob isp_uninit(isp); 1021e95725cbSMatt Jacob if (pcs->ih) { 1022e95725cbSMatt Jacob (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); 1023e95725cbSMatt Jacob } 1024e95725cbSMatt Jacob ISP_UNLOCK(isp); 10252df76c16SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 1026e95725cbSMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); 1027e95725cbSMatt Jacob if (pcs->msicount) { 1028e95725cbSMatt Jacob pci_release_msi(dev); 1029e95725cbSMatt Jacob } 1030e95725cbSMatt Jacob (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); 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 10740a70657fSMatt Jacob isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp) 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)) { 1098126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) { 1099126ec864SMatt Jacob return (0); 1100126ec864SMatt Jacob } 1101126ec864SMatt Jacob } else { 11026a7d12e1SMatt Jacob *mbp = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 1103126ec864SMatt Jacob } 1104126ec864SMatt Jacob } 1105126ec864SMatt Jacob return (1); 1106126ec864SMatt Jacob } 1107126ec864SMatt Jacob 1108126ec864SMatt Jacob static int 1109443e752dSMatt Jacob isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbox0p) 1110126ec864SMatt Jacob { 111110365e5aSMatt Jacob uint32_t hccr; 11121dae40ebSMatt Jacob uint32_t r2hisr; 1113126ec864SMatt Jacob 11146a7d12e1SMatt Jacob if (!(BXR2(isp, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 11153bd40330SMatt Jacob *isrp = 0; 1116db4fa023SMatt Jacob return (0); 11173bd40330SMatt Jacob } 11186a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO)); 1119126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 1120126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 1121126ec864SMatt Jacob *isrp = 0; 1122126ec864SMatt Jacob return (0); 1123126ec864SMatt Jacob } 1124126ec864SMatt Jacob switch (r2hisr & BIU_R2HST_ISTAT_MASK) { 1125126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1126126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1127126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1128126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 1129126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 1130126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1131126ec864SMatt Jacob *mbox0p = (r2hisr >> 16); 1132126ec864SMatt Jacob *semap = 1; 1133126ec864SMatt Jacob return (1); 1134fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 1135fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1136443e752dSMatt Jacob *mbox0p = ASYNC_RIO16_1; 1137fc3bbaaaSMatt Jacob *semap = 1; 1138fc3bbaaaSMatt Jacob return (1); 1139fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 1140fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1141fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CMD_CMPLT; 1142fc3bbaaaSMatt Jacob *semap = 1; 1143fc3bbaaaSMatt Jacob return (1); 1144fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 1145fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1146fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CTIO_DONE; 1147fc3bbaaaSMatt Jacob *semap = 1; 1148fc3bbaaaSMatt Jacob return (1); 1149126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 1150126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1151126ec864SMatt Jacob *mbox0p = 0; 1152126ec864SMatt Jacob *semap = 0; 1153126ec864SMatt Jacob return (1); 1154126ec864SMatt Jacob default: 11558a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 11568a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 11578a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 1158443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR)); 11595ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 11608a97c03aSMatt Jacob } else { 1161443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 11628a97c03aSMatt Jacob } 1163126ec864SMatt Jacob return (0); 1164126ec864SMatt Jacob } 1165126ec864SMatt Jacob } 1166126ec864SMatt Jacob 116710365e5aSMatt Jacob static int 1168443e752dSMatt Jacob isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbox0p) 116910365e5aSMatt Jacob { 117010365e5aSMatt Jacob uint32_t r2hisr; 117110365e5aSMatt Jacob 11726a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO)); 117310365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 117410365e5aSMatt Jacob if ((r2hisr & BIU2400_R2HST_INTR) == 0) { 117510365e5aSMatt Jacob *isrp = 0; 117610365e5aSMatt Jacob return (0); 117710365e5aSMatt Jacob } 117810365e5aSMatt Jacob switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) { 117910365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_OK: 118010365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_FAIL: 118110365e5aSMatt Jacob case ISP2400R2HST_MBX_OK: 118210365e5aSMatt Jacob case ISP2400R2HST_MBX_FAIL: 118310365e5aSMatt Jacob case ISP2400R2HST_ASYNC_EVENT: 118410365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 118510365e5aSMatt Jacob *mbox0p = (r2hisr >> 16); 118610365e5aSMatt Jacob *semap = 1; 118710365e5aSMatt Jacob return (1); 118810365e5aSMatt Jacob case ISP2400R2HST_RSPQ_UPDATE: 118910365e5aSMatt Jacob case ISP2400R2HST_ATIO_RSPQ_UPDATE: 119010365e5aSMatt Jacob case ISP2400R2HST_ATIO_RQST_UPDATE: 119110365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 119210365e5aSMatt Jacob *mbox0p = 0; 119310365e5aSMatt Jacob *semap = 0; 119410365e5aSMatt Jacob return (1); 119510365e5aSMatt Jacob default: 119610365e5aSMatt Jacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 119710365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 119810365e5aSMatt Jacob return (0); 119910365e5aSMatt Jacob } 120010365e5aSMatt Jacob } 120110365e5aSMatt Jacob 120210365e5aSMatt Jacob static uint32_t 12039cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 120465adb54cSMatt Jacob { 12056a7d12e1SMatt Jacob uint16_t rv; 1206126ec864SMatt Jacob int oldconf = 0; 120765adb54cSMatt Jacob 1208d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 120965adb54cSMatt Jacob /* 121065adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 121165adb54cSMatt Jacob */ 12126a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 1213443e752dSMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); 121437bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 121565adb54cSMatt Jacob } 12166a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 1217d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12186a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 121937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 122065adb54cSMatt Jacob } 122165adb54cSMatt Jacob return (rv); 122265adb54cSMatt Jacob } 122365adb54cSMatt Jacob 122465adb54cSMatt Jacob static void 122510365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 122665adb54cSMatt Jacob { 1227126ec864SMatt Jacob int oldconf = 0; 1228d59bd469SMatt Jacob 1229d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 123065adb54cSMatt Jacob /* 123165adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 123265adb54cSMatt Jacob */ 12336a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12346a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1235126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 123637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 123765adb54cSMatt Jacob } 12386a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 123937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 1240d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12416a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 124237bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 124365adb54cSMatt Jacob } 12446a7d12e1SMatt Jacob 1245f9734398SMatt Jacob } 124665adb54cSMatt Jacob 124710365e5aSMatt Jacob static uint32_t 12489cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1249d59bd469SMatt Jacob { 125010365e5aSMatt Jacob uint32_t rv, oc = 0; 1251d59bd469SMatt Jacob 125222e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 125322e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 125410365e5aSMatt Jacob uint32_t tc; 1255d59bd469SMatt Jacob /* 1256d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1257d59bd469SMatt Jacob */ 12586a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 125922e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 126022e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 126122e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 126222e1dc85SMatt Jacob else 126322e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12646a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 126537bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1266d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12676a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12686a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1269126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 127037bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1271d59bd469SMatt Jacob } 12726a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 127322e1dc85SMatt Jacob if (oc) { 12746a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 127537bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1276d59bd469SMatt Jacob } 1277d59bd469SMatt Jacob return (rv); 1278d59bd469SMatt Jacob } 1279d59bd469SMatt Jacob 1280d59bd469SMatt Jacob static void 128110365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1282d59bd469SMatt Jacob { 1283126ec864SMatt Jacob int oc = 0; 1284d59bd469SMatt Jacob 128522e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 128622e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 128710365e5aSMatt Jacob uint32_t tc; 1288d59bd469SMatt Jacob /* 1289d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1290d59bd469SMatt Jacob */ 12916a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 129222e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 129322e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 129422e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 129522e1dc85SMatt Jacob else 129622e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12976a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 129837bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1299d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 13006a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 13016a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1302126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 130337bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 1304d59bd469SMatt Jacob } 13056a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 130637bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 130722e1dc85SMatt Jacob if (oc) { 13086a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 130937bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1); 131010365e5aSMatt Jacob } 131110365e5aSMatt Jacob } 131210365e5aSMatt Jacob 131310365e5aSMatt Jacob static uint32_t 131410365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 131510365e5aSMatt Jacob { 131610365e5aSMatt Jacob uint32_t rv; 131710365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 131810365e5aSMatt Jacob 131910365e5aSMatt Jacob switch (block) { 132010365e5aSMatt Jacob case BIU_BLOCK: 132110365e5aSMatt Jacob break; 132210365e5aSMatt Jacob case MBOX_BLOCK: 13236a7d12e1SMatt Jacob return (BXR2(isp, IspVirt2Off(isp, regoff))); 132410365e5aSMatt Jacob case SXP_BLOCK: 132510365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); 132610365e5aSMatt Jacob return (0xffffffff); 132710365e5aSMatt Jacob case RISC_BLOCK: 132810365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); 132910365e5aSMatt Jacob return (0xffffffff); 133010365e5aSMatt Jacob case DMA_BLOCK: 133110365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); 133210365e5aSMatt Jacob return (0xffffffff); 133310365e5aSMatt Jacob default: 133410365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); 133510365e5aSMatt Jacob return (0xffffffff); 133610365e5aSMatt Jacob } 133710365e5aSMatt Jacob 133810365e5aSMatt Jacob 133910365e5aSMatt Jacob switch (regoff) { 134010365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 134110365e5aSMatt Jacob case BIU2400_FLASH_DATA: 134210365e5aSMatt Jacob case BIU2400_ICR: 134310365e5aSMatt Jacob case BIU2400_ISR: 134410365e5aSMatt Jacob case BIU2400_CSR: 134510365e5aSMatt Jacob case BIU2400_REQINP: 134610365e5aSMatt Jacob case BIU2400_REQOUTP: 134710365e5aSMatt Jacob case BIU2400_RSPINP: 134810365e5aSMatt Jacob case BIU2400_RSPOUTP: 13492df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13502df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 135110365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13522df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 135310365e5aSMatt Jacob case BIU2400_HCCR: 135410365e5aSMatt Jacob case BIU2400_GPIOD: 135510365e5aSMatt Jacob case BIU2400_GPIOE: 135610365e5aSMatt Jacob case BIU2400_HSEMA: 13576a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 135810365e5aSMatt Jacob break; 135910365e5aSMatt Jacob case BIU2400_R2HSTSLO: 13606a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 136110365e5aSMatt Jacob break; 136210365e5aSMatt Jacob case BIU2400_R2HSTSHI: 13636a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16; 136410365e5aSMatt Jacob break; 136510365e5aSMatt Jacob default: 136610365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 136710365e5aSMatt Jacob "isp_pci_rd_reg_2400: unknown offset %x", regoff); 136810365e5aSMatt Jacob rv = 0xffffffff; 136910365e5aSMatt Jacob break; 137010365e5aSMatt Jacob } 137110365e5aSMatt Jacob return (rv); 137210365e5aSMatt Jacob } 137310365e5aSMatt Jacob 137410365e5aSMatt Jacob static void 137510365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 137610365e5aSMatt Jacob { 137710365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 137810365e5aSMatt Jacob 137910365e5aSMatt Jacob switch (block) { 138010365e5aSMatt Jacob case BIU_BLOCK: 138110365e5aSMatt Jacob break; 138210365e5aSMatt Jacob case MBOX_BLOCK: 13836a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 138437bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1); 138510365e5aSMatt Jacob return; 138610365e5aSMatt Jacob case SXP_BLOCK: 138710365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); 138810365e5aSMatt Jacob return; 138910365e5aSMatt Jacob case RISC_BLOCK: 139010365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); 139110365e5aSMatt Jacob return; 139210365e5aSMatt Jacob case DMA_BLOCK: 139310365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); 139410365e5aSMatt Jacob return; 139510365e5aSMatt Jacob default: 139610365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", 139710365e5aSMatt Jacob regoff); 139810365e5aSMatt Jacob break; 139910365e5aSMatt Jacob } 140010365e5aSMatt Jacob 140110365e5aSMatt Jacob switch (regoff) { 140210365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 140310365e5aSMatt Jacob case BIU2400_FLASH_DATA: 140410365e5aSMatt Jacob case BIU2400_ICR: 140510365e5aSMatt Jacob case BIU2400_ISR: 140610365e5aSMatt Jacob case BIU2400_CSR: 140710365e5aSMatt Jacob case BIU2400_REQINP: 140810365e5aSMatt Jacob case BIU2400_REQOUTP: 140910365e5aSMatt Jacob case BIU2400_RSPINP: 141010365e5aSMatt Jacob case BIU2400_RSPOUTP: 14112df76c16SMatt Jacob case BIU2400_PRI_REQINP: 14122df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 141310365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 14142df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 141510365e5aSMatt Jacob case BIU2400_HCCR: 141610365e5aSMatt Jacob case BIU2400_GPIOD: 141710365e5aSMatt Jacob case BIU2400_GPIOE: 141810365e5aSMatt Jacob case BIU2400_HSEMA: 14196a7d12e1SMatt Jacob BXW4(isp, IspVirt2Off(isp, regoff), val); 142037bb79f1SMarius Strobl MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1); 142110365e5aSMatt Jacob break; 142210365e5aSMatt Jacob default: 142310365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 142410365e5aSMatt Jacob "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); 142510365e5aSMatt Jacob break; 1426d59bd469SMatt Jacob } 1427d59bd469SMatt Jacob } 1428d59bd469SMatt Jacob 1429d720e6d5SJustin T. Gibbs 1430222bb542SMatt Jacob struct imush { 14319cd7268eSMatt Jacob ispsoftc_t *isp; 14322df76c16SMatt Jacob caddr_t vbase; 14332df76c16SMatt Jacob int chan; 1434222bb542SMatt Jacob int error; 1435222bb542SMatt Jacob }; 1436222bb542SMatt Jacob 14371923f739SMatt Jacob static void imc(void *, bus_dma_segment_t *, int, int); 14382df76c16SMatt Jacob static void imc1(void *, bus_dma_segment_t *, int, int); 14391923f739SMatt Jacob 1440d720e6d5SJustin T. Gibbs static void 14411923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1442d720e6d5SJustin T. Gibbs { 1443222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 14442df76c16SMatt Jacob 1445222bb542SMatt Jacob if (error) { 1446222bb542SMatt Jacob imushp->error = error; 14472df76c16SMatt Jacob return; 14482df76c16SMatt Jacob } 14492df76c16SMatt Jacob if (nseg != 1) { 14502df76c16SMatt Jacob imushp->error = EINVAL; 14512df76c16SMatt Jacob return; 14522df76c16SMatt Jacob } 14537d3cea31SMatt Jacob isp_prt(imushp->isp, ISP_LOGDEBUG0, "request/result area @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); 14542df76c16SMatt Jacob imushp->isp->isp_rquest = imushp->vbase; 14552df76c16SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 14562df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 14572df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 14582df76c16SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 14592df76c16SMatt Jacob imushp->isp->isp_result = imushp->vbase; 14601923f739SMatt Jacob 14612df76c16SMatt Jacob #ifdef ISP_TARGET_MODE 14622df76c16SMatt Jacob if (IS_24XX(imushp->isp)) { 14632df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 14642df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 14652df76c16SMatt Jacob imushp->isp->isp_atioq_dma = segs->ds_addr; 14662df76c16SMatt Jacob imushp->isp->isp_atioq = imushp->vbase; 14671923f739SMatt Jacob } 14682df76c16SMatt Jacob #endif 1469222bb542SMatt Jacob } 14702df76c16SMatt Jacob 14712df76c16SMatt Jacob static void 14722df76c16SMatt Jacob imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error) 14732df76c16SMatt Jacob { 14742df76c16SMatt Jacob struct imush *imushp = (struct imush *) arg; 14752df76c16SMatt Jacob if (error) { 14762df76c16SMatt Jacob imushp->error = error; 14772df76c16SMatt Jacob return; 14782df76c16SMatt Jacob } 14792df76c16SMatt Jacob if (nseg != 1) { 14802df76c16SMatt Jacob imushp->error = EINVAL; 14812df76c16SMatt Jacob return; 14822df76c16SMatt Jacob } 14837d3cea31SMatt Jacob isp_prt(imushp->isp, ISP_LOGDEBUG0, "scdma @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len); 14842df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr; 14852df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase; 1486d720e6d5SJustin T. Gibbs } 1487d720e6d5SJustin T. Gibbs 1488d720e6d5SJustin T. Gibbs static int 14899cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1490d720e6d5SJustin T. Gibbs { 1491d720e6d5SJustin T. Gibbs caddr_t base; 14921dae40ebSMatt Jacob uint32_t len; 14932df76c16SMatt Jacob int i, error, ns, cmap = 0; 149453af7d22SMatt Jacob bus_size_t slim; /* segment size */ 14954b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 149651effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1497222bb542SMatt Jacob struct imush im; 1498222bb542SMatt Jacob 1499a95ae193SMatt Jacob /* 1500a95ae193SMatt Jacob * Already been here? If so, leave... 1501a95ae193SMatt Jacob */ 1502a95ae193SMatt Jacob if (isp->isp_rquest) { 1503a95ae193SMatt Jacob return (0); 1504a95ae193SMatt Jacob } 15050a70657fSMatt Jacob ISP_UNLOCK(isp); 1506a95ae193SMatt Jacob 150710365e5aSMatt Jacob if (isp->isp_maxcmds == 0) { 150810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "maxcmds not set"); 15090a70657fSMatt Jacob ISP_LOCK(isp); 151010365e5aSMatt Jacob return (1); 151110365e5aSMatt Jacob } 151210365e5aSMatt Jacob 151353af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 15141923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 15159b434edeSMatt Jacob if (sizeof (bus_size_t) > 4) { 151653af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 15179b434edeSMatt Jacob } else { 15189b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 15199b434edeSMatt Jacob } 15201dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 15211923f739SMatt Jacob } else { 15221dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR_32BIT; 15239b434edeSMatt Jacob slim = (1UL << 24); 15241923f739SMatt Jacob } 15251923f739SMatt Jacob 15260a70657fSMatt Jacob len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 15272df76c16SMatt Jacob isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 15280a70657fSMatt Jacob if (isp->isp_osinfo.pcmd_pool == NULL) { 15290a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds"); 15300a70657fSMatt Jacob ISP_LOCK(isp); 15310a70657fSMatt Jacob return (1); 15320a70657fSMatt Jacob } 15330a70657fSMatt Jacob 153409934867SMatt Jacob /* 153509934867SMatt Jacob * XXX: We don't really support 64 bit target mode for parallel scsi yet 153609934867SMatt Jacob */ 153709934867SMatt Jacob #ifdef ISP_TARGET_MODE 153809934867SMatt Jacob if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) { 15390a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 154009934867SMatt Jacob isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet"); 15412df76c16SMatt Jacob ISP_LOCK(isp); 154209934867SMatt Jacob return (1); 154309934867SMatt Jacob } 154409934867SMatt Jacob #endif 154509934867SMatt Jacob 15462df76c16SMatt Jacob if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0, &isp->isp_osinfo.dmat)) { 15470a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 154872429e49SMatt Jacob ISP_LOCK(isp); 15490a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 15501923f739SMatt Jacob return (1); 15511923f739SMatt Jacob } 15521923f739SMatt Jacob 1553c8b8a2c4SMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1554c8b8a2c4SMatt Jacob isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1555a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 15560a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 155772429e49SMatt Jacob ISP_LOCK(isp); 15580a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 1559a95ae193SMatt Jacob return (1); 1560a95ae193SMatt Jacob } 1561c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1562c8b8a2c4SMatt Jacob isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1563c8b8a2c4SMatt Jacob } 1564c8b8a2c4SMatt Jacob isp->isp_xffree = isp->isp_xflist; 156551e23558SNate Lawson #ifdef ISP_TARGET_MODE 156632b3ec7dSMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1567c8b8a2c4SMatt Jacob isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 156851e23558SNate Lawson if (isp->isp_tgtlist == NULL) { 15690a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1570a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 157172429e49SMatt Jacob ISP_LOCK(isp); 15720a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); 1573a95ae193SMatt Jacob return (1); 1574a95ae193SMatt Jacob } 1575c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1576c8b8a2c4SMatt Jacob isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1]; 1577c8b8a2c4SMatt Jacob } 1578c8b8a2c4SMatt Jacob isp->isp_tgtfree = isp->isp_tgtlist; 15790a70657fSMatt Jacob #endif 1580a95ae193SMatt Jacob 1581d720e6d5SJustin T. Gibbs /* 15822df76c16SMatt Jacob * Allocate and map the request and result queues (and ATIO queue 15832df76c16SMatt Jacob * if we're a 2400 supporting target mode). 1584d720e6d5SJustin T. Gibbs */ 1585d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1586d02373f1SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 15872df76c16SMatt Jacob #ifdef ISP_TARGET_MODE 15882df76c16SMatt Jacob if (IS_24XX(isp)) { 15892df76c16SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1590d720e6d5SJustin T. Gibbs } 15912df76c16SMatt Jacob #endif 15921923f739SMatt Jacob 15931923f739SMatt Jacob ns = (len / PAGE_SIZE) + 1; 15942df76c16SMatt Jacob 159553af7d22SMatt Jacob /* 15962df76c16SMatt Jacob * Create a tag for the control spaces. We don't always need this 15972df76c16SMatt Jacob * to be 32 bits, but we do this for simplicity and speed's sake. 159853af7d22SMatt Jacob */ 15992df76c16SMatt Jacob if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, ns, slim, 0, &isp->isp_osinfo.cdmat)) { 16002df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces"); 16010a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1602a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 160351e23558SNate Lawson #ifdef ISP_TARGET_MODE 160451e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 160551e23558SNate Lawson #endif 160672429e49SMatt Jacob ISP_LOCK(isp); 1607d720e6d5SJustin T. Gibbs return (1); 1608d720e6d5SJustin T. Gibbs } 1609d720e6d5SJustin T. Gibbs 161037bb79f1SMarius Strobl if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &isp->isp_osinfo.cdmap) != 0) { 16112df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); 16122df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 16130a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1614a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 161551e23558SNate Lawson #ifdef ISP_TARGET_MODE 161651e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 161751e23558SNate Lawson #endif 161872429e49SMatt Jacob ISP_LOCK(isp); 1619222bb542SMatt Jacob return (1); 1620222bb542SMatt Jacob } 1621d720e6d5SJustin T. Gibbs 16222df76c16SMatt Jacob im.isp = isp; 16232df76c16SMatt Jacob im.chan = 0; 16242df76c16SMatt Jacob im.vbase = base; 16252df76c16SMatt Jacob im.error = 0; 16262df76c16SMatt Jacob 16272df76c16SMatt Jacob bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0); 16282df76c16SMatt Jacob if (im.error) { 16292df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error); 16302df76c16SMatt Jacob goto bad; 16312df76c16SMatt Jacob } 16322df76c16SMatt Jacob 16332df76c16SMatt Jacob if (IS_FC(isp)) { 16342df76c16SMatt Jacob for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 16352df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16362df76c16SMatt 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)) { 16372df76c16SMatt Jacob goto bad; 16382df76c16SMatt Jacob } 163937bb79f1SMarius Strobl if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &fc->tdmap) != 0) { 16402df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16412df76c16SMatt Jacob goto bad; 16422df76c16SMatt Jacob } 16432df76c16SMatt Jacob im.isp = isp; 16442df76c16SMatt Jacob im.chan = cmap; 16452df76c16SMatt Jacob im.vbase = base; 16462df76c16SMatt Jacob im.error = 0; 16472df76c16SMatt Jacob bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0); 16482df76c16SMatt Jacob if (im.error) { 16492df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 16502df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16512df76c16SMatt Jacob goto bad; 16522df76c16SMatt Jacob } 16532df76c16SMatt Jacob } 16542df76c16SMatt Jacob } 16552df76c16SMatt Jacob 1656a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 16570a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 16580a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1659d720e6d5SJustin T. Gibbs if (error) { 16602df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 16611923f739SMatt Jacob while (--i >= 0) { 16622df76c16SMatt Jacob bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap); 16631923f739SMatt Jacob } 16641923f739SMatt Jacob goto bad; 1665d720e6d5SJustin T. Gibbs } 16662df76c16SMatt Jacob callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); 16670a70657fSMatt Jacob if (i == isp->isp_maxcmds-1) { 16680a70657fSMatt Jacob pcmd->next = NULL; 16690a70657fSMatt Jacob } else { 16700a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1671d720e6d5SJustin T. Gibbs } 16720a70657fSMatt Jacob } 16730a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 167472429e49SMatt Jacob ISP_LOCK(isp); 1675d720e6d5SJustin T. Gibbs return (0); 16761923f739SMatt Jacob 16771923f739SMatt Jacob bad: 16782df76c16SMatt Jacob while (--cmap >= 0) { 16792df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16802df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 16812df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16822df76c16SMatt Jacob } 16832df76c16SMatt Jacob bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); 16842df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 16851923f739SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 168651e23558SNate Lawson #ifdef ISP_TARGET_MODE 168751e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 168851e23558SNate Lawson #endif 16890a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 16901923f739SMatt Jacob isp->isp_rquest = NULL; 16910a70657fSMatt Jacob ISP_LOCK(isp); 16921923f739SMatt Jacob return (1); 1693d720e6d5SJustin T. Gibbs } 1694d720e6d5SJustin T. Gibbs 1695d720e6d5SJustin T. Gibbs typedef struct { 16969cd7268eSMatt Jacob ispsoftc_t *isp; 16979e11e5beSMatt Jacob void *cmd_token; 16982df76c16SMatt Jacob void *rq; /* original request */ 16991dae40ebSMatt Jacob int error; 17002df76c16SMatt Jacob bus_size_t mapsize; 1701d720e6d5SJustin T. Gibbs } mush_t; 1702d720e6d5SJustin T. Gibbs 17034873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 17044873663cSMatt Jacob 17059e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 17062df76c16SMatt Jacob static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 17072df76c16SMatt Jacob static void tdma2(void *, bus_dma_segment_t *, int, int); 17089e11e5beSMatt Jacob 1709d720e6d5SJustin T. Gibbs static void 17102df76c16SMatt Jacob tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 1711d720e6d5SJustin T. Gibbs { 1712d720e6d5SJustin T. Gibbs mush_t *mp; 17132df76c16SMatt Jacob mp = (mush_t *)arg; 17142df76c16SMatt Jacob mp->mapsize = mapsize; 17152df76c16SMatt Jacob tdma2(arg, dm_segs, nseg, error); 17162df76c16SMatt Jacob } 17172df76c16SMatt Jacob 17182df76c16SMatt Jacob static void 17192df76c16SMatt Jacob tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 17202df76c16SMatt Jacob { 17212df76c16SMatt Jacob mush_t *mp; 17229cd7268eSMatt Jacob ispsoftc_t *isp; 17232df76c16SMatt Jacob struct ccb_scsiio *csio; 17242df76c16SMatt Jacob isp_ddir_t ddir; 17252df76c16SMatt Jacob ispreq_t *rq; 1726d720e6d5SJustin T. Gibbs 1727d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1728d720e6d5SJustin T. Gibbs if (error) { 1729d720e6d5SJustin T. Gibbs mp->error = error; 1730d720e6d5SJustin T. Gibbs return; 1731d720e6d5SJustin T. Gibbs } 17329e11e5beSMatt Jacob csio = mp->cmd_token; 17334fd13c1bSMatt Jacob isp = mp->isp; 17342df76c16SMatt Jacob rq = mp->rq; 17352df76c16SMatt Jacob if (nseg) { 173609934867SMatt Jacob if (sizeof (bus_addr_t) > 4) { 17372df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 17382df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 17392df76c16SMatt Jacob mp->error = EFAULT; 17409e11e5beSMatt Jacob return; 17419e11e5beSMatt Jacob } 17422df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) { 17432df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_CTIO3; 17442df76c16SMatt Jacob } 174509934867SMatt Jacob } else { 17462df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 17472df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 17482df76c16SMatt Jacob mp->error = EFAULT; 17492df76c16SMatt Jacob return; 175009934867SMatt Jacob } 17512df76c16SMatt Jacob } 17522df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 17532df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 17542df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 17552df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 17562df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 17572df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 175809934867SMatt Jacob } else { 1759a035b0afSMatt Jacob dm_segs = NULL; 1760a035b0afSMatt Jacob nseg = 0; 17612df76c16SMatt Jacob ddir = ISP_NOXFR; 176209934867SMatt Jacob } 17632df76c16SMatt Jacob } else { 17642df76c16SMatt Jacob dm_segs = NULL; 17652df76c16SMatt Jacob nseg = 0; 17662df76c16SMatt Jacob ddir = ISP_NOXFR; 1767fc087171SMatt Jacob } 176865b024e1SMatt Jacob 17692df76c16SMatt Jacob if (isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len) != CMD_QUEUED) { 17702df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 177110365e5aSMatt Jacob } 17729e11e5beSMatt Jacob } 17739e11e5beSMatt Jacob #endif 17749e11e5beSMatt Jacob 17752df76c16SMatt Jacob static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 1776126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 17779e11e5beSMatt Jacob 17786de9bf77SMatt Jacob static void 17792df76c16SMatt Jacob dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 178010365e5aSMatt Jacob { 178110365e5aSMatt Jacob mush_t *mp; 178210365e5aSMatt Jacob mp = (mush_t *)arg; 17832df76c16SMatt Jacob mp->mapsize = mapsize; 17842df76c16SMatt Jacob dma2(arg, dm_segs, nseg, error); 17856de9bf77SMatt Jacob } 17861dae40ebSMatt Jacob 17879e11e5beSMatt Jacob static void 17889e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 17899e11e5beSMatt Jacob { 17909e11e5beSMatt Jacob mush_t *mp; 17919cd7268eSMatt Jacob ispsoftc_t *isp; 17929e11e5beSMatt Jacob struct ccb_scsiio *csio; 17932df76c16SMatt Jacob isp_ddir_t ddir; 17949e11e5beSMatt Jacob ispreq_t *rq; 17959e11e5beSMatt Jacob 17969e11e5beSMatt Jacob mp = (mush_t *) arg; 17979e11e5beSMatt Jacob if (error) { 17989e11e5beSMatt Jacob mp->error = error; 17999e11e5beSMatt Jacob return; 18009e11e5beSMatt Jacob } 18019e11e5beSMatt Jacob csio = mp->cmd_token; 18024fd13c1bSMatt Jacob isp = mp->isp; 18039e11e5beSMatt Jacob rq = mp->rq; 18042df76c16SMatt Jacob if (nseg) { 18052df76c16SMatt Jacob if (sizeof (bus_addr_t) > 4) { 18062df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 18072df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 18082df76c16SMatt Jacob mp->error = EFAULT; 1809d720e6d5SJustin T. Gibbs return; 1810d720e6d5SJustin T. Gibbs } 18112df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) { 18122df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; 18132df76c16SMatt Jacob } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) { 18142df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_A64; 1815d720e6d5SJustin T. Gibbs } 18162df76c16SMatt Jacob } else { 18172df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 18182df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 18192df76c16SMatt Jacob mp->error = EFAULT; 18202df76c16SMatt Jacob return; 182110365e5aSMatt Jacob } 1822d720e6d5SJustin T. Gibbs } 18232df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 18242df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 18252df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 18262df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 18272df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 18282df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 18292df76c16SMatt Jacob } else { 18302df76c16SMatt Jacob ddir = ISP_NOXFR; 18312df76c16SMatt Jacob } 18322df76c16SMatt Jacob } else { 18332df76c16SMatt Jacob dm_segs = NULL; 18342df76c16SMatt Jacob nseg = 0; 18352df76c16SMatt Jacob ddir = ISP_NOXFR; 1836d720e6d5SJustin T. Gibbs } 1837d720e6d5SJustin T. Gibbs 18382df76c16SMatt Jacob if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) { 18392df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 18402df76c16SMatt Jacob } 18412df76c16SMatt Jacob } 18422df76c16SMatt Jacob 1843d720e6d5SJustin T. Gibbs static int 18442df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 1845d720e6d5SJustin T. Gibbs { 1846d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1847126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 18482df76c16SMatt Jacob void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int); 1849d720e6d5SJustin T. Gibbs 18502df76c16SMatt Jacob mp = &mush; 18512df76c16SMatt Jacob mp->isp = isp; 18522df76c16SMatt Jacob mp->cmd_token = csio; 18532df76c16SMatt Jacob mp->rq = ff; 18542df76c16SMatt Jacob mp->error = 0; 18552df76c16SMatt Jacob mp->mapsize = 0; 18562df76c16SMatt Jacob 185765b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 185865b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 18592df76c16SMatt Jacob eptr = tdma2; 18602df76c16SMatt Jacob eptr2 = tdma2_2; 186165b024e1SMatt Jacob } else 186265b024e1SMatt Jacob #endif 18632df76c16SMatt Jacob { 186465b024e1SMatt Jacob eptr = dma2; 18652df76c16SMatt Jacob eptr2 = dma2_2; 18661dae40ebSMatt Jacob } 186765b024e1SMatt Jacob 18684fd13c1bSMatt Jacob 18692df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) { 18702df76c16SMatt Jacob (*eptr)(mp, NULL, 0, 0); 18712df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 18729e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { 18730a70657fSMatt Jacob int error; 18742df76c16SMatt Jacob error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0); 18752df76c16SMatt Jacob #if 0 18762df76c16SMatt Jacob xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error); 18770a70657fSMatt Jacob #endif 18782df76c16SMatt Jacob 1879d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 18802df76c16SMatt Jacob bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 1881d720e6d5SJustin T. Gibbs mp->error = EINVAL; 18822df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); 1883d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 18840a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 18852df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 18860a5f7e8bSMatt Jacob #endif 1887d720e6d5SJustin T. Gibbs mp->error = error; 1888d720e6d5SJustin T. Gibbs } 1889d720e6d5SJustin T. Gibbs } else { 1890d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 1891d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 18926de9bf77SMatt Jacob seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; 1893d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 18949e11e5beSMatt Jacob (*eptr)(mp, &seg, 1, 0); 1895d720e6d5SJustin T. Gibbs } 1896d720e6d5SJustin T. Gibbs } else { 1897d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 1898d720e6d5SJustin T. Gibbs 18999e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { 19002df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported"); 1901d720e6d5SJustin T. Gibbs mp->error = EINVAL; 19029e11e5beSMatt Jacob } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { 19032df76c16SMatt Jacob struct uio sguio; 19042df76c16SMatt Jacob int error; 19052df76c16SMatt Jacob 19062df76c16SMatt Jacob /* 19072df76c16SMatt Jacob * We're taking advantage of the fact that 19082df76c16SMatt Jacob * the pointer/length sizes and layout of the iovec 19092df76c16SMatt Jacob * structure are the same as the bus_dma_segment 19102df76c16SMatt Jacob * structure. This might be a little dangerous, 19112df76c16SMatt Jacob * but only if they change the structures, which 19122df76c16SMatt Jacob * seems unlikely. 19132df76c16SMatt Jacob */ 19142df76c16SMatt Jacob KASSERT((sizeof (sguio.uio_iov) == sizeof (csio->data_ptr) && 19152df76c16SMatt Jacob sizeof (sguio.uio_iovcnt) >= sizeof (csio->sglist_cnt) && 19162df76c16SMatt Jacob sizeof (sguio.uio_resid) >= sizeof (csio->dxfer_len)), ("Ken's assumption failed")); 19172df76c16SMatt Jacob sguio.uio_iov = (struct iovec *)csio->data_ptr; 19182df76c16SMatt Jacob sguio.uio_iovcnt = csio->sglist_cnt; 19192df76c16SMatt Jacob sguio.uio_resid = csio->dxfer_len; 19202df76c16SMatt Jacob sguio.uio_segflg = UIO_SYSSPACE; 19212df76c16SMatt Jacob 19222df76c16SMatt Jacob error = bus_dmamap_load_uio(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, &sguio, eptr2, mp, 0); 19232df76c16SMatt Jacob 19242df76c16SMatt Jacob if (error != 0 && mp->error == 0) { 19252df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 19262df76c16SMatt Jacob mp->error = error; 19272df76c16SMatt Jacob } 1928d720e6d5SJustin T. Gibbs } else { 1929d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 1930d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 19319e11e5beSMatt Jacob (*eptr)(mp, segs, csio->sglist_cnt, 0); 1932d720e6d5SJustin T. Gibbs } 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) { 19390a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_TOO_BIG); 1940d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 19410a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_INVALID); 1942d720e6d5SJustin T. Gibbs } else { 19430a5f7e8bSMatt Jacob XS_SETERR(csio, 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