Beispiel #1
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_device_callback
 *
 * PARAMETERS:  Callback from acpi_get_device
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
 *              present devices, or if they specified a HID, it filters based
 *              on that.
 *
 ******************************************************************************/
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
			    u32 nesting_level,
			    void *context, void **return_value)
{
	struct acpi_get_devices_info *info = context;
	acpi_status status;
	struct acpi_namespace_node *node;
	u32 flags;
	struct acpi_pnp_device_id *hid;
	struct acpi_pnp_device_id_list *cid;
	u32 i;
	u8 found;
	int no_match;

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	node = acpi_ns_validate_handle(obj_handle);
	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	if (!node) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * First, filter based on the device HID and CID.
	 *
	 * 01/2010: For this case where a specific HID is requested, we don't
	 * want to run _STA until we have an actual HID match. Thus, we will
	 * not unnecessarily execute _STA on devices for which the caller
	 * doesn't care about. Previously, _STA was executed unconditionally
	 * on all devices found here.
	 *
	 * A side-effect of this change is that now we will continue to search
	 * for a matching HID even under device trees where the parent device
	 * would have returned a _STA that indicates it is not present or
	 * not functioning (thus aborting the search on that branch).
	 */
	if (info->hid != NULL) {
		status = acpi_ut_execute_HID(node, &hid);
		if (status == AE_NOT_FOUND) {
			return (AE_OK);
		} else if (ACPI_FAILURE(status)) {
			return (AE_CTRL_DEPTH);
		}

		no_match = ACPI_STRCMP(hid->string, info->hid);
		ACPI_FREE(hid);

		if (no_match) {
			/*
			 * HID does not match, attempt match within the
			 * list of Compatible IDs (CIDs)
			 */
			status = acpi_ut_execute_CID(node, &cid);
			if (status == AE_NOT_FOUND) {
				return (AE_OK);
			} else if (ACPI_FAILURE(status)) {
				return (AE_CTRL_DEPTH);
			}

			/* Walk the CID list */

			found = FALSE;
			for (i = 0; i < cid->count; i++) {
				if (ACPI_STRCMP(cid->ids[i].string, info->hid)
				    == 0) {

					/* Found a matching CID */

					found = TRUE;
					break;
				}
			}

			ACPI_FREE(cid);
			if (!found) {
				return (AE_OK);
			}
		}
	}

	/* Run _STA to determine if device is present */

	status = acpi_ut_execute_STA(node, &flags);
	if (ACPI_FAILURE(status)) {
		return (AE_CTRL_DEPTH);
	}

	if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
	    !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
		/*
		 * Don't examine the children of the device only when the
		 * device is neither present nor functional. See ACPI spec,
		 * description of _STA for more information.
		 */
		return (AE_CTRL_DEPTH);
	}

	/* We have a valid device, invoke the user function */

	status = info->user_function(obj_handle, nesting_level, info->context,
				     return_value);
	return (status);
}
Beispiel #2
0
/******************************************************************************
 *
 * 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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,
			u32 nesting_level, void *context, void **return_value)
{
	struct acpi_device_walk_info *walk_info =
	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
	struct acpi_evaluate_info *info = walk_info->evaluate_info;
	u32 flags;
	acpi_status status;
	struct acpi_namespace_node *device_node;

	ACPI_FUNCTION_TRACE(ns_init_one_device);

	/* We are interested in Devices, Processors and thermal_zones only */

	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	if ((device_node->type != ACPI_TYPE_DEVICE) &&
	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
	    (device_node->type != ACPI_TYPE_THERMAL)) {
		return_ACPI_STATUS(AE_OK);
	}

	/*
	 * Because of an earlier namespace analysis, all subtrees that contain an
	 * _INI method are tagged.
	 *
	 * If this device subtree does not contain any _INI methods, we
	 * can exit now and stop traversing this entire subtree.
	 */
	if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
		return_ACPI_STATUS(AE_CTRL_DEPTH);
	}

	/*
	 * Run _STA to determine if this device is present and functioning. We
	 * must know this information for two important reasons (from ACPI spec):
	 *
	 * 1) We can only run _INI if the device is present.
	 * 2) We must abort the device tree walk on this subtree if the device is
	 *    not present and is not functional (we will not examine the children)
	 *
	 * The _STA method is not required to be present under the device, we
	 * assume the device is present if _STA does not exist.
	 */
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));

	status = acpi_ut_execute_STA(device_node, &flags);
	if (ACPI_FAILURE(status)) {

		/* Ignore error and move on to next device */

		return_ACPI_STATUS(AE_OK);
	}

	/*
	 * Flags == -1 means that _STA was not found. In this case, we assume that
	 * the device is both present and functional.
	 *
	 * From the ACPI spec, description of _STA:
	 *
	 * "If a device object (including the processor object) does not have an
	 * _STA object, then OSPM assumes that all of the above bits are set (in
	 * other words, the device is present, ..., and functioning)"
	 */
	if (flags != ACPI_UINT32_MAX) {
		walk_info->num_STA++;
	}

	/*
	 * Examine the PRESENT and FUNCTIONING status bits
	 *
	 * Note: ACPI spec does not seem to specify behavior for the present but
	 * not functioning case, so we assume functioning if present.
	 */
	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {

		/* Device is not present, we must examine the Functioning bit */

		if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
			/*
			 * Device is not present but is "functioning". In this case,
			 * we will not run _INI, but we continue to examine the children
			 * of this device.
			 *
			 * From the ACPI spec, description of _STA: (note - no mention
			 * of whether to run _INI or not on the device in question)
			 *
			 * "_STA may return bit 0 clear (not present) with bit 3 set
			 * (device is functional). This case is used to indicate a valid
			 * device for which no device driver should be loaded (for example,
			 * a bridge device.) Children of this device may be present and
			 * valid. OSPM should continue enumeration below a device whose
			 * _STA returns this bit combination"
			 */
			return_ACPI_STATUS(AE_OK);
		} else {
			/*
			 * Device is not present and is not functioning. We must abort the
			 * walk of this subtree immediately -- don't look at the children
			 * of such a device.
			 *
			 * From the ACPI spec, description of _INI:
			 *
			 * "If the _STA method indicates that the device is not present,
			 * OSPM will not run the _INI and will not examine the children
			 * of the device for _INI methods"
			 */
			return_ACPI_STATUS(AE_CTRL_DEPTH);
		}
	}

	/*
	 * The device is present or is assumed present if no _STA exists.
	 * Run the _INI if it exists (not required to exist)
	 *
	 * Note: We know there is an _INI within this subtree, but it may not be
	 * under this particular device, it may be lower in the branch.
	 */
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));

	ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
	info->prefix_node = device_node;
	info->relative_pathname = METHOD_NAME__INI;
	info->parameters = NULL;
	info->flags = ACPI_IGNORE_RETURN_VALUE;

	status = acpi_ns_evaluate(info);

	if (ACPI_SUCCESS(status)) {
		walk_info->num_INI++;
	}
