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(PKnownNodeDB psNodeDBTable
);
70 void s_vResetCounter(PKnownNodeDB psNodeDBTable
)
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;
81 /*--------------------- Export Variables --------------------------*/
84 /*--------------------- Export Functions --------------------------*/
90 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
94 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE
98 * Return Value: RateIdx
102 DATARATEbyGetRateIdx (
108 //Erase basicRate flag.
109 byRate
= byRate
& 0x7F;//0111 1111
111 for (ii
= 0; ii
< MAX_RATE
; ii
++) {
112 if (acbyIERate
[ii
] == byRate
)
122 * Routine Description:
123 * Rate fallback Algorithm Implementaion
127 * pDevice - Pointer to the adapter
128 * psNodeDBTable - Pointer to Node Data Base
135 #define AUTORATE_TXCNT_THRESHOLD 20
136 #define AUTORATE_INC_THRESHOLD 30
144 * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE
148 * BYTE - Rate value in SuppRates IE or ExtSuppRates IE
152 * Return Value: RateIdx
162 //Erase basicRate flag.
163 byRate
= byRate
& 0x7F;//0111 1111
165 for (ii
= 0; ii
< MAX_RATE
; ii
++) {
166 if (acbyIERate
[ii
] == byRate
)
175 * Parsing the highest basic & support rate in rate field of frame.
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.
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
191 void RATEvParseMaxRate(
192 void *pDeviceHandler
,
193 PWLAN_IE_SUPP_RATES pItemRates
,
194 PWLAN_IE_SUPP_RATES pItemExtRates
,
195 BOOL bUpdateBasicRate
,
196 PWORD pwMaxBasicRate
,
203 PSDevice pDevice
= (PSDevice
) pDeviceHandler
;
205 BYTE byHighSuppRate
= 0;
207 WORD wOldBasicRate
= pDevice
->wBasicRate
;
208 unsigned int uRateLen
;
211 if (pItemRates
== NULL
)
215 uRateLen
= pItemRates
->len
;
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
;
222 if (uRateLen
> WLAN_RATES_MAXLEN_11B
)
223 uRateLen
= WLAN_RATES_MAXLEN_11B
;
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
));
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
));
241 if ((pItemExtRates
!= NULL
) && (pItemExtRates
->byElementID
== WLAN_EID_EXTSUPP_RATES
) &&
242 (pDevice
->byBBType
!= BB_TYPE_11B
)) {
244 unsigned int uExtRateLen
= pItemExtRates
->len
;
246 if (uExtRateLen
> WLAN_RATES_MAXLEN
)
247 uExtRateLen
= WLAN_RATES_MAXLEN
;
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
));
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));
265 } //if(pItemExtRates != NULL)
267 if ((pDevice
->byPacketType
== PK_TYPE_11GB
)
268 && CARDbIsOFDMinBasicRate((void *)pDevice
)) {
269 pDevice
->byPacketType
= PK_TYPE_11GA
;
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
;
278 *pwMaxBasicRate
= pDevice
->byTopOFDMBasicRate
;
279 if (wOldBasicRate
!= pDevice
->wBasicRate
)
280 CARDvSetRSPINF((void *)pDevice
, pDevice
->byBBType
);
282 DBG_PRT(MSG_LEVEL_DEBUG
, KERN_INFO
"Exit ParseMaxRate\n");
288 * Routine Description:
289 * Rate fallback Algorithm Implementaion
293 * pDevice - Pointer to the adapter
294 * psNodeDBTable - Pointer to Node Data Base
301 #define AUTORATE_TXCNT_THRESHOLD 20
302 #define AUTORATE_INC_THRESHOLD 30
306 void *pDeviceHandler
,
307 PKnownNodeDB psNodeDBTable
310 PSDevice pDevice
= (PSDevice
) pDeviceHandler
;
311 PSMgmtObject pMgmt
= &(pDevice
->sMgmtObj
);
312 WORD wIdxDownRate
= 0;
314 BOOL bAutoRate
[MAX_RATE
] = {TRUE
,TRUE
,TRUE
,TRUE
,FALSE
,FALSE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
,TRUE
};
315 DWORD dwThroughputTbl
[MAX_RATE
] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540};
316 DWORD dwThroughput
= 0;
320 if (pMgmt
->eScanState
!= WMAC_NO_SCANNING
) {
321 // Don't do Fallback when scanning Channel
324 psNodeDBTable
->uTimeCount
++;
326 if (psNodeDBTable
->uTxFail
[MAX_RATE
] > psNodeDBTable
->uTxOk
[MAX_RATE
])
327 dwTxDiff
= psNodeDBTable
->uTxFail
[MAX_RATE
] - psNodeDBTable
->uTxOk
[MAX_RATE
];
329 if ((psNodeDBTable
->uTxOk
[MAX_RATE
] < AUTORATE_TXOK_CNT
) &&
330 (dwTxDiff
< AUTORATE_TXFAIL_CNT
) &&
331 (psNodeDBTable
->uTimeCount
< AUTORATE_TIMEOUT
)) {
335 if (psNodeDBTable
->uTimeCount
>= AUTORATE_TIMEOUT
) {
336 psNodeDBTable
->uTimeCount
= 0;
339 for (ii
= 0; ii
< MAX_RATE
; ii
++) {
340 if (psNodeDBTable
->wSuppRate
& (0x0001<<ii
)) {
341 if (bAutoRate
[ii
] == TRUE
) {
342 wIdxUpRate
= (WORD
) ii
;
345 bAutoRate
[ii
] = FALSE
;
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
];
354 psNodeDBTable
->uTxFail
[ii
] *= 4;
356 dwThroughputTbl
[ii
] /= (psNodeDBTable
->uTxOk
[ii
] + psNodeDBTable
->uTxFail
[ii
]);
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
]);
361 dwThroughput
= dwThroughputTbl
[psNodeDBTable
->wTxDataRate
];
363 wIdxDownRate
= psNodeDBTable
->wTxDataRate
;
364 for (ii
= psNodeDBTable
->wTxDataRate
; ii
> 0;) {
366 if ( (dwThroughputTbl
[ii
] > dwThroughput
) &&
367 (bAutoRate
[ii
]==TRUE
) ) {
368 dwThroughput
= dwThroughputTbl
[ii
];
369 wIdxDownRate
= (WORD
) ii
;
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
;
378 }else { // adhoc, if uTxOk(total) =0 & uTxFail(total) = 0
379 if (psNodeDBTable
->uTxFail
[MAX_RATE
] == 0)
380 psNodeDBTable
->wTxDataRate
= wIdxUpRate
;
383 if (pDevice
->byBBType
== BB_TYPE_11A
) {
384 if (psNodeDBTable
->wTxDataRate
<= RATE_11M
)
385 psNodeDBTable
->wTxDataRate
= RATE_6M
;
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
);
396 * This routine is used to assemble available Rate IE.
408 PWLAN_IE_SUPP_RATES pSrcRates
,
409 PWLAN_IE_SUPP_RATES pDstRates
,
410 unsigned int uRateLen
413 unsigned int ii
, uu
, uRateCnt
= 0;
415 if ((pSrcRates
== NULL
) || (pDstRates
== NULL
))
418 if (pSrcRates
->len
== 0)
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
];
429 return (BYTE
)uRateCnt
;