1c3aac50fSPeter Wemm /* $FreeBSD$ */ 265adb54cSMatt Jacob /* 365adb54cSMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 465adb54cSMatt Jacob * FreeBSD Version. 565adb54cSMatt Jacob * 65f5aafe1SMatt Jacob * Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob 765adb54cSMatt Jacob * 865adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 965adb54cSMatt Jacob * modification, are permitted provided that the following conditions 1065adb54cSMatt Jacob * are met: 1165adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 1265adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1365adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 14aa57fd6fSMatt Jacob * 2. The name of the author may not be used to endorse or promote products 15aa57fd6fSMatt Jacob * derived from this software without specific prior written permission. 1665adb54cSMatt Jacob * 1765adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1865adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1965adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2065adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2165adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2265adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2365adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2465adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2565adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2665adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2765adb54cSMatt Jacob * SUCH DAMAGE. 2865adb54cSMatt Jacob */ 29d720e6d5SJustin T. Gibbs 30960f6939SMatt Jacob #include <sys/param.h> 31960f6939SMatt Jacob #include <sys/systm.h> 32960f6939SMatt Jacob #include <sys/kernel.h> 33960f6939SMatt Jacob #include <sys/module.h> 34960f6939SMatt Jacob #include <sys/bus.h> 3565adb54cSMatt Jacob 3665adb54cSMatt Jacob #include <pci/pcireg.h> 3765adb54cSMatt Jacob #include <pci/pcivar.h> 3865adb54cSMatt Jacob 39d720e6d5SJustin T. Gibbs #include <machine/bus_memio.h> 40d720e6d5SJustin T. Gibbs #include <machine/bus_pio.h> 41d720e6d5SJustin T. Gibbs #include <machine/bus.h> 42960f6939SMatt Jacob #include <machine/resource.h> 43960f6939SMatt Jacob #include <sys/rman.h> 44960f6939SMatt Jacob #include <sys/malloc.h> 45960f6939SMatt Jacob 46960f6939SMatt Jacob #include <dev/isp/isp_freebsd.h> 47d59bd469SMatt Jacob 48126ec864SMatt Jacob static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int); 49126ec864SMatt Jacob static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t); 50126ec864SMatt Jacob static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int); 51126ec864SMatt Jacob static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t); 52126ec864SMatt Jacob static int 53126ec864SMatt Jacob isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); 54126ec864SMatt Jacob static int 55126ec864SMatt Jacob isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); 56126ec864SMatt Jacob static int isp_pci_mbxdma(struct ispsoftc *); 57126ec864SMatt Jacob static int 58126ec864SMatt Jacob isp_pci_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *, u_int16_t); 59d720e6d5SJustin T. Gibbs static void 60126ec864SMatt Jacob isp_pci_dmateardown(struct ispsoftc *, XS_T *, u_int16_t); 6165adb54cSMatt Jacob 62126ec864SMatt Jacob static void isp_pci_reset1(struct ispsoftc *); 63126ec864SMatt Jacob static void isp_pci_dumpregs(struct ispsoftc *, const char *); 6465adb54cSMatt Jacob 65fed92c47SMatt Jacob #ifndef ISP_CODE_ORG 66fed92c47SMatt Jacob #define ISP_CODE_ORG 0x1000 67fed92c47SMatt Jacob #endif 68fed92c47SMatt Jacob 6965adb54cSMatt Jacob static struct ispmdvec mdvec = { 70126ec864SMatt Jacob isp_pci_rd_isr, 7165adb54cSMatt Jacob isp_pci_rd_reg, 7265adb54cSMatt Jacob isp_pci_wr_reg, 7365adb54cSMatt Jacob isp_pci_mbxdma, 7465adb54cSMatt Jacob isp_pci_dmasetup, 75d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 7665adb54cSMatt Jacob NULL, 7765adb54cSMatt Jacob isp_pci_reset1, 7865adb54cSMatt Jacob isp_pci_dumpregs, 7956aef503SMatt Jacob NULL, 80d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 8165adb54cSMatt Jacob }; 8265adb54cSMatt Jacob 83d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 84126ec864SMatt Jacob isp_pci_rd_isr, 85d59bd469SMatt Jacob isp_pci_rd_reg_1080, 86d59bd469SMatt Jacob isp_pci_wr_reg_1080, 87d59bd469SMatt Jacob isp_pci_mbxdma, 88d59bd469SMatt Jacob isp_pci_dmasetup, 89d59bd469SMatt Jacob isp_pci_dmateardown, 90d59bd469SMatt Jacob NULL, 91d59bd469SMatt Jacob isp_pci_reset1, 92d59bd469SMatt Jacob isp_pci_dumpregs, 9356aef503SMatt Jacob NULL, 94d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 95d59bd469SMatt Jacob }; 96d59bd469SMatt Jacob 97960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = { 98126ec864SMatt Jacob isp_pci_rd_isr, 99960f6939SMatt Jacob isp_pci_rd_reg_1080, 100960f6939SMatt Jacob isp_pci_wr_reg_1080, 101960f6939SMatt Jacob isp_pci_mbxdma, 102960f6939SMatt Jacob isp_pci_dmasetup, 103960f6939SMatt Jacob isp_pci_dmateardown, 104960f6939SMatt Jacob NULL, 105960f6939SMatt Jacob isp_pci_reset1, 106960f6939SMatt Jacob isp_pci_dumpregs, 10756aef503SMatt Jacob NULL, 108d02373f1SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 109960f6939SMatt Jacob }; 110960f6939SMatt Jacob 11165adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 112126ec864SMatt Jacob isp_pci_rd_isr, 11365adb54cSMatt Jacob isp_pci_rd_reg, 11465adb54cSMatt Jacob isp_pci_wr_reg, 11565adb54cSMatt Jacob isp_pci_mbxdma, 11665adb54cSMatt Jacob isp_pci_dmasetup, 117d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 11865adb54cSMatt Jacob NULL, 11965adb54cSMatt Jacob isp_pci_reset1, 120d02373f1SMatt Jacob isp_pci_dumpregs 12165adb54cSMatt Jacob }; 122222bb542SMatt Jacob 123222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 124126ec864SMatt Jacob isp_pci_rd_isr, 125126ec864SMatt Jacob isp_pci_rd_reg, 126126ec864SMatt Jacob isp_pci_wr_reg, 127126ec864SMatt Jacob isp_pci_mbxdma, 128126ec864SMatt Jacob isp_pci_dmasetup, 129126ec864SMatt Jacob isp_pci_dmateardown, 130126ec864SMatt Jacob NULL, 131126ec864SMatt Jacob isp_pci_reset1, 132126ec864SMatt Jacob isp_pci_dumpregs 133126ec864SMatt Jacob }; 134126ec864SMatt Jacob 135126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = { 136126ec864SMatt Jacob isp_pci_rd_isr_2300, 137222bb542SMatt Jacob isp_pci_rd_reg, 138222bb542SMatt Jacob isp_pci_wr_reg, 139222bb542SMatt Jacob isp_pci_mbxdma, 140222bb542SMatt Jacob isp_pci_dmasetup, 141222bb542SMatt Jacob isp_pci_dmateardown, 142222bb542SMatt Jacob NULL, 143222bb542SMatt Jacob isp_pci_reset1, 144d02373f1SMatt Jacob isp_pci_dumpregs 145222bb542SMatt Jacob }; 146d951bbcaSMatt Jacob 14765adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 14865adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 14965adb54cSMatt Jacob #endif 15065adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 15165adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 15265adb54cSMatt Jacob #endif 153d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 154d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 155d951bbcaSMatt Jacob #endif 156d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 157d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 158d951bbcaSMatt Jacob #endif 159d951bbcaSMatt Jacob 160d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 161d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 162d951bbcaSMatt Jacob #endif 163d951bbcaSMatt Jacob 164d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 165d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 166d951bbcaSMatt Jacob #endif 167d951bbcaSMatt Jacob 168d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 169d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 170d951bbcaSMatt Jacob #endif 171d951bbcaSMatt Jacob 172ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 173ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 174ab6d0040SMatt Jacob #endif 175ab6d0040SMatt Jacob 17665adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 17765adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 17865adb54cSMatt Jacob #endif 17965adb54cSMatt Jacob 18065adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 18165adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 18265adb54cSMatt Jacob #endif 18365adb54cSMatt Jacob 184d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 185d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 186d59bd469SMatt Jacob #endif 187d59bd469SMatt Jacob 188960f6939SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP12160 189960f6939SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 190960f6939SMatt Jacob #endif 191960f6939SMatt Jacob 192d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 193d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 194d59bd469SMatt Jacob #endif 19565adb54cSMatt Jacob 19622e1dc85SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1280 19722e1dc85SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 19822e1dc85SMatt Jacob #endif 19922e1dc85SMatt Jacob 20065adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 20165adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 20265adb54cSMatt Jacob #endif 20365adb54cSMatt Jacob 204222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 205222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 206222bb542SMatt Jacob #endif 207222bb542SMatt Jacob 208126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2300 209126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 210126ec864SMatt Jacob #endif 211126ec864SMatt Jacob 212126ec864SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2312 213126ec864SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 214126ec864SMatt Jacob #endif 215126ec864SMatt Jacob 21656aef503SMatt Jacob #define PCI_QLOGIC_ISP1020 \ 21756aef503SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 218d59bd469SMatt Jacob 219d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 220d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 221d59bd469SMatt Jacob 222960f6939SMatt Jacob #define PCI_QLOGIC_ISP12160 \ 223960f6939SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC) 224960f6939SMatt Jacob 225d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 226d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 227d59bd469SMatt Jacob 22822e1dc85SMatt Jacob #define PCI_QLOGIC_ISP1280 \ 22922e1dc85SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC) 23022e1dc85SMatt Jacob 23165adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 23265adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 23365adb54cSMatt Jacob 234222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 235222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 236222bb542SMatt Jacob 237126ec864SMatt Jacob #define PCI_QLOGIC_ISP2300 \ 238126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) 239126ec864SMatt Jacob 240126ec864SMatt Jacob #define PCI_QLOGIC_ISP2312 \ 241126ec864SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) 242126ec864SMatt Jacob 243e11a1ee8SMatt Jacob /* 244e11a1ee8SMatt Jacob * Odd case for some AMI raid cards... We need to *not* attach to this. 245e11a1ee8SMatt Jacob */ 246e11a1ee8SMatt Jacob #define AMI_RAID_SUBVENDOR_ID 0x101e 247e11a1ee8SMatt Jacob 24865adb54cSMatt Jacob #define IO_MAP_REG 0x10 24965adb54cSMatt Jacob #define MEM_MAP_REG 0x14 25065adb54cSMatt Jacob 251d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 252d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 25365adb54cSMatt Jacob 254960f6939SMatt Jacob static int isp_pci_probe (device_t); 255960f6939SMatt Jacob static int isp_pci_attach (device_t); 25665adb54cSMatt Jacob 25765adb54cSMatt Jacob struct isp_pcisoftc { 25865adb54cSMatt Jacob struct ispsoftc pci_isp; 259960f6939SMatt Jacob device_t pci_dev; 260960f6939SMatt Jacob struct resource * pci_reg; 26165adb54cSMatt Jacob bus_space_tag_t pci_st; 26265adb54cSMatt Jacob bus_space_handle_t pci_sh; 263960f6939SMatt Jacob void * ih; 264d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 265d720e6d5SJustin T. Gibbs bus_dma_tag_t parent_dmat; 266d720e6d5SJustin T. Gibbs bus_dma_tag_t cntrol_dmat; 267d720e6d5SJustin T. Gibbs bus_dmamap_t cntrol_dmap; 268a95ae193SMatt Jacob bus_dmamap_t *dmaps; 26965adb54cSMatt Jacob }; 27056aef503SMatt Jacob ispfwfunc *isp_get_firmware_p = NULL; 27165adb54cSMatt Jacob 272960f6939SMatt Jacob static device_method_t isp_pci_methods[] = { 273960f6939SMatt Jacob /* Device interface */ 274960f6939SMatt Jacob DEVMETHOD(device_probe, isp_pci_probe), 275960f6939SMatt Jacob DEVMETHOD(device_attach, isp_pci_attach), 276960f6939SMatt Jacob { 0, 0 } 27765adb54cSMatt Jacob }; 278126ec864SMatt Jacob static void isp_pci_intr(void *); 27965adb54cSMatt Jacob 280960f6939SMatt Jacob static driver_t isp_pci_driver = { 281960f6939SMatt Jacob "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) 282960f6939SMatt Jacob }; 283960f6939SMatt Jacob static devclass_t isp_devclass; 284960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0); 28556aef503SMatt Jacob MODULE_VERSION(isp, 1); 28665adb54cSMatt Jacob 287960f6939SMatt Jacob static int 288960f6939SMatt Jacob isp_pci_probe(device_t dev) 28965adb54cSMatt Jacob { 290960f6939SMatt Jacob switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) { 29156aef503SMatt Jacob case PCI_QLOGIC_ISP1020: 292960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter"); 29365adb54cSMatt Jacob break; 294d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 295960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter"); 296c6608df3SMatt Jacob break; 297c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 298960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter"); 299d59bd469SMatt Jacob break; 30022e1dc85SMatt Jacob case PCI_QLOGIC_ISP1280: 301960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter"); 302960f6939SMatt Jacob break; 303960f6939SMatt Jacob case PCI_QLOGIC_ISP12160: 304e11a1ee8SMatt Jacob if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) { 305e11a1ee8SMatt Jacob return (ENXIO); 306e11a1ee8SMatt Jacob } 307960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter"); 30822e1dc85SMatt Jacob break; 30965adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 310960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter"); 31165adb54cSMatt Jacob break; 3125542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 313960f6939SMatt Jacob device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); 3145542fe4bSMatt Jacob break; 315126ec864SMatt Jacob case PCI_QLOGIC_ISP2300: 316126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); 317126ec864SMatt Jacob break; 318126ec864SMatt Jacob case PCI_QLOGIC_ISP2312: 319126ec864SMatt Jacob device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); 320126ec864SMatt Jacob break; 32165adb54cSMatt Jacob default: 322960f6939SMatt Jacob return (ENXIO); 32365adb54cSMatt Jacob } 324d02373f1SMatt Jacob if (device_get_unit(dev) == 0 && bootverbose) { 325d02373f1SMatt Jacob printf("Qlogic ISP Driver, FreeBSD Version %d.%d, " 326a95ae193SMatt Jacob "Core Version %d.%d\n", 327d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 328d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 32965adb54cSMatt Jacob } 33056aef503SMatt Jacob /* 33156aef503SMatt Jacob * XXXX: Here is where we might load the f/w module 33256aef503SMatt Jacob * XXXX: (or increase a reference count to it). 33356aef503SMatt Jacob */ 334960f6939SMatt Jacob return (0); 33565adb54cSMatt Jacob } 33665adb54cSMatt Jacob 337960f6939SMatt Jacob static int 338960f6939SMatt Jacob isp_pci_attach(device_t dev) 33965adb54cSMatt Jacob { 340960f6939SMatt Jacob struct resource *regs, *irq; 3416e5c5328SMatt Jacob int tval, rtp, rgd, iqd, m1, m2, isp_debug, role; 342960f6939SMatt Jacob u_int32_t data, cmd, linesz, psize, basetype; 34365adb54cSMatt Jacob struct isp_pcisoftc *pcs; 3443395b056SMatt Jacob struct ispsoftc *isp = NULL; 345c6608df3SMatt Jacob struct ispmdvec *mdvp; 346222bb542SMatt Jacob bus_size_t lim; 34722941bd7SPeter Wemm const char *sptr; 3483395b056SMatt Jacob int locksetup = 0; 34965adb54cSMatt Jacob 350222bb542SMatt Jacob /* 3519ba86737SMatt Jacob * Figure out if we're supposed to skip this one. 352b9b599feSMatt Jacob * If we are, we actually go to ISP_ROLE_NONE. 3539ba86737SMatt Jacob */ 3546e5c5328SMatt Jacob 3556e5c5328SMatt Jacob tval = 0; 3566e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 3576e5c5328SMatt Jacob "disable", &tval) == 0 && tval) { 358b9b599feSMatt Jacob device_printf(dev, "device is disabled\n"); 359b9b599feSMatt Jacob /* but return 0 so the !$)$)*!$*) unit isn't reused */ 360b9b599feSMatt Jacob return (0); 361b9b599feSMatt Jacob } 3626e5c5328SMatt Jacob 3636e5c5328SMatt Jacob role = 0; 3646e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 3656e5c5328SMatt Jacob "role", &role) == 0 && 3666e5c5328SMatt Jacob ((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) { 3676e5c5328SMatt Jacob device_printf(dev, "setting role to 0x%x\n", role); 3686e5c5328SMatt Jacob } else { 369b9b599feSMatt Jacob #ifdef ISP_TARGET_MODE 370b9b599feSMatt Jacob role = ISP_ROLE_INITIATOR|ISP_ROLE_TARGET; 371b9b599feSMatt Jacob #else 372b9b599feSMatt Jacob role = ISP_DEFAULT_ROLES; 373b9b599feSMatt Jacob #endif 3749ba86737SMatt Jacob } 3759ba86737SMatt Jacob 3767cc0979fSDavid Malone pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT | M_ZERO); 377960f6939SMatt Jacob if (pcs == NULL) { 378960f6939SMatt Jacob device_printf(dev, "cannot allocate softc\n"); 379960f6939SMatt Jacob return (ENOMEM); 380960f6939SMatt Jacob } 381960f6939SMatt Jacob 3829ba86737SMatt Jacob /* 383222bb542SMatt Jacob * Figure out which we should try first - memory mapping or i/o mapping? 384222bb542SMatt Jacob */ 38556aef503SMatt Jacob #ifdef __alpha__ 386960f6939SMatt Jacob m1 = PCIM_CMD_MEMEN; 387960f6939SMatt Jacob m2 = PCIM_CMD_PORTEN; 388222bb542SMatt Jacob #else 389960f6939SMatt Jacob m1 = PCIM_CMD_PORTEN; 390960f6939SMatt Jacob m2 = PCIM_CMD_MEMEN; 391222bb542SMatt Jacob #endif 3926e5c5328SMatt Jacob 3936e5c5328SMatt Jacob tval = 0; 3946e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 3956e5c5328SMatt Jacob "prefer_iomap", &tval) == 0 && tval != 0) { 396960f6939SMatt Jacob m1 = PCIM_CMD_PORTEN; 397960f6939SMatt Jacob m2 = PCIM_CMD_MEMEN; 398960f6939SMatt Jacob } 3996e5c5328SMatt Jacob tval = 0; 4006e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 4016e5c5328SMatt Jacob "prefer_memmap", &tval) == 0 && tval != 0) { 4026e5c5328SMatt Jacob m1 = PCIM_CMD_MEMEN; 4036e5c5328SMatt Jacob m2 = PCIM_CMD_PORTEN; 404222bb542SMatt Jacob } 405222bb542SMatt Jacob 406ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 407960f6939SMatt Jacob irq = regs = NULL; 408960f6939SMatt Jacob rgd = rtp = iqd = 0; 409960f6939SMatt Jacob 410960f6939SMatt Jacob cmd = pci_read_config(dev, PCIR_COMMAND, 1); 411960f6939SMatt Jacob if (cmd & m1) { 412960f6939SMatt Jacob rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 413960f6939SMatt Jacob rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 414960f6939SMatt Jacob regs = bus_alloc_resource(dev, rtp, &rgd, 0, ~0, 1, RF_ACTIVE); 41565adb54cSMatt Jacob } 416960f6939SMatt Jacob if (regs == NULL && (cmd & m2)) { 417960f6939SMatt Jacob rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT; 418960f6939SMatt Jacob rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG; 419960f6939SMatt Jacob regs = bus_alloc_resource(dev, rtp, &rgd, 0, ~0, 1, RF_ACTIVE); 42065adb54cSMatt Jacob } 421960f6939SMatt Jacob if (regs == NULL) { 422960f6939SMatt Jacob device_printf(dev, "unable to map any ports\n"); 423960f6939SMatt Jacob goto bad; 42465adb54cSMatt Jacob } 425222bb542SMatt Jacob if (bootverbose) 426f7dddf8aSMatt Jacob device_printf(dev, "using %s space register mapping\n", 427960f6939SMatt Jacob (rgd == IO_MAP_REG)? "I/O" : "Memory"); 428960f6939SMatt Jacob pcs->pci_dev = dev; 429960f6939SMatt Jacob pcs->pci_reg = regs; 430960f6939SMatt Jacob pcs->pci_st = rman_get_bustag(regs); 431960f6939SMatt Jacob pcs->pci_sh = rman_get_bushandle(regs); 43265adb54cSMatt Jacob 433d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 434d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 435d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 436d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 437d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 438c6608df3SMatt Jacob mdvp = &mdvec; 439c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 440c6608df3SMatt Jacob psize = sizeof (sdparam); 441222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_32BIT; 44256aef503SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1020) { 443c6608df3SMatt Jacob mdvp = &mdvec; 444c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 445c6608df3SMatt Jacob psize = sizeof (sdparam); 446222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_24BIT; 447d59bd469SMatt Jacob } 448960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1080) { 449c6608df3SMatt Jacob mdvp = &mdvec_1080; 450c6608df3SMatt Jacob basetype = ISP_HA_SCSI_1080; 451c6608df3SMatt Jacob psize = sizeof (sdparam); 452c6608df3SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 453c6608df3SMatt Jacob ISP1080_DMA_REGS_OFF; 454c6608df3SMatt Jacob } 455960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1240) { 456c6608df3SMatt Jacob mdvp = &mdvec_1080; 45722e1dc85SMatt Jacob basetype = ISP_HA_SCSI_1240; 45822e1dc85SMatt Jacob psize = 2 * sizeof (sdparam); 45922e1dc85SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 46022e1dc85SMatt Jacob ISP1080_DMA_REGS_OFF; 46122e1dc85SMatt Jacob } 462960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP1280) { 46322e1dc85SMatt Jacob mdvp = &mdvec_1080; 46422e1dc85SMatt Jacob basetype = ISP_HA_SCSI_1280; 465c6608df3SMatt Jacob psize = 2 * sizeof (sdparam); 466d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 467d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 468d59bd469SMatt Jacob } 469960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP12160) { 470960f6939SMatt Jacob mdvp = &mdvec_12160; 471960f6939SMatt Jacob basetype = ISP_HA_SCSI_12160; 472960f6939SMatt Jacob psize = 2 * sizeof (sdparam); 473960f6939SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 474960f6939SMatt Jacob ISP1080_DMA_REGS_OFF; 475960f6939SMatt Jacob } 476960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2100) { 477c6608df3SMatt Jacob mdvp = &mdvec_2100; 478c6608df3SMatt Jacob basetype = ISP_HA_FC_2100; 479c6608df3SMatt Jacob psize = sizeof (fcparam); 480d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 481d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 482960f6939SMatt Jacob if (pci_get_revid(dev) < 3) { 483ab6d0040SMatt Jacob /* 484ab6d0040SMatt Jacob * XXX: Need to get the actual revision 485ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 486ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 487ab6d0040SMatt Jacob * XXX; boards. 488ab6d0040SMatt Jacob */ 489ab6d0040SMatt Jacob linesz = 1; 490ab6d0040SMatt Jacob } 49165adb54cSMatt Jacob } 492960f6939SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2200) { 493222bb542SMatt Jacob mdvp = &mdvec_2200; 494222bb542SMatt Jacob basetype = ISP_HA_FC_2200; 495222bb542SMatt Jacob psize = sizeof (fcparam); 496222bb542SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 497222bb542SMatt Jacob PCI_MBOX_REGS2100_OFF; 498222bb542SMatt Jacob } 49975c1e828SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300) { 500126ec864SMatt Jacob mdvp = &mdvec_2300; 501126ec864SMatt Jacob basetype = ISP_HA_FC_2300; 502126ec864SMatt Jacob psize = sizeof (fcparam); 503126ec864SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 504126ec864SMatt Jacob PCI_MBOX_REGS2300_OFF; 505126ec864SMatt Jacob } 50675c1e828SMatt Jacob if (pci_get_devid(dev) == PCI_QLOGIC_ISP2312) { 50775c1e828SMatt Jacob mdvp = &mdvec_2300; 50875c1e828SMatt Jacob basetype = ISP_HA_FC_2312; 50975c1e828SMatt Jacob psize = sizeof (fcparam); 51075c1e828SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 51175c1e828SMatt Jacob PCI_MBOX_REGS2300_OFF; 51275c1e828SMatt Jacob } 513c6608df3SMatt Jacob isp = &pcs->pci_isp; 5147cc0979fSDavid Malone isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); 515c6608df3SMatt Jacob if (isp->isp_param == NULL) { 516960f6939SMatt Jacob device_printf(dev, "cannot allocate parameter data\n"); 517960f6939SMatt Jacob goto bad; 518c6608df3SMatt Jacob } 519c6608df3SMatt Jacob isp->isp_mdvec = mdvp; 520c6608df3SMatt Jacob isp->isp_type = basetype; 521960f6939SMatt Jacob isp->isp_revision = pci_get_revid(dev); 522b9b599feSMatt Jacob isp->isp_role = role; 5236e5c5328SMatt Jacob isp->isp_dev = dev; 52465adb54cSMatt Jacob 52556aef503SMatt Jacob /* 52656aef503SMatt Jacob * Try and find firmware for this device. 52756aef503SMatt Jacob */ 52856aef503SMatt Jacob 52956aef503SMatt Jacob if (isp_get_firmware_p) { 53056aef503SMatt Jacob int device = (int) pci_get_device(dev); 53156aef503SMatt Jacob #ifdef ISP_TARGET_MODE 53256aef503SMatt Jacob (*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw); 53356aef503SMatt Jacob #else 53456aef503SMatt Jacob (*isp_get_firmware_p)(0, 0, device, &mdvp->dv_ispfw); 53556aef503SMatt Jacob #endif 53656aef503SMatt Jacob } 53756aef503SMatt Jacob 53856aef503SMatt Jacob /* 539d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 540d951bbcaSMatt Jacob * are set. 541d951bbcaSMatt Jacob */ 542960f6939SMatt Jacob cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | 543960f6939SMatt Jacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; 54475c1e828SMatt Jacob if (IS_2300(isp)) { /* per QLogic errata */ 54575c1e828SMatt Jacob cmd &= ~PCIM_CMD_INVEN; 54675c1e828SMatt Jacob } 547960f6939SMatt Jacob pci_write_config(dev, PCIR_COMMAND, cmd, 1); 548ab6d0040SMatt Jacob 549d951bbcaSMatt Jacob /* 550222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 551d951bbcaSMatt Jacob */ 552960f6939SMatt Jacob data = pci_read_config(dev, PCIR_CACHELNSZ, 1); 553ab6d0040SMatt Jacob if (data != linesz) { 554d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 555d02373f1SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d", data); 556960f6939SMatt Jacob pci_write_config(dev, PCIR_CACHELNSZ, data, 1); 557d951bbcaSMatt Jacob } 558ab6d0040SMatt Jacob 559d951bbcaSMatt Jacob /* 560d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 561d951bbcaSMatt Jacob */ 562960f6939SMatt Jacob data = pci_read_config(dev, PCIR_LATTIMER, 1); 563d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 564d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 565d02373f1SMatt Jacob isp_prt(isp, ISP_LOGCONFIG, "set PCI latency to %d", data); 566960f6939SMatt Jacob pci_write_config(dev, PCIR_LATTIMER, data, 1); 567d951bbcaSMatt Jacob } 568ab6d0040SMatt Jacob 569ab6d0040SMatt Jacob /* 570ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 571ab6d0040SMatt Jacob */ 572960f6939SMatt Jacob data = pci_read_config(dev, PCIR_ROMADDR, 4); 573ab6d0040SMatt Jacob data &= ~1; 574960f6939SMatt Jacob pci_write_config(dev, PCIR_ROMADDR, data, 4); 57505fbcbb0SMatt Jacob 576d951bbcaSMatt Jacob 577086646f7SJustin T. Gibbs if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 578222bb542SMatt Jacob BUS_SPACE_MAXADDR, NULL, NULL, lim + 1, 579222bb542SMatt Jacob 255, lim, 0, &pcs->parent_dmat) != 0) { 580f7dddf8aSMatt Jacob device_printf(dev, "could not create master dma tag\n"); 581960f6939SMatt Jacob free(isp->isp_param, M_DEVBUF); 582d720e6d5SJustin T. Gibbs free(pcs, M_DEVBUF); 583960f6939SMatt Jacob return (ENXIO); 58465adb54cSMatt Jacob } 58565adb54cSMatt Jacob 586960f6939SMatt Jacob iqd = 0; 587960f6939SMatt Jacob irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0, 588960f6939SMatt Jacob 1, RF_ACTIVE | RF_SHAREABLE); 589960f6939SMatt Jacob if (irq == NULL) { 590960f6939SMatt Jacob device_printf(dev, "could not allocate interrupt\n"); 591960f6939SMatt Jacob goto bad; 592960f6939SMatt Jacob } 593960f6939SMatt Jacob 5946e5c5328SMatt Jacob tval = 0; 5956e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 5966e5c5328SMatt Jacob "fwload_disable", &tval) == 0 && tval != 0) { 597222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 598222bb542SMatt Jacob } 5996e5c5328SMatt Jacob tval = 0; 6006e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6016e5c5328SMatt Jacob "ignore_nvram", &tval) == 0 && tval != 0) { 602222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 603222bb542SMatt Jacob } 6046e5c5328SMatt Jacob tval = 0; 6056e5c5328SMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 6066e5c5328SMatt Jacob "fullduplex", &tval) == 0 && tval != 0) { 607222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 608222bb542SMatt Jacob } 609d134aa0bSMatt Jacob #ifdef ISP_FW_CRASH_DUMP 610d134aa0bSMatt Jacob tval = 0; 611d134aa0bSMatt Jacob if (resource_int_value(device_get_name(dev), device_get_unit(dev), 612d134aa0bSMatt Jacob "fw_dump_enable", &tval) == 0 && tval != 0) { 613d134aa0bSMatt Jacob size_t amt = 0; 614d134aa0bSMatt Jacob if (IS_2200(isp)) { 615d134aa0bSMatt Jacob amt = QLA2200_RISC_IMAGE_DUMP_SIZE; 616d134aa0bSMatt Jacob } else if (IS_23XX(isp)) { 617d134aa0bSMatt Jacob amt = QLA2300_RISC_IMAGE_DUMP_SIZE; 618d134aa0bSMatt Jacob } 619d134aa0bSMatt Jacob if (amt) { 620d134aa0bSMatt Jacob FCPARAM(isp)->isp_dump_data = 621d134aa0bSMatt Jacob malloc(amt, M_DEVBUF, M_WAITOK | M_ZERO); 622d134aa0bSMatt Jacob } else { 623d134aa0bSMatt Jacob device_printf(dev, 624d134aa0bSMatt Jacob "f/w crash dumps not supported for this model\n"); 625d134aa0bSMatt Jacob } 626d134aa0bSMatt Jacob } 627d134aa0bSMatt Jacob #endif 628222bb542SMatt Jacob 6296e5c5328SMatt Jacob sptr = 0; 6306e5c5328SMatt Jacob if (resource_string_value(device_get_name(dev), device_get_unit(dev), 631559a1ad2SMatt Jacob "topology", (const char **) &sptr) == 0 && sptr != 0) { 6326e5c5328SMatt Jacob if (strcmp(sptr, "lport") == 0) { 6336e5c5328SMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT; 6346e5c5328SMatt Jacob } else if (strcmp(sptr, "nport") == 0) { 6356e5c5328SMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT; 6366e5c5328SMatt Jacob } else if (strcmp(sptr, "lport-only") == 0) { 6376e5c5328SMatt Jacob isp->isp_confopts |= ISP_CFG_LPORT_ONLY; 6386e5c5328SMatt Jacob } else if (strcmp(sptr, "nport-only") == 0) { 6396e5c5328SMatt Jacob isp->isp_confopts |= ISP_CFG_NPORT_ONLY; 6409637d68cSMatt Jacob } 6416e5c5328SMatt Jacob } 6426e5c5328SMatt Jacob 6439637d68cSMatt Jacob /* 6446e5c5328SMatt Jacob * Because the resource_*_value functions can neither return 6456e5c5328SMatt Jacob * 64 bit integer values, nor can they be directly coerced 6466e5c5328SMatt Jacob * to interpret the right hand side of the assignment as 6476e5c5328SMatt Jacob * you want them to interpret it, we have to force WWN 6486e5c5328SMatt Jacob * hint replacement to specify WWN strings with a leading 6496e5c5328SMatt Jacob * 'w' (e..g w50000000aaaa0001). Sigh. 6509637d68cSMatt Jacob */ 6516e5c5328SMatt Jacob sptr = 0; 6526e5c5328SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 653559a1ad2SMatt Jacob "portwwn", (const char **) &sptr); 6546e5c5328SMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6556e5c5328SMatt Jacob char *eptr = 0; 6566e5c5328SMatt Jacob isp->isp_osinfo.default_port_wwn = strtouq(sptr, &eptr, 16); 6576e5c5328SMatt Jacob if (eptr < sptr + 16 || isp->isp_osinfo.default_port_wwn == 0) { 6586e5c5328SMatt Jacob device_printf(dev, "mangled portwwn hint '%s'\n", sptr); 6596e5c5328SMatt Jacob isp->isp_osinfo.default_port_wwn = 0; 6609637d68cSMatt Jacob } else { 6613f02619fSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWPN; 662222bb542SMatt Jacob } 6636e5c5328SMatt Jacob } 6646e5c5328SMatt Jacob if (isp->isp_osinfo.default_port_wwn == 0) { 6656e5c5328SMatt Jacob isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull; 6666e5c5328SMatt Jacob } 6676e5c5328SMatt Jacob 6686e5c5328SMatt Jacob sptr = 0; 6696e5c5328SMatt Jacob tval = resource_string_value(device_get_name(dev), device_get_unit(dev), 670559a1ad2SMatt Jacob "nodewwn", (const char **) &sptr); 6716e5c5328SMatt Jacob if (tval == 0 && sptr != 0 && *sptr++ == 'w') { 6726e5c5328SMatt Jacob char *eptr = 0; 6736e5c5328SMatt Jacob isp->isp_osinfo.default_node_wwn = strtouq(sptr, &eptr, 16); 6746e5c5328SMatt Jacob if (eptr < sptr + 16 || isp->isp_osinfo.default_node_wwn == 0) { 6756e5c5328SMatt Jacob device_printf(dev, "mangled nodewwn hint '%s'\n", sptr); 6766e5c5328SMatt Jacob isp->isp_osinfo.default_node_wwn = 0; 6776e5c5328SMatt Jacob } else { 6783f02619fSMatt Jacob isp->isp_confopts |= ISP_CFG_OWNWWNN; 6796e5c5328SMatt Jacob } 6806e5c5328SMatt Jacob } 6816e5c5328SMatt Jacob if (isp->isp_osinfo.default_node_wwn == 0) { 6826e5c5328SMatt Jacob isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull; 6836e5c5328SMatt Jacob } 6846e5c5328SMatt Jacob 685d02373f1SMatt Jacob isp_debug = 0; 6866e5c5328SMatt Jacob (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 6876e5c5328SMatt Jacob "debug", &isp_debug); 688f09b1922SMatt Jacob 689f09b1922SMatt Jacob /* Make sure the lock is set up. */ 690f09b1922SMatt Jacob mtx_init(&isp->isp_osinfo.lock, "isp", MTX_DEF); 691f09b1922SMatt Jacob locksetup++; 692f09b1922SMatt Jacob 6935d571944SMatt Jacob #ifdef ISP_SMPLOCK 6945d571944SMatt Jacob #define INTR_FLAGS INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY 695f09b1922SMatt Jacob #else 6965d571944SMatt Jacob #define INTR_FLAGS INTR_TYPE_CAM | INTR_ENTROPY 6975d571944SMatt Jacob #endif 6985d571944SMatt Jacob if (bus_setup_intr(dev, irq, INTR_FLAGS, isp_pci_intr, isp, &pcs->ih)) { 699f09b1922SMatt Jacob device_printf(dev, "could not setup interrupt\n"); 700f09b1922SMatt Jacob goto bad; 701f09b1922SMatt Jacob } 702960f6939SMatt Jacob 70305fbcbb0SMatt Jacob /* 704d02373f1SMatt Jacob * Set up logging levels. 705d02373f1SMatt Jacob */ 706d02373f1SMatt Jacob if (isp_debug) { 707d02373f1SMatt Jacob isp->isp_dblev = isp_debug; 708d02373f1SMatt Jacob } else { 709d02373f1SMatt Jacob isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR; 710d02373f1SMatt Jacob } 711d02373f1SMatt Jacob if (bootverbose) 712f7dddf8aSMatt Jacob isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO; 713d02373f1SMatt Jacob 714d02373f1SMatt Jacob /* 71575c1e828SMatt Jacob * Last minute checks... 71675c1e828SMatt Jacob */ 71775c1e828SMatt Jacob if (IS_2312(isp)) { 71875c1e828SMatt Jacob isp->isp_port = pci_get_function(dev); 71975c1e828SMatt Jacob } 72075c1e828SMatt Jacob 72175c1e828SMatt Jacob /* 72205fbcbb0SMatt Jacob * Make sure we're in reset state. 72305fbcbb0SMatt Jacob */ 7243395b056SMatt Jacob ISP_LOCK(isp); 72565adb54cSMatt Jacob isp_reset(isp); 72665adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 7273395b056SMatt Jacob ISP_UNLOCK(isp); 728960f6939SMatt Jacob goto bad; 72965adb54cSMatt Jacob } 73065adb54cSMatt Jacob isp_init(isp); 731b9b599feSMatt Jacob if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) { 73265adb54cSMatt Jacob isp_uninit(isp); 7333395b056SMatt Jacob ISP_UNLOCK(isp); 734960f6939SMatt Jacob goto bad; 735d59bd469SMatt Jacob } 73665adb54cSMatt Jacob isp_attach(isp); 737b9b599feSMatt Jacob if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) { 73865adb54cSMatt Jacob isp_uninit(isp); 7393395b056SMatt Jacob ISP_UNLOCK(isp); 740960f6939SMatt Jacob goto bad; 741960f6939SMatt Jacob } 74256aef503SMatt Jacob /* 74356aef503SMatt Jacob * XXXX: Here is where we might unload the f/w module 74456aef503SMatt Jacob * XXXX: (or decrease the reference count to it). 74556aef503SMatt Jacob */ 7463395b056SMatt Jacob ISP_UNLOCK(isp); 747960f6939SMatt Jacob return (0); 748960f6939SMatt Jacob 749960f6939SMatt Jacob bad: 750960f6939SMatt Jacob 751960f6939SMatt Jacob if (pcs && pcs->ih) { 752960f6939SMatt Jacob (void) bus_teardown_intr(dev, irq, pcs->ih); 753960f6939SMatt Jacob } 754960f6939SMatt Jacob 7553395b056SMatt Jacob if (locksetup && isp) { 7563395b056SMatt Jacob mtx_destroy(&isp->isp_osinfo.lock); 7573395b056SMatt Jacob } 7583395b056SMatt Jacob 759960f6939SMatt Jacob if (irq) { 760960f6939SMatt Jacob (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq); 761960f6939SMatt Jacob } 7623395b056SMatt Jacob 7633395b056SMatt Jacob 764960f6939SMatt Jacob if (regs) { 765960f6939SMatt Jacob (void) bus_release_resource(dev, rtp, rgd, regs); 766960f6939SMatt Jacob } 7673395b056SMatt Jacob 768960f6939SMatt Jacob if (pcs) { 769960f6939SMatt Jacob if (pcs->pci_isp.isp_param) 770960f6939SMatt Jacob free(pcs->pci_isp.isp_param, M_DEVBUF); 77165adb54cSMatt Jacob free(pcs, M_DEVBUF); 77265adb54cSMatt Jacob } 7733395b056SMatt Jacob 77456aef503SMatt Jacob /* 77556aef503SMatt Jacob * XXXX: Here is where we might unload the f/w module 77656aef503SMatt Jacob * XXXX: (or decrease the reference count to it). 77756aef503SMatt Jacob */ 778960f6939SMatt Jacob return (ENXIO); 77965adb54cSMatt Jacob } 78065adb54cSMatt Jacob 781f09b1922SMatt Jacob static void 782f09b1922SMatt Jacob isp_pci_intr(void *arg) 783f09b1922SMatt Jacob { 784f09b1922SMatt Jacob struct ispsoftc *isp = arg; 785126ec864SMatt Jacob u_int16_t isr, sema, mbox; 786126ec864SMatt Jacob 787f09b1922SMatt Jacob ISP_LOCK(isp); 788126ec864SMatt Jacob isp->isp_intcnt++; 789126ec864SMatt Jacob if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { 790126ec864SMatt Jacob isp->isp_intbogus++; 791126ec864SMatt Jacob } else { 792b96934e8SMatt Jacob int iok = isp->isp_osinfo.intsok; 793b96934e8SMatt Jacob isp->isp_osinfo.intsok = 0; 794126ec864SMatt Jacob isp_intr(isp, isr, sema, mbox); 795b96934e8SMatt Jacob isp->isp_osinfo.intsok = iok; 796126ec864SMatt Jacob } 797f09b1922SMatt Jacob ISP_UNLOCK(isp); 798f09b1922SMatt Jacob } 799f09b1922SMatt Jacob 800126ec864SMatt Jacob 801126ec864SMatt Jacob #define IspVirt2Off(a, x) \ 802126ec864SMatt Jacob (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ 803126ec864SMatt Jacob _BLK_REG_SHFT] + ((x) & 0xff)) 804126ec864SMatt Jacob 805126ec864SMatt Jacob #define BXR2(pcs, off) \ 806126ec864SMatt Jacob bus_space_read_2(pcs->pci_st, pcs->pci_sh, off) 807126ec864SMatt Jacob #define BXW2(pcs, off, v) \ 808126ec864SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v) 809126ec864SMatt Jacob 810126ec864SMatt Jacob 811126ec864SMatt Jacob static INLINE int 812126ec864SMatt Jacob isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp) 813126ec864SMatt Jacob { 814126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 815126ec864SMatt Jacob u_int16_t val0, val1; 816126ec864SMatt Jacob int i = 0; 817126ec864SMatt Jacob 818126ec864SMatt Jacob do { 819126ec864SMatt Jacob val0 = BXR2(pcs, IspVirt2Off(isp, off)); 820126ec864SMatt Jacob val1 = BXR2(pcs, IspVirt2Off(isp, off)); 821126ec864SMatt Jacob } while (val0 != val1 && ++i < 1000); 822126ec864SMatt Jacob if (val0 != val1) { 823126ec864SMatt Jacob return (1); 824126ec864SMatt Jacob } 825126ec864SMatt Jacob *rp = val0; 826126ec864SMatt Jacob return (0); 827126ec864SMatt Jacob } 828126ec864SMatt Jacob 829126ec864SMatt Jacob static int 830126ec864SMatt Jacob isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, 831126ec864SMatt Jacob u_int16_t *semap, u_int16_t *mbp) 832126ec864SMatt Jacob { 833126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 834126ec864SMatt Jacob u_int16_t isr, sema; 835126ec864SMatt Jacob 836126ec864SMatt Jacob if (IS_2100(isp)) { 837126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { 838126ec864SMatt Jacob return (0); 839126ec864SMatt Jacob } 840126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { 841126ec864SMatt Jacob return (0); 842126ec864SMatt Jacob } 843126ec864SMatt Jacob } else { 844126ec864SMatt Jacob isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR)); 845126ec864SMatt Jacob sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA)); 846126ec864SMatt Jacob } 847126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); 848126ec864SMatt Jacob isr &= INT_PENDING_MASK(isp); 849126ec864SMatt Jacob sema &= BIU_SEMA_LOCK; 850126ec864SMatt Jacob if (isr == 0 && sema == 0) { 851126ec864SMatt Jacob return (0); 852126ec864SMatt Jacob } 853126ec864SMatt Jacob *isrp = isr; 854126ec864SMatt Jacob if ((*semap = sema) != 0) { 855126ec864SMatt Jacob if (IS_2100(isp)) { 856126ec864SMatt Jacob if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) { 857126ec864SMatt Jacob return (0); 858126ec864SMatt Jacob } 859126ec864SMatt Jacob } else { 860126ec864SMatt Jacob *mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0)); 861126ec864SMatt Jacob } 862126ec864SMatt Jacob } 863126ec864SMatt Jacob return (1); 864126ec864SMatt Jacob } 865126ec864SMatt Jacob 866126ec864SMatt Jacob static int 867126ec864SMatt Jacob isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp, 868126ec864SMatt Jacob u_int16_t *semap, u_int16_t *mbox0p) 869126ec864SMatt Jacob { 870126ec864SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 871126ec864SMatt Jacob u_int32_t r2hisr; 872126ec864SMatt Jacob 8733bd40330SMatt Jacob if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) { 8743bd40330SMatt Jacob *isrp = 0; 875db4fa023SMatt Jacob return (0); 8763bd40330SMatt Jacob } 877126ec864SMatt Jacob r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh, 878126ec864SMatt Jacob IspVirt2Off(pcs, BIU_R2HSTSLO)); 879126ec864SMatt Jacob isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); 880126ec864SMatt Jacob if ((r2hisr & BIU_R2HST_INTR) == 0) { 881126ec864SMatt Jacob *isrp = 0; 882126ec864SMatt Jacob return (0); 883126ec864SMatt Jacob } 884126ec864SMatt Jacob switch (r2hisr & BIU_R2HST_ISTAT_MASK) { 885126ec864SMatt Jacob case ISPR2HST_ROM_MBX_OK: 886126ec864SMatt Jacob case ISPR2HST_ROM_MBX_FAIL: 887126ec864SMatt Jacob case ISPR2HST_MBX_OK: 888126ec864SMatt Jacob case ISPR2HST_MBX_FAIL: 889126ec864SMatt Jacob case ISPR2HST_ASYNC_EVENT: 89075c1e828SMatt Jacob case ISPR2HST_RIO_16: 891126ec864SMatt Jacob case ISPR2HST_FPOST: 892126ec864SMatt Jacob case ISPR2HST_FPOST_CTIO: 893126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 894126ec864SMatt Jacob *mbox0p = (r2hisr >> 16); 895126ec864SMatt Jacob *semap = 1; 896126ec864SMatt Jacob return (1); 897126ec864SMatt Jacob case ISPR2HST_RSPQ_UPDATE: 898126ec864SMatt Jacob *isrp = r2hisr & 0xffff; 899126ec864SMatt Jacob *mbox0p = 0; 900126ec864SMatt Jacob *semap = 0; 901126ec864SMatt Jacob return (1); 902126ec864SMatt Jacob default: 903126ec864SMatt Jacob return (0); 904126ec864SMatt Jacob } 905126ec864SMatt Jacob } 906126ec864SMatt Jacob 90765adb54cSMatt Jacob static u_int16_t 908126ec864SMatt Jacob isp_pci_rd_reg(struct ispsoftc *isp, int regoff) 90965adb54cSMatt Jacob { 91065adb54cSMatt Jacob u_int16_t rv; 91165adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 912126ec864SMatt Jacob int oldconf = 0; 91365adb54cSMatt Jacob 914d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 91565adb54cSMatt Jacob /* 91665adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 91765adb54cSMatt Jacob */ 918126ec864SMatt Jacob oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 919126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 920126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 92165adb54cSMatt Jacob } 922126ec864SMatt Jacob rv = BXR2(pcs, IspVirt2Off(isp, regoff)); 923d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 924126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); 92565adb54cSMatt Jacob } 92665adb54cSMatt Jacob return (rv); 92765adb54cSMatt Jacob } 92865adb54cSMatt Jacob 92965adb54cSMatt Jacob static void 930126ec864SMatt Jacob isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) 93165adb54cSMatt Jacob { 93265adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 933126ec864SMatt Jacob int oldconf = 0; 934d59bd469SMatt Jacob 935d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 93665adb54cSMatt Jacob /* 93765adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 93865adb54cSMatt Jacob */ 939126ec864SMatt Jacob oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 940126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 941126ec864SMatt Jacob oldconf | BIU_PCI_CONF1_SXP); 94265adb54cSMatt Jacob } 943126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, regoff), val); 944d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 945126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); 94665adb54cSMatt Jacob } 94765adb54cSMatt Jacob } 94865adb54cSMatt Jacob 949d59bd469SMatt Jacob static u_int16_t 950126ec864SMatt Jacob isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) 951d59bd469SMatt Jacob { 95222e1dc85SMatt Jacob u_int16_t rv, oc = 0; 953d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 954d59bd469SMatt Jacob 95522e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 95622e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 95722e1dc85SMatt Jacob u_int16_t tc; 958d59bd469SMatt Jacob /* 959d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 960d59bd469SMatt Jacob */ 961126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 96222e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 96322e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 96422e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 96522e1dc85SMatt Jacob else 96622e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 967126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); 968d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 969126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 970126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 971126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 972d59bd469SMatt Jacob } 973126ec864SMatt Jacob rv = BXR2(pcs, IspVirt2Off(isp, regoff)); 97422e1dc85SMatt Jacob if (oc) { 975126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); 976d59bd469SMatt Jacob } 977d59bd469SMatt Jacob return (rv); 978d59bd469SMatt Jacob } 979d59bd469SMatt Jacob 980d59bd469SMatt Jacob static void 981126ec864SMatt Jacob isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) 982d59bd469SMatt Jacob { 983d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 984126ec864SMatt Jacob int oc = 0; 985d59bd469SMatt Jacob 98622e1dc85SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 98722e1dc85SMatt Jacob (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { 98822e1dc85SMatt Jacob u_int16_t tc; 989d59bd469SMatt Jacob /* 990d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 991d59bd469SMatt Jacob */ 992126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 99322e1dc85SMatt Jacob tc = oc & ~BIU_PCI1080_CONF1_DMA; 99422e1dc85SMatt Jacob if (regoff & SXP_BANK1_SELECT) 99522e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP1; 99622e1dc85SMatt Jacob else 99722e1dc85SMatt Jacob tc |= BIU_PCI1080_CONF1_SXP0; 998126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); 999d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 1000126ec864SMatt Jacob oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); 1001126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), 1002126ec864SMatt Jacob oc | BIU_PCI1080_CONF1_DMA); 1003d59bd469SMatt Jacob } 1004126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, regoff), val); 100522e1dc85SMatt Jacob if (oc) { 1006126ec864SMatt Jacob BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); 1007d59bd469SMatt Jacob } 1008d59bd469SMatt Jacob } 1009d59bd469SMatt Jacob 1010126ec864SMatt Jacob static void isp_map_rquest(void *, bus_dma_segment_t *, int, int); 1011126ec864SMatt Jacob static void isp_map_result(void *, bus_dma_segment_t *, int, int); 1012126ec864SMatt Jacob static void isp_map_fcscrt(void *, bus_dma_segment_t *, int, int); 1013d720e6d5SJustin T. Gibbs 1014222bb542SMatt Jacob struct imush { 1015222bb542SMatt Jacob struct ispsoftc *isp; 1016222bb542SMatt Jacob int error; 1017222bb542SMatt Jacob }; 1018222bb542SMatt Jacob 1019d720e6d5SJustin T. Gibbs static void 102017e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1021d720e6d5SJustin T. Gibbs { 1022222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 1023222bb542SMatt Jacob if (error) { 1024222bb542SMatt Jacob imushp->error = error; 1025222bb542SMatt Jacob } else { 1026222bb542SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 1027222bb542SMatt Jacob } 1028d720e6d5SJustin T. Gibbs } 1029d720e6d5SJustin T. Gibbs 1030d720e6d5SJustin T. Gibbs static void 103117e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1032d720e6d5SJustin T. Gibbs { 1033222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 1034222bb542SMatt Jacob if (error) { 1035222bb542SMatt Jacob imushp->error = error; 1036222bb542SMatt Jacob } else { 1037222bb542SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 1038222bb542SMatt Jacob } 1039d720e6d5SJustin T. Gibbs } 1040d720e6d5SJustin T. Gibbs 1041d720e6d5SJustin T. Gibbs static void 104217e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1043d720e6d5SJustin T. Gibbs { 1044222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 1045222bb542SMatt Jacob if (error) { 1046222bb542SMatt Jacob imushp->error = error; 1047222bb542SMatt Jacob } else { 1048222bb542SMatt Jacob fcparam *fcp = imushp->isp->isp_param; 1049d720e6d5SJustin T. Gibbs fcp->isp_scdma = segs->ds_addr; 1050d720e6d5SJustin T. Gibbs } 1051222bb542SMatt Jacob } 1052d720e6d5SJustin T. Gibbs 1053d720e6d5SJustin T. Gibbs static int 105417e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 1055d720e6d5SJustin T. Gibbs { 1056d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1057d720e6d5SJustin T. Gibbs caddr_t base; 1058d720e6d5SJustin T. Gibbs u_int32_t len; 1059d720e6d5SJustin T. Gibbs int i, error; 1060222bb542SMatt Jacob bus_size_t lim; 1061222bb542SMatt Jacob struct imush im; 1062222bb542SMatt Jacob 1063222bb542SMatt Jacob 1064a95ae193SMatt Jacob /* 1065a95ae193SMatt Jacob * Already been here? If so, leave... 1066a95ae193SMatt Jacob */ 1067a95ae193SMatt Jacob if (isp->isp_rquest) { 1068a95ae193SMatt Jacob return (0); 1069a95ae193SMatt Jacob } 1070a95ae193SMatt Jacob 1071d02373f1SMatt Jacob len = sizeof (XS_T **) * isp->isp_maxcmds; 10727cc0979fSDavid Malone isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 1073a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 1074d02373f1SMatt Jacob isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array"); 1075a95ae193SMatt Jacob return (1); 1076a95ae193SMatt Jacob } 1077a95ae193SMatt Jacob len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; 1078a95ae193SMatt Jacob pci->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK); 1079a95ae193SMatt Jacob if (pci->dmaps == NULL) { 1080d02373f1SMatt Jacob isp_prt(isp, ISP_LOGERR, "can't alloc dma maps"); 1081a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1082a95ae193SMatt Jacob return (1); 1083a95ae193SMatt Jacob } 1084a95ae193SMatt Jacob 108522e1dc85SMatt Jacob if (IS_FC(isp) || IS_ULTRA2(isp)) 1086222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR + 1; 1087222bb542SMatt Jacob else 1088222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR_24BIT + 1; 1089d720e6d5SJustin T. Gibbs 1090d720e6d5SJustin T. Gibbs /* 1091d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 1092d720e6d5SJustin T. Gibbs */ 1093d02373f1SMatt Jacob len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1094d02373f1SMatt Jacob len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1095222bb542SMatt Jacob if (IS_FC(isp)) { 1096d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 1097d720e6d5SJustin T. Gibbs } 1098222bb542SMatt Jacob if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim, 1099222bb542SMatt Jacob BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, 1100222bb542SMatt Jacob BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { 1101f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1102f7dddf8aSMatt Jacob "cannot create a dma tag for control spaces"); 1103a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1104a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1105d720e6d5SJustin T. Gibbs return (1); 1106d720e6d5SJustin T. Gibbs } 1107d720e6d5SJustin T. Gibbs if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 1108d720e6d5SJustin T. Gibbs BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 1109f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 11103486bfe0SMatt Jacob "cannot allocate %d bytes of CCB memory", len); 1111a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1112a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1113d720e6d5SJustin T. Gibbs return (1); 1114d720e6d5SJustin T. Gibbs } 1115d720e6d5SJustin T. Gibbs 1116d720e6d5SJustin T. Gibbs isp->isp_rquest = base; 1117222bb542SMatt Jacob im.isp = isp; 1118222bb542SMatt Jacob im.error = 0; 1119d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 1120d02373f1SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), isp_map_rquest, &im, 0); 1121222bb542SMatt Jacob if (im.error) { 1122f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1123f7dddf8aSMatt Jacob "error %d loading dma map for DMA request queue", im.error); 1124a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1125a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1126a95ae193SMatt Jacob isp->isp_rquest = NULL; 1127222bb542SMatt Jacob return (1); 1128222bb542SMatt Jacob } 1129d02373f1SMatt Jacob isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)); 1130222bb542SMatt Jacob im.error = 0; 1131d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 1132d02373f1SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)), isp_map_result, &im, 0); 1133222bb542SMatt Jacob if (im.error) { 1134f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1135f7dddf8aSMatt Jacob "error %d loading dma map for DMA result queue", im.error); 1136a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1137a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1138a95ae193SMatt Jacob isp->isp_rquest = NULL; 1139222bb542SMatt Jacob return (1); 1140222bb542SMatt Jacob } 1141d720e6d5SJustin T. Gibbs 1142a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 1143d720e6d5SJustin T. Gibbs error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 1144d720e6d5SJustin T. Gibbs if (error) { 1145f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1146f7dddf8aSMatt Jacob "error %d creating per-cmd DMA maps", error); 1147a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1148a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1149a95ae193SMatt Jacob isp->isp_rquest = NULL; 1150d720e6d5SJustin T. Gibbs return (1); 1151d720e6d5SJustin T. Gibbs } 1152d720e6d5SJustin T. Gibbs } 1153a95ae193SMatt Jacob 1154222bb542SMatt Jacob if (IS_FC(isp)) { 115592c49d78SMatt Jacob fcparam *fcp = (fcparam *) isp->isp_param; 115692c49d78SMatt Jacob fcp->isp_scratch = base + 1157d02373f1SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) + 1158d02373f1SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)); 1159222bb542SMatt Jacob im.error = 0; 116092c49d78SMatt Jacob bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 1161222bb542SMatt Jacob fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0); 1162222bb542SMatt Jacob if (im.error) { 1163f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1164f7dddf8aSMatt Jacob "error %d loading FC scratch area", im.error); 1165a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 1166a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 1167a95ae193SMatt Jacob isp->isp_rquest = NULL; 1168222bb542SMatt Jacob return (1); 1169222bb542SMatt Jacob } 117092c49d78SMatt Jacob } 1171d720e6d5SJustin T. Gibbs return (0); 1172d720e6d5SJustin T. Gibbs } 1173d720e6d5SJustin T. Gibbs 1174d720e6d5SJustin T. Gibbs typedef struct { 1175d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 11769e11e5beSMatt Jacob void *cmd_token; 11779e11e5beSMatt Jacob void *rq; 11784fd13c1bSMatt Jacob u_int16_t *nxtip; 11799637d68cSMatt Jacob u_int16_t optr; 1180d720e6d5SJustin T. Gibbs u_int error; 1181d720e6d5SJustin T. Gibbs } mush_t; 1182d720e6d5SJustin T. Gibbs 11834873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 11844873663cSMatt Jacob 11859e11e5beSMatt Jacob #ifdef ISP_TARGET_MODE 11869e11e5beSMatt Jacob /* 11879e11e5beSMatt Jacob * We need to handle DMA for target mode differently from initiator mode. 11889e11e5beSMatt Jacob * 11899e11e5beSMatt Jacob * DMA mapping and construction and submission of CTIO Request Entries 11909e11e5beSMatt Jacob * and rendevous for completion are very tightly coupled because we start 11919e11e5beSMatt Jacob * out by knowing (per platform) how much data we have to move, but we 11929e11e5beSMatt Jacob * don't know, up front, how many DMA mapping segments will have to be used 11939e11e5beSMatt Jacob * cover that data, so we don't know how many CTIO Request Entries we 11949e11e5beSMatt Jacob * will end up using. Further, for performance reasons we may want to 11959e11e5beSMatt Jacob * (on the last CTIO for Fibre Channel), send status too (if all went well). 11969e11e5beSMatt Jacob * 11979e11e5beSMatt Jacob * The standard vector still goes through isp_pci_dmasetup, but the callback 11989e11e5beSMatt Jacob * for the DMA mapping routines comes here instead with the whole transfer 11999e11e5beSMatt Jacob * mapped and a pointer to a partially filled in already allocated request 12009e11e5beSMatt Jacob * queue entry. We finish the job. 12019e11e5beSMatt Jacob */ 1202e9a2738aSMatt Jacob static void tdma_mk(void *, bus_dma_segment_t *, int, int); 1203e9a2738aSMatt Jacob static void tdma_mkfc(void *, bus_dma_segment_t *, int, int); 1204e9a2738aSMatt Jacob 1205e9a2738aSMatt Jacob #define STATUS_WITH_DATA 1 12069e11e5beSMatt Jacob 1207d720e6d5SJustin T. Gibbs static void 120805fbcbb0SMatt Jacob tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1209d720e6d5SJustin T. Gibbs { 1210d720e6d5SJustin T. Gibbs mush_t *mp; 12119e11e5beSMatt Jacob struct ccb_scsiio *csio; 12124fd13c1bSMatt Jacob struct ispsoftc *isp; 1213d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci; 1214d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 12154fd13c1bSMatt Jacob ct_entry_t *cto, *qe; 121605fbcbb0SMatt Jacob u_int8_t scsi_status; 12174fd13c1bSMatt Jacob u_int16_t curi, nxti, handle; 1218b96934e8SMatt Jacob u_int32_t sflags; 121905fbcbb0SMatt Jacob int32_t resid; 12204fd13c1bSMatt Jacob int nth_ctio, nctios, send_status; 1221d720e6d5SJustin T. Gibbs 1222d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 1223d720e6d5SJustin T. Gibbs if (error) { 1224d720e6d5SJustin T. Gibbs mp->error = error; 1225d720e6d5SJustin T. Gibbs return; 1226d720e6d5SJustin T. Gibbs } 12274fd13c1bSMatt Jacob 12284fd13c1bSMatt Jacob isp = mp->isp; 12299e11e5beSMatt Jacob csio = mp->cmd_token; 12309e11e5beSMatt Jacob cto = mp->rq; 12314fd13c1bSMatt Jacob curi = isp->isp_reqidx; 12324fd13c1bSMatt Jacob qe = (ct_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi); 12339e11e5beSMatt Jacob 123465b024e1SMatt Jacob cto->ct_xfrlen = 0; 123565b024e1SMatt Jacob cto->ct_seg_count = 0; 123665b024e1SMatt Jacob cto->ct_header.rqs_entry_count = 1; 123705fbcbb0SMatt Jacob MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg)); 123805fbcbb0SMatt Jacob 123905fbcbb0SMatt Jacob if (nseg == 0) { 124005fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 1; 12414fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 1242e9a2738aSMatt Jacob "CTIO[%x] lun%d iid%d tag %x flgs %x sts %x ssts %x res %d", 12435f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, cto->ct_iid, 1244e9a2738aSMatt Jacob cto->ct_tag_val, cto->ct_flags, cto->ct_status, 1245e9a2738aSMatt Jacob cto->ct_scsi_status, cto->ct_resid); 12464fd13c1bSMatt Jacob ISP_TDQE(isp, "tdma_mk[no data]", curi, cto); 12474fd13c1bSMatt Jacob isp_put_ctio(isp, cto, qe); 124865b024e1SMatt Jacob return; 124965b024e1SMatt Jacob } 125065b024e1SMatt Jacob 125165b024e1SMatt Jacob nctios = nseg / ISP_RQDSEG; 125265b024e1SMatt Jacob if (nseg % ISP_RQDSEG) { 125365b024e1SMatt Jacob nctios++; 125465b024e1SMatt Jacob } 125565b024e1SMatt Jacob 125605fbcbb0SMatt Jacob /* 12575f5aafe1SMatt Jacob * Save syshandle, and potentially any SCSI status, which we'll 12585f5aafe1SMatt Jacob * reinsert on the last CTIO we're going to send. 125905fbcbb0SMatt Jacob */ 12604fd13c1bSMatt Jacob 12615f5aafe1SMatt Jacob handle = cto->ct_syshandle; 12625f5aafe1SMatt Jacob cto->ct_syshandle = 0; 126305fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 0; 126405fbcbb0SMatt Jacob send_status = (cto->ct_flags & CT_SENDSTATUS) != 0; 126505fbcbb0SMatt Jacob 126605fbcbb0SMatt Jacob if (send_status) { 126705fbcbb0SMatt Jacob sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR); 126805fbcbb0SMatt Jacob cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR); 126905fbcbb0SMatt Jacob /* 127005fbcbb0SMatt Jacob * Preserve residual. 127105fbcbb0SMatt Jacob */ 127205fbcbb0SMatt Jacob resid = cto->ct_resid; 127305fbcbb0SMatt Jacob 127405fbcbb0SMatt Jacob /* 127505fbcbb0SMatt Jacob * Save actual SCSI status. 127605fbcbb0SMatt Jacob */ 127705fbcbb0SMatt Jacob scsi_status = cto->ct_scsi_status; 127805fbcbb0SMatt Jacob 1279e9a2738aSMatt Jacob #ifndef STATUS_WITH_DATA 1280e9a2738aSMatt Jacob sflags |= CT_NO_DATA; 128105fbcbb0SMatt Jacob /* 128205fbcbb0SMatt Jacob * We can't do a status at the same time as a data CTIO, so 128305fbcbb0SMatt Jacob * we need to synthesize an extra CTIO at this level. 128405fbcbb0SMatt Jacob */ 128505fbcbb0SMatt Jacob nctios++; 1286b72b1569SMatt Jacob #endif 128705fbcbb0SMatt Jacob } else { 128805fbcbb0SMatt Jacob sflags = scsi_status = resid = 0; 128905fbcbb0SMatt Jacob } 129005fbcbb0SMatt Jacob 1291b96934e8SMatt Jacob cto->ct_resid = 0; 129205fbcbb0SMatt Jacob cto->ct_scsi_status = 0; 129305fbcbb0SMatt Jacob 12944fd13c1bSMatt Jacob pci = (struct isp_pcisoftc *)isp; 1295469b6b9eSMatt Jacob dp = &pci->dmaps[isp_handle_index(handle)]; 12969e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1297d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 1298d720e6d5SJustin T. Gibbs } else { 1299d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 1300d720e6d5SJustin T. Gibbs } 1301d720e6d5SJustin T. Gibbs 13024fd13c1bSMatt Jacob nxti = *mp->nxtip; 13039e11e5beSMatt Jacob 13044fd13c1bSMatt Jacob for (nth_ctio = 0; nth_ctio < nctios; nth_ctio++) { 130505fbcbb0SMatt Jacob int seglim; 13069e11e5beSMatt Jacob 13079e11e5beSMatt Jacob seglim = nseg; 130805fbcbb0SMatt Jacob if (seglim) { 130905fbcbb0SMatt Jacob int seg; 131005fbcbb0SMatt Jacob 13119e11e5beSMatt Jacob if (seglim > ISP_RQDSEG) 13129e11e5beSMatt Jacob seglim = ISP_RQDSEG; 13139e11e5beSMatt Jacob 131405fbcbb0SMatt Jacob for (seg = 0; seg < seglim; seg++, nseg--) { 131505fbcbb0SMatt Jacob /* 131605fbcbb0SMatt Jacob * Unlike normal initiator commands, we don't 131705fbcbb0SMatt Jacob * do any swizzling here. 131805fbcbb0SMatt Jacob */ 13199e11e5beSMatt Jacob cto->ct_dataseg[seg].ds_count = dm_segs->ds_len; 132005fbcbb0SMatt Jacob cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr; 13219e11e5beSMatt Jacob cto->ct_xfrlen += dm_segs->ds_len; 13229e11e5beSMatt Jacob dm_segs++; 13239e11e5beSMatt Jacob } 13249e11e5beSMatt Jacob cto->ct_seg_count = seg; 13259e11e5beSMatt Jacob } else { 132605fbcbb0SMatt Jacob /* 132705fbcbb0SMatt Jacob * This case should only happen when we're sending an 132805fbcbb0SMatt Jacob * extra CTIO with final status. 132905fbcbb0SMatt Jacob */ 133005fbcbb0SMatt Jacob if (send_status == 0) { 13314fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 1332f7dddf8aSMatt Jacob "tdma_mk ran out of segments"); 133305fbcbb0SMatt Jacob mp->error = EINVAL; 133405fbcbb0SMatt Jacob return; 13359e11e5beSMatt Jacob } 133605fbcbb0SMatt Jacob } 133705fbcbb0SMatt Jacob 133805fbcbb0SMatt Jacob /* 133905fbcbb0SMatt Jacob * At this point, the fields ct_lun, ct_iid, ct_tagval, 134005fbcbb0SMatt Jacob * ct_tagtype, and ct_timeout have been carried over 134105fbcbb0SMatt Jacob * unchanged from what our caller had set. 134205fbcbb0SMatt Jacob * 134305fbcbb0SMatt Jacob * The dataseg fields and the seg_count fields we just got 134405fbcbb0SMatt Jacob * through setting. The data direction we've preserved all 134505fbcbb0SMatt Jacob * along and only clear it if we're now sending status. 134605fbcbb0SMatt Jacob */ 13479e11e5beSMatt Jacob 13484fd13c1bSMatt Jacob if (nth_ctio == nctios - 1) { 13499e11e5beSMatt Jacob /* 135005fbcbb0SMatt Jacob * We're the last in a sequence of CTIOs, so mark 135105fbcbb0SMatt Jacob * this CTIO and save the handle to the CCB such that 135205fbcbb0SMatt Jacob * when this CTIO completes we can free dma resources 135305fbcbb0SMatt Jacob * and do whatever else we need to do to finish the 1354e9a2738aSMatt Jacob * rest of the command. We *don't* give this to the 1355e9a2738aSMatt Jacob * firmware to work on- the caller will do that. 13569e11e5beSMatt Jacob */ 13574fd13c1bSMatt Jacob 13585f5aafe1SMatt Jacob cto->ct_syshandle = handle; 135905fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 1; 136005fbcbb0SMatt Jacob 136105fbcbb0SMatt Jacob if (send_status) { 13629e11e5beSMatt Jacob cto->ct_scsi_status = scsi_status; 1363b72b1569SMatt Jacob cto->ct_flags |= sflags; 136405fbcbb0SMatt Jacob cto->ct_resid = resid; 136542426921SMatt Jacob } 1366d02373f1SMatt Jacob if (send_status) { 13674fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 1368e9a2738aSMatt Jacob "CTIO[%x] lun%d iid %d tag %x ct_flags %x " 13695f5aafe1SMatt Jacob "scsi status %x resid %d", 13705f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 1371e9a2738aSMatt Jacob cto->ct_iid, cto->ct_tag_val, cto->ct_flags, 137205fbcbb0SMatt Jacob cto->ct_scsi_status, cto->ct_resid); 1373d02373f1SMatt Jacob } else { 13744fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 1375e9a2738aSMatt Jacob "CTIO[%x] lun%d iid%d tag %x ct_flags 0x%x", 13765f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 1377e9a2738aSMatt Jacob cto->ct_iid, cto->ct_tag_val, 1378e9a2738aSMatt Jacob cto->ct_flags); 137905fbcbb0SMatt Jacob } 13804fd13c1bSMatt Jacob isp_put_ctio(isp, cto, qe); 13814fd13c1bSMatt Jacob ISP_TDQE(isp, "last tdma_mk", curi, cto); 13824fd13c1bSMatt Jacob if (nctios > 1) { 13834fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, 13844fd13c1bSMatt Jacob curi, QENTRY_LEN); 13854fd13c1bSMatt Jacob } 13869e11e5beSMatt Jacob } else { 13874fd13c1bSMatt Jacob ct_entry_t *oqe = qe; 138805fbcbb0SMatt Jacob 138905fbcbb0SMatt Jacob /* 13905f5aafe1SMatt Jacob * Make sure syshandle fields are clean 139105fbcbb0SMatt Jacob */ 13925f5aafe1SMatt Jacob cto->ct_syshandle = 0; 13939e11e5beSMatt Jacob cto->ct_header.rqs_seqno = 0; 139405fbcbb0SMatt Jacob 13954fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 13965f5aafe1SMatt Jacob "CTIO[%x] lun%d for ID%d ct_flags 0x%x", 13975f5aafe1SMatt Jacob cto->ct_fwhandle, csio->ccb_h.target_lun, 13985f5aafe1SMatt Jacob cto->ct_iid, cto->ct_flags); 139905fbcbb0SMatt Jacob 140005fbcbb0SMatt Jacob /* 140105fbcbb0SMatt Jacob * Get a new CTIO 140205fbcbb0SMatt Jacob */ 14034fd13c1bSMatt Jacob qe = (ct_entry_t *) 14044fd13c1bSMatt Jacob ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 14054fd13c1bSMatt Jacob nxti = ISP_NXT_QENTRY(nxti, RQUEST_QUEUE_LEN(isp)); 14064fd13c1bSMatt Jacob if (nxti == mp->optr) { 14074fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 1408f7dddf8aSMatt Jacob "Queue Overflow in tdma_mk"); 14099e11e5beSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 14109e11e5beSMatt Jacob return; 14119e11e5beSMatt Jacob } 14124fd13c1bSMatt Jacob 14139e11e5beSMatt Jacob /* 14144fd13c1bSMatt Jacob * Now that we're done with the old CTIO, 14154fd13c1bSMatt Jacob * flush it out to the request queue. 14164fd13c1bSMatt Jacob */ 14174fd13c1bSMatt Jacob ISP_TDQE(isp, "dma_tgt_fc", curi, cto); 14184fd13c1bSMatt Jacob isp_put_ctio(isp, cto, oqe); 14194fd13c1bSMatt Jacob if (nth_ctio != 0) { 14204fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, curi, 14214fd13c1bSMatt Jacob QENTRY_LEN); 14224fd13c1bSMatt Jacob } 14234fd13c1bSMatt Jacob curi = ISP_NXT_QENTRY(curi, RQUEST_QUEUE_LEN(isp)); 14244fd13c1bSMatt Jacob 14254fd13c1bSMatt Jacob /* 14264fd13c1bSMatt Jacob * Reset some fields in the CTIO so we can reuse 14274fd13c1bSMatt Jacob * for the next one we'll flush to the request 14284fd13c1bSMatt Jacob * queue. 14299e11e5beSMatt Jacob */ 14309e11e5beSMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 14319e11e5beSMatt Jacob cto->ct_header.rqs_entry_count = 1; 14329e11e5beSMatt Jacob cto->ct_header.rqs_flags = 0; 14339e11e5beSMatt Jacob cto->ct_status = 0; 14349e11e5beSMatt Jacob cto->ct_scsi_status = 0; 14359e11e5beSMatt Jacob cto->ct_xfrlen = 0; 14369e11e5beSMatt Jacob cto->ct_resid = 0; 14379e11e5beSMatt Jacob cto->ct_seg_count = 0; 143805fbcbb0SMatt Jacob MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg)); 14399e11e5beSMatt Jacob } 14409e11e5beSMatt Jacob } 14414fd13c1bSMatt Jacob *mp->nxtip = nxti; 14429e11e5beSMatt Jacob } 14439e11e5beSMatt Jacob 14449e11e5beSMatt Jacob static void 144505fbcbb0SMatt Jacob tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 14469e11e5beSMatt Jacob { 14479e11e5beSMatt Jacob mush_t *mp; 14484fd13c1bSMatt Jacob u_int8_t sense[QLTM_SENSELEN]; 14499e11e5beSMatt Jacob struct ccb_scsiio *csio; 14504fd13c1bSMatt Jacob struct ispsoftc *isp; 14519e11e5beSMatt Jacob struct isp_pcisoftc *pci; 14529e11e5beSMatt Jacob bus_dmamap_t *dp; 14534fd13c1bSMatt Jacob ct2_entry_t *cto, *qe; 14545f5aafe1SMatt Jacob u_int16_t scsi_status, send_status, send_sense, handle; 14554fd13c1bSMatt Jacob u_int16_t curi, nxti; 1456b96934e8SMatt Jacob int32_t resid; 14574fd13c1bSMatt Jacob int nth_ctio, nctios; 14589e11e5beSMatt Jacob 14599e11e5beSMatt Jacob mp = (mush_t *) arg; 14609e11e5beSMatt Jacob if (error) { 14619e11e5beSMatt Jacob mp->error = error; 14629e11e5beSMatt Jacob return; 14639e11e5beSMatt Jacob } 14649e11e5beSMatt Jacob 14654fd13c1bSMatt Jacob isp = mp->isp; 146665b024e1SMatt Jacob csio = mp->cmd_token; 146765b024e1SMatt Jacob cto = mp->rq; 14684fd13c1bSMatt Jacob curi = isp->isp_reqidx; 14694fd13c1bSMatt Jacob qe = (ct2_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi); 147065b024e1SMatt Jacob 147165b024e1SMatt Jacob if (nseg == 0) { 147265b024e1SMatt Jacob if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE1) { 14734fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 1474f7dddf8aSMatt Jacob "dma2_tgt_fc, a status CTIO2 without MODE1 " 1475f7dddf8aSMatt Jacob "set (0x%x)", cto->ct_flags); 147665b024e1SMatt Jacob mp->error = EINVAL; 147765b024e1SMatt Jacob return; 147865b024e1SMatt Jacob } 147965b024e1SMatt Jacob cto->ct_header.rqs_entry_count = 1; 148005fbcbb0SMatt Jacob cto->ct_header.rqs_seqno = 1; 14815f5aafe1SMatt Jacob /* ct_syshandle contains the handle set by caller */ 148265b024e1SMatt Jacob /* 148365b024e1SMatt Jacob * We preserve ct_lun, ct_iid, ct_rxid. We set the data 148465b024e1SMatt Jacob * flags to NO DATA and clear relative offset flags. 148565b024e1SMatt Jacob * We preserve the ct_resid and the response area. 148665b024e1SMatt Jacob */ 148765b024e1SMatt Jacob cto->ct_flags |= CT2_NO_DATA; 148805fbcbb0SMatt Jacob if (cto->ct_resid > 0) 14895d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; 149005fbcbb0SMatt Jacob else if (cto->ct_resid < 0) 14915d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER; 149265b024e1SMatt Jacob cto->ct_seg_count = 0; 149365b024e1SMatt Jacob cto->ct_reloff = 0; 14944fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 14955f5aafe1SMatt Jacob "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts " 1496d02373f1SMatt Jacob "0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun, 1497d02373f1SMatt Jacob cto->ct_iid, cto->ct_flags, cto->ct_status, 149865b024e1SMatt Jacob cto->rsp.m1.ct_scsi_status, cto->ct_resid); 14994fd13c1bSMatt Jacob isp_put_ctio2(isp, cto, qe); 15004fd13c1bSMatt Jacob ISP_TDQE(isp, "dma2_tgt_fc[no data]", curi, qe); 15019e11e5beSMatt Jacob return; 15029e11e5beSMatt Jacob } 15039e11e5beSMatt Jacob 150465b024e1SMatt Jacob if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE0) { 15054fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 1506f7dddf8aSMatt Jacob "dma2_tgt_fc, a data CTIO2 without MODE0 set " 1507f7dddf8aSMatt Jacob "(0x%x)", cto->ct_flags); 150865b024e1SMatt Jacob mp->error = EINVAL; 150965b024e1SMatt Jacob return; 151065b024e1SMatt Jacob } 151165b024e1SMatt Jacob 151265b024e1SMatt Jacob 151365b024e1SMatt Jacob nctios = nseg / ISP_RQDSEG_T2; 151465b024e1SMatt Jacob if (nseg % ISP_RQDSEG_T2) { 151565b024e1SMatt Jacob nctios++; 151665b024e1SMatt Jacob } 151765b024e1SMatt Jacob 15189e11e5beSMatt Jacob /* 151965b024e1SMatt Jacob * Save the handle, status, reloff, and residual. We'll reinsert the 152065b024e1SMatt Jacob * handle into the last CTIO2 we're going to send, and reinsert status 152165b024e1SMatt Jacob * and residual (and possibly sense data) if that's to be sent as well. 152265b024e1SMatt Jacob * 152365b024e1SMatt Jacob * We preserve ct_reloff and adjust it for each data CTIO2 we send past 152465b024e1SMatt Jacob * the first one. This is needed so that the FCP DATA IUs being sent 152565b024e1SMatt Jacob * out have the correct offset (they can arrive at the other end out 152665b024e1SMatt Jacob * of order). 15279e11e5beSMatt Jacob */ 152865b024e1SMatt Jacob 15295f5aafe1SMatt Jacob handle = cto->ct_syshandle; 15305f5aafe1SMatt Jacob cto->ct_syshandle = 0; 15315d571944SMatt Jacob send_status = (cto->ct_flags & CT2_SENDSTATUS) != 0; 153265b024e1SMatt Jacob 15335d571944SMatt Jacob if (send_status) { 15345d571944SMatt Jacob cto->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR); 15359e11e5beSMatt Jacob 153665b024e1SMatt Jacob /* 1537b96934e8SMatt Jacob * Preserve residual. 153865b024e1SMatt Jacob */ 1539b96934e8SMatt Jacob resid = cto->ct_resid; 154065b024e1SMatt Jacob 154165b024e1SMatt Jacob /* 154265b024e1SMatt Jacob * Save actual SCSI status. We'll reinsert the 154365b024e1SMatt Jacob * CT2_SNSLEN_VALID later if appropriate. 154465b024e1SMatt Jacob */ 154565b024e1SMatt Jacob scsi_status = cto->rsp.m0.ct_scsi_status & 0xff; 154665b024e1SMatt Jacob send_sense = cto->rsp.m0.ct_scsi_status & CT2_SNSLEN_VALID; 154765b024e1SMatt Jacob 154865b024e1SMatt Jacob /* 154965b024e1SMatt Jacob * If we're sending status and have a CHECK CONDTION and 155065b024e1SMatt Jacob * have sense data, we send one more CTIO2 with just the 155165b024e1SMatt Jacob * status and sense data. The upper layers have stashed 155265b024e1SMatt Jacob * the sense data in the dataseg structure for us. 155365b024e1SMatt Jacob */ 155465b024e1SMatt Jacob 155565b024e1SMatt Jacob if ((scsi_status & 0xf) == SCSI_STATUS_CHECK_COND && 155665b024e1SMatt Jacob send_sense) { 155765b024e1SMatt Jacob bcopy(cto->rsp.m0.ct_dataseg, sense, QLTM_SENSELEN); 155865b024e1SMatt Jacob nctios++; 155965b024e1SMatt Jacob } 156065b024e1SMatt Jacob } else { 1561b96934e8SMatt Jacob scsi_status = send_sense = resid = 0; 156265b024e1SMatt Jacob } 156365b024e1SMatt Jacob 1564b96934e8SMatt Jacob cto->ct_resid = 0; 156565b024e1SMatt Jacob cto->rsp.m0.ct_scsi_status = 0; 15665d571944SMatt Jacob MEMZERO(&cto->rsp, sizeof (cto->rsp)); 156765b024e1SMatt Jacob 15684fd13c1bSMatt Jacob pci = (struct isp_pcisoftc *)isp; 1569469b6b9eSMatt Jacob dp = &pci->dmaps[isp_handle_index(handle)]; 15709e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 15719e11e5beSMatt Jacob bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 15729e11e5beSMatt Jacob } else { 15739e11e5beSMatt Jacob bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 15749e11e5beSMatt Jacob } 15759e11e5beSMatt Jacob 15764fd13c1bSMatt Jacob nxti = *mp->nxtip; 15774fd13c1bSMatt Jacob 15784fd13c1bSMatt Jacob for (nth_ctio = 0; nth_ctio < nctios; nth_ctio++) { 15794fd13c1bSMatt Jacob u_int32_t oxfrlen; 15804fd13c1bSMatt Jacob int seglim; 15819e11e5beSMatt Jacob 15829e11e5beSMatt Jacob seglim = nseg; 158365b024e1SMatt Jacob if (seglim) { 15844fd13c1bSMatt Jacob int seg; 15859e11e5beSMatt Jacob if (seglim > ISP_RQDSEG_T2) 15869e11e5beSMatt Jacob seglim = ISP_RQDSEG_T2; 15879e11e5beSMatt Jacob for (seg = 0; seg < seglim; seg++) { 158865b024e1SMatt Jacob cto->rsp.m0.ct_dataseg[seg].ds_base = 158965b024e1SMatt Jacob dm_segs->ds_addr; 159065b024e1SMatt Jacob cto->rsp.m0.ct_dataseg[seg].ds_count = 159165b024e1SMatt Jacob dm_segs->ds_len; 15929e11e5beSMatt Jacob cto->rsp.m0.ct_xfrlen += dm_segs->ds_len; 15939e11e5beSMatt Jacob dm_segs++; 15949e11e5beSMatt Jacob } 15959e11e5beSMatt Jacob cto->ct_seg_count = seg; 15964fd13c1bSMatt Jacob oxfrlen = cto->rsp.m0.ct_xfrlen; 15979e11e5beSMatt Jacob } else { 159865b024e1SMatt Jacob /* 159965b024e1SMatt Jacob * This case should only happen when we're sending a 160065b024e1SMatt Jacob * synthesized MODE1 final status with sense data. 160165b024e1SMatt Jacob */ 160265b024e1SMatt Jacob if (send_sense == 0) { 16034fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 1604f7dddf8aSMatt Jacob "dma2_tgt_fc ran out of segments, " 1605f7dddf8aSMatt Jacob "no SENSE DATA"); 160665b024e1SMatt Jacob mp->error = EINVAL; 160765b024e1SMatt Jacob return; 160865b024e1SMatt Jacob } 16094fd13c1bSMatt Jacob oxfrlen = 0; 16109e11e5beSMatt Jacob } 16119e11e5beSMatt Jacob 16124fd13c1bSMatt Jacob 16139e11e5beSMatt Jacob /* 161465b024e1SMatt Jacob * At this point, the fields ct_lun, ct_iid, ct_rxid, 161565b024e1SMatt Jacob * ct_timeout have been carried over unchanged from what 161665b024e1SMatt Jacob * our caller had set. 161765b024e1SMatt Jacob * 161865b024e1SMatt Jacob * The field ct_reloff is either what the caller set, or 161965b024e1SMatt Jacob * what we've added to below. 162065b024e1SMatt Jacob * 162165b024e1SMatt Jacob * The dataseg fields and the seg_count fields we just got 162265b024e1SMatt Jacob * through setting. The data direction we've preserved all 162365b024e1SMatt Jacob * along and only clear it if we're sending a MODE1 status 162465b024e1SMatt Jacob * as the last CTIO. 162565b024e1SMatt Jacob * 162665b024e1SMatt Jacob */ 162765b024e1SMatt Jacob 16284fd13c1bSMatt Jacob if (nth_ctio == nctios - 1) { 162965b024e1SMatt Jacob /* 163065b024e1SMatt Jacob * We're the last in a sequence of CTIO2s, so mark this 163165b024e1SMatt Jacob * CTIO2 and save the handle to the CCB such that when 163265b024e1SMatt Jacob * this CTIO2 completes we can free dma resources and 16339e11e5beSMatt Jacob * do whatever else we need to do to finish the rest 16349e11e5beSMatt Jacob * of the command. 16359e11e5beSMatt Jacob */ 163665b024e1SMatt Jacob 16375f5aafe1SMatt Jacob cto->ct_syshandle = handle; 163865b024e1SMatt Jacob cto->ct_header.rqs_seqno = 1; 163965b024e1SMatt Jacob 164065b024e1SMatt Jacob if (send_status) { 16415d571944SMatt Jacob /* 16425d571944SMatt Jacob * Get 'real' residual and set flags based 16435d571944SMatt Jacob * on it. 16445d571944SMatt Jacob */ 1645b96934e8SMatt Jacob cto->ct_resid = resid; 164665b024e1SMatt Jacob if (send_sense) { 16475d571944SMatt Jacob MEMCPY(cto->rsp.m1.ct_resp, sense, 164865b024e1SMatt Jacob QLTM_SENSELEN); 164965b024e1SMatt Jacob cto->rsp.m1.ct_senselen = 165065b024e1SMatt Jacob QLTM_SENSELEN; 165165b024e1SMatt Jacob scsi_status |= CT2_SNSLEN_VALID; 165265b024e1SMatt Jacob cto->rsp.m1.ct_scsi_status = 165365b024e1SMatt Jacob scsi_status; 165465b024e1SMatt Jacob cto->ct_flags &= CT2_FLAG_MMASK; 165565b024e1SMatt Jacob cto->ct_flags |= CT2_FLAG_MODE1 | 16565d571944SMatt Jacob CT2_NO_DATA | CT2_SENDSTATUS | 16575d571944SMatt Jacob CT2_CCINCR; 16585d571944SMatt Jacob if (cto->ct_resid > 0) 16595d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= 16605d571944SMatt Jacob CT2_DATA_UNDER; 16615d571944SMatt Jacob else if (cto->ct_resid < 0) 16625d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= 16635d571944SMatt Jacob CT2_DATA_OVER; 166465b024e1SMatt Jacob } else { 166565b024e1SMatt Jacob cto->rsp.m0.ct_scsi_status = 166665b024e1SMatt Jacob scsi_status; 16675d571944SMatt Jacob cto->ct_flags |= 16685d571944SMatt Jacob CT2_SENDSTATUS | CT2_CCINCR; 166905fbcbb0SMatt Jacob if (cto->ct_resid > 0) 16705d571944SMatt Jacob cto->rsp.m0.ct_scsi_status |= 16715d571944SMatt Jacob CT2_DATA_UNDER; 167205fbcbb0SMatt Jacob else if (cto->ct_resid < 0) 16735d571944SMatt Jacob cto->rsp.m0.ct_scsi_status |= 16745d571944SMatt Jacob CT2_DATA_OVER; 16755d571944SMatt Jacob } 167665b024e1SMatt Jacob } 16774fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 16785f5aafe1SMatt Jacob "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x" 1679d02373f1SMatt Jacob " ssts 0x%x res %d", cto->ct_rxid, 168065b024e1SMatt Jacob csio->ccb_h.target_lun, (int) cto->ct_iid, 168142426921SMatt Jacob cto->ct_flags, cto->ct_status, 168265b024e1SMatt Jacob cto->rsp.m1.ct_scsi_status, cto->ct_resid); 16834fd13c1bSMatt Jacob isp_put_ctio2(isp, cto, qe); 16844fd13c1bSMatt Jacob ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe); 16854fd13c1bSMatt Jacob if (nctios > 1) { 16864fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, 16874fd13c1bSMatt Jacob curi, QENTRY_LEN); 16884fd13c1bSMatt Jacob } 16899e11e5beSMatt Jacob } else { 16904fd13c1bSMatt Jacob ct2_entry_t *oqe = qe; 169165b024e1SMatt Jacob 169265b024e1SMatt Jacob /* 169365b024e1SMatt Jacob * Make sure handle fields are clean 169465b024e1SMatt Jacob */ 16955f5aafe1SMatt Jacob cto->ct_syshandle = 0; 16969e11e5beSMatt Jacob cto->ct_header.rqs_seqno = 0; 16974fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 16985f5aafe1SMatt Jacob "CTIO2[%x] lun %d->iid%d flgs 0x%x", 1699d02373f1SMatt Jacob cto->ct_rxid, csio->ccb_h.target_lun, 1700d02373f1SMatt Jacob (int) cto->ct_iid, cto->ct_flags); 170165b024e1SMatt Jacob /* 17024fd13c1bSMatt Jacob * Get a new CTIO2 entry from the request queue. 170365b024e1SMatt Jacob */ 17044fd13c1bSMatt Jacob qe = (ct2_entry_t *) 17054fd13c1bSMatt Jacob ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 17064fd13c1bSMatt Jacob nxti = ISP_NXT_QENTRY(nxti, RQUEST_QUEUE_LEN(isp)); 17074fd13c1bSMatt Jacob if (nxti == mp->optr) { 17084fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGWARN, 1709f7dddf8aSMatt Jacob "Queue Overflow in dma2_tgt_fc"); 17109e11e5beSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 17119e11e5beSMatt Jacob return; 17129e11e5beSMatt Jacob } 171365b024e1SMatt Jacob 17149e11e5beSMatt Jacob /* 17154fd13c1bSMatt Jacob * Now that we're done with the old CTIO2, 17164fd13c1bSMatt Jacob * flush it out to the request queue. 17174fd13c1bSMatt Jacob */ 17184fd13c1bSMatt Jacob ISP_TDQE(isp, "tdma_mkfc", curi, cto); 17194fd13c1bSMatt Jacob isp_put_ctio2(isp, cto, oqe); 17204fd13c1bSMatt Jacob if (nth_ctio != 0) { 17214fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, curi, 17224fd13c1bSMatt Jacob QENTRY_LEN); 17234fd13c1bSMatt Jacob } 17244fd13c1bSMatt Jacob curi = ISP_NXT_QENTRY(curi, RQUEST_QUEUE_LEN(isp)); 17254fd13c1bSMatt Jacob 17264fd13c1bSMatt Jacob /* 17274fd13c1bSMatt Jacob * Reset some fields in the CTIO2 so we can reuse 17284fd13c1bSMatt Jacob * for the next one we'll flush to the request 17294fd13c1bSMatt Jacob * queue. 17309e11e5beSMatt Jacob */ 17319e11e5beSMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 17329e11e5beSMatt Jacob cto->ct_header.rqs_entry_count = 1; 17339e11e5beSMatt Jacob cto->ct_header.rqs_flags = 0; 17349e11e5beSMatt Jacob cto->ct_status = 0; 17359e11e5beSMatt Jacob cto->ct_resid = 0; 17369e11e5beSMatt Jacob cto->ct_seg_count = 0; 173765b024e1SMatt Jacob /* 173865b024e1SMatt Jacob * Adjust the new relative offset by the amount which 173965b024e1SMatt Jacob * is recorded in the data segment of the old CTIO2 we 174065b024e1SMatt Jacob * just finished filling out. 174165b024e1SMatt Jacob */ 17424fd13c1bSMatt Jacob cto->ct_reloff += oxfrlen; 17435d571944SMatt Jacob MEMZERO(&cto->rsp, sizeof (cto->rsp)); 17449e11e5beSMatt Jacob } 17459e11e5beSMatt Jacob } 17464fd13c1bSMatt Jacob *mp->nxtip = nxti; 17479e11e5beSMatt Jacob } 17489e11e5beSMatt Jacob #endif 17499e11e5beSMatt Jacob 1750126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int); 17519e11e5beSMatt Jacob 17529e11e5beSMatt Jacob static void 17539e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 17549e11e5beSMatt Jacob { 17559e11e5beSMatt Jacob mush_t *mp; 17564fd13c1bSMatt Jacob struct ispsoftc *isp; 17579e11e5beSMatt Jacob struct ccb_scsiio *csio; 17589e11e5beSMatt Jacob struct isp_pcisoftc *pci; 17599e11e5beSMatt Jacob bus_dmamap_t *dp; 17609e11e5beSMatt Jacob bus_dma_segment_t *eseg; 17619e11e5beSMatt Jacob ispreq_t *rq; 17629e11e5beSMatt Jacob int seglim, datalen; 17634fd13c1bSMatt Jacob u_int16_t nxti; 17649e11e5beSMatt Jacob 17659e11e5beSMatt Jacob mp = (mush_t *) arg; 17669e11e5beSMatt Jacob if (error) { 17679e11e5beSMatt Jacob mp->error = error; 17689e11e5beSMatt Jacob return; 17699e11e5beSMatt Jacob } 17709e11e5beSMatt Jacob 17719e11e5beSMatt Jacob if (nseg < 1) { 1772f7dddf8aSMatt Jacob isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg); 17739e11e5beSMatt Jacob mp->error = EFAULT; 17749e11e5beSMatt Jacob return; 17759e11e5beSMatt Jacob } 17769e11e5beSMatt Jacob csio = mp->cmd_token; 17774fd13c1bSMatt Jacob isp = mp->isp; 17789e11e5beSMatt Jacob rq = mp->rq; 17799e11e5beSMatt Jacob pci = (struct isp_pcisoftc *)mp->isp; 1780469b6b9eSMatt Jacob dp = &pci->dmaps[isp_handle_index(rq->req_handle)]; 17814fd13c1bSMatt Jacob nxti = *mp->nxtip; 17829e11e5beSMatt Jacob 17839e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 17849e11e5beSMatt Jacob bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 17859e11e5beSMatt Jacob } else { 17869e11e5beSMatt Jacob bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 17879e11e5beSMatt Jacob } 17889e11e5beSMatt Jacob 17899e11e5beSMatt Jacob datalen = XS_XFRLEN(csio); 17909e11e5beSMatt Jacob 17919e11e5beSMatt Jacob /* 17929e11e5beSMatt Jacob * We're passed an initial partially filled in entry that 17939e11e5beSMatt Jacob * has most fields filled in except for data transfer 17949e11e5beSMatt Jacob * related values. 17959e11e5beSMatt Jacob * 17969e11e5beSMatt Jacob * Our job is to fill in the initial request queue entry and 17979e11e5beSMatt Jacob * then to start allocating and filling in continuation entries 17989e11e5beSMatt Jacob * until we've covered the entire transfer. 17999e11e5beSMatt Jacob */ 18009e11e5beSMatt Jacob 18014fd13c1bSMatt Jacob if (IS_FC(isp)) { 1802d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 1803d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 18049e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 18059e11e5beSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_IN; 18069e11e5beSMatt Jacob } else { 18079e11e5beSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_OUT; 18089e11e5beSMatt Jacob } 1809d720e6d5SJustin T. Gibbs } else { 1810e142669aSMatt Jacob if (csio->cdb_len > 12) { 1811e142669aSMatt Jacob seglim = 0; 1812e142669aSMatt Jacob } else { 1813d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 1814e142669aSMatt Jacob } 18159e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 18169e11e5beSMatt Jacob rq->req_flags |= REQFLAG_DATA_IN; 18179e11e5beSMatt Jacob } else { 18189e11e5beSMatt Jacob rq->req_flags |= REQFLAG_DATA_OUT; 18199e11e5beSMatt Jacob } 1820d720e6d5SJustin T. Gibbs } 1821d720e6d5SJustin T. Gibbs 1822d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 1823d720e6d5SJustin T. Gibbs 1824d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 18254fd13c1bSMatt Jacob if (IS_FC(isp)) { 1826d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 1827d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 1828d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 1829d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 1830d720e6d5SJustin T. Gibbs dm_segs->ds_len; 1831d720e6d5SJustin T. Gibbs } else { 1832d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 1833d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 1834d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 1835d720e6d5SJustin T. Gibbs dm_segs->ds_len; 1836d720e6d5SJustin T. Gibbs } 1837d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 1838d720e6d5SJustin T. Gibbs rq->req_seg_count++; 1839d720e6d5SJustin T. Gibbs dm_segs++; 1840d720e6d5SJustin T. Gibbs } 1841d720e6d5SJustin T. Gibbs 1842d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 18434fd13c1bSMatt Jacob u_int16_t onxti; 18444fd13c1bSMatt Jacob ispcontreq_t local, *crq = &local, *cqe; 18454fd13c1bSMatt Jacob 18464fd13c1bSMatt Jacob cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti); 18474fd13c1bSMatt Jacob onxti = nxti; 18484fd13c1bSMatt Jacob nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp)); 18494fd13c1bSMatt Jacob if (nxti == mp->optr) { 18504fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++"); 18514873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1852d720e6d5SJustin T. Gibbs return; 1853d720e6d5SJustin T. Gibbs } 1854d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 18554fd13c1bSMatt Jacob MEMZERO((void *)crq, sizeof (*crq)); 1856d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 1857d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 1858d720e6d5SJustin T. Gibbs 1859d720e6d5SJustin T. Gibbs seglim = 0; 1860d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 1861d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 1862d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 1863d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 1864d720e6d5SJustin T. Gibbs dm_segs->ds_len; 1865d720e6d5SJustin T. Gibbs rq->req_seg_count++; 1866d720e6d5SJustin T. Gibbs dm_segs++; 1867d720e6d5SJustin T. Gibbs seglim++; 1868d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 1869d720e6d5SJustin T. Gibbs } 18704fd13c1bSMatt Jacob isp_put_cont_req(isp, crq, cqe); 18714fd13c1bSMatt Jacob MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN); 1872d720e6d5SJustin T. Gibbs } 18734fd13c1bSMatt Jacob *mp->nxtip = nxti; 1874d720e6d5SJustin T. Gibbs } 1875d720e6d5SJustin T. Gibbs 1876d720e6d5SJustin T. Gibbs static int 18779e11e5beSMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq, 18784fd13c1bSMatt Jacob u_int16_t *nxtip, u_int16_t optr) 1879d720e6d5SJustin T. Gibbs { 1880d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 18814fd13c1bSMatt Jacob ispreq_t *qep; 18820a5f7e8bSMatt Jacob bus_dmamap_t *dp = NULL; 1883d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1884126ec864SMatt Jacob void (*eptr)(void *, bus_dma_segment_t *, int, int); 1885d720e6d5SJustin T. Gibbs 18864fd13c1bSMatt Jacob qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx); 188765b024e1SMatt Jacob #ifdef ISP_TARGET_MODE 188865b024e1SMatt Jacob if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { 188965b024e1SMatt Jacob if (IS_FC(isp)) { 189005fbcbb0SMatt Jacob eptr = tdma_mkfc; 189165b024e1SMatt Jacob } else { 189205fbcbb0SMatt Jacob eptr = tdma_mk; 189365b024e1SMatt Jacob } 189405fbcbb0SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || 189505fbcbb0SMatt Jacob (csio->dxfer_len == 0)) { 189665b024e1SMatt Jacob mp = &mush; 189765b024e1SMatt Jacob mp->isp = isp; 189865b024e1SMatt Jacob mp->cmd_token = csio; 1899e9a2738aSMatt Jacob mp->rq = rq; /* really a ct_entry_t or ct2_entry_t */ 19004fd13c1bSMatt Jacob mp->nxtip = nxtip; 190165b024e1SMatt Jacob mp->optr = optr; 190265b024e1SMatt Jacob mp->error = 0; 190365b024e1SMatt Jacob (*eptr)(mp, NULL, 0, 0); 19044fd13c1bSMatt Jacob goto mbxsync; 190565b024e1SMatt Jacob } 190665b024e1SMatt Jacob } else 190765b024e1SMatt Jacob #endif 190865b024e1SMatt Jacob eptr = dma2; 190965b024e1SMatt Jacob 19104fd13c1bSMatt Jacob 191105fbcbb0SMatt Jacob if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || 191205fbcbb0SMatt Jacob (csio->dxfer_len == 0)) { 191342426921SMatt Jacob rq->req_seg_count = 1; 19144fd13c1bSMatt Jacob goto mbxsync; 191542426921SMatt Jacob } 191642426921SMatt Jacob 1917d720e6d5SJustin T. Gibbs /* 1918d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 19194873663cSMatt Jacob * the callback dma allocation that we have to use... 1920d720e6d5SJustin T. Gibbs */ 1921d720e6d5SJustin T. Gibbs mp = &mush; 1922d720e6d5SJustin T. Gibbs mp->isp = isp; 19239e11e5beSMatt Jacob mp->cmd_token = csio; 1924d720e6d5SJustin T. Gibbs mp->rq = rq; 19254fd13c1bSMatt Jacob mp->nxtip = nxtip; 1926d720e6d5SJustin T. Gibbs mp->optr = optr; 1927d720e6d5SJustin T. Gibbs mp->error = 0; 1928d720e6d5SJustin T. Gibbs 19299e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 19309e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { 19314873663cSMatt Jacob int error, s; 1932469b6b9eSMatt Jacob dp = &pci->dmaps[isp_handle_index(rq->req_handle)]; 1933d720e6d5SJustin T. Gibbs s = splsoftvm(); 1934d720e6d5SJustin T. Gibbs error = bus_dmamap_load(pci->parent_dmat, *dp, 19359e11e5beSMatt Jacob csio->data_ptr, csio->dxfer_len, eptr, mp, 0); 1936d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 1937d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 1938d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1939f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1940f7dddf8aSMatt Jacob "deferred dma allocation not supported"); 1941d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 19420a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 19436e5c5328SMatt Jacob isp_prt(isp, ISP_LOGERR, 19446e5c5328SMatt Jacob "error %d in dma mapping code", error); 19450a5f7e8bSMatt Jacob #endif 1946d720e6d5SJustin T. Gibbs mp->error = error; 1947d720e6d5SJustin T. Gibbs } 19484873663cSMatt Jacob splx(s); 1949d720e6d5SJustin T. Gibbs } else { 1950d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 1951d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 1952d720e6d5SJustin T. Gibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 1953d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 19549e11e5beSMatt Jacob (*eptr)(mp, &seg, 1, 0); 1955d720e6d5SJustin T. Gibbs } 1956d720e6d5SJustin T. Gibbs } else { 1957d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 1958d720e6d5SJustin T. Gibbs 19599e11e5beSMatt Jacob if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { 1960f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1961f7dddf8aSMatt Jacob "Physical segment pointers unsupported"); 1962d720e6d5SJustin T. Gibbs mp->error = EINVAL; 19639e11e5beSMatt Jacob } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { 1964f7dddf8aSMatt Jacob isp_prt(isp, ISP_LOGERR, 1965f7dddf8aSMatt Jacob "Virtual segment addresses unsupported"); 1966d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1967d720e6d5SJustin T. Gibbs } else { 1968d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 1969d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 19709e11e5beSMatt Jacob (*eptr)(mp, segs, csio->sglist_cnt, 0); 1971d720e6d5SJustin T. Gibbs } 1972d720e6d5SJustin T. Gibbs } 1973d720e6d5SJustin T. Gibbs if (mp->error) { 19744873663cSMatt Jacob int retval = CMD_COMPLETE; 19754873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 19764873663cSMatt Jacob retval = CMD_EAGAIN; 19774873663cSMatt Jacob } else if (mp->error == EFBIG) { 19780a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_TOO_BIG); 1979d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 19800a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_INVALID); 1981d720e6d5SJustin T. Gibbs } else { 19820a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 1983d720e6d5SJustin T. Gibbs } 19844873663cSMatt Jacob return (retval); 19850a5f7e8bSMatt Jacob } 19864fd13c1bSMatt Jacob mbxsync: 19874fd13c1bSMatt Jacob switch (rq->req_header.rqs_entry_type) { 19884fd13c1bSMatt Jacob case RQSTYPE_REQUEST: 19894fd13c1bSMatt Jacob isp_put_request(isp, rq, qep); 19904fd13c1bSMatt Jacob break; 19914fd13c1bSMatt Jacob case RQSTYPE_CMDONLY: 19924fd13c1bSMatt Jacob isp_put_extended_request(isp, (ispextreq_t *)rq, 19934fd13c1bSMatt Jacob (ispextreq_t *)qep); 19944fd13c1bSMatt Jacob break; 19954fd13c1bSMatt Jacob case RQSTYPE_T2RQS: 19964fd13c1bSMatt Jacob isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) qep); 19974fd13c1bSMatt Jacob break; 19980a5f7e8bSMatt Jacob } 19994873663cSMatt Jacob return (CMD_QUEUED); 2000d720e6d5SJustin T. Gibbs } 2001d720e6d5SJustin T. Gibbs 2002d720e6d5SJustin T. Gibbs static void 2003d8d5f2adSMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle) 2004d720e6d5SJustin T. Gibbs { 2005d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 2006469b6b9eSMatt Jacob bus_dmamap_t *dp = &pci->dmaps[isp_handle_index(handle)]; 2007a95ae193SMatt Jacob if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2008d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 2009d720e6d5SJustin T. Gibbs } else { 2010d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 2011d720e6d5SJustin T. Gibbs } 2012d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 2013d720e6d5SJustin T. Gibbs } 2014d720e6d5SJustin T. Gibbs 201565adb54cSMatt Jacob 201665adb54cSMatt Jacob static void 201717e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp) 201865adb54cSMatt Jacob { 201965adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 202065adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 2021469b6b9eSMatt Jacob /* and enable interrupts */ 2022469b6b9eSMatt Jacob ENABLE_INTS(isp); 202365adb54cSMatt Jacob } 202465adb54cSMatt Jacob 202565adb54cSMatt Jacob static void 2026d02373f1SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp, const char *msg) 202765adb54cSMatt Jacob { 202865adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 2029d02373f1SMatt Jacob if (msg) 20306e5c5328SMatt Jacob printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg); 20316e5c5328SMatt Jacob else 20326e5c5328SMatt Jacob printf("%s:\n", device_get_nameunit(isp->isp_dev)); 2033d02373f1SMatt Jacob if (IS_SCSI(isp)) 2034d02373f1SMatt Jacob printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1)); 2035d02373f1SMatt Jacob else 2036d02373f1SMatt Jacob printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR)); 2037d02373f1SMatt Jacob printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR), 2038d02373f1SMatt Jacob ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA)); 2039d02373f1SMatt Jacob printf("risc_hccr=%x\n", ISP_READ(isp, HCCR)); 2040d02373f1SMatt Jacob 2041d02373f1SMatt Jacob 2042d02373f1SMatt Jacob if (IS_SCSI(isp)) { 2043d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); 2044d02373f1SMatt Jacob printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n", 2045d02373f1SMatt Jacob ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS), 2046d02373f1SMatt Jacob ISP_READ(isp, CDMA_FIFO_STS)); 2047d02373f1SMatt Jacob printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n", 2048d02373f1SMatt Jacob ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS), 2049d02373f1SMatt Jacob ISP_READ(isp, DDMA_FIFO_STS)); 2050d02373f1SMatt Jacob printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n", 2051d02373f1SMatt Jacob ISP_READ(isp, SXP_INTERRUPT), 2052d02373f1SMatt Jacob ISP_READ(isp, SXP_GROSS_ERR), 2053d02373f1SMatt Jacob ISP_READ(isp, SXP_PINS_CTRL)); 2054d02373f1SMatt Jacob ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); 2055d02373f1SMatt Jacob } 2056d02373f1SMatt Jacob printf(" mbox regs: %x %x %x %x %x\n", 2057d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1), 2058d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3), 2059d02373f1SMatt Jacob ISP_READ(isp, OUTMAILBOX4)); 2060d02373f1SMatt Jacob printf(" PCI Status Command/Status=%x\n", 2061960f6939SMatt Jacob pci_read_config(pci->pci_dev, PCIR_COMMAND, 1)); 206265adb54cSMatt Jacob } 2063