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