ACPI_STATUS AcpiEvPciConfigRegionSetup ( ACPI_HANDLE Handle, UINT32 Function, void *HandlerContext, void **RegionContext) { ACPI_STATUS Status = AE_OK; ACPI_INTEGER 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 = AcpiNsGetParentNode (RegionObj->Region.Node); /* * 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 = AcpiNsGetParentNode (PciRootNode); } /* 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 = AcpiNsGetParentNode (PciDeviceNode); } 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 this device's PciId */ AcpiOsDerivePciId (PciRootNode, RegionObj->Region.Node, &PciId); *RegionContext = PciId; return_ACPI_STATUS (AE_OK); }
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); }