Пример #1
0
void
acpi_ns_report_method_error(char *module_name,
                            u32 line_number,
                            char *message,
                            struct acpi_namespace_node *prefix_node,
                            char *path, acpi_status method_status)
{
    acpi_status status;
    struct acpi_namespace_node *node = prefix_node;

    acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);

    if (path) {
        status =
            acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
                             &node);
        if (ACPI_FAILURE(status)) {
            acpi_os_printf("[Could not get node by pathname]");
        }
    }

    acpi_ns_print_node_pathname(node, message);
    acpi_os_printf(", %s\n", acpi_format_exception(method_status));
}
Пример #2
0
/**
 * radeon_atpx_call - call an ATPX method
 *
 * @handle: acpi handle
 * @function: the ATPX function to execute
 * @params: ATPX function params
 *
 * Executes the requested ATPX function (all asics).
 * Returns a pointer to the acpi output buffer.
 */
static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
            struct acpi_buffer *params)
{
    acpi_status status;
    union acpi_object atpx_arg_elements[2];
    struct acpi_object_list atpx_arg;
    struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

    atpx_arg.count = 2;
    atpx_arg.pointer = &atpx_arg_elements[0];

    atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
    atpx_arg_elements[0].integer.value = function;

    if (params) {
        atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
        atpx_arg_elements[1].buffer.length = params->length;
        atpx_arg_elements[1].buffer.pointer = params->pointer;
    } else {
        /* We need a second fake parameter */
        atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
        atpx_arg_elements[1].integer.value = 0;
    }

    status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);

    /* Fail only if calling the method fails and ATPX is supported */
    if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
        printk("failed to evaluate ATPX got %s\n",
               acpi_format_exception(status));
        kfree(buffer.pointer);
        return NULL;
    }

    return buffer.pointer;
}
Пример #3
0
Файл: acpi.c Проект: 01org/prd
void __init acpi_gic_init(void)
{
	struct acpi_table_header *table;
	acpi_status status;
	acpi_size tbl_size;
	int err;

	if (acpi_disabled)
		return;

	status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
	if (ACPI_FAILURE(status)) {
		const char *msg = acpi_format_exception(status);

		pr_err("Failed to get MADT table, %s\n", msg);
		return;
	}

	err = gic_v2_acpi_init(table);
	if (err)
		pr_err("Failed to initialize GIC IRQ controller");

	early_acpi_os_unmap_memory((char *)table, tbl_size);
}
Пример #4
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_exception
 *
 * PARAMETERS:  module_name         - Caller's module name (for error output)
 *              line_number         - Caller's line number (for error output)
 *              status              - Status to be formatted
 *              format              - Printf format string + additional args
 *
 * RETURN:      None
 *
 * DESCRIPTION: Print "ACPI Exception" message with module/line/version info
 *              and decoded acpi_status.
 *
 ******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_exception(const char *module_name,
	       u32 line_number, acpi_status status, const char *format, ...)
{
	va_list arg_list;

	ACPI_MSG_REDIRECT_BEGIN;

	/* For AE_OK, just print the message */

	if (ACPI_SUCCESS(status)) {
		acpi_os_printf(ACPI_MSG_EXCEPTION);

	} else {
		acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
			       acpi_format_exception(status));
	}
	va_start(arg_list, format);
	acpi_os_vprintf(format, arg_list);
	ACPI_MSG_SUFFIX;
	va_end(arg_list);

	ACPI_MSG_REDIRECT_END;
}
Пример #5
0
void __init acpi_hest_init(void)
{
	acpi_status status;
	int rc = -ENODEV;
	unsigned int ghes_count = 0;

	if (hest_disable) {
		pr_info(HEST_PFX "Table parsing disabled.\n");
		return;
	}

	status = acpi_get_table(ACPI_SIG_HEST, 0,
				(struct acpi_table_header **)&hest_tab);
	if (status == AE_NOT_FOUND)
		goto err;
	else if (ACPI_FAILURE(status)) {
		const char *msg = acpi_format_exception(status);
		pr_err(HEST_PFX "Failed to get table, %s\n", msg);
		rc = -EINVAL;
		goto err;
	}

	if (!ghes_disable) {
		rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
		if (rc)
			goto err;
		rc = hest_ghes_dev_register(ghes_count);
		if (rc)
			goto err;
	}

	pr_info(HEST_PFX "Table parsing has been initialized.\n");
	return;
err:
	hest_disable = 1;
}
Пример #6
0
static acpi_status
acpi_ds_init_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	struct acpi_init_walk_info *info =
	    (struct acpi_init_walk_info *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	acpi_object_type type;
	acpi_status status;

	ACPI_FUNCTION_NAME("ds_init_one_object");

	/*
	 * We are only interested in NS nodes owned by the table that
	 * was just loaded
	 */
	if (node->owner_id != info->table_desc->owner_id) {
		return (AE_OK);
	}

	info->object_count++;

	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type(obj_handle);

	switch (type) {
	case ACPI_TYPE_REGION:

		status = acpi_ds_initialize_region(obj_handle);
		if (ACPI_FAILURE(status)) {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
					  "Region %p [%4.4s] - Init failure, %s\n",
					  obj_handle,
					  acpi_ut_get_node_name(obj_handle),
					  acpi_format_exception(status)));
		}

		info->op_region_count++;
		break;

	case ACPI_TYPE_METHOD:

		/*
		 * Print a dot for each method unless we are going to print
		 * the entire pathname
		 */
		if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
		}

		/*
		 * Set the execution data width (32 or 64) based upon the
		 * revision number of the parent ACPI table.
		 * TBD: This is really for possible future support of integer width
		 * on a per-table basis. Currently, we just use a global for the width.
		 */
		if (info->table_desc->pointer->revision == 1) {
			node->flags |= ANOBJ_DATA_WIDTH_32;
		}

		/*
		 * Always parse methods to detect errors, we will delete
		 * the parse tree below
		 */
		status = acpi_ds_parse_method(obj_handle);
		if (ACPI_FAILURE(status)) {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
					  "\n+Method %p [%4.4s] - parse failure, %s\n",
					  obj_handle,
					  acpi_ut_get_node_name(obj_handle),
					  acpi_format_exception(status)));

			/* This parse failed, but we will continue parsing more methods */
		}

		info->method_count++;
		break;

	case ACPI_TYPE_DEVICE:

		info->device_count++;
		break;

	default:
		break;
	}

	/*
	 * We ignore errors from above, and always return OK, since
	 * we don't want to abort the walk on a single error.
	 */
	return (AE_OK);
}
Пример #7
0
/*
 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
 * improvise.  The process is to sleep for one scheduler quantum
 * until the semaphore becomes available.  Downside is that this
 * may result in starvation for timeout-based waits when there's
 * lots of semaphore activity.
 *
 * TODO: Support for units > 1?
 */
acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
{
	acpi_status status = AE_OK;
	struct semaphore *sem = (struct semaphore *)handle;
	int ret = 0;


	if (!sem || (units < 1))
		return AE_BAD_PARAMETER;

	if (units > 1)
		return AE_SUPPORT;

	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
			  handle, units, timeout));

	/*
	 * This can be called during resume with interrupts off.
	 * Like boot-time, we should be single threaded and will
	 * always get the lock if we try -- timeout or not.
	 * If this doesn't succeed, then we will oops courtesy of
	 * might_sleep() in down().
	 */
	if (!down_trylock(sem))
		return AE_OK;

	switch (timeout) {
		/*
		 * No Wait:
		 * --------
		 * A zero timeout value indicates that we shouldn't wait - just
		 * acquire the semaphore if available otherwise return AE_TIME
		 * (a.k.a. 'would block').
		 */
	case 0:
		if (down_trylock(sem))
			status = AE_TIME;
		break;

		/*
		 * Wait Indefinitely:
		 * ------------------
		 */
	case ACPI_WAIT_FOREVER:
		down(sem);
		break;

		/*
		 * Wait w/ Timeout:
		 * ----------------
		 */
	default:
		// TODO: A better timeout algorithm?
		{
			int i = 0;
			static const int quantum_ms = 1000 / HZ;

			ret = down_trylock(sem);
			for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) {
				schedule_timeout_interruptible(1);
				ret = down_trylock(sem);
			}

			if (ret != 0)
				status = AE_TIME;
		}
		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
				  "Failed to acquire semaphore[%p|%d|%d], %s",
				  handle, units, timeout,
				  acpi_format_exception(status)));
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
				  "Acquired semaphore[%p|%d|%d]", handle,
				  units, timeout));
	}

	return status;
}
Пример #8
0
static acpi_status
acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle,
				     u32 nesting_level,
				     void *context, void **return_value)
{
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	struct acpi_db_execute_walk *info =
	    (struct acpi_db_execute_walk *)context;
	char *pathname;
	const union acpi_predefined_info *predefined;
	struct acpi_device_info *obj_info;
	struct acpi_object_list param_objects;
	union acpi_object params[ACPI_METHOD_NUM_ARGS];
	union acpi_object *this_param;
	struct acpi_buffer return_obj;
	acpi_status status;
	u16 arg_type_list;
	u8 arg_count;
	u8 arg_type;
	u32 i;

	/* The name must be a predefined ACPI name */

	predefined = acpi_ut_match_predefined_method(node->name.ascii);
	if (!predefined) {
		return (AE_OK);
	}

	if (node->type == ACPI_TYPE_LOCAL_SCOPE) {
		return (AE_OK);
	}

	pathname = acpi_ns_get_normalized_pathname(node, TRUE);
	if (!pathname) {
		return (AE_OK);
	}

	/* Get the object info for number of method parameters */

	status = acpi_get_object_info(obj_handle, &obj_info);
	if (ACPI_FAILURE(status)) {
		ACPI_FREE(pathname);
		return (status);
	}

	param_objects.count = 0;
	param_objects.pointer = NULL;

	if (obj_info->type == ACPI_TYPE_METHOD) {

		/* Setup default parameters (with proper types) */

		arg_type_list = predefined->info.argument_list;
		arg_count = METHOD_GET_ARG_COUNT(arg_type_list);

		/*
		 * Setup the ACPI-required number of arguments, regardless of what
		 * the actual method defines. If there is a difference, then the
		 * method is wrong and a warning will be issued during execution.
		 */
		this_param = params;
		for (i = 0; i < arg_count; i++) {
			arg_type = METHOD_GET_NEXT_TYPE(arg_type_list);
			this_param->type = arg_type;

			switch (arg_type) {
			case ACPI_TYPE_INTEGER:

				this_param->integer.value = 1;
				break;

			case ACPI_TYPE_STRING:

				this_param->string.pointer =
				    "This is the default argument string";
				this_param->string.length =
				    strlen(this_param->string.pointer);
				break;

			case ACPI_TYPE_BUFFER:

				this_param->buffer.pointer = (u8 *)params;	/* just a garbage buffer */
				this_param->buffer.length = 48;
				break;

			case ACPI_TYPE_PACKAGE:

				this_param->package.elements = NULL;
				this_param->package.count = 0;
				break;

			default:

				acpi_os_printf
				    ("%s: Unsupported argument type: %u\n",
				     pathname, arg_type);
				break;
			}

			this_param++;
		}

		param_objects.count = arg_count;
		param_objects.pointer = params;
	}

	ACPI_FREE(obj_info);
	return_obj.pointer = NULL;
	return_obj.length = ACPI_ALLOCATE_BUFFER;

	/* Do the actual method execution */

	acpi_gbl_method_executing = TRUE;

	status = acpi_evaluate_object(node, NULL, &param_objects, &return_obj);

	acpi_os_printf("%-32s returned %s\n",
		       pathname, acpi_format_exception(status));
	acpi_gbl_method_executing = FALSE;
	ACPI_FREE(pathname);

	/* Ignore status from method execution */

	status = AE_OK;

	/* Update count, check if we have executed enough methods */

	info->count++;
	if (info->count >= info->max_count) {
		status = AE_CTRL_TERMINATE;
	}

	return (status);
}
Пример #9
0
static int __init erst_init(void)
{
    int rc = 0;
    acpi_status status;
    struct apei_exec_context ctx;
    struct apei_resources erst_resources;
    struct resource *r;

    if (acpi_disabled)
        goto err;

    if (erst_disable) {
        pr_info(ERST_PFX
                "Error Record Serialization Table (ERST) support is disabled.\n");
        goto err;
    }

    status = acpi_get_table(ACPI_SIG_ERST, 0,
                            (struct acpi_table_header **)&erst_tab);
    if (status == AE_NOT_FOUND) {
        pr_info(ERST_PFX "Table is not found!\n");
        goto err;
    } else if (ACPI_FAILURE(status)) {
        const char *msg = acpi_format_exception(status);
        pr_err(ERST_PFX "Failed to get table, %s\n", msg);
        rc = -EINVAL;
        goto err;
    }

    rc = erst_check_table(erst_tab);
    if (rc) {
        pr_err(FW_BUG ERST_PFX "ERST table is invalid\n");
        goto err;
    }

    apei_resources_init(&erst_resources);
    erst_exec_ctx_init(&ctx);
    rc = apei_exec_collect_resources(&ctx, &erst_resources);
    if (rc)
        goto err_fini;
    rc = apei_resources_request(&erst_resources, "APEI ERST");
    if (rc)
        goto err_fini;
    rc = apei_exec_pre_map_gars(&ctx);
    if (rc)
        goto err_release;
    rc = erst_get_erange(&erst_erange);
    if (rc) {
        if (rc == -ENODEV)
            pr_info(ERST_PFX
                    "The corresponding hardware device or firmware implementation "
                    "is not available.\n");
        else
            pr_err(ERST_PFX
                   "Failed to get Error Log Address Range.\n");
        goto err_unmap_reg;
    }

    r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
    if (!r) {
        pr_err(ERST_PFX
               "Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n",
               (unsigned long long)erst_erange.base,
               (unsigned long long)erst_erange.base + erst_erange.size);
        rc = -EIO;
        goto err_unmap_reg;
    }
    rc = -ENOMEM;
    erst_erange.vaddr = ioremap_cache(erst_erange.base,
                                      erst_erange.size);
    if (!erst_erange.vaddr)
        goto err_release_erange;

    pr_info(ERST_PFX
            "Error Record Serialization Table (ERST) support is initialized.\n");

    return 0;

err_release_erange:
    release_mem_region(erst_erange.base, erst_erange.size);
err_unmap_reg:
    apei_exec_post_unmap_gars(&ctx);
err_release:
    apei_resources_release(&erst_resources);
err_fini:
    apei_resources_fini(&erst_resources);
err:
    erst_disable = 1;
    return rc;
}
Пример #10
0
static void acpi_db_do_one_sleep_state(u8 sleep_state)
{
	acpi_status status;
	u8 sleep_type_a;
	u8 sleep_type_b;

	/* Validate parameter */

	if (sleep_state > ACPI_S_STATES_MAX) {
		acpi_os_printf("Sleep state %d out of range (%d max)\n",
			       sleep_state, ACPI_S_STATES_MAX);
		return;
	}

	acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n",
		       sleep_state, acpi_gbl_sleep_state_names[sleep_state]);

	/* Get the values for the sleep type registers (for display only) */

	status =
	    acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b);
	if (ACPI_FAILURE(status)) {
		acpi_os_printf("Could not evaluate [%s] method, %s\n",
			       acpi_gbl_sleep_state_names[sleep_state],
			       acpi_format_exception(status));
		return;
	}

	acpi_os_printf
	    ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
	     sleep_state, sleep_type_a, sleep_type_b);

	/* Invoke the various sleep/wake interfaces */

	acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n",
		       sleep_state);
	status = acpi_enter_sleep_state_prep(sleep_state);
	if (ACPI_FAILURE(status)) {
		goto error_exit;
	}

	acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state);
	status = acpi_enter_sleep_state(sleep_state);
	if (ACPI_FAILURE(status)) {
		goto error_exit;
	}

	acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n",
		       sleep_state);
	status = acpi_leave_sleep_state_prep(sleep_state);
	if (ACPI_FAILURE(status)) {
		goto error_exit;
	}

	acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n",
		       sleep_state);
	status = acpi_leave_sleep_state(sleep_state);
	if (ACPI_FAILURE(status)) {
		goto error_exit;
	}

	return;

