Chinaunix首页 | 论坛 | 博客
  • 博客访问: 569667
  • 博文数量: 70
  • 博客积分: 3736
  • 博客等级: 中校
  • 技术积分: 1728
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-08 09:15
文章分类
文章存档

2014年(1)

2012年(21)

2011年(7)

2010年(28)

2009年(13)

分类: LINUX

2010-01-30 13:53:08

paltform设备模型:
static int __init ixp4xx_ehci_init(void)
{
    int ret;
    struct platform_device *device;
    TRACE;
    pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
        ixp4xx_ehci_name,
        sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
        sizeof (struct ehci_itd), sizeof (struct ehci_sitd));

    /* Register device for usb host0 controller */

     TRACE;   
    device = &ixdp4xx_ehci_controller[0];
    ret = platform_device_register(device);
    if ( ret )
        goto error_on_dev_register;
    TRACE;
    if ( cpu_is_ixp43x() )  {
    /* Register device for usb host1 controller */
        ret = platform_device_register(++device);
        if ( ret )
            goto error_on_dev_register;
    }
    TRACE;    
    return driver_register(&ixp4xx_ehci_driver);
error_on_dev_register:
    printk(KERN_ERR "Error in register platform device %s%d\n",
        device->name, device->id );
    return ret;
}
ixp4xx_ehci_init()函数的流程如下:
1.ixp4xx_ehci_init()先调用platform_device_register(device)注册了一个platform device,
假如是ixp43x的arch,那么调用platform_device_register(++device)再注册一个platform device。这两个platform device的定义如下:
static struct platform_device ixdp4xx_ehci_controller[] =  {
    /* Host controller 0 */
    {
        .name        = IXP4XX_EHCI_NAME,
        .id        = 0,
        .dev = {
            .dma_mask               = &ehci_dma_mask,
            .coherent_dma_mask      = 0xffffffff,
        },
        .resource    = ixp4xx_ehci_host0_res,
        .num_resources    = 2,
    },
#ifdef CONFIG_CPU_IXP43X
    /* Host controller 1; only IXP435 has second host controller */
    {
        .name        = IXP4XX_EHCI_NAME,
        .id        = 1,
        .dev = {
            .dma_mask               = &ehci_dma_mask,
            .coherent_dma_mask      = 0xffffffff,
        },
        .resource    = ixp4xx_ehci_host1_res,
        .num_resources    = 2,
    }
#endif
};
这两个platform device和串口驱动里边定义的platform device没有什么特别之处,那么我们如何区分他们的功能,并让对应的驱动找到它们呢?答案是:加载驱动程序时将驱动程序和platform设备逐个比较,如果两者匹配,就使用这个驱动来作进一步的处理(即调用驱动的probe()函数)。是否匹配的判断方法是:platform设备的名称和驱动的名称。上面注册的两个设备的名称均为IXP4XX_EHCI_NAME。
#define IXP4XX_EHCI_NAME    "ixp4xx-ehci"
因为此时总线上还没有名称为"ixp4xx-ehci"的驱动,所以,什么都不作。
2.ixp4xx_ehci_init()最后一句代码为:
return driver_register(&ixp4xx_ehci_driver);
这句代码向系统注册了一个device driver
ixp4xx_ehci_driver的定义如下:
static struct device_driver ixp4xx_ehci_driver = {
    .name        = IXP4XX_EHCI_NAME,
    .bus        = &platform_bus_type,
    .probe        = ixp4xx_ehci_hcd_probe,
    .remove        = ixp4xx_ehci_hcd_remove,
};
这个驱动的名称为:IXP4XX_EHCI_NAME,跟上面注册的platform device的名称一样。于是,driver_register(&ixp4xx_ehci_driver);这个函数被调用的时候,会将ixp4xx_ehci_driver这个驱动和总线上所有的platform device进行逐个比较,它会发现,前面注册的两个platform device设备ixdp4xx_ehci_controller[2]刚好匹配,于是就会调用ixp4xx_ehci_driver->probe()进行进一步的探测。

我们可以看到的是,尽管我的代码从变量名称上看描述的是usb设备和usb驱动,但是,如果将名字换成其他的,你还能看出来么?所以,我想说的是,此处的设备注册(platform_device_register)和驱动注册只是一个构架,所有的platform设备和驱动都可以使用这个构架。那么不同platform设备和不同驱动的实现在哪里区分呢?
我想说的是:设备是个死的东西,是个事物,事物是有属性的,platform_device结构描述了所有platform设备都具有的属性;而设备驱动是有灵性的动物,是有思想的。正如不同的人对数字1的认识不同,不同的驱动对同一个platform_device结构的内容的解释也不同(当然设备毕竟是有区别的,所以我们使用设备名称来区分),这样才产生了形形色色、功能各异的活着的设备。所以,是驱动赋予设备以活力。而驱动赋予设备生命的方式是通过驱动的probe函数。

