Commit ce7d8354 authored by Andy Grover's avatar Andy Grover

ACPI: update to 20030522

Found and fixed a reported problem where an AE_NOT_FOUND error occurred occasionally
during _BST evaluation.  This turned out to be an Owner ID allocation issue where a
called method did not get a new ID assigned to it.  Eventually, (after 64k calls), the
Owner ID UINT16 would wraparound so that the ID would be the same as the caller's and the
called method would delete the caller's namespace.

Implemented extended error reporting for control methods that are aborted due to a
run-time exception.  Output includes the exact AML instruction that caused the method
abort, a dump of the method locals and arguments at the time of the abort, and a trace of
all nested control method calls.

Modified the interpreter to allow the creation of buffers of zero length from the AML
code. Implemented new code to ensure that no attempt is made to actually allocate a
memory buffer (of length zero), only a buffer object with a NULL buffer pointer and
length zero.  A warning is no longer issued when the AML attempts to create a zero-length
buffer.

Implemented a workaround for the "leading asterisk problem" in _HIDs, _UIDs, and _CIDs.
One leading asterisk is automatically removed if present in all HID, UID, and CID
strings.

Implemented full support for _CID methods that return a package of multiple CIDs.  The
AcpiGetObjectInfo interface now returns a device _HID, _UID, and _CID list if present.
This required a change to the external interface to pass an ACPI_BUFFER object as a
parameter, since the _CID list is of variable length.

