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