自娱自乐之Linux UDC驱动


 

自娱自乐1之Linux UDC驱动(形式模板)

 分类:
 

 

首先,我不是做驱动的开发人员。所以只能用自娱自乐来表示我的行为。

我不知道udc和gadget驱动是不是冷门的驱动,资料真是不多。我之前买了一本书,上面说到这些,就教你如何调试已写好的驱动。这样也可以写书,太坑了吧!我随便从网上搜搜都能写的比他好。难道现在的育人机构为了钱都变成了坑人机构。

我以前就希望把自己写过的驱动总结成一个模板,让人能直观的看出linux提供的接口要我们做什么甚至怎么做。虽然做这个比较难,但我还是成功的欺骗了自己,可以做到。

这是自娱自乐第一期,可能废话多了一点,请大家原谅。现在说这个模板。这个是一个未做实际应用的模板,只是编译通过,除了没实践,还缺少DMA和USB的请求类型处理样例。后期我会用它做一个驱动,不断的完善。现在这个应该在理论和实践之间的东西。

常用结构体(别人写的,不是linux-3.2.36,不过差不多)

 

[cpp] view plain copy
 
  1. ========================================================USB UDC与gadget驱动=========================================================  
  2. /* 
  3.  *linux内核中usb设备侧驱动程序分为3个层次:UDC驱动、Gadget API和Gadget驱动程序,UDC驱动程序直接访问硬件usb控制器OHCI/EHCI/UHCI,作为usb设备和主机间的底层通信,向上层 
  4.  *提供与硬件相关操作的回调函数。当前Gadget API是对UDC驱动程序回调函数的简单包装。Gadget驱动程序具体控制系统作为usb设备时的相关功能的实现,使设备表现出“网络连接”、“打印机” 
  5.  *或“USB Mass Storage”等特性。 
  6.  * 
  7.  *    这里的USB设备控制器(UDC)驱动指作为其他USB主机控制器外设的USB硬件设备上底层硬件控制器的驱动,该硬件和驱动负责将USB设备依附于一个USB主机控制器上:比如当某运行linux的手机作为PC 
  8.  *的U盘时,手机的底层USB控制器行使USB设备控制器的功能,这时候运行在底层的是UDC驱动,而手机成为U盘,在UDC驱动之上仍然需要另一个驱动,对于USB大容量存储器为file storage驱动,这一 
  9.  *驱动称为gadget驱动(总之是一个运行linux的系统的usb接口作为另一个linux系统的设备)。usb设备驱动调用usb核心提供的API,因此具体驱动与SOC无关。同样,usb gadget驱动调用通用的gadget API 
  10.  *因此具体gadget驱动也变得与SOC无关。 
  11.  *UDC驱动和gadget驱动都位于内核的drivers/usb/gadget目录下,S3C2410对应的UDC驱动为s3c2410_udc.c。ether.c、f_serial.c、file_storage.c等文件实现了一些gadget驱动 
  12.  */  
  13. #include <linux/gadget.h>  
  14.   
  15. -----------------------------------------------------------struct usb_gadget------------------------------------------------------  
  16. struct usb_gadget {   //描述USB设备控制器  
  17.     /* readonly to gadget driver */                  //针对gadget驱动只读  
  18.     const struct usb_gadget_ops *ops;                //访问硬件函数  
  19.     struct usb_ep           *ep0;                          //端点0,setup使用  
  20.     struct list_head        ep_list;    /* of usb_ep */    //其他端点列表  
  21.     enum usb_device_speed       speed;                     
  22.     unsigned            is_dualspeed:1;  
  23.     unsigned            is_otg:1;  
  24.     unsigned            is_a_peripheral:1;  
  25.     unsigned            b_hnp_enable:1;                    //A-HOST使能了HNP支持  
  26.     unsigned            a_hnp_support:1;                   //A-HOST支持HNP  
  27.     unsigned            a_alt_hnp_support:1;  
  28.     const char          *name;  
  29.     struct device           dev;  
  30. };  
  31.   
  32. ------------------------------------------------------struct usb_gadget_ops-------------------------------------------------------  
  33. struct usb_gadget_ops {  //硬件操作函数  
  34.     int (*get_frame)(struct usb_gadget *);  
  35.     int (*wakeup)(struct usb_gadget *);  
  36.     int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);  
  37.     int (*vbus_session) (struct usb_gadget *, int is_active);  
  38.     int (*vbus_draw) (struct usb_gadget *, unsigned mA);  
  39.     int (*pullup) (struct usb_gadget *, int is_on);  
  40.     int (*ioctl)(struct usb_gadget *,  
  41.                 unsigned code, unsigned long param);  
  42. };  
  43.   
  44. -----------------------------------------------------struct usb_gadget_driver----------------------------------------------------  
  45. struct usb_gadget_driver {  //描述gadget驱动  
  46.     char            *function;                          //描述gadget功能的字符串  
  47.     enum usb_device_speed   speed;  
  48.     int         (*bind)(struct usb_gadget *);         //当驱动和gadget绑定时调用  
  49.     void            (*unbind)(struct usb_gadget *);  
  50.     int         (*setup)(struct usb_gadget *,         //处理硬件驱动未处理的端点0请求  
  51.                     const struct usb_ctrlrequest *);  
  52.     void            (*disconnect)(struct usb_gadget *);  
  53.     void            (*suspend)(struct usb_gadget *);  
  54.     void            (*resume)(struct usb_gadget *);  
  55.   
  56.     /* FIXME support safe rmmod */  
  57.     struct device_driver    driver;  
  58. };  
  59.   
  60. -----------------------------------------------------struct usb_request----------------------------------------------------------  
  61. struct usb_request {  //表示一个传输请求的usb_request(与从机端看到的urb相似)  
  62.     void            *buf;  
  63.     unsigned        length;  
  64.     dma_addr_t      dma;  
  65.   
  66.     unsigned        no_interrupt:1;  
  67.     unsigned        zero:1;  
  68.     unsigned        short_not_ok:1;  
  69.   
  70.     void            (*complete)(struct usb_ep *ep,  
  71.                     struct usb_request *req);  
  72.     void            *context;  
  73.     struct list_head    list;  
  74.   
  75.     int         status;  
  76.     unsigned        actual;  
  77. };  
  78.   
  79. ----------------------------------------------------------struct usb_ep---------------------------------------------------------  
  80. struct usb_ep {   //描述一个端点  
  81.     void            *driver_data;  
  82.   
  83.     const char      *name;  
  84.     const struct usb_ep_ops *ops;  
  85.     struct list_head    ep_list;  
  86.     unsigned        maxpacket:16;  
  87. };  
  88.   
  89. ------------------------------------------------------struct usb_ep_ops---------------------------------------------------------  
  90. struct usb_ep_ops {   //描述端点操作  
  91.     int (*enable) (struct usb_ep *ep,  
  92.         const struct usb_endpoint_descriptor *desc);  
  93.     int (*disable) (struct usb_ep *ep);  
  94.   
  95.     struct usb_request *(*alloc_request) (struct usb_ep *ep,  
  96.         gfp_t gfp_flags);  
  97.     void (*free_request) (struct usb_ep *ep, struct usb_request *req);  
  98.   
  99.     int (*queue) (struct usb_ep *ep, struct usb_request *req,  
  100.         gfp_t gfp_flags);  
  101.     int (*dequeue) (struct usb_ep *ep, struct usb_request *req);  
  102.   
  103.     int (*set_halt) (struct usb_ep *ep, int value);  
  104.     int (*set_wedge) (struct usb_ep *ep);  
  105.   
  106.     int (*fifo_status) (struct usb_ep *ep);  
  107.     void (*fifo_flush) (struct usb_ep *ep);  
  108. };  
  109. --------------------------------------------------------------------------------------------------------------------------------  
  110. /* 
  111.  *UDC和gadget驱动围绕上述数据结构及其成员函数而展开。  
  112.  *在具体的UDC驱动中,需要封装usb_gadget和每个端点usb_ep,实现端点usb_ep_ops,完成usb_request。另外usb_gadget_register_driver和usb_gadget_unregister_driver这两个API需要由UDC 
  113.  *驱动提供,gadget驱动会调用它们。 
  114.  */  
  115. int usb_gadget_register_driver(struct usb_gadget_driver *driver); //注册,在加载模块中调用,该函数中会调用driver->bind()函数,将usb_gadget_driver与具体的gadget绑定  
  116. int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); //注销,在卸载模块中调用,告诉UDC驱动不再投入工作,如果UDC正在和USB主机连接,会先调用driver->disconnect()  
  117.                                                                     //函数,而后会调用unbind()函数  
  118. //在linux/usb/gadget.h中,封装了一些常用的API:                                                                      
  119. int usb_ep_enable(struct usb_ep *ep,const struct usb_endpoint_descriptor *desc);  //使能端点 ,该函数会调用struct usb_ep_ops->enable()  
  120. int usb_ep_disable(struct usb_ep *ep);  //禁止端点,该函数会调用struct usb_ep_ops->disable()  
  121.   
  122. struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,gfp_t gfp_flags);    //分配一个依附于某端点的 usb_request,该函数会调用struct usb_ep_ops->usb_request()  
  123. void usb_ep_free_request(struct usb_ep *ep,struct usb_request *req);            //释放一个依附于某端点的 usb_request,该函数会调用struct usb_ep_ops->free_request()  
  124.   
  125. int usb_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags);//提交usb_request,该函数告诉UDC完成usb_request(读写buffer),当请求被完成后,该请求对应的completion函数会被调用,  
  126.                                                                               //该函数会调用struct usb_ep_ops->queue(),该函数告诉UDC完成usb_request(读写buffer),当请求完成后,该请求对应的completion函数会被调用  
  127. int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req);  //取消usb_request,该函数会调用struct usb_ep_ops->dequeue()  
  128.   
  129. 端点FIFO管理:  
  130. int usb_ep_fifo_status(struct usb_ep *ep);  //该函数会调用truct usb_ep_ops->fifo_status返回目前FIFO中的字节数  
  131. void usb_ep_fifo_flush(struct usb_ep *ep);  //该函数会调用truct usb_ep_ops->fifo_flush,以flush(冲洗)掉FIFO中的数据  
  132.   
  133. int usb_gadget_frame_number(struct usb_gadget *gadget); //它调用gadget->ops->get_frame(gadget)返回目前的帧号  
  134.   
  135. /* 
  136.  *S3C2410的UDC驱动在 /driver/usb/gadget/s3c2410_udc.c 
  137.  */  
  138. /-----------------------------------------------------------------------------------------------------------------------------/  

 

看请求队列的处理

struct xxxxx_request

{

    structlist_head        queue;       /* ep'srequests */

    structusb_request        req;       //对应主机端看到的urb

};

struct xxxxx_ep

{

    struct usb_ep ep; //描述一个端点

   struct list_head queue;

   …

}

 

    /*device/ep0 records init */

    INIT_LIST_HEAD(&dev->gadget.ep_list);

    INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);

   

/* basic endpoint recordsinit */

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

        structxxxxx_ep *ep = &dev->ep[i];

 

        if(i != 0)//除了ep0

            list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);

        …

        INIT_LIST_HEAD(&ep->queue);

 }

ep0就用gadget里面的,这个在上层的gadget驱动才能看到。Udc只要这样做就可以了

 

gadget驱动会调用xxxxx_udc_queue把请求插入ep->queue

udc在端点中断时会从对应的queue取出处理,我的模板没体现这点。


下面说udc驱动大概包涵哪些。

1.       struct usb_ep_ops

2.       struct usb_gadget_ops xxxxx_ops

3.       有一个中断来处理对应的事件,请求一般包涵在次。(目前的模板没有体现)。

事实上现在的模板就是告诉你上面两个要实现什么,及怎么实现。代码中有详细解释。我不多说了。

.H

 

[cpp] view plain copy
 
  1. /*********************************** 
  2.  Copyright(C), 2013 LDP 
  3.  FileName:  xxxxx_udc.h 
  4.  Author:    wwxxxxll 
  5.  Date:           
  6.  Description:   
  7.  History:        
  8.  Author       Date            Desc 
  9. ************************************/  
  10. #ifndef __XXXXX_UDC_H__  
  11. #define __XXXXX_UDC_H__  
  12. /*************配置选项**************/  
  13. #define XXXXX_DEBUG_FS  //使用debugfs  
  14.   
  15. //struct usb_ep_ops  
  16. #define XXXXX_NEWSTYLE  //使用udc_start  
  17. #define XXXXX_SETWEDHE  //实现set_weght方法  
  18. #define XXXXX_FIFO_STATUS //支持fifo_status方法  
  19. #define XXXXX_FIFO_FLUSH //支持fifo_flush方法  
  20.   
  21. //struct usb_gadget_ops  
  22. #define XXXXX_XXXXX_GET_FRAME //支持get_frame  
  23. #define XXXXX_WAKEUP //支持wakeup功能  
  24. #define XXXXX_SELFPOWERED //selfpowered支持  
  25. #define XXXXX_VBUS_SESSION //vbus连接控制支持  
  26. #define XXXXXX_PULLUP //usb连接控制支持  
  27.   
  28. #define XXXXX_HAVE_CLK  //有专用的CLK  
  29. #ifdef XXXXX_HAVE_CLK  
  30. #define CLK_DELAY_TIME 10 //ms  
  31. #endif  
  32.   
  33. #define XXXXX_USE_IRQ  
  34.   
  35. //端口信息  
  36. #define XXXXX_ENDPOINTS 2 //端口数  
  37. #define EP0_FIFO_SIZE 8  
  38. #define EP1_FIFO_SIZE 64  
  39. #define EP1_ADDRESS 1  
  40. #define EP1_ATTR USB_ENDPOINT_XFER_BULK  
  41. #define XXXXX_EP_FILO_SIZE 128  
  42. /***********************************/  
  43.   
  44. /*************寄存器定义************/  
  45.   
  46. /***********************************/  
  47.   
  48.   
  49. struct xxxxx_ep   
  50. {  
  51.     struct usb_ep ep; //描述一个端点  
  52.     struct list_head queue;  
  53.     struct xxxxx_udc *dev;  
  54.     const struct usb_endpoint_descriptor *desc;  
  55.   
  56.     unsigned char fifosize;  
  57.     unsigned char bEndpointAddress;  
  58.     unsigned char bmAttributes;  
  59.   
  60.     u16 fifo_size;  
  61.     u8 num;  
  62.   
  63.     unsigned stopped :1;//维护一个端口停止标志  
  64.   
  65. #ifdef XXXXX_SETWEDHE  
  66.     unsigned wedged :1;  
  67. #endif  
  68. };  
  69.   
  70. #define to_xxxxx_ep(ep_p) container_of(ep_p, struct xxxxx_ep, ep)  
  71.   
  72. struct xxxxx_request   
  73. {  
  74.     struct list_head        queue;        /* ep's requests */  
  75.     struct usb_request        req;        //对应主机端看到的urb  
  76. };  
  77.   
  78. #define to_xxxxx_req(req_p) container_of(req_p, struct xxxxx_request, req)  
  79.   
  80. //根据实际要求定义,这个不能当做模板,主要是便于软件管理  
  81. //一般有下面几个,有的驱动不用这些定义去管理  
  82. enum ep0state {  
  83.     EP0_IDLE,  
  84.     EP0_IN,   
  85.     EP0_OUT,      
  86.     EP0_STALL,          
  87. };  
  88.       
  89. struct xxxxx_udc   
  90. {  
  91.     spinlock_t lock;  
  92.   
  93.     void __iomem *virl_addr;  
  94.     u32 phy_addr;  
  95.     u32 reg_size;  
  96.   
  97.     struct usb_gadget gadget;  
  98.     struct usb_gadget_driver *driver;  
  99.   
  100.     enum ep0state ep0state;  
  101.     struct xxxxx_ep ep[XXXXX_ENDPOINTS];  
  102.     struct xxxxx_request fifo_req;  
  103.   
  104. #ifdef XXXXX_DEBUG_FS  
  105.     struct dentry *debug_info;  
  106. #endif   
  107.   
  108. #ifdef XXXXX_HAVE_CLK  
  109.     struct clk *xxxxx_clk;  
  110. #endif  
  111.   
  112. #ifdef XXXXX_USE_IRQ  
  113.     unsigned int irq_num;  
  114. #endif  
  115.   
  116.     u16    devstatus;  
  117. };  
  118.   
  119. #define to_xxxxx_udc(gadget_p) container_of(gadget_p, struct xxxxx_udc, gadget)  
  120.   
  121. #endif//__XXXXX_UDC_H__  

.c

 

 

