]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/common/cmm_data.c
Staging: rt28x0: run common/*.c files through Lindent
[net-next-2.6.git] / drivers / staging / rt2860 / common / cmm_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
28 #include "../rt_config.h"
29
30 UCHAR SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31 UCHAR SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
32
33 // Add Cisco Aironet SNAP heade for CCX2 support
34 UCHAR SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35 UCHAR CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36 UCHAR EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37 UCHAR EAPOL[] = { 0x88, 0x8e };
38 UCHAR TPID[] = { 0x81, 0x00 };  /* VLAN related */
39
40 UCHAR IPX[] = { 0x81, 0x37 };
41 UCHAR APPLE_TALK[] = { 0x80, 0xf3 };
42
43 UCHAR RateIdToPlcpSignal[12] = {
44         0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3,    /* RATE_11 */// see BBP spec
45         11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */// see IEEE802.11a-1999 p.14
46         9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */
47 };                              // see IEEE802.11a-1999 p.14
48
49 UCHAR OfdmSignalToRateId[16] = {
50         RATE_54, RATE_54, RATE_54, RATE_54,     // OFDM PLCP Signal = 0,  1,  2,  3 respectively
51         RATE_54, RATE_54, RATE_54, RATE_54,     // OFDM PLCP Signal = 4,  5,  6,  7 respectively
52         RATE_48, RATE_24, RATE_12, RATE_6,      // OFDM PLCP Signal = 8,  9,  10, 11 respectively
53         RATE_54, RATE_36, RATE_18, RATE_9,      // OFDM PLCP Signal = 12, 13, 14, 15 respectively
54 };
55
56 UCHAR OfdmRateToRxwiMCS[12] = {
57         0, 0, 0, 0,
58         0, 1, 2, 3,             // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
59         4, 5, 6, 7,             // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
60 };
61
62 UCHAR RxwiMCSToOfdmRate[12] = {
63         RATE_6, RATE_9, RATE_12, RATE_18,
64         RATE_24, RATE_36, RATE_48, RATE_54,     // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
65         4, 5, 6, 7,             // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
66 };
67
68 char *MCSToMbps[] =
69     { "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps",
70 "18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3",
71 "MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13",
72 "MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" };
73
74 UCHAR default_cwmin[] =
75     { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76 //UCHAR default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1};
77 UCHAR default_sta_aifsn[] = { 3, 7, 2, 2 };
78
79 UCHAR MapUserPriorityToAccessCategory[8] =
80     { QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81 QID_AC_VO, QID_AC_VO };
82
83 /*
84         ========================================================================
85
86         Routine Description:
87                 API for MLME to transmit management frame to AP (BSS Mode)
88         or station (IBSS Mode)
89
90         Arguments:
91                 pAd Pointer to our adapter
92                 pData           Pointer to the outgoing 802.11 frame
93                 Length          Size of outgoing management frame
94
95         Return Value:
96                 NDIS_STATUS_FAILURE
97                 NDIS_STATUS_PENDING
98                 NDIS_STATUS_SUCCESS
99
100         IRQL = PASSIVE_LEVEL
101         IRQL = DISPATCH_LEVEL
102
103         Note:
104
105         ========================================================================
106 */
107 NDIS_STATUS MiniportMMRequest(IN PRTMP_ADAPTER pAd,
108                               IN UCHAR QueIdx, IN PUCHAR pData, IN UINT Length)
109 {
110         PNDIS_PACKET pPacket;
111         NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
112         ULONG FreeNum;
113         UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE];       //RTMP_HW_HDR_LEN];
114 #ifdef RTMP_MAC_PCI
115         unsigned long IrqFlags = 0;
116         UCHAR IrqState;
117 #endif // RTMP_MAC_PCI //
118         BOOLEAN bUseDataQ = FALSE;
119         int retryCnt = 0;
120
121         ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
122
123         if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
124                 bUseDataQ = TRUE;
125                 QueIdx &= (~MGMT_USE_QUEUE_FLAG);
126         }
127 #ifdef RTMP_MAC_PCI
128         // 2860C use Tx Ring
129         IrqState = pAd->irq_disabled;
130         if (pAd->MACVersion == 0x28600100) {
131                 QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
132                 bUseDataQ = TRUE;
133         }
134         if (bUseDataQ && (!IrqState))
135                 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136 #endif // RTMP_MAC_PCI //
137
138         do {
139                 // Reset is in progress, stop immediately
140                 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
141                     RTMP_TEST_FLAG(pAd,
142                                    fRTMP_ADAPTER_HALT_IN_PROGRESS |
143                                    fRTMP_ADAPTER_NIC_NOT_EXIST)
144                     || !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
145                         Status = NDIS_STATUS_FAILURE;
146                         break;
147                 }
148                 // Check Free priority queue
149                 // Since we use PBF Queue2 for management frame.  Its corresponding DMA ring should be using TxRing.
150 #ifdef RTMP_MAC_PCI
151                 if (bUseDataQ) {
152                         retryCnt = MAX_DATAMM_RETRY;
153                         // free Tx(QueIdx) resources
154                         RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155                         FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
156                 } else
157 #endif // RTMP_MAC_PCI //
158                 {
159                         FreeNum = GET_MGMTRING_FREENO(pAd);
160                 }
161
162                 if ((FreeNum > 0)) {
163                         // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
164                         NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
165                         Status =
166                             RTMPAllocateNdisPacket(pAd, &pPacket,
167                                                    (PUCHAR) & rtmpHwHdr,
168                                                    (TXINFO_SIZE + TXWI_SIZE),
169                                                    pData, Length);
170                         if (Status != NDIS_STATUS_SUCCESS) {
171                                 DBGPRINT(RT_DEBUG_WARN,
172                                          ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
173                                 break;
174                         }
175                         //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
176                         //pAd->CommonCfg.MlmeRate = RATE_2;
177
178 #ifdef RTMP_MAC_PCI
179                         if (bUseDataQ) {
180                                 Status =
181                                     MlmeDataHardTransmit(pAd, QueIdx, pPacket);
182                                 retryCnt--;
183                         } else
184 #endif // RTMP_MAC_PCI //
185                                 Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
186                         if (Status == NDIS_STATUS_SUCCESS)
187                                 retryCnt = 0;
188                         else
189                                 RTMPFreeNdisPacket(pAd, pPacket);
190                 } else {
191                         pAd->RalinkCounters.MgmtRingFullCount++;
192 #ifdef RTMP_MAC_PCI
193                         if (bUseDataQ) {
194                                 retryCnt--;
195                                 DBGPRINT(RT_DEBUG_TRACE,
196                                          ("retryCnt %d\n", retryCnt));
197                                 if (retryCnt == 0) {
198                                         DBGPRINT(RT_DEBUG_ERROR,
199                                                  ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
200                                                   QueIdx,
201                                                   pAd->RalinkCounters.
202                                                   MgmtRingFullCount));
203                                 }
204                         }
205 #endif // RTMP_MAC_PCI //
206                         DBGPRINT(RT_DEBUG_ERROR,
207                                  ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
208                                   QueIdx,
209                                   pAd->RalinkCounters.MgmtRingFullCount));
210                 }
211         } while (retryCnt > 0);
212
213 #ifdef RTMP_MAC_PCI
214         if (bUseDataQ && (!IrqState))
215                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216 #endif // RTMP_MAC_PCI //
217
218         return Status;
219 }
220
221 /*
222         ========================================================================
223
224         Routine Description:
225                 Copy frame from waiting queue into relative ring buffer and set
226         appropriate ASIC register to kick hardware transmit function
227
228         Arguments:
229                 pAd Pointer to our adapter
230                 pBuffer         Pointer to      memory of outgoing frame
231                 Length          Size of outgoing management frame
232
233         Return Value:
234                 NDIS_STATUS_FAILURE
235                 NDIS_STATUS_PENDING
236                 NDIS_STATUS_SUCCESS
237
238         IRQL = PASSIVE_LEVEL
239         IRQL = DISPATCH_LEVEL
240
241         Note:
242
243         ========================================================================
244 */
245 NDIS_STATUS MlmeHardTransmit(IN PRTMP_ADAPTER pAd,
246                              IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
247 {
248         PACKET_INFO PacketInfo;
249         PUCHAR pSrcBufVA;
250         UINT SrcBufLen;
251         PHEADER_802_11 pHeader_802_11;
252
253         if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
254             ) {
255                 return NDIS_STATUS_FAILURE;
256         }
257
258         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259         if (pSrcBufVA == NULL)
260                 return NDIS_STATUS_FAILURE;
261
262         pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
263
264 #ifdef RTMP_MAC_PCI
265         if (pAd->MACVersion == 0x28600100)
266                 return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
267         else
268 #endif // RTMP_MAC_PCI //
269                 return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
270
271 }
272
273 NDIS_STATUS MlmeHardTransmitMgmtRing(IN PRTMP_ADAPTER pAd,
274                                      IN UCHAR QueIdx, IN PNDIS_PACKET pPacket)
275 {
276         PACKET_INFO PacketInfo;
277         PUCHAR pSrcBufVA;
278         UINT SrcBufLen;
279         PHEADER_802_11 pHeader_802_11;
280         BOOLEAN bAckRequired, bInsertTimestamp;
281         UCHAR MlmeRate;
282         PTXWI_STRUC pFirstTxWI;
283         MAC_TABLE_ENTRY *pMacEntry = NULL;
284         UCHAR PID;
285
286         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
287
288         // Make sure MGMT ring resource won't be used by other threads
289         RTMP_SEM_LOCK(&pAd->MgmtRingLock);
290         if (pSrcBufVA == NULL) {
291                 // The buffer shouldn't be NULL
292                 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
293                 return NDIS_STATUS_FAILURE;
294         }
295
296         {
297                 // outgoing frame always wakeup PHY to prevent frame lost
298                 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299                         AsicForceWakeup(pAd, TRUE);
300         }
301
302         pFirstTxWI = (PTXWI_STRUC) (pSrcBufVA + TXINFO_SIZE);
303         pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);        //TXWI_SIZE);
304
305         if (pHeader_802_11->Addr1[0] & 0x01) {
306                 MlmeRate = pAd->CommonCfg.BasicMlmeRate;
307         } else {
308                 MlmeRate = pAd->CommonCfg.MlmeRate;
309         }
310
311         // Verify Mlme rate for a / g bands.
312         if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6))     // 11A band
313                 MlmeRate = RATE_6;
314
315         if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
316             (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
317                 pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
318         }
319
320         {
321                 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
322                 if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
323                     || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) {
324                         if (pAd->LatchRfRegs.Channel > 14)
325                                 pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
326                         else
327                                 pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
328                 }
329         }
330
331         //
332         // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
333         // Snice it's been set to 0 while on MgtMacHeaderInit
334         // By the way this will cause frame to be send on PWR_SAVE failed.
335         //
336         pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;        // (pAd->StaCfg.Psm == PWR_SAVE);
337
338         //
339         // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
340         // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
341 //      if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
342         {
343                 if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
344                     ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
345                      ((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
346                       (pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) {
347                         if (pAd->StaCfg.Psm == PWR_SAVE)
348                                 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
349                         else
350                                 pHeader_802_11->FC.PwrMgmt =
351                                     pAd->CommonCfg.bAPSDForcePowerSave;
352                 }
353         }
354
355         bInsertTimestamp = FALSE;
356         if (pHeader_802_11->FC.Type == BTYPE_CNTL)      // must be PS-POLL
357         {
358                 //Set PM bit in ps-poll, to fix WLK 1.2  PowerSaveMode_ext failure issue.
359                 if ((pAd->OpMode == OPMODE_STA)
360                     && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) {
361                         pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
362                 }
363                 bAckRequired = FALSE;
364         } else                  // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
365         {
366                 //pAd->Sequence++;
367                 //pHeader_802_11->Sequence = pAd->Sequence;
368
369                 if (pHeader_802_11->Addr1[0] & 0x01)    // MULTICAST, BROADCAST
370                 {
371                         bAckRequired = FALSE;
372                         pHeader_802_11->Duration = 0;
373                 } else {
374                         bAckRequired = TRUE;
375                         pHeader_802_11->Duration =
376                             RTMPCalcDuration(pAd, MlmeRate, 14);
377                         if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
378                             && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
379                                 bInsertTimestamp = TRUE;
380                                 bAckRequired = FALSE;   // Disable ACK to prevent retry 0x1f for Probe Response
381                         } else
382                             if ((pHeader_802_11->FC.SubType ==
383                                  SUBTYPE_PROBE_REQ)
384                                 && (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
385                                 bAckRequired = FALSE;   // Disable ACK to prevent retry 0x1f for Probe Request
386                         }
387                 }
388         }
389
390         pHeader_802_11->Sequence = pAd->Sequence++;
391         if (pAd->Sequence > 0xfff)
392                 pAd->Sequence = 0;
393
394         // Before radar detection done, mgmt frame can not be sent but probe req
395         // Because we need to use probe req to trigger driver to send probe req in passive scan
396         if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
397             && (pAd->CommonCfg.bIEEE80211H == 1)
398             && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
399                 DBGPRINT(RT_DEBUG_ERROR,
400                          ("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
401 //              if (!IrqState)
402                 RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403                 return (NDIS_STATUS_FAILURE);
404         }
405
406         //
407         // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
408         // should always has only one physical buffer, and the whole frame size equals
409         // to the first scatter buffer size
410         //
411
412         // Initialize TX Descriptor
413         // For inter-frame gap, the number is for this frame and next frame
414         // For MLME rate, we will fix as 2Mb to match other vendor's implement
415 //      pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
416
417 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
418         PID = PID_MGMT;
419
420         if (pMacEntry == NULL) {
421                 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
422                               FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
423                               (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,
424                               (UCHAR) pAd->CommonCfg.MlmeTransmit.field.MCS,
425                               IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
426         } else {
427                 /* dont use low rate to send QoS Null data frame */
428                 RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
429                               bInsertTimestamp, FALSE, bAckRequired, FALSE,
430                               0, pMacEntry->Aid,
431                               (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432                               pMacEntry->MaxHTPhyMode.field.MCS, 0,
433                               (UCHAR) pMacEntry->MaxHTPhyMode.field.MCS,
434                               IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
435         }
436
437         // Now do hardware-depened kick out.
438         HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
439
440         // Make sure to release MGMT ring resource
441 //      if (!IrqState)
442         RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443         return NDIS_STATUS_SUCCESS;
444 }
445
446 /********************************************************************************
447
448         New DeQueue Procedures.
449
450  ********************************************************************************/
451
452 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags)                               \
453                         do{                                                                                                     \
454                                 if (bIntContext == FALSE)                                               \
455                                 RTMP_IRQ_LOCK((lock), IrqFlags);                \
456                         }while(0)
457
458 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags)                             \
459                         do{                                                                                                     \
460                                 if (bIntContext == FALSE)                                               \
461                                         RTMP_IRQ_UNLOCK((lock), IrqFlags);      \
462                         }while(0)
463
464 /*
465         ========================================================================
466         Tx Path design algorithm:
467                 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
468                 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
469                                 Classification Rule=>
470                                         Multicast: (*addr1 & 0x01) == 0x01
471                                         Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
472                                         11N Rate : If peer support HT
473                                                                 (1).AMPDU  -- If TXBA is negotiated.
474                                                                 (2).AMSDU  -- If AMSDU is capable for both peer and ourself.
475                                                                                         *). AMSDU can embedded in a AMPDU, but now we didn't support it.
476                                                                 (3).Normal -- Other packets which send as 11n rate.
477
478                                         B/G Rate : If peer is b/g only.
479                                                                 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
480                                                                 (2).Normal -- Other packets which send as b/g rate.
481                                         Fragment:
482                                                                 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
483
484                                 Classified Packet Handle Rule=>
485                                         Multicast:
486                                                                 No ACK,                 //pTxBlk->bAckRequired = FALSE;
487                                                                 No WMM,                 //pTxBlk->bWMM = FALSE;
488                                                                 No piggyback,   //pTxBlk->bPiggyBack = FALSE;
489                                                                 Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
490                                         Specific :      Basically, for specific packet, we should handle it specifically, but now all specific packets are use
491                                                                         the same policy to handle it.
492                                                                 Force LowRate,  //pTxBlk->bForceLowRate = TRUE;
493
494                                         11N Rate :
495                                                                 No piggyback,   //pTxBlk->bPiggyBack = FALSE;
496
497                                                                 (1).AMSDU
498                                                                         pTxBlk->bWMM = TRUE;
499                                                                 (2).AMPDU
500                                                                         pTxBlk->bWMM = TRUE;
501                                                                 (3).Normal
502
503                                         B/G Rate :
504                                                                 (1).ARALINK
505
506                                                                 (2).Normal
507         ========================================================================
508 */
509 static UCHAR TxPktClassification(IN RTMP_ADAPTER * pAd, IN PNDIS_PACKET pPacket)
510 {
511         UCHAR TxFrameType = TX_UNKOWN_FRAME;
512         UCHAR Wcid;
513         MAC_TABLE_ENTRY *pMacEntry = NULL;
514         BOOLEAN bHTRate = FALSE;
515
516         Wcid = RTMP_GET_PACKET_WCID(pPacket);
517         if (Wcid == MCAST_WCID) {       // Handle for RA is Broadcast/Multicast Address.
518                 return TX_MCAST_FRAME;
519         }
520         // Handle for unicast packets
521         pMacEntry = &pAd->MacTab.Content[Wcid];
522         if (RTMP_GET_PACKET_LOWRATE(pPacket)) { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
523                 TxFrameType = TX_LEGACY_FRAME;
524         } else if (IS_HT_RATE(pMacEntry)) {     // it's a 11n capable packet
525
526                 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
527                 //      Currently didn't support A-MSDU embedded in A-MPDU
528                 bHTRate = TRUE;
529                 if (RTMP_GET_PACKET_MOREDATA(pPacket)
530                     || (pMacEntry->PsMode == PWR_SAVE))
531                         TxFrameType = TX_LEGACY_FRAME;
532                 else if ((pMacEntry->
533                           TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) !=
534                          0)
535                         return TX_AMPDU_FRAME;
536                 else if (CLIENT_STATUS_TEST_FLAG
537                          (pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
538                         return TX_AMSDU_FRAME;
539                 else
540                         TxFrameType = TX_LEGACY_FRAME;
541         } else {                // it's a legacy b/g packet.
542                 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) {   // if peer support Ralink Aggregation, we use it.
543                         TxFrameType = TX_RALINK_FRAME;
544                 } else {
545                         TxFrameType = TX_LEGACY_FRAME;
546                 }
547         }
548
549         // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
550         if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
551             && (TxFrameType == TX_LEGACY_FRAME))
552                 TxFrameType = TX_FRAG_FRAME;
553
554         return TxFrameType;
555 }
556
557 BOOLEAN RTMP_FillTxBlkInfo(IN RTMP_ADAPTER * pAd, IN TX_BLK * pTxBlk)
558 {
559         PACKET_INFO PacketInfo;
560         PNDIS_PACKET pPacket;
561         PMAC_TABLE_ENTRY pMacEntry = NULL;
562
563         pPacket = pTxBlk->pPacket;
564         RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
565                              &pTxBlk->SrcBufLen);
566
567         pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
568         pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
569         pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
570         pTxBlk->FrameGap = IFS_HTTXOP;  // ASIC determine Frame Gap
571
572         if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
573                 TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
574         else
575                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
576
577         // Default to clear this flag
578         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
579
580         if (pTxBlk->Wcid == MCAST_WCID) {
581                 pTxBlk->pMacEntry = NULL;
582                 {
583                         pTxBlk->pTransmit =
584                             &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
585                 }
586
587                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);    // AckRequired = FALSE, when broadcast packet in Adhoc mode.
588                 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
589                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
590                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
591                 if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
592                         TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
593                 }
594
595         } else {
596                 pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597                 pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
598
599                 pMacEntry = pTxBlk->pMacEntry;
600
601                 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
602                 if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
603                         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
604                 else
605                         TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
606
607                 if ((pAd->OpMode == OPMODE_STA) &&
608                     (ADHOC_ON(pAd)) &&
609                     (RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) {
610                         if (pAd->CommonCfg.PSPXlink)
611                                 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
612                 }
613
614                 {
615                         {
616
617                                 // If support WMM, enable it.
618                                 if (OPSTATUS_TEST_FLAG
619                                     (pAd, fOP_STATUS_WMM_INUSED)
620                                     && CLIENT_STATUS_TEST_FLAG(pMacEntry,
621                                                                fCLIENT_STATUS_WMM_CAPABLE))
622                                         TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
623
624 //                              if (pAd->StaCfg.bAutoTxRateSwitch)
625 //                                      TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch);
626                         }
627                 }
628
629                 if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) {
630                         if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) {  // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
631                                 pTxBlk->pTransmit =
632                                     &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
633
634                                 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
635                                 if (IS_HT_STA(pTxBlk->pMacEntry) &&
636                                     (CLIENT_STATUS_TEST_FLAG
637                                      (pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET))
638                                     && ((pAd->CommonCfg.bRdg == TRUE)
639                                         && CLIENT_STATUS_TEST_FLAG(pMacEntry,
640                                                                    fCLIENT_STATUS_RDG_CAPABLE)))
641                                 {
642                                         TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
643                                         TX_BLK_SET_FLAG(pTxBlk,
644                                                         fTX_bForceNonQoS);
645                                 }
646                         }
647
648                         if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) {       // Currently piggy-back only support when peer is operate in b/g mode.
649                                 TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
650                         }
651
652                         if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
653                                 TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
654                         }
655                 } else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
656                         TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
657                 }
658
659                 pMacEntry->DebugTxCount++;
660         }
661
662         return TRUE;
663 }
664
665 BOOLEAN CanDoAggregateTransmit(IN RTMP_ADAPTER * pAd,
666                                IN NDIS_PACKET * pPacket, IN TX_BLK * pTxBlk)
667 {
668
669         //DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));
670
671         if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
672                 return FALSE;
673
674         if (RTMP_GET_PACKET_DHCP(pPacket) ||
675             RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
676                 return FALSE;
677
678         if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) {     // For AMSDU, allow the packets with total length < max-amsdu size
679                 return FALSE;
680         }
681
682         if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) {   // For RALINK-Aggregation, allow two frames in one batch.
683                 return FALSE;
684         }
685
686         if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))     // must be unicast to AP
687                 return TRUE;
688         else
689                 return FALSE;
690
691 }
692
693 /*
694         ========================================================================
695
696         Routine Description:
697                 To do the enqueue operation and extract the first item of waiting
698                 list. If a number of available shared memory segments could meet
699                 the request of extracted item, the extracted item will be fragmented
700                 into shared memory segments.
701
702         Arguments:
703                 pAd Pointer to our adapter
704                 pQueue          Pointer to Waiting Queue
705
706         Return Value:
707                 None
708
709         IRQL = DISPATCH_LEVEL
710
711         Note:
712
713         ========================================================================
714 */
715 VOID RTMPDeQueuePacket(IN PRTMP_ADAPTER pAd, IN BOOLEAN bIntContext, IN UCHAR QIdx,     /* BulkOutPipeId */
716                        IN UCHAR Max_Tx_Packets)
717 {
718         PQUEUE_ENTRY pEntry = NULL;
719         PNDIS_PACKET pPacket;
720         NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
721         UCHAR Count = 0;
722         PQUEUE_HEADER pQueue;
723         ULONG FreeNumber[NUM_OF_TX_RING];
724         UCHAR QueIdx, sQIdx, eQIdx;
725         unsigned long IrqFlags = 0;
726         BOOLEAN hasTxDesc = FALSE;
727         TX_BLK TxBlk;
728         TX_BLK *pTxBlk;
729
730         if (QIdx == NUM_OF_TX_RING) {
731                 sQIdx = 0;
732                 eQIdx = 3;      // 4 ACs, start from 0.
733         } else {
734                 sQIdx = eQIdx = QIdx;
735         }
736
737         for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
738                 Count = 0;
739
740                 RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
741
742                 while (1) {
743                         if ((RTMP_TEST_FLAG
744                              (pAd,
745                               (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
746                                fRTMP_ADAPTER_RADIO_OFF |
747                                fRTMP_ADAPTER_RESET_IN_PROGRESS |
748                                fRTMP_ADAPTER_HALT_IN_PROGRESS |
749                                fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
750                                 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
751                                 return;
752                         }
753
754                         if (Count >= Max_Tx_Packets)
755                                 break;
756
757                         DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
758                         if (&pAd->TxSwQueue[QueIdx] == NULL) {
759                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
760                                                IrqFlags);
761                                 break;
762                         }
763 #ifdef RTMP_MAC_PCI
764                         FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
765
766                         if (FreeNumber[QueIdx] <= 5) {
767                                 // free Tx(QueIdx) resources
768                                 RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
769                                 FreeNumber[QueIdx] =
770                                     GET_TXRING_FREENO(pAd, QueIdx);
771                         }
772 #endif // RTMP_MAC_PCI //
773
774                         // probe the Queue Head
775                         pQueue = &pAd->TxSwQueue[QueIdx];
776                         if ((pEntry = pQueue->Head) == NULL) {
777                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
778                                                IrqFlags);
779                                 break;
780                         }
781
782                         pTxBlk = &TxBlk;
783                         NdisZeroMemory((PUCHAR) pTxBlk, sizeof(TX_BLK));
784                         //InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it.
785                         pTxBlk->QueIdx = QueIdx;
786
787                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
788
789                         // Early check to make sure we have enoguh Tx Resource.
790                         hasTxDesc =
791                             RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
792                                                       FreeNumber[QueIdx],
793                                                       pPacket);
794                         if (!hasTxDesc) {
795                                 pAd->PrivateInfo.TxRingFullCnt++;
796
797                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
798                                                IrqFlags);
799
800                                 break;
801                         }
802
803                         pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
804                         pEntry = RemoveHeadQueue(pQueue);
805                         pTxBlk->TotalFrameNum++;
806                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
807                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
808                         pTxBlk->pPacket = pPacket;
809                         InsertTailQueue(&pTxBlk->TxPacketList,
810                                         PACKET_TO_QUEUE_ENTRY(pPacket));
811
812                         if (pTxBlk->TxFrameType == TX_RALINK_FRAME
813                             || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
814                                 // Enhance SW Aggregation Mechanism
815                                 if (NEED_QUEUE_BACK_FOR_AGG
816                                     (pAd, QueIdx, FreeNumber[QueIdx],
817                                      pTxBlk->TxFrameType)) {
818                                         InsertHeadQueue(pQueue,
819                                                         PACKET_TO_QUEUE_ENTRY
820                                                         (pPacket));
821                                         DEQUEUE_UNLOCK(&pAd->irq_lock,
822                                                        bIntContext, IrqFlags);
823                                         break;
824                                 }
825
826                                 do {
827                                         if ((pEntry = pQueue->Head) == NULL)
828                                                 break;
829
830                                         // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
831                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
832                                         FreeNumber[QueIdx] =
833                                             GET_TXRING_FREENO(pAd, QueIdx);
834                                         hasTxDesc =
835                                             RTMP_HAS_ENOUGH_FREE_DESC(pAd,
836                                                                       pTxBlk,
837                                                                       FreeNumber
838                                                                       [QueIdx],
839                                                                       pPacket);
840                                         if ((hasTxDesc == FALSE)
841                                             ||
842                                             (CanDoAggregateTransmit
843                                              (pAd, pPacket, pTxBlk) == FALSE))
844                                                 break;
845
846                                         //Remove the packet from the TxSwQueue and insert into pTxBlk
847                                         pEntry = RemoveHeadQueue(pQueue);
848                                         ASSERT(pEntry);
849                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
850                                         pTxBlk->TotalFrameNum++;
851                                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     // The real fragment number maybe vary
852                                         pTxBlk->TotalFrameLen +=
853                                             GET_OS_PKT_LEN(pPacket);
854                                         InsertTailQueue(&pTxBlk->TxPacketList,
855                                                         PACKET_TO_QUEUE_ENTRY
856                                                         (pPacket));
857                                 } while (1);
858
859                                 if (pTxBlk->TxPacketList.Number == 1)
860                                         pTxBlk->TxFrameType = TX_LEGACY_FRAME;
861                         }
862 #ifdef RTMP_MAC_USB
863                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
864 #endif // RTMP_MAC_USB //
865                         Count += pTxBlk->TxPacketList.Number;
866
867                         // Do HardTransmit now.
868                         Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
869
870 #ifdef RTMP_MAC_PCI
871                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
872                         // static rate also need NICUpdateFifoStaCounters() function.
873                         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
874                         NICUpdateFifoStaCounters(pAd);
875 #endif // RTMP_MAC_PCI //
876
877                 }
878
879                 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
880
881 #ifdef RTMP_MAC_USB
882                 if (!hasTxDesc)
883                         RTUSBKickBulkOut(pAd);
884 #endif // RTMP_MAC_USB //
885         }
886
887 }
888
889 /*
890         ========================================================================
891
892         Routine Description:
893                 Calculates the duration which is required to transmit out frames
894         with given size and specified rate.
895
896         Arguments:
897                 pAd     Pointer to our adapter
898                 Rate                    Transmit rate
899                 Size                    Frame size in units of byte
900
901         Return Value:
902                 Duration number in units of usec
903
904         IRQL = PASSIVE_LEVEL
905         IRQL = DISPATCH_LEVEL
906
907         Note:
908
909         ========================================================================
910 */
911 USHORT RTMPCalcDuration(IN PRTMP_ADAPTER pAd, IN UCHAR Rate, IN ULONG Size)
912 {
913         ULONG Duration = 0;
914
915         if (Rate < RATE_FIRST_OFDM_RATE)        // CCK
916         {
917                 if ((Rate > RATE_1)
918                     && OPSTATUS_TEST_FLAG(pAd,
919                                           fOP_STATUS_SHORT_PREAMBLE_INUSED))
920                         Duration = 96;  // 72+24 preamble+plcp
921                 else
922                         Duration = 192; // 144+48 preamble+plcp
923
924                 Duration += (USHORT) ((Size << 4) / RateIdTo500Kbps[Rate]);
925                 if ((Size << 4) % RateIdTo500Kbps[Rate])
926                         Duration++;
927         } else if (Rate <= RATE_LAST_OFDM_RATE) // OFDM rates
928         {
929                 Duration = 20 + 6;      // 16+4 preamble+plcp + Signal Extension
930                 Duration +=
931                     4 * (USHORT) ((11 + Size * 4) / RateIdTo500Kbps[Rate]);
932                 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
933                         Duration += 4;
934         } else                  //mimo rate
935         {
936                 Duration = 20 + 6;      // 16+4 preamble+plcp + Signal Extension
937         }
938
939         return (USHORT) Duration;
940 }
941
942 /*
943         ========================================================================
944
945         Routine Description:
946                 Calculates the duration which is required to transmit out frames
947         with given size and specified rate.
948
949         Arguments:
950                 pTxWI           Pointer to head of each MPDU to HW.
951                 Ack             Setting for Ack requirement bit
952                 Fragment        Setting for Fragment bit
953                 RetryMode       Setting for retry mode
954                 Ifs             Setting for IFS gap
955                 Rate            Setting for transmit rate
956                 Service         Setting for service
957                 Length          Frame length
958                 TxPreamble      Short or Long preamble when using CCK rates
959                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
960
961         Return Value:
962                 None
963
964         IRQL = PASSIVE_LEVEL
965         IRQL = DISPATCH_LEVEL
966
967     See also : BASmartHardTransmit()    !!!
968
969         ========================================================================
970 */
971 VOID RTMPWriteTxWI(IN PRTMP_ADAPTER pAd, IN PTXWI_STRUC pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq,        // HW new a sequence.
972                    IN UCHAR BASize,
973                    IN UCHAR WCID,
974                    IN ULONG Length,
975                    IN UCHAR PID,
976                    IN UCHAR TID,
977                    IN UCHAR TxRate,
978                    IN UCHAR Txopmode,
979                    IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
980 {
981         PMAC_TABLE_ENTRY pMac = NULL;
982         TXWI_STRUC TxWI;
983         PTXWI_STRUC pTxWI;
984
985         if (WCID < MAX_LEN_OF_MAC_TABLE)
986                 pMac = &pAd->MacTab.Content[WCID];
987
988         //
989         // Always use Long preamble before verifiation short preamble functionality works well.
990         // Todo: remove the following line if short preamble functionality works
991         //
992         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
993         NdisZeroMemory(&TxWI, TXWI_SIZE);
994         pTxWI = &TxWI;
995
996         pTxWI->FRAG = FRAG;
997
998         pTxWI->CFACK = CFACK;
999         pTxWI->TS = InsTimestamp;
1000         pTxWI->AMPDU = AMPDU;
1001         pTxWI->ACK = Ack;
1002         pTxWI->txop = Txopmode;
1003
1004         pTxWI->NSEQ = NSeq;
1005         // John tune the performace with Intel Client in 20 MHz performance
1006         BASize = pAd->CommonCfg.TxBASize;
1007         if (pAd->MACVersion == 0x28720200) {
1008                 if (BASize > 13)
1009                         BASize = 13;
1010         } else {
1011                 if (BASize > 7)
1012                         BASize = 7;
1013         }
1014         pTxWI->BAWinSize = BASize;
1015         pTxWI->ShortGI = pTransmit->field.ShortGI;
1016         pTxWI->STBC = pTransmit->field.STBC;
1017
1018         pTxWI->WirelessCliID = WCID;
1019         pTxWI->MPDUtotalByteCount = Length;
1020         pTxWI->PacketId = PID;
1021
1022         // If CCK or OFDM, BW must be 20
1023         pTxWI->BW =
1024             (pTransmit->field.MODE <=
1025              MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1026
1027         pTxWI->MCS = pTransmit->field.MCS;
1028         pTxWI->PHYMODE = pTransmit->field.MODE;
1029         pTxWI->CFACK = CfAck;
1030
1031         if (pMac) {
1032                 if (pAd->CommonCfg.bMIMOPSEnable) {
1033                         if ((pMac->MmpsMode == MMPS_DYNAMIC)
1034                             && (pTransmit->field.MCS > 7)) {
1035                                 // Dynamic MIMO Power Save Mode
1036                                 pTxWI->MIMOps = 1;
1037                         } else if (pMac->MmpsMode == MMPS_STATIC) {
1038                                 // Static MIMO Power Save Mode
1039                                 if (pTransmit->field.MODE >= MODE_HTMIX
1040                                     && pTransmit->field.MCS > 7) {
1041                                         pTxWI->MCS = 7;
1042                                         pTxWI->MIMOps = 0;
1043                                 }
1044                         }
1045                 }
1046                 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1047                 if (pMac->bIAmBadAtheros
1048                     && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1049                         pTxWI->MpduDensity = 7;
1050                 } else {
1051                         pTxWI->MpduDensity = pMac->MpduDensity;
1052                 }
1053         }
1054
1055         pTxWI->PacketId = pTxWI->MCS;
1056         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1057 }
1058
1059 VOID RTMPWriteTxWI_Data(IN PRTMP_ADAPTER pAd,
1060                         IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1061 {
1062         HTTRANSMIT_SETTING *pTransmit;
1063         PMAC_TABLE_ENTRY pMacEntry;
1064         UCHAR BASize;
1065
1066         ASSERT(pTxWI);
1067
1068         pTransmit = pTxBlk->pTransmit;
1069         pMacEntry = pTxBlk->pMacEntry;
1070
1071         //
1072         // Always use Long preamble before verifiation short preamble functionality works well.
1073         // Todo: remove the following line if short preamble functionality works
1074         //
1075         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1076         NdisZeroMemory(pTxWI, TXWI_SIZE);
1077
1078         pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1079         pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1080         pTxWI->txop = pTxBlk->FrameGap;
1081
1082         pTxWI->WirelessCliID = pTxBlk->Wcid;
1083
1084         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1085         pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1086
1087         // If CCK or OFDM, BW must be 20
1088         pTxWI->BW =
1089             (pTransmit->field.MODE <=
1090              MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1091         pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1092
1093         // John tune the performace with Intel Client in 20 MHz performance
1094         BASize = pAd->CommonCfg.TxBASize;
1095         if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1096                 UCHAR RABAOriIdx = 0;   //The RA's BA Originator table index.
1097
1098                 RABAOriIdx =
1099                     pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1100                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1101         }
1102
1103         pTxWI->TxBF = pTransmit->field.TxBF;
1104         pTxWI->BAWinSize = BASize;
1105         pTxWI->ShortGI = pTransmit->field.ShortGI;
1106         pTxWI->STBC = pTransmit->field.STBC;
1107
1108         pTxWI->MCS = pTransmit->field.MCS;
1109         pTxWI->PHYMODE = pTransmit->field.MODE;
1110
1111         if (pMacEntry) {
1112                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1113                     && (pTransmit->field.MCS > 7)) {
1114                         // Dynamic MIMO Power Save Mode
1115                         pTxWI->MIMOps = 1;
1116                 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1117                         // Static MIMO Power Save Mode
1118                         if (pTransmit->field.MODE >= MODE_HTMIX
1119                             && pTransmit->field.MCS > 7) {
1120                                 pTxWI->MCS = 7;
1121                                 pTxWI->MIMOps = 0;
1122                         }
1123                 }
1124
1125                 if (pMacEntry->bIAmBadAtheros
1126                     && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1127                         pTxWI->MpduDensity = 7;
1128                 } else {
1129                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1130                 }
1131         }
1132
1133         // for rate adapation
1134         pTxWI->PacketId = pTxWI->MCS;
1135 }
1136
1137 VOID RTMPWriteTxWI_Cache(IN PRTMP_ADAPTER pAd,
1138                          IN OUT PTXWI_STRUC pTxWI, IN TX_BLK * pTxBlk)
1139 {
1140         PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1141         PMAC_TABLE_ENTRY pMacEntry;
1142
1143         //
1144         // update TXWI
1145         //
1146         pMacEntry = pTxBlk->pMacEntry;
1147         pTransmit = pTxBlk->pTransmit;
1148
1149         //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1150         //if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry))
1151         //if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch))
1152         if (pMacEntry->bAutoTxRateSwitch) {
1153                 pTxWI->txop = IFS_HTTXOP;
1154
1155                 // If CCK or OFDM, BW must be 20
1156                 pTxWI->BW =
1157                     (pTransmit->field.MODE <=
1158                      MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1159                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1160                 pTxWI->STBC = pTransmit->field.STBC;
1161
1162                 pTxWI->MCS = pTransmit->field.MCS;
1163                 pTxWI->PHYMODE = pTransmit->field.MODE;
1164
1165                 // set PID for TxRateSwitching
1166                 pTxWI->PacketId = pTransmit->field.MCS;
1167         }
1168
1169         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1170         pTxWI->MIMOps = 0;
1171
1172         if (pAd->CommonCfg.bMIMOPSEnable) {
1173                 // MIMO Power Save Mode
1174                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1175                     && (pTransmit->field.MCS > 7)) {
1176                         // Dynamic MIMO Power Save Mode
1177                         pTxWI->MIMOps = 1;
1178                 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1179                         // Static MIMO Power Save Mode
1180                         if ((pTransmit->field.MODE >= MODE_HTMIX)
1181                             && (pTransmit->field.MCS > 7)) {
1182                                 pTxWI->MCS = 7;
1183                                 pTxWI->MIMOps = 0;
1184                         }
1185                 }
1186         }
1187
1188         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1189
1190 }
1191
1192 // should be called only when -
1193 // 1. MEADIA_CONNECTED
1194 // 2. AGGREGATION_IN_USED
1195 // 3. Fragmentation not in used
1196 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1197 BOOLEAN TxFrameIsAggregatible(IN PRTMP_ADAPTER pAd,
1198                               IN PUCHAR pPrevAddr1, IN PUCHAR p8023hdr)
1199 {
1200
1201         // can't aggregate EAPOL (802.1x) frame
1202         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1203                 return FALSE;
1204
1205         // can't aggregate multicast/broadcast frame
1206         if (p8023hdr[0] & 0x01)
1207                 return FALSE;
1208
1209         if (INFRA_ON(pAd))      // must be unicast to AP
1210                 return TRUE;
1211         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr))  // unicast to same STA
1212                 return TRUE;
1213         else
1214                 return FALSE;
1215 }
1216
1217 /*
1218         ========================================================================
1219
1220         Routine Description:
1221            Check the MSDU Aggregation policy
1222         1.HT aggregation is A-MSDU
1223         2.legaacy rate aggregation is software aggregation by Ralink.
1224
1225         Arguments:
1226
1227         Return Value:
1228
1229         Note:
1230
1231         ========================================================================
1232 */
1233 BOOLEAN PeerIsAggreOn(IN PRTMP_ADAPTER pAd,
1234                       IN ULONG TxRate, IN PMAC_TABLE_ENTRY pMacEntry)
1235 {
1236         ULONG AFlags =
1237             (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1238
1239         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1240                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1241                         return TRUE;
1242                 }
1243 #ifdef AGGREGATION_SUPPORT
1244                 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) {  // legacy  Ralink Aggregation support
1245                         return TRUE;
1246                 }
1247 #endif // AGGREGATION_SUPPORT //
1248         }
1249
1250         return FALSE;
1251
1252 }
1253
1254 /*
1255         ========================================================================
1256
1257         Routine Description:
1258                 Check and fine the packet waiting in SW queue with highest priority
1259
1260         Arguments:
1261                 pAd Pointer to our adapter
1262
1263         Return Value:
1264                 pQueue          Pointer to Waiting Queue
1265
1266         IRQL = DISPATCH_LEVEL
1267
1268         Note:
1269
1270         ========================================================================
1271 */
1272 PQUEUE_HEADER RTMPCheckTxSwQueue(IN PRTMP_ADAPTER pAd, OUT PUCHAR pQueIdx)
1273 {
1274
1275         ULONG Number;
1276         // 2004-11-15 to be removed. test aggregation only
1277 //      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1278 //               return NULL;
1279
1280         Number = pAd->TxSwQueue[QID_AC_BK].Number
1281             + pAd->TxSwQueue[QID_AC_BE].Number
1282             + pAd->TxSwQueue[QID_AC_VI].Number
1283             + pAd->TxSwQueue[QID_AC_VO].Number;
1284
1285         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1286                 *pQueIdx = QID_AC_VO;
1287                 return (&pAd->TxSwQueue[QID_AC_VO]);
1288         } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1289                 *pQueIdx = QID_AC_VI;
1290                 return (&pAd->TxSwQueue[QID_AC_VI]);
1291         } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1292                 *pQueIdx = QID_AC_BE;
1293                 return (&pAd->TxSwQueue[QID_AC_BE]);
1294         } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1295                 *pQueIdx = QID_AC_BK;
1296                 return (&pAd->TxSwQueue[QID_AC_BK]);
1297         }
1298         // No packet pending in Tx Sw queue
1299         *pQueIdx = QID_AC_BK;
1300
1301         return (NULL);
1302 }
1303
1304 /*
1305         ========================================================================
1306
1307         Routine Description:
1308                 Suspend MSDU transmission
1309
1310         Arguments:
1311                 pAd     Pointer to our adapter
1312
1313         Return Value:
1314                 None
1315
1316         Note:
1317
1318         ========================================================================
1319 */
1320 VOID RTMPSuspendMsduTransmission(IN PRTMP_ADAPTER pAd)
1321 {
1322         DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1323
1324         //
1325         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1326         // use Lowbound as R66 value on ScanNextChannel(...)
1327         //
1328         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1329                                     &pAd->BbpTuning.R66CurrentValue);
1330
1331         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1332         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1333         RTMPSetAGCInitValue(pAd, BW_20);
1334
1335         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1336         //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
1337 }
1338
1339 /*
1340         ========================================================================
1341
1342         Routine Description:
1343                 Resume MSDU transmission
1344
1345         Arguments:
1346                 pAd     Pointer to our adapter
1347
1348         Return Value:
1349                 None
1350
1351         IRQL = DISPATCH_LEVEL
1352
1353         Note:
1354
1355         ========================================================================
1356 */
1357 VOID RTMPResumeMsduTransmission(IN PRTMP_ADAPTER pAd)
1358 {
1359 //    UCHAR                     IrqState;
1360
1361         DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1362
1363         // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1364         // R66 should not be 0
1365         if (pAd->BbpTuning.R66CurrentValue == 0) {
1366                 pAd->BbpTuning.R66CurrentValue = 0x38;
1367                 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1368         }
1369
1370         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1371                                      pAd->BbpTuning.R66CurrentValue);
1372
1373         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1374 // sample, for IRQ LOCK to SEM LOCK
1375 //    IrqState = pAd->irq_disabled;
1376 //      if (IrqState)
1377 //              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1378 //    else
1379         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1380 }
1381
1382 UINT deaggregate_AMSDU_announce(IN PRTMP_ADAPTER pAd,
1383                                 PNDIS_PACKET pPacket,
1384                                 IN PUCHAR pData, IN ULONG DataSize)
1385 {
1386         USHORT PayloadSize;
1387         USHORT SubFrameSize;
1388         PHEADER_802_3 pAMSDUsubheader;
1389         UINT nMSDU;
1390         UCHAR Header802_3[14];
1391
1392         PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
1393         PNDIS_PACKET pClonePacket;
1394
1395         nMSDU = 0;
1396
1397         while (DataSize > LENGTH_802_3) {
1398
1399                 nMSDU++;
1400
1401                 //hex_dump("subheader", pData, 64);
1402                 pAMSDUsubheader = (PHEADER_802_3) pData;
1403                 //pData += LENGTH_802_3;
1404                 PayloadSize =
1405                     pAMSDUsubheader->Octet[1] +
1406                     (pAMSDUsubheader->Octet[0] << 8);
1407                 SubFrameSize = PayloadSize + LENGTH_802_3;
1408
1409                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1410                         break;
1411                 }
1412                 //DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n",  nMSDU, PayloadSize));
1413
1414                 pPayload = pData + LENGTH_802_3;
1415                 pDA = pData;
1416                 pSA = pData + MAC_ADDR_LEN;
1417
1418                 // convert to 802.3 header
1419                 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1420                                  pRemovedLLCSNAP);
1421
1422                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1423                         /* avoid local heap overflow, use dyanamic allocation */
1424                         MLME_QUEUE_ELEM *Elem =
1425                             (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM),
1426                                                         MEM_ALLOC_FLAG);
1427                         if (Elem != NULL) {
1428                                 memmove(Elem->Msg +
1429                                         (LENGTH_802_11 + LENGTH_802_1_H),
1430                                         pPayload, PayloadSize);
1431                                 Elem->MsgLen =
1432                                     LENGTH_802_11 + LENGTH_802_1_H +
1433                                     PayloadSize;
1434                                 //WpaEAPOLKeyAction(pAd, Elem);
1435                                 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1436                                                           Elem->Msg,
1437                                                           Elem->MsgLen, 0, 0, 0,
1438                                                           0);
1439                                 kfree(Elem);
1440                         }
1441                 }
1442
1443                 {
1444                         if (pRemovedLLCSNAP) {
1445                                 pPayload -= LENGTH_802_3;
1446                                 PayloadSize += LENGTH_802_3;
1447                                 NdisMoveMemory(pPayload, &Header802_3[0],
1448                                                LENGTH_802_3);
1449                         }
1450                 }
1451
1452                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1453                 if (pClonePacket) {
1454                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1455                                                          RTMP_GET_PACKET_IF
1456                                                          (pPacket));
1457                 }
1458
1459                 // A-MSDU has padding to multiple of 4 including subframe header.
1460                 // align SubFrameSize up to multiple of 4
1461                 SubFrameSize = (SubFrameSize + 3) & (~0x3);
1462
1463                 if (SubFrameSize > 1528 || SubFrameSize < 32) {
1464                         break;
1465                 }
1466
1467                 if (DataSize > SubFrameSize) {
1468                         pData += SubFrameSize;
1469                         DataSize -= SubFrameSize;
1470                 } else {
1471                         // end of A-MSDU
1472                         DataSize = 0;
1473                 }
1474         }
1475
1476         // finally release original rx packet
1477         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1478
1479         return nMSDU;
1480 }
1481
1482 UINT BA_Reorder_AMSDU_Annnounce(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1483 {
1484         PUCHAR pData;
1485         USHORT DataSize;
1486         UINT nMSDU = 0;
1487
1488         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1489         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1490
1491         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1492
1493         return nMSDU;
1494 }
1495
1496 /*
1497         ==========================================================================
1498         Description:
1499                 Look up the MAC address in the MAC table. Return NULL if not found.
1500         Return:
1501                 pEntry - pointer to the MAC entry; NULL is not found
1502         ==========================================================================
1503 */
1504 MAC_TABLE_ENTRY *MacTableLookup(IN PRTMP_ADAPTER pAd, PUCHAR pAddr)
1505 {
1506         ULONG HashIdx;
1507         MAC_TABLE_ENTRY *pEntry = NULL;
1508
1509         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1510         pEntry = pAd->MacTab.Hash[HashIdx];
1511
1512         while (pEntry
1513                && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1514                    || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1515                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1516                         break;
1517                 } else
1518                         pEntry = pEntry->pNext;
1519         }
1520
1521         return pEntry;
1522 }
1523
1524 MAC_TABLE_ENTRY *MacTableInsertEntry(IN PRTMP_ADAPTER pAd,
1525                                      IN PUCHAR pAddr,
1526                                      IN UCHAR apidx, IN BOOLEAN CleanAll)
1527 {
1528         UCHAR HashIdx;
1529         int i, FirstWcid;
1530         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1531 //      USHORT  offset;
1532 //      ULONG   addr;
1533
1534         // if FULL, return
1535         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1536                 return NULL;
1537
1538         FirstWcid = 1;
1539
1540         if (pAd->StaCfg.BssType == BSS_INFRA)
1541                 FirstWcid = 2;
1542
1543         // allocate one MAC entry
1544         NdisAcquireSpinLock(&pAd->MacTabLock);
1545         for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++)      // skip entry#0 so that "entry index == AID" for fast lookup
1546         {
1547                 // pick up the first available vacancy
1548                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1549                     (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1550                     (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1551                     (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1552                     ) {
1553                         pEntry = &pAd->MacTab.Content[i];
1554                         if (CleanAll == TRUE) {
1555                                 pEntry->MaxSupportedRate = RATE_11;
1556                                 pEntry->CurrTxRate = RATE_11;
1557                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1558                                 pEntry->PairwiseKey.KeyLen = 0;
1559                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1560                         }
1561                         {
1562                                 {
1563                                         pEntry->ValidAsCLI = TRUE;
1564                                         pEntry->ValidAsWDS = FALSE;
1565                                         pEntry->ValidAsApCli = FALSE;
1566                                         pEntry->ValidAsMesh = FALSE;
1567                                         pEntry->ValidAsDls = FALSE;
1568                                 }
1569                         }
1570
1571                         pEntry->bIAmBadAtheros = FALSE;
1572                         pEntry->pAd = pAd;
1573                         pEntry->CMTimerRunning = FALSE;
1574                         pEntry->EnqueueEapolStartTimerRunning =
1575                             EAPOL_START_DISABLE;
1576                         pEntry->RSNIE_Len = 0;
1577                         NdisZeroMemory(pEntry->R_Counter,
1578                                        sizeof(pEntry->R_Counter));
1579                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1580
1581                         if (pEntry->ValidAsMesh)
1582                                 pEntry->apidx =
1583                                     (apidx - MIN_NET_DEVICE_FOR_MESH);
1584                         else if (pEntry->ValidAsApCli)
1585                                 pEntry->apidx =
1586                                     (apidx - MIN_NET_DEVICE_FOR_APCLI);
1587                         else if (pEntry->ValidAsWDS)
1588                                 pEntry->apidx =
1589                                     (apidx - MIN_NET_DEVICE_FOR_WDS);
1590                         else
1591                                 pEntry->apidx = apidx;
1592
1593                         {
1594                                 {
1595                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1596                                         pEntry->WepStatus =
1597                                             pAd->StaCfg.WepStatus;
1598                                         pEntry->PrivacyFilter =
1599                                             Ndis802_11PrivFilterAcceptAll;
1600 #ifdef RTMP_MAC_PCI
1601                                         AsicRemovePairwiseKeyEntry(pAd,
1602                                                                    pEntry->
1603                                                                    apidx,
1604                                                                    (UCHAR) i);
1605 #endif // RTMP_MAC_PCI //
1606                                 }
1607                         }
1608
1609                         pEntry->GTKState = REKEY_NEGOTIATING;
1610                         pEntry->PairwiseKey.KeyLen = 0;
1611                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1612                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1613
1614                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1615                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1616                         pEntry->Sst = SST_NOT_AUTH;
1617                         pEntry->AuthState = AS_NOT_AUTH;
1618                         pEntry->Aid = (USHORT) i;       //0;
1619                         pEntry->CapabilityInfo = 0;
1620                         pEntry->PsMode = PWR_ACTIVE;
1621                         pEntry->PsQIdleCount = 0;
1622                         pEntry->NoDataIdleCount = 0;
1623                         pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1624                         pEntry->ContinueTxFailCnt = 0;
1625                         InitializeQueueHeader(&pEntry->PsQueue);
1626
1627                         pAd->MacTab.Size++;
1628                         // Add this entry into ASIC RX WCID search table
1629                         RTMP_STA_ENTRY_ADD(pAd, pEntry);
1630
1631                         DBGPRINT(RT_DEBUG_TRACE,
1632                                  ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1633                                   i, pAd->MacTab.Size));
1634                         break;
1635                 }
1636         }
1637
1638         // add this MAC entry into HASH table
1639         if (pEntry) {
1640                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1641                 if (pAd->MacTab.Hash[HashIdx] == NULL) {
1642                         pAd->MacTab.Hash[HashIdx] = pEntry;
1643                 } else {
1644                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1645                         while (pCurrEntry->pNext != NULL)
1646                                 pCurrEntry = pCurrEntry->pNext;
1647                         pCurrEntry->pNext = pEntry;
1648                 }
1649         }
1650
1651         NdisReleaseSpinLock(&pAd->MacTabLock);
1652         return pEntry;
1653 }
1654
1655 /*
1656         ==========================================================================
1657         Description:
1658                 Delete a specified client from MAC table
1659         ==========================================================================
1660  */
1661 BOOLEAN MacTableDeleteEntry(IN PRTMP_ADAPTER pAd,
1662                             IN USHORT wcid, IN PUCHAR pAddr)
1663 {
1664         USHORT HashIdx;
1665         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1666         BOOLEAN Cancelled;
1667         //USHORT        offset; // unused variable
1668         //UCHAR j;                      // unused variable
1669
1670         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1671                 return FALSE;
1672
1673         NdisAcquireSpinLock(&pAd->MacTabLock);
1674
1675         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1676         //pEntry = pAd->MacTab.Hash[HashIdx];
1677         pEntry = &pAd->MacTab.Content[wcid];
1678
1679         if (pEntry
1680             && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1681                 || pEntry->ValidAsMesh)) {
1682                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1683
1684                         // Delete this entry from ASIC on-chip WCID Table
1685                         RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1686
1687                         // free resources of BA
1688                         BASessionTearDownALL(pAd, pEntry->Aid);
1689
1690                         pPrevEntry = NULL;
1691                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
1692                         ASSERT(pProbeEntry);
1693
1694                         // update Hash list
1695                         do {
1696                                 if (pProbeEntry == pEntry) {
1697                                         if (pPrevEntry == NULL) {
1698                                                 pAd->MacTab.Hash[HashIdx] =
1699                                                     pEntry->pNext;
1700                                         } else {
1701                                                 pPrevEntry->pNext =
1702                                                     pEntry->pNext;
1703                                         }
1704                                         break;
1705                                 }
1706
1707                                 pPrevEntry = pProbeEntry;
1708                                 pProbeEntry = pProbeEntry->pNext;
1709                         } while (pProbeEntry);
1710
1711                         // not found !!!
1712                         ASSERT(pProbeEntry != NULL);
1713
1714                         RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1715
1716                         if (pEntry->EnqueueEapolStartTimerRunning !=
1717                             EAPOL_START_DISABLE) {
1718                                 RTMPCancelTimer(&pEntry->
1719                                                 EnqueueStartForPSKTimer,
1720                                                 &Cancelled);
1721                                 pEntry->EnqueueEapolStartTimerRunning =
1722                                     EAPOL_START_DISABLE;
1723                         }
1724
1725                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1726                         pAd->MacTab.Size--;
1727                         DBGPRINT(RT_DEBUG_TRACE,
1728                                  ("MacTableDeleteEntry1 - Total= %d\n",
1729                                   pAd->MacTab.Size));
1730                 } else {
1731                         DBGPRINT(RT_DEBUG_OFF,
1732                                  ("\n%s: Impossible Wcid = %d !!!!!\n",
1733                                   __func__, wcid));
1734                 }
1735         }
1736
1737         NdisReleaseSpinLock(&pAd->MacTabLock);
1738
1739         //Reset operating mode when no Sta.
1740         if (pAd->MacTab.Size == 0) {
1741                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1742                 //AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1743                 RTMP_UPDATE_PROTECT(pAd);       // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
1744         }
1745
1746         return TRUE;
1747 }
1748
1749 /*
1750         ==========================================================================
1751         Description:
1752                 This routine reset the entire MAC table. All packets pending in
1753                 the power-saving queues are freed here.
1754         ==========================================================================
1755  */
1756 VOID MacTableReset(IN PRTMP_ADAPTER pAd)
1757 {
1758         int i;
1759
1760         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1761         //NdisAcquireSpinLock(&pAd->MacTabLock);
1762
1763         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1764 #ifdef RTMP_MAC_PCI
1765                 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1766 #endif // RTMP_MAC_PCI //
1767                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1768
1769                         // free resources of BA
1770                         BASessionTearDownALL(pAd, i);
1771
1772                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1773
1774 #ifdef RTMP_MAC_USB
1775                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1776                         RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1777 #endif // RTMP_MAC_USB //
1778
1779                         //AsicDelWcidTab(pAd, i);
1780                 }
1781         }
1782
1783         return;
1784 }
1785
1786 /*
1787         ==========================================================================
1788         Description:
1789
1790         IRQL = DISPATCH_LEVEL
1791
1792         ==========================================================================
1793 */
1794 VOID AssocParmFill(IN PRTMP_ADAPTER pAd,
1795                    IN OUT MLME_ASSOC_REQ_STRUCT * AssocReq,
1796                    IN PUCHAR pAddr,
1797                    IN USHORT CapabilityInfo,
1798                    IN ULONG Timeout, IN USHORT ListenIntv)
1799 {
1800         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1801         // Add mask to support 802.11b mode only
1802         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;  // not cf-pollable, not cf-poll-request
1803         AssocReq->Timeout = Timeout;
1804         AssocReq->ListenIntv = ListenIntv;
1805 }
1806
1807 /*
1808         ==========================================================================
1809         Description:
1810
1811         IRQL = DISPATCH_LEVEL
1812
1813         ==========================================================================
1814 */
1815 VOID DisassocParmFill(IN PRTMP_ADAPTER pAd,
1816                       IN OUT MLME_DISASSOC_REQ_STRUCT * DisassocReq,
1817                       IN PUCHAR pAddr, IN USHORT Reason)
1818 {
1819         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1820         DisassocReq->Reason = Reason;
1821 }
1822
1823 /*
1824         ========================================================================
1825
1826         Routine Description:
1827                 Check the out going frame, if this is an DHCP or ARP datagram
1828         will be duplicate another frame at low data rate transmit.
1829
1830         Arguments:
1831                 pAd             Pointer to our adapter
1832                 pPacket         Pointer to outgoing Ndis frame
1833
1834         Return Value:
1835                 TRUE            To be duplicate at Low data rate transmit. (1mb)
1836                 FALSE           Do nothing.
1837
1838         IRQL = DISPATCH_LEVEL
1839
1840         Note:
1841
1842                 MAC header + IP Header + UDP Header
1843                   14 Bytes        20 Bytes
1844
1845                 UDP Header
1846                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1847                                                 Source Port
1848                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1849                                         Destination Port
1850
1851                 port 0x43 means Bootstrap Protocol, server.
1852                 Port 0x44 means Bootstrap Protocol, client.
1853
1854         ========================================================================
1855 */
1856
1857 BOOLEAN RTMPCheckDHCPFrame(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1858 {
1859         PACKET_INFO PacketInfo;
1860         ULONG NumberOfBytesRead = 0;
1861         ULONG CurrentOffset = 0;
1862         PVOID pVirtualAddress = NULL;
1863         UINT NdisBufferLength;
1864         PUCHAR pSrc;
1865         USHORT Protocol;
1866         UCHAR ByteOffset36 = 0;
1867         UCHAR ByteOffset38 = 0;
1868         BOOLEAN ReadFirstParm = TRUE;
1869
1870         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *) & pVirtualAddress,
1871                              &NdisBufferLength);
1872
1873         NumberOfBytesRead += NdisBufferLength;
1874         pSrc = (PUCHAR) pVirtualAddress;
1875         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1876
1877         //
1878         // Check DHCP & BOOTP protocol
1879         //
1880         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1881                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1882                         CurrentOffset =
1883                             35 - (NumberOfBytesRead - NdisBufferLength);
1884                         ByteOffset36 = *(pSrc + CurrentOffset);
1885                         ReadFirstParm = FALSE;
1886                 }
1887
1888                 if (NumberOfBytesRead >= 37) {
1889                         CurrentOffset =
1890                             37 - (NumberOfBytesRead - NdisBufferLength);
1891                         ByteOffset38 = *(pSrc + CurrentOffset);
1892                         //End of Read
1893                         break;
1894                 }
1895                 return FALSE;
1896         }
1897
1898         // Check for DHCP & BOOTP protocol
1899         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1900                 //
1901                 // 2054 (hex 0806) for ARP datagrams
1902                 // if this packet is not ARP datagrams, then do nothing
1903                 // ARP datagrams will also be duplicate at 1mb broadcast frames
1904                 //
1905                 if (Protocol != 0x0806)
1906                         return FALSE;
1907         }
1908
1909         return TRUE;
1910 }
1911
1912 BOOLEAN RTMPCheckEtherType(IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket)
1913 {
1914         USHORT TypeLen;
1915         UCHAR Byte0, Byte1;
1916         PUCHAR pSrcBuf;
1917         UINT32 pktLen;
1918         UINT16 srcPort, dstPort;
1919         BOOLEAN status = TRUE;
1920
1921         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1922         pktLen = GET_OS_PKT_LEN(pPacket);
1923
1924         ASSERT(pSrcBuf);
1925
1926         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1927
1928         // get Ethernet protocol field
1929         TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1930
1931         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
1932
1933         if (TypeLen <= 1500) {  // 802.3, 802.3 LLC
1934                 /*
1935                    DestMAC(6) + SrcMAC(6) + Lenght(2) +
1936                    DSAP(1) + SSAP(1) + Control(1) +
1937                    if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1938                    => + SNAP (5, OriginationID(3) + etherType(2))
1939                  */
1940                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1941                     && pSrcBuf[2] == 0x03) {
1942                         Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 6,
1943                                                   &Byte0, &Byte1);
1944                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1945                         TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1946                         pSrcBuf += 8;   // Skip this LLC/SNAP header
1947                 } else {
1948                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
1949                 }
1950         }
1951         // If it's a VLAN packet, get the real Type/Length field.
1952         if (TypeLen == 0x8100) {
1953                 /* 0x8100 means VLAN packets */
1954
1955                 /* Dest. MAC Address (6-bytes) +
1956                    Source MAC Address (6-bytes) +
1957                    Length/Type = 802.1Q Tag Type (2-byte) +
1958                    Tag Control Information (2-bytes) +
1959                    Length / Type (2-bytes) +
1960                    data payload (0-n bytes) +
1961                    Pad (0-p bytes) +
1962                    Frame Check Sequence (4-bytes) */
1963
1964                 RTMP_SET_PACKET_VLAN(pPacket, 1);
1965                 Sniff2BytesFromNdisBuffer((PNDIS_BUFFER) pSrcBuf, 2, &Byte0,
1966                                           &Byte1);
1967                 TypeLen = (USHORT) ((Byte0 << 8) + Byte1);
1968
1969                 pSrcBuf += 4;   // Skip the VLAN Header.
1970         }
1971
1972         switch (TypeLen) {
1973         case 0x0800:
1974                 {
1975                         ASSERT((pktLen > 34));
1976                         if (*(pSrcBuf + 9) == 0x11) {   // udp packet
1977                                 ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
1978
1979                                 pSrcBuf += 20;  // Skip the IP header
1980                                 srcPort =
1981                                     OS_NTOHS(get_unaligned
1982                                              ((PUINT16) (pSrcBuf)));
1983                                 dstPort =
1984                                     OS_NTOHS(get_unaligned
1985                                              ((PUINT16) (pSrcBuf + 2)));
1986
1987                                 if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) {     //It's a BOOTP/DHCP packet
1988                                         RTMP_SET_PACKET_DHCP(pPacket, 1);
1989                                 }
1990                         }
1991                 }
1992                 break;
1993         case 0x0806:
1994                 {
1995                         //ARP Packet.
1996                         RTMP_SET_PACKET_DHCP(pPacket, 1);
1997                 }
1998                 break;
1999         case 0x888e:
2000                 {
2001                         // EAPOL Packet.
2002                         RTMP_SET_PACKET_EAPOL(pPacket, 1);
2003                 }
2004                 break;
2005         default:
2006                 status = FALSE;
2007                 break;
2008         }
2009
2010         return status;
2011
2012 }
2013
2014 VOID Update_Rssi_Sample(IN PRTMP_ADAPTER pAd,
2015                         IN RSSI_SAMPLE * pRssi, IN PRXWI_STRUC pRxWI)
2016 {
2017         CHAR rssi0 = pRxWI->RSSI0;
2018         CHAR rssi1 = pRxWI->RSSI1;
2019         CHAR rssi2 = pRxWI->RSSI2;
2020
2021         if (rssi0 != 0) {
2022                 pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR) rssi0, RSSI_0);
2023                 pRssi->AvgRssi0X8 =
2024                     (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2025                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2026         }
2027
2028         if (rssi1 != 0) {
2029                 pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR) rssi1, RSSI_1);
2030                 pRssi->AvgRssi1X8 =
2031                     (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2032                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2033         }
2034
2035         if (rssi2 != 0) {
2036                 pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR) rssi2, RSSI_2);
2037                 pRssi->AvgRssi2X8 =
2038                     (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2039                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2040         }
2041 }
2042
2043 // Normal legacy Rx packet indication
2044 VOID Indicate_Legacy_Packet(IN PRTMP_ADAPTER pAd,
2045                             IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2046 {
2047         PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2048         UCHAR Header802_3[LENGTH_802_3];
2049
2050         // 1. get 802.3 Header
2051         // 2. remove LLC
2052         //              a. pointer pRxBlk->pData to payload
2053         //      b. modify pRxBlk->DataSize
2054         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2055
2056         if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2057
2058                 // release packet
2059                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2060                 return;
2061         }
2062
2063         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2064
2065 #ifdef RTMP_MAC_USB
2066         if (pAd->CommonCfg.bDisableReordering == 0) {
2067                 PBA_REC_ENTRY pBAEntry;
2068                 ULONG Now32;
2069                 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
2070                 UCHAR TID = pRxBlk->pRxWI->TID;
2071                 USHORT Idx;
2072
2073 #define REORDERING_PACKET_TIMEOUT               ((100 * OS_HZ)/1000)    // system ticks -- 100 ms
2074
2075                 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2076                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2077                         if (Idx != 0) {
2078                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2079                                 // update last rx time
2080                                 NdisGetSystemUpTime(&Now32);
2081                                 if ((pBAEntry->list.qlen > 0) &&
2082                                     RTMP_TIME_AFTER((unsigned long)Now32,
2083                                                     (unsigned long)(pBAEntry->
2084                                                                     LastIndSeqAtTimer
2085                                                                     +
2086                                                                     (REORDERING_PACKET_TIMEOUT)))
2087                                     ) {
2088                                         DBGPRINT(RT_DEBUG_OFF,
2089                                                  ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2090                                                   pRxBlk->Flags,
2091                                                   pRxBlk->pRxWI->TID,
2092                                                   pRxBlk->RxD.AMPDU));
2093                                         hex_dump("Dump the legacy Packet:",
2094                                                  GET_OS_PKT_DATAPTR(pRxBlk->
2095                                                                     pRxPacket),
2096                                                  64);
2097                                         ba_flush_reordering_timeout_mpdus(pAd,
2098                                                                           pBAEntry,
2099                                                                           Now32);
2100                                 }
2101                         }
2102                 }
2103         }
2104 #endif // RTMP_MAC_USB //
2105
2106         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2107
2108         //
2109         // pass this 802.3 packet to upper layer or forward this packet to WM directly
2110         //
2111         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2112 }
2113
2114 // Normal, AMPDU or AMSDU
2115 VOID CmmRxnonRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2116                                  IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2117 {
2118         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2119             && (pAd->CommonCfg.bDisableReordering == 0)) {
2120                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2121         } else {
2122                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2123                         // handle A-MSDU
2124                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2125                 } else {
2126                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2127                 }
2128         }
2129 }
2130
2131 VOID CmmRxRalinkFrameIndicate(IN PRTMP_ADAPTER pAd,
2132                               IN MAC_TABLE_ENTRY * pEntry,
2133                               IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2134 {
2135         UCHAR Header802_3[LENGTH_802_3];
2136         UINT16 Msdu2Size;
2137         UINT16 Payload1Size, Payload2Size;
2138         PUCHAR pData2;
2139         PNDIS_PACKET pPacket2 = NULL;
2140
2141         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2142
2143         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2144                 /* skip two byte MSDU2 len */
2145                 pRxBlk->pData += 2;
2146                 pRxBlk->DataSize -= 2;
2147         } else {
2148                 // release packet
2149                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2150                                     NDIS_STATUS_FAILURE);
2151                 return;
2152         }
2153
2154         // get 802.3 Header and  remove LLC
2155         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2156
2157         ASSERT(pRxBlk->pRxPacket);
2158
2159         // Ralink Aggregation frame
2160         pAd->RalinkCounters.OneSecRxAggregationCount++;
2161         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2162         Payload2Size = Msdu2Size - LENGTH_802_3;
2163
2164         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2165
2166         pPacket2 =
2167             duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2168                           Payload2Size, FromWhichBSSID);
2169
2170         if (!pPacket2) {
2171                 // release packet
2172                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2173                                     NDIS_STATUS_FAILURE);
2174                 return;
2175         }
2176         // update payload size of 1st packet
2177         pRxBlk->DataSize = Payload1Size;
2178         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2179
2180         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2181                                          FromWhichBSSID);
2182
2183         if (pPacket2) {
2184                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2185         }
2186 }
2187
2188 #define RESET_FRAGFRAME(_fragFrame) \
2189         {                                                               \
2190                 _fragFrame.RxSize = 0;          \
2191                 _fragFrame.Sequence = 0;        \
2192                 _fragFrame.LastFrag = 0;        \
2193                 _fragFrame.Flags = 0;           \
2194         }
2195
2196 PNDIS_PACKET RTMPDeFragmentDataFrame(IN PRTMP_ADAPTER pAd, IN RX_BLK * pRxBlk)
2197 {
2198         PHEADER_802_11 pHeader = pRxBlk->pHeader;
2199         PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
2200         UCHAR *pData = pRxBlk->pData;
2201         USHORT DataSize = pRxBlk->DataSize;
2202         PNDIS_PACKET pRetPacket = NULL;
2203         UCHAR *pFragBuffer = NULL;
2204         BOOLEAN bReassDone = FALSE;
2205         UCHAR HeaderRoom = 0;
2206
2207         ASSERT(pHeader);
2208
2209         HeaderRoom = pData - (UCHAR *) pHeader;
2210
2211         // Re-assemble the fragmented packets
2212         if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
2213         {
2214                 // the first pkt of fragment, record it.
2215                 if (pHeader->FC.MoreFrag) {
2216                         ASSERT(pAd->FragFrame.pFragPacket);
2217                         pFragBuffer =
2218                             GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2219                         pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2220                         NdisMoveMemory(pFragBuffer, pHeader,
2221                                        pAd->FragFrame.RxSize);
2222                         pAd->FragFrame.Sequence = pHeader->Sequence;
2223                         pAd->FragFrame.LastFrag = pHeader->Frag;        // Should be 0
2224                         ASSERT(pAd->FragFrame.LastFrag == 0);
2225                         goto done;      // end of processing this frame
2226                 }
2227         } else                  //Middle & End of fragment
2228         {
2229                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2230                     (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2231                         // Fragment is not the same sequence or out of fragment number order
2232                         // Reset Fragment control blk
2233                         RESET_FRAGFRAME(pAd->FragFrame);
2234                         DBGPRINT(RT_DEBUG_ERROR,
2235                                  ("Fragment is not the same sequence or out of fragment number order.\n"));
2236                         goto done;      // give up this frame
2237                 } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2238                         // Fragment frame is too large, it exeeds the maximum frame size.
2239                         // Reset Fragment control blk
2240                         RESET_FRAGFRAME(pAd->FragFrame);
2241                         DBGPRINT(RT_DEBUG_ERROR,
2242                                  ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2243                         goto done;      // give up this frame
2244                 }
2245                 //
2246                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2247                 // In this case, we will dropt it.
2248                 //
2249                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2250                         DBGPRINT(RT_DEBUG_ERROR,
2251                                  ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2252                                   pHeader->Sequence, pHeader->Frag));
2253                         goto done;      // give up this frame
2254                 }
2255
2256                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2257
2258                 // concatenate this fragment into the re-assembly buffer
2259                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2260                                DataSize);
2261                 pAd->FragFrame.RxSize += DataSize;
2262                 pAd->FragFrame.LastFrag = pHeader->Frag;        // Update fragment number
2263
2264                 // Last fragment
2265                 if (pHeader->FC.MoreFrag == FALSE) {
2266                         bReassDone = TRUE;
2267                 }
2268         }
2269
2270 done:
2271         // always release rx fragmented packet
2272         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2273
2274         // return defragmented packet if packet is reassembled completely
2275         // otherwise return NULL
2276         if (bReassDone) {
2277                 PNDIS_PACKET pNewFragPacket;
2278
2279                 // allocate a new packet buffer for fragment
2280                 pNewFragPacket =
2281                     RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2282                 if (pNewFragPacket) {
2283                         // update RxBlk
2284                         pRetPacket = pAd->FragFrame.pFragPacket;
2285                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2286                         pRxBlk->pHeader =
2287                             (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2288                         pRxBlk->pData = (UCHAR *) pRxBlk->pHeader + HeaderRoom;
2289                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2290                         pRxBlk->pRxPacket = pRetPacket;
2291                 } else {
2292                         RESET_FRAGFRAME(pAd->FragFrame);
2293                 }
2294         }
2295
2296         return pRetPacket;
2297 }
2298
2299 VOID Indicate_AMSDU_Packet(IN PRTMP_ADAPTER pAd,
2300                            IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2301 {
2302         UINT nMSDU;
2303
2304         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2305         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2306         nMSDU =
2307             deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2308                                        pRxBlk->DataSize);
2309 }
2310
2311 VOID Indicate_EAPOL_Packet(IN PRTMP_ADAPTER pAd,
2312                            IN RX_BLK * pRxBlk, IN UCHAR FromWhichBSSID)
2313 {
2314         MAC_TABLE_ENTRY *pEntry = NULL;
2315
2316         {
2317                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2318                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2319                 return;
2320         }
2321
2322         if (pEntry == NULL) {
2323                 DBGPRINT(RT_DEBUG_WARN,
2324                          ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2325                 // release packet
2326                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2327                                     NDIS_STATUS_FAILURE);
2328                 return;
2329         }
2330 }
2331
2332 #define BCN_TBTT_OFFSET         64      //defer 64 us
2333 VOID ReSyncBeaconTime(IN PRTMP_ADAPTER pAd)
2334 {
2335
2336         UINT32 Offset;
2337
2338         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2339
2340         pAd->TbttTickCount++;
2341
2342         //
2343         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2344         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2345         //
2346         if (Offset == (BCN_TBTT_OFFSET - 2)) {
2347                 BCN_TIME_CFG_STRUC csr;
2348                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2349                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1;      // ASIC register in units of 1/16 TU = 64us
2350                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2351         } else {
2352                 if (Offset == (BCN_TBTT_OFFSET - 1)) {
2353                         BCN_TIME_CFG_STRUC csr;
2354
2355                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2356                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4;  // ASIC register in units of 1/16 TU
2357                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2358                 }
2359         }
2360 }