




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一:前言Platform总线是kernel中最近加入的一种虚拟总线.在近版的2.6kernel中,很多驱动都用platform改写了.只有在分析完platform总线之后,才能继续深入下去分析.在分析完sysfs和设备驱动模型之后,这部份应该很简单了.闲言少叙.步入正题.GO.GO!以下的源代码分析是基于2.6.25的.二:platform概貌在分析源代码之前,先在内核代码中找一个platform架构的驱动程序.下面以i8042芯片的驱动为例进行分析.在linux-2.6.25/drivers/input/serio/i8042.c的intel 8042的初始化入口中,有以下代码分段:static int _init i8042_init(void) err = platform_driver_register(&i8042_driver); if (err) goto err_platform_exit; i8042_platform_device = platform_device_alloc(i8042, -1); if (!i8042_platform_device) err = -ENOMEM; goto err_unregister_driver; err = platform_device_add(i8042_platform_device); if (err) goto err_free_device; 我们在上面的程序片段中看到,驱动程序先注册了一个platform device.然后又添加了一个platform device.这里就涉及到了platform的两个最主要的操作,一个设备驱动注册,一个设备注册.要了解platform总线的来龙去脉.得从它的初始化开始.三:platform初始化Platform总线的初始化是在linux-2.6.25/drivers/base/platform.c中的platform_bus_init()完成的,代码如下:int _init platform_bus_init(void) int error; error = device_register(&platform_bus); if (error) return error; error = bus_register(&platform_bus_type); if (error) device_unregister(&platform_bus); return error;上面代码中调用的子函数在中已经分析过了.这段初始化代码创建了一个名为 “platform”的设备.后续platform的设备都会以此为parent.在sysfs中表示为:所有platform类型的设备都会添加在platform_bus所代码的目录下.即 /sys/devices/platform下面.接着,这段初始化代码又创建了一个名为“platform”的总线.platform_bus_type的定义如下:struct bus_type platform_bus_type = .name = platform, .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .suspend = platform_suspend, .suspend_late = platform_suspend_late, .resume_early = platform_resume_early, .resume = platform_resume,;我们知道,在bus_type中包含了诸如设备与驱动匹配.hotplug事件等很多重要的操作.这些操作在分析platform设备注册与platform驱动注册的时候依次分析.四:platform device注册在intel 8042的驱动代码中,我们看到注册一个platform device分为了两部分,一部份是创建一个platform device结构,另一部份是将其注册到总线中.先来看第一个接口.struct platform_device *platform_device_alloc(const char *name, int id) struct platform_object *pa; pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); if (pa) strcpy(pa-name, name); = pa-name; pa-pdev.id = id; device_initialize(&pa-pdev.dev); pa-pdev.dev.release = platform_device_release; return pa ? &pa-pdev : NULL;这段代码主要初始化了封装在struct platform_object中的struct device.Struct platform_object结构定义如下:struct platform_object struct platform_device pdev; char name1;在定义中,定义name为一个长度.所以,才有了platform_device_alloc()中分配struct platform_object的时候多加了名称的长度:pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);struct device结构如下:struct platform_device const char * name; int id; struct device dev; u32 num_resources; struct resource * resource;在这个结构里封装了struct device.struct resource. struct resource这个结构在此之前没有接触过,这个结构表示设备所拥有的资源.即I/O端口或者是I/O映射内存.platform_device_add()代码分段分析如下:int platform_device_add(struct platform_device *pdev) int i, ret = 0; if (!pdev) return -EINVAL; if (!pdev-dev.parent) pdev-dev.parent = &platform_bus; pdev-dev.bus = &platform_bus_type;初始化设备的parent为platform_bus.初始化驱备的总线为platform_bus_type.回忆platform初始化的时候.这两个东东这里终于派上用场了. if (pdev-id != -1) snprintf(pdev-dev.bus_id, BUS_ID_SIZE, %s.%d, pdev-name, pdev-id); else strlcpy(pdev-dev.bus_id, pdev-name, BUS_ID_SIZE);设置设备struct device 的bus_id成员.留心这个地方,在以后还需要用到这个的. for (i = 0; i num_resources; i+) struct resource *p, *r = &pdev-resourcei; if (r-name = NULL) r-name = pdev-dev.bus_id; p = r-parent; if (!p) if (r-flags & IORESOURCE_MEM) p = &iomem_resource; else if (r-flags & IORESOURCE_IO) p = &ioport_resource; if (p & insert_resource(p, r) printk(KERN_ERR %s: failed to claim resource %dn, pdev-dev.bus_id, i); ret = -EBUSY; goto failed; 如果设备指定了它所拥有的资源,将这些资源分配给它.如果分配失败,则失败退出.从代码中可以看出.如果struct resource的flags域被指定为IORESOURCE_MEM.则所表示的资源为I/O映射内存.如果指定为IORESOURCE_IO.则所表示的资源为I/O端口. pr_debug(Registering platform device %s. Parent at %sn, pdev-dev.bus_id, pdev-dev.parent-bus_id); ret = device_add(&pdev-dev); if (ret = 0) return ret;failed: while (-i = 0) if (pdev-resourcei.flags & (IORESOURCE_MEM|IORESOURCE_IO) release_resource(&pdev-resourcei); return ret;device_add()已经很熟悉了吧.没错,它就是将设备注册到指定的bus_type.在分析linux设备模型的时候,曾说过.调用device_add()会产生一个hotplug事件.platform device的hotplug与一般的device事件相比.它还要它所属bus_type的uevent().对这个流程不熟悉的可以参照.platform device所属的bus_type为platform_bus_type.它的uevent()接口代码如下:static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) struct platform_device *pdev = to_platform_device(dev); add_uevent_var(env, MODALIAS=platform:%s, pdev-name); return 0;上面的代码很简单,它就是在环境变量中添加一项MODALIAS.五:platform driver的注册在intel 8024的驱动代码中看到.platform driver注册的接口为:int platform_driver_register(struct platform_driver *drv) drv-driver.bus = &platform_bus_type; if (drv-probe) be = platform_drv_probe; if (drv-remove) drv-driver.remove = platform_drv_remove; if (drv-shutdown) drv-driver.shutdown = platform_drv_shutdown; if (drv-suspend) drv-driver.suspend = platform_drv_suspend; if (drv-resume) drv-driver.resume = platform_drv_resume; return driver_register(&drv-driver);struct platform_driver主要封装了struct device_driver结构.如下:struct platform_driver int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver;在这个接口里,它指定platform driver的所属总线.如果在struct platform_driver指定了各项接口的操作,就会为struct device_driver中的相应接口赋值.不要被上面的platform_drv_XXX吓倒了,它们其实很简单,就是将struct device转换为struct platform_device和struct platform_driver.然后调用platform_driver中的相应接口函数最后, platform_driver_register()将驱动注册到总线上.这样,总线上有设备,又有驱动,就会进行设备与匹配的过程,调用的相应接口为:bus -match - bus-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 数学专业考研试题及答案
- 电热专业试题题库及答案
- 农机专业试题及答案要点
- 专业基础知识试题及答案
- 煤矿专业试题及答案
- 安装专业试题及答案
- 广西2025-2026学年七年级语文上学期第一次月考复习试卷(含答案)
- 铝单板凉亭施工方案
- 品牌线下活动策划方案公司
- 泥灰被雨季施工方案
- (高清版)DZT 0216-2020 煤层气储量估算规范
- 人教版四年级上册语文第一单元测试题(含答案)
- 储能电站项目建设流程详解
- 供应商尽职调查模板
- 饮用水配送方案
- 妊娠滋养细胞肿瘤护理查房课件
- 磁粉检测课件
- 日本银行业历史复盘与启示
- 有效管理的5大兵法学习分享-20.2.4
- 2022年湖北统招专升本英语真题带答案
- :广西普通本科高校、高等职业学校国家助学金申请表(电子版和打印纸质版)
评论
0/150
提交评论