dpt_pci.c revision 143161
159078Smdodd/*- 259078Smdodd * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net> 359078Smdodd * All rights reserved. 432801Sjulian * 559078Smdodd * Copyright (c) 1997 Simon Shapiro 659078Smdodd * All Rights Reserved 759078Smdodd * 832801Sjulian * Redistribution and use in source and binary forms, with or without 932801Sjulian * modification, are permitted provided that the following conditions 1032801Sjulian * are met: 1132801Sjulian * 1. Redistributions of source code must retain the above copyright 1259078Smdodd * notice, this list of conditions and the following disclaimer. 1332801Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1432801Sjulian * notice, this list of conditions and the following disclaimer in the 1532801Sjulian * documentation and/or other materials provided with the distribution. 1632801Sjulian * 1732801Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1832801Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1932801Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2059078Smdodd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2159078Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2232801Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2332801Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2432801Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2532801Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2632801Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2732801Sjulian * SUCH DAMAGE. 2832801Sjulian */ 2932801Sjulian 30119418Sobrien#include <sys/cdefs.h> 31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/dpt/dpt_pci.c 143161 2005-03-05 18:30:12Z imp $"); 32119418Sobrien 3332801Sjulian#include <sys/param.h> 3432801Sjulian#include <sys/systm.h> 3532801Sjulian#include <sys/kernel.h> 3659078Smdodd#include <sys/module.h> 37117126Sscottl#include <sys/lock.h> 38117126Sscottl#include <sys/mutex.h> 3959078Smdodd#include <sys/bus.h> 4032801Sjulian 4139234Sgibbs#include <machine/bus_memio.h> 4239234Sgibbs#include <machine/bus_pio.h> 4339234Sgibbs#include <machine/bus.h> 4459078Smdodd#include <machine/resource.h> 4559078Smdodd#include <sys/rman.h> 4639234Sgibbs 47119277Simp#include <dev/pci/pcireg.h> 48119277Simp#include <dev/pci/pcivar.h> 4959078Smdodd 5039234Sgibbs#include <cam/scsi/scsi_all.h> 5139234Sgibbs 5239234Sgibbs#include <dev/dpt/dpt.h> 5332801Sjulian 5459078Smdodd#define DPT_VENDOR_ID 0x1044 5559078Smdodd#define DPT_DEVICE_ID 0xa400 5632801Sjulian 57119690Sjhb#define DPT_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ 58119690Sjhb#define DPT_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ 5932801Sjulian 6059078Smdodd#define ISA_PRIMARY_WD_ADDRESS 0x1f8 6132801Sjulian 6259078Smdoddstatic int dpt_pci_probe (device_t); 6359078Smdoddstatic int dpt_pci_attach (device_t); 6432801Sjulian 6559078Smdoddstatic int 6659078Smdodddpt_pci_probe (device_t dev) 6759078Smdodd{ 6859078Smdodd if ((pci_get_vendor(dev) == DPT_VENDOR_ID) && 6959078Smdodd (pci_get_device(dev) == DPT_DEVICE_ID)) { 7059078Smdodd device_set_desc(dev, "DPT Caching SCSI RAID Controller"); 71143161Simp return (BUS_PROBE_DEFAULT); 7259078Smdodd } 7359078Smdodd return (ENXIO); 7459078Smdodd} 7532801Sjulian 7659078Smdoddstatic int 7759078Smdodddpt_pci_attach (device_t dev) 7832801Sjulian{ 7959078Smdodd dpt_softc_t * dpt; 8059078Smdodd int s; 8159078Smdodd int error = 0; 8232801Sjulian 8359078Smdodd u_int32_t command; 8432801Sjulian 85112780Smdodd dpt = device_get_softc(dev); 86112780Smdodd 8759078Smdodd command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 8832801Sjulian 8959078Smdodd#ifdef DPT_ALLOW_MMIO 9059078Smdodd if ((command & PCIM_CMD_MEMEN) != 0) { 91112780Smdodd dpt->io_rid = DPT_PCI_MEMADDR; 92112780Smdodd dpt->io_type = SYS_RES_MEMORY; 93127135Snjl dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, 94127135Snjl &dpt->io_rid, RF_ACTIVE); 9559078Smdodd } 9632801Sjulian#endif 97112780Smdodd if (dpt->io_res == NULL && (command & PCIM_CMD_PORTEN) != 0) { 98112780Smdodd dpt->io_rid = DPT_PCI_IOADDR; 99112780Smdodd dpt->io_type = SYS_RES_IOPORT; 100127135Snjl dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type, 101127135Snjl &dpt->io_rid, RF_ACTIVE); 10259078Smdodd } 10332801Sjulian 104112780Smdodd if (dpt->io_res == NULL) { 10559078Smdodd device_printf(dev, "can't allocate register resources\n"); 10659078Smdodd error = ENOMEM; 10759078Smdodd goto bad; 10859078Smdodd } 109112780Smdodd dpt->io_offset = 0x10; 11032801Sjulian 111112780Smdodd dpt->irq_rid = 0; 112127135Snjl dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid, 113127135Snjl RF_ACTIVE | RF_SHAREABLE); 114112780Smdodd if (dpt->irq_res == NULL) { 11559078Smdodd device_printf(dev, "No irq?!\n"); 11659078Smdodd error = ENOMEM; 11759078Smdodd goto bad; 11859078Smdodd } 11932801Sjulian 12059078Smdodd /* Ensure busmastering is enabled */ 12159078Smdodd command |= PCIM_CMD_BUSMASTEREN; 12259078Smdodd pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); 12332801Sjulian 124112780Smdodd if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) { 12532801Sjulian#ifdef DPT_DEBUG_WARN 12659078Smdodd device_printf(dev, "Mapped as an IDE controller. " 12759078Smdodd "Disabling SCSI setup\n"); 12832801Sjulian#endif 12959078Smdodd error = ENXIO; 13059078Smdodd goto bad; 13139234Sgibbs } 13232801Sjulian 133112780Smdodd dpt_alloc(dev); 13432801Sjulian 13539234Sgibbs /* Allocate a dmatag representing the capabilities of this attachment */ 13639234Sgibbs /* XXX Should be a child of the PCI bus dma tag */ 13759078Smdodd if (bus_dma_tag_create( /* parent */ NULL, 13859078Smdodd /* alignemnt */ 1, 13959078Smdodd /* boundary */ 0, 14059078Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 14159078Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 14259078Smdodd /* filter */ NULL, 14359078Smdodd /* filterarg */ NULL, 14459078Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 145104710Speter /* nsegments */ ~0, 14659078Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 14759078Smdodd /* flags */ 0, 148117126Sscottl /* lockfunc */ busdma_lock_mutex, 149117126Sscottl /* lockarg */ &Giant, 15059078Smdodd &dpt->parent_dmat) != 0) { 15139234Sgibbs dpt_free(dpt); 15259078Smdodd error = ENXIO; 15359078Smdodd goto bad; 15439234Sgibbs } 15532801Sjulian 15659078Smdodd s = splcam(); 15732801Sjulian 15839234Sgibbs if (dpt_init(dpt) != 0) { 15959078Smdodd error = ENXIO; 16059078Smdodd goto bad; 16139234Sgibbs } 16232801Sjulian 16339234Sgibbs /* Register with the XPT */ 16439234Sgibbs dpt_attach(dpt); 16559078Smdodd 16639234Sgibbs splx(s); 16759078Smdodd 168112780Smdodd if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY, 169112780Smdodd dpt_intr, dpt, &dpt->ih)) { 17059078Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 17159078Smdodd error = ENXIO; 17259078Smdodd goto bad; 17359078Smdodd } 17459078Smdodd 17559078Smdodd return (error); 17659078Smdodd 17759078Smdoddbad: 178112780Smdodd dpt_release_resources(dev); 17959078Smdodd 180142356Ssam dpt_free(dpt); 181112780Smdodd 18259078Smdodd return (error); 18332801Sjulian} 18459078Smdodd 18559078Smdoddstatic device_method_t dpt_pci_methods[] = { 18659078Smdodd /* Device interface */ 18759078Smdodd DEVMETHOD(device_probe, dpt_pci_probe), 18859078Smdodd DEVMETHOD(device_attach, dpt_pci_attach), 189112780Smdodd DEVMETHOD(device_detach, dpt_detach), 19059078Smdodd 19159078Smdodd { 0, 0 } 19259078Smdodd}; 19359078Smdodd 19459078Smdoddstatic driver_t dpt_pci_driver = { 19559078Smdodd "dpt", 19659078Smdodd dpt_pci_methods, 19759078Smdodd sizeof(dpt_softc_t), 19859078Smdodd}; 19959078Smdodd 20059078SmdoddDRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0); 201