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