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 #ifdef _PE_STATE_DUMP_
188 printk("Set channel is %d, band =%d\n", pHwData->Channel,
191 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
192 reg->M28_MacControl |= channel.ChanNo;
193 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
195 sizeof(struct chan_info));
198 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
200 hal_set_current_channel_ex(pHwData, channel);
203 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
205 struct wb35_reg *reg = &pHwData->reg;
207 if (pHwData->SurpriseRemove)
210 reg->M00_MacControl &= ~0x02000000; /* The HW value */
213 reg->M00_MacControl |= 0x02000000; /* The HW value */
215 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
218 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
219 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
221 struct wb35_reg *reg = &pHwData->reg;
223 if (pHwData->SurpriseRemove)
227 reg->M00_MacControl |= 0x00400000;
228 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
230 reg->M00_MacControl &= ~0x00400000;
231 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
235 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
237 struct wb35_reg *reg = &pHwData->reg;
239 if (pHwData->SurpriseRemove)
242 reg->M00_MacControl &= ~0x01000000; /* The HW value */
244 reg->M00_MacControl |= 0x01000000; /* The HW value */
245 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
248 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
250 struct wb35_reg *reg = &pHwData->reg;
252 if (pHwData->SurpriseRemove)
255 if (!enable) /* Due to SME and MLME are not suitable for 35 */
258 reg->M00_MacControl &= ~0x04000000; /* The HW value */
260 reg->M00_MacControl |= 0x04000000; /* The HW value */
262 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
265 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
267 struct wbsoft_priv *priv = dev->priv;
270 printk("wbsoft_config called\n");
272 /* Should use channel_num, or something, as that is already pre-translated */
276 hal_set_current_channel(&priv->sHwData, ch);
277 hal_set_accept_broadcast(&priv->sHwData, 1);
278 hal_set_accept_promiscuous(&priv->sHwData, 1);
279 hal_set_accept_multicast(&priv->sHwData, 1);
280 hal_set_accept_beacon(&priv->sHwData, 1);
281 hal_set_radio_mode(&priv->sHwData, 0);
286 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
288 printk("wbsoft_get_tsf called\n");
292 static const struct ieee80211_ops wbsoft_ops = {
294 .start = wbsoft_start,
296 .add_interface = wbsoft_add_interface,
297 .remove_interface = wbsoft_remove_interface,
298 .config = wbsoft_config,
299 .prepare_multicast = wbsoft_prepare_multicast,
300 .configure_filter = wbsoft_configure_filter,
301 .get_stats = wbsoft_get_stats,
302 .get_tsf = wbsoft_get_tsf,
305 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
309 if (pHwData->SurpriseRemove)
312 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
314 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
315 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
317 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
320 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
322 if (pHwData->SurpriseRemove)
325 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
328 static void hal_stop(struct hw_data *pHwData)
330 struct wb35_reg *reg = &pHwData->reg;
332 pHwData->Wb35Rx.rx_halt = 1;
333 Wb35Rx_stop(pHwData);
335 pHwData->Wb35Tx.tx_halt = 1;
336 Wb35Tx_stop(pHwData);
338 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
339 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
342 static unsigned char hal_idle(struct hw_data *pHwData)
344 struct wb35_reg *reg = &pHwData->reg;
345 struct wb_usb *pWbUsb = &pHwData->WbUsb;
347 if (!pHwData->SurpriseRemove
348 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
354 u8 hal_get_antenna_number(struct hw_data *pHwData)
356 struct wb35_reg *reg = &pHwData->reg;
358 if ((reg->BB2C & BIT(11)) == 0)
364 /* 0 : radio on; 1: radio off */
365 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
367 struct wb35_reg *reg = &pHwData->reg;
369 if (pHwData->SurpriseRemove)
372 /* read the bit16 of register U1B0 */
373 Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0);
374 if ((reg->U1B0 & 0x00010000)) {
375 pHwData->CurrentRadioHw = 1;
378 pHwData->CurrentRadioHw = 0;
383 static u8 LED_GRAY[20] = {
384 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
387 static u8 LED_GRAY2[30] = {
388 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 15, 14, 13, 12, 11, 10, 9, 8
392 static void hal_led_control(unsigned long data)
394 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
395 struct hw_data *pHwData = &adapter->sHwData;
396 struct wb35_reg *reg = &pHwData->reg;
397 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
398 u32 TimeInterval = 500, ltmp, ltmp2;
401 if (pHwData->SurpriseRemove)
404 if (pHwData->LED_control) {
405 ltmp2 = pHwData->LED_control & 0xff;
406 if (ltmp2 == 5) { /* 5 is WPS mode */
408 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
410 case 1: /* [0.2 On][0.1 Off]... */
411 pHwData->LED_Blinking %= 3;
412 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
413 if (pHwData->LED_Blinking == 2) /* Turn off */
416 case 2: /* [0.1 On][0.1 Off]... */
417 pHwData->LED_Blinking %= 2;
418 ltmp = 0x0010; /* Led 0 red color */
419 if (pHwData->LED_Blinking) /* Turn off */
422 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]... */
423 pHwData->LED_Blinking %= 15;
424 ltmp = 0x0010; /* Led 0 red color */
425 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
428 case 4: /* [300 On][ off ] */
429 ltmp = 0x1000; /* Led 1 Green color */
430 if (pHwData->LED_Blinking >= 3000)
431 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
434 pHwData->LED_Blinking++;
436 reg->U1BC_LEDConfigure = ltmp;
437 if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
438 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
439 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
441 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
443 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
444 if (reg->U1BC_LEDConfigure & 0x1010) {
445 reg->U1BC_LEDConfigure &= ~0x1010;
446 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
450 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
451 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
452 /* Blinking if scanning is on progress */
453 if (pHwData->LED_Scanning) {
454 if (pHwData->LED_Blinking == 0) {
455 reg->U1BC_LEDConfigure |= 0x10;
456 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
457 pHwData->LED_Blinking = 1;
460 reg->U1BC_LEDConfigure &= ~0x10;
461 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
462 pHwData->LED_Blinking = 0;
467 if (reg->U1BC_LEDConfigure & 0x10) {
468 reg->U1BC_LEDConfigure &= ~0x10;
469 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
474 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
475 reg->U1BC_LEDConfigure |= 0x10;
476 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
480 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
481 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
482 /* Blinking if scanning is on progress */
483 if (pHwData->LED_Scanning) {
484 if (pHwData->LED_Blinking == 0) {
485 reg->U1BC_LEDConfigure &= ~0xf;
486 reg->U1BC_LEDConfigure |= 0x10;
487 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
488 pHwData->LED_Blinking = 1;
491 reg->U1BC_LEDConfigure &= ~0x1f;
492 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
493 pHwData->LED_Blinking = 0;
497 /* Gray blinking if in disconnect state and not scanning */
498 ltmp = reg->U1BC_LEDConfigure;
499 reg->U1BC_LEDConfigure &= ~0x1f;
500 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
501 reg->U1BC_LEDConfigure |= 0x10;
502 reg->U1BC_LEDConfigure |=
503 LED_GRAY2[(pHwData->LED_Blinking % 30)];
505 pHwData->LED_Blinking++;
506 if (reg->U1BC_LEDConfigure != ltmp)
507 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
512 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
513 reg->U1BC_LEDConfigure |= 0x10;
514 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
518 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
519 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
520 /* Blinking if scanning is on progress */
521 if (pHwData->LED_Scanning) {
522 if (pHwData->LED_Blinking == 0) {
523 reg->U1BC_LEDConfigure |= 0x1000;
524 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
525 pHwData->LED_Blinking = 1;
528 reg->U1BC_LEDConfigure &= ~0x1000;
529 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
530 pHwData->LED_Blinking = 0;
535 if (reg->U1BC_LEDConfigure & 0x1000) {
536 reg->U1BC_LEDConfigure &= ~0x1000;
537 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
541 /* Is transmitting/receiving ?? */
542 if ((adapter->RxByteCount !=
543 pHwData->RxByteCountLast)
544 || (adapter->TxByteCount !=
545 pHwData->TxByteCountLast)) {
546 if ((reg->U1BC_LEDConfigure & 0x3000) !=
548 reg->U1BC_LEDConfigure |= 0x3000;
549 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
551 /* Update variable */
552 pHwData->RxByteCountLast =
553 adapter->RxByteCount;
554 pHwData->TxByteCountLast =
555 adapter->TxByteCount;
558 /* Turn On LED_1 and blinking if transmitting/receiving */
559 if ((reg->U1BC_LEDConfigure & 0x3000) !=
561 reg->U1BC_LEDConfigure &=
563 reg->U1BC_LEDConfigure |=
565 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
570 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
571 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
572 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
573 Wb35Reg_Write(pHwData, 0x03bc,
574 reg->U1BC_LEDConfigure);
577 if (pHwData->LED_Blinking) {
579 reg->U1BC_LEDConfigure &= ~0x0f;
580 reg->U1BC_LEDConfigure |= 0x10;
581 reg->U1BC_LEDConfigure |=
582 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
583 Wb35Reg_Write(pHwData, 0x03bc,
584 reg->U1BC_LEDConfigure);
586 pHwData->LED_Blinking += 2;
587 if (pHwData->LED_Blinking < 40)
590 pHwData->LED_Blinking = 0; /* Stop blinking */
591 reg->U1BC_LEDConfigure &= ~0x0f;
592 Wb35Reg_Write(pHwData, 0x03bc,
593 reg->U1BC_LEDConfigure);
598 if (pHwData->LED_LinkOn) {
599 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
600 /* Try to turn ON LED_0 after gray blinking */
601 reg->U1BC_LEDConfigure |= 0x10;
602 pHwData->LED_Blinking = 1; /* Start blinking */
606 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
607 reg->U1BC_LEDConfigure &= ~0x10;
608 Wb35Reg_Write(pHwData, 0x03bc,
609 reg->U1BC_LEDConfigure);
616 pHwData->time_count += TimeInterval;
617 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
618 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
619 add_timer(&pHwData->LEDTimer);
622 static int hal_init_hardware(struct ieee80211_hw *hw)
624 struct wbsoft_priv *priv = hw->priv;
625 struct hw_data *pHwData = &priv->sHwData;
628 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
629 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
631 if (!Wb35Reg_initial(pHwData))
632 goto error_reg_destroy;
634 if (!Wb35Tx_initial(pHwData))
635 goto error_tx_destroy;
637 if (!Wb35Rx_initial(pHwData))
638 goto error_rx_destroy;
640 init_timer(&pHwData->LEDTimer);
641 pHwData->LEDTimer.function = hal_led_control;
642 pHwData->LEDTimer.data = (unsigned long)priv;
643 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
644 add_timer(&pHwData->LEDTimer);
646 SoftwareSet = hal_software_set(pHwData);
649 /* Try to make sure the EEPROM contain */
651 if (SoftwareSet != 0x82)
656 Wb35Tx_EP2VM_start(priv);
661 Wb35Rx_destroy(pHwData);
663 Wb35Tx_destroy(pHwData);
665 Wb35Reg_destroy(pHwData);
667 pHwData->SurpriseRemove = 1;
671 static int wb35_hw_init(struct ieee80211_hw *hw)
673 struct wbsoft_priv *priv = hw->priv;
674 struct hw_data *pHwData = &priv->sHwData;
681 pHwData->phy_type = RF_DECIDE_BY_INF;
683 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
684 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
686 priv->sLocalPara.region_INF = REGION_AUTO;
687 priv->sLocalPara.TxRateMode = RATE_AUTO;
688 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
689 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
690 priv->sLocalPara.bPreambleMode = AUTO_MODE;
691 priv->sLocalPara.bWepKeyError = false;
692 priv->sLocalPara.bToSelfPacketReceived = false;
693 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
695 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
697 err = hal_init_hardware(hw);
701 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
702 if (EEPROM_region != REGION_AUTO)
703 priv->sLocalPara.region = EEPROM_region;
705 if (priv->sLocalPara.region_INF != REGION_AUTO)
706 priv->sLocalPara.region = priv->sLocalPara.region_INF;
708 priv->sLocalPara.region = REGION_USA; /* default setting */
714 * If no user-defined address in the registry, use the address
715 * "burned" on the NIC instead.
717 pMacAddr = priv->sLocalPara.ThisMacAddress;
718 pMacAddr2 = priv->sLocalPara.PermanentAddress;
720 /* Reading ethernet address from EEPROM */
721 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
722 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
723 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
725 /* Set the user define MAC address */
726 hal_set_ethernet_address(pHwData,
727 priv->sLocalPara.ThisMacAddress);
730 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
731 #ifdef _PE_STATE_DUMP_
732 printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo);
734 hal_get_hw_radio_off(pHwData);
736 /* Waiting for HAL setting OK */
737 while (!hal_idle(pHwData))
742 HwRadioOff = hal_get_hw_radio_off(pHwData);
743 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
745 hal_set_radio_mode(pHwData,
746 (unsigned char)(priv->sLocalPara.RadioOffStatus.
748 || priv->sLocalPara.RadioOffStatus.
751 /* Notify hal that the driver is ready now. */
752 hal_driver_init_OK(pHwData) = 1;
758 static int wb35_probe(struct usb_interface *intf,
759 const struct usb_device_id *id_table)
761 struct usb_device *udev = interface_to_usbdev(intf);
762 struct usb_endpoint_descriptor *endpoint;
763 struct usb_host_interface *interface;
764 struct ieee80211_hw *dev;
765 struct wbsoft_priv *priv;
766 struct wb_usb *pWbUsb;
772 /* Check the device if it already be opened */
773 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
775 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
776 0x0, 0x400, <mp, 4, HZ * 100);
782 /* Is already initialized? */
783 ltmp = cpu_to_le32(ltmp);
789 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
797 pWbUsb = &priv->sHwData.WbUsb;
800 interface = intf->cur_altsetting;
801 endpoint = &interface->endpoint[0].desc;
803 if (endpoint[2].wMaxPacketSize == 512) {
804 printk("[w35und] Working on USB 2.0\n");
808 err = wb35_hw_init(dev);
812 SET_IEEE80211_DEV(dev, &udev->dev);
814 struct hw_data *pHwData = &priv->sHwData;
815 unsigned char dev_addr[MAX_ADDR_LEN];
816 hal_get_permanent_address(pHwData, dev_addr);
817 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
820 dev->extra_tx_headroom = 12; /* FIXME */
821 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
822 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
824 dev->channel_change_time = 1000;
825 dev->max_signal = 100;
828 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
830 err = ieee80211_register_hw(dev);
834 usb_set_intfdata(intf, dev);
839 ieee80211_free_hw(dev);
845 static void hal_halt(struct hw_data *pHwData)
847 del_timer_sync(&pHwData->LEDTimer);
848 /* XXX: Wait for Timer DPC exit. */
850 Wb35Rx_destroy(pHwData);
851 Wb35Tx_destroy(pHwData);
852 Wb35Reg_destroy(pHwData);
855 static void wb35_hw_halt(struct wbsoft_priv *adapter)
857 /* Turn off Rx and Tx hardware ability */
858 hal_stop(&adapter->sHwData);
859 #ifdef _PE_USB_INI_DUMP_
860 printk("[w35und] Hal_stop O.K.\n");
862 /* Waiting Irp completed */
865 hal_halt(&adapter->sHwData);
868 static void wb35_disconnect(struct usb_interface *intf)
870 struct ieee80211_hw *hw = usb_get_intfdata(intf);
871 struct wbsoft_priv *priv = hw->priv;
875 ieee80211_stop_queues(hw);
876 ieee80211_unregister_hw(hw);
877 ieee80211_free_hw(hw);
879 usb_set_intfdata(intf, NULL);
880 usb_put_dev(interface_to_usbdev(intf));
883 static struct usb_driver wb35_driver = {
885 .id_table = wb35_table,
887 .disconnect = wb35_disconnect,
890 static int __init wb35_init(void)
892 return usb_register(&wb35_driver);
895 static void __exit wb35_exit(void)
897 usb_deregister(&wb35_driver);
900 module_init(wb35_init);
901 module_exit(wb35_exit);