static inline UCHAR SelectClearChannelRandom( IN PRTMP_ADAPTER pAd ) { UCHAR cnt, ch = 0, i, RadomIdx; /*BOOLEAN bFindIt = FALSE;*/ UINT8 TempChList[MAX_NUM_OF_CHANNELS] = {0}; if (pAd->CommonCfg.bIEEE80211H) { cnt = 0; /* Filter out an available channel list */ for (i = 0; i < pAd->ChannelListNum; i++) { /* Check DFS channel RemainingTimeForUse */ if (pAd->ChannelList[i].RemainingTimeForUse) continue; /* disable for now because no skip list is provided */ /* Check skip channel list */ /* if (AutoChannelSkipListCheck(pAd, pAd->ChannelList[i].Channel) == TRUE) continue; */ #ifdef DOT11_N_SUPPORT /* Check N-group of BW40 */ /* ?What is this? Somebody tell me */ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && !(pAd->ChannelList[i].Flags & CHANNEL_40M_CAP)) continue; #endif /* DOT11_N_SUPPORT */ /* Store available channel to temp list */ TempChList[cnt++] = pAd->ChannelList[i].Channel; } /* Randomly select a channel from temp list */ if (cnt) { RadomIdx = RandomByte2(pAd)%cnt; ch = TempChList[RadomIdx]; } else { ch = get_channel_by_reference(pAd, 1); } } else { ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; if (ch == 0) ch = FirstChannel(pAd); } DBGPRINT(RT_DEBUG_TRACE,("%s(): Select Channel %d\n", __FUNCTION__, ch)); return ch; }
static inline UCHAR SelectClearChannelRandom( IN PRTMP_ADAPTER pAd ) { UCHAR cnt, ch = 0, i, RadomIdx; UINT8 TempChList[MAX_NUM_OF_CHANNELS] = {0}; if (pAd->CommonCfg.bIEEE80211H) { cnt = 0; /* Filter out an available channel list */ for (i = 0; i < pAd->ChannelListNum; i++) { /* Check DFS channel RemainingTimeForUse */ if (pAd->ChannelList[i].RemainingTimeForUse) continue; /* Check skip channel list */ if (AutoChannelSkipListCheck(pAd, pAd->ChannelList[i].Channel) == TRUE) continue; #ifdef DOT11_N_SUPPORT /* Check N-group of BW40 */ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 && !(pAd->ChannelList[i].Flags & CHANNEL_40M_CAP)) continue; #endif /* DOT11_N_SUPPORT */ /* Store available channel to temp list */ TempChList[cnt++] = pAd->ChannelList[i].Channel; } /* Randomly select a channel from temp list */ if (cnt) { RadomIdx = RandomByte2(pAd)%cnt; ch = TempChList[RadomIdx]; } else { ch = FirstChannel(pAd); } } else { ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; if (ch == 0) ch = FirstChannel(pAd); } printk("%s(): Select Channel %d\n", __FUNCTION__, ch); return ch; }
static inline UCHAR SelectClearChannelRandom( IN PRTMP_ADAPTER pAd ) { UCHAR cnt, ch = 0, i; BOOLEAN bFindIt = FALSE; if (pAd->CommonCfg.bIEEE80211H) { cnt = 0; while(TRUE) { cnt++; ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; if (ch == 0) ch = FirstChannel(pAd); // have no avaiable channel now. force pick first channel here. if (cnt == pAd->ChannelListNum) { ch = FirstChannel(pAd); break; } #ifdef A_BAND_SUPPORT if (RadarChannelCheck(pAd, ch)) continue; #endif for (i=0; i<pAd->ChannelListNum; i++) { if (pAd->ChannelList[i].Channel == ch) { if (pAd->ChannelList[i].RemainingTimeForUse == 0) bFindIt = TRUE; break; } } if (bFindIt == TRUE) break; }; } else { ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; if (ch == 0) ch = FirstChannel(pAd); } printk("Random in A band. Select Channel %d\n",ch); return ch; }
static inline UCHAR SelectClearChannelApCnt( IN PRTMP_ADAPTER pAd ) { /*PBSSINFO pBssInfoTab = pAd->pBssInfoTab; */ PCHANNELINFO pChannelInfo = pAd->pChannelInfo; /*BSSENTRY *pBss; */ UCHAR channel_index = 0,dirty,base = 0; UCHAR final_channel = 0; if(pChannelInfo == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); return (FirstChannel(pAd)); } /* Calculate Dirtiness */ for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) { if (pChannelInfo->ApCnt[channel_index] > 0) { INT ll; pChannelInfo->dirtyness[channel_index] += 30; /*5G */ if (pChannelInfo->IsABand) { int Channel = pAd->ChannelList[channel_index].Channel; /*Make secondary channel dirty */ if(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { if (Channel > 14) { if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel== 60) || (Channel == 100) || (Channel == 108) || (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157)) { if (channel_index + 1 < MAX_NUM_OF_CHANNELS) if(pAd->ChannelList[channel_index+1].Channel - pAd->ChannelList[channel_index].Channel == 4) pChannelInfo->dirtyness[channel_index+1] += 1; } else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) || (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel== 153) || (Channel == 161)) { if(channel_index - 1 >= 0) if(pAd->ChannelList[channel_index].Channel - pAd->ChannelList[channel_index-1].Channel == 4) pChannelInfo->dirtyness[channel_index-1] += 1; } } } } /*2.4G */ if (!pChannelInfo->IsABand) { int ChanOffset = 0; if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&& (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) { /* BW is 40Mhz the distance between two channel to prevent interference is 4 channel width plus 4 channel width (secondary channel) */ ChanOffset = 8; } else { /* BW is 20Mhz The channel width of 2.4G band is 5Mhz. The distance between two channel to prevent interference is 4 channel width */ ChanOffset = 4; } for (ll = channel_index + 1; ll < (channel_index + ChanOffset + 1); ll++) { if (ll < MAX_NUM_OF_CHANNELS) pChannelInfo->dirtyness[ll]++; } if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)&& (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)) { /* BW is 40Mhz */ ChanOffset = 8; } else { /* BW is 20Mhz */ ChanOffset = 4; } for (ll = channel_index - 1; ll > (channel_index - ChanOffset - 1); ll--) { if (ll >= 0) pChannelInfo->dirtyness[ll]++; } } } }/* Calculate Dirtiness */ AutoChannelSkipListSetDirty(pAd); printk("=====================================================\n"); for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) /* debug messages */ printk("Channel %d : Dirty = %ld, ApCnt=%ld, Busy Time = %d, Skip Channel = %s\n", pAd->ChannelList[channel_index].Channel, pChannelInfo->dirtyness[channel_index], pChannelInfo->ApCnt[channel_index], pChannelInfo->chanbusytime[channel_index], (pChannelInfo->SkipList[channel_index] == TRUE) ? "TRUE" : "FALSE"); printk("=====================================================\n"); pAd->ApCfg.AutoChannel_Channel = 0; /* RULE 1. pick up a good channel that no one used */ for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) { if (pChannelInfo->SkipList[channel_index] == TRUE) continue; #ifdef A_BAND_SUPPORT if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) &&(pChannelInfo->IsABand == TRUE) && RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel)) continue; #endif #ifdef AP_QLOAD_SUPPORT /* QLOAD ALARM */ if (QBSS_LoadIsBusyTimeAccepted(pAd, pChannelInfo->chanbusytime[channel_index]) == FALSE) continue; #endif /* AP_QLOAD_SUPPORT */ if (pChannelInfo->dirtyness[channel_index] == 0) break; } if (channel_index < pAd->ChannelListNum) { printk("Rule 1 APCnt : dirtiness == 0 (no one used and no interference) ==> Select Channel %d\n", pAd->ChannelList[channel_index].Channel); return pAd->ChannelList[channel_index].Channel; } /* RULE 2. if not available, then co-use a channel that's no interference (dirtyness=30) */ /* RULE 3. if not available, then co-use a channel that has minimum interference (dirtyness=31,32) */ for (dirty = 30; dirty <= 32; dirty++) { BOOLEAN candidate[MAX_NUM_OF_CHANNELS+1], candidate_num=0; UCHAR min_ApCnt = 255; final_channel = 0; NdisZeroMemory(candidate, MAX_NUM_OF_CHANNELS+1); for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) { if (pChannelInfo->SkipList[channel_index] == TRUE) continue; if (pChannelInfo->dirtyness[channel_index] == dirty) { candidate[channel_index]=TRUE; candidate_num++; } } /* if there's more than 1 candidate, pick up the channel with minimum RSSI */ if (candidate_num) { for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) { #ifdef AP_QLOAD_SUPPORT /* QLOAD ALARM */ /* when busy time of a channel > threshold, skip it */ /* TODO: Use weight for different references to do channel selection */ if (QBSS_LoadIsBusyTimeAccepted(pAd, pChannelInfo->chanbusytime[channel_index]) == FALSE) { /* check next one */ continue; } #endif /* AP_QLOAD_SUPPORT */ if (candidate[channel_index] && (pChannelInfo->ApCnt[channel_index] < min_ApCnt)) { if((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && (BW40_ChannelCheck(pAd->ChannelList[channel_index].Channel) == FALSE)) continue; #ifdef A_BAND_SUPPORT if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) &&(pChannelInfo->IsABand == TRUE) && RadarChannelCheck(pAd, pAd->ChannelList[channel_index].Channel)) continue; #endif final_channel = pAd->ChannelList[channel_index].Channel; min_ApCnt = pChannelInfo->ApCnt[channel_index]; } } if (final_channel != 0) { printk("Rule 2 APCnt : minimum APCnt with minimum interference(dirtiness: 30~32) ==> Select Channel %d\n", final_channel); printk(" Dirtiness = %d , Min ApCnt = %d\n", dirty, min_ApCnt); return final_channel; } } } /* RULE 3. still not available, pick up the random channel */ base = RandomByte2(pAd); for (channel_index=0 ; channel_index < pAd->ChannelListNum ; channel_index++) { final_channel = pAd->ChannelList[(base + channel_index) % pAd->ChannelListNum].Channel; if (AutoChannelSkipListCheck(pAd, final_channel)) continue; #ifdef A_BAND_SUPPORT if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) &&(pChannelInfo->IsABand == TRUE) && RadarChannelCheck(pAd, final_channel)) continue; #endif break; } printk("Rule 3 APCnt : Randomly Select ==> Select Channel %d\n",final_channel); return final_channel; }
/* ========================================================================== Description: This routine calaulates the dirtyness of all channels by the CCA value and Rssi. Store dirtyness to pChannelInfo strcut. This routine is called at iwpriv cmmand or initialization. It chooses and returns a good channel whith less interference. Return: ch - channel number that NOTE: ========================================================================== */ static inline UCHAR SelectClearChannelCCA( IN PRTMP_ADAPTER pAd ) { #define CCA_THRESHOLD (100) PBSSINFO pBssInfoTab = pAd->pBssInfoTab; PCHANNELINFO pChannelInfo = pAd->pChannelInfo; INT ch = 1, channel_idx, BssTab_idx; BSSENTRY *pBss; UINT32 min_dirty, min_falsecca; int candidate_ch; UCHAR ExChannel[2] = {0}; UCHAR candidate_ExChannel[2] = {0}; UCHAR base; if(pBssInfoTab == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("pAd->pBssInfoTab equal NULL.\n")); return (FirstChannel(pAd)); } if(pChannelInfo == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); return (FirstChannel(pAd)); } for (BssTab_idx = 0; BssTab_idx < pBssInfoTab->BssNr; BssTab_idx++) { pBss = &(pBssInfoTab->BssEntry[BssTab_idx]); channel_idx = GetChIdx(pAd, pBss->Channel); if (channel_idx < 0 ) continue; if (pBss->Rssi >= RSSI_TO_DBM_OFFSET-50) { /* high signal >= -50 dbm */ pChannelInfo->dirtyness[channel_idx] += 50; } else if (pBss->Rssi <= RSSI_TO_DBM_OFFSET-80) { /* low signal <= -80 dbm */ pChannelInfo->dirtyness[channel_idx] += 30; } else { /* mid signal -50 ~ -80 dbm */ pChannelInfo->dirtyness[channel_idx] += 40; } pChannelInfo->dirtyness[channel_idx] += 40; { INT BelowBound; INT AboveBound; INT loop; switch(pBss->ExtChOffset) { case EXTCHA_ABOVE: BelowBound = pChannelInfo->IsABand ? 1 : 4; AboveBound = pChannelInfo->IsABand ? 2 : 8; break; case EXTCHA_BELOW: BelowBound = pChannelInfo->IsABand ? 2 : 8; AboveBound = pChannelInfo->IsABand ? 1 : 4; break; default: BelowBound = pChannelInfo->IsABand ? 1 : 4; AboveBound = pChannelInfo->IsABand ? 1 : 4; break; } /* check neighbor channel */ for (loop = (channel_idx+1); loop <= (channel_idx+AboveBound); loop++) { if (loop >= MAX_NUM_OF_CHANNELS) break; if (pAd->ChannelList[loop].Channel - pAd->ChannelList[loop-1].Channel > 4) break; pChannelInfo->dirtyness[loop] += ((9 - (loop - channel_idx)) * 4); } /* check neighbor channel */ for (loop=(channel_idx-1); loop >= (channel_idx-BelowBound); loop--) { if (loop < 0) break; if (pAd->ChannelList[loop+1].Channel - pAd->ChannelList[loop].Channel > 4) continue; pChannelInfo->dirtyness[loop] += ((9 - (channel_idx - loop)) * 4); } } printk(" ch%d bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]); } AutoChannelSkipListSetDirty(pAd); printk("======================RT309x=========================\n"); for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { printk("Channel %d : Dirty = %ld, False CCA = %u, Busy Time = %u, Skip Channel = %s\n", pAd->ChannelList[channel_idx].Channel, pChannelInfo->dirtyness[channel_idx], pChannelInfo->FalseCCA[channel_idx], pChannelInfo->chanbusytime[channel_idx], (pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE"); } printk("=====================================================\n"); min_dirty = min_falsecca = 0xFFFFFFFF; /* * Rule 1. Pick up a good channel that False_CCA =< CCA_THRESHOLD * by dirtyness */ candidate_ch = -1; for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { if (pChannelInfo->SkipList[channel_idx] == TRUE) continue; if (pChannelInfo->FalseCCA[channel_idx] <= CCA_THRESHOLD) { UINT32 dirtyness = pChannelInfo->dirtyness[channel_idx]; ch = pAd->ChannelList[channel_idx].Channel; #ifdef AP_QLOAD_SUPPORT /* QLOAD ALARM */ /* when busy time of a channel > threshold, skip it */ /* TODO: Use weight for different references to do channel selection */ if (QBSS_LoadIsBusyTimeAccepted(pAd, pChannelInfo->chanbusytime[channel_idx]) == FALSE) { /* check next one */ continue; } #endif /* AP_QLOAD_SUPPORT */ #ifdef DOT11_N_SUPPORT /* User require 40MHz Bandwidth. In the case, ignor all channel doesn't support 40MHz Bandwidth. */ if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0))) continue; /* Need to Consider the dirtyness of extending channel in 40 MHz bandwidth channel. */ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { if (pAd->pChannelInfo->IsABand) { if (((channel_idx + GetABandChOffset(ch)) >=0) && ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum)) { INT ChOffsetIdx = channel_idx + GetABandChOffset(ch); dirtyness += pChannelInfo->dirtyness[ChOffsetIdx]; } } else { UCHAR ExChannel_idx = 0; if (pAd->ChannelList[channel_idx].Channel == 14) { dirtyness = 0xFFFFFFFF; break; } else { NdisZeroMemory(ExChannel, sizeof(ExChannel)); if (((channel_idx - 4) >=0) && ((channel_idx - 4) < pAd->ChannelListNum)) { dirtyness += pChannelInfo->dirtyness[channel_idx - 4]; ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx - 4].Channel; } if (((channel_idx + 4) >=0) && ((channel_idx + 4) < pAd->ChannelListNum)) { dirtyness += pChannelInfo->dirtyness[channel_idx + 4]; ExChannel[ExChannel_idx++] = pAd->ChannelList[channel_idx + 4].Channel; } } } } #endif /* DOT11_N_SUPPORT */ if ((min_dirty > dirtyness)) { min_dirty = dirtyness; candidate_ch = channel_idx; NdisMoveMemory(candidate_ExChannel, ExChannel, 2); } } } if (candidate_ch >= 0) { ch = pAd->ChannelList[candidate_ch].Channel; printk("Rule 1 CCA value : Min Dirtiness ==> Select Channel %d \n", ch); printk("Min Dirty = %u\n", min_dirty); printk("ExChannel = %d , %d\n", candidate_ExChannel[0], candidate_ExChannel[1]); printk("BW = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)? "40" : "20"); return ch; } /* * Rule 2. Pick up a good channel that False_CCA > CCA_THRESHOLD * by FalseCCA (FalseCCA + Dirtyness) */ candidate_ch = -1; for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { if (pChannelInfo->SkipList[channel_idx] == TRUE) continue; if (pChannelInfo->FalseCCA[channel_idx] > CCA_THRESHOLD) { UINT32 falsecca = pChannelInfo->FalseCCA[channel_idx] + pChannelInfo->dirtyness[channel_idx]; ch = pAd->ChannelList[channel_idx].Channel; #ifdef DOT11_N_SUPPORT if ((pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && (pChannelInfo->IsABand && (GetABandChOffset(ch) == 0))) continue; #endif /* DOT11_N_SUPPORT */ if ((GetABandChOffset(ch) != 0) && ((channel_idx + GetABandChOffset(ch)) >=0) && ((channel_idx + GetABandChOffset(ch)) < pAd->ChannelListNum)) { INT ChOffsetIdx = channel_idx + GetABandChOffset(ch); falsecca += (pChannelInfo->FalseCCA[ChOffsetIdx] + pChannelInfo->dirtyness[ChOffsetIdx]); } #ifdef AP_QLOAD_SUPPORT /* QLOAD ALARM */ /* when busy time of a channel > threshold, skip it */ /* TODO: Use weight for different references to do channel selection */ if (QBSS_LoadIsBusyTimeAccepted(pAd, pChannelInfo->chanbusytime[channel_idx]) == FALSE) { /* check next one */ continue; } #endif /* AP_QLOAD_SUPPORT */ if ((min_falsecca > falsecca)) { min_falsecca = falsecca; candidate_ch = channel_idx; } } } if (candidate_ch >= 0) { ch = pAd->ChannelList[candidate_ch].Channel; printk("Rule 2 CCA value : Min False CCA value ==> Select Channel %d, min falsecca = %d \n", ch, min_falsecca); return ch; } base = RandomByte2(pAd); for (channel_idx=0 ; channel_idx < pAd->ChannelListNum ; channel_idx++) { ch = pAd->ChannelList[(base + channel_idx) % pAd->ChannelListNum].Channel; if (AutoChannelSkipListCheck(pAd, ch)) continue; #ifdef A_BAND_SUPPORT if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) && (pChannelInfo->IsABand == TRUE) && RadarChannelCheck(pAd, ch)) continue; #endif break; } printk("Rule 3 CCA value : Randomly Select ==> Select Channel %d\n", ch); return ch; }
/* ========================================================================== Description: Setup Frame format. NOTE: This routine should only be used in ATE mode. ========================================================================== */ INT ATESetUpFrame( IN PRTMP_ADAPTER pAd, IN UINT32 TxIdx) { PATE_INFO pATEInfo = &(pAd->ate); UINT pos = 0; TXINFO_STRUC *pTxInfo; TXD_STRUC *pTxD; #ifdef RT_BIG_ENDIAN TXD_STRUC *pDestTxD; UCHAR tx_hw_info[TXD_SIZE]; // TXD_STRUC TxD; #endif /* RT_BIG_ENDIAN */ PNDIS_PACKET pPacket=NULL; PUCHAR pDest=NULL; PVOID AllocVa=NULL; NDIS_PHYSICAL_ADDRESS AllocPa; HTTRANSMIT_SETTING TxHTPhyMode; PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE]; TXWI_STRUC *pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; UINT8 TXWISize = pAd->chipCap.TXWISize; #ifdef RALINK_QA PHEADER_802_11 pHeader80211; #endif /* RALINK_QA */ /* fill TxWI */ TxHTPhyMode.field.BW = pATEInfo->TxWI.TxWIBW; TxHTPhyMode.field.ShortGI = pATEInfo->TxWI.TxWIShortGI; TxHTPhyMode.field.STBC = pATEInfo->TxWI.TxWISTBC; TxHTPhyMode.field.MCS = pATEInfo->TxWI.TxWIMCS; TxHTPhyMode.field.MODE = pATEInfo->TxWI.TxWIPHYMODE; if (pATEInfo->bQATxStart == TRUE) { /* always use QID_AC_BE and FIFO_EDCA */ ATEWriteTxWI(pAd, pTxWI, pATEInfo->TxWI.TxWIFRAG, pATEInfo->TxWI.TxWICFACK, pATEInfo->TxWI.TxWITS, pATEInfo->TxWI.TxWIAMPDU, pATEInfo->TxWI.TxWIACK, pATEInfo->TxWI.TxWINSEQ, pATEInfo->TxWI.TxWIBAWinSize, 0, pATEInfo->TxWI.TxWIMPDUByteCnt, pATEInfo->TxWI.TxWIPacketId, 0, 0, pATEInfo->TxWI.TxWITXOP/*IFS_HTTXOP*/, pATEInfo->TxWI.TxWICFACK/*FALSE*/, &TxHTPhyMode); #ifdef TXBF_SUPPORT if (IS_RT2883(pAd) || IS_RT3883(pAd)) { /* Must copy rsv bits to actual TxWI */ pTxWI->rsv = pATEInfo->TxWI.rsv; pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; pTxWI->Sounding = pATEInfo->TxWI.Sounding; pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; pTxWI->NDPSndBW = pATEInfo->TxWI.NDPSndBW; pTxWI->NDPSndRate = pATEInfo->TxWI.NDPSndRate; } #endif /* TXBF_SUPPORT */ } else { ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 4, 0, pATEInfo->TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); #ifdef TXBF_SUPPORT if (pATEInfo->bTxBF == 1) { if (IS_RT2883(pAd) || IS_RT3883(pAd)) { pTxWI->rsv = 0; pTxWI->iTxBF = pATEInfo->TxWI.iTxBF; pTxWI->Sounding = (pATEInfo->txSoundingMode == 1 ? 1 : 0); pTxWI->eTxBF = pATEInfo->TxWI.eTxBF; pTxWI->Autofallback = pATEInfo->TxWI.Autofallback; pTxWI->NDPSndBW = pATEInfo->TxWI.TxWIBW; if (pATEInfo->txSoundingMode == 3) pTxWI->NDPSndRate = 2; else if (pATEInfo->txSoundingMode == 2) pTxWI->NDPSndRate = 1; else pTxWI->NDPSndRate = 0; } } #endif /* TXBF_SUPPORT */ } /* fill 802.11 header */ #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { NdisMoveMemory(pDMAHeaderBufVA + TXWISize, pATEInfo->Header, pATEInfo->HLen); } else #endif /* RALINK_QA */ { pATEInfo->HLen = LENGTH_802_11; #ifdef TXBF_SUPPORT TemplateFrame[0] = 0x08; /* Data */ TemplateFrame[1] = 0x00; if (pATEInfo->bTxBF && pATEInfo->txSoundingMode!=0) { /* QoS Data */ pATEInfo->HLen = 32; TemplateFrame[0] = 0x88; TemplateFrame[1] = 0x80; switch (pATEInfo->txSoundingMode) { case 1: /* Data Sounding */ TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; TemplateFrame[29] = 0x00; break; case 2: case 3: /* 2 or 3 Stream NDP */ TemplateFrame[28] = pAd->CommonCfg.ETxBfNoncompress? 0x80: 0xc0; TemplateFrame[29] = 0x01; /* NDP Announce */ break; default: TemplateFrame[28] = TemplateFrame[29] = 0x0; } } #endif /* TXBF_SUPPORT */ NdisMoveMemory(pDMAHeaderBufVA + TXWISize, TemplateFrame, pATEInfo->HLen); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, pATEInfo->Addr1, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, ETH_LENGTH_OF_ADDRESS); NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, ETH_LENGTH_OF_ADDRESS); } #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); #endif /* RT_BIG_ENDIAN */ /* alloc buffer for payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->DLen + 0x100, FALSE, &AllocVa, &AllocPa); } else #endif /* RALINK_QA */ { pPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pATEInfo->TxLength, FALSE, &AllocVa, &AllocPa); } if (pPacket == NULL) { pATEInfo->TxCount = 0; DBGPRINT_ERR(("%s : fail to alloc packet space.\n", __FUNCTION__)); return -1; } pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket; pDest = (PUCHAR) AllocVa; #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { GET_OS_PKT_LEN(pPacket) = pATEInfo->DLen; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->DLen; #endif /* LIMUX */ } else #endif /* RALINK_QA */ { GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; #ifndef LINUX GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - LENGTH_802_11; #endif /* LINUX */ } /* prepare frame payload */ #ifdef RALINK_QA if ((pATEInfo->bQATxStart == TRUE) && (pATEInfo->DLen != 0)) { /* copy pattern to payload */ if ((pATEInfo->PLen != 0)) { for (pos = 0; pos < pATEInfo->DLen; pos += pATEInfo->PLen) { memcpy(GET_OS_PKT_DATAPTR(pPacket) + pos, pATEInfo->Pattern, pATEInfo->PLen); } } } else #endif /* RALINK_QA */ { for (pos = 0; pos < GET_OS_PKT_LEN(pPacket); pos++) { if (IS_MT7610E(pAd)) { /* random payload */ pDest[pos] = RandomByte2(pAd); } else { /* fixed payload */ pDest[pos] = pATEInfo->Payload; } } } /* build Tx descriptor */ #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa; pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); #else pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa; NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); pTxD = (TXD_STRUC *)&tx_hw_info[0]; pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); // TxD = *pDestTxD; // pTxD = &TxD; #endif /* !RT_BIG_ENDIAN */ // pTxInfo = (TXINFO_STRUC *)(pTxD + 1); #ifdef RALINK_QA if (pATEInfo->bQATxStart == TRUE) { /* prepare TxD */ NdisZeroMemory(pTxD, TXD_SIZE); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + pATEInfo->HLen; pTxD->SDPtr1 = AllocPa; pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec0 = (pTxD->SDLen1 == 0) ? 1 : 0; pTxD->LastSec1 = 1; ral_write_txd(pAd, NULL, pTxD, pTxInfo, FALSE, FIFO_EDCA); pDest = (PUCHAR)pTxWI; pDest += TXWISize; pHeader80211 = (PHEADER_802_11)pDest; /* modify sequence number... */ if (pATEInfo->TxDoneCount == 0) pATEInfo->seq = pHeader80211->Sequence; else pHeader80211->Sequence = ++pATEInfo->seq; } else #endif /* RALINK_QA */ { NdisZeroMemory(pTxD, TXD_SIZE); /* build Tx descriptor */ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); pTxD->SDLen0 = TXWISize + pATEInfo->HLen; pTxD->SDPtr1 = AllocPa; pTxD->SDLen1 = GET_OS_PKT_LEN(pPacket); pTxD->LastSec0 = (pTxD->SDLen1 == 0) ? 1 : 0; pTxD->LastSec1 = 1; ral_write_txd(pAd, NULL, pTxD, pTxInfo, FALSE, FIFO_EDCA); } #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_WRITE, FALSE); RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); #endif /* RT_BIG_ENDIAN */ return 0; }
static inline UCHAR SelectClearChannelBusyTime( IN PRTMP_ADAPTER pAd ) { PCHANNELINFO pChannelInfo = pAd->pChannelInfo; INT ch = 1, channel_idx; UINT32 min_busytime; int candidate_ch; UCHAR base; if(pChannelInfo == NULL) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("pAd->pChannelInfo equal NULL.\n")); return (FirstChannel(pAd)); } AutoChannelSkipListSetDirty(pAd); MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("=====================================================\n")); for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Channel %d : Busy Time = %u, Skip Channel = %s\n", pAd->ChannelList[channel_idx].Channel, pChannelInfo->chanbusytime[channel_idx], (pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE")); } MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("=====================================================\n")); min_busytime = 0xFFFFFFFF; candidate_ch = -1; for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { if (pChannelInfo->SkipList[channel_idx] == TRUE) continue; if (pChannelInfo->chanbusytime[channel_idx] < min_busytime) { min_busytime = pChannelInfo->chanbusytime[channel_idx]; candidate_ch = channel_idx; } } if (candidate_ch >= 0) { ch = pAd->ChannelList[candidate_ch].Channel; MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Rule 3 Channel Busy time value : Min Channel Busy ==> Select Channel %d \n", ch)); MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Min Channel Busy = %u\n", min_busytime)); MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("BW = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)? "40" : "20")); return ch; } base = RandomByte2(pAd); for (channel_idx=0 ; channel_idx < pAd->ChannelListNum ; channel_idx++) { ch = pAd->ChannelList[(base + channel_idx) % pAd->ChannelListNum].Channel; if (AutoChannelSkipListCheck(pAd, ch)) continue; if ((pAd->ApCfg.bAvoidDfsChannel == TRUE) && (pChannelInfo->IsABand == TRUE) && RadarChannelCheck(pAd, ch)) continue; break; } MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Randomly Select ==> Select Channel %d\n", ch)); return ch; }
static inline UCHAR SelectClearChannelRandom( IN PRTMP_ADAPTER pAd ) { UCHAR cnt, ch = 0, i, RadomIdx; BOOLEAN bFindIt = FALSE; if (pAd->CommonCfg.bIEEE80211H) { cnt = 0; while(TRUE) { cnt++; #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) { /* Counting number of entries in the sub channel list */ for (i = 0; i < pAd->ChannelListNum; i++) if (!pAd->ChannelListN[i].Channel) break; RadomIdx = RandomByte2(pAd)%i; ch = pAd->ChannelListN[RadomIdx].Channel; } else #endif /* DOT11_N_SUPPORT */ { RadomIdx = RandomByte2(pAd)%pAd->ChannelListNum; ch = pAd->ChannelList[RadomIdx].Channel; } if (ch == 0) ch = FirstChannel(pAd); /* have no avaiable channel now. force pick first channel here. */ if (cnt == pAd->ChannelListNum) { ch = FirstChannel(pAd); break; } for (i=0; i<pAd->ChannelListNum; i++) { if (pAd->ChannelList[i].Channel == ch) { if (pAd->ChannelList[i].RemainingTimeForUse == 0) bFindIt = TRUE; break; } } if (bFindIt == TRUE) break; }; } else { ch = pAd->ChannelList[RandomByte2(pAd)%pAd->ChannelListNum].Channel; if (ch == 0) ch = FirstChannel(pAd); } printk("Random in A band. Select Channel %d\n",ch); return ch; }