From 5789be33af09d93eb251011ce4079edcc20a7627 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sat, 7 May 2011 16:50:46 +0000 Subject: [PATCH] Add a way to look up basic PCI info for an ACPI device. It works for retrieving the base bus number and segment which is what we're using them for. It should work generically, however I only tested it to look up PCI bridge devices. The logic is a subset of what is done in AcpiEvPciConfigRegionSetup when setting up the operation region for a PCI device. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41365 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/ACPI.h | 13 ++++ .../kernel/bus_managers/acpi/acpi_busman.c | 65 +++++++++++++++---- .../kernel/bus_managers/acpi/acpi_module.c | 4 +- .../kernel/bus_managers/acpi/acpi_priv.h | 8 +++ 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/headers/os/drivers/ACPI.h b/headers/os/drivers/ACPI.h index 8765136c5a..c508414ae2 100644 --- a/headers/os/drivers/ACPI.h +++ b/headers/os/drivers/ACPI.h @@ -135,6 +135,15 @@ enum { ACPI_ALLOCATE_BUFFER = -1, }; + +typedef struct acpi_pci_info { + uint16 segment; + uint16 bus; + uint16 device; + uint16 function; +} acpi_pci_info; + + /* * acpi_status should return ACPI specific error codes, not BeOS ones. */ @@ -248,6 +257,10 @@ struct acpi_module_info { size_t size); status_t (*enter_sleep_state)(uint8 state); status_t (*reboot)(void); + + /* PCI specific info */ + status_t (*get_pci_info)(acpi_handle pciRootBridge, acpi_handle device, + acpi_pci_info *info); }; diff --git a/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c b/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c index 02eea915ba..7bad5b2615 100644 --- a/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c +++ b/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c @@ -77,8 +77,8 @@ get_device_by_hid_callback(ACPI_HANDLE object, UINT32 depth, void* context, static void dump_madt() { ACPI_STATUS status; ACPI_TABLE_HEADER *madt = NULL; - ACPI_SUBTABLE_HEADER *entry; - void *end; +/* ACPI_SUBTABLE_HEADER *entry; + void *end; */ int madtCount = -1; while (true) { @@ -481,14 +481,14 @@ get_device_hid(const char *path, char *hid, size_t bufferLength) if (info.Type == ACPI_TYPE_INTEGER) { uint32 eisaId = AcpiUtDwordByteSwap(info.Integer.Value); - hid[0] = (char) ('@' + ((eisaId >> 26) & 0x1f)); - hid[1] = (char) ('@' + ((eisaId >> 21) & 0x1f)); - hid[2] = (char) ('@' + ((eisaId >> 16) & 0x1f)); - hid[3] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 12); - hid[4] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 8); - hid[5] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 4); - hid[6] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 0); - hid[7] = 0; + hid[0] = (char) ('@' + ((eisaId >> 26) & 0x1f)); + hid[1] = (char) ('@' + ((eisaId >> 21) & 0x1f)); + hid[2] = (char) ('@' + ((eisaId >> 16) & 0x1f)); + hid[3] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 12); + hid[4] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 8); + hid[5] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 4); + hid[6] = AcpiUtHexToAsciiChar((ACPI_INTEGER)eisaId, 0); + hid[7] = 0; } hid[ACPI_DEVICE_ID_LENGTH] = '\0'; @@ -705,6 +705,48 @@ reboot(void) } +status_t +get_pci_info(acpi_handle pciRootBridge, acpi_handle device, acpi_pci_info *info) +{ + ACPI_STATUS status; + ACPI_HANDLE childNode; + uint64 deviceAddress = 0; + uint64 segment = 0; + uint64 busNumber = 0; + + // We reset the structure to 0 here. Any failed evaluation means default + // values, so we don't have to do anything in the error case. + memset(info, 0, sizeof(acpi_pci_info)); + + status = AcpiUtEvaluateNumericObject(METHOD_NAME__ADR, device, + &deviceAddress); + if (status == AE_OK) { + info->device = (uint8)(deviceAddress >> 16); + info->function = (uint8)deviceAddress; + } + + status = AcpiUtEvaluateNumericObject(METHOD_NAME__SEG, pciRootBridge, + &segment); + if (status == AE_OK) + info->segment = (uint8)segment; + + status = AcpiUtEvaluateNumericObject(METHOD_NAME__BBN, pciRootBridge, + &busNumber); + if (status == AE_OK) + info->bus = (uint8)busNumber; + + // since AcpiHwDerivePciId assumes getting a child object of the device + // it iterates one step less than we need - get any child node to work + // around that + status = AcpiGetNextObject(ACPI_TYPE_METHOD, device, NULL, &childNode); + if (status != AE_OK) + return B_ERROR; + + status = AcpiHwDerivePciId((ACPI_PCI_ID*)info, pciRootBridge, childNode); + return status == AE_OK ? B_OK : B_ERROR; +} + + struct acpi_module_info gACPIModule = { { B_ACPI_MODULE_NAME, @@ -743,5 +785,6 @@ struct acpi_module_info gACPIModule = { get_possible_resources, prepare_sleep_state, enter_sleep_state, - reboot + reboot, + get_pci_info }; diff --git a/src/add-ons/kernel/bus_managers/acpi/acpi_module.c b/src/add-ons/kernel/bus_managers/acpi/acpi_module.c index d8b80d8908..0224293ba0 100644 --- a/src/add-ons/kernel/bus_managers/acpi/acpi_module.c +++ b/src/add-ons/kernel/bus_managers/acpi/acpi_module.c @@ -70,7 +70,6 @@ acpi_enumerate_child_devices(device_node* node, const char* root) { char result[255]; void* counter = NULL; - device_node* parent = NULL; TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root)); @@ -219,7 +218,8 @@ static struct acpi_root_info sACPIRootModule = { get_possible_resources, prepare_sleep_state, enter_sleep_state, - reboot + reboot, + get_pci_info }; diff --git a/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h b/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h index d328048e1d..106c0678ea 100644 --- a/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h +++ b/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h @@ -132,6 +132,10 @@ typedef struct acpi_root_info { size_t size); status_t (*enter_sleep_state)(uint8 state); status_t (*reboot)(void); + + /* PCI specific info */ + status_t (*get_pci_info)(acpi_handle pciRootBridge, acpi_handle device, + acpi_pci_info *info); } acpi_root_info; @@ -205,6 +209,10 @@ status_t prepare_sleep_state(uint8 state, void (*wakeFunc)(void), size_t size); status_t enter_sleep_state(uint8 state); status_t reboot(void); + +status_t get_pci_info(acpi_handle pciRootBridge, acpi_handle device, + acpi_pci_info *info); + __END_DECLS