#ifdef ACPI_DEBUG_OUTPUT
	else if (status != AE_NOT_FOUND) {

		/* Ignore error and move on to next device */

		char *scope_name = acpi_ns_get_external_pathname(info->node);

		ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
				scope_name));
		ACPI_FREE(scope_name);
	}
#endif

	/* Ignore errors from above */

	status = AE_OK;

	/*
	 * The _INI method has been run if present; call the Global Initialization
	 * Handler for this device.
	 */
	if (acpi_gbl_init_handler) {
		status =
		    acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
	}

	return_ACPI_STATUS(status);
}
Beispiel #5
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_device_callback
 *
 * PARAMETERS:  Callback from acpi_get_device
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
 *              present devices, or if they specified a HID, it filters based
 *              on that.
 *
 ******************************************************************************/
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
			    u32 nesting_level,
			    void *context, void **return_value)
{
	struct acpi_get_devices_info *info = context;
	acpi_status status;
	struct acpi_namespace_node *node;
	u32 flags;
	struct acpica_device_id hid;
	struct acpi_compatible_id_list *cid;
	acpi_native_uint i;

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	node = acpi_ns_map_handle_to_node(obj_handle);
	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	if (!node) {
		return (AE_BAD_PARAMETER);
	}

	/* Run _STA to determine if device is present */

	status = acpi_ut_execute_STA(node, &flags);
	if (ACPI_FAILURE(status)) {
		return (AE_CTRL_DEPTH);
	}

	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {

		/* Don't examine children of the device if not present */

		return (AE_CTRL_DEPTH);
	}

	/* Filter based on device HID & CID */

	if (info->hid != NULL) {
		status = acpi_ut_execute_HID(node, &hid);
		if (status == AE_NOT_FOUND) {
			return (AE_OK);
		} else if (ACPI_FAILURE(status)) {
			return (AE_CTRL_DEPTH);
		}

		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);
			} else if (ACPI_FAILURE(status)) {
				return (AE_CTRL_DEPTH);
			}

			/* Walk the CID list */

			for (i = 0; i < cid->count; i++) {
				if (ACPI_STRNCMP(cid->id[i].value, info->hid,
						 sizeof(struct
							acpi_compatible_id)) !=
				    0) {
					ACPI_FREE(cid);
					return (AE_OK);
				}
			}
			ACPI_FREE(cid);
		}
	}

	status = info->user_function(obj_handle, nesting_level, info->context,
				     return_value);
	return (status);
}
Beispiel #6
0
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);
}
Beispiel #7
0
acpi_status
acpi_ns_init_one_device (
	acpi_handle             obj_handle,
	u32                     nesting_level,
	void                    *context,
	void                    **return_value)
{
	acpi_status             status;
	acpi_namespace_node    *node;
	u32                     flags;
	acpi_device_walk_info  *info = (acpi_device_walk_info *) context;


	FUNCTION_TRACE ("Ns_init_one_device");


	if (!(acpi_dbg_level & ACPI_LV_INIT)) {
		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
	}

	info->device_count++;

	acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);

	node = acpi_ns_map_handle_to_node (obj_handle);
	if (!node) {
		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		return (AE_BAD_PARAMETER);
	}

	acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);

	/*
	 * Run _STA to determine if we can run _INI on the device.
	 */
	DEBUG_EXEC (acpi_ut_display_init_pathname (node, "_STA [Method]"));
	status = acpi_ut_execute_STA (node, &flags);
	if (ACPI_FAILURE (status)) {
		/* Ignore error and move on to next device */

		return_ACPI_STATUS (AE_OK);
	}

	info->num_STA++;

	if (!(flags & 0x01)) {
		/* don't look at children of a not present device */

		return_ACPI_STATUS(AE_CTRL_DEPTH);
	}


	/*
	 * The device is present. Run _INI.
	 */
	DEBUG_EXEC (acpi_ut_display_init_pathname (obj_handle, "_INI [Method]"));
	status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
	if (AE_NOT_FOUND == status) {
		/* No _INI means device requires no initialization */

		status = AE_OK;
	}

	else if (ACPI_FAILURE (status)) {
		/* Ignore error and move on to next device */

#ifdef ACPI_DEBUG
		NATIVE_CHAR *scope_name = acpi_ns_get_table_pathname (obj_handle);

		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
				scope_name, acpi_format_exception (status)));

		ACPI_MEM_FREE (scope_name);