[cpp] view plain copy
 
  1. /*********************************** 
  2.  Copyright(C), 2013 LDP 
  3.  FileName:  xxxxx_udc.c 
  4.  Author:    wwxxxxll 
  5.  Date:           
  6.  Description: linux-3.2-36 
  7.  History:        
  8.  Author       Date            Desc 
  9. ************************************/  
  10.   
  11. #include <linux/module.h>//MODULE_*  
  12. #include <linux/init.h>//printk  
  13. #include <linux/slab.h>//kzalloc() kfree()  
  14. #include <linux/usb/gadget.h>//struct usb_gadget等  
  15. #include <linux/clk.h>//struct clk  
  16. #include <linux/platform_device.h>//platform  
  17. #include <linux/ioport.h>  
  18. #include <linux/interrupt.h>  
  19. #include <linux/delay.h>  
  20.   
  21. #include <asm/irq.h>  
  22. #include <asm/io.h>//ioremap  
  23.   
  24. #include "xxxxx_udc.h"  
  25.   
  26. #ifdef XXXXX_DEBUG_FS  
  27. #include <linux/debugfs.h>  
  28. #include <linux/seq_file.h>//seq_printf seq_read  
  29. #endif  
  30.   
  31. #define DRIVER_DESC    "XXXXX USB Device Controller Gadget"  
  32. #define DRIVER_VERSION    "2013"  
  33. #define DRIVER_AUTHOR    "wwxxxxll"  
  34.   
  35. static const char        gadget_name[] = "xxxxx_udc";  
  36. static const char        driver_desc[] = DRIVER_DESC;  
  37.   
  38.   
  39.   
  40. //根据实际情况修改  
  41. static const char ep0name[] = "ep0";  
  42. static const char * const ep_name[] = {  
  43.     ep0name,  
  44.     "ep1",  
  45. };  
  46.   
  47. #ifdef XXXXX_DEBUG_FS  
  48. static struct dentry *xxxxx_udc_debugfs_root;  
  49.   
  50. static int xxxxx_udc_debugfs_seq_show(struct seq_file *m, void *p)  
  51. {  
  52.     seq_printf(m, "My name is %s\n", gadget_name);  
  53.   
  54.     return 0;  
  55. }  
  56.   
  57. static int xxxxx_udc_debugfs_fops_open(struct inode *inode,  
  58.                      struct file *file)  
  59. {  
  60.     return single_open(file, xxxxx_udc_debugfs_seq_show, NULL);  
  61. }  
  62.   
  63. static const struct file_operations xxxxx_udc_debugfs_fops =   
  64. {  
  65.     .open        = xxxxx_udc_debugfs_fops_open,  
  66.     .read        = seq_read,  
  67.     .llseek        = seq_lseek,  
  68.     .release    = single_release,  
  69.     .owner        = THIS_MODULE,  
  70. };  
  71. #endif  
  72.   
  73. /***********************hardware_handler************************/  
  74. static void xxxxx_usb_reset(struct xxxxx_udc *dev)  
  75. {  
  76.     //硬件操作  
  77. }  
  78.   
  79. //udc的这个中断,真是包罗万象,各硬件差别比较大  
  80. //简单一点说,就是清楚中断标致位,再根据中断标志位对应处理  
  81. //实际要复杂的多,如果是ep0,还会从fifo中取得usb_ctrlrequest  
  82. //进行对应的处理,我们在实现具体的实现时再说吧  
  83. static irqreturn_t xxxxx_udc_irq(int dummy, void *_dev)  
  84. {  
  85.     return IRQ_HANDLED;  
  86. }  
  87. /***************************************************************/  
  88.   
  89. /***********************queue***********************************/  
  90. //对于usb请求,一般都要维护一个list去管理请求  
  91.   
  92. //端点list初始化,存入gadget里  
  93. static void xxxxx_usb_reinit(struct xxxxx_udc *dev)  
  94. {  
  95.     u32 i;  
  96.   
  97.     /* device/ep0 records init */  
  98.     INIT_LIST_HEAD (&dev->gadget.ep_list);  
  99.     dev->gadget.ep0 = &dev->ep[0].ep;//ep0单独存放  
  100.     dev->gadget.speed = USB_SPEED_UNKNOWN;  
  101.     dev->ep0state = EP0_IDLE;  
  102.     INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);  
  103.   
  104.     for (i = 0; i < XXXXX_ENDPOINTS; i++) {  
  105.         struct xxxxx_ep *ep = &dev->ep[i];  
  106.   
  107.         if (i != 0)  
  108.             list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);  
  109.   
  110.         ep->dev = dev;  
  111.         ep->desc = NULL;  
  112.         ep->stopped = 0;  
  113.         INIT_LIST_HEAD (&ep->queue);  
  114.     }  
  115. }  
  116.   
  117. static void xxxxx_udc_done(struct xxxxx_ep *ep, struct xxxxx_request *req, int status)  
  118. {  
  119.     struct xxxxx_udc *dev;  
  120.     unsigned stopped = ep->stopped;  
  121.   
  122.     list_del_init(&req->queue);  
  123.   
  124.     if (likely (req->req.status == -EINPROGRESS))//正在进行中  
  125.         req->req.status = status;  
  126.     else  
  127.         status = req->req.status;  
  128.   
  129.     dev = ep->dev;  
  130.   
  131.     /* don't modify queue heads during completion callback */  
  132.     ep->stopped = 1;  
  133.     //先解锁再加锁,加锁是在dequeue_all调用前做的  
  134.     spin_unlock(&dev->lock);  
  135.     req->req.complete(&ep->ep, &req->req);  
  136.     spin_lock(&dev->lock);  
  137.     ep->stopped = stopped;  
  138. }  
  139.   
  140. static void xxxxx_dequeue_all(struct xxxxx_ep *ep, int status)  
  141. {  
  142.     struct xxxxx_request *req;  
  143.   
  144.     if (&ep->queue == NULL)  
  145.         return;  
  146.   
  147.     while (!list_empty(&ep->queue)) //list_del_init会删除链表中的元素  
  148.     {  
  149.         req = list_entry(ep->queue.next, struct xxxxx_request, queue);  
  150.         xxxxx_udc_done(ep, req, status);  
  151.     }  
  152. }  
  153.   
  154.   
  155. /***************************************************************/  
  156. //may not be the endpoint named "ep0".这是gadget.h的源话  
  157. /**************************ep_ops*******************************/  
  158. //描述端点操作  
  159.   
  160. //当设备配置或接口设置改变时,驱动会enable或disable端口  
  161. static int xxxxx_udc_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)  
  162. {  
  163.     struct xxxxx_udc    *dev;  
  164.     struct xxxxx_ep    *ep;  
  165.     u32 max;  
  166.     unsigned long    flags;  
  167.   
  168.     ep = to_xxxxx_ep(_ep);  
  169.     if (!_ep || !desc || ep->desc  
  170.             || (desc->bDescriptorType != USB_DT_ENDPOINT)  
  171.             || (_ep->name == ep0name))  
  172.         return -EINVAL;  
  173.     dev = ep->dev;  
  174.     if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)  
  175.         return -ESHUTDOWN;  
  176.   
  177.     max = usb_endpoint_maxp(desc) & 0x1fff;  
  178.   
  179.     spin_lock_irqsave(&dev->lock, flags);  
  180.   
  181.     _ep->maxpacket = max & 0x7fff;  
  182.     ep->desc = desc;  
  183.   
  184.     ep->stopped = 0;  
  185. #ifdef XXXXX_SETWEDHE  
  186.     ep->wedged = 0;  
  187. #endif  
  188.     ep->bEndpointAddress = desc->bEndpointAddress;  
  189.   
  190.     //寄存器操作  
  191.     spin_unlock_irqrestore(&dev->lock, flags);  
  192.   
  193.     return 0;  
  194. }  
  195.   
  196. static int xxxxx_udc_ep_disable(struct usb_ep *_ep)  
  197. {  
  198.     struct xxxxx_ep *ep = to_xxxxx_ep(_ep);  
  199.     unsigned long flags;  
  200.   
  201.     if (!_ep || !ep->desc) {  
  202.         return -EINVAL;  
  203.     }  
  204.   
  205.     local_irq_save(flags);  
  206.   
  207.     ep->desc = NULL;  
  208.     ep->stopped = 1;  
  209.   
  210.     //清除请求list和关闭ep  
  211.     xxxxx_dequeue_all(ep, -ESHUTDOWN);//关机后将无法传输端点  
  212.   
  213.     local_irq_restore(flags);  
  214.   
  215.     return 0;  
  216. }  
  217.   
  218. //动态分配请求  
  219. static struct usb_request *xxxxx_udc_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)  
  220. {  
  221.     struct xxxxx_request *req;  
  222.   
  223.     if (!_ep)  
  224.         return NULL;  
  225.   
  226.     req = kzalloc (sizeof(struct xxxxx_request), gfp_flags);  
  227.     if (!req)  
  228.         return NULL;  
  229.   
  230.     INIT_LIST_HEAD (&req->queue);  
  231.   
  232.     return &req->req;  
  233. }  
  234.   
  235. //释放请求  
  236. static void xxxxx_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)  
  237. {  
  238.     //struct xxxxx_ep    *ep = to_xxxxx_ep(_ep);  
  239.     struct xxxxx_request *req = to_xxxxx_req(_req);  
  240.   
  241.     if (!_ep || !_req)  
  242.         return;  
  243.   
  244.     WARN_ON (!list_empty (&req->queue));  
  245.     kfree(req);  
  246. }  
  247.   
  248. //下面的queue是插入一个请求  
  249. //dequeue删除一个请求  
  250. static int xxxxx_udc_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  
  251. {  
  252.     struct xxxxx_udc    *dev;  
  253.     unsigned long        flags;  
  254.     struct xxxxx_request    *req = to_xxxxx_req(_req);  
  255.     struct xxxxx_ep        *ep = to_xxxxx_ep(_ep);  
  256.   
  257.     if (unlikely (!_ep || (!ep->desc && ep->num != 0))) //这个逻辑下面会看到很多(_ep为空或[ep->desc为空且不是0端点])  
  258.     {  
  259.         return -EINVAL;  
  260.     }  
  261.   
  262.     dev = ep->dev;  
  263.     if (unlikely (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))   
  264.     {  
  265.         return -ESHUTDOWN;  
  266.     }  
  267.   
  268.     if (unlikely(!_req || !_req->complete  
  269.             || !_req->buf || !list_empty(&req->queue))) //_req或_req->buf为空、complete执行错误、req->queue不为空  
  270.     {  
  271.         return -EINVAL;  
  272.     }  
  273.   
  274.     local_irq_save (flags);  
  275.   
  276.     //硬件操作  
  277.   
  278.     if (likely(req != 0))  
  279.         list_add_tail(&req->queue, &ep->queue);//请求入list  
  280.   
  281.     local_irq_restore(flags);  
  282.   
  283.     return 0;  
  284. }  
  285.   
  286. static int xxxxx_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)  
  287. {  
  288.     struct xxxxx_ep        *ep = to_xxxxx_ep(_ep);  
  289.     struct xxxxx_udc    *dev;  
  290.     int            retval = -EINVAL;  
  291.     unsigned long        flags;  
  292.     struct xxxxx_request    *req = NULL;  
  293.   
  294.   
  295.     if (!_ep || !_req)  
  296.         return retval;  
  297.   
  298.     dev = ep->dev;  
  299.   
  300.     if (!dev->driver)  
  301.         return -ESHUTDOWN;  
  302.   
  303.     local_irq_save (flags);  
  304.   
  305.     list_for_each_entry (req, &ep->queue, queue)   
  306.     {  
  307.         if (&req->req == _req)   
  308.         {  
  309.             list_del_init (&req->queue);  
  310.             _req->status = -ECONNRESET;//Connection reset by peer  
  311.             retval = 0;  
  312.             break;  
  313.         }  
  314.     }  
  315.   
  316.     if (retval == 0)   
  317.     {  
  318.         xxxxx_udc_done(ep, req, -ECONNRESET);  
  319.     }  
  320.   
  321.     local_irq_restore (flags);  
  322.     return retval;  
  323. }  
  324.   
  325. #ifdef XXXXX_FIFO_STATUS  
  326. //fifo状态,返回fifo中的字节数。  
  327. //在上层的调用usb_ep_fifo_statu()如果不用fifo或不支持这个操作返回错误-EOPNOTSUPP  
  328. //net2272就有寄存器EP_AVAIL记录fifo中的字节数。  
  329. //s3c2440硬件不支持,没实现,上层调用会得到-EOPNOTSUPP  
  330. static int xxxxx_udc_fifo_status(struct usb_ep *_ep)  
  331. {  
  332.     struct xxxxx_ep *ep;  
  333.     u16 retval = 0;  
  334.   
  335.     ep = to_xxxxx_ep(_ep);  
  336.     if (!_ep || (!ep->desc && ep->num != 0))  
  337.         return -ENODEV;  
  338.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  339.         return -ESHUTDOWN;  
  340.   
  341.     //retval = 读寄存器  
  342.   
  343.     return retval;  
  344. }  
  345. #endif  
  346.   
  347. #ifdef XXXXX_FIFO_FLUSH  
  348. //冲掉fifo的不明确数据,这个决不用除非端点不能用于任何协议传输,这是上层调用的事  
  349. static void xxxxx_udc_fifo_flush(struct usb_ep *_ep)  
  350. {  
  351.     struct xxxxx_ep *ep;  
  352.   
  353.     ep = to_xxxxx_ep(_ep);  
  354.     if (!_ep || (!ep->desc && ep->num != 0))  
  355.         return;  
  356.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  357.         return;  
  358.   
  359.     //寄存器操作  
  360. }  
  361. #endif  
  362.   
  363. /* 
  364. 上层调用usb_ep_set_wedge 
  365. 停止一个端点并忽略CLEAR_FEATURE请求。如果Gadget驱动清除停止状态,它将自动Unwedge端点 
  366. 一般用一个位wedge表示 
  367. 如果没有实现set_wedge方法。就用set_halt(ep, 1);代替 
  368. 我们看个例子(在file_storage.c中) 
  369. Bulk-only 
  370. 当出现无效的CBW时 
  371. Bulk-only Spec说我们必须停止IN 端点。还说必须保持这个状态知道下一次的reset,但是没有办法 
  372. 告诉控制器忽略CLEAR_FEATURE请求。所以我们用一个位来记录,搞定! 
  373. 下面是参考net2272的代码, 
  374. value=1:set_halt 
  375. = 0:clear_halt 
  376. */  
  377. static int xxxxx_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)  
  378. {  
  379.     struct xxxxx_ep *ep;  
  380.     unsigned long flags;  
  381.     int ret = 0;  
  382.   
  383.     ep = container_of(_ep, struct xxxxx_ep, ep);  
  384.     if (!_ep || (!ep->desc && ep->num != 0))  
  385.         return -EINVAL;  
  386.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  387.         return -ESHUTDOWN;  
  388.     if (ep->desc /* not ep0 */ && usb_endpoint_xfer_isoc(ep->desc))//判断是不是同步端点,见下面  
  389.         return -EINVAL;  
  390.   
  391.     spin_lock_irqsave(&ep->dev->lock, flags);  
  392.   
  393.   
  394.   
  395.     if (!list_empty(&ep->queue))  
  396.         ret = -EAGAIN;  
  397. #ifdef XXXXX_FIFO_STATUS  
  398.     else if ((ep->bEndpointAddress & USB_DIR_IN) && value && xxxxx_udc_fifo_status(_ep) != 0)//fifo_status是上面实现的  
  399.         ret = -EAGAIN;  
  400. #endif  
  401.     else {  
  402.         /* set/clear */  
  403.         if (value) {  
  404.             if (ep->num == 0)  
  405.             {  
  406.                  ep->dev->ep0state = EP0_STALL;  
  407.                  ep->stopped = 1;  
  408.                 //net2272的端点0在setup时自动复位,没有什么操作。s3c2440就不是了  
  409.                 //ep->dev->protocol_stall = 1;  
  410.                 //ep0 set_halt  
  411.             }  
  412.             else  
  413.                 //epx(x != 0) set_halt  
  414.             if (wedged)//维护wedged  
  415.                 ep->wedged = 1;  
  416.         } else {  
  417.             //ep clear_halt  
  418.             ep->wedged = 0;  
  419.         }  
  420.     }  
  421.     spin_unlock_irqrestore(&ep->dev->lock, flags);  
  422.   
  423.     return ret;  
  424. }  
  425. //_ep 不能是同步端点,同步端点不支持错误重发机制。在上面判断  
  426. static int xxxxx_udc_set_halt(struct usb_ep *_ep, int value)  
  427. {  
  428.     return xxxxx_set_halt_and_wedge(_ep, value, 0);  
  429. }  
  430.   
  431. #ifdef XXXXX_SETWEDHE  
  432.   
  433. static int xxxxx_udc_set_wedge(struct usb_ep *_ep)  
  434. {  
  435.     if (!_ep || _ep->name == ep0name)//一般都是端点0请求复位  
  436.         return -EINVAL;  
  437.   
  438.     return xxxxx_set_halt_and_wedge(_ep, 1, 1);  
  439. }  
  440. #endif  
  441.   
  442. static const struct usb_ep_ops xxxxx_ep_ops =   
  443. {  
  444.     .enable        = xxxxx_udc_ep_enable,  
  445.     .disable    = xxxxx_udc_ep_disable,  
  446.   
  447.     .alloc_request    = xxxxx_udc_alloc_request,  
  448.     .free_request    = xxxxx_udc_free_request,  
  449.   
  450.     .queue        = xxxxx_udc_queue,  
  451.     .dequeue    = xxxxx_udc_dequeue,  
  452.    
  453.     .set_halt    = xxxxx_udc_set_halt,  
  454.   
  455. #ifdef XXXXX_SETWEDHE  
  456.     .set_wedge  = xxxxx_udc_set_wedge,  
  457. #endif  
  458.   
  459. #ifdef XXXXX_FIFO_STATUS  
  460.     .fifo_status = xxxxx_udc_fifo_status,  
  461. #endif  
  462.   
  463. #ifdef XXXXX_FIFO_FLUSH  
  464.     .fifo_flush = xxxxx_udc_fifo_flush,  
  465. #endif  
  466. };  
  467.   
  468. /***************************************************************/  
  469. //USB 设备的常用操作包括:设备连接、设备移除、设备配置、地址分配、数据传输、   
  470. //设备挂起、设备唤醒等。  
  471. /**************************usb_gadget_ops***********************/  
  472. //硬件操作函数  
  473.   
  474. //获取帧号,当主机发送USB 数据包时,每个帧的开始(SOF)包包含一个帧号。  
  475. //这个帧号一般自动加载到对应寄存器,此函数主要就是读这些寄存器  
  476. //如果设备不支持返回负  
  477. static int xxxxx_udc_get_frame(struct usb_gadget *usb_gdt_p)  
  478. {  
  479. #ifdef XXXXX_GET_FRAME  
  480.     struct xxxxx_udc *dev = to_xxxxx_udc(usb_gdt_p);  
  481.     int retval = 0;  
  482.     unsigned long flags;  
  483.   
  484.     spin_lock_irqsave(&dev->lock, flags);  
  485.   
  486.     //retval = 读寄存器  
  487.   
  488.     spin_unlock_irqrestore(&dev->lock, flags);  
  489.   
  490.     return retval;  
  491. #else  
  492.     return -EOPNOTSUPP;  
  493. #endif  
  494. }  
  495.   
  496. #ifdef XXXXX_WAKEUP  
  497. //唤醒,举个例子net2272。它的寄存器usbctl0的第五位控制唤醒功能使能  
  498. //寄存器usbctl1的第三位通过写1去resume,s3c2440在PWR_REG也有类似  
  499. static int xxxxx_udc_wakeup(struct usb_gadget *usb_gdt_p)  
  500. {  
  501.     struct xxxxx_udc *dev = to_xxxxx_udc(usb_gdt_p);  
  502.     unsigned long flags;  
  503.   
  504.     spin_lock_irqsave(&dev->lock, flags);  
  505.   
  506.     //寄存器操作  
  507.   
  508.     spin_unlock_irqrestore(&dev->lock, flags);  
  509.   
  510.     return 0;  
  511. }  
  512. #endif  
  513.   
  514. #ifdef XXXXX_SELFPOWERED  
  515. //设置自供电标志(selfpowered feature),一般就用一个变量位或一个位记录一下。USB_RECIP_DEVICE时返回状态  
  516. static int xxxxx_udc_set_selfpowered (struct usb_gadget *usb_gdt_p, int is_selfpowered)  
  517. {  
  518.     struct xxxxx_udc *dev = to_xxxxx_udc(usb_gdt_p);  
  519.   
  520.     if (is_selfpowered)  
  521.         dev->devstatus |= (1 << USB_DEVICE_SELF_POWERED);  
  522.     else  
  523.         dev->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);  
  524.   
  525.     return 0;  
  526. }  
  527. #endif  
  528.   
  529. #ifdef XXXXX_VBUS_SESSION  
  530. //vbus在硬件上就是usb的电源脚,这个函数就是来控制它。一般通过一个gpio拉高拉底  
  531. //这个vbus会话,实际的我看了s3c2410和at91的处理,就是让usb的D+线与一个gpio口连接  
  532. //通过置1置0来控制usb  
  533. static int xxxxx_udc_vbus_session (struct usb_gadget *usb_gdt_p, int is_active)  
  534. {  
  535.     struct xxxxx_udc *dev = to_xxxxx_udc(usb_gdt_p);  
  536.     unsigned long flags;  
  537.   
  538.     spin_lock_irqsave(&dev->lock, flags);  
  539.   
  540.     //寄存器操作  
  541.   
  542.     spin_unlock_irqrestore(&dev->lock, flags);  
  543.   
  544.     return 0;  
  545. }  
  546. #endif  
  547.   
  548. #ifdef XXXXX_VBBUS_DRAW  
  549. //强制vbus电源控制器行为,在SET_CONFIGRATION时,设置vbus的电流量  
  550. //vbus应该是表示总线电压,在硬件上是一个脚  
  551. //主要是对usb电流的设置,看一下gta02平台,这个函数会操作pcf50633(一种移动设备的电源管理芯片)  
  552. static int xxxxx_udc_vbus_draw (struct usb_gadget *usb_gdt_p, unsigned mA)  
  553. {  
  554.     return 0;  
  555. }  
  556. #endif  
  557.   
  558. #ifdef XXXXXX_PULLUP  
  559. //这个和上面的vbus_session区别是  
  560. //vbus_session是控制vbus的连接  
  561. //pullup是控制usb模块的连接  
  562. //在udc-core.c中newstyle的驱动probe函数时才调用它,所以你要实现udc_start和udc_stop,  
  563. //当然除了注册,也可以通过sysfs调用它。和newstyle无关。  
  564. //composite.c也有一些调用  
  565. //这个就是根据is_on来connect或disconnect usb  
  566. //net2272就是由USBCTL0的第三位控制的,s3c2440还是通过gpio和vbus_session没  
  567. //区别  
  568. static int xxxxx_udc_pullup (struct usb_gadget *usb_gdt_p, int is_on)  
  569. {  
  570.     struct xxxxx_udc *dev = to_xxxxx_udc(usb_gdt_p);  
  571.     unsigned long flags;  
  572.   
  573.     spin_lock_irqsave(&dev->lock, flags);  
  574.   
  575.     if (is_on)  
  576.     {  
  577.         //enable  
  578.     }  
  579.     else  
  580.     {  
  581.         //disable  
  582.     }  
  583.   
  584.     spin_unlock_irqrestore(&dev->lock, flags);  
  585.   
  586.     return 0;  
  587. }  
  588. #endif  
  589.   
  590. //不好意思,我看了linux-3.2.36的/gadget的目录没发现有实现这个的硬件  
  591. static int xxxxx_udc_ioctl(struct usb_gadget *usb_gdt_p, unsigned code, unsigned long param)  
  592. {  
  593.     return 0;  
  594. }  
  595.   
  596. //这个也没看驱动实现它,从名字就是获取配置参数,就简单看看struct usb_dcd_config_params  
  597. /* 
  598. struct usb_dcd_config_params { 
  599.         __u8  bU1devExitLat;    // U1 Device exit Latency  u1设备等待时间 
  600. #define USB_DEFAULT_U1_DEV_EXIT_LAT     0x01    // Less then 1 microsec 至少1微秒 
  601.         __le16 bU2DevExitLat;   // U2 Device exit Latency  
  602. #define USB_DEFAULT_U2_DEV_EXIT_LAT     0x1F4   // Less then 500 microsec  
  603. }; 
  604. 对应struct usb_ss_cap_descriptor 中的成员 
  605. 每一个I/O请求包延迟时间限制 
  606. */  
  607. static void xxxxx_udc_get_config_params(struct usb_dcd_config_params *usb_dc_cfg_pm)  
  608. {  
  609. }  
  610.   
  611. //在udc-core.c中start和udc_start的解释一样,在bind()之前调用,只要实现一个就行了  
  612. //我知道start主要有bind回调  
  613. //udc_start主要是设备执行了non-control请求后,要重新连接,net2272和r8a66597实现的就是它  
  614. #ifdef XXXXX_NEWSTYLE  
  615. static int xxxxx_udc_start(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver);  
  616. static int xxxxx_udc_stop(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver);  
  617. #else  
  618. //s3c2410 xxxxx 实现它  
  619. static int xxxxx_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *));  
  620. static int xxxxx_stop(struct usb_gadget_driver *driver);  
  621. #endif  
  622.   
  623. static const struct usb_gadget_ops xxxxx_ops =   
  624. {  
  625.     .get_frame        = xxxxx_udc_get_frame,  
  626. #ifdef XXXXX_WAKEUP  
  627.     .wakeup            = xxxxx_udc_wakeup,  
  628. #endif  
  629.   
  630. #ifdef XXXXX_SELFPOWERED  
  631.     .set_selfpowered = xxxxx_udc_set_selfpowered,  
  632. #endif  
  633.   
  634. #ifdef XXXXX_VBUS_SESSION  
  635.     .vbus_session    = xxxxx_udc_vbus_session,  
  636. #endif  
  637.   
  638. #ifdef XXXXX_VBBUS_DRAW  
  639.     .vbus_draw        = xxxxx_udc_vbus_draw,  
  640. #endif  
  641.   
  642. #ifdef XXXXXX_PULLUP  
  643.     .pullup            = xxxxx_udc_pullup,  
  644. #endif  
  645.   
  646.     .ioctl          = xxxxx_udc_ioctl,  
  647.     .get_config_params = xxxxx_udc_get_config_params,  
  648. #ifdef XXXXX_NEWSTYLE  
  649.     .udc_start         = xxxxx_udc_start,  
  650.     .udc_stop       = xxxxx_udc_stop,  
  651. #else  
  652.     .start            = xxxxx_start,  
  653.     .stop            = xxxxx_stop,  
  654. #endif  
  655. };  
  656.   
  657. /***************************************************************/  
  658.   
  659.   
  660. /***************************************************************/  
  661.   
  662. static struct xxxxx_udc udc_info = {  
  663.     .gadget = {  
  664.         .ops        = &xxxxx_ops,  
  665.         .ep0        = &udc_info.ep[0].ep,  
  666.         .name        = gadget_name,  
  667.         .dev = {  
  668.             .init_name    = "gadget",  
  669.         },  
  670. /* 
  671. 根据自己的硬件选择 
  672. unsigned is_dualspeed:1; 
  673. unsigned is_otg:1; 
  674. unsigned is_a_peripheral:1; 
  675. unsigned b_hnp_enable:1; //hnp:主机协商协议 otg特有的 
  676. unsigned a_hnp_support:1; 
  677. unsigned a_alt_hnp_support:1; 
  678. */  
  679.     },  
  680.   
  681.     /* control endpoint */  
  682.     .ep[0] = {  
  683.         .num = 0,  
  684.         .ep =  
  685.         {  
  686.             .name        = "ep0",  
  687.             .ops        = &xxxxx_ep_ops,  
  688.             .maxpacket    = EP0_FIFO_SIZE,  
  689.         },  
  690.         .dev        = &udc_info,  
  691.     },  
  692.   
  693.     /* first group of endpoints */  
  694.     .ep[1] = {  
  695.         .num = 1,  
  696.         .ep =   
  697.         {  
  698.             .name        = "ep1",  
  699.             .ops        = &xxxxx_ep_ops,  
  700.             .maxpacket    = EP1_FIFO_SIZE,  
  701.         },  
  702.         .dev        = &udc_info,  
  703.         .fifo_size    = EP1_FIFO_SIZE,  
  704.         .bEndpointAddress = EP1_ADDRESS,  
  705.         .bmAttributes    = EP1_ATTR,  
  706.     },  
  707. };  
  708.   
  709. static void stop_activity(struct xxxxx_udc *dev, struct usb_gadget_driver *driver)  
  710. {  
  711.     unsigned i;  
  712.   
  713.     if (dev->gadget.speed == USB_SPEED_UNKNOWN)  
  714.         driver = NULL;  
  715.   
  716.     /* disconnect gadget driver after quiesceing hw and the driver */  
  717.   
  718.     xxxxx_usb_reset(dev);//复位或disable  
  719.     for (i = 0; i < XXXXX_ENDPOINTS; i++)  
  720.     {  
  721.         xxxxx_dequeue_all(&dev->ep[i], -ECONNABORTED);  
  722.     }  
  723.   
  724. #ifndef XXXXX_NEWSTYLE  
  725. /* 
  726. if (udc_is_newstyle(udc)) { 
  727.         udc->driver->disconnect(udc->gadget); 
  728.         udc->driver->unbind(udc->gadget); 
  729.         usb_gadget_udc_stop(udc->gadget, udc->driver); 
  730.         usb_gadget_disconnect(udc->gadget);//对应pull_up 
  731. } else { 
  732.         usb_gadget_stop(udc->gadget, udc->driver);//所以非newstyle要disconnect 
  733. */  
  734.     if (driver)   
  735.     {  
  736.         spin_unlock(&dev->lock);  
  737.         driver->disconnect(&dev->gadget);  
  738.         spin_lock(&dev->lock);  
  739.     }  
  740. #endif  
  741.   
  742.     if (dev->driver)  
  743.     {  
  744.         xxxxx_usb_reinit(dev);//重初始化  
  745.     }  
  746. }  
  747.   
  748. #ifdef XXXXX_NEWSTYLE  
  749. /* 
  750. udc 的probe函数 
  751. if (udc_is_newstyle(udc)) {//是否实现udc_start and udc_stop 
  752.         ret = bind(udc->gadget); 
  753.         if (ret) 
  754.                 goto err1; 
  755.         ret = usb_gadget_udc_start(udc->gadget, driver);//已绑定,bind是gadget实现的 
  756.         if (ret) { 
  757.                 driver->unbind(udc->gadget); 
  758.                 goto err1; 
  759.         } 
  760.         usb_gadget_connect(udc->gadget);//上面的pullup 
  761. } else { 
  762.  
  763.         ret = usb_gadget_start(udc->gadget, driver, bind); 
  764.         if (ret) 
  765.                 goto err1; 
  766.  
  767. */  
  768. //net2272和r8a66597实现的就是它  
  769. //下面参考net2272  
  770. static int xxxxx_udc_start(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver)  
  771. {  
  772.     struct xxxxx_udc *dev;  
  773.   
  774.     if (!driver || !driver->unbind || !driver->setup ||  
  775.         driver->speed != USB_SPEED_HIGH)  
  776.         return -EINVAL;  
  777.   
  778.     dev = container_of(usb_gdt_p, struct xxxxx_udc, gadget);  
  779.   
  780.     /* hook up the driver ... */  
  781.     driver->driver.bus = NULL;  
  782.     dev->driver = driver;  
  783.     dev->gadget.dev.driver = &driver->driver;  
  784.   
  785.     //使能udc,硬件操作  
  786.   
  787.     return 0;  
  788. }  
  789.   
  790. static int xxxxx_udc_stop(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver)  
  791. {  
  792.     struct xxxxx_udc *dev;  
  793.     unsigned long flags;  
  794.   
  795.     dev = container_of(usb_gdt_p, struct xxxxx_udc, gadget);  
  796.   
  797.     spin_lock_irqsave(&dev->lock, flags);  
  798.     stop_activity(dev, driver);  
  799.     spin_unlock_irqrestore(&dev->lock, flags);  
  800.   
  801.     dev->gadget.dev.driver = NULL;  
  802.     dev->driver = NULL;  
  803.   
  804.     return 0;  
  805. }  
  806.   
  807. #else  
  808. //s3c2410 goku实现它,参考goku  
  809. static int xxxxx_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *usb_gdt_p))  
  810. {  
  811.     struct xxxxx_udc *dev = &udc_info;  
  812.     int    retval = 0;  
  813.   
  814.     if (!driver  
  815.             || driver->speed < USB_SPEED_FULL  
  816.             || !bind  
  817.             || !driver->disconnect  
  818.             || !driver->setup)  
  819.         return -EINVAL;  
  820.     if (!dev)  
  821.         return -ENODEV;  
  822.     if (dev->driver)  
  823.         return -EBUSY;  
  824.   
  825.     /* hook up the driver */  
  826.     driver->driver.bus = NULL;  
  827.     dev->driver = driver;  
  828.     dev->gadget.dev.driver = &driver->driver;  
  829.   
  830.     if ((retval = device_add(&dev->gadget.dev)) != 0)   
  831.     {  
  832.         goto register_error;  
  833.     }  
  834.   
  835.     retval = bind(&dev->gadget);  
  836.     if (retval)   
  837.     {  
  838.         device_del(&dev->gadget.dev);  
  839.         goto register_error;  
  840.     }  
  841.   
  842.     //使能udc,硬件操作  
  843.   
  844. register_error:  
  845.     dev->driver = NULL;  
  846.     dev->gadget.dev.driver = NULL;  
  847.     return retval;  
  848. }  
  849.   
  850. static int xxxxx_stop(struct usb_gadget_driver *driver)  
  851. {  
  852.     struct xxxxx_udc *dev = &udc_info;  
  853.     unsigned long    flags;  
  854.   
  855.     if (!dev)  
  856.         return -ENODEV;  
  857.     if (!driver || driver != dev->driver || !driver->unbind)  
  858.         return -EINVAL;  
  859.   
  860.     spin_lock_irqsave(&dev->lock, flags);  
  861.     dev->driver = NULL;  
  862.     stop_activity(dev, driver);  
  863.     spin_unlock_irqrestore(&dev->lock, flags);  
  864.   
  865.     driver->unbind(&dev->gadget);  
  866.     dev->gadget.dev.driver = NULL;  
  867.     dev->driver = NULL;  
  868.   
  869.     device_del(&dev->gadget.dev);  
  870.       
  871.     return 0;  
  872. }  
  873. #endif  
  874.   
  875. /***************************************************************/  
  876. static int xxxxx_udc_probe(struct platform_device *pdev)  
  877. {  
  878.   
  879.     struct xxxxx_udc *udc = &udc_info;  
  880.     struct device *dev = &pdev->dev;  
  881.     int retval;  
  882.     struct resource *res;  
  883. #ifdef XXXXX_USE_IRQ  
  884.     struct resource *resirq;  
  885. #endif  
  886.     resource_size_t res_size;  
  887.   
  888.     dev_dbg(dev, "%s()\n", __func__);  
  889.   
  890. #ifdef XXXXX_HAVE_CLK  
  891.     udc->xxxxx_clk = clk_get(NULL, "xxxxx");  
  892.     if (IS_ERR(udc->xxxxx_clk))   
  893.     {  
  894.         dev_err(dev, "failed to get usb bus clock source\n");  
  895.         return PTR_ERR(udc->xxxxx_clk);  
  896.     }  
  897.   
  898.     clk_enable(udc->xxxxx_clk);  
  899.   
  900. #if (CLK_DELAY_TIME != 0)  
  901.     mdelay(CLK_DELAY_TIME);  
  902. #endif  
  903.   
  904.     dev_dbg(dev, "got and enabled clocks\n");  
  905. #endif //XXXXX_HAVE_CLK  
  906.   
  907.     if (strncmp(pdev->name, "xxxxx", 7) == 0) {  
  908.         dev_info(dev, "xxxxx: increasing FIFO to %d bytes\n", XXXXX_EP_FILO_SIZE);  
  909.         udc_info.ep[1].fifo_size = XXXXX_EP_FILO_SIZE;  
  910.     }  
  911.   
  912.     spin_lock_init (&udc->lock);  
  913.   
  914.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  915.     if (!res)   
  916.     {  
  917.         dev_err(&pdev->dev, "can't get device resources\n");  
  918.         retval = -ENODEV;  
  919.         goto err_clk;  
  920.     }  
  921. /* 
  922.     pdata = pdev->dev.platform_data; 
  923.     if (!pdata) { 
  924.         dev_err(&pdev->dev, "driver needs platform data\n"); 
  925.         return -ENODEV; 
  926.     } 
  927. */  
  928.     res_size = resource_size(res);  
  929.     if (!request_mem_region(res->start, res_size, res->name))   
  930.     {  
  931.         dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",  
  932.             res_size, res->start);  
  933.         retval = -ENOMEM;  
  934.   
  935.         goto err_clk;  
  936.     }  
  937.   
  938.     udc->virl_addr = ioremap(res->start, res_size);  
  939.     if (!udc->virl_addr)   
  940.     {  
  941.         retval = -ENOMEM;  
  942.         goto err_mem;  
  943.     }  
  944.     udc->phy_addr = res->start;  
  945.     udc->reg_size = res_size;  
  946.   
  947.     device_initialize(&udc->gadget.dev);  
  948.     udc->gadget.dev.parent = &pdev->dev;  
  949.     udc->gadget.dev.dma_mask = pdev->dev.dma_mask;  
  950.   
  951.     platform_set_drvdata(pdev, udc);  
  952.   
  953.     //少不了硬件初始化  
  954.     xxxxx_usb_reset(udc);  
  955.     xxxxx_usb_reinit(udc);  
  956.   
  957. #ifdef XXXXX_USE_IRQ  
  958.     resirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  
  959.     if (!resirq)   
  960.     {  
  961.         dev_err(&pdev->dev, "can't get device irq resources\n");  
  962.         retval = -ENODEV;  
  963.         goto err_map;  
  964.     }  
  965.   
  966.     udc->irq_num = resirq->start;  
  967.   
  968.     /* irq setup after old hardware state is cleaned up */  
  969.     retval = request_irq(udc->irq_num, xxxxx_udc_irq, 0, gadget_name, udc);  
  970.     if (retval != 0)   
  971.     {  
  972.         dev_err(dev, "cannot get irq %i, err %d\n", udc->irq_num, retval);  
  973.         retval = -EBUSY;  
  974.         goto err_map;  
  975.     }  
  976.   
  977.     dev_dbg(dev, "got irq %i\n", udc->irq_num);  
  978.   
  979. #endif  
  980.   
  981.     retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);  
  982.     if (retval)  
  983.         goto err_int;  
  984.   
  985. #ifdef XXXXX_DEBUG_FS  
  986.     if (xxxxx_udc_debugfs_root)   
  987.     {  
  988.         udc->debug_info = debugfs_create_file("registers", S_IRUGO, xxxxx_udc_debugfs_root,  
  989.                 udc, &xxxxx_udc_debugfs_fops);  
  990.         if (!udc->debug_info)  
  991.             dev_warn(dev, "debugfs file creation failed\n");  
  992.     }  
  993. #endif  
  994.   
  995.     dev_dbg(dev, "probe ok\n");  
  996.   
  997.     return 0;  
  998.   
  999. err_int:  
  1000. #ifdef XXXXX_USE_IRQ  
  1001.     free_irq(udc->irq_num, udc);  
  1002. #endif  
  1003. err_map:  
  1004.     iounmap(udc->virl_addr);  
  1005. err_mem:  
  1006.     release_mem_region(res->start, res_size);  
  1007. err_clk:  
  1008. #ifdef XXXXX_HAVE_CLK  
  1009.     clk_put(udc->xxxxx_clk);  
  1010.     clk_disable(udc->xxxxx_clk);  
  1011. #endif  
  1012.   
  1013.     return retval;  
  1014. }  
  1015.   
  1016. static int xxxxx_udc_remove(struct platform_device *pdev)  
  1017. {  
  1018.     struct xxxxx_udc *udc = platform_get_drvdata(pdev);  
  1019.   
  1020.     dev_dbg(&pdev->dev, "%s()\n", __func__);  
  1021.   
  1022.     usb_del_gadget_udc(&udc->gadget);  
  1023.     if (udc->driver)  
  1024.         return -EBUSY;  
  1025.   
  1026. #ifdef XXXXX_DEBUG_FS  
  1027.     debugfs_remove(udc->debug_info);  
  1028. #endif  
  1029.   
  1030. #ifdef XXXXX_USE_IRQ  
  1031.     free_irq(udc->irq_num, udc);  
  1032. #endif  
  1033.   
  1034.     iounmap(udc->virl_addr);  
  1035.     release_mem_region(udc->phy_addr, udc->reg_size);  
  1036.   
  1037.     platform_set_drvdata(pdev, NULL);  
  1038.   
  1039. #ifdef XXXXX_HAVE_CLK  
  1040.     if (!IS_ERR(udc->xxxxx_clk) && udc->xxxxx_clk != NULL) {  
  1041.         clk_disable(udc->xxxxx_clk);  
  1042.         clk_put(udc->xxxxx_clk);  
  1043.         udc->xxxxx_clk = NULL;  
  1044.     }  
  1045. #endif  
  1046.   
  1047.     dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);  
  1048.   
  1049.     return 0;  
  1050. }  
  1051.   
  1052. #ifdef CONFIG_PM  
  1053. static int xxxxx_udc_suspend(struct platform_device *pdev, pm_message_t message)  
  1054. {  
  1055.     return 0;  
  1056. }  
  1057.   
  1058. static int xxxxx_udc_resume(struct platform_device *pdev)  
  1059. {  
  1060.     return 0;  
  1061. }  
  1062. #else  
  1063. #define xxxxx_udc_suspend    NULL  
  1064. #define xxxxx_udc_resume    NULL  
  1065. #endif  
  1066.   
  1067. /***************************************************************/  
  1068.   
  1069. static const struct platform_device_id xxxxx_udc_ids[] = {  
  1070.     { "xxxxx-usbgadget", },  
  1071.     { }  
  1072. };  
  1073.   
  1074. MODULE_DEVICE_TABLE(platform, xxxxx_udc_ids);  
  1075.   
  1076. //有些设备可能用struct pci_driver,我就不考虑这么多了。  
  1077. static struct platform_driver udc_driver_xxxxx = {  
  1078.     .driver        = {  
  1079.         .name    = "xxxxx-usbgadget",  
  1080.         .owner    = THIS_MODULE,  
  1081.     },  
  1082.     .probe        = xxxxx_udc_probe,  
  1083.     .remove        = __exit_p(xxxxx_udc_remove),  
  1084.     .suspend    = xxxxx_udc_suspend,  
  1085.     .resume        = xxxxx_udc_resume,  
  1086.     .id_table    = xxxxx_udc_ids,  
  1087. };  
  1088.   
  1089.   
  1090. static int __init udc_init(void)  
  1091. {  
  1092.     int retval;  
  1093.   
  1094.     xxxxx_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);  
  1095.     if (IS_ERR(xxxxx_udc_debugfs_root)) {  
  1096.         printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",  
  1097.             gadget_name, PTR_ERR(xxxxx_udc_debugfs_root));  
  1098.         xxxxx_udc_debugfs_root = NULL;  
  1099.     }  
  1100.   
  1101.     retval = platform_driver_register(&udc_driver_xxxxx);  
  1102.     if (retval)  
  1103.         goto err;  
  1104.   
  1105.     return 0;  
  1106.   
  1107. err:  
  1108.     debugfs_remove(xxxxx_udc_debugfs_root);  
  1109.     return retval;  
  1110. }  
  1111.   
  1112. static void __exit udc_exit(void)  
  1113. {  
  1114.     platform_driver_unregister(&udc_driver_xxxxx);  
  1115.     debugfs_remove(xxxxx_udc_debugfs_root);  
  1116. }  
  1117.   
  1118. module_init(udc_init);  
  1119. module_exit(udc_exit);  
  1120.   
  1121. MODULE_AUTHOR(DRIVER_AUTHOR);  
  1122. MODULE_DESCRIPTION(DRIVER_DESC);  
  1123. MODULE_VERSION(DRIVER_VERSION);  
  1124. MODULE_LICENSE("GPL");  

上期说要用之前的模板写udc驱动。事实我已经做了,等待测试。当我要测试时,我发现还是要用gadget驱动去调试udc驱动。虽然有现成的,但是你如果搞不懂的话,出问题你根本不知道在哪。所以调试udc驱动之前我们要看gadget驱动。

我看了linux-2.6.10没有composite的东西。还是直接操作struct usb_gadget_driver。那已经是过去式了。现在我用的linux-3.2.36是composite。首先我们就看composite有哪些东西,接着通过实例分析怎么用。

 

struct usb_function {

       const char                     *name;//

       struct usb_gadget_strings       **strings;//字符串描述附

    //这个struct usb_descriptor_header包涵了接口描述符和端点描述符

    //在zero中

    /*

static structusb_descriptor_header *fs_source_sink_descs[] = {

         (structusb_descriptor_header *) &source_sink_intf,

         (structusb_descriptor_header *) &fs_sink_desc,

         (structusb_descriptor_header *) &fs_source_desc,

          NULL,

};

    */

       struct usb_descriptor_header  **descriptors;//全速

       struct usb_descriptor_header  **hs_descriptors;//高速

       struct usb_descriptor_header  **ss_descriptors;//超速

 

       struct usb_configuration *config;//下面看到这个,usb_add_function会调用

 

    //绑定可用的源,我看sourecesink就是gedget->ep_list获取可用的端点、并获取端//点的wMaxPacketSize、bEndpointAddress。还有高速和超速描述符赋值

       int                 (*bind)(structusb_configuration *,

                                   structusb_function *);

       void               (*unbind)(structusb_configuration *,

                                   structusb_function *);

       //配置接口,sourecesink就是通过gadget的速度来选择对应的structusb_desctiptor_header

       //就是上面的三个

 

      //set_alt:重配置altsettings

       int                 (*set_alt)(structusb_function *,

                                   unsignedinterface, unsigned alt);

       //get_alt:返回当前活动 altsettings

int                 (*get_alt)(structusb_function *,

                                   unsignedinterface);

    //表示这个function应该disable,原因可能是主机复位、重配置、断开

       void               (*disable)(structusb_function *);

    //setup用于接口特性控制请求

       int                 (*setup)(structusb_function *,

                                   const structusb_ctrlrequest *);

    //suspend和resume不用解释吧

       void               (*suspend)(structusb_function *);

       void               (*resume)(structusb_function *);

 

       //对应主机的GETSTATUS请求

       int                 (*get_status)(structusb_function *);

    //接受到SETFEATURE的USB_INTRF_FUNC_SUSPEND时的回调函数

       int                 (*func_suspend)(structusb_function *,

                                          u8suspend_opt);

 

       struct list_head              list;//下面

       DECLARE_BITMAP(endpoints, 32);

};

 

//把function加入到config中

//就是这句list_add_tail(&function->list,&config->functions);

//然后执行bind(如果有的话),速度标志位赋值

int usb_add_function(struct usb_configuration *config, struct usb_function *function);

 

//这俩个会调用udc中的pull_up,可以多次调用。

//如果deactivate调用三次,那么avtivate要调用三次才能把D+拉高

int usb_function_deactivate(struct usb_function *);

int usb_function_activate(struct usb_function *);

 

/*

int usb_interface_id(structusb_configuration *config,

                struct usb_function *function)

{

        unsigned id =config->next_interface_id;

 

        if (id < MAX_CONFIG_INTERFACES) {

                config->interface[id] =function;

                config->next_interface_id =id + 1;

                return id;

        }

        return -ENODEV;

}

简单,不解释

*/

intusb_interface_id(struct usb_configuration *, struct usb_function *);

 

/*

这就是上面的通过gadget的速度来选择对应的structusb_desctiptor_header

的函数

*/

int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,

                     struct usb_ep *_ep);

 

//usb最多255个接口,linux定义是16个

#define   MAX_CONFIG_INTERFACES           16    /* arbitrary;max 255 */

 

//相当于配置

struct usb_configuration {

       const char                     *label;//相当于name

       struct usb_gadget_strings       **strings;//字符串描述符

       const struct usb_descriptor_header**descriptors;//先前的所有function描述表

 

        //和bind相反 ,bind在哪,下面看到

       void               (*unbind)(structusb_configuration *);

    //代表非标准控制请求,sourecesink实现的就是它

       int                 (*setup)(structusb_configuration *,

                                   const structusb_ctrlrequest *);

 

    //配置描述符的东西,spec说的很详细    

       u8                  bConfigurationValue;

       u8                  iConfiguration;

       u8                  bmAttributes;

       u8                  bMaxPower;

 

    //对应设备

       struct usb_composite_dev      *cdev;

 

       struct list_head       list;  //和上面的结构体的list一样

       struct list_head       functions;       //上面已看到使用

       u8                  next_interface_id;   //下一个接口id,上面的usb_interface_id有用

    // usb_add_function会设置它们

       unsigned         superspeed:1;

       unsigned         highspeed:1;

       unsigned         fullspeed:1;

       struct usb_function *interface[MAX_CONFIG_INTERFACES];

};

 

   //和上面的usb_add_function差不多,bind对应上面的unbind

intusb_add_config(struct usb_composite_dev *cdev,

                struct usb_configuration*config,

                int (*bind)(structusb_configuration *))

 

//相当于usb_gadget_driver

struct usb_composite_driver {

       const char                            *name;//

       const char                            *iProduct;//产品

       const char                            *iManufacturer;//厂商信息

       const struct usb_device_descriptor *dev;//下面

       struct usb_gadget_strings              **strings;//字符串描述符

       enum usb_device_speed               max_speed;//最高速度

       unsigned         needs_serial:1;//是否需要iSerialNumber

 

       //下面不解释

       int                 (*unbind)(structusb_composite_dev *);

 

       void               (*disconnect)(structusb_composite_dev *);

 

       /* global suspend hooks */

       void               (*suspend)(structusb_composite_dev *);

       void               (*resume)(structusb_composite_dev *);

};

 

//先根据driver给composite_driver赋值,再

//usb_gadget_probe_driver(&composite_driver, composite_bind);

/*

composite_driver是个全局的变量

static struct usb_gadget_driver composite_driver = {

#ifdefCONFIG_USB_GADGET_SUPERSPEED

        .speed          = USB_SPEED_SUPER,

#else

        .speed          = USB_SPEED_HIGH,

#endif

 

        .unbind         = composite_unbind,

 

        .setup          = composite_setup,

        .disconnect     = composite_disconnect,

 

        .suspend        = composite_suspend,

        .resume         = composite_resume,

 

        .driver = {

                .owner          = THIS_MODULE,

        },

};

composite就是通过它和gadget的接口联系的

*/

extern int usb_composite_probe(struct usb_composite_driver *driver,

                            int (*bind)(struct usb_composite_dev*cdev));

extern void usb_composite_unregister(struct usb_composite_driver *driver);

//继续控制传输

extern void usb_composite_setup_continue(struct usb_composite_dev*cdev);

 

//相当于设备

struct usb_composite_dev {

       struct usb_gadget           *gadget;//只读,抽象的表示gadget的usb外设控制器

       struct usb_request          *req;//用于控制答复

       unsigned                bufsiz;//req的预分配大小

 

       struct usb_configuration *config;//当前活动的config

 

       /* private: */

       /* internals */

       unsigned int                  suspended:1;

       struct usb_device_descriptor  desc;//设备描述符

       struct list_head              configs;//配置链表

       struct usb_composite_driver  *driver;//上面的

       u8                         next_string_id;

    //下面表示对应的字符串的id

       u8                         manufacturer_override;

       u8                         product_override;

       u8                         serial_override;

 

       /*deactivations是int usb_function_deactivate(struct usb_function *);

         int usb_function_activate(struct usb_function *);计数用的

      */

 

       unsigned                deactivations;

 

       /* the composite driver won't completethe control transfer's

        *data/status stages till delayed_status is zero.//这段英文自己理解

        */

/*

若果设备

USB_REQ_SET_INTERFACE结果返回USB_GADGET_DELAYED_STATUS,计数加1

usb_composite_setup_continue计数减1,到0继续执行控制请求。

*/

       int                        delayed_status;

 

       /* protects deactivations anddelayed_status counts*/

       spinlock_t                     lock;

};

 

/*

int usb_string_id(struct usb_composite_dev *cdev)

{

        if (cdev->next_string_id < 254) {

                /* string id 0 is reserved byUSB spec for list of

                 * supported languages */

                /* 255 reserved as well? --mina86 */

                cdev->next_string_id++;

                return cdev->next_string_id;

        }

        return -ENODEV;

}

简单

看zero

       id = usb_string_id(cdev);

       if (id < 0)

              return id;

       strings_dev[STRING_MANUFACTURER_IDX].id =id;

       device_desc.iManufacturer = id;

 

       id = usb_string_id(cdev);

       if (id < 0)

              return id;

       strings_dev[STRING_PRODUCT_IDX].id = id;

       device_desc.iProduct = id;

 

       id = usb_string_id(cdev);

       if (id < 0)

              return id;

       strings_dev[STRING_SERIAL_IDX].id = id;

       device_desc.iSerialNumber = id;

就是给上面的字符串分配id

*/

extern int usb_string_id(struct usb_composite_dev *c);

//下面两个是批量分配

extern intusb_string_ids_tab(struct usb_composite_dev *c,

                           struct usb_string *str);

extern intusb_string_ids_n(struct usb_composite_dev *c, unsigned n);

 

这几天在群里忙着和别人讨论问题,一直没在弄了。今天简单看了一下zero.c

比较让我惊奇的是,有个

/* If the optional "autoresume" mode isenabled, it provides good

 * functionalcoverage for the "USBCV" test harness from USB-IF.

 */

unsigned autoresume = DEFAULT_AUTORESUME;

module_param(autoresume, uint, S_IRUGO);

MODULE_PARM_DESC(autoresume, "gadget_transfer, or seconds before remotewakeup");

从英文看是为USB-IF测试软件USBCV(可以下载到)做的,这就不管了。

我之前看过hub有个自动挂起的东西。它的主要就是一定时间(默认2s)不用就自动suspend。

这里先假设是2秒吧

