1139749Simp/*- 265942Sgibbs * FreeBSD, PCI product support functions 339222Sgibbs * 471717Sgibbs * Copyright (c) 1995-2001 Justin T. Gibbs 539222Sgibbs * All rights reserved. 639222Sgibbs * 739222Sgibbs * Redistribution and use in source and binary forms, with or without 839222Sgibbs * modification, are permitted provided that the following conditions 939222Sgibbs * are met: 1039222Sgibbs * 1. Redistributions of source code must retain the above copyright 1139222Sgibbs * notice, this list of conditions, and the following disclaimer, 1239222Sgibbs * without modification, immediately at the beginning of the file. 1339222Sgibbs * 2. The name of the author may not be used to endorse or promote products 1439222Sgibbs * derived from this software without specific prior written permission. 1539222Sgibbs * 1663457Sgibbs * Alternatively, this software may be distributed under the terms of the 1763457Sgibbs * GNU Public License ("GPL"). 1839222Sgibbs * 1939222Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2039222Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2139222Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2239222Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2339222Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2439222Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2539222Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2639222Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2739222Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2839222Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2939222Sgibbs * SUCH DAMAGE. 3039222Sgibbs * 31123579Sgibbs * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $ 3239222Sgibbs */ 3339222Sgibbs 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD$"); 36119418Sobrien 3795378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 3839222Sgibbs 3945969Sgibbsstatic int ahc_pci_probe(device_t dev); 4045969Sgibbsstatic int ahc_pci_attach(device_t dev); 4139222Sgibbs 4295378Sgibbsstatic device_method_t ahc_pci_device_methods[] = { 4345969Sgibbs /* Device interface */ 4445969Sgibbs DEVMETHOD(device_probe, ahc_pci_probe), 4545969Sgibbs DEVMETHOD(device_attach, ahc_pci_attach), 4670204Sgibbs DEVMETHOD(device_detach, ahc_detach), 4745969Sgibbs { 0, 0 } 4845969Sgibbs}; 4945969Sgibbs 5045969Sgibbsstatic driver_t ahc_pci_driver = { 51103811Sscottl "ahc", 5295378Sgibbs ahc_pci_device_methods, 5345969Sgibbs sizeof(struct ahc_softc) 5439222Sgibbs}; 5539222Sgibbs 56103811SscottlDRIVER_MODULE(ahc_pci, pci, ahc_pci_driver, ahc_devclass, 0, 0); 5776634SgibbsMODULE_DEPEND(ahc_pci, ahc, 1, 1, 1); 5876634SgibbsMODULE_VERSION(ahc_pci, 1); 5945969Sgibbs 6047275Sgibbsstatic int 6147275Sgibbsahc_pci_probe(device_t dev) 6247275Sgibbs{ 6365942Sgibbs struct ahc_pci_identity *entry; 6447275Sgibbs 6547275Sgibbs entry = ahc_find_pci_device(dev); 6647275Sgibbs if (entry != NULL) { 6747275Sgibbs device_set_desc(dev, entry->name); 68143164Simp return (BUS_PROBE_DEFAULT); 6947275Sgibbs } 7045969Sgibbs return (ENXIO); 7139222Sgibbs} 7239222Sgibbs 7345969Sgibbsstatic int 7445969Sgibbsahc_pci_attach(device_t dev) 7539222Sgibbs{ 7665942Sgibbs struct ahc_pci_identity *entry; 7765942Sgibbs struct ahc_softc *ahc; 7865942Sgibbs char *name; 7965942Sgibbs int error; 8039222Sgibbs 8147275Sgibbs entry = ahc_find_pci_device(dev); 8247275Sgibbs if (entry == NULL) 8347275Sgibbs return (ENXIO); 8439222Sgibbs 8565942Sgibbs /* 8665942Sgibbs * Allocate a softc for this card and 8765942Sgibbs * set it up for attachment by our 8865942Sgibbs * common detect routine. 8965942Sgibbs */ 9065942Sgibbs name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); 9165942Sgibbs if (name == NULL) 9245969Sgibbs return (ENOMEM); 9365942Sgibbs strcpy(name, device_get_nameunit(dev)); 9470204Sgibbs ahc = ahc_alloc(dev, name); 9565942Sgibbs if (ahc == NULL) 9665942Sgibbs return (ENOMEM); 9739222Sgibbs 9871390Sgibbs ahc_set_unit(ahc, device_get_unit(dev)); 9971390Sgibbs 10079874Sgibbs /* 10179874Sgibbs * Should we bother disabling 39Bit addressing 10279874Sgibbs * based on installed memory? 10379874Sgibbs */ 10479874Sgibbs if (sizeof(bus_addr_t) > 4) 10579874Sgibbs ahc->flags |= AHC_39BIT_ADDRESSING; 10679874Sgibbs 10739222Sgibbs /* Allocate a dmatag for our SCB DMA maps */ 108161928Sjmg error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), 109161928Sjmg /*alignment*/1, /*boundary*/0, 11079874Sgibbs (ahc->flags & AHC_39BIT_ADDRESSING) 111121421Sdes ? 0x7FFFFFFFFFLL 11279874Sgibbs : BUS_SPACE_MAXADDR_32BIT, 11339222Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 11439222Sgibbs /*filter*/NULL, /*filterarg*/NULL, 115108479Sscottl /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 116108479Sscottl /*nsegments*/AHC_NSEG, 11739222Sgibbs /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 118114618Sgibbs /*flags*/0, 11965942Sgibbs &ahc->parent_dmat); 12039222Sgibbs 12139222Sgibbs if (error != 0) { 12245969Sgibbs printf("ahc_pci_attach: Could not allocate DMA tag " 12345969Sgibbs "- error %d\n", error); 12439222Sgibbs ahc_free(ahc); 12545969Sgibbs return (ENOMEM); 12639222Sgibbs } 12765942Sgibbs ahc->dev_softc = dev; 12865942Sgibbs error = ahc_pci_config(ahc, entry); 12965942Sgibbs if (error != 0) { 13039222Sgibbs ahc_free(ahc); 13165942Sgibbs return (error); 13239222Sgibbs } 13339222Sgibbs 13445969Sgibbs ahc_attach(ahc); 13545969Sgibbs return (0); 13639222Sgibbs} 13739222Sgibbs 13865942Sgibbsint 13965942Sgibbsahc_pci_map_registers(struct ahc_softc *ahc) 14055580Sgibbs{ 14165942Sgibbs struct resource *regs; 14265942Sgibbs int regs_type; 14365942Sgibbs int regs_id; 144107418Sscottl int allow_memio; 14555580Sgibbs 14665942Sgibbs regs = NULL; 14765942Sgibbs regs_type = 0; 14865942Sgibbs regs_id = 0; 149107418Sscottl 150107418Sscottl /* Retrieve the per-device 'allow_memio' hint */ 151107418Sscottl if (resource_int_value(device_get_name(ahc->dev_softc), 152107418Sscottl device_get_unit(ahc->dev_softc), 153107418Sscottl "allow_memio", &allow_memio) != 0) { 154107418Sscottl if (bootverbose) 155107418Sscottl device_printf(ahc->dev_softc, "Defaulting to MEMIO "); 15666269Sgibbs#ifdef AHC_ALLOW_MEMIO 157107418Sscottl if (bootverbose) 158107418Sscottl printf("on\n"); 159107418Sscottl allow_memio = 1; 160107418Sscottl#else 161107418Sscottl if (bootverbose) 162107418Sscottl printf("off\n"); 163107418Sscottl allow_memio = 0; 164107418Sscottl#endif 165107418Sscottl } 16670204Sgibbs 167254263Sscottl if (allow_memio != 0) { 168107418Sscottl 16965942Sgibbs regs_type = SYS_RES_MEMORY; 17065942Sgibbs regs_id = AHC_PCI_MEMADDR; 171127135Snjl regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, 172127135Snjl ®s_id, RF_ACTIVE); 17365942Sgibbs if (regs != NULL) { 17465942Sgibbs ahc->tag = rman_get_bustag(regs); 17565942Sgibbs ahc->bsh = rman_get_bushandle(regs); 17655580Sgibbs 17763457Sgibbs /* 17865942Sgibbs * Do a quick test to see if memory mapped 17965942Sgibbs * I/O is functioning correctly. 18063457Sgibbs */ 181107418Sscottl if (ahc_pci_test_register_access(ahc) != 0) { 18265942Sgibbs device_printf(ahc->dev_softc, 18365942Sgibbs "PCI Device %d:%d:%d failed memory " 18465942Sgibbs "mapped test. Using PIO.\n", 185123579Sgibbs aic_get_pci_bus(ahc->dev_softc), 186123579Sgibbs aic_get_pci_slot(ahc->dev_softc), 187123579Sgibbs aic_get_pci_function(ahc->dev_softc)); 18865942Sgibbs bus_release_resource(ahc->dev_softc, regs_type, 18965942Sgibbs regs_id, regs); 19065942Sgibbs regs = NULL; 19139222Sgibbs } 19239222Sgibbs } 19339222Sgibbs } 194107418Sscottl 195254263Sscottl if (regs == NULL) { 19665942Sgibbs regs_type = SYS_RES_IOPORT; 19765942Sgibbs regs_id = AHC_PCI_IOADDR; 198127135Snjl regs = bus_alloc_resource_any(ahc->dev_softc, regs_type, 199127135Snjl ®s_id, RF_ACTIVE); 20079874Sgibbs if (regs != NULL) { 20178555Smjacob ahc->tag = rman_get_bustag(regs); 20278555Smjacob ahc->bsh = rman_get_bushandle(regs); 203123579Sgibbs if (ahc_pci_test_register_access(ahc) != 0) { 204123579Sgibbs device_printf(ahc->dev_softc, 205123579Sgibbs "PCI Device %d:%d:%d failed I/O " 206123579Sgibbs "mapped test.\n", 207123579Sgibbs aic_get_pci_bus(ahc->dev_softc), 208123579Sgibbs aic_get_pci_slot(ahc->dev_softc), 209123579Sgibbs aic_get_pci_function(ahc->dev_softc)); 210123579Sgibbs bus_release_resource(ahc->dev_softc, regs_type, 211123579Sgibbs regs_id, regs); 212123579Sgibbs regs = NULL; 213123579Sgibbs } 21478555Smjacob } 21563457Sgibbs } 21665942Sgibbs if (regs == NULL) { 21765942Sgibbs device_printf(ahc->dev_softc, 21865942Sgibbs "can't allocate register resources\n"); 21965942Sgibbs return (ENOMEM); 22039222Sgibbs } 22179874Sgibbs ahc->platform_data->regs_res_type = regs_type; 22279874Sgibbs ahc->platform_data->regs_res_id = regs_id; 22379874Sgibbs ahc->platform_data->regs = regs; 22447192Sgibbs return (0); 22547192Sgibbs} 226