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>
20 #include "wb35reg_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) },
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)
60 if (pHwData->SurpriseRemove)
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);
79 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
80 struct ieee80211_vif *vif)
82 printk("wbsoft_remove interface called\n");
85 static void wbsoft_stop(struct ieee80211_hw *hw)
87 printk(KERN_INFO "%s called\n", __func__);
90 static int wbsoft_get_stats(struct ieee80211_hw *hw,
91 struct ieee80211_low_level_stats *stats)
93 printk(KERN_INFO "%s called\n", __func__);
97 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
98 struct netdev_hw_addr_list *mc_list)
100 return netdev_hw_addr_list_count(mc_list);
103 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
104 unsigned int changed_flags,
105 unsigned int *total_flags,
108 unsigned int new_flags;
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;
117 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
119 *total_flags = new_flags;
122 static void wbsoft_tx(struct ieee80211_hw *dev,
123 struct ieee80211_tx_control *control,
126 struct wbsoft_priv *priv = dev->priv;
128 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
129 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
134 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
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++;
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.
149 static int wbsoft_start(struct ieee80211_hw *dev)
151 struct wbsoft_priv *priv = dev->priv;
153 priv->enabled = true;
158 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
160 struct wb35_reg *reg = &pHwData->reg;
162 if (pHwData->SurpriseRemove)
165 if (radio_off) { /* disable Baseband receive off */
166 pHwData->CurrentRadioSw = 1; /* off */
167 reg->M24_MacControl &= 0xffffffbf;
169 pHwData->CurrentRadioSw = 0; /* on */
170 reg->M24_MacControl |= 0x00000040;
172 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
175 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
177 struct wb35_reg *reg = &pHwData->reg;
179 if (pHwData->SurpriseRemove)
182 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
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,
192 sizeof(struct chan_info));
195 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
197 hal_set_current_channel_ex(pHwData, channel);
200 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
202 struct wb35_reg *reg = &pHwData->reg;
204 if (pHwData->SurpriseRemove)
207 reg->M00_MacControl &= ~0x02000000; /* The HW value */
210 reg->M00_MacControl |= 0x02000000; /* The HW value */
212 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
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)
218 struct wb35_reg *reg = &pHwData->reg;
220 if (pHwData->SurpriseRemove)
224 reg->M00_MacControl |= 0x00400000;
225 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
227 reg->M00_MacControl &= ~0x00400000;
228 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
232 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
234 struct wb35_reg *reg = &pHwData->reg;
236 if (pHwData->SurpriseRemove)
239 reg->M00_MacControl &= ~0x01000000; /* The HW value */
241 reg->M00_MacControl |= 0x01000000; /* The HW value */
242 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
245 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
247 struct wb35_reg *reg = &pHwData->reg;
249 if (pHwData->SurpriseRemove)
252 if (!enable) /* Due to SME and MLME are not suitable for 35 */
255 reg->M00_MacControl &= ~0x04000000; /* The HW value */
257 reg->M00_MacControl |= 0x04000000; /* The HW value */
259 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
262 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
264 struct wbsoft_priv *priv = dev->priv;
267 printk("wbsoft_config called\n");
269 /* Should use channel_num, or something, as that is already pre-translated */
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);
283 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
285 printk("wbsoft_get_tsf called\n");
289 static const struct ieee80211_ops wbsoft_ops = {
291 .start = wbsoft_start,
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,
302 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
306 if (pHwData->SurpriseRemove)
309 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
311 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
312 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
314 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
317 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
319 if (pHwData->SurpriseRemove)
322 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
325 static void hal_stop(struct hw_data *pHwData)
327 struct wb35_reg *reg = &pHwData->reg;
329 pHwData->Wb35Rx.rx_halt = 1;
330 Wb35Rx_stop(pHwData);
332 pHwData->Wb35Tx.tx_halt = 1;
333 Wb35Tx_stop(pHwData);
335 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
336 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
339 static unsigned char hal_idle(struct hw_data *pHwData)
341 struct wb35_reg *reg = &pHwData->reg;
343 if (!pHwData->SurpriseRemove && reg->EP0vm_state != VM_STOP)
349 u8 hal_get_antenna_number(struct hw_data *pHwData)
351 struct wb35_reg *reg = &pHwData->reg;
353 if ((reg->BB2C & BIT(11)) == 0)
359 /* 0 : radio on; 1: radio off */
360 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
362 struct wb35_reg *reg = &pHwData->reg;
364 if (pHwData->SurpriseRemove)
367 /* read the bit16 of register U1B0 */
368 Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0);
369 if ((reg->U1B0 & 0x00010000)) {
370 pHwData->CurrentRadioHw = 1;
373 pHwData->CurrentRadioHw = 0;
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
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
387 static void hal_led_control(unsigned long data)
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;
396 if (pHwData->SurpriseRemove)
399 if (pHwData->LED_control) {
400 ltmp2 = pHwData->LED_control & 0xff;
401 if (ltmp2 == 5) { /* 5 is WPS mode */
403 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
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 */
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 */
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 */
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. */
429 pHwData->LED_Blinking++;
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;
436 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
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);
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;
455 reg->U1BC_LEDConfigure &= ~0x10;
456 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
457 pHwData->LED_Blinking = 0;
462 if (reg->U1BC_LEDConfigure & 0x10) {
463 reg->U1BC_LEDConfigure &= ~0x10;
464 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
469 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
470 reg->U1BC_LEDConfigure |= 0x10;
471 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
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;
486 reg->U1BC_LEDConfigure &= ~0x1f;
487 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
488 pHwData->LED_Blinking = 0;
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)];
500 pHwData->LED_Blinking++;
501 if (reg->U1BC_LEDConfigure != ltmp)
502 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
507 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
508 reg->U1BC_LEDConfigure |= 0x10;
509 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
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;
523 reg->U1BC_LEDConfigure &= ~0x1000;
524 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
525 pHwData->LED_Blinking = 0;
530 if (reg->U1BC_LEDConfigure & 0x1000) {
531 reg->U1BC_LEDConfigure &= ~0x1000;
532 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
536 /* Is transmitting/receiving ?? */
537 if ((adapter->RxByteCount !=
538 pHwData->RxByteCountLast)
539 || (adapter->TxByteCount !=
540 pHwData->TxByteCountLast)) {
541 if ((reg->U1BC_LEDConfigure & 0x3000) !=
543 reg->U1BC_LEDConfigure |= 0x3000;
544 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
546 /* Update variable */
547 pHwData->RxByteCountLast =
548 adapter->RxByteCount;
549 pHwData->TxByteCountLast =
550 adapter->TxByteCount;
553 /* Turn On LED_1 and blinking if transmitting/receiving */
554 if ((reg->U1BC_LEDConfigure & 0x3000) !=
556 reg->U1BC_LEDConfigure &=
558 reg->U1BC_LEDConfigure |=
560 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
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);
572 if (pHwData->LED_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);
581 pHwData->LED_Blinking += 2;
582 if (pHwData->LED_Blinking < 40)
585 pHwData->LED_Blinking = 0; /* Stop blinking */
586 reg->U1BC_LEDConfigure &= ~0x0f;
587 Wb35Reg_Write(pHwData, 0x03bc,
588 reg->U1BC_LEDConfigure);
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 */
601 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
602 reg->U1BC_LEDConfigure &= ~0x10;
603 Wb35Reg_Write(pHwData, 0x03bc,
604 reg->U1BC_LEDConfigure);
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);
617 static int hal_init_hardware(struct ieee80211_hw *hw)
619 struct wbsoft_priv *priv = hw->priv;
620 struct hw_data *pHwData = &priv->sHwData;
623 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
624 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
626 if (!Wb35Reg_initial(pHwData))
627 goto error_reg_destroy;
629 if (!Wb35Tx_initial(pHwData))
630 goto error_tx_destroy;
632 if (!Wb35Rx_initial(pHwData))
633 goto error_rx_destroy;
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);
641 SoftwareSet = hal_software_set(pHwData);
644 Wb35Tx_EP2VM_start(priv);
649 Wb35Rx_destroy(pHwData);
651 Wb35Tx_destroy(pHwData);
653 Wb35Reg_destroy(pHwData);
655 pHwData->SurpriseRemove = 1;
659 static int wb35_hw_init(struct ieee80211_hw *hw)
661 struct wbsoft_priv *priv = hw->priv;
662 struct hw_data *pHwData = &priv->sHwData;
669 pHwData->phy_type = RF_DECIDE_BY_INF;
671 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
672 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
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 */
683 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
685 err = hal_init_hardware(hw);
689 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
690 if (EEPROM_region != REGION_AUTO)
691 priv->sLocalPara.region = EEPROM_region;
693 if (priv->sLocalPara.region_INF != REGION_AUTO)
694 priv->sLocalPara.region = priv->sLocalPara.region_INF;
696 priv->sLocalPara.region = REGION_USA; /* default setting */
702 * If no user-defined address in the registry, use the address
703 * "burned" on the NIC instead.
705 pMacAddr = priv->sLocalPara.ThisMacAddress;
706 pMacAddr2 = priv->sLocalPara.PermanentAddress;
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);
713 /* Set the user define MAC address */
714 hal_set_ethernet_address(pHwData,
715 priv->sLocalPara.ThisMacAddress);
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);
722 /* Waiting for HAL setting OK */
723 while (!hal_idle(pHwData))
728 HwRadioOff = hal_get_hw_radio_off(pHwData);
729 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
731 hal_set_radio_mode(pHwData,
732 (unsigned char)(priv->sLocalPara.RadioOffStatus.
734 || priv->sLocalPara.RadioOffStatus.
737 /* Notify hal that the driver is ready now. */
738 hal_driver_init_OK(pHwData) = 1;
744 static int wb35_probe(struct usb_interface *intf,
745 const struct usb_device_id *id_table)
747 struct usb_device *udev = interface_to_usbdev(intf);
748 struct usb_endpoint_descriptor *endpoint;
749 struct usb_host_interface *interface;
750 struct ieee80211_hw *dev;
751 struct wbsoft_priv *priv;
757 /* Check the device if it already be opened */
758 err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
760 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
761 0x0, 0x400, <mp, 4, HZ * 100);
765 /* Is already initialized? */
766 ltmp = cpu_to_le32(ltmp);
772 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
780 priv->sHwData.udev = udev;
782 interface = intf->cur_altsetting;
783 endpoint = &interface->endpoint[0].desc;
785 if (endpoint[2].wMaxPacketSize == 512)
786 printk("[w35und] Working on USB 2.0\n");
788 err = wb35_hw_init(dev);
792 SET_IEEE80211_DEV(dev, &udev->dev);
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);
800 dev->extra_tx_headroom = 12; /* FIXME */
801 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
802 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
804 dev->channel_change_time = 1000;
805 dev->max_signal = 100;
808 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
810 err = ieee80211_register_hw(dev);
814 usb_set_intfdata(intf, dev);
819 ieee80211_free_hw(dev);
825 static void hal_halt(struct hw_data *pHwData)
827 del_timer_sync(&pHwData->LEDTimer);
828 /* XXX: Wait for Timer DPC exit. */
830 Wb35Rx_destroy(pHwData);
831 Wb35Tx_destroy(pHwData);
832 Wb35Reg_destroy(pHwData);
835 static void wb35_hw_halt(struct wbsoft_priv *adapter)
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 */
843 hal_halt(&adapter->sHwData);
846 static void wb35_disconnect(struct usb_interface *intf)
848 struct ieee80211_hw *hw = usb_get_intfdata(intf);
849 struct wbsoft_priv *priv = hw->priv;
853 ieee80211_stop_queues(hw);
854 ieee80211_unregister_hw(hw);
855 ieee80211_free_hw(hw);
857 usb_set_intfdata(intf, NULL);
858 usb_put_dev(interface_to_usbdev(intf));
861 static struct usb_driver wb35_driver = {
863 .id_table = wb35_table,
865 .disconnect = wb35_disconnect,
868 module_usb_driver(wb35_driver);