]>
Commit | Line | Data |
---|---|---|
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. *** | |
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 | ||
131 | VOID RT2860RejectPendingPackets( | |
132 | IN PRTMP_ADAPTER pAd) | |
133 | { | |
134 | // clear PS packets | |
135 | // clear TxSw packets | |
136 | } | |
137 | ||
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 | ||
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 | |
183 | INT __init rtusb_init(void) | |
184 | { | |
185 | printk("rtusb init --->\n"); | |
186 | return usb_register(&rtusb_driver); | |
187 | } | |
188 | ||
189 | // Deinit driver module | |
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 | */ | |
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 | */ | |
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 | ======================================================================== | |
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 | */ | |
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 | ||
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 | ||
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 | */ | |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | */ | |
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 */ | |
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 | |
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 */ | |
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 | ||
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 | */ | |
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 | ||
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 | */ | |
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 | */ | |
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) | |
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 | |
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 | { | |
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 | ======================================================================== | |
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 | */ | |
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 | */ | |
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 | */ | |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 |