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