在f_sourcesink.c sourcesink_add

       /* support autoresume for remote wakeup testing */

       if (autoresume)

                sourcesink_driver.bmAttributes|= USB_CONFIG_ATT_WAKEUP;

 

       /* support OTG systems */

       if (gadget_is_otg(cdev->gadget)) {

                sourcesink_driver.descriptors =otg_desc;

                sourcesink_driver.bmAttributes|= USB_CONFIG_ATT_WAKEUP;

       }

下面的otg是几乎每个gadget驱动都这样写。我们不管otg

上面说的很清楚支持autoresume为了远程唤醒功能测试

static void zero_autoresume(unsignedlong _c)

{

       struct usb_composite_dev       *cdev = (void *)_c;

       struct usb_gadget               *g= cdev->gadget;

 

       /* unconfigured devices can't issue wakeups */

       if (!cdev->config)

                return;

 

       /* Normally the host would be woken up for something

        * more significant than just a timer firing; likely

        * because of some direct user request.

        */

       if (g->speed != USB_SPEED_UNKNOWN) {

                int status =usb_gadget_wakeup(g);//这个会调用udc中的wakeup

                INFO(cdev, "%s -->%d\n", __func__, status);

       }

}

 

static void zero_suspend(structusb_composite_dev *cdev)

{

       if (cdev->gadget->speed == USB_SPEED_UNKNOWN)

                return;

 

       if (autoresume) {

               mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));

                DBG(cdev, "suspend, wakeupin %d seconds\n", autoresume);

       } else

                DBG(cdev, "%s\n",__func__);

}

 

static void zero_resume(structusb_composite_dev *cdev)

{

       DBG(cdev, "%s\n", __func__);

       del_timer(&autoresume_timer);

}

这个zero_suspend和zero_resume一般都在udc的中断处理中调用

有autoresume也就是定时到时自动wakeup。

没这个的话,这两个函数就等于什么都没干。

 

主机端set feature会有个叫remote_wake的值是0x0001,与配置描述符对应的是

sourcesink_driver.bmAttributes|= USB_CONFIG_ATT_WAKEUP,前面是主机的请求,后面是表示设备有这个能力。

 

我看了net2272有个IRQSTAT1寄存器,如果有请求改变,再判断是否是suspend请求

是调用dev->driver->suspend不是调用dev->driver_resume。这两个不对应上面的。

是composite_suspend和composite_resume。在它们里面调用上面的。

 

在看s3c2440的,它的suspend比较变态,每当总线无活动多于 3ms 将置位此位(指的是suspend中断标志位)。因此,如果 MCU 不在第一个挂起中断后停止时钟,它将会持续每 3ms 中断一次,直到 USB 总线无活动。默认是禁止此中断。

 

我们看第一句话,可以看出s3c2440的suspend中断和主机无关,真的叫自动化。

那个zero的resume大概就是已经唤醒了就不要在执行后面的自动化了,所以del timer。

把这个suspend和resume提出来是因为我要写的东西不会包涵它们。

 

我这几天写文章就像挤牙膏啊,再说一点。gadget_chips.h

这个里面有些东西要定义一下,

static inline int usb_gadget_controller_number(struct usb_gadget *gadget);

获取控制器号

static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
是否支持altsettings,你会看到它里面放的是不支持的,可以想到一般的控制器是支持altsettings的。

说一下第一个

我们如果要写个自己的udc,我的是s3c2440,大家知道s3c2440用的是s3c2410。现在让它独立

#define gadget_is_s3c2410(g)            (!strcmp("s3c2410_udc", (g)->name))
#define gadget_is_s3c2440(g)            (!strcmp("s3c2440_udc", (g)->name))
首先定义这个,"s3c2440_udc"要和它的udc驱动一样的。

在usb_gadget_controller_number()里面加上

        else if (gadget_is_s3c2410(gadget))
                return 0x12;
        else if (gadget_is_s3c2440(gadget))
                return 0x12;

其实我还是用了一样的数。

看zero怎么用这个
    gcnum = usb_gadget_controller_number(gadget);
    if (gcnum >= 0)
        device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
    else {
        /* gadget gadget_transfer is so simple (for now, no altsettings) that
         * it SHOULD NOT have problems with bulk-capable hardware.
         * so just warn about unrcognized controllers -- don't panic.
         *
         * things like configuration and altsetting numbering
         * can need hardware-specific attention though.
         */
        pr_warning("%s: controller '%s' not recognized\n",
            longname, gadget->name);
        device_desc.bcdDevice = cpu_to_le16(0x9999);
    }

就获得之后转为小端做为设备bcd。就是设备描述符里的。没获得就是0x9999

今天说的是字符串描述符,struct usb_gadget_strings我之前说是字符串描述符并不准确,

真正的描述符是struct usb_string_descriptor

上一篇说的结构体中有很多都包涵了struct usb_gadget_strings,它们是struct usb_function、struct usb_configuration、struct usb_composite_driver三世同堂

struct usb_composite_drive包涵struct usb_configuration包涵struct usb_function

而且zero.c f_souresink.c f_loopback.c(这个我不用就不看了)composite.c都有

string usb_string_descripter结构体,这篇文章就了解一下他们的关系

先看一下这几个结构体

/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
        __u8  bLength;//描述符长度
        __u8  bDescriptorType;//就是USB_DT_STRING  0x03

        __le16 wData[1];                /* UTF-16LE encoded */
} __attribute__ ((packed));

 

//这里可以看出usb_gadget_strings包涵struct usb_string

//实例中的定义会看到

struct usb_gadget_strings {
        u16                     language;       /* 0x0409 for en-us */
        struct usb_string       *strings;
};

struct usb_string {
        u8                      id;
        const char              *s;
};

不过在驱动中我们大部分看到的是struct usb_string

先看zero.c

//首先定义

static const char longname[] = "Gadget gadget_transfer";

static char manufacturer[50];

/* default serial number takes at least two packets */
static char serial[] = "0123456789.0123456789.0123456789";

static struct usb_string strings_dev[] = {
    [STRING_MANUFACTURER_IDX].s = manufacturer,
    [STRING_PRODUCT_IDX].s = longname,
    [STRING_SERIAL_IDX].s = serial,
    {  }            /* end of list */
};

static struct usb_gadget_strings stringtab_dev = {
    .language    = 0x0409,    /* en-us */
    .strings    = strings_dev,//包涵struct usb_string
};

static struct usb_gadget_strings *dev_strings[] = {
    &stringtab_dev,
    NULL,
};

//没什么要解释的吧

//在gadget_transfer_bind()中

    //各字符串描述符的引索
    id = usb_string_id(cdev);//这个东西之前有说过,就是cdev->next_string_id++返回,怕id冲突
    if (id < 0)
        return id;
    strings_dev[STRING_MANUFACTURER_IDX].id = id;
    device_desc.iManufacturer = id;

    id = usb_string_id(cdev);
    if (id < 0)
        return id;
    strings_dev[STRING_PRODUCT_IDX].id = id;
    device_desc.iProduct = id;

    id = usb_string_id(cdev);
    if (id < 0)
        return id;
    strings_dev[STRING_SERIAL_IDX].id = id;
    device_desc.iSerialNumber = id;

//manufacturer[50]下面赋值

    //本来下面这句就是给manufacturer赋值,可是非要整个init_utsname()
    //linux gadget的驱动都有这个,我们看一下吧
    /*
        .name = {
            .sysname        = UTS_SYSNAME,
            .nodename       = UTS_NODENAME,
            .release        = UTS_RELEASE,
            .version        = UTS_VERSION,
            .machine        = UTS_MACHINE,
            .domainname     = UTS_DOMAINNAME,
        },
        #ifndef UTS_SYSNAME//也有定义"uClinux"等
            #define UTS_SYSNAME "Linux"
        #endif

        #define UTS_RELEASE "3.2.0"//我的版本
    */
    snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
        init_utsname()->sysname, init_utsname()->release,
        gadget->name);

//还有个静态结构

static struct usb_composite_driver gadget_transfer_driver = {
    .name        = "gadget_transfer",
    .dev        = &device_desc,
    .strings    = dev_strings,
    .max_speed    = USB_SPEED_SUPER,
    .unbind        = gadget_transfer_unbind,
};//我们找到了爷爷usb_composite_driver

//f_sourecesink.c 我只用sink

static struct usb_string strings_sourcesink[] = {
    [0].s = "source and sink data",
    {  }            /* end of list */
};

static struct usb_gadget_strings stringtab_sourcesink = {
    .language    = 0x0409,    /* en-us */
    .strings    = strings_sourcesink,
};

static struct usb_gadget_strings *sourcesink_strings[] = {
    &stringtab_sourcesink,
    NULL,
};

static struct usb_configuration sourcesink_driver = {
    .label        = "source/sink",
    .strings    = sourcesink_strings,
    .setup        = sourcesink_setup,
    .bConfigurationValue = 3,
    .bmAttributes    = USB_CONFIG_ATT_SELFPOWER,
    /* .iConfiguration = DYNAMIC */
};//我们找到了爸爸struct usb_configuration

probe时会加入cdev中

usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);

list_add_tail(&config->list, &cdev->configs);//下面会见到查找列表

 

还差儿子struct usb_function

    ss->function.name = "source/sink";
    ss->function.descriptors = fs_source_sink_descs;
    ss->function.bind = sourcesink_bind;
    ss->function.unbind = sourcesink_unbind;
    ss->function.set_alt = sourcesink_set_alt;
    ss->function.disable = sourcesink_disable;

    status = usb_add_function(c, &ss->function);

很可惜这是个不争气的孩子,没有给string赋值

//composite.c 

struct usb_composite_dev中的这几位,下面会赋值

       u8                         manufacturer_override;

       u8                         product_override;

       u8                         serial_override;


static char *iManufacturer;
module_param(iManufacturer, charp, 0);
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");

static char *iProduct;
module_param(iProduct, charp, 0);
MODULE_PARM_DESC(iProduct, "USB Product string");

static char *iSerialNumber;
module_param(iSerialNumber, charp, 0);
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");

//上面的可以装载时赋值
static char composite_manufacturer[50];

在static int composite_bind(struct usb_gadget *gadget)中

//有个全局的tatic struct usb_composite_driver *composite;

//在int usb_composite_probe(struct usb_composite_driver *driver,
//                   int (*bind)(struct usb_composite_dev *cdev))中

//composite =driver,对我们来说就是zero中的struct usb_composite_driver

    cdev->desc = *composite->dev;

/*

cdev->desc对我们来说就是zero中的

static struct usb_device_descriptor device_desc = {
    .bLength =        sizeof device_desc,
    .bDescriptorType =    USB_DT_DEVICE,

    .bcdUSB =        cpu_to_le16(0x0200),
    .bDeviceClass =        USB_CLASS_VENDOR_SPEC,

    .idVendor =        cpu_to_le16(DRIVER_VENDOR_NUM),//我们有赋值
    .idProduct =        cpu_to_le16(DRIVER_PRODUCT_NUM),
    .bNumConfigurations =    2,
};

*/

 

    /* string overrides */
    if (iManufacturer || !cdev->desc.iManufacturer) {//只要iMonufacturer指定就会用

/*

对于struct usb_composite_driver它里面也有

 

       const char                            *iProduct;//产品

       const char                            *iManufacturer;//厂商信息

zero并没有指定,下面会看到composite->iManufacturer和

composite->iProduct判断

*/

        if (!iManufacturer && !composite->iManufacturer &&
            !*composite_manufacturer)//如果这几个都没有指定
            snprintf(composite_manufacturer,
                 sizeof composite_manufacturer,
                 "%s %s with %s",
                 init_utsname()->sysname,
                 init_utsname()->release,
                 gadget->name);//这个和zero中的一样

/*
static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
{
    if (!*desc) {//如果不是0,就是已分配过id
        int ret = usb_string_id(cdev);//这个已说过
        if (unlikely(ret < 0))
            WARNING(cdev, "failed to override string ID\n");//出错最后返回就是0
        else
            *desc = ret;
    }

    return *desc;
}

*/        

           cdev->manufacturer_override =
            override_id(cdev, &cdev->desc.iManufacturer);
    }
//下面逻辑和上面差不多,不赘述了
    if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
        cdev->product_override =
            override_id(cdev, &cdev->desc.iProduct);

    if (iSerialNumber)
        cdev->serial_override =
            override_id(cdev, &cdev->desc.iSerialNumber);

 

上面这一大堆就是初始化赋值,下面看usb请求,请求我不细说了,就是主机发获得字符串描述符请求时

调用int get_string(struct usb_composite_dev *cdev,  void *buf, u16 language, int id)

static int get_string(struct usb_composite_dev *cdev,
        void *buf, u16 language, int id)
{
    struct usb_configuration    *c;
    struct usb_function        *f;
    int                len;
    const char            *str;

    /* Yes, not only is USB's I18N support probably more than most
     * folk will ever care about ... also, it's all supported here.
     * (Except for UTF8 support for Unicode's "Astral Planes".)
     */

    /* 0 == report all available language codes *///这里写的很清楚,0返回所有支持语言codes
    if (id == 0) {
        struct usb_string_descriptor    *s = buf;//字符串描述符,这个buf就是usb_request中的buf,我们就就是要给它赋值
        struct usb_gadget_strings    **sp;

        memset(s, 0, 256);
        s->bDescriptorType = USB_DT_STRING;//开始就说了
//下面直到list_for_each_entry结束,我们看到了上面说的包涵关系

/*

唯一要说的就是void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)

不贴代码了,就是获得struct usb_gadget_strings的language id并与buf中比较

如果没有相同的就记录下来,里面有个126限制下面也有,应该是指buf的最大长度

*/

        sp = composite->strings;//就是zero中的dev_strings
        if (sp)
            collect_langs(sp, s->wData);

        list_for_each_entry(c, &cdev->configs, list) {
            sp = c->strings;
            if (sp)
                collect_langs(sp, s->wData);

            list_for_each_entry(f, &c->functions, list) {
                sp = f->strings;
                if (sp)
                    collect_langs(sp, s->wData);
            }
        }

        for (len = 0; len <= 126 && s->wData[len]; len++)
            continue;
        if (!len)
            return -EINVAL;

        s->bLength = 2 * (len + 1);//这个其实就是2 * len + 2,前面*2是应为wData是le16就是16位,+2是bLength和bDescriptorType
        return s->bLength;
    }

    /* Otherwise, look up and return a specified string.  First
     * check if the string has not been overridden.
     */
    if (cdev->manufacturer_override == id)
        str = iManufacturer ?: composite->iManufacturer ?:
            composite_manufacturer;
    else if (cdev->product_override == id)
        str = iProduct ?: composite->iProduct;
    else if (cdev->serial_override == id)
        str = iSerialNumber;
    else
        str = NULL;
    if (str) {
        struct usb_gadget_strings strings = {
            .language = language,
            .strings  = &(struct usb_string) { 0xff, str }
        };
        return usb_gadget_get_string(&strings, 0xff, buf);

//usb_gadget_get_string 

//linux解释fill out a string descriptor,不用说了吧,不过你看一下代码会发现,它又判断了id == 0,在这有点多余
    }

//上面一段就是先用转载是指定的strings,下面不看也知道,肯定是查三世同堂的strings

    /* String IDs are device-scoped, so we look up each string
     * table we're told about.  These lookups are infrequent;
     * simpler-is-better here.
     */

//和上面统计语言ID逻辑一样,就是用了lookup_string

/*

static int lookup_string(
    struct usb_gadget_strings    **sp,
    void                *buf,
    u16                language,
    int                id
)

也会调用usb_gadget_get_string,不过调用之前会判断一下

是否和指定language相同

*/

    if (composite->strings) {
        len = lookup_string(composite->strings, buf, language, id);
        if (len > 0)
            return len;
    }
    list_for_each_entry(c, &cdev->configs, list) {
        if (c->strings) {
            len = lookup_string(c->strings, buf, language, id);
            if (len > 0)
                return len;
        }
        list_for_each_entry(f, &c->functions, list) {
            if (!f->strings)
                continue;
            len = lookup_string(f->strings, buf, language, id);
            if (len > 0)
                return len;
        }
    }
    return -EINVAL;
}

 

bind和字符串描述符一样也是有多级关系,首先说一下usb很基础的关系

一个设备可能有多个配置

一个配置可能有多个接口

一个接口可能有多个端点或设置

还记得我在自娱自乐2中说的的结构体吧

我们先变通一下

struct usb_function 相当于接口

struct usb_configuration 相当于配置

struct usb_composite_dev 相当于设备

bind会建立他们的关系,当然bind不止是这层涵义

 

我们在看它们的bind之前先看看

int usb_composite_probe(struct usb_composite_driver *driver,

                     int(*bind)(struct usb_composite_dev *cdev))

这玩意也有个绑定

在zero中usb_composite_probe(&gadget_transfer_driver,gadget_transfer_bind);

gadget_transfer_bind()这个函数我在之前已经列出了它的一部分,只是没明说

主要就是分配厂商设备id,获取设备bcd码,生成厂商字符串。定时器初始化话。

还有重要一点就是调用sourcesink_add(loop我们不看)

int usb_composite_probe(structusb_composite_driver *driver,

                     int(*bind)(struct usb_composite_dev *cdev))

{

     //一些判断赋值省去

     composite = driver;

     composite_gadget_bind = bind;//请记住zero提供的bind函数在此只是赋值

 

     return usb_gadget_probe_driver(&composite_driver, composite_bind);

//composite_driver前面的文章已说过了,这个usb_gadget_probe_drvier不贴全代码了,看一点

/*

        //这个udc是从udc_list中找到的

        if (udc_is_newstyle(udc)) {//自娱自乐1有说udc_is_newstyle()

                ret =bind(udc->gadget);//这个bind是composite_bind,不要搞错

                if (ret)

                        goto err1;

                //…

        } else {

 

                ret =usb_gadget_start(udc->gadget, driver, bind);//gadget->ops->start(driver, bind);不懂就看我之前写的udc模板

                //…

        }

        不管怎么样都要调用composite_bind()函数,下面看到

*/

}

static int composite_bind(struct usb_gadget *gadget)//记住这个gadget是udc中的

{

     structusb_composite_dev    *cdev;

     int                status = -ENOMEM;

 

     cdev = kzalloc(sizeof *cdev, GFP_KERNEL);

     if(!cdev)

         returnstatus;

 

     spin_lock_init(&cdev->lock);//初始化lock

     cdev->gadget = gadget;//保存对应udc中的gadget

     set_gadget_data(gadget, cdev);//相当于gadget->dev->driver_data= cdev;

     //上面两句就是把gadget于udc驱动联系起来

     INIT_LIST_HEAD(&cdev->configs);//初始化配置链表头

 

     cdev->req =usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);//会调用udc中对应方法

     if(!cdev->req)

         gotofail;

     cdev->req->buf =kmalloc(USB_BUFSIZ, GFP_KERNEL);

     if(!cdev->req->buf)

         gotofail;

     cdev->req->complete =composite_setup_complete;//这个是请求完成函数,暂且不管

     gadget->ep0->driver_data =cdev;

 

     cdev->bufsiz = USB_BUFSIZ;

     cdev->driver = composite;//还记得他是谁吧,就是zero中的gadget_transfer_driver

 

     if(CONFIG_USB_GADGET_VBUS_DRAW/*内核配置*/ <= USB_SELF_POWER_VBUS_MAX_DRAW/*100*/)//电力不足

         usb_gadget_set_selfpowered(gadget);//设为自供电

 

     usb_ep_autoconfig_reset(cdev->gadget);

/*

void usb_ep_autoconfig_reset (structusb_gadget *gadget)

{

       struct usb_ep   *ep;

 

       list_for_each_entry (ep, &gadget->ep_list, ep_list) {

                ep->driver_data = NULL;

       }

#ifdef MANY_ENDPOINTS

       in_epnum = 0;

#endif

       epnum = 0;

}

没什么要解释吧

*/

     status =composite_gadget_bind(cdev);//还记的它把,就是zero中的bind函数gadget_transfer_bind,这里面当然会调用sourcesink_add和loopback_add,我们下面看

     if(status < 0)

         gotofail;

 

     cdev->desc =*composite->dev;//zero中的device_desc

 

//这里有一段就是我们之前说的判断装载是是否定义字符串的代码,

//当然还有厂商、产品id等。直接略过

 

//如果看过我之前写的设备模型,应该对device_create_file不陌生吧

     status =device_create_file(&gadget->dev, &dev_attr_suspended);

     if(status)

         gotofail;

 

     return0;

 

fail:

     composite_unbind(gadget);

     returnstatus;

}

//上面就相当于设备的绑定,设备过后当然就是配置

       if (loopdefault) {

                loopback_add(cdev, autoresume !=0);

                sourcesink_add(cdev, autoresume!= 0);

       } else {

                sourcesink_add(cdev, autoresume!= 0);

                loopback_add(cdev, autoresume!= 0);

       }

不管loopdefault是什么,我们可以认为zero有两个配置

我只用f_sourcesink.c

sourcesink_add主要就是

usb_add_config(cdev,&sourcesink_driver, sourcesink_bind_config);

//为了节约纸张,我去掉了一下注释和DBG()

int usb_add_config(struct usb_composite_dev*cdev,

         structusb_configuration *config,

         int(*bind)(struct usb_configuration *))

{

     int                status = -EINVAL;

     structusb_configuration    *c;

 

     if(!config->bConfigurationValue || !bind)

         gotodone;

 

     list_for_each_entry(c,&cdev->configs, list) {//这段很好理解就是判断是否已经注册过了

         if(c->bConfigurationValue == config->bConfigurationValue) {

              status = -EBUSY;

              goto done;

         }

     }

 

     config->cdev = cdev;

     list_add_tail(&config->list,&cdev->configs);//加入设备的配置链表

 

     INIT_LIST_HEAD(&config->functions);//初始化配置中的接口链表头

     config->next_interface_id =0;//接口id初始化为0

 

     status = bind(config);// 就是sourcesink_bind_config,这个就是把接口加入配置,下面看

     if(status < 0) {

         list_del(&config->list);

         config->cdev = NULL;

     } else{

         unsigned i;

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

              struct usb_function    *f =config->interface[i];

 

              if (!f)

                   continue;

         }

     }

 

     usb_ep_autoconfig_reset(cdev->gadget);//上面说过,不过上面的gadget是udc中的,这个是zero驱动中的

 

done:

     returnstatus;

}

//到这我们可以说配置绑完了,下面看接口

static int __initsourcesink_bind_config(struct usb_configuration*c)

{

     structf_sourcesink    *ss;

     int           status;

 

     ss = kzalloc(sizeof *ss, GFP_KERNEL);

     if(!ss)

         return-ENOMEM;

 

     ss->function.name = "source/sink";

     ss->function.descriptors =fs_source_sink_descs;

     ss->function.bind =sourcesink_bind;

     ss->function.unbind =sourcesink_unbind;

     ss->function.set_alt =sourcesink_set_alt;

     ss->function.disable =sourcesink_disable;    

status = usb_add_function(c,&ss->function);//下面会看到

     if(status)

         kfree(ss);

     returnstatus;

}

sink只用一个接口,在这我们要改变一下思维,上面说struct usb_function 相当于接口,在这

我改为struct f_sourcesink相当于接口,struct usb_function相当于接口的操作功能集合

struct f_sourcesink {

     structusb_function    function;

 

     structusb_ep      *in_ep;

     structusb_ep      *out_ep;

};

 

//为了节约纸张,我去掉了一下注释和DBG()

int usb_add_function(struct usb_configuration*config,

         structusb_function *function)

{

     int  value = -EINVAL;

 

     if(!function->set_alt || !function->disable)//set_alt和disable必须实现

         gotodone;

 

     function->config = config;//记住父亲是谁

     list_add_tail(&function->list,&config->functions);

 

     if(function->bind) {//下面看到的sourcesink_bind

         value =function->bind(config, function);

         if(value < 0) {

              list_del(&function->list);

              function->config =NULL;

         }

     } else

         value = 0;

 

     //设置速度标志

     if(!config->fullspeed && function->descriptors)

         config->fullspeed = true;

     if(!config->highspeed && function->hs_descriptors)

         config->highspeed = true;

     if(!config->superspeed && function->ss_descriptors)

         config->superspeed = true;

 

done:

     returnvalue;

}

//到这我们看到接口也绑到配置了,只剩下端点了

static int __init

sourcesink_bind(struct usb_configuration *c, struct usb_function *f)

{

        struct usb_composite_dev*cdev = c->cdev;

        struct f_sourcesink     *ss = func_to_ss(f);

        int     id;

 

        id = usb_interface_id(c, f);//和之前说的分配id没什么两样

        if (id < 0)

                return id;

       source_sink_intf.bInterfaceNumber = id;//接口id赋值

 

        ss->in_ep =usb_ep_autoconfig(cdev->gadget, &fs_source_desc);

/*

struct usb_ep *usb_ep_autoconfig(

        struct usb_gadget               *gadget,

        structusb_endpoint_descriptor  *desc

)

{

        returnusb_ep_autoconfig_ss(gadget, desc, NULL);

}

struct usb_ep *usb_ep_autoconfig_ss(

        struct usb_gadget               *gadget,

        structusb_endpoint_descriptor  *desc,

        structusb_ss_ep_comp_descriptor *ep_comp

)

{

//没全贴,重点就是下面这个,就是从gadget的ep列表中找到合适的ep,主要通过ep_matches()

//这个不细说了,还要说一下就是是通过desc的信息查找的

        list_for_each_entry (ep,&gadget->ep_list, ep_list) {

                if(ep_matches(gadget, ep, desc, ep_comp))

                        return ep;

        }

}

*/

        if (!ss->in_ep) {

autoconf_fail:

                return -ENODEV;

        }

        ss->in_ep->driver_data= cdev;  /* claim */

 

        ss->out_ep =usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);

//和上面一样的,我们可以认为这个就是把端点绑定到接口

        if (!ss->out_ep)

                goto autoconf_fail;

       ss->out_ep->driver_data = cdev; /* claim */

 

        //高速设置

        if(gadget_is_dualspeed(c->cdev->gadget)) {

               hs_source_desc.bEndpointAddress =

                               fs_source_desc.bEndpointAddress;

               hs_sink_desc.bEndpointAddress =

                                fs_sink_desc.bEndpointAddress;

                f->hs_descriptors= hs_source_sink_descs;

        }

        //超速设置

        if(gadget_is_superspeed(c->cdev->gadget)) {

               ss_source_desc.bEndpointAddress =

                               fs_source_desc.bEndpointAddress;

               ss_sink_desc.bEndpointAddress =

                               fs_sink_desc.bEndpointAddress;

                f->ss_descriptors= ss_source_sink_descs;

        }

 

        return 0;

}

该绑的都绑了,我们来总结一下吧

     看上面的过程,bind首先把端点、接口、配置、设备绑在一起

     还有最关键是把gadget和udc绑在一起,这个有两个地方体现,一个是composite_bind()调用传入了udc的gadget,还有就是sourcesink_bind()调用usb_ep_autoconfig()找端点。

    事实上绑定还有一个涵义就是把gadget驱动和其他驱动联系到一起,例如串口、网卡等。我在后面也尽量模拟一下这个过程,当然是简单的驱动。

最后还要提一下

     if(!function->set_alt || !function->disable)//set_alt和disable必须实现

         gotodone;

至少告诉我们基于composite的gadget驱动,必须要实现它们,这个对后面写gadget有用。


 

自娱自乐5之Linux gadget驱动4(接受发送,complete函数,setup函数)

 分类:
 

f_sourcesink.c里面在执行set_alt方法后就调用source_sink_start_ep(),这里面就有usb_ep_queue()可以认为开始进行数据交互。后期我要改一下这个过程,通过一个简单的misc驱动去分开调用接受发送

我们现在看

static int source_sink_start_ep(struct f_sourcesink *ss,boolis_in)

{

     structusb_ep      *ep;

     structusb_request *req;

     int           status;

 

     ep = is_in ? ss->in_ep :ss->out_ep;

//是in还是out,

     req = alloc_ep_req(ep);

     if(!req)

         return-ENOMEM;

 

     req->complete =source_sink_complete;//下面来说

     if(is_in)// 这里要说的就是in是对于主机来说

         reinit_write_data(ep, req);//把数据写到req的buf中

     else

         memset(req->buf, 0x55,req->length);//初始化req->buf

 

     status = usb_ep_queue(ep, req,GFP_ATOMIC);//提交req到硬件fifo

     if(status) {

         structusb_composite_dev    *cdev;

 

         cdev =ss->function.config->cdev;

         free_ep_req(ep, req);

     }

/*

这里总结一下数据交互过程

1. 动态申请空间。

2. 设置完成函数。

3. 是in就或取数据(操作硬件的话,可能用到别的驱动),是out就初始化req->buf。

4. 提交req到硬件fifo。

万变不离其宗,大概就这样。

*/

 

     returnstatus;

}

 

看完成函数

static void source_sink_complete(struct usb_ep *ep,structusb_request *req)

{

     structf_sourcesink    *ss = ep->driver_data;

     structusb_composite_dev *cdev = ss->function.config->cdev;

     int           status = req->status;

 

     switch(status) {

 

     case0:                /*normal completion? */

/*

正常,继续操作req。

*/

         if(ep == ss->out_ep) {

              check_read_data(ss,req);//f_sourcesink提供,MOD63或0

              memset(req->buf,0x55, req->length);

         } else

              reinit_write_data(ep,req);

         break;

 

     /*this endpoint is normally active while we're configured */

     case-ECONNABORTED:         /* hardware forced ep reset */

     case-ECONNRESET:      /*request dequeued */

     case-ESHUTDOWN:       /*disconnect from host *///这几个说明传输停止

         if(ep == ss->out_ep)

              check_read_data(ss,req);

         free_ep_req(ep, req);

         return;

 

     case-EOVERFLOW:       /*buffer overrun on read means that

                        * we didn't provide a big enough

                        * buffer.

                        */

     default:

     case-EREMOTEIO:       /*short read *///一些错误,没有操作buf,相当于重发

         break;

     }

 

     status = usb_ep_queue(ep, req,GFP_ATOMIC);

//继续提交,几乎所有的complete都要做的,正常就要继续

}

/*

总结一下complete

1.是否有一些错误,根据错误判断是停止还是重发。

2.正常就要继续提交req。

*/

最后是setup

这个要从udc说起

看s3c2410,假设ep0中断,且是置位了setup_end位

会调用

dev->driver->setup(&dev->gadget,crq);

就是它,事实这就是和usb枚举相关

static int

composite_setup(struct usb_gadget *gadget,conststructusb_ctrlrequest *ctrl)//ctrl是硬件获得的

{

     u8                 intf = w_index & 0xFF;

     structusb_function         *f = NULL;

     //省掉了一大堆

     switch(ctrl->bRequest) {

 

     //对于各请求,composite_setup写成了一个统一的,我们只要实现接口就可以了

     caseUSB_REQ_GET_DESCRIPTOR:

              /* any number of configs can work */

     caseUSB_REQ_SET_CONFIGURATION:

     caseUSB_REQ_GET_CONFIGURATION:

     caseUSB_REQ_SET_INTERFACE:

     caseUSB_REQ_GET_INTERFACE:

     caseUSB_REQ_GET_STATUS:

     caseUSB_REQ_CLEAR_FEATURE:

     caseUSB_REQ_SET_FEATURE:

         break;

     default:

         switch(ctrl->bRequestType & USB_RECIP_MASK) {//接受对象

         caseUSB_RECIP_INTERFACE://intf = w_index & 0xFF,对应的接口号

              if (!cdev->config || intf >=MAX_CONFIG_INTERFACES)

                   break;

              f =cdev->config->interface[intf];

              break;

 

         caseUSB_RECIP_ENDPOINT:

              endp = ((w_index &0x80) >> 3) | (w_index & 0x0f);

              /*

              这个操作过后,endp的第4位是方向,0~3是地址,对应set_config()中的

              addr =((ep->bEndpointAddress & 0x80) >> 3)

                   | (ep->bEndpointAddress & 0x0f);

              set_bit(addr,f->endpoints);

              */

              list_for_each_entry(f,&cdev->config->functions, list) {

                   if (test_bit(endp, f->endpoints))

                       break;

              }

              if (&f->list == &cdev->config->functions)

                   f = NULL;

              break;

         }//上面就是找对应的struct usb_function

         if(f && f->setup)// structusb_function中的setup优先使用,f_sourcesink没实现

              value = f->setup(f,ctrl);

         else{

              struct usb_configuration    *c;

 

              c = cdev->config;

              if (c && c->setup)

                   value =c->setup(c, ctrl); //对我们来说就是sourcesink_setup()

         }

 

         gotodone;

     }

}

 

static int sourcesink_setup(struct usb_configuration *c,

         conststruct usb_ctrlrequest *ctrl)

{

     structusb_request *req = c->cdev->req;

     int           value = -EOPNOTSUPP;

     u16           w_index = le16_to_cpu(ctrl->wIndex);//小端转换要注意一下

     u16           w_value = le16_to_cpu(ctrl->wValue);

     u16           w_length = le16_to_cpu(ctrl->wLength);

 

     req->length = USB_BUFSIZ;

//我们知道请求分标准和非标准,这下面两个就是非标准,

//控制端口允许多包请求,为了测试

     switch(ctrl->bRequest) {

     case0x5b:    //控制写。 填充buffer

         if(ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))

              goto unknown;

         if(w_value || w_index)

              break;

         if(w_length > req->length)//大于USB_BUFSIZ,就用USB_BUFSIZ

              break;

         value = w_length;//请求的数据长度

         break;

     case0x5c:    //控制读。 返回buffer

         if(ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))

              goto unknown;

         if(w_value || w_index)

              break;

         if(w_length > req->length)

              break;

         value = w_length;

         break;

 

     default:

unknown:

     }

 

     if(value >= 0) {

         req->zero = 0;

         req->length = value;

         value =usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);//看到是从控制端口输出的,对于上面的多包请求,这就是最特别的一点

     }

 

     returnvalue;

}

/*

总结一下setup

1. composite_setup()为我们考虑了标准请求。

2. struct usb_function和struct usb_configuration只要实现一个setup,都实现的话会用struct usb_function。

3. 我们实现的setup从上面看主要是处理特殊请求。

*/

 



在虚拟机装载

 

 

板子提示

 

虚拟机

 

有个skel0 设备文件

 

虚拟机执行

如果板子不动作,最后

 

 

现在执行cat /dev/skel0

板子执行

 

 

 

虚拟机

 

 

反过来

板子读,虚拟机写

 

 

 

 

当你拔去usb是你会发现/dev/skel0消失


 

自娱自乐7之Linux UDC驱动2(自编udc驱动,现完成枚举过程,从驱动代码分析枚举过程)

标签: linux移动设备
 分类:
 

花了半个月,才搞定驱动中的枚举部分,现在说linux的枚举,windows可能有差别。

代码我会贴在后面,现在只是实现枚举,你可能对代码不感兴趣,我就不分析代码了,你可以看看

在《自娱自乐1》中的模板,比较一下,我做了什么,这会给你写udc驱动提供个思路。我直接分析

调试打印,就是枚举过程,我们从代码看枚举。打印位置可以在下面的代码里找到。

如果你要弄懂驱动代码中涉及枚举的地方,你就仔细看看代码在那打印的,这个对你完成一个udc驱

动有帮助。

如果你只是想简单了解枚举你就看看我分析的调试打印就可以了。

http://wenku.baidu.com/view/87064d244b35eefdc8d333dc.html

这个是枚举过程,对照着上面说的看我的调试打印,提示我的是从机,他说的是主机。

# insmod s3c2440_add_udc.ko

UPLLCON = 38022, wxl add//驱动usb的时钟源

# insmod s3c2440_udc.ko

# insmod gadget_transfer.ko