error_exit:
	ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d",
			sleep_state));
}
Пример #11
0
static acpi_status
acpi_db_device_resources(acpi_handle obj_handle,
			 u32 nesting_level, void *context, void **return_value)
{
	struct acpi_namespace_node *node;
	struct acpi_namespace_node *prt_node = NULL;
	struct acpi_namespace_node *crs_node = NULL;
	struct acpi_namespace_node *prs_node = NULL;
	struct acpi_namespace_node *aei_node = NULL;
	char *parent_path;
	struct acpi_buffer return_buffer;
	acpi_status status;

	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
	if (!parent_path) {
		return (AE_NO_MEMORY);
	}

	/* Get handles to the resource methods for this device */

	(void)acpi_get_handle(node, METHOD_NAME__PRT,
			      ACPI_CAST_PTR(acpi_handle, &prt_node));
	(void)acpi_get_handle(node, METHOD_NAME__CRS,
			      ACPI_CAST_PTR(acpi_handle, &crs_node));
	(void)acpi_get_handle(node, METHOD_NAME__PRS,
			      ACPI_CAST_PTR(acpi_handle, &prs_node));
	(void)acpi_get_handle(node, METHOD_NAME__AEI,
			      ACPI_CAST_PTR(acpi_handle, &aei_node));

	if (!prt_node && !crs_node && !prs_node && !aei_node) {
		goto cleanup;	/* Nothing to do */
	}

	acpi_os_printf("\nDevice: %s\n", parent_path);

	/* Prepare for a return object of arbitrary size */

	return_buffer.pointer = acpi_gbl_db_buffer;
	return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

	/* _PRT */

	if (prt_node) {
		acpi_os_printf("Evaluating _PRT\n");

		status =
		    acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRT: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_irq_routing_table(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("GetIrqRoutingTable failed: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
	}

	/* _CRS */

get_crs:
	if (crs_node) {
		acpi_os_printf("Evaluating _CRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _CRS: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resources interface */

		status = acpi_walk_resources(node, METHOD_NAME__CRS,
					     acpi_db_resource_callback, NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* Get the _CRS resource list (test ALLOCATE buffer) */

		return_buffer.pointer = NULL;
		return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

		status = acpi_get_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resource_buffer interface */

		status = acpi_walk_resource_buffer(&return_buffer,
						   acpi_db_resource_callback,
						   NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

		/* Dump the _CRS resource list */

		acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
							 return_buffer.
							 pointer));

		/*
		 * Perform comparison of original AML to newly created AML. This
		 * tests both the AML->Resource conversion and the Resource->AML
		 * conversion.
		 */
		(void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);

		/* Execute _SRS with the resource list */

		acpi_os_printf("Evaluating _SRS\n");

		status = acpi_set_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

end_crs:
		ACPI_FREE(return_buffer.pointer);
	}

	/* _PRS */

get_prs:
	if (prs_node) {
		acpi_os_printf("Evaluating _PRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRS: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_possible_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

	/* _AEI */

get_aei:
	if (aei_node) {
		acpi_os_printf("Evaluating _AEI\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _AEI: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_event_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetEventResources failed: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

cleanup:
	ACPI_FREE(parent_path);
	return (AE_OK);
}
Пример #12
0
Файл: osl.c Проект: PyroOS/Pyro
/*
 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
 * improvise.  The process is to sleep for one scheduler quantum
 * until the semaphore becomes available.  Downside is that this
 * may result in starvation for timeout-based waits when there's
 * lots of semaphore activity.
 *
 * TODO: Support for units > 1?
 */
acpi_status
acpi_os_wait_semaphore(
	acpi_handle		handle,
	u32			units,
	u16			timeout)
{
	acpi_status		status = AE_OK;
	sem_id	*sem = (sem_id*)handle;
	int			ret = 0;
	
	ACPI_FUNCTION_TRACE ("os_wait_semaphore");

//	printk( "lock %i %i\n", *sem, get_semaphore_count( *sem ) );
	if (!sem || (units < 1))
		return_ACPI_STATUS (AE_BAD_PARAMETER);

	if (units > 1)
		return_ACPI_STATUS (AE_SUPPORT);

	ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));

/*	if (in_atomic())
		timeout = 0;
*/
	switch (timeout)
	{
		/*
		 * No Wait:
		 * --------
		 * A zero timeout value indicates that we shouldn't wait - just
		 * acquire the semaphore if available otherwise return AE_TIME
		 * (a.k.a. 'would block').
		 */
		case 0:
		if(TRY_LOCK(*sem))
			status = AE_TIME;
		break;

		/*
		 * Wait Indefinitely:
		 * ------------------
		 */
		case ACPI_WAIT_FOREVER:
		LOCK(*sem);
		break;

		/*
		 * Wait w/ Timeout:
		 * ----------------
		 */
		default:
		// TODO: A better timeout algorithm?
		{
			status = lock_semaphore( *sem, SEM_NOSIG, (bigtime_t)timeout * 1000 );
	
			if (ret != 0)
				status = AE_TIME;
		}
		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Failed to acquire semaphore[%p|%d|%d], %s\n", 
			handle, units, timeout, acpi_format_exception(status)));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
	}

//	printk("sem %i %i %i\n", *sem, timeout, status);


	return_ACPI_STATUS (status);
}
Пример #13
0
acpi_status
acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info)
{
	acpi_status status;
	struct acpi_namespace_node *node = NULL;
	union acpi_generic_state *scope_info;
	char *internal_path = NULL;

	ACPI_FUNCTION_TRACE("ns_evaluate_relative");

	/*
	 * Must have a valid object handle
	 */
	if (!info || !info->node) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Build an internal name string for the method */

	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	scope_info = acpi_ut_create_generic_state();
	if (!scope_info) {
		goto cleanup1;
	}

	/* Get the prefix handle and Node */

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	info->node = acpi_ns_map_handle_to_node(info->node);
	if (!info->node) {
		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/* Lookup the name in the namespace */

	scope_info->scope.node = info->node;
	status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY,
				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
				&node);

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
				  pathname, acpi_format_exception(status)));
		goto cleanup;
	}

	/*
	 * Now that we have a handle to the object, we can attempt to evaluate it.
	 */
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
			  pathname, node, acpi_ns_get_attached_object(node)));

	info->node = node;
	status = acpi_ns_evaluate_by_handle(info);

	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
			  "*** Completed eval of object %s ***\n", pathname));

      cleanup:
	acpi_ut_delete_generic_state(scope_info);

      cleanup1:
	ACPI_MEM_FREE(internal_path);
	return_ACPI_STATUS(status);
}
Пример #14
0
void
acpi_db_display_resources (
	NATIVE_CHAR             *object_arg)
{
#ifndef _IA16
	acpi_operand_object     *obj_desc;
	acpi_status             status;
	acpi_buffer             return_obj;


	acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);

	/* Convert string to object pointer */

	obj_desc = (acpi_operand_object *) STRTOUL (object_arg, NULL, 16);

	/* Prepare for a return object of arbitrary size */

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;


	/* _PRT */

	acpi_os_printf ("Evaluating _PRT\n");

	status = acpi_evaluate_object (obj_desc, "_PRT", NULL, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Could not obtain _PRT: %s\n", acpi_format_exception (status));
		goto get_crs;
	}

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;

	status = acpi_get_irq_routing_table (obj_desc, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Get_irq_routing_table failed: %s\n", acpi_format_exception (status));
	}

	else {
		acpi_rs_dump_irq_list ((u8 *) acpi_gbl_db_buffer);
	}


	/* _CRS */

