1/* 2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * File: datarate.c 20 * 21 * Purpose: Handles the auto fallback & data rates functions 22 * 23 * Author: Lyndon Chen 24 * 25 * Date: July 17, 2002 26 * 27 * Functions: 28 * RATEvParseMaxRate - Parsing the highest basic & support rate in rate field of frame 29 * RATEvTxRateFallBack - Rate fallback Algorithm Implementaion 30 * RATEuSetIE- Set rate IE field. 31 * 32 * Revision History: 33 * 34 */ 35 36#include "ttype.h" 37#include "tmacro.h" 38#include "mac.h" 39#include "80211mgr.h" 40#include "bssdb.h" 41#include "datarate.h" 42#include "card.h" 43#include "baseband.h" 44#include "srom.h" 45#include "rf.h" 46 47/*--------------------- Static Definitions -------------------------*/ 48 49 50 51 52/*--------------------- Static Classes ----------------------------*/ 53 54 55 56/*--------------------- Static Variables --------------------------*/ 57//static int msglevel =MSG_LEVEL_DEBUG; 58static int msglevel =MSG_LEVEL_INFO; 59const BYTE acbyIERate[MAX_RATE] = 60{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; 61 62#define AUTORATE_TXOK_CNT 0x0400 63#define AUTORATE_TXFAIL_CNT 0x0064 64#define AUTORATE_TIMEOUT 10 65 66/*--------------------- Static Functions --------------------------*/ 67 68void s_vResetCounter(PKnownNodeDB psNodeDBTable); 69 70void s_vResetCounter(PKnownNodeDB psNodeDBTable) 71{ 72 BYTE ii; 73 74 // clear statistic counter for auto_rate 75 for (ii = 0; ii <= MAX_RATE; ii++) { 76 psNodeDBTable->uTxOk[ii] = 0; 77 psNodeDBTable->uTxFail[ii] = 0; 78 } 79} 80 81/*--------------------- Export Variables --------------------------*/ 82 83 84/*--------------------- Export Functions --------------------------*/ 85 86 87/*+ 88 * 89 * Description: 90 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE 91 * 92 * Parameters: 93 * In: 94 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE 95 * Out: 96 * none 97 * 98 * Return Value: RateIdx 99 * 100-*/ 101BYTE 102DATARATEbyGetRateIdx ( 103 BYTE byRate 104 ) 105{ 106 BYTE ii; 107 108 //Erase basicRate flag. 109 byRate = byRate & 0x7F;//0111 1111 110 111 for (ii = 0; ii < MAX_RATE; ii ++) { 112 if (acbyIERate[ii] == byRate) 113 return ii; 114 } 115 return 0; 116} 117 118 119 120/*+ 121 * 122 * Routine Description: 123 * Rate fallback Algorithm Implementaion 124 * 125 * Parameters: 126 * In: 127 * pDevice - Pointer to the adapter 128 * psNodeDBTable - Pointer to Node Data Base 129 * Out: 130 * none 131 * 132 * Return Value: none 133 * 134-*/ 135#define AUTORATE_TXCNT_THRESHOLD 20 136#define AUTORATE_INC_THRESHOLD 30 137 138 139 140 141/*+ 142 * 143 * Description: 144 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE 145 * 146 * Parameters: 147 * In: 148 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE 149 * Out: 150 * none 151 * 152 * Return Value: RateIdx 153 * 154-*/ 155WORD 156RATEwGetRateIdx( 157 BYTE byRate 158 ) 159{ 160 WORD ii; 161 162 //Erase basicRate flag. 163 byRate = byRate & 0x7F;//0111 1111 164 165 for (ii = 0; ii < MAX_RATE; ii ++) { 166 if (acbyIERate[ii] == byRate) 167 return ii; 168 } 169 return 0; 170} 171 172/*+ 173 * 174 * Description: 175 * Parsing the highest basic & support rate in rate field of frame. 176 * 177 * Parameters: 178 * In: 179 * pDevice - Pointer to the adapter 180 * pItemRates - Pointer to Rate field defined in 802.11 spec. 181 * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec. 182 * Out: 183 * pwMaxBasicRate - Maximum Basic Rate 184 * pwMaxSuppRate - Maximum Supported Rate 185 * pbyTopCCKRate - Maximum Basic Rate in CCK mode 186 * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode 187 * 188 * Return Value: none 189 * 190-*/ 191void RATEvParseMaxRate( 192 void *pDeviceHandler, 193 PWLAN_IE_SUPP_RATES pItemRates, 194 PWLAN_IE_SUPP_RATES pItemExtRates, 195 BOOL bUpdateBasicRate, 196 PWORD pwMaxBasicRate, 197 PWORD pwMaxSuppRate, 198 PWORD pwSuppRate, 199 PBYTE pbyTopCCKRate, 200 PBYTE pbyTopOFDMRate 201 ) 202{ 203PSDevice pDevice = (PSDevice) pDeviceHandler; 204unsigned int ii; 205BYTE byHighSuppRate = 0; 206BYTE byRate = 0; 207WORD wOldBasicRate = pDevice->wBasicRate; 208unsigned int uRateLen; 209 210 211 if (pItemRates == NULL) 212 return; 213 214 *pwSuppRate = 0; 215 uRateLen = pItemRates->len; 216 217 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen); 218 if (pDevice->byBBType != BB_TYPE_11B) { 219 if (uRateLen > WLAN_RATES_MAXLEN) 220 uRateLen = WLAN_RATES_MAXLEN; 221 } else { 222 if (uRateLen > WLAN_RATES_MAXLEN_11B) 223 uRateLen = WLAN_RATES_MAXLEN_11B; 224 } 225 226 for (ii = 0; ii < uRateLen; ii++) { 227 byRate = (BYTE)(pItemRates->abyRates[ii]); 228 if (WLAN_MGMT_IS_BASICRATE(byRate) && 229 (bUpdateBasicRate == TRUE)) { 230 // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate 231 CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); 232 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate)); 233 } 234 byRate = (BYTE)(pItemRates->abyRates[ii]&0x7F); 235 if (byHighSuppRate == 0) 236 byHighSuppRate = byRate; 237 if (byRate > byHighSuppRate) 238 byHighSuppRate = byRate; 239 *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); 240 } 241 if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && 242 (pDevice->byBBType != BB_TYPE_11B)) { 243 244 unsigned int uExtRateLen = pItemExtRates->len; 245 246 if (uExtRateLen > WLAN_RATES_MAXLEN) 247 uExtRateLen = WLAN_RATES_MAXLEN; 248 249 for (ii = 0; ii < uExtRateLen ; ii++) { 250 byRate = (BYTE)(pItemExtRates->abyRates[ii]); 251 // select highest basic rate 252 if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) { 253 // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate 254 CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate)); 255 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate)); 256 } 257 byRate = (BYTE)(pItemExtRates->abyRates[ii]&0x7F); 258 if (byHighSuppRate == 0) 259 byHighSuppRate = byRate; 260 if (byRate > byHighSuppRate) 261 byHighSuppRate = byRate; 262 *pwSuppRate |= (1<<RATEwGetRateIdx(byRate)); 263 //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", RATEwGetRateIdx(byRate), byRate)); 264 } 265 } //if(pItemExtRates != NULL) 266 267 if ((pDevice->byPacketType == PK_TYPE_11GB) 268 && CARDbIsOFDMinBasicRate((void *)pDevice)) { 269 pDevice->byPacketType = PK_TYPE_11GA; 270 } 271 272 *pbyTopCCKRate = pDevice->byTopCCKBasicRate; 273 *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate; 274 *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate); 275 if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB)) 276 *pwMaxBasicRate = pDevice->byTopCCKBasicRate; 277 else 278 *pwMaxBasicRate = pDevice->byTopOFDMBasicRate; 279 if (wOldBasicRate != pDevice->wBasicRate) 280 CARDvSetRSPINF((void *)pDevice, pDevice->byBBType); 281 282 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n"); 283} 284 285 286/*+ 287 * 288 * Routine Description: 289 * Rate fallback Algorithm Implementaion 290 * 291 * Parameters: 292 * In: 293 * pDevice - Pointer to the adapter 294 * psNodeDBTable - Pointer to Node Data Base 295 * Out: 296 * none 297 * 298 * Return Value: none 299 * 300-*/ 301#define AUTORATE_TXCNT_THRESHOLD 20 302#define AUTORATE_INC_THRESHOLD 30 303 304void 305RATEvTxRateFallBack( 306 void *pDeviceHandler, 307 PKnownNodeDB psNodeDBTable 308 ) 309{ 310PSDevice pDevice = (PSDevice) pDeviceHandler; 311PSMgmtObject pMgmt = &(pDevice->sMgmtObj); 312WORD wIdxDownRate = 0; 313unsigned int ii; 314BOOL bAutoRate[MAX_RATE] = {TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}; 315DWORD dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; 316DWORD dwThroughput = 0; 317WORD wIdxUpRate = 0; 318DWORD dwTxDiff = 0; 319 320 if (pMgmt->eScanState != WMAC_NO_SCANNING) { 321 // Don't do Fallback when scanning Channel 322 return; 323 } 324 psNodeDBTable->uTimeCount ++; 325 326 if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE]) 327 dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE]; 328 329 if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) && 330 (dwTxDiff < AUTORATE_TXFAIL_CNT) && 331 (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) { 332 return; 333 } 334 335 if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) { 336 psNodeDBTable->uTimeCount = 0; 337 } 338 339 for (ii = 0; ii < MAX_RATE; ii++) { 340 if (psNodeDBTable->wSuppRate & (0x0001<<ii)) { 341 if (bAutoRate[ii] == TRUE) { 342 wIdxUpRate = (WORD) ii; 343 } 344 } else { 345 bAutoRate[ii] = FALSE; 346 } 347 } 348 349 for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) { 350 if ( (psNodeDBTable->uTxOk[ii] != 0) || 351 (psNodeDBTable->uTxFail[ii] != 0) ) { 352 dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii]; 353 if (ii < RATE_11M) { 354 psNodeDBTable->uTxFail[ii] *= 4; 355 } 356 dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]); 357 } 358 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n", 359 ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]); 360 } 361 dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; 362 363 wIdxDownRate = psNodeDBTable->wTxDataRate; 364 for (ii = psNodeDBTable->wTxDataRate; ii > 0;) { 365 ii--; 366 if ( (dwThroughputTbl[ii] > dwThroughput) && 367 (bAutoRate[ii]==TRUE) ) { 368 dwThroughput = dwThroughputTbl[ii]; 369 wIdxDownRate = (WORD) ii; 370 } 371 } 372 psNodeDBTable->wTxDataRate = wIdxDownRate; 373 if (psNodeDBTable->uTxOk[MAX_RATE]) { 374 if (psNodeDBTable->uTxOk[MAX_RATE] > 375 (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) { 376 psNodeDBTable->wTxDataRate = wIdxUpRate; 377 } 378 }else { // adhoc, if uTxOk(total) =0 & uTxFail(total) = 0 379 if (psNodeDBTable->uTxFail[MAX_RATE] == 0) 380 psNodeDBTable->wTxDataRate = wIdxUpRate; 381 } 382 383 if (pDevice->byBBType == BB_TYPE_11A) { 384 if (psNodeDBTable->wTxDataRate <= RATE_11M) 385 psNodeDBTable->wTxDataRate = RATE_6M; 386 } 387 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n",(int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]); 388 s_vResetCounter(psNodeDBTable); 389 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate); 390 return; 391} 392 393/*+ 394 * 395 * Description: 396 * This routine is used to assemble available Rate IE. 397 * 398 * Parameters: 399 * In: 400 * pDevice 401 * Out: 402 * 403 * Return Value: None 404 * 405-*/ 406BYTE 407RATEuSetIE ( 408 PWLAN_IE_SUPP_RATES pSrcRates, 409 PWLAN_IE_SUPP_RATES pDstRates, 410 unsigned int uRateLen 411 ) 412{ 413 unsigned int ii, uu, uRateCnt = 0; 414 415 if ((pSrcRates == NULL) || (pDstRates == NULL)) 416 return 0; 417 418 if (pSrcRates->len == 0) 419 return 0; 420 421 for (ii = 0; ii < uRateLen; ii++) { 422 for (uu = 0; uu < pSrcRates->len; uu++) { 423 if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) { 424 pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu]; 425 break; 426 } 427 } 428 } 429 return (BYTE)uRateCnt; 430} 431