芜湖到祁门汽车:linux driver 注册设备 platform_driver_register()
来源:百度文库 编辑:偶看新闻 时间:2024/04/27 07:26:03
platform_driver_register()
是来注册设备的驱动程序
platform_device_register()
是来注册设备硬件,告诉kernel,当前有什么设备
当某个设比connect后,必须在device和driver的两条线上都有匹配的东西后,才算是匹配上,并且开始使用driver的probe等函数进行硬件初始化工作。
以下来自:http://blog.21ic.com/user1/5823/archives/2009/60264.html
二、s3c2410fb_probe 函数分析
2.1 驱动的入口点
摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。这里就应该从long long ago开始了,打开drivers/video/s3c2410fb.c文件,然后找到s3c2410fb_init函数,先不管它里面是怎么回事,再把目光下移就会看到这样一串字符串module_init(s3c2410fb_init),郁闷,这和S3C2410fb_probe有啥关系嘛?这个问题问的好!不要着急慢慢往下面走。先摸摸module_init是何方神圣再说,于是乎我就登陆了http://lxr.linux.no/linux+v2.6.20/网站,在上面一搜,原来module_init老家在include/linux/init.h,原来它居然还有两重身份,其原型如下:
#ifndef MODULE
……
#define module_init(x) __initcall(x); ①
……
#else
……
#define module_init(initfn) \②
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((alias(#c)));
……
#endif
从上面可以看出,module_init到底用哪个,就取决于MODULE了,那么MODULE的作用是什么呢?我们知道Linux可以将设备当作模块动态加进内核,也可以直接编译进内核,说到这里大概有点明白MODULE的作用了,不错!它就是要控制一个驱动加入内核的方式。定义了MODULE就表示将设备当作模块动态加入。所以上面的①表示将设备加进内核。在②中的__attribute__((alias(#initfn)))很有意思,这代表什么呢?主要alias就是属性的意思,它的英文意思是别名,可以在http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/fn_attrib_alias.htm找到它的详细说明,这里简单的说int init_module(void) __attribute__((alias(#initfn)));的意思为init_module是initfn的别名,或者init_module是initfn的一个连接,再简单一点说这个时候module_init宏基因突变成了init_module()了。对于第一种情况,__initcall(fn) 又被宏定义成了device_initcall(fn),也就是说module_init(x)等于device_initcall(fn)。对于device_initcall(fn)又是一个宏定义,它被定义成了__define_initcall("6",fn,6),至于这个宏表示什么意思,在这里就不啰嗦重复了,在Linux-2.6.20的cs8900驱动分析(一)这篇文章中有对它的揭秘。
上面啰嗦了这么多,最终是要说明只要用module_init申明了一个函数,该函数就会被Linux内核在适当的时机运行,这些时机包括在linux启动的do_initcalls()时调用(设备被编译进内核),或者在动态插入时调用。
回到上面的module_init(s3c2410fb_init)处,也就是说内核与buffer驱动发生关系的第一次地点是在s3c2410fb_init函数,该函数就只有一条语句
platform_driver_register (&s3c2410fb_driver);??????……
2.2 platform是何许人也
platform可以理解成一种设备类型,就像字符设备、块设备和网络设备一样,而LCD就属于这种设备。对于platform设备Linux为应用添加了相关的接口,在这里只是简单的说说这些接口的用法,而不去深入探讨这些接口的实现(我现在还没有那个能力呢!)。说到这里,马上就有个问题涌上心头了,那就是Linux提供了那些接口呢?如果我们需要添加这些设备应该怎么样做呢?
platform中的相关数据结构是应用的关键,为了向内核添加一个platform设备,程序员应该填写两个数据结构platform_device 和platform_driver,这两个数据结构的定义都可以在include/linux/platform_device.h文件中找到。看看LCD驱动是怎么做的,第一步是填写platform_device,在arch/arm/mach-s3c2410/devs.c可以找到填写platform_device的代码,如下:
static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
struct platform_device s3c_device_lcd = {
.name = "s3c2410-lcd",
.id = -1,
.num_resources = ARRAY_SIZE (s3c_lcd_resource),
.resource = s3c_lcd_resource,
.dev = {
.dma_mask = &s3c_device_lcd_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
这里面的各个数据成员的意思,在platform_device数据结构中有详细的说明,这里不赘述。上面的代码中的ARRAY_SIZE宏还是比较有意思的,其实是个c的编程技巧,这个技巧很有用哦!可以在include/linux/kernel.h中找到它的定义:
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))该宏可以方便的求出一个数组中有多少数据成员,这在很多情况下是很有用的,比如对于 int a[]={1,5,65,23,12,20,3}数组,可以使用该宏求出a[]有7个元素。
另外,platform_device的另外一项重要成员是resource,在上面的代码中此域被赋予了s3c_lcd_resource,s3c_lcd_resource也可以在arch/arm/mach-s3c2410/devs.c找到。
static struct resource s3c_lcd_resource[] = {
[0] = {
.start = S3C24XX_PA_LCD,
.end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_LCD,
.end = IRQ_LCD,
.flags = IORESOURCE_IRQ,
}
};
struct resource结构实际上描述了该设备占用的硬件资源(如地址空间,中断号等s),s3c_lcd_resource描述了内存空间和中断分配情况。
最后在smdk2410_devices指针数组中添加上s3c_device_lcd的大名,Linux在初始化platform的时候就知道系统中有个s3c_device_lcd设备了。注意了这里只是向Linux描述了设备需要的资源情况,不代表内核会给这些资源的。如果设备要得到这些设备还需要在自己的初始化函数中去申请。
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_ts,
};
说到这里,应该说向Linux添加一个platform设备应该很容易。
2.2 回到s3c2410fb_init
终于把platform的相关知识啰嗦了一番,下面回到s3c2410fb_init函数所调用platform_driver_register(&s3c2410fb_driver)。简单地说platform_driver_register要将向内核注册一个platform设备的驱动,这里是要注册LCD设备。上面说过platform有两个重要的数据结构platform_device和platform_driver,现在是应该提到后者的时候了。platform_driver也在include/linux/platform_device.h中,它的各个成员应该再明白不过来吧!在LCD驱动程序(drivers/video/s3c2410fb.c)中定义了填充了platform_driver这个结构,如下:
static struct platform_driver s3c2410fb_driver = {
.probe = s3c2410fb_probe,
.remove = s3c2410fb_remove,
.suspend = s3c2410fb_suspend,
.resume = s3c2410fb_resume,
.driver = {
.name = "s3c2410-lcd",
.owner = THIS_MODULE,
},
};
可以看到该platform设备的驱动函数有s3c2410fb_probe、s3c2410fb_remove等等。通过platform_driver_register函数注册该设备的过程中,它会回调.probe函数,说到这里也就明白s3c2410fb_probe是在platform_driver_registe中回调的。到目前为止,经过二万五千里长征终于到达s3c2410fb_probe(LCD的驱动程序)了。
是来注册设备的驱动程序
platform_device_register()
是来注册设备硬件,告诉kernel,当前有什么设备
当某个设比connect后,必须在device和driver的两条线上都有匹配的东西后,才算是匹配上,并且开始使用driver的probe等函数进行硬件初始化工作。
以下来自:http://blog.21ic.com/user1/5823/archives/2009/60264.html
二、
摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。这里就应该从long long ago
#ifndef MODULE
……
#define module_init(x) __initcall(x);
……
#else
……
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((alias(#c)));
……
#endif
从上面可以看出,module_init
上面啰嗦了这么多,最终是要说明只要用module_init
回到上面的module_init(s3c2410fb_init)
platform_driver_register (&s3c2410fb_driver)
platform
platform
static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
struct platform_device s3c_device_lcd = {
.name = "s3c2410-lcd",
.id = -1,
.num_resources = ARRAY_SIZE (s3c_lcd_resource),
.resource = s3c_lcd_resource,
.dev = {
.dma_mask = &s3c_device_lcd_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
这里面的各个数据成员的意思,在platform_device
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
另外,platform_device
static struct resource s3c_lcd_resource[] = {
[0] = {
.start = S3C24XX_PA_LCD,
.end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_LCD,
.end = IRQ_LCD,
.flags = IORESOURCE_IRQ,
}
};
struct resource
最后在smdk2410_devices
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_ts,
};
说到这里,应该说向Linux
终于把platform
static struct platform_driver s3c2410fb_driver = {
.probe = s3c2410fb_probe,
.remove = s3c2410fb_remove,
.suspend = s3c2410fb_suspend,
.resume = s3c2410fb_resume,
.driver = {
.name = "s3c2410-lcd",
.owner = THIS_MODULE,
},
};
可以看到该platform
permeo-Driver-combo 注册方法
设备驱动程序Driver xml缺少配置文件
缺少设备驱动器driver xml配置文件
PL SQL Dev 7如何注册啊?
SoundMAX Integrated Digital Audio Driver V0.9.1 for Linux
我的设备管理器中有个memory technology driver是什么意思啊!
谁要考注册设备工程师
注册设备工程师考试
暖通注册公用设备工程师
注册公用设备师考试
在LINUX 平台上进行DRIVER 程序开发的公司有那些家
求助我的电脑没有pci设备,设备管理器里有个黄色问号的pci driver intel845p主板
设备管理器中intel(r) system management bios driver显示黄色感叹号是什么问题?
linux 怎么挂载USB接口的设备
linux中下面哪个是标准串口设备?
2006注册设备工程师江苏省报名时间
注册设备监理工程师的作用是什么?
2006年注册设备工程师人员名单
注册公用设备工程师有用吗
2006江西省注册设备工程师报名时间
gate-driver source driver
升级无限设备的driver后,重开机出现“104-unsupported wireless device”,无法进入WINXP。请教如何解决
我系统重装后就没声音了 声卡驱动找不到了 而且反应缺少设备驱动程序Driver XML 配置文件,这是怎么回事
PL是什么意思?