Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  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
 23MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
 24MODULE_LICENSE("GPL");
 25MODULE_VERSION("0.1");
 26
 27static 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
 38MODULE_DEVICE_TABLE(usb, wb35_table);
 39
 40static struct ieee80211_rate wbsoft_rates[] = {
 41	{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 42};
 43
 44static struct ieee80211_channel wbsoft_channels[] = {
 45	{ .center_freq = 2412 },
 46};
 47
 48static 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
 55static 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
 68static 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
 78static void wbsoft_remove_interface(struct ieee80211_hw *dev,
 79				    struct ieee80211_vif *vif)
 80{
 81	printk("wbsoft_remove interface called\n");
 82}
 83
 84static void wbsoft_stop(struct ieee80211_hw *hw)
 85{
 86	printk(KERN_INFO "%s called\n", __func__);
 87}
 88
 89static 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
 96static 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
102static 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
121static 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
146static 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
155static 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
172static 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
192static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
193{
194	hal_set_current_channel_ex(pHwData, channel);
195}
196
197static 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. */
213static 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
229static 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
242static 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
259static 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
280static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
281{
282	printk("wbsoft_get_tsf called\n");
283	return 0;
284}
285
286static 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
299static 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
314static 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
322static 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
336static 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
346u8 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 */
357static 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
375static 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
379static 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
384static 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
614static 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
645error_rx_destroy:
646	Wb35Rx_destroy(pHwData);
647error_tx_destroy:
648	Wb35Tx_destroy(pHwData);
649error_reg_destroy:
650	Wb35Reg_destroy(pHwData);
651
652	pHwData->SurpriseRemove = 1;
653	return -EINVAL;
654}
655
656static 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
737error:
738	return err;
739}
740
741static 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
817error_free_hw:
818	ieee80211_free_hw(dev);
819error:
820	usb_put_dev(udev);
821	return err;
822}
823
824static 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
834static 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
845static 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
860static struct usb_driver wb35_driver = {
861	.name		= "w35und",
862	.id_table	= wb35_table,
863	.probe		= wb35_probe,
864	.disconnect	= wb35_disconnect,
865};
866
867static int __init wb35_init(void)
868{
869	return usb_register(&wb35_driver);
870}
871
872static void __exit wb35_exit(void)
873{
874	usb_deregister(&wb35_driver);
875}
876
877module_init(wb35_init);
878module_exit(wb35_exit);