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