bt_pci.c revision 119418
124750Sbde/*- 215903Swosch * Product specific probe and attach routines for: 315903Swosch * Buslogic BT946, BT948, BT956, BT958 SCSI controllers 415903Swosch * 515903Swosch * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs 615903Swosch * All rights reserved. 715903Swosch * 815903Swosch * Redistribution and use in source and binary forms, with or without 915903Swosch * modification, are permitted provided that the following conditions 1015903Swosch * are met: 1115903Swosch * 1. Redistributions of source code must retain the above copyright 1215903Swosch * notice, this list of conditions, and the following disclaimer, 1315903Swosch * without modification, immediately at the beginning of the file. 1415903Swosch * 2. The name of the author may not be used to endorse or promote products 1515903Swosch * derived from this software without specific prior written permission. 1615903Swosch * 1715903Swosch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1815903Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1915903Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2015903Swosch * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2115903Swosch * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2215903Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2315903Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2415903Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2515903Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2615903Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2715903Swosch * SUCH DAMAGE. 2815903Swosch */ 291845Swollman 3015903Swosch#include <sys/cdefs.h> 3114986Swosch__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt_pci.c 119418 2003-08-24 17:55:58Z obrien $"); 3214986Swosch 3314986Swosch#include <sys/param.h> 341845Swollman#include <sys/systm.h> 351845Swollman#include <sys/kernel.h> 3616663Sjkh#include <sys/lock.h> 371845Swollman#include <sys/mutex.h> 3814986Swosch#include <sys/bus.h> 3914986Swosch 4014986Swosch#include <dev/pci/pcireg.h> 4114986Swosch#include <dev/pci/pcivar.h> 4214986Swosch 4314986Swosch#include <machine/bus_memio.h> 4414986Swosch#include <machine/bus_pio.h> 4514986Swosch#include <machine/bus.h> 4614986Swosch#include <machine/resource.h> 4714986Swosch#include <sys/rman.h> 4814986Swosch 4914986Swosch#include <dev/buslogic/btreg.h> 5014986Swosch 5114986Swosch#define BT_PCI_IOADDR PCIR_MAPS 5214986Swosch#define BT_PCI_MEMADDR PCIR_MAPS + 4 5314986Swosch 5414986Swosch#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 5514986Swosch#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 5614986Swosch#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 5714986Swosch 5814986Swoschstatic int 5924750Sbdebt_pci_alloc_resources(device_t dev) 6024750Sbde{ 6124750Sbde int command, type = 0, rid, zero; 6214986Swosch struct resource *regs = 0; 631845Swollman struct resource *irq = 0; 6416663Sjkh 651845Swollman command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 661845Swollman#if 0 671845Swollman /* XXX Memory Mapped I/O seems to cause problems */ 681845Swollman if (command & PCIM_CMD_MEMEN) { 691845Swollman type = SYS_RES_MEMORY; 701845Swollman rid = BT_PCI_MEMADDR; 711845Swollman regs = bus_alloc_resource(dev, type, &rid, 721845Swollman 0, ~0, 1, RF_ACTIVE); 731845Swollman } 741845Swollman#else 751845Swollman if (!regs && (command & PCIM_CMD_PORTEN)) { 7616663Sjkh type = SYS_RES_IOPORT; 771845Swollman rid = BT_PCI_IOADDR; 781845Swollman regs = bus_alloc_resource(dev, type, &rid, 791845Swollman 0, ~0, 1, RF_ACTIVE); 8016663Sjkh } 811845Swollman#endif 821845Swollman if (!regs) 831845Swollman return (ENOMEM); 841845Swollman 8516663Sjkh zero = 0; 8616663Sjkh irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, 8716663Sjkh 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 8816663Sjkh if (!irq) { 8916663Sjkh bus_release_resource(dev, type, rid, regs); 9016663Sjkh return (ENOMEM); 9116663Sjkh } 9216663Sjkh 9316663Sjkh bt_init_softc(dev, regs, irq, 0); 9416663Sjkh 9516663Sjkh return (0); 9616663Sjkh} 9716663Sjkh 9816663Sjkhstatic void 9916663Sjkhbt_pci_release_resources(device_t dev) 10016663Sjkh{ 10116663Sjkh struct bt_softc *bt = device_get_softc(dev); 10216663Sjkh 103 if (bt->port) 104 /* XXX can't cope with memory registers anyway */ 105 bus_release_resource(dev, SYS_RES_IOPORT, 106 BT_PCI_IOADDR, bt->port); 107 if (bt->irq) 108 bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 109 bt_free_softc(dev); 110} 111 112static int 113bt_pci_probe(device_t dev) 114{ 115 switch (pci_get_devid(dev)) { 116 case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 117 case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 118 { 119 struct bt_softc *bt = device_get_softc(dev); 120 pci_info_data_t pci_info; 121 int error; 122 123 error = bt_pci_alloc_resources(dev); 124 if (error) 125 return (error); 126 127 /* 128 * Determine if an ISA compatible I/O port has been 129 * enabled. If so, record the port so it will not 130 * be probed by our ISA probe. If the PCI I/O port 131 * was not set to the compatibility port, disable it. 132 */ 133 error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 134 /*param*/NULL, /*paramlen*/0, 135 (u_int8_t*)&pci_info, sizeof(pci_info), 136 DEFAULT_CMD_TIMEOUT); 137 if (error == 0 138 && pci_info.io_port < BIO_DISABLED) { 139 bt_mark_probed_bio(pci_info.io_port); 140 if (rman_get_start(bt->port) != 141 bt_iop_from_bio(pci_info.io_port)) { 142 u_int8_t new_addr; 143 144 new_addr = BIO_DISABLED; 145 bt_cmd(bt, BOP_MODIFY_IO_ADDR, 146 /*param*/&new_addr, 147 /*paramlen*/1, /*reply_buf*/NULL, 148 /*reply_len*/0, 149 DEFAULT_CMD_TIMEOUT); 150 } 151 } 152 bt_pci_release_resources(dev); 153 device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 154 return (0); 155 } 156 default: 157 break; 158 } 159 160 return (ENXIO); 161} 162 163static int 164bt_pci_attach(device_t dev) 165{ 166 struct bt_softc *bt = device_get_softc(dev); 167 int opri; 168 int error; 169 170 /* Initialize softc */ 171 error = bt_pci_alloc_resources(dev); 172 if (error) { 173 device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 174 return error; 175 } 176 177 /* Allocate a dmatag for our CCB DMA maps */ 178 /* XXX Should be a child of the PCI bus dma tag */ 179 if (bus_dma_tag_create( /* parent */ NULL, 180 /* alignemnt */ 1, 181 /* boundary */ 0, 182 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 183 /* highaddr */ BUS_SPACE_MAXADDR, 184 /* filter */ NULL, 185 /* filterarg */ NULL, 186 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 187 /* nsegments */ ~0, 188 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 189 /* flags */ 0, 190 /* lockfunc */ busdma_lock_mutex, 191 /* lockarg */ &Giant, 192 &bt->parent_dmat) != 0) { 193 bt_pci_release_resources(dev); 194 return (ENOMEM); 195 } 196 197 /* 198 * Protect ourself from spurrious interrupts during 199 * intialization and attach. We should really rely 200 * on interrupts during attach, but we don't have 201 * access to our interrupts during ISA probes, so until 202 * that changes, we mask our interrupts during attach 203 * too. 204 */ 205 opri = splcam(); 206 207 if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 208 bt_pci_release_resources(dev); 209 splx(opri); 210 return (ENXIO); 211 } 212 213 error = bt_attach(dev); 214 splx(opri); 215 216 if (error) { 217 bt_pci_release_resources(dev); 218 return (error); 219 } 220 221 return (0); 222} 223 224static device_method_t bt_pci_methods[] = { 225 /* Device interface */ 226 DEVMETHOD(device_probe, bt_pci_probe), 227 DEVMETHOD(device_attach, bt_pci_attach), 228 229 { 0, 0 } 230}; 231 232static driver_t bt_pci_driver = { 233 "bt", 234 bt_pci_methods, 235 sizeof(struct bt_softc), 236}; 237 238static devclass_t bt_devclass; 239 240DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 241