bt_pci.c revision 50477
1285SN/A/* 2462SN/A * Product specific probe and attach routines for: 3285SN/A * Buslogic BT946, BT948, BT956, BT958 SCSI controllers 4285SN/A * 5285SN/A * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs 6285SN/A * All rights reserved. 7285SN/A * 8285SN/A * Redistribution and use in source and binary forms, with or without 9285SN/A * modification, are permitted provided that the following conditions 10285SN/A * are met: 11285SN/A * 1. Redistributions of source code must retain the above copyright 12285SN/A * notice, this list of conditions, and the following disclaimer, 13285SN/A * without modification, immediately at the beginning of the file. 14285SN/A * 2. The name of the author may not be used to endorse or promote products 15285SN/A * derived from this software without specific prior written permission. 16285SN/A * 17285SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18285SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19285SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20285SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21285SN/A * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22285SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23285SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24285SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25285SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26285SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27285SN/A * SUCH DAMAGE. 28285SN/A * 29285SN/A * $FreeBSD: head/sys/dev/buslogic/bt_pci.c 50477 1999-08-28 01:08:13Z peter $ 30285SN/A */ 31285SN/A 32285SN/A#include <sys/param.h> 33285SN/A#include <sys/systm.h> 34285SN/A#include <sys/kernel.h> 35285SN/A#include <sys/bus.h> 36285SN/A 37285SN/A#include <pci/pcireg.h> 38285SN/A#include <pci/pcivar.h> 39285SN/A 40285SN/A#include <machine/bus_memio.h> 41285SN/A#include <machine/bus_pio.h> 42285SN/A#include <machine/bus.h> 43285SN/A#include <machine/resource.h> 44285SN/A#include <sys/rman.h> 45285SN/A 46285SN/A#include <dev/buslogic/btreg.h> 47285SN/A 48285SN/A#define BT_PCI_IOADDR PCIR_MAPS 49285SN/A#define BT_PCI_MEMADDR PCIR_MAPS + 4 50285SN/A 51285SN/A#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 52285SN/A#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 53285SN/A#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 54285SN/A 55285SN/Astatic int 56285SN/Abt_pci_alloc_resources(device_t dev) 57285SN/A{ 58285SN/A int command, type = 0, rid, zero; 59285SN/A struct resource *regs = 0; 60285SN/A struct resource *irq = 0; 61285SN/A 62285SN/A command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 63285SN/A#if 0 64285SN/A /* XXX Memory Mapped I/O seems to cause problems */ 65285SN/A if (command & PCIM_CMD_MEMEN) { 66285SN/A type = SYS_RES_MEMORY; 67285SN/A rid = BT_PCI_MEMADDR; 68285SN/A regs = bus_alloc_resource(dev, type, &rid, 69285SN/A 0, ~0, 1, RF_ACTIVE); 70285SN/A } 71285SN/A#else 72285SN/A if (!regs && (command & PCIM_CMD_PORTEN)) { 73285SN/A type = SYS_RES_IOPORT; 74285SN/A rid = BT_PCI_IOADDR; 75285SN/A regs = bus_alloc_resource(dev, type, &rid, 76285SN/A 0, ~0, 1, RF_ACTIVE); 77285SN/A } 78285SN/A#endif 79285SN/A if (!regs) 80285SN/A return (ENOMEM); 81285SN/A 82285SN/A zero = 0; 83285SN/A irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, 84285SN/A 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 85285SN/A if (!irq) { 86285SN/A bus_release_resource(dev, type, rid, regs); 87285SN/A return (ENOMEM); 88285SN/A } 89285SN/A 90285SN/A bt_init_softc(dev, regs, irq, 0); 91285SN/A 92285SN/A return (0); 93285SN/A} 94285SN/A 95285SN/Astatic void 96285SN/Abt_pci_release_resources(device_t dev) 97285SN/A{ 98285SN/A struct bt_softc *bt = device_get_softc(dev); 99285SN/A 100285SN/A if (bt->port) 101285SN/A /* XXX can't cope with memory registers anyway */ 102285SN/A bus_release_resource(dev, SYS_RES_IOPORT, 103285SN/A BT_PCI_IOADDR, bt->port); 104285SN/A if (bt->irq) 105285SN/A bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 106285SN/A bt_free_softc(dev); 107285SN/A} 108285SN/A 109285SN/Astatic int 110285SN/Abt_pci_probe(device_t dev) 111285SN/A{ 112285SN/A switch (pci_get_devid(dev)) { 113285SN/A case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 114285SN/A case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 115285SN/A { 116285SN/A struct bt_softc *bt = device_get_softc(dev); 117285SN/A pci_info_data_t pci_info; 118285SN/A int error; 119285SN/A 120285SN/A error = bt_pci_alloc_resources(dev); 121285SN/A if (error) 122285SN/A return (error); 123285SN/A 124285SN/A /* 125285SN/A * Determine if an ISA compatible I/O port has been 126285SN/A * enabled. If so, record the port so it will not 127285SN/A * be probed by our ISA probe. If the PCI I/O port 128285SN/A * was not set to the compatibility port, disable it. 129285SN/A */ 130285SN/A error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 131285SN/A /*param*/NULL, /*paramlen*/0, 132285SN/A (u_int8_t*)&pci_info, sizeof(pci_info), 133285SN/A DEFAULT_CMD_TIMEOUT); 134285SN/A if (error == 0 135285SN/A && pci_info.io_port < BIO_DISABLED) { 136285SN/A bt_mark_probed_bio(pci_info.io_port); 137285SN/A if (bt->bsh != bt_iop_from_bio(pci_info.io_port)) { 138285SN/A u_int8_t new_addr; 139285SN/A 140285SN/A new_addr = BIO_DISABLED; 141285SN/A bt_cmd(bt, BOP_MODIFY_IO_ADDR, 142285SN/A /*param*/&new_addr, 143285SN/A /*paramlen*/1, /*reply_buf*/NULL, 144285SN/A /*reply_len*/0, 145285SN/A DEFAULT_CMD_TIMEOUT); 146285SN/A } 147285SN/A } 148285SN/A bt_pci_release_resources(dev); 149285SN/A device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 150285SN/A return (0); 151285SN/A } 152285SN/A default: 153285SN/A break; 154285SN/A } 155285SN/A 156285SN/A return (ENXIO); 157285SN/A} 158285SN/A 159285SN/Astatic int 160285SN/Abt_pci_attach(device_t dev) 161285SN/A{ 162285SN/A struct bt_softc *bt = device_get_softc(dev); 163285SN/A int opri; 164285SN/A int error; 165285SN/A 166285SN/A /* Initialize softc */ 167285SN/A error = bt_pci_alloc_resources(dev); 168285SN/A if (error) { 169285SN/A device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 170285SN/A return error; 171285SN/A } 172285SN/A 173 /* Allocate a dmatag for our CCB DMA maps */ 174 /* XXX Should be a child of the PCI bus dma tag */ 175 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0, 176 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 177 /*highaddr*/BUS_SPACE_MAXADDR, 178 /*filter*/NULL, /*filterarg*/NULL, 179 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 180 /*nsegments*/BUS_SPACE_UNRESTRICTED, 181 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 182 /*flags*/0, &bt->parent_dmat) != 0) { 183 bt_pci_release_resources(dev); 184 return (ENOMEM); 185 } 186 187 /* 188 * Protect ourself from spurrious interrupts during 189 * intialization and attach. We should really rely 190 * on interrupts during attach, but we don't have 191 * access to our interrupts during ISA probes, so until 192 * that changes, we mask our interrupts during attach 193 * too. 194 */ 195 opri = splcam(); 196 197 if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 198 bt_pci_release_resources(dev); 199 splx(opri); 200 return (ENXIO); 201 } 202 203 error = bt_attach(dev); 204 splx(opri); 205 206 if (error) { 207 bt_pci_release_resources(dev); 208 return (error); 209 } 210 211 return (0); 212} 213 214static device_method_t bt_pci_methods[] = { 215 /* Device interface */ 216 DEVMETHOD(device_probe, bt_pci_probe), 217 DEVMETHOD(device_attach, bt_pci_attach), 218 219 { 0, 0 } 220}; 221 222static driver_t bt_pci_driver = { 223 "bt", 224 bt_pci_methods, 225 sizeof(struct bt_softc), 226}; 227 228static devclass_t bt_devclass; 229 230DRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 231