Author: mmlr Date: 2011-05-07 18:50:46 +0200 (Sat, 07 May 2011) New Revision: 41365 Changeset: https://dev.haiku-os.org/changeset/41365 Modified: haiku/trunk/headers/os/drivers/ACPI.h haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_module.c haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h Log: 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. Modified: haiku/trunk/headers/os/drivers/ACPI.h =================================================================== --- haiku/trunk/headers/os/drivers/ACPI.h 2011-05-07 16:40:32 UTC (rev 41364) +++ haiku/trunk/headers/os/drivers/ACPI.h 2011-05-07 16:50:46 UTC (rev 41365) @@ -135,6 +135,15 @@ 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 @@ 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); }; Modified: haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c 2011-05-07 16:40:32 UTC (rev 41364) +++ haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_busman.c 2011-05-07 16:50:46 UTC (rev 41365) @@ -77,8 +77,8 @@ 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 @@ 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 @@ } +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 @@ get_possible_resources, prepare_sleep_state, enter_sleep_state, - reboot + reboot, + get_pci_info }; Modified: haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_module.c =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_module.c 2011-05-07 16:40:32 UTC (rev 41364) +++ haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_module.c 2011-05-07 16:50:46 UTC (rev 41365) @@ -70,7 +70,6 @@ { char result[255]; void* counter = NULL; - device_node* parent = NULL; TRACE(("acpi_enumerate_child_devices: recursing from %s\n", root)); @@ -219,7 +218,8 @@ get_possible_resources, prepare_sleep_state, enter_sleep_state, - reboot + reboot, + get_pci_info }; Modified: haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h =================================================================== --- haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h 2011-05-07 16:40:32 UTC (rev 41364) +++ haiku/trunk/src/add-ons/kernel/bus_managers/acpi/acpi_priv.h 2011-05-07 16:50:46 UTC (rev 41365) @@ -132,6 +132,10 @@ 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 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