acpidev_util.c revision b72d5b75fd6f5bb08d29f65652d60058fc3a2608
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2009, Intel Corporation.
* All rights reserved.
*/
#include <sys/sysmacros.h>
#include <sys/acpidev_impl.h>
/* Data structures used to extract the numeric unit address from string _UID. */
static char *acpidev_uid_formats[] = {
"%u",
};
static char *acpidev_unknown_object_name = "<unknown>";
int
{
int status;
"acpidev: hdl is NULL in acpidev_query_device_status().");
return (0);
}
/*
* Set the default value according to ACPI3.0b sec 6.3.7:
* 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,
* enabled, shown in the UI, and functioning).
*/
status = 0xF;
}
return (status);
}
{
/*
* According to ACPI3.0 Spec, if either the ACPI_STA_DEVICE_PRESENT bit
* or the ACPI_STA_DEVICE_FUNCTIONING bit is set, the device exists.
*/
return (B_TRUE);
}
return (B_FALSE);
}
{
/*
* According to ACPI3.0 Spec, if either the ACPI_STA_DEVICE_PRESENT bit
* or the ACPI_STA_DEVICE_FUNCTIONING bit is set, the device exists.
* Return true if device exists and has been enabled.
*/
(stat & ACPI_STA_DEVICE_ENABLED)) {
return (B_TRUE);
}
return (B_FALSE);
}
{
int i, j;
/* Special case to match all devices if count is 0. */
if (count == 0) {
return (B_TRUE);
"acpidev_match_device_id().");
return (B_FALSE);
}
/* Match _HID first. */
for (i = 0; i < count; i++) {
return (B_TRUE);
}
}
}
/* Match _CID next. */
for (i = 0; i < count; i++) {
sizeof (ACPI_COMPATIBLE_ID)) == 0) {
return (B_TRUE);
}
}
}
}
return (B_FALSE);
}
struct acpidev_get_device_arg {
int id_count;
char **device_ids;
void *user_arg;
};
static ACPI_STATUS
void **retval)
{
struct acpidev_get_device_arg *argp;
/* Query object information. */
if (ACPI_FAILURE(rc)) {
"in acpidev_get_device_callback().");
return (AE_CTRL_DEPTH);
}
/*
* Skip scanning of children if the device is neither PRESENT nor
* FUNCTIONING.
* Please refer to ACPI Spec3.0b Sec 6.3.1 and 6.5.1.
*/
rc = AE_CTRL_DEPTH;
/* Call user callback if matched. */
} else {
}
/* Free ACPI object info buffer. */
return (rc);
}
{
struct acpidev_get_device_arg arg;
"in acpidev_get_device_by_id().");
return (AE_BAD_PARAMETER);
}
/* Enumerate all descendant objects. */
return (rc);
}
{
"acpidev: invalid parameters for acpidev_walk_apic().");
return (AE_BAD_PARAMETER);
}
/* A walk buffer was passed in if bufp isn't NULL. */
/*
* Otherwise, if we have an evaluate method, we get the walk
* buffer from a successful invocation of AcpiEvaluateObject.
*/
"in acpidev_walk_apic().", method);
return (rc);
}
} else {
/* As a last resort, walk the MADT table. */
if (ACPI_FAILURE(rc)) {
"in acpidev_walk_apic().");
return (rc);
}
}
if (len <= sizeof (ACPI_SUBTABLE_HEADER) ||
"!acpidev: invalid APIC entry in MADT/_MAT.");
break;
}
}
}
return (rc);
}
char *
{
char *objname = acpidev_unknown_object_name;
}
return (objname);
}
void
acpidev_free_object_name(char *objname)
{
}
}
{
/* Cache ACPI device information. */
return (NULL);
}
/*
* Get or create an ACPI object data handle, which will be used to
* maintain object status information.
*/
} else {
"handle for %s in acpidev_alloc_walk_info().",
return (NULL);
}
/* Sync DEVICE_CREATED flag. */
}
return (infop);
}
void
{
/*
* The ACPI object data handle will only be released when the
* corresponding object is going to be destroyed.
*/
}
}
}
}
{
}
}
return (NULL);
}
/*
* Called to release resources when the corresponding object is going
* to be destroyed.
*/
/*ARGSUSED*/
static void
{
}
{
void *ptr;
}
return (objhdl);
}
{
(void *)objhdl))) {
"!acpidev: failed to attach handle data to object.");
return (NULL);
}
return (objhdl);
}
void
{
void *ptr;
}
}
{
}
{
return (NULL);
} else {
}
}
int
{
return (0);
} else {
return (hdl->aod_status);
}
}
void
{
}
void
{
}
{
}
static char *
{
return (NULL);
}
break;
}
}
/* uid doesn't exist, create one and insert it into the list. */
}
/*
* Generate a special format unit address with three fields to
* guarantee uniqueness. Normal unit addresses for ACPI devices have
* either one or two fields.
*/
return (NULL);
}
return (buf);
}
static char *
{
return (NULL);
}
/*
* Count '%' in format string to protect sscanf().
* Only support '%u' and '%x', and maximum 2 conversions.
*/
if (fmt[i] != '%') {
continue;
/* Skip next character. */
i++;
cnt++;
} else {
/* Invalid conversion, stop walking. */
}
}
"acpidev: invalid uid format string '%s'.", fmt);
return (NULL);
}
/* Scan uid and generate unitaddr. */
return (NULL);
}
/*
* Reverse the order of the two IDs to match the requirements of the
* hotplug driver.
*/
"acpidev: generated unitaddr is too long.");
return (NULL);
"acpidev: generated unitaddr is too long.");
return (NULL);
}
return (buf);
}
char *
{
size_t i;
/* Use _UID as unit address if it's a decimal integer. */
return (NULL);
} else {
return (buf);
}
}
/* First handle uid format strings from device property. */
/* Walk through format strings and try to generate unitaddr. */
}
}
/* Then handle embedded uid format strings. */
}
}
return (rbuf);
}
/*
* The Solaris device "unit-address" property is composed of a comma-delimited
* list of hexadecimal values. According to the ACPI spec, the ACPI _UID method
* could return an integer or a string. If it returns an integer, it is used
* as the unit-address as is. If _UID returns a string, we try to extract some
* meaningful integers to compose the unit-address property. If we fail to
* extract any integers, a pseudo-sequential number will be generated for the
* unit-address.
*/
char *unitaddr)
{
char unit[64];
"acpidev: invalid parameters in acpidev_set_unitaddr().");
return (AE_BAD_PARAMETER);
}
!= NDI_SUCCESS) {
"!acpidev: failed to set UID property for %s.",
return (AE_ERROR);
}
}
/* Try to generate unit address from _UID. */
nfmt = sizeof (acpidev_uid_formats) / sizeof (char *);
}
/* Generate pseudo sequential unit address. */
}
"address from %s.",
return (AE_ERROR);
}
}
/*
* Some ACPI objects may have no _UID method available, so we
* can't generate the "unit-address" property for them.
* On the other hand, it's legal to support such a device
* without a unit address, so return success here.
*/
return (AE_OK);
}
return (AE_ERROR);
}
return (AE_OK);
}
{
int count, i, j;
char **compatible = NULL;
/*
* Generate compatible list for device based on:
* * Device HID if available
* * Device CIDs if available
* * property array passed in
*/
"in acpidev_set_compatible().");
return (AE_BAD_PARAMETER);
}
/* Compute string count. */
count++;
}
}
/* Generate string array. */
i = 0;
}
}
}
for (j = 0; j < acount; j++) {
compatible[i++] = compat[j];
}
/* Set "compatible" property. */
"property for %s in acpidev_set_compatible().",
return (AE_ERROR);
}
return (AE_OK);
}