From b5dba2e4ad62146d50d7840b67edbafad7856722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 15 Mar 2020 19:56:40 +0100 Subject: [PATCH] acpi: add ACPI_DEVICE_ADDR_ITEM and ACPI_DEVICE_CID_ITEM for device nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ACPI_DEVICE_HID_ITEM is now optional, instead of an empty string. Change-Id: I352ffaaad377659f650a0b8c0d56e40a68b739c3 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2420 Reviewed-by: Jérôme Duval --- headers/os/drivers/ACPI.h | 6 ++- .../kernel/bus_managers/acpi/ACPIPrivate.h | 8 +-- .../kernel/bus_managers/acpi/BusManager.cpp | 51 ++++++++++++++---- .../kernel/bus_managers/acpi/Module.cpp | 53 +++++++++++++------ .../bus_managers/acpi/NamespaceDump.cpp | 13 +++-- 5 files changed, 96 insertions(+), 35 deletions(-) diff --git a/headers/os/drivers/ACPI.h b/headers/os/drivers/ACPI.h index 1efb2a03f1..a5f3b7e814 100644 --- a/headers/os/drivers/ACPI.h +++ b/headers/os/drivers/ACPI.h @@ -243,8 +243,8 @@ struct acpi_module_info { status_t (*get_device)(const char *hid, uint32 index, char *result, size_t resultLength); - status_t (*get_device_hid)(const char *path, char *hid, - size_t hidLength); + status_t (*get_device_info)(const char *path, char** hid, + char** cidList, size_t cidListLength); uint32 (*get_object_type)(const char *path); status_t (*get_object)(const char *path, acpi_object_type **_returnValue); @@ -303,6 +303,8 @@ enum { }; +#define ACPI_DEVICE_ADDR_ITEM "acpi/addr" +#define ACPI_DEVICE_CID_ITEM "acpi/cid" #define ACPI_DEVICE_HID_ITEM "acpi/hid" #define ACPI_DEVICE_PATH_ITEM "acpi/path" #define ACPI_DEVICE_TYPE_ITEM "acpi/type" diff --git a/src/add-ons/kernel/bus_managers/acpi/ACPIPrivate.h b/src/add-ons/kernel/bus_managers/acpi/ACPIPrivate.h index f0071c678b..b4b2e24046 100644 --- a/src/add-ons/kernel/bus_managers/acpi/ACPIPrivate.h +++ b/src/add-ons/kernel/bus_managers/acpi/ACPIPrivate.h @@ -112,8 +112,8 @@ typedef struct acpi_root_info { status_t (*get_device)(const char *hid, uint32 index, char *result, size_t resultLength); - status_t (*get_device_hid)(const char *path, char *hid, - size_t hidLength); + status_t (*get_device_info)(const char *path, char **hid, + char** cidList, size_t cidListCount); uint32 (*get_object_type)(const char *path); status_t (*get_object)(const char *path, acpi_object_type **_returnValue); @@ -213,7 +213,9 @@ status_t get_next_object(uint32 object_type, acpi_handle parent, status_t get_device(const char* hid, uint32 index, char* result, size_t resultLength); -status_t get_device_hid(const char* path, char* hid, size_t hidLength); +status_t get_device_info(const char* path, char** hid, char** cidList, + size_t cidListCount); +status_t get_device_addr(const char* path, uint32* addr); uint32 get_object_type(const char* path); status_t get_object(const char* path, acpi_object_type** _returnValue); status_t get_object_typed(const char* path, acpi_object_type** _returnValue, diff --git a/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp b/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp index 7d60c7f38d..6882862455 100644 --- a/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/acpi/BusManager.cpp @@ -43,7 +43,6 @@ extern "C" { #define ACPI_DEVICE_ID_LENGTH 0x08 -extern pci_module_info* gPCIManager; extern dpc_module_info* gDPC; void* gDPCHandle = NULL; @@ -534,30 +533,60 @@ get_device(const char* hid, uint32 index, char* result, size_t resultLength) status_t -get_device_hid(const char *path, char *hid, size_t bufferLength) +get_device_info(const char *path, char** hid, char** cidList, + size_t cidListCount) { ACPI_HANDLE handle; ACPI_DEVICE_INFO *info; - TRACE("get_device_hid: path %s, hid %s\n", path, hid); + TRACE("get_device_info: path %s\n", path); if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) return B_ENTRY_NOT_FOUND; - if (bufferLength < ACPI_DEVICE_ID_LENGTH) - return B_BUFFER_OVERFLOW; - if (AcpiGetObjectInfo(handle, &info) != AE_OK) return B_BAD_TYPE; - if ((info->Valid & ACPI_VALID_HID) != 0) - strlcpy(hid, info->HardwareId.String, bufferLength); - else - hid[0] = '\0'; + if ((info->Valid & ACPI_VALID_HID) != 0 && hid != NULL) + *hid = strndup(info->HardwareId.String, info->HardwareId.Length); + + if ((info->Valid & ACPI_VALID_CID) != 0 && cidList != NULL) { + if (cidListCount > info->CompatibleIdList.Count) + cidListCount = info->CompatibleIdList.Count; + for (size_t i = 0; i < cidListCount; i++) { + cidList[i] = strndup(info->CompatibleIdList.Ids[i].String, + info->CompatibleIdList.Ids[i].Length); + } + } + AcpiOsFree(info); return B_OK; } +status_t +get_device_addr(const char *path, uint32 *addr) +{ + ACPI_HANDLE handle; + + TRACE("get_device_adr: path %s, hid %s\n", path, hid); + if (AcpiGetHandle(NULL, (ACPI_STRING)path, &handle) != AE_OK) + return B_ENTRY_NOT_FOUND; + + status_t status = B_BAD_VALUE; + acpi_data buf; + acpi_object_type object; + buf.pointer = &object; + buf.length = sizeof(acpi_object_type); + if (addr != NULL + && evaluate_method(handle, "_ADR", NULL, &buf) == B_OK + && object.object_type == ACPI_TYPE_INTEGER) { + status = B_OK; + *addr = object.integer.integer; + } + return status; +} + + uint32 get_object_type(const char* path) { @@ -838,7 +867,7 @@ struct acpi_module_info gACPIModule = { get_next_entry, get_next_object, get_device, - get_device_hid, + get_device_info, get_object_type, get_object, get_object_typed, diff --git a/src/add-ons/kernel/bus_managers/acpi/Module.cpp b/src/add-ons/kernel/bus_managers/acpi/Module.cpp index 82f6c7a227..7227c7dc64 100644 --- a/src/add-ons/kernel/bus_managers/acpi/Module.cpp +++ b/src/add-ons/kernel/bus_managers/acpi/Module.cpp @@ -86,8 +86,7 @@ acpi_enumerate_child_devices(device_node* node, const char* root) case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: case ACPI_TYPE_DEVICE: { - char hid[16] = ""; - device_attr attrs[] = { + device_attr attrs[15] = { // info about device { B_DEVICE_BUS, B_STRING_TYPE, { string: "acpi" }}, @@ -95,24 +94,48 @@ acpi_enumerate_child_devices(device_node* node, const char* root) { ACPI_DEVICE_PATH_ITEM, B_STRING_TYPE, { string: result }}, // info about the device - { ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }}, { ACPI_DEVICE_TYPE_ITEM, B_UINT32_TYPE, { ui32: type }}, - // consumer specification - /*{ B_DRIVER_MAPPING, B_STRING_TYPE, { string: - "hid_%" ACPI_DEVICE_HID_ITEM "%" }}, - { B_DRIVER_MAPPING "/0", B_STRING_TYPE, { string: - "type_%" ACPI_DEVICE_TYPE_ITEM "%" }},*/ - { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: /*B_FIND_CHILD_ON_DEMAND|*/B_FIND_MULTIPLE_CHILDREN }}, + { B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }}, { NULL } }; - if (type == ACPI_TYPE_DEVICE) - get_device_hid(result, hid, sizeof(hid)); + uint32 attrCount = 4; + char* hid = NULL; + char* cidList[8] = { NULL }; + if (type == ACPI_TYPE_DEVICE) { + if (get_device_info(result, &hid, (char**)&cidList, 8) + == B_OK) { + if (hid != NULL) { + attrs[attrCount].name = ACPI_DEVICE_HID_ITEM; + attrs[attrCount].type = B_STRING_TYPE; + attrs[attrCount].value.string = hid; + attrCount++; + } + for (int i = 0; cidList[i] != NULL; i++) { + attrs[attrCount].name = ACPI_DEVICE_CID_ITEM; + attrs[attrCount].type = B_STRING_TYPE; + attrs[attrCount].value.string = cidList[i]; + attrCount++; + } + } + uint32 addr; + if (get_device_addr(result, &addr) == B_OK) { + attrs[attrCount].name = ACPI_DEVICE_ADDR_ITEM; + attrs[attrCount].type = B_UINT32_TYPE; + attrs[attrCount].value.ui32 = addr; + attrCount++; + } + } - if (gDeviceManager->register_node(node, ACPI_DEVICE_MODULE_NAME, attrs, - NULL, &deviceNode) == B_OK) - acpi_enumerate_child_devices(deviceNode, result); + status_t status = gDeviceManager->register_node(node, + ACPI_DEVICE_MODULE_NAME, attrs, NULL, &deviceNode); + free(hid); + for (int i = 0; cidList[i] != NULL; i++) + free(cidList[i]); + if (status != B_OK) + break; + acpi_enumerate_child_devices(deviceNode, result); break; } default: @@ -253,7 +276,7 @@ static struct acpi_root_info sACPIRootModule = { get_next_entry, get_next_object, get_device, - get_device_hid, + get_device_info, get_object_type, get_object, get_object_typed, diff --git a/src/add-ons/kernel/bus_managers/acpi/NamespaceDump.cpp b/src/add-ons/kernel/bus_managers/acpi/NamespaceDump.cpp index 3b930b947f..5c489aa1db 100644 --- a/src/add-ons/kernel/bus_managers/acpi/NamespaceDump.cpp +++ b/src/add-ons/kernel/bus_managers/acpi/NamespaceDump.cpp @@ -83,7 +83,6 @@ dump_acpi_namespace(acpi_ns_device_info *device, char *root, int indenting) char result[255]; char output[320]; char tabs[255] = ""; - char hid[16] = ""; int i; size_t written = 0; for (i = 0; i < indenting; i++) @@ -114,12 +113,18 @@ dump_acpi_namespace(acpi_ns_device_info *device, char *root, int indenting) strlcat(output, " FIELD UNIT", sizeof(output)); break; case ACPI_TYPE_DEVICE: - hid[0] = 0; /* zero-terminate string; get_device_hid can (and will) fail! */ - device->acpi->get_device_hid(result, hid, sizeof(hid)); + { + char* hid = NULL; + device->acpi->get_device_info(result, &hid, NULL, 0); strlcat(output, " DEVICE (", sizeof(output)); - strlcat(output, hid, sizeof(output)); + if (hid != NULL) { + strlcat(output, hid, sizeof(output)); + free(hid); + } else + strlcat(output, "none", sizeof(output)); strlcat(output, ")", sizeof(output)); break; + } case ACPI_TYPE_EVENT: strlcat(output, " EVENT", sizeof(output)); break;