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