acpi_status acpi_get_object_info ( acpi_handle handle, acpi_device_info *info) { acpi_device_id hid; acpi_device_id uid; acpi_status status; u32 device_status = 0; acpi_integer address = 0; acpi_namespace_node *node; /* Parameter validation */ if (!handle || !info) { return (AE_BAD_PARAMETER); } acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); node = acpi_ns_map_handle_to_node (handle); if (!node) { acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } info->type = node->type; info->name = node->name; acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * If not a device, we are all done. */ if (info->type != ACPI_TYPE_DEVICE) { return (AE_OK); } /* * Get extra info for ACPI devices only. Run the * _HID, _UID, _STA, and _ADR methods. Note: none * of these methods are required, so they may or may * not be present. The Info->Valid bits are used * to indicate which methods ran successfully. */ info->valid = 0; /* Execute the _HID method and save the result */ status = acpi_ut_execute_HID (node, &hid); if (ACPI_SUCCESS (status)) { STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); info->valid |= ACPI_VALID_HID; } /* Execute the _UID method and save the result */ status = acpi_ut_execute_UID (node, &uid); if (ACPI_SUCCESS (status)) { STRCPY (info->unique_id, uid.buffer); info->valid |= ACPI_VALID_UID; } /* * Execute the _STA method and save the result * _STA is not always present */ status = acpi_ut_execute_STA (node, &device_status); if (ACPI_SUCCESS (status)) { info->current_status = device_status; info->valid |= ACPI_VALID_STA; } /* * Execute the _ADR method and save result if successful * _ADR is not always present */ status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &address); if (ACPI_SUCCESS (status)) { info->address = address; info->valid |= ACPI_VALID_ADR; } return (AE_OK); }
/****************************************************************************** * * FUNCTION: acpi_get_object_info * * PARAMETERS: Handle - Object Handle * Buffer - Where the info is returned * * RETURN: Status * * DESCRIPTION: Returns information about an object as gleaned from the * namespace node and possibly by running several standard * control methods (Such as in the case of a device.) * ******************************************************************************/ acpi_status acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) { acpi_status status; struct acpi_namespace_node *node; struct acpi_device_info *info; struct acpi_device_info *return_info; struct acpi_compatible_id_list *cid_list = NULL; acpi_size size; /* Parameter validation */ if (!handle || !buffer) { return (AE_BAD_PARAMETER); } status = acpi_ut_validate_buffer(buffer); if (ACPI_FAILURE(status)) { return (status); } info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); if (!info) { return (AE_NO_MEMORY); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; } node = acpi_ns_map_handle_to_node(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); status = AE_BAD_PARAMETER; goto cleanup; } /* Init return structure */ size = sizeof(struct acpi_device_info); info->type = node->type; info->name = node->name.integer; info->valid = 0; if (node->type == ACPI_TYPE_METHOD) { info->param_count = node->object->method.param_count; } status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; } /* If not a device, we are all done */ if (info->type == ACPI_TYPE_DEVICE) { /* * Get extra info for ACPI Devices objects only: * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and ran successfully. */ /* Execute the Device._HID method */ status = acpi_ut_execute_HID(node, &info->hardware_id); if (ACPI_SUCCESS(status)) { info->valid |= ACPI_VALID_HID; } /* Execute the Device._UID method */ status = acpi_ut_execute_UID(node, &info->unique_id); if (ACPI_SUCCESS(status)) { info->valid |= ACPI_VALID_UID; } /* Execute the Device._CID method */ status = acpi_ut_execute_CID(node, &cid_list); if (ACPI_SUCCESS(status)) { size += cid_list->size; info->valid |= ACPI_VALID_CID; } /* Execute the Device._STA method */ status = acpi_ut_execute_STA(node, &info->current_status); if (ACPI_SUCCESS(status)) { info->valid |= ACPI_VALID_STA; } /* Execute the Device._ADR method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, &info->address); if (ACPI_SUCCESS(status)) { info->valid |= ACPI_VALID_ADR; } /* Execute the Device._sx_d methods */ status = acpi_ut_execute_sxds(node, info->highest_dstates); if (ACPI_SUCCESS(status)) { info->valid |= ACPI_VALID_SXDS; } } /* Validate/Allocate/Clear caller buffer */ status = acpi_ut_initialize_buffer(buffer, size); if (ACPI_FAILURE(status)) { goto cleanup; } /* Populate the return buffer */ return_info = buffer->pointer; ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); if (cid_list) { ACPI_MEMCPY(&return_info->compatibility_id, cid_list, cid_list->size); } cleanup: ACPI_FREE(info); if (cid_list) { ACPI_FREE(cid_list); } return (status); }
acpi_status acpi_get_object_info(acpi_handle handle, struct acpi_device_info **return_buffer) { struct acpi_namespace_node *node; struct acpi_device_info *info; struct acpi_pnp_device_id_list *cid_list = NULL; struct acpi_pnp_device_id *hid = NULL; struct acpi_pnp_device_id *uid = NULL; struct acpi_pnp_device_id *sub = NULL; struct acpi_pnp_device_id *cls = NULL; char *next_id_string; acpi_object_type type; acpi_name name; u8 param_count = 0; u16 valid = 0; u32 info_size; u32 i; acpi_status status; /* Parameter validation */ if (!handle || !return_buffer) { return (AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } node = acpi_ns_validate_handle(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } /* Get the namespace node data while the namespace is locked */ info_size = sizeof(struct acpi_device_info); type = node->type; name = node->name.integer; if (node->type == ACPI_TYPE_METHOD) { param_count = node->object->method.param_count; } status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { /* * Get extra info for ACPI Device/Processor objects only: * Run the Device _HID, _UID, _SUB, _CID, and _CLS methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and run successfully. */ /* Execute the Device._HID method */ status = acpi_ut_execute_HID(node, &hid); if (ACPI_SUCCESS(status)) { info_size += hid->length; valid |= ACPI_VALID_HID; } /* Execute the Device._UID method */ status = acpi_ut_execute_UID(node, &uid); if (ACPI_SUCCESS(status)) { info_size += uid->length; valid |= ACPI_VALID_UID; } /* Execute the Device._SUB method */ status = acpi_ut_execute_SUB(node, &sub); if (ACPI_SUCCESS(status)) { info_size += sub->length; valid |= ACPI_VALID_SUB; } /* Execute the Device._CID method */ status = acpi_ut_execute_CID(node, &cid_list); if (ACPI_SUCCESS(status)) { /* Add size of CID strings and CID pointer array */ info_size += (cid_list->list_size - sizeof(struct acpi_pnp_device_id_list)); valid |= ACPI_VALID_CID; } /* Execute the Device._CLS method */ status = acpi_ut_execute_CLS(node, &cls); if (ACPI_SUCCESS(status)) { info_size += cls->length; valid |= ACPI_VALID_CLS; } } /* * Now that we have the variable-length data, we can allocate the * return buffer */ info = ACPI_ALLOCATE_ZEROED(info_size); if (!info) { status = AE_NO_MEMORY; goto cleanup; } /* Get the fixed-length data */ if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { /* * Get extra info for ACPI Device/Processor objects only: * Run the _STA, _ADR and, sx_w, and _sx_d methods. * * Notes: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and run successfully. * * For _STA, if the method does not exist, then (as per the ACPI * specification), the returned current_status flags will indicate * that the device is present/functional/enabled. Otherwise, the * current_status flags reflect the value returned from _STA. */ /* Execute the Device._STA method */ status = acpi_ut_execute_STA(node, &info->current_status); if (ACPI_SUCCESS(status)) { valid |= ACPI_VALID_STA; } /* Execute the Device._ADR method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, &info->address); if (ACPI_SUCCESS(status)) { valid |= ACPI_VALID_ADR; } /* Execute the Device._sx_w methods */ status = acpi_ut_execute_power_methods(node, acpi_gbl_lowest_dstate_names, ACPI_NUM_sx_w_METHODS, info->lowest_dstates); if (ACPI_SUCCESS(status)) { valid |= ACPI_VALID_SXWS; } /* Execute the Device._sx_d methods */ status = acpi_ut_execute_power_methods(node, acpi_gbl_highest_dstate_names, ACPI_NUM_sx_d_METHODS, info->highest_dstates); if (ACPI_SUCCESS(status)) { valid |= ACPI_VALID_SXDS; } } /* * Create a pointer to the string area of the return buffer. * Point to the end of the base struct acpi_device_info structure. */ next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); if (cid_list) { /* Point past the CID PNP_DEVICE_ID array */ next_id_string += ((acpi_size) cid_list->count * sizeof(struct acpi_pnp_device_id)); } /* * Copy the HID, UID, SUB, and CIDs to the return buffer. * The variable-length strings are copied to the reserved area * at the end of the buffer. * * For HID and CID, check if the ID is a PCI Root Bridge. */ if (hid) { next_id_string = acpi_ns_copy_device_id(&info->hardware_id, hid, next_id_string); if (acpi_ut_is_pci_root_bridge(hid->string)) { info->flags |= ACPI_PCI_ROOT_BRIDGE; } } if (uid) { next_id_string = acpi_ns_copy_device_id(&info->unique_id, uid, next_id_string); } if (sub) { next_id_string = acpi_ns_copy_device_id(&info->subsystem_id, sub, next_id_string); } if (cid_list) { info->compatible_id_list.count = cid_list->count; info->compatible_id_list.list_size = cid_list->list_size; /* Copy each CID */ for (i = 0; i < cid_list->count; i++) { next_id_string = acpi_ns_copy_device_id(&info->compatible_id_list. ids[i], &cid_list->ids[i], next_id_string); if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) { info->flags |= ACPI_PCI_ROOT_BRIDGE; } } } if (cls) { next_id_string = acpi_ns_copy_device_id(&info->class_code, cls, next_id_string); } /* Copy the fixed-length data */ info->info_size = info_size; info->type = type; info->name = name; info->param_count = param_count; info->valid = valid; *return_buffer = info; status = AE_OK; cleanup: if (hid) { ACPI_FREE(hid); } if (uid) { ACPI_FREE(uid); } if (sub) { ACPI_FREE(sub); } if (cid_list) { ACPI_FREE(cid_list); } if (cls) { ACPI_FREE(cls); } return (status); }