186cb5d6bSMatt Jacob /* $Id: isp_pci.c,v 1.25 1999/07/05 20:24:46 mjacob Exp $ */ 25542fe4bSMatt Jacob /* release_6_5_99 */ 365adb54cSMatt Jacob /* 465adb54cSMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 565adb54cSMatt Jacob * FreeBSD Version. 665adb54cSMatt Jacob * 765adb54cSMatt Jacob *--------------------------------------- 8222bb542SMatt Jacob * Copyright (c) 1997, 1998, 1999 by Matthew Jacob 965adb54cSMatt Jacob * NASA/Ames Research Center 1065adb54cSMatt Jacob * All rights reserved. 1165adb54cSMatt Jacob *--------------------------------------- 1265adb54cSMatt Jacob * 1365adb54cSMatt Jacob * Redistribution and use in source and binary forms, with or without 1465adb54cSMatt Jacob * modification, are permitted provided that the following conditions 1565adb54cSMatt Jacob * are met: 1665adb54cSMatt Jacob * 1. Redistributions of source code must retain the above copyright 1765adb54cSMatt Jacob * notice immediately at the beginning of the file, without modification, 1865adb54cSMatt Jacob * this list of conditions, and the following disclaimer. 1965adb54cSMatt Jacob * 2. Redistributions in binary form must reproduce the above copyright 2065adb54cSMatt Jacob * notice, this list of conditions and the following disclaimer in the 2165adb54cSMatt Jacob * documentation and/or other materials provided with the distribution. 2265adb54cSMatt Jacob * 3. The name of the author may not be used to endorse or promote products 2365adb54cSMatt Jacob * derived from this software without specific prior written permission. 2465adb54cSMatt Jacob * 2565adb54cSMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2665adb54cSMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2765adb54cSMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2865adb54cSMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2965adb54cSMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3065adb54cSMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3165adb54cSMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3265adb54cSMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3365adb54cSMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3465adb54cSMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3565adb54cSMatt Jacob * SUCH DAMAGE. 3665adb54cSMatt Jacob */ 3765adb54cSMatt Jacob #include <dev/isp/isp_freebsd.h> 3865adb54cSMatt Jacob #include <dev/isp/asm_pci.h> 39d720e6d5SJustin T. Gibbs #include <sys/malloc.h> 40d720e6d5SJustin T. Gibbs #include <vm/vm.h> 41d720e6d5SJustin T. Gibbs #include <vm/pmap.h> 42d720e6d5SJustin T. Gibbs #include <vm/vm_extern.h> 43d720e6d5SJustin T. Gibbs 4465adb54cSMatt Jacob 4565adb54cSMatt Jacob #include <pci/pcireg.h> 4665adb54cSMatt Jacob #include <pci/pcivar.h> 4765adb54cSMatt Jacob 48d720e6d5SJustin T. Gibbs #include <machine/bus_memio.h> 49d720e6d5SJustin T. Gibbs #include <machine/bus_pio.h> 50d720e6d5SJustin T. Gibbs #include <machine/bus.h> 51222bb542SMatt Jacob #include <machine/md_var.h> 52d720e6d5SJustin T. Gibbs 53d59bd469SMatt Jacob 5465adb54cSMatt Jacob static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 5565adb54cSMatt Jacob static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 56d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 57d59bd469SMatt Jacob static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 58d59bd469SMatt Jacob static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 59d59bd469SMatt Jacob #endif 6065adb54cSMatt Jacob static int isp_pci_mbxdma __P((struct ispsoftc *)); 6165adb54cSMatt Jacob static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 6265adb54cSMatt Jacob ispreq_t *, u_int8_t *, u_int8_t)); 63d720e6d5SJustin T. Gibbs static void 64d720e6d5SJustin T. Gibbs isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 6565adb54cSMatt Jacob 6665adb54cSMatt Jacob static void isp_pci_reset1 __P((struct ispsoftc *)); 6765adb54cSMatt Jacob static void isp_pci_dumpregs __P((struct ispsoftc *)); 6865adb54cSMatt Jacob 69d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 7065adb54cSMatt Jacob static struct ispmdvec mdvec = { 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, 7965adb54cSMatt Jacob ISP_RISC_CODE, 8065adb54cSMatt Jacob ISP_CODE_LENGTH, 8165adb54cSMatt Jacob ISP_CODE_ORG, 8265adb54cSMatt Jacob ISP_CODE_VERSION, 83285e230dSMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 84d720e6d5SJustin T. Gibbs 0 8565adb54cSMatt Jacob }; 86d59bd469SMatt Jacob #endif 8765adb54cSMatt Jacob 88d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 89d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 90d59bd469SMatt Jacob isp_pci_rd_reg_1080, 91d59bd469SMatt Jacob isp_pci_wr_reg_1080, 92d59bd469SMatt Jacob isp_pci_mbxdma, 93d59bd469SMatt Jacob isp_pci_dmasetup, 94d59bd469SMatt Jacob isp_pci_dmateardown, 95d59bd469SMatt Jacob NULL, 96d59bd469SMatt Jacob isp_pci_reset1, 97d59bd469SMatt Jacob isp_pci_dumpregs, 9892c49d78SMatt Jacob ISP1080_RISC_CODE, 9992c49d78SMatt Jacob ISP1080_CODE_LENGTH, 10092c49d78SMatt Jacob ISP1080_CODE_ORG, 10192c49d78SMatt Jacob ISP1080_CODE_VERSION, 102d59bd469SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 103d59bd469SMatt Jacob 0 104d59bd469SMatt Jacob }; 105d59bd469SMatt Jacob #endif 106d59bd469SMatt Jacob 107d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 10865adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 10965adb54cSMatt Jacob isp_pci_rd_reg, 11065adb54cSMatt Jacob isp_pci_wr_reg, 11165adb54cSMatt Jacob isp_pci_mbxdma, 11265adb54cSMatt Jacob isp_pci_dmasetup, 113d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 11465adb54cSMatt Jacob NULL, 11565adb54cSMatt Jacob isp_pci_reset1, 11665adb54cSMatt Jacob isp_pci_dumpregs, 11765adb54cSMatt Jacob ISP2100_RISC_CODE, 11865adb54cSMatt Jacob ISP2100_CODE_LENGTH, 11965adb54cSMatt Jacob ISP2100_CODE_ORG, 12065adb54cSMatt Jacob ISP2100_CODE_VERSION, 121285e230dSMatt Jacob 0, /* Irrelevant to the 2100 */ 122d720e6d5SJustin T. Gibbs 0 12365adb54cSMatt Jacob }; 1245542fe4bSMatt Jacob #endif 125222bb542SMatt Jacob 12686cb5d6bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 127222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = { 128222bb542SMatt Jacob isp_pci_rd_reg, 129222bb542SMatt Jacob isp_pci_wr_reg, 130222bb542SMatt Jacob isp_pci_mbxdma, 131222bb542SMatt Jacob isp_pci_dmasetup, 132222bb542SMatt Jacob isp_pci_dmateardown, 133222bb542SMatt Jacob NULL, 134222bb542SMatt Jacob isp_pci_reset1, 135222bb542SMatt Jacob isp_pci_dumpregs, 1365542fe4bSMatt Jacob ISP2200_RISC_CODE, 1375542fe4bSMatt Jacob ISP2200_CODE_LENGTH, 138222bb542SMatt Jacob ISP2100_CODE_ORG, 1395542fe4bSMatt Jacob ISP2200_RISC_CODE, 140222bb542SMatt Jacob 0, 141222bb542SMatt Jacob 0 142222bb542SMatt Jacob }; 143d59bd469SMatt Jacob #endif 14465adb54cSMatt Jacob 145d951bbcaSMatt Jacob #ifndef SCSI_ISP_PREFER_MEM_MAP 146d951bbcaSMatt Jacob #ifdef __alpha__ 147d951bbcaSMatt Jacob #define SCSI_ISP_PREFER_MEM_MAP 0 148d951bbcaSMatt Jacob #else 149d951bbcaSMatt Jacob #define SCSI_ISP_PREFER_MEM_MAP 1 150d951bbcaSMatt Jacob #endif 151d951bbcaSMatt Jacob #endif 152d951bbcaSMatt Jacob 15365adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 15465adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 15565adb54cSMatt Jacob #endif 15665adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 15765adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 15865adb54cSMatt Jacob #endif 159d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 160d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 161d951bbcaSMatt Jacob #endif 162d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 163d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 164d951bbcaSMatt Jacob #endif 165d951bbcaSMatt Jacob 166d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 167d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 168d951bbcaSMatt Jacob #endif 169d951bbcaSMatt Jacob 170d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 171d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 172d951bbcaSMatt Jacob #endif 173d951bbcaSMatt Jacob 174d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 175d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 176d951bbcaSMatt Jacob #endif 177d951bbcaSMatt Jacob 178ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 179ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 180ab6d0040SMatt Jacob #endif 181ab6d0040SMatt Jacob 18265adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 18365adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 18465adb54cSMatt Jacob #endif 18565adb54cSMatt Jacob 18665adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 18765adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 18865adb54cSMatt Jacob #endif 18965adb54cSMatt Jacob 190d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 191d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 192d59bd469SMatt Jacob #endif 193d59bd469SMatt Jacob 194d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 195d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 196d59bd469SMatt Jacob #endif 19765adb54cSMatt Jacob 19865adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 19965adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 20065adb54cSMatt Jacob #endif 20165adb54cSMatt Jacob 202222bb542SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2200 203222bb542SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 204222bb542SMatt Jacob #endif 205222bb542SMatt Jacob 206d59bd469SMatt Jacob #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 207d59bd469SMatt Jacob 208d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 209d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 210d59bd469SMatt Jacob 211d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 212d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 213d59bd469SMatt Jacob 21465adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 21565adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 21665adb54cSMatt Jacob 217222bb542SMatt Jacob #define PCI_QLOGIC_ISP2200 \ 218222bb542SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) 219222bb542SMatt Jacob 22065adb54cSMatt Jacob #define IO_MAP_REG 0x10 22165adb54cSMatt Jacob #define MEM_MAP_REG 0x14 22265adb54cSMatt Jacob 223d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 224d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 22565adb54cSMatt Jacob 226222bb542SMatt Jacob static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type)); 22765adb54cSMatt Jacob static void isp_pci_attach __P((pcici_t config_d, int unit)); 22865adb54cSMatt Jacob 229d720e6d5SJustin T. Gibbs /* This distinguishing define is not right, but it does work */ 230a185f9b1SMatt Jacob #ifdef __alpha__ 231a185f9b1SMatt Jacob #define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 232a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 233a185f9b1SMatt Jacob #else 234a185f9b1SMatt Jacob #define IO_SPACE_MAPPING I386_BUS_SPACE_IO 235a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 236a185f9b1SMatt Jacob #endif 23765adb54cSMatt Jacob 23865adb54cSMatt Jacob struct isp_pcisoftc { 23965adb54cSMatt Jacob struct ispsoftc pci_isp; 24065adb54cSMatt Jacob pcici_t pci_id; 24165adb54cSMatt Jacob bus_space_tag_t pci_st; 24265adb54cSMatt Jacob bus_space_handle_t pci_sh; 243d59bd469SMatt Jacob int16_t pci_poff[_NREG_BLKS]; 244d720e6d5SJustin T. Gibbs bus_dma_tag_t parent_dmat; 245d720e6d5SJustin T. Gibbs bus_dma_tag_t cntrol_dmat; 246d720e6d5SJustin T. Gibbs bus_dmamap_t cntrol_dmap; 247d720e6d5SJustin T. Gibbs bus_dmamap_t dmaps[MAXISPREQUEST]; 24865adb54cSMatt Jacob }; 24965adb54cSMatt Jacob 250d720e6d5SJustin T. Gibbs static u_long ispunit; 25165adb54cSMatt Jacob 25266235db5SEivind Eklund static struct pci_device isp_pci_driver = { 25365adb54cSMatt Jacob "isp", 25465adb54cSMatt Jacob isp_pci_probe, 25565adb54cSMatt Jacob isp_pci_attach, 256d720e6d5SJustin T. Gibbs &ispunit, 25765adb54cSMatt Jacob NULL 25865adb54cSMatt Jacob }; 25996b3554eSPeter Wemm COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver); 26065adb54cSMatt Jacob 26165adb54cSMatt Jacob 262222bb542SMatt Jacob static const char * 26317e318c6SMatt Jacob isp_pci_probe(pcici_t tag, pcidi_t type) 26465adb54cSMatt Jacob { 26565adb54cSMatt Jacob static int oneshot = 1; 26665adb54cSMatt Jacob char *x; 26765adb54cSMatt Jacob 26865adb54cSMatt Jacob switch (type) { 269d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 27065adb54cSMatt Jacob case PCI_QLOGIC_ISP: 271d59bd469SMatt Jacob x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 27265adb54cSMatt Jacob break; 273d59bd469SMatt Jacob #endif 274d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 275d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 276c6608df3SMatt Jacob x = "Qlogic ISP 1080 PCI SCSI Adapter"; 277c6608df3SMatt Jacob break; 278c6608df3SMatt Jacob case PCI_QLOGIC_ISP1240: 279c6608df3SMatt Jacob x = "Qlogic ISP 1240 PCI SCSI Adapter"; 280d59bd469SMatt Jacob break; 281d59bd469SMatt Jacob #endif 282d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 28365adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 28465adb54cSMatt Jacob x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 28565adb54cSMatt Jacob break; 286d59bd469SMatt Jacob #endif 2875542fe4bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 2885542fe4bSMatt Jacob case PCI_QLOGIC_ISP2200: 2895542fe4bSMatt Jacob x = "Qlogic ISP 2200 PCI FC-AL Adapter"; 2905542fe4bSMatt Jacob break; 2915542fe4bSMatt Jacob #endif 29265adb54cSMatt Jacob default: 29365adb54cSMatt Jacob return (NULL); 29465adb54cSMatt Jacob } 29565adb54cSMatt Jacob if (oneshot) { 29665adb54cSMatt Jacob oneshot = 0; 297d720e6d5SJustin T. Gibbs printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 298d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 299d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 30065adb54cSMatt Jacob } 30165adb54cSMatt Jacob return (x); 30265adb54cSMatt Jacob } 30365adb54cSMatt Jacob 30465adb54cSMatt Jacob 30565adb54cSMatt Jacob static void 306222bb542SMatt Jacob isp_pci_attach(pcici_t cfid, int unit) 30765adb54cSMatt Jacob { 308222bb542SMatt Jacob int mapped, prefer_mem_map, bitmap; 309a185f9b1SMatt Jacob pci_port_t io_port; 310c6608df3SMatt Jacob u_int32_t data, linesz, psize, basetype; 31165adb54cSMatt Jacob struct isp_pcisoftc *pcs; 31265adb54cSMatt Jacob struct ispsoftc *isp; 31365adb54cSMatt Jacob vm_offset_t vaddr, paddr; 314c6608df3SMatt Jacob struct ispmdvec *mdvp; 315222bb542SMatt Jacob bus_size_t lim; 31665adb54cSMatt Jacob ISP_LOCKVAL_DECL; 31765adb54cSMatt Jacob 31865adb54cSMatt Jacob pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 31965adb54cSMatt Jacob if (pcs == NULL) { 3209bffbcd4SBruce Evans printf("isp%d: cannot allocate softc\n", unit); 32165adb54cSMatt Jacob return; 32265adb54cSMatt Jacob } 32365adb54cSMatt Jacob bzero(pcs, sizeof (struct isp_pcisoftc)); 32465adb54cSMatt Jacob 325222bb542SMatt Jacob /* 326222bb542SMatt Jacob * Figure out which we should try first - memory mapping or i/o mapping? 327222bb542SMatt Jacob */ 328222bb542SMatt Jacob #if SCSI_ISP_PREFER_MEM_MAP == 1 329222bb542SMatt Jacob prefer_mem_map = 1; 330222bb542SMatt Jacob #else 331222bb542SMatt Jacob prefer_mem_map = 0; 332222bb542SMatt Jacob #endif 333222bb542SMatt Jacob bitmap = 0; 334222bb542SMatt Jacob if (getenv_int("isp_mem_map", &bitmap)) { 335222bb542SMatt Jacob if (bitmap & (1 << unit)) 336222bb542SMatt Jacob prefer_mem_map = 1; 337222bb542SMatt Jacob } 338222bb542SMatt Jacob bitmap = 0; 339222bb542SMatt Jacob if (getenv_int("isp_io_map", &bitmap)) { 340222bb542SMatt Jacob if (bitmap & (1 << unit)) 341222bb542SMatt Jacob prefer_mem_map = 0; 342222bb542SMatt Jacob } 343222bb542SMatt Jacob 34465adb54cSMatt Jacob vaddr = paddr = NULL; 34565adb54cSMatt Jacob mapped = 0; 346ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 347d951bbcaSMatt Jacob /* 348d951bbcaSMatt Jacob * Note that pci_conf_read is a 32 bit word aligned function. 349d951bbcaSMatt Jacob */ 350222bb542SMatt Jacob data = pci_conf_read(cfid, PCIR_COMMAND); 351222bb542SMatt Jacob if (prefer_mem_map) { 352222bb542SMatt Jacob if (data & PCI_COMMAND_MEM_ENABLE) { 353222bb542SMatt Jacob if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 354a185f9b1SMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 355a185f9b1SMatt Jacob pcs->pci_sh = vaddr; 35665adb54cSMatt Jacob mapped++; 35765adb54cSMatt Jacob } 35865adb54cSMatt Jacob } 359a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 360222bb542SMatt Jacob if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 361a185f9b1SMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 362a185f9b1SMatt Jacob pcs->pci_sh = io_port; 36365adb54cSMatt Jacob mapped++; 36465adb54cSMatt Jacob } 36565adb54cSMatt Jacob } 366222bb542SMatt Jacob } else { 367222bb542SMatt Jacob if (data & PCI_COMMAND_IO_ENABLE) { 368222bb542SMatt Jacob if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) { 369d951bbcaSMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 370d951bbcaSMatt Jacob pcs->pci_sh = io_port; 371d951bbcaSMatt Jacob mapped++; 372d951bbcaSMatt Jacob } 373d951bbcaSMatt Jacob } 374d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 375222bb542SMatt Jacob if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) { 376d951bbcaSMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 377d951bbcaSMatt Jacob pcs->pci_sh = vaddr; 378d951bbcaSMatt Jacob mapped++; 379d951bbcaSMatt Jacob } 380d951bbcaSMatt Jacob } 381222bb542SMatt Jacob } 38265adb54cSMatt Jacob if (mapped == 0) { 3839bffbcd4SBruce Evans printf("isp%d: unable to map any ports!\n", unit); 38465adb54cSMatt Jacob free(pcs, M_DEVBUF); 38565adb54cSMatt Jacob return; 38665adb54cSMatt Jacob } 387222bb542SMatt Jacob if (bootverbose) 38865adb54cSMatt Jacob printf("isp%d: using %s space register mapping\n", unit, 389a185f9b1SMatt Jacob pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 39065adb54cSMatt Jacob 391222bb542SMatt Jacob data = pci_conf_read(cfid, PCI_ID_REG); 392d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 393d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 394d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 395d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 396d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 397c6608df3SMatt Jacob /* 398c6608df3SMatt Jacob * GCC! 399c6608df3SMatt Jacob */ 400c6608df3SMatt Jacob mdvp = &mdvec; 401c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 402c6608df3SMatt Jacob psize = sizeof (sdparam); 403222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_32BIT; 404d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 40565adb54cSMatt Jacob if (data == PCI_QLOGIC_ISP) { 406c6608df3SMatt Jacob mdvp = &mdvec; 407c6608df3SMatt Jacob basetype = ISP_HA_SCSI_UNKNOWN; 408c6608df3SMatt Jacob psize = sizeof (sdparam); 409222bb542SMatt Jacob lim = BUS_SPACE_MAXSIZE_24BIT; 410d59bd469SMatt Jacob } 411d59bd469SMatt Jacob #endif 412d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 413c6608df3SMatt Jacob if (data == PCI_QLOGIC_ISP1080) { 414c6608df3SMatt Jacob mdvp = &mdvec_1080; 415c6608df3SMatt Jacob basetype = ISP_HA_SCSI_1080; 416c6608df3SMatt Jacob psize = sizeof (sdparam); 417c6608df3SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 418c6608df3SMatt Jacob ISP1080_DMA_REGS_OFF; 419c6608df3SMatt Jacob } 420c6608df3SMatt Jacob if (data == PCI_QLOGIC_ISP1240) { 421c6608df3SMatt Jacob mdvp = &mdvec_1080; 422c6608df3SMatt Jacob basetype = ISP_HA_SCSI_12X0; 423c6608df3SMatt Jacob psize = 2 * sizeof (sdparam); 424d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 425d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 426d59bd469SMatt Jacob } 427d59bd469SMatt Jacob #endif 428d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 429d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP2100) { 430c6608df3SMatt Jacob mdvp = &mdvec_2100; 431c6608df3SMatt Jacob basetype = ISP_HA_FC_2100; 432c6608df3SMatt Jacob psize = sizeof (fcparam); 433d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 434d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 435222bb542SMatt Jacob data = pci_conf_read(cfid, PCI_CLASS_REG); 436ab6d0040SMatt Jacob if ((data & 0xff) < 3) { 437ab6d0040SMatt Jacob /* 438ab6d0040SMatt Jacob * XXX: Need to get the actual revision 439ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 440ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 441ab6d0040SMatt Jacob * XXX; boards. 442ab6d0040SMatt Jacob */ 443ab6d0040SMatt Jacob linesz = 1; 444ab6d0040SMatt Jacob } 44565adb54cSMatt Jacob } 4465542fe4bSMatt Jacob #endif 4475542fe4bSMatt Jacob #ifndef ISP_DISABLE_2200_SUPPORT 448222bb542SMatt Jacob if (data == PCI_QLOGIC_ISP2200) { 449222bb542SMatt Jacob mdvp = &mdvec_2200; 450222bb542SMatt Jacob basetype = ISP_HA_FC_2200; 451222bb542SMatt Jacob psize = sizeof (fcparam); 452222bb542SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 453222bb542SMatt Jacob PCI_MBOX_REGS2100_OFF; 454222bb542SMatt Jacob } 455d59bd469SMatt Jacob #endif 456c6608df3SMatt Jacob isp = &pcs->pci_isp; 457c6608df3SMatt Jacob isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT); 458c6608df3SMatt Jacob if (isp->isp_param == NULL) { 459c6608df3SMatt Jacob printf("isp%d: cannot allocate parameter data\n", unit); 460c6608df3SMatt Jacob return; 461c6608df3SMatt Jacob } 462c6608df3SMatt Jacob bzero(isp->isp_param, psize); 463c6608df3SMatt Jacob isp->isp_mdvec = mdvp; 464c6608df3SMatt Jacob isp->isp_type = basetype; 465c6608df3SMatt Jacob (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 466c6608df3SMatt Jacob isp->isp_osinfo.unit = unit; 46765adb54cSMatt Jacob 468d951bbcaSMatt Jacob ISP_LOCK(isp); 469ab6d0040SMatt Jacob 470d951bbcaSMatt Jacob /* 471d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 472d951bbcaSMatt Jacob * are set. 473d951bbcaSMatt Jacob */ 474222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_COMMAND, 2); 475d951bbcaSMatt Jacob data |= PCIM_CMD_SEREN | 476d951bbcaSMatt Jacob PCIM_CMD_PERRESPEN | 477d951bbcaSMatt Jacob PCIM_CMD_BUSMASTEREN | 478d951bbcaSMatt Jacob PCIM_CMD_INVEN; 479222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_COMMAND, 2, data); 480ab6d0040SMatt Jacob 481d951bbcaSMatt Jacob /* 482222bb542SMatt Jacob * Make sure the Cache Line Size register is set sensibly. 483d951bbcaSMatt Jacob */ 484222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_CACHELNSZ, 1); 485ab6d0040SMatt Jacob if (data != linesz) { 486d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 487d951bbcaSMatt Jacob printf("%s: set PCI line size to %d\n", isp->isp_name, data); 488222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_CACHELNSZ, data, 1); 489d951bbcaSMatt Jacob } 490ab6d0040SMatt Jacob 491d951bbcaSMatt Jacob /* 492d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 493d951bbcaSMatt Jacob */ 494222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_LATTIMER, 1); 495d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 496d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 497d951bbcaSMatt Jacob printf("%s: set PCI latency to %d\n", isp->isp_name, data); 498222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_LATTIMER, data, 1); 499d951bbcaSMatt Jacob } 500ab6d0040SMatt Jacob 501ab6d0040SMatt Jacob /* 502ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 503ab6d0040SMatt Jacob */ 504222bb542SMatt Jacob data = pci_cfgread(cfid, PCIR_ROMADDR, 4); 505ab6d0040SMatt Jacob data &= ~1; 506222bb542SMatt Jacob pci_cfgwrite(cfid, PCIR_ROMADDR, data, 4); 507d951bbcaSMatt Jacob ISP_UNLOCK(isp); 508d951bbcaSMatt Jacob 509d720e6d5SJustin T. Gibbs if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT, 510222bb542SMatt Jacob BUS_SPACE_MAXADDR, NULL, NULL, lim + 1, 511222bb542SMatt Jacob 255, lim, 0, &pcs->parent_dmat) != 0) { 512d720e6d5SJustin T. Gibbs printf("%s: could not create master dma tag\n", isp->isp_name); 513d720e6d5SJustin T. Gibbs free(pcs, M_DEVBUF); 514d720e6d5SJustin T. Gibbs return; 515d720e6d5SJustin T. Gibbs } 516222bb542SMatt Jacob if (pci_map_int(cfid, (void (*)(void *))isp_intr, 51765adb54cSMatt Jacob (void *)isp, &IMASK) == 0) { 5189bffbcd4SBruce Evans printf("%s: could not map interrupt\n", isp->isp_name); 51965adb54cSMatt Jacob free(pcs, M_DEVBUF); 52065adb54cSMatt Jacob return; 52165adb54cSMatt Jacob } 52265adb54cSMatt Jacob 523222bb542SMatt Jacob pcs->pci_id = cfid; 524d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_FWLOAD_MASK 525d951bbcaSMatt Jacob if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 526d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 527d951bbcaSMatt Jacob #endif 528222bb542SMatt Jacob if (getenv_int("isp_no_fwload", &bitmap)) { 529222bb542SMatt Jacob if (bitmap & (1 << unit)) 530222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 531222bb542SMatt Jacob } 532222bb542SMatt Jacob if (getenv_int("isp_fwload", &bitmap)) { 533222bb542SMatt Jacob if (bitmap & (1 << unit)) 534222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NORELOAD; 535222bb542SMatt Jacob } 536222bb542SMatt Jacob 537d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_NVRAM_MASK 538ab6d0040SMatt Jacob if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 539ab6d0040SMatt Jacob printf("%s: ignoring NVRAM\n", isp->isp_name); 540d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 541ab6d0040SMatt Jacob } 542d951bbcaSMatt Jacob #endif 543222bb542SMatt Jacob if (getenv_int("isp_no_nvram", &bitmap)) { 544222bb542SMatt Jacob if (bitmap & (1 << unit)) 545222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 546222bb542SMatt Jacob } 547222bb542SMatt Jacob if (getenv_int("isp_nvram", &bitmap)) { 548222bb542SMatt Jacob if (bitmap & (1 << unit)) 549222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_NONVRAM; 550222bb542SMatt Jacob } 551222bb542SMatt Jacob 552222bb542SMatt Jacob #ifdef SCSI_ISP_FCDUPLEX 553222bb542SMatt Jacob if (IS_FC(isp)) { 554222bb542SMatt Jacob if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) { 555222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 556222bb542SMatt Jacob } 557222bb542SMatt Jacob } 558222bb542SMatt Jacob #endif 559222bb542SMatt Jacob if (getenv_int("isp_fcduplex", &bitmap)) { 560222bb542SMatt Jacob if (bitmap & (1 << unit)) 561222bb542SMatt Jacob isp->isp_confopts |= ISP_CFG_FULL_DUPLEX; 562222bb542SMatt Jacob } 563222bb542SMatt Jacob if (getenv_int("isp_no_fcduplex", &bitmap)) { 564222bb542SMatt Jacob if (bitmap & (1 << unit)) 565222bb542SMatt Jacob isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX; 566222bb542SMatt Jacob } 567222bb542SMatt Jacob 568222bb542SMatt Jacob if (getenv_int("isp_seed", &isp->isp_osinfo.seed)) { 569222bb542SMatt Jacob isp->isp_osinfo.seed <<= 8; 570222bb542SMatt Jacob isp->isp_osinfo.seed += (unit + 1); 571222bb542SMatt Jacob } else { 572222bb542SMatt Jacob /* 573222bb542SMatt Jacob * poor man's attempt at pseudo randomness. 574222bb542SMatt Jacob */ 575222bb542SMatt Jacob long i = (long) isp; 576222bb542SMatt Jacob 577222bb542SMatt Jacob i >>= 5; 578222bb542SMatt Jacob i &= 0x7; 579222bb542SMatt Jacob 580222bb542SMatt Jacob /* 581222bb542SMatt Jacob * This isn't very random, but it's the best we can do for 582222bb542SMatt Jacob * the real edge case of cards that don't have WWNs. 583222bb542SMatt Jacob */ 584222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->bus) << 16; 585222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->slot) << 8; 586222bb542SMatt Jacob isp->isp_osinfo.seed += ((int) cfid->func); 587222bb542SMatt Jacob while (version[i]) 588222bb542SMatt Jacob isp->isp_osinfo.seed += (int) version[i++]; 589222bb542SMatt Jacob isp->isp_osinfo.seed <<= 8; 590222bb542SMatt Jacob isp->isp_osinfo.seed += (unit + 1); 591222bb542SMatt Jacob } 592222bb542SMatt Jacob 593d720e6d5SJustin T. Gibbs ISP_LOCK(isp); 59465adb54cSMatt Jacob isp_reset(isp); 59565adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 596222bb542SMatt Jacob (void) pci_unmap_int(cfid); 597d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 59865adb54cSMatt Jacob free(pcs, M_DEVBUF); 59965adb54cSMatt Jacob return; 60065adb54cSMatt Jacob } 60165adb54cSMatt Jacob isp_init(isp); 60265adb54cSMatt Jacob if (isp->isp_state != ISP_INITSTATE) { 603d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 604222bb542SMatt Jacob if (IS_SCSI(isp)) { 60565adb54cSMatt Jacob isp_uninit(isp); 606222bb542SMatt Jacob (void) pci_unmap_int(cfid); /* Does nothing */ 607c6608df3SMatt Jacob ISP_UNLOCK(isp); 60865adb54cSMatt Jacob free(pcs, M_DEVBUF); 609c6608df3SMatt Jacob return; 610d59bd469SMatt Jacob } 61165adb54cSMatt Jacob } 61265adb54cSMatt Jacob isp_attach(isp); 61365adb54cSMatt Jacob if (isp->isp_state != ISP_RUNSTATE) { 614d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 61592c49d78SMatt Jacob if (IS_SCSI(isp)) { 61665adb54cSMatt Jacob isp_uninit(isp); 617222bb542SMatt Jacob (void) pci_unmap_int(cfid); /* Does nothing */ 618c6608df3SMatt Jacob ISP_UNLOCK(isp); 61965adb54cSMatt Jacob free(pcs, M_DEVBUF); 620c6608df3SMatt Jacob return; 62165adb54cSMatt Jacob } 622d59bd469SMatt Jacob } 623d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 624e37c0455SDoug Rabson #ifdef __alpha__ 625d951bbcaSMatt Jacob /* 626d951bbcaSMatt Jacob * THIS SHOULD NOT HAVE TO BE HERE 627d951bbcaSMatt Jacob */ 628222bb542SMatt Jacob alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim); 629e37c0455SDoug Rabson #endif 63065adb54cSMatt Jacob } 63165adb54cSMatt Jacob 63265adb54cSMatt Jacob static u_int16_t 633d59bd469SMatt Jacob isp_pci_rd_reg(isp, regoff) 634d59bd469SMatt Jacob struct ispsoftc *isp; 635d59bd469SMatt Jacob int regoff; 63665adb54cSMatt Jacob { 63765adb54cSMatt Jacob u_int16_t rv; 63865adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 639d59bd469SMatt Jacob int offset, oldconf = 0; 64065adb54cSMatt Jacob 641d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 64265adb54cSMatt Jacob /* 64365adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 64465adb54cSMatt Jacob */ 645d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 646d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 64765adb54cSMatt Jacob } 648d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 649d59bd469SMatt Jacob offset += (regoff & 0xff); 65065adb54cSMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 651d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 652d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 65365adb54cSMatt Jacob } 65465adb54cSMatt Jacob return (rv); 65565adb54cSMatt Jacob } 65665adb54cSMatt Jacob 65765adb54cSMatt Jacob static void 658d59bd469SMatt Jacob isp_pci_wr_reg(isp, regoff, val) 659d59bd469SMatt Jacob struct ispsoftc *isp; 660d59bd469SMatt Jacob int regoff; 661d59bd469SMatt Jacob u_int16_t val; 66265adb54cSMatt Jacob { 66365adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 664d59bd469SMatt Jacob int offset, oldconf = 0; 665d59bd469SMatt Jacob 666d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 66765adb54cSMatt Jacob /* 66865adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 66965adb54cSMatt Jacob */ 670d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 671d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 67265adb54cSMatt Jacob } 673d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 674d59bd469SMatt Jacob offset += (regoff & 0xff); 67565adb54cSMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 676d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 677d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 67865adb54cSMatt Jacob } 67965adb54cSMatt Jacob } 68065adb54cSMatt Jacob 681d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 682d59bd469SMatt Jacob static u_int16_t 683d59bd469SMatt Jacob isp_pci_rd_reg_1080(isp, regoff) 684d59bd469SMatt Jacob struct ispsoftc *isp; 685d59bd469SMatt Jacob int regoff; 686d59bd469SMatt Jacob { 687d59bd469SMatt Jacob u_int16_t rv; 688d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 689d59bd469SMatt Jacob int offset, oc = 0; 690d59bd469SMatt Jacob 691d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 692d59bd469SMatt Jacob /* 693d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 694d59bd469SMatt Jacob */ 695d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 696d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 697d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 698d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 699d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 700d59bd469SMatt Jacob } 701d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 702d59bd469SMatt Jacob offset += (regoff & 0xff); 703d59bd469SMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 704d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 705d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 706d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 707d59bd469SMatt Jacob } 708d59bd469SMatt Jacob return (rv); 709d59bd469SMatt Jacob } 710d59bd469SMatt Jacob 711d59bd469SMatt Jacob static void 712d59bd469SMatt Jacob isp_pci_wr_reg_1080(isp, regoff, val) 713d59bd469SMatt Jacob struct ispsoftc *isp; 714d59bd469SMatt Jacob int regoff; 715d59bd469SMatt Jacob u_int16_t val; 716d59bd469SMatt Jacob { 717d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 718d59bd469SMatt Jacob int offset, oc = 0; 719d59bd469SMatt Jacob 720d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 721d59bd469SMatt Jacob /* 722d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 723d59bd469SMatt Jacob */ 724d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 725d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 726d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 727d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 728d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 729d59bd469SMatt Jacob } 730d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 731d59bd469SMatt Jacob offset += (regoff & 0xff); 732d59bd469SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 733d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 734d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 735d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 736d59bd469SMatt Jacob } 737d59bd469SMatt Jacob } 738d59bd469SMatt Jacob #endif 739d59bd469SMatt Jacob 740d59bd469SMatt Jacob 741d720e6d5SJustin T. Gibbs static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 742d720e6d5SJustin T. Gibbs static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 743d720e6d5SJustin T. Gibbs static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 744d720e6d5SJustin T. Gibbs 745222bb542SMatt Jacob struct imush { 746222bb542SMatt Jacob struct ispsoftc *isp; 747222bb542SMatt Jacob int error; 748222bb542SMatt Jacob }; 749222bb542SMatt Jacob 750d720e6d5SJustin T. Gibbs static void 75117e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 752d720e6d5SJustin T. Gibbs { 753222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 754222bb542SMatt Jacob if (error) { 755222bb542SMatt Jacob imushp->error = error; 756222bb542SMatt Jacob } else { 757222bb542SMatt Jacob imushp->isp->isp_rquest_dma = segs->ds_addr; 758222bb542SMatt Jacob } 759d720e6d5SJustin T. Gibbs } 760d720e6d5SJustin T. Gibbs 761d720e6d5SJustin T. Gibbs static void 76217e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 763d720e6d5SJustin T. Gibbs { 764222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 765222bb542SMatt Jacob if (error) { 766222bb542SMatt Jacob imushp->error = error; 767222bb542SMatt Jacob } else { 768222bb542SMatt Jacob imushp->isp->isp_result_dma = segs->ds_addr; 769222bb542SMatt Jacob } 770d720e6d5SJustin T. Gibbs } 771d720e6d5SJustin T. Gibbs 772d720e6d5SJustin T. Gibbs static void 77317e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 774d720e6d5SJustin T. Gibbs { 775222bb542SMatt Jacob struct imush *imushp = (struct imush *) arg; 776222bb542SMatt Jacob if (error) { 777222bb542SMatt Jacob imushp->error = error; 778222bb542SMatt Jacob } else { 779222bb542SMatt Jacob fcparam *fcp = imushp->isp->isp_param; 780d720e6d5SJustin T. Gibbs fcp->isp_scdma = segs->ds_addr; 781d720e6d5SJustin T. Gibbs } 782222bb542SMatt Jacob } 783d720e6d5SJustin T. Gibbs 784d720e6d5SJustin T. Gibbs static int 78517e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 786d720e6d5SJustin T. Gibbs { 787d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 788d720e6d5SJustin T. Gibbs caddr_t base; 789d720e6d5SJustin T. Gibbs u_int32_t len; 790d720e6d5SJustin T. Gibbs int i, error; 791222bb542SMatt Jacob bus_size_t lim; 792222bb542SMatt Jacob struct imush im; 793222bb542SMatt Jacob 794222bb542SMatt Jacob 795222bb542SMatt Jacob if (IS_FC(isp) || IS_1080(isp) || IS_12X0(isp)) 796222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR + 1; 797222bb542SMatt Jacob else 798222bb542SMatt Jacob lim = BUS_SPACE_MAXADDR_24BIT + 1; 799d720e6d5SJustin T. Gibbs 800d720e6d5SJustin T. Gibbs /* 801d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 802d720e6d5SJustin T. Gibbs */ 803d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 804d720e6d5SJustin T. Gibbs len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 805222bb542SMatt Jacob if (IS_FC(isp)) { 806d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 807d720e6d5SJustin T. Gibbs } 808222bb542SMatt Jacob if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim, 809222bb542SMatt Jacob BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, 810222bb542SMatt Jacob BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { 811d720e6d5SJustin T. Gibbs printf("%s: cannot create a dma tag for control spaces\n", 812d720e6d5SJustin T. Gibbs isp->isp_name); 813d720e6d5SJustin T. Gibbs return (1); 814d720e6d5SJustin T. Gibbs } 815d720e6d5SJustin T. Gibbs if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 816d720e6d5SJustin T. Gibbs BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 8174873663cSMatt Jacob printf("%s: cannot allocate %d bytes of CCB memory\n", 8184873663cSMatt Jacob isp->isp_name, len); 819d720e6d5SJustin T. Gibbs return (1); 820d720e6d5SJustin T. Gibbs } 821d720e6d5SJustin T. Gibbs 822d720e6d5SJustin T. Gibbs isp->isp_rquest = base; 823222bb542SMatt Jacob im.isp = isp; 824222bb542SMatt Jacob im.error = 0; 825d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 826222bb542SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, &im, 0); 827222bb542SMatt Jacob if (im.error) { 828222bb542SMatt Jacob printf("%s: error %d loading dma map for DMA request queue\n", 829222bb542SMatt Jacob isp->isp_name, im.error); 830222bb542SMatt Jacob return (1); 831222bb542SMatt Jacob } 832d720e6d5SJustin T. Gibbs isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 833222bb542SMatt Jacob im.error = 0; 834d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 835222bb542SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, &im, 0); 836222bb542SMatt Jacob if (im.error) { 837222bb542SMatt Jacob printf("%s: error %d loading dma map for DMA result queue\n", 838222bb542SMatt Jacob isp->isp_name, im.error); 839222bb542SMatt Jacob return (1); 840222bb542SMatt Jacob } 841d720e6d5SJustin T. Gibbs 842d720e6d5SJustin T. Gibbs /* 843d720e6d5SJustin T. Gibbs * Use this opportunity to initialize/create data DMA maps. 844d720e6d5SJustin T. Gibbs */ 845d720e6d5SJustin T. Gibbs for (i = 0; i < MAXISPREQUEST; i++) { 846d720e6d5SJustin T. Gibbs error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 847d720e6d5SJustin T. Gibbs if (error) { 8484873663cSMatt Jacob printf("%s: error %d creating mailbox DMA maps\n", 849d720e6d5SJustin T. Gibbs isp->isp_name, error); 850d720e6d5SJustin T. Gibbs return (1); 851d720e6d5SJustin T. Gibbs } 852d720e6d5SJustin T. Gibbs } 853222bb542SMatt Jacob if (IS_FC(isp)) { 85492c49d78SMatt Jacob fcparam *fcp = (fcparam *) isp->isp_param; 85592c49d78SMatt Jacob fcp->isp_scratch = base + 85692c49d78SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 85792c49d78SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 858222bb542SMatt Jacob im.error = 0; 85992c49d78SMatt Jacob bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 860222bb542SMatt Jacob fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0); 861222bb542SMatt Jacob if (im.error) { 862222bb542SMatt Jacob printf("%s: error %d loading FC scratch area\n", 863222bb542SMatt Jacob isp->isp_name, im.error); 864222bb542SMatt Jacob return (1); 865222bb542SMatt Jacob } 86692c49d78SMatt Jacob } 867d720e6d5SJustin T. Gibbs return (0); 868d720e6d5SJustin T. Gibbs } 869d720e6d5SJustin T. Gibbs 870d720e6d5SJustin T. Gibbs static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 871d720e6d5SJustin T. Gibbs typedef struct { 872d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 873d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 874d720e6d5SJustin T. Gibbs ispreq_t *rq; 875d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 876d720e6d5SJustin T. Gibbs u_int8_t optr; 877d720e6d5SJustin T. Gibbs u_int error; 878d720e6d5SJustin T. Gibbs } mush_t; 879d720e6d5SJustin T. Gibbs 8804873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 8814873663cSMatt Jacob 882d720e6d5SJustin T. Gibbs static void 88317e318c6SMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 884d720e6d5SJustin T. Gibbs { 885d720e6d5SJustin T. Gibbs mush_t *mp; 886d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 887d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 888d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci; 889d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 890d720e6d5SJustin T. Gibbs bus_dma_segment_t *eseg; 891d720e6d5SJustin T. Gibbs ispreq_t *rq; 892d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 893d720e6d5SJustin T. Gibbs u_int8_t optr; 894d720e6d5SJustin T. Gibbs ispcontreq_t *crq; 895d720e6d5SJustin T. Gibbs int drq, seglim, datalen; 896d720e6d5SJustin T. Gibbs 897d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 898d720e6d5SJustin T. Gibbs if (error) { 899d720e6d5SJustin T. Gibbs mp->error = error; 900d720e6d5SJustin T. Gibbs return; 901d720e6d5SJustin T. Gibbs } 902d720e6d5SJustin T. Gibbs 903d720e6d5SJustin T. Gibbs isp = mp->isp; 904d720e6d5SJustin T. Gibbs if (nseg < 1) { 905d720e6d5SJustin T. Gibbs printf("%s: zero or negative segment count\n", isp->isp_name); 906d720e6d5SJustin T. Gibbs mp->error = EFAULT; 907d720e6d5SJustin T. Gibbs return; 908d720e6d5SJustin T. Gibbs } 909d720e6d5SJustin T. Gibbs ccb = mp->ccb; 910d720e6d5SJustin T. Gibbs rq = mp->rq; 911d720e6d5SJustin T. Gibbs iptrp = mp->iptrp; 912d720e6d5SJustin T. Gibbs optr = mp->optr; 913d720e6d5SJustin T. Gibbs 914d720e6d5SJustin T. Gibbs pci = (struct isp_pcisoftc *)isp; 915d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 916d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 917d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 918d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_IN; 919d720e6d5SJustin T. Gibbs } else { 920d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 921d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_OUT; 922d720e6d5SJustin T. Gibbs } 923d720e6d5SJustin T. Gibbs 924d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(ccb); 925222bb542SMatt Jacob if (IS_FC(isp)) { 926d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 927d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 928d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_flags |= drq; 929d720e6d5SJustin T. Gibbs } else { 930d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 931d720e6d5SJustin T. Gibbs rq->req_flags |= drq; 932d720e6d5SJustin T. Gibbs } 933d720e6d5SJustin T. Gibbs 934d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 935d720e6d5SJustin T. Gibbs 936d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 937222bb542SMatt Jacob if (IS_FC(isp)) { 938d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 939d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 940d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 941d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 942d720e6d5SJustin T. Gibbs dm_segs->ds_len; 943d720e6d5SJustin T. Gibbs } else { 944d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 945d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 946d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 947d720e6d5SJustin T. Gibbs dm_segs->ds_len; 948d720e6d5SJustin T. Gibbs } 949d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 950d720e6d5SJustin T. Gibbs #if 0 951222bb542SMatt Jacob if (IS_FC(isp)) { 952d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 953d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 954d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 955d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count, 956d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base); 957d720e6d5SJustin T. Gibbs } else { 958d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 959d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 960d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count, 961d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base); 962d720e6d5SJustin T. Gibbs } 963d720e6d5SJustin T. Gibbs #endif 964d720e6d5SJustin T. Gibbs rq->req_seg_count++; 965d720e6d5SJustin T. Gibbs dm_segs++; 966d720e6d5SJustin T. Gibbs } 967d720e6d5SJustin T. Gibbs 968d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 969d720e6d5SJustin T. Gibbs crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 9704873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 971d720e6d5SJustin T. Gibbs if (*iptrp == optr) { 9724873663cSMatt Jacob #if 0 9734873663cSMatt Jacob printf("%s: Request Queue Overflow++\n", isp->isp_name); 9744873663cSMatt Jacob #endif 9754873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 976d720e6d5SJustin T. Gibbs return; 977d720e6d5SJustin T. Gibbs } 978d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 979d720e6d5SJustin T. Gibbs bzero((void *)crq, sizeof (*crq)); 980d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 981d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 982d720e6d5SJustin T. Gibbs 983d720e6d5SJustin T. Gibbs seglim = 0; 984d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 985d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 986d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 987d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 988d720e6d5SJustin T. Gibbs dm_segs->ds_len; 989d720e6d5SJustin T. Gibbs #if 0 990d720e6d5SJustin T. Gibbs printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 991d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_header.rqs_entry_count-1, 992d720e6d5SJustin T. Gibbs seglim, crq->req_dataseg[seglim].ds_count, 993d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base); 994d720e6d5SJustin T. Gibbs #endif 995d720e6d5SJustin T. Gibbs rq->req_seg_count++; 996d720e6d5SJustin T. Gibbs dm_segs++; 997d720e6d5SJustin T. Gibbs seglim++; 998d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 999d720e6d5SJustin T. Gibbs } 1000d720e6d5SJustin T. Gibbs } 1001d720e6d5SJustin T. Gibbs } 1002d720e6d5SJustin T. Gibbs 1003d720e6d5SJustin T. Gibbs static int 100417e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 100517e318c6SMatt Jacob u_int8_t *iptrp, u_int8_t optr) 1006d720e6d5SJustin T. Gibbs { 1007d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1008d720e6d5SJustin T. Gibbs struct ccb_hdr *ccb_h; 1009d720e6d5SJustin T. Gibbs struct ccb_scsiio *csio; 1010d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 1011d720e6d5SJustin T. Gibbs mush_t mush, *mp; 1012d720e6d5SJustin T. Gibbs 1013d720e6d5SJustin T. Gibbs csio = (struct ccb_scsiio *) ccb; 1014d720e6d5SJustin T. Gibbs ccb_h = &csio->ccb_h; 1015d720e6d5SJustin T. Gibbs 1016d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 1017d720e6d5SJustin T. Gibbs rq->req_seg_count = 1; 10184873663cSMatt Jacob return (CMD_QUEUED); 1019d720e6d5SJustin T. Gibbs } 1020d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 1021d720e6d5SJustin T. Gibbs 1022d720e6d5SJustin T. Gibbs /* 1023d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 10244873663cSMatt Jacob * the callback dma allocation that we have to use... 1025d720e6d5SJustin T. Gibbs */ 1026d720e6d5SJustin T. Gibbs mp = &mush; 1027d720e6d5SJustin T. Gibbs mp->isp = isp; 1028d720e6d5SJustin T. Gibbs mp->ccb = ccb; 1029d720e6d5SJustin T. Gibbs mp->rq = rq; 1030d720e6d5SJustin T. Gibbs mp->iptrp = iptrp; 1031d720e6d5SJustin T. Gibbs mp->optr = optr; 1032d720e6d5SJustin T. Gibbs mp->error = 0; 1033d720e6d5SJustin T. Gibbs 1034d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 1035d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 10364873663cSMatt Jacob int error, s; 10374873663cSMatt Jacob 1038d720e6d5SJustin T. Gibbs s = splsoftvm(); 1039d720e6d5SJustin T. Gibbs error = bus_dmamap_load(pci->parent_dmat, *dp, 1040d720e6d5SJustin T. Gibbs csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 1041d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 1042d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 1043d720e6d5SJustin T. Gibbs mp->error = EINVAL; 10444873663cSMatt Jacob printf("%s: deferred dma allocation not " 10454873663cSMatt Jacob "supported\n", isp->isp_name); 1046d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 1047d720e6d5SJustin T. Gibbs mp->error = error; 1048d720e6d5SJustin T. Gibbs } 10494873663cSMatt Jacob splx(s); 1050d720e6d5SJustin T. Gibbs } else { 1051d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 1052d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 1053d720e6d5SJustin T. Gibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 1054d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 1055d720e6d5SJustin T. Gibbs dma2(mp, &seg, 1, 0); 1056d720e6d5SJustin T. Gibbs } 1057d720e6d5SJustin T. Gibbs } else { 1058d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 1059d720e6d5SJustin T. Gibbs 1060d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 1061d720e6d5SJustin T. Gibbs printf("%s: Physical segment pointers unsupported", 1062d720e6d5SJustin T. Gibbs isp->isp_name); 1063d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1064d720e6d5SJustin T. Gibbs } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 1065d720e6d5SJustin T. Gibbs printf("%s: Virtual segment addresses unsupported", 1066d720e6d5SJustin T. Gibbs isp->isp_name); 1067d720e6d5SJustin T. Gibbs mp->error = EINVAL; 1068d720e6d5SJustin T. Gibbs } else { 1069d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 1070d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 1071d720e6d5SJustin T. Gibbs dma2(mp, segs, csio->sglist_cnt, 0); 1072d720e6d5SJustin T. Gibbs } 1073d720e6d5SJustin T. Gibbs } 1074d720e6d5SJustin T. Gibbs if (mp->error) { 10754873663cSMatt Jacob int retval = CMD_COMPLETE; 10764873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 10774873663cSMatt Jacob retval = CMD_EAGAIN; 10784873663cSMatt Jacob ccb_h->status = CAM_UNREC_HBA_ERROR; 10794873663cSMatt Jacob } else if (mp->error == EFBIG) { 1080d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_TOO_BIG; 1081d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 1082d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_INVALID; 1083d720e6d5SJustin T. Gibbs } else { 1084d720e6d5SJustin T. Gibbs ccb_h->status = CAM_UNREC_HBA_ERROR; 1085d720e6d5SJustin T. Gibbs } 10864873663cSMatt Jacob return (retval); 10874873663cSMatt Jacob } else { 10884873663cSMatt Jacob return (CMD_QUEUED); 1089d720e6d5SJustin T. Gibbs } 1090d720e6d5SJustin T. Gibbs } 1091d720e6d5SJustin T. Gibbs 1092d720e6d5SJustin T. Gibbs static void 109317e318c6SMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, 109417e318c6SMatt Jacob u_int32_t handle) 1095d720e6d5SJustin T. Gibbs { 1096d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 1097d720e6d5SJustin T. Gibbs bus_dmamap_t *dp = &pci->dmaps[handle]; 1098d720e6d5SJustin T. Gibbs 1099d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1100d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 1101d720e6d5SJustin T. Gibbs } else { 1102d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 1103d720e6d5SJustin T. Gibbs } 1104d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 1105d720e6d5SJustin T. Gibbs } 1106d720e6d5SJustin T. Gibbs 110765adb54cSMatt Jacob 110865adb54cSMatt Jacob static void 110917e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp) 111065adb54cSMatt Jacob { 111165adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 111265adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 111365adb54cSMatt Jacob } 111465adb54cSMatt Jacob 111565adb54cSMatt Jacob static void 111617e318c6SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp) 111765adb54cSMatt Jacob { 111865adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 11199bffbcd4SBruce Evans printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1120d951bbcaSMatt Jacob pci_conf_read(pci->pci_id, PCIR_COMMAND)); 112165adb54cSMatt Jacob } 1122