b725c750a11dc276299cd82d7fecbd50e61d8493
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2870 / 2870_main_dev.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27     Module Name:
28     rtmp_main.c
29
30     Abstract:
31     main initialization routines
32
33     Revision History:
34     Who         When            What
35     --------    ----------      ----------------------------------------------
36     Name        Date            Modification logs
37     Jan Lee             01-10-2005          modified
38         Sample          Jun/01/07               Merge RT2870 and RT2860 drivers.
39 */
40
41 #include "rt_config.h"
42
43
44 // Following information will be show when you run 'modinfo'
45 // *** If you have a solution for the bug in current version of driver, please mail to me.
46 // Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
47 MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
48 MODULE_DESCRIPTION(RT28xx_CHIP_NAME " Wireless LAN Linux Driver");
49 MODULE_LICENSE("GPL");
50 #ifdef MODULE_VERSION
51 MODULE_VERSION(STA_DRIVER_VERSION);
52 #endif
53
54 /* Kernel thread and vars, which handles packets that are completed. Only
55  * packets that have a "complete" function are sent here. This way, the
56  * completion is run out of kernel context, and doesn't block the rest of
57  * the stack. */
58
59 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
60                                                                         IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
61
62 struct usb_device_id rtusb_usb_id[] = {
63         { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */
64         { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
65         { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
66         { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
67         { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
68 #ifdef RT30xx
69         { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
70         { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
71 #endif
72         { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */
73         { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */
74         { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */
75         { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */
76         { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */
77         { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */
78 #ifdef RT30xx
79         { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
80 #endif
81         { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
82         { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
83         { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
84         { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
85         { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
86         { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
87         { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
88         { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
89         { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
90         { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
91 #ifdef RT30xx
92         { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
93         { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
94 #endif
95         { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
96         { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
97         { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
98         { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
99         { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
100         { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */
101         { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */
102         { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */
103         { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */
104         { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */
105         { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */
106         { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */
107 #ifdef RT30xx
108         { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
109 #endif
110         { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
111         { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
112         { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
113 #ifdef RT30xx
114         { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
115         { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
116 #endif
117         { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
118 #ifdef RT30xx
119         { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
120 #endif
121         { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */
122         { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */
123         { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */
124         { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */
125         { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */
126 #ifdef RT30xx
127         { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
128 #endif
129         { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
130         { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
131         { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
132 #ifdef RT30xx
133         { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
134 #endif
135         { USB_DEVICE(0x083A, 0x6618) }, /* Accton */
136         { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */
137         { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */
138         { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */
139         { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */
140         { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */
141         { USB_DEVICE(0x050d, 0x805c) },
142         { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/
143         { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */
144         { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */
145         { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */
146         { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */
147         { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
148         { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
149 #ifdef RT30xx
150         { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
151 #endif
152         { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
153         { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
154         { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
155 #ifdef RT30xx
156         { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
157 #endif
158         { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
159         { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
160         { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
161         { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
162 #ifdef RT30xx
163         { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
164         { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
165 #endif
166         { } /* Terminating entry */
167 };
168
169 INT const               rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
170 MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
171
172 #ifndef PF_NOFREEZE
173 #define PF_NOFREEZE  0
174 #endif
175
176
177 #ifdef CONFIG_PM
178 static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
179 static int rt2870_resume(struct usb_interface *intf);
180 #endif // CONFIG_PM //
181
182 /**************************************************************************/
183 /**************************************************************************/
184 //tested for kernel 2.6series
185 /**************************************************************************/
186 /**************************************************************************/
187 static int rtusb_probe (struct usb_interface *intf,
188                                                 const struct usb_device_id *id);
189 static void rtusb_disconnect(struct usb_interface *intf);
190
191 struct usb_driver rtusb_driver = {
192         .name="rt2870",
193         .probe=rtusb_probe,
194         .disconnect=rtusb_disconnect,
195         .id_table=rtusb_usb_id,
196
197 #ifdef CONFIG_PM
198         suspend:        rt2870_suspend,
199         resume:         rt2870_resume,
200 #endif
201         };
202
203 #ifdef CONFIG_PM
204
205 VOID RT2860RejectPendingPackets(
206         IN      PRTMP_ADAPTER   pAd)
207 {
208         // clear PS packets
209         // clear TxSw packets
210 }
211
212 static int rt2870_suspend(
213         struct usb_interface *intf,
214         pm_message_t state)
215 {
216         struct net_device *net_dev;
217         PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
218
219
220         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
221         net_dev = pAd->net_dev;
222         netif_device_detach (net_dev);
223
224         pAd->PM_FlgSuspend = 1;
225         if (netif_running(net_dev)) {
226                 RTUSBCancelPendingBulkInIRP(pAd);
227                 RTUSBCancelPendingBulkOutIRP(pAd);
228         }
229         DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
230         return 0;
231 }
232
233 static int rt2870_resume(
234         struct usb_interface *intf)
235 {
236         struct net_device *net_dev;
237         PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
238
239
240         DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
241
242         pAd->PM_FlgSuspend = 0;
243         net_dev = pAd->net_dev;
244         netif_device_attach (net_dev);
245         netif_start_queue(net_dev);
246         netif_carrier_on(net_dev);
247         netif_wake_queue(net_dev);
248
249         DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
250         return 0;
251 }
252 #endif // CONFIG_PM //
253
254
255 // Init driver module
256 INT __init rtusb_init(void)
257 {
258         printk("rtusb init --->\n");
259         return usb_register(&rtusb_driver);
260 }
261
262 // Deinit driver module
263 VOID __exit rtusb_exit(void)
264 {
265         usb_deregister(&rtusb_driver);
266         printk("<--- rtusb exit\n");
267 }
268
269 module_init(rtusb_init);
270 module_exit(rtusb_exit);
271
272
273
274
275 /*--------------------------------------------------------------------- */
276 /* function declarations                                                                                                */
277 /*--------------------------------------------------------------------- */
278
279 /*
280 ========================================================================
281 Routine Description:
282     MLME kernel thread.
283
284 Arguments:
285         *Context                        the pAd, driver control block pointer
286
287 Return Value:
288     0                                   close the thread
289
290 Note:
291 ========================================================================
292 */
293 INT MlmeThread(
294         IN void *Context)
295 {
296         PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
297         POS_COOKIE      pObj;
298         int status;
299
300         pObj = (POS_COOKIE)pAd->OS_Cookie;
301
302         rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
303
304         while (pAd->mlme_kill == 0)
305         {
306                 /* lock the device pointers */
307                 //down(&(pAd->mlme_semaphore));
308                 status = down_interruptible(&(pAd->mlme_semaphore));
309
310                 /* lock the device pointers , need to check if required*/
311                 //down(&(pAd->usbdev_semaphore));
312
313                 if (!pAd->PM_FlgSuspend)
314                 MlmeHandler(pAd);
315
316                 /* unlock the device pointers */
317                 //up(&(pAd->usbdev_semaphore));
318                 if (status != 0)
319                 {
320                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
321                         break;
322                 }
323         }
324
325         /* notify the exit routine that we're actually exiting now
326          *
327          * complete()/wait_for_completion() is similar to up()/down(),
328          * except that complete() is safe in the case where the structure
329          * is getting deleted in a parallel mode of execution (i.e. just
330          * after the down() -- that's necessary for the thread-shutdown
331          * case.
332          *
333          * complete_and_exit() goes even further than this -- it is safe in
334          * the case that the thread of the caller is going away (not just
335          * the structure) -- this is necessary for the module-remove case.
336          * This is important in preemption kernels, which transfer the flow
337          * of execution immediately upon a complete().
338          */
339         DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
340
341         pObj->MLMEThr_pid = NULL;
342
343         complete_and_exit (&pAd->mlmeComplete, 0);
344         return 0;
345
346 }
347
348
349 /*
350 ========================================================================
351 Routine Description:
352     USB command kernel thread.
353
354 Arguments:
355         *Context                        the pAd, driver control block pointer
356
357 Return Value:
358     0                                   close the thread
359
360 Note:
361 ========================================================================
362 */
363 INT RTUSBCmdThread(
364         IN void * Context)
365 {
366         PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)Context;
367         POS_COOKIE              pObj;
368         int status;
369
370         pObj = (POS_COOKIE)pAd->OS_Cookie;
371
372         rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
373
374         NdisAcquireSpinLock(&pAd->CmdQLock);
375         pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
376         NdisReleaseSpinLock(&pAd->CmdQLock);
377
378         while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
379         {
380                 /* lock the device pointers */
381                 //down(&(pAd->RTUSBCmd_semaphore));
382                 status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
383
384                 if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
385                         break;
386
387                 if (status != 0)
388                 {
389                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
390                         break;
391                 }
392                 /* lock the device pointers , need to check if required*/
393                 //down(&(pAd->usbdev_semaphore));
394
395                 if (!pAd->PM_FlgSuspend)
396                 CMDHandler(pAd);
397
398                 /* unlock the device pointers */
399                 //up(&(pAd->usbdev_semaphore));
400         }
401
402         if (!pAd->PM_FlgSuspend)
403         {       // Clear the CmdQElements.
404                 CmdQElmt        *pCmdQElmt = NULL;
405
406                 NdisAcquireSpinLock(&pAd->CmdQLock);
407                 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
408                 while(pAd->CmdQ.size)
409                 {
410                         RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
411                         if (pCmdQElmt)
412                         {
413                                 if (pCmdQElmt->CmdFromNdis == TRUE)
414                                 {
415                                         if (pCmdQElmt->buffer != NULL)
416                                                 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
417
418                                         NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
419                                 }
420                                 else
421                                 {
422                                         if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
423                                                 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
424                             {
425                                                 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
426                                         }
427                                 }
428                         }
429                 }
430
431                 NdisReleaseSpinLock(&pAd->CmdQLock);
432         }
433         /* notify the exit routine that we're actually exiting now
434          *
435          * complete()/wait_for_completion() is similar to up()/down(),
436          * except that complete() is safe in the case where the structure
437          * is getting deleted in a parallel mode of execution (i.e. just
438          * after the down() -- that's necessary for the thread-shutdown
439          * case.
440          *
441          * complete_and_exit() goes even further than this -- it is safe in
442          * the case that the thread of the caller is going away (not just
443          * the structure) -- this is necessary for the module-remove case.
444          * This is important in preemption kernels, which transfer the flow
445          * of execution immediately upon a complete().
446          */
447         DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
448
449         pObj->RTUSBCmdThr_pid = NULL;
450
451         complete_and_exit (&pAd->CmdQComplete, 0);
452         return 0;
453
454 }
455
456
457 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
458 {
459         int status;
460         RALINK_TIMER_STRUCT     *pTimer;
461         RT2870_TIMER_ENTRY      *pEntry;
462         unsigned long   irqFlag;
463
464         while(!pAd->TimerFunc_kill)
465         {
466 //              printk("waiting for event!\n");
467                 pTimer = NULL;
468
469                 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
470
471                 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
472                         break;
473
474                 // event happened.
475                 while(pAd->TimerQ.pQHead)
476                 {
477                         RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
478                         pEntry = pAd->TimerQ.pQHead;
479                         if (pEntry)
480                         {
481                                 pTimer = pEntry->pRaTimer;
482
483                                 // update pQHead
484                                 pAd->TimerQ.pQHead = pEntry->pNext;
485                                 if (pEntry == pAd->TimerQ.pQTail)
486                                         pAd->TimerQ.pQTail = NULL;
487
488                                 // return this queue entry to timerQFreeList.
489                                 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
490                                 pAd->TimerQ.pQPollFreeList = pEntry;
491                         }
492                         RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
493
494                         if (pTimer)
495                         {
496                                 if (pTimer->handle != NULL)
497                                 if (!pAd->PM_FlgSuspend)
498                                         pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
499                                 if ((pTimer->Repeat) && (pTimer->State == FALSE))
500                                         RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
501                         }
502                 }
503
504                 if (status != 0)
505                 {
506                         pAd->TimerQ.status = RT2870_THREAD_STOPED;
507                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
508                         break;
509                 }
510         }
511 }
512
513
514 INT TimerQThread(
515         IN OUT PVOID Context)
516 {
517         PRTMP_ADAPTER   pAd;
518         POS_COOKIE      pObj;
519
520         pAd = (PRTMP_ADAPTER)Context;
521         pObj = (POS_COOKIE) pAd->OS_Cookie;
522
523         rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
524
525         RT2870_TimerQ_Handle(pAd);
526
527         /* notify the exit routine that we're actually exiting now
528          *
529          * complete()/wait_for_completion() is similar to up()/down(),
530          * except that complete() is safe in the case where the structure
531          * is getting deleted in a parallel mode of execution (i.e. just
532          * after the down() -- that's necessary for the thread-shutdown
533          * case.
534          *
535          * complete_and_exit() goes even further than this -- it is safe in
536          * the case that the thread of the caller is going away (not just
537          * the structure) -- this is necessary for the module-remove case.
538          * This is important in preemption kernels, which transfer the flow
539          * of execution immediately upon a complete().
540          */
541         DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
542
543         pObj->TimerQThr_pid = NULL;
544
545         complete_and_exit(&pAd->TimerQComplete, 0);
546         return 0;
547
548 }
549
550
551 RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
552         IN RTMP_ADAPTER *pAd,
553         IN RALINK_TIMER_STRUCT *pTimer)
554 {
555         RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
556         unsigned long irqFlags;
557
558
559         RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
560         if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
561         {
562                 if(pAd->TimerQ.pQPollFreeList)
563                 {
564                         pQNode = pAd->TimerQ.pQPollFreeList;
565                         pAd->TimerQ.pQPollFreeList = pQNode->pNext;
566
567                         pQNode->pRaTimer = pTimer;
568                         pQNode->pNext = NULL;
569
570                         pQTail = pAd->TimerQ.pQTail;
571                         if (pAd->TimerQ.pQTail != NULL)
572                                 pQTail->pNext = pQNode;
573                         pAd->TimerQ.pQTail = pQNode;
574                         if (pAd->TimerQ.pQHead == NULL)
575                                 pAd->TimerQ.pQHead = pQNode;
576                 }
577                 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
578
579                 if (pQNode)
580                         up(&pAd->RTUSBTimer_semaphore);
581                         //wake_up(&timerWaitQ);
582         }
583         else
584         {
585                 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
586         }
587         return pQNode;
588 }
589
590
591 BOOLEAN RT2870_TimerQ_Remove(
592         IN RTMP_ADAPTER *pAd,
593         IN RALINK_TIMER_STRUCT *pTimer)
594 {
595         RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
596         unsigned long irqFlags;
597
598         RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
599         if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
600         {
601                 pNode = pAd->TimerQ.pQHead;
602                 while (pNode)
603                 {
604                         if (pNode->pRaTimer == pTimer)
605                                 break;
606                         pPrev = pNode;
607                         pNode = pNode->pNext;
608                 }
609
610                 // Now move it to freeList queue.
611                 if (pNode)
612                 {
613                         if (pNode == pAd->TimerQ.pQHead)
614                                 pAd->TimerQ.pQHead = pNode->pNext;
615                         if (pNode == pAd->TimerQ.pQTail)
616                                 pAd->TimerQ.pQTail = pPrev;
617                         if (pPrev != NULL)
618                                 pPrev->pNext = pNode->pNext;
619
620                         // return this queue entry to timerQFreeList.
621                         pNode->pNext = pAd->TimerQ.pQPollFreeList;
622                         pAd->TimerQ.pQPollFreeList = pNode;
623                 }
624         }
625         RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
626
627         return TRUE;
628 }
629
630
631 void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
632 {
633         RT2870_TIMER_ENTRY *pTimerQ;
634         unsigned long irqFlags;
635
636         RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
637         while (pAd->TimerQ.pQHead)
638         {
639                 pTimerQ = pAd->TimerQ.pQHead;
640                 pAd->TimerQ.pQHead = pTimerQ->pNext;
641                 // remove the timeQ
642         }
643         pAd->TimerQ.pQPollFreeList = NULL;
644         os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
645         pAd->TimerQ.pQTail = NULL;
646         pAd->TimerQ.pQHead = NULL;
647         pAd->TimerQ.status = RT2870_THREAD_STOPED;
648         RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
649
650 }
651
652
653 void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
654 {
655         int     i;
656         RT2870_TIMER_ENTRY *pQNode, *pEntry;
657         unsigned long irqFlags;
658
659         NdisAllocateSpinLock(&pAd->TimerQLock);
660
661         RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
662         NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
663         //InterlockedExchange(&pAd->TimerQ.count, 0);
664
665         /* Initialise the wait q head */
666         //init_waitqueue_head(&timerWaitQ);
667
668         os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
669         if (pAd->TimerQ.pTimerQPoll)
670         {
671                 pEntry = NULL;
672                 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
673                 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
674                 {
675                         pQNode->pNext = pEntry;
676                         pEntry = pQNode;
677                         pQNode++;
678                 }
679                 pAd->TimerQ.pQPollFreeList = pEntry;
680                 pAd->TimerQ.pQHead = NULL;
681                 pAd->TimerQ.pQTail = NULL;
682                 pAd->TimerQ.status = RT2870_THREAD_INITED;
683         }
684         RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
685 }
686
687
688 VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
689 {
690         PHT_TX_CONTEXT          pHTTXContext;
691         int                                     idx;
692         ULONG                           irqFlags;
693         PURB                            pUrb;
694         BOOLEAN                         needDumpSeq = FALSE;
695         UINT32                  MACValue;
696
697
698         idx = 0;
699         RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
700         if ((MACValue & 0xff) !=0 )
701         {
702                 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
703                 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
704                 while((MACValue &0xff) != 0 && (idx++ < 10))
705                 {
706                         RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
707                         NdisMSleep(1);
708                 }
709                 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
710         }
711
712 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
713         idx = 0;
714         if ((MACValue & 0xff00) !=0 )
715         {
716                 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
717                 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
718                 while((MACValue &0xff00) != 0 && (idx++ < 10))
719                 {
720                         RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
721                         NdisMSleep(1);
722                 }
723                 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
724         }
725
726         if (pAd->watchDogRxOverFlowCnt >= 2)
727         {
728                 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
729                 if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
730                                                                         fRTMP_ADAPTER_BULKIN_RESET |
731                                                                         fRTMP_ADAPTER_HALT_IN_PROGRESS |
732                                                                         fRTMP_ADAPTER_NIC_NOT_EXIST))))
733                 {
734                         DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
735                         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
736                         RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
737                         needDumpSeq = TRUE;
738                 }
739                 pAd->watchDogRxOverFlowCnt = 0;
740         }
741
742
743         for (idx = 0; idx < NUM_OF_TX_RING; idx++)
744         {
745                 pUrb = NULL;
746
747                 RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
748                 if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
749                 {
750                         pAd->watchDogTxPendingCnt[idx]++;
751
752                         if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
753                                  (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
754                                 )
755                         {
756                                 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
757                                 pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
758                                 if (pHTTXContext->IRPPending)
759                                 {       // Check TxContext.
760                                         pUrb = pHTTXContext->pUrb;
761                                 }
762                                 else if (idx == MGMTPIPEIDX)
763                                 {
764                                         PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
765
766                                         //Check MgmtContext.
767                                         pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
768                                         pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
769                                         pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
770
771                                         if (pMLMEContext->IRPPending)
772                                         {
773                                                 ASSERT(pMLMEContext->IRPPending);
774                                                 pUrb = pMLMEContext->pUrb;
775                                         }
776                                         else if (pNULLContext->IRPPending)
777                                         {
778                                                 ASSERT(pNULLContext->IRPPending);
779                                                 pUrb = pNULLContext->pUrb;
780                                         }
781                                         else if (pPsPollContext->IRPPending)
782                                         {
783                                                 ASSERT(pPsPollContext->IRPPending);
784                                                 pUrb = pPsPollContext->pUrb;
785                                         }
786                                 }
787
788                                 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
789
790                                 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
791                                 if (pUrb)
792                                 {
793                                         DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
794                                         // unlink it now
795                                         RTUSB_UNLINK_URB(pUrb);
796                                         // Sleep 200 microseconds to give cancellation time to work
797                                         RTMPusecDelay(200);
798                                         needDumpSeq = TRUE;
799                                 }
800                                 else
801                                 {
802                                         DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
803                                 }
804                         }
805                         else
806                         {
807                                 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
808                         }
809                 }
810                 else
811                 {
812                         RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
813                 }
814         }
815
816         // For Sigma debug, dump the ba_reordering sequence.
817         if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
818         {
819                 USHORT                          Idx;
820                 PBA_REC_ENTRY           pBAEntry = NULL;
821                 UCHAR                           count = 0;
822                 struct reordering_mpdu *mpdu_blk;
823
824                 Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
825
826                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
827                 if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
828                 {
829                         DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
830                         NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
831                         mpdu_blk = pBAEntry->list.next;
832                         while (mpdu_blk)
833                         {
834                                 DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
835                                 mpdu_blk = mpdu_blk->next;
836                                 count++;
837                         }
838
839                         DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
840                         NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
841                 }
842         }
843 }
844
845 /*
846 ========================================================================
847 Routine Description:
848     Release allocated resources.
849
850 Arguments:
851     *dev                                Point to the PCI or USB device
852         pAd                                     driver control block pointer
853
854 Return Value:
855     None
856
857 Note:
858 ========================================================================
859 */
860 static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
861 {
862         struct net_device       *net_dev = NULL;
863
864
865         DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
866                                 dev->bus->bus_name, dev->devpath));
867         if (!pAd)
868         {
869                 usb_put_dev(dev);
870
871                 printk("rtusb_disconnect: pAd == NULL!\n");
872                 return;
873         }
874         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
875
876
877
878         // for debug, wait to show some messages to /proc system
879         udelay(1);
880
881
882
883
884         net_dev = pAd->net_dev;
885         if (pAd->net_dev != NULL)
886         {
887                 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
888                 unregister_netdev (pAd->net_dev);
889         }
890         udelay(1);
891         flush_scheduled_work();
892         udelay(1);
893
894         // free net_device memory
895         free_netdev(net_dev);
896
897         // free adapter memory
898         RTMPFreeAdapter(pAd);
899
900         // release a use of the usb device structure
901         usb_put_dev(dev);
902         udelay(1);
903
904         DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
905 }
906
907
908 /*
909 ========================================================================
910 Routine Description:
911     Probe RT28XX chipset.
912
913 Arguments:
914     *dev                                Point to the PCI or USB device
915         interface
916         *id_table                       Point to the PCI or USB device ID
917
918 Return Value:
919     None
920
921 Note:
922 ========================================================================
923 */
924 static int rtusb_probe (struct usb_interface *intf,
925                                                 const struct usb_device_id *id)
926 {
927         PRTMP_ADAPTER pAd;
928         return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
929 }
930
931
932 static void rtusb_disconnect(struct usb_interface *intf)
933 {
934         struct usb_device   *dev = interface_to_usbdev(intf);
935         PRTMP_ADAPTER       pAd;
936
937
938         pAd = usb_get_intfdata(intf);
939         usb_set_intfdata(intf, NULL);
940
941         _rtusb_disconnect(dev, pAd);
942 }
943
944
945 /*
946 ========================================================================
947 Routine Description:
948     Close kernel threads.
949
950 Arguments:
951         *pAd                            the raxx interface data pointer
952
953 Return Value:
954     NONE
955
956 Note:
957 ========================================================================
958 */
959 VOID RT28xxThreadTerminate(
960         IN RTMP_ADAPTER *pAd)
961 {
962         POS_COOKIE      pObj = (POS_COOKIE) pAd->OS_Cookie;
963         INT                     ret;
964
965
966         // Sleep 50 milliseconds so pending io might finish normally
967         RTMPusecDelay(50000);
968
969         // We want to wait until all pending receives and sends to the
970         // device object. We cancel any
971         // irps. Wait until sends and receives have stopped.
972         RTUSBCancelPendingIRPs(pAd);
973
974         // Terminate Threads
975
976         if (pid_nr(pObj->TimerQThr_pid) > 0)
977         {
978                 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
979
980                 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid));
981                 mb();
982                 pAd->TimerFunc_kill = 1;
983                 mb();
984                 ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
985                 if (ret)
986                 {
987                         printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
988                                         pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret);
989                 }
990                 else
991                 {
992                         wait_for_completion(&pAd->TimerQComplete);
993                         pObj->TimerQThr_pid = NULL;
994                 }
995         }
996
997         if (pid_nr(pObj->MLMEThr_pid) > 0)
998         {
999                 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
1000                 mb();
1001                 pAd->mlme_kill = 1;
1002                 //RT28XX_MLME_HANDLER(pAd);
1003                 mb();
1004                 ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
1005                 if (ret)
1006                 {
1007                         printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
1008                                         pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret);
1009                 }
1010                 else
1011                 {
1012                         //wait_for_completion (&pAd->notify);
1013                         wait_for_completion (&pAd->mlmeComplete);
1014                         pObj->MLMEThr_pid = NULL;
1015                 }
1016         }
1017
1018         if (pid_nr(pObj->RTUSBCmdThr_pid) > 0)
1019         {
1020                 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid));
1021                 mb();
1022                 NdisAcquireSpinLock(&pAd->CmdQLock);
1023                 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
1024                 NdisReleaseSpinLock(&pAd->CmdQLock);
1025                 mb();
1026                 //RTUSBCMDUp(pAd);
1027                 ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
1028                 if (ret)
1029                 {
1030                         printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1031                                         pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret);
1032                 }
1033                 else
1034                 {
1035                         //wait_for_completion (&pAd->notify);
1036                         wait_for_completion (&pAd->CmdQComplete);
1037                         pObj->RTUSBCmdThr_pid = NULL;
1038                 }
1039         }
1040
1041         // Kill tasklets
1042         pAd->mlme_kill = 0;
1043         pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1044         pAd->TimerFunc_kill = 0;
1045 }
1046
1047
1048 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1049 {
1050         POS_COOKIE pObj;
1051
1052         pObj = (POS_COOKIE) pAd->OS_Cookie;
1053
1054         tasklet_kill(&pObj->rx_done_task);
1055         tasklet_kill(&pObj->mgmt_dma_done_task);
1056         tasklet_kill(&pObj->ac0_dma_done_task);
1057         tasklet_kill(&pObj->ac1_dma_done_task);
1058         tasklet_kill(&pObj->ac2_dma_done_task);
1059         tasklet_kill(&pObj->ac3_dma_done_task);
1060         tasklet_kill(&pObj->hcca_dma_done_task);
1061         tasklet_kill(&pObj->tbtt_task);
1062
1063 }
1064
1065
1066 /*
1067 ========================================================================
1068 Routine Description:
1069     Check the chipset vendor/product ID.
1070
1071 Arguments:
1072     _dev_p                              Point to the PCI or USB device
1073
1074 Return Value:
1075     TRUE                                Check ok
1076         FALSE                           Check fail
1077
1078 Note:
1079 ========================================================================
1080 */
1081 BOOLEAN RT28XXChipsetCheck(
1082         IN void *_dev_p)
1083 {
1084         struct usb_interface *intf = (struct usb_interface *)_dev_p;
1085         struct usb_device *dev_p = interface_to_usbdev(intf);
1086         UINT32 i;
1087
1088
1089         for(i=0; i<rtusb_usb_id_len; i++)
1090         {
1091                 if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1092                         dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1093                 {
1094                         printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1095                                         dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1096                         break;
1097                 }
1098         }
1099
1100         if (i == rtusb_usb_id_len)
1101         {
1102                 printk("rt2870: Error! Device Descriptor not matching!\n");
1103                 return FALSE;
1104         }
1105
1106         return TRUE;
1107 }
1108
1109
1110 /*
1111 ========================================================================
1112 Routine Description:
1113     Init net device structure.
1114
1115 Arguments:
1116     _dev_p                              Point to the PCI or USB device
1117     *net_dev                    Point to the net device
1118         *pAd                            the raxx interface data pointer
1119
1120 Return Value:
1121     TRUE                                Init ok
1122         FALSE                           Init fail
1123
1124 Note:
1125 ========================================================================
1126 */
1127 BOOLEAN RT28XXNetDevInit(
1128         IN void                                 *_dev_p,
1129         IN struct  net_device   *net_dev,
1130         IN RTMP_ADAPTER                 *pAd)
1131 {
1132         struct usb_interface *intf = (struct usb_interface *)_dev_p;
1133         struct usb_device *dev_p = interface_to_usbdev(intf);
1134
1135
1136         pAd->config = &dev_p->config->desc;
1137         return TRUE;
1138 }
1139
1140
1141 /*
1142 ========================================================================
1143 Routine Description:
1144     Init net device structure.
1145
1146 Arguments:
1147     _dev_p                              Point to the PCI or USB device
1148         *pAd                            the raxx interface data pointer
1149
1150 Return Value:
1151     TRUE                                Config ok
1152         FALSE                           Config fail
1153
1154 Note:
1155 ========================================================================
1156 */
1157 BOOLEAN RT28XXProbePostConfig(
1158         IN void                                 *_dev_p,
1159         IN RTMP_ADAPTER                 *pAd,
1160         IN INT32                                interface)
1161 {
1162         struct usb_interface *intf = (struct usb_interface *)_dev_p;
1163         struct usb_host_interface *iface_desc;
1164         ULONG BulkOutIdx;
1165         UINT32 i;
1166
1167
1168         /* get the active interface descriptor */
1169         iface_desc = intf->cur_altsetting;
1170
1171         /* get # of enpoints  */
1172         pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1173         DBGPRINT(RT_DEBUG_TRACE,
1174                         ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1175
1176         /* Configure Pipes */
1177         BulkOutIdx = 0;
1178
1179         for(i=0; i<pAd->NumberOfPipes; i++)
1180         {
1181                 if ((iface_desc->endpoint[i].desc.bmAttributes ==
1182                                 USB_ENDPOINT_XFER_BULK) &&
1183                         ((iface_desc->endpoint[i].desc.bEndpointAddress &
1184                                 USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1185                 {
1186                         pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1187                         pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1188
1189                         DBGPRINT_RAW(RT_DEBUG_TRACE,
1190                                 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1191                         DBGPRINT_RAW(RT_DEBUG_TRACE,
1192                                 ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1193                 }
1194                 else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1195                                         USB_ENDPOINT_XFER_BULK) &&
1196                                 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1197                                         USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1198                 {
1199                         // there are 6 bulk out EP. EP6 highest priority.
1200                         // EP1-4 is EDCA.  EP5 is HCCA.
1201                         pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1202                         pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1203
1204                         DBGPRINT_RAW(RT_DEBUG_TRACE,
1205                                 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1206                         DBGPRINT_RAW(RT_DEBUG_TRACE,
1207                                 ("EP address = 0x%2x  \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1208                 }
1209         }
1210
1211         if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1212         {
1213                 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
1214                 return FALSE;
1215         }
1216
1217         return TRUE;
1218 }
1219
1220
1221 /*
1222 ========================================================================
1223 Routine Description:
1224     Disable DMA.
1225
1226 Arguments:
1227         *pAd                            the raxx interface data pointer
1228
1229 Return Value:
1230         None
1231
1232 Note:
1233 ========================================================================
1234 */
1235 VOID RT28XXDMADisable(
1236         IN RTMP_ADAPTER                 *pAd)
1237 {
1238         // no use
1239 }
1240
1241
1242
1243 /*
1244 ========================================================================
1245 Routine Description:
1246     Enable DMA.
1247
1248 Arguments:
1249         *pAd                            the raxx interface data pointer
1250
1251 Return Value:
1252         None
1253
1254 Note:
1255 ========================================================================
1256 */
1257 VOID RT28XXDMAEnable(
1258         IN RTMP_ADAPTER                 *pAd)
1259 {
1260         WPDMA_GLO_CFG_STRUC     GloCfg;
1261         USB_DMA_CFG_STRUC       UsbCfg;
1262         int                                     i = 0;
1263
1264
1265         RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1266         do
1267         {
1268                 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1269                 if ((GloCfg.field.TxDMABusy == 0)  && (GloCfg.field.RxDMABusy == 0))
1270                         break;
1271
1272                 DBGPRINT(RT_DEBUG_TRACE, ("==>  DMABusy\n"));
1273                 RTMPusecDelay(1000);
1274                 i++;
1275         }while ( i <200);
1276
1277
1278         RTMPusecDelay(50);
1279         GloCfg.field.EnTXWriteBackDDONE = 1;
1280         GloCfg.field.EnableRxDMA = 1;
1281         GloCfg.field.EnableTxDMA = 1;
1282         DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1283         RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1284
1285         UsbCfg.word = 0;
1286         UsbCfg.field.phyclear = 0;
1287         /* usb version is 1.1,do not use bulk in aggregation */
1288         if (pAd->BulkInMaxPacketSize == 512)
1289                         UsbCfg.field.RxBulkAggEn = 1;
1290         /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1291         UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1292         UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1293         UsbCfg.field.RxBulkEn = 1;
1294         UsbCfg.field.TxBulkEn = 1;
1295
1296         RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1297
1298 }
1299
1300 /*
1301 ========================================================================
1302 Routine Description:
1303     Write Beacon buffer to Asic.
1304
1305 Arguments:
1306         *pAd                            the raxx interface data pointer
1307
1308 Return Value:
1309         None
1310
1311 Note:
1312 ========================================================================
1313 */
1314 VOID RT28xx_UpdateBeaconToAsic(
1315         IN RTMP_ADAPTER         *pAd,
1316         IN INT                          apidx,
1317         IN ULONG                        FrameLen,
1318         IN ULONG                        UpdatePos)
1319 {
1320         PUCHAR          pBeaconFrame = NULL;
1321         UCHAR                   *ptr;
1322         UINT                    i, padding;
1323         BEACON_SYNC_STRUCT      *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1324         UINT32                  longValue;
1325         BOOLEAN                 bBcnReq = FALSE;
1326         UCHAR                   bcn_idx = 0;
1327
1328
1329         if (pBeaconFrame == NULL)
1330         {
1331                 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1332                 return;
1333         }
1334
1335         if (pBeaconSync == NULL)
1336         {
1337                 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1338                 return;
1339         }
1340
1341         //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1342         //      ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1343         //      )
1344         if (bBcnReq == FALSE)
1345         {
1346                 /* when the ra interface is down, do not send its beacon frame */
1347                 /* clear all zero */
1348                 for(i=0; i<TXWI_SIZE; i+=4) {
1349                         RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1350                 }
1351                 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1352                 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1353         }
1354         else
1355         {
1356                 ptr = (PUCHAR)&pAd->BeaconTxWI;
1357
1358                 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1359                 {       // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1360                         pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1361                         NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1362                 }
1363
1364                 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1365                 {
1366                         for (i=0; i<TXWI_SIZE; i+=4)  // 16-byte TXWI field
1367                         {
1368                                 longValue =  *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1369                                 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1370                                 ptr += 4;
1371                         }
1372                 }
1373
1374                 ptr = pBeaconSync->BeaconBuf[bcn_idx];
1375                 padding = (FrameLen & 0x01);
1376                 NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1377                 FrameLen += padding;
1378                 for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1379                 {
1380                         if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1381                         {
1382                                 NdisMoveMemory(ptr, pBeaconFrame, 2);
1383                                 //shortValue = *ptr + (*(ptr+1)<<8);
1384                                 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1385                                 RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1386                         }
1387                         ptr +=2;
1388                         pBeaconFrame += 2;
1389                 }
1390
1391                 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1392
1393                 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1394         }
1395
1396 }
1397
1398
1399 VOID RT2870_BssBeaconStop(
1400         IN RTMP_ADAPTER *pAd)
1401 {
1402         BEACON_SYNC_STRUCT      *pBeaconSync;
1403         int i, offset;
1404         BOOLEAN Cancelled = TRUE;
1405
1406         pBeaconSync = pAd->CommonCfg.pBeaconSync;
1407         if (pBeaconSync && pBeaconSync->EnableBeacon)
1408         {
1409                 INT NumOfBcn;
1410
1411                 NumOfBcn = MAX_MESH_NUM;
1412
1413                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1414
1415                 for(i=0; i<NumOfBcn; i++)
1416                 {
1417                         NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1418                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1419
1420                         for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1421                                 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1422
1423                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1424                         pBeaconSync->TimIELocationInBeacon[i] = 0;
1425                 }
1426                 pBeaconSync->BeaconBitMap = 0;
1427                 pBeaconSync->DtimBitOn = 0;
1428         }
1429 }
1430
1431
1432 VOID RT2870_BssBeaconStart(
1433         IN RTMP_ADAPTER *pAd)
1434 {
1435         int apidx;
1436         BEACON_SYNC_STRUCT      *pBeaconSync;
1437 //      LARGE_INTEGER   tsfTime, deltaTime;
1438
1439         pBeaconSync = pAd->CommonCfg.pBeaconSync;
1440         if (pBeaconSync && pBeaconSync->EnableBeacon)
1441         {
1442                 INT NumOfBcn;
1443
1444                 NumOfBcn = MAX_MESH_NUM;
1445
1446                 for(apidx=0; apidx<NumOfBcn; apidx++)
1447                 {
1448                         UCHAR CapabilityInfoLocationInBeacon = 0;
1449                         UCHAR TimIELocationInBeacon = 0;
1450
1451                         NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1452                         pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1453                         pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1454                         NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1455                 }
1456                 pBeaconSync->BeaconBitMap = 0;
1457                 pBeaconSync->DtimBitOn = 0;
1458                 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1459
1460                 pAd->CommonCfg.BeaconAdjust = 0;
1461                 pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1462                 pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1463                 printk(RT28xx_CHIP_NAME "_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1464                 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1465
1466         }
1467 }
1468
1469
1470 VOID RT2870_BssBeaconInit(
1471         IN RTMP_ADAPTER *pAd)
1472 {
1473         BEACON_SYNC_STRUCT      *pBeaconSync;
1474         int i;
1475
1476         NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1477         if (pAd->CommonCfg.pBeaconSync)
1478         {
1479                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1480                 NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1481                 for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1482                 {
1483                         NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1484                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1485                         pBeaconSync->TimIELocationInBeacon[i] = 0;
1486                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1487                 }
1488                 pBeaconSync->BeaconBitMap = 0;
1489
1490                 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1491                 pBeaconSync->EnableBeacon = TRUE;
1492         }
1493 }
1494
1495
1496 VOID RT2870_BssBeaconExit(
1497         IN RTMP_ADAPTER *pAd)
1498 {
1499         BEACON_SYNC_STRUCT      *pBeaconSync;
1500         BOOLEAN Cancelled = TRUE;
1501         int i;
1502
1503         if (pAd->CommonCfg.pBeaconSync)
1504         {
1505                 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1506                 pBeaconSync->EnableBeacon = FALSE;
1507                 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1508                 pBeaconSync->BeaconBitMap = 0;
1509
1510                 for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1511                 {
1512                         NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1513                         pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1514                         pBeaconSync->TimIELocationInBeacon[i] = 0;
1515                         NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1516                 }
1517
1518                 NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1519                 pAd->CommonCfg.pBeaconSync = NULL;
1520         }
1521 }
1522
1523 VOID BeaconUpdateExec(
1524     IN PVOID SystemSpecific1,
1525     IN PVOID FunctionContext,
1526     IN PVOID SystemSpecific2,
1527     IN PVOID SystemSpecific3)
1528 {
1529         PRTMP_ADAPTER   pAd = (PRTMP_ADAPTER)FunctionContext;
1530         LARGE_INTEGER   tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1531         UINT32                  delta, remain, remain_low, remain_high;
1532 //      BOOLEAN                 positive;
1533
1534         ReSyncBeaconTime(pAd);
1535
1536
1537
1538         RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1539         RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1540
1541
1542         //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1543         remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1544         remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1545         remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1546         delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1547
1548         pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;
1549
1550 }
1551