设备的信息都是通过ACPI的DSDT表传递给kernel的
int __init acpi_ec_dsdt_probe(void)
{
acpi_status status;
struct acpi_ec *ec;
int ret;
/*
* If a platform has ECDT, there is no need to proceed as the
* following probe is not a part of the ACPI device enumeration,
* executing _STA is not safe, and thus this probe may risk of
* picking up an invalid EC device.
*/
if (boot_ec)
return -ENODEV;
ec = acpi_ec_alloc();
if (!ec)
return -ENOMEM;
这里调用acpi_get_devices 来得到device信息
status = acpi_get_devices(ec_device_ids[0].id,
ec_parse_device, ec, NULL);
if (ACPI_FAILURE(status) || !ec->handle) {
ret = -ENODEV;
goto error;
}
}
acpi_status
acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context, void **return_value)
{
acpi_status status;
struct acpi_get_devices_info info;
ACPI_FUNCTION_TRACE(acpi_get_devices);
/* Parameter validation */
if (!user_function) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
info.hid = HID;
info.context = context;
info.user_function = user_function;
当找到device时调用acpi_ns_get_device_callback
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ns_get_device_callback, NULL,
&info, return_value);
}
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
核心代码如下:先匹配dsdt表格中的HID信息,如果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);
}
no_match = 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 (strcmp(cid->ids[i].string, info->hid) == 0) {
/* Found a matching CID */
found = TRUE;
break;
}
}
ACPI_FREE(cid);
if (!found) {
return (AE_OK);
}
}
}
}
int __init acpi_ec_dsdt_probe(void)
{
acpi_status status;
struct acpi_ec *ec;
int ret;
/*
* If a platform has ECDT, there is no need to proceed as the
* following probe is not a part of the ACPI device enumeration,
* executing _STA is not safe, and thus this probe may risk of
* picking up an invalid EC device.
*/
if (boot_ec)
return -ENODEV;
ec = acpi_ec_alloc();
if (!ec)
return -ENOMEM;
这里调用acpi_get_devices 来得到device信息
status = acpi_get_devices(ec_device_ids[0].id,
ec_parse_device, ec, NULL);
if (ACPI_FAILURE(status) || !ec->handle) {
ret = -ENODEV;
goto error;
}
}
acpi_status
acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context, void **return_value)
{
acpi_status status;
struct acpi_get_devices_info info;
ACPI_FUNCTION_TRACE(acpi_get_devices);
/* Parameter validation */
if (!user_function) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
info.hid = HID;
info.context = context;
info.user_function = user_function;
当找到device时调用acpi_ns_get_device_callback
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ns_get_device_callback, NULL,
&info, return_value);
}
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
核心代码如下:先匹配dsdt表格中的HID信息,如果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);
}
no_match = 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 (strcmp(cid->ids[i].string, info->hid) == 0) {
/* Found a matching CID */
found = TRUE;
break;
}
}
ACPI_FREE(cid);
if (!found) {
return (AE_OK);
}
}
}
}