PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / staging / winbond / wbusb.c
blob0d29624416c335887a08da772f9ce2c8b63c85bd
1 /*
2 * Copyright 2008 Pavel Machek <pavel@ucw.cz>
4 * Distribute under GPLv2.
6 * The original driver was written by:
7 * Jeff Lee <YY_Lee@issc.com.tw>
9 * and was adapted to the 2.6 kernel by:
10 * Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>
12 #include <net/mac80211.h>
13 #include <linux/usb.h>
14 #include <linux/module.h>
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"
24 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
25 MODULE_LICENSE("GPL");
26 MODULE_VERSION("0.1");
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, }
39 MODULE_DEVICE_TABLE(usb, wb35_table);
41 static struct ieee80211_rate wbsoft_rates[] = {
42 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
45 static struct ieee80211_channel wbsoft_channels[] = {
46 { .center_freq = 2412 },
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),
56 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
58 u32 tmp;
60 if (pHwData->SurpriseRemove)
61 return;
63 pHwData->BeaconPeriod = beacon_period;
64 tmp = pHwData->BeaconPeriod << 16;
65 tmp |= pHwData->ProbeDelay;
66 Wb35Reg_Write(pHwData, 0x0848, tmp);
69 static int wbsoft_add_interface(struct ieee80211_hw *dev,
70 struct ieee80211_vif *vif)
72 struct wbsoft_priv *priv = dev->priv;
74 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
76 return 0;
79 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
80 struct ieee80211_vif *vif)
84 static void wbsoft_stop(struct ieee80211_hw *hw)
88 static int wbsoft_get_stats(struct ieee80211_hw *hw,
89 struct ieee80211_low_level_stats *stats)
91 return 0;
94 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
95 struct netdev_hw_addr_list *mc_list)
97 return netdev_hw_addr_list_count(mc_list);
100 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
101 unsigned int changed_flags,
102 unsigned int *total_flags,
103 u64 multicast)
105 unsigned int new_flags;
107 new_flags = 0;
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;
114 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
116 *total_flags = new_flags;
119 static void wbsoft_tx(struct ieee80211_hw *dev,
120 struct ieee80211_tx_control *control,
121 struct sk_buff *skb)
123 struct wbsoft_priv *priv = dev->priv;
125 if (priv->sMlmeFrame.is_in_used != PACKET_FREE_TO_USE) {
126 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
127 kfree_skb(skb);
128 return;
131 priv->sMlmeFrame.is_in_used = PACKET_COME_FROM_MLME;
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++;
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.
143 Mds_Tx(priv);
146 static int wbsoft_start(struct ieee80211_hw *dev)
148 struct wbsoft_priv *priv = dev->priv;
150 priv->enabled = true;
152 return 0;
155 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
157 struct wb35_reg *reg = &pHwData->reg;
159 if (pHwData->SurpriseRemove)
160 return;
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;
169 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
172 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
174 struct wb35_reg *reg = &pHwData->reg;
176 if (pHwData->SurpriseRemove)
177 return;
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));
189 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
191 hal_set_current_channel_ex(pHwData, channel);
194 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
196 struct wb35_reg *reg = &pHwData->reg;
198 if (pHwData->SurpriseRemove)
199 return;
201 reg->M00_MacControl &= ~0x02000000; /* The HW value */
203 if (enable)
204 reg->M00_MacControl |= 0x02000000; /* The HW value */
206 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
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)
212 struct wb35_reg *reg = &pHwData->reg;
214 if (pHwData->SurpriseRemove)
215 return;
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);
226 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
228 struct wb35_reg *reg = &pHwData->reg;
230 if (pHwData->SurpriseRemove)
231 return;
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);
239 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
241 struct wb35_reg *reg = &pHwData->reg;
243 if (pHwData->SurpriseRemove)
244 return;
246 if (!enable) /* Due to SME and MLME are not suitable for 35 */
247 return;
249 reg->M00_MacControl &= ~0x04000000; /* The HW value */
250 if (enable)
251 reg->M00_MacControl |= 0x04000000; /* The HW value */
253 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
256 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
258 struct wbsoft_priv *priv = dev->priv;
259 struct chan_info ch;
261 /* Should use channel_num, or something, as that is already pre-translated */
262 ch.band = 1;
263 ch.ChanNo = 1;
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);
272 return 0;
275 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
277 return 0;
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,
293 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
295 u32 ltmp[2];
297 if (pHwData->SurpriseRemove)
298 return;
300 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
302 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
303 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
305 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
308 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
310 if (pHwData->SurpriseRemove)
311 return;
313 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
316 static void hal_stop(struct hw_data *pHwData)
318 struct wb35_reg *reg = &pHwData->reg;
320 pHwData->Wb35Rx.rx_halt = 1;
321 Wb35Rx_stop(pHwData);
323 pHwData->Wb35Tx.tx_halt = 1;
324 Wb35Tx_stop(pHwData);
326 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
327 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
330 static unsigned char hal_idle(struct hw_data *pHwData)
332 struct wb35_reg *reg = &pHwData->reg;
334 if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
335 return false;
337 return true;
340 u8 hal_get_antenna_number(struct hw_data *pHwData)
342 struct wb35_reg *reg = &pHwData->reg;
344 if ((reg->BB2C & BIT(11)) == 0)
345 return 0;
346 else
347 return 1;
350 /* 0 : radio on; 1: radio off */
351 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
353 struct wb35_reg *reg = &pHwData->reg;
355 if (pHwData->SurpriseRemove)
356 return 1;
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;
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
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
378 static void hal_led_control(unsigned long data)
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;
387 if (pHwData->SurpriseRemove)
388 return;
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;
420 pHwData->LED_Blinking++;
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;
427 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
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);
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;
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 */
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 */
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;
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)];
491 pHwData->LED_Blinking++;
492 if (reg->U1BC_LEDConfigure != ltmp)
493 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
494 TimeInterval = 100;
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 */
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;
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 */
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 */
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 */
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);
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);
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);
581 break;
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;
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);
598 break;
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);
608 static int hal_init_hardware(struct ieee80211_hw *hw)
610 struct wbsoft_priv *priv = hw->priv;
611 struct hw_data *pHwData = &priv->sHwData;
612 u16 SoftwareSet;
614 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
615 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
617 if (!Wb35Reg_initial(pHwData))
618 goto error_reg_destroy;
620 if (!Wb35Tx_initial(pHwData))
621 goto error_tx_destroy;
623 if (!Wb35Rx_initial(pHwData))
624 goto error_rx_destroy;
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);
632 SoftwareSet = hal_software_set(pHwData);
634 Wb35Rx_start(hw);
635 Wb35Tx_EP2VM_start(priv);
637 return 0;
639 error_rx_destroy:
640 Wb35Rx_destroy(pHwData);
641 error_tx_destroy:
642 Wb35Tx_destroy(pHwData);
643 error_reg_destroy:
644 Wb35Reg_destroy(pHwData);
646 pHwData->SurpriseRemove = 1;
647 return -EINVAL;
650 static int wb35_hw_init(struct ieee80211_hw *hw)
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;
660 pHwData->phy_type = RF_DECIDE_BY_INF;
662 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
663 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
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 */
674 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
676 err = hal_init_hardware(hw);
677 if (err)
678 goto error;
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 */
690 Mds_initial(priv);
693 * If no user-defined address in the registry, use the address
694 * "burned" on the NIC instead.
696 pMacAddr = priv->sLocalPara.ThisMacAddress;
697 pMacAddr2 = priv->sLocalPara.PermanentAddress;
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);
709 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
710 hal_get_hw_radio_off(pHwData);
712 /* Waiting for HAL setting OK */
713 while (!hal_idle(pHwData))
714 msleep(10);
716 MTO_Init(priv);
718 HwRadioOff = hal_get_hw_radio_off(pHwData);
719 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
721 hal_set_radio_mode(pHwData,
722 (unsigned char)(priv->sLocalPara.RadioOffStatus.
723 boSwRadioOff
724 || priv->sLocalPara.RadioOffStatus.
725 boHwRadioOff));
727 /* Notify hal that the driver is ready now. */
728 hal_driver_init_OK(pHwData) = 1;
730 error:
731 return err;
734 static int wb35_probe(struct usb_interface *intf,
735 const struct usb_device_id *id_table)
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;
745 usb_get_dev(udev);
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;
755 /* Is already initialized? */
756 ltmp = cpu_to_le32(ltmp);
757 if (ltmp) {
758 err = -EBUSY;
759 goto error;
762 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
763 if (!dev) {
764 err = -ENOMEM;
765 goto error;
768 priv = dev->priv;
770 priv->sHwData.udev = udev;
772 interface = intf->cur_altsetting;
773 endpoint = &interface->endpoint[0].desc;
775 err = wb35_hw_init(dev);
776 if (err)
777 goto error_free_hw;
779 SET_IEEE80211_DEV(dev, &udev->dev);
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);
787 dev->extra_tx_headroom = 12; /* FIXME */
788 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
789 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
791 dev->max_signal = 100;
792 dev->queues = 1;
794 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
796 err = ieee80211_register_hw(dev);
797 if (err)
798 goto error_free_hw;
800 usb_set_intfdata(intf, dev);
802 return 0;
804 error_free_hw:
805 ieee80211_free_hw(dev);
806 error:
807 usb_put_dev(udev);
808 return err;
811 static void hal_halt(struct hw_data *pHwData)
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);
821 static void wb35_hw_halt(struct wbsoft_priv *adapter)
823 /* Turn off Rx and Tx hardware ability */
824 hal_stop(&adapter->sHwData);
825 /* Waiting Irp completed */
826 msleep(100);
828 hal_halt(&adapter->sHwData);
831 static void wb35_disconnect(struct usb_interface *intf)
833 struct ieee80211_hw *hw = usb_get_intfdata(intf);
834 struct wbsoft_priv *priv = hw->priv;
836 wb35_hw_halt(priv);
838 ieee80211_stop_queues(hw);
839 ieee80211_unregister_hw(hw);
840 ieee80211_free_hw(hw);
842 usb_set_intfdata(intf, NULL);
843 usb_put_dev(interface_to_usbdev(intf));
846 static struct usb_driver wb35_driver = {
847 .name = "w35und",
848 .id_table = wb35_table,
849 .probe = wb35_probe,
850 .disconnect = wb35_disconnect,
853 module_usb_driver(wb35_driver);