Staging: Drop memory allocation cast
[safe/jmp/linux-2.6] / 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 u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31 u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
32
33 /* Add Cisco Aironet SNAP heade for CCX2 support */
34 u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35 u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36 u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37 u8 EAPOL[] = { 0x88, 0x8e };
38 u8 TPID[] = { 0x81, 0x00 };     /* VLAN related */
39
40 u8 IPX[] = { 0x81, 0x37 };
41 u8 APPLE_TALK[] = { 0x80, 0xf3 };
42
43 u8 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 u8 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 u8 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 u8 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 u8 default_cwmin[] =
75     { CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76 /*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */
77 u8 default_sta_aifsn[] = { 3, 7, 2, 2 };
78
79 u8 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 int MiniportMMRequest(struct rt_rtmp_adapter *pAd,
108                               u8 QueIdx, u8 *pData, u32 Length)
109 {
110         void *pPacket;
111         int Status = NDIS_STATUS_SUCCESS;
112         unsigned long FreeNum;
113         u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE];  /*RTMP_HW_HDR_LEN]; */
114 #ifdef RTMP_MAC_PCI
115         unsigned long IrqFlags = 0;
116         u8 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                                                    (u8 *)& 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 int MlmeHardTransmit(struct rt_rtmp_adapter *pAd,
246                              u8 QueIdx, void *pPacket)
247 {
248         struct rt_packet_info PacketInfo;
249         u8 *pSrcBufVA;
250         u32 SrcBufLen;
251         struct rt_header_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 = (struct rt_header_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 int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd,
274                                      u8 QueIdx, void *pPacket)
275 {
276         struct rt_packet_info PacketInfo;
277         u8 *pSrcBufVA;
278         u32 SrcBufLen;
279         struct rt_header_802_11 * pHeader_802_11;
280         BOOLEAN bAckRequired, bInsertTimestamp;
281         u8 MlmeRate;
282         struct rt_txwi * pFirstTxWI;
283         struct rt_mac_table_entry *pMacEntry = NULL;
284         u8 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 = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE);
303         pHeader_802_11 = (struct rt_header_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                               (u8)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                               (u8)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 u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket)
510 {
511         u8 TxFrameType = TX_UNKOWN_FRAME;
512         u8 Wcid;
513         struct rt_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(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
558 {
559         struct rt_packet_info PacketInfo;
560         void *pPacket;
561         struct rt_mac_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(struct rt_rtmp_adapter *pAd,
666                                char * pPacket, struct rt_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(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx,    /* BulkOutPipeId */
716                        u8 Max_Tx_Packets)
717 {
718         struct rt_queue_entry *pEntry = NULL;
719         void *pPacket;
720         int Status = NDIS_STATUS_SUCCESS;
721         u8 Count = 0;
722         struct rt_queue_header *pQueue;
723         unsigned long FreeNumber[NUM_OF_TX_RING];
724         u8 QueIdx, sQIdx, eQIdx;
725         unsigned long IrqFlags = 0;
726         BOOLEAN hasTxDesc = FALSE;
727         struct rt_tx_blk TxBlk;
728         struct rt_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                         pEntry = pQueue->Head;
777                         if (pEntry == NULL) {
778                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
779                                                IrqFlags);
780                                 break;
781                         }
782
783                         pTxBlk = &TxBlk;
784                         NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk));
785                         /*InitializeQueueHeader(&pTxBlk->TxPacketList);         // Didn't need it because we already memzero it. */
786                         pTxBlk->QueIdx = QueIdx;
787
788                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
789
790                         /* Early check to make sure we have enoguh Tx Resource. */
791                         hasTxDesc =
792                             RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
793                                                       FreeNumber[QueIdx],
794                                                       pPacket);
795                         if (!hasTxDesc) {
796                                 pAd->PrivateInfo.TxRingFullCnt++;
797
798                                 DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
799                                                IrqFlags);
800
801                                 break;
802                         }
803
804                         pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
805                         pEntry = RemoveHeadQueue(pQueue);
806                         pTxBlk->TotalFrameNum++;
807                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     /* The real fragment number maybe vary */
808                         pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
809                         pTxBlk->pPacket = pPacket;
810                         InsertTailQueue(&pTxBlk->TxPacketList,
811                                         PACKET_TO_QUEUE_ENTRY(pPacket));
812
813                         if (pTxBlk->TxFrameType == TX_RALINK_FRAME
814                             || pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
815                                 /* Enhance SW Aggregation Mechanism */
816                                 if (NEED_QUEUE_BACK_FOR_AGG
817                                     (pAd, QueIdx, FreeNumber[QueIdx],
818                                      pTxBlk->TxFrameType)) {
819                                         InsertHeadQueue(pQueue,
820                                                         PACKET_TO_QUEUE_ENTRY
821                                                         (pPacket));
822                                         DEQUEUE_UNLOCK(&pAd->irq_lock,
823                                                        bIntContext, IrqFlags);
824                                         break;
825                                 }
826
827                                 do {
828                                         pEntry = pQueue->Head;
829                                         if (pEntry == NULL)
830                                                 break;
831
832                                         /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
833                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
834                                         FreeNumber[QueIdx] =
835                                             GET_TXRING_FREENO(pAd, QueIdx);
836                                         hasTxDesc =
837                                             RTMP_HAS_ENOUGH_FREE_DESC(pAd,
838                                                                       pTxBlk,
839                                                                       FreeNumber
840                                                                       [QueIdx],
841                                                                       pPacket);
842                                         if ((hasTxDesc == FALSE)
843                                             ||
844                                             (CanDoAggregateTransmit
845                                              (pAd, pPacket, pTxBlk) == FALSE))
846                                                 break;
847
848                                         /*Remove the packet from the TxSwQueue and insert into pTxBlk */
849                                         pEntry = RemoveHeadQueue(pQueue);
850                                         ASSERT(pEntry);
851                                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
852                                         pTxBlk->TotalFrameNum++;
853                                         pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket);     /* The real fragment number maybe vary */
854                                         pTxBlk->TotalFrameLen +=
855                                             GET_OS_PKT_LEN(pPacket);
856                                         InsertTailQueue(&pTxBlk->TxPacketList,
857                                                         PACKET_TO_QUEUE_ENTRY
858                                                         (pPacket));
859                                 } while (1);
860
861                                 if (pTxBlk->TxPacketList.Number == 1)
862                                         pTxBlk->TxFrameType = TX_LEGACY_FRAME;
863                         }
864 #ifdef RTMP_MAC_USB
865                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
866 #endif /* RTMP_MAC_USB // */
867                         Count += pTxBlk->TxPacketList.Number;
868
869                         /* Do HardTransmit now. */
870                         Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
871
872 #ifdef RTMP_MAC_PCI
873                         DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
874                         /* static rate also need NICUpdateFifoStaCounters() function. */
875                         /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
876                         NICUpdateFifoStaCounters(pAd);
877 #endif /* RTMP_MAC_PCI // */
878
879                 }
880
881                 RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
882
883 #ifdef RTMP_MAC_USB
884                 if (!hasTxDesc)
885                         RTUSBKickBulkOut(pAd);
886 #endif /* RTMP_MAC_USB // */
887         }
888
889 }
890
891 /*
892         ========================================================================
893
894         Routine Description:
895                 Calculates the duration which is required to transmit out frames
896         with given size and specified rate.
897
898         Arguments:
899                 pAd     Pointer to our adapter
900                 Rate                    Transmit rate
901                 Size                    Frame size in units of byte
902
903         Return Value:
904                 Duration number in units of usec
905
906         IRQL = PASSIVE_LEVEL
907         IRQL = DISPATCH_LEVEL
908
909         Note:
910
911         ========================================================================
912 */
913 u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size)
914 {
915         unsigned long Duration = 0;
916
917         if (Rate < RATE_FIRST_OFDM_RATE)        /* CCK */
918         {
919                 if ((Rate > RATE_1)
920                     && OPSTATUS_TEST_FLAG(pAd,
921                                           fOP_STATUS_SHORT_PREAMBLE_INUSED))
922                         Duration = 96;  /* 72+24 preamble+plcp */
923                 else
924                         Duration = 192; /* 144+48 preamble+plcp */
925
926                 Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]);
927                 if ((Size << 4) % RateIdTo500Kbps[Rate])
928                         Duration++;
929         } else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */
930         {
931                 Duration = 20 + 6;      /* 16+4 preamble+plcp + Signal Extension */
932                 Duration +=
933                     4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
934                 if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
935                         Duration += 4;
936         } else                  /*mimo rate */
937         {
938                 Duration = 20 + 6;      /* 16+4 preamble+plcp + Signal Extension */
939         }
940
941         return (u16)Duration;
942 }
943
944 /*
945         ========================================================================
946
947         Routine Description:
948                 Calculates the duration which is required to transmit out frames
949         with given size and specified rate.
950
951         Arguments:
952                 pTxWI           Pointer to head of each MPDU to HW.
953                 Ack             Setting for Ack requirement bit
954                 Fragment        Setting for Fragment bit
955                 RetryMode       Setting for retry mode
956                 Ifs             Setting for IFS gap
957                 Rate            Setting for transmit rate
958                 Service         Setting for service
959                 Length          Frame length
960                 TxPreamble      Short or Long preamble when using CCK rates
961                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
962
963         Return Value:
964                 None
965
966         IRQL = PASSIVE_LEVEL
967         IRQL = DISPATCH_LEVEL
968
969     See also : BASmartHardTransmit()    !
970
971         ========================================================================
972 */
973 void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq,       /* HW new a sequence. */
974                    u8 BASize,
975                    u8 WCID,
976                    unsigned long Length,
977                    u8 PID,
978                    u8 TID,
979                    u8 TxRate,
980                    u8 Txopmode,
981                    IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
982 {
983         struct rt_mac_table_entry *pMac = NULL;
984         struct rt_txwi TxWI;
985         struct rt_txwi * pTxWI;
986
987         if (WCID < MAX_LEN_OF_MAC_TABLE)
988                 pMac = &pAd->MacTab.Content[WCID];
989
990         /* */
991         /* Always use Long preamble before verifiation short preamble functionality works well. */
992         /* Todo: remove the following line if short preamble functionality works */
993         /* */
994         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
995         NdisZeroMemory(&TxWI, TXWI_SIZE);
996         pTxWI = &TxWI;
997
998         pTxWI->FRAG = FRAG;
999
1000         pTxWI->CFACK = CFACK;
1001         pTxWI->TS = InsTimestamp;
1002         pTxWI->AMPDU = AMPDU;
1003         pTxWI->ACK = Ack;
1004         pTxWI->txop = Txopmode;
1005
1006         pTxWI->NSEQ = NSeq;
1007         /* John tune the performace with Intel Client in 20 MHz performance */
1008         BASize = pAd->CommonCfg.TxBASize;
1009         if (pAd->MACVersion == 0x28720200) {
1010                 if (BASize > 13)
1011                         BASize = 13;
1012         } else {
1013                 if (BASize > 7)
1014                         BASize = 7;
1015         }
1016         pTxWI->BAWinSize = BASize;
1017         pTxWI->ShortGI = pTransmit->field.ShortGI;
1018         pTxWI->STBC = pTransmit->field.STBC;
1019
1020         pTxWI->WirelessCliID = WCID;
1021         pTxWI->MPDUtotalByteCount = Length;
1022         pTxWI->PacketId = PID;
1023
1024         /* If CCK or OFDM, BW must be 20 */
1025         pTxWI->BW =
1026             (pTransmit->field.MODE <=
1027              MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1028
1029         pTxWI->MCS = pTransmit->field.MCS;
1030         pTxWI->PHYMODE = pTransmit->field.MODE;
1031         pTxWI->CFACK = CfAck;
1032
1033         if (pMac) {
1034                 if (pAd->CommonCfg.bMIMOPSEnable) {
1035                         if ((pMac->MmpsMode == MMPS_DYNAMIC)
1036                             && (pTransmit->field.MCS > 7)) {
1037                                 /* Dynamic MIMO Power Save Mode */
1038                                 pTxWI->MIMOps = 1;
1039                         } else if (pMac->MmpsMode == MMPS_STATIC) {
1040                                 /* Static MIMO Power Save Mode */
1041                                 if (pTransmit->field.MODE >= MODE_HTMIX
1042                                     && pTransmit->field.MCS > 7) {
1043                                         pTxWI->MCS = 7;
1044                                         pTxWI->MIMOps = 0;
1045                                 }
1046                         }
1047                 }
1048                 /*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
1049                 if (pMac->bIAmBadAtheros
1050                     && (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1051                         pTxWI->MpduDensity = 7;
1052                 } else {
1053                         pTxWI->MpduDensity = pMac->MpduDensity;
1054                 }
1055         }
1056
1057         pTxWI->PacketId = pTxWI->MCS;
1058         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi));
1059 }
1060
1061 void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd,
1062                         struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1063 {
1064         HTTRANSMIT_SETTING *pTransmit;
1065         struct rt_mac_table_entry *pMacEntry;
1066         u8 BASize;
1067
1068         ASSERT(pTxWI);
1069
1070         pTransmit = pTxBlk->pTransmit;
1071         pMacEntry = pTxBlk->pMacEntry;
1072
1073         /* */
1074         /* Always use Long preamble before verifiation short preamble functionality works well. */
1075         /* Todo: remove the following line if short preamble functionality works */
1076         /* */
1077         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1078         NdisZeroMemory(pTxWI, TXWI_SIZE);
1079
1080         pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1081         pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1082         pTxWI->txop = pTxBlk->FrameGap;
1083
1084         pTxWI->WirelessCliID = pTxBlk->Wcid;
1085
1086         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1087         pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1088
1089         /* If CCK or OFDM, BW must be 20 */
1090         pTxWI->BW =
1091             (pTransmit->field.MODE <=
1092              MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1093         pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1094
1095         /* John tune the performace with Intel Client in 20 MHz performance */
1096         BASize = pAd->CommonCfg.TxBASize;
1097         if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1098                 u8 RABAOriIdx = 0;      /*The RA's BA Originator table index. */
1099
1100                 RABAOriIdx =
1101                     pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1102                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1103         }
1104
1105         pTxWI->TxBF = pTransmit->field.TxBF;
1106         pTxWI->BAWinSize = BASize;
1107         pTxWI->ShortGI = pTransmit->field.ShortGI;
1108         pTxWI->STBC = pTransmit->field.STBC;
1109
1110         pTxWI->MCS = pTransmit->field.MCS;
1111         pTxWI->PHYMODE = pTransmit->field.MODE;
1112
1113         if (pMacEntry) {
1114                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1115                     && (pTransmit->field.MCS > 7)) {
1116                         /* Dynamic MIMO Power Save Mode */
1117                         pTxWI->MIMOps = 1;
1118                 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1119                         /* Static MIMO Power Save Mode */
1120                         if (pTransmit->field.MODE >= MODE_HTMIX
1121                             && pTransmit->field.MCS > 7) {
1122                                 pTxWI->MCS = 7;
1123                                 pTxWI->MIMOps = 0;
1124                         }
1125                 }
1126
1127                 if (pMacEntry->bIAmBadAtheros
1128                     && (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1129                         pTxWI->MpduDensity = 7;
1130                 } else {
1131                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1132                 }
1133         }
1134
1135         /* for rate adapation */
1136         pTxWI->PacketId = pTxWI->MCS;
1137 }
1138
1139 void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd,
1140                          struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1141 {
1142         PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1143         struct rt_mac_table_entry *pMacEntry;
1144
1145         /* */
1146         /* update TXWI */
1147         /* */
1148         pMacEntry = pTxBlk->pMacEntry;
1149         pTransmit = pTxBlk->pTransmit;
1150
1151         /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
1152         /*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */
1153         /*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */
1154         if (pMacEntry->bAutoTxRateSwitch) {
1155                 pTxWI->txop = IFS_HTTXOP;
1156
1157                 /* If CCK or OFDM, BW must be 20 */
1158                 pTxWI->BW =
1159                     (pTransmit->field.MODE <=
1160                      MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1161                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1162                 pTxWI->STBC = pTransmit->field.STBC;
1163
1164                 pTxWI->MCS = pTransmit->field.MCS;
1165                 pTxWI->PHYMODE = pTransmit->field.MODE;
1166
1167                 /* set PID for TxRateSwitching */
1168                 pTxWI->PacketId = pTransmit->field.MCS;
1169         }
1170
1171         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1172         pTxWI->MIMOps = 0;
1173
1174         if (pAd->CommonCfg.bMIMOPSEnable) {
1175                 /* MIMO Power Save Mode */
1176                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1177                     && (pTransmit->field.MCS > 7)) {
1178                         /* Dynamic MIMO Power Save Mode */
1179                         pTxWI->MIMOps = 1;
1180                 } else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1181                         /* Static MIMO Power Save Mode */
1182                         if ((pTransmit->field.MODE >= MODE_HTMIX)
1183                             && (pTransmit->field.MCS > 7)) {
1184                                 pTxWI->MCS = 7;
1185                                 pTxWI->MIMOps = 0;
1186                         }
1187                 }
1188         }
1189
1190         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1191
1192 }
1193
1194 /* should be called only when - */
1195 /* 1. MEADIA_CONNECTED */
1196 /* 2. AGGREGATION_IN_USED */
1197 /* 3. Fragmentation not in used */
1198 /* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */
1199 BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd,
1200                               u8 *pPrevAddr1, u8 *p8023hdr)
1201 {
1202
1203         /* can't aggregate EAPOL (802.1x) frame */
1204         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1205                 return FALSE;
1206
1207         /* can't aggregate multicast/broadcast frame */
1208         if (p8023hdr[0] & 0x01)
1209                 return FALSE;
1210
1211         if (INFRA_ON(pAd))      /* must be unicast to AP */
1212                 return TRUE;
1213         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr))  /* unicast to same STA */
1214                 return TRUE;
1215         else
1216                 return FALSE;
1217 }
1218
1219 /*
1220         ========================================================================
1221
1222         Routine Description:
1223            Check the MSDU Aggregation policy
1224         1.HT aggregation is A-MSDU
1225         2.legaacy rate aggregation is software aggregation by Ralink.
1226
1227         Arguments:
1228
1229         Return Value:
1230
1231         Note:
1232
1233         ========================================================================
1234 */
1235 BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd,
1236                       unsigned long TxRate, struct rt_mac_table_entry *pMacEntry)
1237 {
1238         unsigned long AFlags =
1239             (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1240
1241         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1242                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1243                         return TRUE;
1244                 }
1245 #ifdef AGGREGATION_SUPPORT
1246                 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 */
1247                         return TRUE;
1248                 }
1249 #endif /* AGGREGATION_SUPPORT // */
1250         }
1251
1252         return FALSE;
1253
1254 }
1255
1256 /*
1257         ========================================================================
1258
1259         Routine Description:
1260                 Check and fine the packet waiting in SW queue with highest priority
1261
1262         Arguments:
1263                 pAd Pointer to our adapter
1264
1265         Return Value:
1266                 pQueue          Pointer to Waiting Queue
1267
1268         IRQL = DISPATCH_LEVEL
1269
1270         Note:
1271
1272         ========================================================================
1273 */
1274 struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx)
1275 {
1276
1277         unsigned long Number;
1278         /* 2004-11-15 to be removed. test aggregation only */
1279 /*      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1280 /*               return NULL; */
1281
1282         Number = pAd->TxSwQueue[QID_AC_BK].Number
1283             + pAd->TxSwQueue[QID_AC_BE].Number
1284             + pAd->TxSwQueue[QID_AC_VI].Number
1285             + pAd->TxSwQueue[QID_AC_VO].Number;
1286
1287         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1288                 *pQueIdx = QID_AC_VO;
1289                 return (&pAd->TxSwQueue[QID_AC_VO]);
1290         } else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1291                 *pQueIdx = QID_AC_VI;
1292                 return (&pAd->TxSwQueue[QID_AC_VI]);
1293         } else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1294                 *pQueIdx = QID_AC_BE;
1295                 return (&pAd->TxSwQueue[QID_AC_BE]);
1296         } else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1297                 *pQueIdx = QID_AC_BK;
1298                 return (&pAd->TxSwQueue[QID_AC_BK]);
1299         }
1300         /* No packet pending in Tx Sw queue */
1301         *pQueIdx = QID_AC_BK;
1302
1303         return (NULL);
1304 }
1305
1306 /*
1307         ========================================================================
1308
1309         Routine Description:
1310                 Suspend MSDU transmission
1311
1312         Arguments:
1313                 pAd     Pointer to our adapter
1314
1315         Return Value:
1316                 None
1317
1318         Note:
1319
1320         ========================================================================
1321 */
1322 void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd)
1323 {
1324         DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1325
1326         /* */
1327         /* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1328         /* use Lowbound as R66 value on ScanNextChannel(...) */
1329         /* */
1330         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1331                                     &pAd->BbpTuning.R66CurrentValue);
1332
1333         /* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */
1334         /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */
1335         RTMPSetAGCInitValue(pAd, BW_20);
1336
1337         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1338         /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings */
1339 }
1340
1341 /*
1342         ========================================================================
1343
1344         Routine Description:
1345                 Resume MSDU transmission
1346
1347         Arguments:
1348                 pAd     Pointer to our adapter
1349
1350         Return Value:
1351                 None
1352
1353         IRQL = DISPATCH_LEVEL
1354
1355         Note:
1356
1357         ========================================================================
1358 */
1359 void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd)
1360 {
1361 /*    u8                     IrqState; */
1362
1363         DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1364
1365         /* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */
1366         /* R66 should not be 0 */
1367         if (pAd->BbpTuning.R66CurrentValue == 0) {
1368                 pAd->BbpTuning.R66CurrentValue = 0x38;
1369                 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1370         }
1371
1372         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1373                                      pAd->BbpTuning.R66CurrentValue);
1374
1375         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1376 /* sample, for IRQ LOCK to SEM LOCK */
1377 /*    IrqState = pAd->irq_disabled; */
1378 /*      if (IrqState) */
1379 /*              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1380 /*    else */
1381         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1382 }
1383
1384 u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
1385                                 void *pPacket,
1386                                 u8 *pData, unsigned long DataSize)
1387 {
1388         u16 PayloadSize;
1389         u16 SubFrameSize;
1390         struct rt_header_802_3 * pAMSDUsubheader;
1391         u32 nMSDU;
1392         u8 Header802_3[14];
1393
1394         u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP;
1395         void *pClonePacket;
1396
1397         nMSDU = 0;
1398
1399         while (DataSize > LENGTH_802_3) {
1400
1401                 nMSDU++;
1402
1403                 /*hex_dump("subheader", pData, 64); */
1404                 pAMSDUsubheader = (struct rt_header_802_3 *) pData;
1405                 /*pData += LENGTH_802_3; */
1406                 PayloadSize =
1407                     pAMSDUsubheader->Octet[1] +
1408                     (pAMSDUsubheader->Octet[0] << 8);
1409                 SubFrameSize = PayloadSize + LENGTH_802_3;
1410
1411                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1412                         break;
1413                 }
1414                 /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n",  nMSDU, PayloadSize)); */
1415
1416                 pPayload = pData + LENGTH_802_3;
1417                 pDA = pData;
1418                 pSA = pData + MAC_ADDR_LEN;
1419
1420                 /* convert to 802.3 header */
1421                 CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1422                                  pRemovedLLCSNAP);
1423
1424                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1425                         /* avoid local heap overflow, use dyanamic allocation */
1426                         struct rt_mlme_queue_elem *Elem =
1427                             kmalloc(sizeof(struct rt_mlme_queue_elem),
1428                                                         MEM_ALLOC_FLAG);
1429                         if (Elem != NULL) {
1430                                 memmove(Elem->Msg +
1431                                         (LENGTH_802_11 + LENGTH_802_1_H),
1432                                         pPayload, PayloadSize);
1433                                 Elem->MsgLen =
1434                                     LENGTH_802_11 + LENGTH_802_1_H +
1435                                     PayloadSize;
1436                                 /*WpaEAPOLKeyAction(pAd, Elem); */
1437                                 REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1438                                                           Elem->Msg,
1439                                                           Elem->MsgLen, 0, 0, 0,
1440                                                           0);
1441                                 kfree(Elem);
1442                         }
1443                 }
1444
1445                 {
1446                         if (pRemovedLLCSNAP) {
1447                                 pPayload -= LENGTH_802_3;
1448                                 PayloadSize += LENGTH_802_3;
1449                                 NdisMoveMemory(pPayload, &Header802_3[0],
1450                                                LENGTH_802_3);
1451                         }
1452                 }
1453
1454                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1455                 if (pClonePacket) {
1456                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1457                                                          RTMP_GET_PACKET_IF
1458                                                          (pPacket));
1459                 }
1460
1461                 /* A-MSDU has padding to multiple of 4 including subframe header. */
1462                 /* align SubFrameSize up to multiple of 4 */
1463                 SubFrameSize = (SubFrameSize + 3) & (~0x3);
1464
1465                 if (SubFrameSize > 1528 || SubFrameSize < 32) {
1466                         break;
1467                 }
1468
1469                 if (DataSize > SubFrameSize) {
1470                         pData += SubFrameSize;
1471                         DataSize -= SubFrameSize;
1472                 } else {
1473                         /* end of A-MSDU */
1474                         DataSize = 0;
1475                 }
1476         }
1477
1478         /* finally release original rx packet */
1479         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1480
1481         return nMSDU;
1482 }
1483
1484 u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
1485 {
1486         u8 *pData;
1487         u16 DataSize;
1488         u32 nMSDU = 0;
1489
1490         pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
1491         DataSize = (u16)GET_OS_PKT_LEN(pPacket);
1492
1493         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1494
1495         return nMSDU;
1496 }
1497
1498 /*
1499         ==========================================================================
1500         Description:
1501                 Look up the MAC address in the MAC table. Return NULL if not found.
1502         Return:
1503                 pEntry - pointer to the MAC entry; NULL is not found
1504         ==========================================================================
1505 */
1506 struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr)
1507 {
1508         unsigned long HashIdx;
1509         struct rt_mac_table_entry *pEntry = NULL;
1510
1511         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1512         pEntry = pAd->MacTab.Hash[HashIdx];
1513
1514         while (pEntry
1515                && (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1516                    || pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1517                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1518                         break;
1519                 } else
1520                         pEntry = pEntry->pNext;
1521         }
1522
1523         return pEntry;
1524 }
1525
1526 struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd,
1527                                      u8 *pAddr,
1528                                      u8 apidx, IN BOOLEAN CleanAll)
1529 {
1530         u8 HashIdx;
1531         int i, FirstWcid;
1532         struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry;
1533 /*      u16  offset; */
1534 /*      unsigned long   addr; */
1535
1536         /* if FULL, return */
1537         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1538                 return NULL;
1539
1540         FirstWcid = 1;
1541
1542         if (pAd->StaCfg.BssType == BSS_INFRA)
1543                 FirstWcid = 2;
1544
1545         /* allocate one MAC entry */
1546         NdisAcquireSpinLock(&pAd->MacTabLock);
1547         for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++)      /* skip entry#0 so that "entry index == AID" for fast lookup */
1548         {
1549                 /* pick up the first available vacancy */
1550                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1551                     (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1552                     (pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1553                     (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1554                     ) {
1555                         pEntry = &pAd->MacTab.Content[i];
1556                         if (CleanAll == TRUE) {
1557                                 pEntry->MaxSupportedRate = RATE_11;
1558                                 pEntry->CurrTxRate = RATE_11;
1559                                 NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1560                                 pEntry->PairwiseKey.KeyLen = 0;
1561                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1562                         }
1563                         {
1564                                 {
1565                                         pEntry->ValidAsCLI = TRUE;
1566                                         pEntry->ValidAsWDS = FALSE;
1567                                         pEntry->ValidAsApCli = FALSE;
1568                                         pEntry->ValidAsMesh = FALSE;
1569                                         pEntry->ValidAsDls = FALSE;
1570                                 }
1571                         }
1572
1573                         pEntry->bIAmBadAtheros = FALSE;
1574                         pEntry->pAd = pAd;
1575                         pEntry->CMTimerRunning = FALSE;
1576                         pEntry->EnqueueEapolStartTimerRunning =
1577                             EAPOL_START_DISABLE;
1578                         pEntry->RSNIE_Len = 0;
1579                         NdisZeroMemory(pEntry->R_Counter,
1580                                        sizeof(pEntry->R_Counter));
1581                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1582
1583                         if (pEntry->ValidAsMesh)
1584                                 pEntry->apidx =
1585                                     (apidx - MIN_NET_DEVICE_FOR_MESH);
1586                         else if (pEntry->ValidAsApCli)
1587                                 pEntry->apidx =
1588                                     (apidx - MIN_NET_DEVICE_FOR_APCLI);
1589                         else if (pEntry->ValidAsWDS)
1590                                 pEntry->apidx =
1591                                     (apidx - MIN_NET_DEVICE_FOR_WDS);
1592                         else
1593                                 pEntry->apidx = apidx;
1594
1595                         {
1596                                 {
1597                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1598                                         pEntry->WepStatus =
1599                                             pAd->StaCfg.WepStatus;
1600                                         pEntry->PrivacyFilter =
1601                                             Ndis802_11PrivFilterAcceptAll;
1602 #ifdef RTMP_MAC_PCI
1603                                         AsicRemovePairwiseKeyEntry(pAd,
1604                                                                    pEntry->
1605                                                                    apidx,
1606                                                                    (u8)i);
1607 #endif /* RTMP_MAC_PCI // */
1608                                 }
1609                         }
1610
1611                         pEntry->GTKState = REKEY_NEGOTIATING;
1612                         pEntry->PairwiseKey.KeyLen = 0;
1613                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1614                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1615
1616                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1617                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1618                         pEntry->Sst = SST_NOT_AUTH;
1619                         pEntry->AuthState = AS_NOT_AUTH;
1620                         pEntry->Aid = (u16)i;   /*0; */
1621                         pEntry->CapabilityInfo = 0;
1622                         pEntry->PsMode = PWR_ACTIVE;
1623                         pEntry->PsQIdleCount = 0;
1624                         pEntry->NoDataIdleCount = 0;
1625                         pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1626                         pEntry->ContinueTxFailCnt = 0;
1627                         InitializeQueueHeader(&pEntry->PsQueue);
1628
1629                         pAd->MacTab.Size++;
1630                         /* Add this entry into ASIC RX WCID search table */
1631                         RTMP_STA_ENTRY_ADD(pAd, pEntry);
1632
1633                         DBGPRINT(RT_DEBUG_TRACE,
1634                                  ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1635                                   i, pAd->MacTab.Size));
1636                         break;
1637                 }
1638         }
1639
1640         /* add this MAC entry into HASH table */
1641         if (pEntry) {
1642                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1643                 if (pAd->MacTab.Hash[HashIdx] == NULL) {
1644                         pAd->MacTab.Hash[HashIdx] = pEntry;
1645                 } else {
1646                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1647                         while (pCurrEntry->pNext != NULL)
1648                                 pCurrEntry = pCurrEntry->pNext;
1649                         pCurrEntry->pNext = pEntry;
1650                 }
1651         }
1652
1653         NdisReleaseSpinLock(&pAd->MacTabLock);
1654         return pEntry;
1655 }
1656
1657 /*
1658         ==========================================================================
1659         Description:
1660                 Delete a specified client from MAC table
1661         ==========================================================================
1662  */
1663 BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd,
1664                             u16 wcid, u8 *pAddr)
1665 {
1666         u16 HashIdx;
1667         struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry;
1668         BOOLEAN Cancelled;
1669         /*u16        offset; // unused variable */
1670         /*u8 j;                      // unused variable */
1671
1672         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1673                 return FALSE;
1674
1675         NdisAcquireSpinLock(&pAd->MacTabLock);
1676
1677         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1678         /*pEntry = pAd->MacTab.Hash[HashIdx]; */
1679         pEntry = &pAd->MacTab.Content[wcid];
1680
1681         if (pEntry
1682             && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1683                 || pEntry->ValidAsMesh)) {
1684                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1685
1686                         /* Delete this entry from ASIC on-chip WCID Table */
1687                         RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1688
1689                         /* free resources of BA */
1690                         BASessionTearDownALL(pAd, pEntry->Aid);
1691
1692                         pPrevEntry = NULL;
1693                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
1694                         ASSERT(pProbeEntry);
1695
1696                         /* update Hash list */
1697                         do {
1698                                 if (pProbeEntry == pEntry) {
1699                                         if (pPrevEntry == NULL) {
1700                                                 pAd->MacTab.Hash[HashIdx] =
1701                                                     pEntry->pNext;
1702                                         } else {
1703                                                 pPrevEntry->pNext =
1704                                                     pEntry->pNext;
1705                                         }
1706                                         break;
1707                                 }
1708
1709                                 pPrevEntry = pProbeEntry;
1710                                 pProbeEntry = pProbeEntry->pNext;
1711                         } while (pProbeEntry);
1712
1713                         /* not found ! */
1714                         ASSERT(pProbeEntry != NULL);
1715
1716                         RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1717
1718                         if (pEntry->EnqueueEapolStartTimerRunning !=
1719                             EAPOL_START_DISABLE) {
1720                                 RTMPCancelTimer(&pEntry->
1721                                                 EnqueueStartForPSKTimer,
1722                                                 &Cancelled);
1723                                 pEntry->EnqueueEapolStartTimerRunning =
1724                                     EAPOL_START_DISABLE;
1725                         }
1726
1727                         NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1728                         pAd->MacTab.Size--;
1729                         DBGPRINT(RT_DEBUG_TRACE,
1730                                  ("MacTableDeleteEntry1 - Total= %d\n",
1731                                   pAd->MacTab.Size));
1732                 } else {
1733                         DBGPRINT(RT_DEBUG_OFF,
1734                                  ("\n%s: Impossible Wcid = %d !\n",
1735                                   __func__, wcid));
1736                 }
1737         }
1738
1739         NdisReleaseSpinLock(&pAd->MacTabLock);
1740
1741         /*Reset operating mode when no Sta. */
1742         if (pAd->MacTab.Size == 0) {
1743                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1744                 RTMP_UPDATE_PROTECT(pAd);       /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */
1745         }
1746
1747         return TRUE;
1748 }
1749
1750 /*
1751         ==========================================================================
1752         Description:
1753                 This routine reset the entire MAC table. All packets pending in
1754                 the power-saving queues are freed here.
1755         ==========================================================================
1756  */
1757 void MacTableReset(struct rt_rtmp_adapter *pAd)
1758 {
1759         int i;
1760
1761         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1762         /*NdisAcquireSpinLock(&pAd->MacTabLock); */
1763
1764         for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1765 #ifdef RTMP_MAC_PCI
1766                 RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1767 #endif /* RTMP_MAC_PCI // */
1768                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1769
1770                         /* free resources of BA */
1771                         BASessionTearDownALL(pAd, i);
1772
1773                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1774
1775 #ifdef RTMP_MAC_USB
1776                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1777                         RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1778 #endif /* RTMP_MAC_USB // */
1779
1780                         /*AsicDelWcidTab(pAd, i); */
1781                 }
1782         }
1783
1784         return;
1785 }
1786
1787 /*
1788         ==========================================================================
1789         Description:
1790
1791         IRQL = DISPATCH_LEVEL
1792
1793         ==========================================================================
1794 */
1795 void AssocParmFill(struct rt_rtmp_adapter *pAd,
1796                    struct rt_mlme_assoc_req *AssocReq,
1797                    u8 *pAddr,
1798                    u16 CapabilityInfo,
1799                    unsigned long Timeout, u16 ListenIntv)
1800 {
1801         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1802         /* Add mask to support 802.11b mode only */
1803         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;  /* not cf-pollable, not cf-poll-request */
1804         AssocReq->Timeout = Timeout;
1805         AssocReq->ListenIntv = ListenIntv;
1806 }
1807
1808 /*
1809         ==========================================================================
1810         Description:
1811
1812         IRQL = DISPATCH_LEVEL
1813
1814         ==========================================================================
1815 */
1816 void DisassocParmFill(struct rt_rtmp_adapter *pAd,
1817                       struct rt_mlme_disassoc_req *DisassocReq,
1818                       u8 *pAddr, u16 Reason)
1819 {
1820         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1821         DisassocReq->Reason = Reason;
1822 }
1823
1824 /*
1825         ========================================================================
1826
1827         Routine Description:
1828                 Check the out going frame, if this is an DHCP or ARP datagram
1829         will be duplicate another frame at low data rate transmit.
1830
1831         Arguments:
1832                 pAd             Pointer to our adapter
1833                 pPacket         Pointer to outgoing Ndis frame
1834
1835         Return Value:
1836                 TRUE            To be duplicate at Low data rate transmit. (1mb)
1837                 FALSE           Do nothing.
1838
1839         IRQL = DISPATCH_LEVEL
1840
1841         Note:
1842
1843                 MAC header + IP Header + UDP Header
1844                   14 Bytes        20 Bytes
1845
1846                 UDP Header
1847                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1848                                                 Source Port
1849                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1850                                         Destination Port
1851
1852                 port 0x43 means Bootstrap Protocol, server.
1853                 Port 0x44 means Bootstrap Protocol, client.
1854
1855         ========================================================================
1856 */
1857
1858 BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket)
1859 {
1860         struct rt_packet_info PacketInfo;
1861         unsigned long NumberOfBytesRead = 0;
1862         unsigned long CurrentOffset = 0;
1863         void *pVirtualAddress = NULL;
1864         u32 NdisBufferLength;
1865         u8 *pSrc;
1866         u16 Protocol;
1867         u8 ByteOffset36 = 0;
1868         u8 ByteOffset38 = 0;
1869         BOOLEAN ReadFirstParm = TRUE;
1870
1871         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress,
1872                              &NdisBufferLength);
1873
1874         NumberOfBytesRead += NdisBufferLength;
1875         pSrc = (u8 *)pVirtualAddress;
1876         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1877
1878         /* */
1879         /* Check DHCP & BOOTP protocol */
1880         /* */
1881         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1882                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1883                         CurrentOffset =
1884                             35 - (NumberOfBytesRead - NdisBufferLength);
1885                         ByteOffset36 = *(pSrc + CurrentOffset);
1886                         ReadFirstParm = FALSE;
1887                 }
1888
1889                 if (NumberOfBytesRead >= 37) {
1890                         CurrentOffset =
1891                             37 - (NumberOfBytesRead - NdisBufferLength);
1892                         ByteOffset38 = *(pSrc + CurrentOffset);
1893                         /*End of Read */
1894                         break;
1895                 }
1896                 return FALSE;
1897         }
1898
1899         /* Check for DHCP & BOOTP protocol */
1900         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1901                 /* */
1902                 /* 2054 (hex 0806) for ARP datagrams */
1903                 /* if this packet is not ARP datagrams, then do nothing */
1904                 /* ARP datagrams will also be duplicate at 1mb broadcast frames */
1905                 /* */
1906                 if (Protocol != 0x0806)
1907                         return FALSE;
1908         }
1909
1910         return TRUE;
1911 }
1912
1913 BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket)
1914 {
1915         u16 TypeLen;
1916         u8 Byte0, Byte1;
1917         u8 *pSrcBuf;
1918         u32 pktLen;
1919         u16 srcPort, dstPort;
1920         BOOLEAN status = TRUE;
1921
1922         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1923         pktLen = GET_OS_PKT_LEN(pPacket);
1924
1925         ASSERT(pSrcBuf);
1926
1927         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1928
1929         /* get Ethernet protocol field */
1930         TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1931
1932         pSrcBuf += LENGTH_802_3;        /* Skip the Ethernet Header. */
1933
1934         if (TypeLen <= 1500) {  /* 802.3, 802.3 LLC */
1935                 /*
1936                    DestMAC(6) + SrcMAC(6) + Lenght(2) +
1937                    DSAP(1) + SSAP(1) + Control(1) +
1938                    if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1939                    => + SNAP (5, OriginationID(3) + etherType(2))
1940                  */
1941                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1942                     && pSrcBuf[2] == 0x03) {
1943                         Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6,
1944                                                   &Byte0, &Byte1);
1945                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1946                         TypeLen = (u16)((Byte0 << 8) + Byte1);
1947                         pSrcBuf += 8;   /* Skip this LLC/SNAP header */
1948                 } else {
1949                         /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */
1950                 }
1951         }
1952         /* If it's a VLAN packet, get the real Type/Length field. */
1953         if (TypeLen == 0x8100) {
1954                 /* 0x8100 means VLAN packets */
1955
1956                 /* Dest. MAC Address (6-bytes) +
1957                    Source MAC Address (6-bytes) +
1958                    Length/Type = 802.1Q Tag Type (2-byte) +
1959                    Tag Control Information (2-bytes) +
1960                    Length / Type (2-bytes) +
1961                    data payload (0-n bytes) +
1962                    Pad (0-p bytes) +
1963                    Frame Check Sequence (4-bytes) */
1964
1965                 RTMP_SET_PACKET_VLAN(pPacket, 1);
1966                 Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0,
1967                                           &Byte1);
1968                 TypeLen = (u16)((Byte0 << 8) + Byte1);
1969
1970                 pSrcBuf += 4;   /* Skip the VLAN Header. */
1971         }
1972
1973         switch (TypeLen) {
1974         case 0x0800:
1975                 {
1976                         ASSERT((pktLen > 34));
1977                         if (*(pSrcBuf + 9) == 0x11) {   /* udp packet */
1978                                 ASSERT((pktLen > 34));  /* 14 for ethernet header, 20 for IP header */
1979
1980                                 pSrcBuf += 20;  /* Skip the IP header */
1981                                 srcPort =
1982                                     OS_NTOHS(get_unaligned
1983                                              ((u16 *)(pSrcBuf)));
1984                                 dstPort =
1985                                     OS_NTOHS(get_unaligned
1986                                              ((u16 *)(pSrcBuf + 2)));
1987
1988                                 if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) {     /*It's a BOOTP/DHCP packet */
1989                                         RTMP_SET_PACKET_DHCP(pPacket, 1);
1990                                 }
1991                         }
1992                 }
1993                 break;
1994         case 0x0806:
1995                 {
1996                         /*ARP Packet. */
1997                         RTMP_SET_PACKET_DHCP(pPacket, 1);
1998                 }
1999                 break;
2000         case 0x888e:
2001                 {
2002                         /* EAPOL Packet. */
2003                         RTMP_SET_PACKET_EAPOL(pPacket, 1);
2004                 }
2005                 break;
2006         default:
2007                 status = FALSE;
2008                 break;
2009         }
2010
2011         return status;
2012
2013 }
2014
2015 void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd,
2016                         struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI)
2017 {
2018         char rssi0 = pRxWI->RSSI0;
2019         char rssi1 = pRxWI->RSSI1;
2020         char rssi2 = pRxWI->RSSI2;
2021
2022         if (rssi0 != 0) {
2023                 pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0);
2024                 pRssi->AvgRssi0X8 =
2025                     (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2026                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2027         }
2028
2029         if (rssi1 != 0) {
2030                 pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1);
2031                 pRssi->AvgRssi1X8 =
2032                     (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2033                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2034         }
2035
2036         if (rssi2 != 0) {
2037                 pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2);
2038                 pRssi->AvgRssi2X8 =
2039                     (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2040                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2041         }
2042 }
2043
2044 /* Normal legacy Rx packet indication */
2045 void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd,
2046                             struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2047 {
2048         void *pRxPacket = pRxBlk->pRxPacket;
2049         u8 Header802_3[LENGTH_802_3];
2050
2051         /* 1. get 802.3 Header */
2052         /* 2. remove LLC */
2053         /*              a. pointer pRxBlk->pData to payload */
2054         /*      b. modify pRxBlk->DataSize */
2055         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2056
2057         if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2058
2059                 /* release packet */
2060                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2061                 return;
2062         }
2063
2064         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2065
2066 #ifdef RTMP_MAC_USB
2067         if (pAd->CommonCfg.bDisableReordering == 0) {
2068                 struct rt_ba_rec_entry *pBAEntry;
2069                 unsigned long Now32;
2070                 u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
2071                 u8 TID = pRxBlk->pRxWI->TID;
2072                 u16 Idx;
2073
2074 #define REORDERING_PACKET_TIMEOUT               ((100 * OS_HZ)/1000)    /* system ticks -- 100 ms */
2075
2076                 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2077                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2078                         if (Idx != 0) {
2079                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2080                                 /* update last rx time */
2081                                 NdisGetSystemUpTime(&Now32);
2082                                 if ((pBAEntry->list.qlen > 0) &&
2083                                     RTMP_TIME_AFTER((unsigned long)Now32,
2084                                                     (unsigned long)(pBAEntry->
2085                                                                     LastIndSeqAtTimer
2086                                                                     +
2087                                                                     (REORDERING_PACKET_TIMEOUT)))
2088                                     ) {
2089                                         DBGPRINT(RT_DEBUG_OFF,
2090                                                  ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2091                                                   pRxBlk->Flags,
2092                                                   pRxBlk->pRxWI->TID,
2093                                                   pRxBlk->RxD.AMPDU));
2094                                         hex_dump("Dump the legacy Packet:",
2095                                                  GET_OS_PKT_DATAPTR(pRxBlk->
2096                                                                     pRxPacket),
2097                                                  64);
2098                                         ba_flush_reordering_timeout_mpdus(pAd,
2099                                                                           pBAEntry,
2100                                                                           Now32);
2101                                 }
2102                         }
2103                 }
2104         }
2105 #endif /* RTMP_MAC_USB // */
2106
2107         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2108
2109         /* */
2110         /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2111         /* */
2112         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2113 }
2114
2115 /* Normal, AMPDU or AMSDU */
2116 void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2117                                  struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2118 {
2119         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2120             && (pAd->CommonCfg.bDisableReordering == 0)) {
2121                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2122         } else {
2123                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2124                         /* handle A-MSDU */
2125                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2126                 } else {
2127                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2128                 }
2129         }
2130 }
2131
2132 void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2133                               struct rt_mac_table_entry *pEntry,
2134                               struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2135 {
2136         u8 Header802_3[LENGTH_802_3];
2137         u16 Msdu2Size;
2138         u16 Payload1Size, Payload2Size;
2139         u8 *pData2;
2140         void *pPacket2 = NULL;
2141
2142         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2143
2144         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2145                 /* skip two byte MSDU2 len */
2146                 pRxBlk->pData += 2;
2147                 pRxBlk->DataSize -= 2;
2148         } else {
2149                 /* release packet */
2150                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2151                                     NDIS_STATUS_FAILURE);
2152                 return;
2153         }
2154
2155         /* get 802.3 Header and  remove LLC */
2156         RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2157
2158         ASSERT(pRxBlk->pRxPacket);
2159
2160         /* Ralink Aggregation frame */
2161         pAd->RalinkCounters.OneSecRxAggregationCount++;
2162         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2163         Payload2Size = Msdu2Size - LENGTH_802_3;
2164
2165         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2166
2167         pPacket2 =
2168             duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2169                           Payload2Size, FromWhichBSSID);
2170
2171         if (!pPacket2) {
2172                 /* release packet */
2173                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2174                                     NDIS_STATUS_FAILURE);
2175                 return;
2176         }
2177         /* update payload size of 1st packet */
2178         pRxBlk->DataSize = Payload1Size;
2179         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2180
2181         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2182                                          FromWhichBSSID);
2183
2184         if (pPacket2) {
2185                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2186         }
2187 }
2188
2189 #define RESET_FRAGFRAME(_fragFrame) \
2190         {                                                               \
2191                 _fragFrame.RxSize = 0;          \
2192                 _fragFrame.Sequence = 0;        \
2193                 _fragFrame.LastFrag = 0;        \
2194                 _fragFrame.Flags = 0;           \
2195         }
2196
2197 void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
2198 {
2199         struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
2200         void *pRxPacket = pRxBlk->pRxPacket;
2201         u8 *pData = pRxBlk->pData;
2202         u16 DataSize = pRxBlk->DataSize;
2203         void *pRetPacket = NULL;
2204         u8 *pFragBuffer = NULL;
2205         BOOLEAN bReassDone = FALSE;
2206         u8 HeaderRoom = 0;
2207
2208         ASSERT(pHeader);
2209
2210         HeaderRoom = pData - (u8 *) pHeader;
2211
2212         /* Re-assemble the fragmented packets */
2213         if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */
2214         {
2215                 /* the first pkt of fragment, record it. */
2216                 if (pHeader->FC.MoreFrag) {
2217                         ASSERT(pAd->FragFrame.pFragPacket);
2218                         pFragBuffer =
2219                             GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2220                         pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2221                         NdisMoveMemory(pFragBuffer, pHeader,
2222                                        pAd->FragFrame.RxSize);
2223                         pAd->FragFrame.Sequence = pHeader->Sequence;
2224                         pAd->FragFrame.LastFrag = pHeader->Frag;        /* Should be 0 */
2225                         ASSERT(pAd->FragFrame.LastFrag == 0);
2226                         goto done;      /* end of processing this frame */
2227                 }
2228         } else                  /*Middle & End of fragment */
2229         {
2230                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2231                     (pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2232                         /* Fragment is not the same sequence or out of fragment number order */
2233                         /* Reset Fragment control blk */
2234                         RESET_FRAGFRAME(pAd->FragFrame);
2235                         DBGPRINT(RT_DEBUG_ERROR,
2236                                  ("Fragment is not the same sequence or out of fragment number order.\n"));
2237                         goto done;      /* give up this frame */
2238                 } else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2239                         /* Fragment frame is too large, it exeeds the maximum frame size. */
2240                         /* Reset Fragment control blk */
2241                         RESET_FRAGFRAME(pAd->FragFrame);
2242                         DBGPRINT(RT_DEBUG_ERROR,
2243                                  ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2244                         goto done;      /* give up this frame */
2245                 }
2246                 /* */
2247                 /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */
2248                 /* In this case, we will dropt it. */
2249                 /* */
2250                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2251                         DBGPRINT(RT_DEBUG_ERROR,
2252                                  ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2253                                   pHeader->Sequence, pHeader->Frag));
2254                         goto done;      /* give up this frame */
2255                 }
2256
2257                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2258
2259                 /* concatenate this fragment into the re-assembly buffer */
2260                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2261                                DataSize);
2262                 pAd->FragFrame.RxSize += DataSize;
2263                 pAd->FragFrame.LastFrag = pHeader->Frag;        /* Update fragment number */
2264
2265                 /* Last fragment */
2266                 if (pHeader->FC.MoreFrag == FALSE) {
2267                         bReassDone = TRUE;
2268                 }
2269         }
2270
2271 done:
2272         /* always release rx fragmented packet */
2273         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2274
2275         /* return defragmented packet if packet is reassembled completely */
2276         /* otherwise return NULL */
2277         if (bReassDone) {
2278                 void *pNewFragPacket;
2279
2280                 /* allocate a new packet buffer for fragment */
2281                 pNewFragPacket =
2282                     RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2283                 if (pNewFragPacket) {
2284                         /* update RxBlk */
2285                         pRetPacket = pAd->FragFrame.pFragPacket;
2286                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2287                         pRxBlk->pHeader =
2288                             (struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket);
2289                         pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom;
2290                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2291                         pRxBlk->pRxPacket = pRetPacket;
2292                 } else {
2293                         RESET_FRAGFRAME(pAd->FragFrame);
2294                 }
2295         }
2296
2297         return pRetPacket;
2298 }
2299
2300 void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd,
2301                            struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2302 {
2303         u32 nMSDU;
2304
2305         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2306         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2307         nMSDU =
2308             deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2309                                        pRxBlk->DataSize);
2310 }
2311
2312 void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd,
2313                            struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2314 {
2315         struct rt_mac_table_entry *pEntry = NULL;
2316
2317         {
2318                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2319                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2320                 return;
2321         }
2322
2323         if (pEntry == NULL) {
2324                 DBGPRINT(RT_DEBUG_WARN,
2325                          ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2326                 /* release packet */
2327                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2328                                     NDIS_STATUS_FAILURE);
2329                 return;
2330         }
2331 }
2332
2333 #define BCN_TBTT_OFFSET         64      /*defer 64 us */
2334 void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd)
2335 {
2336
2337         u32 Offset;
2338
2339         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2340
2341         pAd->TbttTickCount++;
2342
2343         /* */
2344         /* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2345         /* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2346         /* */
2347         if (Offset == (BCN_TBTT_OFFSET - 2)) {
2348                 BCN_TIME_CFG_STRUC csr;
2349                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2350                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1;      /* ASIC register in units of 1/16 TU = 64us */
2351                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2352         } else {
2353                 if (Offset == (BCN_TBTT_OFFSET - 1)) {
2354                         BCN_TIME_CFG_STRUC csr;
2355
2356                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2357                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4;  /* ASIC register in units of 1/16 TU */
2358                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2359                 }
2360         }
2361 }