1aad970f1SDavid E. O'Brien /*- 265adb54cSMatt Jacob * 3e5265237SMatt Jacob * Copyright (c) 1997-2006 by Matthew Jacob 4e5265237SMatt Jacob * All rights reserved. 565adb54cSMatt Jacob * 665adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 765adb54cSMatt Jacob * modification, are permitted provided that the following conditions 865adb54cSMatt Jacob * are met: 965adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 1065adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1165adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 12aa57fd6fSMatt Jacob * 2. The name of the author may not be used to endorse or promote products 13aa57fd6fSMatt Jacob * derived from this software without specific prior written permission. 1465adb54cSMatt Jacob * 1565adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1665adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1765adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1865adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 1965adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2065adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2165adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2265adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2365adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2465adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2565adb54cSMatt Jacob * SUCH DAMAGE. 26e5265237SMatt Jacob * 2765adb54cSMatt Jacob */ 28799881e0SMatt Jacob /* 29799881e0SMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 30799881e0SMatt Jacob * FreeBSD Version. 31799881e0SMatt Jacob */ 32aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 33aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 34aad970f1SDavid E. O'Brien 35960f6939SMatt Jacob #include <sys/param.h> 36960f6939SMatt Jacob #include <sys/systm.h> 37960f6939SMatt Jacob #include <sys/kernel.h> 38960f6939SMatt Jacob #include <sys/module.h> 399a5af410SMatt Jacob #if __FreeBSD_version >= 700000 409a5af410SMatt Jacob #include <sys/linker.h> 419a5af410SMatt Jacob #include <sys/firmware.h> 429a5af410SMatt Jacob #endif 43960f6939SMatt Jacob #include <sys/bus.h> 449cd7268eSMatt Jacob #if __FreeBSD_version < 500000 459cd7268eSMatt Jacob #include <pci/pcireg.h> 469cd7268eSMatt Jacob #include <pci/pcivar.h> 479cd7268eSMatt Jacob #include <machine/bus_memio.h> 489cd7268eSMatt Jacob #include <machine/bus_pio.h> 499cd7268eSMatt Jacob #else 5074a96f43SJohn Baldwin #include <sys/stdint.h> 5177e6a3b2SWarner Losh #include <dev/pci/pcireg.h> 5277e6a3b2SWarner Losh #include <dev/pci/pcivar.h> 539cd7268eSMatt Jacob #endif 54d720e6d5SJustin T. Gibbs #include <machine/bus.h> 55960f6939SMatt Jacob #include <machine/resource.h> 56960f6939SMatt Jacob #include <sys/rman.h> 57960f6939SMatt Jacob #include <sys/malloc.h> 58960f6939SMatt Jacob 59960f6939SMatt Jacob #include <dev/isp/isp_freebsd.h> 60d59bd469SMatt Jacob 619cd7268eSMatt Jacob #if __FreeBSD_version < 500000 629cd7268eSMatt Jacob #define BUS_PROBE_DEFAULT 0 639cd7268eSMatt Jacob #endif 6465adb54cSMatt Jacob 6510365e5aSMatt Jacob static uint32_t isp_pci_rd_reg(ispsoftc_t *, int); 6610365e5aSMatt Jacob static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t); 6710365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int); 6810365e5aSMatt Jacob static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t); 6910365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int); 7010365e5aSMatt Jacob static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t); 719cd7268eSMatt Jacob static int 7210365e5aSMatt Jacob isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); 739cd7268eSMatt Jacob static int 7410365e5aSMatt Jacob isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); 7510365e5aSMatt Jacob static int 7610365e5aSMatt Jacob isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *); 779cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *); 789cd7268eSMatt Jacob static int 7910365e5aSMatt Jacob isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t); 809cd7268eSMatt Jacob static void 8110365e5aSMatt Jacob isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint32_t); 829cd7268eSMatt Jacob 839a5af410SMatt Jacob 843bda7a83SMatt Jacob static void isp_pci_reset0(ispsoftc_t *); 859cd7268eSMatt Jacob static void isp_pci_reset1(ispsoftc_t *); 869cd7268eSMatt Jacob static void isp_pci_dumpregs(ispsoftc_t *, const char *); 8765adb54cSMatt Jacob 8865adb54cSMatt Jacob static struct ispmdvec mdvec = { 89126ec864SMatt Jacob isp_pci_rd_isr, 9065adb54cSMatt Jacob isp_pci_rd_reg, 9165adb54cSMatt Jacob isp_pci_wr_reg, 9265adb54cSMatt Jacob isp_pci_mbxdma, 9365adb54cSMatt Jacob isp_pci_dmasetup, 94d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 953bda7a83SMatt Jacob isp_pci_reset0, 9665adb54cSMatt Jacob isp_pci_reset1, 9765adb54cSMatt Jacob isp_pci_dumpregs, 9856aef503SMatt Jacob NULL, 99d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 10065adb54cSMatt Jacob }; 10165adb54cSMatt Jacob 102d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 103126ec864SMatt Jacob isp_pci_rd_isr, 104d59bd469SMatt Jacob isp_pci_rd_reg_1080, 105d59bd469SMatt Jacob isp_pci_wr_reg_1080, 106d59bd469SMatt Jacob isp_pci_mbxdma, 107d59bd469SMatt Jacob isp_pci_dmasetup, 108d59bd469SMatt Jacob isp_pci_dmateardown, 1093bda7a83SMatt Jacob isp_pci_reset0, 110d59bd469SMatt Jacob isp_pci_reset1, 111d59bd469SMatt Jacob isp_pci_dumpregs, 11256aef503SMatt Jacob NULL, 113d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 114d59bd469SMatt Jacob }; 115d59bd469SMatt Jacob 116960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = { 117126ec864SMatt Jacob isp_pci_rd_isr, 118960f6939SMatt Jacob isp_pci_rd_reg_1080, 119960f6939SMatt Jacob isp_pci_wr_reg_1080, 120960f6939SMatt Jacob isp_pci_mbxdma, 121960f6939SMatt Jacob isp_pci_dmasetup, 122960f6939SMatt Jacob isp_pci_dmateardown, 1233bda7a83SMatt Jacob isp_pci_reset0, 124960f6939SMatt Jacob isp_pci_reset1, 125960f6939SMatt Jacob isp_pci_dumpregs, 12656aef503SMatt Jacob NULL, 127d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 128960f6939SMatt Jacob }; 129960f6939SMatt Jacob 13065adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 131126ec864SMatt Jacob isp_pci_rd_isr, 13265adb54cSMatt Jacob isp_pci_rd_reg, 13365adb54cSMatt Jacob isp_pci_wr_reg, 13465adb54cSMatt Jacob isp_pci_mbxdma, 13565adb54cSMatt Jacob isp_pci_dmasetup, 136d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 1373bda7a83SMatt Jacob isp_pci_reset0, 13865adb54cSMatt Jacob isp_pci_reset1, 139d02373f1SMatt Jacob isp_pci_dumpregs 14065adb54cSMatt Jacob }; 141222bb542SMatt Jacob 142222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 143126ec864SMatt Jacob isp_pci_rd_isr, 144126ec864SMatt Jacob isp_pci_rd_reg, 145126ec864SMatt Jacob isp_pci_wr_reg, 146126ec864SMatt Jacob isp_pci_mbxdma, 147126ec864SMatt Jacob isp_pci_dmasetup, 148126ec864SMatt Jacob isp_pci_dmateardown, 1493bda7a83SMatt Jacob isp_pci_reset0, 150126ec864SMatt Jacob isp_pci_reset1, 151126ec864SMatt Jacob isp_pci_dumpregs 152126ec864SMatt Jacob }; 153126ec864SMatt Jacob 154126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = { 155126ec864SMatt Jacob isp_pci_rd_isr_2300, 156222bb542SMatt Jacob isp_pci_rd_reg, 157222bb542SMatt Jacob isp_pci_wr_reg, 158222bb542SMatt Jacob isp_pci_mbxdma, 159222bb542SMatt Jacob isp_pci_dmasetup, 160222bb542SMatt Jacob isp_pci_dmateardown, 1613bda7a83SMatt Jacob isp_pci_reset0, 162222bb542SMatt Jacob isp_pci_reset1, 163d02373f1SMatt Jacob isp_pci_dumpregs 164222bb542SMatt Jacob }; 165d951bbcaSMatt Jacob 16610365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = { 16710365e5aSMatt Jacob isp_pci_rd_isr_2400, 16810365e5aSMatt Jacob isp_pci_rd_reg_2400, 16910365e5aSMatt Jacob isp_pci_wr_reg_2400, 17010365e5aSMatt Jacob isp_pci_mbxdma, 17110365e5aSMatt Jacob isp_pci_dmasetup, 17210365e5aSMatt Jacob isp_pci_dmateardown, 1733bda7a83SMatt Jacob isp_pci_reset0, 17410365e5aSMatt Jacob isp_pci_reset1, 17510365e5aSMatt Jacob NULL 17610365e5aSMatt Jacob }; 17710365e5aSMatt Jacob 17865adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 17965adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 18065adb54cSMatt Jacob #endif 18165adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 18265adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 18365adb54cSMatt Jacob #endif 184d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 185d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 186d951bbcaSMatt Jacob #endif 187d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 188d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 189d951bbcaSMatt Jacob #endif 1908a97c03aSMatt Jacob #ifndef PCIM_CMD_INTX_DISABLE 1918a97c03aSMatt Jacob #define PCIM_CMD_INTX_DISABLE 0x0400 1928a97c03aSMatt Jacob #endif 193d951bbcaSMatt Jacob 194d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 195d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 196d951bbcaSMatt Jacob #endif 197d951bbcaSMatt Jacob 198d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 199d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 200d951bbcaSMatt Jacob #endif 201d951bbcaSMatt Jacob 202d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 203d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 204d951bbcaSMatt Jacob #endif 205d951bbcaSMatt Jacob 206ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 207ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 208ab6d0040SMatt Jacob #endif 209ab6d0040SMatt Jacob 21065adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 21165adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 21265adb54cSMatt Jacob #endif 21365adb54cSMatt Jacob 21465adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 21565adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 21665adb54cSMatt Jacob #endif 21765adb54cSMatt Jacob 218d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 219d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 220d59bd469SMatt Jacob #endif 221d59bd469SMatt Jacob 222f556e83bSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP10160 223f556e83bSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 224f556e83bSMatt Jacob #endif 225f556e83bSMatt Jacob 226960f6939SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP12160 227960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 228960f6939SMatt Jacob #endif 229960f6939SMatt Jacob 230d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 231d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 232d59bd469SMatt Jacob #endif 23365adb54cSMatt Jacob 23422e1dc85SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1280 23522e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 23622e1dc85SMatt Jacob #endif 23722e1dc85SMatt Jacob 23865adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 23965adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 24065adb54cSMatt Jacob #endif 24165adb54cSMatt Jacob 242222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 243222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 244222bb542SMatt Jacob #endif 245222bb542SMatt Jacob 246126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2300 247126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 248126ec864SMatt Jacob #endif 249126ec864SMatt Jacob 250126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2312 251126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 252126ec864SMatt Jacob #endif 253126ec864SMatt Jacob 254e5265237SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2322 255e5265237SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322 256e5265237SMatt Jacob #endif 257e5265237SMatt Jacob 2588872e3d7SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2422 2598872e3d7SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422 2608872e3d7SMatt Jacob #endif 2618872e3d7SMatt Jacob 26241675df0SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2432 26341675df0SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432 26441675df0SMatt Jacob #endif 26541675df0SMatt Jacob 266dd1419abSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6312 267dd1419abSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312 268dd1419abSMatt Jacob #endif 269dd1419abSMatt Jacob 2709a5af410SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP6322 2719a5af410SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322 2729a5af410SMatt Jacob #endif 2739a5af410SMatt Jacob 2749a5af410SMatt Jacob 27556aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 27656aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 277d59bd469SMatt Jacob 278d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 279d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 280d59bd469SMatt Jacob 281f556e83bSMatt Jacob #define PCI_QLOGIC_ISP10160 \ 282f556e83bSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC) 283f556e83bSMatt Jacob 284960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 285960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 286960f6939SMatt Jacob 287d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 288d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 289d59bd469SMatt Jacob 29022e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 29122e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 29222e1dc85SMatt Jacob 29365adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 29465adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 29565adb54cSMatt Jacob 296222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 297222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 298222bb542SMatt Jacob 299126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 300126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 301126ec864SMatt Jacob 302126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 303126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 304126ec864SMatt Jacob 305e5265237SMatt Jacob #define PCI_QLOGIC_ISP2322 \ 306e5265237SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC) 307e5265237SMatt Jacob 3086c426685SMatt Jacob #define PCI_QLOGIC_ISP2422 \ 3096c426685SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC) 3106c426685SMatt Jacob 31141675df0SMatt Jacob #define PCI_QLOGIC_ISP2432 \ 31241675df0SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC) 31341675df0SMatt Jacob 314dd1419abSMatt Jacob #define PCI_QLOGIC_ISP6312 \ 315dd1419abSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC) 316dd1419abSMatt Jacob 3179a5af410SMatt Jacob #define PCI_QLOGIC_ISP6322 \ 3189a5af410SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC) 3199a5af410SMatt Jacob 320e11a1ee8SMatt Jacob /* 321e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 322e11a1ee8SMatt Jacob */ 323e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 324e11a1ee8SMatt Jacob 32565adb54cSMatt Jacob #define IO_MAP_REG 0x10 32665adb54cSMatt Jacob #define MEM_MAP_REG 0x14 32765adb54cSMatt Jacob 328d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 329d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 33065adb54cSMatt Jacob 331960f6939SMatt Jacob static int isp_pci_probe (device_t); 332960f6939SMatt Jacob static int isp_pci_attach (device_t); 33310365e5aSMatt Jacob static int isp_pci_detach (device_t); 33465adb54cSMatt Jacob 3351923f739SMatt Jacob 33665adb54cSMatt Jacob struct isp_pcisoftc { 3379cd7268eSMatt Jacob ispsoftc_t pci_isp; 338960f6939SMatt Jacob device_t pci_dev; 339960f6939SMatt Jacob struct resource * pci_reg; 34065adb54cSMatt Jacob bus_space_tag_t pci_st; 34165adb54cSMatt Jacob bus_space_handle_t pci_sh; 342960f6939SMatt Jacob void * ih; 343d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 3441923f739SMatt Jacob bus_dma_tag_t dmat; 345a95ae193SMatt Jacob bus_dmamap_t *dmaps; 34665adb54cSMatt Jacob }; 34765adb54cSMatt Jacob 34810365e5aSMatt Jacob 349960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 350960f6939SMatt Jacob /* Device interface */ 351960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 352960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 35310365e5aSMatt Jacob DEVMETHOD(device_detach, isp_pci_detach), 354960f6939SMatt Jacob { 0, 0 } 35565adb54cSMatt Jacob }; 356126ec864SMatt Jacob static void isp_pci_intr(void *); 35765adb54cSMatt Jacob 358960f6939SMatt Jacob static driver_t isp_pci_driver = { 359960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 360960f6939SMatt Jacob }; 361960f6939SMatt Jacob static devclass_t isp_devclass; 362960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 3633cce220cSMatt Jacob #if __FreeBSD_version < 700000 3649a5af410SMatt Jacob extern ispfwfunc *isp_get_firmware_p; 3659a5af410SMatt Jacob #endif 36665adb54cSMatt Jacob 367960f6939SMatt Jacob static int 368960f6939SMatt Jacob isp_pci_probe(device_t dev) 36965adb54cSMatt Jacob { 370960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 37156aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 372960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 37365adb54cSMatt Jacob break; 374d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 375960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 376c6608df3SMatt Jacob break; 377c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 378960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 379d59bd469SMatt Jacob break; 38022e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 381960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 382960f6939SMatt Jacob break; 383f556e83bSMatt Jacob case PCI_QLOGIC_ISP10160: 384f556e83bSMatt Jacob device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter"); 385f556e83bSMatt Jacob break; 386960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 387e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 388e11a1ee8SMatt Jacob return (ENXIO); 389e11a1ee8SMatt Jacob } 390960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 39122e1dc85SMatt Jacob break; 39265adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 393960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 39465adb54cSMatt Jacob break; 3955542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 396960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 3975542fe4bSMatt Jacob break; 398126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 399126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 400126ec864SMatt Jacob break; 401126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 402126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 403126ec864SMatt Jacob break; 404e5265237SMatt Jacob case PCI_QLOGIC_ISP2322: 405e5265237SMatt Jacob device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter"); 406e5265237SMatt Jacob break; 4078872e3d7SMatt Jacob case PCI_QLOGIC_ISP2422: 4088872e3d7SMatt Jacob device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter"); 4098872e3d7SMatt Jacob break; 41041675df0SMatt Jacob case PCI_QLOGIC_ISP2432: 41141675df0SMatt Jacob device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter"); 41241675df0SMatt Jacob break; 413dd1419abSMatt Jacob case PCI_QLOGIC_ISP6312: 414dd1419abSMatt Jacob device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter"); 415dd1419abSMatt Jacob break; 4169a5af410SMatt Jacob case PCI_QLOGIC_ISP6322: 4179a5af410SMatt Jacob device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter"); 4189a5af410SMatt Jacob break; 41965adb54cSMatt Jacob default: 420960f6939SMatt Jacob return (ENXIO); 42165adb54cSMatt Jacob } 42273030e03SMatt Jacob if (isp_announced == 0 && bootverbose) { 423d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 424a95ae193SMatt Jacob "Core Version %d.%d\n", 425d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 426d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 42773030e03SMatt Jacob isp_announced++; 42865adb54cSMatt Jacob } 42956aef503SMatt Jacob /* 43056aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 43156aef503SMatt Jacob * XXXX: (or increase a reference count to it). 43256aef503SMatt Jacob */ 433b77e575eSWarner Losh return (BUS_PROBE_DEFAULT); 43465adb54cSMatt Jacob } 43565adb54cSMatt Jacob 4369cd7268eSMatt Jacob #if __FreeBSD_version < 500000 4379cd7268eSMatt Jacob static void 438336b5612SMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 43965adb54cSMatt Jacob { 4409cd7268eSMatt Jacob uint64_t wwn; 4419cd7268eSMatt Jacob int bitmap, unit; 44265adb54cSMatt Jacob 4439cd7268eSMatt Jacob unit = device_get_unit(dev); 4449cd7268eSMatt Jacob if (getenv_int("isp_disable", &bitmap)) { 4459cd7268eSMatt Jacob if (bitmap & (1 << unit)) { 4469cd7268eSMatt Jacob isp->isp_osinfo.disabled = 1; 4479cd7268eSMatt Jacob return; 4489cd7268eSMatt Jacob } 4499cd7268eSMatt Jacob } 4509cd7268eSMatt Jacob if (getenv_int("isp_no_fwload", &bitmap)) { 4519cd7268eSMatt Jacob if (bitmap & (1 << unit)) 4529cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 4539cd7268eSMatt Jacob } 4549cd7268eSMatt Jacob if (getenv_int("isp_fwload", &bitmap)) { 4559cd7268eSMatt Jacob if (bitmap & (1 << unit)) 4569cd7268eSMatt Jacob isp->isp_confopts &= ~ISP_CFG_NORELOAD; 4579cd7268eSMatt Jacob } 4589cd7268eSMatt Jacob if (getenv_int("isp_no_nvram", &bitmap)) { 4599cd7268eSMatt Jacob if (bitmap & (1 << unit)) 4609cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 4619cd7268eSMatt Jacob } 4629cd7268eSMatt Jacob if (getenv_int("isp_nvram", &bitmap)) { 4639cd7268eSMatt Jacob if (bitmap & (1 << unit)) 4649cd7268eSMatt Jacob isp->isp_confopts &= ~ISP_CFG_NONVRAM; 4659cd7268eSMatt Jacob } 466336b5612SMatt Jacob 467336b5612SMatt Jacob bitmap = 0; 468336b5612SMatt Jacob (void) getenv_int("isp_debug", &bitmap); 469336b5612SMatt Jacob if (bitmap) { 470336b5612SMatt Jacob isp->isp_dblev = bitmap; 471336b5612SMatt Jacob } else { 472336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 473336b5612SMatt Jacob } 474336b5612SMatt Jacob if (bootverbose) { 475336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 476336b5612SMatt Jacob } 477336b5612SMatt Jacob 478336b5612SMatt Jacob bitmap = 0; 479336b5612SMatt Jacob if (getenv_int("role", &bitmap)) { 480336b5612SMatt Jacob isp->isp_role = bitmap; 481336b5612SMatt Jacob } else { 482336b5612SMatt Jacob isp->isp_role = ISP_DEFAULT_ROLES; 483336b5612SMatt Jacob } 484336b5612SMatt Jacob 485336b5612SMatt Jacob } 486336b5612SMatt Jacob 487336b5612SMatt Jacob static void 488336b5612SMatt Jacob isp_get_pci_options(device_t dev, int *m1, int *m2) 489336b5612SMatt Jacob { 490336b5612SMatt Jacob int bitmap; 491336b5612SMatt Jacob int unit = device_get_unit(dev); 492336b5612SMatt Jacob 493336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 494336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 495336b5612SMatt Jacob if (getenv_int("isp_mem_map", &bitmap)) { 496336b5612SMatt Jacob if (bitmap & (1 << unit)) { 497336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 498336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 499336b5612SMatt Jacob } 500336b5612SMatt Jacob } 501336b5612SMatt Jacob bitmap = 0; 502336b5612SMatt Jacob if (getenv_int("isp_io_map", &bitmap)) { 503336b5612SMatt Jacob if (bitmap & (1 << unit)) { 504336b5612SMatt Jacob *m1 = PCIM_CMD_PORTEN; 505336b5612SMatt Jacob *m2 = PCIM_CMD_MEMEN; 506336b5612SMatt Jacob } 507336b5612SMatt Jacob } 508336b5612SMatt Jacob } 509336b5612SMatt Jacob 510336b5612SMatt Jacob static void 511336b5612SMatt Jacob isp_get_specific_options(device_t dev, ispsoftc_t *isp) 512336b5612SMatt Jacob { 513336b5612SMatt Jacob 514336b5612SMatt Jacob callout_handle_init(&isp->isp_osinfo.ldt); 515336b5612SMatt Jacob callout_handle_init(&isp->isp_osinfo.gdt); 516336b5612SMatt Jacob 517336b5612SMatt Jacob if (IS_SCSI(isp)) { 518336b5612SMatt Jacob return; 519336b5612SMatt Jacob } 520336b5612SMatt Jacob 5219cd7268eSMatt Jacob if (getenv_int("isp_fcduplex", &bitmap)) { 5229cd7268eSMatt Jacob if (bitmap & (1 << unit)) 5239cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 5249cd7268eSMatt Jacob } 5259cd7268eSMatt Jacob if (getenv_int("isp_no_fcduplex", &bitmap)) { 5269cd7268eSMatt Jacob if (bitmap & (1 << unit)) 5279cd7268eSMatt Jacob isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX; 5289cd7268eSMatt Jacob } 5299cd7268eSMatt Jacob if (getenv_int("isp_nport", &bitmap)) { 5309cd7268eSMatt Jacob if (bitmap & (1 << unit)) 5319cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 5329cd7268eSMatt Jacob } 5339cd7268eSMatt Jacob 5349cd7268eSMatt Jacob /* 5359cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 5369cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 5379cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 5389cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 5399cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 5409cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 5419cd7268eSMatt Jacob */ 5429cd7268eSMatt Jacob if (getenv_quad("isp_portwwn", &wwn)) { 5439cd7268eSMatt Jacob isp->isp_osinfo.default_port_wwn = wwn; 5449cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWPN; 5459cd7268eSMatt Jacob } 5469cd7268eSMatt Jacob if (isp->isp_osinfo.default_port_wwn == 0) { 5479cd7268eSMatt Jacob isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull; 5489cd7268eSMatt Jacob } 5499cd7268eSMatt Jacob 5509cd7268eSMatt Jacob if (getenv_quad("isp_nodewwn", &wwn)) { 5519cd7268eSMatt Jacob isp->isp_osinfo.default_node_wwn = wwn; 5529cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWNN; 5539cd7268eSMatt Jacob } 5549cd7268eSMatt Jacob if (isp->isp_osinfo.default_node_wwn == 0) { 5559cd7268eSMatt Jacob isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull; 5569cd7268eSMatt Jacob } 5579cd7268eSMatt Jacob 5589cd7268eSMatt Jacob bitmap = 0; 55910365e5aSMatt Jacob (void) getenv_int("isp_fabric_hysteresis", &bitmap); 56010365e5aSMatt Jacob if (bitmap >= 0 && bitmap < 256) { 56110365e5aSMatt Jacob isp->isp_osinfo.hysteresis = bitmap; 56210365e5aSMatt Jacob } else { 56310365e5aSMatt Jacob isp->isp_osinfo.hysteresis = isp_fabric_hysteresis; 56410365e5aSMatt Jacob } 56510365e5aSMatt Jacob 56610365e5aSMatt Jacob bitmap = 0; 56710365e5aSMatt Jacob (void) getenv_int("isp_loop_down_limit", &bitmap); 56810365e5aSMatt Jacob if (bitmap >= 0 && bitmap < 0xffff) { 56910365e5aSMatt Jacob isp->isp_osinfo.loop_down_limit = bitmap; 57010365e5aSMatt Jacob } else { 57110365e5aSMatt Jacob isp->isp_osinfo.loop_down_limit = isp_loop_down_limit; 57210365e5aSMatt Jacob } 57310365e5aSMatt Jacob 574f7c631bcSMatt Jacob bitmap = 0; 575f7c631bcSMatt Jacob (void) getenv_int("isp_gone_device_time", &bitmap); 576f7c631bcSMatt Jacob if (bitmap >= 0 && bitmap < 0xffff) { 577f7c631bcSMatt Jacob isp->isp_osinfo.gone_device_time = bitmap; 578f7c631bcSMatt Jacob } else { 579f7c631bcSMatt Jacob isp->isp_osinfo.gone_device_time = isp_gone_device_time; 580f7c631bcSMatt Jacob } 5819cd7268eSMatt Jacob #ifdef ISP_FW_CRASH_DUMP 5829cd7268eSMatt Jacob bitmap = 0; 5839cd7268eSMatt Jacob if (getenv_int("isp_fw_dump_enable", &bitmap)) { 5849cd7268eSMatt Jacob if (bitmap & (1 << unit) { 5859cd7268eSMatt Jacob size_t amt = 0; 5869cd7268eSMatt Jacob if (IS_2200(isp)) { 5879cd7268eSMatt Jacob amt = QLA2200_RISC_IMAGE_DUMP_SIZE; 5889cd7268eSMatt Jacob } else if (IS_23XX(isp)) { 5899cd7268eSMatt Jacob amt = QLA2300_RISC_IMAGE_DUMP_SIZE; 5909cd7268eSMatt Jacob } 5919cd7268eSMatt Jacob if (amt) { 5929cd7268eSMatt Jacob FCPARAM(isp)->isp_dump_data = 5939cd7268eSMatt Jacob malloc(amt, M_DEVBUF, M_WAITOK); 59409934867SMatt Jacob memset(FCPARAM(isp)->isp_dump_data, 0, amt); 5959cd7268eSMatt Jacob } else { 5969cd7268eSMatt Jacob device_printf(dev, 5979cd7268eSMatt Jacob "f/w crash dumps not supported for card\n"); 5989cd7268eSMatt Jacob } 5999cd7268eSMatt Jacob } 6009cd7268eSMatt Jacob } 6019cd7268eSMatt Jacob #endif 6029cd7268eSMatt Jacob } 6039cd7268eSMatt Jacob #else 6049cd7268eSMatt Jacob static void 605336b5612SMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp) 6069cd7268eSMatt Jacob { 6079cd7268eSMatt Jacob int tval; 608f7c631bcSMatt Jacob 609222bb542SMatt Jacob /* 6109ba86737SMatt Jacob * Figure out if we're supposed to skip this one. 6119ba86737SMatt Jacob */ 6126e5c5328SMatt Jacob tval = 0; 6136e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6146e5c5328SMatt Jacob "disable", &tval) == 0 && tval) { 6159cd7268eSMatt Jacob device_printf(dev, "disabled at user request\n"); 6169cd7268eSMatt Jacob isp->isp_osinfo.disabled = 1; 6179cd7268eSMatt Jacob return; 618b9b599feSMatt Jacob } 6196e5c5328SMatt Jacob 6209cd7268eSMatt Jacob tval = -1; 6216e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6229cd7268eSMatt Jacob "role", &tval) == 0 && tval != -1) { 6239cd7268eSMatt Jacob tval &= (ISP_ROLE_INITIATOR|ISP_ROLE_TARGET); 6249cd7268eSMatt Jacob isp->isp_role = tval; 6259cd7268eSMatt Jacob device_printf(dev, "setting role to 0x%x\n", isp->isp_role); 6266e5c5328SMatt Jacob } else { 627b9b599feSMatt Jacob #ifdef ISP_TARGET_MODE 6289cd7268eSMatt Jacob isp->isp_role = ISP_ROLE_TARGET; 629b9b599feSMatt Jacob #else 6309cd7268eSMatt Jacob isp->isp_role = ISP_DEFAULT_ROLES; 631b9b599feSMatt Jacob #endif 6329ba86737SMatt Jacob } 6339ba86737SMatt Jacob 6349cd7268eSMatt Jacob tval = 0; 6359cd7268eSMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6369cd7268eSMatt Jacob "fwload_disable", &tval) == 0 && tval != 0) { 6379cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 6389cd7268eSMatt Jacob } 6399cd7268eSMatt Jacob tval = 0; 6409cd7268eSMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6419cd7268eSMatt Jacob "ignore_nvram", &tval) == 0 && tval != 0) { 6429cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 6439cd7268eSMatt Jacob } 644336b5612SMatt Jacob 645336b5612SMatt Jacob tval = 0; 646336b5612SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 647336b5612SMatt Jacob "debug", &tval); 648336b5612SMatt Jacob if (tval) { 649336b5612SMatt Jacob isp->isp_dblev = tval; 650336b5612SMatt Jacob } else { 651336b5612SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 652336b5612SMatt Jacob } 653336b5612SMatt Jacob if (bootverbose) { 654336b5612SMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 655336b5612SMatt Jacob } 656336b5612SMatt Jacob 657336b5612SMatt Jacob } 658336b5612SMatt Jacob 659336b5612SMatt Jacob static void 660336b5612SMatt Jacob isp_get_pci_options(device_t dev, int *m1, int *m2) 661336b5612SMatt Jacob { 662336b5612SMatt Jacob int tval; 663336b5612SMatt Jacob /* 664336b5612SMatt Jacob * Which we should try first - memory mapping or i/o mapping? 665336b5612SMatt Jacob * 666336b5612SMatt Jacob * We used to try memory first followed by i/o on alpha, otherwise 667336b5612SMatt Jacob * the reverse, but we should just try memory first all the time now. 668336b5612SMatt Jacob */ 669336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 670336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 671336b5612SMatt Jacob 672336b5612SMatt Jacob tval = 0; 673336b5612SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 674336b5612SMatt Jacob "prefer_iomap", &tval) == 0 && tval != 0) { 675336b5612SMatt Jacob *m1 = PCIM_CMD_PORTEN; 676336b5612SMatt Jacob *m2 = PCIM_CMD_MEMEN; 677336b5612SMatt Jacob } 678336b5612SMatt Jacob tval = 0; 679336b5612SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 680336b5612SMatt Jacob "prefer_memmap", &tval) == 0 && tval != 0) { 681336b5612SMatt Jacob *m1 = PCIM_CMD_MEMEN; 682336b5612SMatt Jacob *m2 = PCIM_CMD_PORTEN; 683336b5612SMatt Jacob } 684336b5612SMatt Jacob } 685336b5612SMatt Jacob 686336b5612SMatt Jacob static void 687336b5612SMatt Jacob isp_get_specific_options(device_t dev, ispsoftc_t *isp) 688336b5612SMatt Jacob { 689336b5612SMatt Jacob const char *sptr; 690336b5612SMatt Jacob int tval; 691336b5612SMatt Jacob 692336b5612SMatt Jacob isp->isp_osinfo.default_id = -1; 693336b5612SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 694336b5612SMatt Jacob "iid", &tval) == 0) { 695336b5612SMatt Jacob isp->isp_osinfo.default_id = tval; 696336b5612SMatt Jacob isp->isp_confopts |= ISP_CFG_OWNLOOPID; 697336b5612SMatt Jacob } 698336b5612SMatt Jacob if (isp->isp_osinfo.default_id == -1) { 699336b5612SMatt Jacob if (IS_FC(isp)) { 700336b5612SMatt Jacob isp->isp_osinfo.default_id = 109; 701336b5612SMatt Jacob } else { 702336b5612SMatt Jacob isp->isp_osinfo.default_id = 7; 703336b5612SMatt Jacob } 704336b5612SMatt Jacob } 705336b5612SMatt Jacob 706336b5612SMatt Jacob callout_handle_init(&isp->isp_osinfo.ldt); 707336b5612SMatt Jacob callout_handle_init(&isp->isp_osinfo.gdt); 708336b5612SMatt Jacob 709336b5612SMatt Jacob if (IS_SCSI(isp)) { 710336b5612SMatt Jacob return; 711336b5612SMatt Jacob } 712336b5612SMatt Jacob 7139cd7268eSMatt Jacob tval = 0; 7149cd7268eSMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 7159cd7268eSMatt Jacob "fullduplex", &tval) == 0 && tval != 0) { 7169cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 7179cd7268eSMatt Jacob } 7189cd7268eSMatt Jacob #ifdef ISP_FW_CRASH_DUMP 7199cd7268eSMatt Jacob tval = 0; 7209cd7268eSMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 7219cd7268eSMatt Jacob "fw_dump_enable", &tval) == 0 && tval != 0) { 7229cd7268eSMatt Jacob size_t amt = 0; 7239cd7268eSMatt Jacob if (IS_2200(isp)) { 7249cd7268eSMatt Jacob amt = QLA2200_RISC_IMAGE_DUMP_SIZE; 7259cd7268eSMatt Jacob } else if (IS_23XX(isp)) { 7269cd7268eSMatt Jacob amt = QLA2300_RISC_IMAGE_DUMP_SIZE; 7279cd7268eSMatt Jacob } 7289cd7268eSMatt Jacob if (amt) { 7299cd7268eSMatt Jacob FCPARAM(isp)->isp_dump_data = 7309cd7268eSMatt Jacob malloc(amt, M_DEVBUF, M_WAITOK | M_ZERO); 7319cd7268eSMatt Jacob } else { 7329cd7268eSMatt Jacob device_printf(dev, 7339cd7268eSMatt Jacob "f/w crash dumps not supported for this model\n"); 7349cd7268eSMatt Jacob } 7359cd7268eSMatt Jacob } 7369cd7268eSMatt Jacob #endif 7379cd7268eSMatt Jacob sptr = 0; 7389cd7268eSMatt Jacob if (resource_string_value(device_get_name(dev), device_get_unit(dev), 7399cd7268eSMatt Jacob "topology", (const char **) &sptr) == 0 && sptr != 0) { 7409cd7268eSMatt Jacob if (strcmp(sptr, "lport") == 0) { 7419cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 7429cd7268eSMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 7439cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 7449cd7268eSMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 7459cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 7469cd7268eSMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 7479cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 7489cd7268eSMatt Jacob } 749960f6939SMatt Jacob } 750960f6939SMatt Jacob 7519ba86737SMatt Jacob /* 7529cd7268eSMatt Jacob * Because the resource_*_value functions can neither return 7539cd7268eSMatt Jacob * 64 bit integer values, nor can they be directly coerced 7549cd7268eSMatt Jacob * to interpret the right hand side of the assignment as 7559cd7268eSMatt Jacob * you want them to interpret it, we have to force WWN 7569cd7268eSMatt Jacob * hint replacement to specify WWN strings with a leading 7579cd7268eSMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 7589cd7268eSMatt Jacob */ 7599cd7268eSMatt Jacob sptr = 0; 7609cd7268eSMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 7619cd7268eSMatt Jacob "portwwn", (const char **) &sptr); 7629cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 7639cd7268eSMatt Jacob char *eptr = 0; 7649cd7268eSMatt Jacob isp->isp_osinfo.default_port_wwn = strtouq(sptr, &eptr, 16); 7659cd7268eSMatt Jacob if (eptr < sptr + 16 || isp->isp_osinfo.default_port_wwn == 0) { 7669cd7268eSMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 7679cd7268eSMatt Jacob isp->isp_osinfo.default_port_wwn = 0; 7689cd7268eSMatt Jacob } else { 7699cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWPN; 7709cd7268eSMatt Jacob } 7719cd7268eSMatt Jacob } 7729cd7268eSMatt Jacob if (isp->isp_osinfo.default_port_wwn == 0) { 7739cd7268eSMatt Jacob isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull; 7749cd7268eSMatt Jacob } 7759cd7268eSMatt Jacob 7769cd7268eSMatt Jacob sptr = 0; 7779cd7268eSMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 7789cd7268eSMatt Jacob "nodewwn", (const char **) &sptr); 7799cd7268eSMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 7809cd7268eSMatt Jacob char *eptr = 0; 7819cd7268eSMatt Jacob isp->isp_osinfo.default_node_wwn = strtouq(sptr, &eptr, 16); 7829cd7268eSMatt Jacob if (eptr < sptr + 16 || isp->isp_osinfo.default_node_wwn == 0) { 7839cd7268eSMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 7849cd7268eSMatt Jacob isp->isp_osinfo.default_node_wwn = 0; 7859cd7268eSMatt Jacob } else { 7869cd7268eSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWNN; 7879cd7268eSMatt Jacob } 7889cd7268eSMatt Jacob } 7899cd7268eSMatt Jacob if (isp->isp_osinfo.default_node_wwn == 0) { 7909cd7268eSMatt Jacob isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull; 7919cd7268eSMatt Jacob } 7929cd7268eSMatt Jacob 7939cd7268eSMatt Jacob 79410365e5aSMatt Jacob tval = 0; 79510365e5aSMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 79610365e5aSMatt Jacob "hysteresis", &tval); 79710365e5aSMatt Jacob if (tval >= 0 && tval < 256) { 79810365e5aSMatt Jacob isp->isp_osinfo.hysteresis = tval; 79910365e5aSMatt Jacob } else { 80010365e5aSMatt Jacob isp->isp_osinfo.hysteresis = isp_fabric_hysteresis; 80110365e5aSMatt Jacob } 80210365e5aSMatt Jacob 803f7c631bcSMatt Jacob tval = -1; 80410365e5aSMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 80510365e5aSMatt Jacob "loop_down_limit", &tval); 80610365e5aSMatt Jacob if (tval >= 0 && tval < 0xffff) { 80710365e5aSMatt Jacob isp->isp_osinfo.loop_down_limit = tval; 80810365e5aSMatt Jacob } else { 80910365e5aSMatt Jacob isp->isp_osinfo.loop_down_limit = isp_loop_down_limit; 81010365e5aSMatt Jacob } 81110365e5aSMatt Jacob 812f7c631bcSMatt Jacob tval = -1; 813f7c631bcSMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 814f7c631bcSMatt Jacob "gone_device_time", &tval); 815f7c631bcSMatt Jacob if (tval >= 0 && tval < 0xffff) { 816f7c631bcSMatt Jacob isp->isp_osinfo.gone_device_time = tval; 817f7c631bcSMatt Jacob } else { 818f7c631bcSMatt Jacob isp->isp_osinfo.gone_device_time = isp_gone_device_time; 819f7c631bcSMatt Jacob } 8209cd7268eSMatt Jacob } 8219cd7268eSMatt Jacob #endif 8229cd7268eSMatt Jacob 8239cd7268eSMatt Jacob static int 8249cd7268eSMatt Jacob isp_pci_attach(device_t dev) 8259cd7268eSMatt Jacob { 8269cd7268eSMatt Jacob struct resource *regs, *irq; 8279cd7268eSMatt Jacob int rtp, rgd, iqd, m1, m2; 8289cd7268eSMatt Jacob uint32_t data, cmd, linesz, psize, basetype; 8299cd7268eSMatt Jacob struct isp_pcisoftc *pcs; 8309cd7268eSMatt Jacob ispsoftc_t *isp = NULL; 8319cd7268eSMatt Jacob struct ispmdvec *mdvp; 8329cd7268eSMatt Jacob #if __FreeBSD_version >= 500000 8339cd7268eSMatt Jacob int locksetup = 0; 8349cd7268eSMatt Jacob #endif 8359cd7268eSMatt Jacob 8369cd7268eSMatt Jacob pcs = device_get_softc(dev); 8379cd7268eSMatt Jacob if (pcs == NULL) { 8389cd7268eSMatt Jacob device_printf(dev, "cannot get softc\n"); 8399cd7268eSMatt Jacob return (ENOMEM); 8409cd7268eSMatt Jacob } 8419cd7268eSMatt Jacob memset(pcs, 0, sizeof (*pcs)); 8429cd7268eSMatt Jacob pcs->pci_dev = dev; 8439cd7268eSMatt Jacob isp = &pcs->pci_isp; 8449cd7268eSMatt Jacob 8459cd7268eSMatt Jacob /* 846336b5612SMatt Jacob * Get Generic Options 8479cd7268eSMatt Jacob */ 848336b5612SMatt Jacob isp_get_generic_options(dev, isp); 8499cd7268eSMatt Jacob 8509cd7268eSMatt Jacob /* 8519cd7268eSMatt Jacob * Check to see if options have us disabled 8529cd7268eSMatt Jacob */ 8539cd7268eSMatt Jacob if (isp->isp_osinfo.disabled) { 8549cd7268eSMatt Jacob /* 8559cd7268eSMatt Jacob * But return zero to preserve unit numbering 8569cd7268eSMatt Jacob */ 8579cd7268eSMatt Jacob return (0); 8589cd7268eSMatt Jacob } 8599cd7268eSMatt Jacob 8609cd7268eSMatt Jacob /* 8619cd7268eSMatt Jacob * Get PCI options- which in this case are just mapping preferences. 8629cd7268eSMatt Jacob */ 8639cd7268eSMatt Jacob isp_get_pci_options(dev, &m1, &m2); 8649cd7268eSMatt Jacob 865ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 866960f6939SMatt Jacob irq = regs = NULL; 867960f6939SMatt Jacob rgd = rtp = iqd = 0; 868960f6939SMatt Jacob 869b49c4674SMatt Jacob cmd = pci_read_config(dev, PCIR_COMMAND, 2); 870960f6939SMatt Jacob if (cmd & m1) { 871960f6939SMatt Jacob rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 872960f6939SMatt Jacob rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 8735f96beb9SNate Lawson regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE); 87465adb54cSMatt Jacob } 875960f6939SMatt Jacob if (regs == NULL && (cmd & m2)) { 876960f6939SMatt Jacob rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 877960f6939SMatt Jacob rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 8785f96beb9SNate Lawson regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE); 87965adb54cSMatt Jacob } 880960f6939SMatt Jacob if (regs == NULL) { 881960f6939SMatt Jacob device_printf(dev, "unable to map any ports\n"); 882960f6939SMatt Jacob goto bad; 88365adb54cSMatt Jacob } 8849cd7268eSMatt Jacob if (bootverbose) { 885f7dddf8aSMatt Jacob device_printf(dev, "using %s space register mapping\n", 886960f6939SMatt Jacob (rgd == IO_MAP_REG)? "I/O" : "Memory"); 8879cd7268eSMatt Jacob } 888960f6939SMatt Jacob pcs->pci_dev = dev; 889960f6939SMatt Jacob pcs->pci_reg = regs; 890960f6939SMatt Jacob pcs->pci_st = rman_get_bustag(regs); 891960f6939SMatt Jacob pcs->pci_sh = rman_get_bushandle(regs); 89265adb54cSMatt Jacob 893d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 894d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 895d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 896d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 897d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 898c6608df3SMatt Jacob mdvp = &mdvec; 899c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 900c6608df3SMatt Jacob psize = sizeof (sdparam); 90156aef503SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1020) { 902c6608df3SMatt Jacob mdvp = &mdvec; 903c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 904c6608df3SMatt Jacob psize = sizeof (sdparam); 905d59bd469SMatt Jacob } 906960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1080) { 907c6608df3SMatt Jacob mdvp = &mdvec_1080; 908c6608df3SMatt Jacob basetype = ISP_HA_SCSI_1080; 909c6608df3SMatt Jacob psize = sizeof (sdparam); 910c6608df3SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 911c6608df3SMatt Jacob ISP1080_DMA_REGS_OFF; 912c6608df3SMatt Jacob } 913960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1240) { 914c6608df3SMatt Jacob mdvp = &mdvec_1080; 91522e1dc85SMatt Jacob basetype = ISP_HA_SCSI_1240; 91622e1dc85SMatt Jacob psize = 2 * sizeof (sdparam); 91722e1dc85SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 91822e1dc85SMatt Jacob ISP1080_DMA_REGS_OFF; 91922e1dc85SMatt Jacob } 920960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1280) { 92122e1dc85SMatt Jacob mdvp = &mdvec_1080; 92222e1dc85SMatt Jacob basetype = ISP_HA_SCSI_1280; 923c6608df3SMatt Jacob psize = 2 * sizeof (sdparam); 924d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 925d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 926d59bd469SMatt Jacob } 927f556e83bSMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP10160) { 928f556e83bSMatt Jacob mdvp = &mdvec_12160; 929f556e83bSMatt Jacob basetype = ISP_HA_SCSI_10160; 930f556e83bSMatt Jacob psize = sizeof (sdparam); 931f556e83bSMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 932f556e83bSMatt Jacob ISP1080_DMA_REGS_OFF; 933f556e83bSMatt Jacob } 934960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP12160) { 935960f6939SMatt Jacob mdvp = &mdvec_12160; 936960f6939SMatt Jacob basetype = ISP_HA_SCSI_12160; 937960f6939SMatt Jacob psize = 2 * sizeof (sdparam); 938960f6939SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 939960f6939SMatt Jacob ISP1080_DMA_REGS_OFF; 940960f6939SMatt Jacob } 941960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2100) { 942c6608df3SMatt Jacob mdvp = &mdvec_2100; 943c6608df3SMatt Jacob basetype = ISP_HA_FC_2100; 944c6608df3SMatt Jacob psize = sizeof (fcparam); 945d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 946d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 947960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 948ab6d0040SMatt Jacob /* 949ab6d0040SMatt Jacob * XXX: Need to get the actual revision 950ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 951ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 952ab6d0040SMatt Jacob * XXX; boards. 953ab6d0040SMatt Jacob */ 954ab6d0040SMatt Jacob linesz = 1; 955ab6d0040SMatt Jacob } 95665adb54cSMatt Jacob } 957960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2200) { 958222bb542SMatt Jacob mdvp = &mdvec_2200; 959222bb542SMatt Jacob basetype = ISP_HA_FC_2200; 960222bb542SMatt Jacob psize = sizeof (fcparam); 961222bb542SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 962222bb542SMatt Jacob PCI_MBOX_REGS2100_OFF; 963222bb542SMatt Jacob } 96475c1e828SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300) { 965126ec864SMatt Jacob mdvp = &mdvec_2300; 966126ec864SMatt Jacob basetype = ISP_HA_FC_2300; 967126ec864SMatt Jacob psize = sizeof (fcparam); 968126ec864SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 969126ec864SMatt Jacob PCI_MBOX_REGS2300_OFF; 970126ec864SMatt Jacob } 971dd1419abSMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2312 || 972dd1419abSMatt Jacob pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 97375c1e828SMatt Jacob mdvp = &mdvec_2300; 97475c1e828SMatt Jacob basetype = ISP_HA_FC_2312; 97575c1e828SMatt Jacob psize = sizeof (fcparam); 97675c1e828SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 97775c1e828SMatt Jacob PCI_MBOX_REGS2300_OFF; 97875c1e828SMatt Jacob } 9799a5af410SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2322 || 9809a5af410SMatt Jacob pci_get_devid(dev) == PCI_QLOGIC_ISP6322) { 981e5265237SMatt Jacob mdvp = &mdvec_2300; 982e5265237SMatt Jacob basetype = ISP_HA_FC_2322; 983e5265237SMatt Jacob psize = sizeof (fcparam); 984e5265237SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 985e5265237SMatt Jacob PCI_MBOX_REGS2300_OFF; 986e5265237SMatt Jacob } 98741675df0SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2422 || 98841675df0SMatt Jacob pci_get_devid(dev) == PCI_QLOGIC_ISP2432) { 98910365e5aSMatt Jacob mdvp = &mdvec_2400; 99010365e5aSMatt Jacob basetype = ISP_HA_FC_2400; 9918872e3d7SMatt Jacob psize = sizeof (fcparam); 9928872e3d7SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 99310365e5aSMatt Jacob PCI_MBOX_REGS2400_OFF; 9948872e3d7SMatt Jacob } 995c6608df3SMatt Jacob isp = &pcs->pci_isp; 9967cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 997c6608df3SMatt Jacob if (isp->isp_param == NULL) { 998960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 999960f6939SMatt Jacob goto bad; 1000c6608df3SMatt Jacob } 1001c6608df3SMatt Jacob isp->isp_mdvec = mdvp; 1002c6608df3SMatt Jacob isp->isp_type = basetype; 1003960f6939SMatt Jacob isp->isp_revision = pci_get_revid(dev); 10046e5c5328SMatt Jacob isp->isp_dev = dev; 100565adb54cSMatt Jacob 1006336b5612SMatt Jacob /* 1007336b5612SMatt Jacob * Now that we know who we are (roughly) get/set specific options 1008336b5612SMatt Jacob */ 1009336b5612SMatt Jacob isp_get_specific_options(dev, isp); 1010336b5612SMatt Jacob 10119a5af410SMatt Jacob #if __FreeBSD_version >= 700000 101256aef503SMatt Jacob /* 101356aef503SMatt Jacob * Try and find firmware for this device. 101456aef503SMatt Jacob */ 10159a5af410SMatt Jacob { 10169a5af410SMatt Jacob char fwname[32]; 10179a5af410SMatt Jacob unsigned int did = pci_get_device(dev); 101856aef503SMatt Jacob 10199a5af410SMatt Jacob /* 10209a5af410SMatt Jacob * Map a few pci ids to fw names 10219a5af410SMatt Jacob */ 10229a5af410SMatt Jacob switch (did) { 10239a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP1020: 10249a5af410SMatt Jacob did = 0x1040; 10259a5af410SMatt Jacob break; 10269a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP1240: 10279a5af410SMatt Jacob did = 0x1080; 10289a5af410SMatt Jacob break; 10299a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP10160: 10309a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP12160: 10319a5af410SMatt Jacob did = 0x12160; 10329a5af410SMatt Jacob break; 10339a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP6312: 10349a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP2312: 10359a5af410SMatt Jacob did = 0x2300; 10369a5af410SMatt Jacob break; 10379a5af410SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP6322: 10389a5af410SMatt Jacob did = 0x2322; 10399a5af410SMatt Jacob break; 104010365e5aSMatt Jacob case PCI_PRODUCT_QLOGIC_ISP2422: 1041392695e0SMatt Jacob case PCI_PRODUCT_QLOGIC_ISP2432: 104210365e5aSMatt Jacob did = 0x2400; 104310365e5aSMatt Jacob break; 10449a5af410SMatt Jacob default: 10459a5af410SMatt Jacob break; 10469a5af410SMatt Jacob } 10479a5af410SMatt Jacob 10489a5af410SMatt Jacob isp->isp_osinfo.fw = NULL; 10499a5af410SMatt Jacob if (isp->isp_role & ISP_ROLE_TARGET) { 10509a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x_it", did); 10519a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 10529a5af410SMatt Jacob } 10539a5af410SMatt Jacob if (isp->isp_osinfo.fw == NULL) { 10549a5af410SMatt Jacob snprintf(fwname, sizeof (fwname), "isp_%04x", did); 10559a5af410SMatt Jacob isp->isp_osinfo.fw = firmware_get(fwname); 10569a5af410SMatt Jacob } 10579a5af410SMatt Jacob if (isp->isp_osinfo.fw != NULL) { 10589a5af410SMatt Jacob union { 10599a5af410SMatt Jacob const void *fred; 10609a5af410SMatt Jacob uint16_t *bob; 10619a5af410SMatt Jacob } u; 10629a5af410SMatt Jacob u.fred = isp->isp_osinfo.fw->data; 10639a5af410SMatt Jacob isp->isp_mdvec->dv_ispfw = u.bob; 10649a5af410SMatt Jacob } 10659a5af410SMatt Jacob } 10669a5af410SMatt Jacob #else 10678a97c03aSMatt Jacob if (isp_get_firmware_p) { 106856aef503SMatt Jacob int device = (int) pci_get_device(dev); 106956aef503SMatt Jacob #ifdef ISP_TARGET_MODE 107056aef503SMatt Jacob (*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw); 107156aef503SMatt Jacob #else 107256aef503SMatt Jacob (*isp_get_firmware_p)(0, 0, device, &mdvp->dv_ispfw); 107356aef503SMatt Jacob #endif 107456aef503SMatt Jacob } 10759a5af410SMatt Jacob #endif 107656aef503SMatt Jacob 107756aef503SMatt Jacob /* 1078d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 1079d951bbcaSMatt Jacob * are set. 1080d951bbcaSMatt Jacob */ 1081960f6939SMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | 1082960f6939SMatt Jacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 10839a5af410SMatt Jacob 108475c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 108575c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 108675c1e828SMatt Jacob } 10879a5af410SMatt Jacob 10888a97c03aSMatt Jacob if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) { 10898a97c03aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 10908a97c03aSMatt Jacob } 10918a97c03aSMatt Jacob 109206cacb29SMatt Jacob #ifdef WE_KNEW_WHAT_WE_WERE_DOING 109310365e5aSMatt Jacob if (IS_24XX(isp)) { 109410365e5aSMatt Jacob int reg; 109510365e5aSMatt Jacob 109610365e5aSMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 109710365e5aSMatt Jacob 109810365e5aSMatt Jacob /* 109910365e5aSMatt Jacob * Is this a PCI-X card? If so, set max read byte count. 110010365e5aSMatt Jacob */ 110110365e5aSMatt Jacob if (pci_find_extcap(dev, PCIY_PCIX, ®) == 0) { 110210365e5aSMatt Jacob uint16_t pxcmd; 110310365e5aSMatt Jacob reg += 2; 110410365e5aSMatt Jacob 110510365e5aSMatt Jacob pxcmd = pci_read_config(dev, reg, 2); 110610365e5aSMatt Jacob pxcmd &= ~0xc; 110710365e5aSMatt Jacob pxcmd |= 0x8; 110810365e5aSMatt Jacob pci_write_config(dev, reg, 2, pxcmd); 110910365e5aSMatt Jacob } 111010365e5aSMatt Jacob 111110365e5aSMatt Jacob /* 111210365e5aSMatt Jacob * Is this a PCI Express card? If so, set max read byte count. 111310365e5aSMatt Jacob */ 111410365e5aSMatt Jacob if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { 111510365e5aSMatt Jacob uint16_t pectl; 111610365e5aSMatt Jacob 111710365e5aSMatt Jacob reg += 0x8; 111810365e5aSMatt Jacob pectl = pci_read_config(dev, reg, 2); 111910365e5aSMatt Jacob pectl &= ~0x7000; 112010365e5aSMatt Jacob pectl |= 0x4000; 112110365e5aSMatt Jacob pci_write_config(dev, reg, 2, pectl); 112210365e5aSMatt Jacob } 112310365e5aSMatt Jacob } 112406cacb29SMatt Jacob #else 112506cacb29SMatt Jacob if (IS_24XX(isp)) { 112606cacb29SMatt Jacob cmd &= ~PCIM_CMD_INTX_DISABLE; 112706cacb29SMatt Jacob } 112806cacb29SMatt Jacob #endif 112910365e5aSMatt Jacob 1130b49c4674SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 1131ab6d0040SMatt Jacob 1132d951bbcaSMatt Jacob /* 1133222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 1134d951bbcaSMatt Jacob */ 1135960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 1136ab6d0040SMatt Jacob if (data != linesz) { 1137d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 1138d02373f1SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d", data); 1139960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 1140d951bbcaSMatt Jacob } 1141ab6d0040SMatt Jacob 1142d951bbcaSMatt Jacob /* 1143d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 1144d951bbcaSMatt Jacob */ 1145960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 1146d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 1147d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 1148d02373f1SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI latency to %d", data); 1149960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 1150d951bbcaSMatt Jacob } 1151ab6d0040SMatt Jacob 1152ab6d0040SMatt Jacob /* 1153ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 1154ab6d0040SMatt Jacob */ 1155960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 1156ab6d0040SMatt Jacob data &= ~1; 1157960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 115805fbcbb0SMatt Jacob 1159960f6939SMatt Jacob iqd = 0; 11605f96beb9SNate Lawson irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, 11615f96beb9SNate Lawson RF_ACTIVE | RF_SHAREABLE); 1162960f6939SMatt Jacob if (irq == NULL) { 1163960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 1164960f6939SMatt Jacob goto bad; 1165960f6939SMatt Jacob } 1166960f6939SMatt Jacob 11679cd7268eSMatt Jacob #if __FreeBSD_version >= 500000 1168f09b1922SMatt Jacob /* Make sure the lock is set up. */ 11696008862bSJohn Baldwin mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); 1170f09b1922SMatt Jacob locksetup++; 11719cd7268eSMatt Jacob #endif 1172f09b1922SMatt Jacob 117372429e49SMatt Jacob if (bus_setup_intr(dev, irq, ISP_IFLAGS, isp_pci_intr, isp, &pcs->ih)) { 1174f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 1175f09b1922SMatt Jacob goto bad; 1176f09b1922SMatt Jacob } 1177960f6939SMatt Jacob 117805fbcbb0SMatt Jacob /* 117975c1e828SMatt Jacob * Last minute checks... 118075c1e828SMatt Jacob */ 118110365e5aSMatt Jacob if (IS_23XX(isp) || IS_24XX(isp)) { 118275c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 118375c1e828SMatt Jacob } 118475c1e828SMatt Jacob 118510365e5aSMatt Jacob if (IS_23XX(isp)) { 118610365e5aSMatt Jacob /* 118710365e5aSMatt Jacob * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command. 118810365e5aSMatt Jacob */ 118910365e5aSMatt Jacob isp->isp_touched = 1; 119010365e5aSMatt Jacob } 119110365e5aSMatt Jacob 119275c1e828SMatt Jacob /* 119305fbcbb0SMatt Jacob * Make sure we're in reset state. 119405fbcbb0SMatt Jacob */ 11953395b056SMatt Jacob ISP_LOCK(isp); 119665adb54cSMatt Jacob isp_reset(isp); 119765adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 11983395b056SMatt Jacob ISP_UNLOCK(isp); 1199960f6939SMatt Jacob goto bad; 120065adb54cSMatt Jacob } 120165adb54cSMatt Jacob isp_init(isp); 1202b9b599feSMatt Jacob if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) { 120365adb54cSMatt Jacob isp_uninit(isp); 12043395b056SMatt Jacob ISP_UNLOCK(isp); 1205960f6939SMatt Jacob goto bad; 1206d59bd469SMatt Jacob } 120765adb54cSMatt Jacob isp_attach(isp); 1208b9b599feSMatt Jacob if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) { 120965adb54cSMatt Jacob isp_uninit(isp); 12103395b056SMatt Jacob ISP_UNLOCK(isp); 1211960f6939SMatt Jacob goto bad; 1212960f6939SMatt Jacob } 121356aef503SMatt Jacob /* 121456aef503SMatt Jacob * XXXX: Here is where we might unload the f/w module 121556aef503SMatt Jacob * XXXX: (or decrease the reference count to it). 121656aef503SMatt Jacob */ 12173395b056SMatt Jacob ISP_UNLOCK(isp); 121810365e5aSMatt Jacob 1219960f6939SMatt Jacob return (0); 1220960f6939SMatt Jacob 1221960f6939SMatt Jacob bad: 1222960f6939SMatt Jacob 1223960f6939SMatt Jacob if (pcs && pcs->ih) { 1224960f6939SMatt Jacob (void) bus_teardown_intr(dev, irq, pcs->ih); 1225960f6939SMatt Jacob } 1226960f6939SMatt Jacob 12279cd7268eSMatt Jacob #if __FreeBSD_version >= 500000 12283395b056SMatt Jacob if (locksetup && isp) { 12293395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 12303395b056SMatt Jacob } 12319cd7268eSMatt Jacob #endif 12323395b056SMatt Jacob 1233960f6939SMatt Jacob if (irq) { 1234960f6939SMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq); 1235960f6939SMatt Jacob } 12363395b056SMatt Jacob 12373395b056SMatt Jacob 1238960f6939SMatt Jacob if (regs) { 1239960f6939SMatt Jacob (void) bus_release_resource(dev, rtp, rgd, regs); 1240960f6939SMatt Jacob } 12413395b056SMatt Jacob 1242960f6939SMatt Jacob if (pcs) { 12439cd7268eSMatt Jacob if (pcs->pci_isp.isp_param) { 12449cd7268eSMatt Jacob #ifdef ISP_FW_CRASH_DUMP 12459cd7268eSMatt Jacob if (IS_FC(isp) && FCPARAM(isp)->isp_dump_data) { 12469cd7268eSMatt Jacob free(FCPARAM(isp)->isp_dump_data, M_DEVBUF); 12479cd7268eSMatt Jacob } 12489cd7268eSMatt Jacob #endif 1249960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 12509cd7268eSMatt Jacob } 125165adb54cSMatt Jacob } 12523395b056SMatt Jacob 125356aef503SMatt Jacob /* 125456aef503SMatt Jacob * XXXX: Here is where we might unload the f/w module 125556aef503SMatt Jacob * XXXX: (or decrease the reference count to it). 125656aef503SMatt Jacob */ 1257960f6939SMatt Jacob return (ENXIO); 125865adb54cSMatt Jacob } 125965adb54cSMatt Jacob 126010365e5aSMatt Jacob static int 126110365e5aSMatt Jacob isp_pci_detach(device_t dev) 126210365e5aSMatt Jacob { 126310365e5aSMatt Jacob struct isp_pcisoftc *pcs; 126410365e5aSMatt Jacob ispsoftc_t *isp; 126510365e5aSMatt Jacob 126610365e5aSMatt Jacob pcs = device_get_softc(dev); 126710365e5aSMatt Jacob if (pcs == NULL) { 126810365e5aSMatt Jacob return (ENXIO); 126910365e5aSMatt Jacob } 127010365e5aSMatt Jacob isp = (ispsoftc_t *) pcs; 127110365e5aSMatt Jacob ISP_DISABLE_INTS(isp); 127210365e5aSMatt Jacob return (0); 127310365e5aSMatt Jacob } 127410365e5aSMatt Jacob 1275f09b1922SMatt Jacob static void 1276f09b1922SMatt Jacob isp_pci_intr(void *arg) 1277f09b1922SMatt Jacob { 12789cd7268eSMatt Jacob ispsoftc_t *isp = arg; 127910365e5aSMatt Jacob uint32_t isr; 128010365e5aSMatt Jacob uint16_t sema, mbox; 1281126ec864SMatt Jacob 1282f09b1922SMatt Jacob ISP_LOCK(isp); 1283126ec864SMatt Jacob isp->isp_intcnt++; 1284126ec864SMatt Jacob if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { 1285126ec864SMatt Jacob isp->isp_intbogus++; 1286126ec864SMatt Jacob } else { 1287126ec864SMatt Jacob isp_intr(isp, isr, sema, mbox); 1288126ec864SMatt Jacob } 1289f09b1922SMatt Jacob ISP_UNLOCK(isp); 1290f09b1922SMatt Jacob } 1291f09b1922SMatt Jacob 1292126ec864SMatt Jacob 1293126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 1294126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 12954cc9e3e7SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xfff)) 1296126ec864SMatt Jacob 1297126ec864SMatt Jacob #define BXR2(pcs, off) \ 1298126ec864SMatt Jacob bus_space_read_2(pcs->pci_st, pcs->pci_sh, off) 1299126ec864SMatt Jacob #define BXW2(pcs, off, v) \ 1300126ec864SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v) 130110365e5aSMatt Jacob #define BXR4(pcs, off) \ 130210365e5aSMatt Jacob bus_space_read_4(pcs->pci_st, pcs->pci_sh, off) 130310365e5aSMatt Jacob #define BXW4(pcs, off, v) \ 130410365e5aSMatt Jacob bus_space_write_4(pcs->pci_st, pcs->pci_sh, off, v) 1305126ec864SMatt Jacob 1306126ec864SMatt Jacob 130753af7d22SMatt Jacob static __inline int 13089cd7268eSMatt Jacob isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp) 1309126ec864SMatt Jacob { 1310126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 131110365e5aSMatt Jacob uint32_t val0, val1; 1312126ec864SMatt Jacob int i = 0; 1313126ec864SMatt Jacob 1314126ec864SMatt Jacob do { 1315126ec864SMatt Jacob val0 = BXR2(pcs, IspVirt2Off(isp, off)); 1316126ec864SMatt Jacob val1 = BXR2(pcs, IspVirt2Off(isp, off)); 1317126ec864SMatt Jacob } while (val0 != val1 && ++i < 1000); 1318126ec864SMatt Jacob if (val0 != val1) { 1319126ec864SMatt Jacob return (1); 1320126ec864SMatt Jacob } 1321126ec864SMatt Jacob *rp = val0; 1322126ec864SMatt Jacob return (0); 1323126ec864SMatt Jacob } 1324126ec864SMatt Jacob 1325126ec864SMatt Jacob static int 132610365e5aSMatt Jacob isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, 13271dae40ebSMatt Jacob uint16_t *semap, uint16_t *mbp) 1328126ec864SMatt Jacob { 1329126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 13301dae40ebSMatt Jacob uint16_t isr, sema; 1331126ec864SMatt Jacob 1332126ec864SMatt Jacob if (IS_2100(isp)) { 1333126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { 1334126ec864SMatt Jacob return (0); 1335126ec864SMatt Jacob } 1336126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { 1337126ec864SMatt Jacob return (0); 1338126ec864SMatt Jacob } 1339126ec864SMatt Jacob } else { 1340126ec864SMatt Jacob isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR)); 1341126ec864SMatt Jacob sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA)); 1342126ec864SMatt Jacob } 1343126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 1344126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 1345126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 1346126ec864SMatt Jacob if (isr == 0 && sema == 0) { 1347126ec864SMatt Jacob return (0); 1348126ec864SMatt Jacob } 1349126ec864SMatt Jacob *isrp = isr; 1350126ec864SMatt Jacob if ((*semap = sema) != 0) { 1351126ec864SMatt Jacob if (IS_2100(isp)) { 1352126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) { 1353126ec864SMatt Jacob return (0); 1354126ec864SMatt Jacob } 1355126ec864SMatt Jacob } else { 1356126ec864SMatt Jacob *mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0)); 1357126ec864SMatt Jacob } 1358126ec864SMatt Jacob } 1359126ec864SMatt Jacob return (1); 1360126ec864SMatt Jacob } 1361126ec864SMatt Jacob 1362126ec864SMatt Jacob static int 136310365e5aSMatt Jacob isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp, 13641dae40ebSMatt Jacob uint16_t *semap, uint16_t *mbox0p) 1365126ec864SMatt Jacob { 1366126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 136710365e5aSMatt Jacob uint32_t hccr; 13681dae40ebSMatt Jacob uint32_t r2hisr; 1369126ec864SMatt Jacob 13703bd40330SMatt Jacob if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 13713bd40330SMatt Jacob *isrp = 0; 1372db4fa023SMatt Jacob return (0); 13733bd40330SMatt Jacob } 137410365e5aSMatt Jacob r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU_R2HSTSLO)); 1375126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 1376126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 1377126ec864SMatt Jacob *isrp = 0; 1378126ec864SMatt Jacob return (0); 1379126ec864SMatt Jacob } 1380126ec864SMatt Jacob switch (r2hisr & BIU_R2HST_ISTAT_MASK) { 1381126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 1382126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 1383126ec864SMatt Jacob case ISPR2HST_MBX_OK: 1384126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 1385126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 1386126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1387126ec864SMatt Jacob *mbox0p = (r2hisr >> 16); 1388126ec864SMatt Jacob *semap = 1; 1389126ec864SMatt Jacob return (1); 1390fc3bbaaaSMatt Jacob case ISPR2HST_RIO_16: 1391fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1392fc3bbaaaSMatt Jacob *mbox0p = ASYNC_RIO1; 1393fc3bbaaaSMatt Jacob *semap = 1; 1394fc3bbaaaSMatt Jacob return (1); 1395fc3bbaaaSMatt Jacob case ISPR2HST_FPOST: 1396fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1397fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CMD_CMPLT; 1398fc3bbaaaSMatt Jacob *semap = 1; 1399fc3bbaaaSMatt Jacob return (1); 1400fc3bbaaaSMatt Jacob case ISPR2HST_FPOST_CTIO: 1401fc3bbaaaSMatt Jacob *isrp = r2hisr & 0xffff; 1402fc3bbaaaSMatt Jacob *mbox0p = ASYNC_CTIO_DONE; 1403fc3bbaaaSMatt Jacob *semap = 1; 1404fc3bbaaaSMatt Jacob return (1); 1405126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 1406126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 1407126ec864SMatt Jacob *mbox0p = 0; 1408126ec864SMatt Jacob *semap = 0; 1409126ec864SMatt Jacob return (1); 1410126ec864SMatt Jacob default: 14118a97c03aSMatt Jacob hccr = ISP_READ(isp, HCCR); 14128a97c03aSMatt Jacob if (hccr & HCCR_PAUSE) { 14138a97c03aSMatt Jacob ISP_WRITE(isp, HCCR, HCCR_RESET); 14148a97c03aSMatt Jacob isp_prt(isp, ISP_LOGERR, 14155ccae6a5SMatt Jacob "RISC paused at interrupt (%x->%x)", hccr, 14168a97c03aSMatt Jacob ISP_READ(isp, HCCR)); 14175ccae6a5SMatt Jacob ISP_WRITE(isp, BIU_ICR, 0); 14188a97c03aSMatt Jacob } else { 141910365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", 14208a97c03aSMatt Jacob r2hisr); 14218a97c03aSMatt Jacob } 1422126ec864SMatt Jacob return (0); 1423126ec864SMatt Jacob } 1424126ec864SMatt Jacob } 1425126ec864SMatt Jacob 142610365e5aSMatt Jacob static int 142710365e5aSMatt Jacob isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp, 142810365e5aSMatt Jacob uint16_t *semap, uint16_t *mbox0p) 142910365e5aSMatt Jacob { 143010365e5aSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 143110365e5aSMatt Jacob uint32_t r2hisr; 143210365e5aSMatt Jacob 143310365e5aSMatt Jacob r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU2400_R2HSTSLO)); 143410365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 143510365e5aSMatt Jacob if ((r2hisr & BIU2400_R2HST_INTR) == 0) { 143610365e5aSMatt Jacob *isrp = 0; 143710365e5aSMatt Jacob return (0); 143810365e5aSMatt Jacob } 143910365e5aSMatt Jacob switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) { 144010365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_OK: 144110365e5aSMatt Jacob case ISP2400R2HST_ROM_MBX_FAIL: 144210365e5aSMatt Jacob case ISP2400R2HST_MBX_OK: 144310365e5aSMatt Jacob case ISP2400R2HST_MBX_FAIL: 144410365e5aSMatt Jacob case ISP2400R2HST_ASYNC_EVENT: 144510365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 144610365e5aSMatt Jacob *mbox0p = (r2hisr >> 16); 144710365e5aSMatt Jacob *semap = 1; 144810365e5aSMatt Jacob return (1); 144910365e5aSMatt Jacob case ISP2400R2HST_RSPQ_UPDATE: 145010365e5aSMatt Jacob case ISP2400R2HST_ATIO_RSPQ_UPDATE: 145110365e5aSMatt Jacob case ISP2400R2HST_ATIO_RQST_UPDATE: 145210365e5aSMatt Jacob *isrp = r2hisr & 0xffff; 145310365e5aSMatt Jacob *mbox0p = 0; 145410365e5aSMatt Jacob *semap = 0; 145510365e5aSMatt Jacob return (1); 145610365e5aSMatt Jacob default: 145710365e5aSMatt Jacob ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT); 145810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr); 145910365e5aSMatt Jacob return (0); 146010365e5aSMatt Jacob } 146110365e5aSMatt Jacob } 146210365e5aSMatt Jacob 146310365e5aSMatt Jacob static uint32_t 14649cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff) 146565adb54cSMatt Jacob { 146610365e5aSMatt Jacob uint32_t rv; 146765adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 1468126ec864SMatt Jacob int oldconf = 0; 146965adb54cSMatt Jacob 1470d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 147165adb54cSMatt Jacob /* 147265adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 147365adb54cSMatt Jacob */ 1474126ec864SMatt Jacob oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1475126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 1476126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 147765adb54cSMatt Jacob } 1478126ec864SMatt Jacob rv = BXR2(pcs, IspVirt2Off(isp, regoff)); 1479d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 1480126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); 148165adb54cSMatt Jacob } 148265adb54cSMatt Jacob return (rv); 148365adb54cSMatt Jacob } 148465adb54cSMatt Jacob 148565adb54cSMatt Jacob static void 148610365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val) 148765adb54cSMatt Jacob { 148865adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 1489126ec864SMatt Jacob int oldconf = 0; 149010365e5aSMatt Jacob volatile int junk; 1491d59bd469SMatt Jacob 1492d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 149365adb54cSMatt Jacob /* 149465adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 149565adb54cSMatt Jacob */ 1496126ec864SMatt Jacob oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1497126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 1498126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 1499f9734398SMatt Jacob if (IS_2100(isp)) { 150010365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 150165adb54cSMatt Jacob } 1502f9734398SMatt Jacob } 1503126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, regoff), val); 1504f9734398SMatt Jacob if (IS_2100(isp)) { 150510365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, regoff)); 1506f9734398SMatt Jacob } 1507d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 1508126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); 1509f9734398SMatt Jacob if (IS_2100(isp)) { 151010365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 151165adb54cSMatt Jacob } 151265adb54cSMatt Jacob } 1513f9734398SMatt Jacob } 151465adb54cSMatt Jacob 151510365e5aSMatt Jacob static uint32_t 15169cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff) 1517d59bd469SMatt Jacob { 151810365e5aSMatt Jacob uint32_t rv, oc = 0; 1519d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 1520d59bd469SMatt Jacob 152122e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 152222e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 152310365e5aSMatt Jacob uint32_t tc; 1524d59bd469SMatt Jacob /* 1525d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1526d59bd469SMatt Jacob */ 1527126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 152822e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 152922e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 153022e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 153122e1dc85SMatt Jacob else 153222e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 1533126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); 1534d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 1535126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1536126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 1537126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 1538d59bd469SMatt Jacob } 1539126ec864SMatt Jacob rv = BXR2(pcs, IspVirt2Off(isp, regoff)); 154022e1dc85SMatt Jacob if (oc) { 1541126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); 1542d59bd469SMatt Jacob } 1543d59bd469SMatt Jacob return (rv); 1544d59bd469SMatt Jacob } 1545d59bd469SMatt Jacob 1546d59bd469SMatt Jacob static void 154710365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val) 1548d59bd469SMatt Jacob { 1549d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 1550126ec864SMatt Jacob int oc = 0; 155110365e5aSMatt Jacob volatile int junk; 1552d59bd469SMatt Jacob 155322e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 155422e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 155510365e5aSMatt Jacob uint32_t tc; 1556d59bd469SMatt Jacob /* 1557d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 1558d59bd469SMatt Jacob */ 1559126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 156022e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 156122e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 156222e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 156322e1dc85SMatt Jacob else 156422e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 1565126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); 156610365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1567d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 1568126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1569126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 1570126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 157110365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1572d59bd469SMatt Jacob } 1573126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, regoff), val); 157410365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, regoff)); 157522e1dc85SMatt Jacob if (oc) { 1576126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); 157710365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 157810365e5aSMatt Jacob } 157910365e5aSMatt Jacob } 158010365e5aSMatt Jacob 158110365e5aSMatt Jacob static uint32_t 158210365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff) 158310365e5aSMatt Jacob { 158410365e5aSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 158510365e5aSMatt Jacob uint32_t rv; 158610365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 158710365e5aSMatt Jacob 158810365e5aSMatt Jacob switch (block) { 158910365e5aSMatt Jacob case BIU_BLOCK: 159010365e5aSMatt Jacob break; 159110365e5aSMatt Jacob case MBOX_BLOCK: 159210365e5aSMatt Jacob return (BXR2(pcs, IspVirt2Off(pcs, regoff))); 159310365e5aSMatt Jacob case SXP_BLOCK: 159410365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff); 159510365e5aSMatt Jacob return (0xffffffff); 159610365e5aSMatt Jacob case RISC_BLOCK: 159710365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff); 159810365e5aSMatt Jacob return (0xffffffff); 159910365e5aSMatt Jacob case DMA_BLOCK: 160010365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff); 160110365e5aSMatt Jacob return (0xffffffff); 160210365e5aSMatt Jacob default: 160310365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff); 160410365e5aSMatt Jacob return (0xffffffff); 160510365e5aSMatt Jacob } 160610365e5aSMatt Jacob 160710365e5aSMatt Jacob 160810365e5aSMatt Jacob switch (regoff) { 160910365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 161010365e5aSMatt Jacob case BIU2400_FLASH_DATA: 161110365e5aSMatt Jacob case BIU2400_ICR: 161210365e5aSMatt Jacob case BIU2400_ISR: 161310365e5aSMatt Jacob case BIU2400_CSR: 161410365e5aSMatt Jacob case BIU2400_REQINP: 161510365e5aSMatt Jacob case BIU2400_REQOUTP: 161610365e5aSMatt Jacob case BIU2400_RSPINP: 161710365e5aSMatt Jacob case BIU2400_RSPOUTP: 161810365e5aSMatt Jacob case BIU2400_PRI_RQINP: 161910365e5aSMatt Jacob case BIU2400_PRI_RSPINP: 162010365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 162110365e5aSMatt Jacob case BIU2400_ATIO_REQINP: 162210365e5aSMatt Jacob case BIU2400_HCCR: 162310365e5aSMatt Jacob case BIU2400_GPIOD: 162410365e5aSMatt Jacob case BIU2400_GPIOE: 162510365e5aSMatt Jacob case BIU2400_HSEMA: 162610365e5aSMatt Jacob rv = BXR4(pcs, IspVirt2Off(pcs, regoff)); 162710365e5aSMatt Jacob break; 162810365e5aSMatt Jacob case BIU2400_R2HSTSLO: 162910365e5aSMatt Jacob rv = BXR4(pcs, IspVirt2Off(pcs, regoff)); 163010365e5aSMatt Jacob break; 163110365e5aSMatt Jacob case BIU2400_R2HSTSHI: 163210365e5aSMatt Jacob rv = BXR4(pcs, IspVirt2Off(pcs, regoff)) >> 16; 163310365e5aSMatt Jacob break; 163410365e5aSMatt Jacob default: 163510365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 163610365e5aSMatt Jacob "isp_pci_rd_reg_2400: unknown offset %x", regoff); 163710365e5aSMatt Jacob rv = 0xffffffff; 163810365e5aSMatt Jacob break; 163910365e5aSMatt Jacob } 164010365e5aSMatt Jacob return (rv); 164110365e5aSMatt Jacob } 164210365e5aSMatt Jacob 164310365e5aSMatt Jacob static void 164410365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val) 164510365e5aSMatt Jacob { 164610365e5aSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 164710365e5aSMatt Jacob int block = regoff & _BLK_REG_MASK; 164810365e5aSMatt Jacob volatile int junk; 164910365e5aSMatt Jacob 165010365e5aSMatt Jacob switch (block) { 165110365e5aSMatt Jacob case BIU_BLOCK: 165210365e5aSMatt Jacob break; 165310365e5aSMatt Jacob case MBOX_BLOCK: 165410365e5aSMatt Jacob BXW2(pcs, IspVirt2Off(pcs, regoff), val); 165510365e5aSMatt Jacob junk = BXR2(pcs, IspVirt2Off(pcs, regoff)); 165610365e5aSMatt Jacob return; 165710365e5aSMatt Jacob case SXP_BLOCK: 165810365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff); 165910365e5aSMatt Jacob return; 166010365e5aSMatt Jacob case RISC_BLOCK: 166110365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff); 166210365e5aSMatt Jacob return; 166310365e5aSMatt Jacob case DMA_BLOCK: 166410365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff); 166510365e5aSMatt Jacob return; 166610365e5aSMatt Jacob default: 166710365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x", 166810365e5aSMatt Jacob regoff); 166910365e5aSMatt Jacob break; 167010365e5aSMatt Jacob } 167110365e5aSMatt Jacob 167210365e5aSMatt Jacob switch (regoff) { 167310365e5aSMatt Jacob case BIU2400_FLASH_ADDR: 167410365e5aSMatt Jacob case BIU2400_FLASH_DATA: 167510365e5aSMatt Jacob case BIU2400_ICR: 167610365e5aSMatt Jacob case BIU2400_ISR: 167710365e5aSMatt Jacob case BIU2400_CSR: 167810365e5aSMatt Jacob case BIU2400_REQINP: 167910365e5aSMatt Jacob case BIU2400_REQOUTP: 168010365e5aSMatt Jacob case BIU2400_RSPINP: 168110365e5aSMatt Jacob case BIU2400_RSPOUTP: 168210365e5aSMatt Jacob case BIU2400_PRI_RQINP: 168310365e5aSMatt Jacob case BIU2400_PRI_RSPINP: 168410365e5aSMatt Jacob case BIU2400_ATIO_RSPINP: 168510365e5aSMatt Jacob case BIU2400_ATIO_REQINP: 168610365e5aSMatt Jacob case BIU2400_HCCR: 168710365e5aSMatt Jacob case BIU2400_GPIOD: 168810365e5aSMatt Jacob case BIU2400_GPIOE: 168910365e5aSMatt Jacob case BIU2400_HSEMA: 169010365e5aSMatt Jacob BXW4(pcs, IspVirt2Off(pcs, regoff), val); 169110365e5aSMatt Jacob junk = BXR4(pcs, IspVirt2Off(pcs, regoff)); 169210365e5aSMatt Jacob break; 169310365e5aSMatt Jacob default: 169410365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, 169510365e5aSMatt Jacob "isp_pci_wr_reg_2400: bad offset 0x%x", regoff); 169610365e5aSMatt Jacob break; 1697d59bd469SMatt Jacob } 1698d59bd469SMatt Jacob } 1699d59bd469SMatt Jacob 1700d720e6d5SJustin T. Gibbs 1701222bb542SMatt Jacob struct imush { 17029cd7268eSMatt Jacob ispsoftc_t *isp; 1703222bb542SMatt Jacob int error; 1704222bb542SMatt Jacob }; 1705222bb542SMatt Jacob 17061923f739SMatt Jacob static void imc(void *, bus_dma_segment_t *, int, int); 17071923f739SMatt Jacob 1708d720e6d5SJustin T. Gibbs static void 17091923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1710d720e6d5SJustin T. Gibbs { 1711222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 1712222bb542SMatt Jacob if (error) { 1713222bb542SMatt Jacob imushp->error = error; 1714222bb542SMatt Jacob } else { 17159cd7268eSMatt Jacob ispsoftc_t *isp =imushp->isp; 17161923f739SMatt Jacob bus_addr_t addr = segs->ds_addr; 17171923f739SMatt Jacob 17181923f739SMatt Jacob isp->isp_rquest_dma = addr; 17191923f739SMatt Jacob addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 17201923f739SMatt Jacob isp->isp_result_dma = addr; 17211923f739SMatt Jacob if (IS_FC(isp)) { 17221923f739SMatt Jacob addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 17231923f739SMatt Jacob FCPARAM(isp)->isp_scdma = addr; 17241923f739SMatt Jacob } 1725222bb542SMatt Jacob } 1726d720e6d5SJustin T. Gibbs } 1727d720e6d5SJustin T. Gibbs 1728d720e6d5SJustin T. Gibbs static int 17299cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp) 1730d720e6d5SJustin T. Gibbs { 17311923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 1732d720e6d5SJustin T. Gibbs caddr_t base; 17331dae40ebSMatt Jacob uint32_t len; 17341923f739SMatt Jacob int i, error, ns; 173553af7d22SMatt Jacob bus_size_t slim; /* segment size */ 17364b2dc3c4SScott Long bus_addr_t llim; /* low limit of unavailable dma */ 173751effc8cSMatt Jacob bus_addr_t hlim; /* high limit of unavailable dma */ 1738222bb542SMatt Jacob struct imush im; 1739222bb542SMatt Jacob 1740a95ae193SMatt Jacob /* 1741a95ae193SMatt Jacob * Already been here? If so, leave... 1742a95ae193SMatt Jacob */ 1743a95ae193SMatt Jacob if (isp->isp_rquest) { 1744a95ae193SMatt Jacob return (0); 1745a95ae193SMatt Jacob } 1746a95ae193SMatt Jacob 174710365e5aSMatt Jacob if (isp->isp_maxcmds == 0) { 174810365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "maxcmds not set"); 174910365e5aSMatt Jacob return (1); 175010365e5aSMatt Jacob } 175110365e5aSMatt Jacob 175253af7d22SMatt Jacob hlim = BUS_SPACE_MAXADDR; 17531923f739SMatt Jacob if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { 175453af7d22SMatt Jacob slim = (bus_size_t) (1ULL << 32); 17551dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR; 17561923f739SMatt Jacob } else { 17571dae40ebSMatt Jacob llim = BUS_SPACE_MAXADDR_32BIT; 175853af7d22SMatt Jacob slim = (1 << 24); 17591923f739SMatt Jacob } 17601923f739SMatt Jacob 176109934867SMatt Jacob /* 176209934867SMatt Jacob * XXX: We don't really support 64 bit target mode for parallel scsi yet 176309934867SMatt Jacob */ 176409934867SMatt Jacob #ifdef ISP_TARGET_MODE 176509934867SMatt Jacob if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) { 176609934867SMatt Jacob isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet"); 176709934867SMatt Jacob return (1); 176809934867SMatt Jacob } 176909934867SMatt Jacob #endif 177009934867SMatt Jacob 177172429e49SMatt Jacob ISP_UNLOCK(isp); 1772f9734398SMatt Jacob if (isp_dma_tag_create(BUS_DMA_ROOTARG(pcs->pci_dev), 1, slim, llim, 1773378f231eSJohn-Mark Gurney hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0, 1774378f231eSJohn-Mark Gurney &pcs->dmat)) { 17751923f739SMatt Jacob isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); 177672429e49SMatt Jacob ISP_LOCK(isp); 17771923f739SMatt Jacob return (1); 17781923f739SMatt Jacob } 17791923f739SMatt Jacob 17801923f739SMatt Jacob 1781d02373f1SMatt Jacob len = sizeof (XS_T **) * isp->isp_maxcmds; 1782a163d034SWarner Losh isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1783a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 1784d02373f1SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 178572429e49SMatt Jacob ISP_LOCK(isp); 1786a95ae193SMatt Jacob return (1); 1787a95ae193SMatt Jacob } 178851e23558SNate Lawson #ifdef ISP_TARGET_MODE 178951e23558SNate Lawson len = sizeof (void **) * isp->isp_maxcmds; 179051e23558SNate Lawson isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 179151e23558SNate Lawson if (isp->isp_tgtlist == NULL) { 179251e23558SNate Lawson isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array"); 179351e23558SNate Lawson ISP_LOCK(isp); 179451e23558SNate Lawson return (1); 179551e23558SNate Lawson } 179651e23558SNate Lawson #endif 1797a95ae193SMatt Jacob len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; 1798a163d034SWarner Losh pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK); 17991923f739SMatt Jacob if (pcs->dmaps == NULL) { 18001923f739SMatt Jacob isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage"); 1801a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 180251e23558SNate Lawson #ifdef ISP_TARGET_MODE 180351e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 180451e23558SNate Lawson #endif 180572429e49SMatt Jacob ISP_LOCK(isp); 1806a95ae193SMatt Jacob return (1); 1807a95ae193SMatt Jacob } 1808a95ae193SMatt Jacob 1809d720e6d5SJustin T. Gibbs /* 1810d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 1811d720e6d5SJustin T. Gibbs */ 1812d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1813d02373f1SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1814222bb542SMatt Jacob if (IS_FC(isp)) { 1815d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 1816d720e6d5SJustin T. Gibbs } 18171923f739SMatt Jacob 18181923f739SMatt Jacob ns = (len / PAGE_SIZE) + 1; 181953af7d22SMatt Jacob /* 182053af7d22SMatt Jacob * Create a tag for the control spaces- force it to within 32 bits. 182153af7d22SMatt Jacob */ 18229cd7268eSMatt Jacob if (isp_dma_tag_create(pcs->dmat, QENTRY_LEN, slim, 182353af7d22SMatt Jacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 18249cd7268eSMatt Jacob NULL, NULL, len, ns, slim, 0, &isp->isp_cdmat)) { 1825f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1826f7dddf8aSMatt Jacob "cannot create a dma tag for control spaces"); 18271923f739SMatt Jacob free(pcs->dmaps, M_DEVBUF); 1828a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 182951e23558SNate Lawson #ifdef ISP_TARGET_MODE 183051e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 183151e23558SNate Lawson #endif 183272429e49SMatt Jacob ISP_LOCK(isp); 1833d720e6d5SJustin T. Gibbs return (1); 1834d720e6d5SJustin T. Gibbs } 1835d720e6d5SJustin T. Gibbs 18361923f739SMatt Jacob if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT, 18371923f739SMatt Jacob &isp->isp_cdmap) != 0) { 1838f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 18391923f739SMatt Jacob "cannot allocate %d bytes of CCB memory", len); 18401923f739SMatt Jacob bus_dma_tag_destroy(isp->isp_cdmat); 1841a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 184251e23558SNate Lawson #ifdef ISP_TARGET_MODE 184351e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 184451e23558SNate Lawson #endif 18451923f739SMatt Jacob free(pcs->dmaps, M_DEVBUF); 184672429e49SMatt Jacob ISP_LOCK(isp); 1847222bb542SMatt Jacob return (1); 1848222bb542SMatt Jacob } 1849d720e6d5SJustin T. Gibbs 1850a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 18511923f739SMatt Jacob error = bus_dmamap_create(pcs->dmat, 0, &pcs->dmaps[i]); 1852d720e6d5SJustin T. Gibbs if (error) { 1853f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1854f7dddf8aSMatt Jacob "error %d creating per-cmd DMA maps", error); 18551923f739SMatt Jacob while (--i >= 0) { 18561923f739SMatt Jacob bus_dmamap_destroy(pcs->dmat, pcs->dmaps[i]); 18571923f739SMatt Jacob } 18581923f739SMatt Jacob goto bad; 1859d720e6d5SJustin T. Gibbs } 1860d720e6d5SJustin T. Gibbs } 1861a95ae193SMatt Jacob 18621923f739SMatt Jacob im.isp = isp; 1863222bb542SMatt Jacob im.error = 0; 18641923f739SMatt Jacob bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0); 1865222bb542SMatt Jacob if (im.error) { 1866f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 18671923f739SMatt Jacob "error %d loading dma map for control areas", im.error); 18681923f739SMatt Jacob goto bad; 1869222bb542SMatt Jacob } 18701923f739SMatt Jacob 18711923f739SMatt Jacob isp->isp_rquest = base; 18721923f739SMatt Jacob base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 18731923f739SMatt Jacob isp->isp_result = base; 18741923f739SMatt Jacob if (IS_FC(isp)) { 18751923f739SMatt Jacob base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 18761923f739SMatt Jacob FCPARAM(isp)->isp_scratch = base; 187792c49d78SMatt Jacob } 187872429e49SMatt Jacob ISP_LOCK(isp); 1879d720e6d5SJustin T. Gibbs return (0); 18801923f739SMatt Jacob 18811923f739SMatt Jacob bad: 18821923f739SMatt Jacob bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap); 18831923f739SMatt Jacob bus_dma_tag_destroy(isp->isp_cdmat); 18841923f739SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 188551e23558SNate Lawson #ifdef ISP_TARGET_MODE 188651e23558SNate Lawson free(isp->isp_tgtlist, M_DEVBUF); 188751e23558SNate Lawson #endif 18881923f739SMatt Jacob free(pcs->dmaps, M_DEVBUF); 188972429e49SMatt Jacob ISP_LOCK(isp); 18901923f739SMatt Jacob isp->isp_rquest = NULL; 18911923f739SMatt Jacob return (1); 1892d720e6d5SJustin T. Gibbs } 1893d720e6d5SJustin T. Gibbs 1894d720e6d5SJustin T. Gibbs typedef struct { 18959cd7268eSMatt Jacob ispsoftc_t *isp; 18969e11e5beSMatt Jacob void *cmd_token; 18979e11e5beSMatt Jacob void *rq; 189810365e5aSMatt Jacob uint32_t *nxtip; 189910365e5aSMatt Jacob uint32_t optr; 19001dae40ebSMatt Jacob int error; 1901d720e6d5SJustin T. Gibbs } mush_t; 1902d720e6d5SJustin T. Gibbs 19034873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 19044873663cSMatt Jacob 19059e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 19069e11e5beSMatt Jacob /* 19079e11e5beSMatt Jacob * We need to handle DMA for target mode differently from initiator mode. 19089e11e5beSMatt Jacob * 19099e11e5beSMatt Jacob * DMA mapping and construction and submission of CTIO Request Entries 19109e11e5beSMatt Jacob * and rendevous for completion are very tightly coupled because we start 19119e11e5beSMatt Jacob * out by knowing (per platform) how much data we have to move, but we 19129e11e5beSMatt Jacob * don't know, up front, how many DMA mapping segments will have to be used 19139e11e5beSMatt Jacob * cover that data, so we don't know how many CTIO Request Entries we 19149e11e5beSMatt Jacob * will end up using. Further, for performance reasons we may want to 19159e11e5beSMatt Jacob * (on the last CTIO for Fibre Channel), send status too (if all went well). 19169e11e5beSMatt Jacob * 19179e11e5beSMatt Jacob * The standard vector still goes through isp_pci_dmasetup, but the callback 19189e11e5beSMatt Jacob * for the DMA mapping routines comes here instead with the whole transfer 19199e11e5beSMatt Jacob * mapped and a pointer to a partially filled in already allocated request 19209e11e5beSMatt Jacob * queue entry. We finish the job. 19219e11e5beSMatt Jacob */ 1922e9a2738aSMatt Jacob static void tdma_mk(void *, bus_dma_segment_t *, int, int); 1923e9a2738aSMatt Jacob static void tdma_mkfc(void *, bus_dma_segment_t *, int, int); 1924e9a2738aSMatt Jacob 1925e9a2738aSMatt Jacob #define STATUS_WITH_DATA 1 19269e11e5beSMatt Jacob 1927d720e6d5SJustin T. Gibbs static void 192805fbcbb0SMatt Jacob tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1929d720e6d5SJustin T. Gibbs { 1930d720e6d5SJustin T. Gibbs mush_t *mp; 19319e11e5beSMatt Jacob struct ccb_scsiio *csio; 19329cd7268eSMatt Jacob ispsoftc_t *isp; 19331923f739SMatt Jacob struct isp_pcisoftc *pcs; 1934d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 19354fd13c1bSMatt Jacob ct_entry_t *cto, *qe; 19361dae40ebSMatt Jacob uint8_t scsi_status; 193710365e5aSMatt Jacob uint32_t curi, nxti, handle; 19381dae40ebSMatt Jacob uint32_t sflags; 193905fbcbb0SMatt Jacob int32_t resid; 19404fd13c1bSMatt Jacob int nth_ctio, nctios, send_status; 1941d720e6d5SJustin T. Gibbs 1942d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1943d720e6d5SJustin T. Gibbs if (error) { 1944d720e6d5SJustin T. Gibbs mp->error = error; 1945d720e6d5SJustin T. Gibbs return; 1946d720e6d5SJustin T. Gibbs } 19474fd13c1bSMatt Jacob 19484fd13c1bSMatt Jacob isp = mp->isp; 19499e11e5beSMatt Jacob csio = mp->cmd_token; 19509e11e5beSMatt Jacob cto = mp->rq; 19514fd13c1bSMatt Jacob curi = isp->isp_reqidx; 19524fd13c1bSMatt Jacob qe = (ct_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi); 19539e11e5beSMatt Jacob 195465b024e1SMatt Jacob cto->ct_xfrlen = 0; 195565b024e1SMatt Jacob cto->ct_seg_count = 0; 195665b024e1SMatt Jacob cto->ct_header.rqs_entry_count = 1; 195705fbcbb0SMatt Jacob MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg)); 195805fbcbb0SMatt Jacob 195905fbcbb0SMatt Jacob if (nseg == 0) { 196005fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 1; 19614fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 1962e9a2738aSMatt Jacob "CTIO[%x] lun%d iid%d tag %x flgs %x sts %x ssts %x res %d", 19635f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, cto->ct_iid, 1964e9a2738aSMatt Jacob cto->ct_tag_val, cto->ct_flags, cto->ct_status, 1965e9a2738aSMatt Jacob cto->ct_scsi_status, cto->ct_resid); 19664fd13c1bSMatt Jacob ISP_TDQE(isp, "tdma_mk[no data]", curi, cto); 19674fd13c1bSMatt Jacob isp_put_ctio(isp, cto, qe); 196865b024e1SMatt Jacob return; 196965b024e1SMatt Jacob } 197065b024e1SMatt Jacob 197165b024e1SMatt Jacob nctios = nseg / ISP_RQDSEG; 197265b024e1SMatt Jacob if (nseg % ISP_RQDSEG) { 197365b024e1SMatt Jacob nctios++; 197465b024e1SMatt Jacob } 197565b024e1SMatt Jacob 197605fbcbb0SMatt Jacob /* 19775f5aafe1SMatt Jacob * Save syshandle, and potentially any SCSI status, which we'll 19785f5aafe1SMatt Jacob * reinsert on the last CTIO we're going to send. 197905fbcbb0SMatt Jacob */ 19804fd13c1bSMatt Jacob 19815f5aafe1SMatt Jacob handle = cto->ct_syshandle; 19825f5aafe1SMatt Jacob cto->ct_syshandle = 0; 198305fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 0; 198405fbcbb0SMatt Jacob send_status = (cto->ct_flags & CT_SENDSTATUS) != 0; 198505fbcbb0SMatt Jacob 198605fbcbb0SMatt Jacob if (send_status) { 198705fbcbb0SMatt Jacob sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR); 198805fbcbb0SMatt Jacob cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR); 198905fbcbb0SMatt Jacob /* 199005fbcbb0SMatt Jacob * Preserve residual. 199105fbcbb0SMatt Jacob */ 199205fbcbb0SMatt Jacob resid = cto->ct_resid; 199305fbcbb0SMatt Jacob 199405fbcbb0SMatt Jacob /* 199505fbcbb0SMatt Jacob * Save actual SCSI status. 199605fbcbb0SMatt Jacob */ 199705fbcbb0SMatt Jacob scsi_status = cto->ct_scsi_status; 199805fbcbb0SMatt Jacob 1999e9a2738aSMatt Jacob #ifndef STATUS_WITH_DATA 2000e9a2738aSMatt Jacob sflags |= CT_NO_DATA; 200105fbcbb0SMatt Jacob /* 200205fbcbb0SMatt Jacob * We can't do a status at the same time as a data CTIO, so 200305fbcbb0SMatt Jacob * we need to synthesize an extra CTIO at this level. 200405fbcbb0SMatt Jacob */ 200505fbcbb0SMatt Jacob nctios++; 2006b72b1569SMatt Jacob #endif 200705fbcbb0SMatt Jacob } else { 200805fbcbb0SMatt Jacob sflags = scsi_status = resid = 0; 200905fbcbb0SMatt Jacob } 201005fbcbb0SMatt Jacob 2011b96934e8SMatt Jacob cto->ct_resid = 0; 201205fbcbb0SMatt Jacob cto->ct_scsi_status = 0; 201305fbcbb0SMatt Jacob 20141923f739SMatt Jacob pcs = (struct isp_pcisoftc *)isp; 20151923f739SMatt Jacob dp = &pcs->dmaps[isp_handle_index(handle)]; 20169e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 20171923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); 2018d720e6d5SJustin T. Gibbs } else { 20191923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); 2020d720e6d5SJustin T. Gibbs } 2021d720e6d5SJustin T. Gibbs 20224fd13c1bSMatt Jacob nxti = *mp->nxtip; 20239e11e5beSMatt Jacob 20244fd13c1bSMatt Jacob for (nth_ctio = 0; nth_ctio < nctios; nth_ctio++) { 202505fbcbb0SMatt Jacob int seglim; 20269e11e5beSMatt Jacob 20279e11e5beSMatt Jacob seglim = nseg; 202805fbcbb0SMatt Jacob if (seglim) { 202905fbcbb0SMatt Jacob int seg; 203005fbcbb0SMatt Jacob 20319e11e5beSMatt Jacob if (seglim > ISP_RQDSEG) 20329e11e5beSMatt Jacob seglim = ISP_RQDSEG; 20339e11e5beSMatt Jacob 203405fbcbb0SMatt Jacob for (seg = 0; seg < seglim; seg++, nseg--) { 203505fbcbb0SMatt Jacob /* 203605fbcbb0SMatt Jacob * Unlike normal initiator commands, we don't 203705fbcbb0SMatt Jacob * do any swizzling here. 203805fbcbb0SMatt Jacob */ 20399e11e5beSMatt Jacob cto->ct_dataseg[seg].ds_count = dm_segs->ds_len; 204005fbcbb0SMatt Jacob cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr; 20419e11e5beSMatt Jacob cto->ct_xfrlen += dm_segs->ds_len; 20429e11e5beSMatt Jacob dm_segs++; 20439e11e5beSMatt Jacob } 20449e11e5beSMatt Jacob cto->ct_seg_count = seg; 20459e11e5beSMatt Jacob } else { 204605fbcbb0SMatt Jacob /* 204705fbcbb0SMatt Jacob * This case should only happen when we're sending an 204805fbcbb0SMatt Jacob * extra CTIO with final status. 204905fbcbb0SMatt Jacob */ 205005fbcbb0SMatt Jacob if (send_status == 0) { 20514fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 2052f7dddf8aSMatt Jacob "tdma_mk ran out of segments"); 205305fbcbb0SMatt Jacob mp->error = EINVAL; 205405fbcbb0SMatt Jacob return; 20559e11e5beSMatt Jacob } 205605fbcbb0SMatt Jacob } 205705fbcbb0SMatt Jacob 205805fbcbb0SMatt Jacob /* 205905fbcbb0SMatt Jacob * At this point, the fields ct_lun, ct_iid, ct_tagval, 206005fbcbb0SMatt Jacob * ct_tagtype, and ct_timeout have been carried over 206105fbcbb0SMatt Jacob * unchanged from what our caller had set. 206205fbcbb0SMatt Jacob * 206305fbcbb0SMatt Jacob * The dataseg fields and the seg_count fields we just got 206405fbcbb0SMatt Jacob * through setting. The data direction we've preserved all 206505fbcbb0SMatt Jacob * along and only clear it if we're now sending status. 206605fbcbb0SMatt Jacob */ 20679e11e5beSMatt Jacob 20684fd13c1bSMatt Jacob if (nth_ctio == nctios - 1) { 20699e11e5beSMatt Jacob /* 207005fbcbb0SMatt Jacob * We're the last in a sequence of CTIOs, so mark 207105fbcbb0SMatt Jacob * this CTIO and save the handle to the CCB such that 207205fbcbb0SMatt Jacob * when this CTIO completes we can free dma resources 207305fbcbb0SMatt Jacob * and do whatever else we need to do to finish the 2074e9a2738aSMatt Jacob * rest of the command. We *don't* give this to the 2075e9a2738aSMatt Jacob * firmware to work on- the caller will do that. 20769e11e5beSMatt Jacob */ 20774fd13c1bSMatt Jacob 20785f5aafe1SMatt Jacob cto->ct_syshandle = handle; 207905fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 1; 208005fbcbb0SMatt Jacob 208105fbcbb0SMatt Jacob if (send_status) { 20829e11e5beSMatt Jacob cto->ct_scsi_status = scsi_status; 2083b72b1569SMatt Jacob cto->ct_flags |= sflags; 208405fbcbb0SMatt Jacob cto->ct_resid = resid; 208542426921SMatt Jacob } 2086d02373f1SMatt Jacob if (send_status) { 20874fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 2088e9a2738aSMatt Jacob "CTIO[%x] lun%d iid %d tag %x ct_flags %x " 20895f5aafe1SMatt Jacob "scsi status %x resid %d", 20905f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 2091e9a2738aSMatt Jacob cto->ct_iid, cto->ct_tag_val, cto->ct_flags, 209205fbcbb0SMatt Jacob cto->ct_scsi_status, cto->ct_resid); 2093d02373f1SMatt Jacob } else { 20944fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 2095e9a2738aSMatt Jacob "CTIO[%x] lun%d iid%d tag %x ct_flags 0x%x", 20965f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 2097e9a2738aSMatt Jacob cto->ct_iid, cto->ct_tag_val, 2098e9a2738aSMatt Jacob cto->ct_flags); 209905fbcbb0SMatt Jacob } 21004fd13c1bSMatt Jacob isp_put_ctio(isp, cto, qe); 21014fd13c1bSMatt Jacob ISP_TDQE(isp, "last tdma_mk", curi, cto); 21024fd13c1bSMatt Jacob if (nctios > 1) { 21034fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, 21044fd13c1bSMatt Jacob curi, QENTRY_LEN); 21054fd13c1bSMatt Jacob } 21069e11e5beSMatt Jacob } else { 21074fd13c1bSMatt Jacob ct_entry_t *oqe = qe; 210805fbcbb0SMatt Jacob 210905fbcbb0SMatt Jacob /* 21105f5aafe1SMatt Jacob * Make sure syshandle fields are clean 211105fbcbb0SMatt Jacob */ 21125f5aafe1SMatt Jacob cto->ct_syshandle = 0; 21139e11e5beSMatt Jacob cto->ct_header.rqs_seqno = 0; 211405fbcbb0SMatt Jacob 21154fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 21165f5aafe1SMatt Jacob "CTIO[%x] lun%d for ID%d ct_flags 0x%x", 21175f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 21185f5aafe1SMatt Jacob cto->ct_iid, cto->ct_flags); 211905fbcbb0SMatt Jacob 212005fbcbb0SMatt Jacob /* 212105fbcbb0SMatt Jacob * Get a new CTIO 212205fbcbb0SMatt Jacob */ 21234fd13c1bSMatt Jacob qe = (ct_entry_t *) 21244fd13c1bSMatt Jacob ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 21254fd13c1bSMatt Jacob nxti = ISP_NXT_QENTRY(nxti, RQUEST_QUEUE_LEN(isp)); 21264fd13c1bSMatt Jacob if (nxti == mp->optr) { 21274fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 2128f7dddf8aSMatt Jacob "Queue Overflow in tdma_mk"); 21299e11e5beSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 21309e11e5beSMatt Jacob return; 21319e11e5beSMatt Jacob } 21324fd13c1bSMatt Jacob 21339e11e5beSMatt Jacob /* 21344fd13c1bSMatt Jacob * Now that we're done with the old CTIO, 21354fd13c1bSMatt Jacob * flush it out to the request queue. 21364fd13c1bSMatt Jacob */ 21374fd13c1bSMatt Jacob ISP_TDQE(isp, "dma_tgt_fc", curi, cto); 21384fd13c1bSMatt Jacob isp_put_ctio(isp, cto, oqe); 21394fd13c1bSMatt Jacob if (nth_ctio != 0) { 21404fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, curi, 21414fd13c1bSMatt Jacob QENTRY_LEN); 21424fd13c1bSMatt Jacob } 21434fd13c1bSMatt Jacob curi = ISP_NXT_QENTRY(curi, RQUEST_QUEUE_LEN(isp)); 21444fd13c1bSMatt Jacob 21454fd13c1bSMatt Jacob /* 21464fd13c1bSMatt Jacob * Reset some fields in the CTIO so we can reuse 21474fd13c1bSMatt Jacob * for the next one we'll flush to the request 21484fd13c1bSMatt Jacob * queue. 21499e11e5beSMatt Jacob */ 21509e11e5beSMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 21519e11e5beSMatt Jacob cto->ct_header.rqs_entry_count = 1; 21529e11e5beSMatt Jacob cto->ct_header.rqs_flags = 0; 21539e11e5beSMatt Jacob cto->ct_status = 0; 21549e11e5beSMatt Jacob cto->ct_scsi_status = 0; 21559e11e5beSMatt Jacob cto->ct_xfrlen = 0; 21569e11e5beSMatt Jacob cto->ct_resid = 0; 21579e11e5beSMatt Jacob cto->ct_seg_count = 0; 215805fbcbb0SMatt Jacob MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg)); 21599e11e5beSMatt Jacob } 21609e11e5beSMatt Jacob } 21614fd13c1bSMatt Jacob *mp->nxtip = nxti; 21629e11e5beSMatt Jacob } 21639e11e5beSMatt Jacob 2164fc087171SMatt Jacob /* 2165fc087171SMatt Jacob * We don't have to do multiple CTIOs here. Instead, we can just do 2166fc087171SMatt Jacob * continuation segments as needed. This greatly simplifies the code 2167fc087171SMatt Jacob * improves performance. 2168fc087171SMatt Jacob */ 2169fc087171SMatt Jacob 21709e11e5beSMatt Jacob static void 217105fbcbb0SMatt Jacob tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 21729e11e5beSMatt Jacob { 21739e11e5beSMatt Jacob mush_t *mp; 21749e11e5beSMatt Jacob struct ccb_scsiio *csio; 21759cd7268eSMatt Jacob ispsoftc_t *isp; 21764fd13c1bSMatt Jacob ct2_entry_t *cto, *qe; 217710365e5aSMatt Jacob uint32_t curi, nxti; 217809934867SMatt Jacob ispds_t *ds; 217909934867SMatt Jacob ispds64_t *ds64; 218009934867SMatt Jacob int segcnt, seglim; 21819e11e5beSMatt Jacob 21829e11e5beSMatt Jacob mp = (mush_t *) arg; 21839e11e5beSMatt Jacob if (error) { 21849e11e5beSMatt Jacob mp->error = error; 21859e11e5beSMatt Jacob return; 21869e11e5beSMatt Jacob } 21879e11e5beSMatt Jacob 21884fd13c1bSMatt Jacob isp = mp->isp; 218965b024e1SMatt Jacob csio = mp->cmd_token; 219065b024e1SMatt Jacob cto = mp->rq; 2191fc087171SMatt Jacob 21924fd13c1bSMatt Jacob curi = isp->isp_reqidx; 21934fd13c1bSMatt Jacob qe = (ct2_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi); 219465b024e1SMatt Jacob 219565b024e1SMatt Jacob if (nseg == 0) { 219665b024e1SMatt Jacob if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE1) { 21974fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 2198f7dddf8aSMatt Jacob "dma2_tgt_fc, a status CTIO2 without MODE1 " 2199f7dddf8aSMatt Jacob "set (0x%x)", cto->ct_flags); 220065b024e1SMatt Jacob mp->error = EINVAL; 220165b024e1SMatt Jacob return; 220265b024e1SMatt Jacob } 220365b024e1SMatt Jacob /* 220465b024e1SMatt Jacob * We preserve ct_lun, ct_iid, ct_rxid. We set the data 220565b024e1SMatt Jacob * flags to NO DATA and clear relative offset flags. 220665b024e1SMatt Jacob * We preserve the ct_resid and the response area. 220765b024e1SMatt Jacob */ 2208fc087171SMatt Jacob cto->ct_header.rqs_seqno = 1; 220965b024e1SMatt Jacob cto->ct_seg_count = 0; 221065b024e1SMatt Jacob cto->ct_reloff = 0; 22114fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 22125f5aafe1SMatt Jacob "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts " 2213d02373f1SMatt Jacob "0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun, 2214d02373f1SMatt Jacob cto->ct_iid, cto->ct_flags, cto->ct_status, 221565b024e1SMatt Jacob cto->rsp.m1.ct_scsi_status, cto->ct_resid); 221610365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 221709934867SMatt Jacob isp_put_ctio2e(isp, 221809934867SMatt Jacob (ct2e_entry_t *)cto, (ct2e_entry_t *)qe); 221909934867SMatt Jacob } else { 22204fd13c1bSMatt Jacob isp_put_ctio2(isp, cto, qe); 222109934867SMatt Jacob } 22224fd13c1bSMatt Jacob ISP_TDQE(isp, "dma2_tgt_fc[no data]", curi, qe); 22239e11e5beSMatt Jacob return; 22249e11e5beSMatt Jacob } 22259e11e5beSMatt Jacob 222665b024e1SMatt Jacob if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE0) { 2227fc087171SMatt Jacob isp_prt(isp, ISP_LOGERR, 2228f7dddf8aSMatt Jacob "dma2_tgt_fc, a data CTIO2 without MODE0 set " 2229f7dddf8aSMatt Jacob "(0x%x)", cto->ct_flags); 223065b024e1SMatt Jacob mp->error = EINVAL; 223165b024e1SMatt Jacob return; 223265b024e1SMatt Jacob } 223365b024e1SMatt Jacob 223465b024e1SMatt Jacob 22354fd13c1bSMatt Jacob nxti = *mp->nxtip; 22364fd13c1bSMatt Jacob 2237fc087171SMatt Jacob /* 223809934867SMatt Jacob * Check to see if we need to DAC addressing or not. 223909934867SMatt Jacob * 224009934867SMatt Jacob * Any address that's over the 4GB boundary causes this 224109934867SMatt Jacob * to happen. 224209934867SMatt Jacob */ 224309934867SMatt Jacob segcnt = nseg; 224409934867SMatt Jacob if (sizeof (bus_addr_t) > 4) { 224509934867SMatt Jacob for (segcnt = 0; segcnt < nseg; segcnt++) { 224609934867SMatt Jacob uint64_t addr = dm_segs[segcnt].ds_addr; 224709934867SMatt Jacob if (addr >= 0x100000000LL) { 224809934867SMatt Jacob break; 224909934867SMatt Jacob } 225009934867SMatt Jacob } 225109934867SMatt Jacob } 225209934867SMatt Jacob if (segcnt != nseg) { 225309934867SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3; 225409934867SMatt Jacob seglim = ISP_RQDSEG_T3; 225510365e5aSMatt Jacob ds64 = &cto->rsp.m0.u.ct_dataseg64[0]; 225609934867SMatt Jacob ds = NULL; 225709934867SMatt Jacob } else { 225809934867SMatt Jacob seglim = ISP_RQDSEG_T2; 225909934867SMatt Jacob ds64 = NULL; 226010365e5aSMatt Jacob ds = &cto->rsp.m0.u.ct_dataseg[0]; 226109934867SMatt Jacob } 226209934867SMatt Jacob cto->ct_seg_count = 0; 226309934867SMatt Jacob 226409934867SMatt Jacob /* 2265fc087171SMatt Jacob * Set up the CTIO2 data segments. 2266fc087171SMatt Jacob */ 226709934867SMatt Jacob for (segcnt = 0; cto->ct_seg_count < seglim && segcnt < nseg; 2268fc087171SMatt Jacob cto->ct_seg_count++, segcnt++) { 226909934867SMatt Jacob if (ds64) { 227009934867SMatt Jacob ds64->ds_basehi = 227109934867SMatt Jacob ((uint64_t) (dm_segs[segcnt].ds_addr) >> 32); 227209934867SMatt Jacob ds64->ds_base = dm_segs[segcnt].ds_addr; 227309934867SMatt Jacob ds64->ds_count = dm_segs[segcnt].ds_len; 227409934867SMatt Jacob ds64++; 227509934867SMatt Jacob } else { 227609934867SMatt Jacob ds->ds_base = dm_segs[segcnt].ds_addr; 227709934867SMatt Jacob ds->ds_count = dm_segs[segcnt].ds_len; 227809934867SMatt Jacob ds++; 227909934867SMatt Jacob } 2280fc087171SMatt Jacob cto->rsp.m0.ct_xfrlen += dm_segs[segcnt].ds_len; 22819cd7268eSMatt Jacob #if __FreeBSD_version < 500000 22829cd7268eSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 22839cd7268eSMatt Jacob "isp_send_ctio2: ent0[%d]0x%llx:%llu", 22849cd7268eSMatt Jacob cto->ct_seg_count, (uint64_t)dm_segs[segcnt].ds_addr, 22859cd7268eSMatt Jacob (uint64_t)dm_segs[segcnt].ds_len); 22869cd7268eSMatt Jacob #else 228776514802SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 228874a96f43SJohn Baldwin "isp_send_ctio2: ent0[%d]0x%jx:%ju", 228974a96f43SJohn Baldwin cto->ct_seg_count, (uintmax_t)dm_segs[segcnt].ds_addr, 229074a96f43SJohn Baldwin (uintmax_t)dm_segs[segcnt].ds_len); 22919cd7268eSMatt Jacob #endif 2292fc087171SMatt Jacob } 22939e11e5beSMatt Jacob 2294fc087171SMatt Jacob while (segcnt < nseg) { 229510365e5aSMatt Jacob uint32_t curip; 22964fd13c1bSMatt Jacob int seg; 2297fc087171SMatt Jacob ispcontreq_t local, *crq = &local, *qep; 22989e11e5beSMatt Jacob 2299fc087171SMatt Jacob qep = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 2300fc087171SMatt Jacob curip = nxti; 2301fc087171SMatt Jacob nxti = ISP_NXT_QENTRY(curip, RQUEST_QUEUE_LEN(isp)); 23024fd13c1bSMatt Jacob if (nxti == mp->optr) { 2303fc087171SMatt Jacob ISP_UNLOCK(isp); 2304fc087171SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 2305fc087171SMatt Jacob "tdma_mkfc: request queue overflow"); 23069e11e5beSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 23079e11e5beSMatt Jacob return; 23089e11e5beSMatt Jacob } 2309fc087171SMatt Jacob cto->ct_header.rqs_entry_count++; 2310fc087171SMatt Jacob MEMZERO((void *)crq, sizeof (*crq)); 2311fc087171SMatt Jacob crq->req_header.rqs_entry_count = 1; 231209934867SMatt Jacob if (cto->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { 231309934867SMatt Jacob seglim = ISP_CDSEG64; 231409934867SMatt Jacob ds = NULL; 231509934867SMatt Jacob ds64 = &((ispcontreq64_t *)crq)->req_dataseg[0]; 231609934867SMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT; 231709934867SMatt Jacob } else { 231809934867SMatt Jacob seglim = ISP_CDSEG; 231909934867SMatt Jacob ds = &crq->req_dataseg[0]; 232009934867SMatt Jacob ds64 = NULL; 2321fc087171SMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 232209934867SMatt Jacob } 232309934867SMatt Jacob for (seg = 0; segcnt < nseg && seg < seglim; 2324fc087171SMatt Jacob segcnt++, seg++) { 232509934867SMatt Jacob if (ds64) { 232609934867SMatt Jacob ds64->ds_basehi = 232709934867SMatt Jacob ((uint64_t) (dm_segs[segcnt].ds_addr) >> 32); 232809934867SMatt Jacob ds64->ds_base = dm_segs[segcnt].ds_addr; 232909934867SMatt Jacob ds64->ds_count = dm_segs[segcnt].ds_len; 233009934867SMatt Jacob ds64++; 233109934867SMatt Jacob } else { 233209934867SMatt Jacob ds->ds_base = dm_segs[segcnt].ds_addr; 233309934867SMatt Jacob ds->ds_count = dm_segs[segcnt].ds_len; 233409934867SMatt Jacob ds++; 233509934867SMatt Jacob } 23369cd7268eSMatt Jacob #if __FreeBSD_version < 500000 23379cd7268eSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 23389cd7268eSMatt Jacob "isp_send_ctio2: ent%d[%d]%llx:%llu", 23399cd7268eSMatt Jacob cto->ct_header.rqs_entry_count-1, seg, 23409cd7268eSMatt Jacob (uint64_t)dm_segs[segcnt].ds_addr, 23419cd7268eSMatt Jacob (uint64_t)dm_segs[segcnt].ds_len); 23429cd7268eSMatt Jacob #else 2343fc087171SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 234474a96f43SJohn Baldwin "isp_send_ctio2: ent%d[%d]%jx:%ju", 2345fc087171SMatt Jacob cto->ct_header.rqs_entry_count-1, seg, 234674a96f43SJohn Baldwin (uintmax_t)dm_segs[segcnt].ds_addr, 234774a96f43SJohn Baldwin (uintmax_t)dm_segs[segcnt].ds_len); 23489cd7268eSMatt Jacob #endif 2349fc087171SMatt Jacob cto->rsp.m0.ct_xfrlen += dm_segs[segcnt].ds_len; 2350fc087171SMatt Jacob cto->ct_seg_count++; 2351fc087171SMatt Jacob } 2352fc087171SMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, curip, QENTRY_LEN); 2353fc087171SMatt Jacob isp_put_cont_req(isp, crq, qep); 2354fc087171SMatt Jacob ISP_TDQE(isp, "cont entry", curi, qep); 2355fc087171SMatt Jacob } 235665b024e1SMatt Jacob 23579e11e5beSMatt Jacob /* 2358fc087171SMatt Jacob * No do final twiddling for the CTIO itself. 23594fd13c1bSMatt Jacob */ 2360fc087171SMatt Jacob cto->ct_header.rqs_seqno = 1; 2361fc087171SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 2362fc087171SMatt Jacob "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts 0x%x resid %d", 2363fc087171SMatt Jacob cto->ct_rxid, csio->ccb_h.target_lun, (int) cto->ct_iid, 2364fc087171SMatt Jacob cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status, 2365fc087171SMatt Jacob cto->ct_resid); 236610365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 236709934867SMatt Jacob isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe); 236810365e5aSMatt Jacob } else { 2369fc087171SMatt Jacob isp_put_ctio2(isp, cto, qe); 237010365e5aSMatt Jacob } 2371fc087171SMatt Jacob ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe); 23724fd13c1bSMatt Jacob *mp->nxtip = nxti; 23739e11e5beSMatt Jacob } 23749e11e5beSMatt Jacob #endif 23759e11e5beSMatt Jacob 237610365e5aSMatt Jacob static void dma_2400(void *, bus_dma_segment_t *, int, int); 23771dae40ebSMatt Jacob static void dma2_a64(void *, bus_dma_segment_t *, int, int); 2378126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 23799e11e5beSMatt Jacob 23806de9bf77SMatt Jacob static void 238110365e5aSMatt Jacob dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 238210365e5aSMatt Jacob { 238310365e5aSMatt Jacob mush_t *mp; 238410365e5aSMatt Jacob ispsoftc_t *isp; 238510365e5aSMatt Jacob struct ccb_scsiio *csio; 238610365e5aSMatt Jacob struct isp_pcisoftc *pcs; 238710365e5aSMatt Jacob bus_dmamap_t *dp; 238810365e5aSMatt Jacob bus_dma_segment_t *eseg; 238910365e5aSMatt Jacob ispreqt7_t *rq; 239010365e5aSMatt Jacob int seglim, datalen; 239110365e5aSMatt Jacob uint32_t nxti; 239210365e5aSMatt Jacob 239310365e5aSMatt Jacob mp = (mush_t *) arg; 239410365e5aSMatt Jacob if (error) { 239510365e5aSMatt Jacob mp->error = error; 239610365e5aSMatt Jacob return; 239710365e5aSMatt Jacob } 239810365e5aSMatt Jacob 239910365e5aSMatt Jacob if (nseg < 1) { 240010365e5aSMatt Jacob isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); 240110365e5aSMatt Jacob mp->error = EFAULT; 240210365e5aSMatt Jacob return; 240310365e5aSMatt Jacob } 240410365e5aSMatt Jacob 240510365e5aSMatt Jacob csio = mp->cmd_token; 240610365e5aSMatt Jacob isp = mp->isp; 240710365e5aSMatt Jacob rq = mp->rq; 240810365e5aSMatt Jacob pcs = (struct isp_pcisoftc *)mp->isp; 240910365e5aSMatt Jacob dp = &pcs->dmaps[isp_handle_index(rq->req_handle)]; 241010365e5aSMatt Jacob nxti = *mp->nxtip; 241110365e5aSMatt Jacob 241210365e5aSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 241310365e5aSMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); 241410365e5aSMatt Jacob } else { 241510365e5aSMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); 241610365e5aSMatt Jacob } 241710365e5aSMatt Jacob datalen = XS_XFRLEN(csio); 241810365e5aSMatt Jacob 241910365e5aSMatt Jacob /* 242010365e5aSMatt Jacob * We're passed an initial partially filled in entry that 242110365e5aSMatt Jacob * has most fields filled in except for data transfer 242210365e5aSMatt Jacob * related values. 242310365e5aSMatt Jacob * 242410365e5aSMatt Jacob * Our job is to fill in the initial request queue entry and 242510365e5aSMatt Jacob * then to start allocating and filling in continuation entries 242610365e5aSMatt Jacob * until we've covered the entire transfer. 242710365e5aSMatt Jacob */ 242810365e5aSMatt Jacob 242910365e5aSMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T7RQS; 243010365e5aSMatt Jacob rq->req_dl = datalen; 243110365e5aSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 243210365e5aSMatt Jacob rq->req_alen_datadir = 0x2; 243310365e5aSMatt Jacob } else { 243410365e5aSMatt Jacob rq->req_alen_datadir = 0x1; 243510365e5aSMatt Jacob } 243610365e5aSMatt Jacob 243710365e5aSMatt Jacob eseg = dm_segs + nseg; 243810365e5aSMatt Jacob 243910365e5aSMatt Jacob rq->req_dataseg.ds_base = DMA_LO32(dm_segs->ds_addr); 244010365e5aSMatt Jacob rq->req_dataseg.ds_basehi = DMA_HI32(dm_segs->ds_addr); 244110365e5aSMatt Jacob rq->req_dataseg.ds_count = dm_segs->ds_len; 244210365e5aSMatt Jacob 244310365e5aSMatt Jacob datalen -= dm_segs->ds_len; 244410365e5aSMatt Jacob 244510365e5aSMatt Jacob dm_segs++; 244610365e5aSMatt Jacob rq->req_seg_count++; 244710365e5aSMatt Jacob 244810365e5aSMatt Jacob while (datalen > 0 && dm_segs != eseg) { 244910365e5aSMatt Jacob uint32_t onxti; 245010365e5aSMatt Jacob ispcontreq64_t local, *crq = &local, *cqe; 245110365e5aSMatt Jacob 245210365e5aSMatt Jacob cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 245310365e5aSMatt Jacob onxti = nxti; 245410365e5aSMatt Jacob nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); 245510365e5aSMatt Jacob if (nxti == mp->optr) { 245610365e5aSMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); 245710365e5aSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 245810365e5aSMatt Jacob return; 245910365e5aSMatt Jacob } 246010365e5aSMatt Jacob rq->req_header.rqs_entry_count++; 246110365e5aSMatt Jacob MEMZERO((void *)crq, sizeof (*crq)); 246210365e5aSMatt Jacob crq->req_header.rqs_entry_count = 1; 246310365e5aSMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT; 246410365e5aSMatt Jacob 246510365e5aSMatt Jacob seglim = 0; 246610365e5aSMatt Jacob while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) { 246710365e5aSMatt Jacob crq->req_dataseg[seglim].ds_base = 246810365e5aSMatt Jacob DMA_LO32(dm_segs->ds_addr); 246910365e5aSMatt Jacob crq->req_dataseg[seglim].ds_basehi = 247010365e5aSMatt Jacob DMA_HI32(dm_segs->ds_addr); 247110365e5aSMatt Jacob crq->req_dataseg[seglim].ds_count = 247210365e5aSMatt Jacob dm_segs->ds_len; 247310365e5aSMatt Jacob rq->req_seg_count++; 247410365e5aSMatt Jacob dm_segs++; 247510365e5aSMatt Jacob seglim++; 247610365e5aSMatt Jacob datalen -= dm_segs->ds_len; 247710365e5aSMatt Jacob } 247810365e5aSMatt Jacob if (isp->isp_dblev & ISP_LOGDEBUG1) { 247910365e5aSMatt Jacob isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); 248010365e5aSMatt Jacob } 248110365e5aSMatt Jacob isp_put_cont64_req(isp, crq, cqe); 248210365e5aSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); 248310365e5aSMatt Jacob } 248410365e5aSMatt Jacob *mp->nxtip = nxti; 248510365e5aSMatt Jacob } 248610365e5aSMatt Jacob 248710365e5aSMatt Jacob static void 24881dae40ebSMatt Jacob dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 24896de9bf77SMatt Jacob { 24906de9bf77SMatt Jacob mush_t *mp; 24919cd7268eSMatt Jacob ispsoftc_t *isp; 24926de9bf77SMatt Jacob struct ccb_scsiio *csio; 24936de9bf77SMatt Jacob struct isp_pcisoftc *pcs; 24946de9bf77SMatt Jacob bus_dmamap_t *dp; 24956de9bf77SMatt Jacob bus_dma_segment_t *eseg; 24966de9bf77SMatt Jacob ispreq64_t *rq; 24976de9bf77SMatt Jacob int seglim, datalen; 249810365e5aSMatt Jacob uint32_t nxti; 24996de9bf77SMatt Jacob 25006de9bf77SMatt Jacob mp = (mush_t *) arg; 25016de9bf77SMatt Jacob if (error) { 25026de9bf77SMatt Jacob mp->error = error; 25036de9bf77SMatt Jacob return; 25046de9bf77SMatt Jacob } 25056de9bf77SMatt Jacob 25066de9bf77SMatt Jacob if (nseg < 1) { 25076de9bf77SMatt Jacob isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); 25086de9bf77SMatt Jacob mp->error = EFAULT; 25096de9bf77SMatt Jacob return; 25106de9bf77SMatt Jacob } 25116de9bf77SMatt Jacob csio = mp->cmd_token; 25126de9bf77SMatt Jacob isp = mp->isp; 25136de9bf77SMatt Jacob rq = mp->rq; 25146de9bf77SMatt Jacob pcs = (struct isp_pcisoftc *)mp->isp; 25156de9bf77SMatt Jacob dp = &pcs->dmaps[isp_handle_index(rq->req_handle)]; 25166de9bf77SMatt Jacob nxti = *mp->nxtip; 25176de9bf77SMatt Jacob 25186de9bf77SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 25196de9bf77SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); 25206de9bf77SMatt Jacob } else { 25216de9bf77SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); 25226de9bf77SMatt Jacob } 25236de9bf77SMatt Jacob datalen = XS_XFRLEN(csio); 25246de9bf77SMatt Jacob 25256de9bf77SMatt Jacob /* 25266de9bf77SMatt Jacob * We're passed an initial partially filled in entry that 25276de9bf77SMatt Jacob * has most fields filled in except for data transfer 25286de9bf77SMatt Jacob * related values. 25296de9bf77SMatt Jacob * 25306de9bf77SMatt Jacob * Our job is to fill in the initial request queue entry and 25316de9bf77SMatt Jacob * then to start allocating and filling in continuation entries 25326de9bf77SMatt Jacob * until we've covered the entire transfer. 25336de9bf77SMatt Jacob */ 25346de9bf77SMatt Jacob 25356de9bf77SMatt Jacob if (IS_FC(isp)) { 253669767099SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_T3RQS; 25376de9bf77SMatt Jacob seglim = ISP_RQDSEG_T3; 25386de9bf77SMatt Jacob ((ispreqt3_t *)rq)->req_totalcnt = datalen; 25396de9bf77SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 25406de9bf77SMatt Jacob ((ispreqt3_t *)rq)->req_flags |= REQFLAG_DATA_IN; 25416de9bf77SMatt Jacob } else { 25426de9bf77SMatt Jacob ((ispreqt3_t *)rq)->req_flags |= REQFLAG_DATA_OUT; 25436de9bf77SMatt Jacob } 25446de9bf77SMatt Jacob } else { 254569767099SMatt Jacob rq->req_header.rqs_entry_type = RQSTYPE_A64; 25466de9bf77SMatt Jacob if (csio->cdb_len > 12) { 25476de9bf77SMatt Jacob seglim = 0; 25486de9bf77SMatt Jacob } else { 25496de9bf77SMatt Jacob seglim = ISP_RQDSEG_A64; 25506de9bf77SMatt Jacob } 25516de9bf77SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 25526de9bf77SMatt Jacob rq->req_flags |= REQFLAG_DATA_IN; 25536de9bf77SMatt Jacob } else { 25546de9bf77SMatt Jacob rq->req_flags |= REQFLAG_DATA_OUT; 25556de9bf77SMatt Jacob } 25566de9bf77SMatt Jacob } 25576de9bf77SMatt Jacob 25586de9bf77SMatt Jacob eseg = dm_segs + nseg; 25596de9bf77SMatt Jacob 25606de9bf77SMatt Jacob while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 25616de9bf77SMatt Jacob if (IS_FC(isp)) { 25626de9bf77SMatt Jacob ispreqt3_t *rq3 = (ispreqt3_t *)rq; 25636de9bf77SMatt Jacob rq3->req_dataseg[rq3->req_seg_count].ds_base = 25641dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 256569767099SMatt Jacob rq3->req_dataseg[rq3->req_seg_count].ds_basehi = 25661dae40ebSMatt Jacob DMA_HI32(dm_segs->ds_addr); 25676de9bf77SMatt Jacob rq3->req_dataseg[rq3->req_seg_count].ds_count = 25686de9bf77SMatt Jacob dm_segs->ds_len; 25696de9bf77SMatt Jacob } else { 25706de9bf77SMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_base = 25711dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 257269767099SMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_basehi = 25731dae40ebSMatt Jacob DMA_HI32(dm_segs->ds_addr); 25746de9bf77SMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_count = 25756de9bf77SMatt Jacob dm_segs->ds_len; 25766de9bf77SMatt Jacob } 25776de9bf77SMatt Jacob datalen -= dm_segs->ds_len; 25786de9bf77SMatt Jacob rq->req_seg_count++; 25796de9bf77SMatt Jacob dm_segs++; 25806de9bf77SMatt Jacob } 25816de9bf77SMatt Jacob 25826de9bf77SMatt Jacob while (datalen > 0 && dm_segs != eseg) { 258310365e5aSMatt Jacob uint32_t onxti; 25846de9bf77SMatt Jacob ispcontreq64_t local, *crq = &local, *cqe; 25856de9bf77SMatt Jacob 25866de9bf77SMatt Jacob cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 25876de9bf77SMatt Jacob onxti = nxti; 25886de9bf77SMatt Jacob nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); 25896de9bf77SMatt Jacob if (nxti == mp->optr) { 25906de9bf77SMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); 25916de9bf77SMatt Jacob mp->error = MUSHERR_NOQENTRIES; 25926de9bf77SMatt Jacob return; 25936de9bf77SMatt Jacob } 25946de9bf77SMatt Jacob rq->req_header.rqs_entry_count++; 25956de9bf77SMatt Jacob MEMZERO((void *)crq, sizeof (*crq)); 25966de9bf77SMatt Jacob crq->req_header.rqs_entry_count = 1; 25976de9bf77SMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT; 25986de9bf77SMatt Jacob 25996de9bf77SMatt Jacob seglim = 0; 26006de9bf77SMatt Jacob while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) { 26016de9bf77SMatt Jacob crq->req_dataseg[seglim].ds_base = 26021dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 260369767099SMatt Jacob crq->req_dataseg[seglim].ds_basehi = 26041dae40ebSMatt Jacob DMA_HI32(dm_segs->ds_addr); 26056de9bf77SMatt Jacob crq->req_dataseg[seglim].ds_count = 26066de9bf77SMatt Jacob dm_segs->ds_len; 26076de9bf77SMatt Jacob rq->req_seg_count++; 26086de9bf77SMatt Jacob dm_segs++; 26096de9bf77SMatt Jacob seglim++; 26106de9bf77SMatt Jacob datalen -= dm_segs->ds_len; 26116de9bf77SMatt Jacob } 261210365e5aSMatt Jacob if (isp->isp_dblev & ISP_LOGDEBUG1) { 261310365e5aSMatt Jacob isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); 261410365e5aSMatt Jacob } 26156de9bf77SMatt Jacob isp_put_cont64_req(isp, crq, cqe); 26166de9bf77SMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); 26176de9bf77SMatt Jacob } 26186de9bf77SMatt Jacob *mp->nxtip = nxti; 26196de9bf77SMatt Jacob } 26201dae40ebSMatt Jacob 26219e11e5beSMatt Jacob static void 26229e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 26239e11e5beSMatt Jacob { 26249e11e5beSMatt Jacob mush_t *mp; 26259cd7268eSMatt Jacob ispsoftc_t *isp; 26269e11e5beSMatt Jacob struct ccb_scsiio *csio; 26271923f739SMatt Jacob struct isp_pcisoftc *pcs; 26289e11e5beSMatt Jacob bus_dmamap_t *dp; 26299e11e5beSMatt Jacob bus_dma_segment_t *eseg; 26309e11e5beSMatt Jacob ispreq_t *rq; 26319e11e5beSMatt Jacob int seglim, datalen; 263210365e5aSMatt Jacob uint32_t nxti; 26339e11e5beSMatt Jacob 26349e11e5beSMatt Jacob mp = (mush_t *) arg; 26359e11e5beSMatt Jacob if (error) { 26369e11e5beSMatt Jacob mp->error = error; 26379e11e5beSMatt Jacob return; 26389e11e5beSMatt Jacob } 26399e11e5beSMatt Jacob 26409e11e5beSMatt Jacob if (nseg < 1) { 2641f7dddf8aSMatt Jacob isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); 26429e11e5beSMatt Jacob mp->error = EFAULT; 26439e11e5beSMatt Jacob return; 26449e11e5beSMatt Jacob } 26459e11e5beSMatt Jacob csio = mp->cmd_token; 26464fd13c1bSMatt Jacob isp = mp->isp; 26479e11e5beSMatt Jacob rq = mp->rq; 26481923f739SMatt Jacob pcs = (struct isp_pcisoftc *)mp->isp; 26491923f739SMatt Jacob dp = &pcs->dmaps[isp_handle_index(rq->req_handle)]; 26504fd13c1bSMatt Jacob nxti = *mp->nxtip; 26519e11e5beSMatt Jacob 26529e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 26531923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD); 26549e11e5beSMatt Jacob } else { 26551923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE); 26569e11e5beSMatt Jacob } 26579e11e5beSMatt Jacob 26589e11e5beSMatt Jacob datalen = XS_XFRLEN(csio); 26599e11e5beSMatt Jacob 26609e11e5beSMatt Jacob /* 26619e11e5beSMatt Jacob * We're passed an initial partially filled in entry that 26629e11e5beSMatt Jacob * has most fields filled in except for data transfer 26639e11e5beSMatt Jacob * related values. 26649e11e5beSMatt Jacob * 26659e11e5beSMatt Jacob * Our job is to fill in the initial request queue entry and 26669e11e5beSMatt Jacob * then to start allocating and filling in continuation entries 26679e11e5beSMatt Jacob * until we've covered the entire transfer. 26689e11e5beSMatt Jacob */ 26699e11e5beSMatt Jacob 26704fd13c1bSMatt Jacob if (IS_FC(isp)) { 2671d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 2672d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 26739e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 26749e11e5beSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_IN; 26759e11e5beSMatt Jacob } else { 26769e11e5beSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_OUT; 26779e11e5beSMatt Jacob } 2678d720e6d5SJustin T. Gibbs } else { 2679e142669aSMatt Jacob if (csio->cdb_len > 12) { 2680e142669aSMatt Jacob seglim = 0; 2681e142669aSMatt Jacob } else { 2682d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 2683e142669aSMatt Jacob } 26849e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 26859e11e5beSMatt Jacob rq->req_flags |= REQFLAG_DATA_IN; 26869e11e5beSMatt Jacob } else { 26879e11e5beSMatt Jacob rq->req_flags |= REQFLAG_DATA_OUT; 26889e11e5beSMatt Jacob } 2689d720e6d5SJustin T. Gibbs } 2690d720e6d5SJustin T. Gibbs 2691d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 2692d720e6d5SJustin T. Gibbs 2693d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 26944fd13c1bSMatt Jacob if (IS_FC(isp)) { 2695d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 2696d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 26971dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 2698d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 2699d720e6d5SJustin T. Gibbs dm_segs->ds_len; 2700d720e6d5SJustin T. Gibbs } else { 2701d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 27021dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 2703d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 2704d720e6d5SJustin T. Gibbs dm_segs->ds_len; 2705d720e6d5SJustin T. Gibbs } 2706d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 2707d720e6d5SJustin T. Gibbs rq->req_seg_count++; 2708d720e6d5SJustin T. Gibbs dm_segs++; 2709d720e6d5SJustin T. Gibbs } 2710d720e6d5SJustin T. Gibbs 2711d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 271210365e5aSMatt Jacob uint32_t onxti; 27134fd13c1bSMatt Jacob ispcontreq_t local, *crq = &local, *cqe; 27144fd13c1bSMatt Jacob 27154fd13c1bSMatt Jacob cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 27164fd13c1bSMatt Jacob onxti = nxti; 27174fd13c1bSMatt Jacob nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); 27184fd13c1bSMatt Jacob if (nxti == mp->optr) { 27194fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); 27204873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 2721d720e6d5SJustin T. Gibbs return; 2722d720e6d5SJustin T. Gibbs } 2723d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 27244fd13c1bSMatt Jacob MEMZERO((void *)crq, sizeof (*crq)); 2725d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 2726d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 2727d720e6d5SJustin T. Gibbs 2728d720e6d5SJustin T. Gibbs seglim = 0; 2729d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 2730d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 27311dae40ebSMatt Jacob DMA_LO32(dm_segs->ds_addr); 2732d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 2733d720e6d5SJustin T. Gibbs dm_segs->ds_len; 2734d720e6d5SJustin T. Gibbs rq->req_seg_count++; 2735d720e6d5SJustin T. Gibbs dm_segs++; 2736d720e6d5SJustin T. Gibbs seglim++; 2737d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 2738d720e6d5SJustin T. Gibbs } 273910365e5aSMatt Jacob if (isp->isp_dblev & ISP_LOGDEBUG1) { 274010365e5aSMatt Jacob isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq); 274110365e5aSMatt Jacob } 27424fd13c1bSMatt Jacob isp_put_cont_req(isp, crq, cqe); 27434fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); 2744d720e6d5SJustin T. Gibbs } 27454fd13c1bSMatt Jacob *mp->nxtip = nxti; 2746d720e6d5SJustin T. Gibbs } 2747d720e6d5SJustin T. Gibbs 27489cd7268eSMatt Jacob /* 27499cd7268eSMatt Jacob * We enter with ISP_LOCK held 27509cd7268eSMatt Jacob */ 2751d720e6d5SJustin T. Gibbs static int 27529cd7268eSMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq, 275310365e5aSMatt Jacob uint32_t *nxtip, uint32_t optr) 2754d720e6d5SJustin T. Gibbs { 27551923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 27564fd13c1bSMatt Jacob ispreq_t *qep; 27570a5f7e8bSMatt Jacob bus_dmamap_t *dp = NULL; 2758d720e6d5SJustin T. Gibbs mush_t mush, *mp; 2759126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 2760d720e6d5SJustin T. Gibbs 27614fd13c1bSMatt Jacob qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx); 276265b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 276365b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 276465b024e1SMatt Jacob if (IS_FC(isp)) { 276505fbcbb0SMatt Jacob eptr = tdma_mkfc; 276665b024e1SMatt Jacob } else { 276705fbcbb0SMatt Jacob eptr = tdma_mk; 276865b024e1SMatt Jacob } 276905fbcbb0SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || 277005fbcbb0SMatt Jacob (csio->dxfer_len == 0)) { 277165b024e1SMatt Jacob mp = &mush; 277265b024e1SMatt Jacob mp->isp = isp; 277365b024e1SMatt Jacob mp->cmd_token = csio; 2774e9a2738aSMatt Jacob mp->rq = rq; /* really a ct_entry_t or ct2_entry_t */ 27754fd13c1bSMatt Jacob mp->nxtip = nxtip; 277665b024e1SMatt Jacob mp->optr = optr; 277765b024e1SMatt Jacob mp->error = 0; 27789cd7268eSMatt Jacob ISPLOCK_2_CAMLOCK(isp); 277965b024e1SMatt Jacob (*eptr)(mp, NULL, 0, 0); 27809cd7268eSMatt Jacob CAMLOCK_2_ISPLOCK(isp); 27814fd13c1bSMatt Jacob goto mbxsync; 278265b024e1SMatt Jacob } 278365b024e1SMatt Jacob } else 278465b024e1SMatt Jacob #endif 278510365e5aSMatt Jacob if (IS_24XX(isp)) { 278610365e5aSMatt Jacob eptr = dma_2400; 278710365e5aSMatt Jacob } else if (sizeof (bus_addr_t) > 4) { 27881dae40ebSMatt Jacob eptr = dma2_a64; 27891dae40ebSMatt Jacob } else { 279065b024e1SMatt Jacob eptr = dma2; 27911dae40ebSMatt Jacob } 279265b024e1SMatt Jacob 27934fd13c1bSMatt Jacob 279405fbcbb0SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || 279505fbcbb0SMatt Jacob (csio->dxfer_len == 0)) { 279642426921SMatt Jacob rq->req_seg_count = 1; 27974fd13c1bSMatt Jacob goto mbxsync; 279842426921SMatt Jacob } 279942426921SMatt Jacob 2800d720e6d5SJustin T. Gibbs /* 2801d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 28024873663cSMatt Jacob * the callback dma allocation that we have to use... 2803d720e6d5SJustin T. Gibbs */ 2804d720e6d5SJustin T. Gibbs mp = &mush; 2805d720e6d5SJustin T. Gibbs mp->isp = isp; 28069e11e5beSMatt Jacob mp->cmd_token = csio; 2807d720e6d5SJustin T. Gibbs mp->rq = rq; 28084fd13c1bSMatt Jacob mp->nxtip = nxtip; 2809d720e6d5SJustin T. Gibbs mp->optr = optr; 2810d720e6d5SJustin T. Gibbs mp->error = 0; 2811d720e6d5SJustin T. Gibbs 28129cd7268eSMatt Jacob ISPLOCK_2_CAMLOCK(isp); 28139e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 28149e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { 28154873663cSMatt Jacob int error, s; 28161923f739SMatt Jacob dp = &pcs->dmaps[isp_handle_index(rq->req_handle)]; 2817d720e6d5SJustin T. Gibbs s = splsoftvm(); 28181923f739SMatt Jacob error = bus_dmamap_load(pcs->dmat, *dp, 28199e11e5beSMatt Jacob csio->data_ptr, csio->dxfer_len, eptr, mp, 0); 2820d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 28211923f739SMatt Jacob bus_dmamap_unload(pcs->dmat, *dp); 2822d720e6d5SJustin T. Gibbs mp->error = EINVAL; 2823f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 2824f7dddf8aSMatt Jacob "deferred dma allocation not supported"); 2825d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 28260a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 28276e5c5328SMatt Jacob isp_prt(isp, ISP_LOGERR, 28286e5c5328SMatt Jacob "error %d in dma mapping code", error); 28290a5f7e8bSMatt Jacob #endif 2830d720e6d5SJustin T. Gibbs mp->error = error; 2831d720e6d5SJustin T. Gibbs } 28324873663cSMatt Jacob splx(s); 2833d720e6d5SJustin T. Gibbs } else { 2834d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 2835d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 28366de9bf77SMatt Jacob seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; 2837d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 28389e11e5beSMatt Jacob (*eptr)(mp, &seg, 1, 0); 2839d720e6d5SJustin T. Gibbs } 2840d720e6d5SJustin T. Gibbs } else { 2841d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 2842d720e6d5SJustin T. Gibbs 28439e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2844f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 2845f7dddf8aSMatt Jacob "Physical segment pointers unsupported"); 2846d720e6d5SJustin T. Gibbs mp->error = EINVAL; 28479e11e5beSMatt Jacob } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { 2848f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 2849f7dddf8aSMatt Jacob "Virtual segment addresses unsupported"); 2850d720e6d5SJustin T. Gibbs mp->error = EINVAL; 2851d720e6d5SJustin T. Gibbs } else { 2852d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 2853d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 28549e11e5beSMatt Jacob (*eptr)(mp, segs, csio->sglist_cnt, 0); 2855d720e6d5SJustin T. Gibbs } 2856d720e6d5SJustin T. Gibbs } 28579cd7268eSMatt Jacob CAMLOCK_2_ISPLOCK(isp); 2858d720e6d5SJustin T. Gibbs if (mp->error) { 28594873663cSMatt Jacob int retval = CMD_COMPLETE; 28604873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 28614873663cSMatt Jacob retval = CMD_EAGAIN; 28624873663cSMatt Jacob } else if (mp->error == EFBIG) { 28630a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_TOO_BIG); 2864d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 28650a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_INVALID); 2866d720e6d5SJustin T. Gibbs } else { 28670a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 2868d720e6d5SJustin T. Gibbs } 28694873663cSMatt Jacob return (retval); 28700a5f7e8bSMatt Jacob } 28714fd13c1bSMatt Jacob mbxsync: 287210365e5aSMatt Jacob if (isp->isp_dblev & ISP_LOGDEBUG1) { 287310365e5aSMatt Jacob isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq); 287410365e5aSMatt Jacob } 28754fd13c1bSMatt Jacob switch (rq->req_header.rqs_entry_type) { 28764fd13c1bSMatt Jacob case RQSTYPE_REQUEST: 28774fd13c1bSMatt Jacob isp_put_request(isp, rq, qep); 28784fd13c1bSMatt Jacob break; 28794fd13c1bSMatt Jacob case RQSTYPE_CMDONLY: 28804fd13c1bSMatt Jacob isp_put_extended_request(isp, (ispextreq_t *)rq, 28814fd13c1bSMatt Jacob (ispextreq_t *)qep); 28824fd13c1bSMatt Jacob break; 28834fd13c1bSMatt Jacob case RQSTYPE_T2RQS: 28844fd13c1bSMatt Jacob isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) qep); 28854fd13c1bSMatt Jacob break; 28866de9bf77SMatt Jacob case RQSTYPE_A64: 28876de9bf77SMatt Jacob case RQSTYPE_T3RQS: 28886de9bf77SMatt Jacob isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep); 28896de9bf77SMatt Jacob break; 289010365e5aSMatt Jacob case RQSTYPE_T7RQS: 289110365e5aSMatt Jacob isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep); 289210365e5aSMatt Jacob break; 28930a5f7e8bSMatt Jacob } 28944873663cSMatt Jacob return (CMD_QUEUED); 2895d720e6d5SJustin T. Gibbs } 2896d720e6d5SJustin T. Gibbs 2897d720e6d5SJustin T. Gibbs static void 289810365e5aSMatt Jacob isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle) 2899d720e6d5SJustin T. Gibbs { 29001923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 29011923f739SMatt Jacob bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)]; 2902a95ae193SMatt Jacob if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 29031923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTREAD); 2904d720e6d5SJustin T. Gibbs } else { 29051923f739SMatt Jacob bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTWRITE); 2906d720e6d5SJustin T. Gibbs } 29071923f739SMatt Jacob bus_dmamap_unload(pcs->dmat, *dp); 2908d720e6d5SJustin T. Gibbs } 2909d720e6d5SJustin T. Gibbs 291065adb54cSMatt Jacob 291165adb54cSMatt Jacob static void 29123bda7a83SMatt Jacob isp_pci_reset0(ispsoftc_t *isp) 29133bda7a83SMatt Jacob { 29143bda7a83SMatt Jacob ISP_DISABLE_INTS(isp); 29153bda7a83SMatt Jacob } 29163bda7a83SMatt Jacob 29173bda7a83SMatt Jacob static void 29189cd7268eSMatt Jacob isp_pci_reset1(ispsoftc_t *isp) 291965adb54cSMatt Jacob { 292010365e5aSMatt Jacob if (!IS_24XX(isp)) { 292165adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 292265adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 292310365e5aSMatt Jacob } 2924469b6b9eSMatt Jacob /* and enable interrupts */ 292510365e5aSMatt Jacob ISP_ENABLE_INTS(isp); 292665adb54cSMatt Jacob } 292765adb54cSMatt Jacob 292865adb54cSMatt Jacob static void 29299cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg) 293065adb54cSMatt Jacob { 29311923f739SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp; 2932d02373f1SMatt Jacob if (msg) 29336e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 29346e5c5328SMatt Jacob else 29356e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 2936d02373f1SMatt Jacob if (IS_SCSI(isp)) 2937d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 2938d02373f1SMatt Jacob else 2939d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 2940d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 2941d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 2942d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 2943d02373f1SMatt Jacob 2944d02373f1SMatt Jacob 2945d02373f1SMatt Jacob if (IS_SCSI(isp)) { 2946d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 2947d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 2948d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 2949d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 2950d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 2951d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 2952d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 2953d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 2954d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 2955d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 2956d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 2957d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 2958d02373f1SMatt Jacob } 2959d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 2960d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 2961d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 2962d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 2963d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 29641923f739SMatt Jacob pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1)); 296565adb54cSMatt Jacob } 2966