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