s3c2440 OHCI驱动的一些函数

 q_descr, hcd)) != 0) {

            dev_err(hcd->self.controller,

                    "request interrupt %d failed\n", irqnum);

            goto err_request_irq;

        }

        hcd->irq = irqnum;

        dev_info(hcd->self.controller, "irq %d, %s 0xllx\n", irqnum,

                (hcd->driver->flags & HCD_MEMORY) ?

                    "io mem" : "io base",

                    (unsigned long long)hcd->rsrc_start);

    } else {

        hcd->irq = -1;

        if (hcd->rsrc_start)

            dev_info(hcd->self.controller, "%s 0xllx\n",

                    (hcd->driver->flags & HCD_MEMORY) ?

                    "io mem" : "io base",

                    (unsigned long long)hcd->rsrc_start);

    }

 

    if ((retval = hcd->driver->start(hcd)) < 0) {

        dev_err(hcd->self.controller, "startup error %d\n", retval);

        goto err_hcd_driver_start;

    }

 

   

    设置root_hub的电流

    rhdev->bus_mA = min(500u, hcd->power_budget);

这里就是重点的。开始注册这个root_hub

开始建立了这设备树,然后调用usb_new_device()注册这的USB设备

    if ((retval = register_root_hub(hcd)) != 0)

        goto err_register_root_hub;

    创建总线属性文件authorized_default。

    retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);

    if (retval < 0) {

        printk(KERN_ERR "Cannot register USB bus sysfs attributes: %d\n",

               retval);

        goto error_create_attr_group;

    }

    if (hcd->uses_new_polling && hcd->poll_rh)

        usb_hcd_poll_rh_status(hcd);

    return retval;

 

error_create_attr_group:

    mutex_lock(&usb_bus_list_lock);

    usb_disconnect(&hcd->self.root_hub);

    mutex_unlock(&usb_bus_list_lock);

err_register_root_hub:

    hcd->driver->stop(hcd);

err_hcd_driver_start:

    if (hcd->irq >= 0)

        free_irq(irqnum, hcd);

err_request_irq:

err_hcd_driver_setup:

    hcd->self.root_hub = NULL;

    usb_put_dev(rhdev);

err_allocate_root_hub:

    usb_deregister_bus(&hcd->self);

err_register_bus:

    hcd_buffer_destroy(hcd);

    return retval;

}

 

 

下面具体分析一些hcd_buffer_create()

说到这个函数,我们可以简单分析一下整个USB系统使用的DMA内存技术

相关的函数有hcd_buffer_create()hcd_buffer_destroy()hcd_buffer_alloc()hcd_buffer_free()

这个几个函数是成对的。

static const size_t   pool_max [HCD_BUFFER_POOLS] = {

   

    32,

    128,

    512,

    PAGE_SIZE / 2

   

};

int hcd_buffer_create(struct usb_hcd *hcd)

{

    char     name[16];

    int       i, size;

 

    if (!hcd->self.controller->dma_mask &&

        !(hcd->driver->flags & HCD_LOCAL_MEM))

        return 0;

 

    for (i = 0; i < HCD_BUFFER_POOLS; i++) {

        size = pool_max[i];

        if (!size)

            continue;

        snprintf(name, sizeof name, "buffer-%d", size);

        hcd->pool[i] = dma_pool_create(name, hcd->self.controller,

                size, size, 0);

        if (!hcd->pool [i]) {

            hcd_buffer_destroy(hcd);

            return -ENOMEM;

        }

    }

    return 0;

}

参数hcd 是为哪个控制器创建一致性DMA内存。dma_pool_create()创建了四个一致性DMA内存,返回的是这四个不同大小的内存池的地址,分别赋值给hcd->pool[0],hcd->pool[1],hcd->pool[2],hcd->pool[3]。

既然分配就有释放hcd_buffer_destroy()。这个函数就是干这个活得。

内存池创建了,那就有分配

hcd_buffer_alloc() 就是从刚创建的内存池中获取。

void *hcd_buffer_alloc(

    struct usb_bus   *bus,

    size_t          size,

    gfp_t           mem_flags,

    dma_addr_t        *dma

)

{

    struct usb_hcd        *hcd = bus_to_hcd(bus);

    int           i;

 

   

    if (!bus->controller->dma_mask &&

        !(hcd->driver->flags & HCD_LOCAL_MEM)) {

        *dma = ~(dma_addr_t) 0;

        return kmalloc(size, mem_flags);

    }

 

    for (i = 0; i < HCD_BUFFER_POOLS; i++) {

        if (size <= pool_max [i])

            return dma_pool_alloc(hcd->pool [i], mem_flags, dma);

    }

    return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags);

}

先看下参数:

bus :我们之前说了,一条usb总线对应一个主机控制器。

size :需要的这个buffer多大

mem_flags :这个不用看都知道是干什么的了,gfp_t 分配内存的标志

dma :DMA总线地址,是给设备用的。调用了这个函数后这个BUFFER的总线地址就会传递给这个参数。

函数中先判断是否设备支持DMA传输,如果不支持,那么就是用PIO吧。否则进入一个for循环。判断申请的buffer是否小于内存池的大小。如果大于了,当然没法获取了。所以就只能是用另外一个函数dma_alloc_coherent()申请一致性一致性DMA内存.

最后这个返回的是一个虚拟地址,给内核空间使用的。这样设备就能和内核空间传递数据了。

 

 

 

过来详细的而说下usb_register_bus()

static int usb_register_bus(struct usb_bus *bus)

