usb_send.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * usb_send.c 
  3.  *
  4.  * S3C2410 USB send function
  5.  * endpoint 2
  6.  *
  7.  * bushi<bushi@mizi.com>
  8.  */
  9. #include <linux/module.h>
  10. #include <linux/pci.h>
  11. #include <linux/errno.h>
  12. #include <linux/delay.h>
  13. #include <asm/hardware.h>
  14. #include <asm/dma.h>
  15. #include <asm/system.h>
  16. #include <asm/byteorder.h>
  17. #include "s3c2410_usb.h"
  18. #include "usb_ctl.h"
  19. //#define USB_DEBUG 1
  20. #ifdef USB_DEBUG
  21. #define LOG(arg...) printk(__FILE__":"__FUNCTION__"(): " ##arg)
  22. #else
  23. #define LOG(arg...) (void)(0)
  24. #endif
  25. /* Enable DMA on the endpoint 2. */
  26. static char *ep2_buf;
  27. static int ep2_len;
  28. static usb_callback_t ep2_callback;
  29. #ifdef USE_USBD_DMA
  30. static dma_addr_t ep2_dma;
  31. static dma_addr_t ep2_curdmapos;
  32. #else
  33. static char *ep2_curbufpos;
  34. #endif
  35. static int ep2_curdmalen;
  36. static int ep2_remain;
  37. static int dmachn_tx;
  38. static int tx_pktsize;
  39. void 
  40. ep2_dma_callback(void *buf_id, int size)
  41. {
  42. LOG("n");
  43. #ifdef USE_USBD_DMA
  44. UD_INDEX = UD_INDEX_EP2;
  45. UD_ICSR1 |= UD_ICSR1_PKTRDY;
  46. #endif
  47. }
  48. /* set feature stall executing, async */
  49. void
  50. ep2_stall( void )
  51. {
  52. LOG("n");
  53. UD_INDEX = UD_INDEX_EP2;
  54. UD_ICSR1 |= UD_ICSR1_SENDSTL; /* send stall, force stall */
  55. }
  56. static void
  57. ep2_start(void)
  58. {
  59. #ifndef USE_USBD_DMA
  60.     int i;
  61. #endif
  62. LOG("n");
  63. if (!ep2_len) {
  64. LOG("!ep2_lenn");
  65. return;
  66. }
  67. ep2_curdmalen = tx_pktsize; /* 64 */
  68. if (ep2_curdmalen > ep2_remain)
  69. ep2_curdmalen = ep2_remain;
  70. LOG("ep2_curdmalen = %dn", ep2_curdmalen);
  71.  
  72. #ifdef USE_USBD_DMA
  73. // 澜.. 绊媚具摆促. full 捞 登搁 遏阑 吧带啊 wait 甫 窍带啊 秦具瘤...
  74. // ucb_ctl.c 俊辑 檬扁拳 矫难临 荐 乐档废 绊妨秦辑...
  75. UD_DMAUC1 = 0x01;
  76. UD_DMAFC1 = (u_char) ep2_curdmalen & UD_DMAFCx_DATA;
  77. // s3c2400 ,  构瘤 ?
  78. // UD_CSR1 = 0x00;
  79. backup = UD_INDEX;
  80. UD_INDEX = UD_INDEX_EP2;
  81. UD_ICSR1 &= ~UD_ICSR1_CLRDT;
  82. UD_INDEX = backup;
  83. // s3c2400
  84. // UD_DMA = (UD_DMA_MODE | UD_DMA_IN_RUN);
  85. UD_DMACON1 = UD_DMACONx_DMAMDOE | UD_DMACONx_IRUN;
  86. s3c2410_dma_queue_buffer(dmachn_tx, NULL, ep2_curdmapos, ep2_curdmalen, 
  87.  DMA_BUF_WR);
  88. #else
  89. for (i = 0; i < ep2_curdmalen; i++) {
  90. LOG("ep2_curbufpos[i] = 0x%02xn", ep2_curbufpos[i]);
  91.     UD_FIFO2 = (u_char) ep2_curbufpos[i] & UD_FIFO2_DATA;
  92. }
  93. UD_INDEX = UD_INDEX_EP2;
  94. UD_ICSR1 |= UD_ICSR1_PKTRDY;
  95. #endif
  96. }
  97. static void
  98. ep2_done(int flag)
  99. {
  100. int size = ep2_len - ep2_remain;
  101. LOG("ep2_len = %d, ep2_remain = %dn", ep2_len, ep2_remain);
  102. if (ep2_len) {
  103. #ifdef USE_USBD_DMA
  104. pci_unmap_single(NULL, ep2_dma, ep2_len, PCI_DMA_TODEVICE);
  105. #endif
  106. ep2_len = 0;
  107. if (ep2_callback)
  108. ep2_callback(flag, size);
  109. }
  110. }
  111. int
  112. ep2_init(int chn)
  113. {
  114. desc_t * pd = s3c2410_usb_get_descriptor_ptr();
  115. tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize ); /* 64 */
  116. LOG("tx_pktsize = %dn", tx_pktsize);
  117. dmachn_tx = chn;
  118. #ifdef USE_USBD_DMA
  119. s3c2410_dma_flush_all(dmachn_tx);
  120. #endif
  121. ep2_done(-EAGAIN);
  122. return 0;
  123. }
  124. void
  125. ep2_reset(void)
  126. {
  127. desc_t * pd = s3c2410_usb_get_descriptor_ptr();
  128. tx_pktsize = __le16_to_cpu( pd->b.ep2.wMaxPacketSize ); /* 64 */
  129. LOG("tx_pktsize = %dn", tx_pktsize);
  130. UD_INDEX = UD_INDEX_EP2;
  131. UD_ICSR1 &= ~(UD_ICSR1_SENDSTL); // write 0 to clear
  132. #ifdef USE_USBD_DMA
  133. s3c2410_dma_flush_all(dmachn_tx);
  134. #endif
  135. ep2_done(-EINTR);
  136. }
  137. void
  138. ep2_int_hndlr(int udcsr)
  139. {
  140. int status;
  141. UD_INDEX = UD_INDEX_EP2;
  142. status = UD_ICSR1;
  143. LOG("status = 0x%08xn", status);
  144. if( status & UD_ICSR1_SENTSTL ) {
  145.     UD_INDEX = UD_INDEX_EP2;
  146.     UD_ICSR1 &= ~UD_ICSR1_SENTSTL; // clear_ep1_sent_stall;
  147.    return;
  148. }
  149. LOG("[%d]n", __LINE__);
  150. if ( !(status & UD_ICSR1_PKTRDY) ) {
  151. LOG("[%d]n", __LINE__);
  152. #ifdef USE_USBD_DMA
  153. s3c2410_dma_flush_all(dmachn_tx);
  154. ep2_curdmapos += ep2_curdmalen;
  155. #else
  156. ep2_curbufpos += ep2_curdmalen;
  157. #endif
  158. ep2_remain -= ep2_curdmalen;
  159. if (ep2_remain != 0) {
  160. LOG("[%d]n", __LINE__);
  161. ep2_start();
  162. } else {
  163. LOG("[%d]n", __LINE__);
  164. ep2_done(0);
  165. }
  166. }
  167. }
  168. int
  169. s3c2410_usb_send(char *buf, int len, usb_callback_t callback)
  170. {
  171. int flags;
  172. LOG("[%d]n", __LINE__);
  173. if (usbd_info.state != USB_STATE_CONFIGURED)
  174. return -ENODEV;
  175. if (ep2_len)
  176. return -EBUSY;
  177. local_irq_save(flags);
  178. ep2_buf = buf;
  179. ep2_len = len;
  180. #ifdef USE_USBD_DMA 
  181. ep2_dma = pci_map_single(NULL, ep2_buf, ep2_len, PCI_DMA_TODEVICE);
  182. ep2_curdmapos = ep2_dma;
  183. #else
  184. ep2_curbufpos = ep2_buf;
  185. #endif
  186. ep2_callback = callback;
  187. ep2_remain = len;
  188. ep2_start();
  189. local_irq_restore(flags);
  190. return 0;
  191. }
  192. void
  193. s3c2410_usb_send_reset(void)
  194. {
  195. LOG("n");
  196. ep2_reset();
  197. }
  198. int s3c2410_usb_xmitter_avail( void )
  199. {
  200. LOG("n");
  201. if (usbd_info.state != USB_STATE_CONFIGURED) {
  202. LOG("[%d]n", __LINE__);
  203. return -ENODEV;
  204. }
  205. if (ep2_len) {
  206. LOG("[%d]n", __LINE__);
  207. return -EBUSY;
  208. }
  209. return 0;
  210. }
  211. EXPORT_SYMBOL(s3c2410_usb_xmitter_avail);
  212. EXPORT_SYMBOL(s3c2410_usb_send);
  213. EXPORT_SYMBOL(s3c2410_usb_send_reset);