从platform驱动看驱动模型
2013-09-05 10:53
239 查看
从platform_driver看驱动模型,
一. device kset 和 bus kset
根据sys的结构图,我们知道,在sysfs中,首先注册的是bus,devices
而buses_init
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
该函数调用
Kset_create(name,uevent_ops,parent_kobj)
和
Kset_register(kset)
Kset_create(name,uevent_ops,parent_kobj)
简单的就是生成一个kset结构,
而Kset_register(kset)
就是将此kset注册(对于kset->kobj->kset为空的则,自己创建为kset头,否则将此kset添加入kset->kobj->kset所指向的kset链表)
Bus 总 kset
static struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
Device 总 kset
static struct kset_uevent_ops device_uevent_ops = {
.filter = dev_uevent_filter,
.name = dev_uevent_name,
.uevent = dev_uevent,
};
具体生成的bus_kset如下,
我们知道由kobject 决定了层次目录,以此为基础进行分析
二.platform bus 和device 已经目录下driver和device
Platform_bus
Platform_bus_init
---------àdevice_register(&platform_bus); 注册到device目录下
struct device platform_bus = {
.bus_id = "platform",
};
---------------àdevice_initialize(dev)
----------------àdevice_add(dev)
以kobject的层次决定目录,我们可以知道
Platform_bus这一device,其platform_bus->kobj->parent=device_kset->kobj
同时,能通过device_kset->kobj->list遍历整个所有的kobj,实际上与遍历文件一样
同时,根据kset容器的定义,可以知道kset目录下放置的全是device,而实际上这些device->kset=device_kset,
所以可以想象,device目录下的结构图为,
---------àbus_register(&platform_bus_type);注册到bus目录下
由于 bus总线下总是绑定着设备和驱动,这样就有了
bus_type_priveate->klist_devices和bus_type_private->klist_drivers
通过将总线上的device(实际只是链接关系,真正的device在device_kset下)通通添加到bus_type_private->klist_devices上,将总线上的驱动通通添加到bus_type_private->klist_drivers上
其中bus_type_priveate->device_kset对应的bus下的device目录
bus_type_private->driver_kset对应的bus下的driver目录
而显然,由目录关系我们知道
Bus_type_private->subsys->kobj->parent=bus_kset->kobj;
Bus_type_private->subsys->kobj->kset=bus_kset;
同时,能通过bus_kset->kobj->list遍历bus整个所有的kobj,实际上与遍历文件一样
而bus下的device目录(kset->parent=bus_type_private->subsys->kobj)
Driver目录(kset->parent=bus_type_private->kobj)
三.platform_driver_register,platform_device_register
以上两步之后,就等着设备和驱动来注册了
分别调用platform_driver_register,platform_device_register
Platform_device_register
static struct platform_device test_device={
.name="test_ts",
.id=-1;
}
If(!pdev->id!=-1)
Id=-1,表明设备只有一个,用设备名为bus_id,
就是将pdev->name赋值给pdev->dev.bus_id
而ID不为1,表明设备有多个,需要用序号来表明bus_id
pdev->dev.bus_id=pdev->name +‘.’+pdev->id
补充platform中资源的应用
简单的就是将对应资源添加到对应的资源树中
比如,
如果platform的资源r是IORESOUCE_MEM,则其parent resource p则为
Iomem_resouce
如果资源为IORESOUCE_IO,则为ioprot_resource
然后调用insert_resource(p,r)将资源添加到资源树中
struct resource iomem_resource = {
.name = "PCI mem",
.start = 0,
.end = -1,
.flags = IORESOURCE_MEM,
};
struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
在bus_attach_device中,先是检查属性文件drivers_autoprobe是否为1,
为1,则调用device_attach,
如果返回为大于等于0的值(未匹配成功),则将设备挂在bus的klist_device下,当驱动请求匹配的时候,platform bus总线就会遍历devices链表为驱动查找合适的设备。具体代码就是
Klist_add_tail(&dev->knode_bus,&bus->p->klist_devices)
对于device_attach,就是对所有的driver调用driver_probe_device,查找是否有匹配的driver
一般是先检测drv->bus->match是否存在,存在则调用(platform match 存在),match主要是检查driver和Device的name是否一样,如果一样则调用probe,否则继续查找
接着是检测drv->bus->probe是否存在,存在则调用(platform bus不存在),否则调用drv->probe,而drv->probe又会转而调用具体的platform_driver->probe
platform_driver_register
static struct platform_driver test_driver={
.probe = test_probe,
.remove =test_remove,
.driver={
.name="test_ts",
.owner=THIS_MODULE,
},
}
在platform_driver_register中,如果platform_driver定义了.Probe,
.remove,
则其内嵌的driver的probe和remove也会相应的设置platform对应的函数,从而能够调用platform_driver的probe和remove。
具体就是
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
driver_register(&drv->driver)
然后通过内嵌的driver调用driver_register进行注册
Driver_register的调用流程如下:
(1) 检测总线的操作函数和驱动的操作函数是否同时存在,同时存在,则使用总线提供的操作函数
(2) 检测是否已经注册过
(3) 添加驱动到总线上 bus_add_drv(drv)
(4) 添加驱动到组driver_add_groups(drv,drv->groups)
Bus_add_drv中,
主要在如果driver_autoprobe设置为1,则调用driver_attach(和device_attach类似),并且将驱动添加到klist_drivers中,
Klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers)
Module_add_driver(drv->owner,drv)// 与/sys/modules */ module_kset有关
经过这样之后,platform驱动模型就建立好了
四.文件的操作和ktype
上面说到的autoprobe的属性文件就是ktype提供的一种修改内核参数的方法。
建立属性文件autoprobe的方法不提,一般使用的sysfs_create_file
而通过系统的调用,文件的操作会调用sysfs_file_operation
const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
.open = sysfs_open_file,
.release = sysfs_release,
.poll = sysfs_poll,
};
在sysfs_open_file中,我们通过file找到sysfs_dirent,再由sysfs_dirent找到对应的kobj结构,(文件对应的kobj)
Struct sysfs_buffer *buffer;
Struct sysfs_ops *ops;
在该函数中,
这种重定向ops的方法,在讲ALSA驱动框架时,说到打开/dev/dsp也提到过。
Ktype作用正在于此
If(kobj->ktype&&kobj->ktype->sysfs_ops)
Ops=kobj->ktype->sysfs_ops;
…
然后将设置好的ops挂在在buffer上,
Buffer->ops=ops;
File->private_data=buffer;
而在sysfs_read_file和sysfs_write_file中,通过这种方式,一路跟踪,最后
分别调用了(对于bus的autoprobe文件而言)
Bus_attr->show(bus_priv->bus,buf)
Bus_attr->store(bus_priv->bus,buf)
这里就是在定义属性文件时提到的.show和.Store
总的来说基本上,驱动模型大致是这样,不过其中的class,uevent等没有细说
Copyright © 1999-2012, CSDN.NET, All Rights Reserved
查看所有通知
暂没有新通知
返回通知列表
下一条
上一条
您有0条新通知
一. device kset 和 bus kset
根据sys的结构图,我们知道,在sysfs中,首先注册的是bus,devices
而buses_init
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
该函数调用
Kset_create(name,uevent_ops,parent_kobj)
和
Kset_register(kset)
Kset_create(name,uevent_ops,parent_kobj)
简单的就是生成一个kset结构,
而Kset_register(kset)
就是将此kset注册(对于kset->kobj->kset为空的则,自己创建为kset头,否则将此kset添加入kset->kobj->kset所指向的kset链表)
Bus 总 kset
static struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
Device 总 kset
static struct kset_uevent_ops device_uevent_ops = {
.filter = dev_uevent_filter,
.name = dev_uevent_name,
.uevent = dev_uevent,
};
具体生成的bus_kset如下,
我们知道由kobject 决定了层次目录,以此为基础进行分析
二.platform bus 和device 已经目录下driver和device
Platform_bus
Platform_bus_init
---------àdevice_register(&platform_bus); 注册到device目录下
struct device platform_bus = {
.bus_id = "platform",
};
---------------àdevice_initialize(dev)
----------------àdevice_add(dev)
以kobject的层次决定目录,我们可以知道
Platform_bus这一device,其platform_bus->kobj->parent=device_kset->kobj
同时,能通过device_kset->kobj->list遍历整个所有的kobj,实际上与遍历文件一样
同时,根据kset容器的定义,可以知道kset目录下放置的全是device,而实际上这些device->kset=device_kset,
所以可以想象,device目录下的结构图为,
---------àbus_register(&platform_bus_type);注册到bus目录下
由于 bus总线下总是绑定着设备和驱动,这样就有了
bus_type_priveate->klist_devices和bus_type_private->klist_drivers
通过将总线上的device(实际只是链接关系,真正的device在device_kset下)通通添加到bus_type_private->klist_devices上,将总线上的驱动通通添加到bus_type_private->klist_drivers上
其中bus_type_priveate->device_kset对应的bus下的device目录
bus_type_private->driver_kset对应的bus下的driver目录
而显然,由目录关系我们知道
Bus_type_private->subsys->kobj->parent=bus_kset->kobj;
Bus_type_private->subsys->kobj->kset=bus_kset;
同时,能通过bus_kset->kobj->list遍历bus整个所有的kobj,实际上与遍历文件一样
而bus下的device目录(kset->parent=bus_type_private->subsys->kobj)
Driver目录(kset->parent=bus_type_private->kobj)
三.platform_driver_register,platform_device_register
以上两步之后,就等着设备和驱动来注册了
分别调用platform_driver_register,platform_device_register
Platform_device_register
static struct platform_device test_device={
.name="test_ts",
.id=-1;
}
If(!pdev->id!=-1)
Id=-1,表明设备只有一个,用设备名为bus_id,
就是将pdev->name赋值给pdev->dev.bus_id
而ID不为1,表明设备有多个,需要用序号来表明bus_id
pdev->dev.bus_id=pdev->name +‘.’+pdev->id
补充platform中资源的应用
简单的就是将对应资源添加到对应的资源树中
比如,
如果platform的资源r是IORESOUCE_MEM,则其parent resource p则为
Iomem_resouce
如果资源为IORESOUCE_IO,则为ioprot_resource
然后调用insert_resource(p,r)将资源添加到资源树中
struct resource iomem_resource = {
.name = "PCI mem",
.start = 0,
.end = -1,
.flags = IORESOURCE_MEM,
};
struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
在bus_attach_device中,先是检查属性文件drivers_autoprobe是否为1,
为1,则调用device_attach,
如果返回为大于等于0的值(未匹配成功),则将设备挂在bus的klist_device下,当驱动请求匹配的时候,platform bus总线就会遍历devices链表为驱动查找合适的设备。具体代码就是
Klist_add_tail(&dev->knode_bus,&bus->p->klist_devices)
对于device_attach,就是对所有的driver调用driver_probe_device,查找是否有匹配的driver
一般是先检测drv->bus->match是否存在,存在则调用(platform match 存在),match主要是检查driver和Device的name是否一样,如果一样则调用probe,否则继续查找
接着是检测drv->bus->probe是否存在,存在则调用(platform bus不存在),否则调用drv->probe,而drv->probe又会转而调用具体的platform_driver->probe
platform_driver_register
static struct platform_driver test_driver={
.probe = test_probe,
.remove =test_remove,
.driver={
.name="test_ts",
.owner=THIS_MODULE,
},
}
在platform_driver_register中,如果platform_driver定义了.Probe,
.remove,
则其内嵌的driver的probe和remove也会相应的设置platform对应的函数,从而能够调用platform_driver的probe和remove。
具体就是
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
driver_register(&drv->driver)
然后通过内嵌的driver调用driver_register进行注册
Driver_register的调用流程如下:
(1) 检测总线的操作函数和驱动的操作函数是否同时存在,同时存在,则使用总线提供的操作函数
(2) 检测是否已经注册过
(3) 添加驱动到总线上 bus_add_drv(drv)
(4) 添加驱动到组driver_add_groups(drv,drv->groups)
Bus_add_drv中,
主要在如果driver_autoprobe设置为1,则调用driver_attach(和device_attach类似),并且将驱动添加到klist_drivers中,
Klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers)
Module_add_driver(drv->owner,drv)// 与/sys/modules */ module_kset有关
经过这样之后,platform驱动模型就建立好了
四.文件的操作和ktype
上面说到的autoprobe的属性文件就是ktype提供的一种修改内核参数的方法。
建立属性文件autoprobe的方法不提,一般使用的sysfs_create_file
而通过系统的调用,文件的操作会调用sysfs_file_operation
const struct file_operations sysfs_file_operations = {
.read = sysfs_read_file,
.write = sysfs_write_file,
.llseek = generic_file_llseek,
.open = sysfs_open_file,
.release = sysfs_release,
.poll = sysfs_poll,
};
在sysfs_open_file中,我们通过file找到sysfs_dirent,再由sysfs_dirent找到对应的kobj结构,(文件对应的kobj)
Struct sysfs_buffer *buffer;
Struct sysfs_ops *ops;
在该函数中,
这种重定向ops的方法,在讲ALSA驱动框架时,说到打开/dev/dsp也提到过。
Ktype作用正在于此
If(kobj->ktype&&kobj->ktype->sysfs_ops)
Ops=kobj->ktype->sysfs_ops;
…
然后将设置好的ops挂在在buffer上,
Buffer->ops=ops;
File->private_data=buffer;
而在sysfs_read_file和sysfs_write_file中,通过这种方式,一路跟踪,最后
分别调用了(对于bus的autoprobe文件而言)
Bus_attr->show(bus_priv->bus,buf)
Bus_attr->store(bus_priv->bus,buf)
这里就是在定义属性文件时提到的.show和.Store
总的来说基本上,驱动模型大致是这样,不过其中的class,uevent等没有细说
Copyright © 1999-2012, CSDN.NET, All Rights Reserved
查看所有通知
暂没有新通知
返回通知列表
下一条
上一条
您有0条新通知
相关文章推荐
- linux驱动模型开发——linux platform总线机制讲解与实例开发
- linux驱动模型开发——linux platform总线机制讲解与实例开发
- 设备模型、设备与驱动关联的全过程分析 platform_device platform_driver driver bus关系
- 设备驱动模型第2节:platform_driver_register
- platform模型驱动中断和内存资源使用步骤
- 基于platform机制的驱动模型
- 详解Linux2.6内核中基于platform机制的驱动模型
- 基于platform机制的驱动模型
- 从串口驱动分析Platform驱动模型
- 详解Linux2.6内核中基于platform机制的驱动模型<强烈推荐,这是一篇学习驱动模型千年一遇的好文章>
- linux设备总线驱动模型 之 platform总线驱动
- Linux驱动设备模型之Platform
- Linux内核中platform驱动模型架构与dm9000网卡驱动移植
- 基于platform机制的驱动模型
- 从串口驱动分析Platform驱动模型
- linux驱动模型开发——linux platform总线机制讲解与实例开发
- linux platform 驱动模型分析
- 详解Linux2.6内核中基于platform机制的驱动模型
- 【linux设备模型】之platform设备驱动
- [linux driver]驱动模型中为什么用一个虚拟的platform_bus/device?