Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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.