adw_pci.c revision 50477
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 * $FreeBSD: head/sys/dev/advansys/adw_pci.c 50477 1999-08-28 01:08:13Z peter $ 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37 38#include <machine/bus_pio.h> 39#include <machine/bus.h> 40 41#include <pci/pcireg.h> 42#include <pci/pcivar.h> 43 44#include <cam/cam.h> 45#include <cam/scsi/scsi_all.h> 46 47#include <dev/advansys/adwvar.h> 48#include <dev/advansys/adwlib.h> 49#include <dev/advansys/adwmcode.h> 50 51#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ 52#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */ 53 54#define PCI_DEVICE_ID_ADVANSYS_3550 0x230010CD 55 56#define ADW_PCI_MAX_DMA_ADDR (0xFFFFFFFFUL) 57#define ADW_PCI_MAX_DMA_COUNT (0xFFFFFFFFUL) 58 59static const char* adwpciprobe(pcici_t tag, pcidi_t type); 60static void adwpciattach(pcici_t config_id, int unit); 61 62static struct pci_device adw_pci_driver = { 63 "adw", 64 adwpciprobe, 65 adwpciattach, 66 &adw_unit, 67 NULL 68}; 69 70COMPAT_PCI_DRIVER (adw_pci, adw_pci_driver); 71 72static const char* 73adwpciprobe(pcici_t tag, pcidi_t type) 74{ 75 switch (type) { 76 case PCI_DEVICE_ID_ADVANSYS_3550: 77 return ("AdvanSys ASC3550 SCSI controller"); 78 default: 79 break; 80 } 81 return (NULL); 82} 83 84static void 85adwpciattach(pcici_t config_id, int unit) 86{ 87 u_int32_t id; 88 u_int32_t command; 89 vm_offset_t vaddr; 90#ifdef ADW_ALLOW_MEMIO 91 vm_offset_t paddr; 92#endif 93 u_int16_t io_port; 94 bus_space_tag_t tag; 95 bus_space_handle_t bsh; 96 struct adw_softc *adw; 97 int error; 98 99 /* 100 * Determine the chip version. 101 */ 102 id = pci_cfgread(config_id, PCI_ID_REG, /*bytes*/4); 103 command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1); 104 105 /* 106 * These cards do not allow memory mapped accesses, so we must 107 * ensure that I/O accesses are available or we won't be able 108 * to talk to them. 109 */ 110 vaddr = 0; 111#ifdef ADW_ALLOW_MEMIO 112 if ((command & PCI_COMMAND_MEM_ENABLE) == 0 113 || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0) 114#endif 115 if ((command & PCI_COMMAND_IO_ENABLE) == 0 116 || (pci_map_port(config_id, PCI_BASEADR0, &io_port)) == 0) 117 return; 118 119 /* XXX Should be passed in by parent bus */ 120 /* XXX Why isn't the 0x10 offset incorporated into the reg defs? */ 121 if (vaddr != 0) { 122 tag = I386_BUS_SPACE_MEM; 123 bsh = vaddr; 124 } else { 125 tag = I386_BUS_SPACE_IO; 126 bsh = io_port; 127 } 128 129 130 if (adw_find_signature(tag, bsh) == 0) 131 return; 132 133 adw = adw_alloc(unit, tag, bsh); 134 if (adw == NULL) 135 return; 136 137 /* Allocate a dmatag for our transfer DMA maps */ 138 /* XXX Should be a child of the PCI bus dma tag */ 139 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 140 /*boundary*/0, 141 /*lowaddr*/ADW_PCI_MAX_DMA_ADDR, 142 /*highaddr*/BUS_SPACE_MAXADDR, 143 /*filter*/NULL, /*filterarg*/NULL, 144 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 145 /*nsegments*/BUS_SPACE_UNRESTRICTED, 146 /*maxsegsz*/ADW_PCI_MAX_DMA_COUNT, 147 /*flags*/0, 148 &adw->parent_dmat); 149 150 adw->init_level++; 151 152 if (error != 0) { 153 printf("%s: Could not allocate DMA tag - error %d\n", 154 adw_name(adw), error); 155 adw_free(adw); 156 return; 157 } 158 159 adw->init_level++; 160 161 if (adw_init(adw) != 0) { 162 adw_free(adw); 163 return; 164 } 165 166 /* 167 * If the PCI Configuration Command Register "Parity Error Response 168 * Control" Bit was clear (0), then set the microcode variable 169 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode 170 * to ignore DMA parity errors. 171 */ 172 if ((command & PCIM_CMD_PERRESPEN) == 0) 173 adw_lram_write_16(adw, ADW_MC_CONTROL_FLAG, 174 adw_lram_read_16(adw, ADW_MC_CONTROL_FLAG) 175 | ADW_MC_CONTROL_IGN_PERR); 176 177 if ((pci_map_int(config_id, adw_intr, (void *)adw, &cam_imask)) == 0) { 178 adw_free(adw); 179 return; 180 } 181 182 adw_attach(adw); 183} 184