bt_pci.c revision 129879
1/*- 2 * Product specific probe and attach routines for: 3 * Buslogic BT946, BT948, BT956, BT958 SCSI controllers 4 * 5 * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt_pci.c 129879 2004-05-30 20:08:47Z phk $"); 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/lock.h> 38#include <sys/mutex.h> 39#include <sys/bus.h> 40 41#include <dev/pci/pcireg.h> 42#include <dev/pci/pcivar.h> 43 44#include <machine/bus_memio.h> 45#include <machine/bus_pio.h> 46#include <machine/bus.h> 47#include <machine/resource.h> 48#include <sys/rman.h> 49 50#include <dev/buslogic/btreg.h> 51 52#define BT_PCI_IOADDR PCIR_BAR(0) 53#define BT_PCI_MEMADDR PCIR_BAR(1) 54 55#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 56#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 57#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 58 59static int 60bt_pci_alloc_resources(device_t dev) 61{ 62 int command, type = 0, rid, zero; 63 struct resource *regs = 0; 64 struct resource *irq = 0; 65 66 command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 67#if 0 68 /* XXX Memory Mapped I/O seems to cause problems */ 69 if (command & PCIM_CMD_MEMEN) { 70 type = SYS_RES_MEMORY; 71 rid = BT_PCI_MEMADDR; 72 regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 73 } 74#else 75 if (!regs && (command & PCIM_CMD_PORTEN)) { 76 type = SYS_RES_IOPORT; 77 rid = BT_PCI_IOADDR; 78 regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 79 } 80#endif 81 if (!regs) 82 return (ENOMEM); 83 84 zero = 0; 85 irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, 86 RF_ACTIVE | RF_SHAREABLE); 87 if (!irq) { 88 bus_release_resource(dev, type, rid, regs); 89 return (ENOMEM); 90 } 91 92 bt_init_softc(dev, regs, irq, 0); 93 94 return (0); 95} 96 97static void 98bt_pci_release_resources(device_t dev) 99{ 100 struct bt_softc *bt = device_get_softc(dev); 101 102 if (bt->port) 103 /* XXX can't cope with memory registers anyway */ 104 bus_release_resource(dev, SYS_RES_IOPORT, 105 BT_PCI_IOADDR, bt->port); 106 if (bt->irq) 107 bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 108 bt_free_softc(dev); 109} 110 111static int 112bt_pci_probe(device_t dev) 113{ 114 switch (pci_get_devid(dev)) { 115 case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 116 case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 117 { 118 struct bt_softc *bt = device_get_softc(dev); 119 pci_info_data_t pci_info; 120 int error; 121 122 error = bt_pci_alloc_resources(dev); 123 if (error) 124 return (error); 125 126 /* 127 * Determine if an ISA compatible I/O port has been 128 * enabled. If so, record the port so it will not 129 * be probed by our ISA probe. If the PCI I/O port 130 * was not set to the compatibility port, disable it. 131 */ 132 error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 133 /*param*/NULL, /*paramlen*/0, 134 (u_int8_t*)&pci_info, sizeof(pci_info), 135 DEFAULT_CMD_TIMEOUT); 136 if (error == 0 137 && pci_info.io_port < BIO_DISABLED) { 138 bt_mark_probed_bio(pci_info.io_port); 139 if (rman_get_start(bt->port) != 140 bt_iop_from_bio(pci_info.io_port)) { 141 u_int8_t new_addr; 142 143 new_addr = BIO_DISABLED; 144 bt_cmd(bt, BOP_MODIFY_IO_ADDR, 145 /*param*/&new_addr, 146 /*paramlen*/1, /*reply_buf*/NULL, 147 /*reply_len*/0, 148 DEFAULT_CMD_TIMEOUT); 149 } 150 } 151 bt_pci_release_resources(dev); 152 device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 153 return (0); 154 } 155 default: 156 break; 157 } 158 159 return (ENXIO); 160} 161 162static int 163bt_pci_attach(device_t dev) 164{ 165 struct bt_softc *bt = device_get_softc(dev); 166 int opri; 167 int error; 168 169 /* Initialize softc */ 170 error = bt_pci_alloc_resources(dev); 171 if (error) { 172 device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 173 return error; 174 } 175 176 /* Allocate a dmatag for our CCB DMA maps */ 177 /* XXX Should be a child of the PCI bus dma tag */ 178 if (bus_dma_tag_create( /* parent */ NULL, 179 /* alignemnt */ 1, 180 /* boundary */ 0, 181 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 182 /* highaddr */ BUS_SPACE_MAXADDR, 183 /* filter */ NULL, 184 /* filterarg */ NULL, 185 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 186 /* nsegments */ ~0, 187 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 188 /* flags */ 0, 189 /* lockfunc */ busdma_lock_mutex, 190 /* lockarg */ &Giant, 191 &bt->parent_dmat) != 0) { 192 bt_pci_release_resources(dev); 193 return (ENOMEM); 194 } 195 196 /* 197 * Protect ourself from spurrious interrupts during 198 * intialization and attach. We should really rely 199 * on interrupts during attach, but we don't have 200 * access to our interrupts during ISA probes, so until 201 * that changes, we mask our interrupts during attach 202 * too. 203 */ 204 opri = splcam(); 205 206 if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 207 bt_pci_release_resources(dev); 208 splx(opri); 209 return (ENXIO); 210 } 211 212 error = bt_attach(dev); 213 splx(opri); 214 215 if (error) { 216 bt_pci_release_resources(dev); 217 return (error); 218 } 219 220 return (0); 221} 222 223static device_method_t bt_pci_methods[] = { 224 /* Device interface */ 225 DEVMETHOD(device_probe, bt_pci_probe), 226 DEVMETHOD(device_attach, bt_pci_attach), 227 228 { 0, 0 } 229}; 230 231static driver_t bt_pci_driver = { 232 "bt", 233 bt_pci_methods, 234 sizeof(struct bt_softc), 235}; 236 237static devclass_t bt_devclass; 238 239DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 240