Staging: add rt2860 wireless driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rt2860 / sta / rtmp_data.c
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 rtmp_data.c
29
30 Abstract:
31 Data path subroutines
32
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
38 */
39 #include "../rt_config.h"
40
41
42
43 VOID STARxEAPOLFrameIndicate(
44 IN PRTMP_ADAPTER pAd,
45 IN MAC_TABLE_ENTRY *pEntry,
46 IN RX_BLK *pRxBlk,
47 IN UCHAR FromWhichBSSID)
48 {
49 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
50 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
51 UCHAR *pTmpBuf;
52
53 #ifdef WPA_SUPPLICANT_SUPPORT
54 if (pAd->StaCfg.WpaSupplicantUP)
55 {
56 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
57 // TBD : process fragmented EAPol frames
58 {
59 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
60 if ( pAd->StaCfg.IEEE8021X == TRUE &&
61 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
62 {
63 PUCHAR Key;
64 UCHAR CipherAlg;
65 int idx = 0;
66
67 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
68 STA_PORT_SECURED(pAd);
69
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
71 {
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
75
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
77 {
78 #ifdef RT2860
79 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
80
81 // Set key material and cipherAlg to Asic
82 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
83
84 // Assign group key info
85 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
86
87 // Assign pairwise key info
88 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
89
90 pAd->IndicateMediaState = NdisMediaStateConnected;
91 pAd->ExtraInfo = GENERAL_LINK_UP;
92 #endif // RT2860 //
93 // For Preventing ShardKey Table is cleared by remove key procedure.
94 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
95 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
96 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
97 pAd->StaCfg.DesireSharedKey[idx].Key,
98 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
99 }
100 }
101 }
102
103 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
104 return;
105 }
106 }
107 else
108 #endif // WPA_SUPPLICANT_SUPPORT //
109 {
110 // Special DATA frame that has to pass to MLME
111 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
112 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
113 {
114 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
115 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
116 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
117 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
118 }
119 }
120
121 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
122 return;
123
124 }
125
126 VOID STARxDataFrameAnnounce(
127 IN PRTMP_ADAPTER pAd,
128 IN MAC_TABLE_ENTRY *pEntry,
129 IN RX_BLK *pRxBlk,
130 IN UCHAR FromWhichBSSID)
131 {
132
133 // non-EAP frame
134 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
135 {
136 {
137 // drop all non-EAP DATA frame before
138 // this client's Port-Access-Control is secured
139 if (pRxBlk->pHeader->FC.Wep)
140 {
141 // unsupported cipher suite
142 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
143 {
144 // release packet
145 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
146 return;
147 }
148 }
149 else
150 {
151 // encryption in-use but receive a non-EAPOL clear text frame, drop it
152 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
153 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
154 {
155 // release packet
156 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
157 return;
158 }
159 }
160 }
161 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
162 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
163 {
164 // Normal legacy, AMPDU or AMSDU
165 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
166
167 }
168 else
169 {
170 // ARALINK
171 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
172 }
173 #ifdef QOS_DLS_SUPPORT
174 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
175 #endif // QOS_DLS_SUPPORT //
176 }
177 else
178 {
179 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
180 #ifdef DOT11_N_SUPPORT
181 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
182 {
183 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
184 }
185 else
186 #endif // DOT11_N_SUPPORT //
187 {
188 // Determin the destination of the EAP frame
189 // to WPA state machine or upper layer
190 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
191 }
192 }
193 }
194
195
196 // For TKIP frame, calculate the MIC value
197 BOOLEAN STACheckTkipMICValue(
198 IN PRTMP_ADAPTER pAd,
199 IN MAC_TABLE_ENTRY *pEntry,
200 IN RX_BLK *pRxBlk)
201 {
202 PHEADER_802_11 pHeader = pRxBlk->pHeader;
203 UCHAR *pData = pRxBlk->pData;
204 USHORT DataSize = pRxBlk->DataSize;
205 UCHAR UserPriority = pRxBlk->UserPriority;
206 PCIPHER_KEY pWpaKey;
207 UCHAR *pDA, *pSA;
208
209 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
210
211 pDA = pHeader->Addr1;
212 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
213 {
214 pSA = pHeader->Addr3;
215 }
216 else
217 {
218 pSA = pHeader->Addr2;
219 }
220
221 if (RTMPTkipCompareMICValue(pAd,
222 pData,
223 pDA,
224 pSA,
225 pWpaKey->RxMic,
226 UserPriority,
227 DataSize) == FALSE)
228 {
229 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
230
231 #ifdef WPA_SUPPLICANT_SUPPORT
232 if (pAd->StaCfg.WpaSupplicantUP)
233 {
234 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
235 }
236 else
237 #endif // WPA_SUPPLICANT_SUPPORT //
238 {
239 RTMPReportMicError(pAd, pWpaKey);
240 }
241
242 // release packet
243 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
244 return FALSE;
245 }
246
247 return TRUE;
248 }
249
250
251 //
252 // All Rx routines use RX_BLK structure to hande rx events
253 // It is very important to build pRxBlk attributes
254 // 1. pHeader pointer to 802.11 Header
255 // 2. pData pointer to payload including LLC (just skip Header)
256 // 3. set payload size including LLC to DataSize
257 // 4. set some flags with RX_BLK_SET_FLAG()
258 //
259 VOID STAHandleRxDataFrame(
260 IN PRTMP_ADAPTER pAd,
261 IN RX_BLK *pRxBlk)
262 {
263 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
264 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
265 PHEADER_802_11 pHeader = pRxBlk->pHeader;
266 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
267 BOOLEAN bFragment = FALSE;
268 MAC_TABLE_ENTRY *pEntry = NULL;
269 UCHAR FromWhichBSSID = BSS0;
270 UCHAR UserPriority = 0;
271
272 {
273 // before LINK UP, all DATA frames are rejected
274 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
275 {
276 // release packet
277 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
278 return;
279 }
280
281 #ifdef QOS_DLS_SUPPORT
282 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
283 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
284 {
285 return;
286 }
287 #endif // QOS_DLS_SUPPORT //
288
289 // Drop not my BSS frames
290 if (pRxD->MyBss == 0)
291 {
292 {
293 // release packet
294 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
295 return;
296 }
297 }
298
299 pAd->RalinkCounters.RxCountSinceLastNULL++;
300 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
301 {
302 UCHAR *pData;
303 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
304
305 // Qos bit 4
306 pData = (PUCHAR)pHeader + LENGTH_802_11;
307 if ((*pData >> 4) & 0x01)
308 {
309 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
310 pAd->CommonCfg.bInServicePeriod = FALSE;
311
312 // Force driver to fall into sleep mode when rcv EOSP frame
313 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
314 {
315 USHORT TbttNumToNextWakeUp;
316 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
317 ULONG Now;
318
319 NdisGetSystemUpTime(&Now);
320 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
321
322 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
323 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
324 TbttNumToNextWakeUp = NextDtim;
325
326 MlmeSetPsmBit(pAd, PWR_SAVE);
327 // if WMM-APSD is failed, try to disable following line
328 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
329 }
330 }
331
332 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
333 {
334 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
335 }
336 }
337
338 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
339 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
340 {
341 // release packet
342 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
343 return;
344 }
345
346 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
347 #ifdef QOS_DLS_SUPPORT
348 if (!pAd->CommonCfg.bDLSCapable)
349 {
350 #endif // QOS_DLS_SUPPORT //
351 if (INFRA_ON(pAd))
352 {
353 // Infrastructure mode, check address 2 for BSSID
354 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
355 {
356 // Receive frame not my BSSID
357 // release packet
358 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
359 return;
360 }
361 }
362 else // Ad-Hoc mode or Not associated
363 {
364 // Ad-Hoc mode, check address 3 for BSSID
365 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
366 {
367 // Receive frame not my BSSID
368 // release packet
369 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
370 return;
371 }
372 }
373 #ifdef QOS_DLS_SUPPORT
374 }
375 #endif // QOS_DLS_SUPPORT //
376
377 //
378 // find pEntry
379 //
380 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
381 {
382 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
383 }
384 else
385 {
386 // 1. release packet if infra mode
387 // 2. new a pEntry if ad-hoc mode
388 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
389 return;
390 }
391
392 // infra or ad-hoc
393 if (INFRA_ON(pAd))
394 {
395 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
396 #ifdef QOS_DLS_SUPPORT
397 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
398 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
399 else
400 #endif // QOS_DLS_SUPPORT //
401 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
402 }
403
404 // check Atheros Client
405 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
406 {
407 pEntry->bIAmBadAtheros = TRUE;
408 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
409 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
410 if (!STA_AES_ON(pAd))
411 {
412 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
413 }
414 }
415 }
416
417 pRxBlk->pData = (UCHAR *)pHeader;
418
419 //
420 // update RxBlk->pData, DataSize
421 // 802.11 Header, QOS, HTC, Hw Padding
422 //
423
424 // 1. skip 802.11 HEADER
425 {
426 pRxBlk->pData += LENGTH_802_11;
427 pRxBlk->DataSize -= LENGTH_802_11;
428 }
429
430 // 2. QOS
431 if (pHeader->FC.SubType & 0x08)
432 {
433 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
434 UserPriority = *(pRxBlk->pData) & 0x0f;
435 // bit 7 in QoS Control field signals the HT A-MSDU format
436 if ((*pRxBlk->pData) & 0x80)
437 {
438 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
439 }
440
441 // skip QOS contorl field
442 pRxBlk->pData += 2;
443 pRxBlk->DataSize -=2;
444 }
445 pRxBlk->UserPriority = UserPriority;
446
447 // 3. Order bit: A-Ralink or HTC+
448 if (pHeader->FC.Order)
449 {
450 #ifdef AGGREGATION_SUPPORT
451 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
452 {
453 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
454 }
455 else
456 #endif
457 {
458 #ifdef DOT11_N_SUPPORT
459 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
460 // skip HTC contorl field
461 pRxBlk->pData += 4;
462 pRxBlk->DataSize -= 4;
463 #endif // DOT11_N_SUPPORT //
464 }
465 }
466
467 // 4. skip HW padding
468 if (pRxD->L2PAD)
469 {
470 // just move pData pointer
471 // because DataSize excluding HW padding
472 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
473 pRxBlk->pData += 2;
474 }
475
476 #ifdef DOT11_N_SUPPORT
477 if (pRxD->BA)
478 {
479 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
480 }
481 #endif // DOT11_N_SUPPORT //
482
483
484 //
485 // Case I Process Broadcast & Multicast data frame
486 //
487 if (pRxD->Bcast || pRxD->Mcast)
488 {
489 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
490
491 // Drop Mcast/Bcast frame with fragment bit on
492 if (pHeader->FC.MoreFrag)
493 {
494 // release packet
495 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
496 return;
497 }
498
499 // Filter out Bcast frame which AP relayed for us
500 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
501 {
502 // release packet
503 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
504 return;
505 }
506
507 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
508 return;
509 }
510 else if (pRxD->U2M)
511 {
512 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
513
514
515 #ifdef QOS_DLS_SUPPORT
516 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
517 {
518 MAC_TABLE_ENTRY *pDlsEntry = NULL;
519
520 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
521 if(pDlsEntry)
522 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
523 }
524 else
525 #endif // QOS_DLS_SUPPORT //
526 if (ADHOC_ON(pAd))
527 {
528 pEntry = MacTableLookup(pAd, pHeader->Addr2);
529 if (pEntry)
530 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
531 }
532
533
534 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
535
536 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
537 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
538
539 pAd->RalinkCounters.OneSecRxOkDataCnt++;
540
541
542 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
543 {
544 // re-assemble the fragmented packets
545 // return complete frame (pRxPacket) or NULL
546 bFragment = TRUE;
547 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
548 }
549
550 if (pRxPacket)
551 {
552 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
553
554 // process complete frame
555 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
556 {
557 // Minus MIC length
558 pRxBlk->DataSize -= 8;
559
560 // For TKIP frame, calculate the MIC value
561 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
562 {
563 return;
564 }
565 }
566
567 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
568 return;
569 }
570 else
571 {
572 // just return
573 // because RTMPDeFragmentDataFrame() will release rx packet,
574 // if packet is fragmented
575 return;
576 }
577 }
578
579 ASSERT(0);
580 // release packet
581 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
582 }
583
584 VOID STAHandleRxMgmtFrame(
585 IN PRTMP_ADAPTER pAd,
586 IN RX_BLK *pRxBlk)
587 {
588 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
589 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
590 PHEADER_802_11 pHeader = pRxBlk->pHeader;
591 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
592
593 do
594 {
595
596 // We should collect RSSI not only U2M data but also my beacon
597 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
598 {
599 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
600
601 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
602 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
603 }
604
605 // First check the size, it MUST not exceed the mlme queue size
606 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
607 {
608 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
609 break;
610 }
611
612 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
613 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
614 } while (FALSE);
615
616 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
617 }
618
619 VOID STAHandleRxControlFrame(
620 IN PRTMP_ADAPTER pAd,
621 IN RX_BLK *pRxBlk)
622 {
623 #ifdef DOT11_N_SUPPORT
624 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
625 #endif // DOT11_N_SUPPORT //
626 PHEADER_802_11 pHeader = pRxBlk->pHeader;
627 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
628
629 switch (pHeader->FC.SubType)
630 {
631 case SUBTYPE_BLOCK_ACK_REQ:
632 #ifdef DOT11_N_SUPPORT
633 {
634 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
635 }
636 break;
637 #endif // DOT11_N_SUPPORT //
638 case SUBTYPE_BLOCK_ACK:
639 case SUBTYPE_ACK:
640 default:
641 break;
642 }
643
644 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
645 }
646
647
648 /*
649 ========================================================================
650
651 Routine Description:
652 Process RxDone interrupt, running in DPC level
653
654 Arguments:
655 pAd Pointer to our adapter
656
657 Return Value:
658 None
659
660 IRQL = DISPATCH_LEVEL
661
662 Note:
663 This routine has to maintain Rx ring read pointer.
664 Need to consider QOS DATA format when converting to 802.3
665 ========================================================================
666 */
667 BOOLEAN STARxDoneInterruptHandle(
668 IN PRTMP_ADAPTER pAd,
669 IN BOOLEAN argc)
670 {
671 NDIS_STATUS Status;
672 UINT32 RxProcessed, RxPending;
673 BOOLEAN bReschedule = FALSE;
674 RT28XX_RXD_STRUC *pRxD;
675 UCHAR *pData;
676 PRXWI_STRUC pRxWI;
677 PNDIS_PACKET pRxPacket;
678 PHEADER_802_11 pHeader;
679 RX_BLK RxCell;
680
681 RxProcessed = RxPending = 0;
682
683 // process whole rx ring
684 while (1)
685 {
686
687 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
688 fRTMP_ADAPTER_RESET_IN_PROGRESS |
689 fRTMP_ADAPTER_HALT_IN_PROGRESS |
690 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
691 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
692 {
693 break;
694 }
695
696 #ifdef RT2860
697 if (RxProcessed++ > MAX_RX_PROCESS_CNT)
698 {
699 // need to reschedule rx handle
700 bReschedule = TRUE;
701 break;
702 }
703 #endif // RT2860 //
704
705 RxProcessed ++; // test
706
707 // 1. allocate a new data packet into rx ring to replace received packet
708 // then processing the received packet
709 // 2. the callee must take charge of release of packet
710 // 3. As far as driver is concerned ,
711 // the rx packet must
712 // a. be indicated to upper layer or
713 // b. be released if it is discarded
714 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
715 if (pRxPacket == NULL)
716 {
717 // no more packet to process
718 break;
719 }
720
721 // get rx ring descriptor
722 pRxD = &(RxCell.RxD);
723 // get rx data buffer
724 pData = GET_OS_PKT_DATAPTR(pRxPacket);
725 pRxWI = (PRXWI_STRUC) pData;
726 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
727
728 #ifdef RT_BIG_ENDIAN
729 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
730 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
731 #endif
732
733 // build RxCell
734 RxCell.pRxWI = pRxWI;
735 RxCell.pHeader = pHeader;
736 RxCell.pRxPacket = pRxPacket;
737 RxCell.pData = (UCHAR *) pHeader;
738 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
739 RxCell.Flags = 0;
740
741 // Increase Total receive byte counter after real data received no mater any error or not
742 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
743 pAd->RalinkCounters.RxCount ++;
744
745 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
746
747 if (pRxWI->MPDUtotalByteCount < 14)
748 Status = NDIS_STATUS_FAILURE;
749
750 if (MONITOR_ON(pAd))
751 {
752 send_monitor_packets(pAd, &RxCell);
753 break;
754 }
755 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
756 #ifdef RALINK_ATE
757 if (ATE_ON(pAd))
758 {
759 pAd->ate.RxCntPerSec++;
760 ATESampleRssi(pAd, pRxWI);
761 #ifdef RALINK_28xx_QA
762 if (pAd->ate.bQARxStart == TRUE)
763 {
764 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
765 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
766 }
767 #endif // RALINK_28xx_QA //
768 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
769 continue;
770 }
771 #endif // RALINK_ATE //
772
773 // Check for all RxD errors
774 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
775
776 // Handle the received frame
777 if (Status == NDIS_STATUS_SUCCESS)
778 {
779 switch (pHeader->FC.Type)
780 {
781 // CASE I, receive a DATA frame
782 case BTYPE_DATA:
783 {
784 // process DATA frame
785 STAHandleRxDataFrame(pAd, &RxCell);
786 }
787 break;
788 // CASE II, receive a MGMT frame
789 case BTYPE_MGMT:
790 {
791 STAHandleRxMgmtFrame(pAd, &RxCell);
792 }
793 break;
794 // CASE III. receive a CNTL frame
795 case BTYPE_CNTL:
796 {
797 STAHandleRxControlFrame(pAd, &RxCell);
798 }
799 break;
800 // discard other type
801 default:
802 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
803 break;
804 }
805 }
806 else
807 {
808 pAd->Counters8023.RxErrors++;
809 // discard this frame
810 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
811 }
812 }
813
814 return bReschedule;
815 }
816
817 /*
818 ========================================================================
819
820 Routine Description:
821 Arguments:
822 pAd Pointer to our adapter
823
824 IRQL = DISPATCH_LEVEL
825
826 ========================================================================
827 */
828 VOID RTMPHandleTwakeupInterrupt(
829 IN PRTMP_ADAPTER pAd)
830 {
831 AsicForceWakeup(pAd, FALSE);
832 }
833
834 /*
835 ========================================================================
836 Routine Description:
837 Early checking and OS-depened parsing for Tx packet send to our STA driver.
838
839 Arguments:
840 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
841 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
842 UINT NumberOfPackets Number of packet in packet array.
843
844 Return Value:
845 NONE
846
847 Note:
848 This function do early checking and classification for send-out packet.
849 You only can put OS-depened & STA related code in here.
850 ========================================================================
851 */
852 VOID STASendPackets(
853 IN NDIS_HANDLE MiniportAdapterContext,
854 IN PPNDIS_PACKET ppPacketArray,
855 IN UINT NumberOfPackets)
856 {
857 UINT Index;
858 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
859 PNDIS_PACKET pPacket;
860 BOOLEAN allowToSend = FALSE;
861
862
863 for (Index = 0; Index < NumberOfPackets; Index++)
864 {
865 pPacket = ppPacketArray[Index];
866
867 do
868 {
869 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
870 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
871 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
872 {
873 // Drop send request since hardware is in reset state
874 break;
875 }
876 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
877 {
878 // Drop send request since there are no physical connection yet
879 break;
880 }
881 else
882 {
883 // Record that orignal packet source is from NDIS layer,so that
884 // later on driver knows how to release this NDIS PACKET
885 #ifdef QOS_DLS_SUPPORT
886 MAC_TABLE_ENTRY *pEntry;
887 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
888
889 pEntry = MacTableLookup(pAd, pSrcBufVA);
890 if (pEntry && (pEntry->ValidAsDls == TRUE))
891 {
892 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
893 }
894 else
895 #endif // QOS_DLS_SUPPORT //
896 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
897 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
898 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
899 pAd->RalinkCounters.PendingNdisPacketCount++;
900
901 allowToSend = TRUE;
902 }
903 } while(FALSE);
904
905 if (allowToSend == TRUE)
906 STASendPacket(pAd, pPacket);
907 else
908 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
909 }
910
911 // Dequeue outgoing frames from TxSwQueue[] and process it
912 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
913
914 }
915
916
917 /*
918 ========================================================================
919 Routine Description:
920 This routine is used to do packet parsing and classification for Tx packet
921 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
922 class.
923
924 Arguments:
925 pAd Pointer to our adapter
926 pPacket Pointer to send packet
927
928 Return Value:
929 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
930 NDIS_STATUS_FAILURE If failed to do en-queue.
931
932 Note:
933 You only can put OS-indepened & STA related code in here.
934 ========================================================================
935 */
936 NDIS_STATUS STASendPacket(
937 IN PRTMP_ADAPTER pAd,
938 IN PNDIS_PACKET pPacket)
939 {
940 PACKET_INFO PacketInfo;
941 PUCHAR pSrcBufVA;
942 UINT SrcBufLen;
943 UINT AllowFragSize;
944 UCHAR NumberOfFrag;
945 UCHAR QueIdx, UserPriority;
946 MAC_TABLE_ENTRY *pEntry = NULL;
947 unsigned int IrqFlags;
948 UCHAR FlgIsIP = 0;
949 UCHAR Rate;
950
951 // Prepare packet information structure for buffer descriptor
952 // chained within a single NDIS packet.
953 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
954
955 if (pSrcBufVA == NULL)
956 {
957 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
958 // Resourece is low, system did not allocate virtual address
959 // return NDIS_STATUS_FAILURE directly to upper layer
960 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
961 return NDIS_STATUS_FAILURE;
962 }
963
964
965 if (SrcBufLen < 14)
966 {
967 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
968 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
969 return (NDIS_STATUS_FAILURE);
970 }
971
972 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
973 // Note multicast packets in adhoc also use BSSID_WCID index.
974 {
975 if(INFRA_ON(pAd))
976 {
977 #ifdef QOS_DLS_SUPPORT
978 USHORT tmpWcid;
979
980 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
981 if (VALID_WCID(tmpWcid) &&
982 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
983 {
984 pEntry = &pAd->MacTab.Content[tmpWcid];
985 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
986 }
987 else
988 #endif // QOS_DLS_SUPPORT //
989 {
990 pEntry = &pAd->MacTab.Content[BSSID_WCID];
991 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
992 Rate = pAd->CommonCfg.TxRate;
993 }
994 }
995 else if (ADHOC_ON(pAd))
996 {
997 if (*pSrcBufVA & 0x01)
998 {
999 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1000 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1001 }
1002 else
1003 {
1004 pEntry = MacTableLookup(pAd, pSrcBufVA);
1005 }
1006 Rate = pAd->CommonCfg.TxRate;
1007 }
1008 }
1009
1010 if (!pEntry)
1011 {
1012 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1013 // Resourece is low, system did not allocate virtual address
1014 // return NDIS_STATUS_FAILURE directly to upper layer
1015 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1016 return NDIS_STATUS_FAILURE;
1017 }
1018
1019 if (ADHOC_ON(pAd)
1020 )
1021 {
1022 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1023 }
1024
1025 //
1026 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1027 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1028 RTMPCheckEtherType(pAd, pPacket);
1029
1030
1031
1032 //
1033 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1034 //
1035 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1036 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1037 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1038 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1039 #ifdef WPA_SUPPLICANT_SUPPORT
1040 || (pAd->StaCfg.IEEE8021X == TRUE)
1041 #endif // WPA_SUPPLICANT_SUPPORT //
1042 #ifdef LEAP_SUPPORT
1043 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1044 #endif // LEAP_SUPPORT //
1045 )
1046 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1047 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1048 )
1049 {
1050 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1051 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1052
1053 return (NDIS_STATUS_FAILURE);
1054 }
1055
1056
1057 // STEP 1. Decide number of fragments required to deliver this MSDU.
1058 // The estimation here is not very accurate because difficult to
1059 // take encryption overhead into consideration here. The result
1060 // "NumberOfFrag" is then just used to pre-check if enough free
1061 // TXD are available to hold this MSDU.
1062
1063
1064 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1065 NumberOfFrag = 1;
1066 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1067 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1068 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1069 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1070 #ifdef DOT11_N_SUPPORT
1071 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1072 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1073 #endif // DOT11_N_SUPPORT //
1074 else
1075 {
1076 // The calculated "NumberOfFrag" is a rough estimation because of various
1077 // encryption/encapsulation overhead not taken into consideration. This number is just
1078 // used to make sure enough free TXD are available before fragmentation takes place.
1079 // In case the actual required number of fragments of an NDIS packet
1080 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1081 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1082 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1083 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1084
1085 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1086 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1087 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1088 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1089 {
1090 NumberOfFrag--;
1091 }
1092 }
1093
1094 // Save fragment number to Ndis packet reserved field
1095 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1096
1097
1098 // STEP 2. Check the requirement of RTS:
1099 // If multiple fragment required, RTS is required only for the first fragment
1100 // if the fragment size large than RTS threshold
1101 // For RT28xx, Let ASIC send RTS/CTS
1102 RTMP_SET_PACKET_RTS(pPacket, 0);
1103 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1104
1105 //
1106 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1107 //
1108 UserPriority = 0;
1109 QueIdx = QID_AC_BE;
1110 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1111 {
1112 USHORT Protocol;
1113 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1114 do
1115 {
1116 // get Ethernet protocol field
1117 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1118 if (Protocol <= 1500)
1119 {
1120 // get Ethernet protocol field from LLC/SNAP
1121 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1122 break;
1123
1124 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1125 LlcSnapLen = 8;
1126 }
1127
1128 // always AC_BE for non-IP packet
1129 if (Protocol != 0x0800)
1130 break;
1131
1132 // get IP header
1133 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1134 break;
1135
1136 // return AC_BE if packet is not IPv4
1137 if ((Byte0 & 0xf0) != 0x40)
1138 break;
1139
1140 FlgIsIP = 1;
1141 UserPriority = (Byte1 & 0xe0) >> 5;
1142 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1143
1144 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1145 // TODO: downgrade UP & QueIdx before passing ACM
1146 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1147 {
1148 UserPriority = 0;
1149 QueIdx = QID_AC_BE;
1150 }
1151 } while (FALSE);
1152 }
1153
1154 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1155
1156
1157
1158 // Make sure SendTxWait queue resource won't be used by other threads
1159 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1160 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1161 {
1162 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1163 #ifdef BLOCK_NET_IF
1164 StopNetIfQueue(pAd, QueIdx, pPacket);
1165 #endif // BLOCK_NET_IF //
1166 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1167
1168 return NDIS_STATUS_FAILURE;
1169 }
1170 else
1171 {
1172 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1173 }
1174 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1175
1176 #ifdef DOT11_N_SUPPORT
1177 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1178 (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1179 {
1180 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1181 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1182 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1183 // For IOT compatibility, if
1184 // 1. It is Ralink chip or
1185 // 2. It is OPEN or AES mode,
1186 // then BA session can be bulit.
1187 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1188 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1189 )
1190 {
1191 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1192 }
1193 }
1194 #endif // DOT11_N_SUPPORT //
1195
1196 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1197 return NDIS_STATUS_SUCCESS;
1198 }
1199
1200
1201 /*
1202 ========================================================================
1203
1204 Routine Description:
1205 This subroutine will scan through releative ring descriptor to find
1206 out avaliable free ring descriptor and compare with request size.
1207
1208 Arguments:
1209 pAd Pointer to our adapter
1210 QueIdx Selected TX Ring
1211
1212 Return Value:
1213 NDIS_STATUS_FAILURE Not enough free descriptor
1214 NDIS_STATUS_SUCCESS Enough free descriptor
1215
1216 IRQL = PASSIVE_LEVEL
1217 IRQL = DISPATCH_LEVEL
1218
1219 Note:
1220
1221 ========================================================================
1222 */
1223 #ifdef RT2860
1224 NDIS_STATUS RTMPFreeTXDRequest(
1225 IN PRTMP_ADAPTER pAd,
1226 IN UCHAR QueIdx,
1227 IN UCHAR NumberRequired,
1228 IN PUCHAR FreeNumberIs)
1229 {
1230 ULONG FreeNumber = 0;
1231 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1232
1233 switch (QueIdx)
1234 {
1235 case QID_AC_BK:
1236 case QID_AC_BE:
1237 case QID_AC_VI:
1238 case QID_AC_VO:
1239 case QID_HCCA:
1240 if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
1241 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1242 else
1243 FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
1244
1245 if (FreeNumber >= NumberRequired)
1246 Status = NDIS_STATUS_SUCCESS;
1247 break;
1248
1249 case QID_MGMT:
1250 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1251 FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
1252 else
1253 FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
1254
1255 if (FreeNumber >= NumberRequired)
1256 Status = NDIS_STATUS_SUCCESS;
1257 break;
1258
1259 default:
1260 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1261 break;
1262 }
1263 *FreeNumberIs = (UCHAR)FreeNumber;
1264
1265 return (Status);
1266 }
1267 #endif // RT2860 //
1268
1269
1270
1271 VOID RTMPSendDisassociationFrame(
1272 IN PRTMP_ADAPTER pAd)
1273 {
1274 }
1275
1276 VOID RTMPSendNullFrame(
1277 IN PRTMP_ADAPTER pAd,
1278 IN UCHAR TxRate,
1279 IN BOOLEAN bQosNull)
1280 {
1281 UCHAR NullFrame[48];
1282 ULONG Length;
1283 PHEADER_802_11 pHeader_802_11;
1284
1285
1286 #ifdef RALINK_ATE
1287 if(ATE_ON(pAd))
1288 {
1289 return;
1290 }
1291 #endif // RALINK_ATE //
1292
1293 // WPA 802.1x secured port control
1294 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1295 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1296 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1297 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1298 #ifdef WPA_SUPPLICANT_SUPPORT
1299 || (pAd->StaCfg.IEEE8021X == TRUE)
1300 #endif
1301 ) &&
1302 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1303 {
1304 return;
1305 }
1306
1307 NdisZeroMemory(NullFrame, 48);
1308 Length = sizeof(HEADER_802_11);
1309
1310 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1311
1312 pHeader_802_11->FC.Type = BTYPE_DATA;
1313 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1314 pHeader_802_11->FC.ToDs = 1;
1315 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1316 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1317 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1318
1319 if (pAd->CommonCfg.bAPSDForcePowerSave)
1320 {
1321 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1322 }
1323 else
1324 {
1325 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1326 }
1327 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1328
1329 pAd->Sequence++;
1330 pHeader_802_11->Sequence = pAd->Sequence;
1331
1332 // Prepare QosNull function frame
1333 if (bQosNull)
1334 {
1335 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1336
1337 // copy QOS control bytes
1338 NullFrame[Length] = 0;
1339 NullFrame[Length+1] = 0;
1340 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1341 }
1342
1343 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1344
1345 }
1346
1347 // IRQL = DISPATCH_LEVEL
1348 VOID RTMPSendRTSFrame(
1349 IN PRTMP_ADAPTER pAd,
1350 IN PUCHAR pDA,
1351 IN unsigned int NextMpduSize,
1352 IN UCHAR TxRate,
1353 IN UCHAR RTSRate,
1354 IN USHORT AckDuration,
1355 IN UCHAR QueIdx,
1356 IN UCHAR FrameGap)
1357 {
1358 }
1359
1360
1361
1362 // --------------------------------------------------------
1363 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1364 // Find the WPA key, either Group or Pairwise Key
1365 // LEAP + TKIP also use WPA key.
1366 // --------------------------------------------------------
1367 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1368 // In Cisco CCX 2.0 Leap Authentication
1369 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1370 // Instead of the SharedKey, SharedKey Length may be Zero.
1371 VOID STAFindCipherAlgorithm(
1372 IN PRTMP_ADAPTER pAd,
1373 IN TX_BLK *pTxBlk)
1374 {
1375 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1376 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1377 UCHAR KeyIdx = 0xff;
1378 PUCHAR pSrcBufVA;
1379 PCIPHER_KEY pKey = NULL;
1380
1381 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1382
1383 {
1384 // Select Cipher
1385 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1386 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1387 else
1388 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1389
1390 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1391 {
1392 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1393
1394 // 4-way handshaking frame must be clear
1395 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1396 (pAd->SharedKey[BSS0][0].KeyLen))
1397 {
1398 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1399 KeyIdx = 0;
1400 }
1401 }
1402 else if (Cipher == Ndis802_11Encryption1Enabled)
1403 {
1404 #ifdef LEAP_SUPPORT
1405 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1406 {
1407 if (LEAP_CCKM_ON(pAd))
1408 {
1409 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1410 KeyIdx = 1;
1411 else
1412 KeyIdx = 0;
1413 }
1414 else
1415 KeyIdx = pAd->StaCfg.DefaultKeyId;
1416 }
1417 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1418 KeyIdx = pAd->StaCfg.DefaultKeyId;
1419 else if (LEAP_CCKM_ON(pAd))
1420 {
1421 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1422 KeyIdx = 1;
1423 else
1424 KeyIdx = 0;
1425 }
1426 else // standard WEP64 or WEP128
1427 #endif // LEAP_SUPPORT //
1428 KeyIdx = pAd->StaCfg.DefaultKeyId;
1429 }
1430 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1431 (Cipher == Ndis802_11Encryption3Enabled))
1432 {
1433 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1434 KeyIdx = pAd->StaCfg.DefaultKeyId;
1435 else if (pAd->SharedKey[BSS0][0].KeyLen)
1436 KeyIdx = 0;
1437 else
1438 KeyIdx = pAd->StaCfg.DefaultKeyId;
1439 }
1440
1441 if (KeyIdx == 0xff)
1442 CipherAlg = CIPHER_NONE;
1443 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1444 CipherAlg = CIPHER_NONE;
1445 #ifdef WPA_SUPPLICANT_SUPPORT
1446 else if ( pAd->StaCfg.WpaSupplicantUP &&
1447 (Cipher == Ndis802_11Encryption1Enabled) &&
1448 (pAd->StaCfg.IEEE8021X == TRUE) &&
1449 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1450 CipherAlg = CIPHER_NONE;
1451 #endif // WPA_SUPPLICANT_SUPPORT //
1452 else
1453 {
1454 //Header_802_11.FC.Wep = 1;
1455 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1456 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1457 }
1458 }
1459
1460 pTxBlk->CipherAlg = CipherAlg;
1461 pTxBlk->pKey = pKey;
1462 }
1463
1464
1465 VOID STABuildCommon802_11Header(
1466 IN PRTMP_ADAPTER pAd,
1467 IN TX_BLK *pTxBlk)
1468 {
1469
1470 HEADER_802_11 *pHeader_802_11;
1471 #ifdef QOS_DLS_SUPPORT
1472 BOOLEAN bDLSFrame = FALSE;
1473 INT DlsEntryIndex = 0;
1474 #endif // QOS_DLS_SUPPORT //
1475
1476 //
1477 // MAKE A COMMON 802.11 HEADER
1478 //
1479
1480 // normal wlan header size : 24 octets
1481 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1482
1483 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1484
1485 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1486
1487 pHeader_802_11->FC.FrDs = 0;
1488 pHeader_802_11->FC.Type = BTYPE_DATA;
1489 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1490
1491 #ifdef QOS_DLS_SUPPORT
1492 if (INFRA_ON(pAd))
1493 {
1494 // Check if the frame can be sent through DLS direct link interface
1495 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1496 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1497 if (DlsEntryIndex >= 0)
1498 bDLSFrame = TRUE;
1499 else
1500 bDLSFrame = FALSE;
1501 }
1502 #endif // QOS_DLS_SUPPORT //
1503
1504 if (pTxBlk->pMacEntry)
1505 {
1506 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1507 {
1508 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1509 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1510 }
1511 else
1512 {
1513 #ifdef QOS_DLS_SUPPORT
1514 if (bDLSFrame)
1515 {
1516 pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
1517 pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
1518 }
1519 else
1520 #endif // QOS_DLS_SUPPORT //
1521 {
1522 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1523 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1524 }
1525 }
1526 }
1527 else
1528 {
1529 pHeader_802_11->Sequence = pAd->Sequence;
1530 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1531 }
1532
1533 pHeader_802_11->Frag = 0;
1534
1535 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1536
1537 {
1538 if (INFRA_ON(pAd))
1539 {
1540 #ifdef QOS_DLS_SUPPORT
1541 if (bDLSFrame)
1542 {
1543 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1544 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1545 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1546 pHeader_802_11->FC.ToDs = 0;
1547 }
1548 else
1549 #endif // QOS_DLS_SUPPORT //
1550 {
1551 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1552 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1553 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1554 pHeader_802_11->FC.ToDs = 1;
1555 }
1556 }
1557 else if (ADHOC_ON(pAd))
1558 {
1559 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1560 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1561 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1562 pHeader_802_11->FC.ToDs = 0;
1563 }
1564 }
1565
1566 if (pTxBlk->CipherAlg != CIPHER_NONE)
1567 pHeader_802_11->FC.Wep = 1;
1568
1569 // -----------------------------------------------------------------
1570 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1571 // -----------------------------------------------------------------
1572 if (pAd->CommonCfg.bAPSDForcePowerSave)
1573 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1574 else
1575 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1576 }
1577
1578 #ifdef DOT11_N_SUPPORT
1579 VOID STABuildCache802_11Header(
1580 IN RTMP_ADAPTER *pAd,
1581 IN TX_BLK *pTxBlk,
1582 IN UCHAR *pHeader)
1583 {
1584 MAC_TABLE_ENTRY *pMacEntry;
1585 PHEADER_802_11 pHeader80211;
1586
1587 pHeader80211 = (PHEADER_802_11)pHeader;
1588 pMacEntry = pTxBlk->pMacEntry;
1589
1590 //
1591 // Update the cached 802.11 HEADER
1592 //
1593
1594 // normal wlan header size : 24 octets
1595 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1596
1597 // More Bit
1598 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1599
1600 // Sequence
1601 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1602 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1603
1604 {
1605 // Check if the frame can be sent through DLS direct link interface
1606 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1607 #ifdef QOS_DLS_SUPPORT
1608 BOOLEAN bDLSFrame = FALSE;
1609 INT DlsEntryIndex = 0;
1610
1611 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1612 if (DlsEntryIndex >= 0)
1613 bDLSFrame = TRUE;
1614 else
1615 bDLSFrame = FALSE;
1616 #endif // QOS_DLS_SUPPORT //
1617
1618 // The addr3 of normal packet send from DS is Dest Mac address.
1619 #ifdef QOS_DLS_SUPPORT
1620 if (bDLSFrame)
1621 {
1622 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1623 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1624 pHeader80211->FC.ToDs = 0;
1625 }
1626 else
1627 #endif // QOS_DLS_SUPPORT //
1628 if (ADHOC_ON(pAd))
1629 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1630 else
1631 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1632 }
1633
1634 // -----------------------------------------------------------------
1635 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1636 // -----------------------------------------------------------------
1637 if (pAd->CommonCfg.bAPSDForcePowerSave)
1638 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1639 else
1640 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1641 }
1642 #endif // DOT11_N_SUPPORT //
1643
1644 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1645 IN RTMP_ADAPTER *pAd,
1646 IN TX_BLK *pTxBlk)
1647 {
1648 PUCHAR pHeaderBufPtr;
1649 HEADER_802_11 *pHeader_802_11;
1650 PNDIS_PACKET pNextPacket;
1651 UINT32 nextBufLen;
1652 PQUEUE_ENTRY pQEntry;
1653
1654 STAFindCipherAlgorithm(pAd, pTxBlk);
1655 STABuildCommon802_11Header(pAd, pTxBlk);
1656
1657
1658 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1659 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1660
1661 // steal "order" bit to mark "aggregation"
1662 pHeader_802_11->FC.Order = 1;
1663
1664 // skip common header
1665 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1666
1667 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1668 {
1669 //
1670 // build QOS Control bytes
1671 //
1672 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1673
1674 *(pHeaderBufPtr+1) = 0;
1675 pHeaderBufPtr +=2;
1676 pTxBlk->MpduHeaderLen += 2;
1677 }
1678
1679 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1680 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1681 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1682 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1683
1684 // For RA Aggregation,
1685 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1686 pQEntry = pTxBlk->TxPacketList.Head;
1687 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1688 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1689 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1690 nextBufLen -= LENGTH_802_1Q;
1691
1692 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1693 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1694
1695 pHeaderBufPtr += 2;
1696 pTxBlk->MpduHeaderLen += 2;
1697
1698 return pHeaderBufPtr;
1699
1700 }
1701
1702 #ifdef DOT11_N_SUPPORT
1703 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1704 IN RTMP_ADAPTER *pAd,
1705 IN TX_BLK *pTxBlk)
1706 {
1707 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1708 HEADER_802_11 *pHeader_802_11;
1709
1710
1711 STAFindCipherAlgorithm(pAd, pTxBlk);
1712 STABuildCommon802_11Header(pAd, pTxBlk);
1713
1714 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1715 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1716
1717 // skip common header
1718 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1719
1720 //
1721 // build QOS Control bytes
1722 //
1723 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1724
1725 //
1726 // A-MSDU packet
1727 //
1728 *pHeaderBufPtr |= 0x80;
1729
1730 *(pHeaderBufPtr+1) = 0;
1731 pHeaderBufPtr +=2;
1732 pTxBlk->MpduHeaderLen += 2;
1733
1734 //pSaveBufPtr = pHeaderBufPtr;
1735
1736 //
1737 // padding at front of LLC header
1738 // LLC header should locate at 4-octets aligment
1739 //
1740 // @@@ MpduHeaderLen excluding padding @@@
1741 //
1742 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1743 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1744 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1745
1746 return pHeaderBufPtr;
1747
1748 }
1749
1750
1751 VOID STA_AMPDU_Frame_Tx(
1752 IN PRTMP_ADAPTER pAd,
1753 IN TX_BLK *pTxBlk)
1754 {
1755 HEADER_802_11 *pHeader_802_11;
1756 PUCHAR pHeaderBufPtr;
1757 USHORT FreeNumber;
1758 MAC_TABLE_ENTRY *pMacEntry;
1759 BOOLEAN bVLANPkt;
1760 PQUEUE_ENTRY pQEntry;
1761
1762 ASSERT(pTxBlk);
1763
1764 while(pTxBlk->TxPacketList.Head)
1765 {
1766 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1767 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1768 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1769 {
1770 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1771 continue;
1772 }
1773
1774 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1775
1776 pMacEntry = pTxBlk->pMacEntry;
1777 if (pMacEntry->isCached)
1778 {
1779 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1780 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1781 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1782 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1783 }
1784 else
1785 {
1786 STAFindCipherAlgorithm(pAd, pTxBlk);
1787 STABuildCommon802_11Header(pAd, pTxBlk);
1788
1789 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1790 }
1791
1792
1793 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1794
1795 // skip common header
1796 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1797
1798 //
1799 // build QOS Control bytes
1800 //
1801 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1802 *(pHeaderBufPtr+1) = 0;
1803 pHeaderBufPtr +=2;
1804 pTxBlk->MpduHeaderLen += 2;
1805
1806 //
1807 // build HTC+
1808 // HTC control filed following QoS field
1809 //
1810 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1811 {
1812 if (pMacEntry->isCached == FALSE)
1813 {
1814 // mark HTC bit
1815 pHeader_802_11->FC.Order = 1;
1816
1817 NdisZeroMemory(pHeaderBufPtr, 4);
1818 *(pHeaderBufPtr+3) |= 0x80;
1819 }
1820 pHeaderBufPtr += 4;
1821 pTxBlk->MpduHeaderLen += 4;
1822 }
1823
1824 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1825 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1826
1827 // skip 802.3 header
1828 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1829 pTxBlk->SrcBufLen -= LENGTH_802_3;
1830
1831 // skip vlan tag
1832 if (bVLANPkt)
1833 {
1834 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1835 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1836 }
1837
1838 //
1839 // padding at front of LLC header
1840 // LLC header should locate at 4-octets aligment
1841 //
1842 // @@@ MpduHeaderLen excluding padding @@@
1843 //
1844 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1845 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1846 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1847
1848 {
1849
1850 //
1851 // Insert LLC-SNAP encapsulation - 8 octets
1852 //
1853 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1854 if (pTxBlk->pExtraLlcSnapEncap)
1855 {
1856 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1857 pHeaderBufPtr += 6;
1858 // get 2 octets (TypeofLen)
1859 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1860 pHeaderBufPtr += 2;
1861 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1862 }
1863
1864 }
1865
1866 if (pMacEntry->isCached)
1867 {
1868 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1869 }
1870 else
1871 {
1872 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1873
1874 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1875 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1876 pMacEntry->isCached = TRUE;
1877 }
1878
1879 // calculate Transmitted AMPDU count and ByteCount
1880 {
1881 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1882 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1883 }
1884
1885 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1886
1887 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1888
1889 //
1890 // Kick out Tx
1891 //
1892 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1893
1894 pAd->RalinkCounters.KickTxCount++;
1895 pAd->RalinkCounters.OneSecTxDoneCount++;
1896 }
1897
1898 }
1899
1900
1901 VOID STA_AMSDU_Frame_Tx(
1902 IN PRTMP_ADAPTER pAd,
1903 IN TX_BLK *pTxBlk)
1904 {
1905 PUCHAR pHeaderBufPtr;
1906 USHORT FreeNumber;
1907 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1908 USHORT totalMPDUSize=0;
1909 UCHAR *subFrameHeader;
1910 UCHAR padding = 0;
1911 USHORT FirstTx = 0, LastTxIdx = 0;
1912 BOOLEAN bVLANPkt;
1913 int frameNum = 0;
1914 PQUEUE_ENTRY pQEntry;
1915
1916
1917 ASSERT(pTxBlk);
1918
1919 ASSERT((pTxBlk->TxPacketList.Number > 1));
1920
1921 while(pTxBlk->TxPacketList.Head)
1922 {
1923 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1924 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1925 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1926 {
1927 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1928 continue;
1929 }
1930
1931 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1932
1933 // skip 802.3 header
1934 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1935 pTxBlk->SrcBufLen -= LENGTH_802_3;
1936
1937 // skip vlan tag
1938 if (bVLANPkt)
1939 {
1940 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1941 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1942 }
1943
1944 if (frameNum == 0)
1945 {
1946 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1947
1948 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1949 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1950 }
1951 else
1952 {
1953 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1954 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1955 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1956 pHeaderBufPtr += padding;
1957 pTxBlk->MpduHeaderLen = padding;
1958 }
1959
1960 //
1961 // A-MSDU subframe
1962 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1963 //
1964 subFrameHeader = pHeaderBufPtr;
1965 subFramePayloadLen = pTxBlk->SrcBufLen;
1966
1967 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1968
1969
1970 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1971 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1972
1973
1974 //
1975 // Insert LLC-SNAP encapsulation - 8 octets
1976 //
1977 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1978
1979 subFramePayloadLen = pTxBlk->SrcBufLen;
1980
1981 if (pTxBlk->pExtraLlcSnapEncap)
1982 {
1983 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1984 pHeaderBufPtr += 6;
1985 // get 2 octets (TypeofLen)
1986 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1987 pHeaderBufPtr += 2;
1988 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1989 subFramePayloadLen += LENGTH_802_1_H;
1990 }
1991
1992 // update subFrame Length field
1993 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1994 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1995
1996 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1997
1998 if (frameNum ==0)
1999 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2000 else
2001 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2002
2003 frameNum++;
2004
2005 pAd->RalinkCounters.KickTxCount++;
2006 pAd->RalinkCounters.OneSecTxDoneCount++;
2007
2008 // calculate Transmitted AMSDU Count and ByteCount
2009 {
2010 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2011 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2012 }
2013
2014 }
2015
2016 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2017 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2018
2019 //
2020 // Kick out Tx
2021 //
2022 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2023 }
2024 #endif // DOT11_N_SUPPORT //
2025
2026 VOID STA_Legacy_Frame_Tx(
2027 IN PRTMP_ADAPTER pAd,
2028 IN TX_BLK *pTxBlk)
2029 {
2030 HEADER_802_11 *pHeader_802_11;
2031 PUCHAR pHeaderBufPtr;
2032 USHORT FreeNumber;
2033 BOOLEAN bVLANPkt;
2034 PQUEUE_ENTRY pQEntry;
2035
2036 ASSERT(pTxBlk);
2037
2038
2039 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2040 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2041 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2042 {
2043 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2044 return;
2045 }
2046
2047 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2048 {
2049 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2050 }
2051
2052 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2053 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2054 else
2055 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2056
2057 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2058
2059 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2060 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2061
2062 STAFindCipherAlgorithm(pAd, pTxBlk);
2063 STABuildCommon802_11Header(pAd, pTxBlk);
2064
2065
2066 // skip 802.3 header
2067 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2068 pTxBlk->SrcBufLen -= LENGTH_802_3;
2069
2070 // skip vlan tag
2071 if (bVLANPkt)
2072 {
2073 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2074 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2075 }
2076
2077 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2078 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2079
2080 // skip common header
2081 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2082
2083 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2084 {
2085 //
2086 // build QOS Control bytes
2087 //
2088 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2089 *(pHeaderBufPtr+1) = 0;
2090 pHeaderBufPtr +=2;
2091 pTxBlk->MpduHeaderLen += 2;
2092 }
2093
2094 // The remaining content of MPDU header should locate at 4-octets aligment
2095 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2096 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2097 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2098
2099 {
2100
2101 //
2102 // Insert LLC-SNAP encapsulation - 8 octets
2103 //
2104 //
2105 // if original Ethernet frame contains no LLC/SNAP,
2106 // then an extra LLC/SNAP encap is required
2107 //
2108 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2109 if (pTxBlk->pExtraLlcSnapEncap)
2110 {
2111 UCHAR vlan_size;
2112
2113 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2114 pHeaderBufPtr += 6;
2115 // skip vlan tag
2116 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2117 // get 2 octets (TypeofLen)
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2119 pHeaderBufPtr += 2;
2120 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2121 }
2122
2123 }
2124
2125 //
2126 // prepare for TXWI
2127 // use Wcid as Key Index
2128 //
2129
2130 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2131
2132 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2133
2134 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2135
2136 pAd->RalinkCounters.KickTxCount++;
2137 pAd->RalinkCounters.OneSecTxDoneCount++;
2138
2139 //
2140 // Kick out Tx
2141 //
2142 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2143 }
2144
2145
2146 VOID STA_ARalink_Frame_Tx(
2147 IN PRTMP_ADAPTER pAd,
2148 IN TX_BLK *pTxBlk)
2149 {
2150 PUCHAR pHeaderBufPtr;
2151 USHORT FreeNumber;
2152 USHORT totalMPDUSize=0;
2153 USHORT FirstTx, LastTxIdx;
2154 int frameNum = 0;
2155 BOOLEAN bVLANPkt;
2156 PQUEUE_ENTRY pQEntry;
2157
2158
2159 ASSERT(pTxBlk);
2160
2161 ASSERT((pTxBlk->TxPacketList.Number== 2));
2162
2163
2164 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2165 while(pTxBlk->TxPacketList.Head)
2166 {
2167 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2168 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2169
2170 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2171 {
2172 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2173 continue;
2174 }
2175
2176 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2177
2178 // skip 802.3 header
2179 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2180 pTxBlk->SrcBufLen -= LENGTH_802_3;
2181
2182 // skip vlan tag
2183 if (bVLANPkt)
2184 {
2185 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2186 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2187 }
2188
2189 if (frameNum == 0)
2190 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2191
2192 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2193
2194 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2195 // will be updated after final frame was handled.
2196 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2197
2198
2199 //
2200 // Insert LLC-SNAP encapsulation - 8 octets
2201 //
2202 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2203
2204 if (pTxBlk->pExtraLlcSnapEncap)
2205 {
2206 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2207 pHeaderBufPtr += 6;
2208 // get 2 octets (TypeofLen)
2209 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2210 pHeaderBufPtr += 2;
2211 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2212 }
2213 }
2214 else
2215 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2216
2217 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2218 pTxBlk->MpduHeaderLen = 0;
2219
2220 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2221 // DA(6)+SA(6)+FrameType(2)
2222 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2223 pHeaderBufPtr += 12;
2224 // get 2 octets (TypeofLen)
2225 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2226 pHeaderBufPtr += 2;
2227 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2228 }
2229
2230 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2231
2232 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2233 if (frameNum ==0)
2234 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2235 else
2236 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2237
2238 frameNum++;
2239
2240 pAd->RalinkCounters.OneSecTxAggregationCount++;
2241 pAd->RalinkCounters.KickTxCount++;
2242 pAd->RalinkCounters.OneSecTxDoneCount++;
2243
2244 }
2245
2246 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2247 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2248
2249 //
2250 // Kick out Tx
2251 //
2252 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2253
2254 }
2255
2256
2257 VOID STA_Fragment_Frame_Tx(
2258 IN RTMP_ADAPTER *pAd,
2259 IN TX_BLK *pTxBlk)
2260 {
2261 HEADER_802_11 *pHeader_802_11;
2262 PUCHAR pHeaderBufPtr;
2263 USHORT FreeNumber;
2264 UCHAR fragNum = 0;
2265 PACKET_INFO PacketInfo;
2266 USHORT EncryptionOverhead = 0;
2267 UINT32 FreeMpduSize, SrcRemainingBytes;
2268 USHORT AckDuration;
2269 UINT NextMpduSize;
2270 BOOLEAN bVLANPkt;
2271 PQUEUE_ENTRY pQEntry;
2272
2273
2274 ASSERT(pTxBlk);
2275
2276 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2277 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2278 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2279 {
2280 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2281 return;
2282 }
2283
2284 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2285 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2286
2287 STAFindCipherAlgorithm(pAd, pTxBlk);
2288 STABuildCommon802_11Header(pAd, pTxBlk);
2289
2290 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2291 {
2292 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2293 if (pTxBlk->pPacket == NULL)
2294 return;
2295 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2296 }
2297
2298 // skip 802.3 header
2299 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2300 pTxBlk->SrcBufLen -= LENGTH_802_3;
2301
2302
2303 // skip vlan tag
2304 if (bVLANPkt)
2305 {
2306 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2307 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2308 }
2309
2310 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2311 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2312
2313
2314 // skip common header
2315 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2316
2317 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2318 {
2319 //
2320 // build QOS Control bytes
2321 //
2322 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2323
2324 *(pHeaderBufPtr+1) = 0;
2325 pHeaderBufPtr +=2;
2326 pTxBlk->MpduHeaderLen += 2;
2327 }
2328
2329 //
2330 // padding at front of LLC header
2331 // LLC header should locate at 4-octets aligment
2332 //
2333 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2334 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2335 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2336
2337
2338
2339 //
2340 // Insert LLC-SNAP encapsulation - 8 octets
2341 //
2342 //
2343 // if original Ethernet frame contains no LLC/SNAP,
2344 // then an extra LLC/SNAP encap is required
2345 //
2346 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2347 if (pTxBlk->pExtraLlcSnapEncap)
2348 {
2349 UCHAR vlan_size;
2350
2351 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2352 pHeaderBufPtr += 6;
2353 // skip vlan tag
2354 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2355 // get 2 octets (TypeofLen)
2356 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2357 pHeaderBufPtr += 2;
2358 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2359 }
2360
2361
2362 // If TKIP is used and fragmentation is required. Driver has to
2363 // append TKIP MIC at tail of the scatter buffer
2364 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2365 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2366 {
2367
2368 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2369 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2370 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2371 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2372 pTxBlk->SrcBufLen += 8;
2373 pTxBlk->TotalFrameLen += 8;
2374 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2375 }
2376
2377 //
2378 // calcuate the overhead bytes that encryption algorithm may add. This
2379 // affects the calculate of "duration" field
2380 //
2381 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2382 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2383 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2384 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2385 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2386 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2387 else if (pTxBlk->CipherAlg == CIPHER_AES)
2388 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2389 else
2390 EncryptionOverhead = 0;
2391
2392 // decide how much time an ACK/CTS frame will consume in the air
2393 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2394
2395 // Init the total payload length of this frame.
2396 SrcRemainingBytes = pTxBlk->SrcBufLen;
2397
2398 pTxBlk->TotalFragNum = 0xff;
2399
2400 do {
2401
2402 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2403
2404 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2405
2406 if (SrcRemainingBytes <= FreeMpduSize)
2407 { // this is the last or only fragment
2408
2409 pTxBlk->SrcBufLen = SrcRemainingBytes;
2410
2411 pHeader_802_11->FC.MoreFrag = 0;
2412 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2413
2414 // Indicate the lower layer that this's the last fragment.
2415 pTxBlk->TotalFragNum = fragNum;
2416 }
2417 else
2418 { // more fragment is required
2419
2420 pTxBlk->SrcBufLen = FreeMpduSize;
2421
2422 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2423 pHeader_802_11->FC.MoreFrag = 1;
2424 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2425 }
2426
2427 if (fragNum == 0)
2428 pTxBlk->FrameGap = IFS_HTTXOP;
2429 else
2430 pTxBlk->FrameGap = IFS_SIFS;
2431
2432 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2433
2434 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2435
2436 pAd->RalinkCounters.KickTxCount++;
2437 pAd->RalinkCounters.OneSecTxDoneCount++;
2438
2439 // Update the frame number, remaining size of the NDIS packet payload.
2440
2441 // space for 802.11 header.
2442 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2443 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2444
2445 fragNum++;
2446 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2447 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2448
2449 pHeader_802_11->Frag++; // increase Frag #
2450
2451 }while(SrcRemainingBytes > 0);
2452
2453 //
2454 // Kick out Tx
2455 //
2456 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2457 }
2458
2459
2460 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2461 while(_pTxBlk->TxPacketList.Head) \
2462 { \
2463 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2464 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2465 }
2466
2467
2468 /*
2469 ========================================================================
2470
2471 Routine Description:
2472 Copy frame from waiting queue into relative ring buffer and set
2473 appropriate ASIC register to kick hardware encryption before really
2474 sent out to air.
2475
2476 Arguments:
2477 pAd Pointer to our adapter
2478 PNDIS_PACKET Pointer to outgoing Ndis frame
2479 NumberOfFrag Number of fragment required
2480
2481 Return Value:
2482 None
2483
2484 IRQL = DISPATCH_LEVEL
2485
2486 Note:
2487
2488 ========================================================================
2489 */
2490 NDIS_STATUS STAHardTransmit(
2491 IN PRTMP_ADAPTER pAd,
2492 IN TX_BLK *pTxBlk,
2493 IN UCHAR QueIdx)
2494 {
2495 NDIS_PACKET *pPacket;
2496 PQUEUE_ENTRY pQEntry;
2497
2498 // ---------------------------------------------
2499 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2500 // ---------------------------------------------
2501 //
2502 ASSERT(pTxBlk->TxPacketList.Number);
2503 if (pTxBlk->TxPacketList.Head == NULL)
2504 {
2505 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2506 return NDIS_STATUS_FAILURE;
2507 }
2508
2509 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2510
2511 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2512 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2513 {
2514 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2515 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2516 return (NDIS_STATUS_FAILURE);
2517 }
2518 #endif // CARRIER_DETECTION_SUPPORT //
2519
2520 // ------------------------------------------------------------------
2521 // STEP 1. WAKE UP PHY
2522 // outgoing frame always wakeup PHY to prevent frame lost and
2523 // turn off PSM bit to improve performance
2524 // ------------------------------------------------------------------
2525 // not to change PSM bit, just send this frame out?
2526 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2527 {
2528 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2529 AsicForceWakeup(pAd, TRUE);
2530 }
2531
2532 // It should not change PSM bit, when APSD turn on.
2533 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2534 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2535 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2536 {
2537 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2538 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2539 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2540 }
2541
2542 switch (pTxBlk->TxFrameType)
2543 {
2544 #ifdef DOT11_N_SUPPORT
2545 case TX_AMPDU_FRAME:
2546 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2547 break;
2548 case TX_AMSDU_FRAME:
2549 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2550 break;
2551 #endif // DOT11_N_SUPPORT //
2552 case TX_LEGACY_FRAME:
2553 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2554 break;
2555 case TX_MCAST_FRAME:
2556 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2557 break;
2558 case TX_RALINK_FRAME:
2559 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2560 break;
2561 case TX_FRAG_FRAME:
2562 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2563 break;
2564 default:
2565 {
2566 // It should not happened!
2567 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2568 while(pTxBlk->TxPacketList.Number)
2569 {
2570 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2571 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2572 if (pPacket)
2573 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2574 }
2575 }
2576 break;
2577 }
2578
2579 return (NDIS_STATUS_SUCCESS);
2580
2581 }
2582
2583 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2584 {
2585 unsigned char *word = value;
2586 unsigned int ret = 0;
2587 unsigned int i;
2588
2589 for(i=0; i < len; i++)
2590 {
2591 int mod = i % 32;
2592 ret ^=(unsigned int) (word[i]) << mod;
2593 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2594 }
2595 return ret;
2596 }
2597
2598 VOID Sta_Announce_or_Forward_802_3_Packet(
2599 IN PRTMP_ADAPTER pAd,
2600 IN PNDIS_PACKET pPacket,
2601 IN UCHAR FromWhichBSSID)
2602 {
2603 if (TRUE
2604 )
2605 {
2606 announce_802_3_packet(pAd, pPacket);
2607 }
2608 else
2609 {
2610 // release packet
2611 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2612 }
2613 }
2614