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