adw_pci.c revision 41771
1/* 2 * Device probe and attach routines for the following 3 * Advanced Systems Inc. SCSI controllers: 4 * 5 * ABP940UW - Bus-Master PCI Ultra-Wide (240 CDB) 6 * 7 * Copyright (c) 1998 Justin Gibbs. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions, and the following disclaimer, 15 * without modification, immediately at the beginning of the file. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Id: adw_pci.c,v 1.2 1998/12/07 21:58:45 archie Exp $ 32 */ 33 34#include <pci.h> 35#if NPCI > 0 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39 40#include <machine/bus_pio.h> 41#include <machine/bus.h> 42 43#include <pci/pcireg.h> 44#include <pci/pcivar.h> 45 46#include <cam/cam.h> 47#include <cam/scsi/scsi_all.h> 48 49#include <dev/advansys/adwvar.h> 50#include <dev/advansys/adwlib.h> 51#include <dev/advansys/adwmcode.h> 52 53#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ 54#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */ 55 56#define PCI_DEVICE_ID_ADVANSYS_3550 0x230010CD 57 58#define ADW_PCI_MAX_DMA_ADDR (0xFFFFFFFFUL) 59#define ADW_PCI_MAX_DMA_COUNT (0xFFFFFFFFUL) 60 61static const char* adwpciprobe(pcici_t tag, pcidi_t type); 62static void adwpciattach(pcici_t config_id, int unit); 63 64static struct pci_device adw_pci_driver = { 65 "adw", 66 adwpciprobe, 67 adwpciattach, 68 &adw_unit, 69 NULL 70}; 71 72DATA_SET (pcidevice_set, adw_pci_driver); 73 74static const char* 75adwpciprobe(pcici_t tag, pcidi_t type) 76{ 77 switch (type) { 78 case PCI_DEVICE_ID_ADVANSYS_3550: 79 return ("AdvanSys ASC3550 SCSI controller"); 80 default: 81 break; 82 } 83 return (NULL); 84} 85 86static void 87adwpciattach(pcici_t config_id, int unit) 88{ 89 u_int32_t id; 90 u_int32_t command; 91 vm_offset_t vaddr; 92#ifdef ADW_ALLOW_MEMIO 93 vm_offset_t paddr; 94#endif 95 u_int16_t io_port; 96 bus_space_tag_t tag; 97 bus_space_handle_t bsh; 98 struct adw_softc *adw; 99 int error; 100 101 /* 102 * Determine the chip version. 103 */ 104 id = pci_cfgread(config_id, PCI_ID_REG, /*bytes*/4); 105 command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1); 106 107 /* 108 * These cards do not allow memory mapped accesses, so we must 109 * ensure that I/O accesses are available or we won't be able 110 * to talk to them. 111 */ 112 vaddr = 0; 113#ifdef ADW_ALLOW_MEMIO 114 if ((command & PCI_COMMAND_MEM_ENABLE) == 0 115 || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0) 116#endif 117 if ((command & PCI_COMMAND_IO_ENABLE) == 0 118 || (pci_map_port(config_id, PCI_BASEADR0, &io_port)) == 0) 119 return; 120 121 /* XXX Should be passed in by parent bus */ 122 /* XXX Why isn't the 0x10 offset incorporated into the reg defs? */ 123 if (vaddr != 0) { 124 tag = I386_BUS_SPACE_MEM; 125 bsh = vaddr; 126 } else { 127 tag = I386_BUS_SPACE_IO; 128 bsh = io_port; 129 } 130 131 132 if (adw_find_signature(tag, bsh) == 0) 133 return; 134 135 adw = adw_alloc(unit, tag, bsh); 136 if (adw == NULL) 137 return; 138 139 /* Allocate a dmatag for our transfer DMA maps */ 140 /* XXX Should be a child of the PCI bus dma tag */ 141 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, 142 /*boundary*/0, 143 /*lowaddr*/ADW_PCI_MAX_DMA_ADDR, 144 /*highaddr*/BUS_SPACE_MAXADDR, 145 /*filter*/NULL, /*filterarg*/NULL, 146 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 147 /*nsegments*/BUS_SPACE_UNRESTRICTED, 148 /*maxsegsz*/ADW_PCI_MAX_DMA_COUNT, 149 /*flags*/0, 150 &adw->parent_dmat); 151 152 adw->init_level++; 153 154 if (error != 0) { 155 printf("%s: Could not allocate DMA tag - error %d\n", 156 adw_name(adw), error); 157 adw_free(adw); 158 return; 159 } 160 161 adw->init_level++; 162 163 if (adw_init(adw) != 0) { 164 adw_free(adw); 165 return; 166 } 167 168 /* 169 * If the PCI Configuration Command Register "Parity Error Response 170 * Control" Bit was clear (0), then set the microcode variable 171 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode 172 * to ignore DMA parity errors. 173 */ 174 if ((command & PCIM_CMD_PERRESPEN) == 0) 175 adw_lram_write_16(adw, ADW_MC_CONTROL_FLAG, 176 adw_lram_read_16(adw, ADW_MC_CONTROL_FLAG) 177 | ADW_MC_CONTROL_IGN_PERR); 178 179 if ((pci_map_int(config_id, adw_intr, (void *)adw, &cam_imask)) == 0) { 180 adw_free(adw); 181 return; 182 } 183 184 adw_attach(adw); 185} 186 187#endif /* NPCI > 0 */ 188