bt_pci.c revision 241592
1119418Sobrien/*- 239223Sgibbs * Product specific probe and attach routines for: 339223Sgibbs * Buslogic BT946, BT948, BT956, BT958 SCSI controllers 439223Sgibbs * 539223Sgibbs * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs 639223Sgibbs * All rights reserved. 739223Sgibbs * 839223Sgibbs * Redistribution and use in source and binary forms, with or without 939223Sgibbs * modification, are permitted provided that the following conditions 1039223Sgibbs * are met: 1139223Sgibbs * 1. Redistributions of source code must retain the above copyright 1239223Sgibbs * notice, this list of conditions, and the following disclaimer, 1339223Sgibbs * without modification, immediately at the beginning of the file. 1439223Sgibbs * 2. The name of the author may not be used to endorse or promote products 1539223Sgibbs * derived from this software without specific prior written permission. 1639223Sgibbs * 1739223Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1839223Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1939223Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2039223Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2139223Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2239223Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2339223Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2439223Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2539223Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2639223Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2739223Sgibbs * SUCH DAMAGE. 2839223Sgibbs */ 2939223Sgibbs 30119418Sobrien#include <sys/cdefs.h> 31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/buslogic/bt_pci.c 241592 2012-10-15 16:13:55Z jhb $"); 32119418Sobrien 3339223Sgibbs#include <sys/param.h> 3439223Sgibbs#include <sys/systm.h> 3539223Sgibbs#include <sys/kernel.h> 36129879Sphk#include <sys/module.h> 37117126Sscottl#include <sys/lock.h> 38117126Sscottl#include <sys/mutex.h> 3945791Speter#include <sys/bus.h> 4039223Sgibbs 41119277Simp#include <dev/pci/pcireg.h> 42119277Simp#include <dev/pci/pcivar.h> 4339223Sgibbs 4439223Sgibbs#include <machine/bus.h> 4545791Speter#include <machine/resource.h> 4645791Speter#include <sys/rman.h> 4739223Sgibbs 4839223Sgibbs#include <dev/buslogic/btreg.h> 4939223Sgibbs 50119690Sjhb#define BT_PCI_IOADDR PCIR_BAR(0) 51119690Sjhb#define BT_PCI_MEMADDR PCIR_BAR(1) 5239223Sgibbs 5339223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 5439223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 5539223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 5639223Sgibbs 5739223Sgibbsstatic int 5845791Speterbt_pci_alloc_resources(device_t dev) 5939223Sgibbs{ 6045791Speter int command, type = 0, rid, zero; 6145791Speter struct resource *regs = 0; 6245791Speter struct resource *irq = 0; 6339223Sgibbs 6445791Speter command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 6545791Speter#if 0 6639223Sgibbs /* XXX Memory Mapped I/O seems to cause problems */ 6745791Speter if (command & PCIM_CMD_MEMEN) { 6845791Speter type = SYS_RES_MEMORY; 6945791Speter rid = BT_PCI_MEMADDR; 70127135Snjl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 7145791Speter } 7245791Speter#else 7345791Speter if (!regs && (command & PCIM_CMD_PORTEN)) { 7445791Speter type = SYS_RES_IOPORT; 7545791Speter rid = BT_PCI_IOADDR; 76127135Snjl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 7745791Speter } 7839223Sgibbs#endif 7945791Speter if (!regs) 8045791Speter return (ENOMEM); 8145791Speter 8245791Speter zero = 0; 83127135Snjl irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, 84127135Snjl RF_ACTIVE | RF_SHAREABLE); 8545791Speter if (!irq) { 8645791Speter bus_release_resource(dev, type, rid, regs); 8745791Speter return (ENOMEM); 8839223Sgibbs } 8939223Sgibbs 9045791Speter bt_init_softc(dev, regs, irq, 0); 9145791Speter 9239223Sgibbs return (0); 9339223Sgibbs} 9439223Sgibbs 9545791Speterstatic void 9645791Speterbt_pci_release_resources(device_t dev) 9739223Sgibbs{ 9845791Speter struct bt_softc *bt = device_get_softc(dev); 9945791Speter 10045791Speter if (bt->port) 10145791Speter /* XXX can't cope with memory registers anyway */ 10245791Speter bus_release_resource(dev, SYS_RES_IOPORT, 10345791Speter BT_PCI_IOADDR, bt->port); 10445791Speter if (bt->irq) 10545969Sgibbs bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 10645791Speter bt_free_softc(dev); 10745791Speter} 10845791Speter 10945791Speterstatic int 11045791Speterbt_pci_probe(device_t dev) 11145791Speter{ 11245791Speter switch (pci_get_devid(dev)) { 11339223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 11439223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 11539223Sgibbs { 11645791Speter struct bt_softc *bt = device_get_softc(dev); 11739223Sgibbs pci_info_data_t pci_info; 11839223Sgibbs int error; 11939223Sgibbs 12045791Speter error = bt_pci_alloc_resources(dev); 12145791Speter if (error) 12245791Speter return (error); 12339223Sgibbs 12439223Sgibbs /* 12539223Sgibbs * Determine if an ISA compatible I/O port has been 12639223Sgibbs * enabled. If so, record the port so it will not 12740749Sgibbs * be probed by our ISA probe. If the PCI I/O port 12840749Sgibbs * was not set to the compatibility port, disable it. 12939223Sgibbs */ 13039223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 13139223Sgibbs /*param*/NULL, /*paramlen*/0, 13239223Sgibbs (u_int8_t*)&pci_info, sizeof(pci_info), 13339223Sgibbs DEFAULT_CMD_TIMEOUT); 13439223Sgibbs if (error == 0 13539223Sgibbs && pci_info.io_port < BIO_DISABLED) { 13639223Sgibbs bt_mark_probed_bio(pci_info.io_port); 13756176Snyan if (rman_get_start(bt->port) != 13856176Snyan bt_iop_from_bio(pci_info.io_port)) { 13940749Sgibbs u_int8_t new_addr; 14040749Sgibbs 14140749Sgibbs new_addr = BIO_DISABLED; 14240749Sgibbs bt_cmd(bt, BOP_MODIFY_IO_ADDR, 14340749Sgibbs /*param*/&new_addr, 14440749Sgibbs /*paramlen*/1, /*reply_buf*/NULL, 14540749Sgibbs /*reply_len*/0, 14640749Sgibbs DEFAULT_CMD_TIMEOUT); 14740749Sgibbs } 14839223Sgibbs } 14945791Speter bt_pci_release_resources(dev); 15045791Speter device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 151241592Sjhb return (BUS_PROBE_DEFAULT); 15239223Sgibbs } 15339223Sgibbs default: 15439223Sgibbs break; 15539223Sgibbs } 15639223Sgibbs 15745791Speter return (ENXIO); 15839223Sgibbs} 15939223Sgibbs 16045791Speterstatic int 16145791Speterbt_pci_attach(device_t dev) 16239223Sgibbs{ 16345791Speter struct bt_softc *bt = device_get_softc(dev); 16445791Speter int error; 16539223Sgibbs 16645969Sgibbs /* Initialize softc */ 16745791Speter error = bt_pci_alloc_resources(dev); 16845791Speter if (error) { 16945791Speter device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 17045791Speter return error; 17145791Speter } 17239223Sgibbs 17339223Sgibbs /* Allocate a dmatag for our CCB DMA maps */ 174232854Sscottl if (bus_dma_tag_create( /* PCI parent */ bus_get_dma_tag(dev), 175112782Smdodd /* alignemnt */ 1, 176112782Smdodd /* boundary */ 0, 177112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 178112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 179112782Smdodd /* filter */ NULL, 180112782Smdodd /* filterarg */ NULL, 181112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 182112782Smdodd /* nsegments */ ~0, 183112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 184112782Smdodd /* flags */ 0, 185241592Sjhb /* lockfunc */ NULL, 186241592Sjhb /* lockarg */ NULL, 187112782Smdodd &bt->parent_dmat) != 0) { 18845791Speter bt_pci_release_resources(dev); 18945791Speter return (ENOMEM); 19039223Sgibbs } 19139223Sgibbs 19245791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 19345791Speter bt_pci_release_resources(dev); 19445791Speter return (ENXIO); 19539223Sgibbs } 19639223Sgibbs 19745791Speter error = bt_attach(dev); 19839223Sgibbs 19945791Speter if (error) { 20045791Speter bt_pci_release_resources(dev); 20145791Speter return (error); 20245791Speter } 20345791Speter 20445791Speter return (0); 20539223Sgibbs} 20639223Sgibbs 20745791Speterstatic device_method_t bt_pci_methods[] = { 20845791Speter /* Device interface */ 20945791Speter DEVMETHOD(device_probe, bt_pci_probe), 21045791Speter DEVMETHOD(device_attach, bt_pci_attach), 21145791Speter 21245791Speter { 0, 0 } 21345791Speter}; 21445791Speter 21545791Speterstatic driver_t bt_pci_driver = { 21645791Speter "bt", 21745791Speter bt_pci_methods, 21845791Speter sizeof(struct bt_softc), 21945791Speter}; 22045791Speter 22145791Speterstatic devclass_t bt_devclass; 22245791Speter 22345791SpeterDRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 224165102SmjacobMODULE_DEPEND(bt, pci, 1, 1, 1); 225