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
66 extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
67 IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
71 struct usb_device_id rtusb_usb_id[] = RT2870_USB_DEVICES;
72 INT const rtusb_usb_id_len = sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
73 MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
80 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
82 /**************************************************************************/
83 /**************************************************************************/
84 //tested for kernel 2.4 series
85 /**************************************************************************/
86 /**************************************************************************/
87 static void *rtusb_probe(struct usb_device *dev, UINT interface,
88 const struct usb_device_id *id_table);
89 static void rtusb_disconnect(struct usb_device *dev, void *ptr);
91 struct usb_driver rtusb_driver = {
94 disconnect:rtusb_disconnect,
95 id_table:rtusb_usb_id,
101 static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
102 static int rt2870_resume(struct usb_interface *intf);
103 #endif // CONFIG_PM //
105 /**************************************************************************/
106 /**************************************************************************/
107 //tested for kernel 2.6series
108 /**************************************************************************/
109 /**************************************************************************/
110 static int rtusb_probe (struct usb_interface *intf,
111 const struct usb_device_id *id);
112 static void rtusb_disconnect(struct usb_interface *intf);
114 struct usb_driver rtusb_driver = {
115 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
116 .owner = THIS_MODULE,
120 .disconnect=rtusb_disconnect,
121 .id_table=rtusb_usb_id,
124 suspend: rt2870_suspend,
125 resume: rt2870_resume,
131 VOID RT2860RejectPendingPackets(
132 IN PRTMP_ADAPTER pAd)
135 // clear TxSw packets
138 static int rt2870_suspend(
139 struct usb_interface *intf,
142 struct net_device *net_dev;
143 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
146 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
147 net_dev = pAd->net_dev;
148 netif_device_detach (net_dev);
150 pAd->PM_FlgSuspend = 1;
151 if (netif_running(net_dev)) {
152 RTUSBCancelPendingBulkInIRP(pAd);
153 RTUSBCancelPendingBulkOutIRP(pAd);
155 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
159 static int rt2870_resume(
160 struct usb_interface *intf)
162 struct net_device *net_dev;
163 PRTMP_ADAPTER pAd = usb_get_intfdata(intf);
166 DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
168 pAd->PM_FlgSuspend = 0;
169 net_dev = pAd->net_dev;
170 netif_device_attach (net_dev);
171 netif_start_queue(net_dev);
172 netif_carrier_on(net_dev);
173 netif_wake_queue(net_dev);
175 DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
178 #endif // CONFIG_PM //
179 #endif // LINUX_VERSION_CODE //
182 // Init driver module
183 INT __init rtusb_init(void)
185 printk("rtusb init --->\n");
186 return usb_register(&rtusb_driver);
189 // Deinit driver module
190 VOID __exit rtusb_exit(void)
192 usb_deregister(&rtusb_driver);
193 printk("<--- rtusb exit\n");
196 module_init(rtusb_init);
197 module_exit(rtusb_exit);
202 /*--------------------------------------------------------------------- */
203 /* function declarations */
204 /*--------------------------------------------------------------------- */
207 ========================================================================
212 *Context the pAd, driver control block pointer
218 ========================================================================
223 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
227 pObj = (POS_COOKIE)pAd->OS_Cookie;
229 rtmp_os_thread_init("rt2870MlmeThread", (PVOID)&(pAd->mlmeComplete));
231 while (pAd->mlme_kill == 0)
233 /* lock the device pointers */
234 //down(&(pAd->mlme_semaphore));
235 status = down_interruptible(&(pAd->mlme_semaphore));
237 /* lock the device pointers , need to check if required*/
238 //down(&(pAd->usbdev_semaphore));
240 if (!pAd->PM_FlgSuspend)
243 /* unlock the device pointers */
244 //up(&(pAd->usbdev_semaphore));
247 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
252 /* notify the exit routine that we're actually exiting now
254 * complete()/wait_for_completion() is similar to up()/down(),
255 * except that complete() is safe in the case where the structure
256 * is getting deleted in a parallel mode of execution (i.e. just
257 * after the down() -- that's necessary for the thread-shutdown
260 * complete_and_exit() goes even further than this -- it is safe in
261 * the case that the thread of the caller is going away (not just
262 * the structure) -- this is necessary for the module-remove case.
263 * This is important in preemption kernels, which transfer the flow
264 * of execution immediately upon a complete().
266 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
268 pObj->MLMEThr_task = NULL;
270 complete_and_exit (&pAd->mlmeComplete, 0);
277 ========================================================================
279 USB command kernel thread.
282 *Context the pAd, driver control block pointer
288 ========================================================================
293 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)Context;
297 pObj = (POS_COOKIE)pAd->OS_Cookie;
299 rtmp_os_thread_init("rt2870CmdThread", (PVOID)&(pAd->CmdQComplete));
301 NdisAcquireSpinLock(&pAd->CmdQLock);
302 pAd->CmdQ.CmdQState = RT2870_THREAD_RUNNING;
303 NdisReleaseSpinLock(&pAd->CmdQLock);
305 while (pAd->CmdQ.CmdQState == RT2870_THREAD_RUNNING)
307 /* lock the device pointers */
308 //down(&(pAd->RTUSBCmd_semaphore));
309 status = down_interruptible(&(pAd->RTUSBCmd_semaphore));
311 if (pAd->CmdQ.CmdQState == RT2870_THREAD_STOPED)
316 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
319 /* lock the device pointers , need to check if required*/
320 //down(&(pAd->usbdev_semaphore));
322 if (!pAd->PM_FlgSuspend)
325 /* unlock the device pointers */
326 //up(&(pAd->usbdev_semaphore));
329 if (!pAd->PM_FlgSuspend)
330 { // Clear the CmdQElements.
331 CmdQElmt *pCmdQElmt = NULL;
333 NdisAcquireSpinLock(&pAd->CmdQLock);
334 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
335 while(pAd->CmdQ.size)
337 RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
340 if (pCmdQElmt->CmdFromNdis == TRUE)
342 if (pCmdQElmt->buffer != NULL)
343 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
345 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
349 if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0))
350 NdisFreeMemory(pCmdQElmt->buffer, pCmdQElmt->bufferlength, 0);
352 NdisFreeMemory(pCmdQElmt, sizeof(CmdQElmt), 0);
358 NdisReleaseSpinLock(&pAd->CmdQLock);
360 /* notify the exit routine that we're actually exiting now
362 * complete()/wait_for_completion() is similar to up()/down(),
363 * except that complete() is safe in the case where the structure
364 * is getting deleted in a parallel mode of execution (i.e. just
365 * after the down() -- that's necessary for the thread-shutdown
368 * complete_and_exit() goes even further than this -- it is safe in
369 * the case that the thread of the caller is going away (not just
370 * the structure) -- this is necessary for the module-remove case.
371 * This is important in preemption kernels, which transfer the flow
372 * of execution immediately upon a complete().
374 DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
376 pObj->RTUSBCmdThr_task = NULL;
378 complete_and_exit (&pAd->CmdQComplete, 0);
384 static void RT2870_TimerQ_Handle(RTMP_ADAPTER *pAd)
387 RALINK_TIMER_STRUCT *pTimer;
388 RT2870_TIMER_ENTRY *pEntry;
389 unsigned long irqFlag;
391 while(!pAd->TimerFunc_kill)
393 // printk("waiting for event!\n");
396 status = down_interruptible(&(pAd->RTUSBTimer_semaphore));
398 if (pAd->TimerQ.status == RT2870_THREAD_STOPED)
402 while(pAd->TimerQ.pQHead)
404 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlag);
405 pEntry = pAd->TimerQ.pQHead;
408 pTimer = pEntry->pRaTimer;
411 pAd->TimerQ.pQHead = pEntry->pNext;
412 if (pEntry == pAd->TimerQ.pQTail)
413 pAd->TimerQ.pQTail = NULL;
415 // return this queue entry to timerQFreeList.
416 pEntry->pNext = pAd->TimerQ.pQPollFreeList;
417 pAd->TimerQ.pQPollFreeList = pEntry;
419 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlag);
423 if (pTimer->handle != NULL)
424 if (!pAd->PM_FlgSuspend)
425 pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
426 if ((pTimer->Repeat) && (pTimer->State == FALSE))
427 RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
433 pAd->TimerQ.status = RT2870_THREAD_STOPED;
434 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
442 IN OUT PVOID Context)
447 pAd = (PRTMP_ADAPTER)Context;
448 pObj = (POS_COOKIE) pAd->OS_Cookie;
450 rtmp_os_thread_init("rt2870TimerQHandle", (PVOID)&(pAd->TimerQComplete));
452 RT2870_TimerQ_Handle(pAd);
454 /* notify the exit routine that we're actually exiting now
456 * complete()/wait_for_completion() is similar to up()/down(),
457 * except that complete() is safe in the case where the structure
458 * is getting deleted in a parallel mode of execution (i.e. just
459 * after the down() -- that's necessary for the thread-shutdown
462 * complete_and_exit() goes even further than this -- it is safe in
463 * the case that the thread of the caller is going away (not just
464 * the structure) -- this is necessary for the module-remove case.
465 * This is important in preemption kernels, which transfer the flow
466 * of execution immediately upon a complete().
468 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
470 pObj->TimerQThr_task = NULL;
472 complete_and_exit(&pAd->TimerQComplete, 0);
478 RT2870_TIMER_ENTRY *RT2870_TimerQ_Insert(
479 IN RTMP_ADAPTER *pAd,
480 IN RALINK_TIMER_STRUCT *pTimer)
482 RT2870_TIMER_ENTRY *pQNode = NULL, *pQTail;
483 unsigned long irqFlags;
486 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
487 if (pAd->TimerQ.status & RT2870_THREAD_CAN_DO_INSERT)
489 if(pAd->TimerQ.pQPollFreeList)
491 pQNode = pAd->TimerQ.pQPollFreeList;
492 pAd->TimerQ.pQPollFreeList = pQNode->pNext;
494 pQNode->pRaTimer = pTimer;
495 pQNode->pNext = NULL;
497 pQTail = pAd->TimerQ.pQTail;
498 if (pAd->TimerQ.pQTail != NULL)
499 pQTail->pNext = pQNode;
500 pAd->TimerQ.pQTail = pQNode;
501 if (pAd->TimerQ.pQHead == NULL)
502 pAd->TimerQ.pQHead = pQNode;
504 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
507 up(&pAd->RTUSBTimer_semaphore);
508 //wake_up(&timerWaitQ);
512 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
518 BOOLEAN RT2870_TimerQ_Remove(
519 IN RTMP_ADAPTER *pAd,
520 IN RALINK_TIMER_STRUCT *pTimer)
522 RT2870_TIMER_ENTRY *pNode, *pPrev = NULL;
523 unsigned long irqFlags;
525 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
526 if (pAd->TimerQ.status >= RT2870_THREAD_INITED)
528 pNode = pAd->TimerQ.pQHead;
531 if (pNode->pRaTimer == pTimer)
534 pNode = pNode->pNext;
537 // Now move it to freeList queue.
540 if (pNode == pAd->TimerQ.pQHead)
541 pAd->TimerQ.pQHead = pNode->pNext;
542 if (pNode == pAd->TimerQ.pQTail)
543 pAd->TimerQ.pQTail = pPrev;
545 pPrev->pNext = pNode->pNext;
547 // return this queue entry to timerQFreeList.
548 pNode->pNext = pAd->TimerQ.pQPollFreeList;
549 pAd->TimerQ.pQPollFreeList = pNode;
552 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
558 void RT2870_TimerQ_Exit(RTMP_ADAPTER *pAd)
560 RT2870_TIMER_ENTRY *pTimerQ;
561 unsigned long irqFlags;
563 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
564 while (pAd->TimerQ.pQHead)
566 pTimerQ = pAd->TimerQ.pQHead;
567 pAd->TimerQ.pQHead = pTimerQ->pNext;
570 pAd->TimerQ.pQPollFreeList = NULL;
571 os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
572 pAd->TimerQ.pQTail = NULL;
573 pAd->TimerQ.pQHead = NULL;
574 pAd->TimerQ.status = RT2870_THREAD_STOPED;
575 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
580 void RT2870_TimerQ_Init(RTMP_ADAPTER *pAd)
583 RT2870_TIMER_ENTRY *pQNode, *pEntry;
584 unsigned long irqFlags;
586 NdisAllocateSpinLock(&pAd->TimerQLock);
588 RTMP_IRQ_LOCK(&pAd->TimerQLock, irqFlags);
589 NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
590 //InterlockedExchange(&pAd->TimerQ.count, 0);
592 /* Initialise the wait q head */
593 //init_waitqueue_head(&timerWaitQ);
595 os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RT2870_TIMER_ENTRY) * TIMER_QUEUE_SIZE_MAX);
596 if (pAd->TimerQ.pTimerQPoll)
599 pQNode = (RT2870_TIMER_ENTRY *)pAd->TimerQ.pTimerQPoll;
600 for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
602 pQNode->pNext = pEntry;
606 pAd->TimerQ.pQPollFreeList = pEntry;
607 pAd->TimerQ.pQHead = NULL;
608 pAd->TimerQ.pQTail = NULL;
609 pAd->TimerQ.status = RT2870_THREAD_INITED;
611 RTMP_IRQ_UNLOCK(&pAd->TimerQLock, irqFlags);
615 VOID RT2870_WatchDog(IN RTMP_ADAPTER *pAd)
617 PHT_TX_CONTEXT pHTTXContext;
621 BOOLEAN needDumpSeq = FALSE;
626 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
627 if ((MACValue & 0xff) !=0 )
629 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
630 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
631 while((MACValue &0xff) != 0 && (idx++ < 10))
633 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
636 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
640 if ((MACValue & 0xff00) !=0 )
642 DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
643 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
644 while((MACValue &0xff00) != 0 && (idx++ < 10))
646 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
649 RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
653 if (pAd->watchDogRxOverFlowCnt >= 2)
655 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
656 if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
657 fRTMP_ADAPTER_BULKIN_RESET |
658 fRTMP_ADAPTER_HALT_IN_PROGRESS |
659 fRTMP_ADAPTER_NIC_NOT_EXIST))))
661 DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
662 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
663 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
666 pAd->watchDogRxOverFlowCnt = 0;
670 for (idx = 0; idx < NUM_OF_TX_RING; idx++)
674 RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
675 if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)
677 pAd->watchDogTxPendingCnt[idx]++;
679 if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
680 (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
683 // FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!
684 pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
685 if (pHTTXContext->IRPPending)
686 { // Check TxContext.
687 pUrb = pHTTXContext->pUrb;
689 else if (idx == MGMTPIPEIDX)
691 PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
694 pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
695 pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
696 pNULLContext = (PTX_CONTEXT)(&pAd->NullContext);
698 if (pMLMEContext->IRPPending)
700 ASSERT(pMLMEContext->IRPPending);
701 pUrb = pMLMEContext->pUrb;
703 else if (pNULLContext->IRPPending)
705 ASSERT(pNULLContext->IRPPending);
706 pUrb = pNULLContext->pUrb;
708 else if (pPsPollContext->IRPPending)
710 ASSERT(pPsPollContext->IRPPending);
711 pUrb = pPsPollContext->pUrb;
715 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
717 DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
720 DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
722 RTUSB_UNLINK_URB(pUrb);
723 // Sleep 200 microseconds to give cancellation time to work
729 DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
734 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
739 RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
743 #ifdef DOT11_N_SUPPORT
744 // For Sigma debug, dump the ba_reordering sequence.
745 if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
748 PBA_REC_ENTRY pBAEntry = NULL;
750 struct reordering_mpdu *mpdu_blk;
752 Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
754 pBAEntry = &pAd->BATable.BARecEntry[Idx];
755 if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
757 DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
758 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
759 mpdu_blk = pBAEntry->list.next;
762 DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
763 mpdu_blk = mpdu_blk->next;
767 DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
768 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
771 #endif // DOT11_N_SUPPORT //
775 ========================================================================
777 Release allocated resources.
780 *dev Point to the PCI or USB device
781 pAd driver control block pointer
787 ========================================================================
789 static void _rtusb_disconnect(struct usb_device *dev, PRTMP_ADAPTER pAd)
791 struct net_device *net_dev = NULL;
794 DBGPRINT(RT_DEBUG_ERROR, ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
795 dev->bus->bus_name, dev->devpath));
798 #ifdef MULTIPLE_CARD_SUPPORT
799 if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))
800 MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address
801 #endif // MULTIPLE_CARD_SUPPORT //
803 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
804 while(MOD_IN_USE > 0)
810 #endif // LINUX_VERSION_CODE //
812 printk("rtusb_disconnect: pAd == NULL!\n");
815 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
819 // for debug, wait to show some messages to /proc system
825 net_dev = pAd->net_dev;
826 if (pAd->net_dev != NULL)
828 printk("rtusb_disconnect: unregister_netdev(), dev->name=%s!\n", net_dev->name);
829 unregister_netdev (pAd->net_dev);
832 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
834 flush_scheduled_work();
835 #endif // LINUX_VERSION_CODE //
838 // free net_device memory
839 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
842 free_netdev(net_dev);
843 #endif // LINUX_VERSION_CODE //
845 // free adapter memory
846 RTMPFreeAdapter(pAd);
848 // release a use of the usb device structure
849 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
850 while(MOD_IN_USE > 0)
856 #endif // LINUX_VERSION_CODE //
859 DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
864 ========================================================================
866 Probe RT28XX chipset.
869 *dev Point to the PCI or USB device
871 *id_table Point to the PCI or USB device ID
877 ========================================================================
879 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
880 static void *rtusb_probe(struct usb_device *dev, UINT interface,
881 const struct usb_device_id *id)
884 rt28xx_probe((void *)dev, (void *)id, interface, &pAd);
888 //Disconnect function is called within exit routine
889 static void rtusb_disconnect(struct usb_device *dev, void *ptr)
891 _rtusb_disconnect(dev, ((PRTMP_ADAPTER)ptr));
894 #else /* kernel 2.6 series */
895 static int rtusb_probe (struct usb_interface *intf,
896 const struct usb_device_id *id)
899 return (int)rt28xx_probe((void *)intf, (void *)id, 0, &pAd);
903 static void rtusb_disconnect(struct usb_interface *intf)
905 struct usb_device *dev = interface_to_usbdev(intf);
909 pAd = usb_get_intfdata(intf);
910 usb_set_intfdata(intf, NULL);
912 _rtusb_disconnect(dev, pAd);
914 #endif // LINUX_VERSION_CODE //
918 ========================================================================
920 Close kernel threads.
923 *pAd the raxx interface data pointer
929 ========================================================================
931 VOID RT28xxThreadTerminate(
932 IN RTMP_ADAPTER *pAd)
934 POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
938 // Sleep 50 milliseconds so pending io might finish normally
939 RTMPusecDelay(50000);
941 // We want to wait until all pending receives and sends to the
942 // device object. We cancel any
943 // irps. Wait until sends and receives have stopped.
944 RTUSBCancelPendingIRPs(pAd);
947 BUG_ON(pObj->TimerQThr_task == NULL);
948 CHECK_PID_LEGALITY(task_pid(pObj->TimerQThr_task))
950 POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
952 printk(KERN_DEBUG "Terminate the TimerQThr pid=%d!\n",
953 pid_nr(task_pid(pObj->TimerQThr_task)));
955 pAd->TimerFunc_kill = 1;
957 kthread_stop(pObj->TimerQThr_task);
958 pObj->TimerQThr_task = NULL;
961 BUG_ON(pObj->MLMEThr_task == NULL);
962 CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task))
964 printk(KERN_DEBUG "Terminate the MLMEThr pid=%d!\n",
965 pid_nr(task_pid(pObj->MLMEThr_task)));
968 //RT28XX_MLME_HANDLER(pAd);
970 kthread_stop(pObj->MLMEThr_task);
971 pObj->MLMEThr_task = NULL;
974 BUG_ON(pObj->RTUSBCmdThr_task == NULL);
975 CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task))
977 printk(KERN_DEBUG "Terminate the RTUSBCmdThr pid=%d!\n",
978 pid_nr(task_pid(pObj->RTUSBCmdThr_task)));
980 NdisAcquireSpinLock(&pAd->CmdQLock);
981 pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
982 NdisReleaseSpinLock(&pAd->CmdQLock);
985 kthread_stop(pObj->RTUSBCmdThr_task);
986 pObj->RTUSBCmdThr_task = NULL;
992 pAd->CmdQ.CmdQState = RT2870_THREAD_UNKNOWN;
993 pAd->TimerFunc_kill = 0;
997 void kill_thread_task(IN PRTMP_ADAPTER pAd)
1001 pObj = (POS_COOKIE) pAd->OS_Cookie;
1003 tasklet_kill(&pObj->rx_done_task);
1004 tasklet_kill(&pObj->mgmt_dma_done_task);
1005 tasklet_kill(&pObj->ac0_dma_done_task);
1006 tasklet_kill(&pObj->ac1_dma_done_task);
1007 tasklet_kill(&pObj->ac2_dma_done_task);
1008 tasklet_kill(&pObj->ac3_dma_done_task);
1009 tasklet_kill(&pObj->hcca_dma_done_task);
1010 tasklet_kill(&pObj->tbtt_task);
1016 ========================================================================
1017 Routine Description:
1018 Check the chipset vendor/product ID.
1021 _dev_p Point to the PCI or USB device
1028 ========================================================================
1030 BOOLEAN RT28XXChipsetCheck(
1033 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1034 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1036 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1037 struct usb_device *dev_p = interface_to_usbdev(intf);
1038 #endif // LINUX_VERSION_CODE //
1042 for(i=0; i<rtusb_usb_id_len; i++)
1044 if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
1045 dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
1047 printk(KERN_DEBUG "rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
1048 dev_p->descriptor.idVendor, dev_p->descriptor.idProduct);
1053 if (i == rtusb_usb_id_len)
1055 printk("rt2870: Error! Device Descriptor not matching!\n");
1064 ========================================================================
1065 Routine Description:
1066 Init net device structure.
1069 _dev_p Point to the PCI or USB device
1070 *net_dev Point to the net device
1071 *pAd the raxx interface data pointer
1078 ========================================================================
1080 BOOLEAN RT28XXNetDevInit(
1082 IN struct net_device *net_dev,
1083 IN RTMP_ADAPTER *pAd)
1085 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1086 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1088 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1089 struct usb_device *dev_p = interface_to_usbdev(intf);
1090 #endif // LINUX_VERSION_CODE //
1093 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* kernel 2.4 series */
1094 pAd->config = dev_p->config;
1096 pAd->config = &dev_p->config->desc;
1097 #endif // LINUX_VERSION_CODE //
1103 ========================================================================
1104 Routine Description:
1105 Init net device structure.
1108 _dev_p Point to the PCI or USB device
1109 *pAd the raxx interface data pointer
1116 ========================================================================
1118 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
1119 BOOLEAN RT28XXProbePostConfig(
1121 IN RTMP_ADAPTER *pAd,
1124 struct usb_device *dev_p = (struct usb_device *)_dev_p;
1125 struct usb_interface *intf;
1126 struct usb_interface_descriptor *iface_desc;
1127 struct usb_endpoint_descriptor *endpoint;
1132 /* get the active interface descriptor */
1133 intf = &dev_p->actconfig->interface[interface];
1134 iface_desc = &intf->altsetting[0];
1136 /* get # of enpoints */
1137 pAd->NumberOfPipes = iface_desc->bNumEndpoints;
1138 DBGPRINT(RT_DEBUG_TRACE, ("NumEndpoints=%d\n", iface_desc->bNumEndpoints));
1140 /* Configure Pipes */
1141 endpoint = &iface_desc->endpoint[0];
1144 for(i=0; i<pAd->NumberOfPipes; i++)
1146 if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
1147 ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1149 pAd->BulkInEpAddr = endpoint[i].bEndpointAddress;
1150 pAd->BulkInMaxPacketSize = endpoint[i].wMaxPacketSize;
1152 DBGPRINT_RAW(RT_DEBUG_TRACE,
1153 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1154 DBGPRINT_RAW(RT_DEBUG_TRACE,
1155 ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress));
1157 else if ((endpoint[i].bmAttributes == USB_ENDPOINT_XFER_BULK) &&
1158 ((endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1160 // There are 6 bulk out EP. EP6 highest priority.
1161 // EP1-4 is EDCA. EP5 is HCCA.
1162 pAd->BulkOutEpAddr[BulkOutIdx++] = endpoint[i].bEndpointAddress;
1163 pAd->BulkOutMaxPacketSize = endpoint[i].wMaxPacketSize;
1165 DBGPRINT_RAW(RT_DEBUG_TRACE,
1166 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1167 DBGPRINT_RAW(RT_DEBUG_TRACE,
1168 ("EP address = 0x%2x \n", endpoint[i].bEndpointAddress));
1172 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1174 printk("Could not find both bulk-in and bulk-out endpoints\n");
1182 BOOLEAN RT28XXProbePostConfig(
1184 IN RTMP_ADAPTER *pAd,
1187 struct usb_interface *intf = (struct usb_interface *)_dev_p;
1188 struct usb_host_interface *iface_desc;
1193 /* get the active interface descriptor */
1194 iface_desc = intf->cur_altsetting;
1196 /* get # of enpoints */
1197 pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
1198 DBGPRINT(RT_DEBUG_TRACE,
1199 ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
1201 /* Configure Pipes */
1204 for(i=0; i<pAd->NumberOfPipes; i++)
1206 if ((iface_desc->endpoint[i].desc.bmAttributes ==
1207 USB_ENDPOINT_XFER_BULK) &&
1208 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1209 USB_ENDPOINT_DIR_MASK) == USB_DIR_IN))
1211 pAd->BulkInEpAddr = iface_desc->endpoint[i].desc.bEndpointAddress;
1212 pAd->BulkInMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1214 DBGPRINT_RAW(RT_DEBUG_TRACE,
1215 ("BULK IN MaximumPacketSize = %d\n", pAd->BulkInMaxPacketSize));
1216 DBGPRINT_RAW(RT_DEBUG_TRACE,
1217 ("EP address = 0x%2x\n", iface_desc->endpoint[i].desc.bEndpointAddress));
1219 else if ((iface_desc->endpoint[i].desc.bmAttributes ==
1220 USB_ENDPOINT_XFER_BULK) &&
1221 ((iface_desc->endpoint[i].desc.bEndpointAddress &
1222 USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT))
1224 // there are 6 bulk out EP. EP6 highest priority.
1225 // EP1-4 is EDCA. EP5 is HCCA.
1226 pAd->BulkOutEpAddr[BulkOutIdx++] = iface_desc->endpoint[i].desc.bEndpointAddress;
1227 pAd->BulkOutMaxPacketSize = iface_desc->endpoint[i].desc.wMaxPacketSize;
1229 DBGPRINT_RAW(RT_DEBUG_TRACE,
1230 ("BULK OUT MaximumPacketSize = %d\n", pAd->BulkOutMaxPacketSize));
1231 DBGPRINT_RAW(RT_DEBUG_TRACE,
1232 ("EP address = 0x%2x \n", iface_desc->endpoint[i].desc.bEndpointAddress));
1236 if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0]))
1238 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
1244 #endif // LINUX_VERSION_CODE //
1248 ========================================================================
1249 Routine Description:
1253 *pAd the raxx interface data pointer
1259 ========================================================================
1261 VOID RT28XXDMADisable(
1262 IN RTMP_ADAPTER *pAd)
1270 ========================================================================
1271 Routine Description:
1275 *pAd the raxx interface data pointer
1281 ========================================================================
1283 VOID RT28XXDMAEnable(
1284 IN RTMP_ADAPTER *pAd)
1286 WPDMA_GLO_CFG_STRUC GloCfg;
1287 USB_DMA_CFG_STRUC UsbCfg;
1291 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
1294 RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
1295 if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
1298 DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
1299 RTMPusecDelay(1000);
1305 GloCfg.field.EnTXWriteBackDDONE = 1;
1306 GloCfg.field.EnableRxDMA = 1;
1307 GloCfg.field.EnableTxDMA = 1;
1308 DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
1309 RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
1312 UsbCfg.field.phyclear = 0;
1313 /* usb version is 1.1,do not use bulk in aggregation */
1314 if (pAd->BulkInMaxPacketSize == 512)
1315 UsbCfg.field.RxBulkAggEn = 1;
1316 /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
1317 UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
1318 UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */
1319 UsbCfg.field.RxBulkEn = 1;
1320 UsbCfg.field.TxBulkEn = 1;
1322 RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word);
1327 ========================================================================
1328 Routine Description:
1329 Write Beacon buffer to Asic.
1332 *pAd the raxx interface data pointer
1338 ========================================================================
1340 VOID RT28xx_UpdateBeaconToAsic(
1341 IN RTMP_ADAPTER *pAd,
1346 PUCHAR pBeaconFrame = NULL;
1349 BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
1351 BOOLEAN bBcnReq = FALSE;
1355 if (pBeaconFrame == NULL)
1357 DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
1361 if (pBeaconSync == NULL)
1363 DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
1367 //if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) ||
1368 // ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP))
1370 if (bBcnReq == FALSE)
1372 /* when the ra interface is down, do not send its beacon frame */
1373 /* clear all zero */
1374 for(i=0; i<TXWI_SIZE; i+=4) {
1375 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
1377 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1378 NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE);
1382 ptr = (PUCHAR)&pAd->BeaconTxWI;
1383 #ifdef RT_BIG_ENDIAN
1384 RTMPWIEndianChange(ptr, TYPE_TXWI);
1386 if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE)
1387 { // If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.
1388 pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
1389 NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE);
1392 if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
1394 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
1396 longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
1397 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue);
1402 ptr = pBeaconSync->BeaconBuf[bcn_idx];
1403 padding = (FrameLen & 0x01);
1404 NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
1405 FrameLen += padding;
1406 for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
1408 if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
1410 NdisMoveMemory(ptr, pBeaconFrame, 2);
1411 //shortValue = *ptr + (*(ptr+1)<<8);
1412 //RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue);
1413 RTUSBMultiWrite(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, ptr, 2);
1419 pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
1425 VOID RT2870_BssBeaconStop(
1426 IN RTMP_ADAPTER *pAd)
1428 BEACON_SYNC_STRUCT *pBeaconSync;
1430 BOOLEAN Cancelled = TRUE;
1432 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1433 if (pBeaconSync && pBeaconSync->EnableBeacon)
1438 #ifdef CONFIG_STA_SUPPORT
1439 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1441 NumOfBcn = MAX_MESH_NUM;
1443 #endif // CONFIG_STA_SUPPORT //
1445 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1447 for(i=0; i<NumOfBcn; i++)
1449 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1450 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1452 for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
1453 RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[i] + offset, 0x00);
1455 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1456 pBeaconSync->TimIELocationInBeacon[i] = 0;
1458 pBeaconSync->BeaconBitMap = 0;
1459 pBeaconSync->DtimBitOn = 0;
1464 VOID RT2870_BssBeaconStart(
1465 IN RTMP_ADAPTER *pAd)
1468 BEACON_SYNC_STRUCT *pBeaconSync;
1469 // LARGE_INTEGER tsfTime, deltaTime;
1471 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1472 if (pBeaconSync && pBeaconSync->EnableBeacon)
1477 #ifdef CONFIG_STA_SUPPORT
1478 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1480 NumOfBcn = MAX_MESH_NUM;
1482 #endif // CONFIG_STA_SUPPORT //
1484 for(apidx=0; apidx<NumOfBcn; apidx++)
1486 UCHAR CapabilityInfoLocationInBeacon = 0;
1487 UCHAR TimIELocationInBeacon = 0;
1489 NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
1490 pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
1491 pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
1492 NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWI_SIZE);
1494 pBeaconSync->BeaconBitMap = 0;
1495 pBeaconSync->DtimBitOn = 0;
1496 pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
1498 pAd->CommonCfg.BeaconAdjust = 0;
1499 pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
1500 pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
1501 printk("RT2870_BssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain);
1502 RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, pAd->CommonCfg.BeaconPeriod);
1508 VOID RT2870_BssBeaconInit(
1509 IN RTMP_ADAPTER *pAd)
1511 BEACON_SYNC_STRUCT *pBeaconSync;
1514 NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(BEACON_SYNC_STRUCT), MEM_ALLOC_FLAG);
1515 if (pAd->CommonCfg.pBeaconSync)
1517 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1518 NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
1519 for(i=0; i < HW_BEACON_MAX_COUNT; i++)
1521 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1522 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1523 pBeaconSync->TimIELocationInBeacon[i] = 0;
1524 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1526 pBeaconSync->BeaconBitMap = 0;
1528 //RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);
1529 pBeaconSync->EnableBeacon = TRUE;
1534 VOID RT2870_BssBeaconExit(
1535 IN RTMP_ADAPTER *pAd)
1537 BEACON_SYNC_STRUCT *pBeaconSync;
1538 BOOLEAN Cancelled = TRUE;
1541 if (pAd->CommonCfg.pBeaconSync)
1543 pBeaconSync = pAd->CommonCfg.pBeaconSync;
1544 pBeaconSync->EnableBeacon = FALSE;
1545 RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
1546 pBeaconSync->BeaconBitMap = 0;
1548 for(i=0; i<HW_BEACON_MAX_COUNT; i++)
1550 NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
1551 pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
1552 pBeaconSync->TimIELocationInBeacon[i] = 0;
1553 NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE);
1556 NdisFreeMemory(pAd->CommonCfg.pBeaconSync, HW_BEACON_OFFSET * HW_BEACON_MAX_COUNT, 0);
1557 pAd->CommonCfg.pBeaconSync = NULL;
1561 VOID BeaconUpdateExec(
1562 IN PVOID SystemSpecific1,
1563 IN PVOID FunctionContext,
1564 IN PVOID SystemSpecific2,
1565 IN PVOID SystemSpecific3)
1567 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
1568 LARGE_INTEGER tsfTime_a;//, tsfTime_b, deltaTime_exp, deltaTime_ab;
1569 UINT32 delta, remain, remain_low, remain_high;
1570 // BOOLEAN positive;
1572 ReSyncBeaconTime(pAd);
1576 RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
1577 RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
1580 //positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);
1581 remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
1582 remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
1583 remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
1584 delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
1586 pAd->CommonCfg.BeaconUpdateTimer.TimerValue = (delta >> 10) + 10;