驱动程序的probe也仅仅是一个构架,针对此设备的更加具体的驱动会在probe函数中对应到此设备。
在usb主控制器驱动里,是hc_driver,它实现了针对usb主控制器设备的具体操作过程;
在8250驱动里,是uart_driver。此结构又封装了tty_driver。
而对于一些比较简单的驱动则不会在probe里边调用更加具体的驱动,在probe里边就会完成设备的初始化等。
比如:
ixp4xx_ehci_hcd_probe()的实现如下:
static int ixp4xx_ehci_hcd_probe(struct device *dev)
{
    TRACE;   
    struct hc_driver const *driver = &ixp4xx_ehci_hc_driver;
    //hc_driver是对usb driver的一个更细致的划分,是usb主控控制器驱动
    //此驱动将承担具体的操作前面注册的usb ehci主控制器(ixdp4xx_ehci_controller)的任务
    struct platform_device *pdev = to_platform_device(dev);
    //此处的pdev结构指向上述platform device结构中的一个:
    //ixdp4xx_ehci_controller[0]或ixdp4xx_ehci_controller[1].
    int    retval = 0;
    struct usb_hcd *hcd = 0;
    char   name[20];
    TRACE;   
    if (usb_disabled())
        return -ENODEV;

    if ( pdev->num_resources != 2 ||
         pdev->resource[0].flags != IORESOURCE_MEM ||
         pdev->resource[1].flags != IORESOURCE_IRQ)  {
        dev_err(&pdev->dev, "invalid resource specified\n");
        return -ENODEV;
    }
    TRACE;   
    strncpy(name, pdev->name, sizeof(name)-2);
    name[sizeof(name)-2] = '\0';
    sprintf(name+strlen(name), "%d", pdev->id);
    hcd = usb_create_hcd (driver, &pdev->dev, name);
    if (!hcd) {
        dev_err(&pdev->dev, "usb_create_hcd failed\n");
        return -ENOMEM;
    }
    hcd->rsrc_start = pdev->resource[0].start;
    hcd->rsrc_len   = pdev->resource[0].end - pdev->resource[0].start + 1;
    if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len, name))  {
        dev_dbg (&pdev->dev, "controller already in use\n");
        retval = -EBUSY;
        goto err1;
    }
    hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
    if ( hcd->regs == NULL ) {
            dev_dbg (&pdev->dev, "error mapping memory\n");
        retval = -EFAULT;
        goto err2;
    }
    //对设备需要的资源进行评估,检测,看能否满足其需要
    writel(USBMODE_BE | USBMODE_HOST, hcd->regs + USBMODE); /* BE, Host only */
    TRACE;   
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
        printk(KERN_INFO "\npdev->resource[1].start=%d\n",pdev->resource[1].start);
             retval = usb_add_hcd (hcd, pdev->resource[1].start, IRQF_SHARED);
#else
             retval = usb_add_hcd (hcd, pdev->resource[1].start, SA_SHIRQ);
#endif
    TRACE;   
    if (retval != 0)
        goto err3;
    return retval;

 err3:
    iounmap(hcd->regs);
 err2:
    release_mem_region(hcd->rsrc_start, hcd->rsrc_len);

 err1:
     usb_put_hcd (hcd);
    dev_err (&pdev->dev, "init %s fail, %d\n", name, retval);
    return retval;
}

ixp4xx_ehci_hc_driver的定义如下:
static const struct hc_driver ixp4xx_ehci_hc_driver = {
    .description =        IXP4XX_HCD_DESC,
    .product_desc =        "IXP4XX EHCI Host Controller",
    .hcd_priv_size =    sizeof(struct ehci_hcd),

    /*
     * generic hardware linkage
     */
    .irq =            ehci_irq,
    .flags =        HCD_MEMORY | HCD_USB2,

    /*
     * basic lifecycle operations
     */
    .reset =        ehci_ixp4xx_setup,
    .start =        ehci_run,
    .stop =            ehci_stop,
    .shutdown =        ehci_shutdown,

    /*
     * managing i/o requests and associated device resources
     */
    .urb_enqueue =        ehci_urb_enqueue,
    .urb_dequeue =        ehci_urb_dequeue,
    .endpoint_disable =    ehci_endpoint_disable,

    /*
     * scheduling support
     */
    .get_frame_number =    ehci_get_frame,

    /*
     * root hub support
     */
    .hub_status_data =    ehci_hub_status_data,
    .hub_control =        ehci_hub_control,
#ifdef    CONFIG_USB_SUSPEND
    .hub_suspend =        ehci_hub_suspend,
    .hub_resume =        ehci_hub_resume,
#endif
    /*.start_port_reset =    ehci_start_port_reset,*/
    .bus_suspend =        ehci_bus_suspend,
    .bus_resume =        ehci_bus_resume,
};


阅读(1579) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~