126f3cdf0SGordon Ross /******************************************************************************* 226f3cdf0SGordon Ross * 326f3cdf0SGordon Ross * Module Name: hwpci - Obtain PCI bus, device, and function numbers 426f3cdf0SGordon Ross * 526f3cdf0SGordon Ross ******************************************************************************/ 626f3cdf0SGordon Ross 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 926f3cdf0SGordon Ross * All rights reserved. 1026f3cdf0SGordon Ross * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 2526f3cdf0SGordon Ross * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 2926f3cdf0SGordon Ross * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 4326f3cdf0SGordon Ross 4426f3cdf0SGordon Ross #include "acpi.h" 4526f3cdf0SGordon Ross #include "accommon.h" 4626f3cdf0SGordon Ross 4726f3cdf0SGordon Ross 4826f3cdf0SGordon Ross #define _COMPONENT ACPI_NAMESPACE 4926f3cdf0SGordon Ross ACPI_MODULE_NAME ("hwpci") 5026f3cdf0SGordon Ross 5126f3cdf0SGordon Ross 5226f3cdf0SGordon Ross /* PCI configuration space values */ 5326f3cdf0SGordon Ross 5426f3cdf0SGordon Ross #define PCI_CFG_HEADER_TYPE_REG 0x0E 5526f3cdf0SGordon Ross #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18 5626f3cdf0SGordon Ross #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19 5726f3cdf0SGordon Ross 5826f3cdf0SGordon Ross /* PCI header values */ 5926f3cdf0SGordon Ross 6026f3cdf0SGordon Ross #define PCI_HEADER_TYPE_MASK 0x7F 6126f3cdf0SGordon Ross #define PCI_TYPE_BRIDGE 0x01 6226f3cdf0SGordon Ross #define PCI_TYPE_CARDBUS_BRIDGE 0x02 6326f3cdf0SGordon Ross 6426f3cdf0SGordon Ross typedef struct acpi_pci_device 6526f3cdf0SGordon Ross { 6626f3cdf0SGordon Ross ACPI_HANDLE Device; 6726f3cdf0SGordon Ross struct acpi_pci_device *Next; 6826f3cdf0SGordon Ross 6926f3cdf0SGordon Ross } ACPI_PCI_DEVICE; 7026f3cdf0SGordon Ross 7126f3cdf0SGordon Ross 7226f3cdf0SGordon Ross /* Local prototypes */ 7326f3cdf0SGordon Ross 7426f3cdf0SGordon Ross static ACPI_STATUS 7526f3cdf0SGordon Ross AcpiHwBuildPciList ( 7626f3cdf0SGordon Ross ACPI_HANDLE RootPciDevice, 7726f3cdf0SGordon Ross ACPI_HANDLE PciRegion, 7826f3cdf0SGordon Ross ACPI_PCI_DEVICE **ReturnListHead); 7926f3cdf0SGordon Ross 8026f3cdf0SGordon Ross static ACPI_STATUS 8126f3cdf0SGordon Ross AcpiHwProcessPciList ( 8226f3cdf0SGordon Ross ACPI_PCI_ID *PciId, 8326f3cdf0SGordon Ross ACPI_PCI_DEVICE *ListHead); 8426f3cdf0SGordon Ross 8526f3cdf0SGordon Ross static void 8626f3cdf0SGordon Ross AcpiHwDeletePciList ( 8726f3cdf0SGordon Ross ACPI_PCI_DEVICE *ListHead); 8826f3cdf0SGordon Ross 8926f3cdf0SGordon Ross static ACPI_STATUS 9026f3cdf0SGordon Ross AcpiHwGetPciDeviceInfo ( 9126f3cdf0SGordon Ross ACPI_PCI_ID *PciId, 9226f3cdf0SGordon Ross ACPI_HANDLE PciDevice, 9326f3cdf0SGordon Ross UINT16 *BusNumber, 9426f3cdf0SGordon Ross BOOLEAN *IsBridge); 9526f3cdf0SGordon Ross 9626f3cdf0SGordon Ross 9726f3cdf0SGordon Ross /******************************************************************************* 9826f3cdf0SGordon Ross * 9926f3cdf0SGordon Ross * FUNCTION: AcpiHwDerivePciId 10026f3cdf0SGordon Ross * 10126f3cdf0SGordon Ross * PARAMETERS: PciId - Initial values for the PCI ID. May be 10226f3cdf0SGordon Ross * modified by this function. 10326f3cdf0SGordon Ross * RootPciDevice - A handle to a PCI device object. This 10426f3cdf0SGordon Ross * object must be a PCI Root Bridge having a 10526f3cdf0SGordon Ross * _HID value of either PNP0A03 or PNP0A08 10626f3cdf0SGordon Ross * PciRegion - A handle to a PCI configuration space 10726f3cdf0SGordon Ross * Operation Region being initialized 10826f3cdf0SGordon Ross * 10926f3cdf0SGordon Ross * RETURN: Status 11026f3cdf0SGordon Ross * 11126f3cdf0SGordon Ross * DESCRIPTION: This function derives a full PCI ID for a PCI device, 11226f3cdf0SGordon Ross * consisting of a Segment number, Bus number, Device number, 11326f3cdf0SGordon Ross * and function code. 11426f3cdf0SGordon Ross * 11526f3cdf0SGordon Ross * The PCI hardware dynamically configures PCI bus numbers 11626f3cdf0SGordon Ross * depending on the bus topology discovered during system 11726f3cdf0SGordon Ross * initialization. This function is invoked during configuration 11826f3cdf0SGordon Ross * of a PCI_Config Operation Region in order to (possibly) update 11926f3cdf0SGordon Ross * the Bus/Device/Function numbers in the PciId with the actual 12026f3cdf0SGordon Ross * values as determined by the hardware and operating system 12126f3cdf0SGordon Ross * configuration. 12226f3cdf0SGordon Ross * 12326f3cdf0SGordon Ross * The PciId parameter is initially populated during the Operation 12426f3cdf0SGordon Ross * Region initialization. This function is then called, and is 12526f3cdf0SGordon Ross * will make any necessary modifications to the Bus, Device, or 12626f3cdf0SGordon Ross * Function number PCI ID subfields as appropriate for the 12726f3cdf0SGordon Ross * current hardware and OS configuration. 12826f3cdf0SGordon Ross * 12926f3cdf0SGordon Ross * NOTE: Created 08/2010. Replaces the previous OSL AcpiOsDerivePciId 13026f3cdf0SGordon Ross * interface since this feature is OS-independent. This module 13126f3cdf0SGordon Ross * specifically avoids any use of recursion by building a local 13226f3cdf0SGordon Ross * temporary device list. 13326f3cdf0SGordon Ross * 13426f3cdf0SGordon Ross ******************************************************************************/ 13526f3cdf0SGordon Ross 13626f3cdf0SGordon Ross ACPI_STATUS 13726f3cdf0SGordon Ross AcpiHwDerivePciId ( 13826f3cdf0SGordon Ross ACPI_PCI_ID *PciId, 13926f3cdf0SGordon Ross ACPI_HANDLE RootPciDevice, 14026f3cdf0SGordon Ross ACPI_HANDLE PciRegion) 14126f3cdf0SGordon Ross { 14226f3cdf0SGordon Ross ACPI_STATUS Status; 143*385cc6b4SJerry Jelinek ACPI_PCI_DEVICE *ListHead; 14426f3cdf0SGordon Ross 14526f3cdf0SGordon Ross 14626f3cdf0SGordon Ross ACPI_FUNCTION_TRACE (HwDerivePciId); 14726f3cdf0SGordon Ross 14826f3cdf0SGordon Ross 14926f3cdf0SGordon Ross if (!PciId) 15026f3cdf0SGordon Ross { 15126f3cdf0SGordon Ross return_ACPI_STATUS (AE_BAD_PARAMETER); 15226f3cdf0SGordon Ross } 15326f3cdf0SGordon Ross 15426f3cdf0SGordon Ross /* Build a list of PCI devices, from PciRegion up to RootPciDevice */ 15526f3cdf0SGordon Ross 15626f3cdf0SGordon Ross Status = AcpiHwBuildPciList (RootPciDevice, PciRegion, &ListHead); 15726f3cdf0SGordon Ross if (ACPI_SUCCESS (Status)) 15826f3cdf0SGordon Ross { 15926f3cdf0SGordon Ross /* Walk the list, updating the PCI device/function/bus numbers */ 16026f3cdf0SGordon Ross 16126f3cdf0SGordon Ross Status = AcpiHwProcessPciList (PciId, ListHead); 16226f3cdf0SGordon Ross 163*385cc6b4SJerry Jelinek /* Delete the list */ 16426f3cdf0SGordon Ross 16526f3cdf0SGordon Ross AcpiHwDeletePciList (ListHead); 166*385cc6b4SJerry Jelinek } 167*385cc6b4SJerry Jelinek 16826f3cdf0SGordon Ross return_ACPI_STATUS (Status); 16926f3cdf0SGordon Ross } 17026f3cdf0SGordon Ross 17126f3cdf0SGordon Ross 17226f3cdf0SGordon Ross /******************************************************************************* 17326f3cdf0SGordon Ross * 17426f3cdf0SGordon Ross * FUNCTION: AcpiHwBuildPciList 17526f3cdf0SGordon Ross * 17626f3cdf0SGordon Ross * PARAMETERS: RootPciDevice - A handle to a PCI device object. This 17726f3cdf0SGordon Ross * object is guaranteed to be a PCI Root 17826f3cdf0SGordon Ross * Bridge having a _HID value of either 17926f3cdf0SGordon Ross * PNP0A03 or PNP0A08 18026f3cdf0SGordon Ross * PciRegion - A handle to the PCI configuration space 18126f3cdf0SGordon Ross * Operation Region 18226f3cdf0SGordon Ross * ReturnListHead - Where the PCI device list is returned 18326f3cdf0SGordon Ross * 18426f3cdf0SGordon Ross * RETURN: Status 18526f3cdf0SGordon Ross * 18626f3cdf0SGordon Ross * DESCRIPTION: Builds a list of devices from the input PCI region up to the 18726f3cdf0SGordon Ross * Root PCI device for this namespace subtree. 18826f3cdf0SGordon Ross * 18926f3cdf0SGordon Ross ******************************************************************************/ 19026f3cdf0SGordon Ross 19126f3cdf0SGordon Ross static ACPI_STATUS 19226f3cdf0SGordon Ross AcpiHwBuildPciList ( 19326f3cdf0SGordon Ross ACPI_HANDLE RootPciDevice, 19426f3cdf0SGordon Ross ACPI_HANDLE PciRegion, 19526f3cdf0SGordon Ross ACPI_PCI_DEVICE **ReturnListHead) 19626f3cdf0SGordon Ross { 19726f3cdf0SGordon Ross ACPI_HANDLE CurrentDevice; 19826f3cdf0SGordon Ross ACPI_HANDLE ParentDevice; 19926f3cdf0SGordon Ross ACPI_STATUS Status; 20026f3cdf0SGordon Ross ACPI_PCI_DEVICE *ListElement; 20126f3cdf0SGordon Ross 20226f3cdf0SGordon Ross 20326f3cdf0SGordon Ross /* 20426f3cdf0SGordon Ross * Ascend namespace branch until the RootPciDevice is reached, building 20526f3cdf0SGordon Ross * a list of device nodes. Loop will exit when either the PCI device is 20626f3cdf0SGordon Ross * found, or the root of the namespace is reached. 20726f3cdf0SGordon Ross */ 208*385cc6b4SJerry Jelinek *ReturnListHead = NULL; 20926f3cdf0SGordon Ross CurrentDevice = PciRegion; 21026f3cdf0SGordon Ross while (1) 21126f3cdf0SGordon Ross { 21226f3cdf0SGordon Ross Status = AcpiGetParent (CurrentDevice, &ParentDevice); 21326f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 21426f3cdf0SGordon Ross { 215*385cc6b4SJerry Jelinek /* Must delete the list before exit */ 216*385cc6b4SJerry Jelinek 217*385cc6b4SJerry Jelinek AcpiHwDeletePciList (*ReturnListHead); 21826f3cdf0SGordon Ross return (Status); 21926f3cdf0SGordon Ross } 22026f3cdf0SGordon Ross 22126f3cdf0SGordon Ross /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ 22226f3cdf0SGordon Ross 22326f3cdf0SGordon Ross if (ParentDevice == RootPciDevice) 22426f3cdf0SGordon Ross { 22526f3cdf0SGordon Ross return (AE_OK); 22626f3cdf0SGordon Ross } 22726f3cdf0SGordon Ross 22826f3cdf0SGordon Ross ListElement = ACPI_ALLOCATE (sizeof (ACPI_PCI_DEVICE)); 22926f3cdf0SGordon Ross if (!ListElement) 23026f3cdf0SGordon Ross { 231*385cc6b4SJerry Jelinek /* Must delete the list before exit */ 232*385cc6b4SJerry Jelinek 233*385cc6b4SJerry Jelinek AcpiHwDeletePciList (*ReturnListHead); 23426f3cdf0SGordon Ross return (AE_NO_MEMORY); 23526f3cdf0SGordon Ross } 23626f3cdf0SGordon Ross 23726f3cdf0SGordon Ross /* Put new element at the head of the list */ 23826f3cdf0SGordon Ross 239*385cc6b4SJerry Jelinek ListElement->Next = *ReturnListHead; 24026f3cdf0SGordon Ross ListElement->Device = ParentDevice; 241*385cc6b4SJerry Jelinek *ReturnListHead = ListElement; 24226f3cdf0SGordon Ross 24326f3cdf0SGordon Ross CurrentDevice = ParentDevice; 24426f3cdf0SGordon Ross } 24526f3cdf0SGordon Ross } 24626f3cdf0SGordon Ross 24726f3cdf0SGordon Ross 24826f3cdf0SGordon Ross /******************************************************************************* 24926f3cdf0SGordon Ross * 25026f3cdf0SGordon Ross * FUNCTION: AcpiHwProcessPciList 25126f3cdf0SGordon Ross * 25226f3cdf0SGordon Ross * PARAMETERS: PciId - Initial values for the PCI ID. May be 25326f3cdf0SGordon Ross * modified by this function. 25426f3cdf0SGordon Ross * ListHead - Device list created by 25526f3cdf0SGordon Ross * AcpiHwBuildPciList 25626f3cdf0SGordon Ross * 25726f3cdf0SGordon Ross * RETURN: Status 25826f3cdf0SGordon Ross * 25926f3cdf0SGordon Ross * DESCRIPTION: Walk downward through the PCI device list, getting the device 26026f3cdf0SGordon Ross * info for each, via the PCI configuration space and updating 26126f3cdf0SGordon Ross * the PCI ID as necessary. Deletes the list during traversal. 26226f3cdf0SGordon Ross * 26326f3cdf0SGordon Ross ******************************************************************************/ 26426f3cdf0SGordon Ross 26526f3cdf0SGordon Ross static ACPI_STATUS 26626f3cdf0SGordon Ross AcpiHwProcessPciList ( 26726f3cdf0SGordon Ross ACPI_PCI_ID *PciId, 26826f3cdf0SGordon Ross ACPI_PCI_DEVICE *ListHead) 26926f3cdf0SGordon Ross { 27026f3cdf0SGordon Ross ACPI_STATUS Status = AE_OK; 27126f3cdf0SGordon Ross ACPI_PCI_DEVICE *Info; 27226f3cdf0SGordon Ross UINT16 BusNumber; 27326f3cdf0SGordon Ross BOOLEAN IsBridge = TRUE; 27426f3cdf0SGordon Ross 27526f3cdf0SGordon Ross 27626f3cdf0SGordon Ross ACPI_FUNCTION_NAME (HwProcessPciList); 27726f3cdf0SGordon Ross 27826f3cdf0SGordon Ross 27926f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 28026f3cdf0SGordon Ross "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", 28126f3cdf0SGordon Ross PciId->Segment, PciId->Bus, PciId->Device, PciId->Function)); 28226f3cdf0SGordon Ross 28326f3cdf0SGordon Ross BusNumber = PciId->Bus; 28426f3cdf0SGordon Ross 28526f3cdf0SGordon Ross /* 28626f3cdf0SGordon Ross * Descend down the namespace tree, collecting PCI device, function, 28726f3cdf0SGordon Ross * and bus numbers. BusNumber is only important for PCI bridges. 28826f3cdf0SGordon Ross * Algorithm: As we descend the tree, use the last valid PCI device, 28926f3cdf0SGordon Ross * function, and bus numbers that are discovered, and assign them 29026f3cdf0SGordon Ross * to the PCI ID for the target device. 29126f3cdf0SGordon Ross */ 29226f3cdf0SGordon Ross Info = ListHead; 29326f3cdf0SGordon Ross while (Info) 29426f3cdf0SGordon Ross { 29526f3cdf0SGordon Ross Status = AcpiHwGetPciDeviceInfo (PciId, Info->Device, 29626f3cdf0SGordon Ross &BusNumber, &IsBridge); 29726f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 29826f3cdf0SGordon Ross { 299*385cc6b4SJerry Jelinek return (Status); 30026f3cdf0SGordon Ross } 30126f3cdf0SGordon Ross 30226f3cdf0SGordon Ross Info = Info->Next; 30326f3cdf0SGordon Ross } 30426f3cdf0SGordon Ross 30526f3cdf0SGordon Ross ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 30626f3cdf0SGordon Ross "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " 30726f3cdf0SGordon Ross "Status %X BusNumber %X IsBridge %X\n", 30826f3cdf0SGordon Ross PciId->Segment, PciId->Bus, PciId->Device, PciId->Function, 30926f3cdf0SGordon Ross Status, BusNumber, IsBridge)); 31026f3cdf0SGordon Ross 311*385cc6b4SJerry Jelinek return (AE_OK); 31226f3cdf0SGordon Ross } 31326f3cdf0SGordon Ross 31426f3cdf0SGordon Ross 31526f3cdf0SGordon Ross /******************************************************************************* 31626f3cdf0SGordon Ross * 31726f3cdf0SGordon Ross * FUNCTION: AcpiHwDeletePciList 31826f3cdf0SGordon Ross * 31926f3cdf0SGordon Ross * PARAMETERS: ListHead - Device list created by 32026f3cdf0SGordon Ross * AcpiHwBuildPciList 32126f3cdf0SGordon Ross * 32226f3cdf0SGordon Ross * RETURN: None 32326f3cdf0SGordon Ross * 32426f3cdf0SGordon Ross * DESCRIPTION: Free the entire PCI list. 32526f3cdf0SGordon Ross * 32626f3cdf0SGordon Ross ******************************************************************************/ 32726f3cdf0SGordon Ross 32826f3cdf0SGordon Ross static void 32926f3cdf0SGordon Ross AcpiHwDeletePciList ( 33026f3cdf0SGordon Ross ACPI_PCI_DEVICE *ListHead) 33126f3cdf0SGordon Ross { 33226f3cdf0SGordon Ross ACPI_PCI_DEVICE *Next; 33326f3cdf0SGordon Ross ACPI_PCI_DEVICE *Previous; 33426f3cdf0SGordon Ross 33526f3cdf0SGordon Ross 33626f3cdf0SGordon Ross Next = ListHead; 33726f3cdf0SGordon Ross while (Next) 33826f3cdf0SGordon Ross { 33926f3cdf0SGordon Ross Previous = Next; 34026f3cdf0SGordon Ross Next = Previous->Next; 34126f3cdf0SGordon Ross ACPI_FREE (Previous); 34226f3cdf0SGordon Ross } 34326f3cdf0SGordon Ross } 34426f3cdf0SGordon Ross 34526f3cdf0SGordon Ross 34626f3cdf0SGordon Ross /******************************************************************************* 34726f3cdf0SGordon Ross * 34826f3cdf0SGordon Ross * FUNCTION: AcpiHwGetPciDeviceInfo 34926f3cdf0SGordon Ross * 35026f3cdf0SGordon Ross * PARAMETERS: PciId - Initial values for the PCI ID. May be 35126f3cdf0SGordon Ross * modified by this function. 35226f3cdf0SGordon Ross * PciDevice - Handle for the PCI device object 35326f3cdf0SGordon Ross * BusNumber - Where a PCI bridge bus number is returned 35426f3cdf0SGordon Ross * IsBridge - Return value, indicates if this PCI 35526f3cdf0SGordon Ross * device is a PCI bridge 35626f3cdf0SGordon Ross * 35726f3cdf0SGordon Ross * RETURN: Status 35826f3cdf0SGordon Ross * 35926f3cdf0SGordon Ross * DESCRIPTION: Get the device info for a single PCI device object. Get the 36026f3cdf0SGordon Ross * _ADR (contains PCI device and function numbers), and for PCI 36126f3cdf0SGordon Ross * bridge devices, get the bus number from PCI configuration 36226f3cdf0SGordon Ross * space. 36326f3cdf0SGordon Ross * 36426f3cdf0SGordon Ross ******************************************************************************/ 36526f3cdf0SGordon Ross 36626f3cdf0SGordon Ross static ACPI_STATUS 36726f3cdf0SGordon Ross AcpiHwGetPciDeviceInfo ( 36826f3cdf0SGordon Ross ACPI_PCI_ID *PciId, 36926f3cdf0SGordon Ross ACPI_HANDLE PciDevice, 37026f3cdf0SGordon Ross UINT16 *BusNumber, 37126f3cdf0SGordon Ross BOOLEAN *IsBridge) 37226f3cdf0SGordon Ross { 37326f3cdf0SGordon Ross ACPI_STATUS Status; 37426f3cdf0SGordon Ross ACPI_OBJECT_TYPE ObjectType; 37526f3cdf0SGordon Ross UINT64 ReturnValue; 37626f3cdf0SGordon Ross UINT64 PciValue; 37726f3cdf0SGordon Ross 37826f3cdf0SGordon Ross 37926f3cdf0SGordon Ross /* We only care about objects of type Device */ 38026f3cdf0SGordon Ross 38126f3cdf0SGordon Ross Status = AcpiGetType (PciDevice, &ObjectType); 38226f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 38326f3cdf0SGordon Ross { 38426f3cdf0SGordon Ross return (Status); 38526f3cdf0SGordon Ross } 38626f3cdf0SGordon Ross 38726f3cdf0SGordon Ross if (ObjectType != ACPI_TYPE_DEVICE) 38826f3cdf0SGordon Ross { 38926f3cdf0SGordon Ross return (AE_OK); 39026f3cdf0SGordon Ross } 39126f3cdf0SGordon Ross 39226f3cdf0SGordon Ross /* We need an _ADR. Ignore device if not present */ 39326f3cdf0SGordon Ross 39426f3cdf0SGordon Ross Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, 39526f3cdf0SGordon Ross PciDevice, &ReturnValue); 39626f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 39726f3cdf0SGordon Ross { 39826f3cdf0SGordon Ross return (AE_OK); 39926f3cdf0SGordon Ross } 40026f3cdf0SGordon Ross 40126f3cdf0SGordon Ross /* 40226f3cdf0SGordon Ross * From _ADR, get the PCI Device and Function and 40326f3cdf0SGordon Ross * update the PCI ID. 40426f3cdf0SGordon Ross */ 40526f3cdf0SGordon Ross PciId->Device = ACPI_HIWORD (ACPI_LODWORD (ReturnValue)); 40626f3cdf0SGordon Ross PciId->Function = ACPI_LOWORD (ACPI_LODWORD (ReturnValue)); 40726f3cdf0SGordon Ross 40826f3cdf0SGordon Ross /* 40926f3cdf0SGordon Ross * If the previous device was a bridge, use the previous 41026f3cdf0SGordon Ross * device bus number 41126f3cdf0SGordon Ross */ 41226f3cdf0SGordon Ross if (*IsBridge) 41326f3cdf0SGordon Ross { 41426f3cdf0SGordon Ross PciId->Bus = *BusNumber; 41526f3cdf0SGordon Ross } 41626f3cdf0SGordon Ross 41726f3cdf0SGordon Ross /* 41826f3cdf0SGordon Ross * Get the bus numbers from PCI Config space: 41926f3cdf0SGordon Ross * 42026f3cdf0SGordon Ross * First, get the PCI HeaderType 42126f3cdf0SGordon Ross */ 42226f3cdf0SGordon Ross *IsBridge = FALSE; 42326f3cdf0SGordon Ross Status = AcpiOsReadPciConfiguration (PciId, 42426f3cdf0SGordon Ross PCI_CFG_HEADER_TYPE_REG, &PciValue, 8); 42526f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 42626f3cdf0SGordon Ross { 42726f3cdf0SGordon Ross return (Status); 42826f3cdf0SGordon Ross } 42926f3cdf0SGordon Ross 43026f3cdf0SGordon Ross /* We only care about bridges (1=PciBridge, 2=CardBusBridge) */ 43126f3cdf0SGordon Ross 43226f3cdf0SGordon Ross PciValue &= PCI_HEADER_TYPE_MASK; 43326f3cdf0SGordon Ross 43426f3cdf0SGordon Ross if ((PciValue != PCI_TYPE_BRIDGE) && 43526f3cdf0SGordon Ross (PciValue != PCI_TYPE_CARDBUS_BRIDGE)) 43626f3cdf0SGordon Ross { 43726f3cdf0SGordon Ross return (AE_OK); 43826f3cdf0SGordon Ross } 43926f3cdf0SGordon Ross 44026f3cdf0SGordon Ross /* Bridge: Get the Primary BusNumber */ 44126f3cdf0SGordon Ross 44226f3cdf0SGordon Ross Status = AcpiOsReadPciConfiguration (PciId, 44326f3cdf0SGordon Ross PCI_CFG_PRIMARY_BUS_NUMBER_REG, &PciValue, 8); 44426f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 44526f3cdf0SGordon Ross { 44626f3cdf0SGordon Ross return (Status); 44726f3cdf0SGordon Ross } 44826f3cdf0SGordon Ross 44926f3cdf0SGordon Ross *IsBridge = TRUE; 45026f3cdf0SGordon Ross PciId->Bus = (UINT16) PciValue; 45126f3cdf0SGordon Ross 45226f3cdf0SGordon Ross /* Bridge: Get the Secondary BusNumber */ 45326f3cdf0SGordon Ross 45426f3cdf0SGordon Ross Status = AcpiOsReadPciConfiguration (PciId, 45526f3cdf0SGordon Ross PCI_CFG_SECONDARY_BUS_NUMBER_REG, &PciValue, 8); 45626f3cdf0SGordon Ross if (ACPI_FAILURE (Status)) 45726f3cdf0SGordon Ross { 45826f3cdf0SGordon Ross return (Status); 45926f3cdf0SGordon Ross } 46026f3cdf0SGordon Ross 46126f3cdf0SGordon Ross *BusNumber = (UINT16) PciValue; 46226f3cdf0SGordon Ross return (AE_OK); 46326f3cdf0SGordon Ross } 464