2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
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.
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.
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.
21 * Purpose: Handles the auto fallback & data rates 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.
47 /*--------------------- Static Definitions -------------------------*/
52 /*--------------------- Static Classes ----------------------------*/
56 /*--------------------- Static Variables --------------------------*/
57 //static int msglevel =MSG_LEVEL_DEBUG;
58 static int msglevel
=MSG_LEVEL_INFO
;
59 const BYTE acbyIERate
[MAX_RATE
] =
60 {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
62 #define AUTORATE_TXOK_CNT 0x0400
63 #define AUTORATE_TXFAIL_CNT 0x0064
64 #define AUTORATE_TIMEOUT 10
66 /*--------------------- Static Functions --------------------------*/
68 VOID
s_vResetCounter (
69 IN PKnownNodeDB psNodeDBTable
76 IN PKnownNodeDB psNodeDBTable
81 // clear statistic counter for auto_rate
82 for(ii
=0;ii
<=MAX_RATE
;ii
++) {
83 psNodeDBTable
->uTxOk
[ii
] = 0;
84 psNodeDBTable
->uTxFail
[ii
] = 0;
88 /*--------------------- Export Variables --------------------------*/
91 /*--------------------- Export Functions --------------------------*/
97 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
101 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE
105 * Return Value: RateIdx
109 DATARATEbyGetRateIdx (
115 //Erase basicRate flag.
116 byRate
= byRate
& 0x7F;//0111 1111
118 for (ii
= 0; ii
< MAX_RATE
; ii
++) {
119 if (acbyIERate
[ii
] == byRate
)
129 * Routine Description:
130 * Rate fallback Algorithm Implementaion
134 * pDevice - Pointer to the adapter
135 * psNodeDBTable - Pointer to Node Data Base
142 #define AUTORATE_TXCNT_THRESHOLD 20
143 #define AUTORATE_INC_THRESHOLD 30
151 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
155 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE
159 * Return Value: RateIdx
169 //Erase basicRate flag.
170 byRate
= byRate
& 0x7F;//0111 1111
172 for (ii
= 0; ii
< MAX_RATE
; ii
++) {
173 if (acbyIERate
[ii
] == byRate
)
182 * Parsing the highest basic & support rate in rate field of frame.
186 * pDevice - Pointer to the adapter
187 * pItemRates - Pointer to Rate field defined in 802.11 spec.
188 * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec.
190 * pwMaxBasicRate - Maximum Basic Rate
191 * pwMaxSuppRate - Maximum Supported Rate
192 * pbyTopCCKRate - Maximum Basic Rate in CCK mode
193 * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode
200 IN PVOID pDeviceHandler
,
201 IN PWLAN_IE_SUPP_RATES pItemRates
,
202 IN PWLAN_IE_SUPP_RATES pItemExtRates
,
203 IN BOOL bUpdateBasicRate
,
204 OUT PWORD pwMaxBasicRate
,
205 OUT PWORD pwMaxSuppRate
,
206 OUT PWORD pwSuppRate
,
207 OUT PBYTE pbyTopCCKRate
,
208 OUT PBYTE pbyTopOFDMRate
211 PSDevice pDevice
= (PSDevice
) pDeviceHandler
;
213 BYTE byHighSuppRate
= 0;
215 WORD wOldBasicRate
= pDevice
->wBasicRate
;
219 if (pItemRates
== NULL
)
223 uRateLen
= pItemRates
->len
;
225 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"ParseMaxRate Len: %d\n", uRateLen
);
226 if (pDevice
->byBBType
!= BB_TYPE_11B
) {
227 if (uRateLen
> WLAN_RATES_MAXLEN
)
228 uRateLen
= WLAN_RATES_MAXLEN
;
230 if (uRateLen
> WLAN_RATES_MAXLEN_11B
)
231 uRateLen
= WLAN_RATES_MAXLEN_11B
;
234 for (ii
= 0; ii
< uRateLen
; ii
++) {
235 byRate
= (BYTE
)(pItemRates
->abyRates
[ii
]);
236 if (WLAN_MGMT_IS_BASICRATE(byRate
) &&
237 (bUpdateBasicRate
== TRUE
)) {
238 // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
239 CARDbAddBasicRate((PVOID
)pDevice
, RATEwGetRateIdx(byRate
));
240 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate
));
242 byRate
= (BYTE
)(pItemRates
->abyRates
[ii
]&0x7F);
243 if (byHighSuppRate
== 0)
244 byHighSuppRate
= byRate
;
245 if (byRate
> byHighSuppRate
)
246 byHighSuppRate
= byRate
;
247 *pwSuppRate
|= (1<<RATEwGetRateIdx(byRate
));
249 if ((pItemExtRates
!= NULL
) && (pItemExtRates
->byElementID
== WLAN_EID_EXTSUPP_RATES
) &&
250 (pDevice
->byBBType
!= BB_TYPE_11B
)) {
252 UINT uExtRateLen
= pItemExtRates
->len
;
254 if (uExtRateLen
> WLAN_RATES_MAXLEN
)
255 uExtRateLen
= WLAN_RATES_MAXLEN
;
257 for (ii
= 0; ii
< uExtRateLen
; ii
++) {
258 byRate
= (BYTE
)(pItemExtRates
->abyRates
[ii
]);
259 // select highest basic rate
260 if (WLAN_MGMT_IS_BASICRATE(pItemExtRates
->abyRates
[ii
])) {
261 // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate
262 CARDbAddBasicRate((PVOID
)pDevice
, RATEwGetRateIdx(byRate
));
263 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate
));
265 byRate
= (BYTE
)(pItemExtRates
->abyRates
[ii
]&0x7F);
266 if (byHighSuppRate
== 0)
267 byHighSuppRate
= byRate
;
268 if (byRate
> byHighSuppRate
)
269 byHighSuppRate
= byRate
;
270 *pwSuppRate
|= (1<<RATEwGetRateIdx(byRate
));
271 //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", RATEwGetRateIdx(byRate), byRate));
273 } //if(pItemExtRates != NULL)
275 if ((pDevice
->byPacketType
== PK_TYPE_11GB
) && CARDbIsOFDMinBasicRate((PVOID
)pDevice
)) {
276 pDevice
->byPacketType
= PK_TYPE_11GA
;
279 *pbyTopCCKRate
= pDevice
->byTopCCKBasicRate
;
280 *pbyTopOFDMRate
= pDevice
->byTopOFDMBasicRate
;
281 *pwMaxSuppRate
= RATEwGetRateIdx(byHighSuppRate
);
282 if ((pDevice
->byPacketType
==PK_TYPE_11B
) || (pDevice
->byPacketType
==PK_TYPE_11GB
))
283 *pwMaxBasicRate
= pDevice
->byTopCCKBasicRate
;
285 *pwMaxBasicRate
= pDevice
->byTopOFDMBasicRate
;
286 if (wOldBasicRate
!= pDevice
->wBasicRate
)
287 CARDvSetRSPINF((PVOID
)pDevice
, pDevice
->byBBType
);
289 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"Exit ParseMaxRate\n");
295 * Routine Description:
296 * Rate fallback Algorithm Implementaion
300 * pDevice - Pointer to the adapter
301 * psNodeDBTable - Pointer to Node Data Base
308 #define AUTORATE_TXCNT_THRESHOLD 20
309 #define AUTORATE_INC_THRESHOLD 30
312 RATEvTxRateFallBack (
313 IN PVOID pDeviceHandler
,
314 IN PKnownNodeDB psNodeDBTable
317 PSDevice pDevice
= (PSDevice
) pDeviceHandler
;
318 PSMgmtObject pMgmt
= &(pDevice
->sMgmtObj
);
319 #if 1 //mike fixed old: use packet lose ratio algorithm to control rate
320 WORD wIdxDownRate
= 0;
322 BOOL bAutoRate
[MAX_RATE
] = {TRUE
,TRUE
,TRUE
,TRUE
,FALSE
,FALSE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
};
323 DWORD dwThroughputTbl
[MAX_RATE
] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
324 DWORD dwThroughput
= 0;
328 if (pMgmt
->eScanState
!= WMAC_NO_SCANNING
) {
329 // Don't do Fallback when scanning Channel
332 psNodeDBTable
->uTimeCount
++;
334 if (psNodeDBTable
->uTxFail
[MAX_RATE
] > psNodeDBTable
->uTxOk
[MAX_RATE
])
335 dwTxDiff
= psNodeDBTable
->uTxFail
[MAX_RATE
] - psNodeDBTable
->uTxOk
[MAX_RATE
];
337 if ((psNodeDBTable
->uTxOk
[MAX_RATE
] < AUTORATE_TXOK_CNT
) &&
338 (dwTxDiff
< AUTORATE_TXFAIL_CNT
) &&
339 (psNodeDBTable
->uTimeCount
< AUTORATE_TIMEOUT
)) {
343 if (psNodeDBTable
->uTimeCount
>= AUTORATE_TIMEOUT
) {
344 psNodeDBTable
->uTimeCount
= 0;
347 for(ii
=0;ii
<MAX_RATE
;ii
++) {
348 if (psNodeDBTable
->wSuppRate
& (0x0001<<ii
)) {
349 if (bAutoRate
[ii
] == TRUE
) {
350 wIdxUpRate
= (WORD
) ii
;
353 bAutoRate
[ii
] = FALSE
;
357 for(ii
=0;ii
<=psNodeDBTable
->wTxDataRate
;ii
++) {
358 if ( (psNodeDBTable
->uTxOk
[ii
] != 0) ||
359 (psNodeDBTable
->uTxFail
[ii
] != 0) ) {
360 dwThroughputTbl
[ii
] *= psNodeDBTable
->uTxOk
[ii
];
362 psNodeDBTable
->uTxFail
[ii
] *= 4;
364 dwThroughputTbl
[ii
] /= (psNodeDBTable
->uTxOk
[ii
] + psNodeDBTable
->uTxFail
[ii
]);
366 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
367 ii
, (int)psNodeDBTable
->uTxOk
[ii
], (int)psNodeDBTable
->uTxFail
[ii
], (int)dwThroughputTbl
[ii
]);
369 dwThroughput
= dwThroughputTbl
[psNodeDBTable
->wTxDataRate
];
371 wIdxDownRate
= psNodeDBTable
->wTxDataRate
;
372 for(ii
= psNodeDBTable
->wTxDataRate
; ii
> 0;) {
374 if ( (dwThroughputTbl
[ii
] > dwThroughput
) &&
375 (bAutoRate
[ii
]==TRUE
) ) {
376 dwThroughput
= dwThroughputTbl
[ii
];
377 wIdxDownRate
= (WORD
) ii
;
380 psNodeDBTable
->wTxDataRate
= wIdxDownRate
;
381 if (psNodeDBTable
->uTxOk
[MAX_RATE
]) {
382 if (psNodeDBTable
->uTxOk
[MAX_RATE
] >
383 (psNodeDBTable
->uTxFail
[MAX_RATE
] * 4) ) {
384 psNodeDBTable
->wTxDataRate
= wIdxUpRate
;
386 }else { // adhoc, if uTxOk(total) =0 & uTxFail(total) = 0
387 if (psNodeDBTable
->uTxFail
[MAX_RATE
] == 0)
388 psNodeDBTable
->wTxDataRate
= wIdxUpRate
;
391 if (pDevice
->byBBType
== BB_TYPE_11A
) {
392 if (psNodeDBTable
->wTxDataRate
<= RATE_11M
)
393 psNodeDBTable
->wTxDataRate
= RATE_6M
;
395 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
]);
396 s_vResetCounter(psNodeDBTable
);
397 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable
->wTxDataRate
, (int)wIdxUpRate
, (int)wIdxDownRate
);
399 #else //mike fixed new: use differ-signal strength to control rate
401 BOOL bAutoRate
[MAX_RATE
] = {TRUE
,TRUE
,TRUE
,TRUE
,FALSE
,FALSE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
};
405 if (pMgmt
->eScanState
!= WMAC_NO_SCANNING
) {
406 // Don't do Fallback when scanning Channel
410 for(ii
=0;ii
<MAX_RATE
;ii
++) {
411 if (psNodeDBTable
->wSuppRate
& (0x0001<<ii
)) {
412 if (bAutoRate
[ii
] == TRUE
) {
413 wIdxUpRate
= (WORD
) ii
;
416 bAutoRate
[ii
] = FALSE
;
420 RFvRSSITodBm(pDevice
, (BYTE
)(pDevice
->uCurrRSSI
), &ldBm
);
423 if ( psNodeDBTable
->wSuppRate
& (0x0001<<RATE_54M
) ) //11a/g
425 psNodeDBTable
->wTxDataRate
= RATE_54M
;
428 psNodeDBTable
->wTxDataRate
= RATE_11M
;
432 if (wIdxUpRate
== RATE_54M
) { //11a/g
434 psNodeDBTable
->wTxDataRate
= RATE_54M
;
435 else if (ldBm
> -61 )
436 psNodeDBTable
->wTxDataRate
= RATE_48M
;
437 else if (ldBm
> -66 )
438 psNodeDBTable
->wTxDataRate
= RATE_36M
;
439 else if (ldBm
> -72 )
440 psNodeDBTable
->wTxDataRate
= RATE_24M
;
441 else if (ldBm
> -80 )
442 psNodeDBTable
->wTxDataRate
= RATE_5M
;
444 psNodeDBTable
->wTxDataRate
= RATE_1M
;
445 //increasingVGA = TRUE;
450 psNodeDBTable
->wTxDataRate
= RATE_11M
;
451 else if (ldBm
> -75 )
452 psNodeDBTable
->wTxDataRate
= RATE_5M
;
454 psNodeDBTable
->wTxDataRate
= RATE_1M
;
464 * This routine is used to assemble available Rate IE.
476 IN PWLAN_IE_SUPP_RATES pSrcRates
,
477 IN PWLAN_IE_SUPP_RATES pDstRates
,
481 UINT ii
, uu
, uRateCnt
= 0;
483 if ((pSrcRates
== NULL
) || (pDstRates
== NULL
))
486 if (pSrcRates
->len
== 0)
489 for (ii
= 0; ii
< uRateLen
; ii
++) {
490 for (uu
= 0; uu
< pSrcRates
->len
; uu
++) {
491 if ((pSrcRates
->abyRates
[uu
] & 0x7F) == acbyIERate
[ii
]) {
492 pDstRates
->abyRates
[uRateCnt
++] = pSrcRates
->abyRates
[uu
];
497 return (BYTE
)uRateCnt
;