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