added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / rt2870 / sta / rtmp_data.c
blob9942ecaf5e2eb0a2d0cdc0c6033462412b26a24b
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 rtmp_data.c
30 Abstract:
31 Data path subroutines
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
39 #include "../rt_config.h"
42 VOID STARxEAPOLFrameIndicate(
43 IN PRTMP_ADAPTER pAd,
44 IN MAC_TABLE_ENTRY *pEntry,
45 IN RX_BLK *pRxBlk,
46 IN UCHAR FromWhichBSSID)
48 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
49 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
50 UCHAR *pTmpBuf;
52 #ifdef WPA_SUPPLICANT_SUPPORT
53 if (pAd->StaCfg.WpaSupplicantUP)
55 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
56 // TBD : process fragmented EAPol frames
58 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
59 if ( pAd->StaCfg.IEEE8021X == TRUE &&
60 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
62 PUCHAR Key;
63 UCHAR CipherAlg;
64 int idx = 0;
66 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
67 //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
68 STA_PORT_SECURED(pAd);
70 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
72 idx = pAd->StaCfg.DesireSharedKeyId;
73 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
74 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
78 #ifdef RT2870
79 union
81 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
82 NDIS_802_11_WEP keyinfo;
83 } WepKey;
84 int len;
87 NdisZeroMemory(&WepKey, sizeof(WepKey));
88 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
90 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
91 pAd->StaCfg.DesireSharedKey[idx].Key,
92 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
94 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
95 WepKey.keyinfo.KeyLength = len;
96 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
98 pAd->IndicateMediaState = NdisMediaStateConnected;
99 pAd->ExtraInfo = GENERAL_LINK_UP;
100 // need to enqueue cmd to thread
101 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
102 #endif // RT2870 //
103 // For Preventing ShardKey Table is cleared by remove key procedure.
104 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
105 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
106 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
107 pAd->StaCfg.DesireSharedKey[idx].Key,
108 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
113 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
114 return;
117 else
118 #endif // WPA_SUPPLICANT_SUPPORT //
120 // Special DATA frame that has to pass to MLME
121 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
122 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
124 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
125 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
126 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
127 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
131 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
132 return;
136 VOID STARxDataFrameAnnounce(
137 IN PRTMP_ADAPTER pAd,
138 IN MAC_TABLE_ENTRY *pEntry,
139 IN RX_BLK *pRxBlk,
140 IN UCHAR FromWhichBSSID)
143 // non-EAP frame
144 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
147 // drop all non-EAP DATA frame before
148 // this client's Port-Access-Control is secured
149 if (pRxBlk->pHeader->FC.Wep)
151 // unsupported cipher suite
152 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
154 // release packet
155 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
156 return;
159 else
161 // encryption in-use but receive a non-EAPOL clear text frame, drop it
162 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
163 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
165 // release packet
166 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
167 return;
171 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
172 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
174 // Normal legacy, AMPDU or AMSDU
175 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
178 else
180 // ARALINK
181 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
183 #ifdef QOS_DLS_SUPPORT
184 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
185 #endif // QOS_DLS_SUPPORT //
187 else
189 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
190 #ifdef DOT11_N_SUPPORT
191 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
193 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
195 else
196 #endif // DOT11_N_SUPPORT //
198 // Determin the destination of the EAP frame
199 // to WPA state machine or upper layer
200 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
206 // For TKIP frame, calculate the MIC value
207 BOOLEAN STACheckTkipMICValue(
208 IN PRTMP_ADAPTER pAd,
209 IN MAC_TABLE_ENTRY *pEntry,
210 IN RX_BLK *pRxBlk)
212 PHEADER_802_11 pHeader = pRxBlk->pHeader;
213 UCHAR *pData = pRxBlk->pData;
214 USHORT DataSize = pRxBlk->DataSize;
215 UCHAR UserPriority = pRxBlk->UserPriority;
216 PCIPHER_KEY pWpaKey;
217 UCHAR *pDA, *pSA;
219 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
221 pDA = pHeader->Addr1;
222 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
224 pSA = pHeader->Addr3;
226 else
228 pSA = pHeader->Addr2;
231 if (RTMPTkipCompareMICValue(pAd,
232 pData,
233 pDA,
234 pSA,
235 pWpaKey->RxMic,
236 UserPriority,
237 DataSize) == FALSE)
239 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
241 #ifdef WPA_SUPPLICANT_SUPPORT
242 if (pAd->StaCfg.WpaSupplicantUP)
244 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
246 else
247 #endif // WPA_SUPPLICANT_SUPPORT //
249 RTMPReportMicError(pAd, pWpaKey);
252 // release packet
253 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
254 return FALSE;
257 return TRUE;
262 // All Rx routines use RX_BLK structure to hande rx events
263 // It is very important to build pRxBlk attributes
264 // 1. pHeader pointer to 802.11 Header
265 // 2. pData pointer to payload including LLC (just skip Header)
266 // 3. set payload size including LLC to DataSize
267 // 4. set some flags with RX_BLK_SET_FLAG()
269 VOID STAHandleRxDataFrame(
270 IN PRTMP_ADAPTER pAd,
271 IN RX_BLK *pRxBlk)
273 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
274 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
275 PHEADER_802_11 pHeader = pRxBlk->pHeader;
276 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
277 BOOLEAN bFragment = FALSE;
278 MAC_TABLE_ENTRY *pEntry = NULL;
279 UCHAR FromWhichBSSID = BSS0;
280 UCHAR UserPriority = 0;
283 // before LINK UP, all DATA frames are rejected
284 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
286 // release packet
287 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
288 return;
291 #ifdef QOS_DLS_SUPPORT
292 //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
293 if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
295 return;
297 #endif // QOS_DLS_SUPPORT //
299 // Drop not my BSS frames
300 if (pRxD->MyBss == 0)
303 // release packet
304 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
305 return;
309 pAd->RalinkCounters.RxCountSinceLastNULL++;
310 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
312 UCHAR *pData;
313 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
315 // Qos bit 4
316 pData = (PUCHAR)pHeader + LENGTH_802_11;
317 if ((*pData >> 4) & 0x01)
319 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
320 pAd->CommonCfg.bInServicePeriod = FALSE;
322 // Force driver to fall into sleep mode when rcv EOSP frame
323 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
325 USHORT TbttNumToNextWakeUp;
326 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
327 ULONG Now;
329 NdisGetSystemUpTime(&Now);
330 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
332 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
333 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
334 TbttNumToNextWakeUp = NextDtim;
336 MlmeSetPsmBit(pAd, PWR_SAVE);
337 // if WMM-APSD is failed, try to disable following line
338 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
342 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
344 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
348 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
349 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
351 // release packet
352 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
353 return;
356 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
357 #ifdef QOS_DLS_SUPPORT
358 if (!pAd->CommonCfg.bDLSCapable)
360 #endif // QOS_DLS_SUPPORT //
361 if (INFRA_ON(pAd))
363 // Infrastructure mode, check address 2 for BSSID
364 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
366 // Receive frame not my BSSID
367 // release packet
368 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
369 return;
372 else // Ad-Hoc mode or Not associated
374 // Ad-Hoc mode, check address 3 for BSSID
375 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
377 // Receive frame not my BSSID
378 // release packet
379 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
380 return;
383 #ifdef QOS_DLS_SUPPORT
385 #endif // QOS_DLS_SUPPORT //
388 // find pEntry
390 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
392 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
394 else
396 // 1. release packet if infra mode
397 // 2. new a pEntry if ad-hoc mode
398 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
399 return;
402 // infra or ad-hoc
403 if (INFRA_ON(pAd))
405 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
406 #ifdef QOS_DLS_SUPPORT
407 if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
408 RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
409 else
410 #endif // QOS_DLS_SUPPORT //
411 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
414 // check Atheros Client
415 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
417 pEntry->bIAmBadAtheros = TRUE;
418 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
419 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
420 if (!STA_AES_ON(pAd))
422 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
427 pRxBlk->pData = (UCHAR *)pHeader;
430 // update RxBlk->pData, DataSize
431 // 802.11 Header, QOS, HTC, Hw Padding
434 // 1. skip 802.11 HEADER
436 pRxBlk->pData += LENGTH_802_11;
437 pRxBlk->DataSize -= LENGTH_802_11;
440 // 2. QOS
441 if (pHeader->FC.SubType & 0x08)
443 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
444 UserPriority = *(pRxBlk->pData) & 0x0f;
445 // bit 7 in QoS Control field signals the HT A-MSDU format
446 if ((*pRxBlk->pData) & 0x80)
448 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
451 // skip QOS contorl field
452 pRxBlk->pData += 2;
453 pRxBlk->DataSize -=2;
455 pRxBlk->UserPriority = UserPriority;
457 // 3. Order bit: A-Ralink or HTC+
458 if (pHeader->FC.Order)
460 #ifdef AGGREGATION_SUPPORT
461 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
463 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
465 else
466 #endif
468 #ifdef DOT11_N_SUPPORT
469 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
470 // skip HTC contorl field
471 pRxBlk->pData += 4;
472 pRxBlk->DataSize -= 4;
473 #endif // DOT11_N_SUPPORT //
477 // 4. skip HW padding
478 if (pRxD->L2PAD)
480 // just move pData pointer
481 // because DataSize excluding HW padding
482 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
483 pRxBlk->pData += 2;
486 #ifdef DOT11_N_SUPPORT
487 if (pRxD->BA)
489 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
491 #endif // DOT11_N_SUPPORT //
495 // Case I Process Broadcast & Multicast data frame
497 if (pRxD->Bcast || pRxD->Mcast)
499 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
501 // Drop Mcast/Bcast frame with fragment bit on
502 if (pHeader->FC.MoreFrag)
504 // release packet
505 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
506 return;
509 // Filter out Bcast frame which AP relayed for us
510 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
512 // release packet
513 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
514 return;
517 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
518 return;
520 else if (pRxD->U2M)
522 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
525 #ifdef QOS_DLS_SUPPORT
526 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
528 MAC_TABLE_ENTRY *pDlsEntry = NULL;
530 pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
531 if(pDlsEntry)
532 Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
534 else
535 #endif // QOS_DLS_SUPPORT //
536 if (ADHOC_ON(pAd))
538 pEntry = MacTableLookup(pAd, pHeader->Addr2);
539 if (pEntry)
540 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
544 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
546 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
547 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
549 pAd->RalinkCounters.OneSecRxOkDataCnt++;
552 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
554 // re-assemble the fragmented packets
555 // return complete frame (pRxPacket) or NULL
556 bFragment = TRUE;
557 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
560 if (pRxPacket)
562 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
564 // process complete frame
565 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
567 // Minus MIC length
568 pRxBlk->DataSize -= 8;
570 // For TKIP frame, calculate the MIC value
571 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
573 return;
577 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
578 return;
580 else
582 // just return
583 // because RTMPDeFragmentDataFrame() will release rx packet,
584 // if packet is fragmented
585 return;
589 ASSERT(0);
590 // release packet
591 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
594 VOID STAHandleRxMgmtFrame(
595 IN PRTMP_ADAPTER pAd,
596 IN RX_BLK *pRxBlk)
598 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
599 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
600 PHEADER_802_11 pHeader = pRxBlk->pHeader;
601 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
606 // We should collect RSSI not only U2M data but also my beacon
607 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
609 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
611 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
612 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
615 // First check the size, it MUST not exceed the mlme queue size
616 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
618 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
619 break;
622 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
623 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
624 } while (FALSE);
626 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
629 VOID STAHandleRxControlFrame(
630 IN PRTMP_ADAPTER pAd,
631 IN RX_BLK *pRxBlk)
633 #ifdef DOT11_N_SUPPORT
634 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
635 #endif // DOT11_N_SUPPORT //
636 PHEADER_802_11 pHeader = pRxBlk->pHeader;
637 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
639 switch (pHeader->FC.SubType)
641 case SUBTYPE_BLOCK_ACK_REQ:
642 #ifdef DOT11_N_SUPPORT
644 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
646 break;
647 #endif // DOT11_N_SUPPORT //
648 case SUBTYPE_BLOCK_ACK:
649 case SUBTYPE_ACK:
650 default:
651 break;
654 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
659 ========================================================================
661 Routine Description:
662 Process RxDone interrupt, running in DPC level
664 Arguments:
665 pAd Pointer to our adapter
667 Return Value:
668 None
670 IRQL = DISPATCH_LEVEL
672 Note:
673 This routine has to maintain Rx ring read pointer.
674 Need to consider QOS DATA format when converting to 802.3
675 ========================================================================
677 BOOLEAN STARxDoneInterruptHandle(
678 IN PRTMP_ADAPTER pAd,
679 IN BOOLEAN argc)
681 NDIS_STATUS Status;
682 UINT32 RxProcessed, RxPending;
683 BOOLEAN bReschedule = FALSE;
684 RT28XX_RXD_STRUC *pRxD;
685 UCHAR *pData;
686 PRXWI_STRUC pRxWI;
687 PNDIS_PACKET pRxPacket;
688 PHEADER_802_11 pHeader;
689 RX_BLK RxCell;
691 RxProcessed = RxPending = 0;
693 // process whole rx ring
694 while (1)
697 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
698 fRTMP_ADAPTER_RESET_IN_PROGRESS |
699 fRTMP_ADAPTER_HALT_IN_PROGRESS |
700 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
701 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
703 break;
707 RxProcessed ++; // test
709 // 1. allocate a new data packet into rx ring to replace received packet
710 // then processing the received packet
711 // 2. the callee must take charge of release of packet
712 // 3. As far as driver is concerned ,
713 // the rx packet must
714 // a. be indicated to upper layer or
715 // b. be released if it is discarded
716 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
717 if (pRxPacket == NULL)
719 // no more packet to process
720 break;
723 // get rx ring descriptor
724 pRxD = &(RxCell.RxD);
725 // get rx data buffer
726 pData = GET_OS_PKT_DATAPTR(pRxPacket);
727 pRxWI = (PRXWI_STRUC) pData;
728 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
730 #ifdef RT_BIG_ENDIAN
731 RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
732 RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
733 #endif
735 // build RxCell
736 RxCell.pRxWI = pRxWI;
737 RxCell.pHeader = pHeader;
738 RxCell.pRxPacket = pRxPacket;
739 RxCell.pData = (UCHAR *) pHeader;
740 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
741 RxCell.Flags = 0;
743 // Increase Total receive byte counter after real data received no mater any error or not
744 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
745 pAd->RalinkCounters.RxCount ++;
747 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
749 if (pRxWI->MPDUtotalByteCount < 14)
750 Status = NDIS_STATUS_FAILURE;
752 if (MONITOR_ON(pAd))
754 send_monitor_packets(pAd, &RxCell);
755 break;
757 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
758 #ifdef RALINK_ATE
759 if (ATE_ON(pAd))
761 pAd->ate.RxCntPerSec++;
762 ATESampleRssi(pAd, pRxWI);
763 #ifdef RALINK_28xx_QA
764 if (pAd->ate.bQARxStart == TRUE)
766 /* (*pRxD) has been swapped in GetPacketFromRxRing() */
767 ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
769 #endif // RALINK_28xx_QA //
770 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
771 continue;
773 #endif // RALINK_ATE //
775 // Check for all RxD errors
776 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
778 // Handle the received frame
779 if (Status == NDIS_STATUS_SUCCESS)
781 switch (pHeader->FC.Type)
783 // CASE I, receive a DATA frame
784 case BTYPE_DATA:
786 // process DATA frame
787 STAHandleRxDataFrame(pAd, &RxCell);
789 break;
790 // CASE II, receive a MGMT frame
791 case BTYPE_MGMT:
793 STAHandleRxMgmtFrame(pAd, &RxCell);
795 break;
796 // CASE III. receive a CNTL frame
797 case BTYPE_CNTL:
799 STAHandleRxControlFrame(pAd, &RxCell);
801 break;
802 // discard other type
803 default:
804 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
805 break;
808 else
810 pAd->Counters8023.RxErrors++;
811 // discard this frame
812 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
816 return bReschedule;
820 ========================================================================
822 Routine Description:
823 Arguments:
824 pAd Pointer to our adapter
826 IRQL = DISPATCH_LEVEL
828 ========================================================================
830 VOID RTMPHandleTwakeupInterrupt(
831 IN PRTMP_ADAPTER pAd)
833 AsicForceWakeup(pAd, FALSE);
837 ========================================================================
838 Routine Description:
839 Early checking and OS-depened parsing for Tx packet send to our STA driver.
841 Arguments:
842 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
843 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
844 UINT NumberOfPackets Number of packet in packet array.
846 Return Value:
847 NONE
849 Note:
850 This function do early checking and classification for send-out packet.
851 You only can put OS-depened & STA related code in here.
852 ========================================================================
854 VOID STASendPackets(
855 IN NDIS_HANDLE MiniportAdapterContext,
856 IN PPNDIS_PACKET ppPacketArray,
857 IN UINT NumberOfPackets)
859 UINT Index;
860 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
861 PNDIS_PACKET pPacket;
862 BOOLEAN allowToSend = FALSE;
865 for (Index = 0; Index < NumberOfPackets; Index++)
867 pPacket = ppPacketArray[Index];
871 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
872 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
873 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
875 // Drop send request since hardware is in reset state
876 break;
878 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
880 // Drop send request since there are no physical connection yet
881 break;
883 else
885 // Record that orignal packet source is from NDIS layer,so that
886 // later on driver knows how to release this NDIS PACKET
887 #ifdef QOS_DLS_SUPPORT
888 MAC_TABLE_ENTRY *pEntry;
889 PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
891 pEntry = MacTableLookup(pAd, pSrcBufVA);
892 if (pEntry && (pEntry->ValidAsDls == TRUE))
894 RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
896 else
897 #endif // QOS_DLS_SUPPORT //
898 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
899 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
900 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
901 pAd->RalinkCounters.PendingNdisPacketCount++;
903 allowToSend = TRUE;
905 } while(FALSE);
907 if (allowToSend == TRUE)
908 STASendPacket(pAd, pPacket);
909 else
910 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
913 // Dequeue outgoing frames from TxSwQueue[] and process it
914 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
920 ========================================================================
921 Routine Description:
922 This routine is used to do packet parsing and classification for Tx packet
923 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
924 class.
926 Arguments:
927 pAd Pointer to our adapter
928 pPacket Pointer to send packet
930 Return Value:
931 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
932 NDIS_STATUS_FAILURE If failed to do en-queue.
934 Note:
935 You only can put OS-indepened & STA related code in here.
936 ========================================================================
938 NDIS_STATUS STASendPacket(
939 IN PRTMP_ADAPTER pAd,
940 IN PNDIS_PACKET pPacket)
942 PACKET_INFO PacketInfo;
943 PUCHAR pSrcBufVA;
944 UINT SrcBufLen;
945 UINT AllowFragSize;
946 UCHAR NumberOfFrag;
947 // UCHAR RTSRequired;
948 UCHAR QueIdx, UserPriority;
949 MAC_TABLE_ENTRY *pEntry = NULL;
950 unsigned int IrqFlags;
951 UCHAR FlgIsIP = 0;
952 UCHAR Rate;
954 // Prepare packet information structure for buffer descriptor
955 // chained within a single NDIS packet.
956 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
958 if (pSrcBufVA == NULL)
960 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
961 // Resourece is low, system did not allocate virtual address
962 // return NDIS_STATUS_FAILURE directly to upper layer
963 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
964 return NDIS_STATUS_FAILURE;
968 if (SrcBufLen < 14)
970 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
971 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
972 return (NDIS_STATUS_FAILURE);
975 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
976 // Note multicast packets in adhoc also use BSSID_WCID index.
978 if(INFRA_ON(pAd))
980 #ifdef QOS_DLS_SUPPORT
981 USHORT tmpWcid;
983 tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
984 if (VALID_WCID(tmpWcid) &&
985 (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
987 pEntry = &pAd->MacTab.Content[tmpWcid];
988 Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
990 else
991 #endif // QOS_DLS_SUPPORT //
993 pEntry = &pAd->MacTab.Content[BSSID_WCID];
994 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
995 Rate = pAd->CommonCfg.TxRate;
998 else if (ADHOC_ON(pAd))
1000 if (*pSrcBufVA & 0x01)
1002 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
1003 pEntry = &pAd->MacTab.Content[MCAST_WCID];
1005 else
1007 pEntry = MacTableLookup(pAd, pSrcBufVA);
1009 Rate = pAd->CommonCfg.TxRate;
1013 if (!pEntry)
1015 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
1016 // Resourece is low, system did not allocate virtual address
1017 // return NDIS_STATUS_FAILURE directly to upper layer
1018 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1019 return NDIS_STATUS_FAILURE;
1022 if (ADHOC_ON(pAd)
1025 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
1029 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
1030 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
1031 RTMPCheckEtherType(pAd, pPacket);
1036 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
1038 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1039 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1040 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1041 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1042 #ifdef WPA_SUPPLICANT_SUPPORT
1043 || (pAd->StaCfg.IEEE8021X == TRUE)
1044 #endif // WPA_SUPPLICANT_SUPPORT //
1045 #ifdef LEAP_SUPPORT
1046 || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
1047 #endif // LEAP_SUPPORT //
1049 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
1050 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
1053 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
1054 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1056 return (NDIS_STATUS_FAILURE);
1060 // STEP 1. Decide number of fragments required to deliver this MSDU.
1061 // The estimation here is not very accurate because difficult to
1062 // take encryption overhead into consideration here. The result
1063 // "NumberOfFrag" is then just used to pre-check if enough free
1064 // TXD are available to hold this MSDU.
1067 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
1068 NumberOfFrag = 1;
1069 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1070 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1071 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1072 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
1073 #ifdef DOT11_N_SUPPORT
1074 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1075 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
1076 #endif // DOT11_N_SUPPORT //
1077 else
1079 // The calculated "NumberOfFrag" is a rough estimation because of various
1080 // encryption/encapsulation overhead not taken into consideration. This number is just
1081 // used to make sure enough free TXD are available before fragmentation takes place.
1082 // In case the actual required number of fragments of an NDIS packet
1083 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1084 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1085 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1086 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1088 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1089 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1090 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1091 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1093 NumberOfFrag--;
1097 // Save fragment number to Ndis packet reserved field
1098 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1101 // STEP 2. Check the requirement of RTS:
1102 // If multiple fragment required, RTS is required only for the first fragment
1103 // if the fragment size large than RTS threshold
1104 // For RT28xx, Let ASIC send RTS/CTS
1105 RTMP_SET_PACKET_RTS(pPacket, 0);
1106 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1109 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1111 UserPriority = 0;
1112 QueIdx = QID_AC_BE;
1113 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1114 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1116 USHORT Protocol;
1117 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1120 // get Ethernet protocol field
1121 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1122 if (Protocol <= 1500)
1124 // get Ethernet protocol field from LLC/SNAP
1125 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1126 break;
1128 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1129 LlcSnapLen = 8;
1132 // always AC_BE for non-IP packet
1133 if (Protocol != 0x0800)
1134 break;
1136 // get IP header
1137 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1138 break;
1140 // return AC_BE if packet is not IPv4
1141 if ((Byte0 & 0xf0) != 0x40)
1142 break;
1144 FlgIsIP = 1;
1145 UserPriority = (Byte1 & 0xe0) >> 5;
1146 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1148 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1149 // TODO: downgrade UP & QueIdx before passing ACM
1150 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1152 UserPriority = 0;
1153 QueIdx = QID_AC_BE;
1155 } while (FALSE);
1158 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1162 // Make sure SendTxWait queue resource won't be used by other threads
1163 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1164 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1166 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1167 #ifdef BLOCK_NET_IF
1168 StopNetIfQueue(pAd, QueIdx, pPacket);
1169 #endif // BLOCK_NET_IF //
1170 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1172 return NDIS_STATUS_FAILURE;
1174 else
1176 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1178 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1180 #ifdef DOT11_N_SUPPORT
1181 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1182 IS_HT_STA(pEntry))
1184 //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID];
1185 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1186 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1187 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1188 // For IOT compatibility, if
1189 // 1. It is Ralink chip or
1190 // 2. It is OPEN or AES mode,
1191 // then BA session can be bulit.
1192 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1193 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1196 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1199 #endif // DOT11_N_SUPPORT //
1201 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1202 return NDIS_STATUS_SUCCESS;
1207 ========================================================================
1209 Routine Description:
1210 This subroutine will scan through releative ring descriptor to find
1211 out avaliable free ring descriptor and compare with request size.
1213 Arguments:
1214 pAd Pointer to our adapter
1215 QueIdx Selected TX Ring
1217 Return Value:
1218 NDIS_STATUS_FAILURE Not enough free descriptor
1219 NDIS_STATUS_SUCCESS Enough free descriptor
1221 IRQL = PASSIVE_LEVEL
1222 IRQL = DISPATCH_LEVEL
1224 Note:
1226 ========================================================================
1229 #ifdef RT2870
1231 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1232 If no frame need to send, go to sleep, else, still wake up.
1234 NDIS_STATUS RTMPFreeTXDRequest(
1235 IN PRTMP_ADAPTER pAd,
1236 IN UCHAR QueIdx,
1237 IN UCHAR NumberRequired,
1238 IN PUCHAR FreeNumberIs)
1240 //ULONG FreeNumber = 0;
1241 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1242 unsigned long IrqFlags;
1243 HT_TX_CONTEXT *pHTTXContext;
1245 switch (QueIdx)
1247 case QID_AC_BK:
1248 case QID_AC_BE:
1249 case QID_AC_VI:
1250 case QID_AC_VO:
1251 case QID_HCCA:
1253 pHTTXContext = &pAd->TxContext[QueIdx];
1254 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1255 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1256 (pHTTXContext->IRPPending == TRUE))
1258 Status = NDIS_STATUS_FAILURE;
1260 else
1262 Status = NDIS_STATUS_SUCCESS;
1264 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1266 break;
1268 case QID_MGMT:
1269 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1270 Status = NDIS_STATUS_FAILURE;
1271 else
1272 Status = NDIS_STATUS_SUCCESS;
1273 break;
1275 default:
1276 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1277 break;
1280 return (Status);
1283 #endif // RT2870 //
1286 VOID RTMPSendDisassociationFrame(
1287 IN PRTMP_ADAPTER pAd)
1291 VOID RTMPSendNullFrame(
1292 IN PRTMP_ADAPTER pAd,
1293 IN UCHAR TxRate,
1294 IN BOOLEAN bQosNull)
1296 UCHAR NullFrame[48];
1297 ULONG Length;
1298 PHEADER_802_11 pHeader_802_11;
1301 #ifdef RALINK_ATE
1302 if(ATE_ON(pAd))
1304 return;
1306 #endif // RALINK_ATE //
1308 // WPA 802.1x secured port control
1309 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1310 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1311 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1312 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1313 #ifdef WPA_SUPPLICANT_SUPPORT
1314 || (pAd->StaCfg.IEEE8021X == TRUE)
1315 #endif
1316 ) &&
1317 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1319 return;
1322 NdisZeroMemory(NullFrame, 48);
1323 Length = sizeof(HEADER_802_11);
1325 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1327 pHeader_802_11->FC.Type = BTYPE_DATA;
1328 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1329 pHeader_802_11->FC.ToDs = 1;
1330 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1331 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1332 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1334 if (pAd->CommonCfg.bAPSDForcePowerSave)
1336 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1338 else
1340 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1342 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1344 pAd->Sequence++;
1345 pHeader_802_11->Sequence = pAd->Sequence;
1347 // Prepare QosNull function frame
1348 if (bQosNull)
1350 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1352 // copy QOS control bytes
1353 NullFrame[Length] = 0;
1354 NullFrame[Length+1] = 0;
1355 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1358 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1362 // IRQL = DISPATCH_LEVEL
1363 VOID RTMPSendRTSFrame(
1364 IN PRTMP_ADAPTER pAd,
1365 IN PUCHAR pDA,
1366 IN unsigned int NextMpduSize,
1367 IN UCHAR TxRate,
1368 IN UCHAR RTSRate,
1369 IN USHORT AckDuration,
1370 IN UCHAR QueIdx,
1371 IN UCHAR FrameGap)
1377 // --------------------------------------------------------
1378 // FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1379 // Find the WPA key, either Group or Pairwise Key
1380 // LEAP + TKIP also use WPA key.
1381 // --------------------------------------------------------
1382 // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1383 // In Cisco CCX 2.0 Leap Authentication
1384 // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1385 // Instead of the SharedKey, SharedKey Length may be Zero.
1386 VOID STAFindCipherAlgorithm(
1387 IN PRTMP_ADAPTER pAd,
1388 IN TX_BLK *pTxBlk)
1390 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1391 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1392 UCHAR KeyIdx = 0xff;
1393 PUCHAR pSrcBufVA;
1394 PCIPHER_KEY pKey = NULL;
1396 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1399 // Select Cipher
1400 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1401 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1402 else
1403 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1405 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1407 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1409 // 4-way handshaking frame must be clear
1410 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1411 (pAd->SharedKey[BSS0][0].KeyLen))
1413 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1414 KeyIdx = 0;
1417 else if (Cipher == Ndis802_11Encryption1Enabled)
1419 #ifdef LEAP_SUPPORT
1420 if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
1422 if (LEAP_CCKM_ON(pAd))
1424 if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
1425 KeyIdx = 1;
1426 else
1427 KeyIdx = 0;
1429 else
1430 KeyIdx = pAd->StaCfg.DefaultKeyId;
1432 else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
1433 KeyIdx = pAd->StaCfg.DefaultKeyId;
1434 else if (LEAP_CCKM_ON(pAd))
1436 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1437 KeyIdx = 1;
1438 else
1439 KeyIdx = 0;
1441 else // standard WEP64 or WEP128
1442 #endif // LEAP_SUPPORT //
1443 KeyIdx = pAd->StaCfg.DefaultKeyId;
1445 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1446 (Cipher == Ndis802_11Encryption3Enabled))
1448 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1449 KeyIdx = pAd->StaCfg.DefaultKeyId;
1450 else if (pAd->SharedKey[BSS0][0].KeyLen)
1451 KeyIdx = 0;
1452 else
1453 KeyIdx = pAd->StaCfg.DefaultKeyId;
1456 if (KeyIdx == 0xff)
1457 CipherAlg = CIPHER_NONE;
1458 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1459 CipherAlg = CIPHER_NONE;
1460 #ifdef WPA_SUPPLICANT_SUPPORT
1461 else if ( pAd->StaCfg.WpaSupplicantUP &&
1462 (Cipher == Ndis802_11Encryption1Enabled) &&
1463 (pAd->StaCfg.IEEE8021X == TRUE) &&
1464 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1465 CipherAlg = CIPHER_NONE;
1466 #endif // WPA_SUPPLICANT_SUPPORT //
1467 else
1469 //Header_802_11.FC.Wep = 1;
1470 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1471 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1475 pTxBlk->CipherAlg = CipherAlg;
1476 pTxBlk->pKey = pKey;
1480 VOID STABuildCommon802_11Header(
1481 IN PRTMP_ADAPTER pAd,
1482 IN TX_BLK *pTxBlk)
1485 HEADER_802_11 *pHeader_802_11;
1486 #ifdef QOS_DLS_SUPPORT
1487 BOOLEAN bDLSFrame = FALSE;
1488 INT DlsEntryIndex = 0;
1489 #endif // QOS_DLS_SUPPORT //
1492 // MAKE A COMMON 802.11 HEADER
1495 // normal wlan header size : 24 octets
1496 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1498 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1500 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1502 pHeader_802_11->FC.FrDs = 0;
1503 pHeader_802_11->FC.Type = BTYPE_DATA;
1504 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1506 #ifdef QOS_DLS_SUPPORT
1507 if (INFRA_ON(pAd))
1509 // Check if the frame can be sent through DLS direct link interface
1510 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1511 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1512 if (DlsEntryIndex >= 0)
1513 bDLSFrame = TRUE;
1514 else
1515 bDLSFrame = FALSE;
1517 #endif // QOS_DLS_SUPPORT //
1519 if (pTxBlk->pMacEntry)
1521 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1523 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1524 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1526 else
1528 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1529 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1532 else
1534 pHeader_802_11->Sequence = pAd->Sequence;
1535 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1538 pHeader_802_11->Frag = 0;
1540 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1543 if (INFRA_ON(pAd))
1545 #ifdef QOS_DLS_SUPPORT
1546 if (bDLSFrame)
1548 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1549 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1550 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1551 pHeader_802_11->FC.ToDs = 0;
1553 else
1554 #endif // QOS_DLS_SUPPORT //
1556 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1557 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1558 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1559 pHeader_802_11->FC.ToDs = 1;
1562 else if (ADHOC_ON(pAd))
1564 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1565 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1566 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1567 pHeader_802_11->FC.ToDs = 0;
1571 if (pTxBlk->CipherAlg != CIPHER_NONE)
1572 pHeader_802_11->FC.Wep = 1;
1574 // -----------------------------------------------------------------
1575 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1576 // -----------------------------------------------------------------
1577 if (pAd->CommonCfg.bAPSDForcePowerSave)
1578 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1579 else
1580 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1583 #ifdef DOT11_N_SUPPORT
1584 VOID STABuildCache802_11Header(
1585 IN RTMP_ADAPTER *pAd,
1586 IN TX_BLK *pTxBlk,
1587 IN UCHAR *pHeader)
1589 MAC_TABLE_ENTRY *pMacEntry;
1590 PHEADER_802_11 pHeader80211;
1592 pHeader80211 = (PHEADER_802_11)pHeader;
1593 pMacEntry = pTxBlk->pMacEntry;
1596 // Update the cached 802.11 HEADER
1599 // normal wlan header size : 24 octets
1600 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1602 // More Bit
1603 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1605 // Sequence
1606 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1607 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1610 // Check if the frame can be sent through DLS direct link interface
1611 // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
1612 #ifdef QOS_DLS_SUPPORT
1613 BOOLEAN bDLSFrame = FALSE;
1614 INT DlsEntryIndex = 0;
1616 DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
1617 if (DlsEntryIndex >= 0)
1618 bDLSFrame = TRUE;
1619 else
1620 bDLSFrame = FALSE;
1621 #endif // QOS_DLS_SUPPORT //
1623 // The addr3 of normal packet send from DS is Dest Mac address.
1624 #ifdef QOS_DLS_SUPPORT
1625 if (bDLSFrame)
1627 COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
1628 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1629 pHeader80211->FC.ToDs = 0;
1631 else
1632 #endif // QOS_DLS_SUPPORT //
1633 if (ADHOC_ON(pAd))
1634 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1635 else
1636 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1639 // -----------------------------------------------------------------
1640 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1641 // -----------------------------------------------------------------
1642 if (pAd->CommonCfg.bAPSDForcePowerSave)
1643 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1644 else
1645 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1647 #endif // DOT11_N_SUPPORT //
1649 static inline PUCHAR STA_Build_ARalink_Frame_Header(
1650 IN RTMP_ADAPTER *pAd,
1651 IN TX_BLK *pTxBlk)
1653 PUCHAR pHeaderBufPtr;
1654 HEADER_802_11 *pHeader_802_11;
1655 PNDIS_PACKET pNextPacket;
1656 UINT32 nextBufLen;
1657 PQUEUE_ENTRY pQEntry;
1659 STAFindCipherAlgorithm(pAd, pTxBlk);
1660 STABuildCommon802_11Header(pAd, pTxBlk);
1663 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1664 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1666 // steal "order" bit to mark "aggregation"
1667 pHeader_802_11->FC.Order = 1;
1669 // skip common header
1670 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1672 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1675 // build QOS Control bytes
1677 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1679 *(pHeaderBufPtr+1) = 0;
1680 pHeaderBufPtr +=2;
1681 pTxBlk->MpduHeaderLen += 2;
1684 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1685 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1686 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1687 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1689 // For RA Aggregation,
1690 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1691 pQEntry = pTxBlk->TxPacketList.Head;
1692 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1693 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1694 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1695 nextBufLen -= LENGTH_802_1Q;
1697 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1698 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1700 pHeaderBufPtr += 2;
1701 pTxBlk->MpduHeaderLen += 2;
1703 return pHeaderBufPtr;
1707 #ifdef DOT11_N_SUPPORT
1708 static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1709 IN RTMP_ADAPTER *pAd,
1710 IN TX_BLK *pTxBlk)
1712 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1713 HEADER_802_11 *pHeader_802_11;
1716 STAFindCipherAlgorithm(pAd, pTxBlk);
1717 STABuildCommon802_11Header(pAd, pTxBlk);
1719 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1720 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1722 // skip common header
1723 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1726 // build QOS Control bytes
1728 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1731 // A-MSDU packet
1733 *pHeaderBufPtr |= 0x80;
1735 *(pHeaderBufPtr+1) = 0;
1736 pHeaderBufPtr +=2;
1737 pTxBlk->MpduHeaderLen += 2;
1739 //pSaveBufPtr = pHeaderBufPtr;
1742 // padding at front of LLC header
1743 // LLC header should locate at 4-octets aligment
1745 // @@@ MpduHeaderLen excluding padding @@@
1747 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1748 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1749 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1751 return pHeaderBufPtr;
1756 VOID STA_AMPDU_Frame_Tx(
1757 IN PRTMP_ADAPTER pAd,
1758 IN TX_BLK *pTxBlk)
1760 HEADER_802_11 *pHeader_802_11;
1761 PUCHAR pHeaderBufPtr;
1762 USHORT FreeNumber;
1763 MAC_TABLE_ENTRY *pMacEntry;
1764 BOOLEAN bVLANPkt;
1765 PQUEUE_ENTRY pQEntry;
1767 ASSERT(pTxBlk);
1769 while(pTxBlk->TxPacketList.Head)
1771 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1772 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1773 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1775 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1776 continue;
1779 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1781 pMacEntry = pTxBlk->pMacEntry;
1782 if (pMacEntry->isCached)
1784 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1785 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1786 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1787 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1789 else
1791 STAFindCipherAlgorithm(pAd, pTxBlk);
1792 STABuildCommon802_11Header(pAd, pTxBlk);
1794 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1798 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1800 // skip common header
1801 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1804 // build QOS Control bytes
1806 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1807 *(pHeaderBufPtr+1) = 0;
1808 pHeaderBufPtr +=2;
1809 pTxBlk->MpduHeaderLen += 2;
1812 // build HTC+
1813 // HTC control filed following QoS field
1815 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1817 if (pMacEntry->isCached == FALSE)
1819 // mark HTC bit
1820 pHeader_802_11->FC.Order = 1;
1822 NdisZeroMemory(pHeaderBufPtr, 4);
1823 *(pHeaderBufPtr+3) |= 0x80;
1825 pHeaderBufPtr += 4;
1826 pTxBlk->MpduHeaderLen += 4;
1829 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1830 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1832 // skip 802.3 header
1833 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1834 pTxBlk->SrcBufLen -= LENGTH_802_3;
1836 // skip vlan tag
1837 if (bVLANPkt)
1839 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1840 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1844 // padding at front of LLC header
1845 // LLC header should locate at 4-octets aligment
1847 // @@@ MpduHeaderLen excluding padding @@@
1849 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1850 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1851 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1856 // Insert LLC-SNAP encapsulation - 8 octets
1858 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1859 if (pTxBlk->pExtraLlcSnapEncap)
1861 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1862 pHeaderBufPtr += 6;
1863 // get 2 octets (TypeofLen)
1864 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1865 pHeaderBufPtr += 2;
1866 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1871 if (pMacEntry->isCached)
1873 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1875 else
1877 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1879 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1880 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1881 pMacEntry->isCached = TRUE;
1884 // calculate Transmitted AMPDU count and ByteCount
1886 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1887 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1890 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1892 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1895 // Kick out Tx
1897 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1899 pAd->RalinkCounters.KickTxCount++;
1900 pAd->RalinkCounters.OneSecTxDoneCount++;
1906 VOID STA_AMSDU_Frame_Tx(
1907 IN PRTMP_ADAPTER pAd,
1908 IN TX_BLK *pTxBlk)
1910 PUCHAR pHeaderBufPtr;
1911 USHORT FreeNumber;
1912 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1913 USHORT totalMPDUSize=0;
1914 UCHAR *subFrameHeader;
1915 UCHAR padding = 0;
1916 USHORT FirstTx = 0, LastTxIdx = 0;
1917 BOOLEAN bVLANPkt;
1918 int frameNum = 0;
1919 PQUEUE_ENTRY pQEntry;
1922 ASSERT(pTxBlk);
1924 ASSERT((pTxBlk->TxPacketList.Number > 1));
1926 while(pTxBlk->TxPacketList.Head)
1928 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1929 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1930 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1932 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1933 continue;
1936 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1938 // skip 802.3 header
1939 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1940 pTxBlk->SrcBufLen -= LENGTH_802_3;
1942 // skip vlan tag
1943 if (bVLANPkt)
1945 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1946 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1949 if (frameNum == 0)
1951 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1953 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1954 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1956 else
1958 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1959 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1960 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1961 pHeaderBufPtr += padding;
1962 pTxBlk->MpduHeaderLen = padding;
1966 // A-MSDU subframe
1967 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1969 subFrameHeader = pHeaderBufPtr;
1970 subFramePayloadLen = pTxBlk->SrcBufLen;
1972 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1975 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1976 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1980 // Insert LLC-SNAP encapsulation - 8 octets
1982 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1984 subFramePayloadLen = pTxBlk->SrcBufLen;
1986 if (pTxBlk->pExtraLlcSnapEncap)
1988 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1989 pHeaderBufPtr += 6;
1990 // get 2 octets (TypeofLen)
1991 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1992 pHeaderBufPtr += 2;
1993 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1994 subFramePayloadLen += LENGTH_802_1_H;
1997 // update subFrame Length field
1998 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1999 subFrameHeader[13] = subFramePayloadLen & 0xFF;
2001 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2003 if (frameNum ==0)
2004 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2005 else
2006 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2008 frameNum++;
2010 pAd->RalinkCounters.KickTxCount++;
2011 pAd->RalinkCounters.OneSecTxDoneCount++;
2013 // calculate Transmitted AMSDU Count and ByteCount
2015 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
2016 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
2021 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2022 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2025 // Kick out Tx
2027 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2029 #endif // DOT11_N_SUPPORT //
2031 VOID STA_Legacy_Frame_Tx(
2032 IN PRTMP_ADAPTER pAd,
2033 IN TX_BLK *pTxBlk)
2035 HEADER_802_11 *pHeader_802_11;
2036 PUCHAR pHeaderBufPtr;
2037 USHORT FreeNumber;
2038 BOOLEAN bVLANPkt;
2039 PQUEUE_ENTRY pQEntry;
2041 ASSERT(pTxBlk);
2044 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2045 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2046 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2048 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2049 return;
2052 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
2054 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
2057 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
2058 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
2059 else
2060 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
2062 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2064 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
2065 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
2067 STAFindCipherAlgorithm(pAd, pTxBlk);
2068 STABuildCommon802_11Header(pAd, pTxBlk);
2071 // skip 802.3 header
2072 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2073 pTxBlk->SrcBufLen -= LENGTH_802_3;
2075 // skip vlan tag
2076 if (bVLANPkt)
2078 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2079 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2082 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2083 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
2085 // skip common header
2086 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2088 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2091 // build QOS Control bytes
2093 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2094 *(pHeaderBufPtr+1) = 0;
2095 pHeaderBufPtr +=2;
2096 pTxBlk->MpduHeaderLen += 2;
2099 // The remaining content of MPDU header should locate at 4-octets aligment
2100 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2101 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2102 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2107 // Insert LLC-SNAP encapsulation - 8 octets
2110 // if original Ethernet frame contains no LLC/SNAP,
2111 // then an extra LLC/SNAP encap is required
2113 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2114 if (pTxBlk->pExtraLlcSnapEncap)
2116 UCHAR vlan_size;
2118 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2119 pHeaderBufPtr += 6;
2120 // skip vlan tag
2121 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2122 // get 2 octets (TypeofLen)
2123 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2124 pHeaderBufPtr += 2;
2125 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2131 // prepare for TXWI
2132 // use Wcid as Key Index
2135 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2137 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2139 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2141 pAd->RalinkCounters.KickTxCount++;
2142 pAd->RalinkCounters.OneSecTxDoneCount++;
2145 // Kick out Tx
2147 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2151 VOID STA_ARalink_Frame_Tx(
2152 IN PRTMP_ADAPTER pAd,
2153 IN TX_BLK *pTxBlk)
2155 PUCHAR pHeaderBufPtr;
2156 USHORT FreeNumber;
2157 USHORT totalMPDUSize=0;
2158 USHORT FirstTx, LastTxIdx;
2159 int frameNum = 0;
2160 BOOLEAN bVLANPkt;
2161 PQUEUE_ENTRY pQEntry;
2164 ASSERT(pTxBlk);
2166 ASSERT((pTxBlk->TxPacketList.Number== 2));
2169 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
2170 while(pTxBlk->TxPacketList.Head)
2172 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2173 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2175 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2177 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2178 continue;
2181 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2183 // skip 802.3 header
2184 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2185 pTxBlk->SrcBufLen -= LENGTH_802_3;
2187 // skip vlan tag
2188 if (bVLANPkt)
2190 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2191 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2194 if (frameNum == 0)
2195 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2197 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2199 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2200 // will be updated after final frame was handled.
2201 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2205 // Insert LLC-SNAP encapsulation - 8 octets
2207 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2209 if (pTxBlk->pExtraLlcSnapEncap)
2211 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2212 pHeaderBufPtr += 6;
2213 // get 2 octets (TypeofLen)
2214 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2215 pHeaderBufPtr += 2;
2216 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2219 else
2220 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2222 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2223 pTxBlk->MpduHeaderLen = 0;
2225 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2226 // DA(6)+SA(6)+FrameType(2)
2227 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2228 pHeaderBufPtr += 12;
2229 // get 2 octets (TypeofLen)
2230 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2231 pHeaderBufPtr += 2;
2232 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2235 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2237 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2238 if (frameNum ==0)
2239 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2240 else
2241 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2243 frameNum++;
2245 pAd->RalinkCounters.OneSecTxAggregationCount++;
2246 pAd->RalinkCounters.KickTxCount++;
2247 pAd->RalinkCounters.OneSecTxDoneCount++;
2251 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2252 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2255 // Kick out Tx
2257 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2262 VOID STA_Fragment_Frame_Tx(
2263 IN RTMP_ADAPTER *pAd,
2264 IN TX_BLK *pTxBlk)
2266 HEADER_802_11 *pHeader_802_11;
2267 PUCHAR pHeaderBufPtr;
2268 USHORT FreeNumber;
2269 UCHAR fragNum = 0;
2270 PACKET_INFO PacketInfo;
2271 USHORT EncryptionOverhead = 0;
2272 UINT32 FreeMpduSize, SrcRemainingBytes;
2273 USHORT AckDuration;
2274 UINT NextMpduSize;
2275 BOOLEAN bVLANPkt;
2276 PQUEUE_ENTRY pQEntry;
2279 ASSERT(pTxBlk);
2281 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2282 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2283 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2285 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2286 return;
2289 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2290 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2292 STAFindCipherAlgorithm(pAd, pTxBlk);
2293 STABuildCommon802_11Header(pAd, pTxBlk);
2295 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2297 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2298 if (pTxBlk->pPacket == NULL)
2299 return;
2300 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2303 // skip 802.3 header
2304 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2305 pTxBlk->SrcBufLen -= LENGTH_802_3;
2308 // skip vlan tag
2309 if (bVLANPkt)
2311 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2312 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2315 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2316 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2319 // skip common header
2320 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2322 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2325 // build QOS Control bytes
2327 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2329 *(pHeaderBufPtr+1) = 0;
2330 pHeaderBufPtr +=2;
2331 pTxBlk->MpduHeaderLen += 2;
2335 // padding at front of LLC header
2336 // LLC header should locate at 4-octets aligment
2338 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2339 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2340 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2345 // Insert LLC-SNAP encapsulation - 8 octets
2348 // if original Ethernet frame contains no LLC/SNAP,
2349 // then an extra LLC/SNAP encap is required
2351 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2352 if (pTxBlk->pExtraLlcSnapEncap)
2354 UCHAR vlan_size;
2356 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2357 pHeaderBufPtr += 6;
2358 // skip vlan tag
2359 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2360 // get 2 octets (TypeofLen)
2361 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2362 pHeaderBufPtr += 2;
2363 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2367 // If TKIP is used and fragmentation is required. Driver has to
2368 // append TKIP MIC at tail of the scatter buffer
2369 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2370 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2373 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2374 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2375 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2376 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2377 pTxBlk->SrcBufLen += 8;
2378 pTxBlk->TotalFrameLen += 8;
2379 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2383 // calcuate the overhead bytes that encryption algorithm may add. This
2384 // affects the calculate of "duration" field
2386 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2387 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2388 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2389 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2390 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2391 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2392 else if (pTxBlk->CipherAlg == CIPHER_AES)
2393 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2394 else
2395 EncryptionOverhead = 0;
2397 // decide how much time an ACK/CTS frame will consume in the air
2398 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2400 // Init the total payload length of this frame.
2401 SrcRemainingBytes = pTxBlk->SrcBufLen;
2403 pTxBlk->TotalFragNum = 0xff;
2405 do {
2407 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2409 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2411 if (SrcRemainingBytes <= FreeMpduSize)
2412 { // this is the last or only fragment
2414 pTxBlk->SrcBufLen = SrcRemainingBytes;
2416 pHeader_802_11->FC.MoreFrag = 0;
2417 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2419 // Indicate the lower layer that this's the last fragment.
2420 pTxBlk->TotalFragNum = fragNum;
2422 else
2423 { // more fragment is required
2425 pTxBlk->SrcBufLen = FreeMpduSize;
2427 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2428 pHeader_802_11->FC.MoreFrag = 1;
2429 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2432 if (fragNum == 0)
2433 pTxBlk->FrameGap = IFS_HTTXOP;
2434 else
2435 pTxBlk->FrameGap = IFS_SIFS;
2437 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2439 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2441 pAd->RalinkCounters.KickTxCount++;
2442 pAd->RalinkCounters.OneSecTxDoneCount++;
2444 // Update the frame number, remaining size of the NDIS packet payload.
2446 // space for 802.11 header.
2447 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2448 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2450 fragNum++;
2451 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2452 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2454 pHeader_802_11->Frag++; // increase Frag #
2456 }while(SrcRemainingBytes > 0);
2459 // Kick out Tx
2461 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2465 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2466 while(_pTxBlk->TxPacketList.Head) \
2468 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2469 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2474 ========================================================================
2476 Routine Description:
2477 Copy frame from waiting queue into relative ring buffer and set
2478 appropriate ASIC register to kick hardware encryption before really
2479 sent out to air.
2481 Arguments:
2482 pAd Pointer to our adapter
2483 PNDIS_PACKET Pointer to outgoing Ndis frame
2484 NumberOfFrag Number of fragment required
2486 Return Value:
2487 None
2489 IRQL = DISPATCH_LEVEL
2491 Note:
2493 ========================================================================
2495 NDIS_STATUS STAHardTransmit(
2496 IN PRTMP_ADAPTER pAd,
2497 IN TX_BLK *pTxBlk,
2498 IN UCHAR QueIdx)
2500 NDIS_PACKET *pPacket;
2501 PQUEUE_ENTRY pQEntry;
2503 // ---------------------------------------------
2504 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2505 // ---------------------------------------------
2507 ASSERT(pTxBlk->TxPacketList.Number);
2508 if (pTxBlk->TxPacketList.Head == NULL)
2510 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2511 return NDIS_STATUS_FAILURE;
2514 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2516 #if 0 //def CARRIER_DETECTION_SUPPORT // Roger sync Carrier
2517 if ((pAd->CommonCfg.CarrierDetect.Enable == TRUE) && (isCarrierDetectExist(pAd) == TRUE))
2519 DBGPRINT(RT_DEBUG_INFO,("STAHardTransmit --> radar detect not in normal mode !!!\n"));
2520 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2521 return (NDIS_STATUS_FAILURE);
2523 #endif // CARRIER_DETECTION_SUPPORT //
2525 // ------------------------------------------------------------------
2526 // STEP 1. WAKE UP PHY
2527 // outgoing frame always wakeup PHY to prevent frame lost and
2528 // turn off PSM bit to improve performance
2529 // ------------------------------------------------------------------
2530 // not to change PSM bit, just send this frame out?
2531 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2533 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2534 AsicForceWakeup(pAd, TRUE);
2537 // It should not change PSM bit, when APSD turn on.
2538 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2539 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2540 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2542 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2543 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2544 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2547 switch (pTxBlk->TxFrameType)
2549 #ifdef DOT11_N_SUPPORT
2550 case TX_AMPDU_FRAME:
2551 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2552 break;
2553 case TX_AMSDU_FRAME:
2554 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2555 break;
2556 #endif // DOT11_N_SUPPORT //
2557 case TX_LEGACY_FRAME:
2558 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2559 break;
2560 case TX_MCAST_FRAME:
2561 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2562 break;
2563 case TX_RALINK_FRAME:
2564 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2565 break;
2566 case TX_FRAG_FRAME:
2567 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2568 break;
2569 default:
2571 // It should not happened!
2572 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2573 while(pTxBlk->TxPacketList.Number)
2575 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2576 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2577 if (pPacket)
2578 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2581 break;
2584 return (NDIS_STATUS_SUCCESS);
2588 ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2590 unsigned char *word = value;
2591 unsigned int ret = 0;
2592 unsigned int i;
2594 for(i=0; i < len; i++)
2596 int mod = i % 32;
2597 ret ^=(unsigned int) (word[i]) << mod;
2598 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2600 return ret;
2603 VOID Sta_Announce_or_Forward_802_3_Packet(
2604 IN PRTMP_ADAPTER pAd,
2605 IN PNDIS_PACKET pPacket,
2606 IN UCHAR FromWhichBSSID)
2608 if (TRUE
2611 announce_802_3_packet(pAd, pPacket);
2613 else
2615 // release packet
2616 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);