// // Description: // Tx Power tracking mechanism routine on 87SE. // Created by Roger, 2007.12.11. // void TxPwrTracking87SE( struct net_device *dev ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); u8 tmpu1Byte, CurrentThermal, Idx; char CckTxPwrIdx, OfdmTxPwrIdx; //u32 u4bRfReg; tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); CurrentThermal = (tmpu1Byte & 0xf0)>>4; //[ 7:4]: thermal meter indication. CurrentThermal = (CurrentThermal>0x0c)? 0x0c:CurrentThermal;//lzm add 080826 //printk("TxPwrTracking87SE(): CurrentThermal(%d)\n", CurrentThermal); if( CurrentThermal != priv->ThermalMeter) { // printk("TxPwrTracking87SE(): Thermal meter changed!!!\n"); // Update Tx Power level on each channel. for(Idx = 1; Idx<15; Idx++) { CckTxPwrIdx = priv->chtxpwr[Idx]; OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; if( CurrentThermal > priv->ThermalMeter ) { // higher thermal meter. CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter)*2; if(CckTxPwrIdx >35) CckTxPwrIdx = 35; // Force TxPower to maximal index. if(OfdmTxPwrIdx >35) OfdmTxPwrIdx = 35; } else { // lower thermal meter. CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal)*2; if(CckTxPwrIdx <0) CckTxPwrIdx = 0; if(OfdmTxPwrIdx <0) OfdmTxPwrIdx = 0; } // Update TxPower level on CCK and OFDM resp. priv->chtxpwr[Idx] = CckTxPwrIdx; priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; } // Update TxPower level immediately. rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); } priv->ThermalMeter = CurrentThermal; }
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) { rtl8225z2_SetTXPowerLevel(dev, ch); RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch]) RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); mdelay(1); force_pci_posting(dev); mdelay(10); }
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) { /* short gset = (priv->ieee80211->state == IEEE80211_LINKED && ieee80211_is_54g(priv->ieee80211->current_network)) || priv->ieee80211->iw_mode == IW_MODE_MONITOR; */ rtl8225z2_SetTXPowerLevel(dev, ch); RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); //YJ,add,080828, if set channel failed, write again if((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch]) { RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); } mdelay(1); force_pci_posting(dev); mdelay(10); //deleted by David : 2006/8/9 #if 0 write_nic_byte(dev,SIFS,0x22);// SIFS: 0x22 if(gset) write_nic_byte(dev,DIFS,20); //DIFS: 20 else write_nic_byte(dev,DIFS,0x24); //DIFS: 36 if(priv->ieee80211->state == IEEE80211_LINKED && ieee80211_is_shortslot(priv->ieee80211->current_network)) write_nic_byte(dev,SLOT,0x9); //SLOT: 9 else write_nic_byte(dev,SLOT,0x14); //SLOT: 20 (0x14) if(gset){ write_nic_byte(dev,EIFS,91 - 20); // EIFS: 91 (0x5B) write_nic_byte(dev,CW_VAL,0x73); //CW VALUE: 0x37 //DMESG("using G net params"); }else{ write_nic_byte(dev,EIFS,91 - 0x24); // EIFS: 91 (0x5B) write_nic_byte(dev,CW_VAL,0xa5); //CW VALUE: 0x37 //DMESG("using B net params"); } #endif }
void TxPwrTracking87SE(struct net_device *dev) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); u8 tmpu1Byte, CurrentThermal, Idx; char CckTxPwrIdx, OfdmTxPwrIdx; tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); CurrentThermal = (tmpu1Byte & 0xf0) >> 4; CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c:CurrentThermal; if (CurrentThermal != priv->ThermalMeter) { for (Idx = 1; Idx < 15; Idx++) { CckTxPwrIdx = priv->chtxpwr[Idx]; OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; if (CurrentThermal > priv->ThermalMeter) { CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; if (CckTxPwrIdx > 35) CckTxPwrIdx = 35; if (OfdmTxPwrIdx > 35) OfdmTxPwrIdx = 35; } else { CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; if (CckTxPwrIdx < 0) CckTxPwrIdx = 0; if (OfdmTxPwrIdx < 0) OfdmTxPwrIdx = 0; } priv->chtxpwr[Idx] = CckTxPwrIdx; priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; } rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); } priv->ThermalMeter = CurrentThermal; }
/* * Description: * Tx Power tracking mechanism routine on 87SE. */ void TxPwrTracking87SE(struct net_device *dev) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); u8 tmpu1Byte, CurrentThermal, Idx; char CckTxPwrIdx, OfdmTxPwrIdx; tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */ CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c:CurrentThermal; if (CurrentThermal != priv->ThermalMeter) { /* Update Tx Power level on each channel. */ for (Idx = 1; Idx < 15; Idx++) { CckTxPwrIdx = priv->chtxpwr[Idx]; OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; if (CurrentThermal > priv->ThermalMeter) { /* higher thermal meter. */ CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; if (CckTxPwrIdx > 35) CckTxPwrIdx = 35; /* Force TxPower to maximal index. */ if (OfdmTxPwrIdx > 35) OfdmTxPwrIdx = 35; } else { /* lower thermal meter. */ CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; if (CckTxPwrIdx < 0) CckTxPwrIdx = 0; if (OfdmTxPwrIdx < 0) OfdmTxPwrIdx = 0; } /* Update TxPower level on CCK and OFDM resp. */ priv->chtxpwr[Idx] = CckTxPwrIdx; priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; } /* Update TxPower level immediately. */ rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); } priv->ThermalMeter = CurrentThermal; }
void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) { struct r8180_priv *priv = ieee80211_priv(dev); short gset = (priv->ieee80211->state == IEEE80211_LINKED && ieee80211_is_54g(priv->ieee80211->current_network)) || priv->ieee80211->iw_mode == IW_MODE_MONITOR; rtl8225z2_SetTXPowerLevel(dev, ch); write_rtl8225(dev, 0x7, rtl8225_chan[ch]); force_pci_posting(dev); mdelay(10); write_nic_byte(dev,SIFS,0x22);// SIFS: 0x22 if(gset) write_nic_byte(dev,DIFS,20); //DIFS: 20 else write_nic_byte(dev,DIFS,0x24); //DIFS: 36 if(priv->ieee80211->state == IEEE80211_LINKED && ieee80211_is_shortslot(priv->ieee80211->current_network)) write_nic_byte(dev,SLOT,0x9); //SLOT: 9 else write_nic_byte(dev,SLOT,0x14); //SLOT: 20 (0x14) if(gset){ write_nic_byte(dev,EIFS,91 - 20); // EIFS: 91 (0x5B) write_nic_byte(dev,CW_VAL,0x73); //CW VALUE: 0x37 //DMESG("using G net params"); }else{ write_nic_byte(dev,EIFS,91 - 0x24); // EIFS: 91 (0x5B) write_nic_byte(dev,CW_VAL,0xa5); //CW VALUE: 0x37 //DMESG("using B net params"); } }
void rtl8225z2_rf_init(struct net_device *dev) { struct r8180_priv *priv = ieee80211_priv(dev); int i; short channel = 1; u16 brsr; u32 data, addr; priv->chan = channel; rtl8225_host_pci_init(dev); write_nic_dword(dev, RF_TIMING, 0x000a8008); brsr = read_nic_word(dev, BRSR); write_nic_word(dev, BRSR, 0xffff); write_nic_dword(dev, RF_PARA, 0x100044); rtl8180_set_mode(dev, EPROM_CMD_CONFIG); write_nic_byte(dev, CONFIG3, 0x44); rtl8180_set_mode(dev, EPROM_CMD_NORMAL); rtl8185_rf_pins_enable(dev); write_rtl8225(dev, 0x0, 0x2bf); mdelay(1); write_rtl8225(dev, 0x1, 0xee0); mdelay(1); write_rtl8225(dev, 0x2, 0x44d); mdelay(1); write_rtl8225(dev, 0x3, 0x441); mdelay(1); write_rtl8225(dev, 0x4, 0x8c3); mdelay(1); write_rtl8225(dev, 0x5, 0xc72); mdelay(1); write_rtl8225(dev, 0x6, 0xe6); mdelay(1); write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1); write_rtl8225(dev, 0x8, 0x3f); mdelay(1); write_rtl8225(dev, 0x9, 0x335); mdelay(1); write_rtl8225(dev, 0xa, 0x9d4); mdelay(1); write_rtl8225(dev, 0xb, 0x7bb); mdelay(1); write_rtl8225(dev, 0xc, 0x850); mdelay(1); write_rtl8225(dev, 0xd, 0xcdf); mdelay(1); write_rtl8225(dev, 0xe, 0x2b); mdelay(1); write_rtl8225(dev, 0xf, 0x114); mdelay(100); write_rtl8225(dev, 0x0, 0x1b7); for (i = 0; i < 95; i++) { write_rtl8225(dev, 0x1, (u8)(i + 1)); write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]); } write_rtl8225(dev, 0x3, 0x80); write_rtl8225(dev, 0x5, 0x4); write_rtl8225(dev, 0x0, 0xb7); write_rtl8225(dev, 0x2, 0xc4d); /* FIXME!! rtl8187 we have to check if calibrarion * is successful and eventually cal. again (repeat * the two write on reg 2) */ data = read_rtl8225(dev, 6); if (!(data & 0x00000080)) { write_rtl8225(dev, 0x02, 0x0c4d); force_pci_posting(dev); mdelay(200); write_rtl8225(dev, 0x02, 0x044d); force_pci_posting(dev); mdelay(100); data = read_rtl8225(dev, 6); if (!(data & 0x00000080)) DMESGW("RF Calibration Failed!!!!\n"); } mdelay(200); write_rtl8225(dev, 0x0, 0x2bf); for (i = 0; i < 128; i++) { data = rtl8225_agc[i]; addr = i + 0x80; /* enable writing AGC table */ write_phy_ofdm(dev, 0xb, data); mdelay(1); write_phy_ofdm(dev, 0xa, addr); mdelay(1); } force_pci_posting(dev); mdelay(1); write_phy_ofdm(dev, 0x00, 0x01); mdelay(1); write_phy_ofdm(dev, 0x01, 0x02); mdelay(1); write_phy_ofdm(dev, 0x02, 0x62); mdelay(1); write_phy_ofdm(dev, 0x03, 0x00); mdelay(1); write_phy_ofdm(dev, 0x04, 0x00); mdelay(1); write_phy_ofdm(dev, 0x05, 0x00); mdelay(1); write_phy_ofdm(dev, 0x06, 0x40); mdelay(1); write_phy_ofdm(dev, 0x07, 0x00); mdelay(1); write_phy_ofdm(dev, 0x08, 0x40); mdelay(1); write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1); write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1); write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1); write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1); write_phy_ofdm(dev, 0x0d, 0x43); write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1); write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1); write_phy_ofdm(dev, 0x10, 0x84); mdelay(1); write_phy_ofdm(dev, 0x11, 0x07); mdelay(1); write_phy_ofdm(dev, 0x12, 0x20); mdelay(1); write_phy_ofdm(dev, 0x13, 0x20); mdelay(1); write_phy_ofdm(dev, 0x14, 0x00); mdelay(1); write_phy_ofdm(dev, 0x15, 0x40); mdelay(1); write_phy_ofdm(dev, 0x16, 0x00); mdelay(1); write_phy_ofdm(dev, 0x17, 0x40); mdelay(1); write_phy_ofdm(dev, 0x18, 0xef); mdelay(1); write_phy_ofdm(dev, 0x19, 0x19); mdelay(1); write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1); write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1); write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1); write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1); write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1); write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1); write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1); write_phy_ofdm(dev, 0x21, 0x17); mdelay(1); write_phy_ofdm(dev, 0x22, 0x16); mdelay(1); write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */ write_phy_ofdm(dev, 0x24, 0x46); mdelay(1); write_phy_ofdm(dev, 0x25, 0x00); mdelay(1); write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); write_phy_ofdm(dev, 0x27, 0x88); mdelay(1); rtl8225z2_set_gain(dev, 4); write_phy_cck(dev, 0x0, 0x98); mdelay(1); write_phy_cck(dev, 0x3, 0x20); mdelay(1); write_phy_cck(dev, 0x4, 0x7e); mdelay(1); write_phy_cck(dev, 0x5, 0x12); mdelay(1); write_phy_cck(dev, 0x6, 0xfc); mdelay(1); write_phy_cck(dev, 0x7, 0x78); mdelay(1); write_phy_cck(dev, 0x8, 0x2e); mdelay(1); write_phy_cck(dev, 0x10, 0x93); mdelay(1); write_phy_cck(dev, 0x11, 0x88); mdelay(1); write_phy_cck(dev, 0x12, 0x47); mdelay(1); write_phy_cck(dev, 0x13, 0xd0); write_phy_cck(dev, 0x19, 0x00); write_phy_cck(dev, 0x1a, 0xa0); write_phy_cck(dev, 0x1b, 0x08); write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */ write_phy_cck(dev, 0x41, 0x8d); mdelay(1); write_phy_cck(dev, 0x42, 0x15); mdelay(1); write_phy_cck(dev, 0x43, 0x18); mdelay(1); write_phy_cck(dev, 0x44, 0x36); mdelay(1); write_phy_cck(dev, 0x45, 0x35); mdelay(1); write_phy_cck(dev, 0x46, 0x2e); mdelay(1); write_phy_cck(dev, 0x47, 0x25); mdelay(1); write_phy_cck(dev, 0x48, 0x1c); mdelay(1); write_phy_cck(dev, 0x49, 0x12); mdelay(1); write_phy_cck(dev, 0x4a, 0x09); mdelay(1); write_phy_cck(dev, 0x4b, 0x04); mdelay(1); write_phy_cck(dev, 0x4c, 0x05); mdelay(1); write_nic_byte(dev, 0x5b, 0x0d); mdelay(1); rtl8225z2_SetTXPowerLevel(dev, channel); /* RX antenna default to A */ write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */ write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */ rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */ /* switch to high-speed 3-wire * last digit. 2 for both cck and ofdm */ write_nic_dword(dev, 0x94, 0x15c00002); rtl8185_rf_pins_enable(dev); rtl8225_rf_set_chan(dev, priv->chan); }
void rtl8180_hw_dig_wq (struct work_struct *work) { struct delayed_work *dwork = container_of(work,struct delayed_work,work); struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq); struct net_device *dev = ieee->dev; #else void rtl8180_hw_dig_wq(struct net_device *dev) { #endif struct r8180_priv *priv = ieee80211_priv(dev); if(priv->card_8187_Bversion == VERSION_8187B_B) { priv->FalseAlarmRegValue = (u32)read_nic_byte(dev, (OFDM_FALSE_ALARM+1)); } else { priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); } if(priv->bDigMechanism) { DynamicInitGain(dev); } if(priv->card_8187 == NIC_8187B) { if(priv->bCCKThMechanism) { DynamicCCKThreshold(dev); } } } void SetTxPowerLevel8187(struct net_device *dev, short chan) { struct r8180_priv *priv = ieee80211_priv(dev); switch(priv->rf_chip) { case RF_ZEBRA: rtl8225_SetTXPowerLevel(dev,chan); break; case RF_ZEBRA2: rtl8225z2_SetTXPowerLevel(dev,chan); break; } } void DoRxHighPower(struct net_device *dev) { struct r8180_priv *priv = ieee80211_priv(dev); TR_SWITCH_STATE TrSwState; u16 HiPwrUpperTh = 0; u16 HiPwrLowerTh = 0; u16 RSSIHiPwrUpperTh = 0; u16 RSSIHiPwrLowerTh = 0; if((priv->card_8187 == NIC_8187B)||(priv->card_8187 == NIC_8187)) { TrSwState = priv->TrSwitchState; switch(priv->rf_chip) { case RF_ZEBRA: HiPwrUpperTh = Z1_HIPWR_UPPER_TH; HiPwrLowerTh = Z1_HIPWR_LOWER_TH; break; case RF_ZEBRA2: if((priv->card_8187 == NIC_8187)) { HiPwrUpperTh = Z2_HIPWR_UPPER_TH; HiPwrLowerTh = Z2_HIPWR_LOWER_TH; } else { HiPwrUpperTh = priv->Z2HiPwrUpperTh; HiPwrLowerTh = priv->Z2HiPwrLowerTh; HiPwrUpperTh = HiPwrUpperTh * 10; HiPwrLowerTh = HiPwrLowerTh * 10; RSSIHiPwrUpperTh = priv->Z2RSSIHiPwrUpperTh; RSSIHiPwrLowerTh = priv->Z2RSSIHiPwrLowerTh; } break; default: return; break; } if((priv->card_8187 == NIC_8187)) { if (priv->UndecoratedSmoothedSS > HiPwrUpperTh) { if( priv->TrSwitchState == TR_HW_CONTROLLED ) { write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect | TR_SW_MASK_8187 )); write_nic_byte(dev, RFPinsOutput, (u8)((priv->wMacRegRfPinsOutput&(~TR_SW_MASK_8187))|TR_SW_MASK_TX_8187)); priv->TrSwitchState = TR_SW_TX; priv->bToUpdateTxPwr = true; } } else if (priv->UndecoratedSmoothedSS < HiPwrLowerTh) { if( priv->TrSwitchState == TR_SW_TX) { write_nic_byte(dev, RFPinsOutput, (u8)(priv->wMacRegRfPinsOutput)); write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect)); priv->TrSwitchState = TR_HW_CONTROLLED; priv->bToUpdateTxPwr = true; } } }else { if(TrSwState == TR_HW_CONTROLLED) { if((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) { write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect|TR_SW_MASK_8187 )); write_nic_byte(dev, RFPinsOutput, (u8)((priv->wMacRegRfPinsOutput&(~TR_SW_MASK_8187))|TR_SW_MASK_TX_8187)); priv->TrSwitchState = TR_SW_TX; priv->bToUpdateTxPwr = true; } } else { if((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) { write_nic_byte(dev, RFPinsOutput, (u8)(priv->wMacRegRfPinsOutput)); write_nic_byte(dev, RFPinsSelect, (u8)(priv->wMacRegRfPinsSelect)); priv->TrSwitchState = TR_HW_CONTROLLED; priv->bToUpdateTxPwr = true; } } } } } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) void rtl8180_tx_pw_wq (struct work_struct *work) { struct delayed_work *dwork = container_of(work,struct delayed_work,work); struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq); struct net_device *dev = ieee->dev; #else void rtl8180_tx_pw_wq(struct net_device *dev) { #endif struct r8180_priv *priv = ieee80211_priv(dev); if(priv->bToUpdateTxPwr) { priv->bToUpdateTxPwr = false; SetTxPowerLevel8187(dev, priv->chan); } DoRxHighPower(dev); } bool CheckHighPower(struct net_device *dev) { struct r8180_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee80211; if(!priv->bRegHighPowerMechanism) { return false; } if((ieee->state == IEEE80211_LINKED_SCANNING)) { return false; } return true; } #ifdef SW_ANTE_DIVERSITY #define ANTENNA_DIVERSITY_TIMER_PERIOD 1000 void SwAntennaDiversityRxOk8185( struct net_device *dev, u8 SignalStrength ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); priv->AdRxOkCnt++; if( priv->AdRxSignalStrength != -1) { priv->AdRxSignalStrength = ((priv->AdRxSignalStrength*7) + (SignalStrength*3)) / 10; } else { priv->AdRxSignalStrength = SignalStrength; } if( priv->LastRxPktAntenna ) priv->AdMainAntennaRxOkCnt++; else priv->AdAuxAntennaRxOkCnt++; } bool SetAntenna8185( struct net_device *dev, u8 u1bAntennaIndex ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); bool bAntennaSwitched = false; switch(u1bAntennaIndex) { case 0: switch(priv->rf_chip) { case RF_ZEBRA: case RF_ZEBRA2: write_nic_byte(dev, 0x7f, ((0x01009b90 & 0xff000000) >> 24)); write_nic_byte(dev, 0x7e, ((0x01009b90 & 0x00ff0000) >> 16)); write_nic_byte(dev, 0x7d, ((0x01009b90 & 0x0000ff00) >> 8)); write_nic_byte(dev, 0x7c, ((0x01009b90 & 0x000000ff) >> 0)); write_nic_byte(dev, 0x7f, ((0x000090a6 & 0xff000000) >> 24)); write_nic_byte(dev, 0x7e, ((0x000090a6 & 0x00ff0000) >> 16)); write_nic_byte(dev, 0x7d, ((0x000090a6 & 0x0000ff00) >> 8)); write_nic_byte(dev, 0x7c, ((0x000090a6 & 0x000000ff) >> 0)); write_nic_byte(dev, ANTSEL, 0x03); bAntennaSwitched = true; break; default: printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); break; } break; case 1: switch(priv->rf_chip) { case RF_ZEBRA: case RF_ZEBRA2: write_nic_byte(dev, 0x7f, ((0x0100db90 & 0xff000000) >> 24)); write_nic_byte(dev, 0x7e, ((0x0100db90 & 0x00ff0000) >> 16)); write_nic_byte(dev, 0x7d, ((0x0100db90 & 0x0000ff00) >> 8)); write_nic_byte(dev, 0x7c, ((0x0100db90 & 0x000000ff) >> 0)); write_nic_byte(dev, 0x7f, ((0x000010a6 & 0xff000000) >> 24)); write_nic_byte(dev, 0x7e, ((0x000010a6 & 0x00ff0000) >> 16)); write_nic_byte(dev, 0x7d, ((0x000010a6 & 0x0000ff00) >> 8)); write_nic_byte(dev, 0x7c, ((0x000010a6 & 0x000000ff) >> 0)); write_nic_byte(dev, ANTSEL, 0x00); bAntennaSwitched = true; break; default: printk("SetAntenna8185: unkown RFChipID(%d)\n", priv->rf_chip); break; } break; default: printk("SetAntenna8185: unkown u1bAntennaIndex(%d)\n", u1bAntennaIndex); break; } if(bAntennaSwitched) { priv->CurrAntennaIndex = u1bAntennaIndex; } return bAntennaSwitched; } bool SwitchAntenna( struct net_device *dev ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); bool bResult = false; if(priv->CurrAntennaIndex == 0) { bResult = SetAntenna8185(dev, 1); if(priv->ieee80211->state == IEEE80211_LINKED) printk("To aux antenna 1......\n"); } else { bResult = SetAntenna8185(dev, 0); if(priv->ieee80211->state == IEEE80211_LINKED) printk("To main antenna 0......\n"); } return bResult; } void SwAntennaDiversity( struct net_device *dev ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); bool bSwCheckSS=true; if(bSwCheckSS) { priv->AdTickCount++; } if(priv->ieee80211->state != IEEE80211_LINKED) { priv->bAdSwitchedChecking = false; SwitchAntenna(dev); } else if(priv->AdRxOkCnt == 0) { priv->bAdSwitchedChecking = false; SwitchAntenna(dev); } else if(priv->bAdSwitchedChecking == true) { priv->bAdSwitchedChecking = false; priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold; if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) { priv->AdCheckPeriod *= 2; if(priv->AdCheckPeriod > priv->AdMaxCheckPeriod) priv->AdCheckPeriod = priv->AdMaxCheckPeriod; SwitchAntenna(dev); } else { priv->AdCheckPeriod = priv->AdMinCheckPeriod; } } else { priv->AdTickCount = 0; if((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) && (priv->CurrAntennaIndex == 0)) { SwitchAntenna(dev); priv->bHWAdSwitched = true; } else if((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) && (priv->CurrAntennaIndex == 1)) { SwitchAntenna(dev); priv->bHWAdSwitched = true; } else { priv->bHWAdSwitched = false; } if( (!priv->bHWAdSwitched) && (bSwCheckSS)) { if(priv->AdRxSignalStrength < priv->AdRxSsThreshold) { priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; priv->bAdSwitchedChecking = true; SwitchAntenna(dev); } else { priv->bAdSwitchedChecking = false; if( (priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) { priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold; } if( priv->AdCheckPeriod > priv->AdMinCheckPeriod ) { priv->AdCheckPeriod /= 2; } } } } priv->AdRxOkCnt = 0; priv->AdMainAntennaRxOkCnt = 0; priv->AdAuxAntennaRxOkCnt = 0; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) void SwAntennaWorkItemCallback(struct work_struct *work) { struct delayed_work *dwork = container_of(work,struct delayed_work,work); struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,SwAntennaWorkItem); struct net_device *dev = ieee->dev; #else void SwAntennaWorkItemCallback(struct net_device *dev) { #endif SwAntennaDiversity(dev); } void SwAntennaDiversityTimerCallback( struct net_device *dev ) { struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); RT_RF_POWER_STATE rtState; rtState = priv->eRFPowerState; do{ if (rtState == eRfOff) { break; } else if (rtState == eRfSleep) { break; } #ifdef SW_ANTE_DIVERSITY #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->SwAntennaWorkItem,0); #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) queue_work(priv->ieee80211->wq,(void *)&priv->ieee80211->SwAntennaWorkItem); #else schedule_task(&priv->ieee80211->SwAntennaWorkItem); #endif #endif }while(false); if(priv->up) { mod_timer(&priv->SwAntennaDiversityTimer, jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD)); } }