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