OsdHardware.c revision 114246
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 114246 2003-04-29 18:50:34Z njl $ 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> 39114246Snjl#include <dev/pci/pcireg.h> 4067760Smsmith 4167760Smsmith/* 4267760Smsmith * ACPICA's rather gung-ho approach to hardware resource ownership is a little 4367760Smsmith * troublesome insofar as there is no easy way for us to know in advance 4467760Smsmith * exactly which I/O resources it's going to want to use. 4567760Smsmith * 4667760Smsmith * In order to deal with this, we ignore resource ownership entirely, and simply 4767760Smsmith * use the native I/O space accessor functionality. This is Evil, but it works. 4867760Smsmith * 4967760Smsmith * XXX use an intermediate #define for the tag/handle 5067760Smsmith */ 5167760Smsmith 5284446Sdfr#ifdef __i386__ 5367760Smsmith#define ACPI_BUS_SPACE_IO I386_BUS_SPACE_IO 5467760Smsmith#define ACPI_BUS_HANDLE 0 5584446Sdfr#endif 5684446Sdfr#ifdef __ia64__ 5784446Sdfr#define ACPI_BUS_SPACE_IO IA64_BUS_SPACE_IO 5884446Sdfr#define ACPI_BUS_HANDLE 0 5984446Sdfr#endif 6067760Smsmith 6180071SmsmithACPI_STATUS 6280071SmsmithAcpiOsReadPort ( 6380071Smsmith ACPI_IO_ADDRESS InPort, 6480071Smsmith void *Value, 6580071Smsmith UINT32 Width) 6667760Smsmith{ 6780071Smsmith switch (Width) { 6880071Smsmith case 8: 6980071Smsmith *(u_int8_t *)Value = bus_space_read_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 7080071Smsmith break; 7180071Smsmith case 16: 7280071Smsmith *(u_int16_t *)Value = bus_space_read_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 7380071Smsmith break; 7480071Smsmith case 32: 7580071Smsmith *(u_int32_t *)Value = bus_space_read_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, InPort); 7680071Smsmith break; 7780071Smsmith default: 7880071Smsmith /* debug trap goes here */ 7992666Speter break; 8080071Smsmith } 8167760Smsmith 8280071Smsmith return(AE_OK); 8367760Smsmith} 8467760Smsmith 8567760SmsmithACPI_STATUS 8680071SmsmithAcpiOsWritePort ( 8780071Smsmith ACPI_IO_ADDRESS OutPort, 8887036Smsmith ACPI_INTEGER Value, 8980071Smsmith UINT32 Width) 9067760Smsmith{ 9180071Smsmith switch (Width) { 9280071Smsmith case 8: 9380071Smsmith bus_space_write_1(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 9480071Smsmith break; 9580071Smsmith case 16: 9680071Smsmith bus_space_write_2(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 9780071Smsmith break; 9880071Smsmith case 32: 9980071Smsmith bus_space_write_4(ACPI_BUS_SPACE_IO, ACPI_BUS_HANDLE, OutPort, Value); 10080071Smsmith break; 10180071Smsmith default: 10280071Smsmith /* debug trap goes here */ 10392666Speter break; 10480071Smsmith } 10567760Smsmith 10667760Smsmith return(AE_OK); 10767760Smsmith} 10867760Smsmith 10967760SmsmithACPI_STATUS 11080071SmsmithAcpiOsReadPciConfiguration ( 11180071Smsmith ACPI_PCI_ID *PciId, 11280071Smsmith UINT32 Register, 11380071Smsmith void *Value, 11480071Smsmith UINT32 Width) 11567760Smsmith{ 11680071Smsmith u_int32_t byte_width = Width / 8; 11780071Smsmith u_int32_t val; 11867760Smsmith 11967760Smsmith if (!pci_cfgregopen()) 12080071Smsmith return(AE_NOT_EXIST); 12167760Smsmith 12280071Smsmith val = pci_cfgregread(PciId->Bus, PciId->Device, PciId->Function, Register, byte_width); 12380071Smsmith switch (Width) { 12480071Smsmith case 8: 12580071Smsmith *(u_int8_t *)Value = val & 0xff; 12680071Smsmith break; 12780071Smsmith case 16: 12880071Smsmith *(u_int16_t *)Value = val & 0xffff; 12980071Smsmith break; 13080071Smsmith case 32: 13180071Smsmith *(u_int32_t *)Value = val; 13280071Smsmith break; 13380071Smsmith default: 13480071Smsmith /* debug trap goes here */ 13592666Speter break; 13680071Smsmith } 13780071Smsmith 13880071Smsmith 13967760Smsmith return(AE_OK); 14067760Smsmith} 14167760Smsmith 14280071Smsmith 14367760SmsmithACPI_STATUS 14480071SmsmithAcpiOsWritePciConfiguration ( 14580071Smsmith ACPI_PCI_ID *PciId, 14680071Smsmith UINT32 Register, 14787036Smsmith ACPI_INTEGER Value, 14880071Smsmith UINT32 Width) 14967760Smsmith{ 15080071Smsmith u_int32_t byte_width = Width / 8; 15167760Smsmith 15267760Smsmith if (!pci_cfgregopen()) 15380071Smsmith return(AE_NOT_EXIST); 15467760Smsmith 15580071Smsmith pci_cfgregwrite(PciId->Bus, PciId->Device, PciId->Function, Register, Value, byte_width); 15680071Smsmith 15767760Smsmith return(AE_OK); 15867760Smsmith} 159114246Snjl 160114246Snjl/* XXX should use acpivar.h but too many include dependencies */ 161114246Snjlextern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int 162114246Snjl *number); 163114246Snjl 164114246Snjl/* 165114246Snjl * Depth-first recursive case for finding the bus, given the slot/function. 166114246Snjl */ 167114246Snjlstatic int 168114246Snjlacpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId) 169114246Snjl{ 170114246Snjl ACPI_HANDLE parent; 171114246Snjl ACPI_OBJECT_TYPE type; 172114246Snjl UINT32 adr; 173114246Snjl int bus, slot, func, class, subclass, header; 174114246Snjl 175114246Snjl /* Try to get the _BBN object of the root, otherwise assume it is 0 */ 176114246Snjl bus = 0; 177114246Snjl if (root == curr) { 178114246Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(root, "_BBN", &bus))) 179114246Snjl printf("acpi_bus_number: root bus has no _BBN, assuming 0\n"); 180114246Snjl return (bus); 181114246Snjl } 182114246Snjl if (ACPI_FAILURE(AcpiGetParent(curr, &parent))) 183114246Snjl return (bus); 184114246Snjl 185114246Snjl /* First, recurse up the tree until we find the host bus */ 186114246Snjl bus = acpi_bus_number(root, parent, PciId); 187114246Snjl 188114246Snjl /* Validate parent bus device type */ 189114246Snjl if (ACPI_FAILURE(AcpiGetType(parent, &type)) || type != ACPI_TYPE_DEVICE) { 190114246Snjl printf("acpi_bus_number: not a device, type %d\n", type); 191114246Snjl return (bus); 192114246Snjl } 193114246Snjl /* Get the parent's slot and function */ 194114246Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(parent, "_ADR", &adr))) { 195114246Snjl printf("acpi_bus_number: can't get _ADR\n"); 196114246Snjl return (bus); 197114246Snjl } 198114246Snjl slot = ACPI_HIWORD(adr); 199114246Snjl func = ACPI_LOWORD(adr); 200114246Snjl 201114246Snjl /* Is this a PCI-PCI or Cardbus-PCI bridge? */ 202114246Snjl class = pci_cfgregread(bus, slot, func, PCIR_CLASS, 1); 203114246Snjl if (class != PCIC_BRIDGE) 204114246Snjl return (bus); 205114246Snjl subclass = pci_cfgregread(bus, slot, func, PCIR_SUBCLASS, 1); 206114246Snjl /* Find the header type, masking off the multifunction bit */ 207114246Snjl header = pci_cfgregread(bus, slot, func, PCIR_HEADERTYPE, 1) & 0x7f; 208114246Snjl if (header == 1 && subclass == PCIS_BRIDGE_PCI) 209114246Snjl bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_1, 1); 210114246Snjl if (header == 2 && subclass == PCIS_BRIDGE_CARDBUS) 211114246Snjl bus = pci_cfgregread(bus, slot, func, PCIR_SECBUS_2, 1); 212114246Snjl return (bus); 213114246Snjl} 214114246Snjl 215114246Snjl/* 216114246Snjl * Find the bus number for a device 217114246Snjl * 218114246Snjl * rhandle: handle for the root bus 219114246Snjl * chandle: handle for the device 220114246Snjl * PciId: pointer to device slot and function, we fill out bus 221114246Snjl */ 222114246Snjlvoid 223114246SnjlAcpiOsDerivePciId ( 224114246Snjl ACPI_HANDLE rhandle, 225114246Snjl ACPI_HANDLE chandle, 226114246Snjl ACPI_PCI_ID **PciId) 227114246Snjl{ 228114246Snjl ACPI_HANDLE parent; 229114246Snjl int bus; 230114246Snjl 231114246Snjl if (pci_cfgregopen() == 0) 232114246Snjl panic("AcpiOsDerivePciId unable to initialize pci bus"); 233114246Snjl 234114246Snjl /* Try to read _BBN for bus number if we're at the root */ 235114246Snjl bus = 0; 236114246Snjl if (rhandle == chandle) { 237114246Snjl if (ACPI_FAILURE(acpi_EvaluateInteger(rhandle, "_BBN", &bus))) 238114246Snjl printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n"); 239114246Snjl } 240114246Snjl /* 241114246Snjl * Get the parent handle and call the recursive case. It is not 242114246Snjl * clear why we seem to be getting a chandle that points to a child 243114246Snjl * of the desired slot/function but passing in the parent handle 244114246Snjl * here works. 245114246Snjl */ 246114246Snjl if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent))) 247114246Snjl bus = acpi_bus_number(rhandle, parent, *PciId); 248114246Snjl (*PciId)->Bus = bus; 249114246Snjl if (bootverbose) { 250114246Snjl printf("AcpiOsDerivePciId: bus %d dev %d func %d\n", 251114246Snjl (*PciId)->Bus, (*PciId)->Device, (*PciId)->Function); 252114246Snjl } 253114246Snjl} 254