#endif
	}

	else {
		/* Count of successful INIs */

		info->num_INI++;
	}

	return_ACPI_STATUS (AE_OK);
}
static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,
			u32 nesting_level, void *context, void **return_value)
{
	struct acpi_device_walk_info *info =
	    (struct acpi_device_walk_info *)context;
	struct acpi_parameter_info pinfo;
	u32 flags;
	acpi_status status;

	ACPI_FUNCTION_TRACE("ns_init_one_device");

	pinfo.parameters = NULL;
	pinfo.parameter_type = ACPI_PARAM_ARGS;

	pinfo.node = acpi_ns_map_handle_to_node(obj_handle);
	if (!pinfo.node) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/*
	 * We will run _STA/_INI on Devices, Processors and thermal_zones only
	 */
	if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
	    (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
	    (pinfo.node->type != ACPI_TYPE_THERMAL)) {
		return_ACPI_STATUS(AE_OK);
	}

	if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
	    (!(acpi_dbg_level & ACPI_LV_INFO))) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
	}

	info->device_count++;

	/*
	 * Run _STA to determine if we can run _INI on the device.
	 */
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
						      pinfo.node,
						      METHOD_NAME__STA));
	status = acpi_ut_execute_STA(pinfo.node, &flags);

	if (ACPI_FAILURE(status)) {
		if (pinfo.node->type == ACPI_TYPE_DEVICE) {
			/* Ignore error and move on to next device */

			return_ACPI_STATUS(AE_OK);
		}

		/* _STA is not required for Processor or thermal_zone objects */
	} else {
		info->num_STA++;

		if (!(flags & 0x01)) {
			/* Don't look at children of a not present device */

			return_ACPI_STATUS(AE_CTRL_DEPTH);
		}
	}

	/*
	 * The device is present. Run _INI.
	 */
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
						      pinfo.node,
						      METHOD_NAME__INI));
	status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
	if (ACPI_FAILURE(status)) {
		/* No _INI (AE_NOT_FOUND) means device requires no initialization */

		if (status != AE_NOT_FOUND) {
			/* Ignore error and move on to next device */

#ifdef ACPI_DEBUG_OUTPUT
			char *scope_name =
			    acpi_ns_get_external_pathname(pinfo.node);

			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "%s._INI failed: %s\n",
					  scope_name,
					  acpi_format_exception(status)));

			ACPI_MEM_FREE(scope_name);
