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