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