get_crs:
	acpi_os_printf ("Evaluating _CRS\n");

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;

	status = acpi_evaluate_object (obj_desc, "_CRS", NULL, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Could not obtain _CRS: %s\n", acpi_format_exception (status));
		goto get_prs;
	}

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;

	status = acpi_get_current_resources (obj_desc, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Acpi_get_current_resources failed: %s\n", acpi_format_exception (status));
	}

	else {
		acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer);
	}


	/* _PRS */

get_prs:
	acpi_os_printf ("Evaluating _PRS\n");

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;

	status = acpi_evaluate_object (obj_desc, "_PRS", NULL, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Could not obtain _PRS: %s\n", acpi_format_exception (status));
		goto cleanup;
	}

	return_obj.pointer          = acpi_gbl_db_buffer;
	return_obj.length           = ACPI_DEBUG_BUFFER_SIZE;

	status = acpi_get_possible_resources (obj_desc, &return_obj);
	if (ACPI_FAILURE (status)) {
		acpi_os_printf ("Acpi_get_possible_resources failed: %s\n", acpi_format_exception (status));
	}

	else {
		acpi_rs_dump_resource_list ((acpi_resource *) acpi_gbl_db_buffer);
	}


cleanup:

	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
	return;
#endif

}
Пример #15
0
acpi_status
acpi_evaluate_object (
	acpi_handle                     handle,
	acpi_string                     pathname,
	struct acpi_object_list         *external_params,
	struct acpi_buffer              *return_buffer)
{
	acpi_status                     status;
	acpi_status                     status2;
	struct acpi_parameter_info      info;
	acpi_size                       buffer_space_needed;
	u32                             i;


	ACPI_FUNCTION_TRACE ("acpi_evaluate_object");


	info.node = handle;
	info.parameters = NULL;
	info.return_object = NULL;
	info.parameter_type = ACPI_PARAM_ARGS;

	/*
	 * If there are parameters to be passed to the object
	 * (which must be a control method), the external objects
	 * must be converted to internal objects
	 */
	if (external_params && external_params->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info.parameters = ACPI_MEM_CALLOCATE (
				 ((acpi_size) external_params->count + 1) *
				 sizeof (void *));
		if (!info.parameters) {
			return_ACPI_STATUS (AE_NO_MEMORY);
		}

		/*
		 * Convert each external object in the list to an
		 * internal object
		 */
		for (i = 0; i < external_params->count; i++) {
			status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
					  &info.parameters[i]);
			if (ACPI_FAILURE (status)) {
				acpi_ut_delete_internal_object_list (info.parameters);
				return_ACPI_STATUS (status);
			}
		}
		info.parameters[external_params->count] = NULL;
	}


	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */
	if ((pathname) &&
		(acpi_ns_valid_root_prefix (pathname[0]))) {
		/*
		 *  The path is fully qualified, just evaluate by name
		 */
		status = acpi_ns_evaluate_by_name (pathname, &info);
	}
	else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname
		 * is specified.  Since we've already handled fully
		 * qualified names above, this is an error
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Both Handle and Pathname are NULL\n"));
		}
		else {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Handle is NULL and Pathname is relative\n"));
		}

		status = AE_BAD_PARAMETER;
	}
	else {
		/*
		 * We get here if we have a handle -- and if we have a
		 * pathname it is relative.  The handle will be validated
		 * in the lower procedures
		 */
		if (!pathname) {
			/*
			 * The null pathname case means the handle is for
			 * the actual object to be evaluated
			 */
			status = acpi_ns_evaluate_by_handle (&info);
		}
		else {
		   /*
			* Both a Handle and a relative Pathname
			*/
			status = acpi_ns_evaluate_relative (pathname, &info);
		}
	}


	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info.return_object) {
			return_buffer->length = 0;
		}
		else {
			if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info.return_object = NULL;  /* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS (status)) {
				/*
				 * Find out how large a buffer is needed
				 * to contain the returned object
				 */
				status = acpi_ut_get_object_size (info.return_object,
						   &buffer_space_needed);
				if (ACPI_SUCCESS (status)) {
					/* Validate/Allocate/Clear caller buffer */

					status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
					if (ACPI_FAILURE (status)) {
						/*
						 * Caller's buffer is too small or a new one can't be allocated
						 */
						ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
							"Needed buffer size %X, %s\n",
							(u32) buffer_space_needed,
							acpi_format_exception (status)));
					}
					else {
						/*
						 *  We have enough space for the object, build it
						 */
						status = acpi_ut_copy_iobject_to_eobject (info.return_object,
								  return_buffer);
					}
				}
			}
		}
	}

	if (info.return_object) {
		/*
		 * Delete the internal return object.  NOTE: Interpreter
		 * must be locked to avoid race condition.
		 */
		status2 = acpi_ex_enter_interpreter ();
		if (ACPI_SUCCESS (status2)) {
			/*
			 * Delete the internal return object. (Or at least
			 * decrement the reference count by one)
			 */
			acpi_ut_remove_reference (info.return_object);
			acpi_ex_exit_interpreter ();
		}
	}

	/*
	 * Free the input parameter list (if we created one),
	 */
	if (info.parameters) {
		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list (info.parameters);
	}

	return_ACPI_STATUS (status);
}
Пример #16
0
static void ACPI_SYSTEM_XFACE
acpi_ev_asynch_execute_gpe_method (
	void                            *context)
{
	struct acpi_gpe_event_info      *gpe_event_info = (void *) context;
	u32                             gpe_number = 0;
	acpi_status                     status;
	struct acpi_gpe_event_info      local_gpe_event_info;
	struct acpi_parameter_info      info;


	ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");


	status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
	if (ACPI_FAILURE (status)) {
		return_VOID;
	}

	/* Must revalidate the gpe_number/gpe_block */

	if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
		status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
		return_VOID;
	}

	/* Set the GPE flags for return to enabled state */

	(void) acpi_ev_enable_gpe (gpe_event_info, FALSE);

	/*
	 * Take a snapshot of the GPE info for this level - we copy the
	 * info to prevent a race condition with remove_handler/remove_block.
	 */
	ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info, sizeof (struct acpi_gpe_event_info));

	status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
	if (ACPI_FAILURE (status)) {
		return_VOID;
	}

	/*
	 * Must check for control method type dispatch one more
	 * time to avoid race with ev_gpe_install_handler
	 */
	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
		/*
		 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
		 * control method that corresponds to this GPE
		 */
		info.node = local_gpe_event_info.dispatch.method_node;
		info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
		info.parameter_type = ACPI_PARAM_GPE;

		status = acpi_ns_evaluate_by_handle (&info);
		if (ACPI_FAILURE (status)) {
			ACPI_REPORT_ERROR ((
				"%s while evaluating method [%4.4s] for GPE[%2X]\n",
				acpi_format_exception (status),
				acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
				gpe_number));
		}
	}
