196b3554eSPeter Wemm /* $Id: isp_pci.c,v 1.19 1999/04/11 02:47:31 eivind Exp $ */ 2ab6d0040SMatt Jacob /* release_4_3_99 */ 365adb54cSMatt Jacob /* 465adb54cSMatt Jacob * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. 565adb54cSMatt Jacob * FreeBSD Version. 665adb54cSMatt Jacob * 765adb54cSMatt Jacob *--------------------------------------- 865adb54cSMatt Jacob * Copyright (c) 1997, 1998 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 483dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 49d720e6d5SJustin T. Gibbs #include <machine/bus_memio.h> 50d720e6d5SJustin T. Gibbs #include <machine/bus_pio.h> 51d720e6d5SJustin T. Gibbs #include <machine/bus.h> 52d720e6d5SJustin T. Gibbs #endif 53d720e6d5SJustin T. Gibbs 54d59bd469SMatt Jacob #include "opt_isp.h" 55d59bd469SMatt Jacob 5665adb54cSMatt Jacob static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); 5765adb54cSMatt Jacob static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); 58d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 59d59bd469SMatt Jacob static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); 60d59bd469SMatt Jacob static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); 61d59bd469SMatt Jacob #endif 6265adb54cSMatt Jacob static int isp_pci_mbxdma __P((struct ispsoftc *)); 6365adb54cSMatt Jacob static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, 6465adb54cSMatt Jacob ispreq_t *, u_int8_t *, u_int8_t)); 653dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 66d720e6d5SJustin T. Gibbs static void 67d720e6d5SJustin T. Gibbs isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); 68ab6d0040SMatt Jacob #define PROBETYPE const char * 69d720e6d5SJustin T. Gibbs #else 70ab6d0040SMatt Jacob typedef u_int16_t pci_port_t; 71d720e6d5SJustin T. Gibbs #define isp_pci_dmateardown NULL 72ab6d0040SMatt Jacob #define PROBETYPE char * 73d720e6d5SJustin T. Gibbs #endif 7465adb54cSMatt Jacob 7565adb54cSMatt Jacob static void isp_pci_reset1 __P((struct ispsoftc *)); 7665adb54cSMatt Jacob static void isp_pci_dumpregs __P((struct ispsoftc *)); 7765adb54cSMatt Jacob 78d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 7965adb54cSMatt Jacob static struct ispmdvec mdvec = { 8065adb54cSMatt Jacob isp_pci_rd_reg, 8165adb54cSMatt Jacob isp_pci_wr_reg, 8265adb54cSMatt Jacob isp_pci_mbxdma, 8365adb54cSMatt Jacob isp_pci_dmasetup, 84d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 8565adb54cSMatt Jacob NULL, 8665adb54cSMatt Jacob isp_pci_reset1, 8765adb54cSMatt Jacob isp_pci_dumpregs, 8865adb54cSMatt Jacob ISP_RISC_CODE, 8965adb54cSMatt Jacob ISP_CODE_LENGTH, 9065adb54cSMatt Jacob ISP_CODE_ORG, 9165adb54cSMatt Jacob ISP_CODE_VERSION, 92285e230dSMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 93d720e6d5SJustin T. Gibbs 0 9465adb54cSMatt Jacob }; 95d59bd469SMatt Jacob #endif 9665adb54cSMatt Jacob 97d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 98d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = { 99d59bd469SMatt Jacob isp_pci_rd_reg_1080, 100d59bd469SMatt Jacob isp_pci_wr_reg_1080, 101d59bd469SMatt Jacob isp_pci_mbxdma, 102d59bd469SMatt Jacob isp_pci_dmasetup, 103d59bd469SMatt Jacob isp_pci_dmateardown, 104d59bd469SMatt Jacob NULL, 105d59bd469SMatt Jacob isp_pci_reset1, 106d59bd469SMatt Jacob isp_pci_dumpregs, 10792c49d78SMatt Jacob ISP1080_RISC_CODE, 10892c49d78SMatt Jacob ISP1080_CODE_LENGTH, 10992c49d78SMatt Jacob ISP1080_CODE_ORG, 11092c49d78SMatt Jacob ISP1080_CODE_VERSION, 111d59bd469SMatt Jacob BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 112d59bd469SMatt Jacob 0 113d59bd469SMatt Jacob }; 114d59bd469SMatt Jacob #endif 115d59bd469SMatt Jacob 116d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 11765adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = { 11865adb54cSMatt Jacob isp_pci_rd_reg, 11965adb54cSMatt Jacob isp_pci_wr_reg, 12065adb54cSMatt Jacob isp_pci_mbxdma, 12165adb54cSMatt Jacob isp_pci_dmasetup, 122d720e6d5SJustin T. Gibbs isp_pci_dmateardown, 12365adb54cSMatt Jacob NULL, 12465adb54cSMatt Jacob isp_pci_reset1, 12565adb54cSMatt Jacob isp_pci_dumpregs, 12665adb54cSMatt Jacob ISP2100_RISC_CODE, 12765adb54cSMatt Jacob ISP2100_CODE_LENGTH, 12865adb54cSMatt Jacob ISP2100_CODE_ORG, 12965adb54cSMatt Jacob ISP2100_CODE_VERSION, 130285e230dSMatt Jacob 0, /* Irrelevant to the 2100 */ 131d720e6d5SJustin T. Gibbs 0 13265adb54cSMatt Jacob }; 133d59bd469SMatt Jacob #endif 13465adb54cSMatt Jacob 135d951bbcaSMatt Jacob #ifndef SCSI_ISP_PREFER_MEM_MAP 136d951bbcaSMatt Jacob #ifdef __alpha__ 137d951bbcaSMatt Jacob #define SCSI_ISP_PREFER_MEM_MAP 0 138d951bbcaSMatt Jacob #else 139d951bbcaSMatt Jacob #define SCSI_ISP_PREFER_MEM_MAP 1 140d951bbcaSMatt Jacob #endif 141d951bbcaSMatt Jacob #endif 142d951bbcaSMatt Jacob 14365adb54cSMatt Jacob #ifndef PCIM_CMD_INVEN 14465adb54cSMatt Jacob #define PCIM_CMD_INVEN 0x10 14565adb54cSMatt Jacob #endif 14665adb54cSMatt Jacob #ifndef PCIM_CMD_BUSMASTEREN 14765adb54cSMatt Jacob #define PCIM_CMD_BUSMASTEREN 0x0004 14865adb54cSMatt Jacob #endif 149d951bbcaSMatt Jacob #ifndef PCIM_CMD_PERRESPEN 150d951bbcaSMatt Jacob #define PCIM_CMD_PERRESPEN 0x0040 151d951bbcaSMatt Jacob #endif 152d951bbcaSMatt Jacob #ifndef PCIM_CMD_SEREN 153d951bbcaSMatt Jacob #define PCIM_CMD_SEREN 0x0100 154d951bbcaSMatt Jacob #endif 155d951bbcaSMatt Jacob 156d951bbcaSMatt Jacob #ifndef PCIR_COMMAND 157d951bbcaSMatt Jacob #define PCIR_COMMAND 0x04 158d951bbcaSMatt Jacob #endif 159d951bbcaSMatt Jacob 160d951bbcaSMatt Jacob #ifndef PCIR_CACHELNSZ 161d951bbcaSMatt Jacob #define PCIR_CACHELNSZ 0x0c 162d951bbcaSMatt Jacob #endif 163d951bbcaSMatt Jacob 164d951bbcaSMatt Jacob #ifndef PCIR_LATTIMER 165d951bbcaSMatt Jacob #define PCIR_LATTIMER 0x0d 166d951bbcaSMatt Jacob #endif 167d951bbcaSMatt Jacob 168ab6d0040SMatt Jacob #ifndef PCIR_ROMADDR 169ab6d0040SMatt Jacob #define PCIR_ROMADDR 0x30 170ab6d0040SMatt Jacob #endif 171ab6d0040SMatt Jacob 17265adb54cSMatt Jacob #ifndef PCI_VENDOR_QLOGIC 17365adb54cSMatt Jacob #define PCI_VENDOR_QLOGIC 0x1077 17465adb54cSMatt Jacob #endif 17565adb54cSMatt Jacob 17665adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1020 17765adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 17865adb54cSMatt Jacob #endif 17965adb54cSMatt Jacob 180d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1080 181d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 182d59bd469SMatt Jacob #endif 183d59bd469SMatt Jacob 184d59bd469SMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP1240 185d59bd469SMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 186d59bd469SMatt Jacob #endif 18765adb54cSMatt Jacob 18865adb54cSMatt Jacob #ifndef PCI_PRODUCT_QLOGIC_ISP2100 18965adb54cSMatt Jacob #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 19065adb54cSMatt Jacob #endif 19165adb54cSMatt Jacob 192d59bd469SMatt Jacob #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) 193d59bd469SMatt Jacob 194d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1080 \ 195d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) 196d59bd469SMatt Jacob 197d59bd469SMatt Jacob #define PCI_QLOGIC_ISP1240 \ 198d59bd469SMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) 199d59bd469SMatt Jacob 20065adb54cSMatt Jacob #define PCI_QLOGIC_ISP2100 \ 20165adb54cSMatt Jacob ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) 20265adb54cSMatt Jacob 20365adb54cSMatt Jacob #define IO_MAP_REG 0x10 20465adb54cSMatt Jacob #define MEM_MAP_REG 0x14 20565adb54cSMatt Jacob 206d951bbcaSMatt Jacob #define PCI_DFLT_LTNCY 0x40 207d951bbcaSMatt Jacob #define PCI_DFLT_LNSZ 0x10 20865adb54cSMatt Jacob 209ab6d0040SMatt Jacob static PROBETYPE isp_pci_probe __P((pcici_t tag, pcidi_t type)); 21065adb54cSMatt Jacob static void isp_pci_attach __P((pcici_t config_d, int unit)); 21165adb54cSMatt Jacob 212d720e6d5SJustin T. Gibbs /* This distinguishing define is not right, but it does work */ 21365adb54cSMatt Jacob 2143dd37e43SMatt Jacob #if __FreeBSD_version < 300004 215a185f9b1SMatt Jacob #define IO_SPACE_MAPPING 0 216a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING 1 21765adb54cSMatt Jacob typedef int bus_space_tag_t; 21865adb54cSMatt Jacob typedef u_long bus_space_handle_t; 219ab6d0040SMatt Jacob typedef unsigned int __uintptr_t; 220ab6d0040SMatt Jacob typedef __uintptr_t uintptr_t; 221a185f9b1SMatt Jacob #ifdef __alpha__ 22265adb54cSMatt Jacob #define bus_space_read_2(st, sh, offset) \ 223d951bbcaSMatt Jacob alpha_mb(), 224a185f9b1SMatt Jacob (st == IO_SPACE_MAPPING)? \ 225a185f9b1SMatt Jacob inw((pci_port_t)sh + offset) : readw((pci_port_t)sh + offset) 22665adb54cSMatt Jacob #define bus_space_write_2(st, sh, offset, val) \ 227d951bbcaSMatt Jacob ((st == IO_SPACE_MAPPING)? outw((pci_port_t)sh + offset, val) : \ 228d951bbcaSMatt Jacob writew((pci_port_t)sh + offset, val)), alpha_mb() 229a185f9b1SMatt Jacob #else 230a185f9b1SMatt Jacob #define bus_space_read_2(st, sh, offset) \ 231a185f9b1SMatt Jacob (st == IO_SPACE_MAPPING)? \ 232a185f9b1SMatt Jacob inw((pci_port_t)sh + offset) : *((u_int16_t *)(uintptr_t)sh) 233a185f9b1SMatt Jacob #define bus_space_write_2(st, sh, offset, val) \ 234a185f9b1SMatt Jacob if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \ 235b97fc948SBruce Evans *((u_int16_t *)(uintptr_t)sh) = val 236d720e6d5SJustin T. Gibbs #endif 237a185f9b1SMatt Jacob #else 238a185f9b1SMatt Jacob #ifdef __alpha__ 239a185f9b1SMatt Jacob #define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO 240a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM 241a185f9b1SMatt Jacob #else 242a185f9b1SMatt Jacob #define IO_SPACE_MAPPING I386_BUS_SPACE_IO 243a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM 244a185f9b1SMatt Jacob #endif 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]; 2533dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 254d720e6d5SJustin T. Gibbs bus_dma_tag_t parent_dmat; 255d720e6d5SJustin T. Gibbs bus_dma_tag_t cntrol_dmat; 256d720e6d5SJustin T. Gibbs bus_dmamap_t cntrol_dmap; 257d720e6d5SJustin T. Gibbs bus_dmamap_t dmaps[MAXISPREQUEST]; 258d720e6d5SJustin T. Gibbs #endif 25965adb54cSMatt Jacob union { 26065adb54cSMatt Jacob sdparam _x; 26192c49d78SMatt Jacob fcparam _y; 26265adb54cSMatt Jacob } _z; 26365adb54cSMatt Jacob }; 26465adb54cSMatt Jacob 265d720e6d5SJustin T. Gibbs static u_long ispunit; 26665adb54cSMatt Jacob 26766235db5SEivind Eklund static struct pci_device isp_pci_driver = { 26865adb54cSMatt Jacob "isp", 26965adb54cSMatt Jacob isp_pci_probe, 27065adb54cSMatt Jacob isp_pci_attach, 271d720e6d5SJustin T. Gibbs &ispunit, 27265adb54cSMatt Jacob NULL 27365adb54cSMatt Jacob }; 27496b3554eSPeter Wemm #ifdef COMPAT_PCI_DRIVER 27596b3554eSPeter Wemm COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver); 27696b3554eSPeter Wemm #else 27765adb54cSMatt Jacob DATA_SET (pcidevice_set, isp_pci_driver); 27896b3554eSPeter Wemm #endif /* COMPAT_PCI_DRIVER */ 27965adb54cSMatt Jacob 28065adb54cSMatt Jacob 281ab6d0040SMatt Jacob static PROBETYPE 28217e318c6SMatt Jacob isp_pci_probe(pcici_t tag, pcidi_t type) 28365adb54cSMatt Jacob { 28465adb54cSMatt Jacob static int oneshot = 1; 28565adb54cSMatt Jacob char *x; 28665adb54cSMatt Jacob 28765adb54cSMatt Jacob switch (type) { 288d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 28965adb54cSMatt Jacob case PCI_QLOGIC_ISP: 290d59bd469SMatt Jacob x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 29165adb54cSMatt Jacob break; 292d59bd469SMatt Jacob #endif 293d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 294d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 295d59bd469SMatt Jacob #if 0 296d59bd469SMatt Jacob case PCI_QLOGIC_ISP1240: /* 1240 not ready yet */ 29792c49d78SMatt Jacob #endif 298d59bd469SMatt Jacob x = "Qlogic ISP 1080/1240 PCI SCSI Adapter"; 299d59bd469SMatt Jacob break; 300d59bd469SMatt Jacob #endif 301d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 30265adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 30365adb54cSMatt Jacob x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 30465adb54cSMatt Jacob break; 305d59bd469SMatt Jacob #endif 30665adb54cSMatt Jacob default: 30765adb54cSMatt Jacob return (NULL); 30865adb54cSMatt Jacob } 30965adb54cSMatt Jacob if (oneshot) { 31065adb54cSMatt Jacob oneshot = 0; 311d720e6d5SJustin T. Gibbs printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 312d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 313d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 31465adb54cSMatt Jacob } 31565adb54cSMatt Jacob return (x); 31665adb54cSMatt Jacob } 31765adb54cSMatt Jacob 31865adb54cSMatt Jacob 31965adb54cSMatt Jacob static void 32017e318c6SMatt Jacob isp_pci_attach(pcici_t config_id, int unit) 32165adb54cSMatt Jacob { 32265adb54cSMatt Jacob int mapped; 323a185f9b1SMatt Jacob pci_port_t io_port; 324ab6d0040SMatt Jacob u_int32_t data, linesz; 32565adb54cSMatt Jacob struct isp_pcisoftc *pcs; 32665adb54cSMatt Jacob struct ispsoftc *isp; 32765adb54cSMatt Jacob vm_offset_t vaddr, paddr; 32865adb54cSMatt Jacob ISP_LOCKVAL_DECL; 32965adb54cSMatt Jacob 33065adb54cSMatt Jacob 33165adb54cSMatt Jacob pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 33265adb54cSMatt Jacob if (pcs == NULL) { 3339bffbcd4SBruce Evans printf("isp%d: cannot allocate softc\n", unit); 33465adb54cSMatt Jacob return; 33565adb54cSMatt Jacob } 33665adb54cSMatt Jacob bzero(pcs, sizeof (struct isp_pcisoftc)); 33765adb54cSMatt Jacob 33865adb54cSMatt Jacob vaddr = paddr = NULL; 33965adb54cSMatt Jacob mapped = 0; 340ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 341d951bbcaSMatt Jacob /* 342d951bbcaSMatt Jacob * Note that pci_conf_read is a 32 bit word aligned function. 343d951bbcaSMatt Jacob */ 344d951bbcaSMatt Jacob data = pci_conf_read(config_id, PCIR_COMMAND); 345d951bbcaSMatt Jacob #if SCSI_ISP_PREFER_MEM_MAP == 1 346a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 347a185f9b1SMatt Jacob if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { 348a185f9b1SMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 349a185f9b1SMatt Jacob pcs->pci_sh = vaddr; 35065adb54cSMatt Jacob mapped++; 35165adb54cSMatt Jacob } 35265adb54cSMatt Jacob } 353a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 354a185f9b1SMatt Jacob if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { 355a185f9b1SMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 356a185f9b1SMatt Jacob pcs->pci_sh = io_port; 35765adb54cSMatt Jacob mapped++; 35865adb54cSMatt Jacob } 35965adb54cSMatt Jacob } 360d951bbcaSMatt Jacob #else 361d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 362d951bbcaSMatt Jacob if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { 363d951bbcaSMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 364d951bbcaSMatt Jacob pcs->pci_sh = io_port; 365d951bbcaSMatt Jacob mapped++; 366d951bbcaSMatt Jacob } 367d951bbcaSMatt Jacob } 368d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 369d951bbcaSMatt Jacob if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { 370d951bbcaSMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 371d951bbcaSMatt Jacob pcs->pci_sh = vaddr; 372d951bbcaSMatt Jacob mapped++; 373d951bbcaSMatt Jacob } 374d951bbcaSMatt Jacob } 375d951bbcaSMatt Jacob #endif 37665adb54cSMatt Jacob if (mapped == 0) { 3779bffbcd4SBruce Evans printf("isp%d: unable to map any ports!\n", unit); 37865adb54cSMatt Jacob free(pcs, M_DEVBUF); 37965adb54cSMatt Jacob return; 38065adb54cSMatt Jacob } 38165adb54cSMatt Jacob printf("isp%d: using %s space register mapping\n", unit, 382a185f9b1SMatt Jacob pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 38365adb54cSMatt Jacob 38465adb54cSMatt Jacob isp = &pcs->pci_isp; 3852fa86a2bSMatt Jacob #if __FreeBSD_version >= 300006 3862127f260SArchie Cobbs (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 3872fa86a2bSMatt Jacob #else 3882fa86a2bSMatt Jacob (void) sprintf(isp->isp_name, "isp%d", unit); 3892fa86a2bSMatt Jacob #endif 39065adb54cSMatt Jacob isp->isp_osinfo.unit = unit; 39165adb54cSMatt Jacob 39265adb54cSMatt Jacob data = pci_conf_read(config_id, PCI_ID_REG); 393d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 394d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 395d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 396d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 397d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 398d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 39965adb54cSMatt Jacob if (data == PCI_QLOGIC_ISP) { 40065adb54cSMatt Jacob isp->isp_mdvec = &mdvec; 40165adb54cSMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 40265adb54cSMatt Jacob isp->isp_param = &pcs->_z._x; 403d59bd469SMatt Jacob } 404d59bd469SMatt Jacob #endif 405d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 406d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP1080 || data == PCI_QLOGIC_ISP1240) { 407d59bd469SMatt Jacob isp->isp_mdvec = &mdvec_1080; 408d59bd469SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 409d59bd469SMatt Jacob isp->isp_param = &pcs->_z._x; 410d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 411d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 412d59bd469SMatt Jacob } 413d59bd469SMatt Jacob #endif 414d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 415d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP2100) { 41665adb54cSMatt Jacob isp->isp_mdvec = &mdvec_2100; 41765adb54cSMatt Jacob isp->isp_type = ISP_HA_FC_2100; 41892c49d78SMatt Jacob isp->isp_param = &pcs->_z._y; 419d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 420d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 421ab6d0040SMatt Jacob 422ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCI_CLASS_REG); 423ab6d0040SMatt Jacob if ((data & 0xff) < 3) { 424ab6d0040SMatt Jacob /* 425ab6d0040SMatt Jacob * XXX: Need to get the actual revision 426ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 427ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 428ab6d0040SMatt Jacob * XXX; boards. 429ab6d0040SMatt Jacob */ 430ab6d0040SMatt Jacob linesz = 1; 431ab6d0040SMatt Jacob } 43265adb54cSMatt Jacob } 433d59bd469SMatt Jacob #endif 43465adb54cSMatt Jacob 4353dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 436d951bbcaSMatt Jacob ISP_LOCK(isp); 437ab6d0040SMatt Jacob 438d951bbcaSMatt Jacob /* 439d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 440d951bbcaSMatt Jacob * are set. 441d951bbcaSMatt Jacob */ 442d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_COMMAND, 2); 443d951bbcaSMatt Jacob data |= PCIM_CMD_SEREN | 444d951bbcaSMatt Jacob PCIM_CMD_PERRESPEN | 445d951bbcaSMatt Jacob PCIM_CMD_BUSMASTEREN | 446d951bbcaSMatt Jacob PCIM_CMD_INVEN; 447d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_COMMAND, 2, data); 448ab6d0040SMatt Jacob 449d951bbcaSMatt Jacob /* 450d951bbcaSMatt Jacob * Make sure the CACHE Line Size register is set sensibly. 451d951bbcaSMatt Jacob */ 452d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_CACHELNSZ, 1); 453ab6d0040SMatt Jacob if (data != linesz) { 454d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 455d951bbcaSMatt Jacob printf("%s: set PCI line size to %d\n", isp->isp_name, data); 456d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_CACHELNSZ, data, 1); 457d951bbcaSMatt Jacob } 458ab6d0040SMatt Jacob 459d951bbcaSMatt Jacob /* 460d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 461d951bbcaSMatt Jacob */ 462d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_LATTIMER, 1); 463d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 464d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 465d951bbcaSMatt Jacob printf("%s: set PCI latency to %d\n", isp->isp_name, data); 466d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_LATTIMER, data, 1); 467d951bbcaSMatt Jacob } 468ab6d0040SMatt Jacob 469ab6d0040SMatt Jacob /* 470ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 471ab6d0040SMatt Jacob */ 472ab6d0040SMatt Jacob data = pci_cfgread(config_id, PCIR_ROMADDR, 4); 473ab6d0040SMatt Jacob data &= ~1; 474ab6d0040SMatt Jacob pci_cfgwrite(config_id, PCIR_ROMADDR, data, 4); 475ab6d0040SMatt Jacob 476d951bbcaSMatt Jacob ISP_UNLOCK(isp); 477d951bbcaSMatt Jacob 478d720e6d5SJustin T. Gibbs if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT, 479d720e6d5SJustin T. Gibbs BUS_SPACE_MAXADDR, NULL, NULL, 1<<24, 480d720e6d5SJustin T. Gibbs 255, 1<<24, 0, &pcs->parent_dmat) != 0) { 481d720e6d5SJustin T. Gibbs printf("%s: could not create master dma tag\n", isp->isp_name); 482d720e6d5SJustin T. Gibbs free(pcs, M_DEVBUF); 483d720e6d5SJustin T. Gibbs return; 484d720e6d5SJustin T. Gibbs } 485ab6d0040SMatt Jacob #else 486ab6d0040SMatt Jacob ISP_LOCK(isp); 487ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_COMMAND); 488ab6d0040SMatt Jacob data |= PCIM_CMD_SEREN | 489ab6d0040SMatt Jacob PCIM_CMD_PERRESPEN | 490ab6d0040SMatt Jacob PCIM_CMD_BUSMASTEREN | 491ab6d0040SMatt Jacob PCIM_CMD_INVEN; 492ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_COMMAND, data); 493ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_CACHELNSZ); 494ab6d0040SMatt Jacob if ((data & ~0xffff) != ((PCI_DFLT_LTNCY << 8) | linesz)) { 495ab6d0040SMatt Jacob data &= ~0xffff; 496ab6d0040SMatt Jacob data |= (PCI_DFLT_LTNCY << 8) | linesz; 497ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_CACHELNSZ, data); 498ab6d0040SMatt Jacob printf("%s: set PCI line size to %d\n", isp->isp_name, linesz); 499ab6d0040SMatt Jacob printf("%s: set PCI latency to %d\n", isp->isp_name, 500ab6d0040SMatt Jacob PCI_DFLT_LTNCY); 501ab6d0040SMatt Jacob } 502d951bbcaSMatt Jacob 503ab6d0040SMatt Jacob /* 504ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 505ab6d0040SMatt Jacob */ 506ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_ROMADDR); 507ab6d0040SMatt Jacob data &= ~1; 508ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_ROMADDR, data); 509ab6d0040SMatt Jacob ISP_UNLOCK(isp); 510d720e6d5SJustin T. Gibbs #endif 51165adb54cSMatt Jacob if (pci_map_int(config_id, (void (*)(void *))isp_intr, 51265adb54cSMatt Jacob (void *)isp, &IMASK) == 0) { 5139bffbcd4SBruce Evans printf("%s: could not map interrupt\n", isp->isp_name); 51465adb54cSMatt Jacob free(pcs, M_DEVBUF); 51565adb54cSMatt Jacob return; 51665adb54cSMatt Jacob } 51765adb54cSMatt Jacob 51865adb54cSMatt Jacob pcs->pci_id = config_id; 519d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_FWLOAD_MASK 520d951bbcaSMatt Jacob if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 521d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 522d951bbcaSMatt Jacob #endif 523d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_NVRAM_MASK 524ab6d0040SMatt Jacob if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 525ab6d0040SMatt Jacob printf("%s: ignoring NVRAM\n", isp->isp_name); 526d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 527ab6d0040SMatt Jacob } 528d951bbcaSMatt Jacob #endif 529d720e6d5SJustin T. Gibbs ISP_LOCK(isp); 53065adb54cSMatt Jacob isp_reset(isp); 53165adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 532d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 53365adb54cSMatt Jacob free(pcs, M_DEVBUF); 53465adb54cSMatt Jacob return; 53565adb54cSMatt Jacob } 53665adb54cSMatt Jacob isp_init(isp); 53765adb54cSMatt Jacob if (isp->isp_state != ISP_INITSTATE) { 538d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 539d59bd469SMatt Jacob if (isp->isp_type & ISP_HA_SCSI) { 54065adb54cSMatt Jacob isp_uninit(isp); 54165adb54cSMatt Jacob free(pcs, M_DEVBUF); 542d59bd469SMatt Jacob } 54365adb54cSMatt Jacob } 54465adb54cSMatt Jacob isp_attach(isp); 54565adb54cSMatt Jacob if (isp->isp_state != ISP_RUNSTATE) { 546d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 54792c49d78SMatt Jacob if (IS_SCSI(isp)) { 54865adb54cSMatt Jacob isp_uninit(isp); 54965adb54cSMatt Jacob free(pcs, M_DEVBUF); 55065adb54cSMatt Jacob } 551d59bd469SMatt Jacob } 552d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 553e37c0455SDoug Rabson #ifdef __alpha__ 554d951bbcaSMatt Jacob /* 555d951bbcaSMatt Jacob * THIS SHOULD NOT HAVE TO BE HERE 556d951bbcaSMatt Jacob */ 557e37c0455SDoug Rabson alpha_register_pci_scsi(config_id->bus, config_id->slot, isp->isp_sim); 558e37c0455SDoug Rabson #endif 55965adb54cSMatt Jacob } 56065adb54cSMatt Jacob 56165adb54cSMatt Jacob static u_int16_t 562d59bd469SMatt Jacob isp_pci_rd_reg(isp, regoff) 563d59bd469SMatt Jacob struct ispsoftc *isp; 564d59bd469SMatt Jacob int regoff; 56565adb54cSMatt Jacob { 56665adb54cSMatt Jacob u_int16_t rv; 56765adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 568d59bd469SMatt Jacob int offset, oldconf = 0; 56965adb54cSMatt Jacob 570d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 57165adb54cSMatt Jacob /* 57265adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 57365adb54cSMatt Jacob */ 574d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 575d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 57665adb54cSMatt Jacob } 577d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 578d59bd469SMatt Jacob offset += (regoff & 0xff); 57965adb54cSMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 580d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 581d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 58265adb54cSMatt Jacob } 58365adb54cSMatt Jacob return (rv); 58465adb54cSMatt Jacob } 58565adb54cSMatt Jacob 58665adb54cSMatt Jacob static void 587d59bd469SMatt Jacob isp_pci_wr_reg(isp, regoff, val) 588d59bd469SMatt Jacob struct ispsoftc *isp; 589d59bd469SMatt Jacob int regoff; 590d59bd469SMatt Jacob u_int16_t val; 59165adb54cSMatt Jacob { 59265adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 593d59bd469SMatt Jacob int offset, oldconf = 0; 594d59bd469SMatt Jacob 595d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 59665adb54cSMatt Jacob /* 59765adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 59865adb54cSMatt Jacob */ 599d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 600d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 60165adb54cSMatt Jacob } 602d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 603d59bd469SMatt Jacob offset += (regoff & 0xff); 60465adb54cSMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 605d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 606d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 60765adb54cSMatt Jacob } 60865adb54cSMatt Jacob } 60965adb54cSMatt Jacob 610d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 611d59bd469SMatt Jacob static u_int16_t 612d59bd469SMatt Jacob isp_pci_rd_reg_1080(isp, regoff) 613d59bd469SMatt Jacob struct ispsoftc *isp; 614d59bd469SMatt Jacob int regoff; 615d59bd469SMatt Jacob { 616d59bd469SMatt Jacob u_int16_t rv; 617d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 618d59bd469SMatt Jacob int offset, oc = 0; 619d59bd469SMatt Jacob 620d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 621d59bd469SMatt Jacob /* 622d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 623d59bd469SMatt Jacob */ 624d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 625d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 626d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 627d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 628d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 629d59bd469SMatt Jacob } 630d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 631d59bd469SMatt Jacob offset += (regoff & 0xff); 632d59bd469SMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 633d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 634d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 635d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 636d59bd469SMatt Jacob } 637d59bd469SMatt Jacob return (rv); 638d59bd469SMatt Jacob } 639d59bd469SMatt Jacob 640d59bd469SMatt Jacob static void 641d59bd469SMatt Jacob isp_pci_wr_reg_1080(isp, regoff, val) 642d59bd469SMatt Jacob struct ispsoftc *isp; 643d59bd469SMatt Jacob int regoff; 644d59bd469SMatt Jacob u_int16_t val; 645d59bd469SMatt Jacob { 646d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 647d59bd469SMatt Jacob int offset, oc = 0; 648d59bd469SMatt Jacob 649d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 650d59bd469SMatt Jacob /* 651d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 652d59bd469SMatt Jacob */ 653d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 654d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 655d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 656d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 657d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 658d59bd469SMatt Jacob } 659d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 660d59bd469SMatt Jacob offset += (regoff & 0xff); 661d59bd469SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 662d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 663d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 664d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 665d59bd469SMatt Jacob } 666d59bd469SMatt Jacob } 667d59bd469SMatt Jacob #endif 668d59bd469SMatt Jacob 669d59bd469SMatt Jacob 6703dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 671d720e6d5SJustin T. Gibbs static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 672d720e6d5SJustin T. Gibbs static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 673d720e6d5SJustin T. Gibbs static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 674d720e6d5SJustin T. Gibbs 675d720e6d5SJustin T. Gibbs static void 67617e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 677d720e6d5SJustin T. Gibbs { 678d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 679d720e6d5SJustin T. Gibbs isp->isp_rquest_dma = segs->ds_addr; 680d720e6d5SJustin T. Gibbs } 681d720e6d5SJustin T. Gibbs 682d720e6d5SJustin T. Gibbs static void 68317e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 684d720e6d5SJustin T. Gibbs { 685d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 686d720e6d5SJustin T. Gibbs isp->isp_result_dma = segs->ds_addr; 687d720e6d5SJustin T. Gibbs } 688d720e6d5SJustin T. Gibbs 689d720e6d5SJustin T. Gibbs static void 69017e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 691d720e6d5SJustin T. Gibbs { 692d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 693d720e6d5SJustin T. Gibbs fcparam *fcp = isp->isp_param; 694d720e6d5SJustin T. Gibbs fcp->isp_scdma = segs->ds_addr; 695d720e6d5SJustin T. Gibbs } 696d720e6d5SJustin T. Gibbs 697d720e6d5SJustin T. Gibbs static int 69817e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 699d720e6d5SJustin T. Gibbs { 700d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 701d720e6d5SJustin T. Gibbs caddr_t base; 702d720e6d5SJustin T. Gibbs u_int32_t len; 703d720e6d5SJustin T. Gibbs int i, error; 704d720e6d5SJustin T. Gibbs 705d720e6d5SJustin T. Gibbs /* 706d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 707d720e6d5SJustin T. Gibbs */ 708d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 709d720e6d5SJustin T. Gibbs len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 710d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 711d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 712d720e6d5SJustin T. Gibbs } 713d720e6d5SJustin T. Gibbs if (bus_dma_tag_create(pci->parent_dmat, 0, 0, BUS_SPACE_MAXADDR, 714d720e6d5SJustin T. Gibbs BUS_SPACE_MAXADDR, NULL, NULL, len, 1, BUS_SPACE_MAXSIZE_32BIT, 715d720e6d5SJustin T. Gibbs 0, &pci->cntrol_dmat) != 0) { 716d720e6d5SJustin T. Gibbs printf("%s: cannot create a dma tag for control spaces\n", 717d720e6d5SJustin T. Gibbs isp->isp_name); 718d720e6d5SJustin T. Gibbs return (1); 719d720e6d5SJustin T. Gibbs } 720d720e6d5SJustin T. Gibbs if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 721d720e6d5SJustin T. Gibbs BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 7224873663cSMatt Jacob printf("%s: cannot allocate %d bytes of CCB memory\n", 7234873663cSMatt Jacob isp->isp_name, len); 724d720e6d5SJustin T. Gibbs return (1); 725d720e6d5SJustin T. Gibbs } 726d720e6d5SJustin T. Gibbs 727d720e6d5SJustin T. Gibbs isp->isp_rquest = base; 728d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 729d720e6d5SJustin T. Gibbs ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, pci, 0); 730d720e6d5SJustin T. Gibbs 731d720e6d5SJustin T. Gibbs isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 732d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 733d720e6d5SJustin T. Gibbs ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, pci, 0); 734d720e6d5SJustin T. Gibbs 735d720e6d5SJustin T. Gibbs /* 736d720e6d5SJustin T. Gibbs * Use this opportunity to initialize/create data DMA maps. 737d720e6d5SJustin T. Gibbs */ 738d720e6d5SJustin T. Gibbs for (i = 0; i < MAXISPREQUEST; i++) { 739d720e6d5SJustin T. Gibbs error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 740d720e6d5SJustin T. Gibbs if (error) { 7414873663cSMatt Jacob printf("%s: error %d creating mailbox DMA maps\n", 742d720e6d5SJustin T. Gibbs isp->isp_name, error); 743d720e6d5SJustin T. Gibbs return (1); 744d720e6d5SJustin T. Gibbs } 745d720e6d5SJustin T. Gibbs } 74692c49d78SMatt Jacob 74792c49d78SMatt Jacob if (isp->isp_type & ISP_HA_FC) { 74892c49d78SMatt Jacob fcparam *fcp = (fcparam *) isp->isp_param; 74992c49d78SMatt Jacob fcp->isp_scratch = base + 75092c49d78SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 75192c49d78SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 75292c49d78SMatt Jacob bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 75392c49d78SMatt Jacob fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, pci, 0); 75492c49d78SMatt Jacob } 755d720e6d5SJustin T. Gibbs return (0); 756d720e6d5SJustin T. Gibbs } 757d720e6d5SJustin T. Gibbs 758d720e6d5SJustin T. Gibbs static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 759d720e6d5SJustin T. Gibbs typedef struct { 760d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 761d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 762d720e6d5SJustin T. Gibbs ispreq_t *rq; 763d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 764d720e6d5SJustin T. Gibbs u_int8_t optr; 765d720e6d5SJustin T. Gibbs u_int error; 766d720e6d5SJustin T. Gibbs } mush_t; 767d720e6d5SJustin T. Gibbs 7684873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 7694873663cSMatt Jacob 770d720e6d5SJustin T. Gibbs static void 77117e318c6SMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 772d720e6d5SJustin T. Gibbs { 773d720e6d5SJustin T. Gibbs mush_t *mp; 774d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 775d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 776d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci; 777d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 778d720e6d5SJustin T. Gibbs bus_dma_segment_t *eseg; 779d720e6d5SJustin T. Gibbs ispreq_t *rq; 780d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 781d720e6d5SJustin T. Gibbs u_int8_t optr; 782d720e6d5SJustin T. Gibbs ispcontreq_t *crq; 783d720e6d5SJustin T. Gibbs int drq, seglim, datalen; 784d720e6d5SJustin T. Gibbs 785d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 786d720e6d5SJustin T. Gibbs if (error) { 787d720e6d5SJustin T. Gibbs mp->error = error; 788d720e6d5SJustin T. Gibbs return; 789d720e6d5SJustin T. Gibbs } 790d720e6d5SJustin T. Gibbs 791d720e6d5SJustin T. Gibbs isp = mp->isp; 792d720e6d5SJustin T. Gibbs if (nseg < 1) { 793d720e6d5SJustin T. Gibbs printf("%s: zero or negative segment count\n", isp->isp_name); 794d720e6d5SJustin T. Gibbs mp->error = EFAULT; 795d720e6d5SJustin T. Gibbs return; 796d720e6d5SJustin T. Gibbs } 797d720e6d5SJustin T. Gibbs ccb = mp->ccb; 798d720e6d5SJustin T. Gibbs rq = mp->rq; 799d720e6d5SJustin T. Gibbs iptrp = mp->iptrp; 800d720e6d5SJustin T. Gibbs optr = mp->optr; 801d720e6d5SJustin T. Gibbs 802d720e6d5SJustin T. Gibbs pci = (struct isp_pcisoftc *)isp; 803d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 804d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 805d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 806d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_IN; 807d720e6d5SJustin T. Gibbs } else { 808d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 809d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_OUT; 810d720e6d5SJustin T. Gibbs } 811d720e6d5SJustin T. Gibbs 812d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(ccb); 813d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 814d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 815d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 816d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_flags |= drq; 817d720e6d5SJustin T. Gibbs } else { 818d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 819d720e6d5SJustin T. Gibbs rq->req_flags |= drq; 820d720e6d5SJustin T. Gibbs } 821d720e6d5SJustin T. Gibbs 822d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 823d720e6d5SJustin T. Gibbs 824d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 825d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 826d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 827d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 828d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 829d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 830d720e6d5SJustin T. Gibbs dm_segs->ds_len; 831d720e6d5SJustin T. Gibbs } else { 832d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 833d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 834d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 835d720e6d5SJustin T. Gibbs dm_segs->ds_len; 836d720e6d5SJustin T. Gibbs } 837d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 838d720e6d5SJustin T. Gibbs #if 0 839d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 840d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 841d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 842d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 843d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count, 844d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base); 845d720e6d5SJustin T. Gibbs } else { 846d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 847d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 848d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count, 849d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base); 850d720e6d5SJustin T. Gibbs } 851d720e6d5SJustin T. Gibbs #endif 852d720e6d5SJustin T. Gibbs rq->req_seg_count++; 853d720e6d5SJustin T. Gibbs dm_segs++; 854d720e6d5SJustin T. Gibbs } 855d720e6d5SJustin T. Gibbs 856d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 857d720e6d5SJustin T. Gibbs crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 8584873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 859d720e6d5SJustin T. Gibbs if (*iptrp == optr) { 8604873663cSMatt Jacob #if 0 8614873663cSMatt Jacob printf("%s: Request Queue Overflow++\n", isp->isp_name); 8624873663cSMatt Jacob #endif 8634873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 864d720e6d5SJustin T. Gibbs return; 865d720e6d5SJustin T. Gibbs } 866d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 867d720e6d5SJustin T. Gibbs bzero((void *)crq, sizeof (*crq)); 868d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 869d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 870d720e6d5SJustin T. Gibbs 871d720e6d5SJustin T. Gibbs seglim = 0; 872d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 873d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 874d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 875d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 876d720e6d5SJustin T. Gibbs dm_segs->ds_len; 877d720e6d5SJustin T. Gibbs #if 0 878d720e6d5SJustin T. Gibbs printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 879d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_header.rqs_entry_count-1, 880d720e6d5SJustin T. Gibbs seglim, crq->req_dataseg[seglim].ds_count, 881d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base); 882d720e6d5SJustin T. Gibbs #endif 883d720e6d5SJustin T. Gibbs rq->req_seg_count++; 884d720e6d5SJustin T. Gibbs dm_segs++; 885d720e6d5SJustin T. Gibbs seglim++; 886d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 887d720e6d5SJustin T. Gibbs } 888d720e6d5SJustin T. Gibbs } 889d720e6d5SJustin T. Gibbs } 890d720e6d5SJustin T. Gibbs 891d720e6d5SJustin T. Gibbs static int 89217e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 89317e318c6SMatt Jacob u_int8_t *iptrp, u_int8_t optr) 894d720e6d5SJustin T. Gibbs { 895d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 896d720e6d5SJustin T. Gibbs struct ccb_hdr *ccb_h; 897d720e6d5SJustin T. Gibbs struct ccb_scsiio *csio; 898d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 899d720e6d5SJustin T. Gibbs mush_t mush, *mp; 900d720e6d5SJustin T. Gibbs 901d720e6d5SJustin T. Gibbs csio = (struct ccb_scsiio *) ccb; 902d720e6d5SJustin T. Gibbs ccb_h = &csio->ccb_h; 903d720e6d5SJustin T. Gibbs 904d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 905d720e6d5SJustin T. Gibbs rq->req_seg_count = 1; 9064873663cSMatt Jacob return (CMD_QUEUED); 907d720e6d5SJustin T. Gibbs } 908d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 909d720e6d5SJustin T. Gibbs 910d720e6d5SJustin T. Gibbs /* 911d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 9124873663cSMatt Jacob * the callback dma allocation that we have to use... 913d720e6d5SJustin T. Gibbs */ 914d720e6d5SJustin T. Gibbs mp = &mush; 915d720e6d5SJustin T. Gibbs mp->isp = isp; 916d720e6d5SJustin T. Gibbs mp->ccb = ccb; 917d720e6d5SJustin T. Gibbs mp->rq = rq; 918d720e6d5SJustin T. Gibbs mp->iptrp = iptrp; 919d720e6d5SJustin T. Gibbs mp->optr = optr; 920d720e6d5SJustin T. Gibbs mp->error = 0; 921d720e6d5SJustin T. Gibbs 922d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 923d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 9244873663cSMatt Jacob int error, s; 9254873663cSMatt Jacob 926d720e6d5SJustin T. Gibbs s = splsoftvm(); 927d720e6d5SJustin T. Gibbs error = bus_dmamap_load(pci->parent_dmat, *dp, 928d720e6d5SJustin T. Gibbs csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 929d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 930d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 931d720e6d5SJustin T. Gibbs mp->error = EINVAL; 9324873663cSMatt Jacob printf("%s: deferred dma allocation not " 9334873663cSMatt Jacob "supported\n", isp->isp_name); 934d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 935d720e6d5SJustin T. Gibbs mp->error = error; 936d720e6d5SJustin T. Gibbs } 9374873663cSMatt Jacob splx(s); 938d720e6d5SJustin T. Gibbs } else { 939d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 940d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 941d720e6d5SJustin T. Gibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 942d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 943d720e6d5SJustin T. Gibbs dma2(mp, &seg, 1, 0); 944d720e6d5SJustin T. Gibbs } 945d720e6d5SJustin T. Gibbs } else { 946d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 947d720e6d5SJustin T. Gibbs 948d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 949d720e6d5SJustin T. Gibbs printf("%s: Physical segment pointers unsupported", 950d720e6d5SJustin T. Gibbs isp->isp_name); 951d720e6d5SJustin T. Gibbs mp->error = EINVAL; 952d720e6d5SJustin T. Gibbs } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 953d720e6d5SJustin T. Gibbs printf("%s: Virtual segment addresses unsupported", 954d720e6d5SJustin T. Gibbs isp->isp_name); 955d720e6d5SJustin T. Gibbs mp->error = EINVAL; 956d720e6d5SJustin T. Gibbs } else { 957d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 958d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 959d720e6d5SJustin T. Gibbs dma2(mp, segs, csio->sglist_cnt, 0); 960d720e6d5SJustin T. Gibbs } 961d720e6d5SJustin T. Gibbs } 962d720e6d5SJustin T. Gibbs if (mp->error) { 9634873663cSMatt Jacob int retval = CMD_COMPLETE; 9644873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 9654873663cSMatt Jacob retval = CMD_EAGAIN; 9664873663cSMatt Jacob ccb_h->status = CAM_UNREC_HBA_ERROR; 9674873663cSMatt Jacob } else if (mp->error == EFBIG) { 968d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_TOO_BIG; 969d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 970d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_INVALID; 971d720e6d5SJustin T. Gibbs } else { 972d720e6d5SJustin T. Gibbs ccb_h->status = CAM_UNREC_HBA_ERROR; 973d720e6d5SJustin T. Gibbs } 9744873663cSMatt Jacob return (retval); 9754873663cSMatt Jacob } else { 9764873663cSMatt Jacob return (CMD_QUEUED); 977d720e6d5SJustin T. Gibbs } 978d720e6d5SJustin T. Gibbs } 979d720e6d5SJustin T. Gibbs 980d720e6d5SJustin T. Gibbs static void 98117e318c6SMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, 98217e318c6SMatt Jacob u_int32_t handle) 983d720e6d5SJustin T. Gibbs { 984d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 985d720e6d5SJustin T. Gibbs bus_dmamap_t *dp = &pci->dmaps[handle]; 986d720e6d5SJustin T. Gibbs 987d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 988d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 989d720e6d5SJustin T. Gibbs } else { 990d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 991d720e6d5SJustin T. Gibbs } 992d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 993d720e6d5SJustin T. Gibbs } 994d720e6d5SJustin T. Gibbs 9953dd37e43SMatt Jacob #else /* __FreeBSD_version >= 300004 */ 9963dd37e43SMatt Jacob 997d720e6d5SJustin T. Gibbs 99865adb54cSMatt Jacob static int 99917e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 100065adb54cSMatt Jacob { 100165adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 100265adb54cSMatt Jacob u_int32_t len; 100365adb54cSMatt Jacob int rseg; 100465adb54cSMatt Jacob 100565adb54cSMatt Jacob /* XXXX CHECK FOR ALIGNMENT */ 100665adb54cSMatt Jacob /* 100765adb54cSMatt Jacob * Allocate and map the request queue. 100865adb54cSMatt Jacob */ 1009d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 101065adb54cSMatt Jacob isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT); 101165adb54cSMatt Jacob if (isp->isp_rquest == NULL) { 101265adb54cSMatt Jacob printf("%s: cannot malloc request queue\n", isp->isp_name); 101365adb54cSMatt Jacob return (1); 101465adb54cSMatt Jacob } 101565adb54cSMatt Jacob isp->isp_rquest_dma = vtophys(isp->isp_rquest); 101665adb54cSMatt Jacob 101765adb54cSMatt Jacob #if 0 101865adb54cSMatt Jacob printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma); 101965adb54cSMatt Jacob #endif 102065adb54cSMatt Jacob 102165adb54cSMatt Jacob /* 102265adb54cSMatt Jacob * Allocate and map the result queue. 102365adb54cSMatt Jacob */ 1024d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 102565adb54cSMatt Jacob isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT); 102665adb54cSMatt Jacob if (isp->isp_result == NULL) { 102765adb54cSMatt Jacob free(isp->isp_rquest, M_DEVBUF); 102865adb54cSMatt Jacob printf("%s: cannot malloc result queue\n", isp->isp_name); 102965adb54cSMatt Jacob return (1); 103065adb54cSMatt Jacob } 103165adb54cSMatt Jacob isp->isp_result_dma = vtophys(isp->isp_result); 103265adb54cSMatt Jacob #if 0 103365adb54cSMatt Jacob printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma); 103465adb54cSMatt Jacob #endif 103565adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 103665adb54cSMatt Jacob fcparam *fcp = isp->isp_param; 103765adb54cSMatt Jacob len = ISP2100_SCRLEN; 1038ab6d0040SMatt Jacob fcp->isp_scratch = (volatile caddr_t) 1039ab6d0040SMatt Jacob malloc(ISP2100_SCRLEN, M_DEVBUF, M_NOWAIT); 1040ab6d0040SMatt Jacob if (fcp->isp_scratch == NULL) { 1041ab6d0040SMatt Jacob printf("%s: cannot alloc scratch\n", isp->isp_name); 1042ab6d0040SMatt Jacob return (1); 1043ab6d0040SMatt Jacob } 104465adb54cSMatt Jacob fcp->isp_scdma = vtophys(fcp->isp_scratch); 104565adb54cSMatt Jacob } 104665adb54cSMatt Jacob return (0); 104765adb54cSMatt Jacob } 104865adb54cSMatt Jacob 104965adb54cSMatt Jacob static int 105017e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, 105117e318c6SMatt Jacob ispreq_t *rq, u_int8_t *iptrp, u_int8_t optr) 105265adb54cSMatt Jacob { 105365adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 105465adb54cSMatt Jacob ispcontreq_t *crq; 105565adb54cSMatt Jacob vm_offset_t vaddr; 105665adb54cSMatt Jacob int drq, seglim; 105765adb54cSMatt Jacob u_int32_t paddr, nextpaddr, datalen, size, *ctrp; 105865adb54cSMatt Jacob 105965adb54cSMatt Jacob if (xs->datalen == 0) { 106065adb54cSMatt Jacob rq->req_seg_count = 1; 10614873663cSMatt Jacob return (CMD_QUEUED); 106265adb54cSMatt Jacob } 106365adb54cSMatt Jacob 106465adb54cSMatt Jacob if (xs->flags & SCSI_DATA_IN) { 106565adb54cSMatt Jacob drq = REQFLAG_DATA_IN; 106665adb54cSMatt Jacob } else { 106765adb54cSMatt Jacob drq = REQFLAG_DATA_OUT; 106865adb54cSMatt Jacob } 106965adb54cSMatt Jacob 107065adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 107165adb54cSMatt Jacob seglim = ISP_RQDSEG_T2; 1072d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs); 107365adb54cSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= drq; 107465adb54cSMatt Jacob } else { 107565adb54cSMatt Jacob seglim = ISP_RQDSEG; 107665adb54cSMatt Jacob rq->req_flags |= drq; 107765adb54cSMatt Jacob } 107865adb54cSMatt Jacob 1079d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(xs); 108065adb54cSMatt Jacob vaddr = (vm_offset_t) xs->data; 108165adb54cSMatt Jacob paddr = vtophys(vaddr); 108265adb54cSMatt Jacob 108365adb54cSMatt Jacob while (datalen != 0 && rq->req_seg_count < seglim) { 108465adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 108565adb54cSMatt Jacob ispreqt2_t *rq2 = (ispreqt2_t *)rq; 108665adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr; 108765adb54cSMatt Jacob ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count; 108865adb54cSMatt Jacob } else { 108965adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_base = paddr; 109065adb54cSMatt Jacob ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count; 109165adb54cSMatt Jacob } 109265adb54cSMatt Jacob nextpaddr = paddr; 109365adb54cSMatt Jacob *(ctrp) = 0; 109465adb54cSMatt Jacob 109565adb54cSMatt Jacob while (datalen != 0 && paddr == nextpaddr) { 109665adb54cSMatt Jacob nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 109765adb54cSMatt Jacob size = nextpaddr - paddr; 109865adb54cSMatt Jacob if (size > datalen) 109965adb54cSMatt Jacob size = datalen; 110065adb54cSMatt Jacob *(ctrp) += size; 110165adb54cSMatt Jacob vaddr += size; 110265adb54cSMatt Jacob datalen -= size; 110365adb54cSMatt Jacob if (datalen != 0) 110465adb54cSMatt Jacob paddr = vtophys(vaddr); 110565adb54cSMatt Jacob 110665adb54cSMatt Jacob } 110765adb54cSMatt Jacob #if 0 110865adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 110965adb54cSMatt Jacob ispreqt2_t *rq2 = (ispreqt2_t *)rq; 111065adb54cSMatt Jacob printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 111165adb54cSMatt Jacob isp->isp_name, rq->req_seg_count, 111265adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_count, 111365adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_base); 111465adb54cSMatt Jacob } else { 111565adb54cSMatt Jacob printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 111665adb54cSMatt Jacob isp->isp_name, rq->req_seg_count, 111765adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_count, 111865adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_base); 111965adb54cSMatt Jacob } 112065adb54cSMatt Jacob #endif 112165adb54cSMatt Jacob rq->req_seg_count++; 112265adb54cSMatt Jacob } 112365adb54cSMatt Jacob 112465adb54cSMatt Jacob 112565adb54cSMatt Jacob 112665adb54cSMatt Jacob if (datalen == 0) 11274873663cSMatt Jacob return (CMD_QUEUED); 112865adb54cSMatt Jacob 112965adb54cSMatt Jacob paddr = vtophys(vaddr); 113065adb54cSMatt Jacob while (datalen > 0) { 113165adb54cSMatt Jacob crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 11324873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 113365adb54cSMatt Jacob if (*iptrp == optr) { 113465adb54cSMatt Jacob printf("%s: Request Queue Overflow\n", isp->isp_name); 1135d720e6d5SJustin T. Gibbs XS_SETERR(xs, HBA_BOTCH); 11364873663cSMatt Jacob return (CMD_EAGAIN); 113765adb54cSMatt Jacob } 113865adb54cSMatt Jacob rq->req_header.rqs_entry_count++; 113965adb54cSMatt Jacob bzero((void *)crq, sizeof (*crq)); 114065adb54cSMatt Jacob crq->req_header.rqs_entry_count = 1; 114165adb54cSMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 114265adb54cSMatt Jacob 114365adb54cSMatt Jacob for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) { 114465adb54cSMatt Jacob crq->req_dataseg[seglim].ds_base = paddr; 114565adb54cSMatt Jacob ctrp = &crq->req_dataseg[seglim].ds_count; 114665adb54cSMatt Jacob *(ctrp) = 0; 114765adb54cSMatt Jacob nextpaddr = paddr; 114865adb54cSMatt Jacob while (datalen != 0 && paddr == nextpaddr) { 114965adb54cSMatt Jacob nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 115065adb54cSMatt Jacob size = nextpaddr - paddr; 115165adb54cSMatt Jacob if (size > datalen) 115265adb54cSMatt Jacob size = datalen; 115365adb54cSMatt Jacob *(ctrp) += size; 115465adb54cSMatt Jacob vaddr += size; 115565adb54cSMatt Jacob datalen -= size; 115665adb54cSMatt Jacob if (datalen != 0) 115765adb54cSMatt Jacob paddr = vtophys(vaddr); 115865adb54cSMatt Jacob } 115965adb54cSMatt Jacob #if 0 116065adb54cSMatt Jacob printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 116165adb54cSMatt Jacob isp->isp_name, rq->req_header.rqs_entry_count-1, 116265adb54cSMatt Jacob seglim, crq->req_dataseg[seglim].ds_count, 116365adb54cSMatt Jacob crq->req_dataseg[seglim].ds_base); 116465adb54cSMatt Jacob #endif 116565adb54cSMatt Jacob rq->req_seg_count++; 116665adb54cSMatt Jacob } 116765adb54cSMatt Jacob } 116865adb54cSMatt Jacob 11694873663cSMatt Jacob return (CMD_QUEUED); 117065adb54cSMatt Jacob } 1171d720e6d5SJustin T. Gibbs #endif 117265adb54cSMatt Jacob 117365adb54cSMatt Jacob static void 117417e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp) 117565adb54cSMatt Jacob { 117665adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 117765adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 117865adb54cSMatt Jacob } 117965adb54cSMatt Jacob 118065adb54cSMatt Jacob static void 118117e318c6SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp) 118265adb54cSMatt Jacob { 118365adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 11849bffbcd4SBruce Evans printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1185d951bbcaSMatt Jacob pci_conf_read(pci->pci_id, PCIR_COMMAND)); 118665adb54cSMatt Jacob } 1187