tizen 2.4 release
[kernel/u-boot-tm1.git] / nand_fdl / common / src / drv_usb.c
1 /******************************************************************************
2  ** File Name:      DRV_usb.c                                                 *
3  ** Author:         JiaYong.Yang                                              *
4  ** DATE:           09/01/2010                                                *
5  ** Copyright:      2010 Spreatrum, Incoporated. All Rights Reserved.         *
6  ** Description:                                                              *
7  ******************************************************************************/
8 /**---------------------------------------------------------------------------*
9  **                         Dependencies                                      *
10  **---------------------------------------------------------------------------*/
11
12 #include <asm/arch/common.h>
13 #include <asm/arch/usb200_fdl.h>
14 #include <asm/arch/drv_usb20.h>
15 #include <asm/arch/virtual_com.h>
16 #include <asm/arch/packet.h>
17 #include <asm/arch/usb20_reg_v3.h>
18
19 #define FDL2_MODULE     1
20
21 PUBLIC void Dcache_InvalRegion(unsigned int addr, unsigned int length);
22 PUBLIC void Dcache_CleanRegion(unsigned int addr, unsigned int length);
23
24 static __inline void usb_handler (void);
25 /**---------------------------------------------------------------------------*
26  **                         Compiler Flag                                     *
27  **---------------------------------------------------------------------------*/
28 #define MAX_RECV_LENGTH     (64*64)//640*64 0xa000
29 #define USB_TIMEOUT             (1000)
30
31 /**---------------------------------------------------------------------------*
32  **                         Data Structures                                   *
33  **---------------------------------------------------------------------------*/
34  
35 static int currentDmaBufferIndex = 0;
36 LOCAL __align(64) uint32    s_setup_packet[8] = {0};
37 LOCAL uint32    enum_speed = 0;
38 LOCAL uint32    recv_length = 0;
39 LOCAL uint32 nIndex = 0;
40 LOCAL uint32 readIndex = 0;
41
42 PUBLIC __align (64)  unsigned char usb_out_endpoint_buf[2] [MAX_RECV_LENGTH];
43
44
45 int error_count = 0;
46  
47 /*****************************************************************************/
48 //  Description:   configure out endpoint0 to receive setup message.
49 //  Global resource dependence:
50 //  Author:        jiayong.yang
51 //  Note:
52 /*****************************************************************************/
53 LOCAL int EPO0_config (BOOLEAN is_dma, uint32 *buffer)
54 {
55     // Programs DOEPTSIZ0 register with Packet Count and Transfer Size
56     * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_29|BIT_30); //setup packet count , 3 packet
57     * (volatile uint32 *) USB_DOEP0TSIZ |= (unsigned int) (BIT_3|BIT_4); //set Transfer Size ,24 bytes
58
59     if (is_dma)
60     {
61         * (volatile uint32 *) USB_DOEPDMA (0) = (uint32) buffer;//lint !e718
62     }
63
64     * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_26;    // set clear NAK
65     * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_31;    // set endpoint enable
66     return 0;
67 }
68 /*****************************************************************************/
69 //  Description:   configure in endpoint0 to send message.
70 //  Global resource dependence:
71 //  Author:        jiayong.yang
72 //  Note:
73 /*****************************************************************************/
74 void EPI0_config (uint32 transfer_size, uint32 packet_count, BOOLEAN is_dma, uint32 *buffer)
75 {
76     volatile USB_DIEP0TSIZ_U *diep0tsiz_ptr = (USB_DIEP0TSIZ_U *) USB_DIEP0TSIZ;
77
78     diep0tsiz_ptr->mBits.transfer_size = transfer_size;
79     diep0tsiz_ptr->mBits.packet_count = packet_count;
80
81     if (is_dma)
82     {
83 #if defined CONFIG_SC8810 || defined CONFIG_SC8825 || defined CONFIG_SC8830 || defined(CONFIG_SC9630)
84         Dcache_CleanRegion((unsigned int)(buffer), transfer_size);
85 #endif
86         * (volatile uint32 *) USB_DIEPDMA (0) = (uint32) buffer;//lint !e718
87     }
88
89     * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_22|BIT_23|BIT_24|BIT_25)); // set EP0 in tx fifo nummber
90
91     * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_26;                    // clear NAK
92
93     * (volatile uint32 *) USB_DIEP0CTL |= (unsigned int) BIT_31;                    // set endpoint enable
94 }
95 /*****************************************************************************/
96 //  Description:   usb reset interrupt handler.
97 //  Global resource dependence:
98 //  Author:        jiayong.yang
99 //  Note:
100 /*****************************************************************************/
101 void usb_EPActive (USB_EP_NUM_E ep_num, BOOLEAN dir)
102 {
103     if (dir) // out endpoint
104     {
105         * (volatile uint32 *) USB_DOEPCTL (ep_num)  |= (unsigned int) BIT_15; //lint !e718// endpoint active
106         * (volatile uint32 *) USB_DOEPMSK = (unsigned int) (BIT_13|BIT_12|BIT_3);
107     }
108     else
109     {
110         * (volatile uint32 *) USB_DIEPCTL (ep_num)  |= (unsigned int) BIT_15; //lint !e718// endpoint active
111         * (volatile uint32 *) USB_DIEPMSK = 0xffffffff;
112     }
113 }
114 /*****************************************************************************/
115 //  Description:   configure specified endpoint to send/receive message.
116 //  Global resource dependence:
117 //  Author:        jiayong.yang
118 //  Note:
119 /*****************************************************************************/
120 LOCAL void EPn_config (USB_EP_NUM_E ep_num, USB_EP_TYPE_E ep_type, BOOLEAN dir, uint32 mps)
121 {
122     // out endpoint
123     if (dir)
124     {
125         volatile USB_DOEPCTL_U *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
126
127         doepctl_ptr->mBits.ep_type = ep_type;
128         doepctl_ptr->mBits.mps =mps;
129         doepctl_ptr->mBits.set_nak = 0x1;
130     }
131     else
132     {
133         volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
134
135         diepctl_ptr->mBits.ep_type = ep_type;
136         diepctl_ptr->mBits.mps = mps;
137         diepctl_ptr->mBits.set_nak = 0x1;
138     }
139 }
140
141 /*****************************************************************************/
142 //  Description:   start endpoint transfer.
143 //  Global resource dependence:
144 //  Author:        jiayong.yang
145 //  Note:
146 /*****************************************************************************/
147 LOCAL void usb_start_transfer (USB_EP_NUM_E ep_num, BOOLEAN dir, uint32 transfer_size, BOOLEAN is_dma, uint32 *buffer)
148 {
149     uint16 packet_count = 0;
150
151     if (dir)
152     {
153         volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (ep_num);
154         volatile USB_DOEPCTL_U   *doepctl_ptr = (USB_DOEPCTL_U *) USB_DOEPCTL (ep_num);
155
156         if (is_dma)
157         {                
158         //      Dcache_InvalRegion((unsigned int)buffer,  MAX_RECV_LENGTH);
159                 * (volatile uint32 *) USB_DOEPDMA (ep_num) = (uint32) buffer;
160         }
161
162         doeptsiz_ptr->mBits.transfer_size = MAX_RECV_LENGTH;    // transfer size
163         doeptsiz_ptr->mBits.packet_count = (MAX_RECV_LENGTH+doepctl_ptr->mBits.mps-1)/doepctl_ptr->mBits.mps;
164         * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_26; // clear nak
165         * (volatile uint32 *) USB_DOEPCTL (ep_num) |= (unsigned int) BIT_31; // endpoint enable
166     }
167     else
168     {
169         volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U *) USB_DIEPTSIZ (ep_num);
170         volatile USB_DIEPCTL_U   *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_num);
171
172
173         if (is_dma)
174         {                
175 #if defined CONFIG_SC8810 || defined CONFIG_SC8825 || defined CONFIG_SC8830 || defined(CONFIG_SC9630)
176                 Dcache_CleanRegion((unsigned int)buffer,  transfer_size);
177 #endif
178                 * (volatile uint32 *) USB_DIEPDMA (ep_num) = (uint32) buffer;
179         } 
180
181         dieptsiz_ptr->mBits.transfer_size = transfer_size;                  // transfer size
182         packet_count = (transfer_size+diepctl_ptr->mBits.mps-1) /diepctl_ptr->mBits.mps;
183         dieptsiz_ptr->mBits.packet_count = packet_count;                    // packet count
184         diepctl_ptr->mBits.tx_fifo_number = ep_num;                         // tx fifo number
185
186         * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_26;            // clear nak
187         * (volatile uint32 *) USB_DIEPCTL (ep_num) |= (unsigned int) BIT_31;            // endpoint enable
188     }
189
190 }
191
192 /*****************************************************************************/
193 //  Description:   process desecriptor request.
194 //  Global resource dependence:
195 //  Author:        jiayong.yang
196 //  Note:
197 /*****************************************************************************/
198 LOCAL void usb_get_descriptor (USB_REQUEST_1_U *request1, USB_REQUEST_2_U *request2)
199 {
200     uint32 length = 0;
201     uint8   *send_data=NULL;
202
203
204     length = (uint32) request2->mBits.length_l;
205
206     switch (request1->mBits.value_m)
207     {
208
209         case USB_DEVICE_DESCRIPTOR_TYPE:
210
211             send_data = (uint8 *) UCOM_Get_DevDesc();//lint !e718
212             EPI0_config (0x12, 0x1, TRUE, (uint32 *) send_data);
213
214             break;
215
216         case USB_CONFIGURATION_DESCRIPTOR_TYPE:
217
218             send_data = (uint8 *) UCOM_Get_CfgDesc();//lint !e718
219
220             if (0xff == length)
221             {
222                 EPI0_config (0x20, 0x1, TRUE, (uint32 *) send_data);
223             }
224             else
225             {
226                 EPI0_config (length, 0x1, TRUE, (uint32 *) send_data);
227             }
228
229             break;
230
231         default:
232             break;
233     }
234 }
235 /*****************************************************************************/
236 //  Description:   process setup transaction.
237 //  Global resource dependence:
238 //  Author:        jiayong.yang
239 //  Note:
240 /*****************************************************************************/
241
242 LOCAL void usb_setup_handle (void)
243 {
244     uint32  vendor_ack = 0;
245     USB_REQUEST_1_U   *request1;
246     USB_REQUEST_2_U   *request2;
247
248     request1 = (USB_REQUEST_1_U *) (unsigned int) (&s_setup_packet[0]);
249     request2 = (USB_REQUEST_2_U *) (unsigned int) (&s_setup_packet[1]);
250
251     switch (request1->mBits.type)
252     {
253
254         case USB_REQ_STANDARD://standard
255
256             switch (request1->mBits.brequest)
257             {
258                 case USB_REQUEST_SET_ADDRESS:
259                     {
260                         volatile USB_DCFG_U *dcfg_ptr = (USB_DCFG_U *) USB_DCFG;
261
262                         dcfg_ptr->mBits.devaddr = request1->mBits.value_l;
263                         EPI0_config (0, 1, FALSE, NULL);
264                     }
265                     break;
266                 case USB_REQUEST_GET_DESCRIPTOR:
267
268                     usb_get_descriptor (request1, request2);
269
270                     break;
271                 case USB_REQUEST_SET_CONFIGURATION:
272                     EPI0_config (0, 1, FALSE, NULL);
273                     break;
274                 default:
275                     EPI0_config (0, 1, TRUE, &vendor_ack);
276                     break;
277             }
278
279             break;
280
281         case USB_REQ_CLASS://class
282
283             switch (request1->mBits.recipient)
284             {
285                 case USB_REC_INTERFACE:
286
287                     if ( (0x01 == request1->mBits.value_l)
288                             && (0x06 == request1->mBits.value_m))
289                     {
290
291                         usb_EPActive (USB_EP5, USB_EP_DIR_IN);
292                         usb_EPActive (USB_EP6, USB_EP_DIR_OUT);
293                     }
294
295                     EPI0_config (0, 1, FALSE, NULL);
296                     break;
297                 default:
298                     EPI0_config (0, 1, TRUE, NULL);
299                     break;
300             }
301
302             break;
303         case USB_REQ_VENDOR:
304             EPI0_config (4, 1, TRUE, &vendor_ack);
305             break;
306         default:
307             EPI0_config (0, 1, TRUE, NULL);
308             break;
309     }
310
311 }
312 /*****************************************************************************/
313 //  Description:   usb reset interrupt handler.
314 //  Global resource dependence:
315 //  Author:        jiayong.yang
316 //  Note:
317 /*****************************************************************************/
318
319 LOCAL void usb_reset_handler (void)
320 {
321
322     uint32  timeout = 0;
323
324     //SCI_TraceLow("enter usb reset.\r\n");
325
326     * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_12);                          // disable reset interrupt
327
328     * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;                            // set NAK for all OUT endpoint
329
330     * (volatile uint32 *) USB_DOEPCTL (6) |= (unsigned int) BIT_27;
331
332     * (volatile uint32 *) USB_DAINTMSK |= (unsigned int) (BIT_0|BIT_16);
333     * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_2|BIT_1);
334     * (volatile uint32 *) USB_DIEPMSK |= (unsigned int) (BIT_0|BIT_3|BIT_1|BIT_2|BIT_5);//lint !e718
335
336     * (volatile uint32 *) USB_GRXFSIZ = (unsigned int) (BIT_2|BIT_4|BIT_9);                 //RX fifo ,276 Dword,start address is 0
337     * (volatile uint32 *) USB_GNPTXFSIZ = (unsigned int) ( (BIT_2|BIT_4|BIT_9) |BIT_21);    //EP0 TX fifo, 32 Dword, start address is 0+276=276
338     * (volatile uint32 *) USB_DIEPTXF (5) = (unsigned int) ( (BIT_2|BIT_4|BIT_5|BIT_9) |BIT_23); //lint !e718//EP5 TX fifo, 64 Dword, start address is 276+32 = 308
339
340     * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_5;                          //reflush tx fifo
341
342     while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_5))
343     {
344         timeout++;
345
346         if (timeout >= USB_TIMEOUT)
347         {
348             break;
349         }
350     }
351
352     timeout = 0;
353     * (volatile uint32 *) USB_GRSTCTL |= (unsigned int) BIT_4;                          //reflush rx fifo
354
355     while ( (* (volatile uint32 *) USB_GRSTCTL) & ( (unsigned int) BIT_4))
356     {
357         timeout++;
358
359         if (timeout >= USB_TIMEOUT)
360         {
361             break;
362         }
363     }
364
365     Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
366      EPO0_config (TRUE, s_setup_packet);
367
368     * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_12;                             // enable reset interrupt
369
370     * (volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_12;                             //clear reset interrupt
371
372 }
373
374 /*****************************************************************************/
375 //  Description:   usb enumeration done handler.
376 //  Global resource dependence:
377 //  Author:        jiayong.yang
378 //  Note:
379 /*****************************************************************************/
380
381 void usb_enumeration_done (void)
382 {
383     volatile USB_DSTS_U *dsts_ptr = (USB_DSTS_U *) USB_DSTS;
384
385     enum_speed = dsts_ptr->mBits.enumspd;                                   //read enumration speed
386     //SCI_TraceLow("usb_enumeration_done: device_speed = %d\r\n",enum_speed);
387
388     * (volatile uint32 *) USB_DIEP0CTL &= (unsigned int) (~ (BIT_0|BIT_1));
389
390     EPn_config (USB_EP5, USB_EP_TYPE_BULK, USB_EP_DIR_IN, USB_PACKET_64);
391     EPn_config (USB_EP6, USB_EP_TYPE_BULK, USB_EP_DIR_OUT, USB_PACKET_64);
392
393     Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
394     EPO0_config (TRUE, s_setup_packet);
395
396     * (volatile uint32 *) USB_DCTL |= (unsigned int) BIT_8;
397
398     * (volatile uint32 *) USB_GINTSTS |= (unsigned int) BIT_13;
399
400 }
401 /*****************************************************************************/
402 //  Description:    out endpoint6 handler.
403 //  Global resource dependence:
404 //  Author:        jiayong.yang
405 //  Note:
406 /*****************************************************************************/
407 LOCAL void usb_EP6_handle (void)
408 {
409     volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (USB_EP6);
410     volatile USB_DOEPINT_U  doepint;
411     volatile USB_DOEPTSIZ_U *doeptsiz_ptr = (USB_DOEPTSIZ_U *) USB_DOEPTSIZ (USB_EP6);
412     volatile uint32  mask;
413
414     mask = * (volatile uint32 *) USB_DOEPMSK;
415     doepint.dwValue = doepint_ptr->dwValue;
416
417     doepint.dwValue &= (unsigned int) mask;
418
419     if (doepint.mBits.transfer_com)
420     {
421         doepint_ptr->mBits.transfer_com = 1;
422         recv_length = MAX_RECV_LENGTH - doeptsiz_ptr->mBits.transfer_size;
423         Dcache_InvalRegion((unsigned int)(&usb_out_endpoint_buf[currentDmaBufferIndex][0]),  MAX_RECV_LENGTH);
424
425         * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_13;
426         * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_4;
427         * (volatile uint32 *) USB_DOEPMSK &= (unsigned int) (~BIT_0);           
428     }
429     else if (doepint.mBits.nak)
430     {    
431         usb_start_transfer (USB_EP6, USB_EP_DIR_OUT, 1, TRUE, (uint32 *) usb_out_endpoint_buf[currentDmaBufferIndex]);
432         * (volatile uint32 *) USB_DOEPMSK &= (unsigned int) (~BIT_13);
433         * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_0;
434         doepint_ptr->mBits.nak = 0x1;
435
436     }
437     else if (doepint.mBits.bbleerr)
438     {
439         doepint_ptr->mBits.bbleerr = 0x01;
440     }
441 }
442 /*****************************************************************************/
443 //  Description:   out endpoint0 handler.
444 //  Global resource dependence:
445 //  Author:        jiayong.yang
446 //  Note:
447 /*****************************************************************************/
448
449 LOCAL void usb_EP0_out_handle (void)
450 {
451     volatile USB_DOEPINT_U *doepint_ptr = (USB_DOEPINT_U *) USB_DOEPINT (0);
452
453     if (doepint_ptr->mBits.timeout_condi)
454     {
455         usb_setup_handle();
456     }
457
458     if (doepint_ptr->mBits.transfer_com)
459     {
460         * (volatile uint32 *) USB_DOEP0CTL |= (unsigned int) BIT_27;
461         doepint_ptr->mBits.transfer_com = 0x1;
462     }
463
464     if (doepint_ptr->mBits.outtokenfifoemp)
465     {
466         doepint_ptr->mBits.outtokenfifoemp = 0x1;
467     }
468
469     doepint_ptr->dwValue = 0xffffffff;// clear all interrupt
470
471     Dcache_InvalRegion((unsigned int)s_setup_packet, sizeof(s_setup_packet));
472     EPO0_config (TRUE, s_setup_packet); //renable ep0 nd set packet count
473 }
474
475 /*****************************************************************************/
476 //  Description:   out endpoint handler.
477 //  Global resource dependence:
478 //  Author:        jiayong.yang
479 //  Note:
480 /*****************************************************************************/
481 LOCAL void usb_EP_out_handle (void)
482 {
483     volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
484     USB_DAINT_U daint;
485
486     daint.dwValue = daint_ptr->dwValue;         // disable EP out interrupt
487     * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_19);
488
489     if (daint.mBits.outepint_0)
490     {
491         usb_EP0_out_handle();
492     }
493
494     if (daint.mBits.outepint_6)
495     {
496         usb_EP6_handle();
497     }
498
499     * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_19; // enable reset interrupt
500 }
501 /*****************************************************************************/
502 //  Description:   in endpoint handler.
503 //  Global resource dependence:
504 //  Author:        jiayong.yang
505 //  Note:
506 /*****************************************************************************/
507 LOCAL void usb_EP_in_handle (void)
508 {
509     volatile USB_DAINT_U *daint_ptr = (USB_DAINT_U *) USB_DAINT;
510     USB_DAINT_U daint;
511
512
513     * (volatile uint32 *) USB_GINTMSK &= (unsigned int) (~BIT_18); // disable EP in interrupt
514     daint.dwValue = daint_ptr->dwValue;
515
516     if (daint.mBits.inepint_0)
517     {
518         volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (0);
519
520         diepint_ptr->dwValue = 0xFFFFFFFF;
521     }
522
523     if (daint.mBits.inepint_5)
524     {
525         volatile USB_DIEPINT_U *diepint_ptr = (USB_DIEPINT_U *) USB_DIEPINT (5);
526
527         diepint_ptr->dwValue = 0xFFFFFFFF;
528     }
529
530     * (volatile uint32 *) USB_GINTMSK |= (unsigned int) BIT_18; // enable EP in interrupt
531 }
532
533 /*****************************************************************************/
534 //  Description:   usb interrupt handler.
535 //  Global resource dependence:
536 //  Author:        jiayong.yang
537 //  Note:
538 /*****************************************************************************/
539 static __inline void usb_handler (void)
540 {
541     volatile USB_INTSTS_U *usb_int_ptr = (USB_INTSTS_U *) USB_GINTSTS;
542     volatile USB_INTSTS_U  usb_int;
543
544     usb_int.dwValue = usb_int_ptr->dwValue;
545
546     // in endpoint interrupt
547     if (usb_int.mBits.iepint)
548     {
549         usb_EP_in_handle();
550     }
551
552     // out endpoint interrupt
553     if (usb_int.mBits.oepint)
554     {
555         usb_EP_out_handle();
556     }
557
558     // enumeration done interrupt
559     if (usb_int.mBits.enumdone)
560     {
561         usb_enumeration_done();
562     }
563
564     // reset interrupt
565     if (usb_int.mBits.usbrst)
566     {
567         usb_reset_handler();
568     }
569 }
570 /*****************************************************************************/
571 //  Description:   configure in endpoint ep_id to send message.
572 //  Global resource dependence:
573 //  Author:        jiayong.yang
574 //  Note:
575 /*****************************************************************************/
576 #define USB_SEND_MAX_TIME 1000
577 PUBLIC int USB_EPxSendData (char ep_id ,unsigned int *pBuf,    int len)
578 {
579         volatile USB_DIEPTSIZ_U *dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
580         volatile USB_DIEPCTL_U *diepctl_ptr = (USB_DIEPCTL_U *) USB_DIEPCTL (ep_id);
581         uint32 old_tick, new_tick;
582         uint32 split_len = 0;
583         if(len == 0)
584                 return 0;
585         if((len % 64) == 0){
586                 split_len = 32;
587                 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, len - split_len, TRUE, (uint32 *) pBuf);
588                 old_tick = new_tick = SCI_GetTickCount();
589                 while(dieptsiz_ptr->dwValue){
590                         new_tick = SCI_GetTickCount();
591                         if(new_tick - old_tick > USB_SEND_MAX_TIME){
592                                 return 1;
593                         }
594                         dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
595                 }
596                 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, split_len, TRUE, (uint32 *) ((uint32)pBuf + len - split_len));
597         }else{
598                 usb_start_transfer ( (USB_EP_NUM_E) ep_id, USB_EP_DIR_IN, len, TRUE, (uint32 *) pBuf);
599         }
600         old_tick = new_tick = SCI_GetTickCount();
601         while(dieptsiz_ptr->dwValue){
602                 new_tick = SCI_GetTickCount();
603                 if(new_tick - old_tick > USB_SEND_MAX_TIME){
604                         return 1;
605                 }
606                 dieptsiz_ptr = (USB_DIEPTSIZ_U*)USB_DIEPTSIZ(ep_id);
607                 if(diepctl_ptr->mBits.nak_status) {
608                     if(dieptsiz_ptr->mBits.transfer_size ==0)
609                         * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) BIT_26;
610                     else {
611                         * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) BIT_30;
612                         * (volatile uint32 *) USB_DIEPCTL (ep_id) |= (unsigned int) (BIT_31|BIT_26);
613                     }
614                 }
615         }
616         return 0;
617 }
618
619 /*****************************************************************************/
620 //  Description:   initialize the usb core.
621 //  Global resource dependence:
622 //  Author:        jiayong.yang
623 //  Note:
624 /*****************************************************************************/
625 PUBLIC void usb_core_init (void)
626 {
627         * (volatile uint32 *) USB_GAHBCFG |= (unsigned int) BIT_5;
628         * (volatile uint32 *) USB_DOEPMSK |= (unsigned int) BIT_13;
629         readIndex = 0;
630         recv_length = 0;
631         return;
632 }
633
634
635 char VCOM_GetChar (void)
636 {
637
638     if (readIndex == recv_length)
639     {     
640         readIndex = 0;
641         recv_length = 0;
642 REGET:
643         usb_handler();
644                 
645         if (recv_length > 0)
646         {
647             nIndex = currentDmaBufferIndex;
648           //Dcache_InvalRegion((unsigned int)(&usb_out_endpoint_buf[nIndex][0]),  MAX_RECV_LENGTH);
649                         
650             currentDmaBufferIndex ^= 0x1;
651         }
652         else
653         {
654             goto REGET;
655         }
656     }
657
658      return usb_out_endpoint_buf[nIndex][readIndex++];
659 }
660
661 int VCOM_GetSingleChar (void)
662
663     if (readIndex == recv_length)
664     {
665         readIndex = 0;
666         recv_length = 0;
667         
668         usb_handler();
669
670         if (recv_length > 0)
671         {
672                 nIndex = currentDmaBufferIndex;
673                 currentDmaBufferIndex ^= 0x1;
674         }
675         else
676         {
677                 return -1;
678         }
679
680
681         //error_count ++;
682         //printf("readIndex = %d  recv_length = %d  nIndex = %d  error_count = %d\n", readIndex, recv_length, nIndex, error_count);
683
684         /*if ((error_count >= 6583) && (error_count <= 6585)) {
685                 printf("\n");
686                 printf("%s %d  error_count = %d\n", __FUNCTION__, __LINE__, error_count);
687                 for (aaa = 0; aaa < recv_length; aaa ++) {
688                         if ((aaa % 16) == 0)
689                                 printf("\n");
690                         printf(" %02x", usb_out_endpoint_buf[nIndex][aaa]);
691                 }
692                 printf("\n");
693
694         }*/
695     
696     }
697     
698     return (int)usb_out_endpoint_buf[nIndex][readIndex++];
699 }
700
701 int VCOM_Read(const unsigned char* buf, unsigned int len)
702 {
703     unsigned char *src, *dest = buf;
704     unsigned escape_flag = 0;
705
706 loop:
707     if(readIndex == recv_length){
708         readIndex = 0;
709         recv_length = 0;
710 REGET:
711         usb_handler();
712
713         if (recv_length > 0){
714             nIndex = currentDmaBufferIndex;
715             currentDmaBufferIndex ^= 0x1;
716         }else
717             goto REGET;
718     }
719     /* We reach an agreement that host can't send 
720       a packet whose size exceeds MAX_PKT_SIZE;
721     */
722     len = recv_length < len ? recv_length : len;
723     src = usb_out_endpoint_buf[nIndex] + readIndex;
724     /* The last byte is HDLC_FLAG in most cases,
725       so it's picked out from escape process.
726     */
727     for(; readIndex < len - 1; readIndex++, src++)
728     {
729         if(*src == HDLC_ESCAPE){
730             escape_flag = 1;
731             continue;
732         }else if(escape_flag){
733             *dest++ = *src ^ HDLC_ESCAPE_MASK;
734             escape_flag = 0;
735         }else
736             *dest++ = *src;
737     }
738     /* Check whether it's an entire packet,
739         if so exit this function, 
740         otherwise continue to receive data from host.
741     */
742     readIndex++;
743     if(*src == HDLC_FLAG)
744         return dest - buf;
745     if(*src == HDLC_ESCAPE)
746         escape_flag = 1;
747     else if(escape_flag){
748         *dest++ = *src ^ HDLC_ESCAPE_MASK;
749         escape_flag = 0;
750     }else
751         *dest++ = *src;
752     len -= dest - buf;
753     goto loop;
754 }
755