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