diff options
Diffstat (limited to 'drivers/staging/winbond/wbusb.c')
-rw-r--r-- | drivers/staging/winbond/wbusb.c | 785 |
1 files changed, 627 insertions, 158 deletions
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index 3b2d52819b4c..745279c528a2 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -2,6 +2,12 @@ * Copyright 2008 Pavel Machek <pavel@suse.cz> * * Distribute under GPLv2. + * + * The original driver was written by: + * Jeff Lee <YY_Lee@issc.com.tw> + * + * and was adapted to the 2.6 kernel by: + * Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar> */ #include <net/mac80211.h> #include <linux/usb.h> @@ -13,19 +19,18 @@ #include "wbhal_f.h" #include "wblinux_f.h" -MODULE_AUTHOR("Original by: Jeff Lee<YY_Lee@issc.com.tw> Adapted to 2.6.x by Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>"); MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); static struct usb_device_id wb35_table[] __devinitdata = { - {USB_DEVICE(0x0416, 0x0035)}, - {USB_DEVICE(0x18E8, 0x6201)}, - {USB_DEVICE(0x18E8, 0x6206)}, - {USB_DEVICE(0x18E8, 0x6217)}, - {USB_DEVICE(0x18E8, 0x6230)}, - {USB_DEVICE(0x18E8, 0x6233)}, - {USB_DEVICE(0x1131, 0x2035)}, + { USB_DEVICE(0x0416, 0x0035) }, + { USB_DEVICE(0x18E8, 0x6201) }, + { USB_DEVICE(0x18E8, 0x6206) }, + { USB_DEVICE(0x18E8, 0x6217) }, + { USB_DEVICE(0x18E8, 0x6230) }, + { USB_DEVICE(0x18E8, 0x6233) }, + { USB_DEVICE(0x1131, 0x2035) }, { 0, } }; @@ -36,7 +41,7 @@ static struct ieee80211_rate wbsoft_rates[] = { }; static struct ieee80211_channel wbsoft_channels[] = { - { .center_freq = 2412}, + { .center_freq = 2412 }, }; static struct ieee80211_supported_band wbsoft_band_2GHz = { @@ -47,14 +52,14 @@ static struct ieee80211_supported_band wbsoft_band_2GHz = { }; static int wbsoft_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_if_init_conf *conf) { printk("wbsoft_add interface called\n"); return 0; } static void wbsoft_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_if_init_conf *conf) { printk("wbsoft_remove interface called\n"); } @@ -79,36 +84,18 @@ static int wbsoft_get_tx_stats(struct ieee80211_hw *hw, } static void wbsoft_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, struct dev_mc_list *mclist) + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_mc_list *mclist) { - unsigned int bit_nr, new_flags; - u32 mc_filter[2]; - int i; + unsigned int new_flags; new_flags = 0; - if (*total_flags & FIF_PROMISC_IN_BSS) { + if (*total_flags & FIF_PROMISC_IN_BSS) new_flags |= FIF_PROMISC_IN_BSS; - mc_filter[1] = mc_filter[0] = ~0; - } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) { + else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) new_flags |= FIF_ALLMULTI; - mc_filter[1] = mc_filter[0] = ~0; - } else { - mc_filter[1] = mc_filter[0] = 0; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - printk("Should call ether_crc here\n"); - //bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - bit_nr = 0; - - bit_nr &= 0x3F; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - mclist = mclist->next; - } - } dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; @@ -124,7 +111,6 @@ static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb) return NETDEV_TX_OK; } - static int wbsoft_start(struct ieee80211_hw *dev) { struct wbsoft_priv *priv = dev->priv; @@ -134,6 +120,127 @@ static int wbsoft_start(struct ieee80211_hw *dev) return 0; } +static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + + if (radio_off) //disable Baseband receive off + { + pHwData->CurrentRadioSw = 1; // off + reg->M24_MacControl &= 0xffffffbf; + } else { + pHwData->CurrentRadioSw = 0; // on + reg->M24_MacControl |= 0x00000040; + } + Wb35Reg_Write(pHwData, 0x0824, reg->M24_MacControl); +} + +static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period) +{ + u32 tmp; + + if (pHwData->SurpriseRemove) + return; + + pHwData->BeaconPeriod = beacon_period; + tmp = pHwData->BeaconPeriod << 16; + tmp |= pHwData->ProbeDelay; + Wb35Reg_Write(pHwData, 0x0848, tmp); +} + +static void +hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + + printk("Going to channel: %d/%d\n", channel.band, channel.ChanNo); + + RFSynthesizer_SwitchingChannel(pHwData, channel); // Switch channel + pHwData->Channel = channel.ChanNo; + pHwData->band = channel.band; +#ifdef _PE_STATE_DUMP_ + printk("Set channel is %d, band =%d\n", pHwData->Channel, + pHwData->band); +#endif + reg->M28_MacControl &= ~0xff; // Clean channel information field + reg->M28_MacControl |= channel.ChanNo; + Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl, + (s8 *) & channel, sizeof(ChanInfo)); +} + +static void hal_set_current_channel(struct hw_data *pHwData, ChanInfo channel) +{ + hal_set_current_channel_ex(pHwData, channel); +} + +static void hal_set_accept_broadcast(struct hw_data *pHwData, u8 enable) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + + reg->M00_MacControl &= ~0x02000000; //The HW value + + if (enable) + reg->M00_MacControl |= 0x02000000; //The HW value + + Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl); +} + +//for wep key error detection, we need to accept broadcast packets to be received temporary. +static void hal_set_accept_promiscuous(struct hw_data *pHwData, u8 enable) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + if (enable) { + reg->M00_MacControl |= 0x00400000; + Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl); + } else { + reg->M00_MacControl &= ~0x00400000; + Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl); + } +} + +static void hal_set_accept_multicast(struct hw_data *pHwData, u8 enable) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + + reg->M00_MacControl &= ~0x01000000; //The HW value + if (enable) + reg->M00_MacControl |= 0x01000000; //The HW value + Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl); +} + +static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return; + + // 20040108 debug + if (!enable) //Due to SME and MLME are not suitable for 35 + return; + + reg->M00_MacControl &= ~0x04000000; //The HW value + if (enable) + reg->M00_MacControl |= 0x04000000; //The HW value + + Wb35Reg_Write(pHwData, 0x0800, reg->M00_MacControl); +} + static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) { struct wbsoft_priv *priv = dev->priv; @@ -142,36 +249,18 @@ static int wbsoft_config(struct ieee80211_hw *dev, u32 changed) printk("wbsoft_config called\n"); + /* Should use channel_num, or something, as that is already pre-translated */ ch.band = 1; - ch.ChanNo = 1; /* Should use channel_num, or something, as that is already pre-translated */ - + ch.ChanNo = 1; hal_set_current_channel(&priv->sHwData, ch); hal_set_beacon_period(&priv->sHwData, conf->beacon_int); -// hal_set_cap_info(&priv->sHwData, ?? ); -// hal_set_ssid(struct hw_data * pHwData, u8 * pssid, u8 ssid_len); ?? hal_set_accept_broadcast(&priv->sHwData, 1); - hal_set_accept_promiscuous(&priv->sHwData, 1); - hal_set_accept_multicast(&priv->sHwData, 1); - hal_set_accept_beacon(&priv->sHwData, 1); - hal_set_radio_mode(&priv->sHwData, 0); - //hal_set_antenna_number( struct hw_data * pHwData, u8 number ) - //hal_set_rf_power(struct hw_data * pHwData, u8 PowerIndex) - - -// hal_start_bss(&priv->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE); ?? + hal_set_accept_promiscuous(&priv->sHwData, 1); + hal_set_accept_multicast(&priv->sHwData, 1); + hal_set_accept_beacon(&priv->sHwData, 1); + hal_set_radio_mode(&priv->sHwData, 0); -//void hal_set_rates(struct hw_data * pHwData, u8 * pbss_rates, -// u8 length, unsigned char basic_rate_set) - - return 0; -} - -static int wbsoft_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - printk("wbsoft_config_interface called\n"); return 0; } @@ -183,63 +272,448 @@ static u64 wbsoft_get_tsf(struct ieee80211_hw *dev) static const struct ieee80211_ops wbsoft_ops = { .tx = wbsoft_tx, - .start = wbsoft_start, /* Start can be pretty much empty as we do wb35_hw_init() during probe? */ + .start = wbsoft_start, .stop = wbsoft_stop, .add_interface = wbsoft_add_interface, .remove_interface = wbsoft_remove_interface, .config = wbsoft_config, - .config_interface = wbsoft_config_interface, .configure_filter = wbsoft_configure_filter, .get_stats = wbsoft_get_stats, .get_tx_stats = wbsoft_get_tx_stats, .get_tsf = wbsoft_get_tsf, -// conf_tx: hal_set_cwmin()/hal_set_cwmax; }; -static unsigned char wb35_hw_init(struct ieee80211_hw *hw) +static void +hal_set_ethernet_address(struct hw_data *pHwData, u8 * current_address) +{ + u32 ltmp[2]; + + if (pHwData->SurpriseRemove) + return; + + memcpy(pHwData->CurrentMacAddress, current_address, ETH_ALEN); + + ltmp[0] = cpu_to_le32(*(u32 *) pHwData->CurrentMacAddress); + ltmp[1] = + cpu_to_le32(*(u32 *) (pHwData->CurrentMacAddress + 4)) & 0xffff; + + Wb35Reg_BurstWrite(pHwData, 0x03e8, ltmp, 2, AUTO_INCREMENT); +} + +static void +hal_get_permanent_address(struct hw_data *pHwData, u8 * pethernet_address) +{ + if (pHwData->SurpriseRemove) + return; + + memcpy(pethernet_address, pHwData->PermanentMacAddress, 6); +} + +static void hal_stop(struct hw_data *pHwData) +{ + struct wb35_reg *reg = &pHwData->reg; + + pHwData->Wb35Rx.rx_halt = 1; + Wb35Rx_stop(pHwData); + + pHwData->Wb35Tx.tx_halt = 1; + Wb35Tx_stop(pHwData); + + reg->D00_DmaControl &= ~0xc0000000; //Tx Off, Rx Off + Wb35Reg_Write(pHwData, 0x0400, reg->D00_DmaControl); +} + +static unsigned char hal_idle(struct hw_data *pHwData) +{ + struct wb35_reg *reg = &pHwData->reg; + struct wb_usb *pWbUsb = &pHwData->WbUsb; + + if (!pHwData->SurpriseRemove + && (pWbUsb->DetectCount || reg->EP0vm_state != VM_STOP)) + return false; + + return true; +} + +u8 hal_get_antenna_number(struct hw_data *pHwData) +{ + struct wb35_reg *reg = &pHwData->reg; + + if ((reg->BB2C & BIT(11)) == 0) + return 0; + else + return 1; +} + +/* 0 : radio on; 1: radio off */ +static u8 hal_get_hw_radio_off(struct hw_data * pHwData) +{ + struct wb35_reg *reg = &pHwData->reg; + + if (pHwData->SurpriseRemove) + return 1; + + //read the bit16 of register U1B0 + Wb35Reg_Read(pHwData, 0x3b0, ®->U1B0); + if ((reg->U1B0 & 0x00010000)) { + pHwData->CurrentRadioHw = 1; + return 1; + } else { + pHwData->CurrentRadioHw = 0; + return 0; + } +} + +static u8 LED_GRAY[20] = { + 0, 3, 4, 6, 8, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 8, 6, 4, 2 +}; + +static u8 LED_GRAY2[30] = { + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 14, 13, 12, 11, 10, 9, 8 +}; + +static void hal_led_control(unsigned long data) +{ + struct wbsoft_priv *adapter = (struct wbsoft_priv *)data; + struct hw_data *pHwData = &adapter->sHwData; + struct wb35_reg *reg = &pHwData->reg; + u32 LEDSet = (pHwData->SoftwareSet & HAL_LED_SET_MASK) >> HAL_LED_SET_SHIFT; + u32 TimeInterval = 500, ltmp, ltmp2; + ltmp = 0; + + if (pHwData->SurpriseRemove) + return; + + if (pHwData->LED_control) { + ltmp2 = pHwData->LED_control & 0xff; + if (ltmp2 == 5) // 5 is WPS mode + { + TimeInterval = 100; + ltmp2 = (pHwData->LED_control >> 8) & 0xff; + switch (ltmp2) { + case 1: // [0.2 On][0.1 Off]... + pHwData->LED_Blinking %= 3; + ltmp = 0x1010; // Led 1 & 0 Green and Red + if (pHwData->LED_Blinking == 2) // Turn off + ltmp = 0; + break; + case 2: // [0.1 On][0.1 Off]... + pHwData->LED_Blinking %= 2; + ltmp = 0x0010; // Led 0 red color + if (pHwData->LED_Blinking) // Turn off + ltmp = 0; + break; + 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]... + pHwData->LED_Blinking %= 15; + ltmp = 0x0010; // Led 0 red color + if ((pHwData->LED_Blinking >= 9) || (pHwData->LED_Blinking % 2)) // Turn off 0.6 sec + ltmp = 0; + break; + case 4: // [300 On][ off ] + ltmp = 0x1000; // Led 1 Green color + if (pHwData->LED_Blinking >= 3000) + ltmp = 0; // led maybe on after 300sec * 32bit counter overlap. + break; + } + pHwData->LED_Blinking++; + + reg->U1BC_LEDConfigure = ltmp; + if (LEDSet != 7) // Only 111 mode has 2 LEDs on PCB. + { + reg->U1BC_LEDConfigure |= (ltmp & 0xff) << 8; // Copy LED result to each LED control register + reg->U1BC_LEDConfigure |= (ltmp & 0xff00) >> 8; + } + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); + } + } else if (pHwData->CurrentRadioSw || pHwData->CurrentRadioHw) // If radio off + { + if (reg->U1BC_LEDConfigure & 0x1010) { + reg->U1BC_LEDConfigure &= ~0x1010; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); + } + } else { + switch (LEDSet) { + case 4: // [100] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing + if (!pHwData->LED_LinkOn) // Blink only if not Link On + { + // Blinking if scanning is on progress + if (pHwData->LED_Scanning) { + if (pHwData->LED_Blinking == 0) { + reg->U1BC_LEDConfigure |= 0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On + pHwData->LED_Blinking = 1; + TimeInterval = 300; + } else { + reg->U1BC_LEDConfigure &= ~0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + pHwData->LED_Blinking = 0; + TimeInterval = 300; + } + } else { + //Turn Off LED_0 + if (reg->U1BC_LEDConfigure & 0x10) { + reg->U1BC_LEDConfigure &= ~0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + } + } + } else { + // Turn On LED_0 + if ((reg->U1BC_LEDConfigure & 0x10) == 0) { + reg->U1BC_LEDConfigure |= 0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + } + } + break; + + case 6: // [110] Only 1 Led be placed on PCB and use pin 21 of IC. Use LED_0 for showing + if (!pHwData->LED_LinkOn) // Blink only if not Link On + { + // Blinking if scanning is on progress + if (pHwData->LED_Scanning) { + if (pHwData->LED_Blinking == 0) { + reg->U1BC_LEDConfigure &= ~0xf; + reg->U1BC_LEDConfigure |= 0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 On + pHwData->LED_Blinking = 1; + TimeInterval = 300; + } else { + reg->U1BC_LEDConfigure &= ~0x1f; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + pHwData->LED_Blinking = 0; + TimeInterval = 300; + } + } else { + // 20060901 Gray blinking if in disconnect state and not scanning + ltmp = reg->U1BC_LEDConfigure; + reg->U1BC_LEDConfigure &= ~0x1f; + if (LED_GRAY2[(pHwData->LED_Blinking % 30)]) { + reg->U1BC_LEDConfigure |= 0x10; + reg->U1BC_LEDConfigure |= + LED_GRAY2[(pHwData->LED_Blinking % 30)]; + } + pHwData->LED_Blinking++; + if (reg->U1BC_LEDConfigure != ltmp) + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + TimeInterval = 100; + } + } else { + // Turn On LED_0 + if ((reg->U1BC_LEDConfigure & 0x10) == 0) { + reg->U1BC_LEDConfigure |= 0x10; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_0 Off + } + } + break; + + case 5: // [101] Only 1 Led be placed on PCB and use LED_1 for showing + if (!pHwData->LED_LinkOn) // Blink only if not Link On + { + // Blinking if scanning is on progress + if (pHwData->LED_Scanning) { + if (pHwData->LED_Blinking == 0) { + reg->U1BC_LEDConfigure |= + 0x1000; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On + pHwData->LED_Blinking = 1; + TimeInterval = 300; + } else { + reg->U1BC_LEDConfigure &= + ~0x1000; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off + pHwData->LED_Blinking = 0; + TimeInterval = 300; + } + } else { + //Turn Off LED_1 + if (reg->U1BC_LEDConfigure & 0x1000) { + reg->U1BC_LEDConfigure &= + ~0x1000; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 Off + } + } + } else { + // Is transmitting/receiving ?? + if ((adapter->RxByteCount != + pHwData->RxByteCountLast) + || (adapter->TxByteCount != + pHwData->TxByteCountLast)) { + if ((reg->U1BC_LEDConfigure & 0x3000) != + 0x3000) { + reg->U1BC_LEDConfigure |= + 0x3000; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On + } + // Update variable + pHwData->RxByteCountLast = + adapter->RxByteCount; + pHwData->TxByteCountLast = + adapter->TxByteCount; + TimeInterval = 200; + } else { + // Turn On LED_1 and blinking if transmitting/receiving + if ((reg->U1BC_LEDConfigure & 0x3000) != + 0x1000) { + reg->U1BC_LEDConfigure &= + ~0x3000; + reg->U1BC_LEDConfigure |= + 0x1000; + Wb35Reg_Write(pHwData, 0x03bc, reg->U1BC_LEDConfigure); // LED_1 On + } + } + } + break; + + default: // Default setting. 2 LED be placed on PCB. LED_0: Link On LED_1 Active + if ((reg->U1BC_LEDConfigure & 0x3000) != 0x3000) { + reg->U1BC_LEDConfigure |= 0x3000; // LED_1 is always on and event enable + Wb35Reg_Write(pHwData, 0x03bc, + reg->U1BC_LEDConfigure); + } + + if (pHwData->LED_Blinking) { + // Gray blinking + reg->U1BC_LEDConfigure &= ~0x0f; + reg->U1BC_LEDConfigure |= 0x10; + reg->U1BC_LEDConfigure |= + LED_GRAY[(pHwData->LED_Blinking - 1) % 20]; + Wb35Reg_Write(pHwData, 0x03bc, + reg->U1BC_LEDConfigure); + + pHwData->LED_Blinking += 2; + if (pHwData->LED_Blinking < 40) + TimeInterval = 100; + else { + pHwData->LED_Blinking = 0; // Stop blinking + reg->U1BC_LEDConfigure &= ~0x0f; + Wb35Reg_Write(pHwData, 0x03bc, + reg->U1BC_LEDConfigure); + } + break; + } + + if (pHwData->LED_LinkOn) { + if (!(reg->U1BC_LEDConfigure & 0x10)) // Check the LED_0 + { + //Try to turn ON LED_0 after gray blinking + reg->U1BC_LEDConfigure |= 0x10; + pHwData->LED_Blinking = 1; //Start blinking + TimeInterval = 50; + } + } else { + if (reg->U1BC_LEDConfigure & 0x10) // Check the LED_0 + { + reg->U1BC_LEDConfigure &= ~0x10; + Wb35Reg_Write(pHwData, 0x03bc, + reg->U1BC_LEDConfigure); + } + } + break; + } + + //20060828.1 Active send null packet to avoid AP disconnect + if (pHwData->LED_LinkOn) { + pHwData->NullPacketCount += TimeInterval; + if (pHwData->NullPacketCount >= + DEFAULT_NULL_PACKET_COUNT) { + pHwData->NullPacketCount = 0; + } + } + } + + pHwData->time_count += TimeInterval; + Wb35Tx_CurrentTime(adapter, pHwData->time_count); // 20060928 add + pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(TimeInterval); + add_timer(&pHwData->LEDTimer); +} + +static int hal_init_hardware(struct ieee80211_hw *hw) { struct wbsoft_priv *priv = hw->priv; - struct hw_data * pHwData; - u8 *pMacAddr; - u8 *pMacAddr2; - u32 InitStep = 0; - u8 EEPROM_region; - u8 HwRadioOff; - - // - // Setting default value for Linux - // - priv->sLocalPara.region_INF = REGION_AUTO; - priv->sLocalPara.TxRateMode = RATE_AUTO; - priv->sLocalPara.bMacOperationMode = MODE_802_11_BG; // B/G mode - priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold; - priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; - hal_set_phy_type( &priv->sHwData, RF_WB_242_1 ); - priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE; - priv->sLocalPara.bPreambleMode = AUTO_MODE; + struct hw_data *pHwData = &priv->sHwData; + u16 SoftwareSet; + + pHwData->MaxReceiveLifeTime = DEFAULT_MSDU_LIFE_TIME; + pHwData->FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; + + if (!Wb35Reg_initial(pHwData)) + goto error_reg_destroy; + + if (!Wb35Tx_initial(pHwData)) + goto error_tx_destroy; + + if (!Wb35Rx_initial(pHwData)) + goto error_rx_destroy; + + init_timer(&pHwData->LEDTimer); + pHwData->LEDTimer.function = hal_led_control; + pHwData->LEDTimer.data = (unsigned long)priv; + pHwData->LEDTimer.expires = jiffies + msecs_to_jiffies(1000); + add_timer(&pHwData->LEDTimer); + + SoftwareSet = hal_software_set(pHwData); + +#ifdef Vendor2 + // Try to make sure the EEPROM contain + SoftwareSet >>= 8; + if (SoftwareSet != 0x82) + return false; +#endif + + Wb35Rx_start(hw); + Wb35Tx_EP2VM_start(priv); + + return 0; + +error_rx_destroy: + Wb35Rx_destroy(pHwData); +error_tx_destroy: + Wb35Tx_destroy(pHwData); +error_reg_destroy: + Wb35Reg_destroy(pHwData); + + pHwData->SurpriseRemove = 1; + return -EINVAL; +} + +static int wb35_hw_init(struct ieee80211_hw *hw) +{ + struct wbsoft_priv *priv = hw->priv; + struct hw_data *pHwData = &priv->sHwData; + u8 EEPROM_region; + u8 HwRadioOff; + u8 *pMacAddr2; + u8 *pMacAddr; + int err; + + pHwData->phy_type = RF_DECIDE_BY_INF; + + priv->Mds.TxRTSThreshold = DEFAULT_RTSThreshold; + priv->Mds.TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; + + priv->sLocalPara.region_INF = REGION_AUTO; + priv->sLocalPara.TxRateMode = RATE_AUTO; + priv->sLocalPara.bMacOperationMode = MODE_802_11_BG; + priv->sLocalPara.MTUsize = MAX_ETHERNET_PACKET_SIZE; + priv->sLocalPara.bPreambleMode = AUTO_MODE; + priv->sLocalPara.bWepKeyError = false; + priv->sLocalPara.bToSelfPacketReceived = false; + priv->sLocalPara.WepKeyDetectTimerCount = 2 * 100; /* 2 seconds */ + priv->sLocalPara.RadioOffStatus.boSwRadioOff = false; - pHwData = &priv->sHwData; - hal_set_phy_type( pHwData, RF_DECIDE_BY_INF ); - - //added by ws for wep key error detection - priv->sLocalPara.bWepKeyError= false; - priv->sLocalPara.bToSelfPacketReceived = false; - priv->sLocalPara.WepKeyDetectTimerCount= 2 * 100; /// 2 seconds - - // Initial USB hal - InitStep = 1; - pHwData = &priv->sHwData; - if (!hal_init_hardware(hw)) + + err = hal_init_hardware(hw); + if (err) goto error; - EEPROM_region = hal_get_region_from_EEPROM( pHwData ); + EEPROM_region = hal_get_region_from_EEPROM(pHwData); if (EEPROM_region != REGION_AUTO) priv->sLocalPara.region = EEPROM_region; else { if (priv->sLocalPara.region_INF != REGION_AUTO) priv->sLocalPara.region = priv->sLocalPara.region_INF; else - priv->sLocalPara.region = REGION_USA; //default setting + priv->sLocalPara.region = REGION_USA; /* default setting */ } // Get Software setting flag from hal @@ -247,93 +721,80 @@ static unsigned char wb35_hw_init(struct ieee80211_hw *hw) if (hal_software_set(pHwData) & 0x00000001) priv->sLocalPara.boAntennaDiversity = true; - // - // For TS module - // - InitStep = 2; - - // For MDS module - InitStep = 3; Mds_initial(priv); - //======================================= - // Initialize the SME, SCAN, MLME, ROAM - //======================================= - InitStep = 4; - InitStep = 5; - InitStep = 6; - - // If no user-defined address in the registry, use the addresss "burned" on the NIC instead. + /* + * If no user-defined address in the registry, use the addresss + * "burned" on the NIC instead. + */ pMacAddr = priv->sLocalPara.ThisMacAddress; pMacAddr2 = priv->sLocalPara.PermanentAddress; - hal_get_permanent_address( pHwData, priv->sLocalPara.PermanentAddress );// Reading ethernet address from EEPROM + + /* Reading ethernet address from EEPROM */ + hal_get_permanent_address(pHwData, priv->sLocalPara.PermanentAddress); if (memcmp(pMacAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) == 0) memcpy(pMacAddr, pMacAddr2, MAC_ADDR_LENGTH); else { - // Set the user define MAC address - hal_set_ethernet_address(pHwData, priv->sLocalPara.ThisMacAddress); + /* Set the user define MAC address */ + hal_set_ethernet_address(pHwData, + priv->sLocalPara.ThisMacAddress); } - //get current antenna priv->sLocalPara.bAntennaNo = hal_get_antenna_number(pHwData); #ifdef _PE_STATE_DUMP_ printk("Driver init, antenna no = %d\n", psLOCAL->bAntennaNo); #endif - hal_get_hw_radio_off( pHwData ); + hal_get_hw_radio_off(pHwData); - // Waiting for HAL setting OK + /* Waiting for HAL setting OK */ while (!hal_idle(pHwData)) msleep(10); MTO_Init(priv); - HwRadioOff = hal_get_hw_radio_off( pHwData ); + HwRadioOff = hal_get_hw_radio_off(pHwData); priv->sLocalPara.RadioOffStatus.boHwRadioOff = !!HwRadioOff; - hal_set_radio_mode( pHwData, (unsigned char)(priv->sLocalPara.RadioOffStatus.boSwRadioOff || priv->sLocalPara.RadioOffStatus.boHwRadioOff) ); + hal_set_radio_mode(pHwData, + (unsigned char)(priv->sLocalPara.RadioOffStatus. + boSwRadioOff + || priv->sLocalPara.RadioOffStatus. + boHwRadioOff)); - hal_driver_init_OK(pHwData) = 1; // Notify hal that the driver is ready now. - //set a tx power for reference..... -// sme_set_tx_power_level(priv, 12); FIXME? - return true; + /* Notify hal that the driver is ready now. */ + hal_driver_init_OK(pHwData) = 1; error: - switch (InitStep) { - case 5: - case 4: - case 3: Mds_Destroy( priv ); - case 2: - case 1: hal_halt( pHwData, NULL ); - case 0: break; - } - - return false; + return err; } -static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table) +static int wb35_probe(struct usb_interface *intf, + const struct usb_device_id *id_table) { - struct wb_usb *pWbUsb; - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - u32 ltmp; struct usb_device *udev = interface_to_usbdev(intf); - struct wbsoft_priv *priv; + struct usb_endpoint_descriptor *endpoint; + struct usb_host_interface *interface; struct ieee80211_hw *dev; + struct wbsoft_priv *priv; + struct wb_usb *pWbUsb; int nr, err; + u32 ltmp; usb_get_dev(udev); - // 20060630.2 Check the device if it already be opened - nr = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ), - 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, - 0x0, 0x400, <mp, 4, HZ*100 ); + /* Check the device if it already be opened */ + nr = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x01, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x0, 0x400, <mp, 4, HZ * 100); if (nr < 0) { err = nr; goto error; } + /* Is already initialized? */ ltmp = cpu_to_le32(ltmp); - if (ltmp) { // Is already initialized? + if (ltmp) { err = -EBUSY; goto error; } @@ -351,23 +812,22 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id pWbUsb = &priv->sHwData.WbUsb; pWbUsb->udev = udev; - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; + interface = intf->cur_altsetting; + endpoint = &interface->endpoint[0].desc; if (endpoint[2].wMaxPacketSize == 512) { printk("[w35und] Working on USB 2.0\n"); pWbUsb->IsUsb20 = 1; } - if (!wb35_hw_init(dev)) { - err = -EINVAL; + err = wb35_hw_init(dev); + if (err) goto error_free_hw; - } SET_IEEE80211_DEV(dev, &udev->dev); { - struct hw_data * pHwData = &priv->sHwData; - unsigned char dev_addr[MAX_ADDR_LEN]; + struct hw_data *pHwData = &priv->sHwData; + unsigned char dev_addr[MAX_ADDR_LEN]; hal_get_permanent_address(pHwData, dev_addr); SET_IEEE80211_PERM_ADDR(dev, dev_addr); } @@ -397,22 +857,31 @@ error: return err; } +static void hal_halt(struct hw_data *pHwData) +{ + del_timer_sync(&pHwData->LEDTimer); + /* XXX: Wait for Timer DPC exit. */ + msleep(100); + Wb35Rx_destroy(pHwData); + Wb35Tx_destroy(pHwData); + Wb35Reg_destroy(pHwData); +} + static void wb35_hw_halt(struct wbsoft_priv *adapter) { - Mds_Destroy( adapter ); + Mds_Destroy(adapter); - // Turn off Rx and Tx hardware ability - hal_stop( &adapter->sHwData ); + /* Turn off Rx and Tx hardware ability */ + hal_stop(&adapter->sHwData); #ifdef _PE_USB_INI_DUMP_ printk("[w35und] Hal_stop O.K.\n"); #endif - msleep(100);// Waiting Irp completed + /* Waiting Irp completed */ + msleep(100); - // Halt the HAL - hal_halt(&adapter->sHwData, NULL); + hal_halt(&adapter->sHwData); } - static void wb35_disconnect(struct usb_interface *intf) { struct ieee80211_hw *hw = usb_get_intfdata(intf); |