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