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