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