acpi bus 的scan
来源:互联网 发布:六十知天命 编辑:程序博客网 时间:2024/06/06 00:42
在acpi子系统中一般我们首先通过下面的方式来注册handler
static struct acpi_scan_handler amba_handler = {
.ids = amba_id_list,
.attach = amba_handler_attach,
};
void __init acpi_amba_init(void)
{
amba_register_dummy_clk();
acpi_scan_add_handler(&amba_handler);
}
而acpi_scan_add_handler 只是将当前的amba_handler 加入到acpi_scan_handlers_list 这个列表中。
int acpi_scan_add_handler(struct acpi_scan_handler *handler)
{
if (!handler)
return -EINVAL;
list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
return 0;
}
当kernel 开始parse uefi传递的acpi表是会调用
acpi_bus_scan->acpi_bus_attach->acpi_scan_attach_handler 来和acpi_scan_handlers_list 表中的driver配对,所以这里也可以看出
acpi_amba_init的执行是在kernel parse acpi之前的
static int acpi_scan_attach_handler(struct acpi_device *device)
{
struct acpi_hardware_id *hwid;
int ret = 0;
list_for_each_entry(hwid, &device->pnp.ids, list) {
const struct acpi_device_id *devid;
struct acpi_scan_handler *handler;
handler = acpi_scan_match_handler(hwid->id, &devid);
if (handler) {
if (!handler->attach) {
device->pnp.type.platform_id = 0;
continue;
}
device->handler = handler;
ret = handler->attach(device, devid);
if (ret > 0)
break;
device->handler = NULL;
if (ret < 0)
break;
}
}
return ret;
}
acpi_scan_attach_handler 首先会调用acpi_scan_match_handler 匹配并拿到handler,如果handler不是空的话就执行attach函数,例如本来中juice会执行amba_handler_attach
static struct acpi_scan_handler *acpi_scan_match_handler(const char *idstr,
const struct acpi_device_id **matchid)
{
struct acpi_scan_handler *handler;
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
if (acpi_scan_handler_matching(handler, idstr, matchid))
return handler;
return NULL;
}
acpi_scan_handler 中就可以看到是遍历acpi_scan_handlers_list ,然后通过acpi_scan_handler_matching来判断是否匹配
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
const char *idstr,
const struct acpi_device_id **matchid)
{
const struct acpi_device_id *devid;
if (handler->match)
return handler->match(idstr, matchid);
for (devid = handler->ids; devid->id[0]; devid++)
if (!strcmp((char *)devid->id, idstr)) {
if (matchid)
*matchid = devid;
return true;
}
return false;
}
在acpi_scan_handler_matching 中如果handler->match 不会空的话,会先执行,也就是对handler而言match会比attach优先执行,即使id不匹配也会执行,后面的for循环就是通过strcmp来比较id这个字符串是否相等.
static struct acpi_scan_handler amba_handler = {
.ids = amba_id_list,
.attach = amba_handler_attach,
};
void __init acpi_amba_init(void)
{
amba_register_dummy_clk();
acpi_scan_add_handler(&amba_handler);
}
而acpi_scan_add_handler 只是将当前的amba_handler 加入到acpi_scan_handlers_list 这个列表中。
int acpi_scan_add_handler(struct acpi_scan_handler *handler)
{
if (!handler)
return -EINVAL;
list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
return 0;
}
当kernel 开始parse uefi传递的acpi表是会调用
acpi_bus_scan->acpi_bus_attach->acpi_scan_attach_handler 来和acpi_scan_handlers_list 表中的driver配对,所以这里也可以看出
acpi_amba_init的执行是在kernel parse acpi之前的
static int acpi_scan_attach_handler(struct acpi_device *device)
{
struct acpi_hardware_id *hwid;
int ret = 0;
list_for_each_entry(hwid, &device->pnp.ids, list) {
const struct acpi_device_id *devid;
struct acpi_scan_handler *handler;
handler = acpi_scan_match_handler(hwid->id, &devid);
if (handler) {
if (!handler->attach) {
device->pnp.type.platform_id = 0;
continue;
}
device->handler = handler;
ret = handler->attach(device, devid);
if (ret > 0)
break;
device->handler = NULL;
if (ret < 0)
break;
}
}
return ret;
}
acpi_scan_attach_handler 首先会调用acpi_scan_match_handler 匹配并拿到handler,如果handler不是空的话就执行attach函数,例如本来中juice会执行amba_handler_attach
static struct acpi_scan_handler *acpi_scan_match_handler(const char *idstr,
const struct acpi_device_id **matchid)
{
struct acpi_scan_handler *handler;
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
if (acpi_scan_handler_matching(handler, idstr, matchid))
return handler;
return NULL;
}
acpi_scan_handler 中就可以看到是遍历acpi_scan_handlers_list ,然后通过acpi_scan_handler_matching来判断是否匹配
static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
const char *idstr,
const struct acpi_device_id **matchid)
{
const struct acpi_device_id *devid;
if (handler->match)
return handler->match(idstr, matchid);
for (devid = handler->ids; devid->id[0]; devid++)
if (!strcmp((char *)devid->id, idstr)) {
if (matchid)
*matchid = devid;
return true;
}
return false;
}
在acpi_scan_handler_matching 中如果handler->match 不会空的话,会先执行,也就是对handler而言match会比attach优先执行,即使id不匹配也会执行,后面的for循环就是通过strcmp来比较id这个字符串是否相等.
0 0
- acpi bus 的scan
- subsys_initcall宏定义的一个例子,acpi/bus.c里面。
- acpi导致的问题
- ACPI
- acpi
- ACPI
- ACPI
- 显示acpi当前的信息
- ACPI的介绍和概念
- 我所认识的ACPI
- uefi对acpi的support
- ACPI的设计与实现 - ACPI overview
- ACPI的设计与实现 - ACPI编程模式
- 在安装FC5时停在“ACPI: Assume Root Bridge [/_SB_.PCI0] bus is 0”之解决办法
- SYSTEM BUS 与APIC BUS 的比较
- ACPI 中SCI的IRQ变更
- BIOS 里的 ACPI Description Table
- ACPI中ASL的简单介绍
- Spring-Mybatis整合注意的问题以及完整代码示例(见评论)
- 构建 Zookeeper + Dubbo + Spring Boot 的分布式调用项目(二)
- 欢迎使用CSDN-markdown编辑器
- 防止用户将表单重复提交的方法汇总
- 理解贝叶斯(一)
- acpi bus 的scan
- 变脸式应用 - 进入与退出应用
- Java实例说明 100个线程同时向一个银行账户中存入1元钱,在没有使用同步机制和使用同步机制情况下的执行情况
- 树莓派2、3 介绍及点亮led灯
- Introduction to Seccomp: BPF linux syscall filter
- TClientDataSet的 fastscript封装
- LaTex语法学习-大括号公式编辑
- Mysql 时区修改问题(冬令时夏令时)
- Leet Code OJ 3. Longest Substring Without Repeating Characters