static ACPI_STATUS AcpiHwGetPciDeviceInfo ( ACPI_PCI_ID *PciId, ACPI_HANDLE PciDevice, UINT16 *BusNumber, BOOLEAN *IsBridge) { ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; UINT64 ReturnValue; UINT64 PciValue; /* We only care about objects of type Device */ Status = AcpiGetType (PciDevice, &ObjectType); if (ACPI_FAILURE (Status)) { return (Status); } if (ObjectType != ACPI_TYPE_DEVICE) { return (AE_OK); } /* We need an _ADR. Ignore device if not present */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, PciDevice, &ReturnValue); if (ACPI_FAILURE (Status)) { return (AE_OK); } /* * From _ADR, get the PCI Device and Function and * update the PCI ID. */ PciId->Device = ACPI_HIWORD (ACPI_LODWORD (ReturnValue)); PciId->Function = ACPI_LOWORD (ACPI_LODWORD (ReturnValue)); /* * If the previous device was a bridge, use the previous * device bus number */ if (*IsBridge) { PciId->Bus = *BusNumber; } /* * Get the bus numbers from PCI Config space: * * First, get the PCI HeaderType */ *IsBridge = FALSE; Status = AcpiOsReadPciConfiguration (PciId, PCI_CFG_HEADER_TYPE_REG, &PciValue, 8); if (ACPI_FAILURE (Status)) { return (Status); } /* We only care about bridges (1=PciBridge, 2=CardBusBridge) */ PciValue &= PCI_HEADER_TYPE_MASK; if ((PciValue != PCI_TYPE_BRIDGE) && (PciValue != PCI_TYPE_CARDBUS_BRIDGE)) { return (AE_OK); } /* Bridge: Get the Primary BusNumber */ Status = AcpiOsReadPciConfiguration (PciId, PCI_CFG_PRIMARY_BUS_NUMBER_REG, &PciValue, 8); if (ACPI_FAILURE (Status)) { return (Status); } *IsBridge = TRUE; PciId->Bus = (UINT16) PciValue; /* Bridge: Get the Secondary BusNumber */ Status = AcpiOsReadPciConfiguration (PciId, PCI_CFG_SECONDARY_BUS_NUMBER_REG, &PciValue, 8); if (ACPI_FAILURE (Status)) { return (Status); } *BusNumber = (UINT16) PciValue; return (AE_OK); }
ACPI_STATUS AcpiEvPciConfigRegionSetup ( ACPI_HANDLE Handle, UINT32 Function, void *HandlerContext, void **RegionContext) { ACPI_STATUS Status = AE_OK; UINT64 PciValue; ACPI_PCI_ID *PciId = *RegionContext; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_NAMESPACE_NODE *ParentNode; ACPI_NAMESPACE_NODE *PciRootNode; ACPI_NAMESPACE_NODE *PciDeviceNode; ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); HandlerObj = RegionObj->Region.Handler; if (!HandlerObj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Attempting to init a region %p, with no handler\n", RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); } *RegionContext = NULL; if (Function == ACPI_REGION_DEACTIVATE) { if (PciId) { ACPI_FREE (PciId); } return_ACPI_STATUS (Status); } ParentNode = RegionObj->Region.Node->Parent; /* * Get the _SEG and _BBN values from the device upon which the handler * is installed. * * We need to get the _SEG and _BBN objects relative to the PCI BUS device. * This is the device the handler has been registered to handle. */ /* * If the AddressSpace.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the OpRegion * handlers with that device. */ if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) { /* Start search from the parent object */ PciRootNode = ParentNode; while (PciRootNode != AcpiGbl_RootNode) { /* Get the _HID/_CID in order to detect a RootBridge */ if (AcpiEvIsPciRootBridge (PciRootNode)) { /* Install a handler for this PCI root bridge */ Status = AcpiInstallAddressSpaceHandler ( (ACPI_HANDLE) PciRootNode, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE (Status)) { if (Status == AE_SAME_HANDLER) { /* * It is OK if the handler is already installed on the * root bridge. Still need to return a context object * for the new PCI_Config operation region, however. */ Status = AE_OK; } else { ACPI_EXCEPTION ((AE_INFO, Status, "Could not install PciConfig handler " "for Root Bridge %4.4s", AcpiUtGetNodeName (PciRootNode))); } } break; } PciRootNode = PciRootNode->Parent; } /* PCI root bridge not found, use namespace root node */ } else { PciRootNode = HandlerObj->AddressSpace.Node; } /* * If this region is now initialized, we are done. * (InstallAddressSpaceHandler could have initialized it) */ if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) { return_ACPI_STATUS (AE_OK); } /* Region is still not initialized. Create a new context */ PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); if (!PciId) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * For PCI_Config space access, we need the segment, bus, device and * function numbers. Acquire them here. * * Find the parent device object. (This allows the operation region to be * within a subscope under the device, such as a control method.) */ PciDeviceNode = RegionObj->Region.Node; while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) { PciDeviceNode = PciDeviceNode->Parent; } if (!PciDeviceNode) { ACPI_FREE (PciId); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * Get the PCI device and function numbers from the _ADR object * contained in the parent's scope. */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, PciDeviceNode, &PciValue); /* * The default is zero, and since the allocation above zeroed the data, * just do nothing on failure. */ if (ACPI_SUCCESS (Status)) { PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); } /* The PCI segment number comes from the _SEG method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, PciRootNode, &PciValue); if (ACPI_SUCCESS (Status)) { PciId->Segment = ACPI_LOWORD (PciValue); } /* The PCI bus number comes from the _BBN method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, PciRootNode, &PciValue); if (ACPI_SUCCESS (Status)) { PciId->Bus = ACPI_LOWORD (PciValue); } /* Complete/update the PCI ID for this device */ Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); if (ACPI_FAILURE (Status)) { ACPI_FREE (PciId); return_ACPI_STATUS (Status); } *RegionContext = PciId; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiGetObjectInfo ( ACPI_HANDLE Handle, ACPI_DEVICE_INFO *Info) { ACPI_DEVICE_ID Hid; ACPI_DEVICE_ID Uid; ACPI_STATUS Status; UINT32 DeviceStatus = 0; ACPI_INTEGER Address = 0; ACPI_NAMESPACE_NODE *Node; /* Ensure that ACPI has been initialized */ ACPI_IS_INITIALIZATION_COMPLETE (Status); if (ACPI_FAILURE (Status)) { return (Status); } /* Parameter validation */ if (!Handle || !Info) { return (AE_BAD_PARAMETER); } AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); Node = AcpiNsConvertHandleToEntry (Handle); if (!Node) { AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } Info->Type = Node->Type; Info->Name = Node->Name; AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* * If not a device, we are all done. */ if (Info->Type != ACPI_TYPE_DEVICE) { return (AE_OK); } /* * Get extra info for ACPI devices only. Run the * _HID, _UID, _STA, and _ADR methods. Note: none * of these methods are required, so they may or may * not be present. The Info->Valid bits are used * to indicate which methods ran successfully. */ Info->Valid = 0; /* Execute the _HID method and save the result */ Status = AcpiUtExecute_HID (Node, &Hid); if (ACPI_SUCCESS (Status)) { STRNCPY (Info->HardwareId, Hid.Buffer, sizeof(Info->HardwareId)); Info->Valid |= ACPI_VALID_HID; } /* Execute the _UID method and save the result */ Status = AcpiUtExecute_UID (Node, &Uid); if (ACPI_SUCCESS (Status)) { STRCPY (Info->UniqueId, Uid.Buffer); Info->Valid |= ACPI_VALID_UID; } /* * Execute the _STA method and save the result * _STA is not always present */ Status = AcpiUtExecute_STA (Node, &DeviceStatus); if (ACPI_SUCCESS (Status)) { Info->CurrentStatus = DeviceStatus; Info->Valid |= ACPI_VALID_STA; } /* * Execute the _ADR method and save result if successful * _ADR is not always present */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, &Address); if (ACPI_SUCCESS (Status)) { Info->Address = Address; Info->Valid |= ACPI_VALID_ADR; } return (AE_OK); }
ACPI_STATUS AcpiGetObjectInfo ( ACPI_HANDLE Handle, ACPI_BUFFER *Buffer) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_DEVICE_INFO *Info; ACPI_DEVICE_INFO *ReturnInfo; ACPI_COMPATIBLE_ID_LIST *CidList = NULL; ACPI_SIZE Size; /* Parameter validation */ if (!Handle || !Buffer) { return (AE_BAD_PARAMETER); } Status = AcpiUtValidateBuffer (Buffer); if (ACPI_FAILURE (Status)) { return (Status); } Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_INFO)); if (!Info) { return (AE_NO_MEMORY); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto Cleanup; } Node = AcpiNsMapHandleToNode (Handle); if (!Node) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); goto Cleanup; } /* Init return structure */ Size = sizeof (ACPI_DEVICE_INFO); Info->Type = Node->Type; Info->Name = Node->Name.Integer; Info->Valid = 0; Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* If not a device, we are all done */ if (Info->Type == ACPI_TYPE_DEVICE) { /* * Get extra info for ACPI Devices objects only: * Run the Device _HID, _UID, _CID, _STA, _ADR and _SxD methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and ran successfully. */ /* Execute the Device._HID method */ Status = AcpiUtExecute_HID (Node, &Info->HardwareId); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_HID; } /* Execute the Device._UID method */ Status = AcpiUtExecute_UID (Node, &Info->UniqueId); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_UID; } /* Execute the Device._CID method */ Status = AcpiUtExecute_CID (Node, &CidList); if (ACPI_SUCCESS (Status)) { Size += CidList->Size; Info->Valid |= ACPI_VALID_CID; } /* Execute the Device._STA method */ Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_STA; } /* Execute the Device._ADR method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, &Info->Address); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_ADR; } /* Execute the Device._SxD methods */ Status = AcpiUtExecute_Sxds (Node, Info->HighestDstates); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_SXDS; } } /* Validate/Allocate/Clear caller buffer */ Status = AcpiUtInitializeBuffer (Buffer, Size); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Populate the return buffer */ ReturnInfo = Buffer->Pointer; ACPI_MEMCPY (ReturnInfo, Info, sizeof (ACPI_DEVICE_INFO)); if (CidList) { ACPI_MEMCPY (&ReturnInfo->CompatibilityId, CidList, CidList->Size); } Cleanup: ACPI_FREE (Info); if (CidList) { ACPI_FREE (CidList); } return (Status); }
ACPI_STATUS AcpiEvPciConfigRegionSetup ( ACPI_HANDLE Handle, UINT32 Function, void *HandlerContext, void **RegionContext) { ACPI_STATUS Status = AE_OK; ACPI_INTEGER Temp; ACPI_PCI_ID *PciId = *RegionContext; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_NAMESPACE_NODE *Node; ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; ACPI_DEVICE_ID ObjectHID; ACPI_FUNCTION_TRACE ("EvPciConfigRegionSetup"); HandlerObj = RegionObj->Region.AddrHandler; if (!HandlerObj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Attempting to init a region %p, with no handler\n", RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); } if (Function == ACPI_REGION_DEACTIVATE) { if (PciId) { ACPI_MEM_FREE (PciId); *RegionContext = NULL; } return_ACPI_STATUS (Status); } /* Create a new context */ PciId = ACPI_MEM_CALLOCATE (sizeof (ACPI_PCI_ID)); if (!PciId) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * For PCI Config space access, we have to pass the segment, bus, * device and function numbers. This routine must acquire those. */ /* * First get device and function numbers from the _ADR object * in the parent's scope. */ Node = AcpiNsGetParentNode (RegionObj->Region.Node); /* Evaluate the _ADR object */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, &Temp); /* * The default is zero, and since the allocation above zeroed * the data, just do nothing on failure. */ if (ACPI_SUCCESS (Status)) { PciId->Device = ACPI_HIWORD (ACPI_LODWORD (Temp)); PciId->Function = ACPI_LOWORD (ACPI_LODWORD (Temp)); } /* * Get the _SEG and _BBN values from the device upon which the handler * is installed. * * We need to get the _SEG and _BBN objects relative to the PCI BUS device. * This is the device the handler has been registered to handle. */ /* * If the AddrHandler.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the OpRegion * handlers with that device. */ if (HandlerObj->AddrHandler.Node == AcpiGbl_RootNode) { /* * Node is currently the parent object */ while (Node != AcpiGbl_RootNode) { Status = AcpiUtExecute_HID (Node, &ObjectHID); if (ACPI_SUCCESS (Status)) { /* Got a valid _HID, check if this is a PCI root */ if (!(ACPI_STRNCMP (ObjectHID.Buffer, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { /* Install a handler for this PCI root bridge */ Status = AcpiInstallAddressSpaceHandler ((ACPI_HANDLE) Node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE (Status)) { ACPI_REPORT_ERROR (("Could not install PciConfig handler for %4.4s, %s\n", Node->Name.Ascii, AcpiFormatException (Status))); } break; } } Node = AcpiNsGetParentNode (Node); } } else { Node = HandlerObj->AddrHandler.Node; } /* * The PCI segment number comes from the _SEG method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, Node, &Temp); if (ACPI_SUCCESS (Status)) { PciId->Segment = ACPI_LOWORD (Temp); } /* * The PCI bus number comes from the _BBN method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, Node, &Temp); if (ACPI_SUCCESS (Status)) { PciId->Bus = ACPI_LOWORD (Temp); } /* * Complete this device's PciId */ AcpiOsDerivePciId (Node, RegionObj->Region.Node, &PciId); *RegionContext = PciId; return_ACPI_STATUS (AE_OK); }