bt_pci.c revision 112782
154359Sroberto/* 256746Sroberto * Product specific probe and attach routines for: 354359Sroberto * Buslogic BT946, BT948, BT956, BT958 SCSI controllers 456746Sroberto * 554359Sroberto * Copyright (c) 1995, 1997, 1998 Justin T. Gibbs 654359Sroberto * All rights reserved. 754359Sroberto * 854359Sroberto * Redistribution and use in source and binary forms, with or without 954359Sroberto * modification, are permitted provided that the following conditions 1054359Sroberto * are met: 1154359Sroberto * 1. Redistributions of source code must retain the above copyright 1254359Sroberto * notice, this list of conditions, and the following disclaimer, 1354359Sroberto * without modification, immediately at the beginning of the file. 1454359Sroberto * 2. The name of the author may not be used to endorse or promote products 1554359Sroberto * derived from this software without specific prior written permission. 1654359Sroberto * 1754359Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1854359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1954359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2054359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2154359Sroberto * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2254359Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2354359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2454359Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2554359Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2654359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2754359Sroberto * SUCH DAMAGE. 2854359Sroberto * 2954359Sroberto * $FreeBSD: head/sys/dev/buslogic/bt_pci.c 112782 2003-03-29 09:46:10Z mdodd $ 3054359Sroberto */ 3154359Sroberto 3254359Sroberto#include <sys/param.h> 3354359Sroberto#include <sys/systm.h> 3454359Sroberto#include <sys/kernel.h> 3554359Sroberto#include <sys/bus.h> 3654359Sroberto 3754359Sroberto#include <pci/pcireg.h> 3854359Sroberto#include <pci/pcivar.h> 3954359Sroberto 4054359Sroberto#include <machine/bus_memio.h> 4154359Sroberto#include <machine/bus_pio.h> 4254359Sroberto#include <machine/bus.h> 4354359Sroberto#include <machine/resource.h> 4454359Sroberto#include <sys/rman.h> 4554359Sroberto 4654359Sroberto#include <dev/buslogic/btreg.h> 4754359Sroberto 4854359Sroberto#define BT_PCI_IOADDR PCIR_MAPS 4954359Sroberto#define BT_PCI_MEMADDR PCIR_MAPS + 4 5054359Sroberto 5154359Sroberto#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040104Bul 5254359Sroberto#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140104Bul 5354359Sroberto#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130104Bul 5454359Sroberto 5554359Srobertostatic int 5654359Srobertobt_pci_alloc_resources(device_t dev) 5754359Sroberto{ 5854359Sroberto int command, type = 0, rid, zero; 5954359Sroberto struct resource *regs = 0; 6054359Sroberto struct resource *irq = 0; 6154359Sroberto 6254359Sroberto command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 6354359Sroberto#if 0 6454359Sroberto /* XXX Memory Mapped I/O seems to cause problems */ 6554359Sroberto if (command & PCIM_CMD_MEMEN) { 6654359Sroberto type = SYS_RES_MEMORY; 6754359Sroberto rid = BT_PCI_MEMADDR; 6854359Sroberto regs = bus_alloc_resource(dev, type, &rid, 6954359Sroberto 0, ~0, 1, RF_ACTIVE); 7054359Sroberto } 7154359Sroberto#else 7254359Sroberto if (!regs && (command & PCIM_CMD_PORTEN)) { 7354359Sroberto type = SYS_RES_IOPORT; 7454359Sroberto rid = BT_PCI_IOADDR; 7554359Sroberto regs = bus_alloc_resource(dev, type, &rid, 7654359Sroberto 0, ~0, 1, RF_ACTIVE); 7754359Sroberto } 7854359Sroberto#endif 7954359Sroberto if (!regs) 8054359Sroberto return (ENOMEM); 8154359Sroberto 8254359Sroberto zero = 0; 8354359Sroberto irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, 8454359Sroberto 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 8554359Sroberto if (!irq) { 8654359Sroberto bus_release_resource(dev, type, rid, regs); 8754359Sroberto return (ENOMEM); 8854359Sroberto } 8954359Sroberto 9054359Sroberto bt_init_softc(dev, regs, irq, 0); 9154359Sroberto 9254359Sroberto return (0); 9354359Sroberto} 9454359Sroberto 9554359Srobertostatic void 9654359Srobertobt_pci_release_resources(device_t dev) 9754359Sroberto{ 9854359Sroberto struct bt_softc *bt = device_get_softc(dev); 9954359Sroberto 10054359Sroberto if (bt->port) 10154359Sroberto /* XXX can't cope with memory registers anyway */ 10254359Sroberto bus_release_resource(dev, SYS_RES_IOPORT, 10354359Sroberto BT_PCI_IOADDR, bt->port); 10454359Sroberto if (bt->irq) 10554359Sroberto bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq); 10654359Sroberto bt_free_softc(dev); 10754359Sroberto} 10854359Sroberto 10954359Srobertostatic int 11054359Srobertobt_pci_probe(device_t dev) 11154359Sroberto{ 11254359Sroberto switch (pci_get_devid(dev)) { 11354359Sroberto case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER: 11454359Sroberto case PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC: 11554359Sroberto { 11654359Sroberto struct bt_softc *bt = device_get_softc(dev); 11754359Sroberto pci_info_data_t pci_info; 11854359Sroberto int error; 11954359Sroberto 12054359Sroberto error = bt_pci_alloc_resources(dev); 12154359Sroberto if (error) 12254359Sroberto return (error); 12354359Sroberto 12454359Sroberto /* 12554359Sroberto * Determine if an ISA compatible I/O port has been 12654359Sroberto * enabled. If so, record the port so it will not 12754359Sroberto * be probed by our ISA probe. If the PCI I/O port 12854359Sroberto * was not set to the compatibility port, disable it. 12954359Sroberto */ 13054359Sroberto error = bt_cmd(bt, BOP_INQUIRE_PCI_INFO, 13154359Sroberto /*param*/NULL, /*paramlen*/0, 13254359Sroberto (u_int8_t*)&pci_info, sizeof(pci_info), 13354359Sroberto DEFAULT_CMD_TIMEOUT); 13454359Sroberto if (error == 0 13554359Sroberto && pci_info.io_port < BIO_DISABLED) { 13654359Sroberto bt_mark_probed_bio(pci_info.io_port); 13756746Sroberto if (rman_get_start(bt->port) != 13854359Sroberto bt_iop_from_bio(pci_info.io_port)) { 13954359Sroberto u_int8_t new_addr; 14054359Sroberto 14154359Sroberto new_addr = BIO_DISABLED; 14254359Sroberto bt_cmd(bt, BOP_MODIFY_IO_ADDR, 14354359Sroberto /*param*/&new_addr, 14454359Sroberto /*paramlen*/1, /*reply_buf*/NULL, 14554359Sroberto /*reply_len*/0, 14654359Sroberto DEFAULT_CMD_TIMEOUT); 14754359Sroberto } 14854359Sroberto } 14954359Sroberto bt_pci_release_resources(dev); 15054359Sroberto device_set_desc(dev, "Buslogic Multi-Master SCSI Host Adapter"); 15154359Sroberto return (0); 15254359Sroberto } 15354359Sroberto default: 15454359Sroberto break; 15554359Sroberto } 15654359Sroberto 15754359Sroberto return (ENXIO); 15854359Sroberto} 15954359Sroberto 16054359Srobertostatic int 16154359Srobertobt_pci_attach(device_t dev) 16254359Sroberto{ 16354359Sroberto struct bt_softc *bt = device_get_softc(dev); 16454359Sroberto int opri; 16554359Sroberto int error; 16654359Sroberto 16754359Sroberto /* Initialize softc */ 16854359Sroberto error = bt_pci_alloc_resources(dev); 16954359Sroberto if (error) { 17054359Sroberto device_printf(dev, "can't allocate resources in bt_pci_attach\n"); 17154359Sroberto return error; 17254359Sroberto } 17354359Sroberto 17454359Sroberto /* Allocate a dmatag for our CCB DMA maps */ 17554359Sroberto /* XXX Should be a child of the PCI bus dma tag */ 17654359Sroberto if (bus_dma_tag_create( /* parent */ NULL, 17754359Sroberto /* alignemnt */ 1, 17854359Sroberto /* boundary */ 0, 17954359Sroberto /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 18054359Sroberto /* highaddr */ BUS_SPACE_MAXADDR, 18154359Sroberto /* filter */ NULL, 18254359Sroberto /* filterarg */ NULL, 18354359Sroberto /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 18454359Sroberto /* nsegments */ ~0, 18554359Sroberto /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 18654359Sroberto /* flags */ 0, 18754359Sroberto &bt->parent_dmat) != 0) { 18854359Sroberto bt_pci_release_resources(dev); 18954359Sroberto return (ENOMEM); 19054359Sroberto } 19154359Sroberto 19254359Sroberto /* 19354359Sroberto * Protect ourself from spurrious interrupts during 19454359Sroberto * intialization and attach. We should really rely 19554359Sroberto * on interrupts during attach, but we don't have 19654359Sroberto * access to our interrupts during ISA probes, so until 19754359Sroberto * that changes, we mask our interrupts during attach 19854359Sroberto * too. 19954359Sroberto */ 20054359Sroberto opri = splcam(); 20154359Sroberto 20254359Sroberto if (bt_probe(dev) || bt_fetch_adapter_info(dev) || bt_init(dev)) { 20354359Sroberto bt_pci_release_resources(dev); 20454359Sroberto splx(opri); 20554359Sroberto return (ENXIO); 20654359Sroberto } 20754359Sroberto 20854359Sroberto error = bt_attach(dev); 20954359Sroberto splx(opri); 21054359Sroberto 21154359Sroberto if (error) { 21254359Sroberto bt_pci_release_resources(dev); 21354359Sroberto return (error); 21454359Sroberto } 21554359Sroberto 21654359Sroberto return (0); 21754359Sroberto} 21854359Sroberto 21954359Srobertostatic device_method_t bt_pci_methods[] = { 22054359Sroberto /* Device interface */ 22154359Sroberto DEVMETHOD(device_probe, bt_pci_probe), 22254359Sroberto DEVMETHOD(device_attach, bt_pci_attach), 22354359Sroberto 22454359Sroberto { 0, 0 } 22554359Sroberto}; 22654359Sroberto 22754359Srobertostatic driver_t bt_pci_driver = { 22854359Sroberto "bt", 22954359Sroberto bt_pci_methods, 23054359Sroberto sizeof(struct bt_softc), 23154359Sroberto}; 23254359Sroberto 23354359Srobertostatic devclass_t bt_devclass; 23454359Sroberto 23554359SrobertoDRIVER_MODULE(bt, pci, bt_pci_driver, bt_devclass, 0, 0); 23654359Sroberto