GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / rt2860 / sta / rtmp_data.c
blob5d348e9d9b797c1a09528290664e896307a9dbb7
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 -------- ---------- ----------------------------------------------
37 #include "../rt_config.h"
39 void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd,
40 struct rt_mac_table_entry *pEntry,
41 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
43 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
44 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
45 u8 *pTmpBuf;
47 if (pAd->StaCfg.WpaSupplicantUP) {
48 /* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */
49 /* TBD : process fragmented EAPol frames */
51 /* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */
52 if (pAd->StaCfg.IEEE8021X == TRUE &&
53 (EAP_CODE_SUCCESS ==
54 WpaCheckEapCode(pAd, pRxBlk->pData,
55 pRxBlk->DataSize,
56 LENGTH_802_1_H))) {
57 u8 *Key;
58 u8 CipherAlg;
59 int idx = 0;
61 DBGPRINT_RAW(RT_DEBUG_TRACE,
62 ("Receive EAP-SUCCESS Packet\n"));
63 /*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */
64 STA_PORT_SECURED(pAd);
66 if (pAd->StaCfg.IEEE8021x_required_keys ==
67 FALSE) {
68 idx = pAd->StaCfg.DesireSharedKeyId;
69 CipherAlg =
70 pAd->StaCfg.DesireSharedKey[idx].
71 CipherAlg;
72 Key =
73 pAd->StaCfg.DesireSharedKey[idx].
74 Key;
76 if (pAd->StaCfg.DesireSharedKey[idx].
77 KeyLen > 0) {
78 #ifdef RTMP_MAC_PCI
79 struct rt_mac_table_entry *pEntry =
80 &pAd->MacTab.
81 Content[BSSID_WCID];
83 /* Set key material and cipherAlg to Asic */
84 AsicAddSharedKeyEntry(pAd, BSS0,
85 idx,
86 CipherAlg,
87 Key, NULL,
88 NULL);
90 /* Assign group key info */
91 RTMPAddWcidAttributeEntry(pAd,
92 BSS0,
93 idx,
94 CipherAlg,
95 NULL);
97 /* Assign pairwise key info */
98 RTMPAddWcidAttributeEntry(pAd,
99 BSS0,
100 idx,
101 CipherAlg,
102 pEntry);
104 pAd->IndicateMediaState =
105 NdisMediaStateConnected;
106 pAd->ExtraInfo =
107 GENERAL_LINK_UP;
108 #endif /* RTMP_MAC_PCI // */
109 #ifdef RTMP_MAC_USB
110 union {
111 char buf[sizeof
112 (struct rt_ndis_802_11_wep)
114 MAX_LEN_OF_KEY
115 - 1];
116 struct rt_ndis_802_11_wep keyinfo;
118 WepKey;
119 int len;
121 NdisZeroMemory(&WepKey,
122 sizeof(WepKey));
123 len =
124 pAd->StaCfg.
125 DesireSharedKey[idx].KeyLen;
127 NdisMoveMemory(WepKey.keyinfo.
128 KeyMaterial,
129 pAd->StaCfg.
130 DesireSharedKey
131 [idx].Key,
132 pAd->StaCfg.
133 DesireSharedKey
134 [idx].KeyLen);
136 WepKey.keyinfo.KeyIndex =
137 0x80000000 + idx;
138 WepKey.keyinfo.KeyLength = len;
139 pAd->SharedKey[BSS0][idx].
140 KeyLen =
141 (u8)(len <= 5 ? 5 : 13);
143 pAd->IndicateMediaState =
144 NdisMediaStateConnected;
145 pAd->ExtraInfo =
146 GENERAL_LINK_UP;
147 /* need to enqueue cmd to thread */
148 RTUSBEnqueueCmdFromNdis(pAd,
149 OID_802_11_ADD_WEP,
150 TRUE,
151 &WepKey,
152 sizeof
153 (WepKey.
154 keyinfo)
155 + len -
157 #endif /* RTMP_MAC_USB // */
158 /* For Preventing ShardKey Table is cleared by remove key procedure. */
159 pAd->SharedKey[BSS0][idx].
160 CipherAlg = CipherAlg;
161 pAd->SharedKey[BSS0][idx].
162 KeyLen =
163 pAd->StaCfg.
164 DesireSharedKey[idx].KeyLen;
165 NdisMoveMemory(pAd->
166 SharedKey[BSS0]
167 [idx].Key,
168 pAd->StaCfg.
169 DesireSharedKey
170 [idx].Key,
171 pAd->StaCfg.
172 DesireSharedKey
173 [idx].KeyLen);
178 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
179 return;
181 } else {
182 /* Special DATA frame that has to pass to MLME */
183 /* 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process */
184 /* 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process */
186 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
187 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
188 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID,
189 pTmpBuf,
190 pRxBlk->DataSize +
191 LENGTH_802_11, pRxWI->RSSI0,
192 pRxWI->RSSI1, pRxWI->RSSI2,
193 pRxD->PlcpSignal);
194 DBGPRINT_RAW(RT_DEBUG_TRACE,
195 ("report EAPOL/AIRONET DATA to MLME (len=%d) !\n",
196 pRxBlk->DataSize));
200 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
201 return;
205 void STARxDataFrameAnnounce(struct rt_rtmp_adapter *pAd,
206 struct rt_mac_table_entry *pEntry,
207 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
210 /* non-EAP frame */
211 if (!RTMPCheckWPAframe
212 (pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) {
215 /* drop all non-EAP DATA frame before */
216 /* this client's Port-Access-Control is secured */
217 if (pRxBlk->pHeader->FC.Wep) {
218 /* unsupported cipher suite */
219 if (pAd->StaCfg.WepStatus ==
220 Ndis802_11EncryptionDisabled) {
221 /* release packet */
222 RELEASE_NDIS_PACKET(pAd,
223 pRxBlk->pRxPacket,
224 NDIS_STATUS_FAILURE);
225 return;
227 } else {
228 /* encryption in-use but receive a non-EAPOL clear text frame, drop it */
229 if ((pAd->StaCfg.WepStatus !=
230 Ndis802_11EncryptionDisabled)
231 && (pAd->StaCfg.PortSecured ==
232 WPA_802_1X_PORT_NOT_SECURED)) {
233 /* release packet */
234 RELEASE_NDIS_PACKET(pAd,
235 pRxBlk->pRxPacket,
236 NDIS_STATUS_FAILURE);
237 return;
241 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
242 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) {
243 /* Normal legacy, AMPDU or AMSDU */
244 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk,
245 FromWhichBSSID);
247 } else {
248 /* ARALINK */
249 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk,
250 FromWhichBSSID);
252 } else {
253 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
255 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
256 && (pAd->CommonCfg.bDisableReordering == 0)) {
257 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
258 } else {
259 /* Determin the destination of the EAP frame */
260 /* to WPA state machine or upper layer */
261 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk,
262 FromWhichBSSID);
267 /* For TKIP frame, calculate the MIC value */
268 BOOLEAN STACheckTkipMICValue(struct rt_rtmp_adapter *pAd,
269 struct rt_mac_table_entry *pEntry, struct rt_rx_blk *pRxBlk)
271 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
272 u8 *pData = pRxBlk->pData;
273 u16 DataSize = pRxBlk->DataSize;
274 u8 UserPriority = pRxBlk->UserPriority;
275 struct rt_cipher_key *pWpaKey;
276 u8 *pDA, *pSA;
278 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
280 pDA = pHeader->Addr1;
281 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) {
282 pSA = pHeader->Addr3;
283 } else {
284 pSA = pHeader->Addr2;
287 if (RTMPTkipCompareMICValue(pAd,
288 pData,
289 pDA,
290 pSA,
291 pWpaKey->RxMic,
292 UserPriority, DataSize) == FALSE) {
293 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n"));
295 if (pAd->StaCfg.WpaSupplicantUP) {
296 WpaSendMicFailureToWpaSupplicant(pAd,
297 (pWpaKey->Type ==
298 PAIRWISEKEY) ? TRUE :
299 FALSE);
300 } else {
301 RTMPReportMicError(pAd, pWpaKey);
304 /* release packet */
305 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
306 NDIS_STATUS_FAILURE);
307 return FALSE;
310 return TRUE;
313 /* */
314 /* All Rx routines use struct rt_rx_blk structure to hande rx events */
315 /* It is very important to build pRxBlk attributes */
316 /* 1. pHeader pointer to 802.11 Header */
317 /* 2. pData pointer to payload including LLC (just skip Header) */
318 /* 3. set payload size including LLC to DataSize */
319 /* 4. set some flags with RX_BLK_SET_FLAG() */
320 /* */
321 void STAHandleRxDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
323 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
324 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
325 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
326 void *pRxPacket = pRxBlk->pRxPacket;
327 BOOLEAN bFragment = FALSE;
328 struct rt_mac_table_entry *pEntry = NULL;
329 u8 FromWhichBSSID = BSS0;
330 u8 UserPriority = 0;
333 /* before LINK UP, all DATA frames are rejected */
334 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
335 /* release packet */
336 RELEASE_NDIS_PACKET(pAd, pRxPacket,
337 NDIS_STATUS_FAILURE);
338 return;
340 /* Drop not my BSS frames */
341 if (pRxD->MyBss == 0) {
343 /* release packet */
344 RELEASE_NDIS_PACKET(pAd, pRxPacket,
345 NDIS_STATUS_FAILURE);
346 return;
350 pAd->RalinkCounters.RxCountSinceLastNULL++;
351 if (pAd->CommonCfg.bAPSDCapable
352 && pAd->CommonCfg.APEdcaParm.bAPSDCapable
353 && (pHeader->FC.SubType & 0x08)) {
354 u8 *pData;
355 DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n"));
357 /* Qos bit 4 */
358 pData = (u8 *)pHeader + LENGTH_802_11;
359 if ((*pData >> 4) & 0x01) {
360 DBGPRINT(RT_DEBUG_INFO,
361 ("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
362 pAd->CommonCfg.bInServicePeriod = FALSE;
364 /* Force driver to fall into sleep mode when rcv EOSP frame */
365 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
366 u16 TbttNumToNextWakeUp;
367 u16 NextDtim =
368 pAd->StaCfg.DtimPeriod;
369 unsigned long Now;
371 NdisGetSystemUpTime(&Now);
372 NextDtim -=
373 (u16)(Now -
374 pAd->StaCfg.
375 LastBeaconRxTime) /
376 pAd->CommonCfg.BeaconPeriod;
378 TbttNumToNextWakeUp =
379 pAd->StaCfg.DefaultListenCount;
380 if (OPSTATUS_TEST_FLAG
381 (pAd, fOP_STATUS_RECEIVE_DTIM)
382 && (TbttNumToNextWakeUp > NextDtim))
383 TbttNumToNextWakeUp = NextDtim;
385 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
386 /* if WMM-APSD is failed, try to disable following line */
387 AsicSleepThenAutoWakeup(pAd,
388 TbttNumToNextWakeUp);
392 if ((pHeader->FC.MoreData)
393 && (pAd->CommonCfg.bInServicePeriod)) {
394 DBGPRINT(RT_DEBUG_TRACE,
395 ("Sending another trigger frame when More Data bit is set to 1\n"));
398 /* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */
399 if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */
401 /* release packet */
402 RELEASE_NDIS_PACKET(pAd, pRxPacket,
403 NDIS_STATUS_FAILURE);
404 return;
406 /* Drop not my BSS frame (we can not only check the MyBss bit in RxD) */
408 if (INFRA_ON(pAd)) {
409 /* Infrastructure mode, check address 2 for BSSID */
410 if (!RTMPEqualMemory
411 (&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) {
412 /* Receive frame not my BSSID */
413 /* release packet */
414 RELEASE_NDIS_PACKET(pAd, pRxPacket,
415 NDIS_STATUS_FAILURE);
416 return;
418 } else /* Ad-Hoc mode or Not associated */
420 /* Ad-Hoc mode, check address 3 for BSSID */
421 if (!RTMPEqualMemory
422 (&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) {
423 /* Receive frame not my BSSID */
424 /* release packet */
425 RELEASE_NDIS_PACKET(pAd, pRxPacket,
426 NDIS_STATUS_FAILURE);
427 return;
431 /* */
432 /* find pEntry */
433 /* */
434 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) {
435 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
436 } else {
437 /* 1. release packet if infra mode */
438 /* 2. new a pEntry if ad-hoc mode */
439 RELEASE_NDIS_PACKET(pAd, pRxPacket,
440 NDIS_STATUS_FAILURE);
441 return;
444 /* infra or ad-hoc */
445 if (INFRA_ON(pAd)) {
446 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
447 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
449 /* check Atheros Client */
450 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1)
451 && (pHeader->FC.Retry)) {
452 pEntry->bIAmBadAtheros = TRUE;
453 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
454 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
455 if (!STA_AES_ON(pAd)) {
456 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE,
457 FALSE);
462 pRxBlk->pData = (u8 *) pHeader;
464 /* */
465 /* update RxBlk->pData, DataSize */
466 /* 802.11 Header, QOS, HTC, Hw Padding */
467 /* */
469 /* 1. skip 802.11 HEADER */
471 pRxBlk->pData += LENGTH_802_11;
472 pRxBlk->DataSize -= LENGTH_802_11;
475 /* 2. QOS */
476 if (pHeader->FC.SubType & 0x08) {
477 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
478 UserPriority = *(pRxBlk->pData) & 0x0f;
479 /* bit 7 in QoS Control field signals the HT A-MSDU format */
480 if ((*pRxBlk->pData) & 0x80) {
481 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
483 /* skip QOS contorl field */
484 pRxBlk->pData += 2;
485 pRxBlk->DataSize -= 2;
487 pRxBlk->UserPriority = UserPriority;
489 /* check if need to resend PS Poll when received packet with MoreData = 1 */
490 if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) {
491 if ((((UserPriority == 0) || (UserPriority == 3)) &&
492 pAd->CommonCfg.bAPSDAC_BE == 0) ||
493 (((UserPriority == 1) || (UserPriority == 2)) &&
494 pAd->CommonCfg.bAPSDAC_BK == 0) ||
495 (((UserPriority == 4) || (UserPriority == 5)) &&
496 pAd->CommonCfg.bAPSDAC_VI == 0) ||
497 (((UserPriority == 6) || (UserPriority == 7)) &&
498 pAd->CommonCfg.bAPSDAC_VO == 0)) {
499 /* non-UAPSD delivery-enabled AC */
500 RTMP_PS_POLL_ENQUEUE(pAd);
503 /* 3. Order bit: A-Ralink or HTC+ */
504 if (pHeader->FC.Order) {
505 #ifdef AGGREGATION_SUPPORT
506 if ((pRxWI->PHYMODE <= MODE_OFDM)
507 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
509 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
510 } else
511 #endif /* AGGREGATION_SUPPORT // */
513 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
514 /* skip HTC contorl field */
515 pRxBlk->pData += 4;
516 pRxBlk->DataSize -= 4;
519 /* 4. skip HW padding */
520 if (pRxD->L2PAD) {
521 /* just move pData pointer */
522 /* because DataSize excluding HW padding */
523 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
524 pRxBlk->pData += 2;
527 if (pRxD->BA) {
528 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
530 /* */
531 /* Case I Process Broadcast & Multicast data frame */
532 /* */
533 if (pRxD->Bcast || pRxD->Mcast) {
534 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
536 /* Drop Mcast/Bcast frame with fragment bit on */
537 if (pHeader->FC.MoreFrag) {
538 /* release packet */
539 RELEASE_NDIS_PACKET(pAd, pRxPacket,
540 NDIS_STATUS_FAILURE);
541 return;
543 /* Filter out Bcast frame which AP relayed for us */
544 if (pHeader->FC.FrDs
545 && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) {
546 /* release packet */
547 RELEASE_NDIS_PACKET(pAd, pRxPacket,
548 NDIS_STATUS_FAILURE);
549 return;
552 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
553 return;
554 } else if (pRxD->U2M) {
555 pAd->LastRxRate =
556 (u16)((pRxWI->MCS) + (pRxWI->BW << 7) +
557 (pRxWI->ShortGI << 8) + (pRxWI->PHYMODE << 14));
559 if (ADHOC_ON(pAd)) {
560 pEntry = MacTableLookup(pAd, pHeader->Addr2);
561 if (pEntry)
562 Update_Rssi_Sample(pAd, &pEntry->RssiSample,
563 pRxWI);
566 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
568 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
569 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
571 pAd->RalinkCounters.OneSecRxOkDataCnt++;
573 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) {
574 /* re-assemble the fragmented packets */
575 /* return complete frame (pRxPacket) or NULL */
576 bFragment = TRUE;
577 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
580 if (pRxPacket) {
581 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
583 /* process complete frame */
584 if (bFragment && (pRxD->Decrypted)
585 && (pEntry->WepStatus ==
586 Ndis802_11Encryption2Enabled)) {
587 /* Minus MIC length */
588 pRxBlk->DataSize -= 8;
590 /* For TKIP frame, calculate the MIC value */
591 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) ==
592 FALSE) {
593 return;
597 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk,
598 FromWhichBSSID);
599 return;
600 } else {
601 /* just return */
602 /* because RTMPDeFragmentDataFrame() will release rx packet, */
603 /* if packet is fragmented */
604 return;
608 ASSERT(0);
609 /* release packet */
610 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
613 void STAHandleRxMgmtFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
615 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
616 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
617 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
618 void *pRxPacket = pRxBlk->pRxPacket;
620 do {
622 /* check if need to resend PS Poll when received packet with MoreData = 1 */
623 if ((pAd->StaCfg.Psm == PWR_SAVE)
624 && (pHeader->FC.MoreData == 1)) {
625 /* for UAPSD, all management frames will be VO priority */
626 if (pAd->CommonCfg.bAPSDAC_VO == 0) {
627 /* non-UAPSD delivery-enabled AC */
628 RTMP_PS_POLL_ENQUEUE(pAd);
632 /* TODO: if MoreData == 0, station can go to sleep */
634 /* We should collect RSSI not only U2M data but also my beacon */
635 if ((pHeader->FC.SubType == SUBTYPE_BEACON)
636 && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
637 && (pAd->RxAnt.EvaluatePeriod == 0)) {
638 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
640 pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
641 pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
644 /* First check the size, it MUST not exceed the mlme queue size */
645 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) {
646 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
647 break;
650 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader,
651 pRxWI->MPDUtotalByteCount,
652 pRxWI->RSSI0, pRxWI->RSSI1,
653 pRxWI->RSSI2, pRxD->PlcpSignal);
654 } while (FALSE);
656 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
659 void STAHandleRxControlFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
661 struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
662 struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
663 void *pRxPacket = pRxBlk->pRxPacket;
665 switch (pHeader->FC.SubType) {
666 case SUBTYPE_BLOCK_ACK_REQ:
668 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID,
669 (pRxWI->MPDUtotalByteCount),
670 (struct rt_frame_ba_req *) pHeader);
672 break;
673 case SUBTYPE_BLOCK_ACK:
674 case SUBTYPE_ACK:
675 default:
676 break;
679 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
683 ========================================================================
685 Routine Description:
686 Process RxDone interrupt, running in DPC level
688 Arguments:
689 pAd Pointer to our adapter
691 Return Value:
692 None
694 IRQL = DISPATCH_LEVEL
696 Note:
697 This routine has to maintain Rx ring read pointer.
698 Need to consider QOS DATA format when converting to 802.3
699 ========================================================================
701 BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc)
703 int Status;
704 u32 RxProcessed, RxPending;
705 BOOLEAN bReschedule = FALSE;
706 PRT28XX_RXD_STRUC pRxD;
707 u8 *pData;
708 struct rt_rxwi * pRxWI;
709 void *pRxPacket;
710 struct rt_header_802_11 * pHeader;
711 struct rt_rx_blk RxCell;
713 RxProcessed = RxPending = 0;
715 /* process whole rx ring */
716 while (1) {
718 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
719 fRTMP_ADAPTER_RESET_IN_PROGRESS |
720 fRTMP_ADAPTER_HALT_IN_PROGRESS |
721 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
722 !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
723 break;
725 #ifdef RTMP_MAC_PCI
726 if (RxProcessed++ > MAX_RX_PROCESS_CNT) {
727 /* need to reschedule rx handle */
728 bReschedule = TRUE;
729 break;
731 #endif /* RTMP_MAC_PCI // */
733 RxProcessed++; /* test */
735 /* 1. allocate a new data packet into rx ring to replace received packet */
736 /* then processing the received packet */
737 /* 2. the callee must take charge of release of packet */
738 /* 3. As far as driver is concerned , */
739 /* the rx packet must */
740 /* a. be indicated to upper layer or */
741 /* b. be released if it is discarded */
742 pRxPacket =
743 GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule,
744 &RxPending);
745 if (pRxPacket == NULL) {
746 /* no more packet to process */
747 break;
749 /* get rx ring descriptor */
750 pRxD = &(RxCell.RxD);
751 /* get rx data buffer */
752 pData = GET_OS_PKT_DATAPTR(pRxPacket);
753 pRxWI = (struct rt_rxwi *) pData;
754 pHeader = (struct rt_header_802_11 *) (pData + RXWI_SIZE);
756 /* build RxCell */
757 RxCell.pRxWI = pRxWI;
758 RxCell.pHeader = pHeader;
759 RxCell.pRxPacket = pRxPacket;
760 RxCell.pData = (u8 *) pHeader;
761 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
762 RxCell.Flags = 0;
764 /* Increase Total receive byte counter after real data received no mater any error or not */
765 pAd->RalinkCounters.ReceivedByteCount +=
766 pRxWI->MPDUtotalByteCount;
767 pAd->RalinkCounters.OneSecReceivedByteCount +=
768 pRxWI->MPDUtotalByteCount;
769 pAd->RalinkCounters.RxCount++;
771 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
773 if (pRxWI->MPDUtotalByteCount < 14)
774 Status = NDIS_STATUS_FAILURE;
776 if (MONITOR_ON(pAd)) {
777 send_monitor_packets(pAd, &RxCell);
778 break;
781 /* STARxDoneInterruptHandle() is called in rtusb_bulk.c */
783 /* Check for all RxD errors */
784 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
786 /* Handle the received frame */
787 if (Status == NDIS_STATUS_SUCCESS) {
788 switch (pHeader->FC.Type) {
789 /* CASE I, receive a DATA frame */
790 case BTYPE_DATA:
792 /* process DATA frame */
793 STAHandleRxDataFrame(pAd, &RxCell);
795 break;
796 /* CASE II, receive a MGMT frame */
797 case BTYPE_MGMT:
799 STAHandleRxMgmtFrame(pAd, &RxCell);
801 break;
802 /* CASE III. receive a CNTL frame */
803 case BTYPE_CNTL:
805 STAHandleRxControlFrame(pAd, &RxCell);
807 break;
808 /* discard other type */
809 default:
810 RELEASE_NDIS_PACKET(pAd, pRxPacket,
811 NDIS_STATUS_FAILURE);
812 break;
814 } else {
815 pAd->Counters8023.RxErrors++;
816 /* discard this frame */
817 RELEASE_NDIS_PACKET(pAd, pRxPacket,
818 NDIS_STATUS_FAILURE);
822 return bReschedule;
826 ========================================================================
828 Routine Description:
829 Arguments:
830 pAd Pointer to our adapter
832 IRQL = DISPATCH_LEVEL
834 ========================================================================
836 void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd)
838 AsicForceWakeup(pAd, FALSE);
842 ========================================================================
843 Routine Description:
844 Early checking and OS-depened parsing for Tx packet send to our STA driver.
846 Arguments:
847 void * MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
848 void ** ppPacketArray The packet array need to do transmission.
849 u32 NumberOfPackets Number of packet in packet array.
851 Return Value:
852 NONE
854 Note:
855 This function do early checking and classification for send-out packet.
856 You only can put OS-depened & STA related code in here.
857 ========================================================================
859 void STASendPackets(void *MiniportAdapterContext,
860 void **ppPacketArray, u32 NumberOfPackets)
862 u32 Index;
863 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)MiniportAdapterContext;
864 void *pPacket;
865 BOOLEAN allowToSend = FALSE;
867 for (Index = 0; Index < NumberOfPackets; Index++) {
868 pPacket = ppPacketArray[Index];
870 do {
871 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)
872 || RTMP_TEST_FLAG(pAd,
873 fRTMP_ADAPTER_HALT_IN_PROGRESS)
874 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) {
875 /* Drop send request since hardware is in reset state */
876 break;
877 } else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) {
878 /* Drop send request since there are no physical connection yet */
879 break;
880 } else {
881 /* Record that orignal packet source is from NDIS layer,so that */
882 /* later on driver knows how to release this NDIS PACKET */
883 RTMP_SET_PACKET_WCID(pPacket, 0); /* this field is useless when in STA mode */
884 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
885 NDIS_SET_PACKET_STATUS(pPacket,
886 NDIS_STATUS_PENDING);
887 pAd->RalinkCounters.PendingNdisPacketCount++;
889 allowToSend = TRUE;
891 } while (FALSE);
893 if (allowToSend == TRUE)
894 STASendPacket(pAd, pPacket);
895 else
896 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
899 /* Dequeue outgoing frames from TxSwQueue[] and process it */
900 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
905 ========================================================================
906 Routine Description:
907 This routine is used to do packet parsing and classification for Tx packet
908 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
909 class.
911 Arguments:
912 pAd Pointer to our adapter
913 pPacket Pointer to send packet
915 Return Value:
916 NDIS_STATUS_SUCCESS If success to queue the packet into TxSwQueue.
917 NDIS_STATUS_FAILURE If failed to do en-queue.
919 Note:
920 You only can put OS-indepened & STA related code in here.
921 ========================================================================
923 int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
925 struct rt_packet_info PacketInfo;
926 u8 *pSrcBufVA;
927 u32 SrcBufLen;
928 u32 AllowFragSize;
929 u8 NumberOfFrag;
930 u8 RTSRequired;
931 u8 QueIdx, UserPriority;
932 struct rt_mac_table_entry *pEntry = NULL;
933 unsigned int IrqFlags;
934 u8 FlgIsIP = 0;
935 u8 Rate;
937 /* Prepare packet information structure for buffer descriptor */
938 /* chained within a single NDIS packet. */
939 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
941 if (pSrcBufVA == NULL) {
942 DBGPRINT(RT_DEBUG_ERROR,
943 ("STASendPacket --> pSrcBufVA == NULL !SrcBufLen=%x\n",
944 SrcBufLen));
945 /* Resourece is low, system did not allocate virtual address */
946 /* return NDIS_STATUS_FAILURE directly to upper layer */
947 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
948 return NDIS_STATUS_FAILURE;
951 if (SrcBufLen < 14) {
952 DBGPRINT(RT_DEBUG_ERROR,
953 ("STASendPacket --> Ndis Packet buffer error!\n"));
954 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
955 return (NDIS_STATUS_FAILURE);
957 /* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */
958 /* Note multicast packets in adhoc also use BSSID_WCID index. */
960 if (INFRA_ON(pAd)) {
962 pEntry = &pAd->MacTab.Content[BSSID_WCID];
963 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
964 Rate = pAd->CommonCfg.TxRate;
966 } else if (ADHOC_ON(pAd)) {
967 if (*pSrcBufVA & 0x01) {
968 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
969 pEntry = &pAd->MacTab.Content[MCAST_WCID];
970 } else {
971 pEntry = MacTableLookup(pAd, pSrcBufVA);
973 Rate = pAd->CommonCfg.TxRate;
977 if (!pEntry) {
978 DBGPRINT(RT_DEBUG_ERROR,
979 ("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n",
980 PRINT_MAC(pSrcBufVA)));
981 /* Resourece is low, system did not allocate virtual address */
982 /* return NDIS_STATUS_FAILURE directly to upper layer */
983 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
984 return NDIS_STATUS_FAILURE;
987 if (ADHOC_ON(pAd)
989 RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
991 /* */
992 /* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */
993 /* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */
994 RTMPCheckEtherType(pAd, pPacket);
996 /* */
997 /* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */
998 /* */
999 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1000 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1001 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1002 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1003 || (pAd->StaCfg.IEEE8021X == TRUE)
1005 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
1006 || (pAd->StaCfg.MicErrCnt >= 2))
1007 && (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)
1009 DBGPRINT(RT_DEBUG_TRACE,
1010 ("STASendPacket --> Drop packet before port secured!\n"));
1011 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1013 return (NDIS_STATUS_FAILURE);
1016 /* STEP 1. Decide number of fragments required to deliver this MSDU. */
1017 /* The estimation here is not very accurate because difficult to */
1018 /* take encryption overhead into consideration here. The result */
1019 /* "NumberOfFrag" is then just used to pre-check if enough free */
1020 /* TXD are available to hold this MSDU. */
1022 if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */
1023 NumberOfFrag = 1;
1024 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1025 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1026 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1027 NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1028 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX)
1029 || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1030 NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */
1031 else {
1032 /* The calculated "NumberOfFrag" is a rough estimation because of various */
1033 /* encryption/encapsulation overhead not taken into consideration. This number is just */
1034 /* used to make sure enough free TXD are available before fragmentation takes place. */
1035 /* In case the actual required number of fragments of an NDIS packet */
1036 /* excceeds "NumberOfFrag"caculated here and not enough free TXD available, the */
1037 /* last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of */
1038 /* resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should */
1039 /* rarely happen and the penalty is just like a TX RETRY fail. Affordable. */
1041 AllowFragSize =
1042 (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 -
1043 LENGTH_CRC;
1044 NumberOfFrag =
1045 ((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1046 LENGTH_802_1_H) / AllowFragSize) + 1;
1047 /* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */
1048 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1049 LENGTH_802_1_H) % AllowFragSize) == 0) {
1050 NumberOfFrag--;
1054 /* Save fragment number to Ndis packet reserved field */
1055 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1057 /* STEP 2. Check the requirement of RTS: */
1058 /* If multiple fragment required, RTS is required only for the first fragment */
1059 /* if the fragment size large than RTS threshold */
1060 /* For RT28xx, Let ASIC send RTS/CTS */
1061 /* RTMP_SET_PACKET_RTS(pPacket, 0); */
1062 if (NumberOfFrag > 1)
1063 RTSRequired =
1064 (pAd->CommonCfg.FragmentThreshold >
1065 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1066 else
1067 RTSRequired =
1068 (PacketInfo.TotalPacketLength >
1069 pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1071 /* Save RTS requirement to Ndis packet reserved field */
1072 RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
1073 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1075 /* */
1076 /* STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> */
1077 /* */
1078 UserPriority = 0;
1079 QueIdx = QID_AC_BE;
1080 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1081 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) {
1082 u16 Protocol;
1083 u8 LlcSnapLen = 0, Byte0, Byte1;
1084 do {
1085 /* get Ethernet protocol field */
1086 Protocol =
1087 (u16)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1088 if (Protocol <= 1500) {
1089 /* get Ethernet protocol field from LLC/SNAP */
1090 if (Sniff2BytesFromNdisBuffer
1091 (PacketInfo.pFirstBuffer, LENGTH_802_3 + 6,
1092 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1093 break;
1095 Protocol = (u16)((Byte0 << 8) + Byte1);
1096 LlcSnapLen = 8;
1098 /* always AC_BE for non-IP packet */
1099 if (Protocol != 0x0800)
1100 break;
1102 /* get IP header */
1103 if (Sniff2BytesFromNdisBuffer
1104 (PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen,
1105 &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1106 break;
1108 /* return AC_BE if packet is not IPv4 */
1109 if ((Byte0 & 0xf0) != 0x40)
1110 break;
1112 FlgIsIP = 1;
1113 UserPriority = (Byte1 & 0xe0) >> 5;
1114 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1116 /* TODO: have to check ACM bit. apply TSPEC if ACM is ON */
1117 /* TODO: downgrade UP & QueIdx before passing ACM */
1119 Under WMM ACM control, we dont need to check the bit;
1120 Or when a TSPEC is built for VO but we will change to issue
1121 BA session for BE here, so we will not use BA to send VO packets.
1123 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) {
1124 UserPriority = 0;
1125 QueIdx = QID_AC_BE;
1127 } while (FALSE);
1130 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1132 /* Make sure SendTxWait queue resource won't be used by other threads */
1133 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1134 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) {
1135 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1136 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1138 return NDIS_STATUS_FAILURE;
1139 } else {
1140 InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx],
1141 PACKET_TO_QUEUE_ENTRY(pPacket));
1143 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1145 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) &&
1146 IS_HT_STA(pEntry)) {
1147 /*struct rt_mac_table_entry *pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; */
1148 if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) &&
1149 ((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) &&
1150 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1151 /* For IOT compatibility, if */
1152 /* 1. It is Ralink chip or */
1153 /* 2. It is OPEN or AES mode, */
1154 /* then BA session can be bulit. */
1155 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0)
1156 || (pEntry->WepStatus != Ndis802_11WEPEnabled
1157 && pEntry->WepStatus !=
1158 Ndis802_11Encryption2Enabled))
1160 BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10,
1161 FALSE);
1165 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */
1166 return NDIS_STATUS_SUCCESS;
1170 ========================================================================
1172 Routine Description:
1173 This subroutine will scan through releative ring descriptor to find
1174 out avaliable free ring descriptor and compare with request size.
1176 Arguments:
1177 pAd Pointer to our adapter
1178 QueIdx Selected TX Ring
1180 Return Value:
1181 NDIS_STATUS_FAILURE Not enough free descriptor
1182 NDIS_STATUS_SUCCESS Enough free descriptor
1184 IRQL = PASSIVE_LEVEL
1185 IRQL = DISPATCH_LEVEL
1187 Note:
1189 ========================================================================
1191 #ifdef RTMP_MAC_PCI
1192 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1193 u8 QueIdx,
1194 u8 NumberRequired, u8 *FreeNumberIs)
1196 unsigned long FreeNumber = 0;
1197 int Status = NDIS_STATUS_FAILURE;
1199 switch (QueIdx) {
1200 case QID_AC_BK:
1201 case QID_AC_BE:
1202 case QID_AC_VI:
1203 case QID_AC_VO:
1204 if (pAd->TxRing[QueIdx].TxSwFreeIdx >
1205 pAd->TxRing[QueIdx].TxCpuIdx)
1206 FreeNumber =
1207 pAd->TxRing[QueIdx].TxSwFreeIdx -
1208 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1209 else
1210 FreeNumber =
1211 pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE -
1212 pAd->TxRing[QueIdx].TxCpuIdx - 1;
1214 if (FreeNumber >= NumberRequired)
1215 Status = NDIS_STATUS_SUCCESS;
1216 break;
1218 case QID_MGMT:
1219 if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1220 FreeNumber =
1221 pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx -
1223 else
1224 FreeNumber =
1225 pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE -
1226 pAd->MgmtRing.TxCpuIdx - 1;
1228 if (FreeNumber >= NumberRequired)
1229 Status = NDIS_STATUS_SUCCESS;
1230 break;
1232 default:
1233 DBGPRINT(RT_DEBUG_ERROR,
1234 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1235 break;
1237 *FreeNumberIs = (u8)FreeNumber;
1239 return (Status);
1241 #endif /* RTMP_MAC_PCI // */
1242 #ifdef RTMP_MAC_USB
1244 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1245 If no frame need to send, go to sleep, else, still wake up.
1247 int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1248 u8 QueIdx,
1249 u8 NumberRequired, u8 *FreeNumberIs)
1251 /*unsigned long FreeNumber = 0; */
1252 int Status = NDIS_STATUS_FAILURE;
1253 unsigned long IrqFlags;
1254 struct rt_ht_tx_context *pHTTXContext;
1256 switch (QueIdx) {
1257 case QID_AC_BK:
1258 case QID_AC_BE:
1259 case QID_AC_VI:
1260 case QID_AC_VO:
1262 pHTTXContext = &pAd->TxContext[QueIdx];
1263 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx],
1264 IrqFlags);
1265 if ((pHTTXContext->CurWritePosition !=
1266 pHTTXContext->ENextBulkOutPosition)
1267 || (pHTTXContext->IRPPending == TRUE)) {
1268 Status = NDIS_STATUS_FAILURE;
1269 } else {
1270 Status = NDIS_STATUS_SUCCESS;
1272 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
1273 IrqFlags);
1275 break;
1276 case QID_MGMT:
1277 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1278 Status = NDIS_STATUS_FAILURE;
1279 else
1280 Status = NDIS_STATUS_SUCCESS;
1281 break;
1282 default:
1283 DBGPRINT(RT_DEBUG_ERROR,
1284 ("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1285 break;
1288 return (Status);
1290 #endif /* RTMP_MAC_USB // */
1292 void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd)
1296 void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd,
1297 u8 TxRate, IN BOOLEAN bQosNull)
1299 u8 NullFrame[48];
1300 unsigned long Length;
1301 struct rt_header_802_11 * pHeader_802_11;
1303 /* WPA 802.1x secured port control */
1304 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1305 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1306 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1307 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1308 || (pAd->StaCfg.IEEE8021X == TRUE)
1309 ) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) {
1310 return;
1313 NdisZeroMemory(NullFrame, 48);
1314 Length = sizeof(struct rt_header_802_11);
1316 pHeader_802_11 = (struct rt_header_802_11 *) NullFrame;
1318 pHeader_802_11->FC.Type = BTYPE_DATA;
1319 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1320 pHeader_802_11->FC.ToDs = 1;
1321 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1322 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1323 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1325 if (pAd->CommonCfg.bAPSDForcePowerSave) {
1326 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1327 } else {
1328 pHeader_802_11->FC.PwrMgmt =
1329 (pAd->StaCfg.Psm == PWR_SAVE) ? 1 : 0;
1331 pHeader_802_11->Duration =
1332 pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1334 pAd->Sequence++;
1335 pHeader_802_11->Sequence = pAd->Sequence;
1337 /* Prepare QosNull function frame */
1338 if (bQosNull) {
1339 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1341 /* copy QOS control bytes */
1342 NullFrame[Length] = 0;
1343 NullFrame[Length + 1] = 0;
1344 Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
1347 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1351 /* IRQL = DISPATCH_LEVEL */
1352 void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd,
1353 u8 *pDA,
1354 IN unsigned int NextMpduSize,
1355 u8 TxRate,
1356 u8 RTSRate,
1357 u16 AckDuration, u8 QueIdx, u8 FrameGap)
1361 /* -------------------------------------------------------- */
1362 /* FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM */
1363 /* Find the WPA key, either Group or Pairwise Key */
1364 /* LEAP + TKIP also use WPA key. */
1365 /* -------------------------------------------------------- */
1366 /* Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst */
1367 /* In Cisco CCX 2.0 Leap Authentication */
1368 /* WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey */
1369 /* Instead of the SharedKey, SharedKey Length may be Zero. */
1370 void STAFindCipherAlgorithm(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1372 NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */
1373 u8 CipherAlg = CIPHER_NONE; /* cipher alogrithm */
1374 u8 KeyIdx = 0xff;
1375 u8 *pSrcBufVA;
1376 struct rt_cipher_key *pKey = NULL;
1378 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1381 /* Select Cipher */
1382 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1383 Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */
1384 else
1385 Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */
1387 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) {
1388 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <=
1389 CIPHER_CKIP128);
1391 /* 4-way handshaking frame must be clear */
1392 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))
1393 && (pAd->SharedKey[BSS0][0].CipherAlg)
1394 && (pAd->SharedKey[BSS0][0].KeyLen)) {
1395 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1396 KeyIdx = 0;
1398 } else if (Cipher == Ndis802_11Encryption1Enabled) {
1399 KeyIdx = pAd->StaCfg.DefaultKeyId;
1400 } else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1401 (Cipher == Ndis802_11Encryption3Enabled)) {
1402 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */
1403 KeyIdx = pAd->StaCfg.DefaultKeyId;
1404 else if (pAd->SharedKey[BSS0][0].KeyLen)
1405 KeyIdx = 0;
1406 else
1407 KeyIdx = pAd->StaCfg.DefaultKeyId;
1410 if (KeyIdx == 0xff)
1411 CipherAlg = CIPHER_NONE;
1412 else if ((Cipher == Ndis802_11EncryptionDisabled)
1413 || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1414 CipherAlg = CIPHER_NONE;
1415 else if (pAd->StaCfg.WpaSupplicantUP &&
1416 (Cipher == Ndis802_11Encryption1Enabled) &&
1417 (pAd->StaCfg.IEEE8021X == TRUE) &&
1418 (pAd->StaCfg.PortSecured ==
1419 WPA_802_1X_PORT_NOT_SECURED))
1420 CipherAlg = CIPHER_NONE;
1421 else {
1422 /*Header_802_11.FC.Wep = 1; */
1423 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1424 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1428 pTxBlk->CipherAlg = CipherAlg;
1429 pTxBlk->pKey = pKey;
1432 void STABuildCommon802_11Header(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1434 struct rt_header_802_11 *pHeader_802_11;
1436 /* */
1437 /* MAKE A COMMON 802.11 HEADER */
1438 /* */
1440 /* normal wlan header size : 24 octets */
1441 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1443 pHeader_802_11 =
1444 (struct rt_header_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1446 NdisZeroMemory(pHeader_802_11, sizeof(struct rt_header_802_11));
1448 pHeader_802_11->FC.FrDs = 0;
1449 pHeader_802_11->FC.Type = BTYPE_DATA;
1450 pHeader_802_11->FC.SubType =
1451 ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA :
1452 SUBTYPE_DATA);
1454 if (pTxBlk->pMacEntry) {
1455 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) {
1456 pHeader_802_11->Sequence =
1457 pTxBlk->pMacEntry->NonQosDataSeq;
1458 pTxBlk->pMacEntry->NonQosDataSeq =
1459 (pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ;
1460 } else {
1462 pHeader_802_11->Sequence =
1463 pTxBlk->pMacEntry->TxSeq[pTxBlk->
1464 UserPriority];
1465 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] =
1466 (pTxBlk->pMacEntry->
1467 TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1470 } else {
1471 pHeader_802_11->Sequence = pAd->Sequence;
1472 pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
1475 pHeader_802_11->Frag = 0;
1477 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1480 if (INFRA_ON(pAd)) {
1482 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1483 pAd->CommonCfg.Bssid);
1484 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1485 pAd->CurrentAddress);
1486 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1487 pTxBlk->pSrcBufHeader);
1488 pHeader_802_11->FC.ToDs = 1;
1490 } else if (ADHOC_ON(pAd)) {
1491 COPY_MAC_ADDR(pHeader_802_11->Addr1,
1492 pTxBlk->pSrcBufHeader);
1493 COPY_MAC_ADDR(pHeader_802_11->Addr2,
1494 pAd->CurrentAddress);
1495 COPY_MAC_ADDR(pHeader_802_11->Addr3,
1496 pAd->CommonCfg.Bssid);
1497 pHeader_802_11->FC.ToDs = 0;
1501 if (pTxBlk->CipherAlg != CIPHER_NONE)
1502 pHeader_802_11->FC.Wep = 1;
1504 /* ----------------------------------------------------------------- */
1505 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1506 /* ----------------------------------------------------------------- */
1507 if (pAd->CommonCfg.bAPSDForcePowerSave)
1508 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1509 else
1510 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1513 void STABuildCache802_11Header(struct rt_rtmp_adapter *pAd,
1514 struct rt_tx_blk *pTxBlk, u8 * pHeader)
1516 struct rt_mac_table_entry *pMacEntry;
1517 struct rt_header_802_11 * pHeader80211;
1519 pHeader80211 = (struct rt_header_802_11 *) pHeader;
1520 pMacEntry = pTxBlk->pMacEntry;
1522 /* */
1523 /* Update the cached 802.11 HEADER */
1524 /* */
1526 /* normal wlan header size : 24 octets */
1527 pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1529 /* More Bit */
1530 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1532 /* Sequence */
1533 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1534 pMacEntry->TxSeq[pTxBlk->UserPriority] =
1535 (pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1538 /* Check if the frame can be sent through DLS direct link interface */
1539 /* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */
1541 /* The addr3 of normal packet send from DS is Dest Mac address. */
1542 if (ADHOC_ON(pAd))
1543 COPY_MAC_ADDR(pHeader80211->Addr3,
1544 pAd->CommonCfg.Bssid);
1545 else
1546 COPY_MAC_ADDR(pHeader80211->Addr3,
1547 pTxBlk->pSrcBufHeader);
1550 /* ----------------------------------------------------------------- */
1551 /* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1552 /* ----------------------------------------------------------------- */
1553 if (pAd->CommonCfg.bAPSDForcePowerSave)
1554 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1555 else
1556 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1559 static inline u8 *STA_Build_ARalink_Frame_Header(struct rt_rtmp_adapter *pAd,
1560 struct rt_tx_blk *pTxBlk)
1562 u8 *pHeaderBufPtr;
1563 struct rt_header_802_11 *pHeader_802_11;
1564 void *pNextPacket;
1565 u32 nextBufLen;
1566 struct rt_queue_entry *pQEntry;
1568 STAFindCipherAlgorithm(pAd, pTxBlk);
1569 STABuildCommon802_11Header(pAd, pTxBlk);
1571 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1572 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1574 /* steal "order" bit to mark "aggregation" */
1575 pHeader_802_11->FC.Order = 1;
1577 /* skip common header */
1578 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1580 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
1581 /* */
1582 /* build QOS Control bytes */
1583 /* */
1584 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1586 *(pHeaderBufPtr + 1) = 0;
1587 pHeaderBufPtr += 2;
1588 pTxBlk->MpduHeaderLen += 2;
1590 /* padding at front of LLC header. LLC header should at 4-bytes aligment. */
1591 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1592 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1593 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1595 /* For RA Aggregation, */
1596 /* put the 2nd MSDU length(extra 2-byte field) after struct rt_qos_control in little endian format */
1597 pQEntry = pTxBlk->TxPacketList.Head;
1598 pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1599 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1600 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1601 nextBufLen -= LENGTH_802_1Q;
1603 *pHeaderBufPtr = (u8)nextBufLen & 0xff;
1604 *(pHeaderBufPtr + 1) = (u8)(nextBufLen >> 8);
1606 pHeaderBufPtr += 2;
1607 pTxBlk->MpduHeaderLen += 2;
1609 return pHeaderBufPtr;
1613 static inline u8 *STA_Build_AMSDU_Frame_Header(struct rt_rtmp_adapter *pAd,
1614 struct rt_tx_blk *pTxBlk)
1616 u8 *pHeaderBufPtr; /*, pSaveBufPtr; */
1617 struct rt_header_802_11 *pHeader_802_11;
1619 STAFindCipherAlgorithm(pAd, pTxBlk);
1620 STABuildCommon802_11Header(pAd, pTxBlk);
1622 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1623 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1625 /* skip common header */
1626 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1628 /* */
1629 /* build QOS Control bytes */
1630 /* */
1631 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1633 /* */
1634 /* A-MSDU packet */
1635 /* */
1636 *pHeaderBufPtr |= 0x80;
1638 *(pHeaderBufPtr + 1) = 0;
1639 pHeaderBufPtr += 2;
1640 pTxBlk->MpduHeaderLen += 2;
1642 /*pSaveBufPtr = pHeaderBufPtr; */
1644 /* */
1645 /* padding at front of LLC header */
1646 /* LLC header should locate at 4-octets aligment */
1647 /* */
1648 /* @@@ MpduHeaderLen excluding padding @@@ */
1649 /* */
1650 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1651 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1652 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1654 return pHeaderBufPtr;
1658 void STA_AMPDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1660 struct rt_header_802_11 *pHeader_802_11;
1661 u8 *pHeaderBufPtr;
1662 u16 FreeNumber;
1663 struct rt_mac_table_entry *pMacEntry;
1664 BOOLEAN bVLANPkt;
1665 struct rt_queue_entry *pQEntry;
1667 ASSERT(pTxBlk);
1669 while (pTxBlk->TxPacketList.Head) {
1670 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1671 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1672 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1673 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1674 NDIS_STATUS_FAILURE);
1675 continue;
1678 bVLANPkt =
1679 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1681 pMacEntry = pTxBlk->pMacEntry;
1682 if (pMacEntry->isCached) {
1683 /* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]! */
1684 NdisMoveMemory((u8 *)& pTxBlk->
1685 HeaderBuf[TXINFO_SIZE],
1686 (u8 *)& pMacEntry->CachedBuf[0],
1687 TXWI_SIZE + sizeof(struct rt_header_802_11));
1688 pHeaderBufPtr =
1689 (u8 *)(&pTxBlk->
1690 HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1691 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1692 } else {
1693 STAFindCipherAlgorithm(pAd, pTxBlk);
1694 STABuildCommon802_11Header(pAd, pTxBlk);
1696 pHeaderBufPtr =
1697 &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1700 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1702 /* skip common header */
1703 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1705 /* */
1706 /* build QOS Control bytes */
1707 /* */
1708 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1709 *(pHeaderBufPtr + 1) = 0;
1710 pHeaderBufPtr += 2;
1711 pTxBlk->MpduHeaderLen += 2;
1713 /* */
1714 /* build HTC+ */
1715 /* HTC control filed following QoS field */
1716 /* */
1717 if ((pAd->CommonCfg.bRdg == TRUE)
1718 && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry,
1719 fCLIENT_STATUS_RDG_CAPABLE)) {
1720 if (pMacEntry->isCached == FALSE) {
1721 /* mark HTC bit */
1722 pHeader_802_11->FC.Order = 1;
1724 NdisZeroMemory(pHeaderBufPtr, 4);
1725 *(pHeaderBufPtr + 3) |= 0x80;
1727 pHeaderBufPtr += 4;
1728 pTxBlk->MpduHeaderLen += 4;
1730 /*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */
1731 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1733 /* skip 802.3 header */
1734 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1735 pTxBlk->SrcBufLen -= LENGTH_802_3;
1737 /* skip vlan tag */
1738 if (bVLANPkt) {
1739 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1740 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1742 /* */
1743 /* padding at front of LLC header */
1744 /* LLC header should locate at 4-octets aligment */
1745 /* */
1746 /* @@@ MpduHeaderLen excluding padding @@@ */
1747 /* */
1748 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1749 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1750 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1754 /* */
1755 /* Insert LLC-SNAP encapsulation - 8 octets */
1756 /* */
1757 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
1758 pSrcBufData - 2,
1759 pTxBlk->
1760 pExtraLlcSnapEncap);
1761 if (pTxBlk->pExtraLlcSnapEncap) {
1762 NdisMoveMemory(pHeaderBufPtr,
1763 pTxBlk->pExtraLlcSnapEncap, 6);
1764 pHeaderBufPtr += 6;
1765 /* get 2 octets (TypeofLen) */
1766 NdisMoveMemory(pHeaderBufPtr,
1767 pTxBlk->pSrcBufData - 2, 2);
1768 pHeaderBufPtr += 2;
1769 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1774 if (pMacEntry->isCached) {
1775 RTMPWriteTxWI_Cache(pAd,
1776 (struct rt_txwi *) (&pTxBlk->
1777 HeaderBuf
1778 [TXINFO_SIZE]),
1779 pTxBlk);
1780 } else {
1781 RTMPWriteTxWI_Data(pAd,
1782 (struct rt_txwi *) (&pTxBlk->
1783 HeaderBuf
1784 [TXINFO_SIZE]),
1785 pTxBlk);
1787 NdisZeroMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1788 sizeof(pMacEntry->CachedBuf));
1789 NdisMoveMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1790 (u8 *)(&pTxBlk->
1791 HeaderBuf[TXINFO_SIZE]),
1792 (pHeaderBufPtr -
1793 (u8 *)(&pTxBlk->
1794 HeaderBuf[TXINFO_SIZE])));
1795 pMacEntry->isCached = TRUE;
1798 /* calculate Transmitted AMPDU count and ByteCount */
1800 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.
1801 LowPart++;
1802 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.
1803 QuadPart += pTxBlk->SrcBufLen;
1806 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
1808 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1810 /* */
1811 /* Kick out Tx */
1812 /* */
1813 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1814 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1816 pAd->RalinkCounters.KickTxCount++;
1817 pAd->RalinkCounters.OneSecTxDoneCount++;
1822 void STA_AMSDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1824 u8 *pHeaderBufPtr;
1825 u16 FreeNumber;
1826 u16 subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */
1827 u16 totalMPDUSize = 0;
1828 u8 *subFrameHeader;
1829 u8 padding = 0;
1830 u16 FirstTx = 0, LastTxIdx = 0;
1831 BOOLEAN bVLANPkt;
1832 int frameNum = 0;
1833 struct rt_queue_entry *pQEntry;
1835 ASSERT(pTxBlk);
1837 ASSERT((pTxBlk->TxPacketList.Number > 1));
1839 while (pTxBlk->TxPacketList.Head) {
1840 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1841 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1842 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1843 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1844 NDIS_STATUS_FAILURE);
1845 continue;
1848 bVLANPkt =
1849 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1851 /* skip 802.3 header */
1852 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1853 pTxBlk->SrcBufLen -= LENGTH_802_3;
1855 /* skip vlan tag */
1856 if (bVLANPkt) {
1857 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1858 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1861 if (frameNum == 0) {
1862 pHeaderBufPtr =
1863 STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1865 /* NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. */
1866 RTMPWriteTxWI_Data(pAd,
1867 (struct rt_txwi *) (&pTxBlk->
1868 HeaderBuf
1869 [TXINFO_SIZE]),
1870 pTxBlk);
1871 } else {
1872 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1873 padding =
1874 ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD +
1875 subFramePayloadLen,
1876 4) - (LENGTH_AMSDU_SUBFRAMEHEAD +
1877 subFramePayloadLen);
1878 NdisZeroMemory(pHeaderBufPtr,
1879 padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1880 pHeaderBufPtr += padding;
1881 pTxBlk->MpduHeaderLen = padding;
1884 /* */
1885 /* A-MSDU subframe */
1886 /* DA(6)+SA(6)+Length(2) + LLC/SNAP Encap */
1887 /* */
1888 subFrameHeader = pHeaderBufPtr;
1889 subFramePayloadLen = pTxBlk->SrcBufLen;
1891 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1893 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1894 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1896 /* */
1897 /* Insert LLC-SNAP encapsulation - 8 octets */
1898 /* */
1899 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
1900 pTxBlk->pExtraLlcSnapEncap);
1902 subFramePayloadLen = pTxBlk->SrcBufLen;
1904 if (pTxBlk->pExtraLlcSnapEncap) {
1905 NdisMoveMemory(pHeaderBufPtr,
1906 pTxBlk->pExtraLlcSnapEncap, 6);
1907 pHeaderBufPtr += 6;
1908 /* get 2 octets (TypeofLen) */
1909 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
1911 pHeaderBufPtr += 2;
1912 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1913 subFramePayloadLen += LENGTH_802_1_H;
1915 /* update subFrame Length field */
1916 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1917 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1919 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1921 if (frameNum == 0)
1922 FirstTx =
1923 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1924 &FreeNumber);
1925 else
1926 LastTxIdx =
1927 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1928 &FreeNumber);
1930 frameNum++;
1932 pAd->RalinkCounters.KickTxCount++;
1933 pAd->RalinkCounters.OneSecTxDoneCount++;
1935 /* calculate Transmitted AMSDU Count and ByteCount */
1937 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++;
1938 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart +=
1939 totalMPDUSize;
1944 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1945 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1947 /* */
1948 /* Kick out Tx */
1949 /* */
1950 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1951 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1954 void STA_Legacy_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1956 struct rt_header_802_11 *pHeader_802_11;
1957 u8 *pHeaderBufPtr;
1958 u16 FreeNumber;
1959 BOOLEAN bVLANPkt;
1960 struct rt_queue_entry *pQEntry;
1962 ASSERT(pTxBlk);
1964 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1965 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1966 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1967 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1968 return;
1971 if (pTxBlk->TxFrameType == TX_MCAST_FRAME) {
1972 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1975 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1976 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1977 else
1978 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1980 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1982 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1983 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1985 STAFindCipherAlgorithm(pAd, pTxBlk);
1986 STABuildCommon802_11Header(pAd, pTxBlk);
1988 /* skip 802.3 header */
1989 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1990 pTxBlk->SrcBufLen -= LENGTH_802_3;
1992 /* skip vlan tag */
1993 if (bVLANPkt) {
1994 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1995 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1998 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1999 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2001 /* skip common header */
2002 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2004 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2005 /* */
2006 /* build QOS Control bytes */
2007 /* */
2008 *(pHeaderBufPtr) =
2009 ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.
2010 AckPolicy[pTxBlk->
2011 QueIdx] << 5));
2012 *(pHeaderBufPtr + 1) = 0;
2013 pHeaderBufPtr += 2;
2014 pTxBlk->MpduHeaderLen += 2;
2016 /* The remaining content of MPDU header should locate at 4-octets aligment */
2017 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2018 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2019 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2023 /* */
2024 /* Insert LLC-SNAP encapsulation - 8 octets */
2025 /* */
2026 /* */
2027 /* if original Ethernet frame contains no LLC/SNAP, */
2028 /* then an extra LLC/SNAP encap is required */
2029 /* */
2030 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2031 pTxBlk->pExtraLlcSnapEncap);
2032 if (pTxBlk->pExtraLlcSnapEncap) {
2033 u8 vlan_size;
2035 NdisMoveMemory(pHeaderBufPtr,
2036 pTxBlk->pExtraLlcSnapEncap, 6);
2037 pHeaderBufPtr += 6;
2038 /* skip vlan tag */
2039 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2040 /* get 2 octets (TypeofLen) */
2041 NdisMoveMemory(pHeaderBufPtr,
2042 pTxBlk->pSrcBufHeader + 12 + vlan_size,
2044 pHeaderBufPtr += 2;
2045 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2050 /* */
2051 /* prepare for TXWI */
2052 /* use Wcid as Key Index */
2053 /* */
2055 RTMPWriteTxWI_Data(pAd, (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]),
2056 pTxBlk);
2058 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2060 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2062 pAd->RalinkCounters.KickTxCount++;
2063 pAd->RalinkCounters.OneSecTxDoneCount++;
2065 /* */
2066 /* Kick out Tx */
2067 /* */
2068 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2069 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2072 void STA_ARalink_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2074 u8 *pHeaderBufPtr;
2075 u16 FreeNumber;
2076 u16 totalMPDUSize = 0;
2077 u16 FirstTx, LastTxIdx;
2078 int frameNum = 0;
2079 BOOLEAN bVLANPkt;
2080 struct rt_queue_entry *pQEntry;
2082 ASSERT(pTxBlk);
2084 ASSERT((pTxBlk->TxPacketList.Number == 2));
2086 FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */
2087 while (pTxBlk->TxPacketList.Head) {
2088 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2089 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2091 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2092 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
2093 NDIS_STATUS_FAILURE);
2094 continue;
2097 bVLANPkt =
2098 (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2100 /* skip 802.3 header */
2101 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2102 pTxBlk->SrcBufLen -= LENGTH_802_3;
2104 /* skip vlan tag */
2105 if (bVLANPkt) {
2106 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2107 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2110 if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */
2112 pHeaderBufPtr =
2113 STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2115 /* It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount */
2116 /* will be updated after final frame was handled. */
2117 RTMPWriteTxWI_Data(pAd,
2118 (struct rt_txwi *) (&pTxBlk->
2119 HeaderBuf
2120 [TXINFO_SIZE]),
2121 pTxBlk);
2123 /* */
2124 /* Insert LLC-SNAP encapsulation - 8 octets */
2125 /* */
2126 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
2127 pSrcBufData - 2,
2128 pTxBlk->
2129 pExtraLlcSnapEncap);
2131 if (pTxBlk->pExtraLlcSnapEncap) {
2132 NdisMoveMemory(pHeaderBufPtr,
2133 pTxBlk->pExtraLlcSnapEncap, 6);
2134 pHeaderBufPtr += 6;
2135 /* get 2 octets (TypeofLen) */
2136 NdisMoveMemory(pHeaderBufPtr,
2137 pTxBlk->pSrcBufData - 2, 2);
2138 pHeaderBufPtr += 2;
2139 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2141 } else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */
2143 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2144 pTxBlk->MpduHeaderLen = 0;
2146 /* A-Ralink sub-sequent frame header is the same as 802.3 header. */
2147 /* DA(6)+SA(6)+FrameType(2) */
2148 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader,
2149 12);
2150 pHeaderBufPtr += 12;
2151 /* get 2 octets (TypeofLen) */
2152 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
2154 pHeaderBufPtr += 2;
2155 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2158 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2160 /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2161 if (frameNum == 0)
2162 FirstTx =
2163 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2164 &FreeNumber);
2165 else
2166 LastTxIdx =
2167 HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2168 &FreeNumber);
2170 frameNum++;
2172 pAd->RalinkCounters.OneSecTxAggregationCount++;
2173 pAd->RalinkCounters.KickTxCount++;
2174 pAd->RalinkCounters.OneSecTxDoneCount++;
2178 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2179 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2181 /* */
2182 /* Kick out Tx */
2183 /* */
2184 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2185 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2189 void STA_Fragment_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2191 struct rt_header_802_11 *pHeader_802_11;
2192 u8 *pHeaderBufPtr;
2193 u16 FreeNumber;
2194 u8 fragNum = 0;
2195 struct rt_packet_info PacketInfo;
2196 u16 EncryptionOverhead = 0;
2197 u32 FreeMpduSize, SrcRemainingBytes;
2198 u16 AckDuration;
2199 u32 NextMpduSize;
2200 BOOLEAN bVLANPkt;
2201 struct rt_queue_entry *pQEntry;
2202 HTTRANSMIT_SETTING *pTransmit;
2204 ASSERT(pTxBlk);
2206 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2207 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2208 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2209 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2210 return;
2213 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2214 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2216 STAFindCipherAlgorithm(pAd, pTxBlk);
2217 STABuildCommon802_11Header(pAd, pTxBlk);
2219 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2220 pTxBlk->pPacket =
2221 duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2222 if (pTxBlk->pPacket == NULL)
2223 return;
2224 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo,
2225 &pTxBlk->pSrcBufHeader,
2226 &pTxBlk->SrcBufLen);
2228 /* skip 802.3 header */
2229 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2230 pTxBlk->SrcBufLen -= LENGTH_802_3;
2232 /* skip vlan tag */
2233 if (bVLANPkt) {
2234 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2235 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2238 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2239 pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2241 /* skip common header */
2242 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2244 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2245 /* */
2246 /* build QOS Control bytes */
2247 /* */
2248 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2250 *(pHeaderBufPtr + 1) = 0;
2251 pHeaderBufPtr += 2;
2252 pTxBlk->MpduHeaderLen += 2;
2254 /* */
2255 /* padding at front of LLC header */
2256 /* LLC header should locate at 4-octets aligment */
2257 /* */
2258 pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2259 pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2260 pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2262 /* */
2263 /* Insert LLC-SNAP encapsulation - 8 octets */
2264 /* */
2265 /* */
2266 /* if original Ethernet frame contains no LLC/SNAP, */
2267 /* then an extra LLC/SNAP encap is required */
2268 /* */
2269 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2270 pTxBlk->pExtraLlcSnapEncap);
2271 if (pTxBlk->pExtraLlcSnapEncap) {
2272 u8 vlan_size;
2274 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2275 pHeaderBufPtr += 6;
2276 /* skip vlan tag */
2277 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2278 /* get 2 octets (TypeofLen) */
2279 NdisMoveMemory(pHeaderBufPtr,
2280 pTxBlk->pSrcBufHeader + 12 + vlan_size, 2);
2281 pHeaderBufPtr += 2;
2282 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2285 /* If TKIP is used and fragmentation is required. Driver has to */
2286 /* append TKIP MIC at tail of the scatter buffer */
2287 /* MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */
2288 if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2289 RTMPCalculateMICValue(pAd, pTxBlk->pPacket,
2290 pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey,
2293 /* NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust */
2294 /* to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. */
2295 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen,
2296 &pAd->PrivateInfo.Tx.MIC[0], 8);
2297 /*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */
2298 pTxBlk->SrcBufLen += 8;
2299 pTxBlk->TotalFrameLen += 8;
2300 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2302 /* */
2303 /* calcuate the overhead bytes that encryption algorithm may add. This */
2304 /* affects the calculate of "duration" field */
2305 /* */
2306 if ((pTxBlk->CipherAlg == CIPHER_WEP64)
2307 || (pTxBlk->CipherAlg == CIPHER_WEP128))
2308 EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */
2309 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2310 EncryptionOverhead = 12; /*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */
2311 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2312 EncryptionOverhead = 20; /*TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] */
2313 else if (pTxBlk->CipherAlg == CIPHER_AES)
2314 EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */
2315 else
2316 EncryptionOverhead = 0;
2318 pTransmit = pTxBlk->pTransmit;
2319 /* Decide the TX rate */
2320 if (pTransmit->field.MODE == MODE_CCK)
2321 pTxBlk->TxRate = pTransmit->field.MCS;
2322 else if (pTransmit->field.MODE == MODE_OFDM)
2323 pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE;
2324 else
2325 pTxBlk->TxRate = RATE_6_5;
2327 /* decide how much time an ACK/CTS frame will consume in the air */
2328 if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
2329 AckDuration =
2330 RTMPCalcDuration(pAd,
2331 pAd->CommonCfg.ExpectedACKRate[pTxBlk->
2332 TxRate],
2333 14);
2334 else
2335 AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
2337 /* Init the total payload length of this frame. */
2338 SrcRemainingBytes = pTxBlk->SrcBufLen;
2340 pTxBlk->TotalFragNum = 0xff;
2342 do {
2344 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2346 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2348 if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */
2350 pTxBlk->SrcBufLen = SrcRemainingBytes;
2352 pHeader_802_11->FC.MoreFrag = 0;
2353 pHeader_802_11->Duration =
2354 pAd->CommonCfg.Dsifs + AckDuration;
2356 /* Indicate the lower layer that this's the last fragment. */
2357 pTxBlk->TotalFragNum = fragNum;
2358 } else { /* more fragment is required */
2360 pTxBlk->SrcBufLen = FreeMpduSize;
2362 NextMpduSize =
2363 min(((u32)SrcRemainingBytes - pTxBlk->SrcBufLen),
2364 ((u32)pAd->CommonCfg.FragmentThreshold));
2365 pHeader_802_11->FC.MoreFrag = 1;
2366 pHeader_802_11->Duration =
2367 (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) +
2368 RTMPCalcDuration(pAd, pTxBlk->TxRate,
2369 NextMpduSize + EncryptionOverhead);
2372 if (fragNum == 0)
2373 pTxBlk->FrameGap = IFS_HTTXOP;
2374 else
2375 pTxBlk->FrameGap = IFS_SIFS;
2377 RTMPWriteTxWI_Data(pAd,
2378 (struct rt_txwi *) (&pTxBlk->
2379 HeaderBuf[TXINFO_SIZE]),
2380 pTxBlk);
2382 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2384 pAd->RalinkCounters.KickTxCount++;
2385 pAd->RalinkCounters.OneSecTxDoneCount++;
2387 /* Update the frame number, remaining size of the NDIS packet payload. */
2389 /* space for 802.11 header. */
2390 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2391 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2393 fragNum++;
2394 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2395 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2397 pHeader_802_11->Frag++; /* increase Frag # */
2399 } while (SrcRemainingBytes > 0);
2401 /* */
2402 /* Kick out Tx */
2403 /* */
2404 if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2405 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2408 #define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2409 while(_pTxBlk->TxPacketList.Head) \
2411 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2412 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2416 ========================================================================
2418 Routine Description:
2419 Copy frame from waiting queue into relative ring buffer and set
2420 appropriate ASIC register to kick hardware encryption before really
2421 sent out to air.
2423 Arguments:
2424 pAd Pointer to our adapter
2425 void * Pointer to outgoing Ndis frame
2426 NumberOfFrag Number of fragment required
2428 Return Value:
2429 None
2431 IRQL = DISPATCH_LEVEL
2433 Note:
2435 ========================================================================
2437 int STAHardTransmit(struct rt_rtmp_adapter *pAd,
2438 struct rt_tx_blk *pTxBlk, u8 QueIdx)
2440 char *pPacket;
2441 struct rt_queue_entry *pQEntry;
2443 /* --------------------------------------------- */
2444 /* STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. */
2445 /* --------------------------------------------- */
2446 /* */
2447 ASSERT(pTxBlk->TxPacketList.Number);
2448 if (pTxBlk->TxPacketList.Head == NULL) {
2449 DBGPRINT(RT_DEBUG_ERROR,
2450 ("pTxBlk->TotalFrameNum == %ld!\n",
2451 pTxBlk->TxPacketList.Number));
2452 return NDIS_STATUS_FAILURE;
2455 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2457 /* ------------------------------------------------------------------ */
2458 /* STEP 1. WAKE UP PHY */
2459 /* outgoing frame always wakeup PHY to prevent frame lost and */
2460 /* turn off PSM bit to improve performance */
2461 /* ------------------------------------------------------------------ */
2462 /* not to change PSM bit, just send this frame out? */
2463 if ((pAd->StaCfg.Psm == PWR_SAVE)
2464 && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
2465 DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n"));
2466 #ifdef RTMP_MAC_PCI
2467 AsicForceWakeup(pAd, TRUE);
2468 #endif /* RTMP_MAC_PCI // */
2469 #ifdef RTMP_MAC_USB
2470 RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0);
2471 #endif /* RTMP_MAC_USB // */
2473 /* It should not change PSM bit, when APSD turn on. */
2474 if ((!
2475 (pAd->CommonCfg.bAPSDCapable
2476 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
2477 && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2478 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2479 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) {
2480 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2481 (pAd->StaCfg.WindowsPowerMode ==
2482 Ndis802_11PowerModeFast_PSP))
2483 RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
2486 switch (pTxBlk->TxFrameType) {
2487 case TX_AMPDU_FRAME:
2488 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2489 break;
2490 case TX_AMSDU_FRAME:
2491 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2492 break;
2493 case TX_LEGACY_FRAME:
2494 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2495 break;
2496 case TX_MCAST_FRAME:
2497 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2498 break;
2499 case TX_RALINK_FRAME:
2500 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2501 break;
2502 case TX_FRAG_FRAME:
2503 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2504 break;
2505 default:
2507 /* It should not happened! */
2508 DBGPRINT(RT_DEBUG_ERROR,
2509 ("Send a packet was not classified! It should not happen!\n"));
2510 while (pTxBlk->TxPacketList.Number) {
2511 pQEntry =
2512 RemoveHeadQueue(&pTxBlk->TxPacketList);
2513 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2514 if (pPacket)
2515 RELEASE_NDIS_PACKET(pAd, pPacket,
2516 NDIS_STATUS_FAILURE);
2519 break;
2522 return (NDIS_STATUS_SUCCESS);
2526 unsigned long HashBytesPolynomial(u8 * value, unsigned int len)
2528 unsigned char *word = value;
2529 unsigned int ret = 0;
2530 unsigned int i;
2532 for (i = 0; i < len; i++) {
2533 int mod = i % 32;
2534 ret ^= (unsigned int)(word[i]) << mod;
2535 ret ^= (unsigned int)(word[i]) >> (32 - mod);
2537 return ret;
2540 void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd,
2541 void *pPacket,
2542 u8 FromWhichBSSID)
2544 if (TRUE) {
2545 announce_802_3_packet(pAd, pPacket);
2546 } else {
2547 /* release packet */
2548 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);