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