s3c2440_start//调用s3c2440_start(),在此会PULL_UP

s3c2440_udc_alloc_request//分配请求结构体内存

gadget_transfer gadget: gadget_transfer ready

# USB reset//pc检测到PULL_UP 复位设备

USB ep0 irq//ep0中断

Host: bRequest = 06 bRequestType = 80 wValue = 0x100wIndex=0x0 wLength=0x40//请求信息

//bRequest = 06是请求描述符,bRequestType = 80输入方向(输入是对主机而言) 端点0,

//请求长度64(微软的策略,这里linux学微软的)。

//wValue = 0x100: 这个前面的1表示设备描述符

 

USB_REQ_GET_DESCRIPTOR//第一次请求主要是获取最大包长度,此值在设备描述符第8个字节

USB_DT_DEVICE//设备描述符请求

s3c2440_udc_queue//调用了s3c2440_udc_queue()

Slave: length = 18 Vendor = ff0 Product = ff0 Device =212 iManufacturer = 1 iProduct = 2 iSerialNumber = 3 bNumConfigurations = 1

// Vendor = ff0 Product = ff0 Device = 212 这个在上一篇的gadget_transfer驱动中可以看到

// iManufacturer = 1 iProduct = 2iSerialNumber = 3 这个是字符串描述符引索

// bNumConfigurations = 1 你看看我上一篇的gadget_transfar驱动写的是2,这里却是1

/*

bNumConfigurations是配置数,是用count_configs()统计的,和你在gadget驱动中赋值无关

     多配置很少,不过还是有,例如multi.c可以配置为RNDIS或ECM。

*/

8bytes USB USB reset //一次发出8个字节,我的ep0最大包长度是8,还有下面的xbytes都是已发的字节数。微软的策略后面没发完的不要了,直接复位设备。没有按usb spec来做。Windows要接受16个才复位。

USB ep0 irq

Host: bRequest = 05 bRequestType = 00 wValue = 0x4wIndex=0x0 wLength=0x0

//主机的请求又来了,这次是设置地址

// bRequest = 05 就是设置地址请求,

// bRequestType = 00 方向out,地址0

//wValue=0x4 设备地址4,在驱动中看不到它的使用,应该是硬件来判断

USB_REQ_SET_ADDRESS

USB ep0 irq//这个我调试是数据没准备好

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x100wIndex=0x0 wLength=0x12

//这次是真的获取设备描述符,长度18

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE

s3c2440_udc_queue

Slave: length = 18 Vendor = ff0 Product = ff0 Device =212 iManufacturer = 1 iProduct = 2 iSerialNumber = 3 bNumConfigurations = 1//上面已解释

8bytes USB ep0 irq

 

 16bytes USB ep0irq

 18bytes USB ep0irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x200wIndex=0x0 wLength=0x9

/*

wValue = 0x200: 这个前面的2表示配置描述符,后面是引索

*/

 

//获取配置描述符

USB_REQ_GET_DESCRIPTOR

USB_DT_CONFIG

s3c2440_udc_queue

Slave: length = 9 TotalLength = 32 NumInterfaces = 1ConfigurationValue = 3 iConfiguration = 4 bMaxPower = 250

/*

length = 9描述符长度为9

TotalLength = 32配置信息的长度--包括配置描述符、接口描述符、端点描述符长度的总和

NumInterfaces = 1 接口数

ConfigurationValue = 3用于表示 USB设备的配置值,主机就是根据这个选

iConfiguration = 4字符串描述符的索引值

bMaxPower = 250用于表示 USB设备运行时所需要消耗的总线电流,单位以2mA 为基准。USB设备可以从USB总线上获得最大的电流为500mA,因此 bMaxPower 字段的最大值可以设置为250。

还有个bmAttributes,没打印

*/

8bytes USB ep0 irq

 9bytes USB ep0irq

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x300wIndex=0x0 wLength=0xff

/*

wValue = 0x300: 这个前面的3表示字符串描述符,后面是引索0

之前并没有看到0引索的字符串描述符,不过看一下composite.c就知道了

/* 0 == report all availablelanguage codes */

可用的语言数,不细说

*/

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 4

 4bytes USB ep0irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x303wIndex=0x409 wLength=0xff

//3是上面的iSerialNumber = 3

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 66

0123456789.0123456789.0123456789

 //可以在上一篇的驱动开的这个,static charserial[] = "0123456789.0123456789.0123456789";

8bytes USB ep0 irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 48bytes USB ep0irq

 56bytes USB ep0irq

 64bytes USB ep0irq

 66bytes USB ep0irq

//下面又来一次,就是获得的字符串描述不同而已

Host: bRequest = 06 bRequestType = 80 wValue = 0x200wIndex=0x0 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_CONFIG

s3c2440_udc_queue

Slave: length = 9 TotalLength = 32 NumInterfaces = 1ConfigurationValue = 3 iConfiguration = 4 bMaxPower = 250

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 32bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x300wIndex=0x0 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 4

 4bytes USB ep0irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x302wIndex=0x409 wLength=0xff

// iProduct = 2

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 46

Gadget gadget_transfer// static const char longname[]= "Gadget gadget_transfer";

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 46bytes USB ep0irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x300wIndex=0x0 wLength=0xff//再一次,不清楚为什么

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 4

 4bytes USB ep0irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x302wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 46

Gadget gadget_transfer

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 46bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x100wIndex=0x0 wLength=0x12

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE//获取设备描述符

s3c2440_udc_queue

Slave: length = 18 Vendor = ff0 Product = ff0 Device =212 iManufacturer = 1 iProduct = 2 iSerialNumber = 3 bNumConfigurations = 1

 8bytes USB ep0irq

 16bytes USB ep0irq

 18bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x100wIndex=0x0 wLength=0x40//这里有用64长度请求一次

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE

s3c2440_udc_queue

Slave: length = 18 Vendor = ff0 Product = ff0 Device =212 iManufacturer = 1 iProduct = 2 iSerialNumber = 3 bNumConfigurations = 1

 8bytes USB ep0irq

 16bytes USB ep0irq

 18bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x100wIndex=0x0 wLength=0x12

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE//又来一次

s3c2440_udc_queue

Slave: length = 18 Vendor = ff0 Product = ff0 Device =212 iManufacturer = 1 iProduct = 2 iSerialNumber = 3 bNumConfigurations = 1

 8bytes USB ep0irq

 16bytes USB ep0irq

 18bytes USB ep0irq

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x600wIndex=0x0 wLength=0xa

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE_QUALIFIER

//设备限定描述符用于指定另一传输速率下该设备的总体信息,如果高速USB设备既需要采用高速传//输又需要全速传输,则它必须支持设备限定描述符(Device_Qualifier)。全速设备不支持

//我的是全速设备用不倒QUALIFIER,composite.c用gadget_is_dualspeed()这个判断

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x600wIndex=0x0 wLength=0xa

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE_QUALIFIER

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x600wIndex=0x0 wLength=0xa

USB_REQ_GET_DESCRIPTOR

USB_DT_DEVICE_QUALIFIER

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x200wIndex=0x0 wLength=0x9

USB_REQ_GET_DESCRIPTOR

USB_DT_CONFIG//这次你会看到到wValue & 0xff 是0到3

// iManufacturer = 1 iProduct = 2iSerialNumber = 3

s3c2440_udc_queue

Slave: length = 9 TotalLength = 32 NumInterfaces = 1ConfigurationValue = 3 iConfiguration = 4 bMaxPower = 250

 8bytes USB ep0irq

 9bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x200wIndex=0x0 wLength=0x20

USB_REQ_GET_DESCRIPTOR

USB_DT_CONFIG

s3c2440_udc_queue

Slave: length = 9 TotalLength = 32 NumInterfaces = 1ConfigurationValue = 3 iConfiguration = 4 bMaxPower = 250

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x300wIndex=0x0 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 4

 4bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x302wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 46

Gadget gadget_transfer

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 46bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x301wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 58

Linux 3.2.0 with s3c2440_udc

/*

还记得我的gadget驱动开始

   snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",

       init_utsname()->sysname, init_utsname()->release,

        gadget->name);

*/

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 48bytes USB ep0irq

 56bytes USB ep0irq

 58bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x303wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 66

0123456789.0123456789.0123456789

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 48bytes USB ep0irq

 56bytes USB ep0irq

 64bytes USB ep0irq

 66bytes USB ep0irq

USB ep0 irq

Host: bRequest = 09 bRequestType = 00 wValue = 0x3wIndex=0x0 wLength=0x0

USB_REQ_SET_CONFIGURATION//设置配置

// wValue = 0x3对应上面的ConfigurationValue = 3程序中是

/*

static struct usb_configurationsourcesink_driver = {

    .label        = "source/sink",

    .strings   = sourcesink_strings,

    .setup        = sourcesink_setup,

    .bConfigurationValue = 3,

    .bmAttributes    = USB_CONFIG_ATT_SELFPOWER,

    /* .iConfiguration = DYNAMIC */

};

*/

gadget_transfer gadget: full-speed config#3: source/sink//上面的.label        ="source/sink",

s3c2440_udc_ep_enable

s3c2440_udc_ep_enable

s3c2440_udc_queue

USB ep0 irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x304wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 42

source and sink data9

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 42bytes USB ep0irq

USB ep0 irq

Host: bRequest = 06 bRequestType = 80 wValue = 0x304wIndex=0x409 wLength=0xff

USB_REQ_GET_DESCRIPTOR//这里引索是4就是iConfiguration = 4

USB_DT_STRING

s3c2440_udc_queue

Slave: length = 42

source and sink data9

/*代码

static struct usb_stringstrings_sourcesink[] = {

    [0].s ="source and sink data",

    {  }           /* end of list */

};

*/

 8bytes USB ep0irq

 16bytes USB ep0irq

 24bytes USB ep0irq

 32bytes USB ep0irq

 40bytes USB ep0irq

 42bytes USB ep0irq

 

有些重复的请求就是为了确认。

下面是代码:(现在只能枚举),可以把内核自带的驱动和我的比较一下,我的宗旨是应用我的模板。

s3c2440_udc.h

 

[cpp] view plain copy
 
  1. /*********************************** 
  2.  Copyright(C), 2013 LDP 
  3.  FileName:  s3c2440_udc.h 
  4.  Author:    wwxxxxll 
  5.  Date:           
  6.  Description:   
  7.  History:        
  8.  Author       Date            Desc 
  9. ************************************/  
  10. #ifndef __S3C2440_UDC_H__  
  11. #define __S3C2440_UDC_H__  
  12. /*************配置选项**************/  
  13. #define S3C2440_DEBUG_FS  //使用debugfs  
  14. #define DEBUG  
  15. //struct usb_ep_ops  
  16. //#define S3C2440_NEWSTYLE  //使用udc_start  
  17. #define S3C2440_SETWEDHE  //实现set_weght方法  
  18. #define S3C2440_FIFO_STATUS //支持fifo_status方法  
  19. #define S3C2440_FIFO_FLUSH //支持fifo_flush方法  
  20.   
  21. //struct usb_gadget_ops  
  22. #define S3C2440_S3C2440_GET_FRAME //支持get_frame  
  23. #define S3C2440_WAKEUP //支持wakeup功能  
  24. #define S3C2440_SELFPOWERED //selfpowered支持  
  25. //#define S3C2440_VBUS_SESSION //vbus连接控制支持  
  26. //#define S3C2440_VBBUS_DRAW  
  27. #define S3C2440X_PULLUP //usb连接控制支持  
  28.   
  29. //s3c2440 有时钟控制  
  30. //寄存器CLKSLOW开启UPLL  
  31. //CLKCON开启USB device时钟,我会定义两个clk,见下面的结构体  
  32. //我可以直接操作寄存器,但是那样太粗鲁了,我们还是用平台提供  
  33. //的时钟机制解决吧  
  34. #define S3C2440_HAVE_CLK  //有专用的CLK  
  35. #ifdef S3C2440_HAVE_CLK  
  36. #define CLK_DELAY_TIME 10 //ms  
  37. #endif  
  38.   
  39. #define S3C2440_USE_IRQ  
  40.   
  41. //端口信息  
  42. #define S3C2440_ENDPOINTS 5 //端口数  
  43. //一个端点的最大数据包  
  44. #define EP0_FIFO_SIZE 8  
  45. #define EP1_FIFO_SIZE 64  
  46. #define EP2_FIFO_SIZE 64  
  47. #define EP3_FIFO_SIZE 64  
  48. #define EP4_FIFO_SIZE 64  
  49.   
  50. #define EP1_ADDRESS 1  
  51. #define EP2_ADDRESS 2  
  52. #define EP3_ADDRESS 3  
  53. #define EP4_ADDRESS 4  
  54.   
  55. #define EP1_ATTR USB_ENDPOINT_XFER_BULK  
  56. #define EP2_ATTR USB_ENDPOINT_XFER_BULK  
  57. #define EP3_ATTR USB_ENDPOINT_XFER_BULK  
  58. #define EP4_ATTR USB_ENDPOINT_XFER_BULK  
  59.   
  60. //fifo长度  
  61. #define S3C2440_EP0_FIFO_SIZE 16  
  62. #define S3C2440_EP1_FIFO_SIZE 128  
  63. #define S3C2440_EP2_FIFO_SIZE 128  
  64. #define S3C2440_EP3_FIFO_SIZE 128  
  65. #define S3C2440_EP4_FIFO_SIZE 128  
  66. /***********************************/  
  67.   
  68. /*************寄存器定义************/  
  69. //s3c2440 有个MISCCR控制usb1为设备还是主机  
  70. //芯片默认为设备,我就不控制了。MISCCR的USB挂起  
  71. //主要为芯片进入睡眠时用的  
  72. //如果按字节模式访问则偏移地址在大端和小端模式中是不同的。  
  73. //我是小端的地址  
  74. #define FUNC_ADDR_REG 0x140  
  75. //func_addr_reg 存储usb地址,更新地址时,第7位置位  
  76. #define PWR_REG       0x144  
  77. /* 
  78. pwr_reg: 
  79. 3: USB_RESET R  主机发复位信号,由USB置位 
  80. 2: MCS_RESUME R/W MCU置位来给MCU重置,在挂起模式时,产生10ms重置信号 
  81. 1: SUSPEND_MODE R 设备进入挂起模式时由USB置位。 
  82. 0: SUBSPEND_EN R 挂起使能位,0:禁止 1:使能 
  83. */  
  84. //一旦 MCU 发生中断,MCU 应该读取中断相关寄存器的内容并且如果需要写回清除其内容。  
  85. #define EP_INT_REG 0x148  
  86. #define USB_INT_REG 0x158  
  87.   
  88. //中断使能  
  89. #define EP_INT_EN_REG 0x15c  
  90. #define USB_INT_EN_REG 0x16c  
  91.   
  92. //帧号  
  93. #define FRAME_NUM1_REG 0x170 //低字节  
  94. #define FRAME_NUM2_REG 0x174 //高字节  
  95.   
  96. //通常被标记的寄存器随INDEX寄存器(INDEX_REG)(偏移地址:0X178)值而定。例如如果希望改写EP0   
  97. //CSR寄存器,必须在写IN_CSR1寄存器前写入‘0x00’到INDEX_REG中  
  98. #define INDEX_REG 0x178  
  99.   
  100. #define MAXP_REG 0x180  
  101. /* 
  102. 推荐: 
  103. EP0 MAXP=8 
  104. EP1~4 MAXP=64, 64自动使能双数据包模式 就是data0和data1 
  105. */  
  106.   
  107. #define EP0_CSR 0x184   
  108.   
  109. #define IN_CSR1_REG 0x184  
  110. #define IN_CSR2_REG 0x188  
  111.   
  112. #define OUT_CSR1_REG 0x190  
  113. #define OUT_CSR2_REG 0x194  
  114.   
  115. //FIFO  
  116. //端点输出写计数寄存器  
  117. //此寄存器保存着包的字节数,该数由MCU卸载  
  118. #define OUT_FIFO_CNT1 0x198  
  119. #define OUT_FIFO_CNT2 0x19c  
  120.   
  121. //EPn_FIFO_REG使能MCU访问EPn FIFO  
  122. #define EP0_FIFO 0x1c0  
  123. #define EP1_FIFO 0x1c4  
  124. #define EP2_FIFO 0x1c8  
  125. #define EP3_FIFO 0x1cc  
  126. #define EP4_FIFO 0x1d0  
  127.   
  128. //DMA  
  129. #define EP1_DMA_CON 0x200  
  130. #define EP2_DMA_CON 0x218  
  131. #define EP3_DMA_CON 0x240  
  132. #define EP4_DMA_CON 0x258  
  133.   
  134. #define EP1_DMA_UNIT 0x204  
  135. #define EP2_DMA_UNIT 0x21c  
  136. #define EP3_DMA_UNIT 0x244  
  137. #define EP4_DMA_UNIT 0x25c  
  138.   
  139. #define EP1_DMA_FIFO 0x208  
  140. #define EP2_DMA_FIFO 0x220  
  141. #define EP3_DMA_FIFO 0x248  
  142. #define EP4_DMA_FIFO 0x260  
  143.   
  144. #define EP1_DMA_TTC_L 0x20c  
  145. #define EP1_DMA_TTC_M 0x210  
  146. #define EP1_DMA_TTC_H 0x214  
  147. #define EP2_DMA_TTC_L 0x224  
  148. #define EP2_DMA_TTC_M 0x228  
  149. #define EP2_DMA_TTC_H 0x22c  
  150. #define EP3_DMA_TTC_L 0x24c  
  151. #define EP3_DMA_TTC_M 0x250   
  152. #define EP3_DMA_TTC_H 0x254  
  153. #define EP4_DMA_TTC_L 0x264  
  154. #define EP4_DMA_TTC_M 0x268  
  155. #define EP4_DMA_TTC_H 0x26c  
  156.   
  157. /***********************************/  
  158.   
  159. /************操作定义***************/  
  160. #define WRITE_REG(_s3c2440_udc, reg, data) writel(data, _s3c2440_udc->virl_addr + reg)  
  161. #define READ_REG(_s3c2440_udc, reg) readl(_s3c2440_udc->virl_addr + reg)  
  162.   
  163. #define SETB(_s3c2440_udc, reg, n) (writel((readl(_s3c2440_udc->virl_addr + reg) | (1 << n)), _s3c2440_udc->virl_addr + reg))  
  164. #define CLRB(_s3c2440_udc, reg, n) (writel((readl(_s3c2440_udc->virl_addr + reg) & (~(1 << n))), _s3c2440_udc->virl_addr + reg))  
  165.   
  166. #define GETB(_s3c2440_udc, reg, n) ((readl(_s3c2440_udc->virl_addr + reg) >> n) & 1)  
  167.   
  168.   
  169. //我的D+控制口为gpc5,这里我也偷懒了,没有mmap gpio,用了平台的  
  170. #define PULL_UP()    do { \  
  171.                        writel((readl(S3C2410_GPCCON) | (1 << 10)) & (~(1 << 11)), S3C2410_GPCCON); \  
  172.                        writel(readl(S3C2410_GPCUP) & (~(1 << 5)), S3C2410_GPCUP); \  
  173.                        writel(readl(S3C2410_GPCDAT) | (1 << 5), S3C2410_GPCDAT); \  
  174.                    }while(0);  
  175.   
  176. #define PULL_DOWN() do { \  
  177.                        writel((readl(S3C2410_GPCCON) | (1 << 10)) & (~(1 << 11)), S3C2410_GPCCON); \  
  178.                        writel(readl(S3C2410_GPCUP) & (~(1 << 5)), S3C2410_GPCUP); \  
  179.                        writel(readl(S3C2410_GPCDAT) & (~(1 << 5)), S3C2410_GPCDAT); \  
  180.                    }while(0);  
  181.   
  182. /***********************************/  
  183.   
  184. /*************简单操作**************/  
  185. //清楚setup_end标志  
  186. #define EP0_CLRSE(_s3c2440_udc) do { \  
  187.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  188.                                  SETB(_s3c2440_udc, EP0_CSR, 7); \  
  189.                                 }while(0)  
  190.   
  191. //out数据已读完标志  
  192. #define EP0_CLROPR(_s3c2440_udc) do { \  
  193.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  194.                                  SETB(_s3c2440_udc, EP0_CSR, 6); \  
  195.                                 }while(0)  
  196.   
  197. #define EP0_SETDE(_s3c2440_udc) do {\  
  198.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  199.                                  SETB(_s3c2440_udc, EP0_CSR, 3); \  
  200.                                 }while(0)                              
  201.   
  202. //清楚stall标志  
  203. #define EP0_CLRSST(_s3c2440_udc) do { \  
  204.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  205.                                  CLRB(_s3c2440_udc, EP0_CSR, 5); \  
  206.                                 }while(0)    
  207. //发送stall  
  208. #define EP0_SETSST(_s3c2440_udc) do { \  
  209.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  210.                                  SETB(_s3c2440_udc, EP0_CSR, 5); \  
  211.                                 }while(0)            
  212.   
  213. //清楚数据异常  
  214. #define EP0_CLRDE(_s3c2440_udc) do { \  
  215.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  216.                                  CLRB(_s3c2440_udc, EP0_CSR, 2); \  
  217.                                 }while(0)  
  218.   
  219. //in数据已写完标志  
  220. #define EP0_SETIPR(_s3c2440_udc) do { \  
  221.                                  WRITE_REG(_s3c2440_udc, INDEX_REG, 0); \  
  222.                                  SETB(_s3c2440_udc, EP0_CSR, 1);  \  
  223.                                 }while(0)   
  224. /***********************************/  
  225.   
  226.   
  227. struct s3c2440_ep   
  228. {  
  229.     struct usb_ep ep; //描述一个端点  
  230.     struct list_head queue;  
  231.     struct s3c2440_udc *dev;  
  232.     const struct usb_endpoint_descriptor *desc;  
  233.   
  234.     unsigned char fifosize;  
  235.     unsigned char bEndpointAddress;  
  236.     unsigned char bmAttributes;  
  237.   
  238.     u16 fifo_size;  
  239.     u8 num;  
  240.   
  241.     unsigned stopped :1;//维护一个端口停止标志  
  242.   
  243. #ifdef S3C2440_SETWEDHE  
  244.     unsigned wedged :1;  
  245. #endif  
  246. };  
  247.   
  248. #define to_s3c2440_ep(ep_p) container_of(ep_p, struct s3c2440_ep, ep)  
  249.   
  250. struct s3c2440_request   
  251. {  
  252.     struct list_head        queue;        /* ep's requests */  
  253.     struct usb_request        req;        //对应主机端看到的urb  
  254. };  
  255.   
  256. #define to_s3c2440_req(req_p) container_of(req_p, struct s3c2440_request, req)  
  257.   
  258. //根据实际要求定义,这个不能当做模板,主要是便于软件管理  
  259. //一般有下面几个,有的驱动不用这些定义去管理  
  260. enum ep0state {  
  261.     EP0_IDLE,  
  262.     EP0_IN,   
  263.     EP0_OUT,      
  264.     EP0_STALL,          
  265. };  
  266.       
  267. struct s3c2440_udc   
  268. {  
  269.     spinlock_t lock;  
  270.       
  271.     void __iomem *virl_addr;  
  272.     u32 phy_addr;  
  273.     u32 reg_size;  
  274.   
  275.     struct usb_gadget gadget;  
  276.     struct usb_gadget_driver *driver;  
  277.   
  278.     enum ep0state ep0state;  
  279.     struct s3c2440_ep ep[S3C2440_ENDPOINTS];  
  280.     struct s3c2440_request fifo_req;  
  281.   
  282. #ifdef S3C2440_DEBUG_FS  
  283.     struct dentry *debug_info;  
  284. #endif   
  285.   
  286. #ifdef S3C2440_HAVE_CLK  
  287.     struct clk *s3c2440_clk_upll;  
  288.     struct clk *s3c2440_clk_udc;  
  289. #endif  
  290.   
  291. #ifdef S3C2440_USE_IRQ  
  292.     unsigned int irq_num;  
  293. #endif  
  294.   
  295.     u16    devstatus;  
  296. };  
  297.   
  298. #define to_s3c2440_udc(gadget_p) container_of(gadget_p, struct s3c2440_udc, gadget)  
  299.   
  300. #endif//__S3C2440_UDC_H__  

s3c2440.c

 

 

