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 */
65 { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
66 { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
68 { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
69 { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
71 { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
72 { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
74 { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */
75 { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */
76 { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */
77 { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */
78 { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */
79 { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */
81 { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
83 { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
84 { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
86 { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
88 { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
89 { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
90 { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
92 { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
94 { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
95 { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
96 { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
98 { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
99 { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
101 { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
102 { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
103 { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
105 { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
106 { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
108 { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */
109 { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */
110 { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */
111 { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */
112 { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */
113 { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */
114 { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */
116 { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
118 { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
119 { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
120 { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
122 { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
123 { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
125 { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
127 { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
129 { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */
130 { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */
131 { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */
132 { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */
133 { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */
135 { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
137 { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
138 { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
139 { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
141 { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
143 { USB_DEVICE(0x083A, 0x6618) }, /* Accton */
144 { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */
145 { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */
146 { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */
147 { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */
148 { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */
149 { USB_DEVICE(0x050d, 0x805c) },
150 { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/
151 { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */
152 { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */
153 { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */
154 { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */
156 { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
157 { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
159 { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
161 { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
162 { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
163 { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
165 { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
167 { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
168 { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
169 { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
171 { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
173 { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
174 { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
176 { } /* Terminating entry */
179 INT
const rtusb_usb_id_len
= sizeof(rtusb_usb_id
) / sizeof(struct usb_device_id
);
180 MODULE_DEVICE_TABLE(usb
, rtusb_usb_id
);
183 #define PF_NOFREEZE 0
188 static int rt2870_suspend(struct usb_interface
*intf
, pm_message_t state
);
189 static int rt2870_resume(struct usb_interface
*intf
);
190 #endif // CONFIG_PM //
192 /**************************************************************************/
193 /**************************************************************************/
194 //tested for kernel 2.6series
195 /**************************************************************************/
196 /**************************************************************************/
197 static int rtusb_probe (struct usb_interface
*intf
,
198 const struct usb_device_id
*id
);
199 static void rtusb_disconnect(struct usb_interface
*intf
);
201 struct usb_driver rtusb_driver
= {
204 .disconnect
=rtusb_disconnect
,
205 .id_table
=rtusb_usb_id
,
208 suspend
: rt2870_suspend
,
209 resume
: rt2870_resume
,
215 VOID
RT2860RejectPendingPackets(
216 IN PRTMP_ADAPTER pAd
)
219 // clear TxSw packets
222 static int rt2870_suspend(
223 struct usb_interface
*intf
,
226 struct net_device
*net_dev
;
227 PRTMP_ADAPTER pAd
= usb_get_intfdata(intf
);
230 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2870_suspend()\n"));
231 net_dev
= pAd
->net_dev
;
232 netif_device_detach (net_dev
);
234 pAd
->PM_FlgSuspend
= 1;
235 if (netif_running(net_dev
)) {
236 RTUSBCancelPendingBulkInIRP(pAd
);
237 RTUSBCancelPendingBulkOutIRP(pAd
);
239 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2870_suspend()\n"));
243 static int rt2870_resume(
244 struct usb_interface
*intf
)
246 struct net_device
*net_dev
;
247 PRTMP_ADAPTER pAd
= usb_get_intfdata(intf
);
250 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2870_resume()\n"));
252 pAd
->PM_FlgSuspend
= 0;
253 net_dev
= pAd
->net_dev
;
254 netif_device_attach (net_dev
);
255 netif_start_queue(net_dev
);
256 netif_carrier_on(net_dev
);
257 netif_wake_queue(net_dev
);
259 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2870_resume()\n"));
262 #endif // CONFIG_PM //
265 // Init driver module
266 INT __init
rtusb_init(void)
268 printk("rtusb init --->\n");
269 return usb_register(&rtusb_driver
);
272 // Deinit driver module
273 VOID __exit
rtusb_exit(void)
275 usb_deregister(&rtusb_driver
);
276 printk("<--- rtusb exit\n");
279 module_init(rtusb_init
);
280 module_exit(rtusb_exit
);
285 /*--------------------------------------------------------------------- */
286 /* function declarations */
287 /*--------------------------------------------------------------------- */
290 ========================================================================
295 *Context the pAd, driver control block pointer
301 ========================================================================
306 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)Context
;
310 pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
312 rtmp_os_thread_init("rt2870MlmeThread", (PVOID
)&(pAd
->mlmeComplete
));
314 while (pAd
->mlme_kill
== 0)
316 /* lock the device pointers */
317 //down(&(pAd->mlme_semaphore));
318 status
= down_interruptible(&(pAd
->mlme_semaphore
));
320 /* lock the device pointers , need to check if required*/
321 //down(&(pAd->usbdev_semaphore));
323 if (!pAd
->PM_FlgSuspend
)
326 /* unlock the device pointers */
327 //up(&(pAd->usbdev_semaphore));
330 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
335 /* notify the exit routine that we're actually exiting now
337 * complete()/wait_for_completion() is similar to up()/down(),
338 * except that complete() is safe in the case where the structure
339 * is getting deleted in a parallel mode of execution (i.e. just
340 * after the down() -- that's necessary for the thread-shutdown
343 * complete_and_exit() goes even further than this -- it is safe in
344 * the case that the thread of the caller is going away (not just
345 * the structure) -- this is necessary for the module-remove case.
346 * This is important in preemption kernels, which transfer the flow
347 * of execution immediately upon a complete().
349 DBGPRINT(RT_DEBUG_TRACE
,( "<---%s\n",__func__
));
352 pObj
->MLMEThr_pid
= THREAD_PID_INIT_VALUE
;
355 pObj
->MLMEThr_pid
= NULL
;
358 complete_and_exit (&pAd
->mlmeComplete
, 0);
365 ========================================================================
367 USB command kernel thread.
370 *Context the pAd, driver control block pointer
376 ========================================================================
381 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)Context
;
385 pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
387 rtmp_os_thread_init("rt2870CmdThread", (PVOID
)&(pAd
->CmdQComplete
));
389 NdisAcquireSpinLock(&pAd
->CmdQLock
);
390 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_RUNNING
;
391 NdisReleaseSpinLock(&pAd
->CmdQLock
);
393 while (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_RUNNING
)
395 /* lock the device pointers */
396 //down(&(pAd->RTUSBCmd_semaphore));
397 status
= down_interruptible(&(pAd
->RTUSBCmd_semaphore
));
399 if (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_STOPED
)
404 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
407 /* lock the device pointers , need to check if required*/
408 //down(&(pAd->usbdev_semaphore));
410 if (!pAd
->PM_FlgSuspend
)
413 /* unlock the device pointers */
414 //up(&(pAd->usbdev_semaphore));
417 if (!pAd
->PM_FlgSuspend
)
418 { // Clear the CmdQElements.
419 CmdQElmt
*pCmdQElmt
= NULL
;
421 NdisAcquireSpinLock(&pAd
->CmdQLock
);
422 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
423 while(pAd
->CmdQ
.size
)
425 RTUSBDequeueCmd(&pAd
->CmdQ
, &pCmdQElmt
);
428 if (pCmdQElmt
->CmdFromNdis
== TRUE
)
430 if (pCmdQElmt
->buffer
!= NULL
)
431 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
433 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
437 if ((pCmdQElmt
->buffer
!= NULL
) && (pCmdQElmt
->bufferlength
!= 0))
438 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
440 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
446 NdisReleaseSpinLock(&pAd
->CmdQLock
);
448 /* notify the exit routine that we're actually exiting now
450 * complete()/wait_for_completion() is similar to up()/down(),
451 * except that complete() is safe in the case where the structure
452 * is getting deleted in a parallel mode of execution (i.e. just
453 * after the down() -- that's necessary for the thread-shutdown
456 * complete_and_exit() goes even further than this -- it is safe in
457 * the case that the thread of the caller is going away (not just
458 * the structure) -- this is necessary for the module-remove case.
459 * This is important in preemption kernels, which transfer the flow
460 * of execution immediately upon a complete().
462 DBGPRINT(RT_DEBUG_TRACE
,( "<---RTUSBCmdThread\n"));
465 pObj
->RTUSBCmdThr_pid
= THREAD_PID_INIT_VALUE
;
468 pObj
->RTUSBCmdThr_pid
= NULL
;
471 complete_and_exit (&pAd
->CmdQComplete
, 0);
477 static void RT2870_TimerQ_Handle(RTMP_ADAPTER
*pAd
)
480 RALINK_TIMER_STRUCT
*pTimer
;
481 RT2870_TIMER_ENTRY
*pEntry
;
482 unsigned long irqFlag
;
484 while(!pAd
->TimerFunc_kill
)
486 // printk("waiting for event!\n");
489 status
= down_interruptible(&(pAd
->RTUSBTimer_semaphore
));
491 if (pAd
->TimerQ
.status
== RT2870_THREAD_STOPED
)
495 while(pAd
->TimerQ
.pQHead
)
497 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlag
);
498 pEntry
= pAd
->TimerQ
.pQHead
;
501 pTimer
= pEntry
->pRaTimer
;
504 pAd
->TimerQ
.pQHead
= pEntry
->pNext
;
505 if (pEntry
== pAd
->TimerQ
.pQTail
)
506 pAd
->TimerQ
.pQTail
= NULL
;
508 // return this queue entry to timerQFreeList.
509 pEntry
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
510 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
512 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlag
);
516 if (pTimer
->handle
!= NULL
)
517 if (!pAd
->PM_FlgSuspend
)
518 pTimer
->handle(NULL
, (PVOID
) pTimer
->cookie
, NULL
, pTimer
);
519 if ((pTimer
->Repeat
) && (pTimer
->State
== FALSE
))
520 RTMP_OS_Add_Timer(&pTimer
->TimerObj
, pTimer
->TimerValue
);
526 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
527 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
535 IN OUT PVOID Context
)
540 pAd
= (PRTMP_ADAPTER
)Context
;
541 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
543 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID
)&(pAd
->TimerQComplete
));
545 RT2870_TimerQ_Handle(pAd
);
547 /* notify the exit routine that we're actually exiting now
549 * complete()/wait_for_completion() is similar to up()/down(),
550 * except that complete() is safe in the case where the structure
551 * is getting deleted in a parallel mode of execution (i.e. just
552 * after the down() -- that's necessary for the thread-shutdown
555 * complete_and_exit() goes even further than this -- it is safe in
556 * the case that the thread of the caller is going away (not just
557 * the structure) -- this is necessary for the module-remove case.
558 * This is important in preemption kernels, which transfer the flow
559 * of execution immediately upon a complete().
561 DBGPRINT(RT_DEBUG_TRACE
,( "<---%s\n",__func__
));
564 pObj
->TimerQThr_pid
= THREAD_PID_INIT_VALUE
;
567 pObj
->TimerQThr_pid
= NULL
;
569 complete_and_exit(&pAd
->TimerQComplete
, 0);
575 RT2870_TIMER_ENTRY
*RT2870_TimerQ_Insert(
576 IN RTMP_ADAPTER
*pAd
,
577 IN RALINK_TIMER_STRUCT
*pTimer
)
579 RT2870_TIMER_ENTRY
*pQNode
= NULL
, *pQTail
;
580 unsigned long irqFlags
;
583 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
584 if (pAd
->TimerQ
.status
& RT2870_THREAD_CAN_DO_INSERT
)
586 if(pAd
->TimerQ
.pQPollFreeList
)
588 pQNode
= pAd
->TimerQ
.pQPollFreeList
;
589 pAd
->TimerQ
.pQPollFreeList
= pQNode
->pNext
;
591 pQNode
->pRaTimer
= pTimer
;
592 pQNode
->pNext
= NULL
;
594 pQTail
= pAd
->TimerQ
.pQTail
;
595 if (pAd
->TimerQ
.pQTail
!= NULL
)
596 pQTail
->pNext
= pQNode
;
597 pAd
->TimerQ
.pQTail
= pQNode
;
598 if (pAd
->TimerQ
.pQHead
== NULL
)
599 pAd
->TimerQ
.pQHead
= pQNode
;
601 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
604 up(&pAd
->RTUSBTimer_semaphore
);
605 //wake_up(&timerWaitQ);
609 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
615 BOOLEAN
RT2870_TimerQ_Remove(
616 IN RTMP_ADAPTER
*pAd
,
617 IN RALINK_TIMER_STRUCT
*pTimer
)
619 RT2870_TIMER_ENTRY
*pNode
, *pPrev
= NULL
;
620 unsigned long irqFlags
;
622 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
623 if (pAd
->TimerQ
.status
>= RT2870_THREAD_INITED
)
625 pNode
= pAd
->TimerQ
.pQHead
;
628 if (pNode
->pRaTimer
== pTimer
)
631 pNode
= pNode
->pNext
;
634 // Now move it to freeList queue.
637 if (pNode
== pAd
->TimerQ
.pQHead
)
638 pAd
->TimerQ
.pQHead
= pNode
->pNext
;
639 if (pNode
== pAd
->TimerQ
.pQTail
)
640 pAd
->TimerQ
.pQTail
= pPrev
;
642 pPrev
->pNext
= pNode
->pNext
;
644 // return this queue entry to timerQFreeList.
645 pNode
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
646 pAd
->TimerQ
.pQPollFreeList
= pNode
;
649 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
655 void RT2870_TimerQ_Exit(RTMP_ADAPTER
*pAd
)
657 RT2870_TIMER_ENTRY
*pTimerQ
;
658 unsigned long irqFlags
;
660 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
661 while (pAd
->TimerQ
.pQHead
)
663 pTimerQ
= pAd
->TimerQ
.pQHead
;
664 pAd
->TimerQ
.pQHead
= pTimerQ
->pNext
;
667 pAd
->TimerQ
.pQPollFreeList
= NULL
;
668 os_free_mem(pAd
, pAd
->TimerQ
.pTimerQPoll
);
669 pAd
->TimerQ
.pQTail
= NULL
;
670 pAd
->TimerQ
.pQHead
= NULL
;
671 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
672 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
677 void RT2870_TimerQ_Init(RTMP_ADAPTER
*pAd
)
680 RT2870_TIMER_ENTRY
*pQNode
, *pEntry
;
681 unsigned long irqFlags
;
683 NdisAllocateSpinLock(&pAd
->TimerQLock
);
685 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
686 NdisZeroMemory(&pAd
->TimerQ
, sizeof(pAd
->TimerQ
));
687 //InterlockedExchange(&pAd->TimerQ.count, 0);
689 /* Initialise the wait q head */
690 //init_waitqueue_head(&timerWaitQ);
692 os_alloc_mem(pAd
, &pAd
->TimerQ
.pTimerQPoll
, sizeof(RT2870_TIMER_ENTRY
) * TIMER_QUEUE_SIZE_MAX
);
693 if (pAd
->TimerQ
.pTimerQPoll
)
696 pQNode
= (RT2870_TIMER_ENTRY
*)pAd
->TimerQ
.pTimerQPoll
;
697 for (i
= 0 ;i
<TIMER_QUEUE_SIZE_MAX
; i
++)
699 pQNode
->pNext
= pEntry
;
703 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
704 pAd
->TimerQ
.pQHead
= NULL
;
705 pAd
->TimerQ
.pQTail
= NULL
;
706 pAd
->TimerQ
.status
= RT2870_THREAD_INITED
;
708 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
712 VOID
RT2870_WatchDog(IN RTMP_ADAPTER
*pAd
)
714 PHT_TX_CONTEXT pHTTXContext
;
718 BOOLEAN needDumpSeq
= FALSE
;
723 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
724 if ((MACValue
& 0xff) !=0 )
726 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
727 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40012);
728 while((MACValue
&0xff) != 0 && (idx
++ < 10))
730 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
733 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
736 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
738 if ((MACValue
& 0xff00) !=0 )
740 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
741 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf4000a);
742 while((MACValue
&0xff00) != 0 && (idx
++ < 10))
744 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
747 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
750 if (pAd
->watchDogRxOverFlowCnt
>= 2)
752 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
753 if ((!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
|
754 fRTMP_ADAPTER_BULKIN_RESET
|
755 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
756 fRTMP_ADAPTER_NIC_NOT_EXIST
))))
758 DBGPRINT(RT_DEBUG_TRACE
, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
759 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_BULKIN_RESET
);
760 RTUSBEnqueueInternalCmd(pAd
, CMDTHREAD_RESET_BULK_IN
, NULL
, 0);
763 pAd
->watchDogRxOverFlowCnt
= 0;
767 for (idx
= 0; idx
< NUM_OF_TX_RING
; idx
++)
771 RTMP_IRQ_LOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
772 if ((pAd
->BulkOutPending
[idx
] == TRUE
) && pAd
->watchDogTxPendingCnt
)
774 pAd
->watchDogTxPendingCnt
[idx
]++;
776 if ((pAd
->watchDogTxPendingCnt
[idx
] > 2) &&
777 (!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
| fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
| fRTMP_ADAPTER_BULKOUT_RESET
)))
780 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
781 pHTTXContext
= (PHT_TX_CONTEXT
)(&pAd
->TxContext
[idx
]);
782 if (pHTTXContext
->IRPPending
)
783 { // Check TxContext.
784 pUrb
= pHTTXContext
->pUrb
;
786 else if (idx
== MGMTPIPEIDX
)
788 PTX_CONTEXT pMLMEContext
, pNULLContext
, pPsPollContext
;
791 pMLMEContext
= (PTX_CONTEXT
)(pAd
->MgmtRing
.Cell
[pAd
->MgmtRing
.TxDmaIdx
].AllocVa
);
792 pPsPollContext
= (PTX_CONTEXT
)(&pAd
->PsPollContext
);
793 pNULLContext
= (PTX_CONTEXT
)(&pAd
->NullContext
);
795 if (pMLMEContext
->IRPPending
)
797 ASSERT(pMLMEContext
->IRPPending
);
798 pUrb
= pMLMEContext
->pUrb
;
800 else if (pNULLContext
->IRPPending
)
802 ASSERT(pNULLContext
->IRPPending
);
803 pUrb
= pNULLContext
->pUrb
;
805 else if (pPsPollContext
->IRPPending
)
807 ASSERT(pPsPollContext
->IRPPending
);
808 pUrb
= pPsPollContext
->pUrb
;
812 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
814 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx
));
817 DBGPRINT(RT_DEBUG_TRACE
, ("Unlink the pending URB!\n"));
819 RTUSB_UNLINK_URB(pUrb
);
820 // Sleep 200 microseconds to give cancellation time to work
826 DBGPRINT(RT_DEBUG_ERROR
, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
831 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
836 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
840 // For Sigma debug, dump the ba_reordering sequence.
841 if((needDumpSeq
== TRUE
) && (pAd
->CommonCfg
.bDisableReordering
== 0))
844 PBA_REC_ENTRY pBAEntry
= NULL
;
846 struct reordering_mpdu
*mpdu_blk
;
848 Idx
= pAd
->MacTab
.Content
[BSSID_WCID
].BARecWcidArray
[0];
850 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
851 if((pBAEntry
->list
.qlen
> 0) && (pBAEntry
->list
.next
!= NULL
))
853 DBGPRINT(RT_DEBUG_TRACE
, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
854 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
855 mpdu_blk
= pBAEntry
->list
.next
;
858 DBGPRINT(RT_DEBUG_TRACE
, ("\t%d:Seq-%d, bAMSDU-%d!\n", count
, mpdu_blk
->Sequence
, mpdu_blk
->bAMSDU
));
859 mpdu_blk
= mpdu_blk
->next
;
863 DBGPRINT(RT_DEBUG_TRACE
, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry
->LastIndSeq
));
864 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
870 ========================================================================
872 Release allocated resources.
875 *dev Point to the PCI or USB device
876 pAd driver control block pointer
882 ========================================================================
884 static void _rtusb_disconnect(struct usb_device
*dev
, PRTMP_ADAPTER pAd
)
886 struct net_device
*net_dev
= NULL
;
889 DBGPRINT(RT_DEBUG_ERROR
, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
890 dev
->bus
->bus_name
, dev
->devpath
));
895 printk("rtusb_disconnect: pAd == NULL!\n");
898 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
);
902 // for debug, wait to show some messages to /proc system
908 net_dev
= pAd
->net_dev
;
909 if (pAd
->net_dev
!= NULL
)
911 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev
->name
);
912 unregister_netdev (pAd
->net_dev
);
915 flush_scheduled_work();
918 // free net_device memory
919 free_netdev(net_dev
);
921 // free adapter memory
922 RTMPFreeAdapter(pAd
);
924 // release a use of the usb device structure
928 DBGPRINT(RT_DEBUG_ERROR
, (" RTUSB disconnect successfully\n"));
933 ========================================================================
935 Probe RT28XX chipset.
938 *dev Point to the PCI or USB device
940 *id_table Point to the PCI or USB device ID
946 ========================================================================
948 static int rtusb_probe (struct usb_interface
*intf
,
949 const struct usb_device_id
*id
)
952 return (int)rt28xx_probe((void *)intf
, (void *)id
, 0, &pAd
);
956 static void rtusb_disconnect(struct usb_interface
*intf
)
958 struct usb_device
*dev
= interface_to_usbdev(intf
);
962 pAd
= usb_get_intfdata(intf
);
963 usb_set_intfdata(intf
, NULL
);
965 _rtusb_disconnect(dev
, pAd
);
970 ========================================================================
972 Close kernel threads.
975 *pAd the raxx interface data pointer
981 ========================================================================
983 VOID
RT28xxThreadTerminate(
984 IN RTMP_ADAPTER
*pAd
)
986 POS_COOKIE pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
990 // Sleep 50 milliseconds so pending io might finish normally
991 RTMPusecDelay(50000);
993 // We want to wait until all pending receives and sends to the
994 // device object. We cancel any
995 // irps. Wait until sends and receives have stopped.
996 RTUSBCancelPendingIRPs(pAd
);
1000 CHECK_PID_LEGALITY(pObj
->TimerQThr_pid
)
1002 POS_COOKIE pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
1004 printk("Terminate the TimerQThr_pid=%d!\n", GET_PID_NUMBER(pObj
->TimerQThr_pid
));
1006 pAd
->TimerFunc_kill
= 1;
1008 ret
= KILL_THREAD_PID(pObj
->TimerQThr_pid
, SIGTERM
, 1);
1011 printk(KERN_WARNING
"%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
1012 pAd
->net_dev
->name
, GET_PID_NUMBER(pObj
->TimerQThr_pid
), ret
);
1016 wait_for_completion(&pAd
->TimerQComplete
);
1017 pObj
->TimerQThr_pid
= THREAD_PID_INIT_VALUE
;
1021 CHECK_PID_LEGALITY(pObj
->MLMEThr_pid
)
1023 printk("Terminate the MLMEThr_pid=%d!\n", GET_PID_NUMBER(pObj
->MLMEThr_pid
));
1026 //RT28XX_MLME_HANDLER(pAd);
1028 ret
= KILL_THREAD_PID(pObj
->MLMEThr_pid
, SIGTERM
, 1);
1031 printk (KERN_WARNING
"%s: unable to Mlme thread, pid=%d, ret=%d!\n",
1032 pAd
->net_dev
->name
, GET_PID_NUMBER(pObj
->MLMEThr_pid
), ret
);
1036 //wait_for_completion (&pAd->notify);
1037 wait_for_completion (&pAd
->mlmeComplete
);
1038 pObj
->MLMEThr_pid
= THREAD_PID_INIT_VALUE
;
1042 CHECK_PID_LEGALITY(pObj
->RTUSBCmdThr_pid
)
1044 printk("Terminate the RTUSBCmdThr_pid=%d!\n", GET_PID_NUMBER(pObj
->RTUSBCmdThr_pid
));
1046 NdisAcquireSpinLock(&pAd
->CmdQLock
);
1047 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
1048 NdisReleaseSpinLock(&pAd
->CmdQLock
);
1051 ret
= KILL_THREAD_PID(pObj
->RTUSBCmdThr_pid
, SIGTERM
, 1);
1054 printk(KERN_WARNING
"%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1055 pAd
->net_dev
->name
, GET_PID_NUMBER(pObj
->RTUSBCmdThr_pid
), ret
);
1059 //wait_for_completion (&pAd->notify);
1060 wait_for_completion (&pAd
->CmdQComplete
);
1061 pObj
->RTUSBCmdThr_pid
= THREAD_PID_INIT_VALUE
;
1066 if (pid_nr(pObj
->MLMEThr_pid
) > 0)
1068 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj
->MLMEThr_pid
));
1071 //RT28XX_MLME_HANDLER(pAd);
1073 ret
= kill_pid(pObj
->MLMEThr_pid
, SIGTERM
, 1);
1076 printk (KERN_WARNING
"%s: unable to Mlme thread, pid=%d, ret=%d!\n",
1077 pAd
->net_dev
->name
, pid_nr(pObj
->MLMEThr_pid
), ret
);
1081 //wait_for_completion (&pAd->notify);
1082 wait_for_completion (&pAd
->mlmeComplete
);
1083 pObj
->MLMEThr_pid
= NULL
;
1087 if (pid_nr(pObj
->RTUSBCmdThr_pid
) > 0)
1089 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj
->RTUSBCmdThr_pid
));
1091 NdisAcquireSpinLock(&pAd
->CmdQLock
);
1092 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
1093 NdisReleaseSpinLock(&pAd
->CmdQLock
);
1096 ret
= kill_pid(pObj
->RTUSBCmdThr_pid
, SIGTERM
, 1);
1099 printk(KERN_WARNING
"%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1100 pAd
->net_dev
->name
, pid_nr(pObj
->RTUSBCmdThr_pid
), ret
);
1104 //wait_for_completion (&pAd->notify);
1105 wait_for_completion (&pAd
->CmdQComplete
);
1106 pObj
->RTUSBCmdThr_pid
= NULL
;
1109 if (pid_nr(pObj
->TimerQThr_pid
) > 0)
1111 POS_COOKIE pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
1112 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj
->TimerQThr_pid
));
1114 pAd
->TimerFunc_kill
= 1;
1116 ret
= kill_pid(pObj
->TimerQThr_pid
, SIGTERM
, 1);
1119 printk(KERN_WARNING
"%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
1120 pAd
->net_dev
->name
, pid_nr(pObj
->TimerQThr_pid
), ret
);
1124 printk("wait_for_completion TimerQThr\n");
1125 wait_for_completion(&pAd
->TimerQComplete
);
1126 pObj
->TimerQThr_pid
= NULL
;
1133 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_UNKNOWN
;
1134 pAd
->TimerFunc_kill
= 0;
1138 void kill_thread_task(IN PRTMP_ADAPTER pAd
)
1142 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
1144 tasklet_kill(&pObj
->rx_done_task
);
1145 tasklet_kill(&pObj
->mgmt_dma_done_task
);
1146 tasklet_kill(&pObj
->ac0_dma_done_task
);
1147 tasklet_kill(&pObj
->ac1_dma_done_task
);
1148 tasklet_kill(&pObj
->ac2_dma_done_task
);
1149 tasklet_kill(&pObj
->ac3_dma_done_task
);
1150 tasklet_kill(&pObj
->hcca_dma_done_task
);
1151 tasklet_kill(&pObj
->tbtt_task
);
1157 ========================================================================
1158 Routine Description:
1159 Check the chipset vendor/product ID.
1162 _dev_p Point to the PCI or USB device
1169 ========================================================================
1171 BOOLEAN
RT28XXChipsetCheck(
1174 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1175 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1179 for(i
=0; i
<rtusb_usb_id_len
; i
++)
1181 if (dev_p
->descriptor
.idVendor
== rtusb_usb_id
[i
].idVendor
&&
1182 dev_p
->descriptor
.idProduct
== rtusb_usb_id
[i
].idProduct
)
1185 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1188 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1190 dev_p
->descriptor
.idVendor
, dev_p
->descriptor
.idProduct
);
1195 if (i
== rtusb_usb_id_len
)
1197 printk("rt2870: Error! Device Descriptor not matching!\n");
1206 ========================================================================
1207 Routine Description:
1208 Init net device structure.
1211 _dev_p Point to the PCI or USB device
1212 *net_dev Point to the net device
1213 *pAd the raxx interface data pointer
1220 ========================================================================
1222 BOOLEAN
RT28XXNetDevInit(
1224 IN
struct net_device
*net_dev
,
1225 IN RTMP_ADAPTER
*pAd
)
1227 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1228 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1231 pAd
->config
= &dev_p
->config
->desc
;
1237 ========================================================================
1238 Routine Description:
1239 Init net device structure.
1242 _dev_p Point to the PCI or USB device
1243 *pAd the raxx interface data pointer
1250 ========================================================================
1252 BOOLEAN
RT28XXProbePostConfig(
1254 IN RTMP_ADAPTER
*pAd
,
1257 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1258 struct usb_host_interface
*iface_desc
;
1263 /* get the active interface descriptor */
1264 iface_desc
= intf
->cur_altsetting
;
1266 /* get # of enpoints */
1267 pAd
->NumberOfPipes
= iface_desc
->desc
.bNumEndpoints
;
1268 DBGPRINT(RT_DEBUG_TRACE
,
1269 ("NumEndpoints=%d\n", iface_desc
->desc
.bNumEndpoints
));
1271 /* Configure Pipes */
1274 for(i
=0; i
<pAd
->NumberOfPipes
; i
++)
1276 if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1277 USB_ENDPOINT_XFER_BULK
) &&
1278 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1279 USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
))
1281 pAd
->BulkInEpAddr
= iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1282 pAd
->BulkInMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1284 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1285 ("BULK IN MaximumPacketSize = %d\n", pAd
->BulkInMaxPacketSize
));
1286 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1287 ("EP address = 0x%2x\n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1289 else if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1290 USB_ENDPOINT_XFER_BULK
) &&
1291 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1292 USB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
))
1294 // there are 6 bulk out EP. EP6 highest priority.
1295 // EP1-4 is EDCA. EP5 is HCCA.
1296 pAd
->BulkOutEpAddr
[BulkOutIdx
++] = iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1297 pAd
->BulkOutMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1299 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1300 ("BULK OUT MaximumPacketSize = %d\n", pAd
->BulkOutMaxPacketSize
));
1301 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1302 ("EP address = 0x%2x \n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1306 if (!(pAd
->BulkInEpAddr
&& pAd
->BulkOutEpAddr
[0]))
1308 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__
);
1317 ========================================================================
1318 Routine Description:
1322 *pAd the raxx interface data pointer
1328 ========================================================================
1330 VOID
RT28XXDMADisable(
1331 IN RTMP_ADAPTER
*pAd
)
1339 ========================================================================
1340 Routine Description:
1344 *pAd the raxx interface data pointer
1350 ========================================================================
1352 VOID
RT28XXDMAEnable(
1353 IN RTMP_ADAPTER
*pAd
)
1355 WPDMA_GLO_CFG_STRUC GloCfg
;
1356 USB_DMA_CFG_STRUC UsbCfg
;
1360 RTMP_IO_WRITE32(pAd
, MAC_SYS_CTRL
, 0x4);
1363 RTMP_IO_READ32(pAd
, WPDMA_GLO_CFG
, &GloCfg
.word
);
1364 if ((GloCfg
.field
.TxDMABusy
== 0) && (GloCfg
.field
.RxDMABusy
== 0))
1367 DBGPRINT(RT_DEBUG_TRACE
, ("==> DMABusy\n"));
1368 RTMPusecDelay(1000);
1374 GloCfg
.field
.EnTXWriteBackDDONE
= 1;
1375 GloCfg
.field
.EnableRxDMA
= 1;
1376 GloCfg
.field
.EnableTxDMA
= 1;
1377 DBGPRINT(RT_DEBUG_TRACE
, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg
.word
));
1378 RTMP_IO_WRITE32(pAd
, WPDMA_GLO_CFG
, GloCfg
.word
);
1381 UsbCfg
.field
.phyclear
= 0;
1382 /* usb version is 1.1,do not use bulk in aggregation */
1383 if (pAd
->BulkInMaxPacketSize
== 512)
1384 UsbCfg
.field
.RxBulkAggEn
= 1;
1385 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1386 UsbCfg
.field
.RxBulkAggLmt
= (MAX_RXBULK_SIZE
/1024)-3;
1387 UsbCfg
.field
.RxBulkAggTOut
= 0x80; /* 2006-10-18 */
1388 UsbCfg
.field
.RxBulkEn
= 1;
1389 UsbCfg
.field
.TxBulkEn
= 1;
1391 RTUSBWriteMACRegister(pAd
, USB_DMA_CFG
, UsbCfg
.word
);
1396 ========================================================================
1397 Routine Description:
1398 Write Beacon buffer to Asic.
1401 *pAd the raxx interface data pointer
1407 ========================================================================
1409 VOID
RT28xx_UpdateBeaconToAsic(
1410 IN RTMP_ADAPTER
*pAd
,
1415 PUCHAR pBeaconFrame
= NULL
;
1418 BEACON_SYNC_STRUCT
*pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1420 BOOLEAN bBcnReq
= FALSE
;
1424 if (pBeaconFrame
== NULL
)
1426 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconFrame is NULL!\n"));
1430 if (pBeaconSync
== NULL
)
1432 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconSync is NULL!\n"));
1436 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1437 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1439 if (bBcnReq
== FALSE
)
1441 /* when the ra interface is down, do not send its beacon frame */
1442 /* clear all zero */
1443 for(i
=0; i
<TXWI_SIZE
; i
+=4) {
1444 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, 0x00);
1446 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1447 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], TXWI_SIZE
);
1451 ptr
= (PUCHAR
)&pAd
->BeaconTxWI
;
1453 if (NdisEqualMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
) == FALSE
)
1454 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1455 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1456 NdisMoveMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
);
1459 if ((pBeaconSync
->BeaconBitMap
& (1 << bcn_idx
)) != (1 << bcn_idx
))
1461 for (i
=0; i
<TXWI_SIZE
; i
+=4) // 16-byte TXWI field
1463 longValue
= *ptr
+ (*(ptr
+1)<<8) + (*(ptr
+2)<<16) + (*(ptr
+3)<<24);
1464 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, longValue
);
1469 ptr
= pBeaconSync
->BeaconBuf
[bcn_idx
];
1470 padding
= (FrameLen
& 0x01);
1471 NdisZeroMemory((PUCHAR
)(pBeaconFrame
+ FrameLen
), padding
);
1472 FrameLen
+= padding
;
1473 for (i
= 0 ; i
< FrameLen
/*HW_BEACON_OFFSET*/; i
+= 2)
1475 if (NdisEqualMemory(ptr
, pBeaconFrame
, 2) == FALSE
)
1477 NdisMoveMemory(ptr
, pBeaconFrame
, 2);
1478 //shortValue = *ptr + (*(ptr+1)<<8);
1479 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1480 RTUSBMultiWrite(pAd
, pAd
->BeaconOffset
[bcn_idx
] + TXWI_SIZE
+ i
, ptr
, 2);
1486 pBeaconSync
->BeaconBitMap
|= (1 << bcn_idx
);
1488 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1494 VOID
RT2870_BssBeaconStop(
1495 IN RTMP_ADAPTER
*pAd
)
1497 BEACON_SYNC_STRUCT
*pBeaconSync
;
1499 BOOLEAN Cancelled
= TRUE
;
1501 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1502 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1506 NumOfBcn
= MAX_MESH_NUM
;
1508 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1510 for(i
=0; i
<NumOfBcn
; i
++)
1512 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1513 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1515 for (offset
=0; offset
<HW_BEACON_OFFSET
; offset
+=4)
1516 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[i
] + offset
, 0x00);
1518 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1519 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1521 pBeaconSync
->BeaconBitMap
= 0;
1522 pBeaconSync
->DtimBitOn
= 0;
1527 VOID
RT2870_BssBeaconStart(
1528 IN RTMP_ADAPTER
*pAd
)
1531 BEACON_SYNC_STRUCT
*pBeaconSync
;
1532 // LARGE_INTEGER tsfTime, deltaTime;
1534 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1535 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1539 NumOfBcn
= MAX_MESH_NUM
;
1541 for(apidx
=0; apidx
<NumOfBcn
; apidx
++)
1543 UCHAR CapabilityInfoLocationInBeacon
= 0;
1544 UCHAR TimIELocationInBeacon
= 0;
1546 NdisZeroMemory(pBeaconSync
->BeaconBuf
[apidx
], HW_BEACON_OFFSET
);
1547 pBeaconSync
->CapabilityInfoLocationInBeacon
[apidx
] = CapabilityInfoLocationInBeacon
;
1548 pBeaconSync
->TimIELocationInBeacon
[apidx
] = TimIELocationInBeacon
;
1549 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[apidx
], TXWI_SIZE
);
1551 pBeaconSync
->BeaconBitMap
= 0;
1552 pBeaconSync
->DtimBitOn
= 0;
1553 pAd
->CommonCfg
.BeaconUpdateTimer
.Repeat
= TRUE
;
1555 pAd
->CommonCfg
.BeaconAdjust
= 0;
1556 pAd
->CommonCfg
.BeaconFactor
= 0xffffffff / (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1557 pAd
->CommonCfg
.BeaconRemain
= (0xffffffff % (pAd
->CommonCfg
.BeaconPeriod
<< 10)) + 1;
1558 printk(RT28xx_CHIP_NAME
"_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd
->CommonCfg
.BeaconFactor
, pAd
->CommonCfg
.BeaconRemain
);
1559 RTMPSetTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, pAd
->CommonCfg
.BeaconPeriod
);
1565 VOID
RT2870_BssBeaconInit(
1566 IN RTMP_ADAPTER
*pAd
)
1568 BEACON_SYNC_STRUCT
*pBeaconSync
;
1571 NdisAllocMemory(pAd
->CommonCfg
.pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
), MEM_ALLOC_FLAG
);
1572 if (pAd
->CommonCfg
.pBeaconSync
)
1574 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1575 NdisZeroMemory(pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
));
1576 for(i
=0; i
< HW_BEACON_MAX_COUNT
; i
++)
1578 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1579 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1580 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1581 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1583 pBeaconSync
->BeaconBitMap
= 0;
1585 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1586 pBeaconSync
->EnableBeacon
= TRUE
;
1591 VOID
RT2870_BssBeaconExit(
1592 IN RTMP_ADAPTER
*pAd
)
1594 BEACON_SYNC_STRUCT
*pBeaconSync
;
1595 BOOLEAN Cancelled
= TRUE
;
1598 if (pAd
->CommonCfg
.pBeaconSync
)
1600 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1601 pBeaconSync
->EnableBeacon
= FALSE
;
1602 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1603 pBeaconSync
->BeaconBitMap
= 0;
1605 for(i
=0; i
<HW_BEACON_MAX_COUNT
; i
++)
1607 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1608 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1609 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1610 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1613 NdisFreeMemory(pAd
->CommonCfg
.pBeaconSync
, HW_BEACON_OFFSET
* HW_BEACON_MAX_COUNT
, 0);
1614 pAd
->CommonCfg
.pBeaconSync
= NULL
;
1618 VOID
BeaconUpdateExec(
1619 IN PVOID SystemSpecific1
,
1620 IN PVOID FunctionContext
,
1621 IN PVOID SystemSpecific2
,
1622 IN PVOID SystemSpecific3
)
1624 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)FunctionContext
;
1625 LARGE_INTEGER tsfTime_a
;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1626 UINT32 delta
, remain
, remain_low
, remain_high
;
1627 // BOOLEAN positive;
1629 ReSyncBeaconTime(pAd
);
1633 RTMP_IO_READ32(pAd
, TSF_TIMER_DW0
, &tsfTime_a
.u
.LowPart
);
1634 RTMP_IO_READ32(pAd
, TSF_TIMER_DW1
, &tsfTime_a
.u
.HighPart
);
1637 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1638 remain_high
= pAd
->CommonCfg
.BeaconRemain
* tsfTime_a
.u
.HighPart
;
1639 remain_low
= tsfTime_a
.u
.LowPart
% (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1640 remain
= (remain_high
+ remain_low
)%(pAd
->CommonCfg
.BeaconPeriod
<< 10);
1641 delta
= (pAd
->CommonCfg
.BeaconPeriod
<< 10) - remain
;
1643 pAd
->CommonCfg
.BeaconUpdateTimer
.TimerValue
= (delta
>> 10) + 10;