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