Commit | Line | Data |
---|---|---|
5449c685 FB |
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 | ||
5449c685 | 36 | #include "ttype.h" |
5449c685 | 37 | #include "tmacro.h" |
5449c685 | 38 | #include "mac.h" |
5449c685 | 39 | #include "80211mgr.h" |
5449c685 | 40 | #include "bssdb.h" |
5449c685 | 41 | #include "datarate.h" |
5449c685 | 42 | #include "card.h" |
5449c685 | 43 | #include "baseband.h" |
5449c685 | 44 | #include "srom.h" |
5449c685 FB |
45 | |
46 | /*--------------------- Static Definitions -------------------------*/ | |
47 | ||
48 | ||
49 | ||
50 | ||
51 | /*--------------------- Static Classes ----------------------------*/ | |
52 | ||
53 | ||
2986db5f | 54 | extern unsigned short TxRate_iwconfig; //2008-5-8 <add> by chester |
5449c685 FB |
55 | /*--------------------- Static Variables --------------------------*/ |
56 | //static int msglevel =MSG_LEVEL_DEBUG; | |
57 | static int msglevel =MSG_LEVEL_INFO; | |
3fc9b584 | 58 | const unsigned char acbyIERate[MAX_RATE] = |
5449c685 FB |
59 | {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C}; |
60 | ||
61 | #define AUTORATE_TXOK_CNT 0x0400 | |
62 | #define AUTORATE_TXFAIL_CNT 0x0064 | |
63 | #define AUTORATE_TIMEOUT 10 | |
64 | ||
65 | /*--------------------- Static Functions --------------------------*/ | |
66 | ||
6b35b7b3 | 67 | void s_vResetCounter ( |
3a215e0f | 68 | PKnownNodeDB psNodeDBTable |
5449c685 FB |
69 | ); |
70 | ||
71 | ||
72 | ||
6b35b7b3 | 73 | void |
5449c685 | 74 | s_vResetCounter ( |
3a215e0f | 75 | PKnownNodeDB psNodeDBTable |
5449c685 FB |
76 | ) |
77 | { | |
3fc9b584 | 78 | unsigned char ii; |
5449c685 FB |
79 | |
80 | // clear statistic counter for auto_rate | |
81 | for(ii=0;ii<=MAX_RATE;ii++) { | |
82 | psNodeDBTable->uTxOk[ii] = 0; | |
83 | psNodeDBTable->uTxFail[ii] = 0; | |
84 | } | |
85 | } | |
86 | ||
87 | /*--------------------- Export Variables --------------------------*/ | |
88 | ||
89 | ||
90 | /*--------------------- Export Functions --------------------------*/ | |
91 | ||
92 | ||
93 | /*+ | |
94 | * | |
95 | * Description: | |
96 | * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE | |
97 | * | |
98 | * Parameters: | |
99 | * In: | |
3fc9b584 | 100 | * unsigned char - Rate value in SuppRates IE or ExtSuppRates IE |
5449c685 FB |
101 | * Out: |
102 | * none | |
103 | * | |
104 | * Return Value: RateIdx | |
105 | * | |
106 | -*/ | |
3fc9b584 | 107 | unsigned char |
5449c685 | 108 | DATARATEbyGetRateIdx ( |
3fc9b584 | 109 | unsigned char byRate |
5449c685 FB |
110 | ) |
111 | { | |
3fc9b584 | 112 | unsigned char ii; |
5449c685 FB |
113 | |
114 | //Erase basicRate flag. | |
115 | byRate = byRate & 0x7F;//0111 1111 | |
116 | ||
117 | for (ii = 0; ii < MAX_RATE; ii ++) { | |
118 | if (acbyIERate[ii] == byRate) | |
119 | return ii; | |
120 | } | |
121 | return 0; | |
122 | } | |
123 | ||
124 | ||
125 | ||
126 | /*+ | |
127 | * | |
128 | * Routine Description: | |
129 | * Rate fallback Algorithm Implementaion | |
130 | * | |
131 | * Parameters: | |
132 | * In: | |
133 | * pDevice - Pointer to the adapter | |
134 | * psNodeDBTable - Pointer to Node Data Base | |
135 | * Out: | |
136 | * none | |
137 | * | |
138 | * Return Value: none | |
139 | * | |
140 | -*/ | |
141 | #define AUTORATE_TXCNT_THRESHOLD 20 | |
142 | #define AUTORATE_INC_THRESHOLD 30 | |
143 | ||
144 | ||
145 | ||
146 | ||
147 | /*+ | |
148 | * | |
149 | * Description: | |
150 | * Get RateIdx from the value in SuppRates IE or ExtSuppRates IE | |
151 | * | |
152 | * Parameters: | |
153 | * In: | |
3fc9b584 | 154 | * unsigned char - Rate value in SuppRates IE or ExtSuppRates IE |
5449c685 FB |
155 | * Out: |
156 | * none | |
157 | * | |
158 | * Return Value: RateIdx | |
159 | * | |
160 | -*/ | |
2986db5f | 161 | unsigned short |
5449c685 | 162 | wGetRateIdx( |
3fc9b584 | 163 | unsigned char byRate |
5449c685 FB |
164 | ) |
165 | { | |
2986db5f | 166 | unsigned short ii; |
5449c685 FB |
167 | |
168 | //Erase basicRate flag. | |
169 | byRate = byRate & 0x7F;//0111 1111 | |
170 | ||
171 | for (ii = 0; ii < MAX_RATE; ii ++) { | |
172 | if (acbyIERate[ii] == byRate) | |
173 | return ii; | |
174 | } | |
175 | return 0; | |
176 | } | |
177 | ||
178 | /*+ | |
179 | * | |
180 | * Description: | |
181 | * Parsing the highest basic & support rate in rate field of frame. | |
182 | * | |
183 | * Parameters: | |
184 | * In: | |
185 | * pDevice - Pointer to the adapter | |
186 | * pItemRates - Pointer to Rate field defined in 802.11 spec. | |
187 | * pItemExtRates - Pointer to Extended Rate field defined in 802.11 spec. | |
188 | * Out: | |
189 | * pwMaxBasicRate - Maximum Basic Rate | |
190 | * pwMaxSuppRate - Maximum Supported Rate | |
191 | * pbyTopCCKRate - Maximum Basic Rate in CCK mode | |
192 | * pbyTopOFDMRate - Maximum Basic Rate in OFDM mode | |
193 | * | |
194 | * Return Value: none | |
195 | * | |
196 | -*/ | |
6b35b7b3 | 197 | void |
5449c685 | 198 | RATEvParseMaxRate ( |
3a215e0f CC |
199 | void *pDeviceHandler, |
200 | PWLAN_IE_SUPP_RATES pItemRates, | |
201 | PWLAN_IE_SUPP_RATES pItemExtRates, | |
7b6a0013 | 202 | bool bUpdateBasicRate, |
15df6c2b CC |
203 | unsigned short *pwMaxBasicRate, |
204 | unsigned short *pwMaxSuppRate, | |
205 | unsigned short *pwSuppRate, | |
2989e96f CC |
206 | unsigned char *pbyTopCCKRate, |
207 | unsigned char *pbyTopOFDMRate | |
5449c685 FB |
208 | ) |
209 | { | |
210 | PSDevice pDevice = (PSDevice) pDeviceHandler; | |
b6e95cd5 | 211 | unsigned int ii; |
3fc9b584 CC |
212 | unsigned char byHighSuppRate = 0; |
213 | unsigned char byRate = 0; | |
2986db5f | 214 | unsigned short wOldBasicRate = pDevice->wBasicRate; |
b6e95cd5 | 215 | unsigned int uRateLen; |
5449c685 FB |
216 | |
217 | ||
218 | if (pItemRates == NULL) | |
219 | return; | |
220 | ||
221 | *pwSuppRate = 0; | |
222 | uRateLen = pItemRates->len; | |
223 | ||
7e809a9b | 224 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen); |
5449c685 FB |
225 | if (pDevice->eCurrentPHYType != PHY_TYPE_11B) { |
226 | if (uRateLen > WLAN_RATES_MAXLEN) | |
227 | uRateLen = WLAN_RATES_MAXLEN; | |
228 | } else { | |
229 | if (uRateLen > WLAN_RATES_MAXLEN_11B) | |
230 | uRateLen = WLAN_RATES_MAXLEN_11B; | |
231 | } | |
232 | ||
233 | for (ii = 0; ii < uRateLen; ii++) { | |
3fc9b584 | 234 | byRate = (unsigned char)(pItemRates->abyRates[ii]); |
5449c685 | 235 | if (WLAN_MGMT_IS_BASICRATE(byRate) && |
1b12068a | 236 | (bUpdateBasicRate == true)) { |
5449c685 | 237 | // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate |
830a619c | 238 | CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate)); |
7e809a9b | 239 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate)); |
5449c685 | 240 | } |
3fc9b584 | 241 | byRate = (unsigned char)(pItemRates->abyRates[ii]&0x7F); |
5449c685 FB |
242 | if (byHighSuppRate == 0) |
243 | byHighSuppRate = byRate; | |
244 | if (byRate > byHighSuppRate) | |
245 | byHighSuppRate = byRate; | |
246 | *pwSuppRate |= (1<<wGetRateIdx(byRate)); | |
247 | } | |
248 | if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) && | |
249 | (pDevice->eCurrentPHYType != PHY_TYPE_11B)) { | |
250 | ||
b6e95cd5 | 251 | unsigned int uExtRateLen = pItemExtRates->len; |
5449c685 FB |
252 | |
253 | if (uExtRateLen > WLAN_RATES_MAXLEN) | |
254 | uExtRateLen = WLAN_RATES_MAXLEN; | |
255 | ||
256 | for (ii = 0; ii < uExtRateLen ; ii++) { | |
3fc9b584 | 257 | byRate = (unsigned char)(pItemExtRates->abyRates[ii]); |
5449c685 FB |
258 | // select highest basic rate |
259 | if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) { | |
260 | // Add to basic rate set, update pDevice->byTopCCKBasicRate and pDevice->byTopOFDMBasicRate | |
830a619c | 261 | CARDbAddBasicRate((void *)pDevice, wGetRateIdx(byRate)); |
7e809a9b | 262 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", wGetRateIdx(byRate)); |
5449c685 | 263 | } |
3fc9b584 | 264 | byRate = (unsigned char)(pItemExtRates->abyRates[ii]&0x7F); |
5449c685 FB |
265 | if (byHighSuppRate == 0) |
266 | byHighSuppRate = byRate; | |
267 | if (byRate > byHighSuppRate) | |
268 | byHighSuppRate = byRate; | |
269 | *pwSuppRate |= (1<<wGetRateIdx(byRate)); | |
270 | //DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n", wGetRateIdx(byRate), byRate)); | |
271 | } | |
272 | } //if(pItemExtRates != NULL) | |
273 | ||
830a619c | 274 | if ((pDevice->byPacketType == PK_TYPE_11GB) && CARDbIsOFDMinBasicRate((void *)pDevice)) { |
5449c685 FB |
275 | pDevice->byPacketType = PK_TYPE_11GA; |
276 | } | |
277 | ||
278 | *pbyTopCCKRate = pDevice->byTopCCKBasicRate; | |
279 | *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate; | |
280 | *pwMaxSuppRate = wGetRateIdx(byHighSuppRate); | |
281 | if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB)) | |
282 | *pwMaxBasicRate = pDevice->byTopCCKBasicRate; | |
283 | else | |
284 | *pwMaxBasicRate = pDevice->byTopOFDMBasicRate; | |
285 | if (wOldBasicRate != pDevice->wBasicRate) | |
830a619c | 286 | CARDvSetRSPINF((void *)pDevice, pDevice->eCurrentPHYType); |
5449c685 | 287 | |
7e809a9b | 288 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n"); |
5449c685 FB |
289 | } |
290 | ||
291 | ||
292 | /*+ | |
293 | * | |
294 | * Routine Description: | |
295 | * Rate fallback Algorithm Implementaion | |
296 | * | |
297 | * Parameters: | |
298 | * In: | |
299 | * pDevice - Pointer to the adapter | |
300 | * psNodeDBTable - Pointer to Node Data Base | |
301 | * Out: | |
302 | * none | |
303 | * | |
304 | * Return Value: none | |
305 | * | |
306 | -*/ | |
307 | #define AUTORATE_TXCNT_THRESHOLD 20 | |
308 | #define AUTORATE_INC_THRESHOLD 30 | |
309 | ||
6b35b7b3 | 310 | void |
5449c685 | 311 | RATEvTxRateFallBack ( |
3a215e0f CC |
312 | void *pDeviceHandler, |
313 | PKnownNodeDB psNodeDBTable | |
5449c685 FB |
314 | ) |
315 | { | |
316 | PSDevice pDevice = (PSDevice) pDeviceHandler; | |
2986db5f | 317 | unsigned short wIdxDownRate = 0; |
b6e95cd5 | 318 | unsigned int ii; |
0f4c60d6 | 319 | //unsigned long dwRateTable[MAX_RATE] = {1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54}; |
7b6a0013 | 320 | bool bAutoRate[MAX_RATE] = {true,true,true,true,false,false,true,true,true,true,true,true}; |
0f4c60d6 CC |
321 | unsigned long dwThroughputTbl[MAX_RATE] = {10, 20, 55, 110, 60, 90, 120, 180, 240, 360, 480, 540}; |
322 | unsigned long dwThroughput = 0; | |
2986db5f | 323 | unsigned short wIdxUpRate = 0; |
0f4c60d6 | 324 | unsigned long dwTxDiff = 0; |
5449c685 FB |
325 | |
326 | if (pDevice->pMgmt->eScanState != WMAC_NO_SCANNING) { | |
327 | // Don't do Fallback when scanning Channel | |
328 | return; | |
329 | } | |
330 | ||
331 | psNodeDBTable->uTimeCount ++; | |
332 | ||
333 | if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE]) | |
334 | dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE]; | |
335 | ||
336 | if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) && | |
337 | (dwTxDiff < AUTORATE_TXFAIL_CNT) && | |
338 | (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) { | |
339 | return; | |
340 | } | |
341 | ||
342 | if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) { | |
343 | psNodeDBTable->uTimeCount = 0; | |
344 | } | |
345 | ||
346 | ||
347 | for(ii=0;ii<MAX_RATE;ii++) { | |
348 | if (psNodeDBTable->wSuppRate & (0x0001<<ii)) { | |
1b12068a | 349 | if (bAutoRate[ii] == true) { |
2986db5f | 350 | wIdxUpRate = (unsigned short) ii; |
5449c685 FB |
351 | } |
352 | } else { | |
5a5a2a6a | 353 | bAutoRate[ii] = false; |
5449c685 FB |
354 | } |
355 | } | |
356 | ||
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]; | |
361 | if (ii < RATE_11M) { | |
362 | psNodeDBTable->uTxFail[ii] *= 4; | |
363 | } | |
364 | dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]); | |
365 | } | |
366 | // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n", | |
367 | // ii, psNodeDBTable->uTxOk[ii], psNodeDBTable->uTxFail[ii], dwThroughputTbl[ii]); | |
368 | } | |
369 | dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate]; | |
370 | ||
371 | wIdxDownRate = psNodeDBTable->wTxDataRate; | |
372 | for(ii = psNodeDBTable->wTxDataRate; ii > 0;) { | |
373 | ii--; | |
374 | if ( (dwThroughputTbl[ii] > dwThroughput) && | |
1b12068a | 375 | (bAutoRate[ii]==true) ) { |
5449c685 | 376 | dwThroughput = dwThroughputTbl[ii]; |
2986db5f | 377 | wIdxDownRate = (unsigned short) ii; |
5449c685 FB |
378 | } |
379 | } | |
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; | |
385 | } | |
386 | }else { // adhoc, if uTxOk =0 & uTxFail = 0 | |
387 | if (psNodeDBTable->uTxFail[MAX_RATE] == 0) | |
388 | psNodeDBTable->wTxDataRate = wIdxUpRate; | |
389 | } | |
390 | //2008-5-8 <add> by chester | |
391 | TxRate_iwconfig=psNodeDBTable->wTxDataRate; | |
392 | s_vResetCounter(psNodeDBTable); | |
393 | // DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", psNodeDBTable->wTxDataRate, wIdxUpRate, wIdxDownRate); | |
394 | ||
395 | return; | |
396 | ||
397 | } | |
398 | ||
399 | /*+ | |
400 | * | |
401 | * Description: | |
402 | * This routine is used to assemble available Rate IE. | |
403 | * | |
404 | * Parameters: | |
405 | * In: | |
406 | * pDevice | |
407 | * Out: | |
408 | * | |
409 | * Return Value: None | |
410 | * | |
411 | -*/ | |
3fc9b584 | 412 | unsigned char |
5449c685 | 413 | RATEuSetIE ( |
3a215e0f CC |
414 | PWLAN_IE_SUPP_RATES pSrcRates, |
415 | PWLAN_IE_SUPP_RATES pDstRates, | |
b6e95cd5 | 416 | unsigned int uRateLen |
5449c685 FB |
417 | ) |
418 | { | |
b6e95cd5 | 419 | unsigned int ii, uu, uRateCnt = 0; |
5449c685 FB |
420 | |
421 | if ((pSrcRates == NULL) || (pDstRates == NULL)) | |
422 | return 0; | |
423 | ||
424 | if (pSrcRates->len == 0) | |
425 | return 0; | |
426 | ||
427 | for (ii = 0; ii < uRateLen; ii++) { | |
428 | for (uu = 0; uu < pSrcRates->len; uu++) { | |
429 | if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) { | |
430 | pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu]; | |
431 | break; | |
432 | } | |
433 | } | |
434 | } | |
3fc9b584 | 435 | return (unsigned char)uRateCnt; |
5449c685 FB |
436 | } |
437 |