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