2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
31 main initialization routines
35 -------- ---------- ----------------------------------------------
36 Name Date Modification logs
37 Jan Lee 01-10-2005 modified
38 Sample Jun/01/07 Merge RT2870 and RT2860 drivers.
41 #include "rt_config.h"
44 // Following information will be show when you run 'modinfo'
45 // *** If you have a solution for the bug in current version of driver, please mail to me.
46 // Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. ***
47 MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
48 MODULE_DESCRIPTION(RT28xx_CHIP_NAME " Wireless LAN Linux Driver");
49 MODULE_LICENSE("GPL");
51 MODULE_VERSION(STA_DRIVER_VERSION);
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
59 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
60 IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
62 struct usb_device_id rtusb_usb_id[] = {
63 { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */
64 { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
65 { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
66 { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
67 { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
69 { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
70 { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
72 { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */
73 { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */
74 { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */
75 { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */
76 { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */
77 { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */
79 { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
81 { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
82 { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
83 { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
84 { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
85 { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
86 { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
87 { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
88 { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
89 { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
90 { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
92 { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
93 { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
95 { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
96 { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
97 { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
98 { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
99 { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
100 { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */
101 { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */
102 { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */
103 { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */
104 { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */
105 { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */
106 { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */
108 { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
110 { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
111 { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
112 { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
114 { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
115 { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
117 { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
119 { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
121 { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */
122 { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */
123 { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */
124 { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */
125 { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */
127 { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
129 { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
130 { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
131 { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
133 { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
135 { USB_DEVICE(0x083A, 0x6618) }, /* Accton */
136 { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */
137 { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */
138 { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */
139 { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */
140 { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */
141 { USB_DEVICE(0x050d, 0x805c) },
142 { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/
143 { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */
144 { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */
145 { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */
146 { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */
147 { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
148 { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
150 { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
152 { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
153 { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
154 { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
156 { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
158 { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
159 { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
160 { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
161 { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
163 { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
164 { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
166 { } /* Terminating entry */
169 INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
170 MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
173 #define PF_NOFREEZE 0
178 static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
179 static int rt2870_resume(struct usb_interface *intf);
180 #endif // CONFIG_PM //
182 /**************************************************************************/
183 /**************************************************************************/
184 //tested for kernel 2.6series
185 /**************************************************************************/
186 /**************************************************************************/
187 static int rtusb_probe (struct usb_interface *intf,
188 const struct usb_device_id *id);
189 static void rtusb_disconnect(struct usb_interface *intf);
191 struct usb_driver rtusb_driver = {
194 .disconnect=rtusb_disconnect,
195 .id_table=rtusb_usb_id,
198 suspend: rt2870_suspend,
199 resume: rt2870_resume,
205 VOID RT2860RejectPendingPackets(
206 IN PRTMP_ADAPTER pAd)
209 // clear TxSw packets
212 static int rt2870_suspend(
213 struct usb_interface *intf,
216 struct net_device *net_dev;
217 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
220 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
221 net_dev = pAd->net_dev;
222 netif_device_detach (net_dev);
224 pAd->PM_FlgSuspend = 1;
225 if (netif_running(net_dev)) {
226 RTUSBCancelPendingBulkInIRP(pAd);
227 RTUSBCancelPendingBulkOutIRP(pAd);
229 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
233 static int rt2870_resume(
234 struct usb_interface *intf)
236 struct net_device *net_dev;
237 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
240 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
242 pAd->PM_FlgSuspend = 0;
243 net_dev = pAd->net_dev;
244 netif_device_attach (net_dev);
245 netif_start_queue(net_dev);
246 netif_carrier_on(net_dev);
247 netif_wake_queue(net_dev);
249 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
252 #endif // CONFIG_PM //
255 // Init driver module
256 INT __init rtusb_init(void)
258 printk("rtusb init --->\n");
259 return usb_register(&rtusb_driver);
262 // Deinit driver module
263 VOID __exit rtusb_exit(void)
265 usb_deregister(&rtusb_driver);
266 printk("<--- rtusb exit\n");
269 module_init(rtusb_init);
270 module_exit(rtusb_exit);
275 /*--------------------------------------------------------------------- */
276 /* function declarations */
277 /*--------------------------------------------------------------------- */
280 ========================================================================
285 *Context the pAd, driver control block pointer
291 ========================================================================
296 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
300 pObj = (POS_COOKIE)pAd->OS_Cookie;
302 rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
304 while (pAd->mlme_kill == 0)
306 /* lock the device pointers */
307 //down(&(pAd->mlme_semaphore));
308 status = down_interruptible(&(pAd->mlme_semaphore));
310 /* lock the device pointers , need to check if required*/
311 //down(&(pAd->usbdev_semaphore));
313 if (!pAd->PM_FlgSuspend)
316 /* unlock the device pointers */
317 //up(&(pAd->usbdev_semaphore));
320 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
325 /* notify the exit routine that we're actually exiting now
327 * complete()/wait_for_completion() is similar to up()/down(),
328 * except that complete() is safe in the case where the structure
329 * is getting deleted in a parallel mode of execution (i.e. just
330 * after the down() -- that's necessary for the thread-shutdown
333 * complete_and_exit() goes even further than this -- it is safe in
334 * the case that the thread of the caller is going away (not just
335 * the structure) -- this is necessary for the module-remove case.
336 * This is important in preemption kernels, which transfer the flow
337 * of execution immediately upon a complete().
339 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
341 pObj->MLMEThr_pid = NULL;
343 complete_and_exit (&pAd->mlmeComplete, 0);
350 ========================================================================
352 USB command kernel thread.
355 *Context the pAd, driver control block pointer
361 ========================================================================
366 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
370 pObj = (POS_COOKIE)pAd->OS_Cookie;
372 rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
374 NdisAcquireSpinLock(&pAd->CmdQLock);
375 pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
376 NdisReleaseSpinLock(&pAd->CmdQLock);
378 while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
380 /* lock the device pointers */
381 //down(&(pAd->RTUSBCmd_semaphore));
382 status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
384 if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
389 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
392 /* lock the device pointers , need to check if required*/
393 //down(&(pAd->usbdev_semaphore));
395 if (!pAd->PM_FlgSuspend)
398 /* unlock the device pointers */
399 //up(&(pAd->usbdev_semaphore));
402 if (!pAd->PM_FlgSuspend)
403 { // Clear the CmdQElements.
404 CmdQElmt *pCmdQElmt = NULL;
406 NdisAcquireSpinLock(&pAd->CmdQLock);
407 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
408 while(pAd->CmdQ.size)
410 RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
413 if (pCmdQElmt->CmdFromNdis == TRUE)
415 if (pCmdQElmt->buffer != NULL)
416 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
418 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
422 if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
423 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
425 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
431 NdisReleaseSpinLock(&pAd->CmdQLock);
433 /* notify the exit routine that we're actually exiting now
435 * complete()/wait_for_completion() is similar to up()/down(),
436 * except that complete() is safe in the case where the structure
437 * is getting deleted in a parallel mode of execution (i.e. just
438 * after the down() -- that's necessary for the thread-shutdown
441 * complete_and_exit() goes even further than this -- it is safe in
442 * the case that the thread of the caller is going away (not just
443 * the structure) -- this is necessary for the module-remove case.
444 * This is important in preemption kernels, which transfer the flow
445 * of execution immediately upon a complete().
447 DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
449 pObj->RTUSBCmdThr_pid = NULL;
451 complete_and_exit (&pAd->CmdQComplete, 0);
457 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
460 RALINK_TIMER_STRUCT *pTimer;
461 RT2870_TIMER_ENTRY *pEntry;
462 unsigned long irqFlag;
464 while(!pAd->TimerFunc_kill)
466 // printk("waiting for event!\n");
469 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
471 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
475 while(pAd->TimerQ.pQHead)
477 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
478 pEntry = pAd->TimerQ.pQHead;
481 pTimer = pEntry->pRaTimer;
484 pAd->TimerQ.pQHead = pEntry->pNext;
485 if (pEntry == pAd->TimerQ.pQTail)
486 pAd->TimerQ.pQTail = NULL;
488 // return this queue entry to timerQFreeList.
489 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
490 pAd->TimerQ.pQPollFreeList = pEntry;
492 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
496 if (pTimer->handle != NULL)
497 if (!pAd->PM_FlgSuspend)
498 pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
499 if ((pTimer->Repeat) && (pTimer->State == FALSE))
500 RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
506 pAd->TimerQ.status = RT2870_THREAD_STOPED;
507 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
515 IN OUT PVOID Context)
520 pAd = (PRTMP_ADAPTER)Context;
521 pObj = (POS_COOKIE) pAd->OS_Cookie;
523 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
525 RT2870_TimerQ_Handle(pAd);
527 /* notify the exit routine that we're actually exiting now
529 * complete()/wait_for_completion() is similar to up()/down(),
530 * except that complete() is safe in the case where the structure
531 * is getting deleted in a parallel mode of execution (i.e. just
532 * after the down() -- that's necessary for the thread-shutdown
535 * complete_and_exit() goes even further than this -- it is safe in
536 * the case that the thread of the caller is going away (not just
537 * the structure) -- this is necessary for the module-remove case.
538 * This is important in preemption kernels, which transfer the flow
539 * of execution immediately upon a complete().
541 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
543 pObj->TimerQThr_pid = NULL;
545 complete_and_exit(&pAd->TimerQComplete, 0);
551 RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
552 IN RTMP_ADAPTER *pAd,
553 IN RALINK_TIMER_STRUCT *pTimer)
555 RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
556 unsigned long irqFlags;
559 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
560 if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
562 if(pAd->TimerQ.pQPollFreeList)
564 pQNode = pAd->TimerQ.pQPollFreeList;
565 pAd->TimerQ.pQPollFreeList = pQNode->pNext;
567 pQNode->pRaTimer = pTimer;
568 pQNode->pNext = NULL;
570 pQTail = pAd->TimerQ.pQTail;
571 if (pAd->TimerQ.pQTail != NULL)
572 pQTail->pNext = pQNode;
573 pAd->TimerQ.pQTail = pQNode;
574 if (pAd->TimerQ.pQHead == NULL)
575 pAd->TimerQ.pQHead = pQNode;
577 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
580 up(&pAd->RTUSBTimer_semaphore);
581 //wake_up(&timerWaitQ);
585 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
591 BOOLEAN RT2870_TimerQ_Remove(
592 IN RTMP_ADAPTER *pAd,
593 IN RALINK_TIMER_STRUCT *pTimer)
595 RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
596 unsigned long irqFlags;
598 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
599 if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
601 pNode = pAd->TimerQ.pQHead;
604 if (pNode->pRaTimer == pTimer)
607 pNode = pNode->pNext;
610 // Now move it to freeList queue.
613 if (pNode == pAd->TimerQ.pQHead)
614 pAd->TimerQ.pQHead = pNode->pNext;
615 if (pNode == pAd->TimerQ.pQTail)
616 pAd->TimerQ.pQTail = pPrev;
618 pPrev->pNext = pNode->pNext;
620 // return this queue entry to timerQFreeList.
621 pNode->pNext = pAd->TimerQ.pQPollFreeList;
622 pAd->TimerQ.pQPollFreeList = pNode;
625 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
631 void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
633 RT2870_TIMER_ENTRY *pTimerQ;
634 unsigned long irqFlags;
636 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
637 while (pAd->TimerQ.pQHead)
639 pTimerQ = pAd->TimerQ.pQHead;
640 pAd->TimerQ.pQHead = pTimerQ->pNext;
643 pAd->TimerQ.pQPollFreeList = NULL;
644 os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
645 pAd->TimerQ.pQTail = NULL;
646 pAd->TimerQ.pQHead = NULL;
647 pAd->TimerQ.status = RT2870_THREAD_STOPED;
648 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
653 void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
656 RT2870_TIMER_ENTRY *pQNode, *pEntry;
657 unsigned long irqFlags;
659 NdisAllocateSpinLock(&pAd->TimerQLock);
661 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
662 NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
663 //InterlockedExchange(&pAd->TimerQ.count, 0);
665 /* Initialise the wait q head */
666 //init_waitqueue_head(&timerWaitQ);
668 os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
669 if (pAd->TimerQ.pTimerQPoll)
672 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
673 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
675 pQNode->pNext = pEntry;
679 pAd->TimerQ.pQPollFreeList = pEntry;
680 pAd->TimerQ.pQHead = NULL;
681 pAd->TimerQ.pQTail = NULL;
682 pAd->TimerQ.status = RT2870_THREAD_INITED;
684 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
688 VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
690 PHT_TX_CONTEXT pHTTXContext;
694 BOOLEAN needDumpSeq = FALSE;
699 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
700 if ((MACValue & 0xff) !=0 )
702 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
703 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
704 while((MACValue &0xff) != 0 && (idx++ < 10))
706 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
709 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
712 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
714 if ((MACValue & 0xff00) !=0 )
716 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
717 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
718 while((MACValue &0xff00) != 0 && (idx++ < 10))
720 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
723 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
726 if (pAd->watchDogRxOverFlowCnt >= 2)
728 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
729 if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
730 fRTMP_ADAPTER_BULKIN_RESET |
731 fRTMP_ADAPTER_HALT_IN_PROGRESS |
732 fRTMP_ADAPTER_NIC_NOT_EXIST))))
734 DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
735 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
736 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
739 pAd->watchDogRxOverFlowCnt = 0;
743 for (idx = 0; idx < NUM_OF_TX_RING; idx++)
747 RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
748 if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
750 pAd->watchDogTxPendingCnt[idx]++;
752 if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
753 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
756 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
757 pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
758 if (pHTTXContext->IRPPending)
759 { // Check TxContext.
760 pUrb = pHTTXContext->pUrb;
762 else if (idx == MGMTPIPEIDX)
764 PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
767 pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
768 pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
769 pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
771 if (pMLMEContext->IRPPending)
773 ASSERT(pMLMEContext->IRPPending);
774 pUrb = pMLMEContext->pUrb;
776 else if (pNULLContext->IRPPending)
778 ASSERT(pNULLContext->IRPPending);
779 pUrb = pNULLContext->pUrb;
781 else if (pPsPollContext->IRPPending)
783 ASSERT(pPsPollContext->IRPPending);
784 pUrb = pPsPollContext->pUrb;
788 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
790 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
793 DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
795 RTUSB_UNLINK_URB(pUrb);
796 // Sleep 200 microseconds to give cancellation time to work
802 DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
807 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
812 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
816 // For Sigma debug, dump the ba_reordering sequence.
817 if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
820 PBA_REC_ENTRY pBAEntry = NULL;
822 struct reordering_mpdu *mpdu_blk;
824 Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
826 pBAEntry = &pAd->BATable.BARecEntry[Idx];
827 if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
829 DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
830 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
831 mpdu_blk = pBAEntry->list.next;
834 DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
835 mpdu_blk = mpdu_blk->next;
839 DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
840 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
846 ========================================================================
848 Release allocated resources.
851 *dev Point to the PCI or USB device
852 pAd driver control block pointer
858 ========================================================================
860 static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
862 struct net_device *net_dev = NULL;
865 DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
866 dev->bus->bus_name, dev->devpath));
871 printk("rtusb_disconnect: pAd == NULL!\n");
874 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
878 // for debug, wait to show some messages to /proc system
884 net_dev = pAd->net_dev;
885 if (pAd->net_dev != NULL)
887 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
888 unregister_netdev (pAd->net_dev);
891 flush_scheduled_work();
894 // free net_device memory
895 free_netdev(net_dev);
897 // free adapter memory
898 RTMPFreeAdapter(pAd);
900 // release a use of the usb device structure
904 DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
909 ========================================================================
911 Probe RT28XX chipset.
914 *dev Point to the PCI or USB device
916 *id_table Point to the PCI or USB device ID
922 ========================================================================
924 static int rtusb_probe (struct usb_interface *intf,
925 const struct usb_device_id *id)
928 return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
932 static void rtusb_disconnect(struct usb_interface *intf)
934 struct usb_device *dev = interface_to_usbdev(intf);
938 pAd = usb_get_intfdata(intf);
939 usb_set_intfdata(intf, NULL);
941 _rtusb_disconnect(dev, pAd);
946 ========================================================================
948 Close kernel threads.
951 *pAd the raxx interface data pointer
957 ========================================================================
959 VOID RT28xxThreadTerminate(
960 IN RTMP_ADAPTER *pAd)
962 POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
966 // Sleep 50 milliseconds so pending io might finish normally
967 RTMPusecDelay(50000);
969 // We want to wait until all pending receives and sends to the
970 // device object. We cancel any
971 // irps. Wait until sends and receives have stopped.
972 RTUSBCancelPendingIRPs(pAd);
976 if (pid_nr(pObj->TimerQThr_pid) > 0)
978 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
980 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid));
982 pAd->TimerFunc_kill = 1;
984 ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
987 printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
988 pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret);
992 wait_for_completion(&pAd->TimerQComplete);
993 pObj->TimerQThr_pid = NULL;
997 if (pid_nr(pObj->MLMEThr_pid) > 0)
999 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
1002 //RT28XX_MLME_HANDLER(pAd);
1004 ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
1007 printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
1008 pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret);
1012 //wait_for_completion (&pAd->notify);
1013 wait_for_completion (&pAd->mlmeComplete);
1014 pObj->MLMEThr_pid = NULL;
1018 if (pid_nr(pObj->RTUSBCmdThr_pid) > 0)
1020 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid));
1022 NdisAcquireSpinLock(&pAd->CmdQLock);
1023 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
1024 NdisReleaseSpinLock(&pAd->CmdQLock);
1027 ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
1030 printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1031 pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret);
1035 //wait_for_completion (&pAd->notify);
1036 wait_for_completion (&pAd->CmdQComplete);
1037 pObj->RTUSBCmdThr_pid = NULL;
1043 pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1044 pAd->TimerFunc_kill = 0;
1048 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1052 pObj = (POS_COOKIE) pAd->OS_Cookie;
1054 tasklet_kill(&pObj->rx_done_task);
1055 tasklet_kill(&pObj->mgmt_dma_done_task);
1056 tasklet_kill(&pObj->ac0_dma_done_task);
1057 tasklet_kill(&pObj->ac1_dma_done_task);
1058 tasklet_kill(&pObj->ac2_dma_done_task);
1059 tasklet_kill(&pObj->ac3_dma_done_task);
1060 tasklet_kill(&pObj->hcca_dma_done_task);
1061 tasklet_kill(&pObj->tbtt_task);
1067 ========================================================================
1068 Routine Description:
1069 Check the chipset vendor/product ID.
1072 _dev_p Point to the PCI or USB device
1079 ========================================================================
1081 BOOLEAN RT28XXChipsetCheck(
1084 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1085 struct usb_device *dev_p = interface_to_usbdev(intf);
1089 for(i=0; i<rtusb_usb_id_len; i++)
1091 if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1092 dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1094 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1095 dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1100 if (i == rtusb_usb_id_len)
1102 printk("rt2870: Error! Device Descriptor not matching!\n");
1111 ========================================================================
1112 Routine Description:
1113 Init net device structure.
1116 _dev_p Point to the PCI or USB device
1117 *net_dev Point to the net device
1118 *pAd the raxx interface data pointer
1125 ========================================================================
1127 BOOLEAN RT28XXNetDevInit(
1129 IN struct net_device *net_dev,
1130 IN RTMP_ADAPTER *pAd)
1132 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1133 struct usb_device *dev_p = interface_to_usbdev(intf);
1136 pAd->config = &dev_p->config->desc;
1142 ========================================================================
1143 Routine Description:
1144 Init net device structure.
1147 _dev_p Point to the PCI or USB device
1148 *pAd the raxx interface data pointer
1155 ========================================================================
1157 BOOLEAN RT28XXProbePostConfig(
1159 IN RTMP_ADAPTER *pAd,
1162 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1163 struct usb_host_interface *iface_desc;
1168 /* get the active interface descriptor */
1169 iface_desc = intf->cur_altsetting;
1171 /* get # of enpoints */
1172 pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1173 DBGPRINT(RT_DEBUG_TRACE,
1174 ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1176 /* Configure Pipes */
1179 for(i=0; i<pAd->NumberOfPipes; i++)
1181 if ((iface_desc->endpoint[i].desc.bmAttributes ==
1182 USB_ENDPOINT_XFER_BULK) &&
1183 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1184 USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1186 pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1187 pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1189 DBGPRINT_RAW(RT_DEBUG_TRACE,
1190 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1191 DBGPRINT_RAW(RT_DEBUG_TRACE,
1192 ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1194 else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1195 USB_ENDPOINT_XFER_BULK) &&
1196 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1197 USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1199 // there are 6 bulk out EP. EP6 highest priority.
1200 // EP1-4 is EDCA. EP5 is HCCA.
1201 pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1202 pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1204 DBGPRINT_RAW(RT_DEBUG_TRACE,
1205 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1206 DBGPRINT_RAW(RT_DEBUG_TRACE,
1207 ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1211 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1213 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
1222 ========================================================================
1223 Routine Description:
1227 *pAd the raxx interface data pointer
1233 ========================================================================
1235 VOID RT28XXDMADisable(
1236 IN RTMP_ADAPTER *pAd)
1244 ========================================================================
1245 Routine Description:
1249 *pAd the raxx interface data pointer
1255 ========================================================================
1257 VOID RT28XXDMAEnable(
1258 IN RTMP_ADAPTER *pAd)
1260 WPDMA_GLO_CFG_STRUC GloCfg;
1261 USB_DMA_CFG_STRUC UsbCfg;
1265 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1268 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1269 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1272 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
1273 RTMPusecDelay(1000);
1279 GloCfg.field.EnTXWriteBackDDONE = 1;
1280 GloCfg.field.EnableRxDMA = 1;
1281 GloCfg.field.EnableTxDMA = 1;
1282 DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1283 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1286 UsbCfg.field.phyclear = 0;
1287 /* usb version is 1.1,do not use bulk in aggregation */
1288 if (pAd->BulkInMaxPacketSize == 512)
1289 UsbCfg.field.RxBulkAggEn = 1;
1290 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1291 UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1292 UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1293 UsbCfg.field.RxBulkEn = 1;
1294 UsbCfg.field.TxBulkEn = 1;
1296 RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1301 ========================================================================
1302 Routine Description:
1303 Write Beacon buffer to Asic.
1306 *pAd the raxx interface data pointer
1312 ========================================================================
1314 VOID RT28xx_UpdateBeaconToAsic(
1315 IN RTMP_ADAPTER *pAd,
1320 PUCHAR pBeaconFrame = NULL;
1323 BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1325 BOOLEAN bBcnReq = FALSE;
1329 if (pBeaconFrame == NULL)
1331 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1335 if (pBeaconSync == NULL)
1337 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1341 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1342 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1344 if (bBcnReq == FALSE)
1346 /* when the ra interface is down, do not send its beacon frame */
1347 /* clear all zero */
1348 for(i=0; i<TXWI_SIZE; i+=4) {
1349 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1351 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1352 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1356 ptr = (PUCHAR)&pAd->BeaconTxWI;
1358 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1359 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1360 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1361 NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1364 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1366 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
1368 longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1369 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1374 ptr = pBeaconSync->BeaconBuf[bcn_idx];
1375 padding = (FrameLen & 0x01);
1376 NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1377 FrameLen += padding;
1378 for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1380 if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1382 NdisMoveMemory(ptr, pBeaconFrame, 2);
1383 //shortValue = *ptr + (*(ptr+1)<<8);
1384 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1385 RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1391 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1393 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1399 VOID RT2870_BssBeaconStop(
1400 IN RTMP_ADAPTER *pAd)
1402 BEACON_SYNC_STRUCT *pBeaconSync;
1404 BOOLEAN Cancelled = TRUE;
1406 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1407 if (pBeaconSync && pBeaconSync->EnableBeacon)
1411 NumOfBcn = MAX_MESH_NUM;
1413 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1415 for(i=0; i<NumOfBcn; i++)
1417 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1418 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1420 for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1421 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1423 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1424 pBeaconSync->TimIELocationInBeacon[i] = 0;
1426 pBeaconSync->BeaconBitMap = 0;
1427 pBeaconSync->DtimBitOn = 0;
1432 VOID RT2870_BssBeaconStart(
1433 IN RTMP_ADAPTER *pAd)
1436 BEACON_SYNC_STRUCT *pBeaconSync;
1437 // LARGE_INTEGER tsfTime, deltaTime;
1439 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1440 if (pBeaconSync && pBeaconSync->EnableBeacon)
1444 NumOfBcn = MAX_MESH_NUM;
1446 for(apidx=0; apidx<NumOfBcn; apidx++)
1448 UCHAR CapabilityInfoLocationInBeacon = 0;
1449 UCHAR TimIELocationInBeacon = 0;
1451 NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1452 pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1453 pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1454 NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1456 pBeaconSync->BeaconBitMap = 0;
1457 pBeaconSync->DtimBitOn = 0;
1458 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1460 pAd->CommonCfg.BeaconAdjust = 0;
1461 pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1462 pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1463 printk(RT28xx_CHIP_NAME "_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1464 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1470 VOID RT2870_BssBeaconInit(
1471 IN RTMP_ADAPTER *pAd)
1473 BEACON_SYNC_STRUCT *pBeaconSync;
1476 NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1477 if (pAd->CommonCfg.pBeaconSync)
1479 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1480 NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1481 for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1483 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1484 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1485 pBeaconSync->TimIELocationInBeacon[i] = 0;
1486 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1488 pBeaconSync->BeaconBitMap = 0;
1490 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1491 pBeaconSync->EnableBeacon = TRUE;
1496 VOID RT2870_BssBeaconExit(
1497 IN RTMP_ADAPTER *pAd)
1499 BEACON_SYNC_STRUCT *pBeaconSync;
1500 BOOLEAN Cancelled = TRUE;
1503 if (pAd->CommonCfg.pBeaconSync)
1505 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1506 pBeaconSync->EnableBeacon = FALSE;
1507 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1508 pBeaconSync->BeaconBitMap = 0;
1510 for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1512 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1513 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1514 pBeaconSync->TimIELocationInBeacon[i] = 0;
1515 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1518 NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1519 pAd->CommonCfg.pBeaconSync = NULL;
1523 VOID BeaconUpdateExec(
1524 IN PVOID SystemSpecific1,
1525 IN PVOID FunctionContext,
1526 IN PVOID SystemSpecific2,
1527 IN PVOID SystemSpecific3)
1529 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
1530 LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1531 UINT32 delta, remain, remain_low, remain_high;
1532 // BOOLEAN positive;
1534 ReSyncBeaconTime(pAd);
1538 RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1539 RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1542 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1543 remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1544 remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1545 remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1546 delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1548 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;