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>
19 #include "wb35reg_f.h"
22 #include "wblinux_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[] __devinitconst = {
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 int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
124 struct wbsoft_priv *priv = dev->priv;
126 if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
127 priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
128 return NETDEV_TX_BUSY;
131 priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
133 priv->sMlmeFrame.pMMPDU = skb->data;
134 priv->sMlmeFrame.DataType = 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.
148 static int wbsoft_start(struct ieee80211_hw *dev)
150 struct wbsoft_priv *priv = dev->priv;
152 priv->enabled = true;
157 static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
159 struct wb35_reg *reg = &pHwData->reg;
161 if (pHwData->SurpriseRemove)
164 if (radio_off) { /* disable Baseband receive off */
165 pHwData->CurrentRadioSw = 1; /* off */
166 reg->M24_MacControl &= 0xffffffbf;
168 pHwData->CurrentRadioSw = 0; /* on */
169 reg->M24_MacControl |= 0x00000040;
171 Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl);
174 static void hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
176 struct wb35_reg *reg = &pHwData->reg;
178 if (pHwData->SurpriseRemove)
181 printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo);
183 RFSynthesizer_SwitchingChannel(pHwData, channel); /* Switch channel */
184 pHwData->Channel = channel.ChanNo;
185 pHwData->band = channel.band;
186 pr_debug("Set channel is %d, band =%d\n", pHwData->Channel, pHwData->band);
187 reg->M28_MacControl &= ~0xff; /* Clean channel information field */
188 reg->M28_MacControl |= channel.ChanNo;
189 Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
191 sizeof(struct chan_info));
194 static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
196 hal_set_current_channel_ex(pHwData, channel);
199 static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable)
201 struct wb35_reg *reg = &pHwData->reg;
203 if (pHwData->SurpriseRemove)
206 reg->M00_MacControl &= ~0x02000000; /* The HW value */
209 reg->M00_MacControl |= 0x02000000; /* The HW value */
211 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
214 /* For wep key error detection, we need to accept broadcast packets to be received temporary. */
215 static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable)
217 struct wb35_reg *reg = &pHwData->reg;
219 if (pHwData->SurpriseRemove)
223 reg->M00_MacControl |= 0x00400000;
224 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
226 reg->M00_MacControl &= ~0x00400000;
227 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
231 static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable)
233 struct wb35_reg *reg = &pHwData->reg;
235 if (pHwData->SurpriseRemove)
238 reg->M00_MacControl &= ~0x01000000; /* The HW value */
240 reg->M00_MacControl |= 0x01000000; /* The HW value */
241 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
244 static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
246 struct wb35_reg *reg = &pHwData->reg;
248 if (pHwData->SurpriseRemove)
251 if (!enable) /* Due to SME and MLME are not suitable for 35 */
254 reg->M00_MacControl &= ~0x04000000; /* The HW value */
256 reg->M00_MacControl |= 0x04000000; /* The HW value */
258 Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl);
261 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
263 struct wbsoft_priv *priv = dev->priv;
266 printk("wbsoft_config called\n");
268 /* Should use channel_num, or something, as that is already pre-translated */
272 hal_set_current_channel(&priv->sHwData, ch);
273 hal_set_accept_broadcast(&priv->sHwData, 1);
274 hal_set_accept_promiscuous(&priv->sHwData, 1);
275 hal_set_accept_multicast(&priv->sHwData, 1);
276 hal_set_accept_beacon(&priv->sHwData, 1);
277 hal_set_radio_mode(&priv->sHwData, 0);
282 static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
284 printk("wbsoft_get_tsf called\n");
288 static const struct ieee80211_ops wbsoft_ops = {
290 .start = wbsoft_start,
292 .add_interface = wbsoft_add_interface,
293 .remove_interface = wbsoft_remove_interface,
294 .config = wbsoft_config,
295 .prepare_multicast = wbsoft_prepare_multicast,
296 .configure_filter = wbsoft_configure_filter,
297 .get_stats = wbsoft_get_stats,
298 .get_tsf = wbsoft_get_tsf,
301 static void hal_set_ethernet_address(struct hw_data *pHwData, u8 *current_address)
305 if (pHwData->SurpriseRemove)
308 memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN);
310 ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress);
311 ltmp[1] = cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff;
313 Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT);
316 static void hal_get_permanent_address(struct hw_data *pHwData, u8 *pethernet_address)
318 if (pHwData->SurpriseRemove)
321 memcpy(pethernet_address, pHwData->PermanentMacAddress, 6);
324 static void hal_stop(struct hw_data *pHwData)
326 struct wb35_reg *reg = &pHwData->reg;
328 pHwData->Wb35Rx.rx_halt = 1;
329 Wb35Rx_stop(pHwData);
331 pHwData->Wb35Tx.tx_halt = 1;
332 Wb35Tx_stop(pHwData);
334 reg->D00_DmaControl &= ~0xc0000000; /* Tx Off, Rx Off */
335 Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl);
338 static unsigned char hal_idle(struct hw_data *pHwData)
340 struct wb35_reg *reg = &pHwData->reg;
341 struct wb_usb *pWbUsb = &pHwData->WbUsb;
343 if (!pHwData->SurpriseRemove
344 && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP))
350 u8 hal_get_antenna_number(struct hw_data *pHwData)
352 struct wb35_reg *reg = &pHwData->reg;
354 if ((reg->BB2C & BIT(11)) == 0)
360 /* 0 : radio on; 1: radio off */
361 static u8 hal_get_hw_radio_off(struct hw_data *pHwData)
363 struct wb35_reg *reg = &pHwData->reg;
365 if (pHwData->SurpriseRemove)
368 /* read the bit16 of register U1B0 */
369 Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0);
370 if ((reg->U1B0 & 0x00010000)) {
371 pHwData->CurrentRadioHw = 1;
374 pHwData->CurrentRadioHw = 0;
379 static u8 LED_GRAY[20] = {
380 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2
383 static u8 LED_GRAY2[30] = {
384 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385 0, 15, 14, 13, 12, 11, 10, 9, 8
388 static void hal_led_control(unsigned long data)
390 struct wbsoft_priv *adapter = (struct wbsoft_priv *)data;
391 struct hw_data *pHwData = &adapter->sHwData;
392 struct wb35_reg *reg = &pHwData->reg;
393 u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT;
394 u32 TimeInterval = 500, ltmp, ltmp2;
397 if (pHwData->SurpriseRemove)
400 if (pHwData->LED_control) {
401 ltmp2 = pHwData->LED_control & 0xff;
402 if (ltmp2 == 5) { /* 5 is WPS mode */
404 ltmp2 = (pHwData->LED_control >> 8) & 0xff;
406 case 1: /* [0.2 On][0.1 Off]... */
407 pHwData->LED_Blinking %= 3;
408 ltmp = 0x1010; /* Led 1 & 0 Green and Red */
409 if (pHwData->LED_Blinking == 2) /* Turn off */
412 case 2: /* [0.1 On][0.1 Off]... */
413 pHwData->LED_Blinking %= 2;
414 ltmp = 0x0010; /* Led 0 red color */
415 if (pHwData->LED_Blinking) /* Turn off */
418 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]... */
419 pHwData->LED_Blinking %= 15;
420 ltmp = 0x0010; /* Led 0 red color */
421 if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) /* Turn off 0.6 sec */
424 case 4: /* [300 On][ off ] */
425 ltmp = 0x1000; /* Led 1 Green color */
426 if (pHwData->LED_Blinking >= 3000)
427 ltmp = 0; /* led maybe on after 300sec * 32bit counter overlap. */
430 pHwData->LED_Blinking++;
432 reg->U1BC_LEDConfigure = ltmp;
433 if (LEDSet != 7) { /* Only 111 mode has 2 LEDs on PCB. */
434 reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; /* Copy LED result to each LED control register */
435 reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8;
437 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
439 } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) { /* If radio off */
440 if (reg->U1BC_LEDConfigure & 0x1010) {
441 reg->U1BC_LEDConfigure &= ~0x1010;
442 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure);
446 case 4: /* [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
447 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
448 /* Blinking if scanning is on progress */
449 if (pHwData->LED_Scanning) {
450 if (pHwData->LED_Blinking == 0) {
451 reg->U1BC_LEDConfigure |= 0x10;
452 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
453 pHwData->LED_Blinking = 1;
456 reg->U1BC_LEDConfigure &= ~0x10;
457 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
458 pHwData->LED_Blinking = 0;
463 if (reg->U1BC_LEDConfigure & 0x10) {
464 reg->U1BC_LEDConfigure &= ~0x10;
465 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
470 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
471 reg->U1BC_LEDConfigure |= 0x10;
472 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
476 case 6: /* [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing */
477 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
478 /* Blinking if scanning is on progress */
479 if (pHwData->LED_Scanning) {
480 if (pHwData->LED_Blinking == 0) {
481 reg->U1BC_LEDConfigure &= ~0xf;
482 reg->U1BC_LEDConfigure |= 0x10;
483 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 On */
484 pHwData->LED_Blinking = 1;
487 reg->U1BC_LEDConfigure &= ~0x1f;
488 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
489 pHwData->LED_Blinking = 0;
493 /* Gray blinking if in disconnect state and not scanning */
494 ltmp = reg->U1BC_LEDConfigure;
495 reg->U1BC_LEDConfigure &= ~0x1f;
496 if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) {
497 reg->U1BC_LEDConfigure |= 0x10;
498 reg->U1BC_LEDConfigure |=
499 LED_GRAY2[(pHwData->LED_Blinking % 30)];
501 pHwData->LED_Blinking++;
502 if (reg->U1BC_LEDConfigure != ltmp)
503 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
508 if ((reg->U1BC_LEDConfigure & 0x10) == 0) {
509 reg->U1BC_LEDConfigure |= 0x10;
510 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_0 Off */
514 case 5: /* [101] Only 1 Led be placed on PCB and use LED_1 for showing */
515 if (!pHwData->LED_LinkOn) { /* Blink only if not Link On */
516 /* Blinking if scanning is on progress */
517 if (pHwData->LED_Scanning) {
518 if (pHwData->LED_Blinking == 0) {
519 reg->U1BC_LEDConfigure |= 0x1000;
520 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
521 pHwData->LED_Blinking = 1;
524 reg->U1BC_LEDConfigure &= ~0x1000;
525 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
526 pHwData->LED_Blinking = 0;
531 if (reg->U1BC_LEDConfigure & 0x1000) {
532 reg->U1BC_LEDConfigure &= ~0x1000;
533 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 Off */
537 /* Is transmitting/receiving ?? */
538 if ((adapter->RxByteCount !=
539 pHwData->RxByteCountLast)
540 || (adapter->TxByteCount !=
541 pHwData->TxByteCountLast)) {
542 if ((reg->U1BC_LEDConfigure & 0x3000) !=
544 reg->U1BC_LEDConfigure |= 0x3000;
545 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
547 /* Update variable */
548 pHwData->RxByteCountLast =
549 adapter->RxByteCount;
550 pHwData->TxByteCountLast =
551 adapter->TxByteCount;
554 /* Turn On LED_1 and blinking if transmitting/receiving */
555 if ((reg->U1BC_LEDConfigure & 0x3000) !=
557 reg->U1BC_LEDConfigure &=
559 reg->U1BC_LEDConfigure |=
561 Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); /* LED_1 On */
566 default: /* Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active */
567 if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) {
568 reg->U1BC_LEDConfigure |= 0x3000; /* LED_1 is always on and event enable */
569 Wb35Reg_Write(pHwData, 0x03bc,
570 reg->U1BC_LEDConfigure);
573 if (pHwData->LED_Blinking) {
575 reg->U1BC_LEDConfigure &= ~0x0f;
576 reg->U1BC_LEDConfigure |= 0x10;
577 reg->U1BC_LEDConfigure |=
578 LED_GRAY[(pHwData->LED_Blinking - 1) % 20];
579 Wb35Reg_Write(pHwData, 0x03bc,
580 reg->U1BC_LEDConfigure);
582 pHwData->LED_Blinking += 2;
583 if (pHwData->LED_Blinking < 40)
586 pHwData->LED_Blinking = 0; /* Stop blinking */
587 reg->U1BC_LEDConfigure &= ~0x0f;
588 Wb35Reg_Write(pHwData, 0x03bc,
589 reg->U1BC_LEDConfigure);
594 if (pHwData->LED_LinkOn) {
595 if (!(reg->U1BC_LEDConfigure & 0x10)) { /* Check the LED_0 */
596 /* Try to turn ON LED_0 after gray blinking */
597 reg->U1BC_LEDConfigure |= 0x10;
598 pHwData->LED_Blinking = 1; /* Start blinking */
602 if (reg->U1BC_LEDConfigure & 0x10) { /* Check the LED_0 */
603 reg->U1BC_LEDConfigure &= ~0x10;
604 Wb35Reg_Write(pHwData, 0x03bc,
605 reg->U1BC_LEDConfigure);
612 pHwData->time_count += TimeInterval;
613 Wb35Tx_CurrentTime(adapter, pHwData->time_count);
614 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval);
615 add_timer(&pHwData->LEDTimer);
618 static int hal_init_hardware(struct ieee80211_hw *hw)
620 struct wbsoft_priv *priv = hw->priv;
621 struct hw_data *pHwData = &priv->sHwData;
624 pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME;
625 pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
627 if (!Wb35Reg_initial(pHwData))
628 goto error_reg_destroy;
630 if (!Wb35Tx_initial(pHwData))
631 goto error_tx_destroy;
633 if (!Wb35Rx_initial(pHwData))
634 goto error_rx_destroy;
636 init_timer(&pHwData->LEDTimer);
637 pHwData->LEDTimer.function = hal_led_control;
638 pHwData->LEDTimer.data = (unsigned long)priv;
639 pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000);
640 add_timer(&pHwData->LEDTimer);
642 SoftwareSet = hal_software_set(pHwData);
645 Wb35Tx_EP2VM_start(priv);
650 Wb35Rx_destroy(pHwData);
652 Wb35Tx_destroy(pHwData);
654 Wb35Reg_destroy(pHwData);
656 pHwData->SurpriseRemove = 1;
660 static int wb35_hw_init(struct ieee80211_hw *hw)
662 struct wbsoft_priv *priv = hw->priv;
663 struct hw_data *pHwData = &priv->sHwData;
670 pHwData->phy_type = RF_DECIDE_BY_INF;
672 priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold;
673 priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
675 priv->sLocalPara.region_INF = REGION_AUTO;
676 priv->sLocalPara.TxRateMode = RATE_AUTO;
677 priv->sLocalPara.bMacOperationMode = MODE_802_11_BG;
678 priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE;
679 priv->sLocalPara.bPreambleMode = AUTO_MODE;
680 priv->sLocalPara.bWepKeyError = false;
681 priv->sLocalPara.bToSelfPacketReceived = false;
682 priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */
684 priv->sLocalPara.RadioOffStatus.boSwRadioOff = false;
686 err = hal_init_hardware(hw);
690 EEPROM_region = hal_get_region_from_EEPROM(pHwData);
691 if (EEPROM_region != REGION_AUTO)
692 priv->sLocalPara.region = EEPROM_region;
694 if (priv->sLocalPara.region_INF != REGION_AUTO)
695 priv->sLocalPara.region = priv->sLocalPara.region_INF;
697 priv->sLocalPara.region = REGION_USA; /* default setting */
703 * If no user-defined address in the registry, use the address
704 * "burned" on the NIC instead.
706 pMacAddr = priv->sLocalPara.ThisMacAddress;
707 pMacAddr2 = priv->sLocalPara.PermanentAddress;
709 /* Reading ethernet address from EEPROM */
710 hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress);
711 if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0)
712 memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH);
714 /* Set the user define MAC address */
715 hal_set_ethernet_address(pHwData,
716 priv->sLocalPara.ThisMacAddress);
719 priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData);
720 pr_debug("Driver init, antenna no = %d\n", priv->sLocalPara.bAntennaNo);
721 hal_get_hw_radio_off(pHwData);
723 /* Waiting for HAL setting OK */
724 while (!hal_idle(pHwData))
729 HwRadioOff = hal_get_hw_radio_off(pHwData);
730 priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff;
732 hal_set_radio_mode(pHwData,
733 (unsigned char)(priv->sLocalPara.RadioOffStatus.
735 || priv->sLocalPara.RadioOffStatus.
738 /* Notify hal that the driver is ready now. */
739 hal_driver_init_OK(pHwData) = 1;
745 static int wb35_probe(struct usb_interface *intf,
746 const struct usb_device_id *id_table)
748 struct usb_device *udev = interface_to_usbdev(intf);
749 struct usb_endpoint_descriptor *endpoint;
750 struct usb_host_interface *interface;
751 struct ieee80211_hw *dev;
752 struct wbsoft_priv *priv;
753 struct wb_usb *pWbUsb;
759 /* Check the device if it already be opened */
760 nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
762 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
763 0x0, 0x400, <mp, 4, HZ * 100);
769 /* Is already initialized? */
770 ltmp = cpu_to_le32(ltmp);
776 dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
784 pWbUsb = &priv->sHwData.WbUsb;
787 interface = intf->cur_altsetting;
788 endpoint = &interface->endpoint[0].desc;
790 if (endpoint[2].wMaxPacketSize == 512) {
791 printk("[w35und] Working on USB 2.0\n");
795 err = wb35_hw_init(dev);
799 SET_IEEE80211_DEV(dev, &udev->dev);
801 struct hw_data *pHwData = &priv->sHwData;
802 unsigned char dev_addr[MAX_ADDR_LEN];
803 hal_get_permanent_address(pHwData, dev_addr);
804 SET_IEEE80211_PERM_ADDR(dev, dev_addr);
807 dev->extra_tx_headroom = 12; /* FIXME */
808 dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
809 dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
811 dev->channel_change_time = 1000;
812 dev->max_signal = 100;
815 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
817 err = ieee80211_register_hw(dev);
821 usb_set_intfdata(intf, dev);
826 ieee80211_free_hw(dev);
832 static void hal_halt(struct hw_data *pHwData)
834 del_timer_sync(&pHwData->LEDTimer);
835 /* XXX: Wait for Timer DPC exit. */
837 Wb35Rx_destroy(pHwData);
838 Wb35Tx_destroy(pHwData);
839 Wb35Reg_destroy(pHwData);
842 static void wb35_hw_halt(struct wbsoft_priv *adapter)
844 /* Turn off Rx and Tx hardware ability */
845 hal_stop(&adapter->sHwData);
846 pr_debug("[w35und] Hal_stop O.K.\n");
847 /* Waiting Irp completed */
850 hal_halt(&adapter->sHwData);
853 static void wb35_disconnect(struct usb_interface *intf)
855 struct ieee80211_hw *hw = usb_get_intfdata(intf);
856 struct wbsoft_priv *priv = hw->priv;
860 ieee80211_stop_queues(hw);
861 ieee80211_unregister_hw(hw);
862 ieee80211_free_hw(hw);
864 usb_set_intfdata(intf, NULL);
865 usb_put_dev(interface_to_usbdev(intf));
868 static struct usb_driver wb35_driver = {
870 .id_table = wb35_table,
872 .disconnect = wb35_disconnect,
875 static int __init wb35_init(void)
877 return usb_register(&wb35_driver);
880 static void __exit wb35_exit(void)
882 usb_deregister(&wb35_driver);
885 module_init(wb35_init);
886 module_exit(wb35_exit);