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