1 /*
2  * Copyright 2008 Pavel Machek <pavel@ucw.cz>
3  *
4  * Distribute under GPLv2.
5  *
6  * The original driver was written by:
7  *     Jeff Lee <YY_Lee@issc.com.tw>
8  *
9  * and was adapted to the 2.6 kernel by:
10  *     Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
11  */
12 #include <net/mac80211.h>
13 #include <linux/usb.h>
14 #include <linux/module.h>
15 
16 #include "core.h"
17 #include "mds_f.h"
18 #include "mto.h"
19 #include "wbhal.h"
20 #include "wb35reg_f.h"
21 #include "wb35tx_f.h"
22 #include "wb35rx_f.h"
23 
24 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
25 MODULE_LICENSE("GPL");
26 MODULE_VERSION("0.1");
27 
28 static const struct usb_device_id wb35_table[] __devinitconst = {
29 	{ USB_DEVICE(0x0416, 0x0035) },
30 	{ USB_DEVICE(0x18E8, 0x6201) },
31 	{ USB_DEVICE(0x18E8, 0x6206) },
32 	{ USB_DEVICE(0x18E8, 0x6217) },
33 	{ USB_DEVICE(0x18E8, 0x6230) },
34 	{ USB_DEVICE(0x18E8, 0x6233) },
35 	{ USB_DEVICE(0x1131, 0x2035) },
36 	{ 0, }
37 };
38 
39 MODULE_DEVICE_TABLE(usb, wb35_table);
40 
41 static struct ieee80211_rate wbsoft_rates[] = {
42 	{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
43 };
44 
45 static struct ieee80211_channel wbsoft_channels[] = {
46 	{ .center_freq = 2412 },
47 };
48 
49 static struct ieee80211_supported_band wbsoft_band_2GHz = {
50 	.channels	= wbsoft_channels,
51 	.n_channels	= ARRAY_SIZE(wbsoft_channels),
52 	.bitrates	= wbsoft_rates,
53 	.n_bitrates	= ARRAY_SIZE(wbsoft_rates),
54 };
55 
hal_set_beacon_period(struct hw_data * pHwData,u16 beacon_period)56 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
57 {
58 	u32 tmp;
59 
60 	if (pHwData->SurpriseRemove)
61 		return;
62 
63 	pHwData->BeaconPeriod = beacon_period;
64 	tmp = pHwData->BeaconPeriod << 16;
65 	tmp |= pHwData->ProbeDelay;
66 	Wb35Reg_Write(pHwData, 0x0848, tmp);
67 }
68 
wbsoft_add_interface(struct ieee80211_hw * dev,struct ieee80211_vif * vif)69 static int wbsoft_add_interface(struct ieee80211_hw *dev,
70 				struct ieee80211_vif *vif)
71 {
72 	struct wbsoft_priv *priv = dev->priv;
73 
74 	hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
75 
76 	return 0;
77 }
78 
wbsoft_remove_interface(struct ieee80211_hw * dev,struct ieee80211_vif * vif)79 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
80 				    struct ieee80211_vif *vif)
81 {
82 	printk("wbsoft_remove interface called\n");
83 }
84 
wbsoft_stop(struct ieee80211_hw * hw)85 static void wbsoft_stop(struct ieee80211_hw *hw)
86 {
87 	printk(KERN_INFO "%s called\n", __func__);
88 }
89 
wbsoft_get_stats(struct ieee80211_hw * hw,struct ieee80211_low_level_stats * stats)90 static int wbsoft_get_stats(struct ieee80211_hw *hw,
91 			    struct ieee80211_low_level_stats *stats)
92 {
93 	printk(KERN_INFO "%s called\n", __func__);
94 	return 0;
95 }
96 
wbsoft_prepare_multicast(struct ieee80211_hw * hw,struct netdev_hw_addr_list * mc_list)97 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
98 				    struct netdev_hw_addr_list *mc_list)
99 {
100 	return netdev_hw_addr_list_count(mc_list);
101 }
102 
wbsoft_configure_filter(struct ieee80211_hw * dev,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)103 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
104 				    unsigned int changed_flags,
105 				    unsigned int *total_flags,
106 				    u64 multicast)
107 {
108 	unsigned int new_flags;
109 
110 	new_flags = 0;
111 
112 	if (*total_flags & FIF_PROMISC_IN_BSS)
113 		new_flags |= FIF_PROMISC_IN_BSS;
114 	else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
115 		new_flags |= FIF_ALLMULTI;
116 
117 	dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
118 
119 	*total_flags = new_flags;
120 }
121 
wbsoft_tx(struct ieee80211_hw * dev,struct sk_buff * skb)122 static void wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
123 {
124 	struct wbsoft_priv *priv = dev->priv;
125 
126 	if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
127 		priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
128 		kfree_skb(skb);
129 		return;
130 	}
131 
132 	priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
133 
134 	priv->sMlmeFrame.pMMPDU		= skb->data;
135 	priv->sMlmeFrame.DataType	= FRAME_TYPE_802_11_MANAGEMENT;
136 	priv->sMlmeFrame.len		= skb->len;
137 	priv->sMlmeFrame.wNumTxMMPDU++;
138 
139 	/*
140 	 * H/W will enter power save by set the register. S/W don't send null
141 	 * frame with PWRMgt bit enbled to enter power save now.
142 	 */
143 
144 	Mds_Tx(priv);
145 }
146 
wbsoft_start(struct ieee80211_hw * dev)147 static int wbsoft_start(struct ieee80211_hw *dev)
148 {
149 	struct wbsoft_priv *priv = dev->priv;
150 
151 	priv->enabled = true;
152 
153 	return 0;
154 }
155 
hal_set_radio_mode(struct hw_data * pHwData,unsigned char radio_off)156 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
157 {
158 	struct wb35_reg *reg = &pHwData->reg;
159 
160 	if (pHwData->SurpriseRemove)
161 		return;
162 
163 	if (radio_off) {	/* disable Baseband receive off */
164 		pHwData->CurrentRadioSw = 1;	/* off */
165 		reg->M24_MacControl &= 0xffffffbf;
166 	} else {
167 		pHwData->CurrentRadioSw = 0;	/* on */
168 		reg->M24_MacControl |= 0x00000040;
169 	}
170 	Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
171 }
172 
hal_set_current_channel_ex(struct hw_data * pHwData,struct chan_info channel)173 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
174 {
175 	struct wb35_reg *reg = &pHwData->reg;
176 
177 	if (pHwData->SurpriseRemove)
178 		return;
179 
180 	printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
181 
182 	RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
183 	pHwData->Channel = channel.ChanNo;
184 	pHwData->band = channel.band;
185 	pr_debug("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band);
186 	reg->M28_MacControl &= ~0xff;	/* Clean channel information field */
187 	reg->M28_MacControl |= channel.ChanNo;
188 	Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
189 				       (s8 *) &channel,
190 				       sizeof(struct chan_info));
191 }
192 
hal_set_current_channel(struct hw_data * pHwData,struct chan_info channel)193 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
194 {
195 	hal_set_current_channel_ex(pHwData, channel);
196 }
197 
hal_set_accept_broadcast(struct hw_data * pHwData,u8 enable)198 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
199 {
200 	struct wb35_reg *reg = &pHwData->reg;
201 
202 	if (pHwData->SurpriseRemove)
203 		return;
204 
205 	reg->M00_MacControl &= ~0x02000000;	/* The HW value */
206 
207 	if (enable)
208 		reg->M00_MacControl |= 0x02000000;	/* The HW value */
209 
210 	Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
211 }
212 
213 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
hal_set_accept_promiscuous(struct hw_data * pHwData,u8 enable)214 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
215 {
216 	struct wb35_reg *reg = &pHwData->reg;
217 
218 	if (pHwData->SurpriseRemove)
219 		return;
220 
221 	if (enable) {
222 		reg->M00_MacControl |= 0x00400000;
223 		Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
224 	} else {
225 		reg->M00_MacControl &= ~0x00400000;
226 		Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
227 	}
228 }
229 
hal_set_accept_multicast(struct hw_data * pHwData,u8 enable)230 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
231 {
232 	struct wb35_reg *reg = &pHwData->reg;
233 
234 	if (pHwData->SurpriseRemove)
235 		return;
236 
237 	reg->M00_MacControl &= ~0x01000000;	/* The HW value */
238 	if (enable)
239 		reg->M00_MacControl |= 0x01000000;	/* The HW value */
240 	Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
241 }
242 
hal_set_accept_beacon(struct hw_data * pHwData,u8 enable)243 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
244 {
245 	struct wb35_reg *reg = &pHwData->reg;
246 
247 	if (pHwData->SurpriseRemove)
248 		return;
249 
250 	if (!enable)	/* Due to SME and MLME are not suitable for 35 */
251 		return;
252 
253 	reg->M00_MacControl &= ~0x04000000;	/* The HW value */
254 	if (enable)
255 		reg->M00_MacControl |= 0x04000000;	/* The HW value */
256 
257 	Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
258 }
259 
wbsoft_config(struct ieee80211_hw * dev,u32 changed)260 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
261 {
262 	struct wbsoft_priv *priv = dev->priv;
263 	struct chan_info ch;
264 
265 	printk("wbsoft_config called\n");
266 
267 	/* Should use channel_num, or something, as that is already pre-translated */
268 	ch.band = 1;
269 	ch.ChanNo = 1;
270 
271 	hal_set_current_channel(&priv->sHwData, ch);
272 	hal_set_accept_broadcast(&priv->sHwData, 1);
273 	hal_set_accept_promiscuous(&priv->sHwData, 1);
274 	hal_set_accept_multicast(&priv->sHwData, 1);
275 	hal_set_accept_beacon(&priv->sHwData, 1);
276 	hal_set_radio_mode(&priv->sHwData, 0);
277 
278 	return 0;
279 }
280 
wbsoft_get_tsf(struct ieee80211_hw * dev,struct ieee80211_vif * vif)281 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
282 {
283 	printk("wbsoft_get_tsf called\n");
284 	return 0;
285 }
286 
287 static const struct ieee80211_ops wbsoft_ops = {
288 	.tx			= wbsoft_tx,
289 	.start			= wbsoft_start,
290 	.stop			= wbsoft_stop,
291 	.add_interface		= wbsoft_add_interface,
292 	.remove_interface	= wbsoft_remove_interface,
293 	.config			= wbsoft_config,
294 	.prepare_multicast	= wbsoft_prepare_multicast,
295 	.configure_filter	= wbsoft_configure_filter,
296 	.get_stats		= wbsoft_get_stats,
297 	.get_tsf		= wbsoft_get_tsf,
298 };
299 
hal_set_ethernet_address(struct hw_data * pHwData,u8 * current_address)300 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
301 {
302 	u32 ltmp[2];
303 
304 	if (pHwData->SurpriseRemove)
305 		return;
306 
307 	memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
308 
309 	ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
310 	ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
311 
312 	Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
313 }
314 
hal_get_permanent_address(struct hw_data * pHwData,u8 * pethernet_address)315 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
316 {
317 	if (pHwData->SurpriseRemove)
318 		return;
319 
320 	memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
321 }
322 
hal_stop(struct hw_data * pHwData)323 static void hal_stop(struct hw_data *pHwData)
324 {
325 	struct wb35_reg *reg = &pHwData->reg;
326 
327 	pHwData->Wb35Rx.rx_halt = 1;
328 	Wb35Rx_stop(pHwData);
329 
330 	pHwData->Wb35Tx.tx_halt = 1;
331 	Wb35Tx_stop(pHwData);
332 
333 	reg->D00_DmaControl &= ~0xc0000000;	/* Tx Off, Rx Off */
334 	Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
335 }
336 
hal_idle(struct hw_data * pHwData)337 static unsigned char hal_idle(struct hw_data *pHwData)
338 {
339 	struct wb35_reg *reg = &pHwData->reg;
340 
341 	if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
342 		return false;
343 
344 	return true;
345 }
346 
hal_get_antenna_number(struct hw_data * pHwData)347 u8 hal_get_antenna_number(struct hw_data *pHwData)
348 {
349 	struct wb35_reg *reg = &pHwData->reg;
350 
351 	if ((reg->BB2C & BIT(11)) == 0)
352 		return 0;
353 	else
354 		return 1;
355 }
356 
357 /* 0 : radio on; 1: radio off */
hal_get_hw_radio_off(struct hw_data * pHwData)358 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
359 {
360 	struct wb35_reg *reg = &pHwData->reg;
361 
362 	if (pHwData->SurpriseRemove)
363 		return 1;
364 
365 	/* read the bit16 of register U1B0 */
366 	Wb35Reg_Read(pHwData, 0x3b0, &reg->U1B0);
367 	if ((reg->U1B0 & 0x00010000)) {
368 		pHwData->CurrentRadioHw = 1;
369 		return 1;
370 	} else {
371 		pHwData->CurrentRadioHw = 0;
372 		return 0;
373 	}
374 }
375 
376 static u8 LED_GRAY[20] = {
377 	0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
378 };
379 
380 static u8 LED_GRAY2[30] = {
381 	7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
382 	0, 15, 14, 13, 12, 11, 10, 9, 8
383 };
384 
hal_led_control(unsigned long data)385 static void hal_led_control(unsigned long data)
386 {
387 	struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
388 	struct hw_data *pHwData = &adapter->sHwData;
389 	struct wb35_reg *reg = &pHwData->reg;
390 	u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
391 	u32 TimeInterval = 500, ltmp, ltmp2;
392 	ltmp = 0;
393 
394 	if (pHwData->SurpriseRemove)
395 		return;
396 
397 	if (pHwData->LED_control) {
398 		ltmp2 = pHwData->LED_control & 0xff;
399 		if (ltmp2 == 5)	{ /* 5 is WPS mode */
400 			TimeInterval = 100;
401 			ltmp2 = (pHwData->LED_control >> 8) & 0xff;
402 			switch (ltmp2) {
403 			case 1:	/* [0.2 On][0.1 Off]... */
404 				pHwData->LED_Blinking %= 3;
405 				ltmp = 0x1010;	/* Led 1 & 0 Green and Red */
406 				if (pHwData->LED_Blinking == 2)	/* Turn off */
407 					ltmp = 0;
408 				break;
409 			case 2:	/* [0.1 On][0.1 Off]... */
410 				pHwData->LED_Blinking %= 2;
411 				ltmp = 0x0010;	/* Led 0 red color */
412 				if (pHwData->LED_Blinking) /* Turn off */
413 					ltmp = 0;
414 				break;
415 			case 3:	/* [0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.1 On][0.1 Off][0.5 Off]... */
416 				pHwData->LED_Blinking %= 15;
417 				ltmp = 0x0010;	/* Led 0 red color */
418 				if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
419 					ltmp = 0;
420 				break;
421 			case 4:	/* [300 On][ off ] */
422 				ltmp = 0x1000;	/* Led 1 Green color */
423 				if (pHwData->LED_Blinking >= 3000)
424 					ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
425 				break;
426 			}
427 			pHwData->LED_Blinking++;
428 
429 			reg->U1BC_LEDConfigure = ltmp;
430 			if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
431 				reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
432 				reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
433 			}
434 			Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
435 		}
436 	} else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
437 		if (reg->U1BC_LEDConfigure & 0x1010) {
438 			reg->U1BC_LEDConfigure &= ~0x1010;
439 			Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
440 		}
441 	} else {
442 		switch (LEDSet) {
443 		case 4:	/* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
444 			if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
445 				/* Blinking if scanning is on progress */
446 				if (pHwData->LED_Scanning) {
447 					if (pHwData->LED_Blinking == 0) {
448 						reg->U1BC_LEDConfigure |= 0x10;
449 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 On */
450 						pHwData->LED_Blinking = 1;
451 						TimeInterval = 300;
452 					} else {
453 						reg->U1BC_LEDConfigure &= ~0x10;
454 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
455 						pHwData->LED_Blinking = 0;
456 						TimeInterval = 300;
457 					}
458 				} else {
459 					/* Turn Off LED_0 */
460 					if (reg->U1BC_LEDConfigure & 0x10) {
461 						reg->U1BC_LEDConfigure &= ~0x10;
462 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
463 					}
464 				}
465 			} else {
466 				/* Turn On LED_0 */
467 				if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
468 					reg->U1BC_LEDConfigure |= 0x10;
469 					Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
470 				}
471 			}
472 			break;
473 		case 6:	/* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
474 			if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
475 				/* Blinking if scanning is on progress */
476 				if (pHwData->LED_Scanning) {
477 					if (pHwData->LED_Blinking == 0) {
478 						reg->U1BC_LEDConfigure &= ~0xf;
479 						reg->U1BC_LEDConfigure |= 0x10;
480 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 On */
481 						pHwData->LED_Blinking = 1;
482 						TimeInterval = 300;
483 					} else {
484 						reg->U1BC_LEDConfigure &= ~0x1f;
485 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
486 						pHwData->LED_Blinking = 0;
487 						TimeInterval = 300;
488 					}
489 				} else {
490 					/* Gray blinking if in disconnect state and not scanning */
491 					ltmp = reg->U1BC_LEDConfigure;
492 					reg->U1BC_LEDConfigure &= ~0x1f;
493 					if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
494 						reg->U1BC_LEDConfigure |= 0x10;
495 						reg->U1BC_LEDConfigure |=
496 						    LED_GRAY2[(pHwData->LED_Blinking % 30)];
497 					}
498 					pHwData->LED_Blinking++;
499 					if (reg->U1BC_LEDConfigure != ltmp)
500 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
501 					TimeInterval = 100;
502 				}
503 			} else {
504 				/* Turn On LED_0 */
505 				if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
506 					reg->U1BC_LEDConfigure |= 0x10;
507 					Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_0 Off */
508 				}
509 			}
510 			break;
511 		case 5:	/* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
512 			if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
513 				/* Blinking if scanning is on progress */
514 				if (pHwData->LED_Scanning) {
515 					if (pHwData->LED_Blinking == 0) {
516 						reg->U1BC_LEDConfigure |= 0x1000;
517 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_1 On */
518 						pHwData->LED_Blinking = 1;
519 						TimeInterval = 300;
520 					} else {
521 						reg->U1BC_LEDConfigure &= ~0x1000;
522 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_1 Off */
523 						pHwData->LED_Blinking = 0;
524 						TimeInterval = 300;
525 					}
526 				} else {
527 					/* Turn Off LED_1 */
528 					if (reg->U1BC_LEDConfigure & 0x1000) {
529 						reg->U1BC_LEDConfigure &= ~0x1000;
530 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_1 Off */
531 					}
532 				}
533 			} else {
534 				/* Is transmitting/receiving ?? */
535 				if ((adapter->RxByteCount !=
536 				     pHwData->RxByteCountLast)
537 				    || (adapter->TxByteCount !=
538 					pHwData->TxByteCountLast)) {
539 					if ((reg->U1BC_LEDConfigure & 0x3000) !=
540 					    0x3000) {
541 						reg->U1BC_LEDConfigure |= 0x3000;
542 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_1 On */
543 					}
544 					/* Update variable */
545 					pHwData->RxByteCountLast =
546 					    adapter->RxByteCount;
547 					pHwData->TxByteCountLast =
548 					    adapter->TxByteCount;
549 					TimeInterval = 200;
550 				} else {
551 					/* Turn On LED_1 and blinking if transmitting/receiving */
552 					if ((reg->U1BC_LEDConfigure & 0x3000) !=
553 					    0x1000) {
554 						reg->U1BC_LEDConfigure &=
555 						    ~0x3000;
556 						reg->U1BC_LEDConfigure |=
557 						    0x1000;
558 						Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);	/* LED_1 On */
559 					}
560 				}
561 			}
562 			break;
563 		default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
564 			if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
565 				reg->U1BC_LEDConfigure |= 0x3000;	/* LED_1 is always on and event enable */
566 				Wb35Reg_Write(pHwData, 0x03bc,
567 					      reg->U1BC_LEDConfigure);
568 			}
569 
570 			if (pHwData->LED_Blinking) {
571 				/* Gray blinking */
572 				reg->U1BC_LEDConfigure &= ~0x0f;
573 				reg->U1BC_LEDConfigure |= 0x10;
574 				reg->U1BC_LEDConfigure |=
575 				    LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
576 				Wb35Reg_Write(pHwData, 0x03bc,
577 					      reg->U1BC_LEDConfigure);
578 
579 				pHwData->LED_Blinking += 2;
580 				if (pHwData->LED_Blinking < 40)
581 					TimeInterval = 100;
582 				else {
583 					pHwData->LED_Blinking = 0; /* Stop blinking */
584 					reg->U1BC_LEDConfigure &= ~0x0f;
585 					Wb35Reg_Write(pHwData, 0x03bc,
586 						      reg->U1BC_LEDConfigure);
587 				}
588 				break;
589 			}
590 
591 			if (pHwData->LED_LinkOn) {
592 				if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
593 					/* Try to turn ON LED_0 after gray blinking */
594 					reg->U1BC_LEDConfigure |= 0x10;
595 					pHwData->LED_Blinking = 1; /* Start blinking */
596 					TimeInterval = 50;
597 				}
598 			} else {
599 				if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
600 					reg->U1BC_LEDConfigure &= ~0x10;
601 					Wb35Reg_Write(pHwData, 0x03bc,
602 						      reg->U1BC_LEDConfigure);
603 				}
604 			}
605 			break;
606 		}
607 	}
608 
609 	pHwData->time_count += TimeInterval;
610 	Wb35Tx_CurrentTime(adapter, pHwData->time_count);
611 	pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
612 	add_timer(&pHwData->LEDTimer);
613 }
614 
hal_init_hardware(struct ieee80211_hw * hw)615 static int hal_init_hardware(struct ieee80211_hw *hw)
616 {
617 	struct wbsoft_priv *priv = hw->priv;
618 	struct hw_data *pHwData = &priv->sHwData;
619 	u16 SoftwareSet;
620 
621 	pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
622 	pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
623 
624 	if (!Wb35Reg_initial(pHwData))
625 		goto error_reg_destroy;
626 
627 	if (!Wb35Tx_initial(pHwData))
628 		goto error_tx_destroy;
629 
630 	if (!Wb35Rx_initial(pHwData))
631 		goto error_rx_destroy;
632 
633 	init_timer(&pHwData->LEDTimer);
634 	pHwData->LEDTimer.function = hal_led_control;
635 	pHwData->LEDTimer.data = (unsigned long)priv;
636 	pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
637 	add_timer(&pHwData->LEDTimer);
638 
639 	SoftwareSet = hal_software_set(pHwData);
640 
641 	Wb35Rx_start(hw);
642 	Wb35Tx_EP2VM_start(priv);
643 
644 	return 0;
645 
646 error_rx_destroy:
647 	Wb35Rx_destroy(pHwData);
648 error_tx_destroy:
649 	Wb35Tx_destroy(pHwData);
650 error_reg_destroy:
651 	Wb35Reg_destroy(pHwData);
652 
653 	pHwData->SurpriseRemove = 1;
654 	return -EINVAL;
655 }
656 
wb35_hw_init(struct ieee80211_hw * hw)657 static int wb35_hw_init(struct ieee80211_hw *hw)
658 {
659 	struct wbsoft_priv *priv = hw->priv;
660 	struct hw_data *pHwData = &priv->sHwData;
661 	u8 EEPROM_region;
662 	u8 HwRadioOff;
663 	u8 *pMacAddr2;
664 	u8 *pMacAddr;
665 	int err;
666 
667 	pHwData->phy_type = RF_DECIDE_BY_INF;
668 
669 	priv->Mds.TxRTSThreshold		= DEFAULT_RTSThreshold;
670 	priv->Mds.TxFragmentThreshold		= DEFAULT_FRAGMENT_THRESHOLD;
671 
672 	priv->sLocalPara.region_INF		= REGION_AUTO;
673 	priv->sLocalPara.TxRateMode		= RATE_AUTO;
674 	priv->sLocalPara.bMacOperationMode	= MODE_802_11_BG;
675 	priv->sLocalPara.MTUsize		= MAX_ETHERNET_PACKET_SIZE;
676 	priv->sLocalPara.bPreambleMode		= AUTO_MODE;
677 	priv->sLocalPara.bWepKeyError		= false;
678 	priv->sLocalPara.bToSelfPacketReceived	= false;
679 	priv->sLocalPara.WepKeyDetectTimerCount	= 2 * 100; /* 2 seconds */
680 
681 	priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
682 
683 	err = hal_init_hardware(hw);
684 	if (err)
685 		goto error;
686 
687 	EEPROM_region = hal_get_region_from_EEPROM(pHwData);
688 	if (EEPROM_region != REGION_AUTO)
689 		priv->sLocalPara.region = EEPROM_region;
690 	else {
691 		if (priv->sLocalPara.region_INF != REGION_AUTO)
692 			priv->sLocalPara.region = priv->sLocalPara.region_INF;
693 		else
694 			priv->sLocalPara.region = REGION_USA;	/* default setting */
695 	}
696 
697 	Mds_initial(priv);
698 
699 	/*
700 	 * If no user-defined address in the registry, use the address
701 	 * "burned" on the NIC instead.
702 	 */
703 	pMacAddr = priv->sLocalPara.ThisMacAddress;
704 	pMacAddr2 = priv->sLocalPara.PermanentAddress;
705 
706 	/* Reading ethernet address from EEPROM */
707 	hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
708 	if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
709 		memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
710 	else {
711 		/* Set the user define MAC address */
712 		hal_set_ethernet_address(pHwData,
713 					 priv->sLocalPara.ThisMacAddress);
714 	}
715 
716 	priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
717 	pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
718 	hal_get_hw_radio_off(pHwData);
719 
720 	/* Waiting for HAL setting OK */
721 	while (!hal_idle(pHwData))
722 		msleep(10);
723 
724 	MTO_Init(priv);
725 
726 	HwRadioOff = hal_get_hw_radio_off(pHwData);
727 	priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
728 
729 	hal_set_radio_mode(pHwData,
730 			   (unsigned char)(priv->sLocalPara.RadioOffStatus.
731 					   boSwRadioOff
732 					   || priv->sLocalPara.RadioOffStatus.
733 					   boHwRadioOff));
734 
735 	/* Notify hal that the driver is ready now. */
736 	hal_driver_init_OK(pHwData) = 1;
737 
738 error:
739 	return err;
740 }
741 
wb35_probe(struct usb_interface * intf,const struct usb_device_id * id_table)742 static int wb35_probe(struct usb_interface *intf,
743 		      const struct usb_device_id *id_table)
744 {
745 	struct usb_device *udev = interface_to_usbdev(intf);
746 	struct usb_endpoint_descriptor *endpoint;
747 	struct usb_host_interface *interface;
748 	struct ieee80211_hw *dev;
749 	struct wbsoft_priv *priv;
750 	int nr, err;
751 	u32 ltmp;
752 
753 	usb_get_dev(udev);
754 
755 	/* Check the device if it already be opened */
756 	nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
757 			     0x01,
758 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
759 			     0x0, 0x400, &ltmp, 4, HZ * 100);
760 	if (nr < 0) {
761 		err = nr;
762 		goto error;
763 	}
764 
765 	/* Is already initialized? */
766 	ltmp = cpu_to_le32(ltmp);
767 	if (ltmp) {
768 		err = -EBUSY;
769 		goto error;
770 	}
771 
772 	dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
773 	if (!dev) {
774 		err = -ENOMEM;
775 		goto error;
776 	}
777 
778 	priv = dev->priv;
779 
780 	priv->sHwData.udev = udev;
781 
782 	interface = intf->cur_altsetting;
783 	endpoint = &interface->endpoint[0].desc;
784 
785 	if (endpoint[2].wMaxPacketSize == 512)
786 		printk("[w35und] Working on USB 2.0\n");
787 
788 	err = wb35_hw_init(dev);
789 	if (err)
790 		goto error_free_hw;
791 
792 	SET_IEEE80211_DEV(dev, &udev->dev);
793 	{
794 		struct hw_data *pHwData = &priv->sHwData;
795 		unsigned char dev_addr[MAX_ADDR_LEN];
796 		hal_get_permanent_address(pHwData, dev_addr);
797 		SET_IEEE80211_PERM_ADDR(dev, dev_addr);
798 	}
799 
800 	dev->extra_tx_headroom = 12;	/* FIXME */
801 	dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
802 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
803 
804 	dev->channel_change_time = 1000;
805 	dev->max_signal = 100;
806 	dev->queues = 1;
807 
808 	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
809 
810 	err = ieee80211_register_hw(dev);
811 	if (err)
812 		goto error_free_hw;
813 
814 	usb_set_intfdata(intf, dev);
815 
816 	return 0;
817 
818 error_free_hw:
819 	ieee80211_free_hw(dev);
820 error:
821 	usb_put_dev(udev);
822 	return err;
823 }
824 
hal_halt(struct hw_data * pHwData)825 static void hal_halt(struct hw_data *pHwData)
826 {
827 	del_timer_sync(&pHwData->LEDTimer);
828 	/* XXX: Wait for Timer DPC exit. */
829 	msleep(100);
830 	Wb35Rx_destroy(pHwData);
831 	Wb35Tx_destroy(pHwData);
832 	Wb35Reg_destroy(pHwData);
833 }
834 
wb35_hw_halt(struct wbsoft_priv * adapter)835 static void wb35_hw_halt(struct wbsoft_priv *adapter)
836 {
837 	/* Turn off Rx and Tx hardware ability */
838 	hal_stop(&adapter->sHwData);
839 	pr_debug("[w35und] Hal_stop O.K.\n");
840 	/* Waiting Irp completed */
841 	msleep(100);
842 
843 	hal_halt(&adapter->sHwData);
844 }
845 
wb35_disconnect(struct usb_interface * intf)846 static void wb35_disconnect(struct usb_interface *intf)
847 {
848 	struct ieee80211_hw *hw = usb_get_intfdata(intf);
849 	struct wbsoft_priv *priv = hw->priv;
850 
851 	wb35_hw_halt(priv);
852 
853 	ieee80211_stop_queues(hw);
854 	ieee80211_unregister_hw(hw);
855 	ieee80211_free_hw(hw);
856 
857 	usb_set_intfdata(intf, NULL);
858 	usb_put_dev(interface_to_usbdev(intf));
859 }
860 
861 static struct usb_driver wb35_driver = {
862 	.name		= "w35und",
863 	.id_table	= wb35_table,
864 	.probe		= wb35_probe,
865 	.disconnect	= wb35_disconnect,
866 };
867 
868 module_usb_driver(wb35_driver);
869