在使用ACPI传递参数给kernel的时候,针对buildin的driver现在只要在调用
module_platform_driver(v2_driver);
其实现如下:
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
继续看
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
可见就是平常我们用到的module_init,且在module_init中已经帮忙调用了platform_driver_register,多好啊,
那问题来了,到底是在哪里调用platform_device_register呢?
答案就是在acpi_create_platform_device
acpi_create_platform_device 一开始会调用(!acpi_match_device_ids(adev, forbidden_id_list)) 屏蔽某些driver,即不会
为这些driver 创建device.这些driver如下:
static const struct acpi_device_id forbidden_id_list[] = {
{"PNP0000", 0}, /* PIC */
{"PNP0100", 0}, /* Timer */
{"PNP0200", 0}, /* AT DMA Controller */
{"", 0},
};
其次会调用count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
来得到resource
int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
void *preproc_data)
{
struct res_proc_context c;
acpi_status status;
if (!adev || !adev->handle || !list_empty(list))
return -EINVAL;
if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
return 0;
c.list = list;
c.preproc = preproc;
c.preproc_data = preproc_data;
c.count = 0;
c.error = 0;
c.adev = adev;
status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
acpi_dev_process_resource, &c);
if (ACPI_FAILURE(status)) {
acpi_dev_free_resource_list(list);
return c.error ? c.error : -EIO;
}
return c.count;
}
可见也是通过acpi_walk_resources 来找_CRS,找到后调用acpi_dev_process_resource
static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
void *context)
{
struct res_proc_context *c = context;
struct resource_win win;
struct resource *res = &win.res;
int i;
if (c->preproc) {
int ret;
ret = c->preproc(ares, c->preproc_data);
if (ret < 0) {
c->error = ret;
return AE_CTRL_TERMINATE;
} else if (ret > 0) {
return AE_OK;
}
}
memset(&win, 0, sizeof(win));
if (acpi_dev_resource_memory(ares, res)
|| acpi_dev_resource_io(ares, res)
|| acpi_dev_resource_address_space(ares, &win)
|| acpi_dev_resource_ext_address_space(ares, &win))
return acpi_dev_new_resource_entry(&win, c);
for (i = 0; __acpi_dev_resource_interrupt(c->adev, ares, i, res); i++) {
acpi_status status;
status = acpi_dev_new_resource_entry(&win, c);
if (ACPI_FAILURE(status))
return status;
}
return AE_OK;
}
从acpi_dev_process_resource 中可以看出resource 基本分为两类
第一类是memory/io/address_space/ext_address_space 这类resource 会调用acpi_dev_new_resource_entry 来parse
第二类就是interrupt,调用acpi_dev_new_resource_entry 来parse
acpi_create_platform_device 中资源parse完成后填充platform_device_info
最后调用platform_device_register_full 来注册platform_device.这个返回返回的结果就是platform_device
module_platform_driver(v2_driver);
其实现如下:
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
继续看
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
可见就是平常我们用到的module_init,且在module_init中已经帮忙调用了platform_driver_register,多好啊,
那问题来了,到底是在哪里调用platform_device_register呢?
答案就是在acpi_create_platform_device
acpi_create_platform_device 一开始会调用(!acpi_match_device_ids(adev, forbidden_id_list)) 屏蔽某些driver,即不会
为这些driver 创建device.这些driver如下:
static const struct acpi_device_id forbidden_id_list[] = {
{"PNP0000", 0}, /* PIC */
{"PNP0100", 0}, /* Timer */
{"PNP0200", 0}, /* AT DMA Controller */
{"", 0},
};
其次会调用count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
来得到resource
int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
int (*preproc)(struct acpi_resource *, void *),
void *preproc_data)
{
struct res_proc_context c;
acpi_status status;
if (!adev || !adev->handle || !list_empty(list))
return -EINVAL;
if (!acpi_has_method(adev->handle, METHOD_NAME__CRS))
return 0;
c.list = list;
c.preproc = preproc;
c.preproc_data = preproc_data;
c.count = 0;
c.error = 0;
c.adev = adev;
status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
acpi_dev_process_resource, &c);
if (ACPI_FAILURE(status)) {
acpi_dev_free_resource_list(list);
return c.error ? c.error : -EIO;
}
return c.count;
}
可见也是通过acpi_walk_resources 来找_CRS,找到后调用acpi_dev_process_resource
static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
void *context)
{
struct res_proc_context *c = context;
struct resource_win win;
struct resource *res = &win.res;
int i;
if (c->preproc) {
int ret;
ret = c->preproc(ares, c->preproc_data);
if (ret < 0) {
c->error = ret;
return AE_CTRL_TERMINATE;
} else if (ret > 0) {
return AE_OK;
}
}
memset(&win, 0, sizeof(win));
if (acpi_dev_resource_memory(ares, res)
|| acpi_dev_resource_io(ares, res)
|| acpi_dev_resource_address_space(ares, &win)
|| acpi_dev_resource_ext_address_space(ares, &win))
return acpi_dev_new_resource_entry(&win, c);
for (i = 0; __acpi_dev_resource_interrupt(c->adev, ares, i, res); i++) {
acpi_status status;
status = acpi_dev_new_resource_entry(&win, c);
if (ACPI_FAILURE(status))
return status;
}
return AE_OK;
}
从acpi_dev_process_resource 中可以看出resource 基本分为两类
第一类是memory/io/address_space/ext_address_space 这类resource 会调用acpi_dev_new_resource_entry 来parse
第二类就是interrupt,调用acpi_dev_new_resource_entry 来parse
acpi_create_platform_device 中资源parse完成后填充platform_device_info
最后调用platform_device_register_full 来注册platform_device.这个返回返回的结果就是platform_device