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