ahc_pci.c revision 161928
160812Sps/*- 2238730Sdelphij * FreeBSD, PCI product support functions 3238730Sdelphij * 4238730Sdelphij * Copyright (c) 1995-2001 Justin T. Gibbs 5238730Sdelphij * All rights reserved. 6238730Sdelphij * 7238730Sdelphij * Redistribution and use in source and binary forms, with or without 8238730Sdelphij * modification, are permitted provided that the following conditions 9238730Sdelphij * are met: 1060786Sps * 1. Redistributions of source code must retain the above copyright 1160786Sps * notice, this list of conditions, and the following disclaimer, 1260786Sps * without modification, immediately at the beginning of the file. 1360786Sps * 2. The name of the author may not be used to endorse or promote products 1460786Sps * derived from this software without specific prior written permission. 1560786Sps * 1660786Sps * Alternatively, this software may be distributed under the terms of the 1789022Sps * GNU Public License ("GPL"). 1889022Sps * 1989022Sps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2060786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2160786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2260786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2360786Sps * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24161478Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2560786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2660786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2760786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2860786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2960786Sps * SUCH DAMAGE. 3060786Sps * 3160786Sps * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $ 3260786Sps */ 3360786Sps 3460786Sps#include <sys/cdefs.h> 3560786Sps__FBSDID("$FreeBSD: head/sys/dev/aic7xxx/ahc_pci.c 161928 2006-09-03 00:27:42Z jmg $"); 3660786Sps 3760786Sps#include <dev/aic7xxx/aic7xxx_osm.h> 3860786Sps 39170259Sdelphijstatic int ahc_pci_probe(device_t dev); 40237613Sdelphijstatic int ahc_pci_attach(device_t dev); 4160786Sps 4260786Spsstatic device_method_t ahc_pci_device_methods[] = { 4360786Sps /* Device interface */ 4460786Sps DEVMETHOD(device_probe, ahc_pci_probe), 4560786Sps DEVMETHOD(device_attach, ahc_pci_attach), 4660786Sps DEVMETHOD(device_detach, ahc_detach), 4760786Sps { 0, 0 } 4860786Sps}; 4960786Sps 5060786Spsstatic driver_t ahc_pci_driver = { 5160786Sps "ahc", 5260786Sps ahc_pci_device_methods, 5360786Sps sizeof(struct ahc_softc) 5460786Sps}; 5560786Sps 5663131SpsDRIVER_MODULE(ahc_pci, pci, ahc_pci_driver, ahc_devclass, 0, 0); 57170259SdelphijDRIVER_MODULE(ahc_pci, cardbus, ahc_pci_driver, ahc_devclass, 0, 0); 58170259SdelphijMODULE_DEPEND(ahc_pci, ahc, 1, 1, 1); 5960786SpsMODULE_VERSION(ahc_pci, 1); 6060786Sps 6160786Spsstatic int 6260786Spsahc_pci_probe(device_t dev) 6360786Sps{ 6460786Sps struct ahc_pci_identity *entry; 65128348Stjr 66170259Sdelphij entry = ahc_find_pci_device(dev); 67221715Sdelphij if (entry != NULL) { 68221715Sdelphij device_set_desc(dev, entry->name); 6960786Sps return (BUS_PROBE_DEFAULT); 7060786Sps } 7160786Sps return (ENXIO); 72161478Sdelphij} 7360786Sps 7460786Spsstatic int 7560786Spsahc_pci_attach(device_t dev) 7660786Sps{ 77221715Sdelphij struct ahc_pci_identity *entry; 78221715Sdelphij struct ahc_softc *ahc; 79221715Sdelphij char *name; 80221715Sdelphij int error; 81221715Sdelphij 82221715Sdelphij entry = ahc_find_pci_device(dev); 83221715Sdelphij if (entry == NULL) 8460786Sps return (ENXIO); 8560786Sps 8660786Sps /* 87170259Sdelphij * Allocate a softc for this card and 8860786Sps * set it up for attachment by our 8960786Sps * common detect routine. 9060786Sps */ 9160786Sps name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); 9260786Sps if (name == NULL) 9360786Sps return (ENOMEM); 94191930Sdelphij strcpy(name, device_get_nameunit(dev)); 9560786Sps ahc = ahc_alloc(dev, name); 96191930Sdelphij if (ahc == NULL) 97170967Sdelphij return (ENOMEM); 9860786Sps 9960786Sps ahc_set_unit(ahc, device_get_unit(dev)); 10060786Sps 10160786Sps /* 10260786Sps * Should we bother disabling 39Bit addressing 10360786Sps * based on installed memory? 10460786Sps */ 10560786Sps if (sizeof(bus_addr_t) > 4) 10660786Sps ahc->flags |= AHC_39BIT_ADDRESSING; 107237613Sdelphij 108237613Sdelphij /* Allocate a dmatag for our SCB DMA maps */ 10960786Sps /* XXX Should be a child of the PCI bus dma tag */ 11060786Sps error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), 11160786Sps /*alignment*/1, /*boundary*/0, 112170259Sdelphij (ahc->flags & AHC_39BIT_ADDRESSING) 11360786Sps ? 0x7FFFFFFFFFLL 11460786Sps : BUS_SPACE_MAXADDR_32BIT, 11560786Sps /*highaddr*/BUS_SPACE_MAXADDR, 11660786Sps /*filter*/NULL, /*filterarg*/NULL, 11760786Sps /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 11860786Sps /*nsegments*/AHC_NSEG, 11960786Sps /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 12060786Sps /*flags*/0, 12160786Sps &ahc->parent_dmat); 12260786Sps 12360786Sps if (error != 0) { 12460786Sps printf("ahc_pci_attach: Could not allocate DMA tag " 12560786Sps "- error %d\n", error); 12660786Sps ahc_free(ahc); 12760786Sps return (ENOMEM); 12860786Sps } 12960786Sps ahc->dev_softc = dev; 130191930Sdelphij error = ahc_pci_config(ahc, entry); 131191930Sdelphij if (error != 0) { 132191930Sdelphij ahc_free(ahc); 133191930Sdelphij return (error); 134191930Sdelphij } 13560786Sps 13660786Sps ahc_attach(ahc); 13760786Sps return (0); 13860786Sps} 13960786Sps 140170259Sdelphijint 14160786Spsahc_pci_map_registers(struct ahc_softc *ahc) 14260786Sps{ 14360786Sps struct resource *regs; 14460786Sps u_int command; 14560786Sps int regs_type; 14660786Sps int regs_id; 14760786Sps int allow_memio; 14860786Sps 14960786Sps command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 15060786Sps regs = NULL; 15160786Sps regs_type = 0; 15260786Sps regs_id = 0; 15360786Sps 154191930Sdelphij /* Retrieve the per-device 'allow_memio' hint */ 155191930Sdelphij if (resource_int_value(device_get_name(ahc->dev_softc), 156191930Sdelphij device_get_unit(ahc->dev_softc), 157191930Sdelphij "allow_memio", &allow_memio) != 0) { 158191930Sdelphij if (bootverbose) 15960786Sps device_printf(ahc->dev_softc, "Defaulting to MEMIO "); 16060786Sps#ifdef AHC_ALLOW_MEMIO 16160786Sps if (bootverbose) 16260786Sps printf("on\n"); 16360786Sps allow_memio = 1; 16460786Sps#else 16560786Sps if (bootverbose) 16660786Sps printf("off\n"); 16760786Sps allow_memio = 0; 16860786Sps#endif 16960786Sps } 17060786Sps 17160786Sps if ((allow_memio != 0) && (command & PCIM_CMD_MEMEN) != 0) { 17260786Sps 17360786Sps regs_type = SYS_RES_MEMORY; 17460786Sps regs_id = AHC_PCI_MEMADDR; 17560786Sps regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, 17660786Sps ®s_id, RF_ACTIVE); 17760786Sps if (regs != NULL) { 17860786Sps ahc->tag = rman_get_bustag(regs); 17960786Sps ahc->bsh = rman_get_bushandle(regs); 18060786Sps 181170259Sdelphij /* 18260786Sps * Do a quick test to see if memory mapped 18360786Sps * I/O is functioning correctly. 18460786Sps */ 18560786Sps if (ahc_pci_test_register_access(ahc) != 0) { 18660786Sps device_printf(ahc->dev_softc, 18760786Sps "PCI Device %d:%d:%d failed memory " 18860786Sps "mapped test. Using PIO.\n", 18960786Sps aic_get_pci_bus(ahc->dev_softc), 19060786Sps aic_get_pci_slot(ahc->dev_softc), 19160786Sps aic_get_pci_function(ahc->dev_softc)); 19260786Sps bus_release_resource(ahc->dev_softc, regs_type, 19360786Sps regs_id, regs); 19460786Sps regs = NULL; 19560786Sps } else { 19660786Sps command &= ~PCIM_CMD_PORTEN; 19760786Sps aic_pci_write_config(ahc->dev_softc, 19860786Sps PCIR_COMMAND, 19960786Sps command, /*bytes*/1); 20060786Sps } 20160786Sps } 20260786Sps } 20360786Sps 20460786Sps if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) { 20560786Sps regs_type = SYS_RES_IOPORT; 20660786Sps regs_id = AHC_PCI_IOADDR; 20760786Sps regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, 20860786Sps ®s_id, RF_ACTIVE); 20960786Sps if (regs != NULL) { 21060786Sps ahc->tag = rman_get_bustag(regs); 21160786Sps ahc->bsh = rman_get_bushandle(regs); 21260786Sps if (ahc_pci_test_register_access(ahc) != 0) { 21360786Sps device_printf(ahc->dev_softc, 21460786Sps "PCI Device %d:%d:%d failed I/O " 215128348Stjr "mapped test.\n", 21660786Sps aic_get_pci_bus(ahc->dev_softc), 217191930Sdelphij aic_get_pci_slot(ahc->dev_softc), 218191930Sdelphij aic_get_pci_function(ahc->dev_softc)); 219191930Sdelphij bus_release_resource(ahc->dev_softc, regs_type, 220191930Sdelphij regs_id, regs); 221191930Sdelphij regs = NULL; 222191930Sdelphij } else { 22360786Sps command &= ~PCIM_CMD_MEMEN; 22460786Sps aic_pci_write_config(ahc->dev_softc, 22560786Sps PCIR_COMMAND, 22660786Sps command, /*bytes*/1); 22760786Sps } 22860786Sps } 22960786Sps } 23060786Sps if (regs == NULL) { 23160786Sps device_printf(ahc->dev_softc, 23260786Sps "can't allocate register resources\n"); 23360786Sps return (ENOMEM); 23460786Sps } 23560786Sps ahc->platform_data->regs_res_type = regs_type; 23660786Sps ahc->platform_data->regs_res_id = regs_id; 237221715Sdelphij ahc->platform_data->regs = regs; 238221715Sdelphij return (0); 23960786Sps} 24060786Sps