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