Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / target / hif / k2_fw_usb_api.c
1 #include "usb_defs.h"
2 #include "usb_type.h"
3 #include "usb_pre.h"
4 #include "usb_extr.h"
5 #include "usb_std.h"
6 #include "reg_defs.h"
7 #include "athos_api.h"
8 #include "usbfifo_api.h"
9
10
11 #include "sys_cfg.h"
12
13 typedef void (* USBFIFO_recv_command)(VBUF *cmd);
14 void _fw_usb_suspend_reboot();
15
16 extern Action      eUsbCxFinishAction;
17 extern CommandType eUsbCxCommand;
18 extern BOOLEAN     UsbChirpFinish;
19 extern USB_FIFO_CONFIG usbFifoConf;
20
21 USBFIFO_recv_command m_origUsbfifoRecvCmd = NULL;
22
23 #if SYSTEM_MODULE_USB
24 #define vUsb_ep0end(void)                                   \
25 {                                                           \
26     eUsbCxCommand = CMD_VOID;                               \
27     USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);   \
28 }
29
30 #define vUsb_ep0fail(void)  USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04)
31
32 #define vUsb_rst()                                              \
33 {                                                               \
34     USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET,                 \
35         (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT1));    \
36     UsbChirpFinish = FALSE;                                     \
37 }
38
39 #define vUsb_suspend()  USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
40                             (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT2))
41
42 #define vUsb_resm() USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET,     \
43                         (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT3))
44
45 void _fw_usbfifo_recv_command(VBUF *buf)
46 {
47     A_UINT8 *cmd_data;
48     A_UINT32 tmp;
49
50     cmd_data = (A_UINT8 *)(buf->desc_list->buf_addr + buf->desc_list->data_offset);
51     tmp = *((A_UINT32 *)cmd_data);
52     if ( tmp == 0xFFFFFFFF ) {
53         _fw_usb_suspend_reboot();
54     } else {
55         m_origUsbfifoRecvCmd(buf);
56     }
57 }
58
59 void _fw_usbfifo_init(USB_FIFO_CONFIG *pConfig)
60 {
61     m_origUsbfifoRecvCmd = pConfig->recv_command;
62
63     usbFifoConf.get_command_buf = pConfig->get_command_buf;
64     usbFifoConf.recv_command    = _fw_usbfifo_recv_command;
65     usbFifoConf.get_event_buf   = pConfig->get_event_buf;
66     usbFifoConf.send_event_done = pConfig->send_event_done;
67 }
68
69 #define CHECK_SOF_LOOP_CNT    50
70
71 void _fw_usb_suspend_reboot()
72 {
73     volatile uint32_t gpio_in = 0;
74     volatile uint32_t pupd = 0;
75     volatile uint32_t t = 0;
76     volatile uint32_t sof_no=0,sof_no_new=0;
77     /* Set GO_TO_SUSPEND bit to USB main control register */
78     vUsb_suspend();
79     A_PRINTF("!USB suspend\n\r");
80
81     // keep the record of suspend
82 #if defined(PROJECT_MAGPIE)
83     *((volatile uint32_t*)WATCH_DOG_MAGIC_PATTERN_ADDR) = SUS_MAGIC_PATTERN;
84 #elif defined(PROJECT_K2)
85     HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
86 #endif /* #if defined(PROJECT_MAGPIE) */
87
88     /* Reset USB FIFO */
89     A_USB_RESET_FIFO();
90
91     /* Turn off power */
92     A_USB_POWER_OFF();
93
94     DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1000;
95
96     // reset ep3/ep4 fifo in case there is data which might affect resuming
97 //  HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
98 //  HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100af)|0x10));
99
100     {
101         // config gpio to input before goto suspend
102
103         //disable JTAG/ICE
104         //jtag = HAL_WORD_REG_READ(0x10004054);
105         //HAL_WORD_REG_WRITE(0x10004054, (jtag|BIT17));
106                 
107                 //disable SPI
108         //spi = HAL_WORD_REG_READ(0x50040);
109         //HAL_WORD_REG_WRITE(0x50040, (spi&~(BIT8)));
110                 
111                 //set all GPIO to input
112         gpio_in = HAL_WORD_REG_READ(0x1000404c);
113         HAL_WORD_REG_WRITE(0x100404c, 0x0);
114                 
115                 //set PU/PD for all GPIO except two UART pins
116         pupd = HAL_WORD_REG_READ(0x10004088);
117         HAL_WORD_REG_WRITE(0x10004088, 0xA982AA6A);
118     }
119
120     sof_no= HAL_WORD_REG_READ(0x10004); 
121     for (t = 0; t < CHECK_SOF_LOOP_CNT; t++)
122     {
123         A_DELAY_USECS(1000);    //delay 1ms     
124         sof_no_new = HAL_WORD_REG_READ(0x10004);
125
126         if(sof_no_new == sof_no)
127             break; 
128
129         sof_no = sof_no_new;      
130     } 
131     
132     /* 
133      * Reset "printf" module patch point(RAM to ROM) when K2 warm start or suspend,  
134      * which fixed the error issue cause by redownload another different firmware. 
135      */
136     _indir_tbl.cmnos.printf._printf = save_cmnos_printf;
137     
138     ///////////////////////////////////////////////////////////////
139     // setting the go suspend here, power down right away...
140     if (t != CHECK_SOF_LOOP_CNT)   // not time out
141         HAL_WORD_REG_WRITE(0x10000, HAL_WORD_REG_READ(0x10000)|(0x8));
142     ///////////////////////////////////////////////////////////////
143
144     DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1100;
145
146 #if 0 // pll unstable, h/w bug?
147     HAL_WORD_REG_WRITE(0x50040, (0x300|6|(1>>1)<<12));
148     A_UART_HWINIT((40*1000*1000)/1, 19200);
149 #endif
150     {
151         // restore gpio setting
152         //HAL_WORD_REG_WRITE(0x10004054, jtag);
153         //HAL_WORD_REG_WRITE(0x50040, spi);
154         HAL_WORD_REG_WRITE(0x1000404c, gpio_in);
155         HAL_WORD_REG_WRITE(0x10004088, pupd);
156     }
157     DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1200;
158
159     {
160         // since we still need to touch mac_base address after resuming back, so that
161         // reset mac can't be done in ResetFifo function, move to here... 
162         // whole mac control reset.... (bit1)
163         HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, (BIT1) );
164         HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)|BIT0));
165         HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0 );
166     }
167
168     //A_PRINTF("reg(0x10020)=(%x)\n", HAL_WORD_REG_READ(0x10020));
169     // disable ep3 int enable, so that resume back won't send wdt magic pattern out!!!
170     mUSB_STATUS_IN_INT_DISABLE();            
171
172     MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
173     MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
174     MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
175     MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
176
177     if (((DEBUG_SYSTEM_STATE&~(0x0000ffff))>>16 == 0x5342)) {
178         /* UART_SEL and SPI_SEL */
179         HAL_WORD_REG_WRITE(0x50040, (0x300|0|(1>>1)<<12));
180     }
181
182     /* Jump to boot code */
183     A_USB_JUMP_BOOT();
184
185 }
186
187 /*
188  * -- patch usb_fw_task --
189  * . usb zero length interrupt should not clear by s/w, h/w will handle that
190  * . complete suspend handle, configure gpio, turn off related function, 
191  *   slow down the pll for stable issue
192  */
193 void _fw_usb_fw_task(void)
194 {
195     register uint8_t usb_interrupt_level1;
196     register uint8_t usb_interrupt_level2;
197
198     usb_interrupt_level1 = USB_BYTE_REG_READ(ZM_INTR_GROUP_OFFSET);
199 #if 0 // these endpoints are handled by DMA
200     if (usb_interrupt_level1 & BIT5)            //Group Byte 5
201     {
202         vUsb_Data_In();
203     }
204 #endif
205     if (usb_interrupt_level1 & BIT4)
206     {
207         usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_4_OFFSET);
208         if( usb_interrupt_level2 & BIT6)
209             A_USB_REG_OUT();//vUsb_Reg_Out();
210     }
211
212     if (usb_interrupt_level1 & BIT6)
213     {
214         //zfGenWatchDogEvent();
215     usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_6_OFFSET);
216         if( usb_interrupt_level2 & BIT6)
217              A_USB_STATUS_IN();//vUsb_Status_In();
218     }
219
220     if (usb_interrupt_level1 & BIT0)            //Group Byte 0
221     {
222         //usb_interrupt_level2 = ZM_INTR_SOURCE_0_REG;
223         usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET);
224
225         // refer to FUSB200, p 48, offset:21H, bit7 description, should clear the command abort interrupt first!?
226         if (usb_interrupt_level2 & BIT7)
227         {
228             //ZM_INTR_SOURCE_0_REG &= 0x7f;       // Handle command abort
229             USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_0_OFFSET, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET)& ~BIT7));
230             A_PRINTF("![SOURCE_0] bit7 on\n\r");
231         }
232
233         if (usb_interrupt_level2 & BIT1)
234         {
235             //A_PRINTF("![USB] ep0 IN in \n\r");
236             A_USB_EP0_TX();                       // USB EP0 tx interrupt
237         }
238         if (usb_interrupt_level2 & BIT2)
239         {
240             //A_PRINTF("![USB] ep0 OUT in\n\r");
241             A_USB_EP0_RX();                       // USB EP0 rx interrupt
242         }
243         if (usb_interrupt_level2 & BIT0)
244         {
245             //A_PRINTF("![USB] ep0 SETUP in\n\r");
246             A_USB_EP0_SETUP();
247             //vWriteUSBFakeData();
248         }
249 //        else if (usb_interrupt_level2 & BIT3)
250         if (usb_interrupt_level2 & BIT3)
251         {
252             vUsb_ep0end();
253 //            A_PRINTF("![SOURCE_0] ep0 CMD_END\n\r");
254         }
255         if (usb_interrupt_level2 & BIT4)
256         {
257             vUsb_ep0fail();
258 //            A_PRINTF("![SOURCE_0] ep0 CMD_FAIL\n\r");
259         }
260         if (eUsbCxFinishAction == ACT_STALL)
261         {
262             // set CX_STL to stall Endpoint0 & will also clear FIFO0
263             USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
264 //            A_PRINTF("![USB] ZM_CX_CONFIG_STATUS_REG = 0x04\n\r");
265         }
266         else if (eUsbCxFinishAction == ACT_DONE)
267         {
268             // set CX_DONE to indicate the transmistion of control frame
269             USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
270         }
271         eUsbCxFinishAction = ACT_IDLE;
272     }
273
274     if (usb_interrupt_level1 & BIT7)            //Group Byte 7
275     {
276         //usb_interrupt_level2 = ZM_INTR_SOURCE_7_REG;
277         usb_interrupt_level2 = USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET);
278
279 #if 0
280         if (usb_interrupt_level2 & BIT7)
281         {
282             vUsb_Data_Out0Byte();
283 //            A_PRINTF("![SOURCE_7] bit7 on, clear it\n\r");
284         }
285         if (usb_interrupt_level2 & BIT6)
286         {
287             vUsb_Data_In0Byte();
288 //            A_PRINTF("![SOURCE_7] bit6 on, clear it\n\r");
289         }
290 #endif
291         
292         if (usb_interrupt_level2 & BIT1)
293         {
294             vUsb_rst();
295             //USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_REG, (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~0x2));
296             A_PRINTF("!USB reset\n\r");
297 //            A_PRINTF("![0x1012c]: %\n\r", USB_WORD_REG_READ(0x12c));
298         }
299         if (usb_interrupt_level2 & BIT2)
300         {
301            // TBD: the suspend resume code should put here, Ryan, 07/18
302            //
303            //  issue, jump back to rom code and what peripherals should we reset here?
304            //
305            _fw_usb_suspend_reboot();            
306         }
307         if (usb_interrupt_level2 & BIT3)
308         {
309             vUsb_resm();
310             A_PRINTF("!USB resume\n\r");
311         }
312     }
313
314 }
315
316
317 void _fw_usb_reset_fifo(void)
318 {
319     volatile uint32_t   *reg_data;
320
321     HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
322     HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100af)|0x10));
323
324     // disable ep3 int enable, so that resume back won't send wdt magic pattern out!!!
325     mUSB_STATUS_IN_INT_DISABLE();
326
327     // update magic pattern to indicate this is a suspend
328     // k2: MAGPIE_REG_RST_WDT_TIMER_CTRL_ADDR
329     // magpie: MAGPIE_REG_RST_STATUS_ADDR
330     HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
331
332     /*
333      * Before USB suspend, USB DMA must be reset(refer to Otus)
334      * Otus runs the following statements only
335      * HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT0|BIT2 );
336      * HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0 );
337      * K2 must run the following statements additionally
338      * reg_data = (A_UINT32 *)(USB_CTRL_BASE_ADDRESS + 0x118);
339      * *reg_data = 0x00000000;
340      * *reg_data = 0x00000001;
341      * because of Hardware bug in K2
342      */
343     reg_data = (uint32_t *)(USB_CTRL_BASE_ADDRESS + 0x118);
344     *reg_data = 0x00000000;
345
346     // reset both usb(bit2)/wlan(bit1) dma
347     HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, (BIT2) );
348     HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, (HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)|BIT0));
349     HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0 );
350
351     *reg_data = 0x00000001;
352
353     /* MAC warem reset */
354     //reg_data = (uint32_t *)(K2_REG_MAC_BASE_ADDR + 0x7000);
355     //*reg_data = 0x00000001;
356
357     //A_DELAY_USECS(1);
358
359     //*reg_data = 0x00000000;
360
361     //while (*reg_data)   ;
362
363     A_PRINTF("\n change clock to 22 and go to suspend now!");
364     
365     /* UART_SEL */
366     HAL_WORD_REG_WRITE(0x50040, (0x200|0|(1>>1)<<12));
367     A_UART_HWINIT((22*1000*1000), 19200);
368 }
369
370 /*
371  * -- support more than 64 bytes command on ep4 -- 
372  */
373 void vUsb_Reg_Out_patch(void)
374 {   
375     uint16_t usbfifolen;
376     uint16_t ii;
377     uint32_t ep4_data;
378     static volatile uint32_t *regaddr;    // = (volatile uint32_t *) ZM_CMD_BUFFER;
379     static uint16_t cmdLen;
380     static VBUF *buf;
381     BOOLEAN cmd_is_last = FALSE;
382     static BOOLEAN cmd_is_new = TRUE;
383
384     // get the size of this transcation
385     usbfifolen = USB_BYTE_REG_READ(ZM_EP4_BYTE_COUNT_LOW_OFFSET);
386
387     // check is command is new
388     if( cmd_is_new ){
389
390         buf = usbFifoConf.get_command_buf();
391         cmdLen = 0;
392     
393         if( !buf )
394             goto ERR;
395     
396         // copy free, assignment buffer of the address
397         regaddr = (uint32_t *)buf->desc_list->buf_addr;
398
399         cmd_is_new = FALSE;
400     }
401     
402     // just in case, suppose should not happen
403     if( !buf )
404         goto ERR;
405     
406     // if size is smaller, this is the last command!
407     //
408     // zero-length supposed should be set through 0x27/bit7->0x19/bit4, not here
409     //
410     if( usbfifolen<bUSB_EP_MAX_PKT_SIZE_64 ) {
411         cmd_is_last = TRUE;
412     }
413     
414     // accumulate the size
415     cmdLen += usbfifolen;
416     
417     // round it to alignment
418     if(usbfifolen % 4)
419         usbfifolen = (usbfifolen >> 2) + 1;
420     else
421         usbfifolen = usbfifolen >> 2;
422     
423 //    A_PRINTF("copy data out from fifo to - %p\n\r", regaddr);
424     // retrieve the data from fifo
425     for(ii = 0; ii < usbfifolen; ii++)
426     {
427         ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
428         *regaddr = ep4_data;
429         regaddr++;
430     }
431     
432     // if this is the last command, callback to HTC
433     if (  cmd_is_last  )
434     {
435         buf->desc_list->next_desc = NULL;
436         buf->desc_list->data_offset = 0;
437         buf->desc_list->data_size = cmdLen;
438         buf->desc_list->control = 0;
439         buf->next_buf = NULL;
440         buf->buf_length = cmdLen;
441     
442         usbFifoConf.recv_command(buf);
443
444         cmd_is_new = TRUE;
445     }
446
447     goto DONE;
448 ERR:
449 //    we might get no command buffer here?
450 //    but if we return here, the ep4 fifo will be lock out,
451 //    so that we still read them out but just drop it ?
452     for(ii = 0; ii < usbfifolen; ii++)
453     {
454         ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
455     }
456
457 DONE:
458     //mUSB_STATUS_IN_INT_ENABLE();
459     ;
460 }
461
462
463
464 /* 
465  *  -- usb1.1 ep6 fix --
466  */
467 extern uint16_t       u8UsbConfigValue;
468 extern uint16_t       u8UsbInterfaceValue;
469 extern uint16_t       u8UsbInterfaceAlternateSetting;
470 extern SetupPacket    ControlCmd;
471 extern void vUsbClrEPx(void);
472
473 void vUSBFIFO_EP6Cfg_FS_patch(void)
474 {
475 #if (FS_C1_I0_A0_EP_NUMBER >= 6)
476     int i;
477
478     //EP0X06
479     mUsbEPMap(EP6, FS_C1_I0_A0_EP6_MAP);
480     mUsbFIFOMap(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_MAP);
481     mUsbFIFOConfig(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_CONFIG);
482
483     for(i = FS_C1_I0_A0_EP6_FIFO_START + 1 ;
484         i < FS_C1_I0_A0_EP6_FIFO_START + FS_C1_I0_A0_EP6_FIFO_NO ; i ++)
485     {
486         mUsbFIFOConfig(i, (FS_C1_I0_A0_EP6_FIFO_CONFIG & (~BIT7)) );
487     }
488                             
489     mUsbEPMxPtSzHigh(EP6, FS_C1_I0_A0_EP6_DIRECTION, (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
490     mUsbEPMxPtSzLow(EP6, FS_C1_I0_A0_EP6_DIRECTION, (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
491     mUsbEPinHighBandSet(EP6 , FS_C1_I0_A0_EP6_DIRECTION, FS_C1_I0_A0_EP6_MAX_PACKET);
492 #endif
493 }
494
495 void vUsbFIFO_EPxCfg_FS_patch(void)
496 {
497     switch (u8UsbConfigValue)
498     {
499         #if (FS_CONFIGURATION_NUMBER >= 1)
500         // Configuration 0X01
501         case 0X01:
502             switch (u8UsbInterfaceValue)
503             {
504                 #if (FS_C1_INTERFACE_NUMBER >= 1)
505                 // Interface 0
506                 case 0:
507                     switch (u8UsbInterfaceAlternateSetting)
508                     {
509
510                         #if (FS_C1_I0_ALT_NUMBER >= 1)
511                         // AlternateSetting 0
512                         case 0:
513
514                                                         // snapped....
515
516                                                         // patch up this ep6_fs config
517                             vUSBFIFO_EP6Cfg_FS_patch();
518
519                             break;
520
521                         #endif
522                         default:
523                             break;
524                     }
525                     break;
526                 #endif
527                 default:
528                     break;
529             }
530             break;
531         #endif
532         default:
533             break;
534     }
535     //mCHECK_STACK();
536 }
537
538
539 BOOLEAN bSet_configuration_patch(void)
540 {
541     //A_PRINTF("bSet_configuration...\n\r");
542
543         bSet_configuration();
544
545     if (mLOW_BYTE(mDEV_REQ_VALUE()) == 0)
546     {
547                 // snapped....
548                 ;
549     }
550     else
551     {
552         if (mUsbHighSpeedST())                  // First judge HS or FS??
553         {
554                         // snapped....
555                         ;
556         }
557         else
558         {
559                         // snapped....
560                         vUsbFIFO_EPxCfg_FS_patch();
561         }
562             
563                 // snapped....
564     }
565
566     eUsbCxFinishAction = ACT_DONE;
567     return TRUE;
568 }
569
570
571 /*
572  * -- support more than 64 bytes command on ep3 -- 
573  */
574 void vUsb_Status_In_patch(void)
575 {
576     uint16_t count;
577     uint16_t remainder;
578     u16_t RegBufLen;
579     BOOLEAN cmdEnd = FALSE;
580
581     static u16_t mBufLen;
582     static VBUF *evntbuf = NULL;
583     static volatile u32_t *regaddr;
584     static BOOLEAN cmd_is_new = TRUE;
585
586     if( cmd_is_new )
587     {
588         evntbuf = usbFifoConf.get_event_buf();
589         if ( evntbuf != NULL )
590         {
591             regaddr = VBUF_GET_DATA_ADDR(evntbuf);
592             mBufLen = evntbuf->buf_length;
593         }
594         else
595         {
596             mUSB_STATUS_IN_INT_DISABLE();
597             goto ERR_DONE;
598         }
599     
600     }
601
602 //    if( mBufLen>bUSB_EP_MAX_PKT_SIZE_64 )
603 //        A_PRINTF("EP3 send %d bytes to host \n", mBufLen);
604
605 //    while(1)
606     {
607         if( mBufLen > bUSB_EP_MAX_PKT_SIZE_64 ) {
608             RegBufLen = bUSB_EP_MAX_PKT_SIZE_64;
609             mBufLen -= bUSB_EP_MAX_PKT_SIZE_64;
610         }
611         // TODO: 64 byes... controller supposed will take care of zero-length?
612         else {
613             RegBufLen = mBufLen;
614             cmdEnd = TRUE;
615         }
616
617         /* INT use EP3 */
618         for(count = 0; count < (RegBufLen / 4); count++)
619         {
620             USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
621             regaddr++;
622         }
623         
624         remainder = RegBufLen % 4;
625         
626         if (remainder)
627         {
628             switch(remainder)
629             {
630             case 3:
631                 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
632                 break;
633             case 2:
634                 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
635                 break;
636             case 1:
637                 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
638                 break;
639             }
640         
641             USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
642
643             // Restore CBus FIFO size to word size            
644             USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
645         }
646
647         mUSB_EP3_XFER_DONE();
648         
649 //        if( mBufLen<=bUSB_EP_MAX_PKT_SIZE_64 )
650 //            break;   
651     }
652
653     if ( evntbuf != NULL && cmdEnd )
654     {
655         usbFifoConf.send_event_done(evntbuf);
656         cmd_is_new = TRUE;
657     }
658     
659 ERR_DONE:
660     ;
661 }
662
663 extern uint16_t *u8ConfigDescriptorEX;
664 extern uint16_t *pu8DescriptorEX;
665 extern uint16_t u16TxRxCounter;
666 extern BOOLEAN bGet_descriptor(void);
667
668 uint16_t ConfigDescriptorPatch[30];
669
670 #define EP3_TRANSFER_TYPE_OFFSET    17
671 #define EP3_INT_INTERVAL            19
672 #define EP4_TRANSFER_TYPE_OFFSET    21
673 #define EP4_INT_INTERVAL            22
674
675 BOOLEAN bGet_descriptor_patch(void)
676 {
677     if (mDEV_REQ_VALUE_HIGH() == 2) {
678         uint8_t *p = (uint8_t *)u8ConfigDescriptorEX;
679
680         /* Copy ConfigDescriptor */
681         memcpy(ConfigDescriptorPatch, p, sizeof(ConfigDescriptorPatch));
682
683         p = (uint8_t *)ConfigDescriptorPatch;
684
685         /* Patch the transfer type of EP3 and EP4 */
686         ConfigDescriptorPatch[EP3_TRANSFER_TYPE_OFFSET] = 0x0283;
687         ConfigDescriptorPatch[EP3_INT_INTERVAL] = 0x0700;
688         ConfigDescriptorPatch[EP4_TRANSFER_TYPE_OFFSET] = 0x4002;
689         ConfigDescriptorPatch[EP4_INT_INTERVAL] = 0x00;
690
691         switch (mDEV_REQ_VALUE_LOW())
692         {
693         case 0x00:      // configuration no: 0
694             pu8DescriptorEX = ConfigDescriptorPatch;
695             u16TxRxCounter = ConfigDescriptorPatch[1];
696             //u16TxRxCounter = 46;
697             break;
698         default:
699             return FALSE;
700         }
701
702         if (u16TxRxCounter > mDEV_REQ_LENGTH())
703             u16TxRxCounter = mDEV_REQ_LENGTH();
704
705         A_USB_EP0_TX_DATA();
706         return TRUE;
707     }
708     else {
709         return bGet_descriptor();
710     }
711 }
712
713 extern BOOLEAN bStandardCommand(void);
714
715 BOOLEAN bStandardCommand_patch(void)
716 {
717     if (mDEV_REQ_REQ() == USB_SET_CONFIGURATION) {
718         A_USB_SET_CONFIG();
719
720 #if ENABLE_SWAP_DATA_MODE
721         // SWAP FUNCTION should be enabled while DMA engine is not working,
722         // the best place to enable it is before we trigger the DMA
723         MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
724         MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
725
726         #if SYSTEM_MODULE_HP_EP5
727             MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
728         #endif
729
730         #if SYSTEM_MODULE_HP_EP6
731             MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
732         #endif
733
734 #endif //ENABLE_SWAP_DATA_MODE
735         return TRUE;
736     }
737     else {
738         return bStandardCommand();
739     }
740 }
741
742 #endif
743
744