#endif
		}

		status = AE_OK;
	} else {
		/* Delete any return object (especially if implicit_return is enabled) */

		if (pinfo.return_object) {
			acpi_ut_remove_reference(pinfo.return_object);
		}

		/* Count of successful INIs */

		info->num_INI++;
	}

	if (acpi_gbl_init_handler) {
		/* External initialization handler is present, call it */

		status =
		    acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
	}

	return_ACPI_STATUS(status);
}
static acpi_status
acpi_ns_init_one_device(acpi_handle obj_handle,
			u32 nesting_level, void *context, void **return_value)
{
	struct acpi_device_walk_info *walk_info =
	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
	struct acpi_evaluate_info *info = walk_info->evaluate_info;
	u32 flags;
	acpi_status status;
	struct acpi_namespace_node *device_node;

	ACPI_FUNCTION_TRACE(ns_init_one_device);

	

	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	if ((device_node->type != ACPI_TYPE_DEVICE) &&
	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
	    (device_node->type != ACPI_TYPE_THERMAL)) {
		return_ACPI_STATUS(AE_OK);
	}

	if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
		return_ACPI_STATUS(AE_CTRL_DEPTH);
	}

	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));

	status = acpi_ut_execute_STA(device_node, &flags);
	if (ACPI_FAILURE(status)) {

		

		return_ACPI_STATUS(AE_OK);
	}

	if (flags != ACPI_UINT32_MAX) {
		walk_info->num_STA++;
	}

	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {

		

		if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
			return_ACPI_STATUS(AE_OK);
		} else {
			return_ACPI_STATUS(AE_CTRL_DEPTH);
		}
	}

	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));

	info->prefix_node = device_node;
	info->pathname = METHOD_NAME__INI;
	info->parameters = NULL;
	info->flags = ACPI_IGNORE_RETURN_VALUE;

	status = acpi_ns_evaluate(info);

	if (ACPI_SUCCESS(status)) {
		walk_info->num_INI++;

		if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
		    (!(acpi_dbg_level & ACPI_LV_INFO))) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
		}
	}
#ifdef ACPI_DEBUG_OUTPUT
	else if (status != AE_NOT_FOUND) {

		

		char *scope_name =
		    acpi_ns_get_external_pathname(info->resolved_node);

		ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
				scope_name));
		ACPI_FREE(scope_name);
	}
#endif

	

	status = AE_OK;

	if (acpi_gbl_init_handler) {
		status =
		    acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
	}

	return_ACPI_STATUS(status);
}