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