[cpp] view plain copy
 
  1. /*********************************** 
  2.  Copyright(C), 2013 LDP 
  3.  FileName:  s3c2440_udc.c 
  4.  Author:    wwxxxxll 
  5.  Date:           
  6.  Description: linux-3.2-36 
  7.  History:        
  8.  Author       Date            Desc 
  9. ************************************/  
  10.   
  11. #include <linux/module.h>//MODULE_*  
  12. #include <linux/init.h>//printk  
  13. #include <linux/slab.h>//kzalloc() kfree()  
  14. #include <linux/usb/gadget.h>//struct usb_gadget等  
  15. #include <linux/clk.h>//struct clk  
  16. #include <linux/platform_device.h>//platform  
  17. #include <linux/ioport.h>  
  18. #include <linux/interrupt.h>  
  19. #include <linux/delay.h>  
  20. #include <linux/prefetch.h>  
  21.   
  22. #include <asm/irq.h>  
  23. #include <asm/io.h>//ioremap  
  24.   
  25. #include <mach/regs-gpio.h>  
  26.   
  27. #include "s3c2440_udc.h"  
  28.   
  29. #ifdef S3C2440_DEBUG_FS  
  30. #include <linux/debugfs.h>  
  31. #include <linux/seq_file.h>//seq_printf seq_read  
  32. #endif  
  33.   
  34. #define DRIVER_DESC    "S3C2440 USB Device Controller Gadget"  
  35. #define DRIVER_VERSION    "2013"  
  36. #define DRIVER_AUTHOR    "wwxxxxll"  
  37.   
  38. static const char        gadget_name[] = "s3c2440_udc";  
  39. static const char        driver_desc[] = DRIVER_DESC;  
  40.   
  41.   
  42.   
  43. //根据实际情况修改  
  44. //在epautoconf.c会看到  
  45. /* type-restriction:  "-iso", "-bulk", or "-int". 
  46.  * direction-restriction:  "in", "out". 
  47.  */  
  48. //我们  
  49. static const char ep0name[] = "ep0";  
  50. static const char * const ep_name[] = {  
  51.     ep0name,  
  52.     "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",  
  53. };  
  54. //需要mount -t debugfs none /sys/kernel/debug/  
  55. ///sys/kernel/debug  
  56. #ifdef S3C2440_DEBUG_FS  
  57. static struct dentry *s3c2440_udc_debugfs_root;  
  58.   
  59. static int s3c2440_udc_debugfs_seq_show(struct seq_file *m, void *p)  
  60. {  
  61.     seq_printf(m, "My name is %s\n", gadget_name);  
  62.   
  63.     return 0;  
  64. }  
  65.   
  66. static int s3c2440_udc_debugfs_fops_open(struct inode *inode,  
  67.                      struct file *file)  
  68. {  
  69.     return single_open(file, s3c2440_udc_debugfs_seq_show, NULL);  
  70. }  
  71.   
  72. static const struct file_operations s3c2440_udc_debugfs_fops =   
  73. {  
  74.     .open        = s3c2440_udc_debugfs_fops_open,  
  75.     .read        = seq_read,  
  76.     .llseek        = seq_lseek,  
  77.     .release    = single_release,  
  78.     .owner        = THIS_MODULE,  
  79. };  
  80. #endif  
  81.   
  82. /***********************hardware_handler************************/  
  83. //s3c2440没有控制usb开启位,就等到start时使能中断,imx不是这样  
  84. static void s3c2440_usb_reset(struct s3c2440_udc *dev)  
  85. {  
  86.     //disable intterupt  
  87.     WRITE_REG(dev, EP_INT_EN_REG, 0x00);  
  88.     WRITE_REG(dev, USB_INT_EN_REG, 0x00);  
  89.   
  90.     //clear intterupt flag  
  91.     WRITE_REG(dev, EP_INT_REG, 0x1f);  
  92.     WRITE_REG(dev, USB_INT_REG, 0x07);  
  93.   
  94.     PULL_DOWN();  
  95.   
  96.     dev->gadget.speed = USB_SPEED_UNKNOWN;  
  97. }  
  98.   
  99. static void s3c2440_udc_enable(struct s3c2440_udc *dev)  
  100. {  
  101.     int i;  
  102.   
  103.     dev->gadget.speed = USB_SPEED_FULL;//s3c2440只支持1.1  
  104.   
  105.     for (i = 0; i < S3C2440_ENDPOINTS; i++)//最大包设置  
  106.     {  
  107.         WRITE_REG(dev, INDEX_REG, i);  
  108.         WRITE_REG(dev, MAXP_REG, dev->ep[i].ep.maxpacket >> 3);  
  109.     }  
  110.   
  111.     //SETB(dev, PWR_REG, 0);//enable suspend模式  
  112.   
  113.     //enable intterupt  
  114.     SETB(dev, EP_INT_EN_REG, 0);  
  115.     WRITE_REG(dev, USB_INT_EN_REG, 0x07);  
  116.   
  117. #ifndef S3C2440_NEWSTYLE  
  118.     PULL_UP();  
  119. #endif  
  120. }  
  121.   
  122. static void s3c2440_usb_fifocnt(struct s3c2440_udc *dev, u32 *fifo_size)  
  123. {  
  124.     *fifo_size = READ_REG(dev, OUT_FIFO_CNT1);  
  125.     *fifo_size |= READ_REG(dev, OUT_FIFO_CNT2) << 8;  
  126. }  
  127.   
  128. static u32 s3c2440_read_ctrlq(struct s3c2440_udc *dev, struct usb_ctrlrequest *_ctrlq)  
  129. {  
  130.     u32 count;  
  131.   
  132.     WRITE_REG(dev, INDEX_REG, 0);  
  133.     s3c2440_usb_fifocnt(dev, &count);  
  134.   
  135.     count = (count > sizeof(struct usb_ctrlrequest)) ? sizeof(struct usb_ctrlrequest) : count;  
  136.   
  137.     readsb(EP0_FIFO + dev->virl_addr, (unsigned char *)_ctrlq, count);  
  138.   
  139.     /* 
  140.     _ctrlq->bRequest 
  141.     bit7: 方向 10 int 0: out 
  142.     bit 6:5: 请求类型 
  143.     bit 4:0: 接收者 
  144.     */  
  145.     printk(  "Host: bRequest = %02x bRequestType = %02x \  
  146. wValue = 0x%x wIndex=0x%x wLength=0x%x\n", _ctrlq->bRequest, _ctrlq->bRequestType, \  
  147.         _ctrlq->wValue, _ctrlq->wIndex, _ctrlq->wLength);  
  148.   
  149.     return count;  
  150. }  
  151.   
  152. static void s3c2440_udc_done(struct s3c2440_ep *ep, struct s3c2440_request *req, int status);  
  153.   
  154. /* 
  155. 返回 
  156. 1: 读包结束 
  157. 0: 还没读完 
  158. -1: 错误 
  159. */  
  160. static int s3c2440_read_fifo(struct s3c2440_udc *dev, struct s3c2440_ep *ep, struct s3c2440_request *req)  
  161. {  
  162.     u32 fifo_reg;  
  163.     u8 *buf;  
  164.     u32 idx = 0;  
  165.     u32 fifo_count, avail, len, bufspace;  
  166.     int ret = 0;  
  167.   
  168.     printk(  "%s\n", __func__);  
  169.   
  170.     idx = ep->bEndpointAddress & 0x7f;  
  171.   
  172.     if (idx > 4)  
  173.     {  
  174.         idx = 0;  
  175.     }  
  176.   
  177.     fifo_reg = EP0_FIFO + 4 * idx;  
  178.   
  179.     if (req->req.length == 0)  
  180.     {  
  181.         return 1;  
  182.     }  
  183.   
  184.     if (req->req.length <= req->req.actual)  
  185.     {  
  186.         return -1;  
  187.     }  
  188.   
  189.     bufspace = req->req.length - req->req.actual;  
  190.     buf = req->req.buf + req->req.actual;  
  191.   
  192.     WRITE_REG(dev, INDEX_REG, idx);  
  193.   
  194.     s3c2440_usb_fifocnt(dev, &fifo_count);  
  195.   
  196.     avail = (fifo_count > ep->ep.maxpacket) ? ep->ep.maxpacket : fifo_count;//一次最多读ep->ep.maxpacket  
  197.       
  198.     len = (bufspace < avail) ? bufspace : avail;  
  199.     req->req.actual += len;  
  200.   
  201.     readsb(fifo_reg + dev->virl_addr, buf, len);  
  202.   
  203.     //req->req.actual已接收长度,req->req.length要接收的总长度  
  204.     printk(  "read: req->req.actual = %d, req->req.length = %d\n", req->req.actual, req->req.length);  
  205.   
  206.     if (fifo_count < ep->ep.maxpacket)  
  207.     {  
  208.         ret = 1;  
  209.   
  210.         if (len != avail)  
  211.         {  
  212.             req->req.status = -EOVERFLOW;//溢出  
  213.         }  
  214.     }  
  215.   
  216.     if (ret)  
  217.     {  
  218.        if (idx == 0)   
  219.        {  
  220.             EP0_SETDE(dev);  
  221.             ep->dev->ep0state = EP0_IDLE;  
  222.         }   
  223.        else   
  224.        {  
  225.        }  
  226.   
  227.         s3c2440_udc_done(ep, req, 0);  
  228.     } else   
  229.     {  
  230.         if (idx == 0)   
  231.         {  
  232.             EP0_CLROPR(dev);  
  233.         }   
  234.         else   
  235.         {  
  236.         }  
  237.     }  
  238.     return ret;  
  239. }  
  240.   
  241. static int printDesc = 0;  
  242.   
  243. static int s3c2440_write_fifo(struct s3c2440_udc *dev, struct s3c2440_ep *ep, struct s3c2440_request *req)  
  244. {  
  245.     u32 fifo_reg;  
  246.     u8 *buf;  
  247.     u32 idx = 0;  
  248.     u32 len;  
  249.     int ret = 0;  
  250.   
  251.     //printk(  "%s\n", __func__);  
  252.   
  253.     struct usb_device_descriptor    *desc;  
  254.     struct usb_string_descriptor    *string;  
  255.     struct usb_config_descriptor    *config;  
  256.     u16                language;  
  257.     u32                 n;  
  258.     u8                *tmp;  
  259.   
  260.     switch (printDesc)   
  261.     {  
  262.     case USB_DT_DEVICE:  
  263.         desc = (struct usb_device_descriptor*)req->req.buf;  
  264.   
  265.         printk(  "Slave: length = %d Vendor = %x Product = %x Device = %x iManufacturer = %d iProduct = %d iSerialNumber = %d bNumConfigurations = %d\n", \  
  266.            desc->bLength, le16_to_cpu(desc->idVendor), le16_to_cpu(desc->idProduct), le16_to_cpu(desc->bcdDevice),\  
  267.            desc->iManufacturer,desc->iProduct,desc->iSerialNumber,desc->bNumConfigurations);  
  268.   
  269.         break;  
  270.     case USB_DT_DEVICE_QUALIFIER:   
  271.         break;  
  272.     case USB_DT_OTHER_SPEED_CONFIG:  
  273.         break;  
  274.     case USB_DT_CONFIG:  
  275.         config = (struct usb_config_descriptor *)req->req.buf;  
  276.   
  277.         printk(  "Slave: length = %d TotalLength = %d NumInterfaces = %d ConfigurationValue = %d iConfiguration = %d bMaxPower = %d\n", \  
  278.            config->bLength, le16_to_cpu(config->wTotalLength), config->bNumInterfaces, config->bConfigurationValue, config->iConfiguration, config->bMaxPower);  
  279.   
  280.         break;  
  281.     case USB_DT_STRING:  
  282.         string = (struct usb_string_descriptor *)req->req.buf;  
  283.         printk(  "Slave: length = %d\n", string->bLength);  
  284.         language = cpu_to_le16(0x0409);//这里偷工减料了,因为gadget是我自己写的我知道是什么语言  
  285.   
  286.         if (string->bLength == 4)//支持语言数量  
  287.         {  
  288.             break;  
  289.         }  
  290.         for (tmp = (u8 *)string->wData, n = 0; n < string->bLength; n++, tmp++)   
  291.         {  
  292.             if (*tmp == language)  
  293.             {  
  294.             }  
  295.             else  
  296.             {  
  297.                 printk( "%c", *tmp);//没考虑大小端  
  298.             }  
  299.         }  
  300.   
  301.         printk("\n");  
  302.   
  303.         break;  
  304.     case USB_DT_BOS:   
  305.         break;  
  306.     default:  
  307.         break;  
  308.     }  
  309.   
  310.     printDesc = 0;  
  311.   
  312.     idx = ep->bEndpointAddress & 0x7f;  
  313.   
  314.     if (idx > 4)  
  315.     {  
  316.         idx = 0;  
  317.     }  
  318.   
  319.     fifo_reg = EP0_FIFO + 4 * idx;  
  320.   
  321.     len = ((req->req.length - req->req.actual) < ep->ep.maxpacket) ? (req->req.length - req->req.actual) : ep->ep.maxpacket;  
  322.     buf = req->req.buf + req->req.actual;  
  323.   
  324.     prefetch(buf);//prefetch将这一块数据读取到cache之中,以便后继快速访问,为了下面的writesb  
  325.   
  326.     req->req.actual += len;  
  327.   
  328.     writesb(fifo_reg + dev->virl_addr, buf, len);  
  329.   
  330.     //req->req.actual已发送长度  
  331.     printk(  " %dbytes ", req->req.actual);  
  332.   
  333.     if (len != ep->ep.maxpacket)  
  334.         ret = 1;  
  335.     else if (req->req.length != req->req.actual || req->req.zero)//zero当要发送的长度小于请求长度是为1  
  336.         ret = 0;  
  337.     else  
  338.         ret = 2;  
  339.   
  340.     //printk(   \  
  341.             "Written ep%d %d.%d of %d b [last %d,z %d], max = %d\n", \  
  342.             idx, len, req->req.actual, req->req.length, \  
  343.              ret, req->req.zero,ep->ep.maxpacket);  
  344.     if (ret)  
  345.     {  
  346.         if (idx == 0)  
  347.         {  
  348.             if (!GETB(dev, USB_INT_REG, 2))  
  349.             {    
  350.                 EP0_SETIPR(dev);  
  351.                 EP0_SETDE(dev);  
  352.             }  
  353.             ep->dev->ep0state = EP0_IDLE;  
  354.         }  
  355.         else  
  356.         {  
  357.   
  358.         }  
  359.   
  360.         s3c2440_udc_done(ep, req, 0);  
  361.     }  
  362.     else  
  363.     {  
  364.         if (idx == 0)  
  365.         {  
  366.             if (!GETB(dev, USB_INT_REG, 2))  
  367.             {    
  368.                 EP0_SETIPR(dev);  
  369.             }  
  370.         }  
  371.         else  
  372.         {  
  373.   
  374.         }  
  375.     }  
  376.   
  377.     return ret;  
  378. }  
  379.   
  380. static void s3c2440_dequeue_all(struct s3c2440_ep *ep, int status);  
  381.   
  382. static void s3c2440_udc_handle_ep0_idle(struct s3c2440_udc *dev, struct s3c2440_ep *ep, u32 ep0_csr)  
  383. {  
  384.     struct usb_ctrlrequest ctrlq;  
  385.     int tmp;  
  386.     bool config = 0;  
  387.   
  388.     //printk(  "%s\n", __func__);  
  389.   
  390.     if (!(ep0_csr & 1))//判断数据是否接收完成  
  391.     {  
  392.         return;  
  393.     }  
  394.   
  395.     s3c2440_dequeue_all(ep, -EPROTO);  
  396.   
  397.     if (s3c2440_read_ctrlq(dev, &ctrlq) < sizeof(struct usb_ctrlrequest))  
  398.     {  
  399.         EP0_SETSST(dev);  
  400.   
  401.         return;  
  402.     }  
  403.   
  404.     //EP0_CLROPR是数据接收结束,EP0_SETDE是数据传输结束  
  405.     switch (ctrlq.bRequest)  
  406.     {  
  407.     case USB_REQ_GET_STATUS: printk(  "USB_REQ_GET_STATUS\n");  
  408.         EP0_CLROPR(dev);  
  409.         if ((ctrlq.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)  
  410.         {  
  411.   
  412.         }  
  413.   
  414.         break;  
  415.     case USB_REQ_CLEAR_FEATURE: printk(  "USB_REQ_CLEAR_FEATURE\n");  
  416.         EP0_CLROPR(dev);  
  417.         break;  
  418.     case USB_REQ_SET_FEATURE: printk(  "USB_REQ_SET_FEATURE\n");  
  419.         EP0_CLROPR(dev);  
  420.         break;  
  421.     case USB_REQ_SET_ADDRESS: printk(  "USB_REQ_SET_ADDRESS\n");  
  422.         if (ctrlq.bRequestType == USB_RECIP_DEVICE)   
  423.         {  
  424.             tmp = ctrlq.wValue & 0x7F;  
  425.             WRITE_REG(dev, FUNC_ADDR_REG, (1 << 7) | tmp);   
  426.   
  427.             EP0_CLROPR(dev);  
  428.             EP0_SETDE(dev);  
  429.             dev->ep0state = EP0_IDLE;  
  430.             return;  
  431.         }  
  432.         break;  
  433.   
  434.     case USB_REQ_GET_DESCRIPTOR: printk(  "USB_REQ_GET_DESCRIPTOR\n");  
  435.         switch (ctrlq.wValue >> 8)   
  436.         {  
  437.         case USB_DT_DEVICE: printk(  "USB_DT_DEVICE\n");  
  438.             break;  
  439.         //设备限定描述符用于指定另一传输速率下该设备的总体信息,如果高速 USB设备既需要采用高速传输又需  
  440.         //要全速传输,则它必须支持设备限定描述符(Device_Qualifier)。全速设备不支持  
  441.         case USB_DT_DEVICE_QUALIFIER: printk(  "USB_DT_DEVICE_QUALIFIER\n");  
  442.             break;  
  443.         case USB_DT_OTHER_SPEED_CONFIG: printk(  "USB_DT_OTHER_SPEED_CONFIG\n");  
  444.             break;  
  445.         case USB_DT_CONFIG: printk(  "USB_DT_CONFIG\n");  
  446.             break;  
  447.         case USB_DT_STRING: printk(  "USB_DT_STRING\n");  
  448.             break;  
  449.         //其他速率配置描述符用于指定另一传输速率下该设备的配置信息,如果高速USB设备既需要采用高速传输  
  450.         //又需要全速传输,则它必须支持其他速率配置描述符  
  451.         case USB_DT_BOS: printk(  "USB_DT_BOS\n");  
  452.             break;  
  453.         }  
  454.   
  455.         EP0_CLROPR(dev);  
  456.   
  457.         break;  
  458.     case USB_REQ_SET_DESCRIPTOR: printk(  "USB_REQ_SET_DESCRIPTOR\n");  
  459.         EP0_CLROPR(dev);  
  460.         break;  
  461.     case USB_REQ_GET_CONFIGURATION: printk(  "USB_REQ_GET_CONFIGURATION\n");  
  462.         EP0_CLROPR(dev);  
  463.         break;  
  464.     case USB_REQ_SET_CONFIGURATION:   
  465.         if (ctrlq.bRequestType == USB_RECIP_DEVICE)   
  466.         {  
  467.             printk(  "USB_REQ_SET_CONFIGURATION\n");  
  468.             config = 1;  
  469.   
  470.             EP0_CLROPR(dev);  
  471.             EP0_SETDE(dev);  
  472.         }  
  473.         break;  
  474.     case USB_REQ_GET_INTERFACE: printk(  "USB_REQ_GET_INTERFACE\n");  
  475.         EP0_CLROPR(dev);  
  476.         break;  
  477.     case USB_REQ_SET_INTERFACE:   
  478.         if (ctrlq.bRequestType == USB_RECIP_INTERFACE)   
  479.         {  
  480.             printk(  "SB_REQ_SET_INTERFACE\n");  
  481.             config = 1;  
  482.   
  483.             EP0_CLROPR(dev);  
  484.             EP0_SETDE(dev);  
  485.         }  
  486.   
  487.         break;  
  488.     case USB_REQ_SYNCH_FRAME: printk(  "USB_REQ_SYNCH_FRAME\n");    
  489.         EP0_CLROPR(dev);  
  490.         break;  
  491.     }  
  492.   
  493.     if (config != 1)//设置就一次传输就可以了  
  494.     {  
  495.         if (ctrlq.bRequestType & USB_DIR_IN)  
  496.             dev->ep0state = EP0_IN;  
  497.         else  
  498.             dev->ep0state = EP0_OUT;  
  499.     }  
  500.   
  501.     if (!dev->driver)  
  502.         return;  
  503.   
  504.     //为了queue()中的调试打印设置标志  
  505.     switch (ctrlq.bRequest)  
  506.     {  
  507.     case USB_REQ_GET_DESCRIPTOR:  
  508.         switch (ctrlq.wValue >> 8)   
  509.         {  
  510.         case USB_DT_DEVICE:printDesc = USB_DT_DEVICE;  
  511.             break;  
  512.         case USB_DT_DEVICE_QUALIFIER: printDesc = USB_DT_DEVICE_QUALIFIER;  
  513.             break;  
  514.         case USB_DT_OTHER_SPEED_CONFIG: printDesc = USB_DT_OTHER_SPEED_CONFIG;  
  515.             break;  
  516.         case USB_DT_CONFIG: printDesc = USB_DT_CONFIG;  
  517.             break;  
  518.         case USB_DT_STRING: printDesc = USB_DT_STRING;  
  519.             break;  
  520.         case USB_DT_BOS:   
  521.             break;  
  522.         }  
  523.         break;  
  524.     }  
  525.   
  526.     if (dev->driver->setup(&dev->gadget, &ctrlq) < 0)  
  527.     {  
  528.         if (config == 1)//配置错误,不要send stall,会重新选配置  
  529.         {  
  530.             return;  
  531.         }  
  532.   
  533.         EP0_SETSST(dev);  
  534.       
  535.         EP0_SETDE(dev);  
  536.         dev->ep0state = EP0_IDLE;  
  537.     }  
  538. }  
  539.   
  540. void s3c2440_handle_ep0(struct s3c2440_udc *dev)  
  541. {  
  542.     struct s3c2440_ep    *ep = &dev->ep[0];  
  543.     struct s3c2440_request *req;  
  544.     u32 ep0_csr = 0;  
  545.   
  546.     if (!list_empty(&ep->queue))  
  547.         req = list_entry(ep->queue.next, struct s3c2440_request, queue);  
  548.     else  
  549.         req = NULL;  
  550.   
  551.     WRITE_REG(dev, INDEX_REG, 0);  
  552.   
  553.     ep0_csr = READ_REG(dev, EP0_CSR);  
  554.   
  555.     if (ep0_csr & (1 << 5))//send_stall  
  556.     {  
  557.         s3c2440_dequeue_all(ep, -EPIPE);//调用complete函数  
  558.   
  559.         EP0_CLRSST(dev);  
  560.   
  561.         dev->ep0state = EP0_IDLE;  
  562.   
  563.         return;  
  564.     }  
  565.       
  566.     if (ep0_csr & (1 << 4))//setup_end  
  567.     {  
  568.         s3c2440_dequeue_all(ep, 0);  
  569.   
  570.         EP0_CLRSE(dev);  
  571.   
  572.         dev->ep0state = EP0_IDLE;  
  573.     }  
  574.   
  575.     switch (dev->ep0state) {  
  576.     case EP0_IDLE:  
  577.         s3c2440_udc_handle_ep0_idle(dev, ep, ep0_csr);  
  578.         break;  
  579.   
  580.     case EP0_IN:    
  581.         if ((!(ep0_csr & (1 << 1))) && req)   
  582.         {  
  583.             s3c2440_write_fifo(dev, ep, req);  
  584.         }  
  585.         break;  
  586.   
  587.     case EP0_OUT:   
  588.         if ((ep0_csr & 1) && req)   
  589.         {  
  590.             s3c2440_read_fifo(dev, ep, req);  
  591.         }  
  592.         break;  
  593.   
  594.     case EP0_STALL:  
  595.         dev->ep0state = EP0_IDLE;  
  596.         break;  
  597.     }  
  598. }  
  599.   
  600. //udc的这个中断,真是包罗万象,各硬件差别比较大  
  601. //简单一点说,就是清楚中断标致位,再根据中断标志位对应处理  
  602. //实际要复杂的多,如果是ep0,还会从fifo中取得usb_ctrlrequest  
  603. //进行对应的处理,我们在实现具体的实现时再说吧  
  604. static irqreturn_t s3c2440_udc_irq(int dummy, void *_dev)  
  605. {  
  606.     struct s3c2440_udc *dev = (struct s3c2440_udc *)_dev;  
  607.     unsigned long flags;  
  608.     int usb_status;  
  609.     int ep_status;  
  610.   
  611.     //printk(  "enter irq\n");  
  612.   
  613.     spin_lock_irqsave(&dev->lock, flags);  
  614.   
  615.     usb_status = READ_REG(dev, USB_INT_REG);  
  616.     ep_status = READ_REG(dev, EP_INT_REG);  
  617.   
  618.     //printk(  "USB_INT_REG = 0x%x\n", usb_status);  
  619.     //printk(  "EP_INT_REG = 0x%x\n", ep_status);  
  620.   
  621.     /* Driver connected ? */  
  622.     if (!dev->driver)   
  623.     {  
  624.         /* Clear interrupts */  
  625.         WRITE_REG(dev, USB_INT_REG, READ_REG(dev, USB_INT_REG));  
  626.         WRITE_REG(dev, EP_INT_REG, READ_REG(dev, EP_INT_REG));  
  627.     }  
  628.   
  629.     //reset  
  630.     if (usb_status & (1 << 2))  
  631.     {  
  632.         printk(  "USB reset\n");  
  633.   
  634.         WRITE_REG(dev, INDEX_REG, 0);  
  635.         WRITE_REG(dev, MAXP_REG, (dev->ep[0].ep.maxpacket & 0x7ff) >> 3);  
  636.   
  637.         dev->ep0state = EP0_IDLE;  
  638.         dev->gadget.speed = USB_SPEED_FULL;  
  639.   
  640.         s3c2440_dequeue_all(&dev->ep[0], -EPROTO);  
  641.   
  642.         SETB(dev, USB_INT_REG, 2);  
  643.   
  644.         spin_unlock_irqrestore(&dev->lock, flags);  
  645.   
  646.         return IRQ_HANDLED;  
  647.     }  
  648.   
  649.     //resume  
  650.     if (usb_status & (1 << 1))  
  651.     {  
  652.         printk(  "USB resume\n");  
  653.   
  654.         SETB(dev, USB_INT_REG, 1);  
  655.   
  656.         if (dev->gadget.speed != USB_SPEED_UNKNOWN  
  657.                 && dev->driver  
  658.                 && dev->driver->resume)  
  659.             dev->driver->resume(&dev->gadget);  
  660.     }  
  661.   
  662.     //suspend  
  663.     if (usb_status & 1)  
  664.     {  
  665.         printk(  "USB suspend\n");  
  666.   
  667.         SETB(dev, USB_INT_REG, 0);  
  668.   
  669.         if (dev->gadget.speed != USB_SPEED_UNKNOWN  
  670.            && dev->driver  
  671.            && dev->driver->suspend)  
  672.         dev->driver->suspend(&dev->gadget);  
  673.   
  674.         dev->ep0state = EP0_IDLE;  
  675.     }  
  676.   
  677.     if (ep_status & 1)  
  678.     {  
  679.         printk(  "USB ep0 irq\n");  
  680.   
  681.         SETB(dev, EP_INT_REG, 0);  
  682.   
  683.         s3c2440_handle_ep0(dev);  
  684.     }  
  685.   
  686.     spin_unlock_irqrestore(&dev->lock, flags);  
  687.   
  688.     return IRQ_HANDLED;  
  689. }  
  690. /***************************************************************/  
  691.   
  692. /***********************queue***********************************/  
  693. //对于usb请求,一般都要维护一个list去管理请求  
  694.   
  695. //端点list初始化,存入gadget里  
  696. static void s3c2440_usb_reinit(struct s3c2440_udc *dev)  
  697. {  
  698.     u8 i;  
  699.   
  700.     /* device/ep0 records init */  
  701.     INIT_LIST_HEAD (&dev->gadget.ep_list);  
  702.     dev->gadget.ep0 = &dev->ep[0].ep;//ep0单独存放  
  703.     dev->ep0state = EP0_IDLE;  
  704.     INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);  
  705.   
  706.     for (i = 0; i < S3C2440_ENDPOINTS; i++) {  
  707.         struct s3c2440_ep *ep = &dev->ep[i];  
  708.   
  709.         if (i != 0)  
  710.             list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);  
  711.   
  712.         ep->dev = dev;  
  713.         ep->desc = NULL;  
  714.         ep->stopped = 0;  
  715.         INIT_LIST_HEAD (&ep->queue);  
  716.     }  
  717. }  
  718.   
  719. static void s3c2440_udc_done(struct s3c2440_ep *ep, struct s3c2440_request *req, int status)  
  720. {  
  721.     struct s3c2440_udc *dev;  
  722.     unsigned stopped = ep->stopped;  
  723.   
  724.     list_del_init(&req->queue);  
  725.   
  726.     if (likely (req->req.status == -EINPROGRESS))//正在进行中  
  727.         req->req.status = status;  
  728.     else  
  729.         status = req->req.status;  
  730.   
  731.     dev = ep->dev;  
  732.   
  733.     /* don't modify queue heads during completion callback */  
  734.     ep->stopped = 1;  
  735.     //先解锁再加锁,加锁是在dequeue_all调用前做的  
  736.     spin_unlock(&dev->lock);  
  737.     req->req.complete(&ep->ep, &req->req);  
  738.     spin_lock(&dev->lock);  
  739.     ep->stopped = stopped;  
  740. }  
  741.   
  742. static void s3c2440_dequeue_all(struct s3c2440_ep *ep, int status)  
  743. {  
  744.     struct s3c2440_request *req;  
  745.   
  746.     if (&ep->queue == NULL)  
  747.         return;  
  748.   
  749.     while (!list_empty(&ep->queue)) //list_del_init会删除链表中的元素  
  750.     {  
  751.         req = list_entry(ep->queue.next, struct s3c2440_request, queue);  
  752.         s3c2440_udc_done(ep, req, status);  
  753.     }  
  754. }  
  755.   
  756.   
  757. /***************************************************************/  
  758. //may not be the endpoint named "ep0".这是gadget.h的源话  
  759. /**************************ep_ops*******************************/  
  760. //描述端点操作  
  761.   
  762. //当设备配置或接口设置改变时,驱动会enable或disable端口  
  763. static int s3c2440_udc_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)  
  764. {  
  765.     struct s3c2440_udc    *dev;  
  766.     struct s3c2440_ep    *ep;  
  767.     u32 max;  
  768.     unsigned long    flags;  
  769.   
  770.     printk(  "%s\n", __func__);  
  771.   
  772.     ep = to_s3c2440_ep(_ep);  
  773.     if (!_ep || !desc || ep->desc  
  774.             || (desc->bDescriptorType != USB_DT_ENDPOINT)  
  775.             || (_ep->name == ep0name))  
  776.         return -EINVAL;  
  777.     dev = ep->dev;  
  778.     if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)  
  779.         return -ESHUTDOWN;  
  780.   
  781.     max = usb_endpoint_maxp(desc) & 0x1fff;  
  782.   
  783.     spin_lock_irqsave(&dev->lock, flags);  
  784.   
  785.     _ep->maxpacket = max & 0x7fff;  
  786.     ep->desc = desc;  
  787.     ep->stopped = 0;  
  788. #ifdef S3C2440_SETWEDHE  
  789.     ep->wedged = 0;  
  790. #endif  
  791.     ep->bEndpointAddress = desc->bEndpointAddress;  
  792.   
  793.     WRITE_REG(dev, INDEX_REG, ep->num);  
  794.     WRITE_REG(dev, MAXP_REG, max >> 3);  
  795.   
  796.     if (desc->bEndpointAddress & USB_DIR_IN)   
  797.     {  
  798.         SETB(dev, IN_CSR1_REG, 0);//清楚IN_PKT_RDY  
  799.         SETB(dev, IN_CSR1_REG, 3);//FLUSH fifo  
  800.   
  801.         SETB(dev, IN_CSR2_REG, 0);//关闭in dma中断,先不用dma  
  802.         SETB(dev, IN_CSR2_REG, 5);//in  
  803.         SETB(dev, IN_CSR2_REG, 6);//批量端点  
  804.     }  
  805.     else  
  806.     {  
  807.         CLRB(dev, IN_CSR2_REG, 5);//out  
  808.   
  809.         SETB(dev, OUT_CSR1_REG, 0);//清楚IN_PKT_RDY  
  810.         SETB(dev, OUT_CSR1_REG, 4);//FLUSH fifo  
  811.   
  812.         SETB(dev, OUT_CSR2_REG, 5);//批量端点  
  813.         SETB(dev, OUT_CSR2_REG, 6);//关闭out dma中断,先不用dma  
  814.     }  
  815.   
  816.     SETB(dev, EP_INT_EN_REG, ep->num);//开中断  
  817.   
  818.     spin_unlock_irqrestore(&dev->lock, flags);  
  819.   
  820.     return 0;  
  821. }  
  822.   
  823. static int s3c2440_udc_ep_disable(struct usb_ep *_ep)  
  824. {  
  825.     struct s3c2440_udc    *dev;  
  826.     struct s3c2440_ep *ep = to_s3c2440_ep(_ep);  
  827.     unsigned long flags;  
  828.   
  829.     printk(  "%s\n", __func__);  
  830.   
  831.     if (!_ep || !ep->desc) {  
  832.         return -EINVAL;  
  833.     }  
  834.   
  835.     local_irq_save(flags);  
  836.   
  837.     ep->desc = NULL;  
  838.     ep->stopped = 1;  
  839.     dev = ep->dev;  
  840.   
  841.     //清除请求list和关闭ep  
  842.     s3c2440_dequeue_all(ep, -ESHUTDOWN);//关机后将无法传输端点  
  843.   
  844.     CLRB(dev, EP_INT_REG, ep->num);//关对应ep中断  
  845.   
  846.     local_irq_restore(flags);  
  847.   
  848.     return 0;  
  849. }  
  850.   
  851. //动态分配请求  
  852. static struct usb_request *s3c2440_udc_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)  
  853. {  
  854.     struct s3c2440_request *req;  
  855.   
  856.     printk(  "%s\n", __func__);  
  857.   
  858.     if (!_ep)  
  859.         return NULL;  
  860.   
  861.     req = kzalloc (sizeof(struct s3c2440_request), gfp_flags);  
  862.     if (!req)  
  863.         return NULL;  
  864.   
  865.     INIT_LIST_HEAD (&req->queue);  
  866.   
  867.     return &req->req;  
  868. }  
  869.   
  870. //释放请求  
  871. static void s3c2440_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)  
  872. {  
  873.     //struct s3c2440_ep    *ep = to_s3c2440_ep(_ep);  
  874.     struct s3c2440_request *req = to_s3c2440_req(_req);  
  875.   
  876.     printk(  "%s\n", __func__);  
  877.   
  878.     if (!_ep || !_req)  
  879.         return;  
  880.   
  881.     WARN_ON (!list_empty (&req->queue));  
  882.     kfree(req);  
  883. }  
  884.   
  885. //下面的queue是插入一个请求  
  886. //dequeue删除一个请求  
  887. static int s3c2440_udc_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)  
  888. {  
  889.     struct s3c2440_udc    *dev;  
  890.     unsigned long        flags;  
  891.     struct s3c2440_request    *req = to_s3c2440_req(_req);  
  892.     struct s3c2440_ep        *ep = to_s3c2440_ep(_ep);  
  893.     u32 fifo_count, ep_csr;  
  894.   
  895.     printk(  "%s\n", __func__);  
  896.   
  897.     if (unlikely (!_ep || (!ep->desc && ep->num != 0))) //这个逻辑下面会看到很多(_ep为空或[ep->desc为空且不是0端点])  
  898.     {  
  899.         return -EINVAL;  
  900.     }  
  901.   
  902.     dev = ep->dev;  
  903.     if (unlikely (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN))   
  904.     {  
  905.         return -ESHUTDOWN;  
  906.     }  
  907.   
  908.     local_irq_save (flags); //因为中断中有queue操作,所以要放在list_empty前  
  909.   
  910.     if (unlikely(!_req || !_req->complete  
  911.             || !_req->buf || !list_empty(&req->queue))) //_req或_req->buf为空、complete执行错误、req->queue不为空  
  912.     {  
  913.         local_irq_restore(flags);  
  914.   
  915.         return -EINVAL;  
  916.     }   
  917.   
  918.     _req->status = -EINPROGRESS;  
  919.     _req->actual = 0;  
  920.   
  921.     WRITE_REG(dev, INDEX_REG, ep->bEndpointAddress & 0x7F);  
  922.     s3c2440_usb_fifocnt(dev, &fifo_count);  
  923.   
  924.     if (ep->bEndpointAddress == 0)  
  925.     {  
  926.         ep_csr = READ_REG(dev, EP0_CSR);  
  927.     }  
  928.     else  
  929.     {  
  930.         ep_csr = READ_REG(dev, (ep->bEndpointAddress & USB_DIR_IN) ? IN_CSR1_REG : OUT_CSR1_REG);  
  931.     }  
  932.   
  933.     if (list_empty(&ep->queue) && !ep->stopped)  
  934.     {  
  935.         if (ep->bEndpointAddress == 0)  
  936.         {  
  937.             switch(dev->ep0state)  
  938.             {  
  939.             case EP0_IN:  
  940.                   
  941.                 if (!(ep_csr & (1 << 1)))  
  942.                 {  
  943.                     if (s3c2440_write_fifo(dev, ep, req))  
  944.                     {  
  945.                         dev->ep0state = EP0_IDLE;  
  946.                         req = NULL;  
  947.                     }  
  948.                 }  
  949.   
  950.                 break;  
  951.   
  952.             case EP0_OUT:  
  953.                 if (ep_csr & 1)  
  954.                 {  
  955.                     if (s3c2440_read_fifo(dev, ep, req) == 1)  
  956.                     {  
  957.                         dev->ep0state = EP0_IDLE;  
  958.                         req = NULL;  
  959.                     }  
  960.                 }  
  961.                 break;  
  962.   
  963.             default:  
  964.                 local_irq_restore(flags);  
  965.   
  966.                 return -EL2HLT;  
  967.             }  
  968.         }  
  969.         else if ((ep->bEndpointAddress & USB_DIR_IN) != 0)  
  970.         {  
  971.         }  
  972.         else  
  973.         {  
  974.         }  
  975.     }  
  976.   
  977.     if (likely(req != 0))  
  978.         list_add_tail(&req->queue, &ep->queue);//请求入list  
  979.   
  980.     local_irq_restore(flags);  
  981.   
  982.     return 0;  
  983. }  
  984.   
  985. static int s3c2440_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)  
  986. {  
  987.     struct s3c2440_ep        *ep = to_s3c2440_ep(_ep);  
  988.     struct s3c2440_udc    *dev;  
  989.     int            retval = -EINVAL;  
  990.     unsigned long        flags;  
  991.     struct s3c2440_request    *req = NULL;  
  992.   
  993.     printk(  "%s\n", __func__);  
  994.   
  995.     if (!_ep || !_req)  
  996.         return retval;  
  997.   
  998.     dev = ep->dev;  
  999.   
  1000.     if (!dev->driver)  
  1001.         return -ESHUTDOWN;  
  1002.   
  1003.     local_irq_save (flags);  
  1004.   
  1005.     list_for_each_entry (req, &ep->queue, queue)   
  1006.     {  
  1007.         if (&req->req == _req)   
  1008.         {  
  1009.             list_del_init (&req->queue);  
  1010.             _req->status = -ECONNRESET;//Connection reset by peer  
  1011.             retval = 0;  
  1012.             break;  
  1013.         }  
  1014.     }  
  1015.   
  1016.     if (retval == 0)   
  1017.     {  
  1018.         s3c2440_udc_done(ep, req, -ECONNRESET);  
  1019.     }  
  1020.   
  1021.     local_irq_restore (flags);  
  1022.     return retval;  
  1023. }  
  1024.   
  1025. #ifdef S3C2440_FIFO_STATUS  
  1026. //fifo状态,返回fifo中的字节数。  
  1027. //在上层的调用usb_ep_fifo_statu()如果不用fifo或不支持这个操作返回错误-EOPNOTSUPP  
  1028. //net2272就有寄存器EP_AVAIL记录fifo中的字节数。  
  1029. //s3c2440硬件不支持,没实现,上层调用会得到-EOPNOTSUPP  
  1030. static int s3c2440_udc_fifo_status(struct usb_ep *_ep)  
  1031. {  
  1032.     struct s3c2440_ep *ep;  
  1033.     u16 retval = 0;  
  1034.   
  1035.     printk(  "%s\n", __func__);  
  1036.   
  1037.     ep = to_s3c2440_ep(_ep);  
  1038.     if (!_ep || (!ep->desc && ep->num != 0))  
  1039.         return -ENODEV;  
  1040.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  1041.         return -ESHUTDOWN;  
  1042.   
  1043.     //retval = 读寄存器  
  1044.   
  1045.     return retval;  
  1046. }  
  1047. #endif  
  1048.   
  1049. #ifdef S3C2440_FIFO_FLUSH  
  1050. //冲掉fifo的不明确数据,这个决不用除非端点不能用于任何协议传输,这是上层调用的事  
  1051. static void s3c2440_udc_fifo_flush(struct usb_ep *_ep)  
  1052. {  
  1053.     struct s3c2440_ep *ep;  
  1054.   
  1055.     printk(  "%s\n", __func__);  
  1056.   
  1057.     ep = to_s3c2440_ep(_ep);  
  1058.     if (!_ep || (!ep->desc && ep->num != 0))  
  1059.         return;  
  1060.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  1061.         return;  
  1062.   
  1063.     //寄存器操作  
  1064. }  
  1065. #endif  
  1066.   
  1067. /* 
  1068. 上层调用usb_ep_set_wedge 
  1069. 停止一个端点并忽略CLEAR_FEATURE请求。如果Gadget驱动清除停止状态,它将自动Unwedge端点 
  1070. 一般用一个位wedge表示 
  1071. 如果没有实现set_wedge方法。就用set_halt(ep, 1);代替 
  1072. 我们看个例子(在file_storage.c中) 
  1073. Bulk-only 
  1074. 当出现无效的CBW时 
  1075. Bulk-only Spec说我们必须停止IN 端点。还说必须保持这个状态知道下一次的reset,但是没有办法 
  1076. 告诉控制器忽略CLEAR_FEATURE请求。所以我们用一个位来记录,搞定! 
  1077. 下面是参考net2272的代码, 
  1078. value=1:set_halt 
  1079. = 0:clear_halt 
  1080. */  
  1081. static int s3c2440_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)  
  1082. {  
  1083.     struct s3c2440_ep *ep;  
  1084.     unsigned long flags;  
  1085.     int ret = 0;  
  1086.   
  1087.     ep = container_of(_ep, struct s3c2440_ep, ep);  
  1088.     if (!_ep || (!ep->desc && ep->num != 0))  
  1089.         return -EINVAL;  
  1090.     if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)  
  1091.         return -ESHUTDOWN;  
  1092.     if (ep->desc /* not ep0 */ && usb_endpoint_xfer_isoc(ep->desc))//判断是不是同步端点,见下面  
  1093.         return -EINVAL;  
  1094.   
  1095.     spin_lock_irqsave(&ep->dev->lock, flags);  
  1096.   
  1097.     if (!list_empty(&ep->queue))  
  1098.         ret = -EAGAIN;  
  1099. #ifdef S3C2440_FIFO_STATUS  
  1100.     else if ((ep->bEndpointAddress & USB_DIR_IN) && value && s3c2440_udc_fifo_status(_ep) != 0)//fifo_status是上面实现的  
  1101.         ret = -EAGAIN;  
  1102. #endif  
  1103.     else {  
  1104.         /* set/clear */  
  1105.         if (value) {  
  1106.             if (ep->num == 0)  
  1107.             {  
  1108.                  ep->dev->ep0state = EP0_STALL;  
  1109.                  ep->stopped = 1;  
  1110.                 //net2272的端点0在setup时自动复位,没有什么操作。s3c2440就不是了  
  1111.                 //ep->dev->protocol_stall = 1;  
  1112.                 //ep0 set_halt  
  1113.             }  
  1114.             else  
  1115.                 //epx(x != 0) set_halt  
  1116.             if (wedged)//维护wedged  
  1117.                 ep->wedged = 1;  
  1118.         } else {  
  1119.             //ep clear_halt  
  1120.             ep->wedged = 0;  
  1121.         }  
  1122.     }  
  1123.     spin_unlock_irqrestore(&ep->dev->lock, flags);  
  1124.   
  1125.     return ret;  
  1126. }  
  1127. //_ep 不能是同步端点,同步端点不支持错误重发机制。在上面判断  
  1128. static int s3c2440_udc_set_halt(struct usb_ep *_ep, int value)  
  1129. {  
  1130.     printk(  "%s\n", __func__);  
  1131.   
  1132.     return s3c2440_set_halt_and_wedge(_ep, value, 0);  
  1133. }  
  1134.   
  1135. #ifdef S3C2440_SETWEDHE  
  1136.   
  1137. static int s3c2440_udc_set_wedge(struct usb_ep *_ep)  
  1138. {  
  1139.   
  1140.     printk(  "%s\n", __func__);  
  1141.   
  1142.     if (!_ep || _ep->name == ep0name)//一般都是端点0请求复位  
  1143.         return -EINVAL;  
  1144.   
  1145.     return s3c2440_set_halt_and_wedge(_ep, 1, 1);  
  1146. }  
  1147. #endif  
  1148.   
  1149. static const struct usb_ep_ops s3c2440_ep_ops =   
  1150. {  
  1151.     .enable        = s3c2440_udc_ep_enable,  
  1152.     .disable    = s3c2440_udc_ep_disable,  
  1153.   
  1154.     .alloc_request    = s3c2440_udc_alloc_request,  
  1155.     .free_request    = s3c2440_udc_free_request,  
  1156.   
  1157.     .queue        = s3c2440_udc_queue,  
  1158.     .dequeue    = s3c2440_udc_dequeue,  
  1159.    
  1160.     .set_halt    = s3c2440_udc_set_halt,  
  1161.   
  1162. #ifdef S3C2440_SETWEDHE  
  1163.     .set_wedge  = s3c2440_udc_set_wedge,  
  1164. #endif  
  1165.   
  1166. #ifdef S3C2440_FIFO_STATUS  
  1167.     .fifo_status = s3c2440_udc_fifo_status,  
  1168. #endif  
  1169.   
  1170. #ifdef S3C2440_FIFO_FLUSH  
  1171.     .fifo_flush = s3c2440_udc_fifo_flush,  
  1172. #endif  
  1173. };  
  1174.   
  1175. /***************************************************************/  
  1176. //USB 设备的常用操作包括:设备连接、设备移除、设备配置、地址分配、数据传输、   
  1177. //设备挂起、设备唤醒等。  
  1178. /**************************usb_gadget_ops***********************/  
  1179. //硬件操作函数  
  1180.   
  1181. //获取帧号,当主机发送USB 数据包时,每个帧的开始(SOF)包包含一个帧号。  
  1182. //这个帧号一般自动加载到对应寄存器,此函数主要就是读这些寄存器  
  1183. //如果设备不支持返回负  
  1184. static int s3c2440_udc_get_frame(struct usb_gadget *usb_gdt_p)  
  1185. {  
  1186.     printk(  "%s\n", __func__);  
  1187.   
  1188. #ifdef S3C2440_GET_FRAME  
  1189.     struct s3c2440_udc *dev = to_s3c2440_udc(usb_gdt_p);  
  1190.     int retval = 0;  
  1191.     unsigned long flags;  
  1192.   
  1193.     spin_lock_irqsave(&dev->lock, flags);  
  1194.   
  1195.     retval = READ_REG(dev, S3C2410_UDC_FRAME_NUM2_REG) << 8;  
  1196.     retval |= READ_REG(dev, S3C2410_UDC_FRAME_NUM1_REG);  
  1197.   
  1198.     spin_unlock_irqrestore(&dev->lock, flags);  
  1199.   
  1200.     return retval;  
  1201. #else  
  1202.     return -EOPNOTSUPP;  
  1203. #endif  
  1204. }  
  1205.   
  1206. #ifdef S3C2440_WAKEUP  
  1207. //唤醒,举个例子net2272。它的寄存器usbctl0的第五位控制唤醒功能使能  
  1208. //寄存器usbctl1的第三位通过写1去resume,s3c2440在PWR_REG也有类似  
  1209. static int s3c2440_udc_wakeup(struct usb_gadget *usb_gdt_p)  
  1210. {  
  1211.     struct s3c2440_udc *dev = to_s3c2440_udc(usb_gdt_p);  
  1212.     unsigned long flags;  
  1213.   
  1214.     printk(  "%s\n", __func__);  
  1215.   
  1216.     spin_lock_irqsave(&dev->lock, flags);  
  1217.   
  1218.     if (GETB(dev, PWR_REG, 0))//如果使能挂起模式  
  1219.     {  
  1220.         SETB(dev, PWR_REG, 2);  
  1221.     }  
  1222.   
  1223.     spin_unlock_irqrestore(&dev->lock, flags);  
  1224.   
  1225.     return 0;  
  1226. }  
  1227. #endif  
  1228.   
  1229. #ifdef S3C2440_SELFPOWERED  
  1230. //设置自供电标志(selfpowered feature),一般就用一个变量位或一个位记录一下。USB_RECIP_DEVICE时返回状态  
  1231. static int s3c2440_udc_set_selfpowered (struct usb_gadget *usb_gdt_p, int is_selfpowered)  
  1232. {  
  1233.     struct s3c2440_udc *dev = to_s3c2440_udc(usb_gdt_p);  
  1234.   
  1235.     printk(  "%s\n", __func__);  
  1236.   
  1237.     if (is_selfpowered)  
  1238.         dev->devstatus |= (1 << USB_DEVICE_SELF_POWERED);  
  1239.     else  
  1240.         dev->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);  
  1241.   
  1242.     return 0;  
  1243. }  
  1244. #endif  
  1245.   
  1246. #ifdef S3C2440_VBUS_SESSION  
  1247. //vbus在硬件上就是usb的电源脚,这个函数就是来控制它。一般通过一个gpio拉高拉底  
  1248. //这个vbus会话,实际的我看了s3c2410和at91的处理,就是让usb的D+线与一个gpio口连接  
  1249. //通过置1置0来控制usb  
  1250. static int s3c2440_udc_vbus_session (struct usb_gadget *usb_gdt_p, int is_active)  
  1251. {  
  1252.     struct s3c2440_udc *dev = to_s3c2440_udc(usb_gdt_p);  
  1253.     unsigned long flags;  
  1254.   
  1255.     printk(  "%s\n", __func__);  
  1256.   
  1257.     spin_lock_irqsave(&dev->lock, flags);  
  1258.   
  1259.     //寄存器操作  
  1260.   
  1261.     spin_unlock_irqrestore(&dev->lock, flags);  
  1262.   
  1263.     return 0;  
  1264. }  
  1265. #endif  
  1266.   
  1267. #ifdef S3C2440_VBBUS_DRAW  
  1268. //强制vbus电源控制器行为,在SET_CONFIGRATION时,设置vbus的电流量  
  1269. //vbus应该是表示总线电压,在硬件上是一个脚  
  1270. //主要是对usb电流的设置,看一下gta02平台,这个函数会操作pcf50633(一种移动设备的电源管理芯片)  
  1271. static int s3c2440_udc_vbus_draw (struct usb_gadget *usb_gdt_p, unsigned mA)  
  1272. {  
  1273.     return 0;  
  1274. }  
  1275. #endif  
  1276.   
  1277. #ifdef S3C2440X_PULLUP  
  1278. //这个和上面的vbus_session区别是  
  1279. //vbus_session是控制vbus的连接  
  1280. //pullup是控制usb模块的连接  
  1281. //在udc-core.c中newstyle的驱动probe函数时才调用它,所以你要实现udc_start和udc_stop,  
  1282. //当然除了注册,也可以通过sysfs调用它。和newstyle无关。  
  1283. //composite.c也有一些调用  
  1284. //这个就是根据is_on来connect或disconnect usb  
  1285. //net2272就是由USBCTL0的第三位控制的,s3c2440还是通过gpio和vbus_session没  
  1286. //区别  
  1287. static int s3c2440_udc_pullup (struct usb_gadget *usb_gdt_p, int is_on)  
  1288. {  
  1289.     struct s3c2440_udc *dev = to_s3c2440_udc(usb_gdt_p);  
  1290.     unsigned long flags;  
  1291.   
  1292.     printk(  "%s\n", __func__);  
  1293.   
  1294.     spin_lock_irqsave(&dev->lock, flags);  
  1295.   
  1296.     if (is_on)  
  1297.     {  
  1298.         PULL_UP();  
  1299.     }  
  1300.     else  
  1301.     {  
  1302.         PULL_DOWN();  
  1303.     }  
  1304.   
  1305.     spin_unlock_irqrestore(&dev->lock, flags);  
  1306.   
  1307.     return 0;  
  1308. }  
  1309. #endif  
  1310.   
  1311. //不好意思,我看了linux-3.2.36的/gadget的目录没发现有实现这个的硬件  
  1312. static int s3c2440_udc_ioctl(struct usb_gadget *usb_gdt_p, unsigned code, unsigned long param)  
  1313. {  
  1314.     return 0;  
  1315. }  
  1316.   
  1317. //这个也没看驱动实现它,从名字就是获取配置参数,就简单看看struct usb_dcd_config_params  
  1318. /* 
  1319. struct usb_dcd_config_params { 
  1320.         __u8  bU1devExitLat;    // U1 Device exit Latency  u1设备等待时间 
  1321. #define USB_DEFAULT_U1_DEV_EXIT_LAT     0x01    // Less then 1 microsec 至少1微秒 
  1322.         __le16 bU2DevExitLat;   // U2 Device exit Latency  
  1323. #define USB_DEFAULT_U2_DEV_EXIT_LAT     0x1F4   // Less then 500 microsec  
  1324. }; 
  1325. 对应struct usb_ss_cap_descriptor 中的成员 
  1326. 每一个I/O请求包延迟时间限制 
  1327. */  
  1328. static void s3c2440_udc_get_config_params(struct usb_dcd_config_params *usb_dc_cfg_pm)  
  1329. {  
  1330. }  
  1331.   
  1332. //在udc-core.c中start和udc_start的解释一样,在bind()之前调用,只要实现一个就行了  
  1333. //我知道start主要有bind回调  
  1334. //udc_start主要是设备执行了non-control请求后,要重新连接,net2272和r8a66597实现的就是它  
  1335. #ifdef S3C2440_NEWSTYLE  
  1336. static int s3c2440_udc_start(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver);  
  1337. static int s3c2440_udc_stop(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver);  
  1338. #else  
  1339. //s3c2410 s3c2440 实现它  
  1340. static int s3c2440_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *));  
  1341. static int s3c2440_stop(struct usb_gadget_driver *driver);  
  1342. #endif  
  1343.   
  1344. static const struct usb_gadget_ops s3c2440_ops =   
  1345. {  
  1346.     .get_frame        = s3c2440_udc_get_frame,  
  1347. #ifdef S3C2440_WAKEUP  
  1348.     .wakeup            = s3c2440_udc_wakeup,  
  1349. #endif  
  1350.   
  1351. #ifdef S3C2440_SELFPOWERED  
  1352.     .set_selfpowered = s3c2440_udc_set_selfpowered,  
  1353. #endif  
  1354.   
  1355. #ifdef S3C2440_VBUS_SESSION  
  1356.     .vbus_session    = s3c2440_udc_vbus_session,  
  1357. #endif  
  1358.   
  1359. #ifdef S3C2440_VBBUS_DRAW  
  1360.     .vbus_draw        = s3c2440_udc_vbus_draw,  
  1361. #endif  
  1362.   
  1363. #ifdef S3C2440X_PULLUP  
  1364.     .pullup            = s3c2440_udc_pullup,  
  1365. #endif  
  1366.   
  1367.     .ioctl          = s3c2440_udc_ioctl,  
  1368.     .get_config_params = s3c2440_udc_get_config_params,  
  1369. #ifdef S3C2440_NEWSTYLE  
  1370.     .udc_start         = s3c2440_udc_start,  
  1371.     .udc_stop       = s3c2440_udc_stop,  
  1372. #else  
  1373.     .start            = s3c2440_start,  
  1374.     .stop            = s3c2440_stop,  
  1375. #endif  
  1376. };  
  1377.   
  1378. /***************************************************************/  
  1379.   
  1380.   
  1381. /***************************************************************/  
  1382.   
  1383. static struct s3c2440_udc udc_info = {  
  1384.     .gadget = {  
  1385.         .ops        = &s3c2440_ops,  
  1386.         .ep0        = &udc_info.ep[0].ep,  
  1387.         .name        = gadget_name,  
  1388.         .dev = {  
  1389.             .init_name    = "gadget",  
  1390.         },  
  1391. /* 
  1392. 根据自己的硬件选择 
  1393. unsigned is_dualspeed:1; 
  1394. unsigned is_otg:1; 
  1395. unsigned is_a_peripheral:1; 
  1396. unsigned b_hnp_enable:1; //hnp:主机协商协议 otg特有的 
  1397. unsigned a_hnp_support:1; 
  1398. unsigned a_alt_hnp_support:1; 
  1399. */  
  1400.     },  
  1401.   
  1402.     /* control endpoint */  
  1403.     .ep[0] = {  
  1404.         .num = 0,  
  1405.         .ep =  
  1406.         {  
  1407.             .name        = "ep0",  
  1408.             .ops        = &s3c2440_ep_ops,  
  1409.             .maxpacket    = EP0_FIFO_SIZE,  
  1410.         },  
  1411.         .dev        = &udc_info,  
  1412.         .fifo_size = S3C2440_EP0_FIFO_SIZE,  
  1413.     },  
  1414.   
  1415.     /* first group of endpoints */  
  1416.     .ep[1] = {  
  1417.         .num = 1,  
  1418.         .ep =   
  1419.         {  
  1420.             .name        = "ep1-bulk",  
  1421.             .ops        = &s3c2440_ep_ops,  
  1422.             .maxpacket    = EP1_FIFO_SIZE,  
  1423.         },  
  1424.         .dev        = &udc_info,  
  1425.         .fifo_size    = S3C2440_EP1_FIFO_SIZE,  
  1426.         .bEndpointAddress = EP1_ADDRESS,  
  1427.         .bmAttributes    = EP1_ATTR,  
  1428.     },  
  1429.     .ep[2] = {  
  1430.         .num = 2,  
  1431.         .ep =   
  1432.         {  
  1433.             .name        = "ep2-bulk",  
  1434.             .ops        = &s3c2440_ep_ops,  
  1435.             .maxpacket    = EP2_FIFO_SIZE,  
  1436.         },  
  1437.         .dev        = &udc_info,  
  1438.         .fifo_size    = S3C2440_EP2_FIFO_SIZE,  
  1439.         .bEndpointAddress = EP2_ADDRESS,  
  1440.         .bmAttributes    = EP2_ATTR,  
  1441.     },  
  1442.     .ep[3] = {  
  1443.         .num = 3,  
  1444.         .ep =   
  1445.         {  
  1446.             .name        = "ep3-bulk",  
  1447.             .ops        = &s3c2440_ep_ops,  
  1448.             .maxpacket    = EP3_FIFO_SIZE,  
  1449.         },  
  1450.         .dev        = &udc_info,  
  1451.         .fifo_size    = S3C2440_EP3_FIFO_SIZE,  
  1452.         .bEndpointAddress = EP3_ADDRESS,  
  1453.         .bmAttributes    = EP3_ATTR,  
  1454.     },  
  1455.     .ep[4] = {  
  1456.         .num = 4,  
  1457.         .ep =   
  1458.         {  
  1459.             .name        = "ep4-bulk",  
  1460.             .ops        = &s3c2440_ep_ops,  
  1461.             .maxpacket    = EP4_FIFO_SIZE,  
  1462.         },  
  1463.         .dev        = &udc_info,  
  1464.         .fifo_size    = S3C2440_EP4_FIFO_SIZE,  
  1465.         .bEndpointAddress = EP4_ADDRESS,  
  1466.         .bmAttributes    = EP4_ATTR,  
  1467.     },  
  1468. };  
  1469.   
  1470. static void stop_activity(struct s3c2440_udc *dev, struct usb_gadget_driver *driver)  
  1471. {  
  1472.     unsigned i;  
  1473.   
  1474.     if (dev->gadget.speed == USB_SPEED_UNKNOWN)  
  1475.         driver = NULL;  
  1476.   
  1477.     /* disconnect gadget driver after quiesceing hw and the driver */  
  1478.   
  1479.     s3c2440_usb_reset(dev);//复位或disable  
  1480.     for (i = 0; i < S3C2440_ENDPOINTS; i++)  
  1481.     {  
  1482.         s3c2440_dequeue_all(&dev->ep[i], -ECONNABORTED);  
  1483.     }  
  1484.   
  1485. #ifndef S3C2440_NEWSTYLE  
  1486. /* 
  1487. if (udc_is_newstyle(udc)) { 
  1488.         udc->driver->disconnect(udc->gadget); 
  1489.         udc->driver->unbind(udc->gadget); 
  1490.         usb_gadget_udc_stop(udc->gadget, udc->driver); 
  1491.         usb_gadget_disconnect(udc->gadget);//对应pull_up 
  1492. } else { 
  1493.         usb_gadget_stop(udc->gadget, udc->driver);//所以非newstyle要disconnect 
  1494. */  
  1495.     if (driver)   
  1496.     {  
  1497.         spin_unlock(&dev->lock);  
  1498.         driver->disconnect(&dev->gadget);  
  1499.         spin_lock(&dev->lock);  
  1500.     }  
  1501. #endif  
  1502.   
  1503.     if (dev->driver)  
  1504.     {  
  1505.         s3c2440_usb_reinit(dev);//重初始化  
  1506.     }  
  1507. }  
  1508.   
  1509. #ifdef S3C2440_NEWSTYLE  
  1510. /* 
  1511. udc 的probe函数 
  1512. if (udc_is_newstyle(udc)) {//是否实现udc_start and udc_stop 
  1513.         ret = bind(udc->gadget); 
  1514.         if (ret) 
  1515.                 goto err1; 
  1516.         ret = usb_gadget_udc_start(udc->gadget, driver);//已绑定,bind是gadget实现的 
  1517.         if (ret) { 
  1518.                 driver->unbind(udc->gadget); 
  1519.                 goto err1; 
  1520.         } 
  1521.         usb_gadget_connect(udc->gadget);//上面的pullup 
  1522. } else { 
  1523.  
  1524.         ret = usb_gadget_start(udc->gadget, driver, bind); 
  1525.         if (ret) 
  1526.                 goto err1; 
  1527.  
  1528. */  
  1529. //net2272和r8a66597实现的就是它  
  1530. //下面参考net2272  
  1531. static int s3c2440_udc_start(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver)  
  1532. {  
  1533.     struct s3c2440_udc *dev;  
  1534.   
  1535.     printk(  "%s\n", __func__);  
  1536.   
  1537.     if (!driver || !driver->unbind || !driver->setup ||  
  1538.         driver->speed != USB_SPEED_HIGH)  
  1539.         return -EINVAL;  
  1540.   
  1541.     dev = container_of(usb_gdt_p, struct s3c2440_udc, gadget);  
  1542.   
  1543.     /* hook up the driver ... */  
  1544.     driver->driver.bus = NULL;  
  1545.     dev->driver = driver;  
  1546.     dev->gadget.dev.driver = &driver->driver;  
  1547.   
  1548.     s3c2440_udc_enable(dev);  
  1549.   
  1550.     return 0;  
  1551. }  
  1552.   
  1553. static int s3c2440_udc_stop(struct usb_gadget *usb_gdt_p, struct usb_gadget_driver *driver)  
  1554. {  
  1555.     struct s3c2440_udc *dev;  
  1556.     unsigned long flags;  
  1557.   
  1558.     printk(  "%s\n", __func__);  
  1559.   
  1560.     dev = container_of(usb_gdt_p, struct s3c2440_udc, gadget);  
  1561.   
  1562.     spin_lock_irqsave(&dev->lock, flags);  
  1563.     stop_activity(dev, driver);  
  1564.     spin_unlock_irqrestore(&dev->lock, flags);  
  1565.   
  1566.     dev->gadget.dev.driver = NULL;  
  1567.     dev->driver = NULL;  
  1568.   
  1569.     return 0;  
  1570. }  
  1571.   
  1572. #else  
  1573. //s3c2410 s3c2440 实现它  
  1574. //下面参考s3c2440  
  1575. static int s3c2440_start(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *usb_gdt_p))  
  1576. {  
  1577.     struct s3c2440_udc *dev = &udc_info;  
  1578.     int    retval = 0;  
  1579.   
  1580.     printk(  "%s\n", __func__);  
  1581.   
  1582.     if (!driver  
  1583.             || driver->speed < USB_SPEED_FULL  
  1584.             || !bind  
  1585.             || !driver->disconnect  
  1586.             || !driver->setup)  
  1587.         return -EINVAL;  
  1588.     if (!dev)  
  1589.         return -ENODEV;  
  1590.     if (dev->driver)  
  1591.         return -EBUSY;  
  1592.   
  1593.     /* hook up the driver */  
  1594.     driver->driver.bus = NULL;  
  1595.     dev->driver = driver;  
  1596.     dev->gadget.dev.driver = &driver->driver;  
  1597.   
  1598.     if ((retval = device_add(&dev->gadget.dev)) != 0)   
  1599.     {  
  1600.         goto register_error;  
  1601.     }  
  1602.   
  1603.     retval = bind(&dev->gadget);  
  1604.     if (retval)   
  1605.     {  
  1606.         device_del(&dev->gadget.dev);  
  1607.         goto register_error;  
  1608.     }  
  1609.   
  1610.     s3c2440_udc_enable(dev);  
  1611.   
  1612.     return 0;  
  1613.   
  1614. register_error:  
  1615.     dev->driver = NULL;  
  1616.     dev->gadget.dev.driver = NULL;  
  1617.     return retval;  
  1618. }  
  1619.   
  1620. static int s3c2440_stop(struct usb_gadget_driver *driver)  
  1621. {  
  1622.     struct s3c2440_udc *dev = &udc_info;  
  1623.     unsigned long    flags;  
  1624.   
  1625.     printk(  "%s\n", __func__);  
  1626.   
  1627.     if (!dev)  
  1628.         return -ENODEV;  
  1629.     if (!driver || driver != dev->driver || !driver->unbind)  
  1630.         return -EINVAL;  
  1631.   
  1632.     spin_lock_irqsave(&dev->lock, flags);  
  1633.     dev->driver = NULL;  
  1634.     stop_activity(dev, driver);  
  1635.     spin_unlock_irqrestore(&dev->lock, flags);  
  1636.   
  1637.     driver->unbind(&dev->gadget);  
  1638.     dev->gadget.dev.driver = NULL;  
  1639.     dev->driver = NULL;  
  1640.   
  1641.     device_del(&dev->gadget.dev);  
  1642.       
  1643.     return 0;  
  1644. }  
  1645. #endif  
  1646.   
  1647. /***************************************************************/  
  1648. static int s3c2440_udc_probe(struct platform_device *pdev)  
  1649. {  
  1650.   
  1651.     struct s3c2440_udc *udc = &udc_info;  
  1652.     struct device *dev = &pdev->dev;  
  1653.     int retval;  
  1654.     struct resource *res;  
  1655. #ifdef S3C2440_USE_IRQ  
  1656.     struct resource *resirq;  
  1657. #endif  
  1658.     resource_size_t res_size;  
  1659.   
  1660.     dev_dbg(dev, "%s()\n", __func__);  
  1661.   
  1662. #ifdef S3C2440_HAVE_CLK  
  1663.     udc->s3c2440_clk_upll = clk_get(NULL, "usb-bus-gadget");  
  1664.     if (IS_ERR(udc->s3c2440_clk_upll))   
  1665.     {  
  1666.         dev_err(dev, "failed to get usb bus clock source\n");  
  1667.         return PTR_ERR(udc->s3c2440_clk_upll);  
  1668.     }  
  1669.   
  1670.     clk_enable(udc->s3c2440_clk_upll);  
  1671.   
  1672.     udc->s3c2440_clk_udc = clk_get(NULL, "usb-device");  
  1673.     if (IS_ERR(udc->s3c2440_clk_udc)) {  
  1674.         dev_err(dev, "failed to get udc clock source\n");  
  1675.         retval = PTR_ERR(udc->s3c2440_clk_udc);  
  1676.         goto err_clk_upll;  
  1677.     }  
  1678.   
  1679.     clk_enable(udc->s3c2440_clk_udc);  
  1680.   
  1681. #if (CLK_DELAY_TIME != 0)  
  1682.     mdelay(CLK_DELAY_TIME);  
  1683. #endif  
  1684.   
  1685.     dev_dbg(dev, "got and enabled clocks\n");  
  1686. #endif //S3C2440_HAVE_CLK  
  1687.   
  1688.     spin_lock_init (&udc->lock);  
  1689.   
  1690.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  1691.     if (!res)   
  1692.     {  
  1693.         dev_err(&pdev->dev, "can't get device resources\n");  
  1694.         retval = -ENODEV;  
  1695.         goto err_clk_udc;  
  1696.     }  
  1697.   
  1698.     res_size = resource_size(res);  
  1699.     if (!request_mem_region(res->start, res_size, res->name))   
  1700.     {  
  1701.         dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",  
  1702.             res_size, res->start);  
  1703.         retval = -ENOMEM;  
  1704.   
  1705.         goto err_clk_udc;  
  1706.     }  
  1707.   
  1708.     udc->virl_addr = ioremap(res->start, res_size);  
  1709.     if (!udc->virl_addr)   
  1710.     {  
  1711.         retval = -ENOMEM;  
  1712.         goto err_mem;  
  1713.     }  
  1714.     udc->phy_addr = res->start;  
  1715.     udc->reg_size = res_size;  
  1716.   
  1717.     device_initialize(&udc->gadget.dev);  
  1718.     udc->gadget.dev.parent = &pdev->dev;  
  1719.     udc->gadget.dev.dma_mask = pdev->dev.dma_mask;  
  1720.   
  1721.     platform_set_drvdata(pdev, udc);  
  1722.   
  1723.     //少不了硬件初始化  
  1724.     s3c2440_usb_reset(udc);  
  1725.     s3c2440_usb_reinit(udc);  
  1726.   
  1727. #ifdef S3C2440_USE_IRQ  
  1728.   
  1729.     resirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  
  1730.     if (!resirq)   
  1731.     {  
  1732.         dev_err(&pdev->dev, "can't get device irq resources\n");  
  1733.         retval = -ENODEV;  
  1734.         goto err_map;  
  1735.     }  
  1736.   
  1737.     udc->irq_num = resirq->start;  
  1738.   
  1739.     retval = request_irq(udc->irq_num, s3c2440_udc_irq, 0, gadget_name, (void*)udc);  
  1740.     if (retval != 0)   
  1741.     {  
  1742.         dev_err(dev, "cannot get irq %i, err %d\n", udc->irq_num, retval);  
  1743.         retval = -EBUSY;  
  1744.         goto err_map;  
  1745.     }  
  1746.   
  1747.     dev_dbg(dev, "got irq %i\n", udc->irq_num);  
  1748.   
  1749. #endif  
  1750.   
  1751.   
  1752.     retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);  
  1753.     if (retval)  
  1754.         goto err_int;  
  1755.   
  1756. #ifdef S3C2440_DEBUG_FS  
  1757.     if (s3c2440_udc_debugfs_root)   
  1758.     {  
  1759.         udc->debug_info = debugfs_create_file("registers", S_IRUGO, s3c2440_udc_debugfs_root,  
  1760.                 udc, &s3c2440_udc_debugfs_fops);  
  1761.         if (!udc->debug_info)  
  1762.             dev_warn(dev, "debugfs file creation failed\n");  
  1763.     }  
  1764. #endif  
  1765.   
  1766.     dev_dbg(dev, "probe ok\n");  
  1767.   
  1768.     return 0;  
  1769.   
  1770. err_int:  
  1771. #ifdef S3C2440_USE_IRQ  
  1772.     free_irq(udc->irq_num, udc);  
  1773. #endif  
  1774. err_map:  
  1775.     iounmap(udc->virl_addr);  
  1776. err_mem:  
  1777.     release_mem_region(res->start, res_size);  
  1778. err_clk_udc:  
  1779. #ifdef S3C2440_HAVE_CLK  
  1780.     clk_put(udc->s3c2440_clk_udc);  
  1781.     clk_disable(udc->s3c2440_clk_udc);  
  1782. #endif  
  1783. err_clk_upll:  
  1784. #ifdef S3C2440_HAVE_CLK  
  1785.     clk_put(udc->s3c2440_clk_upll);  
  1786.     clk_disable(udc->s3c2440_clk_upll);  
  1787. #endif  
  1788.   
  1789.     return retval;  
  1790. }  
  1791.   
  1792. static int s3c2440_udc_remove(struct platform_device *pdev)  
  1793. {  
  1794.     struct s3c2440_udc *udc = platform_get_drvdata(pdev);  
  1795.   
  1796.     dev_dbg(&pdev->dev, "%s()\n", __func__);  
  1797.   
  1798.     usb_del_gadget_udc(&udc->gadget);  
  1799.     if (udc->driver)  
  1800.         return -EBUSY;  
  1801.   
  1802. #ifdef S3C2440_DEBUG_FS  
  1803.     debugfs_remove(udc->debug_info);  
  1804. #endif  
  1805.   
  1806. #ifdef S3C2440_USE_IRQ  
  1807.     free_irq(udc->irq_num, udc);  
  1808. #endif  
  1809.   
  1810.     iounmap(udc->virl_addr);  
  1811.     release_mem_region(udc->phy_addr, udc->reg_size);  
  1812.   
  1813.     platform_set_drvdata(pdev, NULL);  
  1814.   
  1815. #ifdef S3C2440_HAVE_CLK  
  1816.     if (!IS_ERR(udc->s3c2440_clk_udc) && udc->s3c2440_clk_udc != NULL) {  
  1817.         clk_disable(udc->s3c2440_clk_udc);  
  1818.         clk_put(udc->s3c2440_clk_udc);  
  1819.         udc->s3c2440_clk_udc = NULL;  
  1820.     }  
  1821.   
  1822.     if (!IS_ERR(udc->s3c2440_clk_upll) && udc->s3c2440_clk_upll != NULL) {  
  1823.         clk_disable(udc->s3c2440_clk_upll);  
  1824.         clk_put(udc->s3c2440_clk_upll);  
  1825.         udc->s3c2440_clk_upll = NULL;  
  1826.     }  
  1827. #endif  
  1828.   
  1829.     dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);  
  1830.   
  1831.     return 0;  
  1832. }  
  1833.   
  1834. #ifdef CONFIG_PM  
  1835. static int s3c2440_udc_suspend(struct platform_device *pdev, pm_message_t message)  
  1836. {  
  1837.     return 0;  
  1838. }  
  1839.   
  1840. static int s3c2440_udc_resume(struct platform_device *pdev)  
  1841. {  
  1842.     return 0;  
  1843. }  
  1844. #else  
  1845. #define s3c2440_udc_suspend    NULL  
  1846. #define s3c2440_udc_resume    NULL  
  1847. #endif  
  1848.   
  1849. /***************************************************************/  
  1850.   
  1851. //有些设备可能用struct pci_driver,我就不考虑这么多了。  
  1852. static struct platform_driver udc_driver_s3c2440 = {  
  1853.     .driver        = {  
  1854.         .name    = "s3c2440-usbgadget",  
  1855.         .owner    = THIS_MODULE,  
  1856.     },  
  1857.     .probe        = s3c2440_udc_probe,  
  1858.     .remove        = __exit_p(s3c2440_udc_remove),  
  1859.     .suspend    = s3c2440_udc_suspend,  
  1860.     .resume        = s3c2440_udc_resume,  
  1861. };  
  1862.   
  1863.   
  1864. static int __init udc_init(void)  
  1865. {  
  1866.     int retval;  
  1867.   
  1868.     s3c2440_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);  
  1869.     if (IS_ERR(s3c2440_udc_debugfs_root)) {  
  1870.         printk(  "%s: debugfs dir creation failed %ld\n",  
  1871.             gadget_name, PTR_ERR(s3c2440_udc_debugfs_root));  
  1872.         s3c2440_udc_debugfs_root = NULL;  
  1873.     }  
  1874.   
  1875.     retval = platform_driver_register(&udc_driver_s3c2440);  
  1876.     if (retval)  
  1877.         goto err;  
  1878.   
  1879.     return 0;  
  1880.   
  1881. err:  
  1882.     debugfs_remove(s3c2440_udc_debugfs_root);  
  1883.     return retval;  
  1884. }  
  1885.   
  1886. static void __exit udc_exit(void)  
  1887. {  
  1888.     platform_driver_unregister(&udc_driver_s3c2440);  
  1889.     debugfs_remove(s3c2440_udc_debugfs_root);  
  1890. }  
  1891.   
  1892. module_init(udc_init);  
  1893. module_exit(udc_exit);  
  1894.   
  1895. MODULE_AUTHOR(DRIVER_AUTHOR);  
  1896. MODULE_DESCRIPTION(DRIVER_DESC);  
  1897. MODULE_VERSION(DRIVER_VERSION);  
  1898. MODULE_LICENSE("GPL");  

