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