166235db5SEivind Eklund /* $Id: isp_pci.c,v 1.18 1999/04/04 01:14:02 mjacob 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 }; 27465adb54cSMatt Jacob DATA_SET (pcidevice_set, isp_pci_driver); 27565adb54cSMatt Jacob 27665adb54cSMatt Jacob 277ab6d0040SMatt Jacob static PROBETYPE 27817e318c6SMatt Jacob isp_pci_probe(pcici_t tag, pcidi_t type) 27965adb54cSMatt Jacob { 28065adb54cSMatt Jacob static int oneshot = 1; 28165adb54cSMatt Jacob char *x; 28265adb54cSMatt Jacob 28365adb54cSMatt Jacob switch (type) { 284d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 28565adb54cSMatt Jacob case PCI_QLOGIC_ISP: 286d59bd469SMatt Jacob x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; 28765adb54cSMatt Jacob break; 288d59bd469SMatt Jacob #endif 289d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 290d59bd469SMatt Jacob case PCI_QLOGIC_ISP1080: 291d59bd469SMatt Jacob #if 0 292d59bd469SMatt Jacob case PCI_QLOGIC_ISP1240: /* 1240 not ready yet */ 29392c49d78SMatt Jacob #endif 294d59bd469SMatt Jacob x = "Qlogic ISP 1080/1240 PCI SCSI Adapter"; 295d59bd469SMatt Jacob break; 296d59bd469SMatt Jacob #endif 297d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 29865adb54cSMatt Jacob case PCI_QLOGIC_ISP2100: 29965adb54cSMatt Jacob x = "Qlogic ISP 2100 PCI FC-AL Adapter"; 30065adb54cSMatt Jacob break; 301d59bd469SMatt Jacob #endif 30265adb54cSMatt Jacob default: 30365adb54cSMatt Jacob return (NULL); 30465adb54cSMatt Jacob } 30565adb54cSMatt Jacob if (oneshot) { 30665adb54cSMatt Jacob oneshot = 0; 307d720e6d5SJustin T. Gibbs printf("%s Version %d.%d, Core Version %d.%d\n", PVS, 308d720e6d5SJustin T. Gibbs ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR, 309d720e6d5SJustin T. Gibbs ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR); 31065adb54cSMatt Jacob } 31165adb54cSMatt Jacob return (x); 31265adb54cSMatt Jacob } 31365adb54cSMatt Jacob 31465adb54cSMatt Jacob 31565adb54cSMatt Jacob static void 31617e318c6SMatt Jacob isp_pci_attach(pcici_t config_id, int unit) 31765adb54cSMatt Jacob { 31865adb54cSMatt Jacob int mapped; 319a185f9b1SMatt Jacob pci_port_t io_port; 320ab6d0040SMatt Jacob u_int32_t data, linesz; 32165adb54cSMatt Jacob struct isp_pcisoftc *pcs; 32265adb54cSMatt Jacob struct ispsoftc *isp; 32365adb54cSMatt Jacob vm_offset_t vaddr, paddr; 32465adb54cSMatt Jacob ISP_LOCKVAL_DECL; 32565adb54cSMatt Jacob 32665adb54cSMatt Jacob 32765adb54cSMatt Jacob pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT); 32865adb54cSMatt Jacob if (pcs == NULL) { 3299bffbcd4SBruce Evans printf("isp%d: cannot allocate softc\n", unit); 33065adb54cSMatt Jacob return; 33165adb54cSMatt Jacob } 33265adb54cSMatt Jacob bzero(pcs, sizeof (struct isp_pcisoftc)); 33365adb54cSMatt Jacob 33465adb54cSMatt Jacob vaddr = paddr = NULL; 33565adb54cSMatt Jacob mapped = 0; 336ab6d0040SMatt Jacob linesz = PCI_DFLT_LNSZ; 337d951bbcaSMatt Jacob /* 338d951bbcaSMatt Jacob * Note that pci_conf_read is a 32 bit word aligned function. 339d951bbcaSMatt Jacob */ 340d951bbcaSMatt Jacob data = pci_conf_read(config_id, PCIR_COMMAND); 341d951bbcaSMatt Jacob #if SCSI_ISP_PREFER_MEM_MAP == 1 342a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 343a185f9b1SMatt Jacob if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { 344a185f9b1SMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 345a185f9b1SMatt Jacob pcs->pci_sh = vaddr; 34665adb54cSMatt Jacob mapped++; 34765adb54cSMatt Jacob } 34865adb54cSMatt Jacob } 349a185f9b1SMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 350a185f9b1SMatt Jacob if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { 351a185f9b1SMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 352a185f9b1SMatt Jacob pcs->pci_sh = io_port; 35365adb54cSMatt Jacob mapped++; 35465adb54cSMatt Jacob } 35565adb54cSMatt Jacob } 356d951bbcaSMatt Jacob #else 357d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) { 358d951bbcaSMatt Jacob if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) { 359d951bbcaSMatt Jacob pcs->pci_st = IO_SPACE_MAPPING; 360d951bbcaSMatt Jacob pcs->pci_sh = io_port; 361d951bbcaSMatt Jacob mapped++; 362d951bbcaSMatt Jacob } 363d951bbcaSMatt Jacob } 364d951bbcaSMatt Jacob if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) { 365d951bbcaSMatt Jacob if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) { 366d951bbcaSMatt Jacob pcs->pci_st = MEM_SPACE_MAPPING; 367d951bbcaSMatt Jacob pcs->pci_sh = vaddr; 368d951bbcaSMatt Jacob mapped++; 369d951bbcaSMatt Jacob } 370d951bbcaSMatt Jacob } 371d951bbcaSMatt Jacob #endif 37265adb54cSMatt Jacob if (mapped == 0) { 3739bffbcd4SBruce Evans printf("isp%d: unable to map any ports!\n", unit); 37465adb54cSMatt Jacob free(pcs, M_DEVBUF); 37565adb54cSMatt Jacob return; 37665adb54cSMatt Jacob } 37765adb54cSMatt Jacob printf("isp%d: using %s space register mapping\n", unit, 378a185f9b1SMatt Jacob pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory"); 37965adb54cSMatt Jacob 38065adb54cSMatt Jacob isp = &pcs->pci_isp; 3812fa86a2bSMatt Jacob #if __FreeBSD_version >= 300006 3822127f260SArchie Cobbs (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); 3832fa86a2bSMatt Jacob #else 3842fa86a2bSMatt Jacob (void) sprintf(isp->isp_name, "isp%d", unit); 3852fa86a2bSMatt Jacob #endif 38665adb54cSMatt Jacob isp->isp_osinfo.unit = unit; 38765adb54cSMatt Jacob 38865adb54cSMatt Jacob data = pci_conf_read(config_id, PCI_ID_REG); 389d59bd469SMatt Jacob pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; 390d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; 391d59bd469SMatt Jacob pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; 392d59bd469SMatt Jacob pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; 393d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; 394d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT 39565adb54cSMatt Jacob if (data == PCI_QLOGIC_ISP) { 39665adb54cSMatt Jacob isp->isp_mdvec = &mdvec; 39765adb54cSMatt Jacob isp->isp_type = ISP_HA_SCSI_UNKNOWN; 39865adb54cSMatt Jacob isp->isp_param = &pcs->_z._x; 399d59bd469SMatt Jacob } 400d59bd469SMatt Jacob #endif 401d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 402d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP1080 || data == PCI_QLOGIC_ISP1240) { 403d59bd469SMatt Jacob isp->isp_mdvec = &mdvec_1080; 404d59bd469SMatt Jacob isp->isp_type = ISP_HA_SCSI_1080; 405d59bd469SMatt Jacob isp->isp_param = &pcs->_z._x; 406d59bd469SMatt Jacob pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = 407d59bd469SMatt Jacob ISP1080_DMA_REGS_OFF; 408d59bd469SMatt Jacob } 409d59bd469SMatt Jacob #endif 410d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT 411d59bd469SMatt Jacob if (data == PCI_QLOGIC_ISP2100) { 41265adb54cSMatt Jacob isp->isp_mdvec = &mdvec_2100; 41365adb54cSMatt Jacob isp->isp_type = ISP_HA_FC_2100; 41492c49d78SMatt Jacob isp->isp_param = &pcs->_z._y; 415d59bd469SMatt Jacob pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = 416d59bd469SMatt Jacob PCI_MBOX_REGS2100_OFF; 417ab6d0040SMatt Jacob 418ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCI_CLASS_REG); 419ab6d0040SMatt Jacob if ((data & 0xff) < 3) { 420ab6d0040SMatt Jacob /* 421ab6d0040SMatt Jacob * XXX: Need to get the actual revision 422ab6d0040SMatt Jacob * XXX: number of the 2100 FB. At any rate, 423ab6d0040SMatt Jacob * XXX: lower cache line size for early revision 424ab6d0040SMatt Jacob * XXX; boards. 425ab6d0040SMatt Jacob */ 426ab6d0040SMatt Jacob linesz = 1; 427ab6d0040SMatt Jacob } 42865adb54cSMatt Jacob } 429d59bd469SMatt Jacob #endif 43065adb54cSMatt Jacob 4313dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 432d951bbcaSMatt Jacob ISP_LOCK(isp); 433ab6d0040SMatt Jacob 434d951bbcaSMatt Jacob /* 435d951bbcaSMatt Jacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER 436d951bbcaSMatt Jacob * are set. 437d951bbcaSMatt Jacob */ 438d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_COMMAND, 2); 439d951bbcaSMatt Jacob data |= PCIM_CMD_SEREN | 440d951bbcaSMatt Jacob PCIM_CMD_PERRESPEN | 441d951bbcaSMatt Jacob PCIM_CMD_BUSMASTEREN | 442d951bbcaSMatt Jacob PCIM_CMD_INVEN; 443d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_COMMAND, 2, data); 444ab6d0040SMatt Jacob 445d951bbcaSMatt Jacob /* 446d951bbcaSMatt Jacob * Make sure the CACHE Line Size register is set sensibly. 447d951bbcaSMatt Jacob */ 448d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_CACHELNSZ, 1); 449ab6d0040SMatt Jacob if (data != linesz) { 450d951bbcaSMatt Jacob data = PCI_DFLT_LNSZ; 451d951bbcaSMatt Jacob printf("%s: set PCI line size to %d\n", isp->isp_name, data); 452d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_CACHELNSZ, data, 1); 453d951bbcaSMatt Jacob } 454ab6d0040SMatt Jacob 455d951bbcaSMatt Jacob /* 456d951bbcaSMatt Jacob * Make sure the Latency Timer is sane. 457d951bbcaSMatt Jacob */ 458d951bbcaSMatt Jacob data = pci_cfgread(config_id, PCIR_LATTIMER, 1); 459d951bbcaSMatt Jacob if (data < PCI_DFLT_LTNCY) { 460d951bbcaSMatt Jacob data = PCI_DFLT_LTNCY; 461d951bbcaSMatt Jacob printf("%s: set PCI latency to %d\n", isp->isp_name, data); 462d951bbcaSMatt Jacob pci_cfgwrite(config_id, PCIR_LATTIMER, data, 1); 463d951bbcaSMatt Jacob } 464ab6d0040SMatt Jacob 465ab6d0040SMatt Jacob /* 466ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 467ab6d0040SMatt Jacob */ 468ab6d0040SMatt Jacob data = pci_cfgread(config_id, PCIR_ROMADDR, 4); 469ab6d0040SMatt Jacob data &= ~1; 470ab6d0040SMatt Jacob pci_cfgwrite(config_id, PCIR_ROMADDR, data, 4); 471ab6d0040SMatt Jacob 472d951bbcaSMatt Jacob ISP_UNLOCK(isp); 473d951bbcaSMatt Jacob 474d720e6d5SJustin T. Gibbs if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT, 475d720e6d5SJustin T. Gibbs BUS_SPACE_MAXADDR, NULL, NULL, 1<<24, 476d720e6d5SJustin T. Gibbs 255, 1<<24, 0, &pcs->parent_dmat) != 0) { 477d720e6d5SJustin T. Gibbs printf("%s: could not create master dma tag\n", isp->isp_name); 478d720e6d5SJustin T. Gibbs free(pcs, M_DEVBUF); 479d720e6d5SJustin T. Gibbs return; 480d720e6d5SJustin T. Gibbs } 481ab6d0040SMatt Jacob #else 482ab6d0040SMatt Jacob ISP_LOCK(isp); 483ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_COMMAND); 484ab6d0040SMatt Jacob data |= PCIM_CMD_SEREN | 485ab6d0040SMatt Jacob PCIM_CMD_PERRESPEN | 486ab6d0040SMatt Jacob PCIM_CMD_BUSMASTEREN | 487ab6d0040SMatt Jacob PCIM_CMD_INVEN; 488ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_COMMAND, data); 489ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_CACHELNSZ); 490ab6d0040SMatt Jacob if ((data & ~0xffff) != ((PCI_DFLT_LTNCY << 8) | linesz)) { 491ab6d0040SMatt Jacob data &= ~0xffff; 492ab6d0040SMatt Jacob data |= (PCI_DFLT_LTNCY << 8) | linesz; 493ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_CACHELNSZ, data); 494ab6d0040SMatt Jacob printf("%s: set PCI line size to %d\n", isp->isp_name, linesz); 495ab6d0040SMatt Jacob printf("%s: set PCI latency to %d\n", isp->isp_name, 496ab6d0040SMatt Jacob PCI_DFLT_LTNCY); 497ab6d0040SMatt Jacob } 498d951bbcaSMatt Jacob 499ab6d0040SMatt Jacob /* 500ab6d0040SMatt Jacob * Make sure we've disabled the ROM. 501ab6d0040SMatt Jacob */ 502ab6d0040SMatt Jacob data = pci_conf_read(config_id, PCIR_ROMADDR); 503ab6d0040SMatt Jacob data &= ~1; 504ab6d0040SMatt Jacob pci_conf_write(config_id, PCIR_ROMADDR, data); 505ab6d0040SMatt Jacob ISP_UNLOCK(isp); 506d720e6d5SJustin T. Gibbs #endif 50765adb54cSMatt Jacob if (pci_map_int(config_id, (void (*)(void *))isp_intr, 50865adb54cSMatt Jacob (void *)isp, &IMASK) == 0) { 5099bffbcd4SBruce Evans printf("%s: could not map interrupt\n", isp->isp_name); 51065adb54cSMatt Jacob free(pcs, M_DEVBUF); 51165adb54cSMatt Jacob return; 51265adb54cSMatt Jacob } 51365adb54cSMatt Jacob 51465adb54cSMatt Jacob pcs->pci_id = config_id; 515d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_FWLOAD_MASK 516d951bbcaSMatt Jacob if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) 517d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NORELOAD; 518d951bbcaSMatt Jacob #endif 519d951bbcaSMatt Jacob #ifdef SCSI_ISP_NO_NVRAM_MASK 520ab6d0040SMatt Jacob if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { 521ab6d0040SMatt Jacob printf("%s: ignoring NVRAM\n", isp->isp_name); 522d951bbcaSMatt Jacob isp->isp_confopts |= ISP_CFG_NONVRAM; 523ab6d0040SMatt Jacob } 524d951bbcaSMatt Jacob #endif 525d720e6d5SJustin T. Gibbs ISP_LOCK(isp); 52665adb54cSMatt Jacob isp_reset(isp); 52765adb54cSMatt Jacob if (isp->isp_state != ISP_RESETSTATE) { 528d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 52965adb54cSMatt Jacob free(pcs, M_DEVBUF); 53065adb54cSMatt Jacob return; 53165adb54cSMatt Jacob } 53265adb54cSMatt Jacob isp_init(isp); 53365adb54cSMatt Jacob if (isp->isp_state != ISP_INITSTATE) { 534d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 535d59bd469SMatt Jacob if (isp->isp_type & ISP_HA_SCSI) { 53665adb54cSMatt Jacob isp_uninit(isp); 53765adb54cSMatt Jacob free(pcs, M_DEVBUF); 538d59bd469SMatt Jacob } 53965adb54cSMatt Jacob } 54065adb54cSMatt Jacob isp_attach(isp); 54165adb54cSMatt Jacob if (isp->isp_state != ISP_RUNSTATE) { 542d59bd469SMatt Jacob /* If we're a Fibre Channel Card, we allow deferred attach */ 54392c49d78SMatt Jacob if (IS_SCSI(isp)) { 54465adb54cSMatt Jacob isp_uninit(isp); 54565adb54cSMatt Jacob free(pcs, M_DEVBUF); 54665adb54cSMatt Jacob } 547d59bd469SMatt Jacob } 548d720e6d5SJustin T. Gibbs ISP_UNLOCK(isp); 549e37c0455SDoug Rabson #ifdef __alpha__ 550d951bbcaSMatt Jacob /* 551d951bbcaSMatt Jacob * THIS SHOULD NOT HAVE TO BE HERE 552d951bbcaSMatt Jacob */ 553e37c0455SDoug Rabson alpha_register_pci_scsi(config_id->bus, config_id->slot, isp->isp_sim); 554e37c0455SDoug Rabson #endif 55565adb54cSMatt Jacob } 55665adb54cSMatt Jacob 55765adb54cSMatt Jacob static u_int16_t 558d59bd469SMatt Jacob isp_pci_rd_reg(isp, regoff) 559d59bd469SMatt Jacob struct ispsoftc *isp; 560d59bd469SMatt Jacob int regoff; 56165adb54cSMatt Jacob { 56265adb54cSMatt Jacob u_int16_t rv; 56365adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 564d59bd469SMatt Jacob int offset, oldconf = 0; 56565adb54cSMatt Jacob 566d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 56765adb54cSMatt Jacob /* 56865adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 56965adb54cSMatt Jacob */ 570d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 571d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 57265adb54cSMatt Jacob } 573d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 574d59bd469SMatt Jacob offset += (regoff & 0xff); 57565adb54cSMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 576d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 577d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 57865adb54cSMatt Jacob } 57965adb54cSMatt Jacob return (rv); 58065adb54cSMatt Jacob } 58165adb54cSMatt Jacob 58265adb54cSMatt Jacob static void 583d59bd469SMatt Jacob isp_pci_wr_reg(isp, regoff, val) 584d59bd469SMatt Jacob struct ispsoftc *isp; 585d59bd469SMatt Jacob int regoff; 586d59bd469SMatt Jacob u_int16_t val; 58765adb54cSMatt Jacob { 58865adb54cSMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 589d59bd469SMatt Jacob int offset, oldconf = 0; 590d59bd469SMatt Jacob 591d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 59265adb54cSMatt Jacob /* 59365adb54cSMatt Jacob * We will assume that someone has paused the RISC processor. 59465adb54cSMatt Jacob */ 595d59bd469SMatt Jacob oldconf = isp_pci_rd_reg(isp, BIU_CONF1); 596d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); 59765adb54cSMatt Jacob } 598d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 599d59bd469SMatt Jacob offset += (regoff & 0xff); 60065adb54cSMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 601d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 602d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oldconf); 60365adb54cSMatt Jacob } 60465adb54cSMatt Jacob } 60565adb54cSMatt Jacob 606d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT 607d59bd469SMatt Jacob static u_int16_t 608d59bd469SMatt Jacob isp_pci_rd_reg_1080(isp, regoff) 609d59bd469SMatt Jacob struct ispsoftc *isp; 610d59bd469SMatt Jacob int regoff; 611d59bd469SMatt Jacob { 612d59bd469SMatt Jacob u_int16_t rv; 613d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 614d59bd469SMatt Jacob int offset, oc = 0; 615d59bd469SMatt Jacob 616d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 617d59bd469SMatt Jacob /* 618d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 619d59bd469SMatt Jacob */ 620d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 621d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 622d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 623d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 624d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 625d59bd469SMatt Jacob } 626d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 627d59bd469SMatt Jacob offset += (regoff & 0xff); 628d59bd469SMatt Jacob rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); 629d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 630d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 631d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 632d59bd469SMatt Jacob } 633d59bd469SMatt Jacob return (rv); 634d59bd469SMatt Jacob } 635d59bd469SMatt Jacob 636d59bd469SMatt Jacob static void 637d59bd469SMatt Jacob isp_pci_wr_reg_1080(isp, regoff, val) 638d59bd469SMatt Jacob struct ispsoftc *isp; 639d59bd469SMatt Jacob int regoff; 640d59bd469SMatt Jacob u_int16_t val; 641d59bd469SMatt Jacob { 642d59bd469SMatt Jacob struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; 643d59bd469SMatt Jacob int offset, oc = 0; 644d59bd469SMatt Jacob 645d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { 646d59bd469SMatt Jacob /* 647d59bd469SMatt Jacob * We will assume that someone has paused the RISC processor. 648d59bd469SMatt Jacob */ 649d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 650d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); 651d59bd469SMatt Jacob } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { 652d59bd469SMatt Jacob oc = isp_pci_rd_reg(isp, BIU_CONF1); 653d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); 654d59bd469SMatt Jacob } 655d59bd469SMatt Jacob offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; 656d59bd469SMatt Jacob offset += (regoff & 0xff); 657d59bd469SMatt Jacob bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); 658d59bd469SMatt Jacob if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || 659d59bd469SMatt Jacob ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { 660d59bd469SMatt Jacob isp_pci_wr_reg(isp, BIU_CONF1, oc); 661d59bd469SMatt Jacob } 662d59bd469SMatt Jacob } 663d59bd469SMatt Jacob #endif 664d59bd469SMatt Jacob 665d59bd469SMatt Jacob 6663dd37e43SMatt Jacob #if __FreeBSD_version >= 300004 667d720e6d5SJustin T. Gibbs static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); 668d720e6d5SJustin T. Gibbs static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); 669d720e6d5SJustin T. Gibbs static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); 670d720e6d5SJustin T. Gibbs 671d720e6d5SJustin T. Gibbs static void 67217e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 673d720e6d5SJustin T. Gibbs { 674d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 675d720e6d5SJustin T. Gibbs isp->isp_rquest_dma = segs->ds_addr; 676d720e6d5SJustin T. Gibbs } 677d720e6d5SJustin T. Gibbs 678d720e6d5SJustin T. Gibbs static void 67917e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error) 680d720e6d5SJustin T. Gibbs { 681d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 682d720e6d5SJustin T. Gibbs isp->isp_result_dma = segs->ds_addr; 683d720e6d5SJustin T. Gibbs } 684d720e6d5SJustin T. Gibbs 685d720e6d5SJustin T. Gibbs static void 68617e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error) 687d720e6d5SJustin T. Gibbs { 688d720e6d5SJustin T. Gibbs struct ispsoftc *isp = (struct ispsoftc *) arg; 689d720e6d5SJustin T. Gibbs fcparam *fcp = isp->isp_param; 690d720e6d5SJustin T. Gibbs fcp->isp_scdma = segs->ds_addr; 691d720e6d5SJustin T. Gibbs } 692d720e6d5SJustin T. Gibbs 693d720e6d5SJustin T. Gibbs static int 69417e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 695d720e6d5SJustin T. Gibbs { 696d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 697d720e6d5SJustin T. Gibbs caddr_t base; 698d720e6d5SJustin T. Gibbs u_int32_t len; 699d720e6d5SJustin T. Gibbs int i, error; 700d720e6d5SJustin T. Gibbs 701d720e6d5SJustin T. Gibbs /* 702d720e6d5SJustin T. Gibbs * Allocate and map the request, result queues, plus FC scratch area. 703d720e6d5SJustin T. Gibbs */ 704d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 705d720e6d5SJustin T. Gibbs len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 706d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 707d720e6d5SJustin T. Gibbs len += ISP2100_SCRLEN; 708d720e6d5SJustin T. Gibbs } 709d720e6d5SJustin T. Gibbs if (bus_dma_tag_create(pci->parent_dmat, 0, 0, BUS_SPACE_MAXADDR, 710d720e6d5SJustin T. Gibbs BUS_SPACE_MAXADDR, NULL, NULL, len, 1, BUS_SPACE_MAXSIZE_32BIT, 711d720e6d5SJustin T. Gibbs 0, &pci->cntrol_dmat) != 0) { 712d720e6d5SJustin T. Gibbs printf("%s: cannot create a dma tag for control spaces\n", 713d720e6d5SJustin T. Gibbs isp->isp_name); 714d720e6d5SJustin T. Gibbs return (1); 715d720e6d5SJustin T. Gibbs } 716d720e6d5SJustin T. Gibbs if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, 717d720e6d5SJustin T. Gibbs BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { 7184873663cSMatt Jacob printf("%s: cannot allocate %d bytes of CCB memory\n", 7194873663cSMatt Jacob isp->isp_name, len); 720d720e6d5SJustin T. Gibbs return (1); 721d720e6d5SJustin T. Gibbs } 722d720e6d5SJustin T. Gibbs 723d720e6d5SJustin T. Gibbs isp->isp_rquest = base; 724d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, 725d720e6d5SJustin T. Gibbs ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, pci, 0); 726d720e6d5SJustin T. Gibbs 727d720e6d5SJustin T. Gibbs isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 728d720e6d5SJustin T. Gibbs bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, 729d720e6d5SJustin T. Gibbs ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, pci, 0); 730d720e6d5SJustin T. Gibbs 731d720e6d5SJustin T. Gibbs /* 732d720e6d5SJustin T. Gibbs * Use this opportunity to initialize/create data DMA maps. 733d720e6d5SJustin T. Gibbs */ 734d720e6d5SJustin T. Gibbs for (i = 0; i < MAXISPREQUEST; i++) { 735d720e6d5SJustin T. Gibbs error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); 736d720e6d5SJustin T. Gibbs if (error) { 7374873663cSMatt Jacob printf("%s: error %d creating mailbox DMA maps\n", 738d720e6d5SJustin T. Gibbs isp->isp_name, error); 739d720e6d5SJustin T. Gibbs return (1); 740d720e6d5SJustin T. Gibbs } 741d720e6d5SJustin T. Gibbs } 74292c49d78SMatt Jacob 74392c49d78SMatt Jacob if (isp->isp_type & ISP_HA_FC) { 74492c49d78SMatt Jacob fcparam *fcp = (fcparam *) isp->isp_param; 74592c49d78SMatt Jacob fcp->isp_scratch = base + 74692c49d78SMatt Jacob ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + 74792c49d78SMatt Jacob ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 74892c49d78SMatt Jacob bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, 74992c49d78SMatt Jacob fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, pci, 0); 75092c49d78SMatt Jacob } 751d720e6d5SJustin T. Gibbs return (0); 752d720e6d5SJustin T. Gibbs } 753d720e6d5SJustin T. Gibbs 754d720e6d5SJustin T. Gibbs static void dma2 __P((void *, bus_dma_segment_t *, int, int)); 755d720e6d5SJustin T. Gibbs typedef struct { 756d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 757d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 758d720e6d5SJustin T. Gibbs ispreq_t *rq; 759d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 760d720e6d5SJustin T. Gibbs u_int8_t optr; 761d720e6d5SJustin T. Gibbs u_int error; 762d720e6d5SJustin T. Gibbs } mush_t; 763d720e6d5SJustin T. Gibbs 7644873663cSMatt Jacob #define MUSHERR_NOQENTRIES -2 7654873663cSMatt Jacob 766d720e6d5SJustin T. Gibbs static void 76717e318c6SMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 768d720e6d5SJustin T. Gibbs { 769d720e6d5SJustin T. Gibbs mush_t *mp; 770d720e6d5SJustin T. Gibbs ISP_SCSI_XFER_T *ccb; 771d720e6d5SJustin T. Gibbs struct ispsoftc *isp; 772d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci; 773d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 774d720e6d5SJustin T. Gibbs bus_dma_segment_t *eseg; 775d720e6d5SJustin T. Gibbs ispreq_t *rq; 776d720e6d5SJustin T. Gibbs u_int8_t *iptrp; 777d720e6d5SJustin T. Gibbs u_int8_t optr; 778d720e6d5SJustin T. Gibbs ispcontreq_t *crq; 779d720e6d5SJustin T. Gibbs int drq, seglim, datalen; 780d720e6d5SJustin T. Gibbs 781d720e6d5SJustin T. Gibbs mp = (mush_t *) arg; 782d720e6d5SJustin T. Gibbs if (error) { 783d720e6d5SJustin T. Gibbs mp->error = error; 784d720e6d5SJustin T. Gibbs return; 785d720e6d5SJustin T. Gibbs } 786d720e6d5SJustin T. Gibbs 787d720e6d5SJustin T. Gibbs isp = mp->isp; 788d720e6d5SJustin T. Gibbs if (nseg < 1) { 789d720e6d5SJustin T. Gibbs printf("%s: zero or negative segment count\n", isp->isp_name); 790d720e6d5SJustin T. Gibbs mp->error = EFAULT; 791d720e6d5SJustin T. Gibbs return; 792d720e6d5SJustin T. Gibbs } 793d720e6d5SJustin T. Gibbs ccb = mp->ccb; 794d720e6d5SJustin T. Gibbs rq = mp->rq; 795d720e6d5SJustin T. Gibbs iptrp = mp->iptrp; 796d720e6d5SJustin T. Gibbs optr = mp->optr; 797d720e6d5SJustin T. Gibbs 798d720e6d5SJustin T. Gibbs pci = (struct isp_pcisoftc *)isp; 799d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 800d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 801d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); 802d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_IN; 803d720e6d5SJustin T. Gibbs } else { 804d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); 805d720e6d5SJustin T. Gibbs drq = REQFLAG_DATA_OUT; 806d720e6d5SJustin T. Gibbs } 807d720e6d5SJustin T. Gibbs 808d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(ccb); 809d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 810d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG_T2; 811d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = datalen; 812d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_flags |= drq; 813d720e6d5SJustin T. Gibbs } else { 814d720e6d5SJustin T. Gibbs seglim = ISP_RQDSEG; 815d720e6d5SJustin T. Gibbs rq->req_flags |= drq; 816d720e6d5SJustin T. Gibbs } 817d720e6d5SJustin T. Gibbs 818d720e6d5SJustin T. Gibbs eseg = dm_segs + nseg; 819d720e6d5SJustin T. Gibbs 820d720e6d5SJustin T. Gibbs while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { 821d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 822d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 823d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base = 824d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 825d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count = 826d720e6d5SJustin T. Gibbs dm_segs->ds_len; 827d720e6d5SJustin T. Gibbs } else { 828d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base = 829d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 830d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count = 831d720e6d5SJustin T. Gibbs dm_segs->ds_len; 832d720e6d5SJustin T. Gibbs } 833d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 834d720e6d5SJustin T. Gibbs #if 0 835d720e6d5SJustin T. Gibbs if (isp->isp_type & ISP_HA_FC) { 836d720e6d5SJustin T. Gibbs ispreqt2_t *rq2 = (ispreqt2_t *)rq; 837d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 838d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 839d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_count, 840d720e6d5SJustin T. Gibbs rq2->req_dataseg[rq2->req_seg_count].ds_base); 841d720e6d5SJustin T. Gibbs } else { 842d720e6d5SJustin T. Gibbs printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 843d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_seg_count, 844d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_count, 845d720e6d5SJustin T. Gibbs rq->req_dataseg[rq->req_seg_count].ds_base); 846d720e6d5SJustin T. Gibbs } 847d720e6d5SJustin T. Gibbs #endif 848d720e6d5SJustin T. Gibbs rq->req_seg_count++; 849d720e6d5SJustin T. Gibbs dm_segs++; 850d720e6d5SJustin T. Gibbs } 851d720e6d5SJustin T. Gibbs 852d720e6d5SJustin T. Gibbs while (datalen > 0 && dm_segs != eseg) { 853d720e6d5SJustin T. Gibbs crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 8544873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 855d720e6d5SJustin T. Gibbs if (*iptrp == optr) { 8564873663cSMatt Jacob #if 0 8574873663cSMatt Jacob printf("%s: Request Queue Overflow++\n", isp->isp_name); 8584873663cSMatt Jacob #endif 8594873663cSMatt Jacob mp->error = MUSHERR_NOQENTRIES; 860d720e6d5SJustin T. Gibbs return; 861d720e6d5SJustin T. Gibbs } 862d720e6d5SJustin T. Gibbs rq->req_header.rqs_entry_count++; 863d720e6d5SJustin T. Gibbs bzero((void *)crq, sizeof (*crq)); 864d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_count = 1; 865d720e6d5SJustin T. Gibbs crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 866d720e6d5SJustin T. Gibbs 867d720e6d5SJustin T. Gibbs seglim = 0; 868d720e6d5SJustin T. Gibbs while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { 869d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base = 870d720e6d5SJustin T. Gibbs dm_segs->ds_addr; 871d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_count = 872d720e6d5SJustin T. Gibbs dm_segs->ds_len; 873d720e6d5SJustin T. Gibbs #if 0 874d720e6d5SJustin T. Gibbs printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 875d720e6d5SJustin T. Gibbs isp->isp_name, rq->req_header.rqs_entry_count-1, 876d720e6d5SJustin T. Gibbs seglim, crq->req_dataseg[seglim].ds_count, 877d720e6d5SJustin T. Gibbs crq->req_dataseg[seglim].ds_base); 878d720e6d5SJustin T. Gibbs #endif 879d720e6d5SJustin T. Gibbs rq->req_seg_count++; 880d720e6d5SJustin T. Gibbs dm_segs++; 881d720e6d5SJustin T. Gibbs seglim++; 882d720e6d5SJustin T. Gibbs datalen -= dm_segs->ds_len; 883d720e6d5SJustin T. Gibbs } 884d720e6d5SJustin T. Gibbs } 885d720e6d5SJustin T. Gibbs } 886d720e6d5SJustin T. Gibbs 887d720e6d5SJustin T. Gibbs static int 88817e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, 88917e318c6SMatt Jacob u_int8_t *iptrp, u_int8_t optr) 890d720e6d5SJustin T. Gibbs { 891d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 892d720e6d5SJustin T. Gibbs struct ccb_hdr *ccb_h; 893d720e6d5SJustin T. Gibbs struct ccb_scsiio *csio; 894d720e6d5SJustin T. Gibbs bus_dmamap_t *dp; 895d720e6d5SJustin T. Gibbs mush_t mush, *mp; 896d720e6d5SJustin T. Gibbs 897d720e6d5SJustin T. Gibbs csio = (struct ccb_scsiio *) ccb; 898d720e6d5SJustin T. Gibbs ccb_h = &csio->ccb_h; 899d720e6d5SJustin T. Gibbs 900d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { 901d720e6d5SJustin T. Gibbs rq->req_seg_count = 1; 9024873663cSMatt Jacob return (CMD_QUEUED); 903d720e6d5SJustin T. Gibbs } 904d720e6d5SJustin T. Gibbs dp = &pci->dmaps[rq->req_handle - 1]; 905d720e6d5SJustin T. Gibbs 906d720e6d5SJustin T. Gibbs /* 907d720e6d5SJustin T. Gibbs * Do a virtual grapevine step to collect info for 9084873663cSMatt Jacob * the callback dma allocation that we have to use... 909d720e6d5SJustin T. Gibbs */ 910d720e6d5SJustin T. Gibbs mp = &mush; 911d720e6d5SJustin T. Gibbs mp->isp = isp; 912d720e6d5SJustin T. Gibbs mp->ccb = ccb; 913d720e6d5SJustin T. Gibbs mp->rq = rq; 914d720e6d5SJustin T. Gibbs mp->iptrp = iptrp; 915d720e6d5SJustin T. Gibbs mp->optr = optr; 916d720e6d5SJustin T. Gibbs mp->error = 0; 917d720e6d5SJustin T. Gibbs 918d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { 919d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { 9204873663cSMatt Jacob int error, s; 9214873663cSMatt Jacob 922d720e6d5SJustin T. Gibbs s = splsoftvm(); 923d720e6d5SJustin T. Gibbs error = bus_dmamap_load(pci->parent_dmat, *dp, 924d720e6d5SJustin T. Gibbs csio->data_ptr, csio->dxfer_len, dma2, mp, 0); 925d720e6d5SJustin T. Gibbs if (error == EINPROGRESS) { 926d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 927d720e6d5SJustin T. Gibbs mp->error = EINVAL; 9284873663cSMatt Jacob printf("%s: deferred dma allocation not " 9294873663cSMatt Jacob "supported\n", isp->isp_name); 930d720e6d5SJustin T. Gibbs } else if (error && mp->error == 0) { 931d720e6d5SJustin T. Gibbs mp->error = error; 932d720e6d5SJustin T. Gibbs } 9334873663cSMatt Jacob splx(s); 934d720e6d5SJustin T. Gibbs } else { 935d720e6d5SJustin T. Gibbs /* Pointer to physical buffer */ 936d720e6d5SJustin T. Gibbs struct bus_dma_segment seg; 937d720e6d5SJustin T. Gibbs seg.ds_addr = (bus_addr_t)csio->data_ptr; 938d720e6d5SJustin T. Gibbs seg.ds_len = csio->dxfer_len; 939d720e6d5SJustin T. Gibbs dma2(mp, &seg, 1, 0); 940d720e6d5SJustin T. Gibbs } 941d720e6d5SJustin T. Gibbs } else { 942d720e6d5SJustin T. Gibbs struct bus_dma_segment *segs; 943d720e6d5SJustin T. Gibbs 944d720e6d5SJustin T. Gibbs if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { 945d720e6d5SJustin T. Gibbs printf("%s: Physical segment pointers unsupported", 946d720e6d5SJustin T. Gibbs isp->isp_name); 947d720e6d5SJustin T. Gibbs mp->error = EINVAL; 948d720e6d5SJustin T. Gibbs } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { 949d720e6d5SJustin T. Gibbs printf("%s: Virtual segment addresses unsupported", 950d720e6d5SJustin T. Gibbs isp->isp_name); 951d720e6d5SJustin T. Gibbs mp->error = EINVAL; 952d720e6d5SJustin T. Gibbs } else { 953d720e6d5SJustin T. Gibbs /* Just use the segments provided */ 954d720e6d5SJustin T. Gibbs segs = (struct bus_dma_segment *) csio->data_ptr; 955d720e6d5SJustin T. Gibbs dma2(mp, segs, csio->sglist_cnt, 0); 956d720e6d5SJustin T. Gibbs } 957d720e6d5SJustin T. Gibbs } 958d720e6d5SJustin T. Gibbs if (mp->error) { 9594873663cSMatt Jacob int retval = CMD_COMPLETE; 9604873663cSMatt Jacob if (mp->error == MUSHERR_NOQENTRIES) { 9614873663cSMatt Jacob retval = CMD_EAGAIN; 9624873663cSMatt Jacob ccb_h->status = CAM_UNREC_HBA_ERROR; 9634873663cSMatt Jacob } else if (mp->error == EFBIG) { 964d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_TOO_BIG; 965d720e6d5SJustin T. Gibbs } else if (mp->error == EINVAL) { 966d720e6d5SJustin T. Gibbs ccb_h->status = CAM_REQ_INVALID; 967d720e6d5SJustin T. Gibbs } else { 968d720e6d5SJustin T. Gibbs ccb_h->status = CAM_UNREC_HBA_ERROR; 969d720e6d5SJustin T. Gibbs } 9704873663cSMatt Jacob return (retval); 9714873663cSMatt Jacob } else { 9724873663cSMatt Jacob return (CMD_QUEUED); 973d720e6d5SJustin T. Gibbs } 974d720e6d5SJustin T. Gibbs } 975d720e6d5SJustin T. Gibbs 976d720e6d5SJustin T. Gibbs static void 97717e318c6SMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, 97817e318c6SMatt Jacob u_int32_t handle) 979d720e6d5SJustin T. Gibbs { 980d720e6d5SJustin T. Gibbs struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 981d720e6d5SJustin T. Gibbs bus_dmamap_t *dp = &pci->dmaps[handle]; 982d720e6d5SJustin T. Gibbs 983d720e6d5SJustin T. Gibbs if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 984d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); 985d720e6d5SJustin T. Gibbs } else { 986d720e6d5SJustin T. Gibbs bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); 987d720e6d5SJustin T. Gibbs } 988d720e6d5SJustin T. Gibbs bus_dmamap_unload(pci->parent_dmat, *dp); 989d720e6d5SJustin T. Gibbs } 990d720e6d5SJustin T. Gibbs 9913dd37e43SMatt Jacob #else /* __FreeBSD_version >= 300004 */ 9923dd37e43SMatt Jacob 993d720e6d5SJustin T. Gibbs 99465adb54cSMatt Jacob static int 99517e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp) 99665adb54cSMatt Jacob { 99765adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 99865adb54cSMatt Jacob u_int32_t len; 99965adb54cSMatt Jacob int rseg; 100065adb54cSMatt Jacob 100165adb54cSMatt Jacob /* XXXX CHECK FOR ALIGNMENT */ 100265adb54cSMatt Jacob /* 100365adb54cSMatt Jacob * Allocate and map the request queue. 100465adb54cSMatt Jacob */ 1005d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); 100665adb54cSMatt Jacob isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT); 100765adb54cSMatt Jacob if (isp->isp_rquest == NULL) { 100865adb54cSMatt Jacob printf("%s: cannot malloc request queue\n", isp->isp_name); 100965adb54cSMatt Jacob return (1); 101065adb54cSMatt Jacob } 101165adb54cSMatt Jacob isp->isp_rquest_dma = vtophys(isp->isp_rquest); 101265adb54cSMatt Jacob 101365adb54cSMatt Jacob #if 0 101465adb54cSMatt Jacob printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma); 101565adb54cSMatt Jacob #endif 101665adb54cSMatt Jacob 101765adb54cSMatt Jacob /* 101865adb54cSMatt Jacob * Allocate and map the result queue. 101965adb54cSMatt Jacob */ 1020d720e6d5SJustin T. Gibbs len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); 102165adb54cSMatt Jacob isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT); 102265adb54cSMatt Jacob if (isp->isp_result == NULL) { 102365adb54cSMatt Jacob free(isp->isp_rquest, M_DEVBUF); 102465adb54cSMatt Jacob printf("%s: cannot malloc result queue\n", isp->isp_name); 102565adb54cSMatt Jacob return (1); 102665adb54cSMatt Jacob } 102765adb54cSMatt Jacob isp->isp_result_dma = vtophys(isp->isp_result); 102865adb54cSMatt Jacob #if 0 102965adb54cSMatt Jacob printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma); 103065adb54cSMatt Jacob #endif 103165adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 103265adb54cSMatt Jacob fcparam *fcp = isp->isp_param; 103365adb54cSMatt Jacob len = ISP2100_SCRLEN; 1034ab6d0040SMatt Jacob fcp->isp_scratch = (volatile caddr_t) 1035ab6d0040SMatt Jacob malloc(ISP2100_SCRLEN, M_DEVBUF, M_NOWAIT); 1036ab6d0040SMatt Jacob if (fcp->isp_scratch == NULL) { 1037ab6d0040SMatt Jacob printf("%s: cannot alloc scratch\n", isp->isp_name); 1038ab6d0040SMatt Jacob return (1); 1039ab6d0040SMatt Jacob } 104065adb54cSMatt Jacob fcp->isp_scdma = vtophys(fcp->isp_scratch); 104165adb54cSMatt Jacob } 104265adb54cSMatt Jacob return (0); 104365adb54cSMatt Jacob } 104465adb54cSMatt Jacob 104565adb54cSMatt Jacob static int 104617e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, 104717e318c6SMatt Jacob ispreq_t *rq, u_int8_t *iptrp, u_int8_t optr) 104865adb54cSMatt Jacob { 104965adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 105065adb54cSMatt Jacob ispcontreq_t *crq; 105165adb54cSMatt Jacob vm_offset_t vaddr; 105265adb54cSMatt Jacob int drq, seglim; 105365adb54cSMatt Jacob u_int32_t paddr, nextpaddr, datalen, size, *ctrp; 105465adb54cSMatt Jacob 105565adb54cSMatt Jacob if (xs->datalen == 0) { 105665adb54cSMatt Jacob rq->req_seg_count = 1; 10574873663cSMatt Jacob return (CMD_QUEUED); 105865adb54cSMatt Jacob } 105965adb54cSMatt Jacob 106065adb54cSMatt Jacob if (xs->flags & SCSI_DATA_IN) { 106165adb54cSMatt Jacob drq = REQFLAG_DATA_IN; 106265adb54cSMatt Jacob } else { 106365adb54cSMatt Jacob drq = REQFLAG_DATA_OUT; 106465adb54cSMatt Jacob } 106565adb54cSMatt Jacob 106665adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 106765adb54cSMatt Jacob seglim = ISP_RQDSEG_T2; 1068d720e6d5SJustin T. Gibbs ((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs); 106965adb54cSMatt Jacob ((ispreqt2_t *)rq)->req_flags |= drq; 107065adb54cSMatt Jacob } else { 107165adb54cSMatt Jacob seglim = ISP_RQDSEG; 107265adb54cSMatt Jacob rq->req_flags |= drq; 107365adb54cSMatt Jacob } 107465adb54cSMatt Jacob 1075d720e6d5SJustin T. Gibbs datalen = XS_XFRLEN(xs); 107665adb54cSMatt Jacob vaddr = (vm_offset_t) xs->data; 107765adb54cSMatt Jacob paddr = vtophys(vaddr); 107865adb54cSMatt Jacob 107965adb54cSMatt Jacob while (datalen != 0 && rq->req_seg_count < seglim) { 108065adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 108165adb54cSMatt Jacob ispreqt2_t *rq2 = (ispreqt2_t *)rq; 108265adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr; 108365adb54cSMatt Jacob ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count; 108465adb54cSMatt Jacob } else { 108565adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_base = paddr; 108665adb54cSMatt Jacob ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count; 108765adb54cSMatt Jacob } 108865adb54cSMatt Jacob nextpaddr = paddr; 108965adb54cSMatt Jacob *(ctrp) = 0; 109065adb54cSMatt Jacob 109165adb54cSMatt Jacob while (datalen != 0 && paddr == nextpaddr) { 109265adb54cSMatt Jacob nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 109365adb54cSMatt Jacob size = nextpaddr - paddr; 109465adb54cSMatt Jacob if (size > datalen) 109565adb54cSMatt Jacob size = datalen; 109665adb54cSMatt Jacob *(ctrp) += size; 109765adb54cSMatt Jacob vaddr += size; 109865adb54cSMatt Jacob datalen -= size; 109965adb54cSMatt Jacob if (datalen != 0) 110065adb54cSMatt Jacob paddr = vtophys(vaddr); 110165adb54cSMatt Jacob 110265adb54cSMatt Jacob } 110365adb54cSMatt Jacob #if 0 110465adb54cSMatt Jacob if (isp->isp_type & ISP_HA_FC) { 110565adb54cSMatt Jacob ispreqt2_t *rq2 = (ispreqt2_t *)rq; 110665adb54cSMatt Jacob printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 110765adb54cSMatt Jacob isp->isp_name, rq->req_seg_count, 110865adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_count, 110965adb54cSMatt Jacob rq2->req_dataseg[rq2->req_seg_count].ds_base); 111065adb54cSMatt Jacob } else { 111165adb54cSMatt Jacob printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", 111265adb54cSMatt Jacob isp->isp_name, rq->req_seg_count, 111365adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_count, 111465adb54cSMatt Jacob rq->req_dataseg[rq->req_seg_count].ds_base); 111565adb54cSMatt Jacob } 111665adb54cSMatt Jacob #endif 111765adb54cSMatt Jacob rq->req_seg_count++; 111865adb54cSMatt Jacob } 111965adb54cSMatt Jacob 112065adb54cSMatt Jacob 112165adb54cSMatt Jacob 112265adb54cSMatt Jacob if (datalen == 0) 11234873663cSMatt Jacob return (CMD_QUEUED); 112465adb54cSMatt Jacob 112565adb54cSMatt Jacob paddr = vtophys(vaddr); 112665adb54cSMatt Jacob while (datalen > 0) { 112765adb54cSMatt Jacob crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); 11284873663cSMatt Jacob *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); 112965adb54cSMatt Jacob if (*iptrp == optr) { 113065adb54cSMatt Jacob printf("%s: Request Queue Overflow\n", isp->isp_name); 1131d720e6d5SJustin T. Gibbs XS_SETERR(xs, HBA_BOTCH); 11324873663cSMatt Jacob return (CMD_EAGAIN); 113365adb54cSMatt Jacob } 113465adb54cSMatt Jacob rq->req_header.rqs_entry_count++; 113565adb54cSMatt Jacob bzero((void *)crq, sizeof (*crq)); 113665adb54cSMatt Jacob crq->req_header.rqs_entry_count = 1; 113765adb54cSMatt Jacob crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; 113865adb54cSMatt Jacob 113965adb54cSMatt Jacob for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) { 114065adb54cSMatt Jacob crq->req_dataseg[seglim].ds_base = paddr; 114165adb54cSMatt Jacob ctrp = &crq->req_dataseg[seglim].ds_count; 114265adb54cSMatt Jacob *(ctrp) = 0; 114365adb54cSMatt Jacob nextpaddr = paddr; 114465adb54cSMatt Jacob while (datalen != 0 && paddr == nextpaddr) { 114565adb54cSMatt Jacob nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; 114665adb54cSMatt Jacob size = nextpaddr - paddr; 114765adb54cSMatt Jacob if (size > datalen) 114865adb54cSMatt Jacob size = datalen; 114965adb54cSMatt Jacob *(ctrp) += size; 115065adb54cSMatt Jacob vaddr += size; 115165adb54cSMatt Jacob datalen -= size; 115265adb54cSMatt Jacob if (datalen != 0) 115365adb54cSMatt Jacob paddr = vtophys(vaddr); 115465adb54cSMatt Jacob } 115565adb54cSMatt Jacob #if 0 115665adb54cSMatt Jacob printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", 115765adb54cSMatt Jacob isp->isp_name, rq->req_header.rqs_entry_count-1, 115865adb54cSMatt Jacob seglim, crq->req_dataseg[seglim].ds_count, 115965adb54cSMatt Jacob crq->req_dataseg[seglim].ds_base); 116065adb54cSMatt Jacob #endif 116165adb54cSMatt Jacob rq->req_seg_count++; 116265adb54cSMatt Jacob } 116365adb54cSMatt Jacob } 116465adb54cSMatt Jacob 11654873663cSMatt Jacob return (CMD_QUEUED); 116665adb54cSMatt Jacob } 1167d720e6d5SJustin T. Gibbs #endif 116865adb54cSMatt Jacob 116965adb54cSMatt Jacob static void 117017e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp) 117165adb54cSMatt Jacob { 117265adb54cSMatt Jacob /* Make sure the BIOS is disabled */ 117365adb54cSMatt Jacob isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); 117465adb54cSMatt Jacob } 117565adb54cSMatt Jacob 117665adb54cSMatt Jacob static void 117717e318c6SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp) 117865adb54cSMatt Jacob { 117965adb54cSMatt Jacob struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; 11809bffbcd4SBruce Evans printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, 1181d951bbcaSMatt Jacob pci_conf_read(pci->pci_id, PCIR_COMMAND)); 118265adb54cSMatt Jacob } 1183