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