Пример #17
0
acpi_status
acpi_ut_release_mutex (
	acpi_mutex_handle               mutex_id)
{
	acpi_status                     status;
	u32                             i;
	u32                             this_thread_id;


	ACPI_FUNCTION_NAME ("ut_release_mutex");


	this_thread_id = acpi_os_get_thread_id ();
	ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
		"Thread %X releasing Mutex [%s]\n", this_thread_id,
		acpi_ut_get_mutex_name (mutex_id)));

	if (mutex_id > MAX_MUTEX) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * Mutex must be acquired in order to release it!
	 */
	if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Mutex [%s] is not acquired, cannot release\n",
			acpi_ut_get_mutex_name (mutex_id)));

		return (AE_NOT_ACQUIRED);
	}

	/*
	 * Deadlock prevention.  Check if this thread owns any mutexes of value
	 * greater than this one.  If so, the thread has violated the mutex
	 * ordering rule.  This indicates a coding error somewhere in
	 * the ACPI subsystem code.
	 */
	for (i = mutex_id; i < MAX_MUTEX; i++) {
		if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
			if (i == mutex_id) {
				continue;
			}

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Invalid release order: owns [%s], releasing [%s]\n",
				acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id)));

			return (AE_RELEASE_DEADLOCK);
		}
	}

	/* Mark unlocked FIRST */

	acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED;

	status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1);

	if (ACPI_FAILURE (status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Thread %X could not release Mutex [%s] %s\n",
			this_thread_id, acpi_ut_get_mutex_name (mutex_id),
			acpi_format_exception (status)));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
			this_thread_id, acpi_ut_get_mutex_name (mutex_id)));
	}

	return (status);
}
Пример #18
0
acpi_status
acpi_ut_acquire_mutex (
	acpi_mutex_handle               mutex_id)
{
	acpi_status                     status;
	u32                             this_thread_id;


	ACPI_FUNCTION_NAME ("ut_acquire_mutex");


	if (mutex_id > MAX_MUTEX) {
		return (AE_BAD_PARAMETER);
	}

	this_thread_id = acpi_os_get_thread_id ();

#ifdef ACPI_MUTEX_DEBUG
	{
		u32                             i;
		/*
		 * Mutex debug code, for internal debugging only.
		 *
		 * Deadlock prevention.  Check if this thread owns any mutexes of value
		 * greater than or equal to this one.  If so, the thread has violated
		 * the mutex ordering rule.  This indicates a coding error somewhere in
		 * the ACPI subsystem code.
		 */
		for (i = mutex_id; i < MAX_MUTEX; i++) {
			if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) {
				if (i == mutex_id) {
					ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
						"Mutex [%s] already acquired by this thread [%X]\n",
						acpi_ut_get_mutex_name (mutex_id), this_thread_id));

					return (AE_ALREADY_ACQUIRED);
				}

				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
					"Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
					this_thread_id, acpi_ut_get_mutex_name (i),
					acpi_ut_get_mutex_name (mutex_id)));

				return (AE_ACQUIRE_DEADLOCK);
			}
		}
	}
#endif

	ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
		"Thread %X attempting to acquire Mutex [%s]\n",
		this_thread_id, acpi_ut_get_mutex_name (mutex_id)));

	status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex,
			   1, ACPI_WAIT_FOREVER);
	if (ACPI_SUCCESS (status)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
			this_thread_id, acpi_ut_get_mutex_name (mutex_id)));

		acpi_gbl_mutex_info[mutex_id].use_count++;
		acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id;
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Thread %X could not acquire Mutex [%s] %s\n",
				this_thread_id, acpi_ut_get_mutex_name (mutex_id),
				acpi_format_exception (status)));
	}

	return (status);
}
Пример #19
0
void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg)
{
	struct acpi_interface_info *next_interface;
	char *sub_string;
	acpi_status status;

	/* If no arguments, just display current interface list */

	if (!action_arg) {
		(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex,
					    ACPI_WAIT_FOREVER);

		next_interface = acpi_gbl_supported_interfaces;
		while (next_interface) {
			if (!(next_interface->flags & ACPI_OSI_INVALID)) {
				acpi_os_printf("%s\n", next_interface->name);
			}

			next_interface = next_interface->next;
		}

		acpi_os_release_mutex(acpi_gbl_osi_mutex);
		return;
	}

	/* If action_arg exists, so must interface_name_arg */

	if (!interface_name_arg) {
		acpi_os_printf("Missing Interface Name argument\n");
		return;
	}

	/* Uppercase the action for match below */

	acpi_ut_strupr(action_arg);

	/* install - install an interface */

	sub_string = strstr("INSTALL", action_arg);
	if (sub_string) {
		status = acpi_install_interface(interface_name_arg);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("%s, while installing \"%s\"\n",
				       acpi_format_exception(status),
				       interface_name_arg);
		}
		return;
	}

	/* remove - remove an interface */

	sub_string = strstr("REMOVE", action_arg);
	if (sub_string) {
		status = acpi_remove_interface(interface_name_arg);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("%s, while removing \"%s\"\n",
				       acpi_format_exception(status),
				       interface_name_arg);
		}
		return;
	}

	/* Invalid action_arg */

	acpi_os_printf("Invalid action argument: %s\n", action_arg);
	return;
}
Пример #20
0
acpi_status
acpi_ns_init_one_object (
	acpi_handle             obj_handle,
	u32                     level,
	void                    *context,
	void                    **return_value)
{
	acpi_object_type8       type;
	acpi_status             status;
	acpi_init_walk_info     *info = (acpi_init_walk_info *) context;
	acpi_namespace_node     *node = (acpi_namespace_node *) obj_handle;
	acpi_operand_object     *obj_desc;


	PROC_NAME ("Ns_init_one_object");


	info->object_count++;


	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type (obj_handle);
	obj_desc = node->object;
	if (!obj_desc) {
		return (AE_OK);
	}

	if ((type != ACPI_TYPE_REGION) &&
		(type != ACPI_TYPE_BUFFER_FIELD)) {
		return (AE_OK);
	}


	/*
	 * Must lock the interpreter before executing AML code
	 */
	status = acpi_ex_enter_interpreter ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	switch (type) {

	case ACPI_TYPE_REGION:

		info->op_region_count++;
		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
			break;
		}

		info->op_region_init++;
		status = acpi_ds_get_region_arguments (obj_desc);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
					"%s while getting region arguments [%4.4s]\n",
					acpi_format_exception (status), (char*)&node->name));
		}

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

		break;


	case ACPI_TYPE_BUFFER_FIELD:

		info->field_count++;
		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
			break;
		}

		info->field_init++;
		status = acpi_ds_get_buffer_field_arguments (obj_desc);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
					"%s while getting buffer field arguments [%4.4s]\n",
					acpi_format_exception (status), (char*)&node->name));
		}
		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
		}


		break;

	default:
		break;
	}


	/*
	 * We ignore errors from above, and always return OK, since
	 * we don't want to abort the walk on a single error.
	 */
	acpi_ex_exit_interpreter ();
	return (AE_OK);
}
Пример #21
0
static acpi_status
acpi_db_read_from_object(struct acpi_namespace_node *node,
			 acpi_object_type expected_type,
			 union acpi_object **value)
{
	union acpi_object *ret_value;
	struct acpi_object_list param_objects;
	union acpi_object params[2];
	struct acpi_buffer return_obj;
	acpi_status status;

	params[0].type = ACPI_TYPE_LOCAL_REFERENCE;
	params[0].reference.actual_type = node->type;
	params[0].reference.handle = ACPI_CAST_PTR(acpi_handle, node);

	param_objects.count = 1;
	param_objects.pointer = params;

	return_obj.length = ACPI_ALLOCATE_BUFFER;

	acpi_gbl_method_executing = TRUE;
	status = acpi_evaluate_object(read_handle, NULL,
				      &param_objects, &return_obj);
	acpi_gbl_method_executing = FALSE;

	if (ACPI_FAILURE(status)) {
		acpi_os_printf("Could not read from object, %s",
			       acpi_format_exception(status));
		return (status);
	}

