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("RT2870 Wireless Lan Linux Driver");
49 #ifdef CONFIG_STA_SUPPORT
50 MODULE_LICENSE("GPL");
52 MODULE_VERSION(STA_DRIVER_VERSION);
54 #endif // CONFIG_STA_SUPPORT //
56 #ifdef MULTIPLE_CARD_SUPPORT
57 // record whether the card in the card list is used in the card file
58 extern UINT8 MC_CardUsed[];
59 #endif // MULTIPLE_CARD_SUPPORT //
61 /* Kernel thread and vars, which handles packets that are completed. Only
62 * packets that have a "complete" function are sent here. This way, the
63 * completion is run out of kernel context, and doesn't block the rest of
65 //static int mlme_kill = 0; // Mlme kernel thread
66 //static int RTUSBCmd_kill = 0; // Command kernel thread
67 //static int TimerFunc_kill = 0; // TimerQ kernel thread
69 //static wait_queue_head_t timerWaitQ;
70 //static wait_queue_t waitQ;
72 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
73 IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
77 struct usb_device_id rtusb_usb_id[] = RT2870_USB_DEVICES;
78 INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
79 MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
86 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
88 /**************************************************************************/
89 /**************************************************************************/
90 //tested for kernel 2.4 series
91 /**************************************************************************/
92 /**************************************************************************/
93 static void *rtusb_probe(struct usb_device *dev, UINT interface,
94 const struct usb_device_id *id_table);
95 static void rtusb_disconnect(struct usb_device *dev, void *ptr);
97 struct usb_driver rtusb_driver = {
100 disconnect:rtusb_disconnect,
101 id_table:rtusb_usb_id,
107 static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
108 static int rt2870_resume(struct usb_interface *intf);
109 #endif // CONFIG_PM //
111 /**************************************************************************/
112 /**************************************************************************/
113 //tested for kernel 2.6series
114 /**************************************************************************/
115 /**************************************************************************/
116 static int rtusb_probe (struct usb_interface *intf,
117 const struct usb_device_id *id);
118 static void rtusb_disconnect(struct usb_interface *intf);
120 struct usb_driver rtusb_driver = {
121 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
122 .owner = THIS_MODULE,
126 .disconnect=rtusb_disconnect,
127 .id_table=rtusb_usb_id,
130 suspend: rt2870_suspend,
131 resume: rt2870_resume,
137 VOID RT2860RejectPendingPackets(
138 IN PRTMP_ADAPTER pAd)
141 // clear TxSw packets
144 static int rt2870_suspend(
145 struct usb_interface *intf,
148 struct net_device *net_dev;
149 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
152 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
153 net_dev = pAd->net_dev;
154 netif_device_detach(net_dev);
156 pAd->PM_FlgSuspend = 1;
157 if (netif_running(net_dev)) {
158 RTUSBCancelPendingBulkInIRP(pAd);
159 RTUSBCancelPendingBulkOutIRP(pAd);
161 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
165 static int rt2870_resume(
166 struct usb_interface *intf)
168 struct net_device *net_dev;
169 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
172 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
174 pAd->PM_FlgSuspend = 0;
175 net_dev = pAd->net_dev;
176 netif_device_attach(net_dev);
177 netif_start_queue(net_dev);
178 netif_carrier_on(net_dev);
179 netif_wake_queue(net_dev);
181 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
184 #endif // CONFIG_PM //
185 #endif // LINUX_VERSION_CODE //
188 // Init driver module
189 INT __init rtusb_init(void)
191 printk("rtusb init --->\n");
192 return usb_register(&rtusb_driver);
195 // Deinit driver module
196 VOID __exit rtusb_exit(void)
198 usb_deregister(&rtusb_driver);
199 printk("<--- rtusb exit\n");
202 module_init(rtusb_init);
203 module_exit(rtusb_exit);
208 /*--------------------------------------------------------------------- */
209 /* function declarations */
210 /*--------------------------------------------------------------------- */
213 ========================================================================
218 *Context the pAd, driver control block pointer
224 ========================================================================
229 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
233 pObj = (POS_COOKIE)pAd->OS_Cookie;
235 rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
237 while (pAd->mlme_kill == 0)
239 /* lock the device pointers */
240 //down(&(pAd->mlme_semaphore));
241 status = down_interruptible(&(pAd->mlme_semaphore));
243 /* lock the device pointers , need to check if required*/
244 //down(&(pAd->usbdev_semaphore));
246 if (!pAd->PM_FlgSuspend)
249 /* unlock the device pointers */
250 //up(&(pAd->usbdev_semaphore));
253 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
258 /* notify the exit routine that we're actually exiting now
260 * complete()/wait_for_completion() is similar to up()/down(),
261 * except that complete() is safe in the case where the structure
262 * is getting deleted in a parallel mode of execution (i.e. just
263 * after the down() -- that's necessary for the thread-shutdown
266 * complete_and_exit() goes even further than this -- it is safe in
267 * the case that the thread of the caller is going away (not just
268 * the structure) -- this is necessary for the module-remove case.
269 * This is important in preemption kernels, which transfer the flow
270 * of execution immediately upon a complete().
272 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
274 pObj->MLMEThr_pid = NULL;
276 complete_and_exit (&pAd->mlmeComplete, 0);
283 ========================================================================
285 USB command kernel thread.
288 *Context the pAd, driver control block pointer
294 ========================================================================
299 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
303 pObj = (POS_COOKIE)pAd->OS_Cookie;
305 rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
307 NdisAcquireSpinLock(&pAd->CmdQLock);
308 pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
309 NdisReleaseSpinLock(&pAd->CmdQLock);
311 while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
313 /* lock the device pointers */
314 //down(&(pAd->RTUSBCmd_semaphore));
315 status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
317 if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
322 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
325 /* lock the device pointers , need to check if required*/
326 //down(&(pAd->usbdev_semaphore));
328 if (!pAd->PM_FlgSuspend)
331 /* unlock the device pointers */
332 //up(&(pAd->usbdev_semaphore));
335 if (!pAd->PM_FlgSuspend)
336 { // Clear the CmdQElements.
337 CmdQElmt *pCmdQElmt = NULL;
339 NdisAcquireSpinLock(&pAd->CmdQLock);
340 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
341 while(pAd->CmdQ.size)
343 RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
346 if (pCmdQElmt->CmdFromNdis == TRUE)
348 if (pCmdQElmt->buffer != NULL)
349 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
351 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
355 if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
356 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
358 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
364 NdisReleaseSpinLock(&pAd->CmdQLock);
366 /* notify the exit routine that we're actually exiting now
368 * complete()/wait_for_completion() is similar to up()/down(),
369 * except that complete() is safe in the case where the structure
370 * is getting deleted in a parallel mode of execution (i.e. just
371 * after the down() -- that's necessary for the thread-shutdown
374 * complete_and_exit() goes even further than this -- it is safe in
375 * the case that the thread of the caller is going away (not just
376 * the structure) -- this is necessary for the module-remove case.
377 * This is important in preemption kernels, which transfer the flow
378 * of execution immediately upon a complete().
380 DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
382 pObj->RTUSBCmdThr_pid = NULL;
384 complete_and_exit (&pAd->CmdQComplete, 0);
390 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
393 RALINK_TIMER_STRUCT *pTimer;
394 RT2870_TIMER_ENTRY *pEntry;
395 unsigned long irqFlag;
397 while(!pAd->TimerFunc_kill)
399 // printk("waiting for event!\n");
402 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
404 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
408 while(pAd->TimerQ.pQHead)
410 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
411 pEntry = pAd->TimerQ.pQHead;
414 pTimer = pEntry->pRaTimer;
417 pAd->TimerQ.pQHead = pEntry->pNext;
418 if (pEntry == pAd->TimerQ.pQTail)
419 pAd->TimerQ.pQTail = NULL;
421 // return this queue entry to timerQFreeList.
422 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
423 pAd->TimerQ.pQPollFreeList = pEntry;
425 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
429 if (pTimer->handle != NULL)
430 if (!pAd->PM_FlgSuspend)
431 pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
432 if ((pTimer->Repeat) && (pTimer->State == FALSE))
433 RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
439 pAd->TimerQ.status = RT2870_THREAD_STOPED;
440 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
448 IN OUT PVOID Context)
453 pAd = (PRTMP_ADAPTER)Context;
454 pObj = (POS_COOKIE) pAd->OS_Cookie;
456 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
458 RT2870_TimerQ_Handle(pAd);
460 /* notify the exit routine that we're actually exiting now
462 * complete()/wait_for_completion() is similar to up()/down(),
463 * except that complete() is safe in the case where the structure
464 * is getting deleted in a parallel mode of execution (i.e. just
465 * after the down() -- that's necessary for the thread-shutdown
468 * complete_and_exit() goes even further than this -- it is safe in
469 * the case that the thread of the caller is going away (not just
470 * the structure) -- this is necessary for the module-remove case.
471 * This is important in preemption kernels, which transfer the flow
472 * of execution immediately upon a complete().
474 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
476 pObj->TimerQThr_pid = NULL;
478 complete_and_exit(&pAd->TimerQComplete, 0);
484 RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
485 IN RTMP_ADAPTER *pAd,
486 IN RALINK_TIMER_STRUCT *pTimer)
488 RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
489 unsigned long irqFlags;
492 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
493 if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
495 if(pAd->TimerQ.pQPollFreeList)
497 pQNode = pAd->TimerQ.pQPollFreeList;
498 pAd->TimerQ.pQPollFreeList = pQNode->pNext;
500 pQNode->pRaTimer = pTimer;
501 pQNode->pNext = NULL;
503 pQTail = pAd->TimerQ.pQTail;
504 if (pAd->TimerQ.pQTail != NULL)
505 pQTail->pNext = pQNode;
506 pAd->TimerQ.pQTail = pQNode;
507 if (pAd->TimerQ.pQHead == NULL)
508 pAd->TimerQ.pQHead = pQNode;
510 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
513 up(&pAd->RTUSBTimer_semaphore);
514 //wake_up(&timerWaitQ);
518 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
524 BOOLEAN RT2870_TimerQ_Remove(
525 IN RTMP_ADAPTER *pAd,
526 IN RALINK_TIMER_STRUCT *pTimer)
528 RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
529 unsigned long irqFlags;
531 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
532 if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
534 pNode = pAd->TimerQ.pQHead;
537 if (pNode->pRaTimer == pTimer)
540 pNode = pNode->pNext;
543 // Now move it to freeList queue.
546 if (pNode == pAd->TimerQ.pQHead)
547 pAd->TimerQ.pQHead = pNode->pNext;
548 if (pNode == pAd->TimerQ.pQTail)
549 pAd->TimerQ.pQTail = pPrev;
551 pPrev->pNext = pNode->pNext;
553 // return this queue entry to timerQFreeList.
554 pNode->pNext = pAd->TimerQ.pQPollFreeList;
555 pAd->TimerQ.pQPollFreeList = pNode;
558 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
564 void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
566 RT2870_TIMER_ENTRY *pTimerQ;
567 unsigned long irqFlags;
569 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
570 while (pAd->TimerQ.pQHead)
572 pTimerQ = pAd->TimerQ.pQHead;
573 pAd->TimerQ.pQHead = pTimerQ->pNext;
576 pAd->TimerQ.pQPollFreeList = NULL;
577 os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
578 pAd->TimerQ.pQTail = NULL;
579 pAd->TimerQ.pQHead = NULL;
580 pAd->TimerQ.status = RT2870_THREAD_STOPED;
581 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
586 void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
589 RT2870_TIMER_ENTRY *pQNode, *pEntry;
590 unsigned long irqFlags;
592 NdisAllocateSpinLock(&pAd->TimerQLock);
594 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
595 NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
596 //InterlockedExchange(&pAd->TimerQ.count, 0);
598 /* Initialise the wait q head */
599 //init_waitqueue_head(&timerWaitQ);
601 os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
602 if (pAd->TimerQ.pTimerQPoll)
605 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
606 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
608 pQNode->pNext = pEntry;
612 pAd->TimerQ.pQPollFreeList = pEntry;
613 pAd->TimerQ.pQHead = NULL;
614 pAd->TimerQ.pQTail = NULL;
615 pAd->TimerQ.status = RT2870_THREAD_INITED;
617 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
621 VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
623 PHT_TX_CONTEXT pHTTXContext;
627 BOOLEAN needDumpSeq = FALSE;
632 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
633 if ((MACValue & 0xff) !=0 )
635 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
636 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
637 while((MACValue &0xff) != 0 && (idx++ < 10))
639 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
642 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
645 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
646 #ifdef CONFIG_STA_SUPPORT
647 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
650 if ((MACValue & 0xff00) !=0 )
652 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
653 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
654 while((MACValue &0xff00) != 0 && (idx++ < 10))
656 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
659 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
662 #endif // CONFIG_STA_SUPPORT //
664 if (pAd->watchDogRxOverFlowCnt >= 2)
666 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
667 if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
668 fRTMP_ADAPTER_BULKIN_RESET |
669 fRTMP_ADAPTER_HALT_IN_PROGRESS |
670 fRTMP_ADAPTER_NIC_NOT_EXIST))))
672 DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
673 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
674 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
677 pAd->watchDogRxOverFlowCnt = 0;
681 for (idx = 0; idx < NUM_OF_TX_RING; idx++)
685 RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
686 if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
688 pAd->watchDogTxPendingCnt[idx]++;
690 if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
691 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
694 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
695 pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
696 if (pHTTXContext->IRPPending)
697 { // Check TxContext.
698 pUrb = pHTTXContext->pUrb;
700 else if (idx == MGMTPIPEIDX)
702 PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
705 pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
706 pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
707 pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
709 if (pMLMEContext->IRPPending)
711 ASSERT(pMLMEContext->IRPPending);
712 pUrb = pMLMEContext->pUrb;
714 else if (pNULLContext->IRPPending)
716 ASSERT(pNULLContext->IRPPending);
717 pUrb = pNULLContext->pUrb;
719 else if (pPsPollContext->IRPPending)
721 ASSERT(pPsPollContext->IRPPending);
722 pUrb = pPsPollContext->pUrb;
726 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
728 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
731 DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
733 RTUSB_UNLINK_URB(pUrb);
734 // Sleep 200 microseconds to give cancellation time to work
740 DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
745 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
750 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
754 #ifdef DOT11_N_SUPPORT
755 // For Sigma debug, dump the ba_reordering sequence.
756 if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
759 PBA_REC_ENTRY pBAEntry = NULL;
761 struct reordering_mpdu *mpdu_blk;
763 Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
765 pBAEntry = &pAd->BATable.BARecEntry[Idx];
766 if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
768 DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
769 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
770 mpdu_blk = pBAEntry->list.next;
773 DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
774 mpdu_blk = mpdu_blk->next;
778 DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
779 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
782 #endif // DOT11_N_SUPPORT //
786 ========================================================================
788 Release allocated resources.
791 *dev Point to the PCI or USB device
792 pAd driver control block pointer
798 ========================================================================
800 static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
802 struct net_device *net_dev = NULL;
805 DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
806 dev->bus->bus_name, dev->devpath));
809 #ifdef MULTIPLE_CARD_SUPPORT
810 if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))
811 MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address
812 #endif // MULTIPLE_CARD_SUPPORT //
814 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
815 while(MOD_IN_USE > 0)
821 #endif // LINUX_VERSION_CODE //
823 printk("rtusb_disconnect: pAd == NULL!\n");
826 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
830 // for debug, wait to show some messages to /proc system
836 net_dev = pAd->net_dev;
837 if (pAd->net_dev != NULL)
839 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
840 unregister_netdev (pAd->net_dev);
843 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
845 flush_scheduled_work();
846 #endif // LINUX_VERSION_CODE //
849 // free net_device memory
850 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
853 free_netdev(net_dev);
854 #endif // LINUX_VERSION_CODE //
856 // free adapter memory
857 RTMPFreeAdapter(pAd);
859 // release a use of the usb device structure
860 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
861 while(MOD_IN_USE > 0)
867 #endif // LINUX_VERSION_CODE //
870 DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
875 ========================================================================
877 Probe RT28XX chipset.
880 *dev Point to the PCI or USB device
882 *id_table Point to the PCI or USB device ID
888 ========================================================================
890 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
891 static void *rtusb_probe(struct usb_device *dev, UINT interface,
892 const struct usb_device_id *id)
895 rt28xx_probe((void *)dev, (void *)id, interface, &pAd);
899 //Disconnect function is called within exit routine
900 static void rtusb_disconnect(struct usb_device *dev, void *ptr)
902 _rtusb_disconnect(dev, ((PRTMP_ADAPTER)ptr));
905 #else /* kernel 2.6 series */
906 static int rtusb_probe (struct usb_interface *intf,
907 const struct usb_device_id *id)
910 return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
914 static void rtusb_disconnect(struct usb_interface *intf)
916 struct usb_device *dev = interface_to_usbdev(intf);
920 pAd = usb_get_intfdata(intf);
921 usb_set_intfdata(intf, NULL);
923 _rtusb_disconnect(dev, pAd);
925 #endif // LINUX_VERSION_CODE //
929 ========================================================================
931 Close kernel threads.
934 *pAd the raxx interface data pointer
940 ========================================================================
942 VOID RT28xxThreadTerminate(
943 IN RTMP_ADAPTER *pAd)
945 POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
949 // Sleep 50 milliseconds so pending io might finish normally
950 RTMPusecDelay(50000);
952 // We want to wait until all pending receives and sends to the
953 // device object. We cancel any
954 // irps. Wait until sends and receives have stopped.
955 RTUSBCancelPendingIRPs(pAd);
958 if (pObj->MLMEThr_pid)
960 printk("Terminate the MLMEThr_pid=%d!\n", pid_nr(pObj->MLMEThr_pid));
963 //RT28XX_MLME_HANDLER(pAd);
965 ret = kill_pid(pObj->MLMEThr_pid, SIGTERM, 1);
968 printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
969 pAd->net_dev->name, pid_nr(pObj->MLMEThr_pid), ret);
973 //wait_for_completion (&pAd->notify);
974 wait_for_completion (&pAd->mlmeComplete);
975 pObj->MLMEThr_pid = NULL;
979 if (pObj->RTUSBCmdThr_pid >= 0)
981 printk("Terminate the RTUSBCmdThr_pid=%d!\n", pid_nr(pObj->RTUSBCmdThr_pid));
983 NdisAcquireSpinLock(&pAd->CmdQLock);
984 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
985 NdisReleaseSpinLock(&pAd->CmdQLock);
988 ret = kill_pid(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
991 printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
992 pAd->net_dev->name, pid_nr(pObj->RTUSBCmdThr_pid), ret);
996 //wait_for_completion (&pAd->notify);
997 wait_for_completion (&pAd->CmdQComplete);
998 pObj->RTUSBCmdThr_pid = NULL;
1001 if (pObj->TimerQThr_pid >= 0)
1003 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
1005 printk("Terminate the TimerQThr_pid=%d!\n", pid_nr(pObj->TimerQThr_pid));
1007 pAd->TimerFunc_kill = 1;
1009 ret = kill_pid(pObj->TimerQThr_pid, SIGTERM, 1);
1012 printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
1013 pAd->net_dev->name, pid_nr(pObj->TimerQThr_pid), ret);
1017 printk("wait_for_completion TimerQThr\n");
1018 wait_for_completion(&pAd->TimerQComplete);
1019 pObj->TimerQThr_pid = NULL;
1024 pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
1025 pAd->TimerFunc_kill = 0;
1029 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1033 pObj = (POS_COOKIE) pAd->OS_Cookie;
1035 tasklet_kill(&pObj->rx_done_task);
1036 tasklet_kill(&pObj->mgmt_dma_done_task);
1037 tasklet_kill(&pObj->ac0_dma_done_task);
1038 tasklet_kill(&pObj->ac1_dma_done_task);
1039 tasklet_kill(&pObj->ac2_dma_done_task);
1040 tasklet_kill(&pObj->ac3_dma_done_task);
1041 tasklet_kill(&pObj->hcca_dma_done_task);
1042 tasklet_kill(&pObj->tbtt_task);
1048 ========================================================================
1049 Routine Description:
1050 Check the chipset vendor/product ID.
1053 _dev_p Point to the PCI or USB device
1060 ========================================================================
1062 BOOLEAN RT28XXChipsetCheck(
1065 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1066 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1068 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1069 struct usb_device *dev_p = interface_to_usbdev(intf);
1070 #endif // LINUX_VERSION_CODE //
1074 for(i=0; i<rtusb_usb_id_len; i++)
1076 if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1077 dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1079 printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1080 dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1085 if (i == rtusb_usb_id_len)
1087 printk("rt2870: Error! Device Descriptor not matching!\n");
1096 ========================================================================
1097 Routine Description:
1098 Init net device structure.
1101 _dev_p Point to the PCI or USB device
1102 *net_dev Point to the net device
1103 *pAd the raxx interface data pointer
1110 ========================================================================
1112 BOOLEAN RT28XXNetDevInit(
1114 IN struct net_device *net_dev,
1115 IN RTMP_ADAPTER *pAd)
1117 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1118 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1120 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1121 struct usb_device *dev_p = interface_to_usbdev(intf);
1122 #endif // LINUX_VERSION_CODE //
1125 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1126 pAd->config = dev_p->config;
1128 pAd->config = &dev_p->config->desc;
1129 #endif // LINUX_VERSION_CODE //
1135 ========================================================================
1136 Routine Description:
1137 Init net device structure.
1140 _dev_p Point to the PCI or USB device
1141 *pAd the raxx interface data pointer
1148 ========================================================================
1150 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1151 BOOLEAN RT28XXProbePostConfig(
1153 IN RTMP_ADAPTER *pAd,
1156 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1157 struct usb_interface *intf;
1158 struct usb_interface_descriptor *iface_desc;
1159 struct usb_endpoint_descriptor *endpoint;
1164 /* get the active interface descriptor */
1165 intf = &dev_p->actconfig->interface[interface];
1166 iface_desc = &intf->altsetting[0];
1168 /* get # of enpoints */
1169 pAd->NumberOfPipes = iface_desc->bNumEndpoints;
1170 DBGPRINT(RT_DEBUG_TRACE, ("NumEndpoints=%d\n", iface_desc->bNumEndpoints));
1172 /* Configure Pipes */
1173 endpoint = &iface_desc->endpoint[0];
1176 for(i=0; i<pAd->NumberOfPipes; i++)
1178 if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
1179 ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1181 pAd->BulkInEpAddr = endpoint[i].bEndpointAddress;
1182 pAd->BulkInMaxPacketSize = endpoint[i].wMaxPacketSize;
1184 DBGPRINT_RAW(RT_DEBUG_TRACE,
1185 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1186 DBGPRINT_RAW(RT_DEBUG_TRACE,
1187 ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress));
1189 else if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
1190 ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1192 // There are 6 bulk out EP. EP6 highest priority.
1193 // EP1-4 is EDCA. EP5 is HCCA.
1194 pAd->BulkOutEpAddr[BulkOutIdx++] = endpoint[i].bEndpointAddress;
1195 pAd->BulkOutMaxPacketSize = endpoint[i].wMaxPacketSize;
1197 DBGPRINT_RAW(RT_DEBUG_TRACE,
1198 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1199 DBGPRINT_RAW(RT_DEBUG_TRACE,
1200 ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress));
1204 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1206 printk("Could not find both bulk-in and bulk-out endpoints\n");
1214 BOOLEAN RT28XXProbePostConfig(
1216 IN RTMP_ADAPTER *pAd,
1219 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1220 struct usb_host_interface *iface_desc;
1225 /* get the active interface descriptor */
1226 iface_desc = intf->cur_altsetting;
1228 /* get # of enpoints */
1229 pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1230 DBGPRINT(RT_DEBUG_TRACE,
1231 ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1233 /* Configure Pipes */
1236 for(i=0; i<pAd->NumberOfPipes; i++)
1238 if ((iface_desc->endpoint[i].desc.bmAttributes ==
1239 USB_ENDPOINT_XFER_BULK) &&
1240 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1241 USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1243 pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1244 pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1246 DBGPRINT_RAW(RT_DEBUG_TRACE,
1247 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1248 DBGPRINT_RAW(RT_DEBUG_TRACE,
1249 ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1251 else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1252 USB_ENDPOINT_XFER_BULK) &&
1253 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1254 USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1256 // there are 6 bulk out EP. EP6 highest priority.
1257 // EP1-4 is EDCA. EP5 is HCCA.
1258 pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1259 pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1261 DBGPRINT_RAW(RT_DEBUG_TRACE,
1262 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1263 DBGPRINT_RAW(RT_DEBUG_TRACE,
1264 ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1268 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1270 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __FUNCTION__);
1276 #endif // LINUX_VERSION_CODE //
1280 ========================================================================
1281 Routine Description:
1285 *pAd the raxx interface data pointer
1291 ========================================================================
1293 VOID RT28XXDMADisable(
1294 IN RTMP_ADAPTER *pAd)
1302 ========================================================================
1303 Routine Description:
1307 *pAd the raxx interface data pointer
1313 ========================================================================
1315 VOID RT28XXDMAEnable(
1316 IN RTMP_ADAPTER *pAd)
1318 WPDMA_GLO_CFG_STRUC GloCfg;
1319 USB_DMA_CFG_STRUC UsbCfg;
1323 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1326 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1327 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1330 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
1331 RTMPusecDelay(1000);
1337 GloCfg.field.EnTXWriteBackDDONE = 1;
1338 GloCfg.field.EnableRxDMA = 1;
1339 GloCfg.field.EnableTxDMA = 1;
1340 DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1341 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1344 UsbCfg.field.phyclear = 0;
1345 /* usb version is 1.1,do not use bulk in aggregation */
1346 if (pAd->BulkInMaxPacketSize == 512)
1347 UsbCfg.field.RxBulkAggEn = 1;
1348 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1349 UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1350 UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1351 UsbCfg.field.RxBulkEn = 1;
1352 UsbCfg.field.TxBulkEn = 1;
1354 RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1359 ========================================================================
1360 Routine Description:
1361 Write Beacon buffer to Asic.
1364 *pAd the raxx interface data pointer
1370 ========================================================================
1372 VOID RT28xx_UpdateBeaconToAsic(
1373 IN RTMP_ADAPTER *pAd,
1378 PUCHAR pBeaconFrame = NULL;
1381 BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1383 // USHORT shortValue;
1384 BOOLEAN bBcnReq = FALSE;
1388 if (pBeaconFrame == NULL)
1390 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1394 if (pBeaconSync == NULL)
1396 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1400 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1401 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1403 if (bBcnReq == FALSE)
1405 /* when the ra interface is down, do not send its beacon frame */
1406 /* clear all zero */
1407 for(i=0; i<TXWI_SIZE; i+=4) {
1408 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1410 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1411 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1415 ptr = (PUCHAR)&pAd->BeaconTxWI;
1416 #ifdef RT_BIG_ENDIAN
1417 RTMPWIEndianChange(ptr, TYPE_TXWI);
1419 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1420 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1421 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1422 NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1425 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1427 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
1429 longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1430 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1435 ptr = pBeaconSync->BeaconBuf[bcn_idx];
1436 padding = (FrameLen & 0x01);
1437 NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1438 FrameLen += padding;
1439 for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1441 if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1443 NdisMoveMemory(ptr, pBeaconFrame, 2);
1444 //shortValue = *ptr + (*(ptr+1)<<8);
1445 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1446 RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1452 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1454 // For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.
1460 VOID RT2870_BssBeaconStop(
1461 IN RTMP_ADAPTER *pAd)
1463 BEACON_SYNC_STRUCT *pBeaconSync;
1465 BOOLEAN Cancelled = TRUE;
1467 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1468 if (pBeaconSync && pBeaconSync->EnableBeacon)
1473 #ifdef CONFIG_STA_SUPPORT
1474 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1476 NumOfBcn = MAX_MESH_NUM;
1478 #endif // CONFIG_STA_SUPPORT //
1480 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1482 for(i=0; i<NumOfBcn; i++)
1484 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1485 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1487 for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1488 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1490 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1491 pBeaconSync->TimIELocationInBeacon[i] = 0;
1493 pBeaconSync->BeaconBitMap = 0;
1494 pBeaconSync->DtimBitOn = 0;
1499 VOID RT2870_BssBeaconStart(
1500 IN RTMP_ADAPTER *pAd)
1503 BEACON_SYNC_STRUCT *pBeaconSync;
1504 // LARGE_INTEGER tsfTime, deltaTime;
1506 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1507 if (pBeaconSync && pBeaconSync->EnableBeacon)
1512 #ifdef CONFIG_STA_SUPPORT
1513 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1515 NumOfBcn = MAX_MESH_NUM;
1517 #endif // CONFIG_STA_SUPPORT //
1519 for(apidx=0; apidx<NumOfBcn; apidx++)
1521 UCHAR CapabilityInfoLocationInBeacon = 0;
1522 UCHAR TimIELocationInBeacon = 0;
1524 #ifdef CONFIG_STA_SUPPORT
1525 #endif // CONFIG_STA_SUPPORT //
1527 NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1528 pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1529 pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1530 NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1532 pBeaconSync->BeaconBitMap = 0;
1533 pBeaconSync->DtimBitOn = 0;
1534 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1536 pAd->CommonCfg.BeaconAdjust = 0;
1537 pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1538 pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1539 printk("RT2870_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1540 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1546 VOID RT2870_BssBeaconInit(
1547 IN RTMP_ADAPTER *pAd)
1549 BEACON_SYNC_STRUCT *pBeaconSync;
1552 NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1553 if (pAd->CommonCfg.pBeaconSync)
1555 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1556 NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1557 for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1559 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1560 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1561 pBeaconSync->TimIELocationInBeacon[i] = 0;
1562 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1564 pBeaconSync->BeaconBitMap = 0;
1566 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1567 pBeaconSync->EnableBeacon = TRUE;
1572 VOID RT2870_BssBeaconExit(
1573 IN RTMP_ADAPTER *pAd)
1575 BEACON_SYNC_STRUCT *pBeaconSync;
1576 BOOLEAN Cancelled = TRUE;
1579 if (pAd->CommonCfg.pBeaconSync)
1581 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1582 pBeaconSync->EnableBeacon = FALSE;
1583 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1584 pBeaconSync->BeaconBitMap = 0;
1586 for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1588 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1589 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1590 pBeaconSync->TimIELocationInBeacon[i] = 0;
1591 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1594 NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1595 pAd->CommonCfg.pBeaconSync = NULL;
1599 VOID BeaconUpdateExec(
1600 IN PVOID SystemSpecific1,
1601 IN PVOID FunctionContext,
1602 IN PVOID SystemSpecific2,
1603 IN PVOID SystemSpecific3)
1605 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
1606 LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1607 UINT32 delta, remain, remain_low, remain_high;
1608 // BOOLEAN positive;
1610 ReSyncBeaconTime(pAd);
1614 RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1615 RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1618 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1619 remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1620 remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1621 remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1622 delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1624 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;