1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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 *************************************************************************
26
27 Module Name:
28 rtmp_main.c
29
30 Abstract:
31 main initialization routines
32
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.
39 */
40
41 #include "rt_config.h"
42
43
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("RT2870 Wireless Lan Linux Driver");
49 MODULE_LICENSE("GPL");
50 #ifdef MODULE_VERSION
51 MODULE_VERSION(STA_DRIVER_VERSION);
52 #endif
53
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. */
58
59 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
60 IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
61
62
63 /* module table */
64 struct usb_device_id rtusb_usb_id[] = RT2870_USB_DEVICES;
65 INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
66 MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
67
68 #ifndef PF_NOFREEZE
69 #define PF_NOFREEZE 0
70 #endif
71
72
73 #ifdef CONFIG_PM
74 static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
75 static int rt2870_resume(struct usb_interface *intf);
76 #endif // CONFIG_PM //
77
78 /**************************************************************************/
79 /**************************************************************************/
80 //tested for kernel 2.6series
81 /**************************************************************************/
82 /**************************************************************************/
83 static int rtusb_probe (struct usb_interface *intf,
84 const struct usb_device_id *id);
85 static void rtusb_disconnect(struct usb_interface *intf);
86
87 struct usb_driver rtusb_driver = {
88 .name="rt2870",
89 .probe=rtusb_probe,
90 .disconnect=rtusb_disconnect,
91 .id_table=rtusb_usb_id,
92
93 #ifdef CONFIG_PM
94 suspend: rt2870_suspend,
95 resume: rt2870_resume,
96 #endif
97 };
98
99 #ifdef CONFIG_PM
100
101 VOID RT2860RejectPendingPackets(
102 IN PRTMP_ADAPTER pAd)
103 {
104 // clear PS packets
105 // clear TxSw packets
106 }
107
108 static int rt2870_suspend(
109 struct usb_interface *intf,
110 pm_message_t state)
111 {
112 struct net_device *net_dev;
113 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
114
115
116 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
117 net_dev = pAd->net_dev;
118 netif_device_detach (net_dev);
119
120 pAd->PM_FlgSuspend = 1;
121 if (netif_running(net_dev)) {
122 RTUSBCancelPendingBulkInIRP(pAd);
123 RTUSBCancelPendingBulkOutIRP(pAd);
124 }
125 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
126 return 0;
127 }
128
129 static int rt2870_resume(
130 struct usb_interface *intf)
131 {
132 struct net_device *net_dev;
133 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
134
135
136 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
137
138 pAd->PM_FlgSuspend = 0;
139 net_dev = pAd->net_dev;
140 netif_device_attach (net_dev);
141 netif_start_queue(net_dev);
142 netif_carrier_on(net_dev);
143 netif_wake_queue(net_dev);
144
145 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
146 return 0;
147 }
148 #endif // CONFIG_PM //
149
150
151 // Init driver module
152 INT __init rtusb_init(void)
153 {
154 printk("rtusb init --->\n");
155 return usb_register(&rtusb_driver);
156 }
157
158 // Deinit driver module
159 VOID __exit rtusb_exit(void)
160 {
161 usb_deregister(&rtusb_driver);
162 printk("<--- rtusb exit\n");
163 }
164
165 module_init(rtusb_init);
166 module_exit(rtusb_exit);
167
168
169
170
171 /*--------------------------------------------------------------------- */
172 /* function declarations */
173 /*--------------------------------------------------------------------- */
174
175 /*
176 ========================================================================
177 Routine Description:
178 MLME kernel thread.
179
180 Arguments:
181 *Context the pAd, driver control block pointer
182
183 Return Value:
184 0 close the thread
185
186 Note:
187 ========================================================================
188 */
189 INT MlmeThread(
190 IN void *Context)
191 {
192 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
193 POS_COOKIE pObj;
194 int status;
195
196 pObj = (POS_COOKIE)pAd->OS_Cookie;
197
198 rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
199
200 while (pAd->mlme_kill == 0)
201 {
202 /* lock the device pointers */
203 //down(&(pAd->mlme_semaphore));
204 status = down_interruptible(&(pAd->mlme_semaphore));
205
206 /* lock the device pointers , need to check if required*/
207 //down(&(pAd->usbdev_semaphore));
208
209 if (!pAd->PM_FlgSuspend)
210 MlmeHandler(pAd);
211
212 /* unlock the device pointers */
213 //up(&(pAd->usbdev_semaphore));
214 if (status != 0)
215 {
216 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
217 break;
218 }
219 }
220
221 /* notify the exit routine that we're actually exiting now
222 *
223 * complete()/wait_for_completion() is similar to up()/down(),
224 * except that complete() is safe in the case where the structure
225 * is getting deleted in a parallel mode of execution (i.e. just
226 * after the down() -- that's necessary for the thread-shutdown
227 * case.
228 *
229 * complete_and_exit() goes even further than this -- it is safe in
230 * the case that the thread of the caller is going away (not just
231 * the structure) -- this is necessary for the module-remove case.
232 * This is important in preemption kernels, which transfer the flow
233 * of execution immediately upon a complete().
234 */
235 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
236
237 #ifndef RT30xx
238 pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
239 #endif
240 #ifdef RT30xx
241 pObj->MLMEThr_pid = NULL;
242 #endif
243
244 complete_and_exit (&pAd->mlmeComplete, 0);
245 return 0;
246
247 }
248
249
250 /*
251 ========================================================================
252 Routine Description:
253 USB command kernel thread.
254
255 Arguments:
256 *Context the pAd, driver control block pointer
257
258 Return Value:
259 0 close the thread
260
261 Note:
262 ========================================================================
263 */
264 INT RTUSBCmdThread(
265 IN void * Context)
266 {
267 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
268 POS_COOKIE pObj;
269 int status;
270
271 pObj = (POS_COOKIE)pAd->OS_Cookie;
272
273 rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
274
275 NdisAcquireSpinLock(&pAd->CmdQLock);
276 pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
277 NdisReleaseSpinLock(&pAd->CmdQLock);
278
279 while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
280 {
281 /* lock the device pointers */
282 //down(&(pAd->RTUSBCmd_semaphore));
283 status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
284
285 if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
286 break;
287
288 if (status != 0)
289 {
290 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
291 break;
292 }
293 /* lock the device pointers , need to check if required*/
294 //down(&(pAd->usbdev_semaphore));
295
296 if (!pAd->PM_FlgSuspend)
297 CMDHandler(pAd);
298
299 /* unlock the device pointers */
300 //up(&(pAd->usbdev_semaphore));
301 }
302
303 if (!pAd->PM_FlgSuspend)
304 { // Clear the CmdQElements.
305 CmdQElmt *pCmdQElmt = NULL;
306
307 NdisAcquireSpinLock(&pAd->CmdQLock);
308 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
309 while(pAd->CmdQ.size)
310 {
311 RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
312 if (pCmdQElmt)
313 {
314 if (pCmdQElmt->CmdFromNdis == TRUE)
315 {
316 if (pCmdQElmt->buffer != NULL)
317 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
318
319 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
320 }
321 else
322 {
323 if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
324 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
325 {
326 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
327 }
328 }
329 }
330 }
331
332 NdisReleaseSpinLock(&pAd->CmdQLock);
333 }
334 /* notify the exit routine that we're actually exiting now
335 *
336 * complete()/wait_for_completion() is similar to up()/down(),
337 * except that complete() is safe in the case where the structure
338 * is getting deleted in a parallel mode of execution (i.e. just
339 * after the down() -- that's necessary for the thread-shutdown
340 * case.
341 *
342 * complete_and_exit() goes even further than this -- it is safe in
343 * the case that the thread of the caller is going away (not just
344 * the structure) -- this is necessary for the module-remove case.
345 * This is important in preemption kernels, which transfer the flow
346 * of execution immediately upon a complete().
347 */
348 DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
349
350 #ifndef RT30xx
351 pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
352 #endif
353 #ifdef RT30xx
354 pObj->RTUSBCmdThr_pid = NULL;
355 #endif
356
357 complete_and_exit (&pAd->CmdQComplete, 0);
358 return 0;
359
360 }
361
362
363 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
364 {
365 int status;
366 RALINK_TIMER_STRUCT *pTimer;
367 RT2870_TIMER_ENTRY *pEntry;
368 unsigned long irqFlag;
369
370 while(!pAd->TimerFunc_kill)
371 {
372 // printk("waiting for event!\n");
373 pTimer = NULL;
374
375 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
376
377 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
378 break;
379
380 // event happened.
381 while(pAd->TimerQ.pQHead)
382 {
383 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
384 pEntry = pAd->TimerQ.pQHead;
385 if (pEntry)
386 {
387 pTimer = pEntry->pRaTimer;
388
389 // update pQHead
390 pAd->TimerQ.pQHead = pEntry->pNext;
391 if (pEntry == pAd->TimerQ.pQTail)
392 pAd->TimerQ.pQTail = NULL;
393
394 // return this queue entry to timerQFreeList.
395 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
396 pAd->TimerQ.pQPollFreeList = pEntry;
397 }
398 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
399
400 if (pTimer)
401 {
402 if (pTimer->handle != NULL)
403 if (!pAd->PM_FlgSuspend)
404 pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
405 if ((pTimer->Repeat) && (pTimer->State == FALSE))
406 RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
407 }
408 }
409
410 if (status != 0)
411 {
412 pAd->TimerQ.status = RT2870_THREAD_STOPED;
413 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
414 break;
415 }
416 }
417 }
418
419
420 INT TimerQThread(
421 IN OUT PVOID Context)
422 {
423 PRTMP_ADAPTER pAd;
424 POS_COOKIE pObj;
425
426 pAd = (PRTMP_ADAPTER)Context;
427 pObj = (POS_COOKIE) pAd->OS_Cookie;
428
429 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
430
431 RT2870_TimerQ_Handle(pAd);
432
433 /* notify the exit routine that we're actually exiting now
434 *
435 * complete()/wait_for_completion() is similar to up()/down(),
436 * except that complete() is safe in the case where the structure
437 * is getting deleted in a parallel mode of execution (i.e. just
438 * after the down() -- that's necessary for the thread-shutdown
439 * case.
440 *
441 * complete_and_exit() goes even further than this -- it is safe in
442 * the case that the thread of the caller is going away (not just
443 * the structure) -- this is necessary for the module-remove case.
444 * This is important in preemption kernels, which transfer the flow
445 * of execution immediately upon a complete().
446 */
447 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
448
449 #ifndef RT30xx
450 pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
451 #endif
452 #ifdef RT30xx
453 pObj->TimerQThr_pid = NULL;
454 #endif
455 complete_and_exit(&pAd->TimerQComplete, 0);
456 return 0;
457
458 }
459
460
461 RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
462 IN RTMP_ADAPTER *pAd,
463 IN RALINK_TIMER_STRUCT *pTimer)
464 {
465 RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
466 unsigned long irqFlags;
467
468
469 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
470 if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
471 {
472 if(pAd->TimerQ.pQPollFreeList)
473 {
474 pQNode = pAd->TimerQ.pQPollFreeList;
475 pAd->TimerQ.pQPollFreeList = pQNode->pNext;
476
477 pQNode->pRaTimer = pTimer;
478 pQNode->pNext = NULL;
479
480 pQTail = pAd->TimerQ.pQTail;
481 if (pAd->TimerQ.pQTail != NULL)
482 pQTail->pNext = pQNode;
483 pAd->TimerQ.pQTail = pQNode;
484 if (pAd->TimerQ.pQHead == NULL)
485 pAd->TimerQ.pQHead = pQNode;
486 }
487 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
488
489 if (pQNode)
490 up(&pAd->RTUSBTimer_semaphore);
491 //wake_up(&timerWaitQ);
492 }
493 else
494 {
495 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
496 }
497 return pQNode;
498 }
499
500
501 BOOLEAN RT2870_TimerQ_Remove(
502 IN RTMP_ADAPTER *pAd,
503 IN RALINK_TIMER_STRUCT *pTimer)
504 {
505 RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
506 unsigned long irqFlags;
507
508 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
509 if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
510 {
511 pNode = pAd->TimerQ.pQHead;
512 while (pNode)
513 {
514 if (pNode->pRaTimer == pTimer)
515 break;
516 pPrev = pNode;
517 pNode = pNode->pNext;
518 }
519
520 // Now move it to freeList queue.
521 if (pNode)
522 {
523 if (pNode == pAd->TimerQ.pQHead)
524 pAd->TimerQ.pQHead = pNode->pNext;
525 if (pNode == pAd->TimerQ.pQTail)
526 pAd->TimerQ.pQTail = pPrev;
527 if (pPrev != NULL)
528 pPrev->pNext = pNode->pNext;
529
530 // return this queue entry to timerQFreeList.
531 pNode->pNext = pAd->TimerQ.pQPollFreeList;
532 pAd->TimerQ.pQPollFreeList = pNode;
533 }
534 }
535 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
536
537 return TRUE;
538 }
539
540
541 void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
542 {
543 RT2870_TIMER_ENTRY *pTimerQ;
544 unsigned long irqFlags;
545
546 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
547 while (pAd->TimerQ.pQHead)
548 {
549 pTimerQ = pAd->TimerQ.pQHead;
550 pAd->TimerQ.pQHead = pTimerQ->pNext;
551 // remove the timeQ
552 }
553 pAd->TimerQ.pQPollFreeList = NULL;
554 os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
555 pAd->TimerQ.pQTail = NULL;
556 pAd->TimerQ.pQHead = NULL;
557 pAd->TimerQ.status = RT2870_THREAD_STOPED;
558 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
559
560 }
561
562
563 void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
564 {
565 int i;
566 RT2870_TIMER_ENTRY *pQNode, *pEntry;
567 unsigned long irqFlags;
568
569 NdisAllocateSpinLock(&pAd->TimerQLock);
570
571 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
572 NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
573 //InterlockedExchange(&pAd->TimerQ.count, 0);
574
575 /* Initialise the wait q head */
576 //init_waitqueue_head(&timerWaitQ);
577
578 os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
579 if (pAd->TimerQ.pTimerQPoll)
580 {
581 pEntry = NULL;
582 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
583 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
584 {
585 pQNode->pNext = pEntry;
586 pEntry = pQNode;
587 pQNode++;
588 }
589 pAd->TimerQ.pQPollFreeList = pEntry;
590 pAd->TimerQ.pQHead = NULL;
591 pAd->TimerQ.pQTail = NULL;
592 pAd->TimerQ.status = RT2870_THREAD_INITED;
593 }
594 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
595 }
596
597
598 VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
599 {
600 PHT_TX_CONTEXT pHTTXContext;
601 int idx;
602 ULONG irqFlags;
603 PURB pUrb;
604 BOOLEAN needDumpSeq = FALSE;
605 UINT32 MACValue;
606
607
608 idx = 0;
609 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
610 if ((MACValue & 0xff) !=0 )
611 {
612 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
613 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
614 while((MACValue &0xff) != 0 && (idx++ < 10))
615 {
616 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
617 NdisMSleep(1);
618 }
619 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
620 }
621
622 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
623 idx = 0;
624 if ((MACValue & 0xff00) !=0 )
625 {
626 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
627 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
628 while((MACValue &0xff00) != 0 && (idx++ < 10))
629 {
630 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
631 NdisMSleep(1);
632 }
633 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
634 }
635
636 if (pAd->watchDogRxOverFlowCnt >= 2)
637 {
638 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
639 if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
640 fRTMP_ADAPTER_BULKIN_RESET |
641 fRTMP_ADAPTER_HALT_IN_PROGRESS |
642 fRTMP_ADAPTER_NIC_NOT_EXIST))))
643 {
644 DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
645 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
646 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
647 needDumpSeq = TRUE;
648 }
649 pAd->watchDogRxOverFlowCnt = 0;
650 }
651
652
653 for (idx = 0; idx < NUM_OF_TX_RING; idx++)
654 {
655 pUrb = NULL;
656
657 RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
658 if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
659 {
660 pAd->watchDogTxPendingCnt[idx]++;
661
662 if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
663 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
664 )
665 {
666 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
667 pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
668 if (pHTTXContext->IRPPending)
669 { // Check TxContext.
670 pUrb = pHTTXContext->pUrb;
671 }
672 else if (idx == MGMTPIPEIDX)
673 {
674 PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
675
676 //Check MgmtContext.
677 pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
678 pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
679 pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
680
681 if (pMLMEContext->IRPPending)
682 {
683 ASSERT(pMLMEContext->IRPPending);
684 pUrb = pMLMEContext->pUrb;
685 }
686 else if (pNULLContext->IRPPending)
687 {
688 ASSERT(pNULLContext->IRPPending);
689 pUrb = pNULLContext->pUrb;
690 }
691 else if (pPsPollContext->IRPPending)
692 {
693 ASSERT(pPsPollContext->IRPPending);
694 pUrb = pPsPollContext->pUrb;
695 }
696 }
697
698 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
699
700 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
701 if (pUrb)
702 {
703 DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
704 // unlink it now
705 RTUSB_UNLINK_URB(pUrb);
706 // Sleep 200 microseconds to give cancellation time to work
707 RTMPusecDelay(200);
708 needDumpSeq = TRUE;
709 }
710 else
711 {
712 DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
713 }
714 }
715 else
716 {
717 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
718 }
719 }
720 else
721 {
722 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
723 }
724 }
725
726 // For Sigma debug, dump the ba_reordering sequence.
727 if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
728 {
729 USHORT Idx;
730 PBA_REC_ENTRY pBAEntry = NULL;
731 UCHAR count = 0;
732 struct reordering_mpdu *mpdu_blk;
733
734 Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
735
736 pBAEntry = &pAd->BATable.BARecEntry[Idx];
737 if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
738 {
739 DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
740 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
741 mpdu_blk = pBAEntry->list.next;
742 while (mpdu_blk)
743 {
744 DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
745 mpdu_blk = mpdu_blk->next;
746 count++;
747 }
748
749 DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
750 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
751 }
752 }
753 }
754
755 /*
756 ========================================================================
757 Routine Description:
758 Release allocated resources.
759
760 Arguments:
761 *dev Point to the PCI or USB device
762 pAd driver control block pointer
763
764 Return Value:
765 None
766
767 Note:
768 ========================================================================
769 */
770 static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
771 {
772 struct net_device *net_dev = NULL;
773
774
775 DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
776 dev->bus->bus_name, dev->devpath));
777 if (!pAd)
778 {
779 usb_put_dev(dev);
780
781 printk("rtusb_disconnect: pAd == NULL!\n");
782 return;
783 }
784 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
785
786
787
788 // for debug, wait to show some messages to /proc system
789 udelay(1);
790
791
792
793
794 net_dev = pAd->net_dev;
795 if (pAd->net_dev != NULL)
796 {
797 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
798 unregister_netdev (pAd->net_dev);
799 }
800 udelay(1);
801 flush_scheduled_work();
802 udelay(1);
803
804 // free net_device memory
805 free_netdev(net_dev);
806
807 // free adapter memory
808 RTMPFreeAdapter(pAd);
809
810 // release a use of the usb device structure
811 usb_put_dev(dev);
812 udelay(1);
813
814 DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
815 }
816
817
818 /*
819 ========================================================================
820 Routine Description:
821 Probe RT28XX chipset.
822
823 Arguments:
824 *dev Point to the PCI or USB device
825 interface
826 *id_table Point to the PCI or USB device ID
827
828 Return Value:
829 None
830
831 Note:
832 ========================================================================
833 */
834 static int rtusb_probe (struct usb_interface *intf,
835 const struct usb_device_id *id)
836 {
837 PRTMP_ADAPTER pAd;
838 return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
839 }
840
841
842 static void rtusb_disconnect(struct usb_interface *intf)
843 {
844 struct usb_device *dev = interface_to_usbdev(intf);
845 PRTMP_ADAPTER pAd;
846
847
848 pAd = usb_get_intfdata(intf);
849 usb_set_intfdata(intf, NULL);
850
851 _rtusb_disconnect(dev, pAd);
852 }
853
854
855 /*
856 ========================================================================
857 Routine Description:
858 Close kernel threads.
859
860 Arguments:
861 *pAd the raxx interface data pointer
862
863 Return Value:
864 NONE
865
866 Note:
867 ========================================================================
868 */
869 VOID RT28xxThreadTerminate(
870 IN RTMP_ADAPTER *pAd)
871 {
872 POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
873 INT ret;
874
875
876 // Sleep 50 milliseconds so pending io might finish normally
877 RTMPusecDelay(50000);
878
879 // We want to wait until all pending receives and sends to the
880 // device object. We cancel any
881 // irps. Wait until sends and receives have stopped.
882 RTUSBCancelPendingIRPs(pAd);
883
884 // Terminate Threads
885 #ifndef RT30xx
886 CHECK_PID_LEGALITY(pObj->TimerQThr_pid)
887 {
888 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
889
890 printk("Terminate the TimerQThr_pid=%d!\n", GET_PID_NUMBER(pObj->TimerQThr_pid));
891 mb();
892 pAd->TimerFunc_kill = 1;
893 mb();
894 ret = KILL_THREAD_PID(pObj->TimerQThr_pid, SIGTERM, 1);
895 if (ret)
896 {
897 printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
898 pAd->net_dev->name, GET_PID_NUMBER(pObj->TimerQThr_pid), ret);
899 }
900 else
901 {
902 wait_for_completion(&pAd->TimerQComplete);
903 pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
904 }
905 }
906
907 CHECK_PID_LEGALITY(pObj->MLMEThr_pid)
908 {
909 printk("Terminate the MLMEThr_pid=%d!\n", GET_PID_NUMBER(pObj->MLMEThr_pid));
910 mb();
911 pAd->mlme_kill = 1;
912 //RT28XX_MLME_HANDLER(pAd);
913 mb();
914 ret = KILL_THREAD_PID(pObj->MLMEThr_pid, SIGTERM, 1);
915 if (ret)
916 {
917 printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
918 pAd->net_dev->name, GET_PID_NUMBER(pObj->MLMEThr_pid), ret);
919 }
920 else
921 {
922 //wait_for_completion (&pAd->notify);
923 wait_for_completion (&pAd->mlmeComplete);
924 pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
925 }
926 }
927
928 CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)
929 {
930 printk("Terminate the RTUSBCmdThr_pid=%d!\n", GET_PID_NUMBER(pObj->RTUSBCmdThr_pid));
931 mb();
932 NdisAcquireSpinLock(&pAd->CmdQLock);
933 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
934 NdisReleaseSpinLock(&pAd->CmdQLock);
935 mb();
936 //RTUSBCMDUp(pAd);
937 ret = KILL_THREAD_PID(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
938 if (ret)
939 {
940 printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
941 pAd->net_dev->name, GET_PID_NUMBER(pObj->RTUSBCmdThr_pid), ret);
942 }
943 else
944 {
945 //wait_for_completion (&pAd->notify);
946 wait_for_completion (&pAd->CmdQComplete);
947 pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
948 }
949 }
950 #endif
951 #ifdef RT30xx
952 if (pObj->MLMEThr_pid)
953 {
954 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
955 mb();
956 pAd->mlme_kill = 1;
957 //RT28XX_MLME_HANDLER(pAd);
958 mb();
959 ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
960 if (ret)
961 {
962 printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
963 pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret);
964 }
965 else
966 {
967 //wait_for_completion (&pAd->notify);
968 wait_for_completion (&pAd->mlmeComplete);
969 pObj->MLMEThr_pid = NULL;
970 }
971 }
972
973 if (pObj->RTUSBCmdThr_pid >= 0)
974 {
975 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid));
976 mb();
977 NdisAcquireSpinLock(&pAd->CmdQLock);
978 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
979 NdisReleaseSpinLock(&pAd->CmdQLock);
980 mb();
981 //RTUSBCMDUp(pAd);
982 ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
983 if (ret)
984 {
985 printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
986 pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret);
987 }
988 else
989 {
990 //wait_for_completion (&pAd->notify);
991 wait_for_completion (&pAd->CmdQComplete);
992 pObj->RTUSBCmdThr_pid = NULL;
993 }
994 }
995 if (pObj->TimerQThr_pid >= 0)
996 {
997 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
998 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid));
999 mb();
1000 pAd->TimerFunc_kill = 1;
1001 mb();
1002 ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
1003 if (ret)
1004 {
1005 printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
1006 pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret);
1007 }
1008 else
1009 {
1010 printk("wait_for_completion TimerQThr\n");
1011 wait_for_completion(&pAd->TimerQComplete);
1012 pObj->TimerQThr_pid = NULL;
1013 }
1014 }
1015 #endif
1016
1017 // Kill tasklets
1018 pAd->mlme_kill = 0;
1019 pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1020 pAd->TimerFunc_kill = 0;
1021 }
1022
1023
1024 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1025 {
1026 POS_COOKIE pObj;
1027
1028 pObj = (POS_COOKIE) pAd->OS_Cookie;
1029
1030 tasklet_kill(&pObj->rx_done_task);
1031 tasklet_kill(&pObj->mgmt_dma_done_task);
1032 tasklet_kill(&pObj->ac0_dma_done_task);
1033 tasklet_kill(&pObj->ac1_dma_done_task);
1034 tasklet_kill(&pObj->ac2_dma_done_task);
1035 tasklet_kill(&pObj->ac3_dma_done_task);
1036 tasklet_kill(&pObj->hcca_dma_done_task);
1037 tasklet_kill(&pObj->tbtt_task);
1038
1039 }
1040
1041
1042 /*
1043 ========================================================================
1044 Routine Description:
1045 Check the chipset vendor/product ID.
1046
1047 Arguments:
1048 _dev_p Point to the PCI or USB device
1049
1050 Return Value:
1051 TRUE Check ok
1052 FALSE Check fail
1053
1054 Note:
1055 ========================================================================
1056 */
1057 BOOLEAN RT28XXChipsetCheck(
1058 IN void *_dev_p)
1059 {
1060 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1061 struct usb_device *dev_p = interface_to_usbdev(intf);
1062 UINT32 i;
1063
1064
1065 for(i=0; i<rtusb_usb_id_len; i++)
1066 {
1067 if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1068 dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1069 {
1070 #ifndef RT30xx
1071 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1072 #endif
1073 #ifdef RT30xx
1074 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1075 #endif
1076 dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1077 break;
1078 }
1079 }
1080
1081 if (i == rtusb_usb_id_len)
1082 {
1083 printk("rt2870: Error! Device Descriptor not matching!\n");
1084 return FALSE;
1085 }
1086
1087 return TRUE;
1088 }
1089
1090
1091 /*
1092 ========================================================================
1093 Routine Description:
1094 Init net device structure.
1095
1096 Arguments:
1097 _dev_p Point to the PCI or USB device
1098 *net_dev Point to the net device
1099 *pAd the raxx interface data pointer
1100
1101 Return Value:
1102 TRUE Init ok
1103 FALSE Init fail
1104
1105 Note:
1106 ========================================================================
1107 */
1108 BOOLEAN RT28XXNetDevInit(
1109 IN void *_dev_p,
1110 IN struct net_device *net_dev,
1111 IN RTMP_ADAPTER *pAd)
1112 {
1113 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1114 struct usb_device *dev_p = interface_to_usbdev(intf);
1115
1116
1117 pAd->config = &dev_p->config->desc;
1118 return TRUE;
1119 }
1120
1121
1122 /*
1123 ========================================================================
1124 Routine Description:
1125 Init net device structure.
1126
1127 Arguments:
1128 _dev_p Point to the PCI or USB device
1129 *pAd the raxx interface data pointer
1130
1131 Return Value:
1132 TRUE Config ok
1133 FALSE Config fail
1134
1135 Note:
1136 ========================================================================
1137 */
1138 BOOLEAN RT28XXProbePostConfig(
1139 IN void *_dev_p,
1140 IN RTMP_ADAPTER *pAd,
1141 IN INT32 interface)
1142 {
1143 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1144 struct usb_host_interface *iface_desc;
1145 ULONG BulkOutIdx;
1146 UINT32 i;
1147
1148
1149 /* get the active interface descriptor */
1150 iface_desc = intf->cur_altsetting;
1151
1152 /* get # of enpoints */
1153 pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1154 DBGPRINT(RT_DEBUG_TRACE,
1155 ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1156
1157 /* Configure Pipes */
1158 BulkOutIdx = 0;
1159
1160 for(i=0; i<pAd->NumberOfPipes; i++)
1161 {
1162 if ((iface_desc->endpoint[i].desc.bmAttributes ==
1163 USB_ENDPOINT_XFER_BULK) &&
1164 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1165 USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1166 {
1167 pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1168 pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1169
1170 DBGPRINT_RAW(RT_DEBUG_TRACE,
1171 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1172 DBGPRINT_RAW(RT_DEBUG_TRACE,
1173 ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1174 }
1175 else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1176 USB_ENDPOINT_XFER_BULK) &&
1177 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1178 USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1179 {
1180 // there are 6 bulk out EP. EP6 highest priority.
1181 // EP1-4 is EDCA. EP5 is HCCA.
1182 pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1183 pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1184
1185 DBGPRINT_RAW(RT_DEBUG_TRACE,
1186 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1187 DBGPRINT_RAW(RT_DEBUG_TRACE,
1188 ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1189 }
1190 }
1191
1192 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1193 {
1194 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
1195 return FALSE;
1196 }
1197
1198 return TRUE;
1199 }
1200
1201
1202 /*
1203 ========================================================================
1204 Routine Description:
1205 Disable DMA.
1206
1207 Arguments:
1208 *pAd the raxx interface data pointer
1209
1210 Return Value:
1211 None
1212
1213 Note:
1214 ========================================================================
1215 */
1216 VOID RT28XXDMADisable(
1217 IN RTMP_ADAPTER *pAd)
1218 {
1219 // no use
1220 }
1221
1222
1223
1224 /*
1225 ========================================================================
1226 Routine Description:
1227 Enable DMA.
1228
1229 Arguments:
1230 *pAd the raxx interface data pointer
1231
1232 Return Value:
1233 None
1234
1235 Note:
1236 ========================================================================
1237 */
1238 VOID RT28XXDMAEnable(
1239 IN RTMP_ADAPTER *pAd)
1240 {
1241 WPDMA_GLO_CFG_STRUC GloCfg;
1242 USB_DMA_CFG_STRUC UsbCfg;
1243 int i = 0;
1244
1245
1246 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1247 do
1248 {
1249 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1250 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1251 break;
1252
1253 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
1254 RTMPusecDelay(1000);
1255 i++;
1256 }while ( i <200);
1257
1258
1259 RTMPusecDelay(50);
1260 GloCfg.field.EnTXWriteBackDDONE = 1;
1261 GloCfg.field.EnableRxDMA = 1;
1262 GloCfg.field.EnableTxDMA = 1;
1263 DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1264 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1265
1266 UsbCfg.word = 0;
1267 UsbCfg.field.phyclear = 0;
1268 /* usb version is 1.1,do not use bulk in aggregation */
1269 if (pAd->BulkInMaxPacketSize == 512)
1270 UsbCfg.field.RxBulkAggEn = 1;
1271 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1272 UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1273 UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1274 UsbCfg.field.RxBulkEn = 1;
1275 UsbCfg.field.TxBulkEn = 1;
1276
1277 RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1278
1279 }
1280
1281 /*
1282 ========================================================================
1283 Routine Description:
1284 Write Beacon buffer to Asic.
1285
1286 Arguments:
1287 *pAd the raxx interface data pointer
1288
1289 Return Value:
1290 None
1291
1292 Note:
1293 ========================================================================
1294 */
1295 VOID RT28xx_UpdateBeaconToAsic(
1296 IN RTMP_ADAPTER *pAd,
1297 IN INT apidx,
1298 IN ULONG FrameLen,
1299 IN ULONG UpdatePos)
1300 {
1301 PUCHAR pBeaconFrame = NULL;
1302 UCHAR *ptr;
1303 UINT i, padding;
1304 BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1305 UINT32 longValue;
1306 BOOLEAN bBcnReq = FALSE;
1307 UCHAR bcn_idx = 0;
1308
1309
1310 if (pBeaconFrame == NULL)
1311 {
1312 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1313 return;
1314 }
1315
1316 if (pBeaconSync == NULL)
1317 {
1318 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1319 return;
1320 }
1321
1322 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1323 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1324 // )
1325 if (bBcnReq == FALSE)
1326 {
1327 /* when the ra interface is down, do not send its beacon frame */
1328 /* clear all zero */
1329 for(i=0; i<TXWI_SIZE; i+=4) {
1330 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1331 }
1332 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1333 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1334 }
1335 else
1336 {
1337 ptr = (PUCHAR)&pAd->BeaconTxWI;
1338
1339 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1340 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1341 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1342 NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1343 }
1344
1345 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1346 {
1347 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
1348 {
1349 longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1350 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1351 ptr += 4;
1352 }
1353 }
1354
1355 ptr = pBeaconSync->BeaconBuf[bcn_idx];
1356 padding = (FrameLen & 0x01);
1357 NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1358 FrameLen += padding;
1359 for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1360 {
1361 if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1362 {
1363 NdisMoveMemory(ptr, pBeaconFrame, 2);
1364 //shortValue = *ptr + (*(ptr+1)<<8);
1365 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1366 RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1367 }
1368 ptr +=2;
1369 pBeaconFrame += 2;
1370 }
1371
1372 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1373
1374 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1375 }
1376
1377 }
1378
1379
1380 VOID RT2870_BssBeaconStop(
1381 IN RTMP_ADAPTER *pAd)
1382 {
1383 BEACON_SYNC_STRUCT *pBeaconSync;
1384 int i, offset;
1385 BOOLEAN Cancelled = TRUE;
1386
1387 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1388 if (pBeaconSync && pBeaconSync->EnableBeacon)
1389 {
1390 INT NumOfBcn;
1391
1392 NumOfBcn = MAX_MESH_NUM;
1393
1394 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1395
1396 for(i=0; i<NumOfBcn; i++)
1397 {
1398 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1399 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1400
1401 for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1402 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1403
1404 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1405 pBeaconSync->TimIELocationInBeacon[i] = 0;
1406 }
1407 pBeaconSync->BeaconBitMap = 0;
1408 pBeaconSync->DtimBitOn = 0;
1409 }
1410 }
1411
1412
1413 VOID RT2870_BssBeaconStart(
1414 IN RTMP_ADAPTER *pAd)
1415 {
1416 int apidx;
1417 BEACON_SYNC_STRUCT *pBeaconSync;
1418 // LARGE_INTEGER tsfTime, deltaTime;
1419
1420 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1421 if (pBeaconSync && pBeaconSync->EnableBeacon)
1422 {
1423 INT NumOfBcn;
1424
1425 NumOfBcn = MAX_MESH_NUM;
1426
1427 for(apidx=0; apidx<NumOfBcn; apidx++)
1428 {
1429 UCHAR CapabilityInfoLocationInBeacon = 0;
1430 UCHAR TimIELocationInBeacon = 0;
1431
1432 NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1433 pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1434 pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1435 NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1436 }
1437 pBeaconSync->BeaconBitMap = 0;
1438 pBeaconSync->DtimBitOn = 0;
1439 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1440
1441 pAd->CommonCfg.BeaconAdjust = 0;
1442 pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1443 pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1444 printk("RT2870_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1445 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1446
1447 }
1448 }
1449
1450
1451 VOID RT2870_BssBeaconInit(
1452 IN RTMP_ADAPTER *pAd)
1453 {
1454 BEACON_SYNC_STRUCT *pBeaconSync;
1455 int i;
1456
1457 NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1458 if (pAd->CommonCfg.pBeaconSync)
1459 {
1460 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1461 NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1462 for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1463 {
1464 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1465 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1466 pBeaconSync->TimIELocationInBeacon[i] = 0;
1467 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1468 }
1469 pBeaconSync->BeaconBitMap = 0;
1470
1471 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1472 pBeaconSync->EnableBeacon = TRUE;
1473 }
1474 }
1475
1476
1477 VOID RT2870_BssBeaconExit(
1478 IN RTMP_ADAPTER *pAd)
1479 {
1480 BEACON_SYNC_STRUCT *pBeaconSync;
1481 BOOLEAN Cancelled = TRUE;
1482 int i;
1483
1484 if (pAd->CommonCfg.pBeaconSync)
1485 {
1486 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1487 pBeaconSync->EnableBeacon = FALSE;
1488 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1489 pBeaconSync->BeaconBitMap = 0;
1490
1491 for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1492 {
1493 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1494 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1495 pBeaconSync->TimIELocationInBeacon[i] = 0;
1496 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1497 }
1498
1499 NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1500 pAd->CommonCfg.pBeaconSync = NULL;
1501 }
1502 }
1503
1504 VOID BeaconUpdateExec(
1505 IN PVOID SystemSpecific1,
1506 IN PVOID FunctionContext,
1507 IN PVOID SystemSpecific2,
1508 IN PVOID SystemSpecific3)
1509 {
1510 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
1511 LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1512 UINT32 delta, remain, remain_low, remain_high;
1513 // BOOLEAN positive;
1514
1515 ReSyncBeaconTime(pAd);
1516
1517
1518
1519 RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1520 RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1521
1522
1523 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1524 remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1525 remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1526 remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1527 delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1528
1529 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;
1530
1531 }
1532
1533
|
This page was automatically generated by the
LXR engine.
|