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$"); 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{ 60254263Sscottl int type = 0, rid, zero; 6145791Speter struct resource *regs = 0; 6245791Speter struct resource *irq = 0; 6339223Sgibbs 6445791Speter#if 0 6539223Sgibbs /* XXX Memory Mapped I/O seems to cause problems */ 66254263Sscottl type = SYS_RES_MEMORY; 67254263Sscottl rid = BT_PCI_MEMADDR; 68254263Sscottl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 6945791Speter#else 70254263Sscottl type = SYS_RES_IOPORT; 71254263Sscottl rid = BT_PCI_IOADDR; 72254263Sscottl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 7339223Sgibbs#endif 7445791Speter if (!regs) 7545791Speter return (ENOMEM); 7645791Speter 7745791Speter zero = 0; 78127135Snjl irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, 79127135Snjl RF_ACTIVE | RF_SHAREABLE); 8045791Speter if (!irq) { 8145791Speter bus_release_resource(dev, type, rid, regs); 8245791Speter return (ENOMEM); 8339223Sgibbs } 8439223Sgibbs 8545791Speter bt_init_softc(dev, regs, irq, 0); 8645791Speter 8739223Sgibbs return (0); 8839223Sgibbs} 8939223Sgibbs 9045791Speterstatic void 9145791Speterbt_pci_release_resources(device_t dev) 9239223Sgibbs{ 9345791Speter struct bt_softc *bt = device_get_softc(dev); 9445791Speter 9545791Speter if (bt->port) 9645791Speter /* XXX can't cope with memory registers anyway */ 9745791Speter bus_release_resource(dev, SYS_RES_IOPORT, 9845791Speter BT_PCI_IOADDR, bt->port); 9945791Speter if (bt->irq) 10045969Sgibbs bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 10145791Speter bt_free_softc(dev); 10245791Speter} 10345791Speter 10445791Speterstatic int 10545791Speterbt_pci_probe(device_t dev) 10645791Speter{ 10745791Speter switch (pci_get_devid(dev)) { 10839223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 10939223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 11039223Sgibbs { 11145791Speter struct bt_softc *bt = device_get_softc(dev); 11239223Sgibbs pci_info_data_t pci_info; 11339223Sgibbs int error; 11439223Sgibbs 11545791Speter error = bt_pci_alloc_resources(dev); 11645791Speter if (error) 11745791Speter return (error); 11839223Sgibbs 11939223Sgibbs /* 12039223Sgibbs * Determine if an ISA compatible I/O port has been 12139223Sgibbs * enabled. If so, record the port so it will not 12240749Sgibbs * be probed by our ISA probe. If the PCI I/O port 12340749Sgibbs * was not set to the compatibility port, disable it. 12439223Sgibbs */ 12539223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 12639223Sgibbs /*param*/NULL, /*paramlen*/0, 12739223Sgibbs (u_int8_t*)&pci_info, sizeof(pci_info), 12839223Sgibbs DEFAULT_CMD_TIMEOUT); 12939223Sgibbs if (error == 0 13039223Sgibbs && pci_info.io_port < BIO_DISABLED) { 13139223Sgibbs bt_mark_probed_bio(pci_info.io_port); 13256176Snyan if (rman_get_start(bt->port) != 13356176Snyan bt_iop_from_bio(pci_info.io_port)) { 13440749Sgibbs u_int8_t new_addr; 13540749Sgibbs 13640749Sgibbs new_addr = BIO_DISABLED; 13740749Sgibbs bt_cmd(bt, BOP_MODIFY_IO_ADDR, 13840749Sgibbs /*param*/&new_addr, 13940749Sgibbs /*paramlen*/1, /*reply_buf*/NULL, 14040749Sgibbs /*reply_len*/0, 14140749Sgibbs DEFAULT_CMD_TIMEOUT); 14240749Sgibbs } 14339223Sgibbs } 14445791Speter bt_pci_release_resources(dev); 14545791Speter device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 146241592Sjhb return (BUS_PROBE_DEFAULT); 14739223Sgibbs } 14839223Sgibbs default: 14939223Sgibbs break; 15039223Sgibbs } 15139223Sgibbs 15245791Speter return (ENXIO); 15339223Sgibbs} 15439223Sgibbs 15545791Speterstatic int 15645791Speterbt_pci_attach(device_t dev) 15739223Sgibbs{ 15845791Speter struct bt_softc *bt = device_get_softc(dev); 15945791Speter int error; 16039223Sgibbs 16145969Sgibbs /* Initialize softc */ 16245791Speter error = bt_pci_alloc_resources(dev); 16345791Speter if (error) { 16445791Speter device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 16545791Speter return error; 16645791Speter } 16739223Sgibbs 16839223Sgibbs /* Allocate a dmatag for our CCB DMA maps */ 169232854Sscottl if (bus_dma_tag_create( /* PCI parent */ bus_get_dma_tag(dev), 170112782Smdodd /* alignemnt */ 1, 171112782Smdodd /* boundary */ 0, 172112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 173112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 174112782Smdodd /* filter */ NULL, 175112782Smdodd /* filterarg */ NULL, 176112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 177112782Smdodd /* nsegments */ ~0, 178112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 179112782Smdodd /* flags */ 0, 180241592Sjhb /* lockfunc */ NULL, 181241592Sjhb /* lockarg */ NULL, 182112782Smdodd &bt->parent_dmat) != 0) { 18345791Speter bt_pci_release_resources(dev); 18445791Speter return (ENOMEM); 18539223Sgibbs } 18639223Sgibbs 18745791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 18845791Speter bt_pci_release_resources(dev); 18945791Speter return (ENXIO); 19039223Sgibbs } 19139223Sgibbs 19245791Speter error = bt_attach(dev); 19339223Sgibbs 19445791Speter if (error) { 19545791Speter bt_pci_release_resources(dev); 19645791Speter return (error); 19745791Speter } 19845791Speter 19945791Speter return (0); 20039223Sgibbs} 20139223Sgibbs 20245791Speterstatic device_method_t bt_pci_methods[] = { 20345791Speter /* Device interface */ 20445791Speter DEVMETHOD(device_probe, bt_pci_probe), 20545791Speter DEVMETHOD(device_attach, bt_pci_attach), 20645791Speter 20745791Speter { 0, 0 } 20845791Speter}; 20945791Speter 21045791Speterstatic driver_t bt_pci_driver = { 21145791Speter "bt", 21245791Speter bt_pci_methods, 21345791Speter sizeof(struct bt_softc), 21445791Speter}; 21545791Speter 21645791Speterstatic devclass_t bt_devclass; 21745791Speter 21845791SpeterDRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 219165102SmjacobMODULE_DEPEND(bt, pci, 1, 1, 1); 220