acpi_pcib_acpi.c revision 129879
138451Smsmith/*- 238451Smsmith * Copyright (c) 2000 Michael Smith 338451Smsmith * Copyright (c) 2000 BSDi 438451Smsmith * All rights reserved. 538451Smsmith * 638451Smsmith * Redistribution and use in source and binary forms, with or without 738451Smsmith * modification, are permitted provided that the following conditions 838451Smsmith * are met: 938451Smsmith * 1. Redistributions of source code must retain the above copyright 1038451Smsmith * notice, this list of conditions and the following disclaimer. 1138451Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1238451Smsmith * notice, this list of conditions and the following disclaimer in the 1338451Smsmith * documentation and/or other materials provided with the distribution. 1438451Smsmith * 1538451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1638451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1738451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1838451Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1938451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2038451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2138451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2238451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2338451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2438451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2538451Smsmith * SUCH DAMAGE. 2638451Smsmith * 2738451Smsmith * $FreeBSD: head/sys/dev/acpica/acpi_pcib_acpi.c 129879 2004-05-30 20:08:47Z phk $ 2838451Smsmith */ 2938451Smsmith#include "opt_acpi.h" 3038451Smsmith#include <sys/param.h> 3138451Smsmith#include <sys/bus.h> 3238451Smsmith#include <sys/kernel.h> 3338451Smsmith#include <sys/malloc.h> 3438451Smsmith#include <sys/module.h> 3538451Smsmith 3638451Smsmith#include "acpi.h" 3738451Smsmith#include <dev/acpica/acpivar.h> 3884221Sdillon 3984221Sdillon#include <machine/pci_cfgreg.h> 4084221Sdillon#include <dev/pci/pcivar.h> 4138451Smsmith#include <dev/pci/pcib_private.h> 4238451Smsmith#include "pcib_if.h" 4338451Smsmith 4438451Smsmith#include <dev/acpica/acpi_pcibvar.h> 4538451Smsmith 4638451Smsmith/* Hooks for the ACPI CA debugging infrastructure. */ 4738451Smsmith#define _COMPONENT ACPI_BUS 4838451SmsmithACPI_MODULE_NAME("PCI_ACPI") 4938451Smsmith 50185643Sluigistruct acpi_hpcib_softc { 51185643Sluigi device_t ap_dev; 52193189Sed ACPI_HANDLE ap_handle; 53185643Sluigi 54185643Sluigi int ap_segment; /* analagous to Alpha 'hose' */ 55185643Sluigi int ap_bus; /* bios-assigned bus number */ 5638451Smsmith 5738451Smsmith ACPI_BUFFER ap_prt; /* interrupt routing table */ 5838451Smsmith}; 5938451Smsmith 6038451Smsmithstatic int acpi_pcib_acpi_probe(device_t bus); 6138451Smsmithstatic int acpi_pcib_acpi_attach(device_t bus); 6238451Smsmithstatic int acpi_pcib_acpi_resume(device_t bus); 6338451Smsmithstatic int acpi_pcib_read_ivar(device_t dev, device_t child, 6438451Smsmith int which, uintptr_t *result); 6538451Smsmithstatic int acpi_pcib_write_ivar(device_t dev, device_t child, 6638451Smsmith int which, uintptr_t value); 6738451Smsmithstatic uint32_t acpi_pcib_read_config(device_t dev, int bus, int slot, 6838451Smsmith int func, int reg, int bytes); 6938451Smsmithstatic void acpi_pcib_write_config(device_t dev, int bus, int slot, 7038451Smsmith int func, int reg, uint32_t data, int bytes); 7138451Smsmithstatic int acpi_pcib_acpi_route_interrupt(device_t pcib, 7238451Smsmith device_t dev, int pin); 7338451Smsmithstatic struct resource *acpi_pcib_acpi_alloc_resource(device_t dev, 7438451Smsmith device_t child, int type, int *rid, 7538451Smsmith u_long start, u_long end, u_long count, 7638451Smsmith u_int flags); 7738451Smsmith 7838451Smsmithstatic device_method_t acpi_pcib_acpi_methods[] = { 7938451Smsmith /* Device interface */ 8038451Smsmith DEVMETHOD(device_probe, acpi_pcib_acpi_probe), 81185643Sluigi DEVMETHOD(device_attach, acpi_pcib_acpi_attach), 82185643Sluigi DEVMETHOD(device_shutdown, bus_generic_shutdown), 83185643Sluigi DEVMETHOD(device_suspend, bus_generic_suspend), 84185643Sluigi DEVMETHOD(device_resume, acpi_pcib_acpi_resume), 85185643Sluigi 86185643Sluigi /* Bus interface */ 87185643Sluigi DEVMETHOD(bus_print_child, bus_generic_print_child), 8838451Smsmith DEVMETHOD(bus_read_ivar, acpi_pcib_read_ivar), 8938451Smsmith DEVMETHOD(bus_write_ivar, acpi_pcib_write_ivar), 9038451Smsmith DEVMETHOD(bus_alloc_resource, acpi_pcib_acpi_alloc_resource), 9138451Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 9238451Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 9338451Smsmith DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 9438451Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 9564527Sps DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 9638451Smsmith 9764527Sps /* pcib interface */ 9838451Smsmith DEVMETHOD(pcib_maxslots, pcib_maxslots), 9938451Smsmith DEVMETHOD(pcib_read_config, acpi_pcib_read_config), 10092913Sobrien DEVMETHOD(pcib_write_config, acpi_pcib_write_config), 10138451Smsmith DEVMETHOD(pcib_route_interrupt, acpi_pcib_acpi_route_interrupt), 10238451Smsmith 10338451Smsmith {0, 0} 10438451Smsmith}; 10538451Smsmith 10638451Smsmithstatic driver_t acpi_pcib_acpi_driver = { 10738451Smsmith "pcib", 10838451Smsmith acpi_pcib_acpi_methods, 10938451Smsmith sizeof(struct acpi_hpcib_softc), 11038451Smsmith}; 11138451Smsmith 11238451SmsmithDRIVER_MODULE(acpi_pcib, acpi, acpi_pcib_acpi_driver, pcib_devclass, 0, 0); 11338451SmsmithMODULE_DEPEND(acpi_pcib, acpi, 1, 1, 1); 11438451Smsmith 11538451Smsmithstatic int 11638451Smsmithacpi_pcib_acpi_probe(device_t dev) 11738451Smsmith{ 11838451Smsmith 11938451Smsmith if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("pci") && 12038451Smsmith acpi_MatchHid(dev, "PNP0A03")) { 12138451Smsmith 12238451Smsmith if (pci_cfgregopen() == 0) 12338451Smsmith return (ENXIO); 12438451Smsmith device_set_desc(dev, "ACPI Host-PCI bridge"); 12538451Smsmith return (0); 12638451Smsmith } 12738451Smsmith return (ENXIO); 12838451Smsmith} 12938451Smsmith 13038451Smsmithstatic int 13138451Smsmithacpi_pcib_acpi_attach(device_t dev) 13238451Smsmith{ 13338451Smsmith struct acpi_hpcib_softc *sc; 13438451Smsmith ACPI_STATUS status; 13538451Smsmith u_int addr, slot, func, busok; 13638451Smsmith uint8_t busno; 13738451Smsmith 13838451Smsmith ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 13938451Smsmith 14064527Sps sc = device_get_softc(dev); 14164527Sps sc->ap_dev = dev; 14264527Sps sc->ap_handle = acpi_get_handle(dev); 14364527Sps 14464527Sps /* 14564527Sps * Get our base bus number by evaluating _BBN. 14664527Sps * If this doesn't work, we assume we're bus number 0. 14764527Sps * 14864527Sps * XXX note that it may also not exist in the case where we are 14964527Sps * meant to use a private configuration space mechanism for this bus, 15064527Sps * so we should dig out our resources and check to see if we have 15164527Sps * anything like that. How do we do this? 15264527Sps * XXX If we have the requisite information, and if we don't think the 15338451Smsmith * default PCI configuration space handlers can deal with this bus, 15438451Smsmith * we should attach our own handler. 15538451Smsmith * XXX invoke _REG on this for the PCI config space address space? 15638451Smsmith * XXX It seems many BIOS's with multiple Host-PCI bridges do not set 15738451Smsmith * _BBN correctly. They set _BBN to zero for all bridges. Thus, 15838451Smsmith * if _BBN is zero and pcib0 already exists, we try to read our 15938451Smsmith * bus number from the configuration registers at address _ADR. 16038451Smsmith */ 16138451Smsmith status = acpi_GetInteger(sc->ap_handle, "_BBN", &sc->ap_bus); 16238451Smsmith if (ACPI_FAILURE(status)) { 16338451Smsmith if (status != AE_NOT_FOUND) { 16438451Smsmith device_printf(dev, "could not evaluate _BBN - %s\n", 16538451Smsmith AcpiFormatException(status)); 16638451Smsmith return_VALUE (ENXIO); 16738451Smsmith } else { 16838451Smsmith /* If it's not found, assume 0. */ 16938451Smsmith sc->ap_bus = 0; 17038451Smsmith } 17138451Smsmith } 17238451Smsmith 17338451Smsmith /* 17438451Smsmith * If the bus is zero and pcib0 already exists, read the bus number 17538451Smsmith * via PCI config space. 17638451Smsmith */ 17738451Smsmith busok = 1; 17838451Smsmith if (sc->ap_bus == 0 && devclass_get_device(pcib_devclass, 0) != dev) { 17938451Smsmith busok = 0; 18038451Smsmith status = acpi_GetInteger(sc->ap_handle, "_ADR", &addr); 18138451Smsmith if (ACPI_FAILURE(status)) { 18238451Smsmith if (status != AE_NOT_FOUND) { 18338451Smsmith device_printf(dev, "could not evaluate _ADR - %s\n", 18438451Smsmith AcpiFormatException(status)); 18538451Smsmith return_VALUE (ENXIO); 18638451Smsmith } else 18738451Smsmith device_printf(dev, "couldn't find _ADR\n"); 18838451Smsmith } else { 18964527Sps /* XXX: We assume bus 0. */ 19064527Sps slot = addr >> 16; 19164527Sps func = addr & 0xffff; 19264527Sps if (bootverbose) 19364527Sps device_printf(dev, "reading config registers from 0:%d:%d\n", 19464527Sps slot, func); 19564527Sps if (host_pcib_get_busno(pci_cfgregread, 0, slot, func, &busno) == 0) 19638451Smsmith device_printf(dev, "couldn't read bus number from cfg space\n"); 19738451Smsmith else { 19838451Smsmith sc->ap_bus = busno; 19938451Smsmith busok = 1; 20038451Smsmith } 20138451Smsmith } 20238451Smsmith } 20338451Smsmith 20438451Smsmith /* 20538451Smsmith * If nothing else worked, hope that ACPI at least lays out the 20638451Smsmith * host-PCI bridges in order and that as a result our unit number 20738451Smsmith * is actually our bus number. There are several reasons this 20838451Smsmith * might not be true. 20938451Smsmith */ 21038451Smsmith if (busok == 0) { 21138451Smsmith sc->ap_bus = device_get_unit(dev); 21238451Smsmith device_printf(dev, "trying bus number %d\n", sc->ap_bus); 21338451Smsmith } 21438451Smsmith 21566134Sps /* 21638451Smsmith * Get our segment number by evaluating _SEG 21766134Sps * It's OK for this to not exist. 21838451Smsmith */ 21938451Smsmith status = acpi_GetInteger(sc->ap_handle, "_SEG", &sc->ap_segment); 22038451Smsmith if (ACPI_FAILURE(status)) { 22138451Smsmith if (status != AE_NOT_FOUND) { 22238451Smsmith device_printf(dev, "could not evaluate _SEG - %s\n", 22338451Smsmith AcpiFormatException(status)); 22438451Smsmith return_VALUE (ENXIO); 22538451Smsmith } 22638451Smsmith /* If it's not found, assume 0. */ 22738451Smsmith sc->ap_segment = 0; 22838451Smsmith } 22938451Smsmith 23038451Smsmith return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_bus)); 23138451Smsmith} 23238451Smsmith 23338451Smsmithstatic int 23438451Smsmithacpi_pcib_acpi_resume(device_t dev) 23538451Smsmith{ 23638451Smsmith struct acpi_hpcib_softc *sc = device_get_softc(dev); 23738451Smsmith 23838451Smsmith return (acpi_pcib_resume(dev, &sc->ap_prt, sc->ap_bus)); 23938451Smsmith} 24038451Smsmith 24138451Smsmith/* 24238451Smsmith * Support for standard PCI bridge ivars. 24338451Smsmith */ 24438451Smsmithstatic int 24538451Smsmithacpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 24638451Smsmith{ 24738451Smsmith struct acpi_hpcib_softc *sc = device_get_softc(dev); 24838451Smsmith 24938451Smsmith switch (which) { 25038451Smsmith case PCIB_IVAR_BUS: 25138451Smsmith *result = sc->ap_bus; 25238451Smsmith return (0); 25338451Smsmith case ACPI_IVAR_HANDLE: 25438451Smsmith *result = (uintptr_t)sc->ap_handle; 25538451Smsmith return (0); 25638451Smsmith } 25738451Smsmith return (ENOENT); 25838451Smsmith} 25938451Smsmith 26038451Smsmithstatic int 26138451Smsmithacpi_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 26238451Smsmith{ 26338451Smsmith struct acpi_hpcib_softc *sc = device_get_softc(dev); 26438451Smsmith 26538451Smsmith switch (which) { 26638451Smsmith case PCIB_IVAR_BUS: 26738451Smsmith sc->ap_bus = value; 26892913Sobrien return (0); 26992913Sobrien } 27092913Sobrien return (ENOENT); 27138451Smsmith} 27292913Sobrien 27338451Smsmithstatic uint32_t 27438451Smsmithacpi_pcib_read_config(device_t dev, int bus, int slot, int func, int reg, 27538451Smsmith int bytes) 27638451Smsmith{ 27738451Smsmith return (pci_cfgregread(bus, slot, func, reg, bytes)); 27838451Smsmith} 27938451Smsmith 28038451Smsmithstatic void 28138451Smsmithacpi_pcib_write_config(device_t dev, int bus, int slot, int func, int reg, 28238451Smsmith uint32_t data, int bytes) 28338451Smsmith{ 28438451Smsmith pci_cfgregwrite(bus, slot, func, reg, data, bytes); 28538451Smsmith} 28638451Smsmith 28738451Smsmithstatic int 28838451Smsmithacpi_pcib_acpi_route_interrupt(device_t pcib, device_t dev, int pin) 28938451Smsmith{ 29038451Smsmith struct acpi_hpcib_softc *sc; 29138451Smsmith 29292913Sobrien /* Find the bridge softc. */ 29392913Sobrien sc = device_get_softc(pcib); 29492913Sobrien return (acpi_pcib_route_interrupt(pcib, dev, pin, &sc->ap_prt)); 29538451Smsmith} 29638451Smsmith 29792913Sobrienstruct resource * 29892913Sobrienacpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid, 29938451Smsmith u_long start, u_long end, u_long count, u_int flags) 30038451Smsmith{ 30138451Smsmith /* 30238451Smsmith * If no memory preference is given, use upper 256MB slot most 30338451Smsmith * bioses use for their memory window. Typically other bridges 30438451Smsmith * before us get in the way to assert their preferences on memory. 30538451Smsmith * Hardcoding like this sucks, so a more MD/MI way needs to be 30638451Smsmith * found to do it. 30738451Smsmith */ 30838451Smsmith if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL) 30938451Smsmith start = 0xf0000000; 31038451Smsmith return (bus_generic_alloc_resource(dev, child, type, rid, start, end, 31138451Smsmith count, flags)); 31238451Smsmith} 31338451Smsmith