bt_pci.c revision 127135
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 127135 2004-03-17 17:50:55Z njl $"); 32119418Sobrien 3339223Sgibbs#include <sys/param.h> 3439223Sgibbs#include <sys/systm.h> 3539223Sgibbs#include <sys/kernel.h> 36117126Sscottl#include <sys/lock.h> 37117126Sscottl#include <sys/mutex.h> 3845791Speter#include <sys/bus.h> 3939223Sgibbs 40119277Simp#include <dev/pci/pcireg.h> 41119277Simp#include <dev/pci/pcivar.h> 4239223Sgibbs 4339223Sgibbs#include <machine/bus_memio.h> 4439223Sgibbs#include <machine/bus_pio.h> 4539223Sgibbs#include <machine/bus.h> 4645791Speter#include <machine/resource.h> 4745791Speter#include <sys/rman.h> 4839223Sgibbs 4939223Sgibbs#include <dev/buslogic/btreg.h> 5039223Sgibbs 51119690Sjhb#define BT_PCI_IOADDR PCIR_BAR(0) 52119690Sjhb#define BT_PCI_MEMADDR PCIR_BAR(1) 5339223Sgibbs 5439223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 5539223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 5639223Sgibbs#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 5739223Sgibbs 5839223Sgibbsstatic int 5945791Speterbt_pci_alloc_resources(device_t dev) 6039223Sgibbs{ 6145791Speter int command, type = 0, rid, zero; 6245791Speter struct resource *regs = 0; 6345791Speter struct resource *irq = 0; 6439223Sgibbs 6545791Speter command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 6645791Speter#if 0 6739223Sgibbs /* XXX Memory Mapped I/O seems to cause problems */ 6845791Speter if (command & PCIM_CMD_MEMEN) { 6945791Speter type = SYS_RES_MEMORY; 7045791Speter rid = BT_PCI_MEMADDR; 71127135Snjl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 7245791Speter } 7345791Speter#else 7445791Speter if (!regs && (command & PCIM_CMD_PORTEN)) { 7545791Speter type = SYS_RES_IOPORT; 7645791Speter rid = BT_PCI_IOADDR; 77127135Snjl regs = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); 7845791Speter } 7939223Sgibbs#endif 8045791Speter if (!regs) 8145791Speter return (ENOMEM); 8245791Speter 8345791Speter zero = 0; 84127135Snjl irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero, 85127135Snjl RF_ACTIVE | RF_SHAREABLE); 8645791Speter if (!irq) { 8745791Speter bus_release_resource(dev, type, rid, regs); 8845791Speter return (ENOMEM); 8939223Sgibbs } 9039223Sgibbs 9145791Speter bt_init_softc(dev, regs, irq, 0); 9245791Speter 9339223Sgibbs return (0); 9439223Sgibbs} 9539223Sgibbs 9645791Speterstatic void 9745791Speterbt_pci_release_resources(device_t dev) 9839223Sgibbs{ 9945791Speter struct bt_softc *bt = device_get_softc(dev); 10045791Speter 10145791Speter if (bt->port) 10245791Speter /* XXX can't cope with memory registers anyway */ 10345791Speter bus_release_resource(dev, SYS_RES_IOPORT, 10445791Speter BT_PCI_IOADDR, bt->port); 10545791Speter if (bt->irq) 10645969Sgibbs bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 10745791Speter bt_free_softc(dev); 10845791Speter} 10945791Speter 11045791Speterstatic int 11145791Speterbt_pci_probe(device_t dev) 11245791Speter{ 11345791Speter switch (pci_get_devid(dev)) { 11439223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 11539223Sgibbs case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 11639223Sgibbs { 11745791Speter struct bt_softc *bt = device_get_softc(dev); 11839223Sgibbs pci_info_data_t pci_info; 11939223Sgibbs int error; 12039223Sgibbs 12145791Speter error = bt_pci_alloc_resources(dev); 12245791Speter if (error) 12345791Speter return (error); 12439223Sgibbs 12539223Sgibbs /* 12639223Sgibbs * Determine if an ISA compatible I/O port has been 12739223Sgibbs * enabled. If so, record the port so it will not 12840749Sgibbs * be probed by our ISA probe. If the PCI I/O port 12940749Sgibbs * was not set to the compatibility port, disable it. 13039223Sgibbs */ 13139223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 13239223Sgibbs /*param*/NULL, /*paramlen*/0, 13339223Sgibbs (u_int8_t*)&pci_info, sizeof(pci_info), 13439223Sgibbs DEFAULT_CMD_TIMEOUT); 13539223Sgibbs if (error == 0 13639223Sgibbs && pci_info.io_port < BIO_DISABLED) { 13739223Sgibbs bt_mark_probed_bio(pci_info.io_port); 13856176Snyan if (rman_get_start(bt->port) != 13956176Snyan bt_iop_from_bio(pci_info.io_port)) { 14040749Sgibbs u_int8_t new_addr; 14140749Sgibbs 14240749Sgibbs new_addr = BIO_DISABLED; 14340749Sgibbs bt_cmd(bt, BOP_MODIFY_IO_ADDR, 14440749Sgibbs /*param*/&new_addr, 14540749Sgibbs /*paramlen*/1, /*reply_buf*/NULL, 14640749Sgibbs /*reply_len*/0, 14740749Sgibbs DEFAULT_CMD_TIMEOUT); 14840749Sgibbs } 14939223Sgibbs } 15045791Speter bt_pci_release_resources(dev); 15145791Speter device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 15245791Speter return (0); 15339223Sgibbs } 15439223Sgibbs default: 15539223Sgibbs break; 15639223Sgibbs } 15739223Sgibbs 15845791Speter return (ENXIO); 15939223Sgibbs} 16039223Sgibbs 16145791Speterstatic int 16245791Speterbt_pci_attach(device_t dev) 16339223Sgibbs{ 16445791Speter struct bt_softc *bt = device_get_softc(dev); 16539223Sgibbs int opri; 16645791Speter int error; 16739223Sgibbs 16845969Sgibbs /* Initialize softc */ 16945791Speter error = bt_pci_alloc_resources(dev); 17045791Speter if (error) { 17145791Speter device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 17245791Speter return error; 17345791Speter } 17439223Sgibbs 17539223Sgibbs /* Allocate a dmatag for our CCB DMA maps */ 17639223Sgibbs /* XXX Should be a child of the PCI bus dma tag */ 177112782Smdodd if (bus_dma_tag_create( /* parent */ NULL, 178112782Smdodd /* alignemnt */ 1, 179112782Smdodd /* boundary */ 0, 180112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 181112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 182112782Smdodd /* filter */ NULL, 183112782Smdodd /* filterarg */ NULL, 184112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 185112782Smdodd /* nsegments */ ~0, 186112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 187112782Smdodd /* flags */ 0, 188117126Sscottl /* lockfunc */ busdma_lock_mutex, 189117126Sscottl /* lockarg */ &Giant, 190112782Smdodd &bt->parent_dmat) != 0) { 19145791Speter bt_pci_release_resources(dev); 19245791Speter return (ENOMEM); 19339223Sgibbs } 19439223Sgibbs 19539223Sgibbs /* 19639223Sgibbs * Protect ourself from spurrious interrupts during 19739223Sgibbs * intialization and attach. We should really rely 19839223Sgibbs * on interrupts during attach, but we don't have 19939223Sgibbs * access to our interrupts during ISA probes, so until 20039223Sgibbs * that changes, we mask our interrupts during attach 20139223Sgibbs * too. 20239223Sgibbs */ 20339223Sgibbs opri = splcam(); 20439223Sgibbs 20545791Speter if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 20645791Speter bt_pci_release_resources(dev); 20739223Sgibbs splx(opri); 20845791Speter return (ENXIO); 20939223Sgibbs } 21039223Sgibbs 21145791Speter error = bt_attach(dev); 21245791Speter splx(opri); 21339223Sgibbs 21445791Speter if (error) { 21545791Speter bt_pci_release_resources(dev); 21645791Speter return (error); 21745791Speter } 21845791Speter 21945791Speter return (0); 22039223Sgibbs} 22139223Sgibbs 22245791Speterstatic device_method_t bt_pci_methods[] = { 22345791Speter /* Device interface */ 22445791Speter DEVMETHOD(device_probe, bt_pci_probe), 22545791Speter DEVMETHOD(device_attach, bt_pci_attach), 22645791Speter 22745791Speter { 0, 0 } 22845791Speter}; 22945791Speter 23045791Speterstatic driver_t bt_pci_driver = { 23145791Speter "bt", 23245791Speter bt_pci_methods, 23345791Speter sizeof(struct bt_softc), 23445791Speter}; 23545791Speter 23645791Speterstatic devclass_t bt_devclass; 23745791Speter 23845791SpeterDRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 239