OsdHardware.c revision 119539
167760Smsmith/*- 280071Smsmith * Copyright (c) 2000, 2001 Michael Smith 367760Smsmith * Copyright (c) 2000 BSDi 467760Smsmith * All rights reserved. 567760Smsmith * 667760Smsmith * Redistribution and use in source and binary forms, with or without 767760Smsmith * modification, are permitted provided that the following conditions 867760Smsmith * are met: 967760Smsmith * 1. Redistributions of source code must retain the above copyright 1067760Smsmith * notice, this list of conditions and the following disclaimer. 1167760Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1267760Smsmith * notice, this list of conditions and the following disclaimer in the 1367760Smsmith * documentation and/or other materials provided with the distribution. 1467760Smsmith * 1567760Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1667760Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1767760Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1867760Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1967760Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2067760Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2167760Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2267760Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2367760Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2467760Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2567760Smsmith * SUCH DAMAGE. 2667760Smsmith * 2767760Smsmith * $FreeBSD: head/sys/dev/acpica/Osd/OsdHardware.c 119539 2003-08-28 21:22:25Z jhb $ 2867760Smsmith */ 2967760Smsmith 3067760Smsmith/* 3167760Smsmith * 6.7 : Hardware Abstraction 3267760Smsmith */ 3367760Smsmith 3467760Smsmith#include "acpi.h" 3567760Smsmith 3667760Smsmith#include <machine/bus_pio.h> 3767760Smsmith#include <machine/bus.h> 3867760Smsmith#include <machine/pci_cfgreg.h> 39114977Sjhb#if __FreeBSD_version >= 500000 40114246Snjl#include <dev/pci/pcireg.h> 41114977Sjhb#else 42114977Sjhb#include <pci/pcireg.h> 43114977Sjhb#endif 4467760Smsmith 4567760Smsmith/* 4667760Smsmith * ACPICA's rather gung-ho approach to hardware resource ownership is a little 4767760Smsmith * troublesome insofar as there is no easy way for us to know in advance 4867760Smsmith * exactly which I/O resources it's going to want to use. 4967760Smsmith * 5067760Smsmith * In order to deal with this, we ignore resource ownership entirely, and simply 5167760Smsmith * use the native I/O space accessor functionality. This is Evil, but it works. 5267760Smsmith * 5367760Smsmith * XXX use an intermediate #define for the tag/handle 5467760Smsmith */ 5567760Smsmith 5684446Sdfr#ifdef __i386__ 5767760Smsmith#define ACPI_BUS_SPACE_IO I386_BUS_SPACE_IO 5867760Smsmith#define ACPI_BUS_HANDLE 0 5984446Sdfr#endif 6084446Sdfr#ifdef __ia64__ 6184446Sdfr#define ACPI_BUS_SPACE_IO IA64_BUS_SPACE_IO 6284446Sdfr#define ACPI_BUS_HANDLE 0 6384446Sdfr#endif 64115427Speter#ifdef __amd64__ 65115427Speter#define ACPI_BUS_SPACE_IO AMD64_BUS_SPACE_IO 66115427Speter#define ACPI_BUS_HANDLE 0 67115427Speter#endif 6867760Smsmith 6980071SmsmithACPI_STATUS 7080071SmsmithAcpiOsReadPort ( 7180071Smsmith ACPI_IO_ADDRESS InPort, 72117530Snjl UINT32 *Value, 7380071Smsmith UINT32 Width) 7467760Smsmith{ 7580071Smsmith switch (Width) { 7680071Smsmith case 8: 7780071Smsmith *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 7880071Smsmith break; 7980071Smsmith case 16: 8080071Smsmith *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 8180071Smsmith break; 8280071Smsmith case 32: 8380071Smsmith *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 8480071Smsmith break; 8580071Smsmith default: 8680071Smsmith /* debug trap goes here */ 8792666Speter break; 8880071Smsmith } 8967760Smsmith 9080071Smsmith return(AE_OK); 9167760Smsmith} 9267760Smsmith 9367760SmsmithACPI_STATUS 9480071SmsmithAcpiOsWritePort ( 9580071Smsmith ACPI_IO_ADDRESS OutPort, 96117530Snjl UINT32 Value, 9780071Smsmith UINT32 Width) 9867760Smsmith{ 9980071Smsmith switch (Width) { 10080071Smsmith case 8: 10180071Smsmith bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 10280071Smsmith break; 10380071Smsmith case 16: 10480071Smsmith bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 10580071Smsmith break; 10680071Smsmith case 32: 10780071Smsmith bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 10880071Smsmith break; 10980071Smsmith default: 11080071Smsmith /* debug trap goes here */ 11192666Speter break; 11280071Smsmith } 11367760Smsmith 11467760Smsmith return(AE_OK); 11567760Smsmith} 11667760Smsmith 11767760SmsmithACPI_STATUS 11880071SmsmithAcpiOsReadPciConfiguration ( 11980071Smsmith ACPI_PCI_ID *PciId, 12080071Smsmith UINT32 Register, 12180071Smsmith void *Value, 12280071Smsmith UINT32 Width) 12367760Smsmith{ 12480071Smsmith u_int32_t byte_width = Width / 8; 12580071Smsmith u_int32_t val; 12667760Smsmith 12767760Smsmith if (!pci_cfgregopen()) 12880071Smsmith return(AE_NOT_EXIST); 12967760Smsmith 13080071Smsmith val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width); 13180071Smsmith switch (Width) { 13280071Smsmith case 8: 13380071Smsmith *(u_int8_t *)Value = val & 0xff; 13480071Smsmith break; 13580071Smsmith case 16: 13680071Smsmith *(u_int16_t *)Value = val & 0xffff; 13780071Smsmith break; 13880071Smsmith case 32: 13980071Smsmith *(u_int32_t *)Value = val; 14080071Smsmith break; 14180071Smsmith default: 14280071Smsmith /* debug trap goes here */ 14392666Speter break; 14480071Smsmith } 14580071Smsmith 14680071Smsmith 14767760Smsmith return(AE_OK); 14867760Smsmith} 14967760Smsmith 15080071Smsmith 15167760SmsmithACPI_STATUS 15280071SmsmithAcpiOsWritePciConfiguration ( 15380071Smsmith ACPI_PCI_ID *PciId, 15480071Smsmith UINT32 Register, 15587036Smsmith ACPI_INTEGER Value, 15680071Smsmith UINT32 Width) 15767760Smsmith{ 15880071Smsmith u_int32_t byte_width = Width / 8; 15967760Smsmith 16067760Smsmith if (!pci_cfgregopen()) 16180071Smsmith return(AE_NOT_EXIST); 16267760Smsmith 16380071Smsmith pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width); 16480071Smsmith 16567760Smsmith return(AE_OK); 16667760Smsmith} 167114246Snjl 168114246Snjl/* XXX should use acpivar.h but too many include dependencies */ 169114246Snjlextern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int 170114246Snjl *number); 171114246Snjl 172114246Snjl/* 173114246Snjl * Depth-first recursive case for finding the bus, given the slot/function. 174114246Snjl */ 175114246Snjlstatic int 176114246Snjlacpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId) 177114246Snjl{ 178114246Snjl ACPI_HANDLE parent; 179114246Snjl ACPI_OBJECT_TYPE type; 180114246Snjl UINT32 adr; 181114246Snjl int bus, slot, func, class, subclass, header; 182114246Snjl 183114246Snjl /* Try to get the _BBN object of the root, otherwise assume it is 0 */ 184114246Snjl bus = 0; 185114246Snjl if (root == curr) { 186114949Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus)) && 187114949Snjl bootverbose) 188114246Snjl printf("acpi_bus_number: root bus has no _BBN, assuming 0\n"); 189114246Snjl return (bus); 190114246Snjl } 191114246Snjl if (ACPI_FAILURE(AcpiGetParent(curr, &parent))) 192114246Snjl return (bus); 193114246Snjl 194114246Snjl /* First, recurse up the tree until we find the host bus */ 195114246Snjl bus = acpi_bus_number(root, parent, PciId); 196114246Snjl 197114246Snjl /* Validate parent bus device type */ 198114246Snjl if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) { 199114246Snjl printf("acpi_bus_number: not a device, type %d\n", type); 200114246Snjl return (bus); 201114246Snjl } 202114246Snjl /* Get the parent's slot and function */ 203114246Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) { 204114246Snjl printf("acpi_bus_number: can't get _ADR\n"); 205114246Snjl return (bus); 206114246Snjl } 207114246Snjl slot = ACPI_HIWORD(adr); 208114246Snjl func = ACPI_LOWORD(adr); 209114246Snjl 210114246Snjl /* Is this a PCI-PCI or Cardbus-PCI bridge? */ 211114246Snjl class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1); 212114246Snjl if (class != PCIC_BRIDGE) 213114246Snjl return (bus); 214114246Snjl subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1); 215114246Snjl /* Find the header type, masking off the multifunction bit */ 216119539Sjhb header = pci_cfgregread(bus, slot, func, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE; 217119539Sjhb if (header == PCIM_HDRTYPE_BRIDGE && subclass == PCIS_BRIDGE_PCI) 218114246Snjl bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1); 219119539Sjhb if (header == PCIM_HDRTYPE_CARDBUS && subclass == PCIS_BRIDGE_CARDBUS) 220114246Snjl bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1); 221114246Snjl return (bus); 222114246Snjl} 223114246Snjl 224114246Snjl/* 225114246Snjl * Find the bus number for a device 226114246Snjl * 227114246Snjl * rhandle: handle for the root bus 228114246Snjl * chandle: handle for the device 229114246Snjl * PciId: pointer to device slot and function, we fill out bus 230114246Snjl */ 231114246Snjlvoid 232114246SnjlAcpiOsDerivePciId ( 233114246Snjl ACPI_HANDLE rhandle, 234114246Snjl ACPI_HANDLE chandle, 235114246Snjl ACPI_PCI_ID **PciId) 236114246Snjl{ 237114246Snjl ACPI_HANDLE parent; 238114246Snjl int bus; 239114246Snjl 240114246Snjl if (pci_cfgregopen() == 0) 241114246Snjl panic("AcpiOsDerivePciId unable to initialize pci bus"); 242114246Snjl 243114246Snjl /* Try to read _BBN for bus number if we're at the root */ 244114246Snjl bus = 0; 245114246Snjl if (rhandle == chandle) { 246114949Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus)) && 247114949Snjl bootverbose) 248114246Snjl printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n"); 249114246Snjl } 250114246Snjl /* 251114246Snjl * Get the parent handle and call the recursive case. It is not 252114246Snjl * clear why we seem to be getting a chandle that points to a child 253114246Snjl * of the desired slot/function but passing in the parent handle 254114246Snjl * here works. 255114246Snjl */ 256114246Snjl if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent))) 257114246Snjl bus = acpi_bus_number(rhandle, parent, *PciId); 258114246Snjl (*PciId)->Bus = bus; 259114246Snjl if (bootverbose) { 260114246Snjl printf("AcpiOsDerivePciId: bus %d dev %d func %d\n", 261114246Snjl (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function); 262114246Snjl } 263114246Snjl} 264