]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/winbond/wbusb.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[mirror_ubuntu-artful-kernel.git] / drivers / staging / winbond / wbusb.c
CommitLineData
66101de1 1/*
a2531293 2 * Copyright 2008 Pavel Machek <pavel@ucw.cz>
66101de1
PM
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 13#include <linux/usb.h>
45296236 14#include <linux/module.h>
80aba536 15
cc180710 16#include "core.h"
912b209f 17#include "mds_f.h"
64328c87 18#include "mto.h"
b5ef0761 19#include "wbhal.h"
72ca8819
PE
20#include "wb35reg_f.h"
21#include "wb35tx_f.h"
22#include "wb35rx_f.h"
66101de1 23
7b9a79bf 24MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
66101de1
PM
25MODULE_LICENSE("GPL");
26MODULE_VERSION("0.1");
27
a457732b 28static const struct usb_device_id wb35_table[] __devinitconst = {
a32b9810
PE
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) },
68ab0c96 36 { 0, }
66101de1
PM
37};
38
dd38da46 39MODULE_DEVICE_TABLE(usb, wb35_table);
66101de1 40
68ab0c96 41static struct ieee80211_rate wbsoft_rates[] = {
66101de1
PM
42 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
43};
44
68ab0c96 45static struct ieee80211_channel wbsoft_channels[] = {
a32b9810 46 { .center_freq = 2412 },
66101de1
PM
47};
48
a36e0894
PE
49static 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
4074e77c
PE
56static 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
66101de1 69static int wbsoft_add_interface(struct ieee80211_hw *dev,
a71b676f 70 struct ieee80211_vif *vif)
66101de1 71{
4074e77c
PE
72 struct wbsoft_priv *priv = dev->priv;
73
a71b676f 74 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
4074e77c 75
66101de1
PM
76 return 0;
77}
78
79static void wbsoft_remove_interface(struct ieee80211_hw *dev,
a71b676f 80 struct ieee80211_vif *vif)
66101de1
PM
81{
82 printk("wbsoft_remove interface called\n");
83}
84
68ab0c96 85static void wbsoft_stop(struct ieee80211_hw *hw)
66101de1 86{
68ab0c96
GKH
87 printk(KERN_INFO "%s called\n", __func__);
88}
89
90static 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
22bedad3
JP
97static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
98 struct netdev_hw_addr_list *mc_list)
6d7fd647 99{
22bedad3 100 return netdev_hw_addr_list_count(mc_list);
6d7fd647
JM
101}
102
66101de1 103static void wbsoft_configure_filter(struct ieee80211_hw *dev,
a32b9810
PE
104 unsigned int changed_flags,
105 unsigned int *total_flags,
6d7fd647 106 u64 multicast)
66101de1 107{
6ab32127 108 unsigned int new_flags;
66101de1
PM
109
110 new_flags = 0;
111
6ab32127 112 if (*total_flags & FIF_PROMISC_IN_BSS)
66101de1 113 new_flags |= FIF_PROMISC_IN_BSS;
6d7fd647 114 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
66101de1 115 new_flags |= FIF_ALLMULTI;
66101de1
PM
116
117 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
118
119 *total_flags = new_flags;
120}
121
7bb45683 122static void wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
66101de1 123{
cc180710
PE
124 struct wbsoft_priv *priv = dev->priv;
125
11c9a55d
PE
126 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
127 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
7bb45683
JB
128 kfree_skb(skb);
129 return;
11c9a55d
PE
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);
66101de1
PM
145}
146
66101de1
PM
147static int wbsoft_start(struct ieee80211_hw *dev)
148{
c930e0c0
PE
149 struct wbsoft_priv *priv = dev->priv;
150
151 priv->enabled = true;
152
66101de1
PM
153 return 0;
154}
155
22a82bcd
PE
156static 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
e5851c20
LL
163 if (radio_off) { /* disable Baseband receive off */
164 pHwData->CurrentRadioSw = 1; /* off */
22a82bcd
PE
165 reg->M24_MacControl &= 0xffffffbf;
166 } else {
e5851c20 167 pHwData->CurrentRadioSw = 0; /* on */
22a82bcd
PE
168 reg->M24_MacControl |= 0x00000040;
169 }
170 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
171}
172
e5851c20 173static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
22a82bcd
PE
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
e5851c20 182 RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
22a82bcd
PE
183 pHwData->Channel = channel.ChanNo;
184 pHwData->band = channel.band;
2855bb79 185 pr_debug("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band);
e5851c20 186 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
22a82bcd
PE
187 reg->M28_MacControl |= channel.ChanNo;
188 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
e5851c20
LL
189 (s8 *) &channel,
190 sizeof(struct chan_info));
22a82bcd
PE
191}
192
440a233d 193static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
22a82bcd
PE
194{
195 hal_set_current_channel_ex(pHwData, channel);
196}
197
198static 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
e5851c20 205 reg->M00_MacControl &= ~0x02000000; /* The HW value */
22a82bcd
PE
206
207 if (enable)
e5851c20 208 reg->M00_MacControl |= 0x02000000; /* The HW value */
22a82bcd
PE
209
210 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
211}
212
e5851c20 213/* For wep key error detection, we need to accept broadcast packets to be received temporary. */
22a82bcd
PE
214static 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;
e5851c20 220
22a82bcd
PE
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
230static 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
e5851c20 237 reg->M00_MacControl &= ~0x01000000; /* The HW value */
22a82bcd 238 if (enable)
e5851c20 239 reg->M00_MacControl |= 0x01000000; /* The HW value */
22a82bcd
PE
240 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
241}
242
243static 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
e5851c20 250 if (!enable) /* Due to SME and MLME are not suitable for 35 */
22a82bcd
PE
251 return;
252
e5851c20 253 reg->M00_MacControl &= ~0x04000000; /* The HW value */
22a82bcd 254 if (enable)
e5851c20 255 reg->M00_MacControl |= 0x04000000; /* The HW value */
22a82bcd
PE
256
257 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
258}
259
f02466fc 260static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
66101de1 261{
cc180710 262 struct wbsoft_priv *priv = dev->priv;
440a233d 263 struct chan_info ch;
f02466fc 264
66101de1
PM
265 printk("wbsoft_config called\n");
266
bdbb8839 267 /* Should use channel_num, or something, as that is already pre-translated */
66101de1 268 ch.band = 1;
bdbb8839 269 ch.ChanNo = 1;
66101de1 270
1e8a2b60 271 hal_set_current_channel(&priv->sHwData, ch);
1e8a2b60 272 hal_set_accept_broadcast(&priv->sHwData, 1);
a32b9810
PE
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);
66101de1
PM
277
278 return 0;
279}
280
37a41b4a 281static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
66101de1
PM
282{
283 printk("wbsoft_get_tsf called\n");
284 return 0;
285}
286
287static const struct ieee80211_ops wbsoft_ops = {
288 .tx = wbsoft_tx,
bdbb8839 289 .start = wbsoft_start,
68ab0c96 290 .stop = wbsoft_stop,
66101de1
PM
291 .add_interface = wbsoft_add_interface,
292 .remove_interface = wbsoft_remove_interface,
293 .config = wbsoft_config,
6d7fd647 294 .prepare_multicast = wbsoft_prepare_multicast,
66101de1 295 .configure_filter = wbsoft_configure_filter,
68ab0c96 296 .get_stats = wbsoft_get_stats,
66101de1 297 .get_tsf = wbsoft_get_tsf,
66101de1
PM
298};
299
e5851c20 300static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
22a82bcd
PE
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);
e5851c20 310 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
22a82bcd
PE
311
312 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
313}
314
e5851c20 315static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
22a82bcd
PE
316{
317 if (pHwData->SurpriseRemove)
318 return;
319
320 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
321}
322
323static 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
e5851c20 333 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
22a82bcd
PE
334 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
335}
336
337static unsigned char hal_idle(struct hw_data *pHwData)
338{
339 struct wb35_reg *reg = &pHwData->reg;
22a82bcd 340
9be98819 341 if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
22a82bcd
PE
342 return false;
343
344 return true;
345}
346
347u8 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 */
e5851c20 358static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
22a82bcd
PE
359{
360 struct wb35_reg *reg = &pHwData->reg;
361
362 if (pHwData->SurpriseRemove)
363 return 1;
364
e5851c20 365 /* read the bit16 of register U1B0 */
22a82bcd
PE
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
833d0cd3
PE
376static 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
380static 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
80767e6e
PE
385static void hal_led_control(unsigned long data)
386{
a32b9810
PE
387 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
388 struct hw_data *pHwData = &adapter->sHwData;
80767e6e 389 struct wb35_reg *reg = &pHwData->reg;
a32b9810 390 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
a32b9810
PE
391 u32 TimeInterval = 500, ltmp, ltmp2;
392 ltmp = 0;
80767e6e 393
a32b9810
PE
394 if (pHwData->SurpriseRemove)
395 return;
80767e6e 396
a32b9810 397 if (pHwData->LED_control) {
80767e6e 398 ltmp2 = pHwData->LED_control & 0xff;
e5851c20 399 if (ltmp2 == 5) { /* 5 is WPS mode */
80767e6e 400 TimeInterval = 100;
a32b9810
PE
401 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
402 switch (ltmp2) {
e5851c20 403 case 1: /* [0.2 On][0.1 Off]... */
a32b9810 404 pHwData->LED_Blinking %= 3;
e5851c20
LL
405 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
406 if (pHwData->LED_Blinking == 2) /* Turn off */
a32b9810
PE
407 ltmp = 0;
408 break;
e5851c20 409 case 2: /* [0.1 On][0.1 Off]... */
a32b9810 410 pHwData->LED_Blinking %= 2;
e5851c20
LL
411 ltmp = 0x0010; /* Led 0 red color */
412 if (pHwData->LED_Blinking) /* Turn off */
a32b9810
PE
413 ltmp = 0;
414 break;
e5851c20 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]... */
a32b9810 416 pHwData->LED_Blinking %= 15;
e5851c20
LL
417 ltmp = 0x0010; /* Led 0 red color */
418 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
a32b9810
PE
419 ltmp = 0;
420 break;
e5851c20
LL
421 case 4: /* [300 On][ off ] */
422 ltmp = 0x1000; /* Led 1 Green color */
a32b9810 423 if (pHwData->LED_Blinking >= 3000)
e5851c20 424 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
a32b9810 425 break;
80767e6e
PE
426 }
427 pHwData->LED_Blinking++;
428
429 reg->U1BC_LEDConfigure = ltmp;
e5851c20
LL
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 */
a32b9810 432 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
80767e6e 433 }
a32b9810 434 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
80767e6e 435 }
e5851c20 436 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
a32b9810 437 if (reg->U1BC_LEDConfigure & 0x1010) {
80767e6e 438 reg->U1BC_LEDConfigure &= ~0x1010;
a32b9810 439 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
80767e6e 440 }
a32b9810
PE
441 } else {
442 switch (LEDSet) {
e5851c20
LL
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 */
a32b9810
PE
446 if (pHwData->LED_Scanning) {
447 if (pHwData->LED_Blinking == 0) {
448 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 449 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
a32b9810
PE
450 pHwData->LED_Blinking = 1;
451 TimeInterval = 300;
452 } else {
453 reg->U1BC_LEDConfigure &= ~0x10;
e5851c20 454 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
455 pHwData->LED_Blinking = 0;
456 TimeInterval = 300;
80767e6e 457 }
a32b9810 458 } else {
e5851c20 459 /* Turn Off LED_0 */
a32b9810
PE
460 if (reg->U1BC_LEDConfigure & 0x10) {
461 reg->U1BC_LEDConfigure &= ~0x10;
e5851c20 462 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
80767e6e
PE
463 }
464 }
a32b9810 465 } else {
e5851c20 466 /* Turn On LED_0 */
a32b9810
PE
467 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
468 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 469 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
80767e6e 470 }
a32b9810
PE
471 }
472 break;
e5851c20
LL
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 */
a32b9810
PE
476 if (pHwData->LED_Scanning) {
477 if (pHwData->LED_Blinking == 0) {
478 reg->U1BC_LEDConfigure &= ~0xf;
479 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 480 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
a32b9810
PE
481 pHwData->LED_Blinking = 1;
482 TimeInterval = 300;
483 } else {
80767e6e 484 reg->U1BC_LEDConfigure &= ~0x1f;
e5851c20 485 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
486 pHwData->LED_Blinking = 0;
487 TimeInterval = 300;
80767e6e 488 }
a32b9810 489 } else {
e5851c20 490 /* Gray blinking if in disconnect state and not scanning */
a32b9810
PE
491 ltmp = reg->U1BC_LEDConfigure;
492 reg->U1BC_LEDConfigure &= ~0x1f;
833d0cd3 493 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
80767e6e 494 reg->U1BC_LEDConfigure |= 0x10;
a32b9810 495 reg->U1BC_LEDConfigure |=
833d0cd3 496 LED_GRAY2[(pHwData->LED_Blinking % 30)];
80767e6e 497 }
a32b9810
PE
498 pHwData->LED_Blinking++;
499 if (reg->U1BC_LEDConfigure != ltmp)
e5851c20 500 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810 501 TimeInterval = 100;
80767e6e 502 }
a32b9810 503 } else {
e5851c20 504 /* Turn On LED_0 */
a32b9810
PE
505 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
506 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 507 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
a32b9810
PE
508 }
509 }
510 break;
e5851c20
LL
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 */
a32b9810
PE
514 if (pHwData->LED_Scanning) {
515 if (pHwData->LED_Blinking == 0) {
e5851c20
LL
516 reg->U1BC_LEDConfigure |= 0x1000;
517 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
a32b9810
PE
518 pHwData->LED_Blinking = 1;
519 TimeInterval = 300;
520 } else {
e5851c20
LL
521 reg->U1BC_LEDConfigure &= ~0x1000;
522 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
a32b9810
PE
523 pHwData->LED_Blinking = 0;
524 TimeInterval = 300;
80767e6e 525 }
a32b9810 526 } else {
e5851c20 527 /* Turn Off LED_1 */
a32b9810 528 if (reg->U1BC_LEDConfigure & 0x1000) {
e5851c20
LL
529 reg->U1BC_LEDConfigure &= ~0x1000;
530 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
80767e6e
PE
531 }
532 }
a32b9810 533 } else {
e5851c20 534 /* Is transmitting/receiving ?? */
a32b9810
PE
535 if ((adapter->RxByteCount !=
536 pHwData->RxByteCountLast)
537 || (adapter->TxByteCount !=
538 pHwData->TxByteCountLast)) {
539 if ((reg->U1BC_LEDConfigure & 0x3000) !=
540 0x3000) {
e5851c20
LL
541 reg->U1BC_LEDConfigure |= 0x3000;
542 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
80767e6e 543 }
e5851c20 544 /* Update variable */
a32b9810
PE
545 pHwData->RxByteCountLast =
546 adapter->RxByteCount;
547 pHwData->TxByteCountLast =
548 adapter->TxByteCount;
549 TimeInterval = 200;
550 } else {
e5851c20 551 /* Turn On LED_1 and blinking if transmitting/receiving */
a32b9810
PE
552 if ((reg->U1BC_LEDConfigure & 0x3000) !=
553 0x1000) {
554 reg->U1BC_LEDConfigure &=
555 ~0x3000;
556 reg->U1BC_LEDConfigure |=
557 0x1000;
e5851c20 558 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
80767e6e
PE
559 }
560 }
a32b9810
PE
561 }
562 break;
e5851c20 563 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
a32b9810 564 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
e5851c20 565 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
a32b9810
PE
566 Wb35Reg_Write(pHwData, 0x03bc,
567 reg->U1BC_LEDConfigure);
568 }
80767e6e 569
a32b9810 570 if (pHwData->LED_Blinking) {
e5851c20 571 /* Gray blinking */
a32b9810
PE
572 reg->U1BC_LEDConfigure &= ~0x0f;
573 reg->U1BC_LEDConfigure |= 0x10;
574 reg->U1BC_LEDConfigure |=
833d0cd3 575 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
a32b9810
PE
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 {
e5851c20 583 pHwData->LED_Blinking = 0; /* Stop blinking */
80767e6e 584 reg->U1BC_LEDConfigure &= ~0x0f;
a32b9810
PE
585 Wb35Reg_Write(pHwData, 0x03bc,
586 reg->U1BC_LEDConfigure);
80767e6e 587 }
a32b9810
PE
588 break;
589 }
80767e6e 590
a32b9810 591 if (pHwData->LED_LinkOn) {
e5851c20
LL
592 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
593 /* Try to turn ON LED_0 after gray blinking */
a32b9810 594 reg->U1BC_LEDConfigure |= 0x10;
e5851c20 595 pHwData->LED_Blinking = 1; /* Start blinking */
a32b9810 596 TimeInterval = 50;
80767e6e 597 }
a32b9810 598 } else {
e5851c20 599 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
a32b9810
PE
600 reg->U1BC_LEDConfigure &= ~0x10;
601 Wb35Reg_Write(pHwData, 0x03bc,
602 reg->U1BC_LEDConfigure);
80767e6e 603 }
a32b9810
PE
604 }
605 break;
80767e6e 606 }
80767e6e
PE
607 }
608
609 pHwData->time_count += TimeInterval;
e5851c20 610 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
80767e6e
PE
611 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
612 add_timer(&pHwData->LEDTimer);
613}
614
cfe31f81 615static int hal_init_hardware(struct ieee80211_hw *hw)
80767e6e
PE
616{
617 struct wbsoft_priv *priv = hw->priv;
a32b9810 618 struct hw_data *pHwData = &priv->sHwData;
80767e6e
PE
619 u16 SoftwareSet;
620
bdbb8839
PE
621 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
622 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
80767e6e 623
00e2e05d 624 if (!Wb35Reg_initial(pHwData))
a39ee671 625 goto error_reg_destroy;
00e2e05d 626
00e2e05d 627 if (!Wb35Tx_initial(pHwData))
a39ee671 628 goto error_tx_destroy;
00e2e05d 629
00e2e05d 630 if (!Wb35Rx_initial(pHwData))
a39ee671 631 goto error_rx_destroy;
00e2e05d 632
00e2e05d
PE
633 init_timer(&pHwData->LEDTimer);
634 pHwData->LEDTimer.function = hal_led_control;
a32b9810 635 pHwData->LEDTimer.data = (unsigned long)priv;
00e2e05d
PE
636 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
637 add_timer(&pHwData->LEDTimer);
638
a32b9810 639 SoftwareSet = hal_software_set(pHwData);
00e2e05d 640
00e2e05d
PE
641 Wb35Rx_start(hw);
642 Wb35Tx_EP2VM_start(priv);
643
644 return 0;
80767e6e 645
a39ee671
PE
646error_rx_destroy:
647 Wb35Rx_destroy(pHwData);
648error_tx_destroy:
649 Wb35Tx_destroy(pHwData);
650error_reg_destroy:
651 Wb35Reg_destroy(pHwData);
652
80767e6e 653 pHwData->SurpriseRemove = 1;
cfe31f81 654 return -EINVAL;
80767e6e
PE
655}
656
26598511 657static int wb35_hw_init(struct ieee80211_hw *hw)
912b209f
PE
658{
659 struct wbsoft_priv *priv = hw->priv;
a32b9810
PE
660 struct hw_data *pHwData = &priv->sHwData;
661 u8 EEPROM_region;
662 u8 HwRadioOff;
663 u8 *pMacAddr2;
664 u8 *pMacAddr;
26598511 665 int err;
912b209f 666
9ca748ce 667 pHwData->phy_type = RF_DECIDE_BY_INF;
912b209f 668
a32b9810
PE
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;
912b209f 682
cfe31f81
PE
683 err = hal_init_hardware(hw);
684 if (err)
912b209f
PE
685 goto error;
686
a32b9810 687 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
912b209f
PE
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
a32b9810 694 priv->sLocalPara.region = REGION_USA; /* default setting */
912b209f
PE
695 }
696
912b209f
PE
697 Mds_initial(priv);
698
bdbb8839 699 /*
f69b0d64 700 * If no user-defined address in the registry, use the address
bdbb8839
PE
701 * "burned" on the NIC instead.
702 */
912b209f
PE
703 pMacAddr = priv->sLocalPara.ThisMacAddress;
704 pMacAddr2 = priv->sLocalPara.PermanentAddress;
bdbb8839
PE
705
706 /* Reading ethernet address from EEPROM */
a32b9810 707 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
912b209f
PE
708 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
709 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
710 else {
bdbb8839 711 /* Set the user define MAC address */
a32b9810
PE
712 hal_set_ethernet_address(pHwData,
713 priv->sLocalPara.ThisMacAddress);
912b209f
PE
714 }
715
912b209f 716 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
2855bb79 717 pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
a32b9810 718 hal_get_hw_radio_off(pHwData);
912b209f 719
bdbb8839 720 /* Waiting for HAL setting OK */
912b209f
PE
721 while (!hal_idle(pHwData))
722 msleep(10);
723
724 MTO_Init(priv);
725
a32b9810 726 HwRadioOff = hal_get_hw_radio_off(pHwData);
912b209f
PE
727 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
728
a32b9810
PE
729 hal_set_radio_mode(pHwData,
730 (unsigned char)(priv->sLocalPara.RadioOffStatus.
731 boSwRadioOff
732 || priv->sLocalPara.RadioOffStatus.
733 boHwRadioOff));
912b209f 734
bdbb8839
PE
735 /* Notify hal that the driver is ready now. */
736 hal_driver_init_OK(pHwData) = 1;
912b209f
PE
737
738error:
26598511 739 return err;
912b209f
PE
740}
741
a32b9810
PE
742static int wb35_probe(struct usb_interface *intf,
743 const struct usb_device_id *id_table)
66101de1 744{
66101de1 745 struct usb_device *udev = interface_to_usbdev(intf);
a32b9810
PE
746 struct usb_endpoint_descriptor *endpoint;
747 struct usb_host_interface *interface;
1523ddc4 748 struct ieee80211_hw *dev;
a32b9810 749 struct wbsoft_priv *priv;
acfa5110 750 int nr, err;
a32b9810 751 u32 ltmp;
66101de1
PM
752
753 usb_get_dev(udev);
754
bdbb8839 755 /* Check the device if it already be opened */
a32b9810
PE
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);
acfa5110
PE
760 if (nr < 0) {
761 err = nr;
dc7e04fe 762 goto error;
acfa5110 763 }
66101de1 764
bdbb8839 765 /* Is already initialized? */
dc7e04fe 766 ltmp = cpu_to_le32(ltmp);
bdbb8839 767 if (ltmp) {
1523ddc4 768 err = -EBUSY;
dc7e04fe 769 goto error;
1523ddc4 770 }
66101de1 771
1e8a2b60 772 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
acfa5110
PE
773 if (!dev) {
774 err = -ENOMEM;
1523ddc4 775 goto error;
acfa5110 776 }
66101de1 777
1e8a2b60 778 priv = dev->priv;
1e8a2b60 779
2894c6cd 780 priv->sHwData.udev = udev;
66101de1 781
a32b9810
PE
782 interface = intf->cur_altsetting;
783 endpoint = &interface->endpoint[0].desc;
66101de1 784
9be98819 785 if (endpoint[2].wMaxPacketSize == 512)
dc7e04fe 786 printk("[w35und] Working on USB 2.0\n");
66101de1 787
26598511
PE
788 err = wb35_hw_init(dev);
789 if (err)
1e8a2b60 790 goto error_free_hw;
66101de1 791
1523ddc4
PE
792 SET_IEEE80211_DEV(dev, &udev->dev);
793 {
a32b9810
PE
794 struct hw_data *pHwData = &priv->sHwData;
795 unsigned char dev_addr[MAX_ADDR_LEN];
1523ddc4
PE
796 hal_get_permanent_address(pHwData, dev_addr);
797 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
798 }
66101de1 799
1523ddc4 800 dev->extra_tx_headroom = 12; /* FIXME */
05e361ca
PM
801 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
802 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
66101de1 803
1523ddc4 804 dev->channel_change_time = 1000;
05e361ca 805 dev->max_signal = 100;
1523ddc4 806 dev->queues = 1;
dc7e04fe 807
a36e0894 808 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
66101de1 809
1523ddc4
PE
810 err = ieee80211_register_hw(dev);
811 if (err)
812 goto error_free_hw;
66101de1 813
82fbb01c 814 usb_set_intfdata(intf, dev);
66101de1 815
dc7e04fe 816 return 0;
1523ddc4
PE
817
818error_free_hw:
819 ieee80211_free_hw(dev);
dc7e04fe 820error:
4af12e55 821 usb_put_dev(udev);
1523ddc4 822 return err;
66101de1
PM
823}
824
f592a859
PE
825static 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
912b209f
PE
835static void wb35_hw_halt(struct wbsoft_priv *adapter)
836{
bdbb8839 837 /* Turn off Rx and Tx hardware ability */
a32b9810 838 hal_stop(&adapter->sHwData);
2855bb79 839 pr_debug("[w35und] Hal_stop O.K.\n");
bdbb8839
PE
840 /* Waiting Irp completed */
841 msleep(100);
912b209f 842
f592a859 843 hal_halt(&adapter->sHwData);
912b209f
PE
844}
845
302bae85 846static void wb35_disconnect(struct usb_interface *intf)
66101de1 847{
82fbb01c
PE
848 struct ieee80211_hw *hw = usb_get_intfdata(intf);
849 struct wbsoft_priv *priv = hw->priv;
66101de1 850
912b209f 851 wb35_hw_halt(priv);
66101de1 852
82fbb01c
PE
853 ieee80211_stop_queues(hw);
854 ieee80211_unregister_hw(hw);
855 ieee80211_free_hw(hw);
856
4af12e55
PE
857 usb_set_intfdata(intf, NULL);
858 usb_put_dev(interface_to_usbdev(intf));
66101de1
PM
859}
860
dd38da46
PE
861static struct usb_driver wb35_driver = {
862 .name = "w35und",
863 .id_table = wb35_table,
864 .probe = wb35_probe,
865 .disconnect = wb35_disconnect,
866};
867
bac2c126 868module_usb_driver(wb35_driver);