	ret_value = (union acpi_object *)return_obj.pointer;

	switch (ret_value->type) {
	case ACPI_TYPE_INTEGER:
	case ACPI_TYPE_BUFFER:
	case ACPI_TYPE_STRING:
		/*
		 * Did we receive the type we wanted? Most important for the
		 * Integer/Buffer case (when a field is larger than an Integer,
		 * it should return a Buffer).
		 */
		if (ret_value->type != expected_type) {
			acpi_os_printf
			    (" Type mismatch: Expected %s, Received %s",
			     acpi_ut_get_type_name(expected_type),
			     acpi_ut_get_type_name(ret_value->type));

			return (AE_TYPE);
		}

		*value = ret_value;
		break;

	default:

		acpi_os_printf(" Unsupported return object type, %s",
			       acpi_ut_get_type_name(ret_value->type));

		acpi_os_free(return_obj.pointer);
		return (AE_TYPE);
	}

	return (status);
}
Пример #22
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);
}
Пример #23
0
// Returns 0 if the call succeeded and non-zero otherwise. If the call
// succeeded, the result is stored in "result" providing that the result is an
// integer or a buffer containing 4 values
static int acpi_call_dsm(acpi_handle handle, const char muid[16], int revid,
    int func, char args[4], uint32_t *result) {
    struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
    struct acpi_object_list input;
    union acpi_object params[4];
    union acpi_object *obj;
    int err;

    input.count = 4;
    input.pointer = params;
    params[0].type = ACPI_TYPE_BUFFER;
    params[0].buffer.length = 16;
    params[0].buffer.pointer = (char *)muid;
    params[1].type = ACPI_TYPE_INTEGER;
    params[1].integer.value = revid;
    params[2].type = ACPI_TYPE_INTEGER;
    params[2].integer.value = func;
    params[3].type = ACPI_TYPE_BUFFER;
    params[3].buffer.length = 4;
    if (args) {
        params[3].buffer.pointer = args;
    } else {
        // Some implementations (Asus U36SD) seem to check the args before the
        // function ID and crash if it is not a buffer.
        params[3].buffer.pointer = (char[4]){0, 0, 0, 0};
    }

    err = acpi_evaluate_object(handle, "_DSM", &input, &output);
    if (err) {
        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
        char muid_str[5 * 16];
        char args_str[5 * 4];

        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf);

        pr_warn("failed to evaluate %s._DSM {%s} 0x%X 0x%X {%s}: %s\n",
            (char *)buf.pointer,
            buffer_to_string(muid, 16, muid_str), revid, func,
            buffer_to_string(args,  4, args_str), acpi_format_exception(err));
        return err;
    }

    obj = (union acpi_object *)output.pointer;

    if (obj->type == ACPI_TYPE_INTEGER && result) {
        *result = obj->integer.value;
    } else if (obj->type == ACPI_TYPE_BUFFER) {
        if (obj->buffer.length == 4 && result) {
            *result = 0;
            *result |= obj->buffer.pointer[0];
            *result |= (obj->buffer.pointer[1] << 8);
            *result |= (obj->buffer.pointer[2] << 16);
            *result |= (obj->buffer.pointer[3] << 24);
        }
    } else {
        pr_warn("_DSM call yields an unsupported result type: %#x\n",
            obj->type);
    }

    kfree(output.pointer);
    return 0;
}

