]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2870/2870_main_dev.c
staging: __FUNCTION__ is gcc-specific, use __func__
[net-next-2.6.git] / drivers / staging / rt2870 / 2870_main_dev.c
CommitLineData
c55519ff
GKH
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 */
d599edca 266 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
c55519ff
GKH
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 */
d599edca 468 DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
c55519ff
GKH
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 {
d599edca 1261 printk("%s: Could not find both bulk-in and bulk-out endpoints\n", __func__);
c55519ff
GKH
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