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