/* TODO: Change code to take advantage of driver model more */ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ struct acpi_pci_id **id, int *is_bridge, u8 * bus_number) { acpi_handle handle; struct acpi_pci_id *pci_id = *id; acpi_status status; unsigned long temp; acpi_object_type type; u8 tu8; acpi_get_parent(chandle, &handle); if (handle != rhandle) { acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number); status = acpi_get_type(handle, &type); if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) return; status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); if (ACPI_SUCCESS(status)) { pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp)); pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp)); if (*is_bridge) pci_id->bus = *bus_number; /* any nicer way to get bus number of bridge ? */ status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); if (ACPI_SUCCESS(status) && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8); if (!ACPI_SUCCESS(status)) { /* Certainly broken... FIX ME */ return; } *is_bridge = 1; pci_id->bus = tu8; status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); if (ACPI_SUCCESS(status)) { *bus_number = tu8; } } else *is_bridge = 0; } } }
acpi_status acpi_ex_pci_config_space_handler ( u32 function, ACPI_PHYSICAL_ADDRESS address, u32 bit_width, u32 *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; acpi_pci_id *pci_id; u16 pci_register; FUNCTION_TRACE ("Ex_pci_config_space_handler"); /* * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: * * Pci_segment is the PCI bus segment range 0-31 * Pci_bus is the PCI bus number range 0-255 * Pci_device is the PCI device number range 0-31 * Pci_function is the PCI device function number * Pci_register is the Config space register range 0-255 bytes * * Value - input value for write, output address for read * */ pci_id = (acpi_pci_id *) region_context; pci_register = (u16) address; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, pci_register)); switch (function) { case ACPI_READ_ADR_SPACE: *value = 0; status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width); break; case ACPI_WRITE_ADR_SPACE: status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width); break; default: status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (status); }
acpi_status acpi_ex_pci_config_space_handler ( u32 function, acpi_physical_address address, u32 bit_width, acpi_integer *value, void *handler_context, void *region_context) { acpi_status status = AE_OK; struct acpi_pci_id *pci_id; u16 pci_register; ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler"); /* * The arguments to acpi_os(Read|Write)pci_configuration are: * * pci_segment is the PCI bus segment range 0-31 * pci_bus is the PCI bus number range 0-255 * pci_device is the PCI device number range 0-31 * pci_function is the PCI device function number * pci_register is the Config space register range 0-255 bytes * * Value - input value for write, output address for read * */ pci_id = (struct acpi_pci_id *) region_context; pci_register = (u16) (u32) address; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, pci_register)); switch (function) { case ACPI_READ: *value = 0; status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width); break; case ACPI_WRITE: status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width); break; default: status = AE_BAD_PARAMETER; break; } return_ACPI_STATUS (status); }
static acpi_status acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, acpi_handle pci_device, u16 *bus_number, u8 *is_bridge) { acpi_status status; acpi_object_type object_type; u64 return_value; u64 pci_value; /* We only care about objects of type Device */ 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) */ pci_value &= PCI_HEADER_TYPE_MASK; if ((pci_value != PCI_TYPE_BRIDGE) && (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { return (AE_OK); } /* Bridge: Get the Primary bus_number */ status = acpi_os_read_pci_configuration(pci_id, PCI_CFG_PRIMARY_BUS_NUMBER_REG, &pci_value, 8); if (ACPI_FAILURE(status)) { return (status); } *is_bridge = TRUE; pci_id->bus = (u16)pci_value; /* Bridge: Get the Secondary bus_number */ status = acpi_os_read_pci_configuration(pci_id, PCI_CFG_SECONDARY_BUS_NUMBER_REG, &pci_value, 8); if (ACPI_FAILURE(status)) { return (status); } *bus_number = (u16)pci_value; return (AE_OK); }