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