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
);
53 MODULE_ALIAS("rt3070sta");
55 /* Kernel thread and vars, which handles packets that are completed. Only
56 * packets that have a "complete" function are sent here. This way, the
57 * completion is run out of kernel context, and doesn't block the rest of
60 extern INT __devinit
rt28xx_probe(IN
void *_dev_p
, IN
void *_dev_id_p
,
61 IN UINT argc
, OUT PRTMP_ADAPTER
*ppAd
);
63 struct usb_device_id rtusb_usb_id
[] = {
64 { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */
65 { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
66 { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
67 { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
68 { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
69 { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
70 { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
71 { USB_DEVICE(0x0B05, 0x1731) }, /* Asus */
72 { USB_DEVICE(0x0B05, 0x1732) }, /* Asus */
73 { USB_DEVICE(0x0B05, 0x1742) }, /* Asus */
74 { USB_DEVICE(0x0DF6, 0x0017) }, /* Sitecom */
75 { USB_DEVICE(0x0DF6, 0x002B) }, /* Sitecom */
76 { USB_DEVICE(0x0DF6, 0x002C) }, /* Sitecom */
77 { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
78 { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
79 { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
80 { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
81 { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
82 { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
83 { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
84 { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
85 { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
86 { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
87 { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
88 { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
89 { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
90 { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
91 { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
92 { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
93 { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
94 { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
95 { USB_DEVICE(0x14B2, 0x3C23) }, /* Airlink */
96 { USB_DEVICE(0x14B2, 0x3C27) }, /* Airlink */
97 { USB_DEVICE(0x07AA, 0x002F) }, /* Corega */
98 { USB_DEVICE(0x07AA, 0x003C) }, /* Corega */
99 { USB_DEVICE(0x07AA, 0x003F) }, /* Corega */
100 { USB_DEVICE(0x18C5, 0x0012) }, /* Corega 3070 */
101 { USB_DEVICE(0x1044, 0x800B) }, /* Gigabyte */
102 { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
103 { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
104 { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
105 { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
106 { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
107 { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
108 { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
109 { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
110 { USB_DEVICE(0x0CDE, 0x0022) }, /* ZCOM */
111 { USB_DEVICE(0x0586, 0x3416) }, /* Zyxel */
112 { USB_DEVICE(0x0CDE, 0x0025) }, /* Zyxel */
113 { USB_DEVICE(0x1740, 0x9701) }, /* EnGenius */
114 { USB_DEVICE(0x1740, 0x9702) }, /* EnGenius */
115 { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
116 { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
117 { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
118 { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
119 { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
120 { USB_DEVICE(0x083A, 0x6618) }, /* Accton */
121 { USB_DEVICE(0x15c5, 0x0008) }, /* Amit */
122 { USB_DEVICE(0x0E66, 0x0001) }, /* Hawking */
123 { USB_DEVICE(0x0E66, 0x0003) }, /* Hawking */
124 { USB_DEVICE(0x129B, 0x1828) }, /* Siemens */
125 { USB_DEVICE(0x157E, 0x300E) }, /* U-Media */
126 { USB_DEVICE(0x050d, 0x805c) },
127 { USB_DEVICE(0x1482, 0x3C09) }, /* Abocom*/
128 { USB_DEVICE(0x14B2, 0x3C09) }, /* Alpha */
129 { USB_DEVICE(0x04E8, 0x2018) }, /* samsung */
130 { USB_DEVICE(0x07B8, 0x3070) }, /* AboCom 3070 */
131 { USB_DEVICE(0x07B8, 0x3071) }, /* AboCom 3071 */
132 { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
133 { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
134 { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
135 { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
136 { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
137 { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
138 { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
139 { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
140 { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
141 { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
142 { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
143 { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
144 { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
145 { } /* Terminating entry */
148 INT
const rtusb_usb_id_len
= sizeof(rtusb_usb_id
) / sizeof(struct usb_device_id
);
149 MODULE_DEVICE_TABLE(usb
, rtusb_usb_id
);
152 #define PF_NOFREEZE 0
157 static int rt2870_suspend(struct usb_interface
*intf
, pm_message_t state
);
158 static int rt2870_resume(struct usb_interface
*intf
);
159 #endif // CONFIG_PM //
161 /**************************************************************************/
162 /**************************************************************************/
163 //tested for kernel 2.6series
164 /**************************************************************************/
165 /**************************************************************************/
166 static int rtusb_probe (struct usb_interface
*intf
,
167 const struct usb_device_id
*id
);
168 static void rtusb_disconnect(struct usb_interface
*intf
);
170 struct usb_driver rtusb_driver
= {
173 .disconnect
=rtusb_disconnect
,
174 .id_table
=rtusb_usb_id
,
177 suspend
: rt2870_suspend
,
178 resume
: rt2870_resume
,
184 VOID
RT2860RejectPendingPackets(
185 IN PRTMP_ADAPTER pAd
)
188 // clear TxSw packets
191 static int rt2870_suspend(
192 struct usb_interface
*intf
,
195 struct net_device
*net_dev
;
196 PRTMP_ADAPTER pAd
= usb_get_intfdata(intf
);
199 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2870_suspend()\n"));
200 net_dev
= pAd
->net_dev
;
201 netif_device_detach (net_dev
);
203 pAd
->PM_FlgSuspend
= 1;
204 if (netif_running(net_dev
)) {
205 RTUSBCancelPendingBulkInIRP(pAd
);
206 RTUSBCancelPendingBulkOutIRP(pAd
);
208 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2870_suspend()\n"));
212 static int rt2870_resume(
213 struct usb_interface
*intf
)
215 struct net_device
*net_dev
;
216 PRTMP_ADAPTER pAd
= usb_get_intfdata(intf
);
219 DBGPRINT(RT_DEBUG_TRACE
, ("===> rt2870_resume()\n"));
221 pAd
->PM_FlgSuspend
= 0;
222 net_dev
= pAd
->net_dev
;
223 netif_device_attach (net_dev
);
224 netif_start_queue(net_dev
);
225 netif_carrier_on(net_dev
);
226 netif_wake_queue(net_dev
);
228 DBGPRINT(RT_DEBUG_TRACE
, ("<=== rt2870_resume()\n"));
231 #endif // CONFIG_PM //
234 // Init driver module
235 INT __init
rtusb_init(void)
237 printk("rtusb init --->\n");
238 return usb_register(&rtusb_driver
);
241 // Deinit driver module
242 VOID __exit
rtusb_exit(void)
244 usb_deregister(&rtusb_driver
);
245 printk("<--- rtusb exit\n");
248 module_init(rtusb_init
);
249 module_exit(rtusb_exit
);
254 /*--------------------------------------------------------------------- */
255 /* function declarations */
256 /*--------------------------------------------------------------------- */
259 ========================================================================
264 *Context the pAd, driver control block pointer
270 ========================================================================
275 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)Context
;
279 pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
281 rtmp_os_thread_init("rt2870MlmeThread", (PVOID
)&(pAd
->mlmeComplete
));
283 while (pAd
->mlme_kill
== 0)
285 /* lock the device pointers */
286 //down(&(pAd->mlme_semaphore));
287 status
= down_interruptible(&(pAd
->mlme_semaphore
));
289 /* lock the device pointers , need to check if required*/
290 //down(&(pAd->usbdev_semaphore));
292 if (!pAd
->PM_FlgSuspend
)
295 /* unlock the device pointers */
296 //up(&(pAd->usbdev_semaphore));
299 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
304 /* notify the exit routine that we're actually exiting now
306 * complete()/wait_for_completion() is similar to up()/down(),
307 * except that complete() is safe in the case where the structure
308 * is getting deleted in a parallel mode of execution (i.e. just
309 * after the down() -- that's necessary for the thread-shutdown
312 * complete_and_exit() goes even further than this -- it is safe in
313 * the case that the thread of the caller is going away (not just
314 * the structure) -- this is necessary for the module-remove case.
315 * This is important in preemption kernels, which transfer the flow
316 * of execution immediately upon a complete().
318 DBGPRINT(RT_DEBUG_TRACE
,( "<---%s\n",__func__
));
320 pObj
->MLMEThr_pid
= NULL
;
322 complete_and_exit (&pAd
->mlmeComplete
, 0);
329 ========================================================================
331 USB command kernel thread.
334 *Context the pAd, driver control block pointer
340 ========================================================================
345 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)Context
;
349 pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
351 rtmp_os_thread_init("rt2870CmdThread", (PVOID
)&(pAd
->CmdQComplete
));
353 NdisAcquireSpinLock(&pAd
->CmdQLock
);
354 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_RUNNING
;
355 NdisReleaseSpinLock(&pAd
->CmdQLock
);
357 while (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_RUNNING
)
359 /* lock the device pointers */
360 //down(&(pAd->RTUSBCmd_semaphore));
361 status
= down_interruptible(&(pAd
->RTUSBCmd_semaphore
));
363 if (pAd
->CmdQ
.CmdQState
== RT2870_THREAD_STOPED
)
368 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
371 /* lock the device pointers , need to check if required*/
372 //down(&(pAd->usbdev_semaphore));
374 if (!pAd
->PM_FlgSuspend
)
377 /* unlock the device pointers */
378 //up(&(pAd->usbdev_semaphore));
381 if (!pAd
->PM_FlgSuspend
)
382 { // Clear the CmdQElements.
383 CmdQElmt
*pCmdQElmt
= NULL
;
385 NdisAcquireSpinLock(&pAd
->CmdQLock
);
386 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
387 while(pAd
->CmdQ
.size
)
389 RTUSBDequeueCmd(&pAd
->CmdQ
, &pCmdQElmt
);
392 if (pCmdQElmt
->CmdFromNdis
== TRUE
)
394 if (pCmdQElmt
->buffer
!= NULL
)
395 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
397 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
401 if ((pCmdQElmt
->buffer
!= NULL
) && (pCmdQElmt
->bufferlength
!= 0))
402 NdisFreeMemory(pCmdQElmt
->buffer
, pCmdQElmt
->bufferlength
, 0);
404 NdisFreeMemory(pCmdQElmt
, sizeof(CmdQElmt
), 0);
410 NdisReleaseSpinLock(&pAd
->CmdQLock
);
412 /* notify the exit routine that we're actually exiting now
414 * complete()/wait_for_completion() is similar to up()/down(),
415 * except that complete() is safe in the case where the structure
416 * is getting deleted in a parallel mode of execution (i.e. just
417 * after the down() -- that's necessary for the thread-shutdown
420 * complete_and_exit() goes even further than this -- it is safe in
421 * the case that the thread of the caller is going away (not just
422 * the structure) -- this is necessary for the module-remove case.
423 * This is important in preemption kernels, which transfer the flow
424 * of execution immediately upon a complete().
426 DBGPRINT(RT_DEBUG_TRACE
,( "<---RTUSBCmdThread\n"));
428 pObj
->RTUSBCmdThr_pid
= NULL
;
430 complete_and_exit (&pAd
->CmdQComplete
, 0);
436 static void RT2870_TimerQ_Handle(RTMP_ADAPTER
*pAd
)
439 RALINK_TIMER_STRUCT
*pTimer
;
440 RT2870_TIMER_ENTRY
*pEntry
;
441 unsigned long irqFlag
;
443 while(!pAd
->TimerFunc_kill
)
445 // printk("waiting for event!\n");
448 status
= down_interruptible(&(pAd
->RTUSBTimer_semaphore
));
450 if (pAd
->TimerQ
.status
== RT2870_THREAD_STOPED
)
454 while(pAd
->TimerQ
.pQHead
)
456 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlag
);
457 pEntry
= pAd
->TimerQ
.pQHead
;
460 pTimer
= pEntry
->pRaTimer
;
463 pAd
->TimerQ
.pQHead
= pEntry
->pNext
;
464 if (pEntry
== pAd
->TimerQ
.pQTail
)
465 pAd
->TimerQ
.pQTail
= NULL
;
467 // return this queue entry to timerQFreeList.
468 pEntry
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
469 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
471 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlag
);
475 if (pTimer
->handle
!= NULL
)
476 if (!pAd
->PM_FlgSuspend
)
477 pTimer
->handle(NULL
, (PVOID
) pTimer
->cookie
, NULL
, pTimer
);
478 if ((pTimer
->Repeat
) && (pTimer
->State
== FALSE
))
479 RTMP_OS_Add_Timer(&pTimer
->TimerObj
, pTimer
->TimerValue
);
485 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
486 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
);
494 IN OUT PVOID Context
)
499 pAd
= (PRTMP_ADAPTER
)Context
;
500 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
502 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID
)&(pAd
->TimerQComplete
));
504 RT2870_TimerQ_Handle(pAd
);
506 /* notify the exit routine that we're actually exiting now
508 * complete()/wait_for_completion() is similar to up()/down(),
509 * except that complete() is safe in the case where the structure
510 * is getting deleted in a parallel mode of execution (i.e. just
511 * after the down() -- that's necessary for the thread-shutdown
514 * complete_and_exit() goes even further than this -- it is safe in
515 * the case that the thread of the caller is going away (not just
516 * the structure) -- this is necessary for the module-remove case.
517 * This is important in preemption kernels, which transfer the flow
518 * of execution immediately upon a complete().
520 DBGPRINT(RT_DEBUG_TRACE
,( "<---%s\n",__func__
));
522 pObj
->TimerQThr_pid
= NULL
;
524 complete_and_exit(&pAd
->TimerQComplete
, 0);
530 RT2870_TIMER_ENTRY
*RT2870_TimerQ_Insert(
531 IN RTMP_ADAPTER
*pAd
,
532 IN RALINK_TIMER_STRUCT
*pTimer
)
534 RT2870_TIMER_ENTRY
*pQNode
= NULL
, *pQTail
;
535 unsigned long irqFlags
;
538 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
539 if (pAd
->TimerQ
.status
& RT2870_THREAD_CAN_DO_INSERT
)
541 if(pAd
->TimerQ
.pQPollFreeList
)
543 pQNode
= pAd
->TimerQ
.pQPollFreeList
;
544 pAd
->TimerQ
.pQPollFreeList
= pQNode
->pNext
;
546 pQNode
->pRaTimer
= pTimer
;
547 pQNode
->pNext
= NULL
;
549 pQTail
= pAd
->TimerQ
.pQTail
;
550 if (pAd
->TimerQ
.pQTail
!= NULL
)
551 pQTail
->pNext
= pQNode
;
552 pAd
->TimerQ
.pQTail
= pQNode
;
553 if (pAd
->TimerQ
.pQHead
== NULL
)
554 pAd
->TimerQ
.pQHead
= pQNode
;
556 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
559 up(&pAd
->RTUSBTimer_semaphore
);
560 //wake_up(&timerWaitQ);
564 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
570 BOOLEAN
RT2870_TimerQ_Remove(
571 IN RTMP_ADAPTER
*pAd
,
572 IN RALINK_TIMER_STRUCT
*pTimer
)
574 RT2870_TIMER_ENTRY
*pNode
, *pPrev
= NULL
;
575 unsigned long irqFlags
;
577 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
578 if (pAd
->TimerQ
.status
>= RT2870_THREAD_INITED
)
580 pNode
= pAd
->TimerQ
.pQHead
;
583 if (pNode
->pRaTimer
== pTimer
)
586 pNode
= pNode
->pNext
;
589 // Now move it to freeList queue.
592 if (pNode
== pAd
->TimerQ
.pQHead
)
593 pAd
->TimerQ
.pQHead
= pNode
->pNext
;
594 if (pNode
== pAd
->TimerQ
.pQTail
)
595 pAd
->TimerQ
.pQTail
= pPrev
;
597 pPrev
->pNext
= pNode
->pNext
;
599 // return this queue entry to timerQFreeList.
600 pNode
->pNext
= pAd
->TimerQ
.pQPollFreeList
;
601 pAd
->TimerQ
.pQPollFreeList
= pNode
;
604 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
610 void RT2870_TimerQ_Exit(RTMP_ADAPTER
*pAd
)
612 RT2870_TIMER_ENTRY
*pTimerQ
;
613 unsigned long irqFlags
;
615 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
616 while (pAd
->TimerQ
.pQHead
)
618 pTimerQ
= pAd
->TimerQ
.pQHead
;
619 pAd
->TimerQ
.pQHead
= pTimerQ
->pNext
;
622 pAd
->TimerQ
.pQPollFreeList
= NULL
;
623 os_free_mem(pAd
, pAd
->TimerQ
.pTimerQPoll
);
624 pAd
->TimerQ
.pQTail
= NULL
;
625 pAd
->TimerQ
.pQHead
= NULL
;
626 pAd
->TimerQ
.status
= RT2870_THREAD_STOPED
;
627 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
632 void RT2870_TimerQ_Init(RTMP_ADAPTER
*pAd
)
635 RT2870_TIMER_ENTRY
*pQNode
, *pEntry
;
636 unsigned long irqFlags
;
638 NdisAllocateSpinLock(&pAd
->TimerQLock
);
640 RTMP_IRQ_LOCK(&pAd
->TimerQLock
, irqFlags
);
641 NdisZeroMemory(&pAd
->TimerQ
, sizeof(pAd
->TimerQ
));
642 //InterlockedExchange(&pAd->TimerQ.count, 0);
644 /* Initialise the wait q head */
645 //init_waitqueue_head(&timerWaitQ);
647 os_alloc_mem(pAd
, &pAd
->TimerQ
.pTimerQPoll
, sizeof(RT2870_TIMER_ENTRY
) * TIMER_QUEUE_SIZE_MAX
);
648 if (pAd
->TimerQ
.pTimerQPoll
)
651 pQNode
= (RT2870_TIMER_ENTRY
*)pAd
->TimerQ
.pTimerQPoll
;
652 for (i
= 0 ;i
<TIMER_QUEUE_SIZE_MAX
; i
++)
654 pQNode
->pNext
= pEntry
;
658 pAd
->TimerQ
.pQPollFreeList
= pEntry
;
659 pAd
->TimerQ
.pQHead
= NULL
;
660 pAd
->TimerQ
.pQTail
= NULL
;
661 pAd
->TimerQ
.status
= RT2870_THREAD_INITED
;
663 RTMP_IRQ_UNLOCK(&pAd
->TimerQLock
, irqFlags
);
667 VOID
RT2870_WatchDog(IN RTMP_ADAPTER
*pAd
)
669 PHT_TX_CONTEXT pHTTXContext
;
673 BOOLEAN needDumpSeq
= FALSE
;
678 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
679 if ((MACValue
& 0xff) !=0 )
681 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
682 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40012);
683 while((MACValue
&0xff) != 0 && (idx
++ < 10))
685 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
688 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
691 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
693 if ((MACValue
& 0xff00) !=0 )
695 DBGPRINT(RT_DEBUG_TRACE
, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue
));
696 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf4000a);
697 while((MACValue
&0xff00) != 0 && (idx
++ < 10))
699 RTMP_IO_READ32(pAd
, TXRXQ_PCNT
, &MACValue
);
702 RTMP_IO_WRITE32(pAd
, PBF_CFG
, 0xf40006);
705 if (pAd
->watchDogRxOverFlowCnt
>= 2)
707 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
708 if ((!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
|
709 fRTMP_ADAPTER_BULKIN_RESET
|
710 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
711 fRTMP_ADAPTER_NIC_NOT_EXIST
))))
713 DBGPRINT(RT_DEBUG_TRACE
, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
714 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_BULKIN_RESET
);
715 RTUSBEnqueueInternalCmd(pAd
, CMDTHREAD_RESET_BULK_IN
, NULL
, 0);
718 pAd
->watchDogRxOverFlowCnt
= 0;
722 for (idx
= 0; idx
< NUM_OF_TX_RING
; idx
++)
726 RTMP_IRQ_LOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
727 if ((pAd
->BulkOutPending
[idx
] == TRUE
) && pAd
->watchDogTxPendingCnt
)
729 pAd
->watchDogTxPendingCnt
[idx
]++;
731 if ((pAd
->watchDogTxPendingCnt
[idx
] > 2) &&
732 (!RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_RESET_IN_PROGRESS
| fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
| fRTMP_ADAPTER_BULKOUT_RESET
)))
735 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
736 pHTTXContext
= (PHT_TX_CONTEXT
)(&pAd
->TxContext
[idx
]);
737 if (pHTTXContext
->IRPPending
)
738 { // Check TxContext.
739 pUrb
= pHTTXContext
->pUrb
;
741 else if (idx
== MGMTPIPEIDX
)
743 PTX_CONTEXT pMLMEContext
, pNULLContext
, pPsPollContext
;
746 pMLMEContext
= (PTX_CONTEXT
)(pAd
->MgmtRing
.Cell
[pAd
->MgmtRing
.TxDmaIdx
].AllocVa
);
747 pPsPollContext
= (PTX_CONTEXT
)(&pAd
->PsPollContext
);
748 pNULLContext
= (PTX_CONTEXT
)(&pAd
->NullContext
);
750 if (pMLMEContext
->IRPPending
)
752 ASSERT(pMLMEContext
->IRPPending
);
753 pUrb
= pMLMEContext
->pUrb
;
755 else if (pNULLContext
->IRPPending
)
757 ASSERT(pNULLContext
->IRPPending
);
758 pUrb
= pNULLContext
->pUrb
;
760 else if (pPsPollContext
->IRPPending
)
762 ASSERT(pPsPollContext
->IRPPending
);
763 pUrb
= pPsPollContext
->pUrb
;
767 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
769 DBGPRINT(RT_DEBUG_TRACE
, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx
));
772 DBGPRINT(RT_DEBUG_TRACE
, ("Unlink the pending URB!\n"));
774 RTUSB_UNLINK_URB(pUrb
);
775 // Sleep 200 microseconds to give cancellation time to work
781 DBGPRINT(RT_DEBUG_ERROR
, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
786 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
791 RTMP_IRQ_UNLOCK(&pAd
->BulkOutLock
[idx
], irqFlags
);
795 // For Sigma debug, dump the ba_reordering sequence.
796 if((needDumpSeq
== TRUE
) && (pAd
->CommonCfg
.bDisableReordering
== 0))
799 PBA_REC_ENTRY pBAEntry
= NULL
;
801 struct reordering_mpdu
*mpdu_blk
;
803 Idx
= pAd
->MacTab
.Content
[BSSID_WCID
].BARecWcidArray
[0];
805 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
806 if((pBAEntry
->list
.qlen
> 0) && (pBAEntry
->list
.next
!= NULL
))
808 DBGPRINT(RT_DEBUG_TRACE
, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
809 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
810 mpdu_blk
= pBAEntry
->list
.next
;
813 DBGPRINT(RT_DEBUG_TRACE
, ("\t%d:Seq-%d, bAMSDU-%d!\n", count
, mpdu_blk
->Sequence
, mpdu_blk
->bAMSDU
));
814 mpdu_blk
= mpdu_blk
->next
;
818 DBGPRINT(RT_DEBUG_TRACE
, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry
->LastIndSeq
));
819 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
825 ========================================================================
827 Release allocated resources.
830 *dev Point to the PCI or USB device
831 pAd driver control block pointer
837 ========================================================================
839 static void _rtusb_disconnect(struct usb_device
*dev
, PRTMP_ADAPTER pAd
)
841 struct net_device
*net_dev
= NULL
;
844 DBGPRINT(RT_DEBUG_ERROR
, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
845 dev
->bus
->bus_name
, dev
->devpath
));
850 printk("rtusb_disconnect: pAd == NULL!\n");
853 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_NIC_NOT_EXIST
);
857 // for debug, wait to show some messages to /proc system
863 net_dev
= pAd
->net_dev
;
864 if (pAd
->net_dev
!= NULL
)
866 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev
->name
);
867 unregister_netdev (pAd
->net_dev
);
870 flush_scheduled_work();
873 // free net_device memory
874 free_netdev(net_dev
);
876 // free adapter memory
877 RTMPFreeAdapter(pAd
);
879 // release a use of the usb device structure
883 DBGPRINT(RT_DEBUG_ERROR
, (" RTUSB disconnect successfully\n"));
888 ========================================================================
890 Probe RT28XX chipset.
893 *dev Point to the PCI or USB device
895 *id_table Point to the PCI or USB device ID
901 ========================================================================
903 static int rtusb_probe (struct usb_interface
*intf
,
904 const struct usb_device_id
*id
)
907 return (int)rt28xx_probe((void *)intf
, (void *)id
, 0, &pAd
);
911 static void rtusb_disconnect(struct usb_interface
*intf
)
913 struct usb_device
*dev
= interface_to_usbdev(intf
);
917 pAd
= usb_get_intfdata(intf
);
918 usb_set_intfdata(intf
, NULL
);
920 _rtusb_disconnect(dev
, pAd
);
925 ========================================================================
927 Close kernel threads.
930 *pAd the raxx interface data pointer
936 ========================================================================
938 VOID
RT28xxThreadTerminate(
939 IN RTMP_ADAPTER
*pAd
)
941 POS_COOKIE pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
945 // Sleep 50 milliseconds so pending io might finish normally
946 RTMPusecDelay(50000);
948 // We want to wait until all pending receives and sends to the
949 // device object. We cancel any
950 // irps. Wait until sends and receives have stopped.
951 RTUSBCancelPendingIRPs(pAd
);
955 if (pid_nr(pObj
->TimerQThr_pid
) > 0)
957 POS_COOKIE pObj
= (POS_COOKIE
)pAd
->OS_Cookie
;
959 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj
->TimerQThr_pid
));
961 pAd
->TimerFunc_kill
= 1;
963 ret
= kill_pid(pObj
->TimerQThr_pid
, SIGTERM
, 1);
966 printk(KERN_WARNING
"%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
967 pAd
->net_dev
->name
, pid_nr(pObj
->TimerQThr_pid
), ret
);
971 wait_for_completion(&pAd
->TimerQComplete
);
972 pObj
->TimerQThr_pid
= NULL
;
976 if (pid_nr(pObj
->MLMEThr_pid
) > 0)
978 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj
->MLMEThr_pid
));
981 //RT28XX_MLME_HANDLER(pAd);
983 ret
= kill_pid(pObj
->MLMEThr_pid
, SIGTERM
, 1);
986 printk (KERN_WARNING
"%s: unable to Mlme thread, pid=%d, ret=%d!\n",
987 pAd
->net_dev
->name
, pid_nr(pObj
->MLMEThr_pid
), ret
);
991 //wait_for_completion (&pAd->notify);
992 wait_for_completion (&pAd
->mlmeComplete
);
993 pObj
->MLMEThr_pid
= NULL
;
997 if (pid_nr(pObj
->RTUSBCmdThr_pid
) > 0)
999 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj
->RTUSBCmdThr_pid
));
1001 NdisAcquireSpinLock(&pAd
->CmdQLock
);
1002 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_STOPED
;
1003 NdisReleaseSpinLock(&pAd
->CmdQLock
);
1006 ret
= kill_pid(pObj
->RTUSBCmdThr_pid
, SIGTERM
, 1);
1009 printk(KERN_WARNING
"%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
1010 pAd
->net_dev
->name
, pid_nr(pObj
->RTUSBCmdThr_pid
), ret
);
1014 //wait_for_completion (&pAd->notify);
1015 wait_for_completion (&pAd
->CmdQComplete
);
1016 pObj
->RTUSBCmdThr_pid
= NULL
;
1022 pAd
->CmdQ
.CmdQState
= RT2870_THREAD_UNKNOWN
;
1023 pAd
->TimerFunc_kill
= 0;
1027 void kill_thread_task(IN PRTMP_ADAPTER pAd
)
1031 pObj
= (POS_COOKIE
) pAd
->OS_Cookie
;
1033 tasklet_kill(&pObj
->rx_done_task
);
1034 tasklet_kill(&pObj
->mgmt_dma_done_task
);
1035 tasklet_kill(&pObj
->ac0_dma_done_task
);
1036 tasklet_kill(&pObj
->ac1_dma_done_task
);
1037 tasklet_kill(&pObj
->ac2_dma_done_task
);
1038 tasklet_kill(&pObj
->ac3_dma_done_task
);
1039 tasklet_kill(&pObj
->hcca_dma_done_task
);
1040 tasklet_kill(&pObj
->tbtt_task
);
1046 ========================================================================
1047 Routine Description:
1048 Check the chipset vendor/product ID.
1051 _dev_p Point to the PCI or USB device
1058 ========================================================================
1060 BOOLEAN
RT28XXChipsetCheck(
1063 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1064 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1068 for(i
=0; i
<rtusb_usb_id_len
; i
++)
1070 if (dev_p
->descriptor
.idVendor
== rtusb_usb_id
[i
].idVendor
&&
1071 dev_p
->descriptor
.idProduct
== rtusb_usb_id
[i
].idProduct
)
1073 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1074 dev_p
->descriptor
.idVendor
, dev_p
->descriptor
.idProduct
);
1079 if (i
== rtusb_usb_id_len
)
1081 printk("rt2870: Error! Device Descriptor not matching!\n");
1090 ========================================================================
1091 Routine Description:
1092 Init net device structure.
1095 _dev_p Point to the PCI or USB device
1096 *net_dev Point to the net device
1097 *pAd the raxx interface data pointer
1104 ========================================================================
1106 BOOLEAN
RT28XXNetDevInit(
1108 IN
struct net_device
*net_dev
,
1109 IN RTMP_ADAPTER
*pAd
)
1111 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1112 struct usb_device
*dev_p
= interface_to_usbdev(intf
);
1115 pAd
->config
= &dev_p
->config
->desc
;
1121 ========================================================================
1122 Routine Description:
1123 Init net device structure.
1126 _dev_p Point to the PCI or USB device
1127 *pAd the raxx interface data pointer
1134 ========================================================================
1136 BOOLEAN
RT28XXProbePostConfig(
1138 IN RTMP_ADAPTER
*pAd
,
1141 struct usb_interface
*intf
= (struct usb_interface
*)_dev_p
;
1142 struct usb_host_interface
*iface_desc
;
1147 /* get the active interface descriptor */
1148 iface_desc
= intf
->cur_altsetting
;
1150 /* get # of enpoints */
1151 pAd
->NumberOfPipes
= iface_desc
->desc
.bNumEndpoints
;
1152 DBGPRINT(RT_DEBUG_TRACE
,
1153 ("NumEndpoints=%d\n", iface_desc
->desc
.bNumEndpoints
));
1155 /* Configure Pipes */
1158 for(i
=0; i
<pAd
->NumberOfPipes
; i
++)
1160 if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1161 USB_ENDPOINT_XFER_BULK
) &&
1162 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1163 USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
))
1165 pAd
->BulkInEpAddr
= iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1166 pAd
->BulkInMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1168 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1169 ("BULK IN MaximumPacketSize = %d\n", pAd
->BulkInMaxPacketSize
));
1170 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1171 ("EP address = 0x%2x\n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1173 else if ((iface_desc
->endpoint
[i
].desc
.bmAttributes
==
1174 USB_ENDPOINT_XFER_BULK
) &&
1175 ((iface_desc
->endpoint
[i
].desc
.bEndpointAddress
&
1176 USB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
))
1178 // there are 6 bulk out EP. EP6 highest priority.
1179 // EP1-4 is EDCA. EP5 is HCCA.
1180 pAd
->BulkOutEpAddr
[BulkOutIdx
++] = iface_desc
->endpoint
[i
].desc
.bEndpointAddress
;
1181 pAd
->BulkOutMaxPacketSize
= iface_desc
->endpoint
[i
].desc
.wMaxPacketSize
;
1183 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1184 ("BULK OUT MaximumPacketSize = %d\n", pAd
->BulkOutMaxPacketSize
));
1185 DBGPRINT_RAW(RT_DEBUG_TRACE
,
1186 ("EP address = 0x%2x \n", iface_desc
->endpoint
[i
].desc
.bEndpointAddress
));
1190 if (!(pAd
->BulkInEpAddr
&& pAd
->BulkOutEpAddr
[0]))
1192 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__
);
1201 ========================================================================
1202 Routine Description:
1206 *pAd the raxx interface data pointer
1212 ========================================================================
1214 VOID
RT28XXDMADisable(
1215 IN RTMP_ADAPTER
*pAd
)
1223 ========================================================================
1224 Routine Description:
1228 *pAd the raxx interface data pointer
1234 ========================================================================
1236 VOID
RT28XXDMAEnable(
1237 IN RTMP_ADAPTER
*pAd
)
1239 WPDMA_GLO_CFG_STRUC GloCfg
;
1240 USB_DMA_CFG_STRUC UsbCfg
;
1244 RTMP_IO_WRITE32(pAd
, MAC_SYS_CTRL
, 0x4);
1247 RTMP_IO_READ32(pAd
, WPDMA_GLO_CFG
, &GloCfg
.word
);
1248 if ((GloCfg
.field
.TxDMABusy
== 0) && (GloCfg
.field
.RxDMABusy
== 0))
1251 DBGPRINT(RT_DEBUG_TRACE
, ("==> DMABusy\n"));
1252 RTMPusecDelay(1000);
1258 GloCfg
.field
.EnTXWriteBackDDONE
= 1;
1259 GloCfg
.field
.EnableRxDMA
= 1;
1260 GloCfg
.field
.EnableTxDMA
= 1;
1261 DBGPRINT(RT_DEBUG_TRACE
, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg
.word
));
1262 RTMP_IO_WRITE32(pAd
, WPDMA_GLO_CFG
, GloCfg
.word
);
1265 UsbCfg
.field
.phyclear
= 0;
1266 /* usb version is 1.1,do not use bulk in aggregation */
1267 if (pAd
->BulkInMaxPacketSize
== 512)
1268 UsbCfg
.field
.RxBulkAggEn
= 1;
1269 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1270 UsbCfg
.field
.RxBulkAggLmt
= (MAX_RXBULK_SIZE
/1024)-3;
1271 UsbCfg
.field
.RxBulkAggTOut
= 0x80; /* 2006-10-18 */
1272 UsbCfg
.field
.RxBulkEn
= 1;
1273 UsbCfg
.field
.TxBulkEn
= 1;
1275 RTUSBWriteMACRegister(pAd
, USB_DMA_CFG
, UsbCfg
.word
);
1280 ========================================================================
1281 Routine Description:
1282 Write Beacon buffer to Asic.
1285 *pAd the raxx interface data pointer
1291 ========================================================================
1293 VOID
RT28xx_UpdateBeaconToAsic(
1294 IN RTMP_ADAPTER
*pAd
,
1299 PUCHAR pBeaconFrame
= NULL
;
1302 BEACON_SYNC_STRUCT
*pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1304 BOOLEAN bBcnReq
= FALSE
;
1308 if (pBeaconFrame
== NULL
)
1310 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconFrame is NULL!\n"));
1314 if (pBeaconSync
== NULL
)
1316 DBGPRINT(RT_DEBUG_ERROR
,("pBeaconSync is NULL!\n"));
1320 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1321 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1323 if (bBcnReq
== FALSE
)
1325 /* when the ra interface is down, do not send its beacon frame */
1326 /* clear all zero */
1327 for(i
=0; i
<TXWI_SIZE
; i
+=4) {
1328 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, 0x00);
1330 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1331 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], TXWI_SIZE
);
1335 ptr
= (PUCHAR
)&pAd
->BeaconTxWI
;
1337 if (NdisEqualMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
) == FALSE
)
1338 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1339 pBeaconSync
->BeaconBitMap
&= (~(BEACON_BITMAP_MASK
& (1 << bcn_idx
)));
1340 NdisMoveMemory(pBeaconSync
->BeaconTxWI
[bcn_idx
], &pAd
->BeaconTxWI
, TXWI_SIZE
);
1343 if ((pBeaconSync
->BeaconBitMap
& (1 << bcn_idx
)) != (1 << bcn_idx
))
1345 for (i
=0; i
<TXWI_SIZE
; i
+=4) // 16-byte TXWI field
1347 longValue
= *ptr
+ (*(ptr
+1)<<8) + (*(ptr
+2)<<16) + (*(ptr
+3)<<24);
1348 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[bcn_idx
] + i
, longValue
);
1353 ptr
= pBeaconSync
->BeaconBuf
[bcn_idx
];
1354 padding
= (FrameLen
& 0x01);
1355 NdisZeroMemory((PUCHAR
)(pBeaconFrame
+ FrameLen
), padding
);
1356 FrameLen
+= padding
;
1357 for (i
= 0 ; i
< FrameLen
/*HW_BEACON_OFFSET*/; i
+= 2)
1359 if (NdisEqualMemory(ptr
, pBeaconFrame
, 2) == FALSE
)
1361 NdisMoveMemory(ptr
, pBeaconFrame
, 2);
1362 //shortValue = *ptr + (*(ptr+1)<<8);
1363 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1364 RTUSBMultiWrite(pAd
, pAd
->BeaconOffset
[bcn_idx
] + TXWI_SIZE
+ i
, ptr
, 2);
1370 pBeaconSync
->BeaconBitMap
|= (1 << bcn_idx
);
1372 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1378 VOID
RT2870_BssBeaconStop(
1379 IN RTMP_ADAPTER
*pAd
)
1381 BEACON_SYNC_STRUCT
*pBeaconSync
;
1383 BOOLEAN Cancelled
= TRUE
;
1385 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1386 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1390 NumOfBcn
= MAX_MESH_NUM
;
1392 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1394 for(i
=0; i
<NumOfBcn
; i
++)
1396 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1397 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1399 for (offset
=0; offset
<HW_BEACON_OFFSET
; offset
+=4)
1400 RTMP_IO_WRITE32(pAd
, pAd
->BeaconOffset
[i
] + offset
, 0x00);
1402 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1403 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1405 pBeaconSync
->BeaconBitMap
= 0;
1406 pBeaconSync
->DtimBitOn
= 0;
1411 VOID
RT2870_BssBeaconStart(
1412 IN RTMP_ADAPTER
*pAd
)
1415 BEACON_SYNC_STRUCT
*pBeaconSync
;
1416 // LARGE_INTEGER tsfTime, deltaTime;
1418 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1419 if (pBeaconSync
&& pBeaconSync
->EnableBeacon
)
1423 NumOfBcn
= MAX_MESH_NUM
;
1425 for(apidx
=0; apidx
<NumOfBcn
; apidx
++)
1427 UCHAR CapabilityInfoLocationInBeacon
= 0;
1428 UCHAR TimIELocationInBeacon
= 0;
1430 NdisZeroMemory(pBeaconSync
->BeaconBuf
[apidx
], HW_BEACON_OFFSET
);
1431 pBeaconSync
->CapabilityInfoLocationInBeacon
[apidx
] = CapabilityInfoLocationInBeacon
;
1432 pBeaconSync
->TimIELocationInBeacon
[apidx
] = TimIELocationInBeacon
;
1433 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[apidx
], TXWI_SIZE
);
1435 pBeaconSync
->BeaconBitMap
= 0;
1436 pBeaconSync
->DtimBitOn
= 0;
1437 pAd
->CommonCfg
.BeaconUpdateTimer
.Repeat
= TRUE
;
1439 pAd
->CommonCfg
.BeaconAdjust
= 0;
1440 pAd
->CommonCfg
.BeaconFactor
= 0xffffffff / (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1441 pAd
->CommonCfg
.BeaconRemain
= (0xffffffff % (pAd
->CommonCfg
.BeaconPeriod
<< 10)) + 1;
1442 printk(RT28xx_CHIP_NAME
"_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd
->CommonCfg
.BeaconFactor
, pAd
->CommonCfg
.BeaconRemain
);
1443 RTMPSetTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, pAd
->CommonCfg
.BeaconPeriod
);
1449 VOID
RT2870_BssBeaconInit(
1450 IN RTMP_ADAPTER
*pAd
)
1452 BEACON_SYNC_STRUCT
*pBeaconSync
;
1455 NdisAllocMemory(pAd
->CommonCfg
.pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
), MEM_ALLOC_FLAG
);
1456 if (pAd
->CommonCfg
.pBeaconSync
)
1458 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1459 NdisZeroMemory(pBeaconSync
, sizeof(BEACON_SYNC_STRUCT
));
1460 for(i
=0; i
< HW_BEACON_MAX_COUNT
; i
++)
1462 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1463 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1464 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1465 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1467 pBeaconSync
->BeaconBitMap
= 0;
1469 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1470 pBeaconSync
->EnableBeacon
= TRUE
;
1475 VOID
RT2870_BssBeaconExit(
1476 IN RTMP_ADAPTER
*pAd
)
1478 BEACON_SYNC_STRUCT
*pBeaconSync
;
1479 BOOLEAN Cancelled
= TRUE
;
1482 if (pAd
->CommonCfg
.pBeaconSync
)
1484 pBeaconSync
= pAd
->CommonCfg
.pBeaconSync
;
1485 pBeaconSync
->EnableBeacon
= FALSE
;
1486 RTMPCancelTimer(&pAd
->CommonCfg
.BeaconUpdateTimer
, &Cancelled
);
1487 pBeaconSync
->BeaconBitMap
= 0;
1489 for(i
=0; i
<HW_BEACON_MAX_COUNT
; i
++)
1491 NdisZeroMemory(pBeaconSync
->BeaconBuf
[i
], HW_BEACON_OFFSET
);
1492 pBeaconSync
->CapabilityInfoLocationInBeacon
[i
] = 0;
1493 pBeaconSync
->TimIELocationInBeacon
[i
] = 0;
1494 NdisZeroMemory(pBeaconSync
->BeaconTxWI
[i
], TXWI_SIZE
);
1497 NdisFreeMemory(pAd
->CommonCfg
.pBeaconSync
, HW_BEACON_OFFSET
* HW_BEACON_MAX_COUNT
, 0);
1498 pAd
->CommonCfg
.pBeaconSync
= NULL
;
1502 VOID
BeaconUpdateExec(
1503 IN PVOID SystemSpecific1
,
1504 IN PVOID FunctionContext
,
1505 IN PVOID SystemSpecific2
,
1506 IN PVOID SystemSpecific3
)
1508 PRTMP_ADAPTER pAd
= (PRTMP_ADAPTER
)FunctionContext
;
1509 LARGE_INTEGER tsfTime_a
;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1510 UINT32 delta
, remain
, remain_low
, remain_high
;
1511 // BOOLEAN positive;
1513 ReSyncBeaconTime(pAd
);
1517 RTMP_IO_READ32(pAd
, TSF_TIMER_DW0
, &tsfTime_a
.u
.LowPart
);
1518 RTMP_IO_READ32(pAd
, TSF_TIMER_DW1
, &tsfTime_a
.u
.HighPart
);
1521 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1522 remain_high
= pAd
->CommonCfg
.BeaconRemain
* tsfTime_a
.u
.HighPart
;
1523 remain_low
= tsfTime_a
.u
.LowPart
% (pAd
->CommonCfg
.BeaconPeriod
<< 10);
1524 remain
= (remain_high
+ remain_low
)%(pAd
->CommonCfg
.BeaconPeriod
<< 10);
1525 delta
= (pAd
->CommonCfg
.BeaconPeriod
<< 10) - remain
;
1527 pAd
->CommonCfg
.BeaconUpdateTimer
.TimerValue
= (delta
>> 10) + 10;