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