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