免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1042 | 回复: 0
打印 上一主题 下一主题

linux 驱动分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-27 14:15 |只看该作者 |倒序浏览

                                Linux驱动分析
总的来说,linux
2.6以后的内核,其驱动部分,可以分为三大主要部分,分别为,1.linux 驱动模型,2.linux 设备,3.linux
驱动 1.linux
驱动模型的相应数据结构,主要包括,底层的,用来组成/sys/文件系统的,kobject,
kset,subsystem.和上层用来抽象设备,驱动,总线的,device,device_driver,bus.等
等。   
接下来,我们主要分析,linux 是如何建立驱动模型的。在
init.c:
/** *    driver_init - initialize driver model.
* *    Call the driver model init functions to initialize their
*    subsystems. Called early from init/main.c.
*/
void __init driver_init(void){   
/* These are the core pieces */   
devices_init();   
buses_init();   
classes_init();   
firmware_init();   
/* These are also core pieces, but must come after the     
* core core pieces.     */  
  
platform_bus_init();   
system_bus_init();   
cpu_dev_init();   
attribute_container_init();}
2.linux 设备 为例在2.6内核中将每个设备的资源用结构platform_device来描述,该结构体定义在kernel\include\linux\platform_device.h中,
struct platform_device
{
const char * name;
u32    id;
struct device dev;
u32    num_resources;
struct resource * resource;
};
该结构一个重要的元素是resource,该元素存入了最为重要的设备资源信息,定义在kernel\include\linux\ioport.h中,
struct resource {
const char *name;
unsigned long start, end;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
下面举个例子来说明一下:
在kernel\arch\arm\mach-pxa\pxa27x.c定义了
tatic struct resource pxa27x_ohci_resources[] = {
[0] = {
    .start    = 0x4C000000,
   
.end      = 0x4C00ff6f,
   
.flags    = IORESOURCE_MEM,
},
[1] = {
    .start    = IRQ_USBH1,
   
.end      = IRQ_USBH1,
   
.flags    = IORESOURCE_IRQ,
},
};
这里定义了两组resource,它描述了一个usb host设备的资源,第1组描述了这个usb host设备所占用的
总线地址范围,IORESOURCE_MEM表示第1组描述的是内存类型的资源信息,第2组描述了这个usb host设备
的中断号,IORESOURCE_IRQ表示第2组描述的是中断资源信息。设备驱动会根据flags来获取相应的资源信息。
有了resource信息,就可以定义platform_device了:
static struct platform_device ohci_device =
{
.name    = "pxa27x-ohci",
.id    = -1,
.dev    = {
  
.dma_mask = &pxa27x_dmamask,
   
.coherent_dma_mask = 0xffffffff,
},
.num_resources    = ARRAY_SIZE(pxa27x_ohci_resources),
.resource         = pxa27x_ohci_resources,
};
有了platform_device就可以调用函数platform_add_devices向系统中添加该设备了,这里的实现是
static int __init pxa27x_init(void)
{
return platform_add_devices(devices, ARRAY_SIZE(devices));
}
platform_add_devices 的情景分析
platform_add_devices=>device_register(&pdev->dev);
                      device_register=>device_add(dev);
                          
                                       device_add=>bus_add_device(dev);
接下来,我们详细看一下 bus_add_device 这个函数
        list_add_tail(&dev->bus_list, &dev->bus->devices.list);
        device_attach(dev);
        up_write(&dev->bus->subsys.rwsem);
        device_add_attrs(bus, dev);
        sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
bus_add_device=>device_attach
    if (dev->driver) {
        device_bind_driver(dev);
        return 1;
    }
    if (bus->match) {
        list_for_each(entry, &bus->drivers.list) {
            struct device_driver * drv = to_drv(entry);
            error = driver_probe_device(drv, dev);
            if (!error)
                /* success, driver matched */
                return 1;
            if (error != -ENODEV && error != -ENXIO)
                /* driver matched but the probe failed */
                printk(KERN_WARNING
                    "%s: probe of %s failed with error %d\n",
                    drv->name, dev->bus_id, error);
        }
    }
device_attach=>device_bind_driver:
   
   list_add_tail(&dev->driver_list, &dev->driver->devices);
    sysfs_create_link(&dev->driver->kobj, &dev->kobj,
              kobject_name(&dev->kobj));
    sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
我以 platform device serial_8250 为例 说明一下两个 sysfs_create_link 函数,反映在 sysfs文件系统上实质现象。
steven@steven-laptop:/sys/bus/platform/drivers/serial8250$ ls -l
total 0
--w------- 1 root root 4096 2009-06-29 00:08 bind
lrwxrwxrwx 1 root root    0 2009-06-29 00:08 serial8250 -> ../../../../devices/platform/serial8250
--w------- 1 root root 4096 2009-06-29 00:08 uevent
--w------- 1 root root 4096 2009-06-29 00:08 unbind
steven@steven-laptop:/sys/bus/platform/drivers/serial8250$ cd /sys/devices/platform/serial8250/
steven@steven-laptop:/sys/devices/platform/serial8250$ ls
driver  modalias  power  subsystem  tty  uevent
steven@steven-laptop:/sys/devices/platform/serial8250$ ls -l
total 0
lrwxrwxrwx 1 root root    0 2009-06-29 00:13 driver -> ../../../bus/platform/drivers/serial8250
-r--r--r-- 1 root root 4096 2009-06-29 00:13 modalias
drwxr-xr-x 2 root root    0 2009-06-29 00:13 power
lrwxrwxrwx 1 root root    0 2009-06-29 00:13 subsystem -> ../../../bus/platform
drwxr-xr-x 6 root root    0 2009-06-29 00:13 tty
-rw-r--r-- 1 root root 4096 2009-06-29 00:13 uevent
steven@steven-laptop:/sys/devices/platform/serial8250$
这里的pxa27x_init必须在设备驱动加载之前被调用,可以把它放到
subsys_initcall(pxa27x_init);
关于 subsys_initcall 参考 说说subsys_initcall3.linux 驱动
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/98875/showart_1979342.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP