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>
17 #include "mlmetxrx_f.h"
20 #include "wb35reg_f.h"
23 #include "wblinux_f.h"
25 MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
26 MODULE_LICENSE("GPL");
27 MODULE_VERSION("0.1");
29 static const struct usb_device_id wb35_table[] __devinitconst = {
30 { USB_DEVICE(0x0416, 0x0035) },
31 { USB_DEVICE(0x18E8, 0x6201) },
32 { USB_DEVICE(0x18E8, 0x6206) },
33 { USB_DEVICE(0x18E8, 0x6217) },
34 { USB_DEVICE(0x18E8, 0x6230) },
35 { USB_DEVICE(0x18E8, 0x6233) },
36 { USB_DEVICE(0x1131, 0x2035) },
40 MODULE_DEVICE_TABLE(usb, wb35_table);
42 static struct ieee80211_rate wbsoft_rates[] = {
43 { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
46 static struct ieee80211_channel wbsoft_channels[] = {
47 { .center_freq = 2412 },
50 static struct ieee80211_supported_band wbsoft_band_2GHz = {
51 .channels = wbsoft_channels,
52 .n_channels = ARRAY_SIZE(wbsoft_channels),
53 .bitrates = wbsoft_rates,
54 .n_bitrates = ARRAY_SIZE(wbsoft_rates),
57 static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
61 if (pHwData->SurpriseRemove)
64 pHwData->BeaconPeriod = beacon_period;
65 tmp = pHwData->BeaconPeriod << 16;
66 tmp |= pHwData->ProbeDelay;
67 Wb35Reg_Write(pHwData, 0x0848, tmp);
70 static int wbsoft_add_interface(struct ieee80211_hw *dev,
71 struct ieee80211_vif *vif)
73 struct wbsoft_priv *priv = dev->priv;
75 hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
80 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
81 struct ieee80211_vif *vif)
83 printk("wbsoft_remove interface called\n");
86 static void wbsoft_stop(struct ieee80211_hw *hw)
88 printk(KERN_INFO "%s called\n", __func__);
91 static int wbsoft_get_stats(struct ieee80211_hw *hw,
92 struct ieee80211_low_level_stats *stats)
94 printk(KERN_INFO "%s called\n", __func__);
98 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw,
99 struct netdev_hw_addr_list *mc_list)
101 return netdev_hw_addr_list_count(mc_list);
104 static void wbsoft_configure_filter(struct ieee80211_hw *dev,
105 unsigned int changed_flags,
106 unsigned int *total_flags,
109 unsigned int new_flags;
113 if (*total_flags & FIF_PROMISC_IN_BSS)
114 new_flags |= FIF_PROMISC_IN_BSS;
115 else if ((*total_flags & FIF_ALLMULTI) || (multicast > 32))
116 new_flags |= FIF_ALLMULTI;
118 dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
120 *total_flags = new_flags;
123 static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
125 struct wbsoft_priv *priv = dev->priv;
127 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
128 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
129 return NETDEV_TX_BUSY;
132 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
134 priv->sMlmeFrame.pMMPDU = skb->data;
135 priv->sMlmeFrame.DataType = FRAME_TYPE_802_11_MANAGEMENT;
136 priv->sMlmeFrame.len = skb->len;
137 priv->sMlmeFrame.wNumTxMMPDU++;
140 * H/W will enter power save by set the register. S/W don't send null
141 * 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)
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;
342 struct wb_usb *pWbUsb = &pHwData->WbUsb;
344 if (!pHwData->SurpriseRemove
345 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
351 u8 hal_get_antenna_number(struct hw_data *pHwData)
353 struct wb35_reg *reg = &pHwData->reg;
355 if ((reg->BB2C & BIT(11)) == 0)
361 /* 0 : radio on; 1: radio off */
362 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
364 struct wb35_reg *reg = &pHwData->reg;
366 if (pHwData->SurpriseRemove)
369 /* read the bit16 of register U1B0 */
370 Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0);
371 if ((reg->U1B0 & 0x00010000)) {
372 pHwData->CurrentRadioHw = 1;
375 pHwData->CurrentRadioHw = 0;
380 static u8 LED_GRAY[20] = {
381 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
384 static u8 LED_GRAY2[30] = {
385 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
386 0, 15, 14, 13, 12, 11, 10, 9, 8
389 static void hal_led_control(unsigned long data)
391 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
392 struct hw_data *pHwData = &adapter->sHwData;
393 struct wb35_reg *reg = &pHwData->reg;
394 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
395 u32 TimeInterval = 500, ltmp, ltmp2;
398 if (pHwData->SurpriseRemove)
401 if (pHwData->LED_control) {
402 ltmp2 = pHwData->LED_control & 0xff;
403 if (ltmp2 == 5) { /* 5 is WPS mode */
405 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
407 case 1: /* [0.2 On][0.1 Off]... */
408 pHwData->LED_Blinking %= 3;
409 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
410 if (pHwData->LED_Blinking == 2) /* Turn off */
413 case 2: /* [0.1 On][0.1 Off]... */
414 pHwData->LED_Blinking %= 2;
415 ltmp = 0x0010; /* Led 0 red color */
416 if (pHwData->LED_Blinking) /* Turn off */
419 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]... */
420 pHwData->LED_Blinking %= 15;
421 ltmp = 0x0010; /* Led 0 red color */
422 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
425 case 4: /* [300 On][ off ] */
426 ltmp = 0x1000; /* Led 1 Green color */
427 if (pHwData->LED_Blinking >= 3000)
428 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
431 pHwData->LED_Blinking++;
433 reg->U1BC_LEDConfigure = ltmp;
434 if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
435 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
436 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
438 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
440 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
441 if (reg->U1BC_LEDConfigure & 0x1010) {
442 reg->U1BC_LEDConfigure &= ~0x1010;
443 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
447 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
448 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
449 /* Blinking if scanning is on progress */
450 if (pHwData->LED_Scanning) {
451 if (pHwData->LED_Blinking == 0) {
452 reg->U1BC_LEDConfigure |= 0x10;
453 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
454 pHwData->LED_Blinking = 1;
457 reg->U1BC_LEDConfigure &= ~0x10;
458 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
459 pHwData->LED_Blinking = 0;
464 if (reg->U1BC_LEDConfigure & 0x10) {
465 reg->U1BC_LEDConfigure &= ~0x10;
466 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
471 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
472 reg->U1BC_LEDConfigure |= 0x10;
473 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
477 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
478 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
479 /* Blinking if scanning is on progress */
480 if (pHwData->LED_Scanning) {
481 if (pHwData->LED_Blinking == 0) {
482 reg->U1BC_LEDConfigure &= ~0xf;
483 reg->U1BC_LEDConfigure |= 0x10;
484 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
485 pHwData->LED_Blinking = 1;
488 reg->U1BC_LEDConfigure &= ~0x1f;
489 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
490 pHwData->LED_Blinking = 0;
494 /* Gray blinking if in disconnect state and not scanning */
495 ltmp = reg->U1BC_LEDConfigure;
496 reg->U1BC_LEDConfigure &= ~0x1f;
497 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
498 reg->U1BC_LEDConfigure |= 0x10;
499 reg->U1BC_LEDConfigure |=
500 LED_GRAY2[(pHwData->LED_Blinking % 30)];
502 pHwData->LED_Blinking++;
503 if (reg->U1BC_LEDConfigure != ltmp)
504 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
509 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
510 reg->U1BC_LEDConfigure |= 0x10;
511 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
515 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
516 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
517 /* Blinking if scanning is on progress */
518 if (pHwData->LED_Scanning) {
519 if (pHwData->LED_Blinking == 0) {
520 reg->U1BC_LEDConfigure |= 0x1000;
521 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
522 pHwData->LED_Blinking = 1;
525 reg->U1BC_LEDConfigure &= ~0x1000;
526 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
527 pHwData->LED_Blinking = 0;
532 if (reg->U1BC_LEDConfigure & 0x1000) {
533 reg->U1BC_LEDConfigure &= ~0x1000;
534 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
538 /* Is transmitting/receiving ?? */
539 if ((adapter->RxByteCount !=
540 pHwData->RxByteCountLast)
541 || (adapter->TxByteCount !=
542 pHwData->TxByteCountLast)) {
543 if ((reg->U1BC_LEDConfigure & 0x3000) !=
545 reg->U1BC_LEDConfigure |= 0x3000;
546 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
548 /* Update variable */
549 pHwData->RxByteCountLast =
550 adapter->RxByteCount;
551 pHwData->TxByteCountLast =
552 adapter->TxByteCount;
555 /* Turn On LED_1 and blinking if transmitting/receiving */
556 if ((reg->U1BC_LEDConfigure & 0x3000) !=
558 reg->U1BC_LEDConfigure &=
560 reg->U1BC_LEDConfigure |=
562 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
567 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
568 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
569 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
570 Wb35Reg_Write(pHwData, 0x03bc,
571 reg->U1BC_LEDConfigure);
574 if (pHwData->LED_Blinking) {
576 reg->U1BC_LEDConfigure &= ~0x0f;
577 reg->U1BC_LEDConfigure |= 0x10;
578 reg->U1BC_LEDConfigure |=
579 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
580 Wb35Reg_Write(pHwData, 0x03bc,
581 reg->U1BC_LEDConfigure);
583 pHwData->LED_Blinking += 2;
584 if (pHwData->LED_Blinking < 40)
587 pHwData->LED_Blinking = 0; /* Stop blinking */
588 reg->U1BC_LEDConfigure &= ~0x0f;
589 Wb35Reg_Write(pHwData, 0x03bc,
590 reg->U1BC_LEDConfigure);
595 if (pHwData->LED_LinkOn) {
596 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
597 /* Try to turn ON LED_0 after gray blinking */
598 reg->U1BC_LEDConfigure |= 0x10;
599 pHwData->LED_Blinking = 1; /* Start blinking */
603 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
604 reg->U1BC_LEDConfigure &= ~0x10;
605 Wb35Reg_Write(pHwData, 0x03bc,
606 reg->U1BC_LEDConfigure);
613 pHwData->time_count += TimeInterval;
614 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
615 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
616 add_timer(&pHwData->LEDTimer);
619 static int hal_init_hardware(struct ieee80211_hw *hw)
621 struct wbsoft_priv *priv = hw->priv;
622 struct hw_data *pHwData = &priv->sHwData;
625 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
626 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
628 if (!Wb35Reg_initial(pHwData))
629 goto error_reg_destroy;
631 if (!Wb35Tx_initial(pHwData))
632 goto error_tx_destroy;
634 if (!Wb35Rx_initial(pHwData))
635 goto error_rx_destroy;
637 init_timer(&pHwData->LEDTimer);
638 pHwData->LEDTimer.function = hal_led_control;
639 pHwData->LEDTimer.data = (unsigned long)priv;
640 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
641 add_timer(&pHwData->LEDTimer);
643 SoftwareSet = hal_software_set(pHwData);
646 /* Try to make sure the EEPROM contain */
648 if (SoftwareSet != 0x82)
653 Wb35Tx_EP2VM_start(priv);
658 Wb35Rx_destroy(pHwData);
660 Wb35Tx_destroy(pHwData);
662 Wb35Reg_destroy(pHwData);
664 pHwData->SurpriseRemove = 1;
668 static int wb35_hw_init(struct ieee80211_hw *hw)
670 struct wbsoft_priv *priv = hw->priv;
671 struct hw_data *pHwData = &priv->sHwData;
678 pHwData->phy_type = RF_DECIDE_BY_INF;
680 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
681 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
683 priv->sLocalPara.region_INF = REGION_AUTO;
684 priv->sLocalPara.TxRateMode = RATE_AUTO;
685 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
686 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
687 priv->sLocalPara.bPreambleMode = AUTO_MODE;
688 priv->sLocalPara.bWepKeyError = false;
689 priv->sLocalPara.bToSelfPacketReceived = false;
690 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
692 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
694 err = hal_init_hardware(hw);
698 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
699 if (EEPROM_region != REGION_AUTO)
700 priv->sLocalPara.region = EEPROM_region;
702 if (priv->sLocalPara.region_INF != REGION_AUTO)
703 priv->sLocalPara.region = priv->sLocalPara.region_INF;
705 priv->sLocalPara.region = REGION_USA; /* default setting */
711 * If no user-defined address in the registry, use the address
712 * "burned" on the NIC instead.
714 pMacAddr = priv->sLocalPara.ThisMacAddress;
715 pMacAddr2 = priv->sLocalPara.PermanentAddress;
717 /* Reading ethernet address from EEPROM */
718 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
719 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
720 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
722 /* Set the user define MAC address */
723 hal_set_ethernet_address(pHwData,
724 priv->sLocalPara.ThisMacAddress);
727 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
728 pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
729 hal_get_hw_radio_off(pHwData);
731 /* Waiting for HAL setting OK */
732 while (!hal_idle(pHwData))
737 HwRadioOff = hal_get_hw_radio_off(pHwData);
738 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
740 hal_set_radio_mode(pHwData,
741 (unsigned char)(priv->sLocalPara.RadioOffStatus.
743 || priv->sLocalPara.RadioOffStatus.
746 /* Notify hal that the driver is ready now. */
747 hal_driver_init_OK(pHwData) = 1;
753 static int wb35_probe(struct usb_interface *intf,
754 const struct usb_device_id *id_table)
756 struct usb_device *udev = interface_to_usbdev(intf);
757 struct usb_endpoint_descriptor *endpoint;
758 struct usb_host_interface *interface;
759 struct ieee80211_hw *dev;
760 struct wbsoft_priv *priv;
761 struct wb_usb *pWbUsb;
767 /* Check the device if it already be opened */
768 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
770 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
771 0x0, 0x400, <mp, 4, HZ * 100);
777 /* Is already initialized? */
778 ltmp = cpu_to_le32(ltmp);
784 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
792 pWbUsb = &priv->sHwData.WbUsb;
795 interface = intf->cur_altsetting;
796 endpoint = &interface->endpoint[0].desc;
798 if (endpoint[2].wMaxPacketSize == 512) {
799 printk("[w35und] Working on USB 2.0\n");
803 err = wb35_hw_init(dev);
807 SET_IEEE80211_DEV(dev, &udev->dev);
809 struct hw_data *pHwData = &priv->sHwData;
810 unsigned char dev_addr[MAX_ADDR_LEN];
811 hal_get_permanent_address(pHwData, dev_addr);
812 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
815 dev->extra_tx_headroom = 12; /* FIXME */
816 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
817 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
819 dev->channel_change_time = 1000;
820 dev->max_signal = 100;
823 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
825 err = ieee80211_register_hw(dev);
829 usb_set_intfdata(intf, dev);
834 ieee80211_free_hw(dev);
840 static void hal_halt(struct hw_data *pHwData)
842 del_timer_sync(&pHwData->LEDTimer);
843 /* XXX: Wait for Timer DPC exit. */
845 Wb35Rx_destroy(pHwData);
846 Wb35Tx_destroy(pHwData);
847 Wb35Reg_destroy(pHwData);
850 static void wb35_hw_halt(struct wbsoft_priv *adapter)
852 /* Turn off Rx and Tx hardware ability */
853 hal_stop(&adapter->sHwData);
854 pr_debug("[w35und] Hal_stop O.K.\n");
855 /* Waiting Irp completed */
858 hal_halt(&adapter->sHwData);
861 static void wb35_disconnect(struct usb_interface *intf)
863 struct ieee80211_hw *hw = usb_get_intfdata(intf);
864 struct wbsoft_priv *priv = hw->priv;
868 ieee80211_stop_queues(hw);
869 ieee80211_unregister_hw(hw);
870 ieee80211_free_hw(hw);
872 usb_set_intfdata(intf, NULL);
873 usb_put_dev(interface_to_usbdev(intf));
876 static struct usb_driver wb35_driver = {
878 .id_table = wb35_table,
880 .disconnect = wb35_disconnect,
883 static int __init wb35_init(void)
885 return usb_register(&wb35_driver);
888 static void __exit wb35_exit(void)
890 usb_deregister(&wb35_driver);
893 module_init(wb35_init);
894 module_exit(wb35_exit);