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