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