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 49*17bc427dSMarius Strobl #ifdef __sparc64__ 50*17bc427dSMarius Strobl #include <dev/ofw/openfirm.h> 51*17bc427dSMarius Strobl #include <machine/ofw_machdep.h> 52*17bc427dSMarius Strobl #endif 53*17bc427dSMarius 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 2759a5af410SMatt Jacob 27656aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 27756aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 278d59bd469SMatt Jacob 279d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 280d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 281d59bd469SMatt Jacob 282f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 283f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 284f556e83bSMatt Jacob 285960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 286960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 287960f6939SMatt Jacob 288d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 289d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 290d59bd469SMatt Jacob 29122e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 29222e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 29322e1dc85SMatt Jacob 29465adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 29565adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 29665adb54cSMatt Jacob 297222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 298222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 299222bb542SMatt Jacob 300126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 301126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 302126ec864SMatt Jacob 303126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 304126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 305126ec864SMatt Jacob 306e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 307e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 308e5265237SMatt Jacob 3096c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 3106c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 3116c426685SMatt Jacob 31241675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 31341675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 31441675df0SMatt Jacob 3152df76c16SMatt Jacob #define PCI_QLOGIC_ISP2532 \ 3162df76c16SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC) 3172df76c16SMatt Jacob 318dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 319dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 320dd1419abSMatt Jacob 3219a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 3229a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 3239a5af410SMatt Jacob 324e11a1ee8SMatt Jacob /* 325e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 326e11a1ee8SMatt Jacob */ 327e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 328e11a1ee8SMatt Jacob 32965adb54cSMatt Jacob #define IO_MAP_REG 0x10 33065adb54cSMatt Jacob #define MEM_MAP_REG 0x14 33165adb54cSMatt Jacob 332d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 333d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 33465adb54cSMatt Jacob 335960f6939SMatt Jacob static int isp_pci_probe (device_t); 336960f6939SMatt Jacob static int isp_pci_attach (device_t); 33710365e5aSMatt Jacob static int isp_pci_detach (device_t); 33865adb54cSMatt Jacob 3391923f739SMatt Jacob 3400230a28bSMatt Jacob #define ISP_PCD(isp) ((struct isp_pcisoftc *)isp)->pci_dev 34165adb54cSMatt Jacob struct isp_pcisoftc { 3429cd7268eSMatt Jacob ispsoftc_t pci_isp; 343960f6939SMatt Jacob device_t pci_dev; 344960f6939SMatt Jacob struct resource * pci_reg; 345960f6939SMatt Jacob void * ih; 346d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3471923f739SMatt Jacob bus_dma_tag_t dmat; 3480a70657fSMatt Jacob int msicount; 34965adb54cSMatt Jacob }; 35065adb54cSMatt Jacob 35110365e5aSMatt Jacob 352960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 353960f6939SMatt Jacob /* Device interface */ 354960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 355960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 35610365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 357960f6939SMatt Jacob { 0, 0 } 35865adb54cSMatt Jacob }; 35965adb54cSMatt Jacob 360960f6939SMatt Jacob static driver_t isp_pci_driver = { 361960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 362960f6939SMatt Jacob }; 363960f6939SMatt Jacob static devclass_t isp_devclass; 364960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 36565adb54cSMatt Jacob 366960f6939SMatt Jacob static int 367960f6939SMatt Jacob isp_pci_probe(device_t dev) 36865adb54cSMatt Jacob { 369960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 37056aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 371960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 37265adb54cSMatt Jacob break; 373d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 374960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 375c6608df3SMatt Jacob break; 376c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 377960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 378d59bd469SMatt Jacob break; 37922e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 380960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 381960f6939SMatt Jacob break; 382f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 383f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 384f556e83bSMatt Jacob break; 385960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 386e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 387e11a1ee8SMatt Jacob return (ENXIO); 388e11a1ee8SMatt Jacob } 389960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 39022e1dc85SMatt Jacob break; 39165adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 392960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 39365adb54cSMatt Jacob break; 3945542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 395960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 3965542fe4bSMatt Jacob break; 397126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 398126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 399126ec864SMatt Jacob break; 400126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 401126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 402126ec864SMatt Jacob break; 403e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 404e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 405e5265237SMatt Jacob break; 4068872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 4078872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 4088872e3d7SMatt Jacob break; 40941675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 41041675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 41141675df0SMatt Jacob break; 4122df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 4132df76c16SMatt Jacob device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter"); 4142df76c16SMatt Jacob break; 415dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 416dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 417dd1419abSMatt Jacob break; 4189a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4199a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4209a5af410SMatt Jacob break; 42165adb54cSMatt Jacob default: 422960f6939SMatt Jacob return (ENXIO); 42365adb54cSMatt Jacob } 42473030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 425d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 426a95ae193SMatt Jacob "Core Version %d.%d\n", 427d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 428d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 42973030e03SMatt Jacob isp_announced++; 43065adb54cSMatt Jacob } 43156aef503SMatt Jacob /* 43256aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 43356aef503SMatt Jacob * XXXX: (or increase a reference count to it). 43456aef503SMatt Jacob */ 435b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 43665adb54cSMatt Jacob } 43765adb54cSMatt Jacob 4389cd7268eSMatt Jacob static void 4392df76c16SMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp, int *nvp) 4409cd7268eSMatt Jacob { 4419cd7268eSMatt Jacob int tval; 442f7c631bcSMatt Jacob 443222bb542SMatt Jacob /* 4449ba86737SMatt Jacob * Figure out if we're supposed to skip this one. 4459ba86737SMatt Jacob */ 4466e5c5328SMatt Jacob tval = 0; 4472df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "disable", &tval) == 0 && tval) { 4489cd7268eSMatt Jacob device_printf(dev, "disabled at user request\n"); 4499cd7268eSMatt Jacob isp->isp_osinfo.disabled = 1; 4509cd7268eSMatt Jacob return; 451b9b599feSMatt Jacob } 4526e5c5328SMatt Jacob 4539cd7268eSMatt Jacob tval = 0; 4542df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) { 4559cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4569cd7268eSMatt Jacob } 4579cd7268eSMatt Jacob tval = 0; 4582df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) { 4599cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 4609cd7268eSMatt Jacob } 461336b5612SMatt Jacob tval = 0; 4622df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval); 463336b5612SMatt Jacob if (tval) { 464336b5612SMatt Jacob isp->isp_dblev = tval; 465336b5612SMatt Jacob } else { 466336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 467336b5612SMatt Jacob } 468336b5612SMatt Jacob if (bootverbose) { 469336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 470336b5612SMatt Jacob } 4712df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval); 4722df76c16SMatt Jacob if (tval > 0 && tval < 127) { 4732df76c16SMatt Jacob *nvp = tval; 4742df76c16SMatt Jacob } else { 4752df76c16SMatt Jacob *nvp = 0; 4762df76c16SMatt Jacob } 4772df76c16SMatt Jacob tval = 1; 4782df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "autoconfig", &tval); 4792df76c16SMatt Jacob isp_autoconfig = tval; 4802df76c16SMatt Jacob tval = 7; 4812df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval); 4822df76c16SMatt Jacob isp_quickboot_time = tval; 483336b5612SMatt Jacob 4842df76c16SMatt Jacob tval = 0; 4852df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "forcemulti", &tval) == 0 && tval != 0) { 4862df76c16SMatt Jacob isp->isp_osinfo.forcemulti = 1; 4872df76c16SMatt Jacob } 488336b5612SMatt Jacob } 489336b5612SMatt Jacob 490336b5612SMatt Jacob static void 491336b5612SMatt Jacob isp_get_pci_options(device_t dev, int *m1, int *m2) 492336b5612SMatt Jacob { 493336b5612SMatt Jacob int tval; 494336b5612SMatt Jacob /* 495336b5612SMatt Jacob * Which we should try first - memory mapping or i/o mapping? 496336b5612SMatt Jacob * 497336b5612SMatt Jacob * We used to try memory first followed by i/o on alpha, otherwise 498336b5612SMatt Jacob * the reverse, but we should just try memory first all the time now. 499336b5612SMatt Jacob */ 500336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 501336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 502336b5612SMatt Jacob 503336b5612SMatt Jacob tval = 0; 5042df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_iomap", &tval) == 0 && tval != 0) { 505336b5612SMatt Jacob *m1 = PCIM_CMD_PORTEN; 506336b5612SMatt Jacob *m2 = PCIM_CMD_MEMEN; 507336b5612SMatt Jacob } 508336b5612SMatt Jacob tval = 0; 5092df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_memmap", &tval) == 0 && tval != 0) { 510336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 511336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 512336b5612SMatt Jacob } 513336b5612SMatt Jacob } 514336b5612SMatt Jacob 515336b5612SMatt Jacob static void 5162df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) 517336b5612SMatt Jacob { 518336b5612SMatt Jacob const char *sptr; 519336b5612SMatt Jacob int tval; 520336b5612SMatt Jacob 5212df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "iid", &tval)) { 5222df76c16SMatt Jacob if (IS_FC(isp)) { 5232df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = 109 - chan; 5242df76c16SMatt Jacob } else { 525*17bc427dSMarius Strobl #ifdef __sparc64__ 526*17bc427dSMarius Strobl ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev); 527*17bc427dSMarius Strobl #else 5282df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = 7; 529*17bc427dSMarius Strobl #endif 5302df76c16SMatt Jacob } 5312df76c16SMatt Jacob } else { 5322df76c16SMatt Jacob if (IS_FC(isp)) { 5332df76c16SMatt Jacob ISP_FC_PC(isp, chan)->default_id = tval - chan; 5342df76c16SMatt Jacob } else { 5352df76c16SMatt Jacob ISP_SPI_PC(isp, chan)->iid = tval; 5362df76c16SMatt Jacob } 537336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 538336b5612SMatt Jacob } 5392df76c16SMatt Jacob 5402df76c16SMatt Jacob tval = -1; 5412df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "role", &tval) == 0) { 5422df76c16SMatt Jacob switch (tval) { 5432df76c16SMatt Jacob case ISP_ROLE_NONE: 5442df76c16SMatt Jacob case ISP_ROLE_INITIATOR: 5452df76c16SMatt Jacob case ISP_ROLE_TARGET: 5462df76c16SMatt Jacob case ISP_ROLE_INITIATOR|ISP_ROLE_TARGET: 5472df76c16SMatt Jacob device_printf(dev, "setting role to 0x%x\n", tval); 5482df76c16SMatt Jacob break; 5492df76c16SMatt Jacob default: 5502df76c16SMatt Jacob tval = -1; 5512df76c16SMatt Jacob break; 552336b5612SMatt Jacob } 553336b5612SMatt Jacob } 5542df76c16SMatt Jacob if (tval == -1) { 5552df76c16SMatt Jacob tval = ISP_DEFAULT_ROLES; 5562df76c16SMatt Jacob } 557336b5612SMatt Jacob 558336b5612SMatt Jacob if (IS_SCSI(isp)) { 5594ecb1d4aSMatt Jacob ISP_SPI_PC(isp, chan)->def_role = tval; 560336b5612SMatt Jacob return; 561336b5612SMatt Jacob } 5624ecb1d4aSMatt Jacob ISP_FC_PC(isp, chan)->def_role = tval; 563336b5612SMatt Jacob 5649cd7268eSMatt Jacob tval = 0; 5652df76c16SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fullduplex", &tval) == 0 && tval != 0) { 5669cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5679cd7268eSMatt Jacob } 5689cd7268eSMatt Jacob sptr = 0; 5692df76c16SMatt Jacob if (resource_string_value(device_get_name(dev), device_get_unit(dev), "topology", (const char **) &sptr) == 0 && sptr != 0) { 5709cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 5719cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 5729cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 5739cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5749cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 5759cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 5769cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 5779cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 5789cd7268eSMatt Jacob } 579960f6939SMatt Jacob } 580960f6939SMatt Jacob 5819ba86737SMatt Jacob /* 5829cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 5839cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 5849cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 5859cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 5869cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 5879cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 5889cd7268eSMatt Jacob */ 5899cd7268eSMatt Jacob sptr = 0; 5902df76c16SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "portwwn", (const char **) &sptr); 5919cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 5929cd7268eSMatt Jacob char *eptr = 0; 5932df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16); 5942df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) { 5959cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 5962df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwpn = 0; 5979cd7268eSMatt Jacob } 5989cd7268eSMatt Jacob } 5999cd7268eSMatt Jacob 6009cd7268eSMatt Jacob sptr = 0; 6012df76c16SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "nodewwn", (const char **) &sptr); 6029cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6039cd7268eSMatt Jacob char *eptr = 0; 6042df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16); 6052df76c16SMatt Jacob if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) { 6069cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6072df76c16SMatt Jacob ISP_FC_PC(isp, chan)->def_wwnn = 0; 6089cd7268eSMatt Jacob } 6099cd7268eSMatt Jacob } 6109cd7268eSMatt Jacob 61110365e5aSMatt Jacob tval = 0; 6122df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "hysteresis", &tval); 61310365e5aSMatt Jacob if (tval >= 0 && tval < 256) { 6142df76c16SMatt Jacob ISP_FC_PC(isp, chan)->hysteresis = tval; 61510365e5aSMatt Jacob } else { 6162df76c16SMatt Jacob ISP_FC_PC(isp, chan)->hysteresis = isp_fabric_hysteresis; 61710365e5aSMatt Jacob } 61810365e5aSMatt Jacob 619f7c631bcSMatt Jacob tval = -1; 6202df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "loop_down_limit", &tval); 62110365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6222df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = tval; 62310365e5aSMatt Jacob } else { 6242df76c16SMatt Jacob ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit; 62510365e5aSMatt Jacob } 62610365e5aSMatt Jacob 627f7c631bcSMatt Jacob tval = -1; 6282df76c16SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "gone_device_time", &tval); 629f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 6302df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = tval; 631f7c631bcSMatt Jacob } else { 6322df76c16SMatt Jacob ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time; 633f7c631bcSMatt Jacob } 6349cd7268eSMatt Jacob } 6359cd7268eSMatt Jacob 6369cd7268eSMatt Jacob static int 6379cd7268eSMatt Jacob isp_pci_attach(device_t dev) 6389cd7268eSMatt Jacob { 6399cd7268eSMatt Jacob struct resource *regs, *irq; 6402df76c16SMatt Jacob int rtp, rgd, iqd, i, m1, m2, locksetup = 0; 6412df76c16SMatt Jacob int isp_nvports = 0; 6422df76c16SMatt Jacob uint32_t data, cmd, linesz, did; 6439cd7268eSMatt Jacob struct isp_pcisoftc *pcs; 6449cd7268eSMatt Jacob ispsoftc_t *isp = NULL; 6452df76c16SMatt Jacob size_t psize, xsize; 6462df76c16SMatt Jacob char fwname[32]; 6479cd7268eSMatt Jacob 6489cd7268eSMatt Jacob pcs = device_get_softc(dev); 6499cd7268eSMatt Jacob if (pcs == NULL) { 6509cd7268eSMatt Jacob device_printf(dev, "cannot get softc\n"); 6519cd7268eSMatt Jacob return (ENOMEM); 6529cd7268eSMatt Jacob } 6539cd7268eSMatt Jacob memset(pcs, 0, sizeof (*pcs)); 6542df76c16SMatt Jacob 6559cd7268eSMatt Jacob pcs->pci_dev = dev; 6569cd7268eSMatt Jacob isp = &pcs->pci_isp; 6572df76c16SMatt Jacob isp->isp_dev = dev; 6582df76c16SMatt Jacob isp->isp_nchan = 1; 6599cd7268eSMatt Jacob 6609cd7268eSMatt Jacob /* 661336b5612SMatt Jacob * Get Generic Options 6629cd7268eSMatt Jacob */ 6632df76c16SMatt Jacob isp_get_generic_options(dev, isp, &isp_nvports); 6649cd7268eSMatt Jacob 6659cd7268eSMatt Jacob /* 6669cd7268eSMatt Jacob * Check to see if options have us disabled 6679cd7268eSMatt Jacob */ 6689cd7268eSMatt Jacob if (isp->isp_osinfo.disabled) { 6699cd7268eSMatt Jacob /* 6709cd7268eSMatt Jacob * But return zero to preserve unit numbering 6719cd7268eSMatt Jacob */ 6729cd7268eSMatt Jacob return (0); 6739cd7268eSMatt Jacob } 6749cd7268eSMatt Jacob 6759cd7268eSMatt Jacob /* 6769cd7268eSMatt Jacob * Get PCI options- which in this case are just mapping preferences. 6779cd7268eSMatt Jacob */ 6789cd7268eSMatt Jacob isp_get_pci_options(dev, &m1, &m2); 6799cd7268eSMatt Jacob 680ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 681960f6939SMatt Jacob irq = regs = NULL; 682960f6939SMatt Jacob rgd = rtp = iqd = 0; 683960f6939SMatt Jacob 684b49c4674SMatt Jacob cmd = pci_read_config(dev, PCIR_COMMAND, 2); 685960f6939SMatt Jacob if (cmd & m1) { 686960f6939SMatt Jacob rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 687960f6939SMatt Jacob rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 6885f96beb9SNate Lawson regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE); 68965adb54cSMatt Jacob } 690960f6939SMatt Jacob if (regs == NULL && (cmd & m2)) { 691960f6939SMatt Jacob rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 692960f6939SMatt Jacob rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 6935f96beb9SNate Lawson regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE); 69465adb54cSMatt Jacob } 695960f6939SMatt Jacob if (regs == NULL) { 696960f6939SMatt Jacob device_printf(dev, "unable to map any ports\n"); 697960f6939SMatt Jacob goto bad; 69865adb54cSMatt Jacob } 6999cd7268eSMatt Jacob if (bootverbose) { 7002df76c16SMatt Jacob device_printf(dev, "using %s space register mapping\n", (rgd == IO_MAP_REG)? "I/O" : "Memory"); 7019cd7268eSMatt Jacob } 7026a7d12e1SMatt Jacob isp->isp_bus_tag = rman_get_bustag(regs); 7036a7d12e1SMatt Jacob isp->isp_bus_handle = rman_get_bushandle(regs); 70465adb54cSMatt Jacob 7052df76c16SMatt Jacob pcs->pci_dev = dev; 7062df76c16SMatt Jacob pcs->pci_reg = regs; 707d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 708d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 709d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 710d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 711d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 7122df76c16SMatt Jacob 7132df76c16SMatt Jacob switch (pci_get_devid(dev)) { 7142df76c16SMatt Jacob case PCI_QLOGIC_ISP1020: 7152df76c16SMatt Jacob did = 0x1040; 7162df76c16SMatt Jacob isp->isp_mdvec = &mdvec; 7172df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 7182df76c16SMatt Jacob break; 7192df76c16SMatt Jacob case PCI_QLOGIC_ISP1080: 7202df76c16SMatt Jacob did = 0x1080; 7212df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7222df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 7232df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7242df76c16SMatt Jacob break; 7252df76c16SMatt Jacob case PCI_QLOGIC_ISP1240: 7262df76c16SMatt Jacob did = 0x1080; 7272df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7282df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1240; 7292df76c16SMatt Jacob isp->isp_nchan = 2; 7302df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7312df76c16SMatt Jacob break; 7322df76c16SMatt Jacob case PCI_QLOGIC_ISP1280: 7332df76c16SMatt Jacob did = 0x1080; 7342df76c16SMatt Jacob isp->isp_mdvec = &mdvec_1080; 7352df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_1280; 7362df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7372df76c16SMatt Jacob break; 7382df76c16SMatt Jacob case PCI_QLOGIC_ISP10160: 7392df76c16SMatt Jacob did = 0x12160; 7402df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7412df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_10160; 7422df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7432df76c16SMatt Jacob break; 7442df76c16SMatt Jacob case PCI_QLOGIC_ISP12160: 7452df76c16SMatt Jacob did = 0x12160; 7462df76c16SMatt Jacob isp->isp_nchan = 2; 7472df76c16SMatt Jacob isp->isp_mdvec = &mdvec_12160; 7482df76c16SMatt Jacob isp->isp_type = ISP_HA_SCSI_12160; 7492df76c16SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; 7502df76c16SMatt Jacob break; 7512df76c16SMatt Jacob case PCI_QLOGIC_ISP2100: 7522df76c16SMatt Jacob did = 0x2100; 7532df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2100; 7542df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2100; 7552df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 756960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 757ab6d0040SMatt Jacob /* 758ab6d0040SMatt Jacob * XXX: Need to get the actual revision 759ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 760ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 761ab6d0040SMatt Jacob * XXX; boards. 762ab6d0040SMatt Jacob */ 763ab6d0040SMatt Jacob linesz = 1; 764ab6d0040SMatt Jacob } 7652df76c16SMatt Jacob break; 7662df76c16SMatt Jacob case PCI_QLOGIC_ISP2200: 7672df76c16SMatt Jacob did = 0x2200; 7682df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2200; 7692df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2200; 7702df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; 7712df76c16SMatt Jacob break; 7722df76c16SMatt Jacob case PCI_QLOGIC_ISP2300: 7732df76c16SMatt Jacob did = 0x2300; 7742df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7752df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2300; 7762df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7772df76c16SMatt Jacob break; 7782df76c16SMatt Jacob case PCI_QLOGIC_ISP2312: 7792df76c16SMatt Jacob case PCI_QLOGIC_ISP6312: 7802df76c16SMatt Jacob did = 0x2300; 7812df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7822df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2312; 7832df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7842df76c16SMatt Jacob break; 7852df76c16SMatt Jacob case PCI_QLOGIC_ISP2322: 7862df76c16SMatt Jacob case PCI_QLOGIC_ISP6322: 7872df76c16SMatt Jacob did = 0x2322; 7882df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2300; 7892df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2322; 7902df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; 7912df76c16SMatt Jacob break; 7922df76c16SMatt Jacob case PCI_QLOGIC_ISP2422: 7932df76c16SMatt Jacob case PCI_QLOGIC_ISP2432: 7942df76c16SMatt Jacob did = 0x2400; 7952df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 7962df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2400; 7972df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2400; 7982df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 7992df76c16SMatt Jacob break; 8002df76c16SMatt Jacob case PCI_QLOGIC_ISP2532: 8012df76c16SMatt Jacob did = 0x2500; 8022df76c16SMatt Jacob isp->isp_nchan += isp_nvports; 8032df76c16SMatt Jacob isp->isp_mdvec = &mdvec_2500; 8042df76c16SMatt Jacob isp->isp_type = ISP_HA_FC_2500; 8052df76c16SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF; 8062df76c16SMatt Jacob break; 8072df76c16SMatt Jacob default: 8082df76c16SMatt Jacob device_printf(dev, "unknown device type\n"); 8092df76c16SMatt Jacob goto bad; 8102df76c16SMatt Jacob break; 81165adb54cSMatt Jacob } 8122df76c16SMatt Jacob isp->isp_revision = pci_get_revid(dev); 8132df76c16SMatt Jacob 8142df76c16SMatt Jacob if (IS_FC(isp)) { 815222bb542SMatt Jacob psize = sizeof (fcparam); 8162df76c16SMatt Jacob xsize = sizeof (struct isp_fc); 8172df76c16SMatt Jacob } else { 8182df76c16SMatt Jacob psize = sizeof (sdparam); 8192df76c16SMatt Jacob xsize = sizeof (struct isp_spi); 820222bb542SMatt Jacob } 8212df76c16SMatt Jacob psize *= isp->isp_nchan; 8222df76c16SMatt Jacob xsize *= isp->isp_nchan; 8237cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 824c6608df3SMatt Jacob if (isp->isp_param == NULL) { 825960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 826960f6939SMatt Jacob goto bad; 827c6608df3SMatt Jacob } 8282df76c16SMatt Jacob isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO); 8292df76c16SMatt Jacob if (isp->isp_osinfo.pc.ptr == NULL) { 8302df76c16SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 8312df76c16SMatt Jacob goto bad; 8322df76c16SMatt Jacob } 83365adb54cSMatt Jacob 834336b5612SMatt Jacob /* 835336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 836336b5612SMatt Jacob */ 8372df76c16SMatt Jacob for (i = 0; i < isp->isp_nchan; i++) { 8382df76c16SMatt Jacob isp_get_specific_options(dev, i, isp); 8399a5af410SMatt Jacob } 8409a5af410SMatt Jacob 8412df76c16SMatt Jacob /* 8422df76c16SMatt Jacob * The 'it' suffix really only matters for SCSI cards in target mode. 8432df76c16SMatt Jacob */ 8449a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 8454ecb1d4aSMatt Jacob if (IS_SCSI(isp) && (ISP_SPI_PC(isp, 0)->def_role & ISP_ROLE_TARGET)) { 8469a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x_it", did); 8479a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8482df76c16SMatt Jacob } else if (IS_24XX(isp) && (isp->isp_nchan > 1 || isp->isp_osinfo.forcemulti)) { 8492df76c16SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x_multi", did); 8502df76c16SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8519a5af410SMatt Jacob } 8529a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 8539a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 8549a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 8559a5af410SMatt Jacob } 8569a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 8575f634111SMatt Jacob isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data; 8589a5af410SMatt Jacob } 85956aef503SMatt Jacob 86056aef503SMatt Jacob /* 861d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 862d951bbcaSMatt Jacob * are set. 863d951bbcaSMatt Jacob */ 864960f6939SMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | 865960f6939SMatt Jacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 8669a5af410SMatt Jacob 86775c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 86875c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 86975c1e828SMatt Jacob } 8709a5af410SMatt Jacob 8718a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 8728a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 8738a97c03aSMatt Jacob } 8748a97c03aSMatt Jacob 87506cacb29SMatt Jacob if (IS_24XX(isp)) { 87606cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 87706cacb29SMatt Jacob } 87810365e5aSMatt Jacob 879b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 880ab6d0040SMatt Jacob 881d951bbcaSMatt Jacob /* 882222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 883d951bbcaSMatt Jacob */ 884960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 8856a7d12e1SMatt Jacob if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) { 8862df76c16SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d from %d", linesz, data); 8876a7d12e1SMatt Jacob data = linesz; 888960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 889d951bbcaSMatt Jacob } 890ab6d0040SMatt Jacob 891d951bbcaSMatt Jacob /* 892d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 893d951bbcaSMatt Jacob */ 894960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 895d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 896d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 897d02373f1SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI latency to %d", data); 898960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 899d951bbcaSMatt Jacob } 900ab6d0040SMatt Jacob 901ab6d0040SMatt Jacob /* 902ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 903ab6d0040SMatt Jacob */ 904960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 905ab6d0040SMatt Jacob data &= ~1; 906960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 9072df76c16SMatt Jacob 9082df76c16SMatt Jacob /* 9092df76c16SMatt Jacob * Do MSI 9102df76c16SMatt Jacob * 9112df76c16SMatt Jacob * NB: MSI-X needs to be disabled for the 2432 (PCI-Express) 9122df76c16SMatt Jacob */ 9130a70657fSMatt Jacob if (IS_24XX(isp) || IS_2322(isp)) { 9140a70657fSMatt Jacob pcs->msicount = pci_msi_count(dev); 9150a70657fSMatt Jacob if (pcs->msicount > 1) { 9160a70657fSMatt Jacob pcs->msicount = 1; 9170a70657fSMatt Jacob } 9180a70657fSMatt Jacob if (pci_alloc_msi(dev, &pcs->msicount) == 0) { 9190a70657fSMatt Jacob iqd = 1; 9200a70657fSMatt Jacob } else { 921960f6939SMatt Jacob iqd = 0; 9220a70657fSMatt Jacob } 9230a70657fSMatt Jacob } 9242df76c16SMatt Jacob irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | RF_SHAREABLE); 925960f6939SMatt Jacob if (irq == NULL) { 926960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 927960f6939SMatt Jacob goto bad; 928960f6939SMatt Jacob } 929960f6939SMatt Jacob 930f09b1922SMatt Jacob /* Make sure the lock is set up. */ 9316008862bSJohn Baldwin mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); 932f09b1922SMatt Jacob locksetup++; 933f09b1922SMatt Jacob 9342df76c16SMatt Jacob if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { 935f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 936f09b1922SMatt Jacob goto bad; 937f09b1922SMatt Jacob } 938960f6939SMatt Jacob 93905fbcbb0SMatt Jacob /* 94075c1e828SMatt Jacob * Last minute checks... 94175c1e828SMatt Jacob */ 94210365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 94375c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 94475c1e828SMatt Jacob } 94575c1e828SMatt Jacob 94675c1e828SMatt Jacob /* 94705fbcbb0SMatt Jacob * Make sure we're in reset state. 94805fbcbb0SMatt Jacob */ 9493395b056SMatt Jacob ISP_LOCK(isp); 9502df76c16SMatt Jacob isp_reset(isp, 1); 95165adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 9523395b056SMatt Jacob ISP_UNLOCK(isp); 953960f6939SMatt Jacob goto bad; 95465adb54cSMatt Jacob } 95565adb54cSMatt Jacob isp_init(isp); 9562df76c16SMatt Jacob if (isp->isp_state == ISP_INITSTATE) { 9572df76c16SMatt Jacob isp->isp_state = ISP_RUNSTATE; 9582df76c16SMatt Jacob } 9592df76c16SMatt Jacob ISP_UNLOCK(isp); 9602df76c16SMatt Jacob if (isp_attach(isp)) { 9612df76c16SMatt Jacob ISP_LOCK(isp); 96265adb54cSMatt Jacob isp_uninit(isp); 9633395b056SMatt Jacob ISP_UNLOCK(isp); 964960f6939SMatt Jacob goto bad; 965d59bd469SMatt Jacob } 966960f6939SMatt Jacob return (0); 967960f6939SMatt Jacob 968960f6939SMatt Jacob bad: 969960f6939SMatt Jacob if (pcs && pcs->ih) { 970960f6939SMatt Jacob (void) bus_teardown_intr(dev, irq, pcs->ih); 971960f6939SMatt Jacob } 9723395b056SMatt Jacob if (locksetup && isp) { 9733395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 9743395b056SMatt Jacob } 975960f6939SMatt Jacob if (irq) { 976960f6939SMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq); 977960f6939SMatt Jacob } 9780a70657fSMatt Jacob if (pcs && pcs->msicount) { 9790a70657fSMatt Jacob pci_release_msi(dev); 9800a70657fSMatt Jacob } 981960f6939SMatt Jacob if (regs) { 982960f6939SMatt Jacob (void) bus_release_resource(dev, rtp, rgd, regs); 983960f6939SMatt Jacob } 984960f6939SMatt Jacob if (pcs) { 9859cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 986960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 9872df76c16SMatt Jacob pcs->pci_isp.isp_param = NULL; 9882df76c16SMatt Jacob } 9892df76c16SMatt Jacob if (pcs->pci_isp.isp_osinfo.pc.ptr) { 9902df76c16SMatt Jacob free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); 9912df76c16SMatt Jacob pcs->pci_isp.isp_osinfo.pc.ptr = NULL; 9929cd7268eSMatt Jacob } 99365adb54cSMatt Jacob } 994960f6939SMatt Jacob return (ENXIO); 99565adb54cSMatt Jacob } 99665adb54cSMatt Jacob 99710365e5aSMatt Jacob static int 99810365e5aSMatt Jacob isp_pci_detach(device_t dev) 99910365e5aSMatt Jacob { 100010365e5aSMatt Jacob struct isp_pcisoftc *pcs; 100110365e5aSMatt Jacob ispsoftc_t *isp; 100210365e5aSMatt Jacob 100310365e5aSMatt Jacob pcs = device_get_softc(dev); 100410365e5aSMatt Jacob if (pcs == NULL) { 100510365e5aSMatt Jacob return (ENXIO); 100610365e5aSMatt Jacob } 100710365e5aSMatt Jacob isp = (ispsoftc_t *) pcs; 100810365e5aSMatt Jacob ISP_DISABLE_INTS(isp); 10092df76c16SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 101010365e5aSMatt Jacob return (0); 101110365e5aSMatt Jacob } 101210365e5aSMatt Jacob 1013126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 1014126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 10154cc9e3e7SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xfff)) 1016126ec864SMatt Jacob 10176a7d12e1SMatt Jacob #define BXR2(isp, off) \ 10186a7d12e1SMatt Jacob bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off) 10196a7d12e1SMatt Jacob #define BXW2(isp, off, v) \ 10206a7d12e1SMatt Jacob bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, off, v) 10216a7d12e1SMatt Jacob #define BXR4(isp, off) \ 10226a7d12e1SMatt Jacob bus_space_read_4(isp->isp_bus_tag, isp->isp_bus_handle, off) 10236a7d12e1SMatt Jacob #define BXW4(isp, off, v) \ 10246a7d12e1SMatt Jacob bus_space_write_4(isp->isp_bus_tag, isp->isp_bus_handle, off, v) 1025126ec864SMatt Jacob 1026126ec864SMatt Jacob 10272df76c16SMatt Jacob static ISP_INLINE int 10289cd7268eSMatt Jacob isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) 1029126ec864SMatt Jacob { 103010365e5aSMatt Jacob uint32_t val0, val1; 1031126ec864SMatt Jacob int i = 0; 1032126ec864SMatt Jacob 1033126ec864SMatt Jacob do { 10346a7d12e1SMatt Jacob val0 = BXR2(isp, IspVirt2Off(isp, off)); 10356a7d12e1SMatt Jacob val1 = BXR2(isp, IspVirt2Off(isp, off)); 1036126ec864SMatt Jacob } while (val0 != val1 && ++i < 1000); 1037126ec864SMatt Jacob if (val0 != val1) { 1038126ec864SMatt Jacob return (1); 1039126ec864SMatt Jacob } 1040126ec864SMatt Jacob *rp = val0; 1041126ec864SMatt Jacob return (0); 1042126ec864SMatt Jacob } 1043126ec864SMatt Jacob 1044126ec864SMatt Jacob static int 10450a70657fSMatt Jacob isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp) 1046126ec864SMatt Jacob { 10471dae40ebSMatt Jacob uint16_t isr, sema; 1048126ec864SMatt Jacob 1049126ec864SMatt Jacob if (IS_2100(isp)) { 1050126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { 1051126ec864SMatt Jacob return (0); 1052126ec864SMatt Jacob } 1053126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { 1054126ec864SMatt Jacob return (0); 1055126ec864SMatt Jacob } 1056126ec864SMatt Jacob } else { 10576a7d12e1SMatt Jacob isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR)); 10586a7d12e1SMatt Jacob sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA)); 1059126ec864SMatt Jacob } 1060126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 1061126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 1062126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 1063126ec864SMatt Jacob if (isr == 0 && sema == 0) { 1064126ec864SMatt Jacob return (0); 1065126ec864SMatt Jacob } 1066126ec864SMatt Jacob *isrp = isr; 1067126ec864SMatt Jacob if ((*semap = sema) != 0) { 1068126ec864SMatt Jacob if (IS_2100(isp)) { 1069126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) { 1070126ec864SMatt Jacob return (0); 1071126ec864SMatt Jacob } 1072126ec864SMatt Jacob } else { 10736a7d12e1SMatt Jacob *mbp = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0)); 1074126ec864SMatt Jacob } 1075126ec864SMatt Jacob } 1076126ec864SMatt Jacob return (1); 1077126ec864SMatt Jacob } 1078126ec864SMatt Jacob 1079126ec864SMatt Jacob static int 1080443e752dSMatt Jacob isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbox0p) 1081126ec864SMatt Jacob { 108210365e5aSMatt Jacob uint32_t hccr; 10831dae40ebSMatt Jacob uint32_t r2hisr; 1084126ec864SMatt Jacob 10856a7d12e1SMatt Jacob if (!(BXR2(isp, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 10863bd40330SMatt Jacob *isrp = 0; 1087db4fa023SMatt Jacob return (0); 10883bd40330SMatt Jacob } 10896a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO)); 1090126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 1091126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 1092126ec864SMatt Jacob *isrp = 0; 1093126ec864SMatt Jacob return (0); 1094126ec864SMatt Jacob } 1095126ec864SMatt Jacob switch (r2hisr & BIU_R2HST_ISTAT_MASK) { 1096126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1097126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1098126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1099126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 1100126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 1101126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1102126ec864SMatt Jacob *mbox0p = (r2hisr >> 16); 1103126ec864SMatt Jacob *semap = 1; 1104126ec864SMatt Jacob return (1); 1105fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 1106fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1107443e752dSMatt Jacob *mbox0p = ASYNC_RIO16_1; 1108fc3bbaaaSMatt Jacob *semap = 1; 1109fc3bbaaaSMatt Jacob return (1); 1110fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 1111fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1112fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CMD_CMPLT; 1113fc3bbaaaSMatt Jacob *semap = 1; 1114fc3bbaaaSMatt Jacob return (1); 1115fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 1116fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1117fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CTIO_DONE; 1118fc3bbaaaSMatt Jacob *semap = 1; 1119fc3bbaaaSMatt Jacob return (1); 1120126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 1121126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1122126ec864SMatt Jacob *mbox0p = 0; 1123126ec864SMatt Jacob *semap = 0; 1124126ec864SMatt Jacob return (1); 1125126ec864SMatt Jacob default: 11268a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 11278a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 11288a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 1129443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR)); 11305ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 11318a97c03aSMatt Jacob } else { 1132443e752dSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 11338a97c03aSMatt Jacob } 1134126ec864SMatt Jacob return (0); 1135126ec864SMatt Jacob } 1136126ec864SMatt Jacob } 1137126ec864SMatt Jacob 113810365e5aSMatt Jacob static int 1139443e752dSMatt Jacob isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbox0p) 114010365e5aSMatt Jacob { 114110365e5aSMatt Jacob uint32_t r2hisr; 114210365e5aSMatt Jacob 11436a7d12e1SMatt Jacob r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO)); 114410365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 114510365e5aSMatt Jacob if ((r2hisr & BIU2400_R2HST_INTR) == 0) { 114610365e5aSMatt Jacob *isrp = 0; 114710365e5aSMatt Jacob return (0); 114810365e5aSMatt Jacob } 114910365e5aSMatt Jacob switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) { 115010365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_OK: 115110365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_FAIL: 115210365e5aSMatt Jacob case ISP2400R2HST_MBX_OK: 115310365e5aSMatt Jacob case ISP2400R2HST_MBX_FAIL: 115410365e5aSMatt Jacob case ISP2400R2HST_ASYNC_EVENT: 115510365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 115610365e5aSMatt Jacob *mbox0p = (r2hisr >> 16); 115710365e5aSMatt Jacob *semap = 1; 115810365e5aSMatt Jacob return (1); 115910365e5aSMatt Jacob case ISP2400R2HST_RSPQ_UPDATE: 116010365e5aSMatt Jacob case ISP2400R2HST_ATIO_RSPQ_UPDATE: 116110365e5aSMatt Jacob case ISP2400R2HST_ATIO_RQST_UPDATE: 116210365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 116310365e5aSMatt Jacob *mbox0p = 0; 116410365e5aSMatt Jacob *semap = 0; 116510365e5aSMatt Jacob return (1); 116610365e5aSMatt Jacob default: 116710365e5aSMatt Jacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 116810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 116910365e5aSMatt Jacob return (0); 117010365e5aSMatt Jacob } 117110365e5aSMatt Jacob } 117210365e5aSMatt Jacob 117310365e5aSMatt Jacob static uint32_t 11749cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 117565adb54cSMatt Jacob { 11766a7d12e1SMatt Jacob uint16_t rv; 1177126ec864SMatt Jacob int oldconf = 0; 117865adb54cSMatt Jacob 1179d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 118065adb54cSMatt Jacob /* 118165adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 118265adb54cSMatt Jacob */ 11836a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 1184443e752dSMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); 11856a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 118665adb54cSMatt Jacob } 11876a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 1188d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 11896a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 11906a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 119165adb54cSMatt Jacob } 119265adb54cSMatt Jacob return (rv); 119365adb54cSMatt Jacob } 119465adb54cSMatt Jacob 119565adb54cSMatt Jacob static void 119610365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 119765adb54cSMatt Jacob { 1198126ec864SMatt Jacob int oldconf = 0; 1199d59bd469SMatt Jacob 1200d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 120165adb54cSMatt Jacob /* 120265adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 120365adb54cSMatt Jacob */ 12046a7d12e1SMatt Jacob oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12056a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1206126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 12076a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 120865adb54cSMatt Jacob } 12096a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 12106a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); 1211d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 12126a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf); 12136a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 121465adb54cSMatt Jacob } 12156a7d12e1SMatt Jacob 1216f9734398SMatt Jacob } 121765adb54cSMatt Jacob 121810365e5aSMatt Jacob static uint32_t 12199cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1220d59bd469SMatt Jacob { 122110365e5aSMatt Jacob uint32_t rv, oc = 0; 1222d59bd469SMatt Jacob 122322e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 122422e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 122510365e5aSMatt Jacob uint32_t tc; 1226d59bd469SMatt Jacob /* 1227d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1228d59bd469SMatt Jacob */ 12296a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 123022e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 123122e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 123222e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 123322e1dc85SMatt Jacob else 123422e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12356a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 12366a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 1237d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12386a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12396a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1240126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 12416a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 1242d59bd469SMatt Jacob } 12436a7d12e1SMatt Jacob rv = BXR2(isp, IspVirt2Off(isp, regoff)); 124422e1dc85SMatt Jacob if (oc) { 12456a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 12466a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 1247d59bd469SMatt Jacob } 1248d59bd469SMatt Jacob return (rv); 1249d59bd469SMatt Jacob } 1250d59bd469SMatt Jacob 1251d59bd469SMatt Jacob static void 125210365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1253d59bd469SMatt Jacob { 1254126ec864SMatt Jacob int oc = 0; 1255d59bd469SMatt Jacob 125622e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 125722e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 125810365e5aSMatt Jacob uint32_t tc; 1259d59bd469SMatt Jacob /* 1260d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1261d59bd469SMatt Jacob */ 12626a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 126322e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 126422e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 126522e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 126622e1dc85SMatt Jacob else 126722e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 12686a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc); 12696a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 1270d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 12716a7d12e1SMatt Jacob oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1)); 12726a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), 1273126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 12746a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 1275d59bd469SMatt Jacob } 12766a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 12776a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); 127822e1dc85SMatt Jacob if (oc) { 12796a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc); 12806a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2); 128110365e5aSMatt Jacob } 128210365e5aSMatt Jacob } 128310365e5aSMatt Jacob 128410365e5aSMatt Jacob static uint32_t 128510365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 128610365e5aSMatt Jacob { 128710365e5aSMatt Jacob uint32_t rv; 128810365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 128910365e5aSMatt Jacob 129010365e5aSMatt Jacob switch (block) { 129110365e5aSMatt Jacob case BIU_BLOCK: 129210365e5aSMatt Jacob break; 129310365e5aSMatt Jacob case MBOX_BLOCK: 12946a7d12e1SMatt Jacob return (BXR2(isp, IspVirt2Off(isp, regoff))); 129510365e5aSMatt Jacob case SXP_BLOCK: 129610365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); 129710365e5aSMatt Jacob return (0xffffffff); 129810365e5aSMatt Jacob case RISC_BLOCK: 129910365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); 130010365e5aSMatt Jacob return (0xffffffff); 130110365e5aSMatt Jacob case DMA_BLOCK: 130210365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); 130310365e5aSMatt Jacob return (0xffffffff); 130410365e5aSMatt Jacob default: 130510365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); 130610365e5aSMatt Jacob return (0xffffffff); 130710365e5aSMatt Jacob } 130810365e5aSMatt Jacob 130910365e5aSMatt Jacob 131010365e5aSMatt Jacob switch (regoff) { 131110365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 131210365e5aSMatt Jacob case BIU2400_FLASH_DATA: 131310365e5aSMatt Jacob case BIU2400_ICR: 131410365e5aSMatt Jacob case BIU2400_ISR: 131510365e5aSMatt Jacob case BIU2400_CSR: 131610365e5aSMatt Jacob case BIU2400_REQINP: 131710365e5aSMatt Jacob case BIU2400_REQOUTP: 131810365e5aSMatt Jacob case BIU2400_RSPINP: 131910365e5aSMatt Jacob case BIU2400_RSPOUTP: 13202df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13212df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 132210365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13232df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 132410365e5aSMatt Jacob case BIU2400_HCCR: 132510365e5aSMatt Jacob case BIU2400_GPIOD: 132610365e5aSMatt Jacob case BIU2400_GPIOE: 132710365e5aSMatt Jacob case BIU2400_HSEMA: 13286a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 132910365e5aSMatt Jacob break; 133010365e5aSMatt Jacob case BIU2400_R2HSTSLO: 13316a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)); 133210365e5aSMatt Jacob break; 133310365e5aSMatt Jacob case BIU2400_R2HSTSHI: 13346a7d12e1SMatt Jacob rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16; 133510365e5aSMatt Jacob break; 133610365e5aSMatt Jacob default: 133710365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 133810365e5aSMatt Jacob "isp_pci_rd_reg_2400: unknown offset %x", regoff); 133910365e5aSMatt Jacob rv = 0xffffffff; 134010365e5aSMatt Jacob break; 134110365e5aSMatt Jacob } 134210365e5aSMatt Jacob return (rv); 134310365e5aSMatt Jacob } 134410365e5aSMatt Jacob 134510365e5aSMatt Jacob static void 134610365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 134710365e5aSMatt Jacob { 134810365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 134910365e5aSMatt Jacob 135010365e5aSMatt Jacob switch (block) { 135110365e5aSMatt Jacob case BIU_BLOCK: 135210365e5aSMatt Jacob break; 135310365e5aSMatt Jacob case MBOX_BLOCK: 13546a7d12e1SMatt Jacob BXW2(isp, IspVirt2Off(isp, regoff), val); 13556a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2); 135610365e5aSMatt Jacob return; 135710365e5aSMatt Jacob case SXP_BLOCK: 135810365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); 135910365e5aSMatt Jacob return; 136010365e5aSMatt Jacob case RISC_BLOCK: 136110365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); 136210365e5aSMatt Jacob return; 136310365e5aSMatt Jacob case DMA_BLOCK: 136410365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); 136510365e5aSMatt Jacob return; 136610365e5aSMatt Jacob default: 136710365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", 136810365e5aSMatt Jacob regoff); 136910365e5aSMatt Jacob break; 137010365e5aSMatt Jacob } 137110365e5aSMatt Jacob 137210365e5aSMatt Jacob switch (regoff) { 137310365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 137410365e5aSMatt Jacob case BIU2400_FLASH_DATA: 137510365e5aSMatt Jacob case BIU2400_ICR: 137610365e5aSMatt Jacob case BIU2400_ISR: 137710365e5aSMatt Jacob case BIU2400_CSR: 137810365e5aSMatt Jacob case BIU2400_REQINP: 137910365e5aSMatt Jacob case BIU2400_REQOUTP: 138010365e5aSMatt Jacob case BIU2400_RSPINP: 138110365e5aSMatt Jacob case BIU2400_RSPOUTP: 13822df76c16SMatt Jacob case BIU2400_PRI_REQINP: 13832df76c16SMatt Jacob case BIU2400_PRI_REQOUTP: 138410365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 13852df76c16SMatt Jacob case BIU2400_ATIO_RSPOUTP: 138610365e5aSMatt Jacob case BIU2400_HCCR: 138710365e5aSMatt Jacob case BIU2400_GPIOD: 138810365e5aSMatt Jacob case BIU2400_GPIOE: 138910365e5aSMatt Jacob case BIU2400_HSEMA: 13906a7d12e1SMatt Jacob BXW4(isp, IspVirt2Off(isp, regoff), val); 13916a7d12e1SMatt Jacob MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4); 139210365e5aSMatt Jacob break; 139310365e5aSMatt Jacob default: 139410365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 139510365e5aSMatt Jacob "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); 139610365e5aSMatt Jacob break; 1397d59bd469SMatt Jacob } 1398d59bd469SMatt Jacob } 1399d59bd469SMatt Jacob 1400d720e6d5SJustin T. Gibbs 1401222bb542SMatt Jacob struct imush { 14029cd7268eSMatt Jacob ispsoftc_t *isp; 14032df76c16SMatt Jacob caddr_t vbase; 14042df76c16SMatt Jacob int chan; 1405222bb542SMatt Jacob int error; 1406222bb542SMatt Jacob }; 1407222bb542SMatt Jacob 14081923f739SMatt Jacob static void imc(void *, bus_dma_segment_t *, int, int); 14092df76c16SMatt Jacob static void imc1(void *, bus_dma_segment_t *, int, int); 14101923f739SMatt Jacob 1411d720e6d5SJustin T. Gibbs static void 14121923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1413d720e6d5SJustin T. Gibbs { 1414222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 14152df76c16SMatt Jacob 1416222bb542SMatt Jacob if (error) { 1417222bb542SMatt Jacob imushp->error = error; 14182df76c16SMatt Jacob return; 14192df76c16SMatt Jacob } 14202df76c16SMatt Jacob if (nseg != 1) { 14212df76c16SMatt Jacob imushp->error = EINVAL; 14222df76c16SMatt Jacob return; 14232df76c16SMatt Jacob } 14242df76c16SMatt Jacob imushp->isp->isp_rquest = imushp->vbase; 14252df76c16SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 14262df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 14272df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp)); 14282df76c16SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 14292df76c16SMatt Jacob imushp->isp->isp_result = imushp->vbase; 14301923f739SMatt Jacob 14312df76c16SMatt Jacob #ifdef ISP_TARGET_MODE 14322df76c16SMatt Jacob if (IS_24XX(imushp->isp)) { 14332df76c16SMatt Jacob segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 14342df76c16SMatt Jacob imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp)); 14352df76c16SMatt Jacob imushp->isp->isp_atioq_dma = segs->ds_addr; 14362df76c16SMatt Jacob imushp->isp->isp_atioq = imushp->vbase; 14371923f739SMatt Jacob } 14382df76c16SMatt Jacob #endif 1439222bb542SMatt Jacob } 14402df76c16SMatt Jacob 14412df76c16SMatt Jacob static void 14422df76c16SMatt Jacob imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error) 14432df76c16SMatt Jacob { 14442df76c16SMatt Jacob struct imush *imushp = (struct imush *) arg; 14452df76c16SMatt Jacob if (error) { 14462df76c16SMatt Jacob imushp->error = error; 14472df76c16SMatt Jacob return; 14482df76c16SMatt Jacob } 14492df76c16SMatt Jacob if (nseg != 1) { 14502df76c16SMatt Jacob imushp->error = EINVAL; 14512df76c16SMatt Jacob return; 14522df76c16SMatt Jacob } 14532df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr; 14542df76c16SMatt Jacob FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase; 1455d720e6d5SJustin T. Gibbs } 1456d720e6d5SJustin T. Gibbs 1457d720e6d5SJustin T. Gibbs static int 14589cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1459d720e6d5SJustin T. Gibbs { 1460d720e6d5SJustin T. Gibbs caddr_t base; 14611dae40ebSMatt Jacob uint32_t len; 14622df76c16SMatt Jacob int i, error, ns, cmap = 0; 146353af7d22SMatt Jacob bus_size_t slim; /* segment size */ 14644b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 146551effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1466222bb542SMatt Jacob struct imush im; 1467222bb542SMatt Jacob 1468a95ae193SMatt Jacob /* 1469a95ae193SMatt Jacob * Already been here? If so, leave... 1470a95ae193SMatt Jacob */ 1471a95ae193SMatt Jacob if (isp->isp_rquest) { 1472a95ae193SMatt Jacob return (0); 1473a95ae193SMatt Jacob } 14740a70657fSMatt Jacob ISP_UNLOCK(isp); 1475a95ae193SMatt Jacob 147610365e5aSMatt Jacob if (isp->isp_maxcmds == 0) { 147710365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "maxcmds not set"); 14780a70657fSMatt Jacob ISP_LOCK(isp); 147910365e5aSMatt Jacob return (1); 148010365e5aSMatt Jacob } 148110365e5aSMatt Jacob 148253af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 14831923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 14849b434edeSMatt Jacob if (sizeof (bus_size_t) > 4) { 148553af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 14869b434edeSMatt Jacob } else { 14879b434edeSMatt Jacob slim = (bus_size_t) (1UL << 31); 14889b434edeSMatt Jacob } 14891dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 14901923f739SMatt Jacob } else { 14911dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR_32BIT; 14929b434edeSMatt Jacob slim = (1UL << 24); 14931923f739SMatt Jacob } 14941923f739SMatt Jacob 14950a70657fSMatt Jacob len = isp->isp_maxcmds * sizeof (struct isp_pcmd); 14962df76c16SMatt Jacob isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 14970a70657fSMatt Jacob if (isp->isp_osinfo.pcmd_pool == NULL) { 14980a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds"); 14990a70657fSMatt Jacob ISP_LOCK(isp); 15000a70657fSMatt Jacob return (1); 15010a70657fSMatt Jacob } 15020a70657fSMatt Jacob 150309934867SMatt Jacob /* 150409934867SMatt Jacob * XXX: We don't really support 64 bit target mode for parallel scsi yet 150509934867SMatt Jacob */ 150609934867SMatt Jacob #ifdef ISP_TARGET_MODE 150709934867SMatt Jacob if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) { 15080a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 150909934867SMatt Jacob isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet"); 15102df76c16SMatt Jacob ISP_LOCK(isp); 151109934867SMatt Jacob return (1); 151209934867SMatt Jacob } 151309934867SMatt Jacob #endif 151409934867SMatt Jacob 15152df76c16SMatt 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)) { 15160a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 151772429e49SMatt Jacob ISP_LOCK(isp); 15180a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 15191923f739SMatt Jacob return (1); 15201923f739SMatt Jacob } 15211923f739SMatt Jacob 1522c8b8a2c4SMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1523c8b8a2c4SMatt Jacob isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1524a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 15250a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 152672429e49SMatt Jacob ISP_LOCK(isp); 15270a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 1528a95ae193SMatt Jacob return (1); 1529a95ae193SMatt Jacob } 1530c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1531c8b8a2c4SMatt Jacob isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; 1532c8b8a2c4SMatt Jacob } 1533c8b8a2c4SMatt Jacob isp->isp_xffree = isp->isp_xflist; 153451e23558SNate Lawson #ifdef ISP_TARGET_MODE 153532b3ec7dSMatt Jacob len = sizeof (isp_hdl_t) * isp->isp_maxcmds; 1536c8b8a2c4SMatt Jacob isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 153751e23558SNate Lawson if (isp->isp_tgtlist == NULL) { 15380a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1539a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 154072429e49SMatt Jacob ISP_LOCK(isp); 15410a70657fSMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); 1542a95ae193SMatt Jacob return (1); 1543a95ae193SMatt Jacob } 1544c8b8a2c4SMatt Jacob for (len = 0; len < isp->isp_maxcmds - 1; len++) { 1545c8b8a2c4SMatt Jacob isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1]; 1546c8b8a2c4SMatt Jacob } 1547c8b8a2c4SMatt Jacob isp->isp_tgtfree = isp->isp_tgtlist; 15480a70657fSMatt Jacob #endif 1549a95ae193SMatt Jacob 1550d720e6d5SJustin T. Gibbs /* 15512df76c16SMatt Jacob * Allocate and map the request and result queues (and ATIO queue 15522df76c16SMatt Jacob * if we're a 2400 supporting target mode). 1553d720e6d5SJustin T. Gibbs */ 1554d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1555d02373f1SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 15562df76c16SMatt Jacob #ifdef ISP_TARGET_MODE 15572df76c16SMatt Jacob if (IS_24XX(isp)) { 15582df76c16SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1559d720e6d5SJustin T. Gibbs } 15602df76c16SMatt Jacob #endif 15611923f739SMatt Jacob 15621923f739SMatt Jacob ns = (len / PAGE_SIZE) + 1; 15632df76c16SMatt Jacob 156453af7d22SMatt Jacob /* 15652df76c16SMatt Jacob * Create a tag for the control spaces. We don't always need this 15662df76c16SMatt Jacob * to be 32 bits, but we do this for simplicity and speed's sake. 156753af7d22SMatt Jacob */ 15682df76c16SMatt 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)) { 15692df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces"); 15700a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1571a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 157251e23558SNate Lawson #ifdef ISP_TARGET_MODE 157351e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 157451e23558SNate Lawson #endif 157572429e49SMatt Jacob ISP_LOCK(isp); 1576d720e6d5SJustin T. Gibbs return (1); 1577d720e6d5SJustin T. Gibbs } 1578d720e6d5SJustin T. Gibbs 15792df76c16SMatt Jacob if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT, &isp->isp_osinfo.cdmap) != 0) { 15802df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len); 15812df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 15820a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 1583a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 158451e23558SNate Lawson #ifdef ISP_TARGET_MODE 158551e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 158651e23558SNate Lawson #endif 158772429e49SMatt Jacob ISP_LOCK(isp); 1588222bb542SMatt Jacob return (1); 1589222bb542SMatt Jacob } 1590d720e6d5SJustin T. Gibbs 15912df76c16SMatt Jacob im.isp = isp; 15922df76c16SMatt Jacob im.chan = 0; 15932df76c16SMatt Jacob im.vbase = base; 15942df76c16SMatt Jacob im.error = 0; 15952df76c16SMatt Jacob 15962df76c16SMatt Jacob bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0); 15972df76c16SMatt Jacob if (im.error) { 15982df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error); 15992df76c16SMatt Jacob goto bad; 16002df76c16SMatt Jacob } 16012df76c16SMatt Jacob 16022df76c16SMatt Jacob if (IS_FC(isp)) { 16032df76c16SMatt Jacob for (cmap = 0; cmap < isp->isp_nchan; cmap++) { 16042df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16052df76c16SMatt 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)) { 16062df76c16SMatt Jacob goto bad; 16072df76c16SMatt Jacob } 16082df76c16SMatt Jacob if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT, &fc->tdmap) != 0) { 16092df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16102df76c16SMatt Jacob goto bad; 16112df76c16SMatt Jacob } 16122df76c16SMatt Jacob im.isp = isp; 16132df76c16SMatt Jacob im.chan = cmap; 16142df76c16SMatt Jacob im.vbase = base; 16152df76c16SMatt Jacob im.error = 0; 16162df76c16SMatt Jacob bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0); 16172df76c16SMatt Jacob if (im.error) { 16182df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 16192df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16202df76c16SMatt Jacob goto bad; 16212df76c16SMatt Jacob } 16222df76c16SMatt Jacob } 16232df76c16SMatt Jacob } 16242df76c16SMatt Jacob 1625a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 16260a70657fSMatt Jacob struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; 16270a70657fSMatt Jacob error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); 1628d720e6d5SJustin T. Gibbs if (error) { 16292df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); 16301923f739SMatt Jacob while (--i >= 0) { 16312df76c16SMatt Jacob bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap); 16321923f739SMatt Jacob } 16331923f739SMatt Jacob goto bad; 1634d720e6d5SJustin T. Gibbs } 16352df76c16SMatt Jacob callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); 16360a70657fSMatt Jacob if (i == isp->isp_maxcmds-1) { 16370a70657fSMatt Jacob pcmd->next = NULL; 16380a70657fSMatt Jacob } else { 16390a70657fSMatt Jacob pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; 1640d720e6d5SJustin T. Gibbs } 16410a70657fSMatt Jacob } 16420a70657fSMatt Jacob isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; 164372429e49SMatt Jacob ISP_LOCK(isp); 1644d720e6d5SJustin T. Gibbs return (0); 16451923f739SMatt Jacob 16461923f739SMatt Jacob bad: 16472df76c16SMatt Jacob while (--cmap >= 0) { 16482df76c16SMatt Jacob struct isp_fc *fc = ISP_FC_PC(isp, cmap); 16492df76c16SMatt Jacob bus_dmamem_free(fc->tdmat, base, fc->tdmap); 16502df76c16SMatt Jacob bus_dma_tag_destroy(fc->tdmat); 16512df76c16SMatt Jacob } 16522df76c16SMatt Jacob bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap); 16532df76c16SMatt Jacob bus_dma_tag_destroy(isp->isp_osinfo.cdmat); 16541923f739SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 165551e23558SNate Lawson #ifdef ISP_TARGET_MODE 165651e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 165751e23558SNate Lawson #endif 16580a70657fSMatt Jacob free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); 16591923f739SMatt Jacob isp->isp_rquest = NULL; 16600a70657fSMatt Jacob ISP_LOCK(isp); 16611923f739SMatt Jacob return (1); 1662d720e6d5SJustin T. Gibbs } 1663d720e6d5SJustin T. Gibbs 1664d720e6d5SJustin T. Gibbs typedef struct { 16659cd7268eSMatt Jacob ispsoftc_t *isp; 16669e11e5beSMatt Jacob void *cmd_token; 16672df76c16SMatt Jacob void *rq; /* original request */ 16681dae40ebSMatt Jacob int error; 16692df76c16SMatt Jacob bus_size_t mapsize; 1670d720e6d5SJustin T. Gibbs } mush_t; 1671d720e6d5SJustin T. Gibbs 16724873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 16734873663cSMatt Jacob 16749e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 16752df76c16SMatt Jacob static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 16762df76c16SMatt Jacob static void tdma2(void *, bus_dma_segment_t *, int, int); 16779e11e5beSMatt Jacob 1678d720e6d5SJustin T. Gibbs static void 16792df76c16SMatt Jacob tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 1680d720e6d5SJustin T. Gibbs { 1681d720e6d5SJustin T. Gibbs mush_t *mp; 16822df76c16SMatt Jacob mp = (mush_t *)arg; 16832df76c16SMatt Jacob mp->mapsize = mapsize; 16842df76c16SMatt Jacob tdma2(arg, dm_segs, nseg, error); 16852df76c16SMatt Jacob } 16862df76c16SMatt Jacob 16872df76c16SMatt Jacob static void 16882df76c16SMatt Jacob tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 16892df76c16SMatt Jacob { 16902df76c16SMatt Jacob mush_t *mp; 16919cd7268eSMatt Jacob ispsoftc_t *isp; 16922df76c16SMatt Jacob struct ccb_scsiio *csio; 16932df76c16SMatt Jacob isp_ddir_t ddir; 16942df76c16SMatt Jacob ispreq_t *rq; 1695d720e6d5SJustin T. Gibbs 1696d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1697d720e6d5SJustin T. Gibbs if (error) { 1698d720e6d5SJustin T. Gibbs mp->error = error; 1699d720e6d5SJustin T. Gibbs return; 1700d720e6d5SJustin T. Gibbs } 17019e11e5beSMatt Jacob csio = mp->cmd_token; 17024fd13c1bSMatt Jacob isp = mp->isp; 17032df76c16SMatt Jacob rq = mp->rq; 17042df76c16SMatt Jacob if (nseg) { 170509934867SMatt Jacob if (sizeof (bus_addr_t) > 4) { 17062df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 17072df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 17082df76c16SMatt Jacob mp->error = EFAULT; 17099e11e5beSMatt Jacob return; 17109e11e5beSMatt Jacob } 17112df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) { 17122df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_CTIO3; 17132df76c16SMatt Jacob } 171409934867SMatt Jacob } else { 17152df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 17162df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 17172df76c16SMatt Jacob mp->error = EFAULT; 17182df76c16SMatt Jacob return; 171909934867SMatt Jacob } 17202df76c16SMatt Jacob } 17212df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 17222df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 17232df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 17242df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 17252df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 17262df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 172709934867SMatt Jacob } else { 17282df76c16SMatt Jacob ddir = ISP_NOXFR; 172909934867SMatt Jacob } 17302df76c16SMatt Jacob } else { 17312df76c16SMatt Jacob dm_segs = NULL; 17322df76c16SMatt Jacob nseg = 0; 17332df76c16SMatt Jacob ddir = ISP_NOXFR; 1734fc087171SMatt Jacob } 173565b024e1SMatt Jacob 17362df76c16SMatt Jacob if (isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len) != CMD_QUEUED) { 17372df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 173810365e5aSMatt Jacob } 17399e11e5beSMatt Jacob } 17409e11e5beSMatt Jacob #endif 17419e11e5beSMatt Jacob 17422df76c16SMatt Jacob static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int); 1743126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 17449e11e5beSMatt Jacob 17456de9bf77SMatt Jacob static void 17462df76c16SMatt Jacob dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error) 174710365e5aSMatt Jacob { 174810365e5aSMatt Jacob mush_t *mp; 174910365e5aSMatt Jacob mp = (mush_t *)arg; 17502df76c16SMatt Jacob mp->mapsize = mapsize; 17512df76c16SMatt Jacob dma2(arg, dm_segs, nseg, error); 17526de9bf77SMatt Jacob } 17531dae40ebSMatt Jacob 17549e11e5beSMatt Jacob static void 17559e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 17569e11e5beSMatt Jacob { 17579e11e5beSMatt Jacob mush_t *mp; 17589cd7268eSMatt Jacob ispsoftc_t *isp; 17599e11e5beSMatt Jacob struct ccb_scsiio *csio; 17602df76c16SMatt Jacob isp_ddir_t ddir; 17619e11e5beSMatt Jacob ispreq_t *rq; 17629e11e5beSMatt Jacob 17639e11e5beSMatt Jacob mp = (mush_t *) arg; 17649e11e5beSMatt Jacob if (error) { 17659e11e5beSMatt Jacob mp->error = error; 17669e11e5beSMatt Jacob return; 17679e11e5beSMatt Jacob } 17689e11e5beSMatt Jacob csio = mp->cmd_token; 17694fd13c1bSMatt Jacob isp = mp->isp; 17709e11e5beSMatt Jacob rq = mp->rq; 17712df76c16SMatt Jacob if (nseg) { 17722df76c16SMatt Jacob if (sizeof (bus_addr_t) > 4) { 17732df76c16SMatt Jacob if (nseg >= ISP_NSEG64_MAX) { 17742df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX); 17752df76c16SMatt Jacob mp->error = EFAULT; 1776d720e6d5SJustin T. Gibbs return; 1777d720e6d5SJustin T. Gibbs } 17782df76c16SMatt Jacob if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) { 17792df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; 17802df76c16SMatt Jacob } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) { 17812df76c16SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_A64; 1782d720e6d5SJustin T. Gibbs } 17832df76c16SMatt Jacob } else { 17842df76c16SMatt Jacob if (nseg >= ISP_NSEG_MAX) { 17852df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX); 17862df76c16SMatt Jacob mp->error = EFAULT; 17872df76c16SMatt Jacob return; 178810365e5aSMatt Jacob } 1789d720e6d5SJustin T. Gibbs } 17902df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 17912df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD); 17922df76c16SMatt Jacob ddir = ISP_FROM_DEVICE; 17932df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 17942df76c16SMatt Jacob bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE); 17952df76c16SMatt Jacob ddir = ISP_TO_DEVICE; 17962df76c16SMatt Jacob } else { 17972df76c16SMatt Jacob ddir = ISP_NOXFR; 17982df76c16SMatt Jacob } 17992df76c16SMatt Jacob } else { 18002df76c16SMatt Jacob dm_segs = NULL; 18012df76c16SMatt Jacob nseg = 0; 18022df76c16SMatt Jacob ddir = ISP_NOXFR; 1803d720e6d5SJustin T. Gibbs } 1804d720e6d5SJustin T. Gibbs 18052df76c16SMatt Jacob if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) { 18062df76c16SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 18072df76c16SMatt Jacob } 18082df76c16SMatt Jacob } 18092df76c16SMatt Jacob 1810d720e6d5SJustin T. Gibbs static int 18112df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) 1812d720e6d5SJustin T. Gibbs { 1813d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1814126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 18152df76c16SMatt Jacob void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int); 1816d720e6d5SJustin T. Gibbs 18172df76c16SMatt Jacob mp = &mush; 18182df76c16SMatt Jacob mp->isp = isp; 18192df76c16SMatt Jacob mp->cmd_token = csio; 18202df76c16SMatt Jacob mp->rq = ff; 18212df76c16SMatt Jacob mp->error = 0; 18222df76c16SMatt Jacob mp->mapsize = 0; 18232df76c16SMatt Jacob 182465b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 182565b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 18262df76c16SMatt Jacob eptr = tdma2; 18272df76c16SMatt Jacob eptr2 = tdma2_2; 182865b024e1SMatt Jacob } else 182965b024e1SMatt Jacob #endif 18302df76c16SMatt Jacob { 183165b024e1SMatt Jacob eptr = dma2; 18322df76c16SMatt Jacob eptr2 = dma2_2; 18331dae40ebSMatt Jacob } 183465b024e1SMatt Jacob 18354fd13c1bSMatt Jacob 18362df76c16SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) { 18372df76c16SMatt Jacob (*eptr)(mp, NULL, 0, 0); 18382df76c16SMatt Jacob } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 18399e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { 18400a70657fSMatt Jacob int error; 18412df76c16SMatt Jacob error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0); 18422df76c16SMatt Jacob #if 0 18432df76c16SMatt 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); 18440a70657fSMatt Jacob #endif 18452df76c16SMatt Jacob 1846d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 18472df76c16SMatt Jacob bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); 1848d720e6d5SJustin T. Gibbs mp->error = EINVAL; 18492df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); 1850d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 18510a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 18522df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 18530a5f7e8bSMatt Jacob #endif 1854d720e6d5SJustin T. Gibbs mp->error = error; 1855d720e6d5SJustin T. Gibbs } 1856d720e6d5SJustin T. Gibbs } else { 1857d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 1858d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 18596de9bf77SMatt Jacob seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; 1860d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 18619e11e5beSMatt Jacob (*eptr)(mp, &seg, 1, 0); 1862d720e6d5SJustin T. Gibbs } 1863d720e6d5SJustin T. Gibbs } else { 1864d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 1865d720e6d5SJustin T. Gibbs 18669e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { 18672df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported"); 1868d720e6d5SJustin T. Gibbs mp->error = EINVAL; 18699e11e5beSMatt Jacob } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { 18702df76c16SMatt Jacob struct uio sguio; 18712df76c16SMatt Jacob int error; 18722df76c16SMatt Jacob 18732df76c16SMatt Jacob /* 18742df76c16SMatt Jacob * We're taking advantage of the fact that 18752df76c16SMatt Jacob * the pointer/length sizes and layout of the iovec 18762df76c16SMatt Jacob * structure are the same as the bus_dma_segment 18772df76c16SMatt Jacob * structure. This might be a little dangerous, 18782df76c16SMatt Jacob * but only if they change the structures, which 18792df76c16SMatt Jacob * seems unlikely. 18802df76c16SMatt Jacob */ 18812df76c16SMatt Jacob KASSERT((sizeof (sguio.uio_iov) == sizeof (csio->data_ptr) && 18822df76c16SMatt Jacob sizeof (sguio.uio_iovcnt) >= sizeof (csio->sglist_cnt) && 18832df76c16SMatt Jacob sizeof (sguio.uio_resid) >= sizeof (csio->dxfer_len)), ("Ken's assumption failed")); 18842df76c16SMatt Jacob sguio.uio_iov = (struct iovec *)csio->data_ptr; 18852df76c16SMatt Jacob sguio.uio_iovcnt = csio->sglist_cnt; 18862df76c16SMatt Jacob sguio.uio_resid = csio->dxfer_len; 18872df76c16SMatt Jacob sguio.uio_segflg = UIO_SYSSPACE; 18882df76c16SMatt Jacob 18892df76c16SMatt Jacob error = bus_dmamap_load_uio(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, &sguio, eptr2, mp, 0); 18902df76c16SMatt Jacob 18912df76c16SMatt Jacob if (error != 0 && mp->error == 0) { 18922df76c16SMatt Jacob isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); 18932df76c16SMatt Jacob mp->error = error; 18942df76c16SMatt Jacob } 1895d720e6d5SJustin T. Gibbs } else { 1896d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 1897d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 18989e11e5beSMatt Jacob (*eptr)(mp, segs, csio->sglist_cnt, 0); 1899d720e6d5SJustin T. Gibbs } 1900d720e6d5SJustin T. Gibbs } 1901d720e6d5SJustin T. Gibbs if (mp->error) { 19024873663cSMatt Jacob int retval = CMD_COMPLETE; 19034873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 19044873663cSMatt Jacob retval = CMD_EAGAIN; 19054873663cSMatt Jacob } else if (mp->error == EFBIG) { 19060a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_TOO_BIG); 1907d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 19080a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_INVALID); 1909d720e6d5SJustin T. Gibbs } else { 19100a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 1911d720e6d5SJustin T. Gibbs } 19124873663cSMatt Jacob return (retval); 19130a5f7e8bSMatt Jacob } 19144873663cSMatt Jacob return (CMD_QUEUED); 1915d720e6d5SJustin T. Gibbs } 1916d720e6d5SJustin T. Gibbs 1917d720e6d5SJustin T. Gibbs static void 19183bda7a83SMatt Jacob isp_pci_reset0(ispsoftc_t *isp) 19193bda7a83SMatt Jacob { 19203bda7a83SMatt Jacob ISP_DISABLE_INTS(isp); 19213bda7a83SMatt Jacob } 19223bda7a83SMatt Jacob 19233bda7a83SMatt Jacob static void 19249cd7268eSMatt Jacob isp_pci_reset1(ispsoftc_t *isp) 192565adb54cSMatt Jacob { 192610365e5aSMatt Jacob if (!IS_24XX(isp)) { 192765adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 192865adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 192910365e5aSMatt Jacob } 1930469b6b9eSMatt Jacob /* and enable interrupts */ 193110365e5aSMatt Jacob ISP_ENABLE_INTS(isp); 193265adb54cSMatt Jacob } 193365adb54cSMatt Jacob 193465adb54cSMatt Jacob static void 19359cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg) 193665adb54cSMatt Jacob { 19371923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 1938d02373f1SMatt Jacob if (msg) 19396e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 19406e5c5328SMatt Jacob else 19416e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 1942d02373f1SMatt Jacob if (IS_SCSI(isp)) 1943d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 1944d02373f1SMatt Jacob else 1945d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 1946d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 1947d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 1948d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 1949d02373f1SMatt Jacob 1950d02373f1SMatt Jacob 1951d02373f1SMatt Jacob if (IS_SCSI(isp)) { 1952d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 1953d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 1954d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 1955d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 1956d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 1957d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 1958d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 1959d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 1960d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 1961d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 1962d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 1963d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 1964d02373f1SMatt Jacob } 1965d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 1966d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 1967d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 1968d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 1969d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 19701923f739SMatt Jacob pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1)); 197165adb54cSMatt Jacob } 1972