// Returns 1 if a _DSM function and its function index exists and 0 otherwise
static int has_dsm_func(const char muid[16], int revid, int sfnc) {
    u32 result = 0;

    // fail if the _DSM call failed
    if (acpi_call_dsm(dis_handle, muid, revid, 0, 0, &result))
        return 0;

    // ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If
    // the n-th bit is enabled, function n is supported
    return result & 1 && result & (1 << sfnc);
}
Пример #24
0
acpi_status
acpi_enter_sleep_state_prep (
	u8                          sleep_state)
{
	acpi_status                 status;
	struct acpi_object_list     arg_list;
	union acpi_object           arg;


	ACPI_FUNCTION_TRACE ("acpi_enter_sleep_state_prep");


	/*
	 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
	 */
	status = acpi_get_sleep_type_data (sleep_state,
			  &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/* Setup parameter object */

	arg_list.count = 1;
	arg_list.pointer = &arg;

	arg.type = ACPI_TYPE_INTEGER;
	arg.integer.value = sleep_state;

	/* Run the _PTS and _GTS methods */

	status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		return_ACPI_STATUS (status);
	}

	status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		return_ACPI_STATUS (status);
	}

	/* Setup the argument to _SST */

	switch (sleep_state) {
	case ACPI_STATE_S0:
		arg.integer.value = ACPI_SST_WORKING;
		break;

	case ACPI_STATE_S1:
	case ACPI_STATE_S2:
	case ACPI_STATE_S3:
		arg.integer.value = ACPI_SST_SLEEPING;
		break;

	case ACPI_STATE_S4:
		arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
		break;

	default:
		arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
		break;
	}

	/* Set the system indicators to show the desired sleep state. */

	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
	}

	return_ACPI_STATUS (AE_OK);
}
Пример #25
0
acpi_status
acpi_ev_gpe_initialize (void)
{
	u32                             register_count0 = 0;
	u32                             register_count1 = 0;
	u32                             gpe_number_max = 0;
	acpi_handle                     gpe_device;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ev_gpe_initialize");


	/* Get a handle to the predefined _GPE object */

	status = acpi_get_handle (NULL, "\\_GPE", &gpe_device);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/*
	 * Initialize the GPE Blocks defined in the FADT
	 *
	 * Why the GPE register block lengths are divided by 2:  From the ACPI Spec,
	 * section "General-Purpose Event Registers", we have:
	 *
	 * "Each register block contains two registers of equal length
	 *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
	 *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
	 *  The length of the GPE1_STS and GPE1_EN registers is equal to
	 *  half the GPE1_LEN. If a generic register block is not supported
	 *  then its respective block pointer and block length values in the
	 *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
	 *  to be the same size."
	 */

	/*
	 * Determine the maximum GPE number for this machine.
	 *
	 * Note: both GPE0 and GPE1 are optional, and either can exist without
	 * the other.
	 *
	 * If EITHER the register length OR the block address are zero, then that
	 * particular block is not supported.
	 */
	if (acpi_gbl_FADT->gpe0_blk_len &&
		acpi_gbl_FADT->xgpe0_blk.address) {
		/* GPE block 0 exists (has both length and address > 0) */

		register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2);

		gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;

		/* Install GPE Block 0 */

		status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe0_blk,
				 register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
		if (ACPI_FAILURE (status)) {
			ACPI_REPORT_ERROR ((
				"Could not create GPE Block 0, %s\n",
				acpi_format_exception (status)));
		}
	}

	if (acpi_gbl_FADT->gpe1_blk_len &&
		acpi_gbl_FADT->xgpe1_blk.address) {
		/* GPE block 1 exists (has both length and address > 0) */

		register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2);

		/* Check for GPE0/GPE1 overlap (if both banks exist) */

		if ((register_count0) &&
			(gpe_number_max >= acpi_gbl_FADT->gpe1_base)) {
			ACPI_REPORT_ERROR ((
				"GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1\n",
				gpe_number_max, acpi_gbl_FADT->gpe1_base,
				acpi_gbl_FADT->gpe1_base +
				((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1)));

			/* Ignore GPE1 block by setting the register count to zero */

			register_count1 = 0;
		}
		else {
			/* Install GPE Block 1 */

			status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe1_blk,
					 register_count1, acpi_gbl_FADT->gpe1_base,
					 acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
			if (ACPI_FAILURE (status)) {
				ACPI_REPORT_ERROR ((
					"Could not create GPE Block 1, %s\n",
					acpi_format_exception (status)));
			}

			/*
			 * GPE0 and GPE1 do not have to be contiguous in the GPE number
			 * space. However, GPE0 always starts at GPE number zero.
			 */
			gpe_number_max = acpi_gbl_FADT->gpe1_base +
					   ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
		}
	}

	/* Exit if there are no GPE registers */

	if ((register_count0 + register_count1) == 0) {
		/* GPEs are not required by ACPI, this is OK */

		ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
		return_ACPI_STATUS (AE_OK);
	}

	/* Check for Max GPE number out-of-range */

	if (gpe_number_max > ACPI_GPE_MAX) {
		ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n",
			gpe_number_max));
		return_ACPI_STATUS (AE_BAD_VALUE);
	}

	return_ACPI_STATUS (AE_OK);
}
Пример #26
0
acpi_status
acpi_leave_sleep_state (
	u8                              sleep_state)
{
	struct acpi_object_list         arg_list;
	union acpi_object               arg;
	acpi_status                     status;
	struct acpi_bit_register_info   *sleep_type_reg_info;
	struct acpi_bit_register_info   *sleep_enable_reg_info;
	u32                             PM1Acontrol;
	u32                             PM1Bcontrol;


	ACPI_FUNCTION_TRACE ("acpi_leave_sleep_state");


	/*
	 * Set SLP_TYPE and SLP_EN to state S0.
	 * This is unclear from the ACPI Spec, but it is required
	 * by some machines.
	 */
	status = acpi_get_sleep_type_data (ACPI_STATE_S0,
			  &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b);
	if (ACPI_SUCCESS (status)) {
		sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
		sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);

		/* Get current value of PM1A control */

		status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
				 ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
		if (ACPI_SUCCESS (status)) {
			/* Clear SLP_EN and SLP_TYP fields */

			PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
					   sleep_enable_reg_info->access_bit_mask);
			PM1Bcontrol = PM1Acontrol;

			/* Insert SLP_TYP bits */

			PM1Acontrol |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
			PM1Bcontrol |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);

			/* Just ignore any errors */

			(void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
					  ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
			(void) acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
					  ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
		}
	}

	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */

	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;

	/* Setup parameter object */

	arg_list.count = 1;
	arg_list.pointer = &arg;
	arg.type = ACPI_TYPE_INTEGER;

	/* Ignore any errors from these methods */

	arg.integer.value = ACPI_SST_WAKING;
	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
	}

	arg.integer.value = sleep_state;
	status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
	}

	status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
	}
	/* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */

	/*
	 * Restore the GPEs:
	 * 1) Disable/Clear all GPEs
	 * 2) Enable all runtime GPEs
	 */
	status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}
	acpi_gbl_system_awake_and_running = TRUE;

	status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/* Enable power button */

	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
			1, ACPI_MTX_DO_NOT_LOCK);
	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
			1, ACPI_MTX_DO_NOT_LOCK);

	arg.integer.value = ACPI_SST_WORKING;
	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
	}

	return_ACPI_STATUS (status);
}
Пример #27
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  handle              - Object handle (optional)
 *              pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL. May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary. One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_validate_handle(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * Get the actual namespace node for the target object.
	 * Handles these cases:
	 *
	 * 1) Null node, valid pathname from root (absolute path)
	 * 2) Node and valid pathname (path relative to Node)
	 * 3) Node, Null pathname
	 */
	if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {

		/* The path is fully qualified, just evaluate by name */

		info->prefix_node = NULL;
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname is specified.
		 * Since we've already handled fully qualified names above, this is
		 * an error.
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	info->relative_pathname = pathname;

	/*
	 * Convert all external objects passed as arguments to the
	 * internal version(s).
	 */
	if (external_params && external_params->count) {
		info->param_count = (u16)external_params->count;

		/* Warn on impossible argument count */

		if (info->param_count > ACPI_METHOD_NUM_ARGS) {
			ACPI_WARN_PREDEFINED((AE_INFO, pathname,
					      ACPI_WARN_ALWAYS,
					      "Excess arguments (%u) - using only %u",
					      info->param_count,
					      ACPI_METHOD_NUM_ARGS));

			info->param_count = ACPI_METHOD_NUM_ARGS;
		}

		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
							 param_count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Convert each external object in the list to an internal object */

		for (i = 0; i < info->param_count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info->
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}

		info->parameters[info->param_count] = NULL;
	}

#ifdef _FUTURE_FEATURE

	/*
	 * Begin incoming argument count analysis. Check for too few args
	 * and too many args.
	 */
	switch (acpi_ns_get_type(info->node)) {
	case ACPI_TYPE_METHOD:

		/* Check incoming argument count against the method definition */

		if (info->obj_desc->method.param_count > info->param_count) {
			ACPI_ERROR((AE_INFO,
				    "Insufficient arguments (%u) - %u are required",
				    info->param_count,
				    info->obj_desc->method.param_count));

			status = AE_MISSING_ARGUMENTS;
			goto cleanup;
		}

		else if (info->obj_desc->method.param_count < info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "Excess arguments (%u) - only %u are required",
				      info->param_count,
				      info->obj_desc->method.param_count));

			/* Just pass the required number of arguments */

			info->param_count = info->obj_desc->method.param_count;
		}

		/*
		 * Any incoming external objects to be passed as arguments to the
		 * method must be converted to internal objects
		 */
		if (info->param_count) {
			/*
			 * Allocate a new parameter block for the internal objects
			 * Add 1 to count to allow for null terminated internal list
			 */
			info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
								 info->
								 param_count +
								 1) *
								sizeof(void *));
			if (!info->parameters) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}

			/* Convert each external object in the list to an internal object */

			for (i = 0; i < info->param_count; i++) {
				status =
				    acpi_ut_copy_eobject_to_iobject
				    (&external_params->pointer[i],
				     &info->parameters[i]);
				if (ACPI_FAILURE(status)) {
					goto cleanup;
				}
			}

			info->parameters[info->param_count] = NULL;
		}
		break;

	default:

		/* Warn if arguments passed to an object that is not a method */

		if (info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "%u arguments were passed to a non-method ACPI object",
				      info->param_count));
		}
		break;
	}

#endif

	/* Now we can evaluate the object */

	status = acpi_ns_evaluate(info);

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (!return_buffer) {
		goto cleanup_return_object;
	}

	if (!info->return_object) {
		return_buffer->length = 0;
		goto cleanup;
	}

	if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
	    ACPI_DESC_TYPE_NAMED) {
		/*
		 * If we received a NS Node as a return object, this means that
		 * the object we are evaluating has nothing interesting to
		 * return (such as a mutex, etc.)  We return an error because
		 * these types are essentially unsupported by this interface.
		 * We don't check up front because this makes it easier to add
		 * support for various types at a later date if necessary.
		 */
		status = AE_TYPE;
		info->return_object = NULL;	/* No need to delete a NS Node */
		return_buffer->length = 0;
	}

	if (ACPI_FAILURE(status)) {
		goto cleanup_return_object;
	}

	/* Dereference Index and ref_of references */

	acpi_ns_resolve_references(info);

	/* Get the size of the returned object */

	status = acpi_ut_get_object_size(info->return_object,
					 &buffer_space_needed);
	if (ACPI_SUCCESS(status)) {

		/* Validate/Allocate/Clear caller buffer */

		status = acpi_ut_initialize_buffer(return_buffer,
						   buffer_space_needed);
		if (ACPI_FAILURE(status)) {
			/*
			 * Caller's buffer is too small or a new one can't
			 * be allocated
			 */
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Needed buffer size %X, %s\n",
					  (u32)buffer_space_needed,
					  acpi_format_exception(status)));
		} else {
			/* We have enough space for the object, build it */

			status =
			    acpi_ut_copy_iobject_to_eobject(info->return_object,
							    return_buffer);
		}
	}