{

    int result = -E2BIG;

    int busnum;

 

    mutex_lock(&usb_bus_list_lock);

    busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);

    if (busnum >= USB_MAXBUS) {

        printk (KERN_ERR "%s: too many buses\n", usbcore_name);

        goto error_find_busnum;

    }

    set_bit (busnum, busmap.busmap);

    bus->busnum = busnum;

 

   

    list_add (&bus->bus_list, &usb_bus_list);

    mutex_unlock(&usb_bus_list_lock);

 

    usb_notify_add_bus(bus);

 

    dev_info (bus->controller, "new USB bus registered, assigned bus "

          "number %d\n", bus->busnum);

    return 0;

 

error_find_busnum:

    mutex_unlock(&usb_bus_list_lock);

    return result;

}

#define USB_MAXBUS      64

struct usb_busmap {

    unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];

};

static struct usb_busmap busmap;

先前简单的说了下这个函数的作用。

我们知道sizeof (unsigned long)的值是4.所以static struct usb_busmap busmap;

 可以写成这样

struct usb_busmap {

    unsigned long busmap [2];

};

所以busmap[2]有64位。每一位表示一条总线。假如说第5位置一了,那么USB_BUS

成员就busnum就为5.

当我们注册一条USB总线的时候,先在这个位图中找到一个第一个不为0的位赋值给busnum.并且把usb_bus的bus_list加到usb_bus_list链表头usb_notify_add_bus()的作用是在SYS文件系统上建立相关的信息。这个通知链是在USB系统初始化的时候注册的。

 

接下来是usb_alloc_dev()函数。这个函数很长。

usb_alloc_dev(NULL, &hcd->self, 0)

第一个参数是HULL,因为是root_hub。所以它处于金字塔的最顶端,它没有parent.第二个参数是这个设备所在的总线。第三个参数是0.一样,root_hub 忽略该位。

下面是整个函数

struct usb_device *usb_alloc_dev(struct usb_device *parent,

                 struct usb_bus *bus, unsigned port1)

{

    struct usb_device *dev;

    struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);

    unsigned root_hub = 0;

 

    dev = kzalloc(sizeof(*dev), GFP_KERNEL);

    if (!dev)

        return NULL;

  增加hcd的也引用计数

    if (!usb_get_hcd(bus_to_hcd(bus))) {

        kfree(dev);

        return NULL;

    }

   

    if (usb_hcd->driver->alloc_dev && parent &&

        !usb_hcd->driver->alloc_dev(usb_hcd, dev)) {

        usb_put_hcd(bus_to_hcd(bus)); 增加hcd的也引用计数

        kfree(dev);

        return NULL;

    }

 

    device_initialize(&dev->dev);设备模型的dev初始化

    dev->dev.bus = &usb_bus_type;

    dev->dev.type = &usb_device_type;

    dev->dev.groups = usb_device_groups;

    dev->dev.dma_mask = bus->controller->dma_mask;

    set_dev_node(&dev->dev, dev_to_node(bus->controller));

    dev->state = USB_STATE_ATTACHED;

    atomic_set(&dev->urbnum, 0);

 

    INIT_LIST_HEAD(&dev->ep0.urb_list);

    dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;

    dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;

   

第三个参数为false时不会复位这个端点。第二个参数是端点usb_host_endpoint。通过一系列的判断,完善参数一的    struct usb_host_endpoint *ep_in[16];

    struct usb_host_endpoint *ep_out[16];这个两个指针数组。在这个上下文中是完善ep_out[0],ep_int[0].

    usb_enable_endpoint(dev, &dev->ep0, false);

 

    dev->can_submit = 1;

 

   

是root_hub就会运行这行 

if (unlikely(!parent)) {

        dev->devpath[0] = '0';

        dev->route = 0;

 

        dev->dev.parent = bus->controller;

        dev_set_name(&dev->dev, "usb%d", bus->busnum);

在SYS文件系统的sys/bus/usb/ 下会出现usb1.因为只有一条总线

        root_hub = 1;

    } else {

       

    设备接在root_hub运行这里

        if (parent->devpath[0] == '0') {

            snprintf(dev->devpath, sizeof dev->devpath,

                "%d", port1);

           

            dev->route = 0;

        } else {在我的板上不会运行这里,因为我没接集线器,这里运行时因为设备接在某个集线器上

            snprintf(dev->devpath, sizeof dev->devpath,

                "%s.%d", parent->devpath, port1);

           

            if (port1 < 15)

                dev->route = parent->route +

                    (port1 << ((parent->level - 1)*4));

            else

                dev->route = parent->route +

                    (15 << ((parent->level - 1)*4));

        }

 

        dev->dev.parent = &parent->dev;

        dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);

运行到这里,我们可以确定一些问题了。当我把设备U盘插入到ROOT_HUB上时,那么会在sys/bus/usb/usb 出现 1-1:第一个1表示总线,第二个1表示接在了root_hub的第一个端口上。

 

       

    }

 

    dev->portnum = port1;

    dev->bus = bus;

    dev->parent = parent;

    INIT_LIST_HEAD(&dev->filelist);

 

#ifdef  CONFIG_PM

    mutex_init(&dev->pm_mutex);

    INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);

    INIT_WORK(&dev->autoresume, usb_autoresume_work);

    dev->autosuspend_delay = usb_autosuspend_delay * HZ;

    dev->connect_time = jiffies;

    dev->active_duration = -jiffies;

#endif

    if (root_hub) 

        dev->authorized = 1;

    else {

        dev->authorized = usb_hcd->authorized_default;

        dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;

    }

    return dev;

}

 

最后一个函数register_root_hub()。

 

 

你可能感兴趣的:(c,struct,list,null,buffer,attributes)