acpi_pcib_acpi.c revision 78993
1140609Sdas/*- 2226245Sdas * Copyright (c) 2000 Michael Smith 3140609Sdas * Copyright (c) 2000 BSDi 4140609Sdas * All rights reserved. 5140609Sdas * 6140609Sdas * Redistribution and use in source and binary forms, with or without 7140609Sdas * modification, are permitted provided that the following conditions 8140609Sdas * are met: 9140609Sdas * 1. Redistributions of source code must retain the above copyright 10140609Sdas * notice, this list of conditions and the following disclaimer. 11140609Sdas * 2. Redistributions in binary form must reproduce the above copyright 12140609Sdas * notice, this list of conditions and the following disclaimer in the 13140609Sdas * documentation and/or other materials provided with the distribution. 14140609Sdas * 15140609Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16140609Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17140609Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18140609Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19140609Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20140609Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21140609Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22140609Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23140609Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24140609Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25140609Sdas * SUCH DAMAGE. 26140609Sdas * 27140609Sdas * $FreeBSD: head/sys/dev/acpica/acpi_pcib_acpi.c 78993 2001-06-29 20:32:29Z msmith $ 28140609Sdas */ 29140609Sdas#include "opt_acpi.h" 30140609Sdas#include <sys/param.h> 31140609Sdas#include <sys/kernel.h> 32140609Sdas#include <sys/bus.h> 33140609Sdas 34226371Sdas#include "acpi.h" 35226371Sdas 36140609Sdas#include <dev/acpica/acpivar.h> 37226245Sdas 38226245Sdas#include <machine/pci_cfgreg.h> 39226245Sdas#include <pci/pcivar.h> 40226245Sdas#include "pcib_if.h" 41226245Sdas 42226245Sdas/* 43226245Sdas * Hooks for the ACPI CA debugging infrastructure 44226245Sdas */ 45226245Sdas#define _COMPONENT ACPI_BUS 46226245SdasMODULE_NAME("PCI") 47226245Sdas 48226245Sdasstruct acpi_pcib_softc { 49226245Sdas device_t ap_dev; 50226245Sdas ACPI_HANDLE ap_handle; 51226245Sdas 52226245Sdas int ap_segment; /* analagous to Alpha 'hose' */ 53226245Sdas int ap_bus; /* bios-assigned bus number */ 54226245Sdas}; 55226245Sdas 56226245Sdasstatic int acpi_pcib_probe(device_t bus); 57226245Sdasstatic int acpi_pcib_attach(device_t bus); 58226245Sdasstatic int acpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); 59226245Sdasstatic int acpi_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value); 60226245Sdasstatic int acpi_pcib_maxslots(device_t dev); 61226245Sdasstatic u_int32_t acpi_pcib_read_config(device_t dev, int bus, int slot, int func, int reg, int bytes); 62226245Sdasstatic void acpi_pcib_write_config(device_t dev, int bus, int slot, int func, int reg, 63226245Sdas u_int32_t data, int bytes); 64226371Sdasstatic int acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin); 65226371Sdas 66226371Sdasstatic device_method_t acpi_pcib_methods[] = { 67226371Sdas /* Device interface */ 68226371Sdas DEVMETHOD(device_probe, acpi_pcib_probe), 69226371Sdas DEVMETHOD(device_attach, acpi_pcib_attach), 70226371Sdas DEVMETHOD(device_shutdown, bus_generic_shutdown), 71226371Sdas DEVMETHOD(device_suspend, bus_generic_suspend), 72226371Sdas DEVMETHOD(device_resume, bus_generic_resume), 73226371Sdas 74226371Sdas /* Bus interface */ 75226371Sdas DEVMETHOD(bus_print_child, bus_generic_print_child), 76226371Sdas DEVMETHOD(bus_read_ivar, acpi_pcib_read_ivar), 77226371Sdas DEVMETHOD(bus_write_ivar, acpi_pcib_write_ivar), 78226371Sdas DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 79226371Sdas DEVMETHOD(bus_release_resource, bus_generic_release_resource), 80226371Sdas DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 81226371Sdas DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 82226371Sdas DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 83226371Sdas DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 84226371Sdas 85226371Sdas /* pcib interface */ 86226371Sdas DEVMETHOD(pcib_maxslots, acpi_pcib_maxslots), 87226371Sdas DEVMETHOD(pcib_read_config, acpi_pcib_read_config), 88226371Sdas DEVMETHOD(pcib_write_config, acpi_pcib_write_config), 89226371Sdas DEVMETHOD(pcib_route_interrupt, acpi_pcib_route_interrupt), 90226371Sdas 91226371Sdas {0, 0} 92226371Sdas}; 93226371Sdas 94226371Sdasstatic driver_t acpi_pcib_driver = { 95226371Sdas "acpi_pcib", 96226371Sdas acpi_pcib_methods, 97226371Sdas sizeof(struct acpi_pcib_softc), 98226371Sdas}; 99226371Sdas 100226371Sdasdevclass_t acpi_pcib_devclass; 101226371SdasDRIVER_MODULE(acpi_pcib, acpi, acpi_pcib_driver, acpi_pcib_devclass, 0, 0); 102226371Sdas 103226371Sdasstatic int 104226371Sdasacpi_pcib_probe(device_t dev) 105226371Sdas{ 106226371Sdas 107226371Sdas if ((acpi_get_type(dev) == ACPI_TYPE_DEVICE) && 108226371Sdas !acpi_disabled("pci") && 109226371Sdas acpi_MatchHid(dev, "PNP0A03")) { 110226371Sdas 111226371Sdas /* 112226371Sdas * Set device description 113226371Sdas */ 114226371Sdas device_set_desc(dev, "Host-PCI bridge"); 115226371Sdas return(0); 116226371Sdas } 117226371Sdas return(ENXIO); 118226371Sdas} 119226371Sdas 120252170Seadlerstatic int 121226371Sdasacpi_pcib_attach(device_t dev) 122226371Sdas{ 123226371Sdas struct acpi_pcib_softc *sc; 124226371Sdas device_t child; 125226371Sdas ACPI_STATUS status; 126226371Sdas int result; 127226371Sdas 128226371Sdas FUNCTION_TRACE(__func__); 129226371Sdas 130226371Sdas sc = device_get_softc(dev); 131226245Sdas sc->ap_dev = dev; 132226245Sdas sc->ap_handle = acpi_get_handle(dev); 133226245Sdas 134226245Sdas /* 135226245Sdas * Don't attach if we're not really there. 136226245Sdas * 137226245Sdas * XXX this isn't entirely correct, since we may be a PCI bus 138226245Sdas * on a hot-plug docking station, etc. 139226245Sdas */ 140226245Sdas if (!acpi_DeviceIsPresent(dev)) 141226245Sdas return_VALUE(ENXIO); 142226245Sdas 143226245Sdas /* 144226245Sdas * Get our segment number by evaluating _SEG 145226245Sdas * It's OK for this to not exist. 146226245Sdas */ 147226245Sdas if ((status = acpi_EvaluateInteger(sc->ap_handle, "_SEG", &sc->ap_segment)) != AE_OK) { 148226245Sdas if (status != AE_NOT_FOUND) { 149226245Sdas device_printf(dev, "could not evaluate _SEG - %s\n", acpi_strerror(status)); 150226245Sdas return_VALUE(ENXIO); 151226245Sdas } 152226245Sdas /* if it's not found, assume 0 */ 153226245Sdas sc->ap_segment = 0; 154226245Sdas } 155226245Sdas 156226245Sdas /* 157226245Sdas * Get our base bus number by evaluating _BBN 158226245Sdas * If this doesn't exist, we assume we're bus number 0. 159226245Sdas * 160226245Sdas * XXX note that it may also not exist in the case where we are 161140609Sdas * meant to use a private configuration space mechanism for this bus, 162140609Sdas * so we should dig out our resources and check to see if we have 163140609Sdas * anything like that. How do we do this? 164140609Sdas * XXX If we have the requisite information, and if we don't think the 165140609Sdas * default PCI configuration space handlers can deal with this bus, 166140609Sdas * we should attach our own handler. 167140609Sdas * XXX invoke _REG on this for the PCI config space address space? 168140609Sdas */ 169140609Sdas if ((status = acpi_EvaluateInteger(sc->ap_handle, "_BBN", &sc->ap_bus)) != AE_OK) { 170140609Sdas if (status != AE_NOT_FOUND) { 171140609Sdas device_printf(dev, "could not evaluate _BBN - %s\n", acpi_strerror(status)); 172140609Sdas return_VALUE(ENXIO); 173140609Sdas } 174143780Sdas /* if it's not found, assume 0 */ 175143780Sdas sc->ap_bus = 0; 176140609Sdas } 177140609Sdas 178140609Sdas /* 179140609Sdas * Make sure that this bus hasn't already been found. If it has, return silently 180226371Sdas * (should we complain here?). 181226371Sdas */ 182140609Sdas if (devclass_get_device(devclass_find("pci"), sc->ap_bus) != NULL) 183140609Sdas return_VALUE(0); 184140609Sdas 185140609Sdas /* 186177875Sdas * Attach the PCI bus proper. 187177875Sdas */ 188177875Sdas if ((child = device_add_child(dev, "pci", sc->ap_bus)) == NULL) { 189177875Sdas device_printf(device_get_parent(dev), "couldn't attach pci bus"); 190177875Sdas return_VALUE(ENXIO); 191177875Sdas } 192177875Sdas 193140609Sdas /* 194140609Sdas * Now go scan the bus. 195177875Sdas * 196143230Sdas * XXX It would be nice to defer this and count on the nexus getting it 197177875Sdas * after the first pass, but this does not seem to be reliable. 198177875Sdas */ 199140609Sdas result = bus_generic_attach(dev); 200140609Sdas return_VALUE(result); 201140609Sdas} 202140609Sdas 203140609Sdasstatic int 204140609Sdasacpi_pcib_maxslots(device_t dev) 205140609Sdas{ 206140609Sdas return(31); 207140609Sdas} 208140609Sdas 209140609Sdasstatic int 210140609Sdasacpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 211140609Sdas{ 212140609Sdas struct acpi_pcib_softc *sc = device_get_softc(dev); 213140609Sdas 214140609Sdas switch (which) { 215140609Sdas case PCIB_IVAR_BUS: 216140609Sdas *result = sc->ap_bus; 217140609Sdas return(0); 218140609Sdas } 219140609Sdas return(ENOENT); 220140609Sdas} 221140609Sdas 222140609Sdasstatic int 223140609Sdasacpi_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 224140609Sdas{ 225140609Sdas struct acpi_pcib_softc *sc = device_get_softc(dev); 226140609Sdas 227140609Sdas switch (which) { 228140609Sdas case PCIB_IVAR_BUS: 229140609Sdas sc->ap_bus = value; 230140609Sdas return(0); 231140609Sdas } 232140609Sdas return(ENOENT); 233140609Sdas} 234140609Sdas 235226371Sdasstatic u_int32_t 236226371Sdasacpi_pcib_read_config(device_t dev, int bus, int slot, int func, int reg, int bytes) 237226371Sdas{ 238226371Sdas return(pci_cfgregread(bus, slot, func, reg, bytes)); 239140609Sdas} 240140609Sdas 241251024Sdasstatic void 242251024Sdasacpi_pcib_write_config(device_t dev, int bus, int slot, int func, int reg, u_int32_t data, int bytes) 243140609Sdas{ 244226371Sdas pci_cfgregwrite(bus, slot, func, reg, data, bytes); 245226371Sdas} 246226371Sdas 247226371Sdasstatic int 248226371Sdasacpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin) 249226371Sdas{ 250226371Sdas /* XXX this is not the right way to do this! */ 251226371Sdas pci_cfgregopen(); 252251024Sdas return(pci_cfgintr(pci_get_bus(dev), pci_get_slot(dev), pin)); 253226245Sdas} 254140609Sdas