167761Smsmith/*- 267761Smsmith * Copyright (c) 2000 Michael Smith 367761Smsmith * Copyright (c) 2000 BSDi 467761Smsmith * All rights reserved. 567761Smsmith * 667761Smsmith * Redistribution and use in source and binary forms, with or without 767761Smsmith * modification, are permitted provided that the following conditions 867761Smsmith * are met: 967761Smsmith * 1. Redistributions of source code must retain the above copyright 1067761Smsmith * notice, this list of conditions and the following disclaimer. 1167761Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1267761Smsmith * notice, this list of conditions and the following disclaimer in the 1367761Smsmith * documentation and/or other materials provided with the distribution. 1467761Smsmith * 1567761Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1667761Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1767761Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1867761Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1967761Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2067761Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2167761Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2267761Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2367761Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2467761Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2567761Smsmith * SUCH DAMAGE. 2667761Smsmith */ 27143002Sobrien 28143002Sobrien#include <sys/cdefs.h> 29143002Sobrien__FBSDID("$FreeBSD$"); 30143002Sobrien 3167761Smsmith#include "opt_acpi.h" 3267761Smsmith#include <sys/param.h> 3379284Smsmith#include <sys/bus.h> 34129811Snjl#include <sys/kernel.h> 35224069Sjhb#include <sys/limits.h> 3679284Smsmith#include <sys/malloc.h> 37129879Sphk#include <sys/module.h> 38221393Sjhb#include <sys/rman.h> 39136397Simp#include <sys/sysctl.h> 4067761Smsmith 41193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 42193530Sjkim#include <contrib/dev/acpica/include/accommon.h> 43193530Sjkim 4467761Smsmith#include <dev/acpica/acpivar.h> 4567761Smsmith 4667761Smsmith#include <machine/pci_cfgreg.h> 47119281Simp#include <dev/pci/pcivar.h> 48119281Simp#include <dev/pci/pcib_private.h> 4967761Smsmith#include "pcib_if.h" 5067761Smsmith 51102447Sjhb#include <dev/acpica/acpi_pcibvar.h> 52102447Sjhb 53129811Snjl/* Hooks for the ACPI CA debugging infrastructure. */ 5478993Smsmith#define _COMPONENT ACPI_BUS 55102447SjhbACPI_MODULE_NAME("PCI_ACPI") 5669744Smsmith 57102447Sjhbstruct acpi_hpcib_softc { 5867761Smsmith device_t ap_dev; 5967761Smsmith ACPI_HANDLE ap_handle; 60131341Snjl int ap_flags; 6167761Smsmith 62234150Sjhb int ap_segment; /* PCI domain */ 6367761Smsmith int ap_bus; /* bios-assigned bus number */ 64234150Sjhb int ap_addr; /* device/func of PCI-Host bridge */ 6579284Smsmith 6679284Smsmith ACPI_BUFFER ap_prt; /* interrupt routing table */ 67224069Sjhb#ifdef NEW_PCIB 68224069Sjhb struct pcib_host_resources ap_host_res; 69224069Sjhb#endif 7067761Smsmith}; 7167761Smsmith 72102447Sjhbstatic int acpi_pcib_acpi_probe(device_t bus); 73102447Sjhbstatic int acpi_pcib_acpi_attach(device_t bus); 74129811Snjlstatic int acpi_pcib_read_ivar(device_t dev, device_t child, 75129811Snjl int which, uintptr_t *result); 76129811Snjlstatic int acpi_pcib_write_ivar(device_t dev, device_t child, 77129811Snjl int which, uintptr_t value); 78188163Simpstatic uint32_t acpi_pcib_read_config(device_t dev, u_int bus, 79188163Simp u_int slot, u_int func, u_int reg, int bytes); 80188163Simpstatic void acpi_pcib_write_config(device_t dev, u_int bus, 81188163Simp u_int slot, u_int func, u_int reg, uint32_t data, 82188163Simp int bytes); 83102447Sjhbstatic int acpi_pcib_acpi_route_interrupt(device_t pcib, 84129811Snjl device_t dev, int pin); 85165128Sjhbstatic int acpi_pcib_alloc_msi(device_t pcib, device_t dev, 86165128Sjhb int count, int maxcount, int *irqs); 87169221Sjhbstatic int acpi_pcib_map_msi(device_t pcib, device_t dev, 88169221Sjhb int irq, uint64_t *addr, uint32_t *data); 89165128Sjhbstatic int acpi_pcib_alloc_msix(device_t pcib, device_t dev, 90169221Sjhb int *irq); 91128058Simpstatic struct resource *acpi_pcib_acpi_alloc_resource(device_t dev, 92137098Sdes device_t child, int type, int *rid, 93128058Simp u_long start, u_long end, u_long count, 94128058Simp u_int flags); 95224069Sjhb#ifdef NEW_PCIB 96224069Sjhbstatic int acpi_pcib_acpi_adjust_resource(device_t dev, 97224069Sjhb device_t child, int type, struct resource *r, 98224069Sjhb u_long start, u_long end); 99224069Sjhb#endif 10067761Smsmith 101102447Sjhbstatic device_method_t acpi_pcib_acpi_methods[] = { 10267761Smsmith /* Device interface */ 103102447Sjhb DEVMETHOD(device_probe, acpi_pcib_acpi_probe), 104102447Sjhb DEVMETHOD(device_attach, acpi_pcib_acpi_attach), 10567761Smsmith DEVMETHOD(device_shutdown, bus_generic_shutdown), 10667761Smsmith DEVMETHOD(device_suspend, bus_generic_suspend), 107210864Sjhb DEVMETHOD(device_resume, bus_generic_resume), 10867761Smsmith 10967761Smsmith /* Bus interface */ 11067761Smsmith DEVMETHOD(bus_read_ivar, acpi_pcib_read_ivar), 11167761Smsmith DEVMETHOD(bus_write_ivar, acpi_pcib_write_ivar), 112128058Simp DEVMETHOD(bus_alloc_resource, acpi_pcib_acpi_alloc_resource), 113224069Sjhb#ifdef NEW_PCIB 114224069Sjhb DEVMETHOD(bus_adjust_resource, acpi_pcib_acpi_adjust_resource), 115224069Sjhb#else 116221324Sjhb DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 117224069Sjhb#endif 11867761Smsmith DEVMETHOD(bus_release_resource, bus_generic_release_resource), 11967761Smsmith DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 120137098Sdes DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 12167761Smsmith DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 12267761Smsmith DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 12367761Smsmith 12467761Smsmith /* pcib interface */ 125102447Sjhb DEVMETHOD(pcib_maxslots, pcib_maxslots), 12667761Smsmith DEVMETHOD(pcib_read_config, acpi_pcib_read_config), 12767761Smsmith DEVMETHOD(pcib_write_config, acpi_pcib_write_config), 128102447Sjhb DEVMETHOD(pcib_route_interrupt, acpi_pcib_acpi_route_interrupt), 129165128Sjhb DEVMETHOD(pcib_alloc_msi, acpi_pcib_alloc_msi), 130164264Sjhb DEVMETHOD(pcib_release_msi, pcib_release_msi), 131165128Sjhb DEVMETHOD(pcib_alloc_msix, acpi_pcib_alloc_msix), 132164264Sjhb DEVMETHOD(pcib_release_msix, pcib_release_msix), 133169221Sjhb DEVMETHOD(pcib_map_msi, acpi_pcib_map_msi), 134211430Sjhb DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep), 13567761Smsmith 136229093Shselasky DEVMETHOD_END 13767761Smsmith}; 13867761Smsmith 139154079Sjhbstatic devclass_t pcib_devclass; 14067761Smsmith 141154079SjhbDEFINE_CLASS_0(pcib, acpi_pcib_acpi_driver, acpi_pcib_acpi_methods, 142154079Sjhb sizeof(struct acpi_hpcib_softc)); 143102447SjhbDRIVER_MODULE(acpi_pcib, acpi, acpi_pcib_acpi_driver, pcib_devclass, 0, 0); 144128071SnjlMODULE_DEPEND(acpi_pcib, acpi, 1, 1, 1); 14567761Smsmith 14667761Smsmithstatic int 147102447Sjhbacpi_pcib_acpi_probe(device_t dev) 14867761Smsmith{ 149197105Sjkim ACPI_DEVICE_INFO *devinfo; 150197105Sjkim ACPI_HANDLE h; 151197105Sjkim int root; 15267761Smsmith 153197105Sjkim if (acpi_disabled("pcib") || (h = acpi_get_handle(dev)) == NULL || 154197105Sjkim ACPI_FAILURE(AcpiGetObjectInfo(h, &devinfo))) 155131282Snjl return (ENXIO); 156197105Sjkim root = (devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0; 157197105Sjkim AcpiOsFree(devinfo); 158197105Sjkim if (!root || pci_cfgregopen() == 0) 159197105Sjkim return (ENXIO); 16067761Smsmith 161131282Snjl device_set_desc(dev, "ACPI Host-PCI bridge"); 162131282Snjl return (0); 16367761Smsmith} 16467761Smsmith 165224069Sjhb#ifdef NEW_PCIB 166224069Sjhbstatic ACPI_STATUS 167224069Sjhbacpi_pcib_producer_handler(ACPI_RESOURCE *res, void *context) 168224069Sjhb{ 169224069Sjhb struct acpi_hpcib_softc *sc; 170224069Sjhb UINT64 length, min, max; 171224069Sjhb u_int flags; 172224069Sjhb int error, type; 173224069Sjhb 174224069Sjhb sc = context; 175224069Sjhb switch (res->Type) { 176224069Sjhb case ACPI_RESOURCE_TYPE_START_DEPENDENT: 177224069Sjhb case ACPI_RESOURCE_TYPE_END_DEPENDENT: 178224069Sjhb panic("host bridge has depenedent resources"); 179224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS16: 180224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS32: 181224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS64: 182224069Sjhb case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: 183224069Sjhb if (res->Data.Address.ProducerConsumer != ACPI_PRODUCER) 184224069Sjhb break; 185224069Sjhb switch (res->Type) { 186224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS16: 187224069Sjhb min = res->Data.Address16.Minimum; 188224069Sjhb max = res->Data.Address16.Maximum; 189224069Sjhb length = res->Data.Address16.AddressLength; 190224069Sjhb break; 191224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS32: 192224069Sjhb min = res->Data.Address32.Minimum; 193224069Sjhb max = res->Data.Address32.Maximum; 194224069Sjhb length = res->Data.Address32.AddressLength; 195224069Sjhb break; 196224069Sjhb case ACPI_RESOURCE_TYPE_ADDRESS64: 197224069Sjhb min = res->Data.Address64.Minimum; 198224069Sjhb max = res->Data.Address64.Maximum; 199224069Sjhb length = res->Data.Address64.AddressLength; 200224069Sjhb break; 201224069Sjhb default: 202224069Sjhb KASSERT(res->Type == 203224069Sjhb ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, 204224069Sjhb ("should never happen")); 205224069Sjhb min = res->Data.ExtAddress64.Minimum; 206224069Sjhb max = res->Data.ExtAddress64.Maximum; 207224069Sjhb length = res->Data.ExtAddress64.AddressLength; 208224069Sjhb break; 209224069Sjhb } 210224254Sjhb if (length == 0) 211224069Sjhb break; 212224254Sjhb if (min + length - 1 != max && 213224254Sjhb (res->Data.Address.MinAddressFixed != ACPI_ADDRESS_FIXED || 214224254Sjhb res->Data.Address.MaxAddressFixed != ACPI_ADDRESS_FIXED)) 215224254Sjhb break; 216224069Sjhb flags = 0; 217224069Sjhb switch (res->Data.Address.ResourceType) { 218224069Sjhb case ACPI_MEMORY_RANGE: 219224069Sjhb type = SYS_RES_MEMORY; 220224069Sjhb if (res->Type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) { 221224069Sjhb if (res->Data.Address.Info.Mem.Caching == 222224069Sjhb ACPI_PREFETCHABLE_MEMORY) 223224069Sjhb flags |= RF_PREFETCHABLE; 224224069Sjhb } else { 225224069Sjhb /* 226224069Sjhb * XXX: Parse prefetch flag out of 227224069Sjhb * TypeSpecific. 228224069Sjhb */ 229224069Sjhb } 230224069Sjhb break; 231224069Sjhb case ACPI_IO_RANGE: 232224069Sjhb type = SYS_RES_IOPORT; 233224069Sjhb break; 234224069Sjhb#ifdef PCI_RES_BUS 235224069Sjhb case ACPI_BUS_NUMBER_RANGE: 236224069Sjhb type = PCI_RES_BUS; 237224069Sjhb break; 238224069Sjhb#endif 239224069Sjhb default: 240224069Sjhb return (AE_OK); 241224069Sjhb } 242224069Sjhb 243224069Sjhb if (min + length - 1 != max) 244224069Sjhb device_printf(sc->ap_dev, 245224069Sjhb "Length mismatch for %d range: %jx vs %jx\n", type, 246224069Sjhb (uintmax_t)max - min + 1, (uintmax_t)length); 247224069Sjhb#ifdef __i386__ 248224069Sjhb if (min > ULONG_MAX) { 249224069Sjhb device_printf(sc->ap_dev, 250224069Sjhb "Ignoring %d range above 4GB (%#jx-%#jx)\n", 251224069Sjhb type, (uintmax_t)min, (uintmax_t)max); 252224069Sjhb break; 253224069Sjhb } 254224069Sjhb if (max > ULONG_MAX) { 255224069Sjhb device_printf(sc->ap_dev, 256224069Sjhb "Truncating end of %d range above 4GB (%#jx-%#jx)\n", 257224069Sjhb type, (uintmax_t)min, (uintmax_t)max); 258224069Sjhb max = ULONG_MAX; 259224069Sjhb } 260224069Sjhb#endif 261224069Sjhb error = pcib_host_res_decodes(&sc->ap_host_res, type, min, max, 262224069Sjhb flags); 263224069Sjhb if (error) 264224069Sjhb panic("Failed to manage %d range (%#jx-%#jx): %d", 265224069Sjhb type, (uintmax_t)min, (uintmax_t)max, error); 266224069Sjhb break; 267224069Sjhb default: 268224069Sjhb break; 269224069Sjhb } 270224069Sjhb return (AE_OK); 271224069Sjhb} 272224069Sjhb#endif 273224069Sjhb 27467761Smsmithstatic int 275102447Sjhbacpi_pcib_acpi_attach(device_t dev) 27667761Smsmith{ 277102447Sjhb struct acpi_hpcib_softc *sc; 27867761Smsmith ACPI_STATUS status; 279193829Sjhb static int bus0_seen = 0; 280234150Sjhb u_int slot, func, busok; 281107173Sjhb uint8_t busno; 28267761Smsmith 28396926Speter ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 28469744Smsmith 28567761Smsmith sc = device_get_softc(dev); 28667761Smsmith sc->ap_dev = dev; 28767761Smsmith sc->ap_handle = acpi_get_handle(dev); 28867761Smsmith 28967761Smsmith /* 290253426Sjhb * Don't attach if we're not really there. 291253426Sjhb */ 292253426Sjhb if (!acpi_DeviceIsPresent(dev)) 293253426Sjhb return (ENXIO); 294253426Sjhb 295253426Sjhb /* 296234150Sjhb * Get our segment number by evaluating _SEG. 297193829Sjhb * It's OK for this to not exist. 298193829Sjhb */ 299193829Sjhb status = acpi_GetInteger(sc->ap_handle, "_SEG", &sc->ap_segment); 300193829Sjhb if (ACPI_FAILURE(status)) { 301193829Sjhb if (status != AE_NOT_FOUND) { 302193829Sjhb device_printf(dev, "could not evaluate _SEG - %s\n", 303193829Sjhb AcpiFormatException(status)); 304193829Sjhb return_VALUE (ENXIO); 305193829Sjhb } 306193829Sjhb /* If it's not found, assume 0. */ 307193829Sjhb sc->ap_segment = 0; 308193829Sjhb } 309193829Sjhb 310234150Sjhb /* 311234150Sjhb * Get the address (device and function) of the associated 312234150Sjhb * PCI-Host bridge device from _ADR. Assume we don't have one if 313234150Sjhb * it doesn't exist. 314234150Sjhb */ 315234150Sjhb status = acpi_GetInteger(sc->ap_handle, "_ADR", &sc->ap_addr); 316234150Sjhb if (ACPI_FAILURE(status)) { 317234150Sjhb device_printf(dev, "could not evaluate _ADR - %s\n", 318234150Sjhb AcpiFormatException(status)); 319234150Sjhb sc->ap_addr = -1; 320234150Sjhb } 321234150Sjhb 322224069Sjhb#ifdef NEW_PCIB 323193829Sjhb /* 324224069Sjhb * Determine which address ranges this bridge decodes and setup 325224069Sjhb * resource managers for those ranges. 326224069Sjhb */ 327224069Sjhb if (pcib_host_res_init(sc->ap_dev, &sc->ap_host_res) != 0) 328224069Sjhb panic("failed to init hostb resources"); 329224069Sjhb if (!acpi_disabled("hostres")) { 330224069Sjhb status = AcpiWalkResources(sc->ap_handle, "_CRS", 331224069Sjhb acpi_pcib_producer_handler, sc); 332224069Sjhb if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) 333224069Sjhb device_printf(sc->ap_dev, "failed to parse resources: %s\n", 334224069Sjhb AcpiFormatException(status)); 335224069Sjhb } 336224069Sjhb#endif 337224069Sjhb 338224069Sjhb /* 339107173Sjhb * Get our base bus number by evaluating _BBN. 34091124Smsmith * If this doesn't work, we assume we're bus number 0. 34167761Smsmith * 342137098Sdes * XXX note that it may also not exist in the case where we are 34367761Smsmith * meant to use a private configuration space mechanism for this bus, 34467761Smsmith * so we should dig out our resources and check to see if we have 34567761Smsmith * anything like that. How do we do this? 34669458Smsmith * XXX If we have the requisite information, and if we don't think the 34769458Smsmith * default PCI configuration space handlers can deal with this bus, 34869458Smsmith * we should attach our own handler. 34969458Smsmith * XXX invoke _REG on this for the PCI config space address space? 350107173Sjhb * XXX It seems many BIOS's with multiple Host-PCI bridges do not set 351107173Sjhb * _BBN correctly. They set _BBN to zero for all bridges. Thus, 352193829Sjhb * if _BBN is zero and PCI bus 0 already exists, we try to read our 353107173Sjhb * bus number from the configuration registers at address _ADR. 354193829Sjhb * We only do this for domain/segment 0 in the hopes that this is 355193829Sjhb * only needed for old single-domain machines. 35667761Smsmith */ 357126560Snjl status = acpi_GetInteger(sc->ap_handle, "_BBN", &sc->ap_bus); 358107173Sjhb if (ACPI_FAILURE(status)) { 35967761Smsmith if (status != AE_NOT_FOUND) { 360107173Sjhb device_printf(dev, "could not evaluate _BBN - %s\n", 361107173Sjhb AcpiFormatException(status)); 362253426Sjhb return (ENXIO); 363107249Sjhb } else { 364129811Snjl /* If it's not found, assume 0. */ 365107249Sjhb sc->ap_bus = 0; 36667761Smsmith } 367107173Sjhb } 368107173Sjhb 369107173Sjhb /* 370193829Sjhb * If this is segment 0, the bus is zero, and PCI bus 0 already 371193829Sjhb * exists, read the bus number via PCI config space. 372107173Sjhb */ 373107173Sjhb busok = 1; 374193829Sjhb if (sc->ap_segment == 0 && sc->ap_bus == 0 && bus0_seen) { 375107249Sjhb busok = 0; 376234150Sjhb if (sc->ap_addr != -1) { 377107173Sjhb /* XXX: We assume bus 0. */ 378234150Sjhb slot = ACPI_ADR_PCI_SLOT(sc->ap_addr); 379234150Sjhb func = ACPI_ADR_PCI_FUNC(sc->ap_addr); 380107173Sjhb if (bootverbose) 381107173Sjhb device_printf(dev, "reading config registers from 0:%d:%d\n", 382107173Sjhb slot, func); 383107249Sjhb if (host_pcib_get_busno(pci_cfgregread, 0, slot, func, &busno) == 0) 384129811Snjl device_printf(dev, "couldn't read bus number from cfg space\n"); 385107249Sjhb else { 386107173Sjhb sc->ap_bus = busno; 387107249Sjhb busok = 1; 388107173Sjhb } 38991124Smsmith } 39067761Smsmith } 39167761Smsmith 39267761Smsmith /* 393107173Sjhb * If nothing else worked, hope that ACPI at least lays out the 394107173Sjhb * host-PCI bridges in order and that as a result our unit number 395107173Sjhb * is actually our bus number. There are several reasons this 396107173Sjhb * might not be true. 397107173Sjhb */ 398107173Sjhb if (busok == 0) { 399107173Sjhb sc->ap_bus = device_get_unit(dev); 400107173Sjhb device_printf(dev, "trying bus number %d\n", sc->ap_bus); 401107173Sjhb } 402107173Sjhb 403193829Sjhb /* If this is bus 0 on segment 0, note that it has been seen already. */ 404193829Sjhb if (sc->ap_segment == 0 && sc->ap_bus == 0) 405193829Sjhb bus0_seen = 1; 40669458Smsmith 407102447Sjhb return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_bus)); 40867761Smsmith} 40967761Smsmith 41079284Smsmith/* 41179284Smsmith * Support for standard PCI bridge ivars. 41279284Smsmith */ 41367761Smsmithstatic int 41467761Smsmithacpi_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 41567761Smsmith{ 416102447Sjhb struct acpi_hpcib_softc *sc = device_get_softc(dev); 41767761Smsmith 41867761Smsmith switch (which) { 419172394Smarius case PCIB_IVAR_DOMAIN: 420221336Sjhb *result = sc->ap_segment; 421172394Smarius return (0); 422129811Snjl case PCIB_IVAR_BUS: 42367761Smsmith *result = sc->ap_bus; 424129811Snjl return (0); 425129811Snjl case ACPI_IVAR_HANDLE: 426102447Sjhb *result = (uintptr_t)sc->ap_handle; 427129811Snjl return (0); 428131341Snjl case ACPI_IVAR_FLAGS: 429131341Snjl *result = (uintptr_t)sc->ap_flags; 430131341Snjl return (0); 43167761Smsmith } 432129811Snjl return (ENOENT); 43367761Smsmith} 43467761Smsmith 43567761Smsmithstatic int 43667761Smsmithacpi_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 43767761Smsmith{ 438137098Sdes struct acpi_hpcib_softc *sc = device_get_softc(dev); 43967761Smsmith 44067761Smsmith switch (which) { 441172394Smarius case PCIB_IVAR_DOMAIN: 442172394Smarius return (EINVAL); 443129811Snjl case PCIB_IVAR_BUS: 44467761Smsmith sc->ap_bus = value; 445129811Snjl return (0); 446131341Snjl case ACPI_IVAR_HANDLE: 447131341Snjl sc->ap_handle = (ACPI_HANDLE)value; 448131341Snjl return (0); 449131341Snjl case ACPI_IVAR_FLAGS: 450131341Snjl sc->ap_flags = (int)value; 451131341Snjl return (0); 45267761Smsmith } 453129811Snjl return (ENOENT); 45467761Smsmith} 45567761Smsmith 456129811Snjlstatic uint32_t 457188163Simpacpi_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, 458188163Simp u_int reg, int bytes) 45967761Smsmith{ 460129811Snjl return (pci_cfgregread(bus, slot, func, reg, bytes)); 46167761Smsmith} 46267761Smsmith 46367761Smsmithstatic void 464188163Simpacpi_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, 465188163Simp u_int reg, uint32_t data, int bytes) 46667761Smsmith{ 46767761Smsmith pci_cfgregwrite(bus, slot, func, reg, data, bytes); 46867761Smsmith} 46967761Smsmith 47067761Smsmithstatic int 471102447Sjhbacpi_pcib_acpi_route_interrupt(device_t pcib, device_t dev, int pin) 47267761Smsmith{ 473138033Sjhb struct acpi_hpcib_softc *sc = device_get_softc(pcib); 47482372Smsmith 475138033Sjhb return (acpi_pcib_route_interrupt(pcib, dev, pin, &sc->ap_prt)); 47667761Smsmith} 477128058Simp 478165128Sjhbstatic int 479165128Sjhbacpi_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, 480165128Sjhb int *irqs) 481165128Sjhb{ 482165128Sjhb device_t bus; 483165128Sjhb 484165128Sjhb bus = device_get_parent(pcib); 485165128Sjhb return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount, 486165128Sjhb irqs)); 487165128Sjhb} 488165128Sjhb 489165128Sjhbstatic int 490169221Sjhbacpi_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) 491165128Sjhb{ 492165128Sjhb device_t bus; 493165128Sjhb 494165128Sjhb bus = device_get_parent(pcib); 495169221Sjhb return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); 496165128Sjhb} 497165128Sjhb 498169221Sjhbstatic int 499169221Sjhbacpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, 500169221Sjhb uint32_t *data) 501169221Sjhb{ 502234150Sjhb struct acpi_hpcib_softc *sc; 503234150Sjhb device_t bus, hostb; 504234150Sjhb int error; 505169221Sjhb 506169221Sjhb bus = device_get_parent(pcib); 507234150Sjhb error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data); 508234150Sjhb if (error) 509234150Sjhb return (error); 510234150Sjhb 511234150Sjhb sc = device_get_softc(dev); 512234150Sjhb if (sc->ap_addr == -1) 513234150Sjhb return (0); 514234150Sjhb /* XXX: Assumes all bridges are on bus 0. */ 515234150Sjhb hostb = pci_find_dbsf(sc->ap_segment, 0, ACPI_ADR_PCI_SLOT(sc->ap_addr), 516234150Sjhb ACPI_ADR_PCI_FUNC(sc->ap_addr)); 517234150Sjhb if (hostb != NULL) 518234150Sjhb pci_ht_map_msi(hostb, *addr); 519234150Sjhb return (0); 520169221Sjhb} 521169221Sjhb 522128058Simpstruct resource * 523128058Simpacpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid, 524129811Snjl u_long start, u_long end, u_long count, u_int flags) 525128058Simp{ 526224069Sjhb#ifdef NEW_PCIB 527224069Sjhb struct acpi_hpcib_softc *sc; 528227397Sjhb struct resource *res; 529224069Sjhb#endif 530223424Sjhb 531223424Sjhb#if defined(__i386__) || defined(__amd64__) 532223424Sjhb start = hostb_alloc_start(type, start, end, count); 533223424Sjhb#endif 534224069Sjhb 535224069Sjhb#ifdef NEW_PCIB 536224069Sjhb sc = device_get_softc(dev); 537227397Sjhb res = pcib_host_res_alloc(&sc->ap_host_res, child, type, rid, start, end, 538227397Sjhb count, flags); 539230085Sjhb 540230085Sjhb /* 541230085Sjhb * XXX: If this is a request for a specific range, assume it is 542230085Sjhb * correct and pass it up to the parent. What we probably want to 543230085Sjhb * do long-term is explicitly trust any firmware-configured 544230085Sjhb * resources during the initial bus scan on boot and then disable 545230085Sjhb * this after that. 546230085Sjhb */ 547227397Sjhb if (res == NULL && start + count - 1 == end) 548230085Sjhb res = bus_generic_alloc_resource(dev, child, type, rid, start, end, 549230085Sjhb count, flags); 550227397Sjhb return (res); 551224069Sjhb#else 552129811Snjl return (bus_generic_alloc_resource(dev, child, type, rid, start, end, 553129811Snjl count, flags)); 554224069Sjhb#endif 555128058Simp} 556224069Sjhb 557224069Sjhb#ifdef NEW_PCIB 558224069Sjhbint 559224069Sjhbacpi_pcib_acpi_adjust_resource(device_t dev, device_t child, int type, 560224069Sjhb struct resource *r, u_long start, u_long end) 561224069Sjhb{ 562224069Sjhb struct acpi_hpcib_softc *sc; 563224069Sjhb 564224069Sjhb sc = device_get_softc(dev); 565224069Sjhb return (pcib_host_res_adjust(&sc->ap_host_res, child, type, r, start, 566224069Sjhb end)); 567224069Sjhb} 568224069Sjhb#endif 569