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