• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rt2860/
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#include "rt_config.h"
28
29/* Following information will be show when you run 'modinfo' */
30/* *** If you have a solution for the bug in current version of driver, please mail to me. */
31/* Otherwise post to forum in ralinktech's web site(www.ralinktech.com) and let all users help you. *** */
32MODULE_AUTHOR("Paul Lin <paul_lin@ralinktech.com>");
33MODULE_DESCRIPTION("RT2870/RT3070 Wireless Lan Linux Driver");
34MODULE_LICENSE("GPL");
35#ifdef MODULE_VERSION
36MODULE_VERSION(STA_DRIVER_VERSION);
37#endif
38
39/* module table */
40struct usb_device_id rtusb_usb_id[] = {
41#ifdef RT2870
42	{USB_DEVICE(0x148F, 0x2770)},	/* Ralink */
43	{USB_DEVICE(0x148F, 0x2870)},	/* Ralink */
44	{USB_DEVICE(0x07B8, 0x2870)},	/* AboCom */
45	{USB_DEVICE(0x07B8, 0x2770)},	/* AboCom */
46	{USB_DEVICE(0x0DF6, 0x0039)},	/* Sitecom 2770 */
47	{USB_DEVICE(0x0DF6, 0x003F)},	/* Sitecom 2770 */
48	{USB_DEVICE(0x083A, 0x7512)},	/* Arcadyan 2770 */
49	{USB_DEVICE(0x0789, 0x0162)},	/* Logitec 2870 */
50	{USB_DEVICE(0x0789, 0x0163)},	/* Logitec 2870 */
51	{USB_DEVICE(0x0789, 0x0164)},	/* Logitec 2870 */
52	{USB_DEVICE(0x177f, 0x0302)},	/* lsusb */
53	{USB_DEVICE(0x0B05, 0x1731)},	/* Asus */
54	{USB_DEVICE(0x0B05, 0x1732)},	/* Asus */
55	{USB_DEVICE(0x0B05, 0x1742)},	/* Asus */
56	{USB_DEVICE(0x0DF6, 0x0017)},	/* Sitecom */
57	{USB_DEVICE(0x0DF6, 0x002B)},	/* Sitecom */
58	{USB_DEVICE(0x0DF6, 0x002C)},	/* Sitecom */
59	{USB_DEVICE(0x0DF6, 0x002D)},	/* Sitecom */
60	{USB_DEVICE(0x14B2, 0x3C06)},	/* Conceptronic */
61	{USB_DEVICE(0x14B2, 0x3C28)},	/* Conceptronic */
62	{USB_DEVICE(0x2019, 0xED06)},	/* Planex Communications, Inc. */
63	{USB_DEVICE(0x07D1, 0x3C09)},	/* D-Link */
64	{USB_DEVICE(0x07D1, 0x3C11)},	/* D-Link */
65	{USB_DEVICE(0x14B2, 0x3C07)},	/* AL */
66	{USB_DEVICE(0x050D, 0x8053)},	/* Belkin */
67	{USB_DEVICE(0x050D, 0x825B)},	/* Belkin */
68	{USB_DEVICE(0x050D, 0x935A)},	/* Belkin F6D4050 v1 */
69	{USB_DEVICE(0x050D, 0x935B)},	/* Belkin F6D4050 v2 */
70	{USB_DEVICE(0x14B2, 0x3C23)},	/* Airlink */
71	{USB_DEVICE(0x14B2, 0x3C27)},	/* Airlink */
72	{USB_DEVICE(0x07AA, 0x002F)},	/* Corega */
73	{USB_DEVICE(0x07AA, 0x003C)},	/* Corega */
74	{USB_DEVICE(0x07AA, 0x003F)},	/* Corega */
75	{USB_DEVICE(0x1044, 0x800B)},	/* Gigabyte */
76	{USB_DEVICE(0x15A9, 0x0006)},	/* Sparklan */
77	{USB_DEVICE(0x083A, 0xB522)},	/* SMC */
78	{USB_DEVICE(0x083A, 0xA618)},	/* SMC */
79	{USB_DEVICE(0x083A, 0x8522)},	/* Arcadyan */
80	{USB_DEVICE(0x083A, 0x7522)},	/* Arcadyan */
81	{USB_DEVICE(0x0CDE, 0x0022)},	/* ZCOM */
82	{USB_DEVICE(0x0586, 0x3416)},	/* Zyxel */
83	{USB_DEVICE(0x0586, 0x341a)},	/* Zyxel NWD-270N */
84	{USB_DEVICE(0x0CDE, 0x0025)},	/* Zyxel */
85	{USB_DEVICE(0x1740, 0x9701)},	/* EnGenius */
86	{USB_DEVICE(0x1740, 0x9702)},	/* EnGenius */
87	{USB_DEVICE(0x0471, 0x200f)},	/* Philips */
88	{USB_DEVICE(0x14B2, 0x3C25)},	/* Draytek */
89	{USB_DEVICE(0x13D3, 0x3247)},	/* AzureWave */
90	{USB_DEVICE(0x083A, 0x6618)},	/* Accton */
91	{USB_DEVICE(0x15c5, 0x0008)},	/* Amit */
92	{USB_DEVICE(0x0E66, 0x0001)},	/* Hawking */
93	{USB_DEVICE(0x0E66, 0x0003)},	/* Hawking */
94	{USB_DEVICE(0x129B, 0x1828)},	/* Siemens */
95	{USB_DEVICE(0x157E, 0x300E)},	/* U-Media */
96	{USB_DEVICE(0x050d, 0x805c)},
97	{USB_DEVICE(0x050d, 0x815c)},
98	{USB_DEVICE(0x1482, 0x3C09)},	/* Abocom */
99	{USB_DEVICE(0x14B2, 0x3C09)},	/* Alpha */
100	{USB_DEVICE(0x04E8, 0x2018)},	/* samsung linkstick2 */
101	{USB_DEVICE(0x1690, 0x0740)},	/* Askey */
102	{USB_DEVICE(0x5A57, 0x0280)},	/* Zinwell */
103	{USB_DEVICE(0x5A57, 0x0282)},	/* Zinwell */
104	{USB_DEVICE(0x7392, 0x7718)},
105	{USB_DEVICE(0x7392, 0x7717)},
106	{USB_DEVICE(0x0411, 0x016f)},	/* MelCo.,Inc. WLI-UC-G301N */
107	{USB_DEVICE(0x1737, 0x0070)},	/* Linksys WUSB100 */
108	{USB_DEVICE(0x1737, 0x0071)},	/* Linksys WUSB600N */
109	{USB_DEVICE(0x1737, 0x0078)},	/* Linksys WUSB100v2 */
110	{USB_DEVICE(0x0411, 0x00e8)},	/* Buffalo WLI-UC-G300N */
111	{USB_DEVICE(0x050d, 0x815c)},	/* Belkin F5D8053 */
112	{USB_DEVICE(0x100D, 0x9031)},	/* Motorola 2770 */
113#endif /* RT2870 // */
114#ifdef RT3070
115	{USB_DEVICE(0x148F, 0x3070)},	/* Ralink 3070 */
116	{USB_DEVICE(0x148F, 0x3071)},	/* Ralink 3071 */
117	{USB_DEVICE(0x148F, 0x3072)},	/* Ralink 3072 */
118	{USB_DEVICE(0x0DB0, 0x3820)},	/* Ralink 3070 */
119	{USB_DEVICE(0x0DB0, 0x871C)},	/* Ralink 3070 */
120	{USB_DEVICE(0x0DB0, 0x822C)},	/* Ralink 3070 */
121	{USB_DEVICE(0x0DB0, 0x871B)},	/* Ralink 3070 */
122	{USB_DEVICE(0x0DB0, 0x822B)},	/* Ralink 3070 */
123	{USB_DEVICE(0x0DF6, 0x003E)},	/* Sitecom 3070 */
124	{USB_DEVICE(0x0DF6, 0x0042)},	/* Sitecom 3072 */
125	{USB_DEVICE(0x0DF6, 0x0048)},	/* Sitecom 3070 */
126	{USB_DEVICE(0x0DF6, 0x0047)},	/* Sitecom 3071 */
127	{USB_DEVICE(0x14B2, 0x3C12)},	/* AL 3070 */
128	{USB_DEVICE(0x18C5, 0x0012)},	/* Corega 3070 */
129	{USB_DEVICE(0x083A, 0x7511)},	/* Arcadyan 3070 */
130	{USB_DEVICE(0x083A, 0xA701)},	/* SMC 3070 */
131	{USB_DEVICE(0x083A, 0xA702)},	/* SMC 3072 */
132	{USB_DEVICE(0x1740, 0x9703)},	/* EnGenius 3070 */
133	{USB_DEVICE(0x1740, 0x9705)},	/* EnGenius 3071 */
134	{USB_DEVICE(0x1740, 0x9706)},	/* EnGenius 3072 */
135	{USB_DEVICE(0x1740, 0x9707)},	/* EnGenius 3070 */
136	{USB_DEVICE(0x1740, 0x9708)},	/* EnGenius 3071 */
137	{USB_DEVICE(0x1740, 0x9709)},	/* EnGenius 3072 */
138	{USB_DEVICE(0x13D3, 0x3273)},	/* AzureWave 3070 */
139	{USB_DEVICE(0x13D3, 0x3305)},	/* AzureWave 3070*/
140	{USB_DEVICE(0x1044, 0x800D)},	/* Gigabyte GN-WB32L 3070 */
141	{USB_DEVICE(0x2019, 0xAB25)},	/* Planex Communications, Inc. RT3070 */
142	{USB_DEVICE(0x07B8, 0x3070)},	/* AboCom 3070 */
143	{USB_DEVICE(0x07B8, 0x3071)},	/* AboCom 3071 */
144	{USB_DEVICE(0x07B8, 0x3072)},	/* Abocom 3072 */
145	{USB_DEVICE(0x7392, 0x7711)},	/* Edimax 3070 */
146	{USB_DEVICE(0x1A32, 0x0304)},	/* Quanta 3070 */
147	{USB_DEVICE(0x1EDA, 0x2310)},	/* AirTies 3070 */
148	{USB_DEVICE(0x07D1, 0x3C0A)},	/* D-Link 3072 */
149	{USB_DEVICE(0x07D1, 0x3C0D)},	/* D-Link 3070 */
150	{USB_DEVICE(0x07D1, 0x3C0E)},	/* D-Link 3070 */
151	{USB_DEVICE(0x07D1, 0x3C0F)},	/* D-Link 3070 */
152	{USB_DEVICE(0x07D1, 0x3C16)},	/* D-Link 3070 */
153	{USB_DEVICE(0x07D1, 0x3C17)},	/* D-Link 8070 */
154	{USB_DEVICE(0x1D4D, 0x000C)},	/* Pegatron Corporation 3070 */
155	{USB_DEVICE(0x1D4D, 0x000E)},	/* Pegatron Corporation 3070 */
156	{USB_DEVICE(0x5A57, 0x5257)},	/* Zinwell 3070 */
157	{USB_DEVICE(0x5A57, 0x0283)},	/* Zinwell 3072 */
158	{USB_DEVICE(0x04BB, 0x0945)},	/* I-O DATA 3072 */
159	{USB_DEVICE(0x04BB, 0x0947)},	/* I-O DATA 3070 */
160	{USB_DEVICE(0x04BB, 0x0948)},	/* I-O DATA 3072 */
161	{USB_DEVICE(0x203D, 0x1480)},	/* Encore 3070 */
162	{USB_DEVICE(0x20B8, 0x8888)},	/* PARA INDUSTRIAL 3070 */
163	{USB_DEVICE(0x0B05, 0x1784)},	/* Asus 3072 */
164	{USB_DEVICE(0x203D, 0x14A9)},	/* Encore 3070*/
165	{USB_DEVICE(0x0DB0, 0x899A)},	/* MSI 3070*/
166	{USB_DEVICE(0x0DB0, 0x3870)},	/* MSI 3070*/
167	{USB_DEVICE(0x0DB0, 0x870A)},	/* MSI 3070*/
168	{USB_DEVICE(0x0DB0, 0x6899)},	/* MSI 3070 */
169	{USB_DEVICE(0x0DB0, 0x3822)},	/* MSI 3070 */
170	{USB_DEVICE(0x0DB0, 0x3871)},	/* MSI 3070 */
171	{USB_DEVICE(0x0DB0, 0x871A)},	/* MSI 3070 */
172	{USB_DEVICE(0x0DB0, 0x822A)},	/* MSI 3070 */
173	{USB_DEVICE(0x0DB0, 0x3821)},	/* Ralink 3070 */
174	{USB_DEVICE(0x0DB0, 0x821A)},	/* Ralink 3070 */
175	{USB_DEVICE(0x083A, 0xA703)},	/* IO-MAGIC */
176	{USB_DEVICE(0x13D3, 0x3307)},	/* Azurewave */
177	{USB_DEVICE(0x13D3, 0x3321)},	/* Azurewave */
178	{USB_DEVICE(0x07FA, 0x7712)},	/* Edimax */
179	{USB_DEVICE(0x0789, 0x0166)},	/* Edimax */
180	{USB_DEVICE(0x148F, 0x2070)},	/* Edimax */
181#endif /* RT3070 // */
182	{USB_DEVICE(0x1737, 0x0077)},	/* Linksys WUSB54GC-EU v3 */
183	{USB_DEVICE(0x2001, 0x3C09)},	/* D-Link */
184	{USB_DEVICE(0x2001, 0x3C0A)},	/* D-Link 3072 */
185	{USB_DEVICE(0x2019, 0xED14)},	/* Planex Communications, Inc. */
186	{USB_DEVICE(0x0411, 0x015D)},	/* Buffalo Airstation WLI-UC-GN */
187	{}			/* Terminating entry */
188};
189
190int const rtusb_usb_id_len =
191    sizeof(rtusb_usb_id) / sizeof(struct usb_device_id);
192
193MODULE_DEVICE_TABLE(usb, rtusb_usb_id);
194
195static void rt2870_disconnect(struct usb_device *dev, struct rt_rtmp_adapter *pAd);
196
197static int __devinit rt2870_probe(IN struct usb_interface *intf,
198				  IN struct usb_device *usb_dev,
199				  IN const struct usb_device_id *dev_id,
200				  struct rt_rtmp_adapter **ppAd);
201
202#ifndef PF_NOFREEZE
203#define PF_NOFREEZE  0
204#endif
205
206extern int rt28xx_close(IN struct net_device *net_dev);
207extern int rt28xx_open(struct net_device *net_dev);
208
209static BOOLEAN USBDevConfigInit(IN struct usb_device *dev,
210				IN struct usb_interface *intf,
211				struct rt_rtmp_adapter *pAd);
212
213/*
214========================================================================
215Routine Description:
216    Check the chipset vendor/product ID.
217
218Arguments:
219    _dev_p				Point to the PCI or USB device
220
221Return Value:
222    TRUE				Check ok
223	FALSE				Check fail
224
225Note:
226========================================================================
227*/
228BOOLEAN RT28XXChipsetCheck(IN void *_dev_p)
229{
230	struct usb_interface *intf = (struct usb_interface *)_dev_p;
231	struct usb_device *dev_p = interface_to_usbdev(intf);
232	u32 i;
233
234	for (i = 0; i < rtusb_usb_id_len; i++) {
235		if (dev_p->descriptor.idVendor == rtusb_usb_id[i].idVendor &&
236		    dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct) {
237			printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
238			       dev_p->descriptor.idVendor,
239			       dev_p->descriptor.idProduct);
240			break;
241		}
242	}
243
244	if (i == rtusb_usb_id_len) {
245		printk("rt2870: Error! Device Descriptor not matching!\n");
246		return FALSE;
247	}
248
249	return TRUE;
250}
251
252/**************************************************************************/
253/**************************************************************************/
254/*tested for kernel 2.6series */
255/**************************************************************************/
256/**************************************************************************/
257
258#ifdef CONFIG_PM
259static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
260static int rt2870_resume(struct usb_interface *intf);
261#endif /* CONFIG_PM // */
262
263static BOOLEAN USBDevConfigInit(IN struct usb_device *dev,
264				IN struct usb_interface *intf,
265				struct rt_rtmp_adapter *pAd)
266{
267	struct usb_host_interface *iface_desc;
268	unsigned long BulkOutIdx;
269	u32 i;
270
271	/* get the active interface descriptor */
272	iface_desc = intf->cur_altsetting;
273
274	/* get # of enpoints  */
275	pAd->NumberOfPipes = iface_desc->desc.bNumEndpoints;
276	DBGPRINT(RT_DEBUG_TRACE,
277		 ("NumEndpoints=%d\n", iface_desc->desc.bNumEndpoints));
278
279	/* Configure Pipes */
280	BulkOutIdx = 0;
281
282	for (i = 0; i < pAd->NumberOfPipes; i++) {
283		if ((iface_desc->endpoint[i].desc.bmAttributes ==
284		     USB_ENDPOINT_XFER_BULK) &&
285		    ((iface_desc->endpoint[i].desc.bEndpointAddress &
286		      USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)) {
287			pAd->BulkInEpAddr =
288			    iface_desc->endpoint[i].desc.bEndpointAddress;
289			pAd->BulkInMaxPacketSize =
290			    le2cpu16(iface_desc->endpoint[i].desc.
291				     wMaxPacketSize);
292
293			DBGPRINT_RAW(RT_DEBUG_TRACE,
294				     ("BULK IN MaxPacketSize = %d\n",
295				      pAd->BulkInMaxPacketSize));
296			DBGPRINT_RAW(RT_DEBUG_TRACE,
297				     ("EP address = 0x%2x\n",
298				      iface_desc->endpoint[i].desc.
299				      bEndpointAddress));
300		} else
301		    if ((iface_desc->endpoint[i].desc.bmAttributes ==
302			 USB_ENDPOINT_XFER_BULK)
303			&&
304			((iface_desc->endpoint[i].desc.
305			  bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
306			 USB_DIR_OUT)) {
307			/* there are 6 bulk out EP. EP6 highest priority. */
308			/* EP1-4 is EDCA.  EP5 is HCCA. */
309			pAd->BulkOutEpAddr[BulkOutIdx++] =
310			    iface_desc->endpoint[i].desc.bEndpointAddress;
311			pAd->BulkOutMaxPacketSize =
312			    le2cpu16(iface_desc->endpoint[i].desc.
313				     wMaxPacketSize);
314
315			DBGPRINT_RAW(RT_DEBUG_TRACE,
316				     ("BULK OUT MaxPacketSize = %d\n",
317				      pAd->BulkOutMaxPacketSize));
318			DBGPRINT_RAW(RT_DEBUG_TRACE,
319				     ("EP address = 0x%2x  \n",
320				      iface_desc->endpoint[i].desc.
321				      bEndpointAddress));
322		}
323	}
324
325	if (!(pAd->BulkInEpAddr && pAd->BulkOutEpAddr[0])) {
326		printk
327		    ("%s: Could not find both bulk-in and bulk-out endpoints\n",
328		     __FUNCTION__);
329		return FALSE;
330	}
331
332	pAd->config = &dev->config->desc;
333	usb_set_intfdata(intf, pAd);
334
335	return TRUE;
336
337}
338
339static int __devinit rtusb_probe(struct usb_interface *intf,
340		       const struct usb_device_id *id)
341{
342	struct rt_rtmp_adapter *pAd;
343	struct usb_device *dev;
344	int rv;
345
346	dev = interface_to_usbdev(intf);
347	dev = usb_get_dev(dev);
348
349	rv = rt2870_probe(intf, dev, id, &pAd);
350	if (rv != 0)
351		usb_put_dev(dev);
352
353	return rv;
354}
355
356static void rtusb_disconnect(struct usb_interface *intf)
357{
358	struct usb_device *dev = interface_to_usbdev(intf);
359	struct rt_rtmp_adapter *pAd;
360
361	pAd = usb_get_intfdata(intf);
362	usb_set_intfdata(intf, NULL);
363
364	rt2870_disconnect(dev, pAd);
365}
366
367struct usb_driver rtusb_driver = {
368	.name = "rt2870",
369	.probe = rtusb_probe,
370	.disconnect = rtusb_disconnect,
371	.id_table = rtusb_usb_id,
372
373#ifdef CONFIG_PM
374suspend:rt2870_suspend,
375resume:rt2870_resume,
376#endif
377};
378
379#ifdef CONFIG_PM
380
381void RT2870RejectPendingPackets(struct rt_rtmp_adapter *pAd)
382{
383	/* clear PS packets */
384	/* clear TxSw packets */
385}
386
387static int rt2870_suspend(struct usb_interface *intf, pm_message_t state)
388{
389	struct net_device *net_dev;
390	struct rt_rtmp_adapter *pAd = usb_get_intfdata(intf);
391
392	DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_suspend()\n"));
393	net_dev = pAd->net_dev;
394	netif_device_detach(net_dev);
395
396	pAd->PM_FlgSuspend = 1;
397	if (netif_running(net_dev)) {
398		RTUSBCancelPendingBulkInIRP(pAd);
399		RTUSBCancelPendingBulkOutIRP(pAd);
400	}
401	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_suspend()\n"));
402	return 0;
403}
404
405static int rt2870_resume(struct usb_interface *intf)
406{
407	struct net_device *net_dev;
408	struct rt_rtmp_adapter *pAd = usb_get_intfdata(intf);
409
410	DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n"));
411
412	pAd->PM_FlgSuspend = 0;
413	net_dev = pAd->net_dev;
414	netif_device_attach(net_dev);
415	netif_start_queue(net_dev);
416	netif_carrier_on(net_dev);
417	netif_wake_queue(net_dev);
418
419	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n"));
420	return 0;
421}
422#endif /* CONFIG_PM // */
423
424/* Init driver module */
425int __init rtusb_init(void)
426{
427	printk("rtusb init --->\n");
428	return usb_register(&rtusb_driver);
429}
430
431/* Deinit driver module */
432void __exit rtusb_exit(void)
433{
434	usb_deregister(&rtusb_driver);
435	printk("<--- rtusb exit\n");
436}
437
438module_init(rtusb_init);
439module_exit(rtusb_exit);
440
441/*---------------------------------------------------------------------	*/
442/* function declarations												*/
443/*---------------------------------------------------------------------	*/
444
445/*
446========================================================================
447Routine Description:
448    MLME kernel thread.
449
450Arguments:
451	*Context			the pAd, driver control block pointer
452
453Return Value:
454    0					close the thread
455
456Note:
457========================================================================
458*/
459int MlmeThread(IN void *Context)
460{
461	struct rt_rtmp_adapter *pAd;
462	struct rt_rtmp_os_task *pTask;
463	int status;
464	status = 0;
465
466	pTask = Context;
467	pAd = pTask->priv;
468
469	RtmpOSTaskCustomize(pTask);
470
471	while (!pTask->task_killed) {
472#ifdef KTHREAD_SUPPORT
473		RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask);
474#else
475		RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status);
476
477		/* unlock the device pointers */
478		if (status != 0) {
479			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
480			break;
481		}
482#endif
483
484		/* lock the device pointers , need to check if required */
485		/*down(&(pAd->usbdev_semaphore)); */
486
487		if (!pAd->PM_FlgSuspend)
488			MlmeHandler(pAd);
489	}
490
491	/* notify the exit routine that we're actually exiting now
492	 *
493	 * complete()/wait_for_completion() is similar to up()/down(),
494	 * except that complete() is safe in the case where the structure
495	 * is getting deleted in a parallel mode of execution (i.e. just
496	 * after the down() -- that's necessary for the thread-shutdown
497	 * case.
498	 *
499	 * complete_and_exit() goes even further than this -- it is safe in
500	 * the case that the thread of the caller is going away (not just
501	 * the structure) -- this is necessary for the module-remove case.
502	 * This is important in preemption kernels, which transfer the flow
503	 * of execution immediately upon a complete().
504	 */
505	DBGPRINT(RT_DEBUG_TRACE, ("<---%s\n", __FUNCTION__));
506#ifndef KTHREAD_SUPPORT
507	pTask->taskPID = THREAD_PID_INIT_VALUE;
508	complete_and_exit(&pTask->taskComplete, 0);
509#endif
510	return 0;
511
512}
513
514/*
515========================================================================
516Routine Description:
517    USB command kernel thread.
518
519Arguments:
520	*Context			the pAd, driver control block pointer
521
522Return Value:
523    0					close the thread
524
525Note:
526========================================================================
527*/
528int RTUSBCmdThread(IN void *Context)
529{
530	struct rt_rtmp_adapter *pAd;
531	struct rt_rtmp_os_task *pTask;
532	int status;
533	status = 0;
534
535	pTask = Context;
536	pAd = pTask->priv;
537
538	RtmpOSTaskCustomize(pTask);
539
540	NdisAcquireSpinLock(&pAd->CmdQLock);
541	pAd->CmdQ.CmdQState = RTMP_TASK_STAT_RUNNING;
542	NdisReleaseSpinLock(&pAd->CmdQLock);
543
544	while (pAd && pAd->CmdQ.CmdQState == RTMP_TASK_STAT_RUNNING) {
545#ifdef KTHREAD_SUPPORT
546		RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask);
547#else
548		/* lock the device pointers */
549		RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status);
550
551		if (status != 0) {
552			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
553			break;
554		}
555#endif
556
557		if (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_STOPED)
558			break;
559
560		if (!pAd->PM_FlgSuspend)
561			CMDHandler(pAd);
562	}
563
564	if (pAd && !pAd->PM_FlgSuspend) {	/* Clear the CmdQElements. */
565		struct rt_cmdqelmt *pCmdQElmt = NULL;
566
567		NdisAcquireSpinLock(&pAd->CmdQLock);
568		pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED;
569		while (pAd->CmdQ.size) {
570			RTUSBDequeueCmd(&pAd->CmdQ, &pCmdQElmt);
571			if (pCmdQElmt) {
572				if (pCmdQElmt->CmdFromNdis == TRUE) {
573					if (pCmdQElmt->buffer != NULL)
574						os_free_mem(pAd,
575							    pCmdQElmt->buffer);
576					os_free_mem(pAd, (u8 *)pCmdQElmt);
577				} else {
578					if ((pCmdQElmt->buffer != NULL)
579					    && (pCmdQElmt->bufferlength != 0))
580						os_free_mem(pAd,
581							    pCmdQElmt->buffer);
582					os_free_mem(pAd, (u8 *)pCmdQElmt);
583				}
584			}
585		}
586
587		NdisReleaseSpinLock(&pAd->CmdQLock);
588	}
589	/* notify the exit routine that we're actually exiting now
590	 *
591	 * complete()/wait_for_completion() is similar to up()/down(),
592	 * except that complete() is safe in the case where the structure
593	 * is getting deleted in a parallel mode of execution (i.e. just
594	 * after the down() -- that's necessary for the thread-shutdown
595	 * case.
596	 *
597	 * complete_and_exit() goes even further than this -- it is safe in
598	 * the case that the thread of the caller is going away (not just
599	 * the structure) -- this is necessary for the module-remove case.
600	 * This is important in preemption kernels, which transfer the flow
601	 * of execution immediately upon a complete().
602	 */
603	DBGPRINT(RT_DEBUG_TRACE, ("<---RTUSBCmdThread\n"));
604
605#ifndef KTHREAD_SUPPORT
606	pTask->taskPID = THREAD_PID_INIT_VALUE;
607	complete_and_exit(&pTask->taskComplete, 0);
608#endif
609	return 0;
610
611}
612
613void RTUSBWatchDog(struct rt_rtmp_adapter *pAd)
614{
615	struct rt_ht_tx_context *pHTTXContext;
616	int idx;
617	unsigned long irqFlags;
618	PURB pUrb;
619	BOOLEAN needDumpSeq = FALSE;
620	u32 MACValue;
621	u32 TxRxQ_Pcnt;
622
623	idx = 0;
624	RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
625	if ((MACValue & 0xff) != 0) {
626		DBGPRINT(RT_DEBUG_TRACE,
627			 ("TX QUEUE 0 Not EMPTY(Value=0x%0x)!\n",
628			  MACValue));
629		RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
630		while ((MACValue & 0xff) != 0 && (idx++ < 10)) {
631			RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
632			RTMPusecDelay(1);
633		}
634		RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
635	}
636
637	if (pAd->watchDogRxOverFlowCnt >= 2) {
638		DBGPRINT(RT_DEBUG_TRACE,
639			 ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
640		if ((!RTMP_TEST_FLAG
641		     (pAd,
642		      (fRTMP_ADAPTER_RESET_IN_PROGRESS |
643		       fRTMP_ADAPTER_BULKIN_RESET |
644		       fRTMP_ADAPTER_HALT_IN_PROGRESS |
645		       fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
646			DBGPRINT(RT_DEBUG_TRACE,
647				 ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
648			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
649			RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN,
650						NULL, 0);
651			needDumpSeq = TRUE;
652		}
653		pAd->watchDogRxOverFlowCnt = 0;
654	}
655
656	RTUSBReadMACRegister(pAd, 0x438, &TxRxQ_Pcnt);
657
658	for (idx = 0; idx < NUM_OF_TX_RING; idx++) {
659		pUrb = NULL;
660
661		RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
662		if ((pAd->BulkOutPending[idx] == TRUE)
663		    && pAd->watchDogTxPendingCnt) {
664			int actual_length = 0, transfer_buffer_length = 0;
665			BOOLEAN isDataPacket = FALSE;
666			pAd->watchDogTxPendingCnt[idx]++;
667
668			if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
669			    (!RTMP_TEST_FLAG
670			     (pAd,
671			      (fRTMP_ADAPTER_RESET_IN_PROGRESS |
672			       fRTMP_ADAPTER_HALT_IN_PROGRESS |
673			       fRTMP_ADAPTER_NIC_NOT_EXIST |
674			       fRTMP_ADAPTER_BULKOUT_RESET)))
675			    ) {
676				pHTTXContext =
677				    (struct rt_ht_tx_context *)(&pAd->TxContext[idx]);
678				if (pHTTXContext->IRPPending) {	/* Check TxContext. */
679					pUrb = pHTTXContext->pUrb;
680
681					actual_length = pUrb->actual_length;
682					transfer_buffer_length =
683					    pUrb->transfer_buffer_length;
684					isDataPacket = TRUE;
685				} else if (idx == MGMTPIPEIDX) {
686					struct rt_tx_context *pMLMEContext, *pNULLContext,
687					    *pPsPollContext;
688
689					/*Check MgmtContext. */
690					pMLMEContext =
691					    (struct rt_tx_context *)(pAd->MgmtRing.
692							   Cell[pAd->MgmtRing.
693								TxDmaIdx].
694							   AllocVa);
695					pPsPollContext =
696					    (struct rt_tx_context *)(&pAd->PsPollContext);
697					pNULLContext =
698					    (struct rt_tx_context *)(&pAd->NullContext);
699
700					if (pMLMEContext->IRPPending) {
701						ASSERT(pMLMEContext->
702						       IRPPending);
703						pUrb = pMLMEContext->pUrb;
704					} else if (pNULLContext->IRPPending) {
705						ASSERT(pNULLContext->
706						       IRPPending);
707						pUrb = pNULLContext->pUrb;
708					} else if (pPsPollContext->IRPPending) {
709						ASSERT(pPsPollContext->
710						       IRPPending);
711						pUrb = pPsPollContext->pUrb;
712					}
713				}
714
715				RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx],
716						irqFlags);
717
718				printk(KERN_INFO "%d:%lu LTL=%d , TL=%d L:%d\n",
719				       idx, pAd->watchDogTxPendingCnt[idx],
720				       pAd->TransferedLength[idx],
721				       actual_length, transfer_buffer_length);
722
723				if (pUrb) {
724					if ((isDataPacket
725					     && pAd->TransferedLength[idx] ==
726					     actual_length
727					     && pAd->TransferedLength[idx] <
728					     transfer_buffer_length
729					     && actual_length != 0
730/*                                      && TxRxQ_Pcnt==0 */
731					     && pAd->watchDogTxPendingCnt[idx] >
732					     3)
733					    || isDataPacket == FALSE
734					    || pAd->watchDogTxPendingCnt[idx] >
735					    6) {
736						DBGPRINT(RT_DEBUG_TRACE,
737							 ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n",
738							  idx));
739						DBGPRINT(RT_DEBUG_TRACE,
740							 ("Unlink the pending URB!\n"));
741						/* unlink it now */
742						RTUSB_UNLINK_URB(pUrb);
743						/* Sleep 200 microseconds to give cancellation time to work */
744						/*RTMPusecDelay(200); */
745						needDumpSeq = TRUE;
746					}
747				} else {
748					DBGPRINT(RT_DEBUG_ERROR,
749						 ("Unknown bulkOut URB maybe hanged!\n"));
750				}
751			} else {
752				RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx],
753						irqFlags);
754			}
755
756			if (isDataPacket == TRUE)
757				pAd->TransferedLength[idx] = actual_length;
758		} else {
759			RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
760		}
761	}
762
763	/* For Sigma debug, dump the ba_reordering sequence. */
764	if ((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0)) {
765		u16 Idx;
766		struct rt_ba_rec_entry *pBAEntry = NULL;
767		u8 count = 0;
768		struct reordering_mpdu *mpdu_blk;
769
770		Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
771
772		pBAEntry = &pAd->BATable.BARecEntry[Idx];
773		if ((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL)) {
774			DBGPRINT(RT_DEBUG_TRACE,
775				 ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
776			NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
777			mpdu_blk = pBAEntry->list.next;
778			while (mpdu_blk) {
779				DBGPRINT(RT_DEBUG_TRACE,
780					 ("\t%d:Seq-%d, bAMSDU-%d!\n", count,
781					  mpdu_blk->Sequence,
782					  mpdu_blk->bAMSDU));
783				mpdu_blk = mpdu_blk->next;
784				count++;
785			}
786
787			DBGPRINT(RT_DEBUG_TRACE,
788				 ("\npBAEntry->LastIndSeq=%d!\n",
789				  pBAEntry->LastIndSeq));
790			NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
791		}
792	}
793}
794
795/*
796========================================================================
797Routine Description:
798    Release allocated resources.
799
800Arguments:
801    *dev				Point to the PCI or USB device
802	pAd					driver control block pointer
803
804Return Value:
805    None
806
807Note:
808========================================================================
809*/
810static void rt2870_disconnect(struct usb_device *dev, struct rt_rtmp_adapter *pAd)
811{
812	DBGPRINT(RT_DEBUG_ERROR,
813		 ("rtusb_disconnect: unregister usbnet usb-%s-%s\n",
814		  dev->bus->bus_name, dev->devpath));
815	if (!pAd) {
816		usb_put_dev(dev);
817		printk("rtusb_disconnect: pAd == NULL!\n");
818		return;
819	}
820	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
821
822	/* for debug, wait to show some messages to /proc system */
823	udelay(1);
824
825	RtmpPhyNetDevExit(pAd, pAd->net_dev);
826
827	udelay(1);
828	flush_scheduled_work();
829	udelay(1);
830
831	/* free the root net_device */
832	RtmpOSNetDevFree(pAd->net_dev);
833
834	RtmpRaDevCtrlExit(pAd);
835
836	/* release a use of the usb device structure */
837	usb_put_dev(dev);
838	udelay(1);
839
840	DBGPRINT(RT_DEBUG_ERROR, (" RTUSB disconnect successfully\n"));
841}
842
843static int __devinit rt2870_probe(IN struct usb_interface *intf,
844				  IN struct usb_device *usb_dev,
845				  IN const struct usb_device_id *dev_id,
846				  struct rt_rtmp_adapter **ppAd)
847{
848	struct net_device *net_dev = NULL;
849	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)NULL;
850	int status, rv;
851	void *handle;
852	struct rt_rtmp_os_netdev_op_hook netDevHook;
853
854	DBGPRINT(RT_DEBUG_TRACE, ("===>rt2870_probe()!\n"));
855
856	/* Check chipset vendor/product ID */
857	/*if (RT28XXChipsetCheck(_dev_p) == FALSE) */
858	/*      goto err_out; */
859
860/*RtmpDevInit============================================= */
861	/* Allocate struct rt_rtmp_adapter adapter structure */
862	handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
863	if (handle == NULL) {
864		printk
865		    ("rt2870_probe(): Allocate memory for os handle failed!\n");
866		return -ENOMEM;
867	}
868	((struct os_cookie *)handle)->pUsb_Dev = usb_dev;
869
870	rv = RTMPAllocAdapterBlock(handle, &pAd);
871	if (rv != NDIS_STATUS_SUCCESS) {
872		kfree(handle);
873		goto err_out;
874	}
875/*USBDevInit============================================== */
876	if (USBDevConfigInit(usb_dev, intf, pAd) == FALSE)
877		goto err_out_free_radev;
878
879	RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_USB);
880
881/*NetDevInit============================================== */
882	net_dev = RtmpPhyNetDevInit(pAd, &netDevHook);
883	if (net_dev == NULL)
884		goto err_out_free_radev;
885
886	/* Here are the net_device structure with usb specific parameters. */
887	/* for supporting Network Manager.
888	 * Set the sysfs physical device reference for the network logical device if set prior to registration will
889	 * cause a symlink during initialization.
890	 */
891	SET_NETDEV_DEV(net_dev, &(usb_dev->dev));
892
893	pAd->StaCfg.OriDevType = net_dev->type;
894
895/*All done, it's time to register the net device to linux kernel. */
896	/* Register this device */
897	status = RtmpOSNetDevAttach(net_dev, &netDevHook);
898	if (status != 0)
899		goto err_out_free_netdev;
900
901#ifdef KTHREAD_SUPPORT
902	init_waitqueue_head(&pAd->mlmeTask.kthread_q);
903	init_waitqueue_head(&pAd->timerTask.kthread_q);
904	init_waitqueue_head(&pAd->cmdQTask.kthread_q);
905#endif
906
907	*ppAd = pAd;
908
909	DBGPRINT(RT_DEBUG_TRACE, ("<===rt2870_probe()!\n"));
910
911	return 0;
912
913	/* --------------------------- ERROR HANDLE --------------------------- */
914err_out_free_netdev:
915	RtmpOSNetDevFree(net_dev);
916
917err_out_free_radev:
918	RTMPFreeAdapter(pAd);
919
920err_out:
921	*ppAd = NULL;
922
923	return -1;
924
925}
926