次我说的是三星平台的dma,不是三星的某款芯片的dma使用。这主要得益于三星公司统一了接口。比如我后有的例子是在s3c2440上做的但是我是参考s3c64xx的spi驱动。
当然内核还是linux-3.2.36,我们看dma-ops.h

[cpp] view plain copy
 
  1. /* arch/arm/plat-samsung/include/plat/dma-ops.h 
  2.  * 
  3.  * Copyright (c) 2011 Samsung Electronics Co., Ltd. 
  4.  *        http://www.samsung.com 
  5.  * 
  6.  * Samsung DMA support 
  7.  * 
  8.  * This program is free software; you can redistribute it and/or modify 
  9.  * it under the terms of the GNU General Public License version 2 as 
  10.  * published by the Free Software Foundation. 
  11.  */  
  12.   
  13. #ifndef __SAMSUNG_DMA_OPS_H_  
  14. #define __SAMSUNG_DMA_OPS_H_ __FILE__  
  15.   
  16. #include <linux/dmaengine.h>  
  17.   
  18. struct samsung_dma_prep_info {  
  19.     enum dma_transaction_type cap;//dma处理类型  
  20.     enum dma_data_direction direction;//dma传输方向  
  21.     dma_addr_t buf;//内存地址  
  22.     unsigned long period;//  
  23.     unsigned long len;//buf长度,sizeof(buf) * width,width在下面struct samsung_dma_info  
  24.     /* 
  25.     .c中调用 
  26.     int len = (info->cap == DMA_CYCLIC) ? info->period : info->len; 
  27.     ... 
  28.     我不是太清楚period和len区别 
  29.     */  
  30.     void (*fp)(void *data);//dma中断时会调用,一般作为dma传输完成的接口  
  31.     void *fp_param;//传入上面fp的参数  
  32. };  
  33.   
  34. struct samsung_dma_info {  
  35.     enum dma_transaction_type cap;//dma处理类型  
  36.     /* 
  37.             if (info->cap == DMA_CYCLIC) 
  38.                 s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);//chan->flags设置 
  39.     这个可能和芯片有点关系 
  40.     我的plat-s3c24xx中,通道请求函数 
  41.         if (chan->flags & S3C2410_DMAF_AUTOSTART) {//如果设置为自动运行,就调用start函数 
  42.             s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL, 
  43.                      S3C2410_DMAOP_START); 
  44.         } 
  45.     没有判断S3C2410_DMAF_CIRCULAR标志 
  46.     */  
  47.   
  48.     enum dma_data_direction direction;//dma传输方向  
  49.     enum dma_slave_buswidth width;//要传输的数据宽度,就是(字节、半字、字)  
  50.     dma_addr_t fifo;//外设地址  
  51.     struct s3c2410_dma_client *client;  
  52.     /* 
  53.     struct s3c2410_dma_client { 
  54.         char                *name; 
  55.     }; 
  56.     就是一个name,你申请通道时命名就可以了,主要dma中断注册是用、free通道时判断 
  57.     是不是正确通道 
  58.     */  
  59. };  
  60.   
  61. struct samsung_dma_ops {  
  62.     unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);//请求会有些限制  
  63.     //1.总是认为我们的外围设备是一个固定的地址  
  64.     //2.总是认为我们的内存地址增加  
  65.     //3.硬件触发  
  66.     //4.所有传输完成产生中断  
  67.     //上面这个从数据手册上看是可以设的,但是三星写的驱动代码没有选的可能  
  68.     int (*release)(unsigned ch, struct s3c2410_dma_client *client);//释放  
  69.     int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);//准备  
  70.     //准备会把内存数据加入链表中,如果有数据在传输,会打开再加载开关  
  71.     int (*trigger)(unsigned ch);//触发  
  72.     int (*started)(unsigned ch);//再次开始,实际就是再次载入数据  
  73.     int (*flush)(unsigned ch);//清除通道数据  
  74.     int (*stop)(unsigned ch);//停止  
  75. };  
  76.   
  77. extern void *samsung_dmadev_get_ops(void);  
  78. extern void *s3c_dma_get_ops(void);  
  79.   
  80. //去获取一个struct samsung_dma_ops全局变量,  
  81. //然后调用驱动,这个倒是给我们提供了一种驱动之间调用的方法  
  82. static inline void *__samsung_dma_get_ops(void)  
  83. {  
  84.     if (samsung_dma_is_dmadev())  
  85.         return samsung_dmadev_get_ops();  
  86.     else  
  87.         return s3c_dma_get_ops();  
  88. }  
  89.   
  90. /* 
  91.  * samsung_dma_get_ops 
  92.  * get the set of samsung dma operations 
  93.  */  
  94. //在驱动中调用这个  
  95. #define samsung_dma_get_ops() __samsung_dma_get_ops()  
  96.   
  97. #endif /* __SAMSUNG_DMA_OPS_H_ */  


