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