Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/staging/winbond/wbusb.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us