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