Staging: rtxxx0: PID checking fixes
[firewire-audio.git] / drivers / staging / rt2870 / 2870_main_dev.c
blob9b8ec40ea873705c06f5a05883c523b966d5c156
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
27 Module Name:
28 rtmp_main.c
30 Abstract:
31 main initialization routines
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36 Name Date Modification logs
37 Jan Lee 01-10-2005 modified
38 Sample Jun/01/07 Merge RT2870 and RT2860 drivers.
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");
50 #ifdef MODULE_VERSION
51 MODULE_VERSION(STA_DRIVER_VERSION);
52 #endif
54 /* Kernel thread and vars, which handles packets that are completed. Only
55 * packets that have a "complete" function are sent here. This way, the
56 * completion is run out of kernel context, and doesn't block the rest of
57 * the stack. */
59 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
60 IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
62 struct usb_device_id rtusb_usb_id[] = {
63 { USB_DEVICE(0x148F, 0x2770) }, /* Ralink */
64 #ifndef RT30xx
65 { USB_DEVICE(0x1737, 0x0071) }, /* Linksys WUSB600N */
66 { USB_DEVICE(0x1737, 0x0070) }, /* Linksys */
67 #endif
68 { USB_DEVICE(0x148F, 0x2870) }, /* Ralink */
69 { USB_DEVICE(0x148F, 0x3070) }, /* Ralink 3070 */
70 #ifdef RT30xx
71 { USB_DEVICE(0x148F, 0x3071) }, /* Ralink 3071 */
72 { USB_DEVICE(0x148F, 0x3072) }, /* Ralink 3072 */
73 #endif
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 */
80 #ifdef RT30xx
81 { USB_DEVICE(0x0DF6, 0x003E) }, /* Sitecom 3070 */
82 #endif
83 { USB_DEVICE(0x0DF6, 0x002D) }, /* Sitecom */
84 { USB_DEVICE(0x0DF6, 0x0039) }, /* Sitecom 2770 */
85 #ifndef RT30xx
86 { USB_DEVICE(0x0DF6, 0x003F) }, /* Sitecom WL-608 */
87 #endif
88 { USB_DEVICE(0x14B2, 0x3C06) }, /* Conceptronic */
89 { USB_DEVICE(0x14B2, 0x3C28) }, /* Conceptronic */
90 { USB_DEVICE(0x2019, 0xED06) }, /* Planex Communications, Inc. */
91 #ifndef RT30xx
92 { USB_DEVICE(0x2019, 0xED14) }, /* Planex Communications, Inc. */
93 #endif
94 { USB_DEVICE(0x2019, 0xAB25) }, /* Planex Communications, Inc. RT3070 */
95 { USB_DEVICE(0x07D1, 0x3C09) }, /* D-Link */
96 { USB_DEVICE(0x07D1, 0x3C11) }, /* D-Link */
97 #ifdef RT30xx
98 { USB_DEVICE(0x2001, 0x3C09) }, /* D-Link */
99 { USB_DEVICE(0x2001, 0x3C0A) }, /* D-Link 3072*/
100 #endif
101 { USB_DEVICE(0x14B2, 0x3C07) }, /* AL */
102 { USB_DEVICE(0x14B2, 0x3C12) }, /* AL 3070 */
103 { USB_DEVICE(0x050D, 0x8053) }, /* Belkin */
104 #ifndef RT30xx
105 { USB_DEVICE(0x050D, 0x815C) }, /* Belkin */
106 { USB_DEVICE(0x050D, 0x825a) }, /* Belkin */
107 #endif
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 */
115 #ifdef RT30xx
116 { USB_DEVICE(0x1044, 0x800D) }, /* Gigabyte GN-WB32L 3070 */
117 #endif
118 { USB_DEVICE(0x15A9, 0x0006) }, /* Sparklan */
119 { USB_DEVICE(0x083A, 0xB522) }, /* SMC */
120 { USB_DEVICE(0x083A, 0xA618) }, /* SMC */
121 #ifdef RT30xx
122 { USB_DEVICE(0x083A, 0x8522) }, /* Arcadyan */
123 { USB_DEVICE(0x083A, 0x7512) }, /* Arcadyan 2770 */
124 #endif
125 { USB_DEVICE(0x083A, 0x7522) }, /* Arcadyan */
126 #ifdef RT30xx
127 { USB_DEVICE(0x083A, 0x7511) }, /* Arcadyan 3070 */
128 #endif
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 */
134 #ifdef RT30xx
135 { USB_DEVICE(0x1740, 0x9703) }, /* EnGenius 3070 */
136 #endif
137 { USB_DEVICE(0x0471, 0x200f) }, /* Philips */
138 { USB_DEVICE(0x14B2, 0x3C25) }, /* Draytek */
139 { USB_DEVICE(0x13D3, 0x3247) }, /* AzureWave */
140 #ifdef RT30xx
141 { USB_DEVICE(0x13D3, 0x3273) }, /* AzureWave 3070*/
142 #endif
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 */
155 #ifndef RT30xx
156 { USB_DEVICE(0x07B8, 0x2870) }, /* AboCom */
157 { USB_DEVICE(0x07B8, 0x2770) }, /* AboCom */
158 #else
159 { USB_DEVICE(0x07B8, 0x3072) }, /* Abocom 3072 */
160 #endif
161 { USB_DEVICE(0x7392, 0x7711) }, /* Edimax 3070 */
162 { USB_DEVICE(0x5A57, 0x0280) }, /* Zinwell */
163 { USB_DEVICE(0x5A57, 0x0282) }, /* Zinwell */
164 #ifdef RT30xx
165 { USB_DEVICE(0x1A32, 0x0304) }, /* Quanta 3070 */
166 #endif
167 { USB_DEVICE(0x0789, 0x0162) }, /* Logitec 2870 */
168 { USB_DEVICE(0x0789, 0x0163) }, /* Logitec 2870 */
169 { USB_DEVICE(0x0789, 0x0164) }, /* Logitec 2870 */
170 #ifndef RT30xx
171 { USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
172 #else
173 { USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
174 { USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
175 #endif
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);
182 #ifndef PF_NOFREEZE
183 #define PF_NOFREEZE 0
184 #endif
187 #ifdef CONFIG_PM
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 = {
202 .name="rt2870",
203 .probe=rtusb_probe,
204 .disconnect=rtusb_disconnect,
205 .id_table=rtusb_usb_id,
207 #ifdef CONFIG_PM
208 suspend: rt2870_suspend,
209 resume: rt2870_resume,
210 #endif
213 #ifdef CONFIG_PM
215 VOID RT2860RejectPendingPackets(
216 IN PRTMP_ADAPTER pAd)
218 // clear PS packets
219 // clear TxSw packets
222 static int rt2870_suspend(
223 struct usb_interface *intf,
224 pm_message_t state)
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"));
240 return 0;
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"));
260 return 0;
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 ========================================================================
291 Routine Description:
292 MLME kernel thread.
294 Arguments:
295 *Context the pAd, driver control block pointer
297 Return Value:
298 0 close the thread
300 Note:
301 ========================================================================
303 INT MlmeThread(
304 IN void *Context)
306 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
307 POS_COOKIE pObj;
308 int status;
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)
324 MlmeHandler(pAd);
326 /* unlock the device pointers */
327 //up(&(pAd->usbdev_semaphore));
328 if (status != 0)
330 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
331 break;
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
341 * case.
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 #ifndef RT30xx
352 pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
353 #endif
354 #ifdef RT30xx
355 pObj->MLMEThr_pid = NULL;
356 #endif
358 complete_and_exit (&pAd->mlmeComplete, 0);
359 return 0;
365 ========================================================================
366 Routine Description:
367 USB command kernel thread.
369 Arguments:
370 *Context the pAd, driver control block pointer
372 Return Value:
373 0 close the thread
375 Note:
376 ========================================================================
378 INT RTUSBCmdThread(
379 IN void * Context)
381 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
382 POS_COOKIE pObj;
383 int status;
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)
400 break;
402 if (status != 0)
404 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
405 break;
407 /* lock the device pointers , need to check if required*/
408 //down(&(pAd->usbdev_semaphore));
410 if (!pAd->PM_FlgSuspend)
411 CMDHandler(pAd);
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);
426 if (pCmdQElmt)
428 if (pCmdQElmt->CmdFromNdis == TRUE)
430 if (pCmdQElmt->buffer != NULL)
431 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
433 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
435 else
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
454 * case.
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"));
464 #ifndef RT30xx
465 pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
466 #endif
467 #ifdef RT30xx
468 pObj->RTUSBCmdThr_pid = NULL;
469 #endif
471 complete_and_exit (&pAd->CmdQComplete, 0);
472 return 0;
477 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
479 int status;
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");
487 pTimer = NULL;
489 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
491 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
492 break;
494 // event happened.
495 while(pAd->TimerQ.pQHead)
497 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
498 pEntry = pAd->TimerQ.pQHead;
499 if (pEntry)
501 pTimer = pEntry->pRaTimer;
503 // update pQHead
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);
514 if (pTimer)
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);
524 if (status != 0)
526 pAd->TimerQ.status = RT2870_THREAD_STOPED;
527 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
528 break;
534 INT TimerQThread(
535 IN OUT PVOID Context)
537 PRTMP_ADAPTER pAd;
538 POS_COOKIE pObj;
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
553 * case.
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__));
563 #ifndef RT30xx
564 pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
565 #endif
566 #ifdef RT30xx
567 pObj->TimerQThr_pid = NULL;
568 #endif
569 complete_and_exit(&pAd->TimerQComplete, 0);
570 return 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);
603 if (pQNode)
604 up(&pAd->RTUSBTimer_semaphore);
605 //wake_up(&timerWaitQ);
607 else
609 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
611 return pQNode;
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;
626 while (pNode)
628 if (pNode->pRaTimer == pTimer)
629 break;
630 pPrev = pNode;
631 pNode = pNode->pNext;
634 // Now move it to freeList queue.
635 if (pNode)
637 if (pNode == pAd->TimerQ.pQHead)
638 pAd->TimerQ.pQHead = pNode->pNext;
639 if (pNode == pAd->TimerQ.pQTail)
640 pAd->TimerQ.pQTail = pPrev;
641 if (pPrev != NULL)
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);
651 return TRUE;
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;
665 // remove the timeQ
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)
679 int i;
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)
695 pEntry = NULL;
696 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
697 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
699 pQNode->pNext = pEntry;
700 pEntry = pQNode;
701 pQNode++;
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;
715 int idx;
716 ULONG irqFlags;
717 PURB pUrb;
718 BOOLEAN needDumpSeq = FALSE;
719 UINT32 MACValue;
722 idx = 0;
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);
731 NdisMSleep(1);
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)
737 idx = 0;
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);
745 NdisMSleep(1);
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);
761 needDumpSeq = TRUE;
763 pAd->watchDogRxOverFlowCnt = 0;
767 for (idx = 0; idx < NUM_OF_TX_RING; idx++)
769 pUrb = NULL;
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;
790 //Check MgmtContext.
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));
815 if (pUrb)
817 DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
818 // unlink it now
819 RTUSB_UNLINK_URB(pUrb);
820 // Sleep 200 microseconds to give cancellation time to work
821 RTMPusecDelay(200);
822 needDumpSeq = TRUE;
824 else
826 DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
829 else
831 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
834 else
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))
843 USHORT Idx;
844 PBA_REC_ENTRY pBAEntry = NULL;
845 UCHAR count = 0;
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;
856 while (mpdu_blk)
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;
860 count++;
863 DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
864 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
870 ========================================================================
871 Routine Description:
872 Release allocated resources.
874 Arguments:
875 *dev Point to the PCI or USB device
876 pAd driver control block pointer
878 Return Value:
879 None
881 Note:
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));
891 if (!pAd)
893 usb_put_dev(dev);
895 printk("rtusb_disconnect: pAd == NULL!\n");
896 return;
898 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
902 // for debug, wait to show some messages to /proc system
903 udelay(1);
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);
914 udelay(1);
915 flush_scheduled_work();
916 udelay(1);
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
925 usb_put_dev(dev);
926 udelay(1);
928 DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
933 ========================================================================
934 Routine Description:
935 Probe RT28XX chipset.
937 Arguments:
938 *dev Point to the PCI or USB device
939 interface
940 *id_table Point to the PCI or USB device ID
942 Return Value:
943 None
945 Note:
946 ========================================================================
948 static int rtusb_probe (struct usb_interface *intf,
949 const struct usb_device_id *id)
951 PRTMP_ADAPTER pAd;
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);
959 PRTMP_ADAPTER pAd;
962 pAd = usb_get_intfdata(intf);
963 usb_set_intfdata(intf, NULL);
965 _rtusb_disconnect(dev, pAd);
970 ========================================================================
971 Routine Description:
972 Close kernel threads.
974 Arguments:
975 *pAd the raxx interface data pointer
977 Return Value:
978 NONE
980 Note:
981 ========================================================================
983 VOID RT28xxThreadTerminate(
984 IN RTMP_ADAPTER *pAd)
986 POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
987 INT ret;
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);
998 // Terminate Threads
999 #ifndef RT30xx
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));
1005 mb();
1006 pAd->TimerFunc_kill = 1;
1007 mb();
1008 ret = KILL_THREAD_PID(pObj->TimerQThr_pid, SIGTERM, 1);
1009 if (ret)
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);
1014 else
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));
1024 mb();
1025 pAd->mlme_kill = 1;
1026 //RT28XX_MLME_HANDLER(pAd);
1027 mb();
1028 ret = KILL_THREAD_PID(pObj->MLMEThr_pid, SIGTERM, 1);
1029 if (ret)
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);
1034 else
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));
1045 mb();
1046 NdisAcquireSpinLock(&pAd->CmdQLock);
1047 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
1048 NdisReleaseSpinLock(&pAd->CmdQLock);
1049 mb();
1050 //RTUSBCMDUp(pAd);
1051 ret = KILL_THREAD_PID(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
1052 if (ret)
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);
1057 else
1059 //wait_for_completion (&pAd->notify);
1060 wait_for_completion (&pAd->CmdQComplete);
1061 pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
1064 #endif
1065 #ifdef RT30xx
1066 if (pid_nr(pObj->MLMEThr_pid) > 0)
1068 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
1069 mb();
1070 pAd->mlme_kill = 1;
1071 //RT28XX_MLME_HANDLER(pAd);
1072 mb();
1073 ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
1074 if (ret)
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);
1079 else
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));
1090 mb();
1091 NdisAcquireSpinLock(&pAd->CmdQLock);
1092 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
1093 NdisReleaseSpinLock(&pAd->CmdQLock);
1094 mb();
1095 //RTUSBCMDUp(pAd);
1096 ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
1097 if (ret)
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);
1102 else
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));
1113 mb();
1114 pAd->TimerFunc_kill = 1;
1115 mb();
1116 ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
1117 if (ret)
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);
1122 else
1124 printk("wait_for_completion TimerQThr\n");
1125 wait_for_completion(&pAd->TimerQComplete);
1126 pObj->TimerQThr_pid = NULL;
1129 #endif
1131 // Kill tasklets
1132 pAd->mlme_kill = 0;
1133 pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1134 pAd->TimerFunc_kill = 0;
1138 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1140 POS_COOKIE pObj;
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.
1161 Arguments:
1162 _dev_p Point to the PCI or USB device
1164 Return Value:
1165 TRUE Check ok
1166 FALSE Check fail
1168 Note:
1169 ========================================================================
1171 BOOLEAN RT28XXChipsetCheck(
1172 IN void *_dev_p)
1174 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1175 struct usb_device *dev_p = interface_to_usbdev(intf);
1176 UINT32 i;
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)
1184 #ifndef RT30xx
1185 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1186 #endif
1187 #ifdef RT30xx
1188 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1189 #endif
1190 dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1191 break;
1195 if (i == rtusb_usb_id_len)
1197 printk("rt2870: Error! Device Descriptor not matching!\n");
1198 return FALSE;
1201 return TRUE;
1206 ========================================================================
1207 Routine Description:
1208 Init net device structure.
1210 Arguments:
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
1215 Return Value:
1216 TRUE Init ok
1217 FALSE Init fail
1219 Note:
1220 ========================================================================
1222 BOOLEAN RT28XXNetDevInit(
1223 IN void *_dev_p,
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;
1232 return TRUE;
1237 ========================================================================
1238 Routine Description:
1239 Init net device structure.
1241 Arguments:
1242 _dev_p Point to the PCI or USB device
1243 *pAd the raxx interface data pointer
1245 Return Value:
1246 TRUE Config ok
1247 FALSE Config fail
1249 Note:
1250 ========================================================================
1252 BOOLEAN RT28XXProbePostConfig(
1253 IN void *_dev_p,
1254 IN RTMP_ADAPTER *pAd,
1255 IN INT32 interface)
1257 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1258 struct usb_host_interface *iface_desc;
1259 ULONG BulkOutIdx;
1260 UINT32 i;
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 */
1272 BulkOutIdx = 0;
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__);
1309 return FALSE;
1312 return TRUE;
1317 ========================================================================
1318 Routine Description:
1319 Disable DMA.
1321 Arguments:
1322 *pAd the raxx interface data pointer
1324 Return Value:
1325 None
1327 Note:
1328 ========================================================================
1330 VOID RT28XXDMADisable(
1331 IN RTMP_ADAPTER *pAd)
1333 // no use
1339 ========================================================================
1340 Routine Description:
1341 Enable DMA.
1343 Arguments:
1344 *pAd the raxx interface data pointer
1346 Return Value:
1347 None
1349 Note:
1350 ========================================================================
1352 VOID RT28XXDMAEnable(
1353 IN RTMP_ADAPTER *pAd)
1355 WPDMA_GLO_CFG_STRUC GloCfg;
1356 USB_DMA_CFG_STRUC UsbCfg;
1357 int i = 0;
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))
1365 break;
1367 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
1368 RTMPusecDelay(1000);
1369 i++;
1370 }while ( i <200);
1373 RTMPusecDelay(50);
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);
1380 UsbCfg.word = 0;
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.
1400 Arguments:
1401 *pAd the raxx interface data pointer
1403 Return Value:
1404 None
1406 Note:
1407 ========================================================================
1409 VOID RT28xx_UpdateBeaconToAsic(
1410 IN RTMP_ADAPTER *pAd,
1411 IN INT apidx,
1412 IN ULONG FrameLen,
1413 IN ULONG UpdatePos)
1415 PUCHAR pBeaconFrame = NULL;
1416 UCHAR *ptr;
1417 UINT i, padding;
1418 BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1419 UINT32 longValue;
1420 BOOLEAN bBcnReq = FALSE;
1421 UCHAR bcn_idx = 0;
1424 if (pBeaconFrame == NULL)
1426 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1427 return;
1430 if (pBeaconSync == NULL)
1432 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1433 return;
1436 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1437 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1438 // )
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);
1449 else
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);
1465 ptr += 4;
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);
1482 ptr +=2;
1483 pBeaconFrame += 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;
1498 int i, offset;
1499 BOOLEAN Cancelled = TRUE;
1501 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1502 if (pBeaconSync && pBeaconSync->EnableBeacon)
1504 INT NumOfBcn;
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)
1530 int apidx;
1531 BEACON_SYNC_STRUCT *pBeaconSync;
1532 // LARGE_INTEGER tsfTime, deltaTime;
1534 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1535 if (pBeaconSync && pBeaconSync->EnableBeacon)
1537 INT NumOfBcn;
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;
1569 int i;
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;
1596 int i;
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;