如果你只是想看看应用接口,你可以在此打住,直接看《自娱自乐10》中dma使用的例子,增加你的理解。

 

如果你和我一样死脑筋,你可以看看下面的源码分析:主要有三个文件

下面这个文件,看的时候不要纠结,主要是为第二个通道使用的,知道就行。

 

[cpp] view plain copy
 
  1. /* linux/arch/arm/plat-samsung/dma.c 
  2.  * 
  3.  * Copyright (c) 2003-2009 Simtec Electronics 
  4.  *  Ben Dooks <ben@simtec.co.uk> 
  5.  *  http://armlinux.simtec.co.uk/ 
  6.  * 
  7.  * S3C DMA core 
  8.  * 
  9.  * This program is free software; you can redistribute it and/or modify 
  10.  * it under the terms of the GNU General Public License version 2 as 
  11.  * published by the Free Software Foundation. 
  12. */  
  13.   
  14. struct s3c2410_dma_buf;  
  15. /* 
  16. struct s3c2410_dma_buf { 
  17.         struct s3c2410_dma_buf  *next; 
  18.         int                      magic;         // magic  
  19.         int                      size;          // buffer size in bytes  
  20.         dma_addr_t               data;          // start of DMA data  
  21.         dma_addr_t               ptr;           // where the DMA got to [1]  
  22.         void                    *id;            // client's id  
  23. }; 
  24.  
  25. */  
  26.   
  27. #include <linux/kernel.h>  
  28. #include <linux/module.h>  
  29. #include <linux/errno.h>  
  30.   
  31. #include <mach/dma.h>  
  32. #include <mach/irqs.h>  
  33.   
  34. /* dma channel state information */  
  35. struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];  
  36. struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];  
  37.   
  38. /* s3c_dma_lookup_channel 
  39.  * 
  40.  * change the dma channel number given into a real dma channel id 
  41. */  
  42. //查找对应通道的struct s3c2410_dma_chan   
  43. //这个通道不是dma每个通道,是指外设对应的。  
  44. struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)  
  45. {  
  46.     if (channel & DMACH_LOW_LEVEL)  
  47.         return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];  
  48.     else  
  49.         return s3c_dma_chan_map[channel];  
  50. }  
  51.   
  52. /* do we need to protect the settings of the fields from 
  53.  * irq? 
  54. */  
  55.   
  56. int s3c2410_dma_set_opfn(enum dma_ch channel, s3c2410_dma_opfn_t rtn)  
  57. {  
  58.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  59.   
  60.     if (chan == NULL)  
  61.         return -EINVAL;  
  62.   
  63.     pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);  
  64.   
  65.     chan->op_fn = rtn;  
  66.     //从下面可以看出在开始和结束时会调用这个函数  
  67.   
  68.     return 0;  
  69. }  
  70. EXPORT_SYMBOL(s3c2410_dma_set_opfn);  
  71.   
  72. int s3c2410_dma_set_buffdone_fn(enum dma_ch channel, s3c2410_dma_cbfn_t rtn)  
  73. {  
  74.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  75.   
  76.     if (chan == NULL)  
  77.         return -EINVAL;  
  78.   
  79.     pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);  
  80.   
  81.     //在s3c2410_dma_flush和中断函数中调用  
  82.     chan->callback_fn = rtn;  
  83.   
  84.     return 0;  
  85. }  
  86. EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);  
  87.   
  88. //设置标志  
  89. int s3c2410_dma_setflags(enum dma_ch channel, unsigned int flags)  
  90. {  
  91.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  92.   
  93.     if (chan == NULL)  
  94.         return -EINVAL;  
  95.   
  96.     chan->flags = flags;  
  97.     return 0;  
  98. }  
  99. EXPORT_SYMBOL(s3c2410_dma_setflags);  


下面是plat-s3c24xx中的,应该只适用s3c24xx芯片

 

文件有点大,我提供一个看的方法

1. 看init函数。

2. 看request函数。

3. 看s3c2410_dma_ctrl,里面有停止、开始等。

4. 看中断函数。

5. 看电源管理。

[cpp] view plain copy
 
  1. /* linux/arch/arm/plat-s3c24xx/dma.c 
  2.  * 
  3.  * Copyright 2003-2006 Simtec Electronics 
  4.  *  Ben Dooks <ben@simtec.co.uk> 
  5.  * 
  6.  * S3C2410 DMA core 
  7.  * 
  8.  * http://armlinux.simtec.co.uk/ 
  9.  * 
  10.  * This program is free software; you can redistribute it and/or modify 
  11.  * it under the terms of the GNU General Public License version 2 as 
  12.  * published by the Free Software Foundation. 
  13. */  
  14.   
  15.   
  16. #ifdef CONFIG_S3C2410_DMA_DEBUG  
  17. #define DEBUG  
  18. #endif  
  19.   
  20. #include <linux/module.h>  
  21. #include <linux/init.h>  
  22. #include <linux/sched.h>  
  23. #include <linux/spinlock.h>  
  24. #include <linux/interrupt.h>  
  25. #include <linux/syscore_ops.h>  
  26. #include <linux/slab.h>  
  27. #include <linux/errno.h>  
  28. #include <linux/io.h>  
  29.   
  30. #include <asm/system.h>  
  31. #include <asm/irq.h>  
  32. #include <mach/hardware.h>  
  33. #include <mach/dma.h>  
  34. #include <mach/map.h>  
  35.   
  36. #include <plat/dma-s3c24xx.h>  
  37. #include <plat/regs-dma.h>  
  38.   
  39. /* io map for dma */  
  40. static void __iomem *dma_base;  
  41. static struct kmem_cache *dma_kmem;  
  42.   
  43. static int dma_channels;  
  44.   
  45. static struct s3c24xx_dma_selection dma_sel;  
  46.   
  47. //调试功能就不看了  
  48.   
  49. /* debugging functions */  
  50.   
  51. #define BUF_MAGIC (0xcafebabe)  
  52.   
  53. #define dmawarn(fmt...) printk(KERN_DEBUG fmt)  
  54.   
  55. #define dma_regaddr(chan, reg) ((chan)->regs + (reg))  
  56.   
  57. #if 1  
  58. #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))  
  59. #else  
  60. static inline void  
  61. dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)  
  62. {  
  63.     pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);  
  64.     writel(val, dma_regaddr(chan, reg));  
  65. }  
  66. #endif  
  67.   
  68. #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))  
  69.   
  70. /* captured register state for debug */  
  71.   
  72. struct s3c2410_dma_regstate {  
  73.     unsigned long         dcsrc; //源  
  74.     unsigned long         disrc; //目标  
  75.     unsigned long         dstat; //状态  
  76.     unsigned long         dcon;  //配置  
  77.     unsigned long         dmsktrig; //触发屏蔽  
  78. };  
  79.   
  80.   
  81. //下面还是调试,不看了  
  82. #ifdef CONFIG_S3C2410_DMA_DEBUG  
  83.   
  84. /* dmadbg_showregs 
  85.  * 
  86.  * simple debug routine to print the current state of the dma registers 
  87. */  
  88.   
  89. static void  
  90. dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)  
  91. {  
  92.     regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);  
  93.     regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);  
  94.     regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);  
  95.     regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);  
  96.     regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);  
  97. }  
  98.   
  99. static void  
  100. dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,  
  101.          struct s3c2410_dma_regstate *regs)  
  102. {  
  103.     printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",  
  104.            chan->number, fname, line,  
  105.            regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,  
  106.            regs->dcon);  
  107. }  
  108.   
  109. static void  
  110. dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)  
  111. {  
  112.     struct s3c2410_dma_regstate state;  
  113.   
  114.     dmadbg_capture(chan, &state);  
  115.   
  116.     printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",  
  117.            chan->number, fname, line, chan->load_state,  
  118.            chan->curr, chan->next, chan->end);  
  119.   
  120.     dmadbg_dumpregs(fname, line, chan, &state);  
  121. }  
  122.   
  123. static void  
  124. dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)  
  125. {  
  126.     struct s3c2410_dma_regstate state;  
  127.   
  128.     dmadbg_capture(chan, &state);  
  129.     dmadbg_dumpregs(fname, line, chan, &state);  
  130. }  
  131.   
  132. #define dbg_showregs(chan) dmadbg_showregs(__func__, __LINE__, (chan))  
  133. #define dbg_showchan(chan) dmadbg_showchan(__func__, __LINE__, (chan))  
  134. #else  
  135. #define dbg_showregs(chan) do { } while(0)  
  136. #define dbg_showchan(chan) do { } while(0)  
  137. #endif /* CONFIG_S3C2410_DMA_DEBUG */  
  138.   
  139. /* s3c2410_dma_stats_timeout 
  140.  * 
  141.  * Update DMA stats from timeout info 
  142. */  
  143. //记录dma传输用时  
  144. static void  
  145. s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)  
  146. {  
  147.     if (stats == NULL)  
  148.         return;  
  149.   
  150.     if (val > stats->timeout_longest)  
  151.         stats->timeout_longest = val;  
  152.     if (val < stats->timeout_shortest)  
  153.         stats->timeout_shortest = val;  
  154.   
  155.     stats->timeout_avg += val;  
  156. }  
  157.   
  158. /* s3c2410_dma_waitforload 
  159.  * 
  160.  * wait for the DMA engine to load a buffer, and update the state accordingly 
  161. */  
  162. //等待DMA引擎载入一个缓冲  
  163. static int  
  164. s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)  
  165. {  
  166.     int timeout = chan->load_timeout;//1 << 18  
  167.     int took;  
  168.   
  169.     if (chan->load_state != S3C2410_DMALOAD_1LOADED) {  
  170.         printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);  
  171.         return 0;  
  172.     }  
  173.   
  174.     if (chan->stats != NULL)  
  175.         chan->stats->loads++;//载入加一  
  176.   
  177.     while (--timeout > 0) {  
  178.         if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {//左移11位,如果等于0,就表示DMA控制器就绪且传输计数值为0  
  179.             took = chan->load_timeout - timeout;//已计时间  
  180.   
  181.             s3c2410_dma_stats_timeout(chan->stats, took);//在上面  
  182.   
  183.             switch (chan->load_state) {  
  184.             case S3C2410_DMALOAD_1LOADED:  
  185.                 chan->load_state = S3C2410_DMALOAD_1RUNNING;  
  186.                 break;  
  187.   
  188.             default:  
  189.                 printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);  
  190.             }  
  191.   
  192.             return 1;  
  193.         }  
  194.     }  
  195.   
  196.     if (chan->stats != NULL) {  
  197.         chan->stats->timeout_failed++;//超时,错误加一  
  198.     }  
  199.   
  200.     return 0;  
  201. }  
  202.   
  203. /* s3c2410_dma_loadbuffer 
  204.  * 
  205.  * load a buffer, and update the channel state 
  206. */  
  207. //载入  
  208. static inline int  
  209. s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,  
  210.                struct s3c2410_dma_buf *buf)  
  211. {  
  212.     unsigned long reload;  
  213.   
  214.     if (buf == NULL) {  
  215.         dmawarn("buffer is NULL\n");  
  216.         return -EINVAL;  
  217.     }  
  218.   
  219.     pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",  
  220.          buf, (unsigned long)buf->data, buf->size);  
  221.   
  222.     /* check the state of the channel before we do anything */  
  223.     //状态检查,并警告  
  224.     if (chan->load_state == S3C2410_DMALOAD_1LOADED) {//有一个载入  
  225.         dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");  
  226.     }  
  227.   
  228.     if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {//一个载入一个运行  
  229.         dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");  
  230.     }  
  231.   
  232.     /* it would seem sensible if we are the last buffer to not bother 
  233.      * with the auto-reload bit, so that the DMA engine will not try 
  234.      * and load another transfer after this one has finished... 
  235.      */  
  236.     if (chan->load_state == S3C2410_DMALOAD_NONE) {  
  237.         pr_debug("load_state is none, checking for noreload (next=%p)\n",  
  238.              buf->next);  
  239.         //next为空说明是最后一个,就不需要再次载入  
  240.         reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;  
  241.     } else {  
  242.         //pr_debug("load_state is %d => autoreload\n", chan->load_state);  
  243.         reload = S3C2410_DCON_AUTORELOAD;  
  244.     }  
  245.   
  246.     if ((buf->data & 0xf0000000) != 0x30000000) {//内存物理地址从0x30000000开始  
  247.         dmawarn("dmaload: buffer is %p\n", (void *)buf->data);  
  248.     }  
  249.   
  250.     writel(buf->data, chan->addr_reg);//数据写入  
  251.   
  252.     dma_wrreg(chan, S3C2410_DMA_DCON,  
  253.           chan->dcon | reload | (buf->size/chan->xfer_unit));//配置  
  254.   
  255.     chan->next = buf->next;  
  256.   
  257.     /* update the state of the channel */  
  258.   
  259.     switch (chan->load_state) {  
  260.     case S3C2410_DMALOAD_NONE:  
  261.         chan->load_state = S3C2410_DMALOAD_1LOADED;  
  262.         break;  
  263.   
  264.     case S3C2410_DMALOAD_1RUNNING:  
  265.         chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;  
  266.         break;  
  267.   
  268.     default:  
  269.         dmawarn("dmaload: unknown state %d in loadbuffer\n",  
  270.             chan->load_state);  
  271.         break;  
  272.     }  
  273.   
  274.     return 0;  
  275. }  
  276.   
  277. /* s3c2410_dma_call_op 
  278.  * 
  279.  * small routine to call the op routine with the given op if it has been 
  280.  * registered 
  281. */  
  282.   
  283. static void  
  284. s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)  
  285. {  
  286.     //通过s3c2410_dma_set_opfn函数赋值  
  287.     if (chan->op_fn != NULL) {  
  288.         (chan->op_fn)(chan, op);  
  289.     }  
  290. }  
  291.   
  292. /* s3c2410_dma_buffdone 
  293.  * 
  294.  * small wrapper to check if callback routine needs to be called, and 
  295.  * if so, call it 
  296. */  
  297.   
  298. static inline void  
  299. s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,  
  300.              enum s3c2410_dma_buffresult result)  
  301. {  
  302. #if 0  
  303.     pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",  
  304.          chan->callback_fn, buf, buf->id, buf->size, result);  
  305. #endif  
  306.   
  307.     if (chan->callback_fn != NULL) {  
  308.         (chan->callback_fn)(chan, buf->id, buf->size, result);  
  309.     }  
  310. }  
  311.   
  312. /* s3c2410_dma_start 
  313.  * 
  314.  * start a dma channel going 
  315. */  
  316.   
  317. static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)  
  318. {  
  319.     unsigned long tmp;  
  320.     unsigned long flags;  
  321.   
  322.     pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);  
  323.   
  324.     local_irq_save(flags);  
  325.   
  326.     if (chan->state == S3C2410_DMA_RUNNING) {  
  327.         pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);  
  328.         local_irq_restore(flags);  
  329.         return 0;  
  330.     }  
  331.   
  332.     //记录状态  
  333.     chan->state = S3C2410_DMA_RUNNING;  
  334.   
  335.     /* check wether there is anything to load, and if not, see 
  336.      * if we can find anything to load 
  337.      */  
  338.     //判断是否已载入载入  
  339.     if (chan->load_state == S3C2410_DMALOAD_NONE) {  
  340.         if (chan->next == NULL) {  
  341.             printk(KERN_ERR "dma%d: channel has nothing loaded\n",  
  342.                    chan->number);  
  343.             chan->state = S3C2410_DMA_IDLE;//没有可载入的state记为空闲  
  344.             local_irq_restore(flags);  
  345.             return -EINVAL;  
  346.         }  
  347.   
  348.         s3c2410_dma_loadbuffer(chan, chan->next);//载入缓存  
  349.     }  
  350.   
  351.     dbg_showchan(chan);//调试信息  
  352.   
  353.     /* enable the channel */  
  354.   
  355.     if (!chan->irq_enabled) {  
  356.         enable_irq(chan->irq);//如果中断关闭,开启中断  
  357.         chan->irq_enabled = 1;  
  358.     }  
  359.   
  360.     /* start the channel going */  
  361.   
  362.     tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);  
  363.     tmp &= ~S3C2410_DMASKTRIG_STOP;  
  364.     tmp |= S3C2410_DMASKTRIG_ON;  
  365.     dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);//开始运行  
  366.   
  367.     pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);  
  368.   
  369. #if 0  
  370.     /* the dma buffer loads should take care of clearing the AUTO 
  371.      * reloading feature */  
  372.     tmp = dma_rdreg(chan, S3C2410_DMA_DCON);  
  373.     tmp &= ~S3C2410_DCON_NORELOAD;  
  374.     dma_wrreg(chan, S3C2410_DMA_DCON, tmp);  
  375. #endif  
  376.   
  377.     s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);//回调  
  378.   
  379.     dbg_showchan(chan);  
  380.   
  381.     /* if we've only loaded one buffer onto the channel, then chec 
  382.      * to see if we have another, and if so, try and load it so when 
  383.      * the first buffer is finished, the new one will be loaded onto 
  384.      * the channel */  
  385.   
  386.     if (chan->next != NULL) {  
  387.         if (chan->load_state == S3C2410_DMALOAD_1LOADED) {//已有一个正在载入  
  388.   
  389.             if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {//等待...  
  390.                 pr_debug("%s: buff not yet loaded, no more todo\n",  
  391.                      __func__);  
  392.             } else {  
  393.                 //这里还有下面的,可以看出在s3c2410_dma_loadbuffer中  
  394.                 //S3C2410_DMALOAD_1RUNNING会使用AUTORELOAD模式  
  395.                 chan->load_state = S3C2410_DMALOAD_1RUNNING;  
  396.                 s3c2410_dma_loadbuffer(chan, chan->next);  
  397.             }  
  398.   
  399.         } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {  
  400.             s3c2410_dma_loadbuffer(chan, chan->next);  
  401.         }  
  402.     }  
  403.   
  404.   
  405.     local_irq_restore(flags);  
  406.   
  407.     return 0;  
  408. }  
  409.   
  410. /* s3c2410_dma_canload 
  411.  * 
  412.  * work out if we can queue another buffer into the DMA engine 
  413. */  
  414.   
  415. static int  
  416. s3c2410_dma_canload(struct s3c2410_dma_chan *chan)  
  417. {  
  418.     if (chan->load_state == S3C2410_DMALOAD_NONE ||  
  419.         chan->load_state == S3C2410_DMALOAD_1RUNNING)  
  420.         return 1;  
  421.   
  422.     return 0;  
  423. }  
  424.   
  425. /* s3c2410_dma_enqueue 
  426.  * 
  427.  * queue an given buffer for dma transfer. 
  428.  * 
  429.  * id         the device driver's id information for this buffer 
  430.  * data       the physical address of the buffer data 
  431.  * size       the size of the buffer in bytes 
  432.  * 
  433.  * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART 
  434.  * is checked, and if set, the channel is started. If this flag isn't set, 
  435.  * then an error will be returned. 
  436.  * 
  437.  * It is possible to queue more than one DMA buffer onto a channel at 
  438.  * once, and the code will deal with the re-loading of the next buffer 
  439.  * when necessary. 
  440. */  
  441. //把数据加入链表  
  442. int s3c2410_dma_enqueue(unsigned int channel, void *id,  
  443.             dma_addr_t data, int size)  
  444. {  
  445.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  446.     struct s3c2410_dma_buf *buf;  
  447.     unsigned long flags;  
  448.   
  449.     if (chan == NULL)  
  450.         return -EINVAL;  
  451.   
  452.     pr_debug("%s: id=%p, data=%08x, size=%d\n",  
  453.          __func__, id, (unsigned int)data, size);  
  454.   
  455.     buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);//申请内存  
  456.     if (buf == NULL) {  
  457.         pr_debug("%s: out of memory (%ld alloc)\n",  
  458.              __func__, (long)sizeof(*buf));  
  459.         return -ENOMEM;  
  460.     }  
  461.   
  462.     //pr_debug("%s: new buffer %p\n", __func__, buf);  
  463.     //dbg_showchan(chan);  
  464.   
  465.     //给buf赋值  
  466.     buf->next  = NULL;  
  467.     buf->data  = buf->ptr = data;  
  468.     buf->size  = size;  
  469.     buf->id    = id;  
  470.     buf->magic = BUF_MAGIC;  
  471.   
  472.     local_irq_save(flags);  
  473.   
  474.     //chan->curr赋值并把buf加入链表中  
  475.     if (chan->curr == NULL) {  
  476.         /* we've got nothing loaded... */  
  477.         pr_debug("%s: buffer %p queued onto empty channel\n",  
  478.              __func__, buf);  
  479.   
  480.         chan->curr = buf;  
  481.         chan->end  = buf;  
  482.         chan->next = NULL;  
  483.     } else {  
  484.         pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",  
  485.              chan->number, __func__, buf);  
  486.   
  487.         if (chan->end == NULL)  
  488.             pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",  
  489.                  chan->number, __func__, chan);  
  490.   
  491.         chan->end->next = buf;  
  492.         chan->end = buf;  
  493.     }  
  494.   
  495.     /* if necessary, update the next buffer field */  
  496.     if (chan->next == NULL)  
  497.         chan->next = buf;  
  498.   
  499.     /* check to see if we can load a buffer */  
  500.     if (chan->state == S3C2410_DMA_RUNNING) {  
  501.         if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {//当前是否有一个在传输  
  502.             if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {//等待  
  503.                 printk(KERN_ERR "dma%d: loadbuffer:"  
  504.                        "timeout loading buffer\n",  
  505.                        chan->number);  
  506.                 dbg_showchan(chan);  
  507.                 local_irq_restore(flags);  
  508.                 return -EINVAL;  
  509.             }  
  510.         }  
  511.   
  512.         while (s3c2410_dma_canload(chan) && chan->next != NULL) {//可加载且chan->next不为空  
  513.             s3c2410_dma_loadbuffer(chan, chan->next);  
  514.         }  
  515.     } else if (chan->state == S3C2410_DMA_IDLE) {  
  516.         if (chan->flags & S3C2410_DMAF_AUTOSTART) {//如果设置为自动运行,就调用start函数  
  517.             s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,  
  518.                      S3C2410_DMAOP_START);  
  519.         }  
  520.     }  
  521.   
  522.     local_irq_restore(flags);  
  523.     return 0;  
  524. }  
  525.   
  526. EXPORT_SYMBOL(s3c2410_dma_enqueue);  
  527.   
  528. static inline void  
  529. s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)  
  530. {  
  531.     int magicok = (buf->magic == BUF_MAGIC);  
  532.   
  533.     buf->magic = -1;  
  534.   
  535.     if (magicok) {  
  536.         kmem_cache_free(dma_kmem, buf);  
  537.     } else {  
  538.         printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);  
  539.     }  
  540. }  
  541.   
  542. /* s3c2410_dma_lastxfer 
  543.  * 
  544.  * called when the system is out of buffers, to ensure that the channel 
  545.  * is prepared for shutdown. 
  546. */  
  547.   
  548. static inline void  
  549. s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)  
  550. {  
  551. #if 0  
  552.     pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",  
  553.          chan->number, chan->load_state);  
  554. #endif  
  555.   
  556.     switch (chan->load_state) {  
  557.     case S3C2410_DMALOAD_NONE:  
  558.         break;  
  559.   
  560.     case S3C2410_DMALOAD_1LOADED:  
  561.         if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {  
  562.                 /* flag error? */  
  563.             printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",  
  564.                    chan->number, __func__);  
  565.             return;  
  566.         }  
  567.         break;  
  568.   
  569.     case S3C2410_DMALOAD_1LOADED_1RUNNING:  
  570.         /* I believe in this case we do not have anything to do 
  571.          * until the next buffer comes along, and we turn off the 
  572.          * reload */  
  573.         return;  
  574.   
  575.     default:  
  576.         pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",  
  577.              chan->number, chan->load_state);  
  578.         return;  
  579.   
  580.     }  
  581.   
  582.     /* hopefully this'll shut the damned thing up after the transfer... */  
  583.     dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);  
  584. }  
  585.   
  586.   
  587. #define dmadbg2(x...)  
  588.   
  589. static irqreturn_t  
  590. s3c2410_dma_irq(int irq, void *devpw)  
  591. {  
  592.     struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;  
  593.     struct s3c2410_dma_buf  *buf;  
  594.   
  595.     buf = chan->curr;  
  596.   
  597.     dbg_showchan(chan);  
  598.   
  599.     /* modify the channel state */  
  600.     //更新状态  
  601.     switch (chan->load_state) {  
  602.     case S3C2410_DMALOAD_1RUNNING:  
  603.         /* TODO - if we are running only one buffer, we probably 
  604.          * want to reload here, and then worry about the buffer 
  605.          * callback */  
  606.           
  607.         chan->load_state = S3C2410_DMALOAD_NONE;  
  608.         break;  
  609.   
  610.     case S3C2410_DMALOAD_1LOADED:  
  611.         /* iirc, we should go back to NONE loaded here, we 
  612.          * had a buffer, and it was never verified as being 
  613.          * loaded. 
  614.          */  
  615.   
  616.         chan->load_state = S3C2410_DMALOAD_NONE;  
  617.         break;  
  618.   
  619.     case S3C2410_DMALOAD_1LOADED_1RUNNING:  
  620.         /* we'll worry about checking to see if another buffer is 
  621.          * ready after we've called back the owner. This should 
  622.          * ensure we do not wait around too long for the DMA 
  623.          * engine to start the next transfer 
  624.          */  
  625.   
  626.         chan->load_state = S3C2410_DMALOAD_1LOADED;  
  627.         break;  
  628.   
  629.     case S3C2410_DMALOAD_NONE:  
  630.         printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",  
  631.                chan->number);  
  632.         break;  
  633.   
  634.     default:  
  635.         printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",  
  636.                chan->number, chan->load_state);  
  637.         break;  
  638.     }  
  639.   
  640.     if (buf != NULL) {  
  641.         /* update the chain to make sure that if we load any more 
  642.          * buffers when we call the callback function, things should 
  643.          * work properly */  
  644.   
  645.         //更新链表  
  646.         chan->curr = buf->next;  
  647.         buf->next  = NULL;  
  648.   
  649.         if (buf->magic != BUF_MAGIC) {  
  650.             printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",  
  651.                    chan->number, __func__, buf);  
  652.             return IRQ_HANDLED;  
  653.         }  
  654.   
  655.         s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);//回调,使一些事情工作正常  
  656.   
  657.         /* free resouces */  
  658.         s3c2410_dma_freebuf(buf);//释放空间  
  659.     } else {  
  660.     }  
  661.   
  662.     /* only reload if the channel is still running... our buffer done 
  663.      * routine may have altered the state by requesting the dma channel 
  664.      * to stop or shutdown... */  
  665.   
  666.     /* todo: check that when the channel is shut-down from inside this 
  667.      * function, we cope with unsetting reload, etc */  
  668.   
  669.     if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {  
  670.         unsigned long flags;  
  671.   
  672.         switch (chan->load_state) {  
  673.         case S3C2410_DMALOAD_1RUNNING:  
  674.             /* don't need to do anything for this state */  
  675.             break;  
  676.   
  677.         case S3C2410_DMALOAD_NONE:  
  678.             /* can load buffer immediately */  
  679.             break;  
  680.   
  681.         case S3C2410_DMALOAD_1LOADED:  
  682.             if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {//等待传输完  
  683.                 /* flag error? */  
  684.                 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",  
  685.                        chan->number, __func__);  
  686.                 return IRQ_HANDLED;  
  687.             }  
  688.   
  689.             break;  
  690.   
  691.         case S3C2410_DMALOAD_1LOADED_1RUNNING:  
  692.             goto no_load;  
  693.   
  694.         default:  
  695.             printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",  
  696.                    chan->number, chan->load_state);  
  697.             return IRQ_HANDLED;  
  698.         }  
  699.   
  700.         local_irq_save(flags);  
  701.         s3c2410_dma_loadbuffer(chan, chan->next);//再次载入  
  702.         local_irq_restore(flags);  
  703.     } else {  
  704.         s3c2410_dma_lastxfer(chan);//最后一个缓冲区  
  705.   
  706.         /* see if we can stop this channel.. */  
  707.         if (chan->load_state == S3C2410_DMALOAD_NONE) {  
  708.             pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",  
  709.                  chan->number, jiffies);  
  710.             s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,  
  711.                      S3C2410_DMAOP_STOP);//停止  
  712.         }  
  713.     }  
  714.   
  715.  no_load:  
  716.     return IRQ_HANDLED;  
  717. }  
  718.   
  719. static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);  
  720.   
  721. /* s3c2410_request_dma 
  722.  * 
  723.  * get control of an dma channel 
  724. */  
  725. //获取一个dma通道  
  726. //下面你会看到,获取一个通道信息并注册中断  
  727. int s3c2410_dma_request(enum dma_ch channel,  
  728.             struct s3c2410_dma_client *client,  
  729.             void *dev)  
  730. {  
  731.     struct s3c2410_dma_chan *chan;  
  732.     unsigned long flags;  
  733.     int err;  
  734.   
  735.     pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",  
  736.          channel, client->name, dev);  
  737.   
  738.     local_irq_save(flags);  
  739.   
  740.     //请求一个通道,下面有详细说明  
  741.     chan = s3c2410_dma_map_channel(channel);  
  742.     if (chan == NULL) {  
  743.         local_irq_restore(flags);  
  744.         return -EBUSY;  
  745.     }  
  746.   
  747.     dbg_showchan(chan);  
  748.   
  749.     chan->client = client;  
  750.     chan->in_use = 1;//标志为使用  
  751.   
  752.     if (!chan->irq_claimed) {  
  753.         pr_debug("dma%d: %s : requesting irq %d\n",  
  754.              channel, __func__, chan->irq);  
  755.   
  756.         chan->irq_claimed = 1;//中断声明标志为1  
  757.         local_irq_restore(flags);  
  758.   
  759.         err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,  
  760.                   client->name, (void *)chan);  
  761.   
  762.         local_irq_save(flags);  
  763.   
  764.         if (err) {  
  765.             chan->in_use = 0;  
  766.             chan->irq_claimed = 0;  
  767.             local_irq_restore(flags);  
  768.   
  769.             printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",  
  770.                    client->name, chan->irq, chan->number);  
  771.             return err;  
  772.         }  
  773.   
  774.         chan->irq_enabled = 1;  
  775.     }  
  776.   
  777.     local_irq_restore(flags);  
  778.   
  779.     /* need to setup */  
  780.   
  781.     pr_debug("%s: channel initialised, %p\n", __func__, chan);  
  782.   
  783.     return chan->number | DMACH_LOW_LEVEL;  
  784. }  
  785.   
  786. EXPORT_SYMBOL(s3c2410_dma_request);  
  787.   
  788. /* s3c2410_dma_free 
  789.  * 
  790.  * release the given channel back to the system, will stop and flush 
  791.  * any outstanding transfers, and ensure the channel is ready for the 
  792.  * next claimant. 
  793.  * 
  794.  * Note, although a warning is currently printed if the freeing client 
  795.  * info is not the same as the registrant's client info, the free is still 
  796.  * allowed to go through. 
  797. */  
  798.   
  799. int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)  
  800. {  
  801.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  802.     unsigned long flags;  
  803.   
  804.     if (chan == NULL)  
  805.         return -EINVAL;  
  806.   
  807.     local_irq_save(flags);  
  808.   
  809.     if (chan->client != client) {//检查是否为正确通道  
  810.         printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",  
  811.                channel, chan->client, client);  
  812.     }  
  813.   
  814.     /* sort out stopping and freeing the channel */  
  815.   
  816.     if (chan->state != S3C2410_DMA_IDLE) {  
  817.         pr_debug("%s: need to stop dma channel %p\n",  
  818.                __func__, chan);  
  819.   
  820.         /* possibly flush the channel */  
  821.         s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);//不是空闲,就停止通道  
  822.     }  
  823.   
  824.     chan->client = NULL;  
  825.     chan->in_use = 0;  
  826.   
  827.     if (chan->irq_claimed)  
  828.         free_irq(chan->irq, (void *)chan);//如果注册的中断就释放  
  829.   
  830.     chan->irq_claimed = 0;  
  831.   
  832.     if (!(channel & DMACH_LOW_LEVEL))  
  833.         s3c_dma_chan_map[channel] = NULL;//对应的数据置空  
  834.   
  835.     local_irq_restore(flags);  
  836.   
  837.     return 0;  
  838. }  
  839.   
  840. EXPORT_SYMBOL(s3c2410_dma_free);  
  841.   
  842. static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)  
  843. {  
  844.     unsigned long flags;  
  845.     unsigned long tmp;  
  846.   
  847.     pr_debug("%s:\n", __func__);  
  848.   
  849.     dbg_showchan(chan);//调试不看了  
  850.   
  851.     local_irq_save(flags);  
  852.   
  853.     s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);  
  854.     //(chan->op_fn)(chan, op); 回调函数  
  855.   
  856.     tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);//读对应通道的寄存器  
  857.     tmp |= S3C2410_DMASKTRIG_STOP;//DMASKTRIG的第2位是STOP  
  858.     //tmp &= ~S3C2410_DMASKTRIG_ON;  
  859.     dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);  
  860.   
  861. #if 0 //为了适合WinCE,关闭再加载  
  862.     /* should also clear interrupts, according to WinCE BSP */  
  863.     tmp = dma_rdreg(chan, S3C2410_DMA_DCON);  
  864.     tmp |= S3C2410_DCON_NORELOAD;  
  865.     dma_wrreg(chan, S3C2410_DMA_DCON, tmp);  
  866. #endif  
  867.   
  868.     /* should stop do this, or should we wait for flush? */  
  869.     chan->state      = S3C2410_DMA_IDLE;//dma状态  
  870.     chan->load_state = S3C2410_DMALOAD_NONE;//dma数据传输状态  
  871.   
  872.     local_irq_restore(flags);  
  873.   
  874.     return 0;  
  875. }  
  876.   
  877. static void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)  
  878. {  
  879.     unsigned long tmp;  
  880.     unsigned int timeout = 0x10000;  
  881.   
  882.     while (timeout-- > 0) {  
  883.         tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);  
  884.   
  885.         if (!(tmp & S3C2410_DMASKTRIG_ON))//判断DMASKTRIG寄存器第1位是否为0  
  886.             return;  
  887.     }  
  888.   
  889.     pr_debug("dma%d: failed to stop?\n", chan->number);  
  890. }  
  891.   
  892.   
  893. /* s3c2410_dma_flush 
  894.  * 
  895.  * stop the channel, and remove all current and pending transfers 
  896. */  
  897. //停止通道,并移除当前和即将发生的传输  
  898. static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)  
  899. {  
  900.     struct s3c2410_dma_buf *buf, *next;  
  901.     unsigned long flags;  
  902.   
  903.     pr_debug("%s: chan %p (%d)\n", __func__, chan, chan->number);  
  904.   
  905.     dbg_showchan(chan);  
  906.   
  907.     local_irq_save(flags);  
  908.   
  909.     if (chan->state != S3C2410_DMA_IDLE) {  
  910.         pr_debug("%s: stopping channel...\n", __func__ );  
  911.         //不是空闲,调用s3c2410_dma_dostop  
  912.         s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);  
  913.     }  
  914.   
  915.     buf = chan->curr;  
  916.     if (buf == NULL)  
  917.         buf = chan->next;  
  918.   
  919.     //清除数据  
  920.     chan->curr = chan->next = chan->end = NULL;  
  921.   
  922.     //释放空间  
  923.     if (buf != NULL) {  
  924.         for ( ; buf != NULL; buf = next) {  
  925.             next = buf->next;  
  926.   
  927.             pr_debug("%s: free buffer %p, next %p\n",  
  928.                    __func__, buf, buf->next);  
  929.   
  930.             s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);//回调函数调用  
  931.             s3c2410_dma_freebuf(buf);//就是调用kmem_cache_free释放  
  932.         }  
  933.     }  
  934.   
  935.     dbg_showregs(chan);  
  936.   
  937.     s3c2410_dma_waitforstop(chan);//等待停止  
  938.   
  939. #if 0  
  940.     /* should also clear interrupts, according to WinCE BSP */  
  941.     {  
  942.         unsigned long tmp;  
  943.   
  944.         tmp = dma_rdreg(chan, S3C2410_DMA_DCON);  
  945.         tmp |= S3C2410_DCON_NORELOAD;  
  946.         dma_wrreg(chan, S3C2410_DMA_DCON, tmp);  
  947.     }  
  948. #endif  
  949.   
  950.     dbg_showregs(chan);  
  951.   
  952.     local_irq_restore(flags);  
  953.   
  954.     return 0;  
  955. }  
  956.   
  957. static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)  
  958. {  
  959.     unsigned long flags;  
  960.   
  961.     local_irq_save(flags);  
  962.   
  963.     dbg_showchan(chan);  
  964.   
  965.     /* if we've only loaded one buffer onto the channel, then chec 
  966.      * to see if we have another, and if so, try and load it so when 
  967.      * the first buffer is finished, the new one will be loaded onto 
  968.      * the channel */  
  969.   
  970.     //下面的判断可以查看s3c2410_dma_start()  
  971.     if (chan->next != NULL) {  
  972.         if (chan->load_state == S3C2410_DMALOAD_1LOADED) {  
  973.   
  974.             if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {  
  975.                 pr_debug("%s: buff not yet loaded, no more todo\n",  
  976.                      __func__);  
  977.             } else {  
  978.                 chan->load_state = S3C2410_DMALOAD_1RUNNING;  
  979.                 s3c2410_dma_loadbuffer(chan, chan->next);  
  980.             }  
  981.   
  982.         } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {  
  983.             s3c2410_dma_loadbuffer(chan, chan->next);  
  984.         }  
  985.     }  
  986.   
  987.   
  988.     local_irq_restore(flags);  
  989.   
  990.     return 0;  
  991.   
  992. }  
  993.   
  994. //dma 控制函数  
  995. int  
  996. s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)  
  997. {  
  998.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  999.   
  1000.     if (chan == NULL)  
  1001.         return -EINVAL;  
  1002.   
  1003.     switch (op) {  
  1004.     case S3C2410_DMAOP_START://开始  
  1005.         return s3c2410_dma_start(chan);  
  1006.   
  1007.     case S3C2410_DMAOP_STOP://停止  
  1008.         return s3c2410_dma_dostop(chan);  
  1009.   
  1010.     case S3C2410_DMAOP_PAUSE://暂停  
  1011.     case S3C2410_DMAOP_RESUME:  
  1012.         return -ENOENT;  
  1013.   
  1014.     case S3C2410_DMAOP_FLUSH://冲掉  
  1015.         return s3c2410_dma_flush(chan);  
  1016.   
  1017.     case S3C2410_DMAOP_STARTED://再次开始  
  1018.         return s3c2410_dma_started(chan);  
  1019.   
  1020.     case S3C2410_DMAOP_TIMEOUT://超时  
  1021.         return 0;  
  1022.   
  1023.     }  
  1024.   
  1025.     return -ENOENT;      /* unknown, don't bother */  
  1026. }  
  1027.   
  1028. EXPORT_SYMBOL(s3c2410_dma_ctrl);  
  1029.   
  1030. /* DMA configuration for each channel 
  1031.  * 
  1032.  * DISRCC -> source of the DMA (AHB,APB) 
  1033.  * DISRC  -> source address of the DMA 
  1034.  * DIDSTC -> destination of the DMA (AHB,APD) 
  1035.  * DIDST  -> destination address of the DMA 
  1036. */  
  1037.   
  1038. /* s3c2410_dma_config 
  1039.  * 
  1040.  * xfersize:     size of unit in bytes (1,2,4) 
  1041. */  
  1042.   
  1043. int s3c2410_dma_config(enum dma_ch channel,  
  1044.                int xferunit)  
  1045. {  
  1046.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  1047.     unsigned int dcon;  
  1048.   
  1049.     pr_debug("%s: chan=%d, xfer_unit=%d\n", __func__, channel, xferunit);  
  1050.   
  1051.     if (chan == NULL)  
  1052.         return -EINVAL;  
  1053.   
  1054.     dcon = chan->dcon & dma_sel.dcon_mask;  
  1055.     pr_debug("%s: dcon is %08x\n", __func__, dcon);  
  1056.   
  1057.     //DCON寄存器的24~26位选择请求源  
  1058.     switch (chan->req_ch) {  
  1059.     case DMACH_I2S_IN:  
  1060.     case DMACH_I2S_OUT:  
  1061.     case DMACH_PCM_IN:  
  1062.     case DMACH_PCM_OUT:  
  1063.     case DMACH_MIC_IN:  
  1064.     default:  
  1065.         dcon |= S3C2410_DCON_HANDSHAKE;  
  1066.         dcon |= S3C2410_DCON_SYNC_PCLK;  
  1067.         break;  
  1068.   
  1069.     case DMACH_SDI:  
  1070.         /* note, ensure if need HANDSHAKE or not */  
  1071.         dcon |= S3C2410_DCON_SYNC_PCLK;  
  1072.         break;  
  1073.   
  1074.     case DMACH_XD0:  
  1075.     case DMACH_XD1:  
  1076.         dcon |= S3C2410_DCON_HANDSHAKE;  
  1077.         dcon |= S3C2410_DCON_SYNC_HCLK;  
  1078.         break;  
  1079.     }  
  1080.     //上面的HANDSHAKE是选择握手模式  
  1081.     //除了SDI要选,其他的都是握手模式,chan->dcon来记录你的dcon的配置  
  1082.   
  1083.     //传输大小  
  1084.     switch (xferunit) {  
  1085.     case 1:  
  1086.         dcon |= S3C2410_DCON_BYTE;  
  1087.         break;  
  1088.   
  1089.     case 2:  
  1090.         dcon |= S3C2410_DCON_HALFWORD;  
  1091.         break;  
  1092.   
  1093.     case 4:  
  1094.         dcon |= S3C2410_DCON_WORD;  
  1095.         break;  
  1096.   
  1097.     default:  
  1098.         pr_debug("%s: bad transfer size %d\n", __func__, xferunit);  
  1099.         return -EINVAL;  
  1100.     }  
  1101.   
  1102.     dcon |= S3C2410_DCON_HWTRIG;//硬件触发  
  1103.     dcon |= S3C2410_DCON_INTREQ;//所有传输完成产生中断  
  1104.   
  1105.     pr_debug("%s: dcon now %08x\n", __func__, dcon);  
  1106.   
  1107.     //记录下配置  
  1108.     chan->dcon = dcon;  
  1109.     chan->xfer_unit = xferunit;  
  1110.   
  1111.     return 0;  
  1112. }  
  1113.   
  1114. EXPORT_SYMBOL(s3c2410_dma_config);  
  1115.   
  1116.   
  1117. /* s3c2410_dma_devconfig 
  1118.  * 
  1119.  * configure the dma source/destination hardware type and address 
  1120.  * 
  1121.  * source:    DMA_FROM_DEVICE: source is hardware 
  1122.  *            DMA_TO_DEVICE: source is memory 
  1123.  * 
  1124.  * devaddr:   physical address of the source 
  1125. */  
  1126.   
  1127. int s3c2410_dma_devconfig(enum dma_ch channel,  
  1128.               enum dma_data_direction source,  
  1129.               unsigned long devaddr)  
  1130. {  
  1131.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  1132.     unsigned int hwcfg;  
  1133.   
  1134.     if (chan == NULL)  
  1135.         return -EINVAL;  
  1136.   
  1137.     pr_debug("%s: source=%d, devaddr=%08lx\n",  
  1138.          __func__, (int)source, devaddr);  
  1139.   
  1140.     chan->source = source;//源类型,内存或者硬件  
  1141.     chan->dev_addr = devaddr;//  
  1142.   
  1143.     switch (chan->req_ch) {  
  1144.     case DMACH_XD0:  
  1145.     case DMACH_XD1:  
  1146.         hwcfg = 0; /* AHB */  
  1147.         break;  
  1148.   
  1149.     default:  
  1150.         hwcfg = S3C2410_DISRCC_APB;  
  1151.     }  
  1152.     //除了XD0和XD1在AHB总线上,其他都是APB  
  1153.   
  1154.     /* always assume our peripheral desintation is a fixed 
  1155.      * address in memory. */  
  1156.     //总是认为我们的外围设备是一个固定的地址  
  1157.     hwcfg |= S3C2410_DISRCC_INC;//在传输后地址不改变  
  1158.   
  1159.     switch (source) {  
  1160.     case DMA_FROM_DEVICE://源是硬件  
  1161.         /* source is hardware */  
  1162.         pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",  
  1163.              __func__, devaddr, hwcfg);  
  1164.         dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);//源控制  
  1165.         dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);//源地址  
  1166.         dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));//目标控制:系统总线,地址增加  
  1167.   
  1168.         chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);//记下内存地址  
  1169.         break;  
  1170.   
  1171.     case DMA_TO_DEVICE://源是内存  
  1172.         /* source is memory */  
  1173.         pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",  
  1174.              __func__, devaddr, hwcfg);  
  1175.         dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));//源:系统总线,地址增加  
  1176.         dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);//目标地址地址  
  1177.         dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);//目标控制  
  1178.   
  1179.         chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);//记下内存地址  
  1180.         break;  
  1181.   
  1182.     default:  
  1183.         printk(KERN_ERR "dma%d: invalid source type (%d)\n",  
  1184.                channel, source);  
  1185.   
  1186.         return -EINVAL;  
  1187.     }  
  1188.   
  1189.     if (dma_sel.direction != NULL)//s3c2440为空  
  1190.         (dma_sel.direction)(chan, chan->map, source);  
  1191.   
  1192.     return 0;  
  1193. }  
  1194.   
  1195. EXPORT_SYMBOL(s3c2410_dma_devconfig);  
  1196.   
  1197. /* s3c2410_dma_getposition 
  1198.  * 
  1199.  * returns the current transfer points for the dma source and destination 
  1200. */  
  1201.   
  1202. //当前源或目标地址  
  1203. int s3c2410_dma_getposition(enum dma_ch channel, dma_addr_t *src, dma_addr_t *dst)  
  1204. {  
  1205.     struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);  
  1206.   
  1207.     if (chan == NULL)  
  1208.         return -EINVAL;  
  1209.   
  1210.     if (src != NULL)  
  1211.         *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);  
  1212.   
  1213.     if (dst != NULL)  
  1214.         *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);  
  1215.   
  1216.     return 0;  
  1217. }  
  1218.   
  1219. EXPORT_SYMBOL(s3c2410_dma_getposition);  
  1220.   
  1221. /* system core operations */  
  1222.   
  1223. #ifdef CONFIG_PM  
  1224.   
  1225. static void s3c2410_dma_suspend_chan(struct s3c2410_dma_chan *cp)  
  1226. {  
  1227.     printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);  
  1228.   
  1229.     if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {  
  1230.         /* the dma channel is still working, which is probably 
  1231.          * a bad thing to do over suspend/resume. We stop the 
  1232.          * channel and assume that the client is either going to 
  1233.          * retry after resume, or that it is broken. 
  1234.          */  
  1235.   
  1236.         printk(KERN_INFO "dma: stopping channel %d due to suspend\n",  
  1237.                cp->number);  
  1238.   
  1239.         s3c2410_dma_dostop(cp);  
  1240.     }  
  1241. }  
  1242.   
  1243. static int s3c2410_dma_suspend(void)  
  1244. {  
  1245.     struct s3c2410_dma_chan *cp = s3c2410_chans;  
  1246.     int channel;  
  1247.   
  1248.     for (channel = 0; channel < dma_channels; cp++, channel++)  
  1249.         s3c2410_dma_suspend_chan(cp);  
  1250.   
  1251.     return 0;  
  1252. }  
  1253.   
  1254. static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp)  
  1255. {  
  1256.     unsigned int no = cp->number | DMACH_LOW_LEVEL;  
  1257.   
  1258.     /* restore channel's hardware configuration */  
  1259.   
  1260.     if (!cp->in_use)  
  1261.         return;  
  1262.   
  1263.     printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);  
  1264.   
  1265.     s3c2410_dma_config(no, cp->xfer_unit);  
  1266.     s3c2410_dma_devconfig(no, cp->source, cp->dev_addr);  
  1267.   
  1268.     /* re-select the dma source for this channel */  
  1269.   
  1270.     if (cp->map != NULL)  
  1271.         dma_sel.select(cp, cp->map);  
  1272. }  
  1273.   
  1274. static void s3c2410_dma_resume(void)  
  1275. {  
  1276.     struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1;  
  1277.     int channel;  
  1278.   
  1279.     for (channel = dma_channels - 1; channel >= 0; cp++, channel--)  
  1280.         s3c2410_dma_resume_chan(cp);  
  1281. }  
  1282.   
  1283. #else  
  1284. #define s3c2410_dma_suspend NULL  
  1285. #define s3c2410_dma_resume  NULL  
  1286. #endif /* CONFIG_PM */  
  1287.   
  1288. /* 
  1289. struct syscore_ops { 
  1290.         struct list_head node; 
  1291.         int (*suspend)(void); 
  1292.         void (*resume)(void); 
  1293.         void (*shutdown)(void); 
  1294. }; 
  1295. 这个syscore是通过一个全局的list管理的,如下 
  1296. LIST_HEAD(syscore_ops_list); 
  1297. */  
  1298.   
  1299. struct syscore_ops dma_syscore_ops = {  
  1300.     .suspend    = s3c2410_dma_suspend,  
  1301.     .resume     = s3c2410_dma_resume,  
  1302. };  
  1303.   
  1304. /* kmem cache implementation */  
  1305. //下面看到  
  1306. static void s3c2410_dma_cache_ctor(void *p)  
  1307. {  
  1308.     memset(p, 0, sizeof(struct s3c2410_dma_buf));  
  1309. }  
  1310.   
  1311. /* initialisation code */  
  1312.   
  1313. static int __init s3c24xx_dma_syscore_init(void)  
  1314. {  
  1315. //注册的实质就是  
  1316. //list_add_tail(&ops->node, &syscore_ops_list);  
  1317. //加入链表  
  1318.     register_syscore_ops(&dma_syscore_ops);  
  1319.   
  1320.     return 0;  
  1321. }  
  1322.   
  1323. //late_initcall启动时会执行,在那个阶段我们就不管了  
  1324. late_initcall(s3c24xx_dma_syscore_init);  
  1325. /* 
  1326. 下面这个函数告诉我们这些__init函数的调用位置 
  1327. static int __init s3c2440_dma_add(struct sys_device *sysdev) 
  1328.         s3c2410_dma_init(); 
  1329.         s3c24xx_dma_order_set(&s3c2440_dma_order); 
  1330.         return s3c24xx_dma_init_map(&s3c2440_dma_sel); 
  1331.  
  1332. static struct sysdev_driver s3c2440_dma_driver = { 
  1333.         .add    = s3c2440_dma_add, 
  1334. }; 
  1335.  
  1336. static int __init s3c2440_dma_init(void) 
  1337.         return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver); 
  1338.  
  1339. struct sysdev_class s3c2440_sysclass = { 
  1340.         .name           = "s3c2440-core", 
  1341. }; 
  1342.  
  1343. static struct sys_device s3c2440_sysdev = { 
  1344.         .cls            = &s3c2440_sysclass, 
  1345. }; 
  1346.  
  1347. 在s3c2440_init()中会调用 
  1348. sysdev_register(&s3c2440_sysdev); 
  1349. 我们从这可以看到设备与驱动的概念,当然这不是我们的重点,我只说想说 
  1350. s3c2440_dma_add初始化会被调用,我们就安初始化调用过程来看代码 
  1351.  
  1352. 启动时调用 
  1353. arch_initcall(s3c2440_dma_init); 
  1354. */  
  1355.   
  1356. //s3c24xx_dma_init在下面s3c2410_dma_init()被调用  
  1357. //s3c2440或s3c2410平台s3c24xx_dma_init(4, IRQ_DMA0, 0x40);  
  1358. //4个通道,中断号为IRQ_DMA0,0x40 * 4就是io要映射的大小  
  1359. int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,  
  1360.                 unsigned int stride)  
  1361. {  
  1362.     struct s3c2410_dma_chan *cp;  
  1363.     int channel;  
  1364.     int ret;  
  1365.   
  1366.     printk("S3C24XX DMA Driver, Copyright 2003-2006 Simtec Electronics\n");  
  1367.   
  1368.     dma_channels = channels;  
  1369.   
  1370.     //寄存器映射  
  1371.     dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);  
  1372.     if (dma_base == NULL) {  
  1373.         printk(KERN_ERR "dma failed to remap register block\n");  
  1374.         return -ENOMEM;  
  1375.     }  
  1376.   
  1377.     //申请后备缓存  
  1378.     dma_kmem = kmem_cache_create("dma_desc",  
  1379.                      sizeof(struct s3c2410_dma_buf), 0,  
  1380.                      SLAB_HWCACHE_ALIGN,  
  1381.                      s3c2410_dma_cache_ctor);  
  1382.     /* 
  1383.     原型: 
  1384.     struct kmem_cache *kmem_cache_create(const char *name, size_t size, 
  1385.                 size_t align, unsigned long flags, void (*ctor)(void *)) 
  1386.     SLAB_HWCACHE_ALIGN: 
  1387.     这个标志需要每个数据对象被对齐到一个缓存行; 实际对齐依赖主机平 
  1388.     台的缓存分布. 这个选项可以是一个好的选择, 如果在 SMP 机器上你的 
  1389.     缓存包含频繁存取的项. 但是, 用来获得缓存行对齐的填充可以浪费可 
  1390.     观的内存量.  
  1391.     s3c2410_dma_cache_ctor: 
  1392.     构造函数,上面可以看到就是把申请的内存空间清零。 
  1393.     */  
  1394.   
  1395.     if (dma_kmem == NULL) {  
  1396.         printk(KERN_ERR "dma failed to make kmem cache\n");  
  1397.         ret = -ENOMEM;  
  1398.         goto err;  
  1399.     }  
  1400.     /* 
  1401.     在mach-s3c2410/include/mach/dma.h下定义的结构体 
  1402.     struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS]; 
  1403.     */  
  1404.     for (channel = 0; channel < channels;  channel++) {  
  1405.         cp = &s3c2410_chans[channel];  
  1406.   
  1407.         memset(cp, 0, sizeof(struct s3c2410_dma_chan));  
  1408.   
  1409.         /* dma channel irqs are in order.. */  
  1410.         cp->number = channel; //通道号  
  1411.         cp->irq    = channel + irq; //中断号   
  1412.         cp->regs   = dma_base + (channel * stride); //寄存器基地址  
  1413.   
  1414.         /* point current stats somewhere */  
  1415.         /* 
  1416.         struct s3c2410_dma_stats *stats; 
  1417.         struct s3c2410_dma_stats  stats_store; 
  1418.         下面就是个指针初始化 
  1419.         */  
  1420.         cp->stats  = &cp->stats_store;  
  1421.         cp->stats_store.timeout_shortest = LONG_MAX;//#define LONG_MAX       ((long)(~0UL>>1))  
  1422.   
  1423.         /* basic channel configuration */  
  1424.   
  1425.         cp->load_timeout = 1<<18;//向dma载入缓冲的超时时间  
  1426.   
  1427.         printk("DMA channel %d at %p, irq %d\n",  
  1428.                cp->number, cp->regs, cp->irq);  
  1429.     }  
  1430.   
  1431.     return 0;  
  1432.   
  1433.  err:  
  1434.     kmem_cache_destroy(dma_kmem);  
  1435.     iounmap(dma_base);  
  1436.     dma_base = NULL;  
  1437.     return ret;  
  1438. }  
  1439.   
  1440. int __init s3c2410_dma_init(void)  
  1441. {  
  1442.     return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);  
  1443. }  
  1444.   
  1445. static inline int is_channel_valid(unsigned int channel)  
  1446. {  
  1447. //#define DMA_CH_VALID          (1<<31)  
  1448.     return (channel & DMA_CH_VALID);  
  1449. }  
  1450.   
  1451. static struct s3c24xx_dma_order *dma_order;  
  1452.   
  1453.   
  1454. /* s3c2410_dma_map_channel() 
  1455.  * 
  1456.  * turn the virtual channel number into a real, and un-used hardware 
  1457.  * channel. 
  1458.  * 
  1459.  * first, try the dma ordering given to us by either the relevant 
  1460.  * dma code, or the board. Then just find the first usable free 
  1461.  * channel 
  1462. */  
  1463. //根据虚拟通道号,找到一个可以的通道  
  1464. //实际就是根据channel从数组s3c2440_dma_order和  
  1465. //s3c2440_dma_mapping和中找到对应且可用的元素  
  1466. //s3c2410_dma_request()会调用这个函数  
  1467. static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)  
  1468. {  
  1469.     struct s3c24xx_dma_order_ch *ord = NULL;  
  1470.     struct s3c24xx_dma_map *ch_map;  
  1471.     struct s3c2410_dma_chan *dmach;  
  1472.     int ch;  
  1473.   
  1474.     //dma_sel.map就是s3c2440_dma_mappings[]  
  1475.     //dma_sel.map_size就是ARRAY_SIZE(s3c2440_dma_mappings)  
  1476.     if (dma_sel.map == NULL || channel > dma_sel.map_size)  
  1477.         return NULL;  
  1478.   
  1479.     ch_map = dma_sel.map + channel;  
  1480.     //从上面这句可以看出这个channel不是指dma的4个通道  
  1481.     //而是s3c2440_dma_mappings[]对应的数组元素,下面有  
  1482.     /*channel的值如下 
  1483.     enum dma_ch { 
  1484.     DMACH_XD0, 
  1485.     DMACH_XD1, 
  1486.     DMACH_SDI, 
  1487.     DMACH_SPI0, 
  1488.     DMACH_SPI1, 
  1489.     DMACH_UART0, 
  1490.     DMACH_UART1, 
  1491.     ... 
  1492.     和s3c2440_dma_mappings[]对应 
  1493.     */  
  1494.       
  1495.     /* first, try the board mapping */  
  1496.   
  1497.     if (dma_order) {  
  1498.         ord = &dma_order->channels[channel];//找到对应的  
  1499.   
  1500.         for (ch = 0; ch < dma_channels; ch++) {  
  1501.             int tmp;  
  1502.             if (!is_channel_valid(ord->list[ch]))//判断通道可用  
  1503.                 continue;  
  1504.   
  1505.             tmp = ord->list[ch] & ~DMA_CH_VALID;//标志为不可用  
  1506.             //s3c2410_dma_request函数会使in_use变为1  
  1507.             if (s3c2410_chans[tmp].in_use == 0) {  
  1508.                 ch = tmp;  
  1509.                 goto found;  
  1510.             }  
  1511.         }  
  1512.   
  1513.         if (ord->flags & DMA_CH_NEVER)  
  1514.             return NULL;  
  1515.     }  
  1516.   
  1517.     /* second, search the channel map for first free */  
  1518.   
  1519.     for (ch = 0; ch < dma_channels; ch++) {  
  1520.         if (!is_channel_valid(ch_map->channels[ch]))//判断可用  
  1521.             continue;  
  1522.   
  1523.         if (s3c2410_chans[ch].in_use == 0) {  
  1524.             printk("mapped channel %d to %d\n", channel, ch);  
  1525.             break;  
  1526.         }  
  1527.     }  
  1528.     /* 
  1529.     上面的is_channel_valid是在平台提供的数组中的标记 
  1530.     in_use是此代码中的标记。 
  1531.     */  
  1532.       
  1533.     if (ch >= dma_channels)  
  1534.         return NULL;  
  1535.   
  1536.     /* update our channel mapping */  
  1537.   
  1538.  found:  
  1539.     dmach = &s3c2410_chans[ch];  
  1540.     dmach->map = ch_map; //对应的struct s3c24xx_dma_map结构体  
  1541.     dmach->req_ch = channel;  
  1542.     s3c_dma_chan_map[channel] = dmach;//放入struct s3c2410_dma_chan结构体中  
  1543.   
  1544.     /* select the channel */  
  1545.   
  1546.     (dma_sel.select)(dmach, ch_map);//下面有s3c2440的select函数s3c2440_dma_select()  
  1547.   
  1548.     return dmach;  
  1549. }  
  1550.   
  1551. static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)  
  1552. {  
  1553.     return 0;  
  1554. }  
  1555.   
  1556. int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)  
  1557. {  
  1558.     //传入的是s3c2440_dma_sel  
  1559.     /* 
  1560.     struct s3c24xx_dma_map { 
  1561.             const char              *name; 
  1562.  
  1563.             unsigned long            channels[S3C_DMA_CHANNELS]; 
  1564.             unsigned long            channels_rx[S3C_DMA_CHANNELS]; 
  1565.     }; 
  1566.  
  1567.     struct s3c24xx_dma_selection { 
  1568.         struct s3c24xx_dma_map  *map; 
  1569.         unsigned long            map_size; 
  1570.         unsigned long            dcon_mask; 
  1571.  
  1572.         void    (*select)(struct s3c2410_dma_chan *chan, 
  1573.                           struct s3c24xx_dma_map *map); 
  1574.  
  1575.         void    (*direction)(struct s3c2410_dma_chan *chan, 
  1576.                              struct s3c24xx_dma_map *map, 
  1577.                              enum dma_data_direction dir); 
  1578.     }; 
  1579.     static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = { 
  1580.         [DMACH_XD0] = { 
  1581.                 .name           = "xdreq0", 
  1582.                 .channels[0]    = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID, 
  1583.         }, 
  1584.         [DMACH_XD1] = { 
  1585.                 .name           = "xdreq1", 
  1586.                 .channels[1]    = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID, 
  1587.         }, 
  1588.         [DMACH_SDI] = { 
  1589.                 .name           = "sdi", 
  1590.                 .channels[0]    = S3C2410_DCON_CH0_SDI | DMA_CH_VALID, 
  1591.                 .channels[1]    = S3C2440_DCON_CH1_SDI | DMA_CH_VALID, 
  1592.                 .channels[2]    = S3C2410_DCON_CH2_SDI | DMA_CH_VALID, 
  1593.                 .channels[3]    = S3C2410_DCON_CH3_SDI | DMA_CH_VALID, 
  1594.         }, 
  1595.     //太长没贴完,就是支持的外设信息 
  1596.  
  1597.     static void s3c2440_dma_select(struct s3c2410_dma_chan *chan, 
  1598.                                    struct s3c24xx_dma_map *map) 
  1599.     { 
  1600.             chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;//选择一个通道并置为不可用 
  1601.     } 
  1602.  
  1603.     static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = { 
  1604.             .select         = s3c2440_dma_select, 
  1605.             .dcon_mask      = 7 << 24, //dcon寄存器的24~26位 源选择 
  1606.             .map            = s3c2440_dma_mappings, 
  1607.             .map_size       = ARRAY_SIZE(s3c2440_dma_mappings), 
  1608.     }; 
  1609.     */  
  1610.     struct s3c24xx_dma_map *nmap;  
  1611.     size_t map_sz = sizeof(*nmap) * sel->map_size;  
  1612.     int ptr;  
  1613.   
  1614.     nmap = kmalloc(map_sz, GFP_KERNEL);  
  1615.     if (nmap == NULL)  
  1616.         return -ENOMEM;  
  1617.   
  1618.     memcpy(nmap, sel->map, map_sz);  
  1619.     memcpy(&dma_sel, sel, sizeof(*sel));  
  1620.   
  1621.     dma_sel.map = nmap;  
  1622.     //上面一段就是,申请内存,把s3c2440_dma_sel的信息放入dma_sel中  
  1623.     for (ptr = 0; ptr < sel->map_size; ptr++)  
  1624.         s3c24xx_dma_check_entry(nmap+ptr, ptr);//在上面,空函数  
  1625.   
  1626.     return 0;  
  1627. }  
  1628.   
  1629. int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)  
  1630. {  
  1631.     //传入的就是s3c2440_dma_order  
  1632.     /* 
  1633.     struct s3c24xx_dma_order_ch { 
  1634.             unsigned int    list[S3C_DMA_CHANNELS]; // list of channels  
  1635.             unsigned int    flags;                          // flags  
  1636.     }; 
  1637.  
  1638.  
  1639.     struct s3c24xx_dma_order { 
  1640.             struct s3c24xx_dma_order_ch     channels[DMACH_MAX]; 
  1641.     }; 
  1642.     DMACH_MAX指的是外设的最大ID,通过类似DMACH_UART0_TX来表示外设 
  1643.     S3C_DMA_CHANNELS是最大通道数,s3c2440是4个通道 
  1644.  
  1645.     static struct s3c24xx_dma_order __initdata s3c2440_dma_order = { 
  1646.     .channels   = { 
  1647.         [DMACH_SDI] = { 
  1648.             .list   = { 
  1649.                 [0] = 3 | DMA_CH_VALID, 
  1650.                 [1] = 2 | DMA_CH_VALID, 
  1651.                 [2] = 1 | DMA_CH_VALID, 
  1652.                 [3] = 0 | DMA_CH_VALID, 
  1653.             }, 
  1654.         }, 
  1655.         [DMACH_I2S_IN]  = { 
  1656.             .list   = { 
  1657.                 [0] = 1 | DMA_CH_VALID, 
  1658.                 [1] = 2 | DMA_CH_VALID, 
  1659.             }, 
  1660.         }, 
  1661.         [DMACH_I2S_OUT] = { 
  1662.             .list   = { 
  1663.                 [0] = 2 | DMA_CH_VALID, 
  1664.                 [1] = 1 | DMA_CH_VALID, 
  1665.             }, 
  1666.         }, 
  1667.         [DMACH_PCM_IN] = { 
  1668.             .list   = { 
  1669.                 [0] = 2 | DMA_CH_VALID, 
  1670.                 [1] = 1 | DMA_CH_VALID, 
  1671.     ... 
  1672.     太多,没贴完。 
  1673.     */  
  1674.     struct s3c24xx_dma_order *nord = dma_order;  
  1675.   
  1676.     if (nord == NULL)//为空的话重分配  
  1677.         nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);  
  1678.   
  1679.     if (nord == NULL) {  
  1680.         printk(KERN_ERR "no memory to store dma channel order\n");  
  1681.         return -ENOMEM;  
  1682.     }  
  1683.   
  1684.     dma_order = nord;  
  1685.     memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));  
  1686.     return 0;  
  1687. }  


