/* ======================================================================== Routine Description: Initialize wireless channel in 2.4GHZ and 5GHZ. Arguments: pAd - WLAN control block pointer pWiphy - WLAN PHY interface pChannels - Current channel info pRates - Current rate info Return Value: TRUE - init successfully FALSE - init fail Note: TX Power related: 1. Suppose we can send power to 15dBm in the board. 2. A value 0x0 ~ 0x1F for a channel. We will adjust it based on 15dBm/ 54Mbps. So if value == 0x07, the TX power of 54Mbps is 15dBm and the value is 0x07 in the EEPROM. 3. Based on TX power value of 54Mbps/channel, adjust another value 0x0 ~ 0xF for other data rate. (-6dBm ~ +6dBm) Other related factors: 1. TX power percentage from UI/users; 2. Maximum TX power limitation in the regulatory domain. ======================================================================== */ BOOLEAN CFG80211_SupBandInit(void *pCB, CFG80211_BAND *pDriverBandInfo, void *pWiphyOrg, void *pChannelsOrg, void *pRatesOrg) { CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; struct ieee80211_channel *pChannels = (struct ieee80211_channel *)pChannelsOrg; struct ieee80211_rate *pRates = (struct ieee80211_rate *)pRatesOrg; struct ieee80211_supported_band *pBand; UINT32 NumOfChan = 0, NumOfRate = 0; UINT32 IdLoop = 0; UINT32 CurTxPower; /* sanity check */ if (pDriverBandInfo->RFICType == 0) pDriverBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ; /* 1. Calcute the Channel Number */ if (pDriverBandInfo->RFICType & RFIC_5GHZ) NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ; else NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ; /* 2. Calcute the Rate Number */ if (pDriverBandInfo->FlgIsBMode == TRUE) NumOfRate = 4; else NumOfRate = 4 + 8; CFG80211DBG(RT_DEBUG_TRACE, ("80211> RFICType= %d, NumOfChan= %d\n", pDriverBandInfo->RFICType, NumOfChan)); CFG80211DBG(RT_DEBUG_TRACE, ("80211> Number of rate = %d\n", NumOfRate)); /* 3. Allocate the Channel instance */ if (pChannels == NULL) { pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL); if (!pChannels) { return FALSE; } } /* 4. Allocate the Rate instance */ if (pRates == NULL) { pRates = kzalloc(sizeof(*pRates) * NumOfRate, GFP_KERNEL); if (!pRates) { os_free_mem(pChannels); return FALSE; } } /* get TX power */ #ifdef SINGLE_SKU CurTxPower = pDriverBandInfo->DefineMaxTxPwr; /* dBm */ #else CurTxPower = 20; /* unknown */ #endif /* SINGLE_SKU */ CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower)); /* 5. init channel */ for (IdLoop = 0; IdLoop < NumOfChan; IdLoop++) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) if (IdLoop >= 14) { pChannels[IdLoop].band = IEEE80211_BAND_5GHZ; pChannels[IdLoop].center_freq = \ ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], IEEE80211_BAND_5GHZ); } else { pChannels[IdLoop].band = IEEE80211_BAND_2GHZ; pChannels[IdLoop].center_freq = \ ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], IEEE80211_BAND_2GHZ); } #else pChannels[IdLoop].center_freq = ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop]); #endif pChannels[IdLoop].hw_value = IdLoop; if (IdLoop < CFG80211_NUM_OF_CHAN_2GHZ) pChannels[IdLoop].max_power = CurTxPower; else pChannels[IdLoop].max_power = CurTxPower; pChannels[IdLoop].max_antenna_gain = 0xff; /* if (RadarChannelCheck(pAd, Cfg80211_Chan[IdLoop])) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) /* for kernel 3.14 , both value are changed to IEEE80211_CHAN_NO_IR*/ #define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR #define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR #endif if (IsRadarChannel(Cfg80211_Chan[IdLoop])) { pChannels[IdLoop].flags = 0; printk("====> Radar Channel %d\n", Cfg80211_Chan[IdLoop]); pChannels[IdLoop].flags |= (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN); } /* CFG_TODO: pChannels[IdLoop].flags enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, IEEE80211_CHAN_NO_IBSS = 1<<2, IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_HT40PLUS = 1<<4, IEEE80211_CHAN_NO_HT40MINUS = 1<<5, }; */ } /* 6. init rate */ for (IdLoop = 0; IdLoop < NumOfRate; IdLoop++) memcpy(&pRates[IdLoop], &Cfg80211_SupRate[IdLoop], sizeof(*pRates)); /* CFG_TODO: enum ieee80211_rate_flags { IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, IEEE80211_RATE_MANDATORY_A = 1<<1, IEEE80211_RATE_MANDATORY_B = 1<<2, IEEE80211_RATE_MANDATORY_G = 1<<3, IEEE80211_RATE_ERP_G = 1<<4, }; */ /* 7. Fill the Band 2.4GHz */ pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_2GHZ]; if (pDriverBandInfo->RFICType & RFIC_24GHZ) { pBand->n_channels = CFG80211_NUM_OF_CHAN_2GHZ; pBand->n_bitrates = NumOfRate; pBand->channels = pChannels; pBand->bitrates = pRates; #ifdef DOT11_N_SUPPORT /* for HT, assign pBand->ht_cap */ pBand->ht_cap.ht_supported = true; pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); CFG80211DBG(RT_DEBUG_ERROR, ("80211> TxStream = %d\n", pDriverBandInfo->TxStream)); switch(pDriverBandInfo->TxStream) { case 1: default: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); break; case 2: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); break; case 3: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_mask[2] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); break; } pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; #endif /* DOT11_N_SUPPORT */ pWiphy->bands[IEEE80211_BAND_2GHZ] = pBand; } else { pWiphy->bands[IEEE80211_BAND_2GHZ] = NULL; pBand->channels = NULL; pBand->bitrates = NULL; } /* 8. Fill the Band 5GHz */ pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_5GHZ]; if (pDriverBandInfo->RFICType & RFIC_5GHZ) { pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ; pBand->n_bitrates = NumOfRate - 4; /*Disable 11B rate*/ pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ]; pBand->bitrates = &pRates[4]; #ifdef DOT11_N_SUPPORT /* for HT, assign pBand->ht_cap */ pBand->ht_cap.ht_supported = true; pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); switch(pDriverBandInfo->RxStream) { case 1: default: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); break; case 2: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); break; case 3: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_mask[2] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); break; } pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; #endif /* DOT11_N_SUPPORT */ pWiphy->bands[IEEE80211_BAND_5GHZ] = pBand; } else { pWiphy->bands[IEEE80211_BAND_5GHZ] = NULL; pBand->channels = NULL; pBand->bitrates = NULL; } /* 9. re-assign to mainDevice info */ pCfg80211_CB->pCfg80211_Channels = pChannels; pCfg80211_CB->pCfg80211_Rates = pRates; return TRUE; }
/* ======================================================================== Routine Description: Initialize wireless channel in 2.4GHZ and 5GHZ. Arguments: pAd - WLAN control block pointer pWiphy - WLAN PHY interface pChannels - Current channel info pRates - Current rate info Return Value: true - init successfully false - init fail Note: TX Power related: 1. Suppose we can send power to 15dBm in the board. 2. A value 0x0 ~ 0x1F for a channel. We will adjust it based on 15dBm/ 54Mbps. So if value == 0x07, the TX power of 54Mbps is 15dBm and the value is 0x07 in the EEPROM. 3. Based on TX power value of 54Mbps/channel, adjust another value 0x0 ~ 0xF for other data rate. (-6dBm ~ +6dBm) Other related factors: 1. TX power percentage from UI/users; 2. Maximum TX power limitation in the regulatory domain. ======================================================================== */ bool CFG80211_SupBandInit( IN VOID *pCB, IN CFG80211_BAND *pDriverBandInfo, IN VOID *pWiphyOrg, IN VOID *pChannelsOrg, IN VOID *pRatesOrg) { struct mt7612u_cfg80211_cb *pCfg80211_CB = (struct mt7612u_cfg80211_cb *)pCB; struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; struct ieee80211_channel *pChannels = (struct ieee80211_channel *)pChannelsOrg; struct ieee80211_rate *pRates = (struct ieee80211_rate *)pRatesOrg; struct ieee80211_supported_band *pBand; uint32_t NumOfChan = 0, NumOfRate = 0; uint32_t IdLoop = 0; uint32_t CurTxPower; /* sanity check */ if (pDriverBandInfo->RFICType == 0) pDriverBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ; /* 1. Calcute the Channel Number */ if (pDriverBandInfo->RFICType & RFIC_5GHZ) NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ; else NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ; /* 2. Calcute the Rate Number */ if (pDriverBandInfo->FlgIsBMode == true) NumOfRate = 4; else NumOfRate = 4 + 8; CFG80211DBG(RT_DEBUG_ERROR, ("80211> RFICType= %d, NumOfChan= %d\n", pDriverBandInfo->RFICType, NumOfChan)); CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of rate = %d\n", NumOfRate)); /* 3. Allocate the Channel instance */ if (pChannels == NULL) { pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL); if (!pChannels) { DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_channel allocation fail!\n")); return false; } } /* 4. Allocate the Rate instance */ if (pRates == NULL) { pRates = kzalloc(sizeof(*pRates) * NumOfRate, GFP_KERNEL); if (!pRates) { kfree(pChannels); DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_rate allocation fail!\n")); return false; } } /* get TX power */ CurTxPower = 20; /* unknown */ CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower)); /* 5. init channel */ for(IdLoop=0; IdLoop<NumOfChan; IdLoop++) { if (IdLoop >= 14) { pChannels[IdLoop].band = NL80211_BAND_5GHZ; pChannels[IdLoop].center_freq = \ ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], NL80211_BAND_5GHZ); } else { pChannels[IdLoop].band = NL80211_BAND_2GHZ; pChannels[IdLoop].center_freq = \ ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop], NL80211_BAND_2GHZ); } pChannels[IdLoop].hw_value = IdLoop; if (IdLoop < CFG80211_NUM_OF_CHAN_2GHZ) pChannels[IdLoop].max_power = CurTxPower; else pChannels[IdLoop].max_power = CurTxPower; pChannels[IdLoop].max_antenna_gain = 0xff; /* if (RadarChannelCheck(pAd, Cfg80211_Chan[IdLoop])) */ if (IsRadarChannel(Cfg80211_Chan[IdLoop])) { pChannels[IdLoop].flags = 0; printk("====> Rader Channel %d\n", Cfg80211_Chan[IdLoop]); pChannels[IdLoop].flags |= IEEE80211_CHAN_RADAR; } /* CFG_TODO: pChannels[IdLoop].flags enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, IEEE80211_CHAN_NO_IBSS = 1<<2, IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_HT40PLUS = 1<<4, IEEE80211_CHAN_NO_HT40MINUS = 1<<5, }; */ } /* 6. init rate */ for(IdLoop=0; IdLoop<NumOfRate; IdLoop++) memcpy(&pRates[IdLoop], &Cfg80211_SupRate[IdLoop], sizeof(*pRates)); /* CFG_TODO: enum ieee80211_rate_flags { IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, IEEE80211_RATE_MANDATORY_A = 1<<1, IEEE80211_RATE_MANDATORY_B = 1<<2, IEEE80211_RATE_MANDATORY_G = 1<<3, IEEE80211_RATE_ERP_G = 1<<4, }; */ /* 7. Fill the Band 2.4GHz */ pBand = &pCfg80211_CB->Cfg80211_bands[NL80211_BAND_2GHZ]; if (pDriverBandInfo->RFICType & RFIC_24GHZ) { pBand->n_channels = CFG80211_NUM_OF_CHAN_2GHZ; pBand->n_bitrates = NumOfRate; pBand->channels = pChannels; pBand->bitrates = pRates; /* for HT, assign pBand->ht_cap */ pBand->ht_cap.ht_supported = true; pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); CFG80211DBG(RT_DEBUG_ERROR, ("80211> TxStream = %d\n", pDriverBandInfo->TxStream)); switch(pDriverBandInfo->TxStream) { case 1: default: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); break; case 2: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); break; case 3: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_mask[2] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); break; } pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; pWiphy->bands[NL80211_BAND_2GHZ] = pBand; } else { pWiphy->bands[NL80211_BAND_2GHZ] = NULL; pBand->channels = NULL; pBand->bitrates = NULL; } /* 8. Fill the Band 5GHz */ pBand = &pCfg80211_CB->Cfg80211_bands[NL80211_BAND_5GHZ]; if (pDriverBandInfo->RFICType & RFIC_5GHZ) { pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ; pBand->n_bitrates = NumOfRate - 4; /*Disable 11B rate*/ pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ]; pBand->bitrates = &pRates[4]; /* for HT, assign pBand->ht_cap */ pBand->ht_cap.ht_supported = true; pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; pBand->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; /* 2 ^ 16 */ pBand->ht_cap.ampdu_density = pDriverBandInfo->MpduDensity; /* YF_TODO */ memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); switch(pDriverBandInfo->RxStream) { case 1: default: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(150); break; case 2: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(300); break; case 3: pBand->ht_cap.mcs.rx_mask[0] = 0xff; pBand->ht_cap.mcs.rx_mask[1] = 0xff; pBand->ht_cap.mcs.rx_mask[2] = 0xff; pBand->ht_cap.mcs.rx_highest = cpu_to_le16(450); break; } pBand->ht_cap.mcs.rx_mask[4] = 0x01; /* 40MHz*/ pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; pWiphy->bands[NL80211_BAND_5GHZ] = pBand; } else { pWiphy->bands[NL80211_BAND_5GHZ] = NULL; pBand->channels = NULL; pBand->bitrates = NULL; } /* 9. re-assign to mainDevice info */ pCfg80211_CB->pCfg80211_Channels = pChannels; pCfg80211_CB->pCfg80211_Rates = pRates; return true; }