/******************************************************************************* * * FUNCTION: acpi_hw_derive_pci_id * * PARAMETERS: pci_id - Initial values for the PCI ID. May be * modified by this function. * root_pci_device - A handle to a PCI device object. This * object must be a PCI Root Bridge having a * _HID value of either PNP0A03 or PNP0A08 * pci_region - A handle to a PCI configuration space * Operation Region being initialized * * RETURN: Status * * DESCRIPTION: This function derives a full PCI ID for a PCI device, * consisting of a Segment number, Bus number, Device number, * and function code. * * The PCI hardware dynamically configures PCI bus numbers * depending on the bus topology discovered during system * initialization. This function is invoked during configuration * of a PCI_Config Operation Region in order to (possibly) update * the Bus/Device/Function numbers in the pci_id with the actual * values as determined by the hardware and operating system * configuration. * * The pci_id parameter is initially populated during the Operation * Region initialization. This function is then called, and is * will make any necessary modifications to the Bus, Device, or * Function number PCI ID subfields as appropriate for the * current hardware and OS configuration. * * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id * interface since this feature is OS-independent. This module * specifically avoids any use of recursion by building a local * temporary device list. *
******************************************************************************/
if (!pci_id) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Build a list of PCI devices, from pci_region up to root_pci_device */
status =
acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head); if (ACPI_SUCCESS(status)) {
/* Walk the list, updating the PCI device/function/bus numbers */
status = acpi_hw_process_pci_list(pci_id, list_head);
/* Delete the list */
acpi_hw_delete_pci_list(list_head);
}
return_ACPI_STATUS(status);
}
/******************************************************************************* * * FUNCTION: acpi_hw_build_pci_list * * PARAMETERS: root_pci_device - A handle to a PCI device object. This * object is guaranteed to be a PCI Root * Bridge having a _HID value of either * PNP0A03 or PNP0A08 * pci_region - A handle to the PCI configuration space * Operation Region * return_list_head - Where the PCI device list is returned * * RETURN: Status * * DESCRIPTION: Builds a list of devices from the input PCI region up to the * Root PCI device for this namespace subtree. *
******************************************************************************/
/* * Ascend namespace branch until the root_pci_device is reached, building * a list of device nodes. Loop will exit when either the PCI device is * found, or the root of the namespace is reached.
*/
*return_list_head = NULL;
current_device = pci_region; while (1) {
status = acpi_get_parent(current_device, &parent_device); if (ACPI_FAILURE(status)) {
/******************************************************************************* * * FUNCTION: acpi_hw_process_pci_list * * PARAMETERS: pci_id - Initial values for the PCI ID. May be * modified by this function. * list_head - Device list created by * acpi_hw_build_pci_list * * RETURN: Status * * DESCRIPTION: Walk downward through the PCI device list, getting the device * info for each, via the PCI configuration space and updating * the PCI ID as necessary. Deletes the list during traversal. *
******************************************************************************/
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function));
bus_number = pci_id->bus;
/* * Descend down the namespace tree, collecting PCI device, function, * and bus numbers. bus_number is only important for PCI bridges. * Algorithm: As we descend the tree, use the last valid PCI device, * function, and bus numbers that are discovered, and assign them * to the PCI ID for the target device.
*/
info = list_head; while (info) {
status = acpi_hw_get_pci_device_info(pci_id, info->device,
&bus_number, &is_bridge); if (ACPI_FAILURE(status)) { return (status);
}
info = info->next;
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " "Status %X BusNumber %X IsBridge %X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function, status, bus_number, is_bridge));
return (AE_OK);
}
/******************************************************************************* * * FUNCTION: acpi_hw_delete_pci_list * * PARAMETERS: list_head - Device list created by * acpi_hw_build_pci_list * * RETURN: None * * DESCRIPTION: Free the entire PCI list. *
******************************************************************************/
next = list_head; while (next) {
previous = next;
next = previous->next;
ACPI_FREE(previous);
}
}
/******************************************************************************* * * FUNCTION: acpi_hw_get_pci_device_info * * PARAMETERS: pci_id - Initial values for the PCI ID. May be * modified by this function. * pci_device - Handle for the PCI device object * bus_number - Where a PCI bridge bus number is returned * is_bridge - Return value, indicates if this PCI * device is a PCI bridge * * RETURN: Status * * DESCRIPTION: Get the device info for a single PCI device object. Get the * _ADR (contains PCI device and function numbers), and for PCI * bridge devices, get the bus number from PCI configuration * space. *
******************************************************************************/
status = acpi_get_type(pci_device, &object_type); if (ACPI_FAILURE(status)) { return (status);
}
if (object_type != ACPI_TYPE_DEVICE) { return (AE_OK);
}
/* We need an _ADR. Ignore device if not present */
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
pci_device, &return_value); if (ACPI_FAILURE(status)) { return (AE_OK);
}
/* * From _ADR, get the PCI Device and Function and * update the PCI ID.
*/
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
/* * If the previous device was a bridge, use the previous * device bus number
*/ if (*is_bridge) {
pci_id->bus = *bus_number;
}
/* * Get the bus numbers from PCI Config space: * * First, get the PCI header_type
*/
*is_bridge = FALSE;
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_HEADER_TYPE_REG,
&pci_value, 8); if (ACPI_FAILURE(status)) { return (status);
}
/* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.