平台总线设备驱动模型——基础知识

来源:互联网 发布:seo推广学院招聘 编辑:程序博客网 时间:2024/06/13 12:47
平台总线设备驱动程序采用了分层分离的机制,我们先简述一下其大体上的原理,然后在从具体代码出发进行分析。
大体原理:在内核中存在平台设备总线,我们要把设备挂载到总线设备列表中,同时也要把驱动挂在到总线驱动列表中,但是相匹配的设备和驱动的名字要保持一致,因为总线会根据设备和驱动的名字是否一致,来决定他们是否匹配,一旦设备和驱动匹配起来,就会调用驱动程序里的probe函数进行处理。
代码分析,以/dirvers/mtd/nand/s3c2410.c为例来分析:
          platform_driver_register(&s3c2410_nand_driver);//驱动名为s3c2410-nand          drv->driver.bus = &platform_bus_type;//platform_bus_type里存在match函数,待会会分析          driver_register(&drv->driver);                     bus_add_driver(drv);//将驱动添加到平台总线驱动列表中我们搜索名“s3c2410-nand”的设备,最终在/arch/arm/plat-s3c24xx/devs.c中发现了线索:        struct platform_device s3c_device_nand = {        .name = "s3c2410-nand",        .id = -1,        .num_resources = ARRAY_SIZE(s3c_nand_resource),        .resource = s3c_nand_resource,        };那么这个设备是如何添加到总线上的呢?         .init_machine = osiris_init,         platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));//关于osiris_devices的定义见注释1         platform_device_register(devs[i]);         platform_device_add(pdev);         device_add(&pdev->dev);//将设备添加到总线
这样设备和驱动都注册到了总线上面,那么总线要做什么呢?
我们还记得注册驱动的时候有这么一句吧:   
   drv->driver.bus = &platform_bus_type;
我们来看看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,       };
这里面有match函数,总线就是根据这个函数来判断设备和驱动是否匹配的,我们来看一下代码:
 static int platform_match(struct device * dev, struct device_driver * drv)    {    struct platform_device *pdev = container_of(dev, struct platform_device, dev);    return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);    }
我们看到了,确实是根据驱动和设备的名字是否一致,来判断是否匹配的。
一旦匹配就会调用probe函数。
注释1: 
    static struct platform_device *osiris_devices[] __initdata = {    &s3c_device_i2c,    &s3c_device_wdt,    &s3c_device_nand,    &osiris_pcmcia,    };

疑问?
我水比较差,只能分析到这个地步了,下面是我的几点疑问,希望大家帮我一下好吗:
(1)我搜遍了代码也没有发现有谁调用了match函数,那么这个函数怎么被执行呢?
(2)为什么match成功后会调用probe函数呢?它也没有在哪个函数里面被调用啊!
(3)
int platform_driver_register(struct platform_driver *drv){drv->driver.bus = &platform_bus_type;if (drv->probe)drv->driver.probe = 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);}


 

为什么一旦设置了 drv->probe就要自动设置drv->driver.probe = platform_drv_probe;?drv.probe和drv->driver.probe两个probe有什么区别啊?

(4)
MACHINE_START(OSIRIS, "Simtec-OSIRIS")/* Maintainer: Ben Dooks <ben@simtec.co.uk> */.phys_io= S3C2410_PA_UART,.io_pg_offst= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,.boot_params= S3C2410_SDRAM_PA + 0x100,.map_io= osiris_map_io,.init_machine= osiris_init,.init_irq= s3c24xx_init_irq,.init_machine= osiris_init,.timer= &s3c24xx_timer,MACHINE_END
这之间的代码何时被执行?