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