1c3aac50fSPeter Wemm /* $FreeBSD$ */ 265adb54cSMatt Jacob /* 365adb54cSMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 465adb54cSMatt Jacob * FreeBSD Version. 565adb54cSMatt Jacob * 665adb54cSMatt Jacob *--------------------------------------- 7222bb542SMatt Jacob * Copyright (c) 1997, 1998, 1999 by Matthew Jacob 865adb54cSMatt Jacob * NASA/Ames Research Center 965adb54cSMatt Jacob * All rights reserved. 1065adb54cSMatt Jacob *--------------------------------------- 1165adb54cSMatt Jacob * 1265adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 1365adb54cSMatt Jacob * modification, are permitted provided that the following conditions 1465adb54cSMatt Jacob * are met: 1565adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 1665adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1765adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 1865adb54cSMatt Jacob * 2. Redistributions in binary form must reproduce the above copyright 1965adb54cSMatt Jacob * notice, this list of conditions and the following disclaimer in the 2065adb54cSMatt Jacob * documentation and/or other materials provided with the distribution. 2165adb54cSMatt Jacob * 3. The name of the author may not be used to endorse or promote products 2265adb54cSMatt Jacob * derived from this software without specific prior written permission. 2365adb54cSMatt Jacob * 2465adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2565adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2665adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2765adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2865adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2965adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3065adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3165adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3265adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3365adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3465adb54cSMatt Jacob * SUCH DAMAGE. 3565adb54cSMatt Jacob */ 3665adb54cSMatt Jacob #include <dev/isp/isp_freebsd.h> 3765adb54cSMatt Jacob #include <dev/isp/asm_pci.h> 38d720e6d5SJustin T. Gibbs #include <sys/malloc.h> 39d720e6d5SJustin T. Gibbs #include <vm/vm.h> 40d720e6d5SJustin T. Gibbs #include <vm/pmap.h> 41d720e6d5SJustin T. Gibbs 4265adb54cSMatt Jacob 4365adb54cSMatt Jacob #include <pci/pcireg.h> 4465adb54cSMatt Jacob #include <pci/pcivar.h> 4565adb54cSMatt Jacob 46d720e6d5SJustin T. Gibbs #include <machine/bus_memio.h> 47d720e6d5SJustin T. Gibbs #include <machine/bus_pio.h> 48d720e6d5SJustin T. Gibbs #include <machine/bus.h> 49a95ae193SMatt Jacob #include <machine/md_var.h> 50d59bd469SMatt Jacob 5165adb54cSMatt Jacob static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 5265adb54cSMatt Jacob static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 53d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 54d59bd469SMatt Jacob static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 55d59bd469SMatt Jacob static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 56d59bd469SMatt Jacob #endif 5765adb54cSMatt Jacob static int isp_pci_mbxdma __P((struct ispsoftc *)); 5865adb54cSMatt Jacob static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 5965adb54cSMatt Jacob ispreq_t *, u_int8_t *, u_int8_t)); 60d720e6d5SJustin T. Gibbs static void 61d720e6d5SJustin T. Gibbs isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 6265adb54cSMatt Jacob 6365adb54cSMatt Jacob static void isp_pci_reset1 __P((struct ispsoftc *)); 6465adb54cSMatt Jacob static void isp_pci_dumpregs __P((struct ispsoftc *)); 6565adb54cSMatt Jacob 66fed92c47SMatt Jacob #ifndef ISP_CODE_ORG 67fed92c47SMatt Jacob #define ISP_CODE_ORG 0x1000 68fed92c47SMatt Jacob #endif 69fed92c47SMatt Jacob #ifndef ISP_1040_RISC_CODE 70fed92c47SMatt Jacob #define ISP_1040_RISC_CODE NULL 71fed92c47SMatt Jacob #endif 72fed92c47SMatt Jacob #ifndef ISP_1080_RISC_CODE 73fed92c47SMatt Jacob #define ISP_1080_RISC_CODE NULL 74fed92c47SMatt Jacob #endif 75fed92c47SMatt Jacob #ifndef ISP_2100_RISC_CODE 76fed92c47SMatt Jacob #define ISP_2100_RISC_CODE NULL 77fed92c47SMatt Jacob #endif 78fed92c47SMatt Jacob #ifndef ISP_2200_RISC_CODE 79fed92c47SMatt Jacob #define ISP_2200_RISC_CODE NULL 80fed92c47SMatt Jacob #endif 81fed92c47SMatt Jacob 82d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 8365adb54cSMatt Jacob static struct ispmdvec mdvec = { 8465adb54cSMatt Jacob isp_pci_rd_reg, 8565adb54cSMatt Jacob isp_pci_wr_reg, 8665adb54cSMatt Jacob isp_pci_mbxdma, 8765adb54cSMatt Jacob isp_pci_dmasetup, 88d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 8965adb54cSMatt Jacob NULL, 9065adb54cSMatt Jacob isp_pci_reset1, 9165adb54cSMatt Jacob isp_pci_dumpregs, 92fed92c47SMatt Jacob ISP_1040_RISC_CODE, 93fed92c47SMatt Jacob 0, 9465adb54cSMatt Jacob ISP_CODE_ORG, 95a95ae193SMatt Jacob 0, 96285e230dSMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 97d720e6d5SJustin T. Gibbs 0 9865adb54cSMatt Jacob }; 99d59bd469SMatt Jacob #endif 10065adb54cSMatt Jacob 101d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 102d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 103d59bd469SMatt Jacob isp_pci_rd_reg_1080, 104d59bd469SMatt Jacob isp_pci_wr_reg_1080, 105d59bd469SMatt Jacob isp_pci_mbxdma, 106d59bd469SMatt Jacob isp_pci_dmasetup, 107d59bd469SMatt Jacob isp_pci_dmateardown, 108d59bd469SMatt Jacob NULL, 109d59bd469SMatt Jacob isp_pci_reset1, 110d59bd469SMatt Jacob isp_pci_dumpregs, 111fed92c47SMatt Jacob ISP_1080_RISC_CODE, 112fed92c47SMatt Jacob 0, 113fed92c47SMatt Jacob ISP_CODE_ORG, 114a95ae193SMatt Jacob 0, 115d59bd469SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 116d59bd469SMatt Jacob 0 117d59bd469SMatt Jacob }; 118d59bd469SMatt Jacob #endif 119d59bd469SMatt Jacob 120d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 12165adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 12265adb54cSMatt Jacob isp_pci_rd_reg, 12365adb54cSMatt Jacob isp_pci_wr_reg, 12465adb54cSMatt Jacob isp_pci_mbxdma, 12565adb54cSMatt Jacob isp_pci_dmasetup, 126d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 12765adb54cSMatt Jacob NULL, 12865adb54cSMatt Jacob isp_pci_reset1, 12965adb54cSMatt Jacob isp_pci_dumpregs, 130fed92c47SMatt Jacob ISP_2100_RISC_CODE, 131fed92c47SMatt Jacob 0, 132fed92c47SMatt Jacob ISP_CODE_ORG, 133a95ae193SMatt Jacob 0, 134a95ae193SMatt Jacob 0, 135d720e6d5SJustin T. Gibbs 0 13665adb54cSMatt Jacob }; 1375542fe4bSMatt Jacob #endif 138222bb542SMatt Jacob 13986cb5d6bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 140222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 141222bb542SMatt Jacob isp_pci_rd_reg, 142222bb542SMatt Jacob isp_pci_wr_reg, 143222bb542SMatt Jacob isp_pci_mbxdma, 144222bb542SMatt Jacob isp_pci_dmasetup, 145222bb542SMatt Jacob isp_pci_dmateardown, 146222bb542SMatt Jacob NULL, 147222bb542SMatt Jacob isp_pci_reset1, 148222bb542SMatt Jacob isp_pci_dumpregs, 149fed92c47SMatt Jacob ISP_2200_RISC_CODE, 150fed92c47SMatt Jacob 0, 151fed92c47SMatt Jacob ISP_CODE_ORG, 152a95ae193SMatt Jacob 0, 153222bb542SMatt Jacob 0, 154222bb542SMatt Jacob 0 155222bb542SMatt Jacob }; 156d59bd469SMatt Jacob #endif 15765adb54cSMatt Jacob 158d951bbcaSMatt Jacob #ifndef SCSI_ISP_PREFER_MEM_MAP 159d951bbcaSMatt Jacob #define SCSI_ISP_PREFER_MEM_MAP 0 160d951bbcaSMatt Jacob #endif 161d951bbcaSMatt Jacob 16265adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 16365adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 16465adb54cSMatt Jacob #endif 16565adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 16665adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 16765adb54cSMatt Jacob #endif 168d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 169d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 170d951bbcaSMatt Jacob #endif 171d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 172d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 173d951bbcaSMatt Jacob #endif 174d951bbcaSMatt Jacob 175d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 176d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 177d951bbcaSMatt Jacob #endif 178d951bbcaSMatt Jacob 179d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 180d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 181d951bbcaSMatt Jacob #endif 182d951bbcaSMatt Jacob 183d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 184d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 185d951bbcaSMatt Jacob #endif 186d951bbcaSMatt Jacob 187ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 188ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 189ab6d0040SMatt Jacob #endif 190ab6d0040SMatt Jacob 19165adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 19265adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 19365adb54cSMatt Jacob #endif 19465adb54cSMatt Jacob 19565adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 19665adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 19765adb54cSMatt Jacob #endif 19865adb54cSMatt Jacob 199d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 200d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 201d59bd469SMatt Jacob #endif 202d59bd469SMatt Jacob 203d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 204d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 205d59bd469SMatt Jacob #endif 20665adb54cSMatt Jacob 20765adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 20865adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 20965adb54cSMatt Jacob #endif 21065adb54cSMatt Jacob 211222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 212222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 213222bb542SMatt Jacob #endif 214222bb542SMatt Jacob 215d59bd469SMatt Jacob #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 216d59bd469SMatt Jacob 217d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 218d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 219d59bd469SMatt Jacob 220d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 221d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 222d59bd469SMatt Jacob 22365adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 22465adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 22565adb54cSMatt Jacob 226222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 227222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 228222bb542SMatt Jacob 22965adb54cSMatt Jacob #define IO_MAP_REG 0x10 23065adb54cSMatt Jacob #define MEM_MAP_REG 0x14 23165adb54cSMatt Jacob 232d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 233d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 23465adb54cSMatt Jacob 235222bb542SMatt Jacob static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type)); 23665adb54cSMatt Jacob static void isp_pci_attach __P((pcici_t config_d, int unit)); 23765adb54cSMatt Jacob 238d720e6d5SJustin T. Gibbs /* This distinguishing define is not right, but it does work */ 239a185f9b1SMatt Jacob #ifdef __alpha__ 240a185f9b1SMatt Jacob #define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 241a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 242a185f9b1SMatt Jacob #else 243a185f9b1SMatt Jacob #define IO_SPACE_MAPPING I386_BUS_SPACE_IO 244a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 245a185f9b1SMatt Jacob #endif 24665adb54cSMatt Jacob 24765adb54cSMatt Jacob struct isp_pcisoftc { 24865adb54cSMatt Jacob struct ispsoftc pci_isp; 24965adb54cSMatt Jacob pcici_t pci_id; 25065adb54cSMatt Jacob bus_space_tag_t pci_st; 25165adb54cSMatt Jacob bus_space_handle_t pci_sh; 252d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 253d720e6d5SJustin T. Gibbs bus_dma_tag_t parent_dmat; 254d720e6d5SJustin T. Gibbs bus_dma_tag_t cntrol_dmat; 255d720e6d5SJustin T. Gibbs bus_dmamap_t cntrol_dmap; 256a95ae193SMatt Jacob bus_dmamap_t *dmaps; 25765adb54cSMatt Jacob }; 25865adb54cSMatt Jacob 259d720e6d5SJustin T. Gibbs static u_long ispunit; 26065adb54cSMatt Jacob 26166235db5SEivind Eklund static struct pci_device isp_pci_driver = { 26265adb54cSMatt Jacob "isp", 26365adb54cSMatt Jacob isp_pci_probe, 26465adb54cSMatt Jacob isp_pci_attach, 265d720e6d5SJustin T. Gibbs &ispunit, 26665adb54cSMatt Jacob NULL 26765adb54cSMatt Jacob }; 26896b3554eSPeter Wemm COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver); 26965adb54cSMatt Jacob 27065adb54cSMatt Jacob 271222bb542SMatt Jacob static const char * 27217e318c6SMatt Jacob isp_pci_probe(pcici_t tag, pcidi_t type) 27365adb54cSMatt Jacob { 27465adb54cSMatt Jacob static int oneshot = 1; 27565adb54cSMatt Jacob char *x; 27665adb54cSMatt Jacob 27765adb54cSMatt Jacob switch (type) { 278d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 27965adb54cSMatt Jacob case PCI_QLOGIC_ISP: 280d59bd469SMatt Jacob x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 28165adb54cSMatt Jacob break; 282d59bd469SMatt Jacob #endif 283d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 284d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 285c6608df3SMatt Jacob x = "Qlogic ISP 1080 PCI SCSI Adapter"; 286c6608df3SMatt Jacob break; 287c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 288c6608df3SMatt Jacob x = "Qlogic ISP 1240 PCI SCSI Adapter"; 289d59bd469SMatt Jacob break; 290d59bd469SMatt Jacob #endif 291d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 29265adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 29365adb54cSMatt Jacob x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 29465adb54cSMatt Jacob break; 295d59bd469SMatt Jacob #endif 2965542fe4bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 2975542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 2985542fe4bSMatt Jacob x = "Qlogic ISP 2200 PCI FC-AL Adapter"; 2995542fe4bSMatt Jacob break; 3005542fe4bSMatt Jacob #endif 30165adb54cSMatt Jacob default: 30265adb54cSMatt Jacob return (NULL); 30365adb54cSMatt Jacob } 30465adb54cSMatt Jacob if (oneshot) { 30565adb54cSMatt Jacob oneshot = 0; 306a95ae193SMatt Jacob CFGPRINTF("Qlogic ISP Driver, FreeBSD Version %d.%d, " 307a95ae193SMatt Jacob "Core Version %d.%d\n", 308d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 309d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 31065adb54cSMatt Jacob } 31165adb54cSMatt Jacob return (x); 31265adb54cSMatt Jacob } 31365adb54cSMatt Jacob 31465adb54cSMatt Jacob static void 315222bb542SMatt Jacob isp_pci_attach(pcici_t cfid, int unit) 31665adb54cSMatt Jacob { 317222bb542SMatt Jacob int mapped, prefer_mem_map, bitmap; 318a185f9b1SMatt Jacob pci_port_t io_port; 319c6608df3SMatt Jacob u_int32_t data, linesz, psize, basetype; 32065adb54cSMatt Jacob struct isp_pcisoftc *pcs; 32165adb54cSMatt Jacob struct ispsoftc *isp; 32265adb54cSMatt Jacob vm_offset_t vaddr, paddr; 323c6608df3SMatt Jacob struct ispmdvec *mdvp; 324222bb542SMatt Jacob bus_size_t lim; 32565adb54cSMatt Jacob ISP_LOCKVAL_DECL; 32665adb54cSMatt Jacob 32765adb54cSMatt Jacob pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 32865adb54cSMatt Jacob if (pcs == NULL) { 3299bffbcd4SBruce Evans printf("isp%d: cannot allocate softc\n", unit); 33065adb54cSMatt Jacob return; 33165adb54cSMatt Jacob } 33265adb54cSMatt Jacob bzero(pcs, sizeof (struct isp_pcisoftc)); 33365adb54cSMatt Jacob 334222bb542SMatt Jacob /* 3359ba86737SMatt Jacob * Figure out if we're supposed to skip this one. 3369ba86737SMatt Jacob */ 3379ba86737SMatt Jacob if (getenv_int("isp_disable", &bitmap)) { 3389ba86737SMatt Jacob if (bitmap & (1 << unit)) { 3399ba86737SMatt Jacob printf("isp%d: not configuring\n", unit); 3409ba86737SMatt Jacob return; 3419ba86737SMatt Jacob } 3429ba86737SMatt Jacob } 3439ba86737SMatt Jacob 3449ba86737SMatt Jacob /* 345222bb542SMatt Jacob * Figure out which we should try first - memory mapping or i/o mapping? 346222bb542SMatt Jacob */ 347222bb542SMatt Jacob #if SCSI_ISP_PREFER_MEM_MAP == 1 348222bb542SMatt Jacob prefer_mem_map = 1; 349222bb542SMatt Jacob #else 350222bb542SMatt Jacob prefer_mem_map = 0; 351222bb542SMatt Jacob #endif 352222bb542SMatt Jacob bitmap = 0; 353222bb542SMatt Jacob if (getenv_int("isp_mem_map", &bitmap)) { 354222bb542SMatt Jacob if (bitmap & (1 << unit)) 355222bb542SMatt Jacob prefer_mem_map = 1; 356222bb542SMatt Jacob } 357222bb542SMatt Jacob bitmap = 0; 358222bb542SMatt Jacob if (getenv_int("isp_io_map", &bitmap)) { 359222bb542SMatt Jacob if (bitmap & (1 << unit)) 360222bb542SMatt Jacob prefer_mem_map = 0; 361222bb542SMatt Jacob } 362222bb542SMatt Jacob 36365adb54cSMatt Jacob vaddr = paddr = NULL; 36465adb54cSMatt Jacob mapped = 0; 365ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 366d951bbcaSMatt Jacob /* 367d951bbcaSMatt Jacob * Note that pci_conf_read is a 32 bit word aligned function. 368d951bbcaSMatt Jacob */ 369222bb542SMatt Jacob data = pci_conf_read(cfid, PCIR_COMMAND); 370222bb542SMatt Jacob if (prefer_mem_map) { 371222bb542SMatt Jacob if (data & PCI_COMMAND_MEM_ENABLE) { 372222bb542SMatt Jacob if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 373a185f9b1SMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 374a185f9b1SMatt Jacob pcs->pci_sh = vaddr; 37565adb54cSMatt Jacob mapped++; 37665adb54cSMatt Jacob } 37765adb54cSMatt Jacob } 378a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 379222bb542SMatt Jacob if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 380a185f9b1SMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 381a185f9b1SMatt Jacob pcs->pci_sh = io_port; 38265adb54cSMatt Jacob mapped++; 38365adb54cSMatt Jacob } 38465adb54cSMatt Jacob } 385222bb542SMatt Jacob } else { 386222bb542SMatt Jacob if (data & PCI_COMMAND_IO_ENABLE) { 387222bb542SMatt Jacob if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 388d951bbcaSMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 389d951bbcaSMatt Jacob pcs->pci_sh = io_port; 390d951bbcaSMatt Jacob mapped++; 391d951bbcaSMatt Jacob } 392d951bbcaSMatt Jacob } 393d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 394222bb542SMatt Jacob if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 395d951bbcaSMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 396d951bbcaSMatt Jacob pcs->pci_sh = vaddr; 397d951bbcaSMatt Jacob mapped++; 398d951bbcaSMatt Jacob } 399d951bbcaSMatt Jacob } 400222bb542SMatt Jacob } 40165adb54cSMatt Jacob if (mapped == 0) { 4029bffbcd4SBruce Evans printf("isp%d: unable to map any ports!\n", unit); 40365adb54cSMatt Jacob free(pcs, M_DEVBUF); 40465adb54cSMatt Jacob return; 40565adb54cSMatt Jacob } 406222bb542SMatt Jacob if (bootverbose) 40765adb54cSMatt Jacob printf("isp%d: using %s space register mapping\n", unit, 408a185f9b1SMatt Jacob pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 40965adb54cSMatt Jacob 410222bb542SMatt Jacob data = pci_conf_read(cfid, PCI_ID_REG); 411d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 412d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 413d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 414d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 415d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 416c6608df3SMatt Jacob /* 417c6608df3SMatt Jacob * GCC! 418c6608df3SMatt Jacob */ 419c6608df3SMatt Jacob mdvp = &mdvec; 420c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 421c6608df3SMatt Jacob psize = sizeof (sdparam); 422222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_32BIT; 423d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 42465adb54cSMatt Jacob if (data == PCI_QLOGIC_ISP) { 425c6608df3SMatt Jacob mdvp = &mdvec; 426c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 427c6608df3SMatt Jacob psize = sizeof (sdparam); 428222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_24BIT; 429d59bd469SMatt Jacob } 430d59bd469SMatt Jacob #endif 431d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 432c6608df3SMatt Jacob if (data == PCI_QLOGIC_ISP1080) { 433c6608df3SMatt Jacob mdvp = &mdvec_1080; 434c6608df3SMatt Jacob basetype = ISP_HA_SCSI_1080; 435c6608df3SMatt Jacob psize = sizeof (sdparam); 436c6608df3SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 437c6608df3SMatt Jacob ISP1080_DMA_REGS_OFF; 438c6608df3SMatt Jacob } 439c6608df3SMatt Jacob if (data == PCI_QLOGIC_ISP1240) { 440c6608df3SMatt Jacob mdvp = &mdvec_1080; 441c6608df3SMatt Jacob basetype = ISP_HA_SCSI_12X0; 442c6608df3SMatt Jacob psize = 2 * sizeof (sdparam); 443d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 444d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 445d59bd469SMatt Jacob } 446d59bd469SMatt Jacob #endif 447d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 448d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP2100) { 449c6608df3SMatt Jacob mdvp = &mdvec_2100; 450c6608df3SMatt Jacob basetype = ISP_HA_FC_2100; 451c6608df3SMatt Jacob psize = sizeof (fcparam); 452d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 453d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 454222bb542SMatt Jacob data = pci_conf_read(cfid, PCI_CLASS_REG); 455ab6d0040SMatt Jacob if ((data & 0xff) < 3) { 456ab6d0040SMatt Jacob /* 457ab6d0040SMatt Jacob * XXX: Need to get the actual revision 458ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 459ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 460ab6d0040SMatt Jacob * XXX; boards. 461ab6d0040SMatt Jacob */ 462ab6d0040SMatt Jacob linesz = 1; 463ab6d0040SMatt Jacob } 46465adb54cSMatt Jacob } 4655542fe4bSMatt Jacob #endif 4665542fe4bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 467222bb542SMatt Jacob if (data == PCI_QLOGIC_ISP2200) { 468222bb542SMatt Jacob mdvp = &mdvec_2200; 469222bb542SMatt Jacob basetype = ISP_HA_FC_2200; 470222bb542SMatt Jacob psize = sizeof (fcparam); 471222bb542SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 472222bb542SMatt Jacob PCI_MBOX_REGS2100_OFF; 473222bb542SMatt Jacob } 474d59bd469SMatt Jacob #endif 475c6608df3SMatt Jacob isp = &pcs->pci_isp; 476c6608df3SMatt Jacob isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT); 477c6608df3SMatt Jacob if (isp->isp_param == NULL) { 478c6608df3SMatt Jacob printf("isp%d: cannot allocate parameter data\n", unit); 479c6608df3SMatt Jacob return; 480c6608df3SMatt Jacob } 481c6608df3SMatt Jacob bzero(isp->isp_param, psize); 482c6608df3SMatt Jacob isp->isp_mdvec = mdvp; 483c6608df3SMatt Jacob isp->isp_type = basetype; 484c6608df3SMatt Jacob (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 485c6608df3SMatt Jacob isp->isp_osinfo.unit = unit; 48665adb54cSMatt Jacob 487d951bbcaSMatt Jacob ISP_LOCK(isp); 488ab6d0040SMatt Jacob 489d951bbcaSMatt Jacob /* 490d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 491d951bbcaSMatt Jacob * are set. 492d951bbcaSMatt Jacob */ 493222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_COMMAND, 2); 494d951bbcaSMatt Jacob data |= PCIM_CMD_SEREN | 495d951bbcaSMatt Jacob PCIM_CMD_PERRESPEN | 496d951bbcaSMatt Jacob PCIM_CMD_BUSMASTEREN | 497d951bbcaSMatt Jacob PCIM_CMD_INVEN; 498222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_COMMAND, 2, data); 499ab6d0040SMatt Jacob 500d951bbcaSMatt Jacob /* 501222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 502d951bbcaSMatt Jacob */ 503222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_CACHELNSZ, 1); 504ab6d0040SMatt Jacob if (data != linesz) { 505d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 506a95ae193SMatt Jacob CFGPRINTF("%s: set PCI line size to %d\n", isp->isp_name, data); 507222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_CACHELNSZ, data, 1); 508d951bbcaSMatt Jacob } 509ab6d0040SMatt Jacob 510d951bbcaSMatt Jacob /* 511d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 512d951bbcaSMatt Jacob */ 513222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_LATTIMER, 1); 514d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 515d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 516a95ae193SMatt Jacob CFGPRINTF("%s: set PCI latency to %d\n", isp->isp_name, data); 517222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_LATTIMER, data, 1); 518d951bbcaSMatt Jacob } 519ab6d0040SMatt Jacob 520ab6d0040SMatt Jacob /* 521ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 522ab6d0040SMatt Jacob */ 523222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_ROMADDR, 4); 524ab6d0040SMatt Jacob data &= ~1; 525222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_ROMADDR, data, 4); 526d951bbcaSMatt Jacob ISP_UNLOCK(isp); 527d951bbcaSMatt Jacob 528086646f7SJustin T. Gibbs if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 529222bb542SMatt Jacob BUS_SPACE_MAXADDR, NULL, NULL, lim + 1, 530222bb542SMatt Jacob 255, lim, 0, &pcs->parent_dmat) != 0) { 531d720e6d5SJustin T. Gibbs printf("%s: could not create master dma tag\n", isp->isp_name); 532d720e6d5SJustin T. Gibbs free(pcs, M_DEVBUF); 533d720e6d5SJustin T. Gibbs return; 534d720e6d5SJustin T. Gibbs } 535222bb542SMatt Jacob if (pci_map_int(cfid, (void (*)(void *))isp_intr, 53665adb54cSMatt Jacob (void *)isp, &IMASK) == 0) { 5379bffbcd4SBruce Evans printf("%s: could not map interrupt\n", isp->isp_name); 53865adb54cSMatt Jacob free(pcs, M_DEVBUF); 53965adb54cSMatt Jacob return; 54065adb54cSMatt Jacob } 54165adb54cSMatt Jacob 542222bb542SMatt Jacob pcs->pci_id = cfid; 543d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_FWLOAD_MASK 544d951bbcaSMatt Jacob if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 545d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 546d951bbcaSMatt Jacob #endif 547222bb542SMatt Jacob if (getenv_int("isp_no_fwload", &bitmap)) { 548222bb542SMatt Jacob if (bitmap & (1 << unit)) 549222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 550222bb542SMatt Jacob } 551222bb542SMatt Jacob if (getenv_int("isp_fwload", &bitmap)) { 552222bb542SMatt Jacob if (bitmap & (1 << unit)) 553222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NORELOAD; 554222bb542SMatt Jacob } 555222bb542SMatt Jacob 556d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_NVRAM_MASK 557ab6d0040SMatt Jacob if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 558ab6d0040SMatt Jacob printf("%s: ignoring NVRAM\n", isp->isp_name); 559d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 560ab6d0040SMatt Jacob } 561d951bbcaSMatt Jacob #endif 562222bb542SMatt Jacob if (getenv_int("isp_no_nvram", &bitmap)) { 563222bb542SMatt Jacob if (bitmap & (1 << unit)) 564222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 565222bb542SMatt Jacob } 566222bb542SMatt Jacob if (getenv_int("isp_nvram", &bitmap)) { 567222bb542SMatt Jacob if (bitmap & (1 << unit)) 568222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NONVRAM; 569222bb542SMatt Jacob } 570222bb542SMatt Jacob 571222bb542SMatt Jacob #ifdef SCSI_ISP_FCDUPLEX 572222bb542SMatt Jacob if (IS_FC(isp)) { 573222bb542SMatt Jacob if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) { 574222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 575222bb542SMatt Jacob } 576222bb542SMatt Jacob } 577222bb542SMatt Jacob #endif 578222bb542SMatt Jacob if (getenv_int("isp_fcduplex", &bitmap)) { 579222bb542SMatt Jacob if (bitmap & (1 << unit)) 580222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 581222bb542SMatt Jacob } 582222bb542SMatt Jacob if (getenv_int("isp_no_fcduplex", &bitmap)) { 583222bb542SMatt Jacob if (bitmap & (1 << unit)) 584222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX; 585222bb542SMatt Jacob } 586222bb542SMatt Jacob 587222bb542SMatt Jacob if (getenv_int("isp_seed", &isp->isp_osinfo.seed)) { 588222bb542SMatt Jacob isp->isp_osinfo.seed <<= 8; 589222bb542SMatt Jacob isp->isp_osinfo.seed += (unit + 1); 590222bb542SMatt Jacob } else { 591222bb542SMatt Jacob /* 592222bb542SMatt Jacob * poor man's attempt at pseudo randomness. 593222bb542SMatt Jacob */ 594d009ccfaSBruce Evans long i = (intptr_t) isp; 595222bb542SMatt Jacob 596222bb542SMatt Jacob i >>= 5; 597222bb542SMatt Jacob i &= 0x7; 598222bb542SMatt Jacob 599222bb542SMatt Jacob /* 600222bb542SMatt Jacob * This isn't very random, but it's the best we can do for 601222bb542SMatt Jacob * the real edge case of cards that don't have WWNs. 602222bb542SMatt Jacob */ 603222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->bus) << 16; 604222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->slot) << 8; 605222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->func); 606222bb542SMatt Jacob while (version[i]) 607222bb542SMatt Jacob isp->isp_osinfo.seed += (int) version[i++]; 608222bb542SMatt Jacob isp->isp_osinfo.seed <<= 8; 609222bb542SMatt Jacob isp->isp_osinfo.seed += (unit + 1); 610222bb542SMatt Jacob } 611a95ae193SMatt Jacob (void) getenv_int("isp_debug", &isp_debug); 612d720e6d5SJustin T. Gibbs ISP_LOCK(isp); 61365adb54cSMatt Jacob isp_reset(isp); 61465adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 615222bb542SMatt Jacob (void) pci_unmap_int(cfid); 616d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 61765adb54cSMatt Jacob free(pcs, M_DEVBUF); 61865adb54cSMatt Jacob return; 61965adb54cSMatt Jacob } 62065adb54cSMatt Jacob isp_init(isp); 62165adb54cSMatt Jacob if (isp->isp_state != ISP_INITSTATE) { 622d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 623222bb542SMatt Jacob if (IS_SCSI(isp)) { 62465adb54cSMatt Jacob isp_uninit(isp); 625222bb542SMatt Jacob (void) pci_unmap_int(cfid); /* Does nothing */ 626c6608df3SMatt Jacob ISP_UNLOCK(isp); 62765adb54cSMatt Jacob free(pcs, M_DEVBUF); 628c6608df3SMatt Jacob return; 629d59bd469SMatt Jacob } 63065adb54cSMatt Jacob } 63165adb54cSMatt Jacob isp_attach(isp); 63265adb54cSMatt Jacob if (isp->isp_state != ISP_RUNSTATE) { 633d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 63492c49d78SMatt Jacob if (IS_SCSI(isp)) { 63565adb54cSMatt Jacob isp_uninit(isp); 636222bb542SMatt Jacob (void) pci_unmap_int(cfid); /* Does nothing */ 637c6608df3SMatt Jacob ISP_UNLOCK(isp); 63865adb54cSMatt Jacob free(pcs, M_DEVBUF); 639c6608df3SMatt Jacob return; 64065adb54cSMatt Jacob } 641d59bd469SMatt Jacob } 642d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 643e37c0455SDoug Rabson #ifdef __alpha__ 644d951bbcaSMatt Jacob /* 645d951bbcaSMatt Jacob * THIS SHOULD NOT HAVE TO BE HERE 646d951bbcaSMatt Jacob */ 647222bb542SMatt Jacob alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim); 648e37c0455SDoug Rabson #endif 64965adb54cSMatt Jacob } 65065adb54cSMatt Jacob 65165adb54cSMatt Jacob static u_int16_t 652d59bd469SMatt Jacob isp_pci_rd_reg(isp, regoff) 653d59bd469SMatt Jacob struct ispsoftc *isp; 654d59bd469SMatt Jacob int regoff; 65565adb54cSMatt Jacob { 65665adb54cSMatt Jacob u_int16_t rv; 65765adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 658d59bd469SMatt Jacob int offset, oldconf = 0; 65965adb54cSMatt Jacob 660d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 66165adb54cSMatt Jacob /* 66265adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 66365adb54cSMatt Jacob */ 664d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 665d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 66665adb54cSMatt Jacob } 667d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 668d59bd469SMatt Jacob offset += (regoff & 0xff); 66965adb54cSMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 670d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 671d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 67265adb54cSMatt Jacob } 67365adb54cSMatt Jacob return (rv); 67465adb54cSMatt Jacob } 67565adb54cSMatt Jacob 67665adb54cSMatt Jacob static void 677d59bd469SMatt Jacob isp_pci_wr_reg(isp, regoff, val) 678d59bd469SMatt Jacob struct ispsoftc *isp; 679d59bd469SMatt Jacob int regoff; 680d59bd469SMatt Jacob u_int16_t val; 68165adb54cSMatt Jacob { 68265adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 683d59bd469SMatt Jacob int offset, oldconf = 0; 684d59bd469SMatt Jacob 685d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 68665adb54cSMatt Jacob /* 68765adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 68865adb54cSMatt Jacob */ 689d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 690d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 69165adb54cSMatt Jacob } 692d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 693d59bd469SMatt Jacob offset += (regoff & 0xff); 69465adb54cSMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 695d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 696d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 69765adb54cSMatt Jacob } 69865adb54cSMatt Jacob } 69965adb54cSMatt Jacob 700d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 701d59bd469SMatt Jacob static u_int16_t 702d59bd469SMatt Jacob isp_pci_rd_reg_1080(isp, regoff) 703d59bd469SMatt Jacob struct ispsoftc *isp; 704d59bd469SMatt Jacob int regoff; 705d59bd469SMatt Jacob { 706d59bd469SMatt Jacob u_int16_t rv; 707d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 708d59bd469SMatt Jacob int offset, oc = 0; 709d59bd469SMatt Jacob 710d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 711d59bd469SMatt Jacob /* 712d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 713d59bd469SMatt Jacob */ 714d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 715d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 716d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 717d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 718d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 719d59bd469SMatt Jacob } 720d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 721d59bd469SMatt Jacob offset += (regoff & 0xff); 722d59bd469SMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 723d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 724d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 725d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 726d59bd469SMatt Jacob } 727d59bd469SMatt Jacob return (rv); 728d59bd469SMatt Jacob } 729d59bd469SMatt Jacob 730d59bd469SMatt Jacob static void 731d59bd469SMatt Jacob isp_pci_wr_reg_1080(isp, regoff, val) 732d59bd469SMatt Jacob struct ispsoftc *isp; 733d59bd469SMatt Jacob int regoff; 734d59bd469SMatt Jacob u_int16_t val; 735d59bd469SMatt Jacob { 736d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 737d59bd469SMatt Jacob int offset, oc = 0; 738d59bd469SMatt Jacob 739d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 740d59bd469SMatt Jacob /* 741d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 742d59bd469SMatt Jacob */ 743d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 744d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 745d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 746d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 747d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 748d59bd469SMatt Jacob } 749d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 750d59bd469SMatt Jacob offset += (regoff & 0xff); 751d59bd469SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 752d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 753d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 754d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 755d59bd469SMatt Jacob } 756d59bd469SMatt Jacob } 757d59bd469SMatt Jacob #endif 758d59bd469SMatt Jacob 759d59bd469SMatt Jacob 760d720e6d5SJustin T. Gibbs static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 761d720e6d5SJustin T. Gibbs static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 762d720e6d5SJustin T. Gibbs static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 763d720e6d5SJustin T. Gibbs 764222bb542SMatt Jacob struct imush { 765222bb542SMatt Jacob struct ispsoftc *isp; 766222bb542SMatt Jacob int error; 767222bb542SMatt Jacob }; 768222bb542SMatt Jacob 769d720e6d5SJustin T. Gibbs static void 77017e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 771d720e6d5SJustin T. Gibbs { 772222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 773222bb542SMatt Jacob if (error) { 774222bb542SMatt Jacob imushp->error = error; 775222bb542SMatt Jacob } else { 776222bb542SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 777222bb542SMatt Jacob } 778d720e6d5SJustin T. Gibbs } 779d720e6d5SJustin T. Gibbs 780d720e6d5SJustin T. Gibbs static void 78117e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 782d720e6d5SJustin T. Gibbs { 783222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 784222bb542SMatt Jacob if (error) { 785222bb542SMatt Jacob imushp->error = error; 786222bb542SMatt Jacob } else { 787222bb542SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 788222bb542SMatt Jacob } 789d720e6d5SJustin T. Gibbs } 790d720e6d5SJustin T. Gibbs 791d720e6d5SJustin T. Gibbs static void 79217e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 793d720e6d5SJustin T. Gibbs { 794222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 795222bb542SMatt Jacob if (error) { 796222bb542SMatt Jacob imushp->error = error; 797222bb542SMatt Jacob } else { 798222bb542SMatt Jacob fcparam *fcp = imushp->isp->isp_param; 799d720e6d5SJustin T. Gibbs fcp->isp_scdma = segs->ds_addr; 800d720e6d5SJustin T. Gibbs } 801222bb542SMatt Jacob } 802d720e6d5SJustin T. Gibbs 803d720e6d5SJustin T. Gibbs static int 80417e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 805d720e6d5SJustin T. Gibbs { 806d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 807d720e6d5SJustin T. Gibbs caddr_t base; 808d720e6d5SJustin T. Gibbs u_int32_t len; 809d720e6d5SJustin T. Gibbs int i, error; 810222bb542SMatt Jacob bus_size_t lim; 811222bb542SMatt Jacob struct imush im; 812222bb542SMatt Jacob 813222bb542SMatt Jacob 814a95ae193SMatt Jacob /* 815a95ae193SMatt Jacob * Already been here? If so, leave... 816a95ae193SMatt Jacob */ 817a95ae193SMatt Jacob if (isp->isp_rquest) { 818a95ae193SMatt Jacob return (0); 819a95ae193SMatt Jacob } 820a95ae193SMatt Jacob 821a95ae193SMatt Jacob len = sizeof (ISP_SCSI_XFER_T **) * isp->isp_maxcmds; 822a95ae193SMatt Jacob isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(len, M_DEVBUF, M_WAITOK); 823a95ae193SMatt Jacob if (isp->isp_xflist == NULL) { 824a95ae193SMatt Jacob printf("%s: can't alloc xflist array\n", isp->isp_name); 825a95ae193SMatt Jacob return (1); 826a95ae193SMatt Jacob } 827a95ae193SMatt Jacob bzero(isp->isp_xflist, len); 828a95ae193SMatt Jacob len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; 829a95ae193SMatt Jacob pci->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK); 830a95ae193SMatt Jacob if (pci->dmaps == NULL) { 831a95ae193SMatt Jacob printf("%s: can't alloc dma maps\n", isp->isp_name); 832a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 833a95ae193SMatt Jacob return (1); 834a95ae193SMatt Jacob } 835a95ae193SMatt Jacob 836222bb542SMatt Jacob if (IS_FC(isp) || IS_1080(isp) || IS_12X0(isp)) 837222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR + 1; 838222bb542SMatt Jacob else 839222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR_24BIT + 1; 840d720e6d5SJustin T. Gibbs 841d720e6d5SJustin T. Gibbs /* 842d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 843d720e6d5SJustin T. Gibbs */ 844d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 845d720e6d5SJustin T. Gibbs len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 846222bb542SMatt Jacob if (IS_FC(isp)) { 847d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 848d720e6d5SJustin T. Gibbs } 849222bb542SMatt Jacob if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim, 850222bb542SMatt Jacob BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, 851222bb542SMatt Jacob BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { 852d720e6d5SJustin T. Gibbs printf("%s: cannot create a dma tag for control spaces\n", 853d720e6d5SJustin T. Gibbs isp->isp_name); 854a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 855a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 856d720e6d5SJustin T. Gibbs return (1); 857d720e6d5SJustin T. Gibbs } 858d720e6d5SJustin T. Gibbs if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 859d720e6d5SJustin T. Gibbs BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 8604873663cSMatt Jacob printf("%s: cannot allocate %d bytes of CCB memory\n", 8614873663cSMatt Jacob isp->isp_name, len); 862a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 863a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 864d720e6d5SJustin T. Gibbs return (1); 865d720e6d5SJustin T. Gibbs } 866d720e6d5SJustin T. Gibbs 867d720e6d5SJustin T. Gibbs isp->isp_rquest = base; 868222bb542SMatt Jacob im.isp = isp; 869222bb542SMatt Jacob im.error = 0; 870d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 871222bb542SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, &im, 0); 872222bb542SMatt Jacob if (im.error) { 873222bb542SMatt Jacob printf("%s: error %d loading dma map for DMA request queue\n", 874222bb542SMatt Jacob isp->isp_name, im.error); 875a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 876a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 877a95ae193SMatt Jacob isp->isp_rquest = NULL; 878222bb542SMatt Jacob return (1); 879222bb542SMatt Jacob } 880d720e6d5SJustin T. Gibbs isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 881222bb542SMatt Jacob im.error = 0; 882d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 883222bb542SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, &im, 0); 884222bb542SMatt Jacob if (im.error) { 885222bb542SMatt Jacob printf("%s: error %d loading dma map for DMA result queue\n", 886222bb542SMatt Jacob isp->isp_name, im.error); 887a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 888a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 889a95ae193SMatt Jacob isp->isp_rquest = NULL; 890222bb542SMatt Jacob return (1); 891222bb542SMatt Jacob } 892d720e6d5SJustin T. Gibbs 893a95ae193SMatt Jacob for (i = 0; i < isp->isp_maxcmds; i++) { 894d720e6d5SJustin T. Gibbs error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 895d720e6d5SJustin T. Gibbs if (error) { 896a95ae193SMatt Jacob printf("%s: error %d creating per-cmd DMA maps\n", 897d720e6d5SJustin T. Gibbs isp->isp_name, error); 898a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 899a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 900a95ae193SMatt Jacob isp->isp_rquest = NULL; 901d720e6d5SJustin T. Gibbs return (1); 902d720e6d5SJustin T. Gibbs } 903d720e6d5SJustin T. Gibbs } 904a95ae193SMatt Jacob 905222bb542SMatt Jacob if (IS_FC(isp)) { 90692c49d78SMatt Jacob fcparam *fcp = (fcparam *) isp->isp_param; 90792c49d78SMatt Jacob fcp->isp_scratch = base + 90892c49d78SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 90992c49d78SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 910222bb542SMatt Jacob im.error = 0; 91192c49d78SMatt Jacob bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 912222bb542SMatt Jacob fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0); 913222bb542SMatt Jacob if (im.error) { 914222bb542SMatt Jacob printf("%s: error %d loading FC scratch area\n", 915222bb542SMatt Jacob isp->isp_name, im.error); 916a95ae193SMatt Jacob free(isp->isp_xflist, M_DEVBUF); 917a95ae193SMatt Jacob free(pci->dmaps, M_DEVBUF); 918a95ae193SMatt Jacob isp->isp_rquest = NULL; 919222bb542SMatt Jacob return (1); 920222bb542SMatt Jacob } 92192c49d78SMatt Jacob } 922d720e6d5SJustin T. Gibbs return (0); 923d720e6d5SJustin T. Gibbs } 924d720e6d5SJustin T. Gibbs 925d720e6d5SJustin T. Gibbs static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 926d720e6d5SJustin T. Gibbs typedef struct { 927d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 928d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 929d720e6d5SJustin T. Gibbs ispreq_t *rq; 930d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 931d720e6d5SJustin T. Gibbs u_int8_t optr; 932d720e6d5SJustin T. Gibbs u_int error; 933d720e6d5SJustin T. Gibbs } mush_t; 934d720e6d5SJustin T. Gibbs 9354873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 9364873663cSMatt Jacob 937d720e6d5SJustin T. Gibbs static void 93817e318c6SMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 939d720e6d5SJustin T. Gibbs { 940d720e6d5SJustin T. Gibbs mush_t *mp; 941d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 942d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 943d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci; 944d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 945d720e6d5SJustin T. Gibbs bus_dma_segment_t *eseg; 946d720e6d5SJustin T. Gibbs ispreq_t *rq; 947d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 948d720e6d5SJustin T. Gibbs u_int8_t optr; 949d720e6d5SJustin T. Gibbs ispcontreq_t *crq; 950d720e6d5SJustin T. Gibbs int drq, seglim, datalen; 951d720e6d5SJustin T. Gibbs 952d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 953d720e6d5SJustin T. Gibbs if (error) { 954d720e6d5SJustin T. Gibbs mp->error = error; 955d720e6d5SJustin T. Gibbs return; 956d720e6d5SJustin T. Gibbs } 957d720e6d5SJustin T. Gibbs 958d720e6d5SJustin T. Gibbs isp = mp->isp; 959d720e6d5SJustin T. Gibbs if (nseg < 1) { 960d720e6d5SJustin T. Gibbs printf("%s: zero or negative segment count\n", isp->isp_name); 961d720e6d5SJustin T. Gibbs mp->error = EFAULT; 962d720e6d5SJustin T. Gibbs return; 963d720e6d5SJustin T. Gibbs } 964d720e6d5SJustin T. Gibbs ccb = mp->ccb; 965d720e6d5SJustin T. Gibbs rq = mp->rq; 966d720e6d5SJustin T. Gibbs iptrp = mp->iptrp; 967d720e6d5SJustin T. Gibbs optr = mp->optr; 968d720e6d5SJustin T. Gibbs pci = (struct isp_pcisoftc *)isp; 969d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 970a95ae193SMatt Jacob 971d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 972d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 973d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_IN; 974d720e6d5SJustin T. Gibbs } else { 975d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 976d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_OUT; 977d720e6d5SJustin T. Gibbs } 978d720e6d5SJustin T. Gibbs 979d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(ccb); 980222bb542SMatt Jacob if (IS_FC(isp)) { 981d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 982d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 983d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_flags |= drq; 984d720e6d5SJustin T. Gibbs } else { 985d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 986d720e6d5SJustin T. Gibbs rq->req_flags |= drq; 987d720e6d5SJustin T. Gibbs } 988d720e6d5SJustin T. Gibbs 989d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 990d720e6d5SJustin T. Gibbs 991d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 992222bb542SMatt Jacob if (IS_FC(isp)) { 993d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 994d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 995d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 996d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 997d720e6d5SJustin T. Gibbs dm_segs->ds_len; 998d720e6d5SJustin T. Gibbs } else { 999d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 1000d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 1001d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 1002d720e6d5SJustin T. Gibbs dm_segs->ds_len; 1003d720e6d5SJustin T. Gibbs } 1004d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 1005d720e6d5SJustin T. Gibbs #if 0 1006222bb542SMatt Jacob if (IS_FC(isp)) { 1007d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 1008d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 1009d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 1010d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count, 1011d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base); 1012d720e6d5SJustin T. Gibbs } else { 1013d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 1014d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 1015d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count, 1016d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base); 1017d720e6d5SJustin T. Gibbs } 1018d720e6d5SJustin T. Gibbs #endif 1019d720e6d5SJustin T. Gibbs rq->req_seg_count++; 1020d720e6d5SJustin T. Gibbs dm_segs++; 1021d720e6d5SJustin T. Gibbs } 1022d720e6d5SJustin T. Gibbs 1023d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 1024d720e6d5SJustin T. Gibbs crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 10254873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 1026d720e6d5SJustin T. Gibbs if (*iptrp == optr) { 10274873663cSMatt Jacob #if 0 10284873663cSMatt Jacob printf("%s: Request Queue Overflow++\n", isp->isp_name); 10294873663cSMatt Jacob #endif 10304873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 1031d720e6d5SJustin T. Gibbs return; 1032d720e6d5SJustin T. Gibbs } 1033d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 1034d720e6d5SJustin T. Gibbs bzero((void *)crq, sizeof (*crq)); 1035d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 1036d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 1037d720e6d5SJustin T. Gibbs 1038d720e6d5SJustin T. Gibbs seglim = 0; 1039d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 1040d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 1041d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 1042d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 1043d720e6d5SJustin T. Gibbs dm_segs->ds_len; 1044d720e6d5SJustin T. Gibbs #if 0 1045d720e6d5SJustin T. Gibbs printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 1046d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_header.rqs_entry_count-1, 1047d720e6d5SJustin T. Gibbs seglim, crq->req_dataseg[seglim].ds_count, 1048d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base); 1049d720e6d5SJustin T. Gibbs #endif 1050d720e6d5SJustin T. Gibbs rq->req_seg_count++; 1051d720e6d5SJustin T. Gibbs dm_segs++; 1052d720e6d5SJustin T. Gibbs seglim++; 1053d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 1054d720e6d5SJustin T. Gibbs } 1055d720e6d5SJustin T. Gibbs } 1056d720e6d5SJustin T. Gibbs } 1057d720e6d5SJustin T. Gibbs 1058d720e6d5SJustin T. Gibbs static int 105917e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 106017e318c6SMatt Jacob u_int8_t *iptrp, u_int8_t optr) 1061d720e6d5SJustin T. Gibbs { 1062d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1063d720e6d5SJustin T. Gibbs struct ccb_hdr *ccb_h; 1064d720e6d5SJustin T. Gibbs struct ccb_scsiio *csio; 10650a5f7e8bSMatt Jacob bus_dmamap_t *dp = NULL; 1066d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1067d720e6d5SJustin T. Gibbs 1068d720e6d5SJustin T. Gibbs csio = (struct ccb_scsiio *) ccb; 1069d720e6d5SJustin T. Gibbs ccb_h = &csio->ccb_h; 1070d720e6d5SJustin T. Gibbs 1071d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 1072d720e6d5SJustin T. Gibbs rq->req_seg_count = 1; 10734873663cSMatt Jacob return (CMD_QUEUED); 1074d720e6d5SJustin T. Gibbs } 1075d720e6d5SJustin T. Gibbs 1076d720e6d5SJustin T. Gibbs /* 1077d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 10784873663cSMatt Jacob * the callback dma allocation that we have to use... 1079d720e6d5SJustin T. Gibbs */ 1080d720e6d5SJustin T. Gibbs mp = &mush; 1081d720e6d5SJustin T. Gibbs mp->isp = isp; 1082d720e6d5SJustin T. Gibbs mp->ccb = ccb; 1083d720e6d5SJustin T. Gibbs mp->rq = rq; 1084d720e6d5SJustin T. Gibbs mp->iptrp = iptrp; 1085d720e6d5SJustin T. Gibbs mp->optr = optr; 1086d720e6d5SJustin T. Gibbs mp->error = 0; 1087d720e6d5SJustin T. Gibbs 1088d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 1089d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 10904873663cSMatt Jacob int error, s; 10910a5f7e8bSMatt Jacob dp = &pci->dmaps[rq->req_handle - 1]; 1092d720e6d5SJustin T. Gibbs s = splsoftvm(); 1093d720e6d5SJustin T. Gibbs error = bus_dmamap_load(pci->parent_dmat, *dp, 1094d720e6d5SJustin T. Gibbs csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 1095d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 1096d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 1097d720e6d5SJustin T. Gibbs mp->error = EINVAL; 10984873663cSMatt Jacob printf("%s: deferred dma allocation not " 10994873663cSMatt Jacob "supported\n", isp->isp_name); 1100d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 11010a5f7e8bSMatt Jacob #ifdef DIAGNOSTIC 11020a5f7e8bSMatt Jacob printf("%s: error %d in dma mapping code\n", 11030a5f7e8bSMatt Jacob isp->isp_name, error); 11040a5f7e8bSMatt Jacob #endif 1105d720e6d5SJustin T. Gibbs mp->error = error; 1106d720e6d5SJustin T. Gibbs } 11074873663cSMatt Jacob splx(s); 1108d720e6d5SJustin T. Gibbs } else { 1109d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 1110d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 1111d720e6d5SJustin T. Gibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 1112d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 1113d720e6d5SJustin T. Gibbs dma2(mp, &seg, 1, 0); 1114d720e6d5SJustin T. Gibbs } 1115d720e6d5SJustin T. Gibbs } else { 1116d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 1117d720e6d5SJustin T. Gibbs 1118d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 1119d720e6d5SJustin T. Gibbs printf("%s: Physical segment pointers unsupported", 1120d720e6d5SJustin T. Gibbs isp->isp_name); 1121d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1122d720e6d5SJustin T. Gibbs } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 1123d720e6d5SJustin T. Gibbs printf("%s: Virtual segment addresses unsupported", 1124d720e6d5SJustin T. Gibbs isp->isp_name); 1125d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1126d720e6d5SJustin T. Gibbs } else { 1127d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 1128d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 1129d720e6d5SJustin T. Gibbs dma2(mp, segs, csio->sglist_cnt, 0); 1130d720e6d5SJustin T. Gibbs } 1131d720e6d5SJustin T. Gibbs } 1132d720e6d5SJustin T. Gibbs if (mp->error) { 11334873663cSMatt Jacob int retval = CMD_COMPLETE; 11344873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 11354873663cSMatt Jacob retval = CMD_EAGAIN; 11364873663cSMatt Jacob } else if (mp->error == EFBIG) { 11370a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_TOO_BIG); 1138d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 11390a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_REQ_INVALID); 1140d720e6d5SJustin T. Gibbs } else { 11410a5f7e8bSMatt Jacob XS_SETERR(csio, CAM_UNREC_HBA_ERROR); 1142d720e6d5SJustin T. Gibbs } 11434873663cSMatt Jacob return (retval); 11444873663cSMatt Jacob } else { 11450a5f7e8bSMatt Jacob /* 11460a5f7e8bSMatt Jacob * Check to see if we weren't cancelled while sleeping on 11470a5f7e8bSMatt Jacob * getting DMA resources... 11480a5f7e8bSMatt Jacob */ 11490a5f7e8bSMatt Jacob if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 11500a5f7e8bSMatt Jacob if (dp) { 11510a5f7e8bSMatt Jacob bus_dmamap_unload(pci->parent_dmat, *dp); 11520a5f7e8bSMatt Jacob } 11530a5f7e8bSMatt Jacob return (CMD_COMPLETE); 11540a5f7e8bSMatt Jacob } 11554873663cSMatt Jacob return (CMD_QUEUED); 1156d720e6d5SJustin T. Gibbs } 1157d720e6d5SJustin T. Gibbs } 1158d720e6d5SJustin T. Gibbs 1159d720e6d5SJustin T. Gibbs static void 1160a95ae193SMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, u_int32_t handle) 1161d720e6d5SJustin T. Gibbs { 1162d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1163a95ae193SMatt Jacob bus_dmamap_t *dp = &pci->dmaps[handle - 1]; 1164a95ae193SMatt Jacob KASSERT((handle > 0 && handle <= isp->isp_maxcmds), 1165a95ae193SMatt Jacob ("bad handle in isp_pci_dmateardonw")); 1166a95ae193SMatt Jacob if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1167d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 1168d720e6d5SJustin T. Gibbs } else { 1169d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 1170d720e6d5SJustin T. Gibbs } 1171d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 1172d720e6d5SJustin T. Gibbs } 1173d720e6d5SJustin T. Gibbs 117465adb54cSMatt Jacob 117565adb54cSMatt Jacob static void 117617e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp) 117765adb54cSMatt Jacob { 117865adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 117965adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 118065adb54cSMatt Jacob } 118165adb54cSMatt Jacob 118265adb54cSMatt Jacob static void 118317e318c6SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp) 118465adb54cSMatt Jacob { 118565adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 11869bffbcd4SBruce Evans printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1187d951bbcaSMatt Jacob pci_conf_read(pci->pci_id, PCIR_COMMAND)); 118865adb54cSMatt Jacob } 1189