Fixed a problem with the new AE_SAME_HANDLER exception where handler initialization code
did not know about this exception.
parent 17d0e4f4
......@@ -290,6 +290,8 @@ acpi_ds_call_control_method (
return_ACPI_STATUS (AE_NULL_OBJECT);
}
obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
/* Init for new method, wait on concurrency semaphore */
status = acpi_ds_begin_method_execution (method_node, obj_desc,
......
......@@ -204,7 +204,8 @@ acpi_ds_build_internal_buffer_obj (
if (obj_desc->buffer.length == 0) {
obj_desc->buffer.pointer = NULL;
ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
"Buffer defined with zero length in AML, creating\n"));
}
else {
obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
......
......@@ -50,6 +50,7 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acdebug.h>
#include <acpi/acdisasm.h>
#define _COMPONENT ACPI_DISPATCHER
......@@ -657,6 +658,16 @@ acpi_ds_exec_end_op (
/* Always clear the object stack */
walk_state->num_operands = 0;
#ifdef ACPI_DISASSEMBLER
/* On error, display method locals/args */
if (ACPI_FAILURE (status)) {
acpi_dm_dump_method_info (status, walk_state, op);
}
#endif
return_ACPI_STATUS (status);
}
......
......@@ -732,18 +732,16 @@ acpi_ev_create_gpe_block (
/* Dump info about this GPE block */
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: [%4.4s] %X registers at %8.8X%8.8X on interrupt %d\n",
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
gpe_block->block_base_number,
(u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
gpe_device->name.ascii,
gpe_block->register_count,
ACPI_HIDWORD (gpe_block->block_address.address),
ACPI_LODWORD (gpe_block->block_address.address),
interrupt_level));
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n",
gpe_block->block_base_number,
(u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1))));
/* Find all GPE methods (_Lxx, _Exx) for this block */
status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
......
......@@ -50,24 +50,32 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME ("evregion")
#define ACPI_NUM_DEFAULT_SPACES 4
u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
ACPI_ADR_SPACE_SYSTEM_MEMORY,
ACPI_ADR_SPACE_SYSTEM_IO,
ACPI_ADR_SPACE_PCI_CONFIG,
ACPI_ADR_SPACE_DATA_TABLE};
/*******************************************************************************
*
* FUNCTION: acpi_ev_init_address_spaces
*
* PARAMETERS:
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Installs the core subsystem address space handlers.
* DESCRIPTION: Installs the core subsystem default address space handlers.
*
******************************************************************************/
acpi_status
acpi_ev_init_address_spaces (
void)
{
void) {
acpi_status status;
acpi_native_uint i;
ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
......@@ -75,9 +83,11 @@ acpi_ev_init_address_spaces (
/*
* All address spaces (PCI Config, EC, SMBus) are scope dependent
* and registration must occur for a specific device. In the case
* system memory and IO address spaces there is currently no device
* associated with the address space. For these we use the root.
* and registration must occur for a specific device.
*
* In the case of the system memory and IO address spaces there is currently
* no device associated with the address space. For these we use the root.
*
* We install the default PCI config space handler at the root so
* that this space is immediately available even though the we have
* not enumerated all the PCI Root Buses yet. This is to conform
......@@ -86,39 +96,27 @@ acpi_ev_init_address_spaces (
* near ready to find the PCI root buses at this point.
*
* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
* has already been installed (via acpi_install_address_space_handler)
* has already been installed (via acpi_install_address_space_handler).
* Similar for AE_SAME_HANDLER.
*/
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
ACPI_ADR_SPACE_SYSTEM_MEMORY,
ACPI_DEFAULT_HANDLER, NULL, NULL);
if ((ACPI_FAILURE (status)) &&
(status != AE_ALREADY_EXISTS)) {
return_ACPI_STATUS (status);
}
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
acpi_gbl_default_address_spaces[i],
ACPI_DEFAULT_HANDLER, NULL, NULL);
switch (status) {
case AE_OK:
case AE_SAME_HANDLER:
case AE_ALREADY_EXISTS:
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
ACPI_ADR_SPACE_SYSTEM_IO,
ACPI_DEFAULT_HANDLER, NULL, NULL);
if ((ACPI_FAILURE (status)) &&
(status != AE_ALREADY_EXISTS)) {
return_ACPI_STATUS (status);
}
/* These exceptions are all OK */
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
ACPI_ADR_SPACE_PCI_CONFIG,
ACPI_DEFAULT_HANDLER, NULL, NULL);
if ((ACPI_FAILURE (status)) &&
(status != AE_ALREADY_EXISTS)) {
return_ACPI_STATUS (status);
}
break;
default:
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
ACPI_ADR_SPACE_DATA_TABLE,
ACPI_DEFAULT_HANDLER, NULL, NULL);
if ((ACPI_FAILURE (status)) &&
(status != AE_ALREADY_EXISTS)) {
return_ACPI_STATUS (status);
return_ACPI_STATUS (status);
}
}
return_ACPI_STATUS (AE_OK);
......
......@@ -220,7 +220,7 @@ acpi_ev_pci_config_region_setup (
if (ACPI_SUCCESS (status)) {
/* Got a valid _HID, check if this is a PCI root */
if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING,
if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING,
sizeof (PCI_ROOT_HID_STRING)))) {
/* Install a handler for this PCI root bridge */
......
......@@ -72,7 +72,8 @@ acpi_ns_dump_one_device (
void *context,
void **return_value)
{
struct acpi_device_info info;
struct acpi_buffer buffer;
struct acpi_device_info *info;
acpi_status status;
u32 i;
......@@ -82,16 +83,19 @@ acpi_ns_dump_one_device (
status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
status = acpi_get_object_info (obj_handle, &info);
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_get_object_info (obj_handle, &buffer);
if (ACPI_SUCCESS (status)) {
info = buffer.pointer;
for (i = 0; i < level; i++) {
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
info.hardware_id,
ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address),
info.current_status));
info->hardware_id.value,
ACPI_HIDWORD (info->address), ACPI_LODWORD (info->address),
info->current_status));
ACPI_MEM_FREE (info);
}
return (status);
......
......@@ -117,8 +117,9 @@ acpi_ns_search_node (
* Found matching entry.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
"Name %4.4s Type [%s] found at %p\n",
(char *) &target_name, acpi_ut_get_type_name (next_node->type), next_node));
"Name %4.4s Type [%s] found in scope [%4.4s] %p\n",
(char *) &target_name, acpi_ut_get_type_name (next_node->type),
next_node->name.ascii, next_node));
*return_node = next_node;
return_ACPI_STATUS (AE_OK);
......@@ -141,8 +142,10 @@ acpi_ns_search_node (
/* Searched entire namespace level, not found */
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s Type [%s] not found at %p\n",
(char *) &target_name, acpi_ut_get_type_name (type), next_node));
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
"Name %4.4s Type [%s] not found in search in scope [%4.4s] %p first child %p\n",
(char *) &target_name, acpi_ut_get_type_name (type),
node->name.ascii, node, node->child));
return_ACPI_STATUS (AE_NOT_FOUND);
}
......
......@@ -181,7 +181,11 @@ acpi_ns_print_node_pathname (
status = acpi_ns_handle_to_pathname (node, &buffer);
if (ACPI_SUCCESS (status)) {
acpi_os_printf ("%s [%s] (Node %p)", msg, (char *) buffer.pointer, node);
if (msg) {
acpi_os_printf ("%s ", msg);
}
acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node);
ACPI_MEM_FREE (buffer.pointer);
}
}
......
......@@ -437,16 +437,15 @@ acpi_ns_get_device_callback (
void *context,
void **return_value)
{
struct acpi_get_devices_info *info = context;
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
struct acpi_device_id hid;
struct acpi_device_id cid;
struct acpi_get_devices_info *info;
struct acpi_compatible_id_list *cid;
acpi_native_uint i;
info = context;
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return (status);
......@@ -462,9 +461,8 @@ acpi_ns_get_device_callback (
return (AE_BAD_PARAMETER);
}
/*
* Run _STA to determine if device is present
*/
/* Run _STA to determine if device is present */
status = acpi_ut_execute_STA (node, &flags);
if (ACPI_FAILURE (status)) {
return (AE_CTRL_DEPTH);
......@@ -472,12 +470,12 @@ acpi_ns_get_device_callback (
if (!(flags & 0x01)) {
/* Don't return at the device or children of the device if not there */
return (AE_CTRL_DEPTH);
}
/*
* Filter based on device HID & CID
*/
/* Filter based on device HID & CID */
if (info->hid != NULL) {
status = acpi_ut_execute_HID (node, &hid);
if (status == AE_NOT_FOUND) {
......@@ -487,7 +485,9 @@ acpi_ns_get_device_callback (
return (AE_CTRL_DEPTH);
}
if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) {
if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) {
/* Get the list of Compatible IDs */
status = acpi_ut_execute_CID (node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
......@@ -496,11 +496,16 @@ acpi_ns_get_device_callback (
return (AE_CTRL_DEPTH);
}
/* TBD: Handle CID packages */
/* Walk the CID list */
if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) {
return (AE_OK);
for (i = 0; i < cid->count; i++) {
if (ACPI_STRNCMP (cid->id[i].value, info->hid,
sizeof (struct acpi_compatible_id)) != 0) {
ACPI_MEM_FREE (cid);
return (AE_OK);
}
}
ACPI_MEM_FREE (cid);
}
}
......
......@@ -51,7 +51,7 @@
ACPI_MODULE_NAME ("nsxfname")
/****************************************************************************
/******************************************************************************
*
* FUNCTION: acpi_get_handle
*
......@@ -119,7 +119,8 @@ acpi_get_handle (
/*
* Find the Node and convert to a handle
*/
status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, &node);
status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
&node);
*ret_handle = NULL;
if (ACPI_SUCCESS (status)) {
......@@ -130,7 +131,7 @@ acpi_get_handle (
}
/****************************************************************************
/******************************************************************************
*
* FUNCTION: acpi_get_name
*
......@@ -211,7 +212,7 @@ acpi_get_name (
}
/****************************************************************************
/******************************************************************************
*
* FUNCTION: acpi_get_object_info
*
......@@ -229,22 +230,27 @@ acpi_get_name (
acpi_status
acpi_get_object_info (
acpi_handle handle,
struct acpi_device_info *info)
struct acpi_buffer *buffer)
{
struct acpi_device_id hid;
struct acpi_device_id uid;
acpi_status status;
u32 device_status = 0;
acpi_integer address = 0;
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 || !info) {
if (!handle || !buffer) {
return (AE_BAD_PARAMETER);
}
status = acpi_ut_validate_buffer (buffer);
if (ACPI_FAILURE (status)) {
return (status);
}
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return (status);
......@@ -256,69 +262,94 @@ acpi_get_object_info (
return (AE_BAD_PARAMETER);
}
info->type = node->type;
info->name = node->name.integer;
/* Init return structure */
size = sizeof (struct acpi_device_info);
ACPI_MEMSET (&info, 0, size);
info.type = node->type;
info.name = node->name.integer;
info.valid = 0;
status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return (status);
}
/*
* If not a device, we are all done.
*/
if (info->type != ACPI_TYPE_DEVICE) {
return (AE_OK);
}
/* 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, and _ADR 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.
*/
/*
* 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 Device._HID method */
/* Execute the _HID method and save the result */
status = acpi_ut_execute_HID (node, &info.hardware_id);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_HID;
}
status = acpi_ut_execute_HID (node, &hid);
if (ACPI_SUCCESS (status)) {
ACPI_STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id));
info->valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
/* Execute the _UID method and save the result */
status = acpi_ut_execute_UID (node, &info.unique_id);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_UID;
}
status = acpi_ut_execute_UID (node, &uid);
if (ACPI_SUCCESS (status)) {
ACPI_STRCPY (info->unique_id, uid.buffer);
info->valid |= ACPI_VALID_UID;
/* Execute the Device._CID method */
status = acpi_ut_execute_CID (node, &cid_list);
if (ACPI_SUCCESS (status)) {
size += ((acpi_size) cid_list->count - 1) *
sizeof (struct acpi_compatible_id);
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;
}
status = AE_OK;
}
/*
* 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;
/* Validate/Allocate/Clear caller buffer */
status = acpi_ut_initialize_buffer (buffer, size);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
/*
* 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);
/* Populate the return buffer */
if (ACPI_SUCCESS (status)) {
info->address = address;
info->valid |= ACPI_VALID_ADR;
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);
}
return (AE_OK);
cleanup:
if (cid_list) {
ACPI_MEM_FREE (cid_list);
}
return (status);
}
......@@ -350,6 +350,11 @@ acpi_ps_get_next_namepath (
(status != AE_NOT_FOUND)) {
ACPI_REPORT_NSERROR (path, status);
acpi_os_printf ("search_node %p start_node %p return_node %p\n",
scope_info.scope.node, parser_state->start_node, node);
}
else {
/*
......
......@@ -651,13 +651,21 @@ acpi_ut_copy_simple_object (
*/
if ((source_desc->buffer.pointer) &&
(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
dest_desc->buffer.pointer = NULL;
/* Create an actual buffer only if length > 0 */
ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer,
source_desc->buffer.length);
if (source_desc->buffer.length) {
dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
/* Copy the actual buffer data */
ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer,
source_desc->buffer.length);
}
}
break;
......
......@@ -208,6 +208,46 @@ acpi_ut_evaluate_numeric_object (
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
*
* PARAMETERS: Destination - Where to copy the string
* Source - Source string
* max_length - Length of the destination buffer
*
* RETURN: None
*
* DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
* Performs removal of a leading asterisk if present -- workaround
* for a known issue on a bunch of machines.
*
******************************************************************************/
static void
acpi_ut_copy_id_string (
char *destination,
char *source,
acpi_size max_length)
{
/*
* Workaround for ID strings that have a leading asterisk. This construct
* is not allowed by the ACPI specification (ID strings must be
* alphanumeric), but enough existing machines have this embedded in their
* ID strings that the following code is useful.
*/
if (*source == '*') {
source++;
}
/* Do the actual copy */
ACPI_STRNCPY (destination, source, max_length);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
......@@ -245,12 +285,13 @@ acpi_ut_execute_HID (
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
/* Convert the Numeric HID to string */
acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer);
acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value);
}
else {
/* Copy the String HID from the returned object */
ACPI_STRNCPY (hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer));
acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer,
sizeof (hid->value));
}
/* On exit, we must delete the return object */
......@@ -260,6 +301,57 @@ acpi_ut_execute_HID (
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_translate_one_cid
*
* PARAMETERS: obj_desc - _CID object, must be integer or string
* one_cid - Where the CID string is returned
*
* RETURN: Status
*
* DESCRIPTION: Return a numeric or string _CID value as a string.
* (Compatible ID)
*
* NOTE: Assumes a maximum _CID string length of
* ACPI_MAX_CID_LENGTH.
*
******************************************************************************/
static acpi_status
acpi_ut_translate_one_cid (
union acpi_operand_object *obj_desc,
struct acpi_compatible_id *one_cid)
{
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
case ACPI_TYPE_INTEGER:
/* Convert the Numeric CID to string */
acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value);
return (AE_OK);
case ACPI_TYPE_STRING:
if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) {
return (AE_AML_STRING_LIMIT);
}
/* Copy the String CID from the returned object */
acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer,
ACPI_MAX_CID_LENGTH);
return (AE_OK);
default:
return (AE_TYPE);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
......@@ -279,55 +371,86 @@ acpi_ut_execute_HID (
acpi_status
acpi_ut_execute_CID (
struct acpi_namespace_node *device_node,
struct acpi_device_id *cid)
struct acpi_compatible_id_list **return_cid_list)
{
union acpi_operand_object *obj_desc;
acpi_status status;
u32 count;
u32 size;
struct acpi_compatible_id_list *cid_list;
acpi_native_uint i;
ACPI_FUNCTION_TRACE ("ut_execute_CID");
/* Evaluate the _CID method for this device */
status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, &obj_desc);
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
&obj_desc);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/*
* A _CID can return either a single compatible ID or a package of compatible
* IDs. Each compatible ID can be a Number (32 bit compressed EISA ID) or
* string (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss").
*/
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
case ACPI_TYPE_INTEGER:
/* Get the number of _CIDs returned */
/* Convert the Numeric CID to string */
count = 1;
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
}
acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, cid->buffer);
break;
/* Allocate a worst-case buffer for the _CIDs */
case ACPI_TYPE_STRING:
size = (((count - 1) * sizeof (struct acpi_compatible_id)) +
sizeof (struct acpi_compatible_id_list));
/* Copy the String CID from the returned object */
cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size);
if (!cid_list) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
ACPI_STRNCPY (cid->buffer, obj_desc->string.pointer, sizeof (cid->buffer));
break;
/* Init CID list */
case ACPI_TYPE_PACKAGE:
cid_list->count = count;
cid_list->size = size;
/* TBD: Parse package elements; need different return struct, etc. */
/*
* A _CID can return either a single compatible ID or a package of compatible
* IDs. Each compatible ID can be one of the following:
* -- Number (32 bit compressed EISA ID) or
* -- String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss").
*/
status = AE_SUPPORT;
break;
/* The _CID object can be either a single CID or a package (list) of CIDs */
default:
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) {
/* Translate each package element */
status = AE_TYPE;
break;
for (i = 0; i < count; i++) {
status = acpi_ut_translate_one_cid (obj_desc->package.elements[i],
&cid_list->id[i]);
if (ACPI_FAILURE (status)) {
break;
}
}
}
else {
/* Only one CID, translate to a string */
/* On exit, we must delete the return object */
status = acpi_ut_translate_one_cid (obj_desc, cid_list->id);
}
/* Cleanup on error */
if (ACPI_FAILURE (status)) {
ACPI_MEM_FREE (cid_list);
}
else {
*return_cid_list = cid_list;
}
/* On exit, we must delete the _CID return object */
acpi_ut_remove_reference (obj_desc);
return_ACPI_STATUS (status);
......@@ -371,12 +494,13 @@ acpi_ut_execute_UID (
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
/* Convert the Numeric UID to string */
acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer);
acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value);
}
else {
/* Copy the String UID from the returned object */
ACPI_STRNCPY (uid->buffer, obj_desc->string.pointer, sizeof (uid->buffer));
acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer,
sizeof (uid->value));
}
/* On exit, we must delete the return object */
......
......@@ -149,7 +149,7 @@ acpi_ut_create_buffer_object (
acpi_size buffer_size)
{
union acpi_operand_object *buffer_desc;
u8 *buffer;
u8 *buffer = NULL;
ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size);
......@@ -163,14 +163,18 @@ acpi_ut_create_buffer_object (
return_PTR (NULL);
}
/* Allocate the actual buffer */
/* Create an actual buffer only if size > 0 */
buffer = ACPI_MEM_CALLOCATE (buffer_size);
if (!buffer) {
ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n",
(u32) buffer_size));
acpi_ut_remove_reference (buffer_desc);
return_PTR (NULL);
if (buffer_size > 0) {
/* Allocate the actual buffer */
buffer = ACPI_MEM_CALLOCATE (buffer_size);
if (!buffer) {
ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n",
(u32) buffer_size));
acpi_ut_remove_reference (buffer_desc);
return_PTR (NULL);
}
}
/* Complete buffer object initialization */
......
......@@ -64,7 +64,7 @@
/* Version string */
#define ACPI_CA_VERSION 0x20030509
#define ACPI_CA_VERSION 0x20030522
/* Maximum objects in the various object caches */
......@@ -133,6 +133,11 @@
#define ACPI_MAX_STRING_CONVERSION 200
/* Length of _HID, _UID, and _CID values */
#define ACPI_DEVICE_ID_LENGTH 0x09
#define ACPI_MAX_CID_LENGTH 48
/*
* Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG
*/
......
......@@ -229,10 +229,6 @@ acpi_db_decode_and_display_object (
char *target,
char *output_type);
void
acpi_db_decode_node (
struct acpi_namespace_node *node);
void
acpi_db_display_result_object (
union acpi_operand_object *obj_desc,
......@@ -242,11 +238,6 @@ acpi_status
acpi_db_display_all_methods (
char *display_count_arg);
void
acpi_db_display_internal_object (
union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void
acpi_db_display_arguments (
void);
......@@ -263,6 +254,10 @@ void
acpi_db_display_calling_tree (
void);
void
acpi_db_display_object_type (
char *object_arg);
void
acpi_db_display_argument_object (
union acpi_operand_object *obj_desc,
......@@ -276,10 +271,6 @@ void *
acpi_db_get_pointer (
void *target);
void
acpi_db_decode_internal_object (
union acpi_operand_object *obj_desc);
/*
* dbexec - debugger control method execution
......
This diff is collapsed.
......@@ -856,16 +856,6 @@ struct acpi_bit_register_info
#define ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE 0x8A
/* String version of device HIDs and UIDs */
#define ACPI_DEVICE_ID_LENGTH 0x09
struct acpi_device_id
{
char buffer[ACPI_DEVICE_ID_LENGTH];
};
/*****************************************************************************
*
* Miscellaneous
......
......@@ -228,8 +228,8 @@ acpi_evaluate_object_typed (
acpi_status
acpi_get_object_info (
acpi_handle device,
struct acpi_device_info *info);
acpi_handle handle,
struct acpi_buffer *return_buffer);
acpi_status
acpi_get_next_object (
......
......@@ -832,12 +832,35 @@ acpi_status (*acpi_walk_callback) (
#define ACPI_INTERRUPT_HANDLED 0x01
/* Structure and flags for acpi_get_device_info */
/* Common string version of device HIDs and UIDs */
#define ACPI_VALID_HID 0x1
#define ACPI_VALID_UID 0x2
#define ACPI_VALID_ADR 0x4
#define ACPI_VALID_STA 0x8
struct acpi_device_id
{
char value[ACPI_DEVICE_ID_LENGTH];
};
/* Common string version of device CIDs */
struct acpi_compatible_id
{
char value[ACPI_MAX_CID_LENGTH];
};
struct acpi_compatible_id_list
{
u32 count;
u32 size;
struct acpi_compatible_id id[1];
};
/* Structure and flags for acpi_get_object_info */
#define ACPI_VALID_STA 0x0001
#define ACPI_VALID_ADR 0x0002
#define ACPI_VALID_HID 0x0004
#define ACPI_VALID_UID 0x0008
#define ACPI_VALID_CID 0x0010
#define ACPI_COMMON_OBJ_INFO \
......@@ -851,15 +874,18 @@ struct acpi_obj_info_header
};
/* Structure returned from Get Object Info */
struct acpi_device_info
{
ACPI_COMMON_OBJ_INFO;
u32 valid; /* Are the next bits legit? */
char hardware_id[9]; /* _HID value if any */
char unique_id[9]; /* _UID value if any */
acpi_integer address; /* _ADR value if any */
u32 current_status; /* _STA value */
u32 valid; /* Indicates which fields are valid */
u32 current_status; /* _STA value */
acpi_integer address; /* _ADR value if any */
struct acpi_device_id hardware_id; /* _HID value if any */
struct acpi_device_id unique_id; /* _UID value if any */
struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */
};
......
......@@ -488,7 +488,7 @@ acpi_ut_execute_HID (
acpi_status
acpi_ut_execute_CID (
struct acpi_namespace_node *device_node,
struct acpi_device_id *cid);
struct acpi_compatible_id_list **return_cid_list);
acpi_status
acpi_ut_execute_STA (
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment