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__
));
351 pObj
->MLMEThr_pid
= NULL
;
353 complete_and_exit (&pAd
->mlmeComplete
, 0);
360 ========================================================================
362 USB command kernel thread.
365 *Context the pAd, driver control block pointer
371 ========================================================================
376 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)Context
;
380 pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
382 rtmp_os_thread_init("rt2870CmdThread", (PVOID
)&(pAd
->CmdQComplete
));
384 NdisAcquireSpinLock(&pAd
->CmdQLock
);
385 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_RUNNING
;
386 NdisReleaseSpinLock(&pAd
->CmdQLock
);
388 while (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_RUNNING
)
390 /* lock the device pointers */
391 //down(&(pAd->RTUSBCmd_semaphore));
392 status
= down_interruptible(&(pAd
->RTUSBCmd_semaphore
));
394 if (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_STOPED
)
399 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
402 /* lock the device pointers , need to check if required*/
403 //down(&(pAd->usbdev_semaphore));
405 if (!pAd
->PM_FlgSuspend
)
408 /* unlock the device pointers */
409 //up(&(pAd->usbdev_semaphore));
412 if (!pAd
->PM_FlgSuspend
)
413 { // Clear the CmdQElements.
414 CmdQElmt
*pCmdQElmt
= NULL
;
416 NdisAcquireSpinLock(&pAd
->CmdQLock
);
417 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
418 while(pAd
->CmdQ
.size
)
420 RTUSBDequeueCmd(&pAd
->CmdQ
, &pCmdQElmt
);
423 if (pCmdQElmt
->CmdFromNdis
== TRUE
)
425 if (pCmdQElmt
->buffer
!= NULL
)
426 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
428 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
432 if ((pCmdQElmt
->buffer
!= NULL
) && (pCmdQElmt
->bufferlength
!= 0))
433 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
435 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
441 NdisReleaseSpinLock(&pAd
->CmdQLock
);
443 /* notify the exit routine that we're actually exiting now
445 * complete()/wait_for_completion() is similar to up()/down(),
446 * except that complete() is safe in the case where the structure
447 * is getting deleted in a parallel mode of execution (i.e. just
448 * after the down() -- that's necessary for the thread-shutdown
451 * complete_and_exit() goes even further than this -- it is safe in
452 * the case that the thread of the caller is going away (not just
453 * the structure) -- this is necessary for the module-remove case.
454 * This is important in preemption kernels, which transfer the flow
455 * of execution immediately upon a complete().
457 DBGPRINT(RT_DEBUG_TRACE
,( "<---RTUSBCmdThread\n"));
459 pObj
->RTUSBCmdThr_pid
= NULL
;
461 complete_and_exit (&pAd
->CmdQComplete
, 0);
467 static void RT2870_TimerQ_Handle(RTMP_ADAPTER
*pAd
)
470 RALINK_TIMER_STRUCT
*pTimer
;
471 RT2870_TIMER_ENTRY
*pEntry
;
472 unsigned long irqFlag
;
474 while(!pAd
->TimerFunc_kill
)
476 // printk("waiting for event!\n");
479 status
= down_interruptible(&(pAd
->RTUSBTimer_semaphore
));
481 if (pAd
->TimerQ
.status
== RT2870_THREAD_STOPED
)
485 while(pAd
->TimerQ
.pQHead
)
487 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlag
);
488 pEntry
= pAd
->TimerQ
.pQHead
;
491 pTimer
= pEntry
->pRaTimer
;
494 pAd
->TimerQ
.pQHead
= pEntry
->pNext
;
495 if (pEntry
== pAd
->TimerQ
.pQTail
)
496 pAd
->TimerQ
.pQTail
= NULL
;
498 // return this queue entry to timerQFreeList.
499 pEntry
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
500 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
502 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlag
);
506 if (pTimer
->handle
!= NULL
)
507 if (!pAd
->PM_FlgSuspend
)
508 pTimer
->handle(NULL
, (PVOID
) pTimer
->cookie
, NULL
, pTimer
);
509 if ((pTimer
->Repeat
) && (pTimer
->State
== FALSE
))
510 RTMP_OS_Add_Timer(&pTimer
->TimerObj
, pTimer
->TimerValue
);
516 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
517 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
525 IN OUT PVOID Context
)
530 pAd
= (PRTMP_ADAPTER
)Context
;
531 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
533 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID
)&(pAd
->TimerQComplete
));
535 RT2870_TimerQ_Handle(pAd
);
537 /* notify the exit routine that we're actually exiting now
539 * complete()/wait_for_completion() is similar to up()/down(),
540 * except that complete() is safe in the case where the structure
541 * is getting deleted in a parallel mode of execution (i.e. just
542 * after the down() -- that's necessary for the thread-shutdown
545 * complete_and_exit() goes even further than this -- it is safe in
546 * the case that the thread of the caller is going away (not just
547 * the structure) -- this is necessary for the module-remove case.
548 * This is important in preemption kernels, which transfer the flow
549 * of execution immediately upon a complete().
551 DBGPRINT(RT_DEBUG_TRACE
,( "<---%s\n",__func__
));
553 pObj
->TimerQThr_pid
= NULL
;
555 complete_and_exit(&pAd
->TimerQComplete
, 0);
561 RT2870_TIMER_ENTRY
*RT2870_TimerQ_Insert(
562 IN RTMP_ADAPTER
*pAd
,
563 IN RALINK_TIMER_STRUCT
*pTimer
)
565 RT2870_TIMER_ENTRY
*pQNode
= NULL
, *pQTail
;
566 unsigned long irqFlags
;
569 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
570 if (pAd
->TimerQ
.status
& RT2870_THREAD_CAN_DO_INSERT
)
572 if(pAd
->TimerQ
.pQPollFreeList
)
574 pQNode
= pAd
->TimerQ
.pQPollFreeList
;
575 pAd
->TimerQ
.pQPollFreeList
= pQNode
->pNext
;
577 pQNode
->pRaTimer
= pTimer
;
578 pQNode
->pNext
= NULL
;
580 pQTail
= pAd
->TimerQ
.pQTail
;
581 if (pAd
->TimerQ
.pQTail
!= NULL
)
582 pQTail
->pNext
= pQNode
;
583 pAd
->TimerQ
.pQTail
= pQNode
;
584 if (pAd
->TimerQ
.pQHead
== NULL
)
585 pAd
->TimerQ
.pQHead
= pQNode
;
587 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
590 up(&pAd
->RTUSBTimer_semaphore
);
591 //wake_up(&timerWaitQ);
595 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
601 BOOLEAN
RT2870_TimerQ_Remove(
602 IN RTMP_ADAPTER
*pAd
,
603 IN RALINK_TIMER_STRUCT
*pTimer
)
605 RT2870_TIMER_ENTRY
*pNode
, *pPrev
= NULL
;
606 unsigned long irqFlags
;
608 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
609 if (pAd
->TimerQ
.status
>= RT2870_THREAD_INITED
)
611 pNode
= pAd
->TimerQ
.pQHead
;
614 if (pNode
->pRaTimer
== pTimer
)
617 pNode
= pNode
->pNext
;
620 // Now move it to freeList queue.
623 if (pNode
== pAd
->TimerQ
.pQHead
)
624 pAd
->TimerQ
.pQHead
= pNode
->pNext
;
625 if (pNode
== pAd
->TimerQ
.pQTail
)
626 pAd
->TimerQ
.pQTail
= pPrev
;
628 pPrev
->pNext
= pNode
->pNext
;
630 // return this queue entry to timerQFreeList.
631 pNode
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
632 pAd
->TimerQ
.pQPollFreeList
= pNode
;
635 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
641 void RT2870_TimerQ_Exit(RTMP_ADAPTER
*pAd
)
643 RT2870_TIMER_ENTRY
*pTimerQ
;
644 unsigned long irqFlags
;
646 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
647 while (pAd
->TimerQ
.pQHead
)
649 pTimerQ
= pAd
->TimerQ
.pQHead
;
650 pAd
->TimerQ
.pQHead
= pTimerQ
->pNext
;
653 pAd
->TimerQ
.pQPollFreeList
= NULL
;
654 os_free_mem(pAd
, pAd
->TimerQ
.pTimerQPoll
);
655 pAd
->TimerQ
.pQTail
= NULL
;
656 pAd
->TimerQ
.pQHead
= NULL
;
657 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
658 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
663 void RT2870_TimerQ_Init(RTMP_ADAPTER
*pAd
)
666 RT2870_TIMER_ENTRY
*pQNode
, *pEntry
;
667 unsigned long irqFlags
;
669 NdisAllocateSpinLock(&pAd
->TimerQLock
);
671 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
672 NdisZeroMemory(&pAd
->TimerQ
, sizeof(pAd
->TimerQ
));
673 //InterlockedExchange(&pAd->TimerQ.count, 0);
675 /* Initialise the wait q head */
676 //init_waitqueue_head(&timerWaitQ);
678 os_alloc_mem(pAd
, &pAd
->TimerQ
.pTimerQPoll
, sizeof(RT2870_TIMER_ENTRY
) * TIMER_QUEUE_SIZE_MAX
);
679 if (pAd
->TimerQ
.pTimerQPoll
)
682 pQNode
= (RT2870_TIMER_ENTRY
*)pAd
->TimerQ
.pTimerQPoll
;
683 for (i
= 0 ;i
<TIMER_QUEUE_SIZE_MAX
; i
++)
685 pQNode
->pNext
= pEntry
;
689 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
690 pAd
->TimerQ
.pQHead
= NULL
;
691 pAd
->TimerQ
.pQTail
= NULL
;
692 pAd
->TimerQ
.status
= RT2870_THREAD_INITED
;
694 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
698 VOID
RT2870_WatchDog(IN RTMP_ADAPTER
*pAd
)
700 PHT_TX_CONTEXT pHTTXContext
;
704 BOOLEAN needDumpSeq
= FALSE
;
709 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
710 if ((MACValue
& 0xff) !=0 )
712 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
713 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40012);
714 while((MACValue
&0xff) != 0 && (idx
++ < 10))
716 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
719 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
722 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
724 if ((MACValue
& 0xff00) !=0 )
726 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
727 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf4000a);
728 while((MACValue
&0xff00) != 0 && (idx
++ < 10))
730 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
733 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
736 if (pAd
->watchDogRxOverFlowCnt
>= 2)
738 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
739 if ((!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
|
740 fRTMP_ADAPTER_BULKIN_RESET
|
741 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
742 fRTMP_ADAPTER_NIC_NOT_EXIST
))))
744 DBGPRINT(RT_DEBUG_TRACE
, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
745 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_BULKIN_RESET
);
746 RTUSBEnqueueInternalCmd(pAd
, CMDTHREAD_RESET_BULK_IN
, NULL
, 0);
749 pAd
->watchDogRxOverFlowCnt
= 0;
753 for (idx
= 0; idx
< NUM_OF_TX_RING
; idx
++)
757 RTMP_IRQ_LOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
758 if ((pAd
->BulkOutPending
[idx
] == TRUE
) && pAd
->watchDogTxPendingCnt
)
760 pAd
->watchDogTxPendingCnt
[idx
]++;
762 if ((pAd
->watchDogTxPendingCnt
[idx
] > 2) &&
763 (!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
| fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
| fRTMP_ADAPTER_BULKOUT_RESET
)))
766 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
767 pHTTXContext
= (PHT_TX_CONTEXT
)(&pAd
->TxContext
[idx
]);
768 if (pHTTXContext
->IRPPending
)
769 { // Check TxContext.
770 pUrb
= pHTTXContext
->pUrb
;
772 else if (idx
== MGMTPIPEIDX
)
774 PTX_CONTEXT pMLMEContext
, pNULLContext
, pPsPollContext
;
777 pMLMEContext
= (PTX_CONTEXT
)(pAd
->MgmtRing
.Cell
[pAd
->MgmtRing
.TxDmaIdx
].AllocVa
);
778 pPsPollContext
= (PTX_CONTEXT
)(&pAd
->PsPollContext
);
779 pNULLContext
= (PTX_CONTEXT
)(&pAd
->NullContext
);
781 if (pMLMEContext
->IRPPending
)
783 ASSERT(pMLMEContext
->IRPPending
);
784 pUrb
= pMLMEContext
->pUrb
;
786 else if (pNULLContext
->IRPPending
)
788 ASSERT(pNULLContext
->IRPPending
);
789 pUrb
= pNULLContext
->pUrb
;
791 else if (pPsPollContext
->IRPPending
)
793 ASSERT(pPsPollContext
->IRPPending
);
794 pUrb
= pPsPollContext
->pUrb
;
798 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
800 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx
));
803 DBGPRINT(RT_DEBUG_TRACE
, ("Unlink the pending URB!\n"));
805 RTUSB_UNLINK_URB(pUrb
);
806 // Sleep 200 microseconds to give cancellation time to work
812 DBGPRINT(RT_DEBUG_ERROR
, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
817 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
822 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
826 // For Sigma debug, dump the ba_reordering sequence.
827 if((needDumpSeq
== TRUE
) && (pAd
->CommonCfg
.bDisableReordering
== 0))
830 PBA_REC_ENTRY pBAEntry
= NULL
;
832 struct reordering_mpdu
*mpdu_blk
;
834 Idx
= pAd
->MacTab
.Content
[BSSID_WCID
].BARecWcidArray
[0];
836 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
837 if((pBAEntry
->list
.qlen
> 0) && (pBAEntry
->list
.next
!= NULL
))
839 DBGPRINT(RT_DEBUG_TRACE
, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
840 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
841 mpdu_blk
= pBAEntry
->list
.next
;
844 DBGPRINT(RT_DEBUG_TRACE
, ("\t%d:Seq-%d, bAMSDU-%d!\n", count
, mpdu_blk
->Sequence
, mpdu_blk
->bAMSDU
));
845 mpdu_blk
= mpdu_blk
->next
;
849 DBGPRINT(RT_DEBUG_TRACE
, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry
->LastIndSeq
));
850 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
856 ========================================================================
858 Release allocated resources.
861 *dev Point to the PCI or USB device
862 pAd driver control block pointer
868 ========================================================================
870 static void _rtusb_disconnect(struct usb_device
*dev
, PRTMP_ADAPTER pAd
)
872 struct net_device
*net_dev
= NULL
;
875 DBGPRINT(RT_DEBUG_ERROR
, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
876 dev
->bus
->bus_name
, dev
->devpath
));
881 printk("rtusb_disconnect: pAd == NULL!\n");
884 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
);
888 // for debug, wait to show some messages to /proc system
894 net_dev
= pAd
->net_dev
;
895 if (pAd
->net_dev
!= NULL
)
897 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev
->name
);
898 unregister_netdev (pAd
->net_dev
);
901 flush_scheduled_work();
904 // free net_device memory
905 free_netdev(net_dev
);
907 // free adapter memory
908 RTMPFreeAdapter(pAd
);
910 // release a use of the usb device structure
914 DBGPRINT(RT_DEBUG_ERROR
, (" RTUSB disconnect successfully\n"));
919 ========================================================================
921 Probe RT28XX chipset.
924 *dev Point to the PCI or USB device
926 *id_table Point to the PCI or USB device ID
932 ========================================================================
934 static int rtusb_probe (struct usb_interface
*intf
,
935 const struct usb_device_id
*id
)
938 return (int)rt28xx_probe((void *)intf
, (void *)id
, 0, &pAd
);
942 static void rtusb_disconnect(struct usb_interface
*intf
)
944 struct usb_device
*dev
= interface_to_usbdev(intf
);
948 pAd
= usb_get_intfdata(intf
);
949 usb_set_intfdata(intf
, NULL
);
951 _rtusb_disconnect(dev
, pAd
);
956 ========================================================================
958 Close kernel threads.
961 *pAd the raxx interface data pointer
967 ========================================================================
969 VOID
RT28xxThreadTerminate(
970 IN RTMP_ADAPTER
*pAd
)
972 POS_COOKIE pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
976 // Sleep 50 milliseconds so pending io might finish normally
977 RTMPusecDelay(50000);
979 // We want to wait until all pending receives and sends to the
980 // device object. We cancel any
981 // irps. Wait until sends and receives have stopped.
982 RTUSBCancelPendingIRPs(pAd
);
986 if (pid_nr(pObj
->TimerQThr_pid
) > 0)
988 POS_COOKIE pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
990 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj
->TimerQThr_pid
));
992 pAd
->TimerFunc_kill
= 1;
994 ret
= kill_pid(pObj
->TimerQThr_pid
, SIGTERM
, 1);
997 printk(KERN_WARNING
"%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
998 pAd
->net_dev
->name
, pid_nr(pObj
->TimerQThr_pid
), ret
);
1002 wait_for_completion(&pAd
->TimerQComplete
);
1003 pObj
->TimerQThr_pid
= NULL
;
1007 if (pid_nr(pObj
->MLMEThr_pid
) > 0)
1009 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj
->MLMEThr_pid
));
1012 //RT28XX_MLME_HANDLER(pAd);
1014 ret
= kill_pid(pObj
->MLMEThr_pid
, SIGTERM
, 1);
1017 printk (KERN_WARNING
"%s: unable to Mlme thread, pid=%d, ret=%d!\n",
1018 pAd
->net_dev
->name
, pid_nr(pObj
->MLMEThr_pid
), ret
);
1022 //wait_for_completion (&pAd->notify);
1023 wait_for_completion (&pAd
->mlmeComplete
);
1024 pObj
->MLMEThr_pid
= NULL
;
1028 if (pid_nr(pObj
->RTUSBCmdThr_pid
) > 0)
1030 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj
->RTUSBCmdThr_pid
));
1032 NdisAcquireSpinLock(&pAd
->CmdQLock
);
1033 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
1034 NdisReleaseSpinLock(&pAd
->CmdQLock
);
1037 ret
= kill_pid(pObj
->RTUSBCmdThr_pid
, SIGTERM
, 1);
1040 printk(KERN_WARNING
"%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1041 pAd
->net_dev
->name
, pid_nr(pObj
->RTUSBCmdThr_pid
), ret
);
1045 //wait_for_completion (&pAd->notify);
1046 wait_for_completion (&pAd
->CmdQComplete
);
1047 pObj
->RTUSBCmdThr_pid
= NULL
;
1053 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_UNKNOWN
;
1054 pAd
->TimerFunc_kill
= 0;
1058 void kill_thread_task(IN PRTMP_ADAPTER pAd
)
1062 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
1064 tasklet_kill(&pObj
->rx_done_task
);
1065 tasklet_kill(&pObj
->mgmt_dma_done_task
);
1066 tasklet_kill(&pObj
->ac0_dma_done_task
);
1067 tasklet_kill(&pObj
->ac1_dma_done_task
);
1068 tasklet_kill(&pObj
->ac2_dma_done_task
);
1069 tasklet_kill(&pObj
->ac3_dma_done_task
);
1070 tasklet_kill(&pObj
->hcca_dma_done_task
);
1071 tasklet_kill(&pObj
->tbtt_task
);
1077 ========================================================================
1078 Routine Description:
1079 Check the chipset vendor/product ID.
1082 _dev_p Point to the PCI or USB device
1089 ========================================================================
1091 BOOLEAN
RT28XXChipsetCheck(
1094 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1095 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1099 for(i
=0; i
<rtusb_usb_id_len
; i
++)
1101 if (dev_p
->descriptor
.idVendor
== rtusb_usb_id
[i
].idVendor
&&
1102 dev_p
->descriptor
.idProduct
== rtusb_usb_id
[i
].idProduct
)
1105 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1108 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1110 dev_p
->descriptor
.idVendor
, dev_p
->descriptor
.idProduct
);
1115 if (i
== rtusb_usb_id_len
)
1117 printk("rt2870: Error! Device Descriptor not matching!\n");
1126 ========================================================================
1127 Routine Description:
1128 Init net device structure.
1131 _dev_p Point to the PCI or USB device
1132 *net_dev Point to the net device
1133 *pAd the raxx interface data pointer
1140 ========================================================================
1142 BOOLEAN
RT28XXNetDevInit(
1144 IN
struct net_device
*net_dev
,
1145 IN RTMP_ADAPTER
*pAd
)
1147 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1148 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1151 pAd
->config
= &dev_p
->config
->desc
;
1157 ========================================================================
1158 Routine Description:
1159 Init net device structure.
1162 _dev_p Point to the PCI or USB device
1163 *pAd the raxx interface data pointer
1170 ========================================================================
1172 BOOLEAN
RT28XXProbePostConfig(
1174 IN RTMP_ADAPTER
*pAd
,
1177 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1178 struct usb_host_interface
*iface_desc
;
1183 /* get the active interface descriptor */
1184 iface_desc
= intf
->cur_altsetting
;
1186 /* get # of enpoints */
1187 pAd
->NumberOfPipes
= iface_desc
->desc
.bNumEndpoints
;
1188 DBGPRINT(RT_DEBUG_TRACE
,
1189 ("NumEndpoints=%d\n", iface_desc
->desc
.bNumEndpoints
));
1191 /* Configure Pipes */
1194 for(i
=0; i
<pAd
->NumberOfPipes
; i
++)
1196 if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1197 USB_ENDPOINT_XFER_BULK
) &&
1198 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1199 USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
))
1201 pAd
->BulkInEpAddr
= iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1202 pAd
->BulkInMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1204 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1205 ("BULK IN MaximumPacketSize = %d\n", pAd
->BulkInMaxPacketSize
));
1206 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1207 ("EP address = 0x%2x\n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1209 else if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1210 USB_ENDPOINT_XFER_BULK
) &&
1211 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1212 USB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
))
1214 // there are 6 bulk out EP. EP6 highest priority.
1215 // EP1-4 is EDCA. EP5 is HCCA.
1216 pAd
->BulkOutEpAddr
[BulkOutIdx
++] = iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1217 pAd
->BulkOutMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1219 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1220 ("BULK OUT MaximumPacketSize = %d\n", pAd
->BulkOutMaxPacketSize
));
1221 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1222 ("EP address = 0x%2x \n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1226 if (!(pAd
->BulkInEpAddr
&& pAd
->BulkOutEpAddr
[0]))
1228 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__
);
1237 ========================================================================
1238 Routine Description:
1242 *pAd the raxx interface data pointer
1248 ========================================================================
1250 VOID
RT28XXDMADisable(
1251 IN RTMP_ADAPTER
*pAd
)
1259 ========================================================================
1260 Routine Description:
1264 *pAd the raxx interface data pointer
1270 ========================================================================
1272 VOID
RT28XXDMAEnable(
1273 IN RTMP_ADAPTER
*pAd
)
1275 WPDMA_GLO_CFG_STRUC GloCfg
;
1276 USB_DMA_CFG_STRUC UsbCfg
;
1280 RTMP_IO_WRITE32(pAd
, MAC_SYS_CTRL
, 0x4);
1283 RTMP_IO_READ32(pAd
, WPDMA_GLO_CFG
, &GloCfg
.word
);
1284 if ((GloCfg
.field
.TxDMABusy
== 0) && (GloCfg
.field
.RxDMABusy
== 0))
1287 DBGPRINT(RT_DEBUG_TRACE
, ("==> DMABusy\n"));
1288 RTMPusecDelay(1000);
1294 GloCfg
.field
.EnTXWriteBackDDONE
= 1;
1295 GloCfg
.field
.EnableRxDMA
= 1;
1296 GloCfg
.field
.EnableTxDMA
= 1;
1297 DBGPRINT(RT_DEBUG_TRACE
, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg
.word
));
1298 RTMP_IO_WRITE32(pAd
, WPDMA_GLO_CFG
, GloCfg
.word
);
1301 UsbCfg
.field
.phyclear
= 0;
1302 /* usb version is 1.1,do not use bulk in aggregation */
1303 if (pAd
->BulkInMaxPacketSize
== 512)
1304 UsbCfg
.field
.RxBulkAggEn
= 1;
1305 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1306 UsbCfg
.field
.RxBulkAggLmt
= (MAX_RXBULK_SIZE
/1024)-3;
1307 UsbCfg
.field
.RxBulkAggTOut
= 0x80; /* 2006-10-18 */
1308 UsbCfg
.field
.RxBulkEn
= 1;
1309 UsbCfg
.field
.TxBulkEn
= 1;
1311 RTUSBWriteMACRegister(pAd
, USB_DMA_CFG
, UsbCfg
.word
);
1316 ========================================================================
1317 Routine Description:
1318 Write Beacon buffer to Asic.
1321 *pAd the raxx interface data pointer
1327 ========================================================================
1329 VOID
RT28xx_UpdateBeaconToAsic(
1330 IN RTMP_ADAPTER
*pAd
,
1335 PUCHAR pBeaconFrame
= NULL
;
1338 BEACON_SYNC_STRUCT
*pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1340 BOOLEAN bBcnReq
= FALSE
;
1344 if (pBeaconFrame
== NULL
)
1346 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconFrame is NULL!\n"));
1350 if (pBeaconSync
== NULL
)
1352 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconSync is NULL!\n"));
1356 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1357 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1359 if (bBcnReq
== FALSE
)
1361 /* when the ra interface is down, do not send its beacon frame */
1362 /* clear all zero */
1363 for(i
=0; i
<TXWI_SIZE
; i
+=4) {
1364 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, 0x00);
1366 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1367 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], TXWI_SIZE
);
1371 ptr
= (PUCHAR
)&pAd
->BeaconTxWI
;
1373 if (NdisEqualMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
) == FALSE
)
1374 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1375 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1376 NdisMoveMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
);
1379 if ((pBeaconSync
->BeaconBitMap
& (1 << bcn_idx
)) != (1 << bcn_idx
))
1381 for (i
=0; i
<TXWI_SIZE
; i
+=4) // 16-byte TXWI field
1383 longValue
= *ptr
+ (*(ptr
+1)<<8) + (*(ptr
+2)<<16) + (*(ptr
+3)<<24);
1384 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, longValue
);
1389 ptr
= pBeaconSync
->BeaconBuf
[bcn_idx
];
1390 padding
= (FrameLen
& 0x01);
1391 NdisZeroMemory((PUCHAR
)(pBeaconFrame
+ FrameLen
), padding
);
1392 FrameLen
+= padding
;
1393 for (i
= 0 ; i
< FrameLen
/*HW_BEACON_OFFSET*/; i
+= 2)
1395 if (NdisEqualMemory(ptr
, pBeaconFrame
, 2) == FALSE
)
1397 NdisMoveMemory(ptr
, pBeaconFrame
, 2);
1398 //shortValue = *ptr + (*(ptr+1)<<8);
1399 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1400 RTUSBMultiWrite(pAd
, pAd
->BeaconOffset
[bcn_idx
] + TXWI_SIZE
+ i
, ptr
, 2);
1406 pBeaconSync
->BeaconBitMap
|= (1 << bcn_idx
);
1408 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1414 VOID
RT2870_BssBeaconStop(
1415 IN RTMP_ADAPTER
*pAd
)
1417 BEACON_SYNC_STRUCT
*pBeaconSync
;
1419 BOOLEAN Cancelled
= TRUE
;
1421 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1422 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1426 NumOfBcn
= MAX_MESH_NUM
;
1428 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1430 for(i
=0; i
<NumOfBcn
; i
++)
1432 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1433 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1435 for (offset
=0; offset
<HW_BEACON_OFFSET
; offset
+=4)
1436 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[i
] + offset
, 0x00);
1438 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1439 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1441 pBeaconSync
->BeaconBitMap
= 0;
1442 pBeaconSync
->DtimBitOn
= 0;
1447 VOID
RT2870_BssBeaconStart(
1448 IN RTMP_ADAPTER
*pAd
)
1451 BEACON_SYNC_STRUCT
*pBeaconSync
;
1452 // LARGE_INTEGER tsfTime, deltaTime;
1454 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1455 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1459 NumOfBcn
= MAX_MESH_NUM
;
1461 for(apidx
=0; apidx
<NumOfBcn
; apidx
++)
1463 UCHAR CapabilityInfoLocationInBeacon
= 0;
1464 UCHAR TimIELocationInBeacon
= 0;
1466 NdisZeroMemory(pBeaconSync
->BeaconBuf
[apidx
], HW_BEACON_OFFSET
);
1467 pBeaconSync
->CapabilityInfoLocationInBeacon
[apidx
] = CapabilityInfoLocationInBeacon
;
1468 pBeaconSync
->TimIELocationInBeacon
[apidx
] = TimIELocationInBeacon
;
1469 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[apidx
], TXWI_SIZE
);
1471 pBeaconSync
->BeaconBitMap
= 0;
1472 pBeaconSync
->DtimBitOn
= 0;
1473 pAd
->CommonCfg
.BeaconUpdateTimer
.Repeat
= TRUE
;
1475 pAd
->CommonCfg
.BeaconAdjust
= 0;
1476 pAd
->CommonCfg
.BeaconFactor
= 0xffffffff / (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1477 pAd
->CommonCfg
.BeaconRemain
= (0xffffffff % (pAd
->CommonCfg
.BeaconPeriod
<< 10)) + 1;
1478 printk(RT28xx_CHIP_NAME
"_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd
->CommonCfg
.BeaconFactor
, pAd
->CommonCfg
.BeaconRemain
);
1479 RTMPSetTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, pAd
->CommonCfg
.BeaconPeriod
);
1485 VOID
RT2870_BssBeaconInit(
1486 IN RTMP_ADAPTER
*pAd
)
1488 BEACON_SYNC_STRUCT
*pBeaconSync
;
1491 NdisAllocMemory(pAd
->CommonCfg
.pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
), MEM_ALLOC_FLAG
);
1492 if (pAd
->CommonCfg
.pBeaconSync
)
1494 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1495 NdisZeroMemory(pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
));
1496 for(i
=0; i
< HW_BEACON_MAX_COUNT
; i
++)
1498 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1499 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1500 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1501 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1503 pBeaconSync
->BeaconBitMap
= 0;
1505 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1506 pBeaconSync
->EnableBeacon
= TRUE
;
1511 VOID
RT2870_BssBeaconExit(
1512 IN RTMP_ADAPTER
*pAd
)
1514 BEACON_SYNC_STRUCT
*pBeaconSync
;
1515 BOOLEAN Cancelled
= TRUE
;
1518 if (pAd
->CommonCfg
.pBeaconSync
)
1520 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1521 pBeaconSync
->EnableBeacon
= FALSE
;
1522 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1523 pBeaconSync
->BeaconBitMap
= 0;
1525 for(i
=0; i
<HW_BEACON_MAX_COUNT
; i
++)
1527 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1528 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1529 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1530 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1533 NdisFreeMemory(pAd
->CommonCfg
.pBeaconSync
, HW_BEACON_OFFSET
* HW_BEACON_MAX_COUNT
, 0);
1534 pAd
->CommonCfg
.pBeaconSync
= NULL
;
1538 VOID
BeaconUpdateExec(
1539 IN PVOID SystemSpecific1
,
1540 IN PVOID FunctionContext
,
1541 IN PVOID SystemSpecific2
,
1542 IN PVOID SystemSpecific3
)
1544 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)FunctionContext
;
1545 LARGE_INTEGER tsfTime_a
;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1546 UINT32 delta
, remain
, remain_low
, remain_high
;
1547 // BOOLEAN positive;
1549 ReSyncBeaconTime(pAd
);
1553 RTMP_IO_READ32(pAd
, TSF_TIMER_DW0
, &tsfTime_a
.u
.LowPart
);
1554 RTMP_IO_READ32(pAd
, TSF_TIMER_DW1
, &tsfTime_a
.u
.HighPart
);
1557 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1558 remain_high
= pAd
->CommonCfg
.BeaconRemain
* tsfTime_a
.u
.HighPart
;
1559 remain_low
= tsfTime_a
.u
.LowPart
% (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1560 remain
= (remain_high
+ remain_low
)%(pAd
->CommonCfg
.BeaconPeriod
<< 10);
1561 delta
= (pAd
->CommonCfg
.BeaconPeriod
<< 10) - remain
;
1563 pAd
->CommonCfg
.BeaconUpdateTimer
.TimerValue
= (delta
>> 10) + 10;