Staging: rt2870: remove dead QOS_DLS_SUPPORT 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 #ifdef DOT11N_DRAFT3
1092         if (pTxWI->BW)
1093                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1094 #endif // DOT11N_DRAFT3 //
1095
1096         pTxWI->MCS = pTransmit->field.MCS;
1097         pTxWI->PHYMODE = pTransmit->field.MODE;
1098         pTxWI->CFACK = CfAck;
1099
1100 #ifdef DOT11_N_SUPPORT
1101         if (pMac)
1102         {
1103                 if (pAd->CommonCfg.bMIMOPSEnable)
1104                 {
1105                         if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1106                         {
1107                                 // Dynamic MIMO Power Save Mode
1108                                 pTxWI->MIMOps = 1;
1109                         }
1110                         else if (pMac->MmpsMode == MMPS_STATIC)
1111                         {
1112                                 // Static MIMO Power Save Mode
1113                                 if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1114                                 {
1115                                         pTxWI->MCS = 7;
1116                                         pTxWI->MIMOps = 0;
1117                                 }
1118                         }
1119                 }
1120                 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1121                 if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
1122                 {
1123                         pTxWI->MpduDensity = 7;
1124                 }
1125                 else
1126                 {
1127                         pTxWI->MpduDensity = pMac->MpduDensity;
1128                 }
1129         }
1130 #endif // DOT11_N_SUPPORT //
1131
1132         pTxWI->PacketId = pTxWI->MCS;
1133         NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
1134 }
1135
1136
1137 VOID RTMPWriteTxWI_Data(
1138         IN      PRTMP_ADAPTER           pAd,
1139         IN      OUT PTXWI_STRUC         pTxWI,
1140         IN      TX_BLK                          *pTxBlk)
1141 {
1142         HTTRANSMIT_SETTING      *pTransmit;
1143         PMAC_TABLE_ENTRY        pMacEntry;
1144 #ifdef DOT11_N_SUPPORT
1145         UCHAR                           BASize;
1146 #endif // DOT11_N_SUPPORT //
1147
1148
1149         ASSERT(pTxWI);
1150
1151         pTransmit = pTxBlk->pTransmit;
1152         pMacEntry = pTxBlk->pMacEntry;
1153
1154
1155         //
1156         // Always use Long preamble before verifiation short preamble functionality works well.
1157         // Todo: remove the following line if short preamble functionality works
1158         //
1159         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1160         NdisZeroMemory(pTxWI, TXWI_SIZE);
1161
1162         pTxWI->FRAG             = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1163         pTxWI->ACK              = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1164         pTxWI->txop             = pTxBlk->FrameGap;
1165
1166                 pTxWI->WirelessCliID            = pTxBlk->Wcid;
1167
1168         pTxWI->MPDUtotalByteCount       = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1169         pTxWI->CFACK                            = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1170
1171         // If CCK or OFDM, BW must be 20
1172         pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1173 #ifdef DOT11_N_SUPPORT
1174 #ifdef DOT11N_DRAFT3
1175         if (pTxWI->BW)
1176                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1177 #endif // DOT11N_DRAFT3 //
1178         pTxWI->AMPDU    = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1179
1180         // John tune the performace with Intel Client in 20 MHz performance
1181         BASize = pAd->CommonCfg.TxBASize;
1182         if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
1183         {
1184                 UCHAR           RABAOriIdx = 0; //The RA's BA Originator table index.
1185
1186                 RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1187                 BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1188         }
1189
1190 #if 0 // 3*3
1191         if (BASize > 7)
1192                 BASize = 7;
1193 #endif
1194
1195         pTxWI->TxBF = pTransmit->field.TxBF;
1196         pTxWI->BAWinSize = BASize;
1197         pTxWI->ShortGI = pTransmit->field.ShortGI;
1198         pTxWI->STBC = pTransmit->field.STBC;
1199 #endif // DOT11_N_SUPPORT //
1200
1201         pTxWI->MCS = pTransmit->field.MCS;
1202         pTxWI->PHYMODE = pTransmit->field.MODE;
1203
1204 #ifdef DOT11_N_SUPPORT
1205         if (pMacEntry)
1206         {
1207                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1208                 {
1209                         // Dynamic MIMO Power Save Mode
1210                         pTxWI->MIMOps = 1;
1211                 }
1212                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1213                 {
1214                         // Static MIMO Power Save Mode
1215                         if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
1216                         {
1217                                 pTxWI->MCS = 7;
1218                                 pTxWI->MIMOps = 0;
1219                         }
1220                 }
1221
1222                 if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
1223                 {
1224                         pTxWI->MpduDensity = 7;
1225                 }
1226                 else
1227                 {
1228                         pTxWI->MpduDensity = pMacEntry->MpduDensity;
1229                 }
1230         }
1231 #endif // DOT11_N_SUPPORT //
1232
1233 #ifdef DBG_DIAGNOSE
1234                 if (pTxBlk->QueIdx== 0)
1235                 {
1236                         pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1237                         pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1238                 }
1239 #endif // DBG_DIAGNOSE //
1240
1241         // for rate adapation
1242         pTxWI->PacketId = pTxWI->MCS;
1243 }
1244
1245
1246 VOID RTMPWriteTxWI_Cache(
1247         IN      PRTMP_ADAPTER           pAd,
1248         IN      OUT PTXWI_STRUC         pTxWI,
1249         IN      TX_BLK                          *pTxBlk)
1250 {
1251         PHTTRANSMIT_SETTING     /*pTxHTPhyMode,*/ pTransmit;
1252         PMAC_TABLE_ENTRY        pMacEntry;
1253
1254         //
1255         // update TXWI
1256         //
1257         pMacEntry = pTxBlk->pMacEntry;
1258         pTransmit = pTxBlk->pTransmit;
1259
1260         if (pMacEntry->bAutoTxRateSwitch)
1261         {
1262                 pTxWI->txop = IFS_HTTXOP;
1263
1264                 // If CCK or OFDM, BW must be 20
1265                 pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1266                 pTxWI->ShortGI = pTransmit->field.ShortGI;
1267                 pTxWI->STBC = pTransmit->field.STBC;
1268
1269                 pTxWI->MCS = pTransmit->field.MCS;
1270                 pTxWI->PHYMODE = pTransmit->field.MODE;
1271
1272                 // set PID for TxRateSwitching
1273                 pTxWI->PacketId = pTransmit->field.MCS;
1274         }
1275
1276 #ifdef DOT11_N_SUPPORT
1277         pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
1278         pTxWI->MIMOps = 0;
1279
1280 #ifdef DOT11N_DRAFT3
1281         if (pTxWI->BW)
1282                 pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
1283 #endif // DOT11N_DRAFT3 //
1284
1285         if (pAd->CommonCfg.bMIMOPSEnable)
1286         {
1287                 // MIMO Power Save Mode
1288                 if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
1289                 {
1290                         // Dynamic MIMO Power Save Mode
1291                         pTxWI->MIMOps = 1;
1292                 }
1293                 else if (pMacEntry->MmpsMode == MMPS_STATIC)
1294                 {
1295                         // Static MIMO Power Save Mode
1296                         if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
1297                         {
1298                                 pTxWI->MCS = 7;
1299                                 pTxWI->MIMOps = 0;
1300                         }
1301                 }
1302         }
1303 #endif // DOT11_N_SUPPORT //
1304
1305 #ifdef DBG_DIAGNOSE
1306         if (pTxBlk->QueIdx== 0)
1307         {
1308                 pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
1309                 pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
1310         }
1311 #endif // DBG_DIAGNOSE //
1312
1313         pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1314
1315 }
1316
1317
1318 /*
1319         ========================================================================
1320
1321         Routine Description:
1322                 Calculates the duration which is required to transmit out frames
1323         with given size and specified rate.
1324
1325         Arguments:
1326                 pTxD            Pointer to transmit descriptor
1327                 Ack             Setting for Ack requirement bit
1328                 Fragment        Setting for Fragment bit
1329                 RetryMode       Setting for retry mode
1330                 Ifs             Setting for IFS gap
1331                 Rate            Setting for transmit rate
1332                 Service         Setting for service
1333                 Length          Frame length
1334                 TxPreamble      Short or Long preamble when using CCK rates
1335                 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1336
1337         Return Value:
1338                 None
1339
1340         IRQL = PASSIVE_LEVEL
1341         IRQL = DISPATCH_LEVEL
1342
1343         ========================================================================
1344 */
1345 VOID RTMPWriteTxDescriptor(
1346         IN      PRTMP_ADAPTER   pAd,
1347         IN      PTXD_STRUC              pTxD,
1348         IN      BOOLEAN                 bWIV,
1349         IN      UCHAR                   QueueSEL)
1350 {
1351         //
1352         // Always use Long preamble before verifiation short preamble functionality works well.
1353         // Todo: remove the following line if short preamble functionality works
1354         //
1355         OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1356
1357         pTxD->WIV       = (bWIV) ? 1: 0;
1358         pTxD->QSEL= (QueueSEL);
1359         //RT2860c??  fixed using EDCA queue for test...  We doubt Queue1 has problem.  2006-09-26 Jan
1360         //pTxD->QSEL= FIFO_EDCA;
1361         if (pAd->bGenOneHCCA == TRUE)
1362                 pTxD->QSEL= FIFO_HCCA;
1363         pTxD->DMADONE = 0;
1364 }
1365
1366
1367 // should be called only when -
1368 // 1. MEADIA_CONNECTED
1369 // 2. AGGREGATION_IN_USED
1370 // 3. Fragmentation not in used
1371 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1372 BOOLEAN TxFrameIsAggregatible(
1373         IN      PRTMP_ADAPTER   pAd,
1374         IN      PUCHAR                  pPrevAddr1,
1375         IN      PUCHAR                  p8023hdr)
1376 {
1377
1378         // can't aggregate EAPOL (802.1x) frame
1379         if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1380                 return FALSE;
1381
1382         // can't aggregate multicast/broadcast frame
1383         if (p8023hdr[0] & 0x01)
1384                 return FALSE;
1385
1386         if (INFRA_ON(pAd)) // must be unicast to AP
1387                 return TRUE;
1388         else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
1389                 return TRUE;
1390         else
1391                 return FALSE;
1392 }
1393
1394
1395 /*
1396         ========================================================================
1397
1398         Routine Description:
1399            Check the MSDU Aggregation policy
1400         1.HT aggregation is A-MSDU
1401         2.legaacy rate aggregation is software aggregation by Ralink.
1402
1403         Arguments:
1404
1405         Return Value:
1406
1407         Note:
1408
1409         ========================================================================
1410 */
1411 BOOLEAN PeerIsAggreOn(
1412         IN      PRTMP_ADAPTER   pAd,
1413         IN      ULONG              TxRate,
1414         IN      PMAC_TABLE_ENTRY pMacEntry)
1415 {
1416         ULONG   AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1417
1418         if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
1419         {
1420 #ifdef DOT11_N_SUPPORT
1421                 if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
1422                 {
1423                         return TRUE;
1424                 }
1425 #endif // DOT11_N_SUPPORT //
1426
1427 #ifdef AGGREGATION_SUPPORT
1428                 if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
1429                 {       // legacy  Ralink Aggregation support
1430                         return TRUE;
1431                 }
1432 #endif // AGGREGATION_SUPPORT //
1433         }
1434
1435         return FALSE;
1436
1437 }
1438
1439 /*
1440         ========================================================================
1441
1442         Routine Description:
1443                 Check and fine the packet waiting in SW queue with highest priority
1444
1445         Arguments:
1446                 pAd Pointer to our adapter
1447
1448         Return Value:
1449                 pQueue          Pointer to Waiting Queue
1450
1451         IRQL = DISPATCH_LEVEL
1452
1453         Note:
1454
1455         ========================================================================
1456 */
1457 PQUEUE_HEADER   RTMPCheckTxSwQueue(
1458         IN      PRTMP_ADAPTER   pAd,
1459         OUT PUCHAR                      pQueIdx)
1460 {
1461
1462         ULONG   Number;
1463         // 2004-11-15 to be removed. test aggregation only
1464 //      if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2))
1465 //               return NULL;
1466
1467         Number = pAd->TxSwQueue[QID_AC_BK].Number
1468                          + pAd->TxSwQueue[QID_AC_BE].Number
1469                          + pAd->TxSwQueue[QID_AC_VI].Number
1470                          + pAd->TxSwQueue[QID_AC_VO].Number
1471                          + pAd->TxSwQueue[QID_HCCA].Number;
1472
1473         if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
1474         {
1475                 *pQueIdx = QID_AC_VO;
1476                 return (&pAd->TxSwQueue[QID_AC_VO]);
1477         }
1478         else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
1479         {
1480                 *pQueIdx = QID_AC_VI;
1481                 return (&pAd->TxSwQueue[QID_AC_VI]);
1482         }
1483         else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
1484         {
1485                 *pQueIdx = QID_AC_BE;
1486                 return (&pAd->TxSwQueue[QID_AC_BE]);
1487         }
1488         else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
1489         {
1490                 *pQueIdx = QID_AC_BK;
1491                 return (&pAd->TxSwQueue[QID_AC_BK]);
1492         }
1493         else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
1494         {
1495                 *pQueIdx = QID_HCCA;
1496                 return (&pAd->TxSwQueue[QID_HCCA]);
1497         }
1498
1499         // No packet pending in Tx Sw queue
1500         *pQueIdx = QID_AC_BK;
1501
1502         return (NULL);
1503 }
1504
1505
1506
1507 /*
1508         ========================================================================
1509
1510         Routine Description:
1511                 Suspend MSDU transmission
1512
1513         Arguments:
1514                 pAd     Pointer to our adapter
1515
1516         Return Value:
1517                 None
1518
1519         Note:
1520
1521         ========================================================================
1522 */
1523 VOID    RTMPSuspendMsduTransmission(
1524         IN      PRTMP_ADAPTER   pAd)
1525 {
1526         DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
1527
1528
1529         //
1530         // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1531         // use Lowbound as R66 value on ScanNextChannel(...)
1532         //
1533         RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1534
1535         // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1536         //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd)));
1537         RTMPSetAGCInitValue(pAd, BW_20);
1538
1539         RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1540         //RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000);                // abort all TX rings
1541 }
1542
1543
1544 /*
1545         ========================================================================
1546
1547         Routine Description:
1548                 Resume MSDU transmission
1549
1550         Arguments:
1551                 pAd     Pointer to our adapter
1552
1553         Return Value:
1554                 None
1555
1556         IRQL = DISPATCH_LEVEL
1557
1558         Note:
1559
1560         ========================================================================
1561 */
1562 VOID RTMPResumeMsduTransmission(
1563         IN      PRTMP_ADAPTER   pAd)
1564 {
1565 //    UCHAR                     IrqState;
1566
1567         DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
1568
1569
1570         RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
1571
1572         RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1573 // sample, for IRQ LOCK to SEM LOCK
1574 //    IrqState = pAd->irq_disabled;
1575 //      if (IrqState)
1576 //              RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1577 //    else
1578         RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1579 }
1580
1581
1582 UINT deaggregate_AMSDU_announce(
1583         IN      PRTMP_ADAPTER   pAd,
1584         PNDIS_PACKET            pPacket,
1585         IN      PUCHAR                  pData,
1586         IN      ULONG                   DataSize)
1587 {
1588         USHORT                  PayloadSize;
1589         USHORT                  SubFrameSize;
1590         PHEADER_802_3   pAMSDUsubheader;
1591         UINT                    nMSDU;
1592     UCHAR                       Header802_3[14];
1593
1594         PUCHAR                  pPayload, pDA, pSA, pRemovedLLCSNAP;
1595         PNDIS_PACKET    pClonePacket;
1596
1597
1598
1599         nMSDU = 0;
1600
1601         while (DataSize > LENGTH_802_3)
1602         {
1603
1604                 nMSDU++;
1605
1606                 //hex_dump("subheader", pData, 64);
1607                 pAMSDUsubheader = (PHEADER_802_3)pData;
1608                 //pData += LENGTH_802_3;
1609                 PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
1610                 SubFrameSize = PayloadSize + LENGTH_802_3;
1611
1612
1613                 if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
1614                 {
1615                         break;
1616                 }
1617
1618                 //printk("%d subframe: Size = %d\n",  nMSDU, PayloadSize);
1619
1620                 pPayload = pData + LENGTH_802_3;
1621                 pDA = pData;
1622                 pSA = pData + MAC_ADDR_LEN;
1623
1624                 // convert to 802.3 header
1625         CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
1626
1627 #ifdef CONFIG_STA_SUPPORT
1628                 if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
1629                 {
1630                     // avoid local heap overflow, use dyanamic allocation
1631                    MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
1632                    memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
1633                    Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
1634                    WpaEAPOLKeyAction(pAd, Elem);
1635                    kfree(Elem);
1636                 }
1637 #endif // CONFIG_STA_SUPPORT //
1638
1639 #ifdef CONFIG_STA_SUPPORT
1640                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1641                 {
1642                         if (pRemovedLLCSNAP)
1643                         {
1644                                 pPayload -= LENGTH_802_3;
1645                                 PayloadSize += LENGTH_802_3;
1646                                 NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
1647                         }
1648                 }
1649 #endif // CONFIG_STA_SUPPORT //
1650
1651                 pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1652                 if (pClonePacket)
1653                 {
1654 #ifdef CONFIG_STA_SUPPORT
1655                         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1656                                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
1657 #endif // CONFIG_STA_SUPPORT //
1658                 }
1659
1660
1661                 // A-MSDU has padding to multiple of 4 including subframe header.
1662                 // align SubFrameSize up to multiple of 4
1663                 SubFrameSize = (SubFrameSize+3)&(~0x3);
1664
1665
1666                 if (SubFrameSize > 1528 || SubFrameSize < 32)
1667                 {
1668                         break;
1669                 }
1670
1671                 if (DataSize > SubFrameSize)
1672                 {
1673                         pData += SubFrameSize;
1674                         DataSize -= SubFrameSize;
1675                 }
1676                 else
1677                 {
1678                         // end of A-MSDU
1679                         DataSize = 0;
1680                 }
1681         }
1682
1683         // finally release original rx packet
1684         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1685
1686         return nMSDU;
1687 }
1688
1689
1690 UINT BA_Reorder_AMSDU_Annnounce(
1691         IN      PRTMP_ADAPTER   pAd,
1692         IN      PNDIS_PACKET    pPacket)
1693 {
1694         PUCHAR                  pData;
1695         USHORT                  DataSize;
1696         UINT                    nMSDU = 0;
1697
1698         pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
1699         DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
1700
1701         nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1702
1703         return nMSDU;
1704 }
1705
1706
1707 /*
1708         ==========================================================================
1709         Description:
1710                 Look up the MAC address in the MAC table. Return NULL if not found.
1711         Return:
1712                 pEntry - pointer to the MAC entry; NULL is not found
1713         ==========================================================================
1714 */
1715 MAC_TABLE_ENTRY *MacTableLookup(
1716         IN PRTMP_ADAPTER pAd,
1717         PUCHAR pAddr)
1718 {
1719         ULONG HashIdx;
1720         MAC_TABLE_ENTRY *pEntry = NULL;
1721
1722         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1723         pEntry = pAd->MacTab.Hash[HashIdx];
1724
1725         while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
1726         {
1727                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1728                 {
1729                         break;
1730                 }
1731                 else
1732                         pEntry = pEntry->pNext;
1733         }
1734
1735         return pEntry;
1736 }
1737
1738 MAC_TABLE_ENTRY *MacTableInsertEntry(
1739         IN  PRTMP_ADAPTER   pAd,
1740         IN  PUCHAR                      pAddr,
1741         IN      UCHAR                   apidx,
1742         IN BOOLEAN      CleanAll)
1743 {
1744         UCHAR HashIdx;
1745         int i, FirstWcid;
1746         MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1747
1748         // if FULL, return
1749         if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1750                 return NULL;
1751
1752         FirstWcid = 1;
1753 #ifdef CONFIG_STA_SUPPORT
1754         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1755         if (pAd->StaCfg.BssType == BSS_INFRA)
1756                 FirstWcid = 2;
1757 #endif // CONFIG_STA_SUPPORT //
1758
1759         // allocate one MAC entry
1760         NdisAcquireSpinLock(&pAd->MacTabLock);
1761         for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++)   // skip entry#0 so that "entry index == AID" for fast lookup
1762         {
1763                 // pick up the first available vacancy
1764                 if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1765                         (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1766                         (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
1767                         (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1768                         )
1769                 {
1770                         pEntry = &pAd->MacTab.Content[i];
1771                         if (CleanAll == TRUE)
1772                         {
1773                                 pEntry->MaxSupportedRate = RATE_11;
1774                                 pEntry->CurrTxRate = RATE_11;
1775                                 NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1776                                 pEntry->PairwiseKey.KeyLen = 0;
1777                                 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1778                         }
1779                         {
1780
1781 #ifdef CONFIG_STA_SUPPORT
1782                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1783                                 {
1784                                         pEntry->ValidAsCLI = TRUE;
1785                                         pEntry->ValidAsWDS = FALSE;
1786                                         pEntry->ValidAsApCli = FALSE;
1787                                         pEntry->ValidAsMesh = FALSE;
1788                                         pEntry->ValidAsDls = FALSE;
1789                                 }
1790 #endif // CONFIG_STA_SUPPORT //
1791                         }
1792
1793                         pEntry->bIAmBadAtheros = FALSE;
1794                         pEntry->pAd = pAd;
1795                         pEntry->CMTimerRunning = FALSE;
1796                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1797                         pEntry->RSNIE_Len = 0;
1798                         NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
1799                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1800
1801                         if (pEntry->ValidAsMesh)
1802                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
1803                         else if (pEntry->ValidAsApCli)
1804                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
1805                         else if (pEntry->ValidAsWDS)
1806                                 pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
1807                         else
1808                                 pEntry->apidx = apidx;
1809
1810                         {
1811
1812 #ifdef CONFIG_STA_SUPPORT
1813                                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1814                                 {
1815                                         pEntry->AuthMode = pAd->StaCfg.AuthMode;
1816                                         pEntry->WepStatus = pAd->StaCfg.WepStatus;
1817                                         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1818                                 }
1819 #endif // CONFIG_STA_SUPPORT //
1820                         }
1821
1822                         pEntry->GTKState = REKEY_NEGOTIATING;
1823                         pEntry->PairwiseKey.KeyLen = 0;
1824                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1825                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1826                         pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1827                         COPY_MAC_ADDR(pEntry->Addr, pAddr);
1828                         pEntry->Sst = SST_NOT_AUTH;
1829                         pEntry->AuthState = AS_NOT_AUTH;
1830                         pEntry->Aid = (USHORT)i;  //0;
1831                         pEntry->CapabilityInfo = 0;
1832                         pEntry->PsMode = PWR_ACTIVE;
1833                         pEntry->PsQIdleCount = 0;
1834                         pEntry->NoDataIdleCount = 0;
1835                         pEntry->ContinueTxFailCnt = 0;
1836                         InitializeQueueHeader(&pEntry->PsQueue);
1837
1838
1839                         pAd->MacTab.Size ++;
1840                         // Add this entry into ASIC RX WCID search table
1841                         RT28XX_STA_ENTRY_ADD(pAd, pEntry);
1842
1843                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
1844                         break;
1845                 }
1846         }
1847
1848         // add this MAC entry into HASH table
1849         if (pEntry)
1850         {
1851                 HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1852                 if (pAd->MacTab.Hash[HashIdx] == NULL)
1853                 {
1854                         pAd->MacTab.Hash[HashIdx] = pEntry;
1855                 }
1856                 else
1857                 {
1858                         pCurrEntry = pAd->MacTab.Hash[HashIdx];
1859                         while (pCurrEntry->pNext != NULL)
1860                                 pCurrEntry = pCurrEntry->pNext;
1861                         pCurrEntry->pNext = pEntry;
1862                 }
1863         }
1864
1865         NdisReleaseSpinLock(&pAd->MacTabLock);
1866         return pEntry;
1867 }
1868
1869 /*
1870         ==========================================================================
1871         Description:
1872                 Delete a specified client from MAC table
1873         ==========================================================================
1874  */
1875 BOOLEAN MacTableDeleteEntry(
1876         IN PRTMP_ADAPTER pAd,
1877         IN USHORT wcid,
1878         IN PUCHAR pAddr)
1879 {
1880         USHORT HashIdx;
1881         MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
1882         BOOLEAN Cancelled;
1883         //USHORT        offset; // unused variable
1884         //UCHAR j;                      // unused variable
1885
1886         if (wcid >= MAX_LEN_OF_MAC_TABLE)
1887                 return FALSE;
1888
1889         NdisAcquireSpinLock(&pAd->MacTabLock);
1890
1891         HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1892         //pEntry = pAd->MacTab.Hash[HashIdx];
1893         pEntry = &pAd->MacTab.Content[wcid];
1894
1895         if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
1896                 ))
1897         {
1898                 if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
1899                 {
1900
1901                         // Delete this entry from ASIC on-chip WCID Table
1902                         RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
1903
1904 #ifdef DOT11_N_SUPPORT
1905                         // free resources of BA
1906                         BASessionTearDownALL(pAd, pEntry->Aid);
1907 #endif // DOT11_N_SUPPORT //
1908
1909
1910                         pPrevEntry = NULL;
1911                         pProbeEntry = pAd->MacTab.Hash[HashIdx];
1912                         ASSERT(pProbeEntry);
1913
1914                         // update Hash list
1915                         do
1916                         {
1917                                 if (pProbeEntry == pEntry)
1918                                 {
1919                                         if (pPrevEntry == NULL)
1920                                         {
1921                                                 pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
1922                                         }
1923                                         else
1924                                         {
1925                                                 pPrevEntry->pNext = pEntry->pNext;
1926                                         }
1927                                         break;
1928                                 }
1929
1930                                 pPrevEntry = pProbeEntry;
1931                                 pProbeEntry = pProbeEntry->pNext;
1932                         } while (pProbeEntry);
1933
1934                         // not found !!!
1935                         ASSERT(pProbeEntry != NULL);
1936
1937                         RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1938
1939
1940                 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
1941                 {
1942                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
1943                         pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
1944                 }
1945
1946
1947                         NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
1948                         pAd->MacTab.Size --;
1949                         DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
1950                 }
1951                 else
1952                 {
1953                         printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
1954                 }
1955         }
1956
1957         NdisReleaseSpinLock(&pAd->MacTabLock);
1958
1959         //Reset operating mode when no Sta.
1960         if (pAd->MacTab.Size == 0)
1961         {
1962 #ifdef DOT11_N_SUPPORT
1963                 pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1964 #endif // DOT11_N_SUPPORT //
1965                 AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
1966         }
1967
1968         return TRUE;
1969 }
1970
1971
1972 /*
1973         ==========================================================================
1974         Description:
1975                 This routine reset the entire MAC table. All packets pending in
1976                 the power-saving queues are freed here.
1977         ==========================================================================
1978  */
1979 VOID MacTableReset(
1980         IN  PRTMP_ADAPTER  pAd)
1981 {
1982         int         i;
1983
1984         DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1985         //NdisAcquireSpinLock(&pAd->MacTabLock);
1986
1987         for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1988         {
1989                 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1990            {
1991
1992 #ifdef DOT11_N_SUPPORT
1993                         // free resources of BA
1994                         BASessionTearDownALL(pAd, i);
1995 #endif // DOT11_N_SUPPORT //
1996
1997                         pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1998
1999
2000
2001 #ifdef RT2870
2002                         NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
2003                         RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
2004 #endif // RT2870 //
2005
2006                         //AsicDelWcidTab(pAd, i);
2007                 }
2008         }
2009
2010         return;
2011 }
2012
2013 /*
2014         ==========================================================================
2015         Description:
2016
2017         IRQL = DISPATCH_LEVEL
2018
2019         ==========================================================================
2020 */
2021 VOID AssocParmFill(
2022         IN PRTMP_ADAPTER pAd,
2023         IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
2024         IN PUCHAR                     pAddr,
2025         IN USHORT                     CapabilityInfo,
2026         IN ULONG                      Timeout,
2027         IN USHORT                     ListenIntv)
2028 {
2029         COPY_MAC_ADDR(AssocReq->Addr, pAddr);
2030         // Add mask to support 802.11b mode only
2031         AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
2032         AssocReq->Timeout = Timeout;
2033         AssocReq->ListenIntv = ListenIntv;
2034 }
2035
2036
2037 /*
2038         ==========================================================================
2039         Description:
2040
2041         IRQL = DISPATCH_LEVEL
2042
2043         ==========================================================================
2044 */
2045 VOID DisassocParmFill(
2046         IN PRTMP_ADAPTER pAd,
2047         IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
2048         IN PUCHAR pAddr,
2049         IN USHORT Reason)
2050 {
2051         COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
2052         DisassocReq->Reason = Reason;
2053 }
2054
2055
2056 /*
2057         ========================================================================
2058
2059         Routine Description:
2060                 Check the out going frame, if this is an DHCP or ARP datagram
2061         will be duplicate another frame at low data rate transmit.
2062
2063         Arguments:
2064                 pAd             Pointer to our adapter
2065                 pPacket         Pointer to outgoing Ndis frame
2066
2067         Return Value:
2068                 TRUE            To be duplicate at Low data rate transmit. (1mb)
2069                 FALSE           Do nothing.
2070
2071         IRQL = DISPATCH_LEVEL
2072
2073         Note:
2074
2075                 MAC header + IP Header + UDP Header
2076                   14 Bytes        20 Bytes
2077
2078                 UDP Header
2079                 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2080                                                 Source Port
2081                 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2082                                         Destination Port
2083
2084                 port 0x43 means Bootstrap Protocol, server.
2085                 Port 0x44 means Bootstrap Protocol, client.
2086
2087         ========================================================================
2088 */
2089
2090 BOOLEAN RTMPCheckDHCPFrame(
2091         IN      PRTMP_ADAPTER   pAd,
2092         IN      PNDIS_PACKET    pPacket)
2093 {
2094         PACKET_INFO     PacketInfo;
2095         ULONG                   NumberOfBytesRead = 0;
2096         ULONG                   CurrentOffset = 0;
2097         PVOID                   pVirtualAddress = NULL;
2098         UINT                    NdisBufferLength;
2099         PUCHAR                  pSrc;
2100         USHORT                  Protocol;
2101         UCHAR                   ByteOffset36 = 0;
2102         UCHAR                   ByteOffset38 = 0;
2103         BOOLEAN                 ReadFirstParm = TRUE;
2104
2105         RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
2106
2107         NumberOfBytesRead += NdisBufferLength;
2108         pSrc = (PUCHAR) pVirtualAddress;
2109         Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
2110
2111         //
2112         // Check DHCP & BOOTP protocol
2113         //
2114         while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
2115         {
2116                 if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
2117                 {
2118                         CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
2119                         ByteOffset36 = *(pSrc + CurrentOffset);
2120                         ReadFirstParm = FALSE;
2121                 }
2122
2123                 if (NumberOfBytesRead >= 37)
2124                 {
2125                         CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
2126                         ByteOffset38 = *(pSrc + CurrentOffset);
2127                         //End of Read
2128                         break;
2129                 }
2130                 return FALSE;
2131         }
2132
2133         // Check for DHCP & BOOTP protocol
2134         if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
2135                 {
2136                 //
2137                 // 2054 (hex 0806) for ARP datagrams
2138                 // if this packet is not ARP datagrams, then do nothing
2139                 // ARP datagrams will also be duplicate at 1mb broadcast frames
2140                 //
2141                 if (Protocol != 0x0806 )
2142                         return FALSE;
2143                 }
2144
2145         return TRUE;
2146 }
2147
2148
2149 BOOLEAN RTMPCheckEtherType(
2150         IN      PRTMP_ADAPTER   pAd,
2151         IN      PNDIS_PACKET    pPacket)
2152 {
2153         USHORT  TypeLen;
2154         UCHAR   Byte0, Byte1;
2155         PUCHAR  pSrcBuf;
2156         UINT32  pktLen;
2157         UINT16  srcPort, dstPort;
2158         BOOLEAN status = TRUE;
2159
2160
2161         pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
2162         pktLen = GET_OS_PKT_LEN(pPacket);
2163
2164         ASSERT(pSrcBuf);
2165
2166         RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
2167
2168         // get Ethernet protocol field
2169         TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
2170
2171         pSrcBuf += LENGTH_802_3;        // Skip the Ethernet Header.
2172
2173         if (TypeLen <= 1500)
2174         {       // 802.3, 802.3 LLC
2175                 /*
2176                         DestMAC(6) + SrcMAC(6) + Lenght(2) +
2177                         DSAP(1) + SSAP(1) + Control(1) +
2178                         if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2179                                 => + SNAP (5, OriginationID(3) + etherType(2))
2180                 */
2181                 if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
2182                 {
2183                         Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
2184                         RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
2185                         TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2186                         pSrcBuf += 8; // Skip this LLC/SNAP header
2187                 }
2188                 else
2189                 {
2190                         //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2191                 }
2192         }
2193
2194         // If it's a VLAN packet, get the real Type/Length field.
2195         if (TypeLen == 0x8100)
2196         {
2197                 /* 0x8100 means VLAN packets */
2198
2199                 /* Dest. MAC Address (6-bytes) +
2200                    Source MAC Address (6-bytes) +
2201                    Length/Type = 802.1Q Tag Type (2-byte) +
2202                    Tag Control Information (2-bytes) +
2203                    Length / Type (2-bytes) +
2204                    data payload (0-n bytes) +
2205                    Pad (0-p bytes) +
2206                    Frame Check Sequence (4-bytes) */
2207
2208                 RTMP_SET_PACKET_VLAN(pPacket, 1);
2209                 Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
2210                 TypeLen = (USHORT)((Byte0 << 8) + Byte1);
2211
2212                 pSrcBuf += 4; // Skip the VLAN Header.
2213         }
2214
2215         switch (TypeLen)
2216         {
2217                 case 0x0800:
2218                         {
2219                                 ASSERT((pktLen > 34));
2220                                 if (*(pSrcBuf + 9) == 0x11)
2221                                 {       // udp packet
2222                                         ASSERT((pktLen > 34));  // 14 for ethernet header, 20 for IP header
2223
2224                                         pSrcBuf += 20;  // Skip the IP header
2225                                         srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
2226                                         dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
2227
2228                                         if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
2229                                         {       //It's a BOOTP/DHCP packet
2230                                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2231                                         }
2232                                 }
2233                         }
2234                         break;
2235                 case 0x0806:
2236                         {
2237                                 //ARP Packet.
2238                                 RTMP_SET_PACKET_DHCP(pPacket, 1);
2239                         }
2240                         break;
2241                 case 0x888e:
2242                         {
2243                                 // EAPOL Packet.
2244                                 RTMP_SET_PACKET_EAPOL(pPacket, 1);
2245                         }
2246                         break;
2247                 default:
2248                         status = FALSE;
2249                         break;
2250         }
2251
2252         return status;
2253
2254 }
2255
2256
2257
2258 VOID Update_Rssi_Sample(
2259         IN PRTMP_ADAPTER        pAd,
2260         IN RSSI_SAMPLE          *pRssi,
2261         IN PRXWI_STRUC          pRxWI)
2262                 {
2263         CHAR    rssi0 = pRxWI->RSSI0;
2264         CHAR    rssi1 = pRxWI->RSSI1;
2265         CHAR    rssi2 = pRxWI->RSSI2;
2266
2267         if (rssi0 != 0)
2268         {
2269                 pRssi->LastRssi0        = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
2270                 pRssi->AvgRssi0X8       = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2271                 pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2272         }
2273
2274         if (rssi1 != 0)
2275         {
2276                 pRssi->LastRssi1        = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
2277                 pRssi->AvgRssi1X8       = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2278                 pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2279         }
2280
2281         if (rssi2 != 0)
2282         {
2283                 pRssi->LastRssi2        = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
2284                 pRssi->AvgRssi2X8  = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2285                 pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2286         }
2287 }
2288
2289
2290
2291 // Normal legacy Rx packet indication
2292 VOID Indicate_Legacy_Packet(
2293         IN      PRTMP_ADAPTER   pAd,
2294         IN      RX_BLK                  *pRxBlk,
2295         IN      UCHAR                   FromWhichBSSID)
2296 {
2297         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2298         UCHAR                   Header802_3[LENGTH_802_3];
2299
2300         // 1. get 802.3 Header
2301         // 2. remove LLC
2302         //              a. pointer pRxBlk->pData to payload
2303         //      b. modify pRxBlk->DataSize
2304 #ifdef CONFIG_STA_SUPPORT
2305         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2306                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2307 #endif // CONFIG_STA_SUPPORT //
2308
2309         if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
2310         {
2311 #if 0 // sample take off, for multiple card design
2312                 static int err_size;
2313
2314                 err_size++;
2315                 if (err_size > 20)
2316                 {
2317                          printk("Legacy DataSize = %d\n", pRxBlk->DataSize);
2318                          hex_dump("802.3 Header", Header802_3, LENGTH_802_3);
2319                          hex_dump("Payload", pRxBlk->pData, 64);
2320                          err_size = 0;
2321                 }
2322 #endif
2323
2324                 // release packet
2325                 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2326                 return;
2327         }
2328
2329
2330         STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2331
2332 #ifdef RT2870
2333 #ifdef DOT11_N_SUPPORT
2334         if (pAd->CommonCfg.bDisableReordering == 0)
2335         {
2336                 PBA_REC_ENTRY           pBAEntry;
2337                 ULONG                           Now32;
2338                 UCHAR                           Wcid = pRxBlk->pRxWI->WirelessCliID;
2339                 UCHAR                           TID = pRxBlk->pRxWI->TID;
2340                 USHORT                          Idx;
2341
2342 #define REORDERING_PACKET_TIMEOUT               ((100 * HZ)/1000)       // system ticks -- 100 ms
2343
2344                 if (Wcid < MAX_LEN_OF_MAC_TABLE)
2345                 {
2346                         Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2347                         if (Idx != 0)
2348                         {
2349                                 pBAEntry = &pAd->BATable.BARecEntry[Idx];
2350                                 // update last rx time
2351                                 NdisGetSystemUpTime(&Now32);
2352                                 if ((pBAEntry->list.qlen > 0) &&
2353                                          RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
2354                                         )
2355                                 {
2356                                         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);
2357                                         hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
2358                                         ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
2359                                 }
2360                         }
2361                 }
2362         }
2363 #endif // DOT11_N_SUPPORT //
2364 #endif // RT2870 //
2365
2366         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2367
2368         //
2369         // pass this 802.3 packet to upper layer or forward this packet to WM directly
2370         //
2371 #ifdef CONFIG_STA_SUPPORT
2372         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2373                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2374 #endif // CONFIG_STA_SUPPORT //
2375
2376 }
2377
2378
2379 // Normal, AMPDU or AMSDU
2380 VOID CmmRxnonRalinkFrameIndicate(
2381         IN      PRTMP_ADAPTER   pAd,
2382         IN      RX_BLK                  *pRxBlk,
2383         IN      UCHAR                   FromWhichBSSID)
2384 {
2385 #ifdef DOT11_N_SUPPORT
2386         if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
2387         {
2388                 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2389         }
2390         else
2391 #endif // DOT11_N_SUPPORT //
2392         {
2393 #ifdef DOT11_N_SUPPORT
2394                 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
2395                 {
2396                         // handle A-MSDU
2397                         Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2398                 }
2399                 else
2400 #endif // DOT11_N_SUPPORT //
2401                 {
2402                         Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2403                 }
2404         }
2405 }
2406
2407
2408 VOID CmmRxRalinkFrameIndicate(
2409         IN      PRTMP_ADAPTER   pAd,
2410         IN      MAC_TABLE_ENTRY *pEntry,
2411         IN      RX_BLK                  *pRxBlk,
2412         IN      UCHAR                   FromWhichBSSID)
2413 {
2414         UCHAR                   Header802_3[LENGTH_802_3];
2415         UINT16                  Msdu2Size;
2416         UINT16                  Payload1Size, Payload2Size;
2417         PUCHAR                  pData2;
2418         PNDIS_PACKET    pPacket2 = NULL;
2419
2420
2421
2422         Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
2423
2424         if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
2425         {
2426                 /* skip two byte MSDU2 len */
2427                 pRxBlk->pData += 2;
2428                 pRxBlk->DataSize -= 2;
2429         }
2430         else
2431         {
2432                 // release packet
2433                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2434                 return;
2435         }
2436
2437         // get 802.3 Header and  remove LLC
2438 #ifdef CONFIG_STA_SUPPORT
2439         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2440                 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2441 #endif // CONFIG_STA_SUPPORT //
2442
2443
2444         ASSERT(pRxBlk->pRxPacket);
2445
2446         // Ralink Aggregation frame
2447         pAd->RalinkCounters.OneSecRxAggregationCount ++;
2448         Payload1Size = pRxBlk->DataSize - Msdu2Size;
2449         Payload2Size = Msdu2Size - LENGTH_802_3;
2450
2451         pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2452 #ifdef CONFIG_STA_SUPPORT
2453         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2454                 pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
2455 #endif // CONFIG_STA_SUPPORT //
2456
2457         if (!pPacket2)
2458         {
2459                 // release packet
2460                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2461                 return;
2462         }
2463
2464         // update payload size of 1st packet
2465         pRxBlk->DataSize = Payload1Size;
2466         wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2467
2468 #ifdef CONFIG_STA_SUPPORT
2469         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2470                 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
2471 #endif // CONFIG_STA_SUPPORT //
2472
2473         if (pPacket2)
2474         {
2475 #ifdef CONFIG_STA_SUPPORT
2476                 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2477                         ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2478 #endif // CONFIG_STA_SUPPORT //
2479         }
2480 }
2481
2482
2483 #define RESET_FRAGFRAME(_fragFrame) \
2484         {                                                               \
2485                 _fragFrame.RxSize = 0;          \
2486                 _fragFrame.Sequence = 0;        \
2487                 _fragFrame.LastFrag = 0;        \
2488                 _fragFrame.Flags = 0;           \
2489         }
2490
2491
2492 PNDIS_PACKET RTMPDeFragmentDataFrame(
2493         IN      PRTMP_ADAPTER   pAd,
2494         IN      RX_BLK                  *pRxBlk)
2495 {
2496         PHEADER_802_11  pHeader = pRxBlk->pHeader;
2497         PNDIS_PACKET    pRxPacket = pRxBlk->pRxPacket;
2498         UCHAR                   *pData = pRxBlk->pData;
2499         USHORT                  DataSize = pRxBlk->DataSize;
2500         PNDIS_PACKET    pRetPacket = NULL;
2501         UCHAR                   *pFragBuffer = NULL;
2502         BOOLEAN                 bReassDone = FALSE;
2503         UCHAR                   HeaderRoom = 0;
2504
2505
2506         ASSERT(pHeader);
2507
2508         HeaderRoom = pData - (UCHAR *)pHeader;
2509
2510         // Re-assemble the fragmented packets
2511         if (pHeader->Frag == 0)         // Frag. Number is 0 : First frag or only one pkt
2512         {
2513                 // the first pkt of fragment, record it.
2514                 if (pHeader->FC.MoreFrag)
2515                 {
2516                         ASSERT(pAd->FragFrame.pFragPacket);
2517                         pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2518                         pAd->FragFrame.RxSize   = DataSize + HeaderRoom;
2519                         NdisMoveMemory(pFragBuffer,      pHeader, pAd->FragFrame.RxSize);
2520                         pAd->FragFrame.Sequence = pHeader->Sequence;
2521                         pAd->FragFrame.LastFrag = pHeader->Frag;           // Should be 0
2522                         ASSERT(pAd->FragFrame.LastFrag == 0);
2523                         goto done;      // end of processing this frame
2524                 }
2525         }
2526         else    //Middle & End of fragment
2527         {
2528                 if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2529                         (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
2530                 {
2531                         // Fragment is not the same sequence or out of fragment number order
2532                         // Reset Fragment control blk
2533                         RESET_FRAGFRAME(pAd->FragFrame);
2534                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
2535                         goto done; // give up this frame
2536                 }
2537                 else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
2538                 {
2539                         // Fragment frame is too large, it exeeds the maximum frame size.
2540                         // Reset Fragment control blk
2541                         RESET_FRAGFRAME(pAd->FragFrame);
2542                         DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2543                         goto done; // give up this frame
2544                 }
2545
2546         //
2547                 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2548                 // In this case, we will dropt it.
2549                 //
2550                 if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
2551                 {
2552                         DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
2553                         goto done; // give up this frame
2554                 }
2555
2556                 pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2557
2558                 // concatenate this fragment into the re-assembly buffer
2559                 NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
2560                 pAd->FragFrame.RxSize  += DataSize;
2561                 pAd->FragFrame.LastFrag = pHeader->Frag;           // Update fragment number
2562
2563                 // Last fragment
2564                 if (pHeader->FC.MoreFrag == FALSE)
2565                 {
2566                         bReassDone = TRUE;
2567                 }
2568         }
2569
2570 done:
2571         // always release rx fragmented packet
2572         RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2573
2574         // return defragmented packet if packet is reassembled completely
2575         // otherwise return NULL
2576         if (bReassDone)
2577         {
2578                 PNDIS_PACKET pNewFragPacket;
2579
2580                 // allocate a new packet buffer for fragment
2581                 pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2582                 if (pNewFragPacket)
2583                 {
2584                         // update RxBlk
2585                         pRetPacket = pAd->FragFrame.pFragPacket;
2586                         pAd->FragFrame.pFragPacket = pNewFragPacket;
2587                         pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
2588                         pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
2589                         pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2590                         pRxBlk->pRxPacket = pRetPacket;
2591                 }
2592                 else
2593                 {
2594                         RESET_FRAGFRAME(pAd->FragFrame);
2595                 }
2596         }
2597
2598         return pRetPacket;
2599 }
2600
2601
2602 VOID Indicate_AMSDU_Packet(
2603         IN      PRTMP_ADAPTER   pAd,
2604         IN      RX_BLK                  *pRxBlk,
2605         IN      UCHAR                   FromWhichBSSID)
2606 {
2607         UINT                    nMSDU;
2608
2609         update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2610         RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2611         nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
2612 }
2613
2614 VOID Indicate_EAPOL_Packet(
2615         IN      PRTMP_ADAPTER   pAd,
2616         IN      RX_BLK                  *pRxBlk,
2617         IN      UCHAR                   FromWhichBSSID)
2618 {
2619         MAC_TABLE_ENTRY *pEntry = NULL;
2620
2621
2622 #ifdef CONFIG_STA_SUPPORT
2623         IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2624         {
2625                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
2626                 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2627                 return;
2628         }
2629 #endif // CONFIG_STA_SUPPORT //
2630
2631         if (pEntry == NULL)
2632         {
2633                 DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2634                 // release packet
2635                 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
2636                 return;
2637         }
2638 }
2639
2640 #define BCN_TBTT_OFFSET         64      //defer 64 us
2641 VOID ReSyncBeaconTime(
2642         IN  PRTMP_ADAPTER   pAd)
2643 {
2644
2645         UINT32  Offset;
2646
2647
2648         Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2649
2650         pAd->TbttTickCount++;
2651
2652         //
2653         // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2654         // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2655         //
2656         if (Offset == (BCN_TBTT_OFFSET-2))
2657         {
2658                 BCN_TIME_CFG_STRUC csr;
2659                 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2660                 csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ;     // ASIC register in units of 1/16 TU = 64us
2661                 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2662         }
2663         else
2664         {
2665                 if (Offset == (BCN_TBTT_OFFSET-1))
2666                 {
2667                         BCN_TIME_CFG_STRUC csr;
2668
2669                         RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2670                         csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
2671                         RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2672                 }
2673         }
2674 }
2675