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