如果你看懂了上面的代码,下面的plat-samsung中的代码基本不用分析了

 

 

[cpp] view plain copy
 
    1. /* linux/arch/arm/plat-samsung/s3c-dma-ops.c 
    2.  * 
    3.  * Copyright (c) 2011 Samsung Electronics Co., Ltd. 
    4.  *              http://www.samsung.com 
    5.  * 
    6.  * Samsung S3C-DMA Operations 
    7.  * 
    8.  * This program is free software; you can redistribute it and/or modify 
    9.  * it under the terms of the GNU General Public License version 2 as 
    10.  * published by the Free Software Foundation. 
    11.  */  
    12.   
    13. #include <linux/kernel.h>  
    14. #include <linux/errno.h>  
    15. #include <linux/slab.h>  
    16. #include <linux/types.h>  
    17. #include <linux/export.h>  
    18.   
    19. #include <mach/dma.h>  
    20.   
    21. struct cb_data {  
    22.         void (*fp) (void *);  
    23.         void *fp_param;  
    24.         unsigned ch;  
    25.         struct list_head node;  
    26. };  
    27.   
    28. static LIST_HEAD(dma_list);  
    29. //s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);  
    30. //s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);  
    31. /* 
    32.     if (chan->callback_fn != NULL) { 
    33.         (chan->callback_fn)(chan, buf->id, buf->size, result); 
    34.     } 
    35. */  
    36.   
    37. static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,  
    38.                        int size, enum s3c2410_dma_buffresult res)  
    39. {  
    40.         struct cb_data *data = param;  
    41.   
    42.         data->fp(data->fp_param);  
    43. }  
    44.   
    45. static unsigned s3c_dma_request(enum dma_ch dma_ch,  
    46.                                  struct samsung_dma_info *info)  
    47. {  
    48.         struct cb_data *data;  
    49.   
    50.         if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {  
    51.                 s3c2410_dma_free(dma_ch, info->client);  
    52.                 return 0;  
    53.         }  
    54.   
    55.         data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);  
    56.         data->ch = dma_ch;  
    57.         list_add_tail(&data->node, &dma_list);  
    58.   
    59.         s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);  
    60.   
    61.         if (info->cap == DMA_CYCLIC)  
    62.                 s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);  
    63.   
    64.         s3c2410_dma_config(dma_ch, info->width);  
    65.   
    66.         return (unsigned)dma_ch;  
    67. }  
    68.   
    69. static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)  
    70. {  
    71.         struct cb_data *data;  
    72.   
    73.         list_for_each_entry(data, &dma_list, node)  
    74.                 if (data->ch == ch)  
    75.                         break;  
    76.         list_del(&data->node);  
    77.   
    78.         s3c2410_dma_free(ch, client);  
    79.         kfree(data);  
    80.   
    81.         return 0;  
    82. }  
    83.   
    84. static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)  
    85. {  
    86.         struct cb_data *data;  
    87.         int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;  
    88.   
    89.         list_for_each_entry(data, &dma_list, node)  
    90.                 if (data->ch == ch)  
    91.                         break;  
    92.   
    93.         if (!data->fp) {  
    94.                 s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);  
    95.                 data->fp = info->fp;  
    96.                 data->fp_param = info->fp_param;  
    97.         }  
    98.   
    99.         s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);  
    100.   
    101.         return 0;  
    102. }  
    103.   
    104. static inline int s3c_dma_trigger(unsigned ch)  
    105. {  
    106.         return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);  
    107. }  
    108.   
    109. static inline int s3c_dma_started(unsigned ch)  
    110. {  
    111.         return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);  
    112. }  
    113.   
    114. static inline int s3c_dma_flush(unsigned ch)  
    115. {  
    116.         return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);  
    117. }  
    118.   
    119. static inline int s3c_dma_stop(unsigned ch)  
    120. {  
    121.         return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);  
    122. }  
    123.   
    124. static struct samsung_dma_ops s3c_dma_ops = {  
    125.         .request        = s3c_dma_request,  
    126.         .release        = s3c_dma_release,  
    127.         .prepare        = s3c_dma_prepare,  
    128.         .trigger        = s3c_dma_trigger,  
    129.         .started        = s3c_dma_started,  
    130.         .flush          = s3c_dma_flush,  
    131.         .stop           = s3c_dma_stop,  
    132. };  
    133.   
    134. void *s3c_dma_get_ops(void)  
    135. {  
    136.         return &s3c_dma_ops;  
    137. }  
    138. EXPORT_SYMBOL(s3c_dma_get_ops);  

 

posted on 2016-08-24 15:41  jamboo  阅读(2031)  评论(0编辑  收藏  举报

导航