cleanup_return_object:

	if (info->return_object) {
		/*
		 * Delete the internal return object. NOTE: Interpreter must be
		 * locked to avoid race condition.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

cleanup:

	/* Free the input parameter list (if we created one) */

	if (info->parameters) {

		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info->parameters);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}
Пример #28
0
acpi_status
acpi_ev_pci_config_region_setup (
	acpi_handle                     handle,
	u32                             function,
	void                            *handler_context,
	void                            **region_context)
{
	acpi_status                     status = AE_OK;
	acpi_integer                    pci_value;
	struct acpi_pci_id              *pci_id = *region_context;
	union acpi_operand_object       *handler_obj;
	struct acpi_namespace_node      *parent_node;
	struct acpi_namespace_node      *pci_root_node;
	union acpi_operand_object       *region_obj = (union acpi_operand_object   *) handle;
	struct acpi_device_id           object_hID;


	ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup");


	handler_obj = region_obj->region.handler;
	if (!handler_obj) {
		/*
		 * No installed handler. This shouldn't happen because the dispatch
		 * routine checks before we get here, but we check again just in case.
		 */
		ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
			"Attempting to init a region %p, with no handler\n", region_obj));
		return_ACPI_STATUS (AE_NOT_EXIST);
	}

	*region_context = NULL;
	if (function == ACPI_REGION_DEACTIVATE) {
		if (pci_id) {
			ACPI_MEM_FREE (pci_id);
		}
		return_ACPI_STATUS (status);
	}

	parent_node = acpi_ns_get_parent_node (region_obj->region.node);

	/*
	 * Get the _SEG and _BBN values from the device upon which the handler
	 * is installed.
	 *
	 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
	 * This is the device the handler has been registered to handle.
	 */

	/*
	 * If the address_space.Node is still pointing to the root, we need
	 * to scan upward for a PCI Root bridge and re-associate the op_region
	 * handlers with that device.
	 */
	if (handler_obj->address_space.node == acpi_gbl_root_node) {
		/* Start search from the parent object */

		pci_root_node = parent_node;
		while (pci_root_node != acpi_gbl_root_node) {
			status = acpi_ut_execute_HID (pci_root_node, &object_hID);
			if (ACPI_SUCCESS (status)) {
				/* Got a valid _HID, check if this is a PCI root */

				if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING,
						   sizeof (PCI_ROOT_HID_STRING)))) {
					/* Install a handler for this PCI root bridge */

					status = acpi_install_address_space_handler ((acpi_handle) pci_root_node,
							   ACPI_ADR_SPACE_PCI_CONFIG,
							   ACPI_DEFAULT_HANDLER, NULL, NULL);
					if (ACPI_FAILURE (status)) {
						if (status == AE_SAME_HANDLER) {
							/*
							 * It is OK if the handler is already installed on the root
							 * bridge.  Still need to return a context object for the
							 * new PCI_Config operation region, however.
							 */
							status = AE_OK;
						}
						else {
							ACPI_REPORT_ERROR ((
								"Could not install pci_config handler for Root Bridge %4.4s, %s\n",
								acpi_ut_get_node_name (pci_root_node), acpi_format_exception (status)));
						}
					}
					break;
				}
			}

			pci_root_node = acpi_ns_get_parent_node (pci_root_node);
		}

		/* PCI root bridge not found, use namespace root node */
	}
	else {
		pci_root_node = handler_obj->address_space.node;
	}

	/*
	 * If this region is now initialized, we are done.
	 * (install_address_space_handler could have initialized it)
	 */
	if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
		return_ACPI_STATUS (AE_OK);
	}

	/* Region is still not initialized. Create a new context */

	pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id));
	if (!pci_id) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/*
	 * For PCI_Config space access, we need the segment, bus,
	 * device and function numbers.  Acquire them here.
	 */

	/*
	 * Get the PCI device and function numbers from the _ADR object
	 * contained in the parent's scope.
	 */
	status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value);

	/*
	 * The default is zero, and since the allocation above zeroed
	 * the data, just do nothing on failure.
	 */
	if (ACPI_SUCCESS (status)) {
		pci_id->device  = ACPI_HIWORD (ACPI_LODWORD (pci_value));
		pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value));
	}

	/* The PCI segment number comes from the _SEG method */

	status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value);
	if (ACPI_SUCCESS (status)) {
		pci_id->segment = ACPI_LOWORD (pci_value);
	}

	/* The PCI bus number comes from the _BBN method */

	status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value);
	if (ACPI_SUCCESS (status)) {
		pci_id->bus = ACPI_LOWORD (pci_value);
	}

	/* Complete this device's pci_id */

	acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id);

	*region_context = pci_id;
	return_ACPI_STATUS (AE_OK);
}
Пример #29
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  handle              - Object handle (optional)
 *              pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL. May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary. One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->pathname = pathname;

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_validate_handle(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * If there are parameters to be passed to a control method, the external
	 * objects must all be converted to internal objects
	 */
	if (external_params && external_params->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
							 external_params->
							 count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Convert each external object in the list to an internal object */

		for (i = 0; i < external_params->count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info->
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}
		info->parameters[external_params->count] = NULL;
	}

	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */
	if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {

		/* The path is fully qualified, just evaluate by name */

		info->prefix_node = NULL;
		status = acpi_ns_evaluate(info);
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname is specified.
		 * Since we've already handled fully qualified names above, this is
		 * an error
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
	} else {
		/* We have a namespace a node and a possible relative path */

		status = acpi_ns_evaluate(info);
	}

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info->return_object) {
			return_buffer->length = 0;
		} else {
			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
			    ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info->return_object = NULL;	/* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS(status)) {

				/* Dereference Index and ref_of references */

				acpi_ns_resolve_references(info);

				/* Get the size of the returned object */

				status =
				    acpi_ut_get_object_size(info->return_object,
							    &buffer_space_needed);
				if (ACPI_SUCCESS(status)) {

					/* Validate/Allocate/Clear caller buffer */

					status =
					    acpi_ut_initialize_buffer
					    (return_buffer,
					     buffer_space_needed);
					if (ACPI_FAILURE(status)) {
						/*
						 * Caller's buffer is too small or a new one can't
						 * be allocated
						 */
						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
								  "Needed buffer size %X, %s\n",
								  (u32)
								  buffer_space_needed,
								  acpi_format_exception
								  (status)));
					} else {
						/* We have enough space for the object, build it */

						status =
						    acpi_ut_copy_iobject_to_eobject
						    (info->return_object,
						     return_buffer);
					}
				}
			}
		}
	}

	if (info->return_object) {
		/*
		 * Delete the internal return object. NOTE: Interpreter must be
		 * locked to avoid race condition.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

      cleanup:

	/* Free the input parameter list (if we created one) */

	if (info->parameters) {

		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info->parameters);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}
Пример #30
0
acpi_status
acpi_load_tables (void)
{
    struct acpi_pointer             rsdp_address;
    acpi_status                     status;


    ACPI_FUNCTION_TRACE ("acpi_load_tables");


    /* Get the RSDP */

    status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
                                       &rsdp_address);
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Map and validate the RSDP */

    acpi_gbl_table_flags = rsdp_address.pointer_type;

    status = acpi_tb_verify_rsdp (&rsdp_address);
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Get the RSDT via the RSDP */

    status = acpi_tb_get_table_rsdt ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */

    status = acpi_tb_get_required_tables ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));


    /* Load the namespace from the tables */

    status = acpi_ns_load_namespace ();
    if (ACPI_FAILURE (status)) {
        ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
                            acpi_format_exception (status)));
        goto error_exit;
    }

    return_ACPI_STATUS (AE_OK);


error_exit:
    ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
                        acpi_format_exception (status)));

    return_ACPI_STATUS (status);
}