2
*************************************************************************
4
* 5F., No.36, Taiyuan St., Jhubei City,
8
* (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25
*************************************************************************
28
#include "../rt_config.h"
30
u8 SNAP_802_1H[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
31
u8 SNAP_BRIDGE_TUNNEL[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
33
/* Add Cisco Aironet SNAP heade for CCX2 support */
34
u8 SNAP_AIRONET[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
35
u8 CKIP_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02 };
36
u8 EAPOL_LLC_SNAP[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
37
u8 EAPOL[] = { 0x88, 0x8e };
38
u8 TPID[] = { 0x81, 0x00 }; /* VLAN related */
40
u8 IPX[] = { 0x81, 0x37 };
41
u8 APPLE_TALK[] = { 0x80, 0xf3 };
43
u8 RateIdToPlcpSignal[12] = {
44
0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 *//* see BBP spec */
45
11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 *//* see IEEE802.11a-1999 p.14 */
46
9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */
47
}; /* see IEEE802.11a-1999 p.14 */
49
u8 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 */
56
u8 OfdmRateToRxwiMCS[12] = {
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 */
62
u8 RxwiMCSToOfdmRate[12] = {
63
RATE_6, RATE_9, RATE_12, RATE_18,
64
RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
65
4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
69
{ "1Mbps", "2Mbps", "5.5Mbps", "11Mbps", "06Mbps", "09Mbps", "12Mbps",
70
"18Mbps", "24Mbps", "36Mbps", "48Mbps", "54Mbps", "MM-0", "MM-1", "MM-2", "MM-3",
71
"MM-4", "MM-5", "MM-6", "MM-7", "MM-8", "MM-9", "MM-10", "MM-11", "MM-12", "MM-13",
72
"MM-14", "MM-15", "MM-32", "ee1", "ee2", "ee3" };
75
{ CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS - 1, CW_MIN_IN_BITS - 2 };
76
/*u8 default_cwmax[]={CW_MAX_IN_BITS, CW_MAX_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1}; */
77
u8 default_sta_aifsn[] = { 3, 7, 2, 2 };
79
u8 MapUserPriorityToAccessCategory[8] =
80
{ QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI,
81
QID_AC_VO, QID_AC_VO };
84
========================================================================
87
API for MLME to transmit management frame to AP (BSS Mode)
88
or station (IBSS Mode)
91
pAd Pointer to our adapter
92
pData Pointer to the outgoing 802.11 frame
93
Length Size of outgoing management frame
101
IRQL = DISPATCH_LEVEL
105
========================================================================
107
int MiniportMMRequest(struct rt_rtmp_adapter *pAd,
108
u8 QueIdx, u8 *pData, u32 Length)
111
int Status = NDIS_STATUS_SUCCESS;
112
unsigned long FreeNum;
113
u8 rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; /*RTMP_HW_HDR_LEN]; */
115
unsigned long IrqFlags = 0;
117
#endif /* RTMP_MAC_PCI // */
118
BOOLEAN bUseDataQ = FALSE;
121
ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
123
if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) {
125
QueIdx &= (~MGMT_USE_QUEUE_FLAG);
128
/* 2860C use Tx Ring */
129
IrqState = pAd->irq_disabled;
130
if (pAd->MACVersion == 0x28600100) {
131
QueIdx = (bUseDataQ == TRUE ? QueIdx : 3);
134
if (bUseDataQ && (!IrqState))
135
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
136
#endif /* RTMP_MAC_PCI // */
139
/* Reset is in progress, stop immediately */
140
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
142
fRTMP_ADAPTER_HALT_IN_PROGRESS |
143
fRTMP_ADAPTER_NIC_NOT_EXIST)
144
|| !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
145
Status = NDIS_STATUS_FAILURE;
148
/* Check Free priority queue */
149
/* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing. */
152
retryCnt = MAX_DATAMM_RETRY;
153
/* free Tx(QueIdx) resources */
154
RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
155
FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
157
#endif /* RTMP_MAC_PCI // */
159
FreeNum = GET_MGMTRING_FREENO(pAd);
163
/* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870 */
164
NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
166
RTMPAllocateNdisPacket(pAd, &pPacket,
168
(TXINFO_SIZE + TXWI_SIZE),
170
if (Status != NDIS_STATUS_SUCCESS) {
171
DBGPRINT(RT_DEBUG_WARN,
172
("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
175
/*pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; */
176
/*pAd->CommonCfg.MlmeRate = RATE_2; */
181
MlmeDataHardTransmit(pAd, QueIdx, pPacket);
184
#endif /* RTMP_MAC_PCI // */
185
Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
186
if (Status == NDIS_STATUS_SUCCESS)
189
RTMPFreeNdisPacket(pAd, pPacket);
191
pAd->RalinkCounters.MgmtRingFullCount++;
195
DBGPRINT(RT_DEBUG_TRACE,
196
("retryCnt %d\n", retryCnt));
198
DBGPRINT(RT_DEBUG_ERROR,
199
("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n",
205
#endif /* RTMP_MAC_PCI // */
206
DBGPRINT(RT_DEBUG_ERROR,
207
("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
209
pAd->RalinkCounters.MgmtRingFullCount));
211
} while (retryCnt > 0);
214
if (bUseDataQ && (!IrqState))
215
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
216
#endif /* RTMP_MAC_PCI // */
222
========================================================================
225
Copy frame from waiting queue into relative ring buffer and set
226
appropriate ASIC register to kick hardware transmit function
229
pAd Pointer to our adapter
230
pBuffer Pointer to memory of outgoing frame
231
Length Size of outgoing management frame
239
IRQL = DISPATCH_LEVEL
243
========================================================================
245
int MlmeHardTransmit(struct rt_rtmp_adapter *pAd,
246
u8 QueIdx, void *pPacket)
248
struct rt_packet_info PacketInfo;
251
struct rt_header_802_11 * pHeader_802_11;
253
if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
255
return NDIS_STATUS_FAILURE;
258
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
259
if (pSrcBufVA == NULL)
260
return NDIS_STATUS_FAILURE;
262
pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE);
265
if (pAd->MACVersion == 0x28600100)
266
return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
268
#endif /* RTMP_MAC_PCI // */
269
return MlmeHardTransmitMgmtRing(pAd, QueIdx, pPacket);
273
int MlmeHardTransmitMgmtRing(struct rt_rtmp_adapter *pAd,
274
u8 QueIdx, void *pPacket)
276
struct rt_packet_info PacketInfo;
279
struct rt_header_802_11 * pHeader_802_11;
280
BOOLEAN bAckRequired, bInsertTimestamp;
282
struct rt_txwi * pFirstTxWI;
283
struct rt_mac_table_entry *pMacEntry = NULL;
286
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
288
/* Make sure MGMT ring resource won't be used by other threads */
289
RTMP_SEM_LOCK(&pAd->MgmtRingLock);
290
if (pSrcBufVA == NULL) {
291
/* The buffer shouldn't be NULL */
292
RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
293
return NDIS_STATUS_FAILURE;
297
/* outgoing frame always wakeup PHY to prevent frame lost */
298
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
299
AsicForceWakeup(pAd, TRUE);
302
pFirstTxWI = (struct rt_txwi *) (pSrcBufVA + TXINFO_SIZE);
303
pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); /*TXWI_SIZE); */
305
if (pHeader_802_11->Addr1[0] & 0x01) {
306
MlmeRate = pAd->CommonCfg.BasicMlmeRate;
308
MlmeRate = pAd->CommonCfg.MlmeRate;
311
/* Verify Mlme rate for a / g bands. */
312
if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
315
if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
316
(pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
317
pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
321
/* Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode. */
322
if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
323
|| pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) {
324
if (pAd->LatchRfRegs.Channel > 14)
325
pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
327
pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
332
/* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */
333
/* Snice it's been set to 0 while on MgtMacHeaderInit */
334
/* By the way this will cause frame to be send on PWR_SAVE failed. */
336
pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE); */
339
/* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */
340
/* Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */
341
/* if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL)) */
343
if ((pHeader_802_11->FC.SubType == SUBTYPE_ACTION) ||
344
((pHeader_802_11->FC.Type == BTYPE_DATA) &&
345
((pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL) ||
346
(pHeader_802_11->FC.SubType == SUBTYPE_NULL_FUNC)))) {
347
if (pAd->StaCfg.Psm == PWR_SAVE)
348
pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
350
pHeader_802_11->FC.PwrMgmt =
351
pAd->CommonCfg.bAPSDForcePowerSave;
355
bInsertTimestamp = FALSE;
356
if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */
358
/*Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue. */
359
if ((pAd->OpMode == OPMODE_STA)
360
&& (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL)) {
361
pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
363
bAckRequired = FALSE;
364
} else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
366
/*pAd->Sequence++; */
367
/*pHeader_802_11->Sequence = pAd->Sequence; */
369
if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */
371
bAckRequired = FALSE;
372
pHeader_802_11->Duration = 0;
375
pHeader_802_11->Duration =
376
RTMPCalcDuration(pAd, MlmeRate, 14);
377
if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
378
&& (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
379
bInsertTimestamp = TRUE;
380
bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response */
382
if ((pHeader_802_11->FC.SubType ==
384
&& (pHeader_802_11->FC.Type == BTYPE_MGMT)) {
385
bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request */
390
pHeader_802_11->Sequence = pAd->Sequence++;
391
if (pAd->Sequence > 0xfff)
394
/* Before radar detection done, mgmt frame can not be sent but probe req */
395
/* Because we need to use probe req to trigger driver to send probe req in passive scan */
396
if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
397
&& (pAd->CommonCfg.bIEEE80211H == 1)
398
&& (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
399
DBGPRINT(RT_DEBUG_ERROR,
400
("MlmeHardTransmit --> radar detect not in normal mode!\n"));
402
RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
403
return (NDIS_STATUS_FAILURE);
407
/* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */
408
/* should always has only one physical buffer, and the whole frame size equals */
409
/* to the first scatter buffer size */
412
/* Initialize TX Descriptor */
413
/* For inter-frame gap, the number is for this frame and next frame */
414
/* For MLME rate, we will fix as 2Mb to match other vendor's implement */
415
/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */
417
/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */
420
if (pMacEntry == NULL) {
421
RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
422
FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
423
(SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID, 0,
424
(u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
425
IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
427
/* dont use low rate to send QoS Null data frame */
428
RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
429
bInsertTimestamp, FALSE, bAckRequired, FALSE,
431
(SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
432
pMacEntry->MaxHTPhyMode.field.MCS, 0,
433
(u8)pMacEntry->MaxHTPhyMode.field.MCS,
434
IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
437
/* Now do hardware-depened kick out. */
438
HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
440
/* Make sure to release MGMT ring resource */
442
RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
443
return NDIS_STATUS_SUCCESS;
446
/********************************************************************************
448
New DeQueue Procedures.
450
********************************************************************************/
452
#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
454
if (bIntContext == FALSE) \
455
RTMP_IRQ_LOCK((lock), IrqFlags); \
458
#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
460
if (bIntContext == FALSE) \
461
RTMP_IRQ_UNLOCK((lock), IrqFlags); \
465
========================================================================
466
Tx Path design algorithm:
467
Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
468
Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
469
Classification Rule=>
470
Multicast: (*addr1 & 0x01) == 0x01
471
Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
472
11N Rate : If peer support HT
473
(1).AMPDU -- If TXBA is negotiated.
474
(2).AMSDU -- If AMSDU is capable for both peer and ourself.
475
*). AMSDU can embedded in a AMPDU, but now we didn't support it.
476
(3).Normal -- Other packets which send as 11n rate.
478
B/G Rate : If peer is b/g only.
479
(1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
480
(2).Normal -- Other packets which send as b/g rate.
482
The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
484
Classified Packet Handle Rule=>
486
No ACK, //pTxBlk->bAckRequired = FALSE;
487
No WMM, //pTxBlk->bWMM = FALSE;
488
No piggyback, //pTxBlk->bPiggyBack = FALSE;
489
Force LowRate, //pTxBlk->bForceLowRate = TRUE;
490
Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
491
the same policy to handle it.
492
Force LowRate, //pTxBlk->bForceLowRate = TRUE;
495
No piggyback, //pTxBlk->bPiggyBack = FALSE;
507
========================================================================
509
static u8 TxPktClassification(struct rt_rtmp_adapter *pAd, void *pPacket)
511
u8 TxFrameType = TX_UNKOWN_FRAME;
513
struct rt_mac_table_entry *pMacEntry = NULL;
514
BOOLEAN bHTRate = FALSE;
516
Wcid = RTMP_GET_PACKET_WCID(pPacket);
517
if (Wcid == MCAST_WCID) { /* Handle for RA is Broadcast/Multicast Address. */
518
return TX_MCAST_FRAME;
520
/* Handle for unicast packets */
521
pMacEntry = &pAd->MacTab.Content[Wcid];
522
if (RTMP_GET_PACKET_LOWRATE(pPacket)) { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame */
523
TxFrameType = TX_LEGACY_FRAME;
524
} else if (IS_HT_RATE(pMacEntry)) { /* it's a 11n capable packet */
526
/* Depends on HTPhyMode to check if the peer support the HTRate transmission. */
527
/* Currently didn't support A-MSDU embedded in A-MPDU */
529
if (RTMP_GET_PACKET_MOREDATA(pPacket)
530
|| (pMacEntry->PsMode == PWR_SAVE))
531
TxFrameType = TX_LEGACY_FRAME;
532
else if ((pMacEntry->
533
TXBAbitmap & (1 << (RTMP_GET_PACKET_UP(pPacket)))) !=
535
return TX_AMPDU_FRAME;
536
else if (CLIENT_STATUS_TEST_FLAG
537
(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
538
return TX_AMSDU_FRAME;
540
TxFrameType = TX_LEGACY_FRAME;
541
} else { /* it's a legacy b/g packet. */
542
if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) && (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* if peer support Ralink Aggregation, we use it. */
543
TxFrameType = TX_RALINK_FRAME;
545
TxFrameType = TX_LEGACY_FRAME;
549
/* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU. */
550
if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
551
&& (TxFrameType == TX_LEGACY_FRAME))
552
TxFrameType = TX_FRAG_FRAME;
557
BOOLEAN RTMP_FillTxBlkInfo(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
559
struct rt_packet_info PacketInfo;
561
struct rt_mac_table_entry *pMacEntry = NULL;
563
pPacket = pTxBlk->pPacket;
564
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader,
567
pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
568
pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
569
pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
570
pTxBlk->FrameGap = IFS_HTTXOP; /* ASIC determine Frame Gap */
572
if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
573
TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
575
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
577
/* Default to clear this flag */
578
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
580
if (pTxBlk->Wcid == MCAST_WCID) {
581
pTxBlk->pMacEntry = NULL;
584
&pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
587
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode. */
588
/*TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate); */
589
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
590
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
591
if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
592
TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
596
pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
597
pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
599
pMacEntry = pTxBlk->pMacEntry;
601
/* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK. */
602
if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
603
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
605
TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
607
if ((pAd->OpMode == OPMODE_STA) &&
609
(RX_FILTER_TEST_FLAG(pAd, fRX_FILTER_ACCEPT_PROMISCUOUS))) {
610
if (pAd->CommonCfg.PSPXlink)
611
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
617
/* If support WMM, enable it. */
618
if (OPSTATUS_TEST_FLAG
619
(pAd, fOP_STATUS_WMM_INUSED)
620
&& CLIENT_STATUS_TEST_FLAG(pMacEntry,
621
fCLIENT_STATUS_WMM_CAPABLE))
622
TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
624
/* if (pAd->StaCfg.bAutoTxRateSwitch) */
625
/* TX_BLK_SET_FLAG(pTxBlk, fTX_AutoRateSwitch); */
629
if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) {
630
if ((RTMP_GET_PACKET_LOWRATE(pPacket)) || ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))) { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. */
632
&pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
634
/* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it??? */
635
if (IS_HT_STA(pTxBlk->pMacEntry) &&
636
(CLIENT_STATUS_TEST_FLAG
637
(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET))
638
&& ((pAd->CommonCfg.bRdg == TRUE)
639
&& CLIENT_STATUS_TEST_FLAG(pMacEntry,
640
fCLIENT_STATUS_RDG_CAPABLE)))
642
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
643
TX_BLK_SET_FLAG(pTxBlk,
648
if ((IS_HT_RATE(pMacEntry) == FALSE) && (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE))) { /* Currently piggy-back only support when peer is operate in b/g mode. */
649
TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
652
if (RTMP_GET_PACKET_MOREDATA(pPacket)) {
653
TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
655
} else if (pTxBlk->TxFrameType == TX_FRAG_FRAME) {
656
TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
659
pMacEntry->DebugTxCount++;
665
BOOLEAN CanDoAggregateTransmit(struct rt_rtmp_adapter *pAd,
666
char * pPacket, struct rt_tx_blk *pTxBlk)
669
/*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType)); */
671
if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
674
if (RTMP_GET_PACKET_DHCP(pPacket) ||
675
RTMP_GET_PACKET_EAPOL(pPacket) || RTMP_GET_PACKET_WAI(pPacket))
678
if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) && ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket)) > (RX_BUFFER_AGGRESIZE - 100))) { /* For AMSDU, allow the packets with total length < max-amsdu size */
682
if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) && (pTxBlk->TxPacketList.Number == 2)) { /* For RALINK-Aggregation, allow two frames in one batch. */
686
if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) /* must be unicast to AP */
694
========================================================================
697
To do the enqueue operation and extract the first item of waiting
698
list. If a number of available shared memory segments could meet
699
the request of extracted item, the extracted item will be fragmented
700
into shared memory segments.
703
pAd Pointer to our adapter
704
pQueue Pointer to Waiting Queue
709
IRQL = DISPATCH_LEVEL
713
========================================================================
715
void RTMPDeQueuePacket(struct rt_rtmp_adapter *pAd, IN BOOLEAN bIntContext, u8 QIdx, /* BulkOutPipeId */
718
struct rt_queue_entry *pEntry = NULL;
720
int Status = NDIS_STATUS_SUCCESS;
722
struct rt_queue_header *pQueue;
723
unsigned long FreeNumber[NUM_OF_TX_RING];
724
u8 QueIdx, sQIdx, eQIdx;
725
unsigned long IrqFlags = 0;
726
BOOLEAN hasTxDesc = FALSE;
727
struct rt_tx_blk TxBlk;
728
struct rt_tx_blk *pTxBlk;
730
if (QIdx == NUM_OF_TX_RING) {
732
eQIdx = 3; /* 4 ACs, start from 0. */
734
sQIdx = eQIdx = QIdx;
737
for (QueIdx = sQIdx; QueIdx <= eQIdx; QueIdx++) {
740
RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
745
(fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
746
fRTMP_ADAPTER_RADIO_OFF |
747
fRTMP_ADAPTER_RESET_IN_PROGRESS |
748
fRTMP_ADAPTER_HALT_IN_PROGRESS |
749
fRTMP_ADAPTER_NIC_NOT_EXIST)))) {
750
RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
754
if (Count >= Max_Tx_Packets)
757
DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
758
if (&pAd->TxSwQueue[QueIdx] == NULL) {
759
DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
764
FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
766
if (FreeNumber[QueIdx] <= 5) {
767
/* free Tx(QueIdx) resources */
768
RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
770
GET_TXRING_FREENO(pAd, QueIdx);
772
#endif /* RTMP_MAC_PCI // */
774
/* probe the Queue Head */
775
pQueue = &pAd->TxSwQueue[QueIdx];
776
pEntry = pQueue->Head;
777
if (pEntry == NULL) {
778
DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
784
NdisZeroMemory((u8 *)pTxBlk, sizeof(struct rt_tx_blk));
785
/*InitializeQueueHeader(&pTxBlk->TxPacketList); // Didn't need it because we already memzero it. */
786
pTxBlk->QueIdx = QueIdx;
788
pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
790
/* Early check to make sure we have enoguh Tx Resource. */
792
RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk,
796
pAd->PrivateInfo.TxRingFullCnt++;
798
DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext,
804
pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
805
pEntry = RemoveHeadQueue(pQueue);
806
pTxBlk->TotalFrameNum++;
807
pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
808
pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
809
pTxBlk->pPacket = pPacket;
810
InsertTailQueue(&pTxBlk->TxPacketList,
811
PACKET_TO_QUEUE_ENTRY(pPacket));
813
if (pTxBlk->TxFrameType == TX_RALINK_FRAME
814
|| pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
815
/* Enhance SW Aggregation Mechanism */
816
if (NEED_QUEUE_BACK_FOR_AGG
817
(pAd, QueIdx, FreeNumber[QueIdx],
818
pTxBlk->TxFrameType)) {
819
InsertHeadQueue(pQueue,
820
PACKET_TO_QUEUE_ENTRY
822
DEQUEUE_UNLOCK(&pAd->irq_lock,
823
bIntContext, IrqFlags);
828
pEntry = pQueue->Head;
832
/* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation. */
833
pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
835
GET_TXRING_FREENO(pAd, QueIdx);
837
RTMP_HAS_ENOUGH_FREE_DESC(pAd,
842
if ((hasTxDesc == FALSE)
844
(CanDoAggregateTransmit
845
(pAd, pPacket, pTxBlk) == FALSE))
848
/*Remove the packet from the TxSwQueue and insert into pTxBlk */
849
pEntry = RemoveHeadQueue(pQueue);
851
pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
852
pTxBlk->TotalFrameNum++;
853
pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary */
854
pTxBlk->TotalFrameLen +=
855
GET_OS_PKT_LEN(pPacket);
856
InsertTailQueue(&pTxBlk->TxPacketList,
857
PACKET_TO_QUEUE_ENTRY
861
if (pTxBlk->TxPacketList.Number == 1)
862
pTxBlk->TxFrameType = TX_LEGACY_FRAME;
865
DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
866
#endif /* RTMP_MAC_USB // */
867
Count += pTxBlk->TxPacketList.Number;
869
/* Do HardTransmit now. */
870
Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
873
DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
874
/* static rate also need NICUpdateFifoStaCounters() function. */
875
/*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
876
NICUpdateFifoStaCounters(pAd);
877
#endif /* RTMP_MAC_PCI // */
881
RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
885
RTUSBKickBulkOut(pAd);
886
#endif /* RTMP_MAC_USB // */
892
========================================================================
895
Calculates the duration which is required to transmit out frames
896
with given size and specified rate.
899
pAd Pointer to our adapter
901
Size Frame size in units of byte
904
Duration number in units of usec
907
IRQL = DISPATCH_LEVEL
911
========================================================================
913
u16 RTMPCalcDuration(struct rt_rtmp_adapter *pAd, u8 Rate, unsigned long Size)
915
unsigned long Duration = 0;
917
if (Rate < RATE_FIRST_OFDM_RATE) /* CCK */
920
&& OPSTATUS_TEST_FLAG(pAd,
921
fOP_STATUS_SHORT_PREAMBLE_INUSED))
922
Duration = 96; /* 72+24 preamble+plcp */
924
Duration = 192; /* 144+48 preamble+plcp */
926
Duration += (u16)((Size << 4) / RateIdTo500Kbps[Rate]);
927
if ((Size << 4) % RateIdTo500Kbps[Rate])
929
} else if (Rate <= RATE_LAST_OFDM_RATE) /* OFDM rates */
931
Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
933
4 * (u16)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
934
if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
936
} else /*mimo rate */
938
Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension */
941
return (u16)Duration;
945
========================================================================
948
Calculates the duration which is required to transmit out frames
949
with given size and specified rate.
952
pTxWI Pointer to head of each MPDU to HW.
953
Ack Setting for Ack requirement bit
954
Fragment Setting for Fragment bit
955
RetryMode Setting for retry mode
956
Ifs Setting for IFS gap
957
Rate Setting for transmit rate
958
Service Setting for service
960
TxPreamble Short or Long preamble when using CCK rates
961
QueIdx - 0-3, according to 802.11e/d4.4 June/2003
967
IRQL = DISPATCH_LEVEL
969
See also : BASmartHardTransmit() !
971
========================================================================
973
void RTMPWriteTxWI(struct rt_rtmp_adapter *pAd, struct rt_txwi * pOutTxWI, IN BOOLEAN FRAG, IN BOOLEAN CFACK, IN BOOLEAN InsTimestamp, IN BOOLEAN AMPDU, IN BOOLEAN Ack, IN BOOLEAN NSeq, /* HW new a sequence. */
976
unsigned long Length,
981
IN BOOLEAN CfAck, IN HTTRANSMIT_SETTING * pTransmit)
983
struct rt_mac_table_entry *pMac = NULL;
985
struct rt_txwi * pTxWI;
987
if (WCID < MAX_LEN_OF_MAC_TABLE)
988
pMac = &pAd->MacTab.Content[WCID];
991
/* Always use Long preamble before verifiation short preamble functionality works well. */
992
/* Todo: remove the following line if short preamble functionality works */
994
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
995
NdisZeroMemory(&TxWI, TXWI_SIZE);
1000
pTxWI->CFACK = CFACK;
1001
pTxWI->TS = InsTimestamp;
1002
pTxWI->AMPDU = AMPDU;
1004
pTxWI->txop = Txopmode;
1007
/* John tune the performace with Intel Client in 20 MHz performance */
1008
BASize = pAd->CommonCfg.TxBASize;
1009
if (pAd->MACVersion == 0x28720200) {
1016
pTxWI->BAWinSize = BASize;
1017
pTxWI->ShortGI = pTransmit->field.ShortGI;
1018
pTxWI->STBC = pTransmit->field.STBC;
1020
pTxWI->WirelessCliID = WCID;
1021
pTxWI->MPDUtotalByteCount = Length;
1022
pTxWI->PacketId = PID;
1024
/* If CCK or OFDM, BW must be 20 */
1026
(pTransmit->field.MODE <=
1027
MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1029
pTxWI->MCS = pTransmit->field.MCS;
1030
pTxWI->PHYMODE = pTransmit->field.MODE;
1031
pTxWI->CFACK = CfAck;
1034
if (pAd->CommonCfg.bMIMOPSEnable) {
1035
if ((pMac->MmpsMode == MMPS_DYNAMIC)
1036
&& (pTransmit->field.MCS > 7)) {
1037
/* Dynamic MIMO Power Save Mode */
1039
} else if (pMac->MmpsMode == MMPS_STATIC) {
1040
/* Static MIMO Power Save Mode */
1041
if (pTransmit->field.MODE >= MODE_HTMIX
1042
&& pTransmit->field.MCS > 7) {
1048
/*pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0; */
1049
if (pMac->bIAmBadAtheros
1050
&& (pMac->WepStatus != Ndis802_11WEPDisabled)) {
1051
pTxWI->MpduDensity = 7;
1053
pTxWI->MpduDensity = pMac->MpduDensity;
1057
pTxWI->PacketId = pTxWI->MCS;
1058
NdisMoveMemory(pOutTxWI, &TxWI, sizeof(struct rt_txwi));
1061
void RTMPWriteTxWI_Data(struct rt_rtmp_adapter *pAd,
1062
struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1064
HTTRANSMIT_SETTING *pTransmit;
1065
struct rt_mac_table_entry *pMacEntry;
1070
pTransmit = pTxBlk->pTransmit;
1071
pMacEntry = pTxBlk->pMacEntry;
1074
/* Always use Long preamble before verifiation short preamble functionality works well. */
1075
/* Todo: remove the following line if short preamble functionality works */
1077
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1078
NdisZeroMemory(pTxWI, TXWI_SIZE);
1080
pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
1081
pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
1082
pTxWI->txop = pTxBlk->FrameGap;
1084
pTxWI->WirelessCliID = pTxBlk->Wcid;
1086
pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1087
pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
1089
/* If CCK or OFDM, BW must be 20 */
1091
(pTransmit->field.MODE <=
1092
MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1093
pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
1095
/* John tune the performace with Intel Client in 20 MHz performance */
1096
BASize = pAd->CommonCfg.TxBASize;
1097
if ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry)) {
1098
u8 RABAOriIdx = 0; /*The RA's BA Originator table index. */
1101
pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
1102
BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
1105
pTxWI->TxBF = pTransmit->field.TxBF;
1106
pTxWI->BAWinSize = BASize;
1107
pTxWI->ShortGI = pTransmit->field.ShortGI;
1108
pTxWI->STBC = pTransmit->field.STBC;
1110
pTxWI->MCS = pTransmit->field.MCS;
1111
pTxWI->PHYMODE = pTransmit->field.MODE;
1114
if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1115
&& (pTransmit->field.MCS > 7)) {
1116
/* Dynamic MIMO Power Save Mode */
1118
} else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1119
/* Static MIMO Power Save Mode */
1120
if (pTransmit->field.MODE >= MODE_HTMIX
1121
&& pTransmit->field.MCS > 7) {
1127
if (pMacEntry->bIAmBadAtheros
1128
&& (pMacEntry->WepStatus != Ndis802_11WEPDisabled)) {
1129
pTxWI->MpduDensity = 7;
1131
pTxWI->MpduDensity = pMacEntry->MpduDensity;
1135
/* for rate adapation */
1136
pTxWI->PacketId = pTxWI->MCS;
1139
void RTMPWriteTxWI_Cache(struct rt_rtmp_adapter *pAd,
1140
struct rt_txwi * pTxWI, struct rt_tx_blk *pTxBlk)
1142
PHTTRANSMIT_SETTING /*pTxHTPhyMode, */ pTransmit;
1143
struct rt_mac_table_entry *pMacEntry;
1148
pMacEntry = pTxBlk->pMacEntry;
1149
pTransmit = pTxBlk->pTransmit;
1151
/*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
1152
/*if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pMacEntry)) */
1153
/*if (TX_BLK_TEST_FLAG(pTxBlk, fTX_AutoRateSwitch)) */
1154
if (pMacEntry->bAutoTxRateSwitch) {
1155
pTxWI->txop = IFS_HTTXOP;
1157
/* If CCK or OFDM, BW must be 20 */
1159
(pTransmit->field.MODE <=
1160
MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
1161
pTxWI->ShortGI = pTransmit->field.ShortGI;
1162
pTxWI->STBC = pTransmit->field.STBC;
1164
pTxWI->MCS = pTransmit->field.MCS;
1165
pTxWI->PHYMODE = pTransmit->field.MODE;
1167
/* set PID for TxRateSwitching */
1168
pTxWI->PacketId = pTransmit->field.MCS;
1171
pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE : FALSE);
1174
if (pAd->CommonCfg.bMIMOPSEnable) {
1175
/* MIMO Power Save Mode */
1176
if ((pMacEntry->MmpsMode == MMPS_DYNAMIC)
1177
&& (pTransmit->field.MCS > 7)) {
1178
/* Dynamic MIMO Power Save Mode */
1180
} else if (pMacEntry->MmpsMode == MMPS_STATIC) {
1181
/* Static MIMO Power Save Mode */
1182
if ((pTransmit->field.MODE >= MODE_HTMIX)
1183
&& (pTransmit->field.MCS > 7)) {
1190
pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1194
/* should be called only when - */
1195
/* 1. MEADIA_CONNECTED */
1196
/* 2. AGGREGATION_IN_USED */
1197
/* 3. Fragmentation not in used */
1198
/* 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible */
1199
BOOLEAN TxFrameIsAggregatible(struct rt_rtmp_adapter *pAd,
1200
u8 *pPrevAddr1, u8 *p8023hdr)
1203
/* can't aggregate EAPOL (802.1x) frame */
1204
if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
1207
/* can't aggregate multicast/broadcast frame */
1208
if (p8023hdr[0] & 0x01)
1211
if (INFRA_ON(pAd)) /* must be unicast to AP */
1213
else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) /* unicast to same STA */
1220
========================================================================
1222
Routine Description:
1223
Check the MSDU Aggregation policy
1224
1.HT aggregation is A-MSDU
1225
2.legaacy rate aggregation is software aggregation by Ralink.
1233
========================================================================
1235
BOOLEAN PeerIsAggreOn(struct rt_rtmp_adapter *pAd,
1236
unsigned long TxRate, struct rt_mac_table_entry *pMacEntry)
1238
unsigned long AFlags =
1239
(fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
1241
if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags)) {
1242
if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) {
1245
#ifdef AGGREGATION_SUPPORT
1246
if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))) { /* legacy Ralink Aggregation support */
1249
#endif /* AGGREGATION_SUPPORT // */
1257
========================================================================
1259
Routine Description:
1260
Check and fine the packet waiting in SW queue with highest priority
1263
pAd Pointer to our adapter
1266
pQueue Pointer to Waiting Queue
1268
IRQL = DISPATCH_LEVEL
1272
========================================================================
1274
struct rt_queue_header *RTMPCheckTxSwQueue(struct rt_rtmp_adapter *pAd, u8 *pQueIdx)
1277
unsigned long Number;
1278
/* 2004-11-15 to be removed. test aggregation only */
1279
/* if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) && (*pNumber < 2)) */
1282
Number = pAd->TxSwQueue[QID_AC_BK].Number
1283
+ pAd->TxSwQueue[QID_AC_BE].Number
1284
+ pAd->TxSwQueue[QID_AC_VI].Number
1285
+ pAd->TxSwQueue[QID_AC_VO].Number;
1287
if (pAd->TxSwQueue[QID_AC_VO].Head != NULL) {
1288
*pQueIdx = QID_AC_VO;
1289
return (&pAd->TxSwQueue[QID_AC_VO]);
1290
} else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL) {
1291
*pQueIdx = QID_AC_VI;
1292
return (&pAd->TxSwQueue[QID_AC_VI]);
1293
} else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL) {
1294
*pQueIdx = QID_AC_BE;
1295
return (&pAd->TxSwQueue[QID_AC_BE]);
1296
} else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL) {
1297
*pQueIdx = QID_AC_BK;
1298
return (&pAd->TxSwQueue[QID_AC_BK]);
1300
/* No packet pending in Tx Sw queue */
1301
*pQueIdx = QID_AC_BK;
1307
========================================================================
1309
Routine Description:
1310
Suspend MSDU transmission
1313
pAd Pointer to our adapter
1320
========================================================================
1322
void RTMPSuspendMsduTransmission(struct rt_rtmp_adapter *pAd)
1324
DBGPRINT(RT_DEBUG_TRACE, ("SCANNING, suspend MSDU transmission ...\n"));
1327
/* Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and */
1328
/* use Lowbound as R66 value on ScanNextChannel(...) */
1330
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66,
1331
&pAd->BbpTuning.R66CurrentValue);
1333
/* set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning) */
1334
/*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x26 + GET_LNA_GAIN(pAd))); */
1335
RTMPSetAGCInitValue(pAd, BW_20);
1337
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1338
/*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); // abort all TX rings */
1342
========================================================================
1344
Routine Description:
1345
Resume MSDU transmission
1348
pAd Pointer to our adapter
1353
IRQL = DISPATCH_LEVEL
1357
========================================================================
1359
void RTMPResumeMsduTransmission(struct rt_rtmp_adapter *pAd)
1363
DBGPRINT(RT_DEBUG_TRACE, ("SCAN done, resume MSDU transmission ...\n"));
1365
/* After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value */
1366
/* R66 should not be 0 */
1367
if (pAd->BbpTuning.R66CurrentValue == 0) {
1368
pAd->BbpTuning.R66CurrentValue = 0x38;
1369
DBGPRINT_ERR("RTMPResumeMsduTransmission, R66CurrentValue=0...\n");
1372
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66,
1373
pAd->BbpTuning.R66CurrentValue);
1375
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1376
/* sample, for IRQ LOCK to SEM LOCK */
1377
/* IrqState = pAd->irq_disabled; */
1379
/* RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); */
1381
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
1384
u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
1386
u8 *pData, unsigned long DataSize)
1390
struct rt_header_802_3 * pAMSDUsubheader;
1394
u8 *pPayload, *pDA, *pSA, *pRemovedLLCSNAP;
1399
while (DataSize > LENGTH_802_3) {
1403
/*hex_dump("subheader", pData, 64); */
1404
pAMSDUsubheader = (struct rt_header_802_3 *) pData;
1405
/*pData += LENGTH_802_3; */
1407
pAMSDUsubheader->Octet[1] +
1408
(pAMSDUsubheader->Octet[0] << 8);
1409
SubFrameSize = PayloadSize + LENGTH_802_3;
1411
if ((DataSize < SubFrameSize) || (PayloadSize > 1518)) {
1414
/*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize)); */
1416
pPayload = pData + LENGTH_802_3;
1418
pSA = pData + MAC_ADDR_LEN;
1420
/* convert to 802.3 header */
1421
CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize,
1424
if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E)) {
1425
/* avoid local heap overflow, use dyanamic allocation */
1426
struct rt_mlme_queue_elem *Elem =
1427
kmalloc(sizeof(struct rt_mlme_queue_elem),
1431
(LENGTH_802_11 + LENGTH_802_1_H),
1432
pPayload, PayloadSize);
1434
LENGTH_802_11 + LENGTH_802_1_H +
1436
/*WpaEAPOLKeyAction(pAd, Elem); */
1437
REPORT_MGMT_FRAME_TO_MLME(pAd, BSSID_WCID,
1439
Elem->MsgLen, 0, 0, 0,
1446
if (pRemovedLLCSNAP) {
1447
pPayload -= LENGTH_802_3;
1448
PayloadSize += LENGTH_802_3;
1449
NdisMoveMemory(pPayload, &Header802_3[0],
1454
pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
1456
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket,
1461
/* A-MSDU has padding to multiple of 4 including subframe header. */
1462
/* align SubFrameSize up to multiple of 4 */
1463
SubFrameSize = (SubFrameSize + 3) & (~0x3);
1465
if (SubFrameSize > 1528 || SubFrameSize < 32) {
1469
if (DataSize > SubFrameSize) {
1470
pData += SubFrameSize;
1471
DataSize -= SubFrameSize;
1478
/* finally release original rx packet */
1479
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
1484
u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
1490
pData = (u8 *)GET_OS_PKT_DATAPTR(pPacket);
1491
DataSize = (u16)GET_OS_PKT_LEN(pPacket);
1493
nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
1499
==========================================================================
1501
Look up the MAC address in the MAC table. Return NULL if not found.
1503
pEntry - pointer to the MAC entry; NULL is not found
1504
==========================================================================
1506
struct rt_mac_table_entry *MacTableLookup(struct rt_rtmp_adapter *pAd, u8 *pAddr)
1508
unsigned long HashIdx;
1509
struct rt_mac_table_entry *pEntry = NULL;
1511
HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1512
pEntry = pAd->MacTab.Hash[HashIdx];
1515
&& (pEntry->ValidAsCLI || pEntry->ValidAsWDS
1516
|| pEntry->ValidAsApCli || pEntry->ValidAsMesh)) {
1517
if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1520
pEntry = pEntry->pNext;
1526
struct rt_mac_table_entry *MacTableInsertEntry(struct rt_rtmp_adapter *pAd,
1528
u8 apidx, IN BOOLEAN CleanAll)
1532
struct rt_mac_table_entry *pEntry = NULL, *pCurrEntry;
1534
/* unsigned long addr; */
1536
/* if FULL, return */
1537
if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
1542
if (pAd->StaCfg.BssType == BSS_INFRA)
1545
/* allocate one MAC entry */
1546
NdisAcquireSpinLock(&pAd->MacTabLock);
1547
for (i = FirstWcid; i < MAX_LEN_OF_MAC_TABLE; i++) /* skip entry#0 so that "entry index == AID" for fast lookup */
1549
/* pick up the first available vacancy */
1550
if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
1551
(pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
1552
(pAd->MacTab.Content[i].ValidAsApCli == FALSE) &&
1553
(pAd->MacTab.Content[i].ValidAsMesh == FALSE)
1555
pEntry = &pAd->MacTab.Content[i];
1556
if (CleanAll == TRUE) {
1557
pEntry->MaxSupportedRate = RATE_11;
1558
pEntry->CurrTxRate = RATE_11;
1559
NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1560
pEntry->PairwiseKey.KeyLen = 0;
1561
pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1565
pEntry->ValidAsCLI = TRUE;
1566
pEntry->ValidAsWDS = FALSE;
1567
pEntry->ValidAsApCli = FALSE;
1568
pEntry->ValidAsMesh = FALSE;
1569
pEntry->ValidAsDls = FALSE;
1573
pEntry->bIAmBadAtheros = FALSE;
1575
pEntry->CMTimerRunning = FALSE;
1576
pEntry->EnqueueEapolStartTimerRunning =
1577
EAPOL_START_DISABLE;
1578
pEntry->RSNIE_Len = 0;
1579
NdisZeroMemory(pEntry->R_Counter,
1580
sizeof(pEntry->R_Counter));
1581
pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
1583
if (pEntry->ValidAsMesh)
1585
(apidx - MIN_NET_DEVICE_FOR_MESH);
1586
else if (pEntry->ValidAsApCli)
1588
(apidx - MIN_NET_DEVICE_FOR_APCLI);
1589
else if (pEntry->ValidAsWDS)
1591
(apidx - MIN_NET_DEVICE_FOR_WDS);
1593
pEntry->apidx = apidx;
1597
pEntry->AuthMode = pAd->StaCfg.AuthMode;
1599
pAd->StaCfg.WepStatus;
1600
pEntry->PrivacyFilter =
1601
Ndis802_11PrivFilterAcceptAll;
1603
AsicRemovePairwiseKeyEntry(pAd,
1607
#endif /* RTMP_MAC_PCI // */
1611
pEntry->GTKState = REKEY_NEGOTIATING;
1612
pEntry->PairwiseKey.KeyLen = 0;
1613
pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
1614
pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1616
pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
1617
COPY_MAC_ADDR(pEntry->Addr, pAddr);
1618
pEntry->Sst = SST_NOT_AUTH;
1619
pEntry->AuthState = AS_NOT_AUTH;
1620
pEntry->Aid = (u16)i; /*0; */
1621
pEntry->CapabilityInfo = 0;
1622
pEntry->PsMode = PWR_ACTIVE;
1623
pEntry->PsQIdleCount = 0;
1624
pEntry->NoDataIdleCount = 0;
1625
pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT;
1626
pEntry->ContinueTxFailCnt = 0;
1627
InitializeQueueHeader(&pEntry->PsQueue);
1630
/* Add this entry into ASIC RX WCID search table */
1631
RTMP_STA_ENTRY_ADD(pAd, pEntry);
1633
DBGPRINT(RT_DEBUG_TRACE,
1634
("MacTableInsertEntry - allocate entry #%d, Total= %d\n",
1635
i, pAd->MacTab.Size));
1640
/* add this MAC entry into HASH table */
1642
HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1643
if (pAd->MacTab.Hash[HashIdx] == NULL) {
1644
pAd->MacTab.Hash[HashIdx] = pEntry;
1646
pCurrEntry = pAd->MacTab.Hash[HashIdx];
1647
while (pCurrEntry->pNext != NULL)
1648
pCurrEntry = pCurrEntry->pNext;
1649
pCurrEntry->pNext = pEntry;
1653
NdisReleaseSpinLock(&pAd->MacTabLock);
1658
==========================================================================
1660
Delete a specified client from MAC table
1661
==========================================================================
1663
BOOLEAN MacTableDeleteEntry(struct rt_rtmp_adapter *pAd,
1664
u16 wcid, u8 *pAddr)
1667
struct rt_mac_table_entry *pEntry, *pPrevEntry, *pProbeEntry;
1669
/*u16 offset; // unused variable */
1670
/*u8 j; // unused variable */
1672
if (wcid >= MAX_LEN_OF_MAC_TABLE)
1675
NdisAcquireSpinLock(&pAd->MacTabLock);
1677
HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
1678
/*pEntry = pAd->MacTab.Hash[HashIdx]; */
1679
pEntry = &pAd->MacTab.Content[wcid];
1682
&& (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS
1683
|| pEntry->ValidAsMesh)) {
1684
if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr)) {
1686
/* Delete this entry from ASIC on-chip WCID Table */
1687
RTMP_STA_ENTRY_MAC_RESET(pAd, wcid);
1689
/* free resources of BA */
1690
BASessionTearDownALL(pAd, pEntry->Aid);
1693
pProbeEntry = pAd->MacTab.Hash[HashIdx];
1694
ASSERT(pProbeEntry);
1696
/* update Hash list */
1698
if (pProbeEntry == pEntry) {
1699
if (pPrevEntry == NULL) {
1700
pAd->MacTab.Hash[HashIdx] =
1709
pPrevEntry = pProbeEntry;
1710
pProbeEntry = pProbeEntry->pNext;
1711
} while (pProbeEntry);
1714
ASSERT(pProbeEntry != NULL);
1716
RTMP_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
1718
if (pEntry->EnqueueEapolStartTimerRunning !=
1719
EAPOL_START_DISABLE) {
1720
RTMPCancelTimer(&pEntry->
1721
EnqueueStartForPSKTimer,
1723
pEntry->EnqueueEapolStartTimerRunning =
1724
EAPOL_START_DISABLE;
1727
NdisZeroMemory(pEntry, sizeof(struct rt_mac_table_entry));
1729
DBGPRINT(RT_DEBUG_TRACE,
1730
("MacTableDeleteEntry1 - Total= %d\n",
1733
DBGPRINT(RT_DEBUG_OFF,
1734
("\n%s: Impossible Wcid = %d !\n",
1739
NdisReleaseSpinLock(&pAd->MacTabLock);
1741
/*Reset operating mode when no Sta. */
1742
if (pAd->MacTab.Size == 0) {
1743
pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
1744
RTMP_UPDATE_PROTECT(pAd); /* edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */
1751
==========================================================================
1753
This routine reset the entire MAC table. All packets pending in
1754
the power-saving queues are freed here.
1755
==========================================================================
1757
void MacTableReset(struct rt_rtmp_adapter *pAd)
1761
DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
1762
/*NdisAcquireSpinLock(&pAd->MacTabLock); */
1764
for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
1766
RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1767
#endif /* RTMP_MAC_PCI // */
1768
if (pAd->MacTab.Content[i].ValidAsCLI == TRUE) {
1770
/* free resources of BA */
1771
BASessionTearDownALL(pAd, i);
1773
pAd->MacTab.Content[i].ValidAsCLI = FALSE;
1776
NdisZeroMemory(pAd->MacTab.Content[i].Addr, 6);
1777
RTMP_STA_ENTRY_MAC_RESET(pAd, i);
1778
#endif /* RTMP_MAC_USB // */
1780
/*AsicDelWcidTab(pAd, i); */
1788
==========================================================================
1791
IRQL = DISPATCH_LEVEL
1793
==========================================================================
1795
void AssocParmFill(struct rt_rtmp_adapter *pAd,
1796
struct rt_mlme_assoc_req *AssocReq,
1799
unsigned long Timeout, u16 ListenIntv)
1801
COPY_MAC_ADDR(AssocReq->Addr, pAddr);
1802
/* Add mask to support 802.11b mode only */
1803
AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request */
1804
AssocReq->Timeout = Timeout;
1805
AssocReq->ListenIntv = ListenIntv;
1809
==========================================================================
1812
IRQL = DISPATCH_LEVEL
1814
==========================================================================
1816
void DisassocParmFill(struct rt_rtmp_adapter *pAd,
1817
struct rt_mlme_disassoc_req *DisassocReq,
1818
u8 *pAddr, u16 Reason)
1820
COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
1821
DisassocReq->Reason = Reason;
1825
========================================================================
1827
Routine Description:
1828
Check the out going frame, if this is an DHCP or ARP datagram
1829
will be duplicate another frame at low data rate transmit.
1832
pAd Pointer to our adapter
1833
pPacket Pointer to outgoing Ndis frame
1836
TRUE To be duplicate at Low data rate transmit. (1mb)
1839
IRQL = DISPATCH_LEVEL
1843
MAC header + IP Header + UDP Header
1847
00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
1849
16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
1852
port 0x43 means Bootstrap Protocol, server.
1853
Port 0x44 means Bootstrap Protocol, client.
1855
========================================================================
1858
BOOLEAN RTMPCheckDHCPFrame(struct rt_rtmp_adapter *pAd, void *pPacket)
1860
struct rt_packet_info PacketInfo;
1861
unsigned long NumberOfBytesRead = 0;
1862
unsigned long CurrentOffset = 0;
1863
void *pVirtualAddress = NULL;
1864
u32 NdisBufferLength;
1867
u8 ByteOffset36 = 0;
1868
u8 ByteOffset38 = 0;
1869
BOOLEAN ReadFirstParm = TRUE;
1871
RTMP_QueryPacketInfo(pPacket, &PacketInfo, (u8 **) & pVirtualAddress,
1874
NumberOfBytesRead += NdisBufferLength;
1875
pSrc = (u8 *)pVirtualAddress;
1876
Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
1879
/* Check DHCP & BOOTP protocol */
1881
while (NumberOfBytesRead <= PacketInfo.TotalPacketLength) {
1882
if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE)) {
1884
35 - (NumberOfBytesRead - NdisBufferLength);
1885
ByteOffset36 = *(pSrc + CurrentOffset);
1886
ReadFirstParm = FALSE;
1889
if (NumberOfBytesRead >= 37) {
1891
37 - (NumberOfBytesRead - NdisBufferLength);
1892
ByteOffset38 = *(pSrc + CurrentOffset);
1899
/* Check for DHCP & BOOTP protocol */
1900
if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43)) {
1902
/* 2054 (hex 0806) for ARP datagrams */
1903
/* if this packet is not ARP datagrams, then do nothing */
1904
/* ARP datagrams will also be duplicate at 1mb broadcast frames */
1906
if (Protocol != 0x0806)
1913
BOOLEAN RTMPCheckEtherType(struct rt_rtmp_adapter *pAd, void *pPacket)
1919
u16 srcPort, dstPort;
1920
BOOLEAN status = TRUE;
1922
pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
1923
pktLen = GET_OS_PKT_LEN(pPacket);
1927
RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
1929
/* get Ethernet protocol field */
1930
TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
1932
pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header. */
1934
if (TypeLen <= 1500) { /* 802.3, 802.3 LLC */
1936
DestMAC(6) + SrcMAC(6) + Lenght(2) +
1937
DSAP(1) + SSAP(1) + Control(1) +
1938
if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
1939
=> + SNAP (5, OriginationID(3) + etherType(2))
1941
if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA
1942
&& pSrcBuf[2] == 0x03) {
1943
Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 6,
1945
RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
1946
TypeLen = (u16)((Byte0 << 8) + Byte1);
1947
pSrcBuf += 8; /* Skip this LLC/SNAP header */
1949
/*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it. */
1952
/* If it's a VLAN packet, get the real Type/Length field. */
1953
if (TypeLen == 0x8100) {
1954
/* 0x8100 means VLAN packets */
1956
/* Dest. MAC Address (6-bytes) +
1957
Source MAC Address (6-bytes) +
1958
Length/Type = 802.1Q Tag Type (2-byte) +
1959
Tag Control Information (2-bytes) +
1960
Length / Type (2-bytes) +
1961
data payload (0-n bytes) +
1963
Frame Check Sequence (4-bytes) */
1965
RTMP_SET_PACKET_VLAN(pPacket, 1);
1966
Sniff2BytesFromNdisBuffer((char *)pSrcBuf, 2, &Byte0,
1968
TypeLen = (u16)((Byte0 << 8) + Byte1);
1970
pSrcBuf += 4; /* Skip the VLAN Header. */
1976
ASSERT((pktLen > 34));
1977
if (*(pSrcBuf + 9) == 0x11) { /* udp packet */
1978
ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header */
1980
pSrcBuf += 20; /* Skip the IP header */
1982
OS_NTOHS(get_unaligned
1983
((u16 *)(pSrcBuf)));
1985
OS_NTOHS(get_unaligned
1986
((u16 *)(pSrcBuf + 2)));
1988
if ((srcPort == 0x44 && dstPort == 0x43) || (srcPort == 0x43 && dstPort == 0x44)) { /*It's a BOOTP/DHCP packet */
1989
RTMP_SET_PACKET_DHCP(pPacket, 1);
1997
RTMP_SET_PACKET_DHCP(pPacket, 1);
2003
RTMP_SET_PACKET_EAPOL(pPacket, 1);
2015
void Update_Rssi_Sample(struct rt_rtmp_adapter *pAd,
2016
struct rt_rssi_sample *pRssi, struct rt_rxwi * pRxWI)
2018
char rssi0 = pRxWI->RSSI0;
2019
char rssi1 = pRxWI->RSSI1;
2020
char rssi2 = pRxWI->RSSI2;
2023
pRssi->LastRssi0 = ConvertToRssi(pAd, (char)rssi0, RSSI_0);
2025
(pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
2026
pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
2030
pRssi->LastRssi1 = ConvertToRssi(pAd, (char)rssi1, RSSI_1);
2032
(pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
2033
pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
2037
pRssi->LastRssi2 = ConvertToRssi(pAd, (char)rssi2, RSSI_2);
2039
(pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
2040
pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
2044
/* Normal legacy Rx packet indication */
2045
void Indicate_Legacy_Packet(struct rt_rtmp_adapter *pAd,
2046
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2048
void *pRxPacket = pRxBlk->pRxPacket;
2049
u8 Header802_3[LENGTH_802_3];
2051
/* 1. get 802.3 Header */
2053
/* a. pointer pRxBlk->pData to payload */
2054
/* b. modify pRxBlk->DataSize */
2055
RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2057
if (pRxBlk->DataSize > MAX_RX_PKT_LEN) {
2059
/* release packet */
2060
RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2064
STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
2067
if (pAd->CommonCfg.bDisableReordering == 0) {
2068
struct rt_ba_rec_entry *pBAEntry;
2069
unsigned long Now32;
2070
u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
2071
u8 TID = pRxBlk->pRxWI->TID;
2074
#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
2076
if (Wcid < MAX_LEN_OF_MAC_TABLE) {
2077
Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
2079
pBAEntry = &pAd->BATable.BARecEntry[Idx];
2080
/* update last rx time */
2081
NdisGetSystemUpTime(&Now32);
2082
if ((pBAEntry->list.qlen > 0) &&
2083
RTMP_TIME_AFTER((unsigned long)Now32,
2084
(unsigned long)(pBAEntry->
2087
(REORDERING_PACKET_TIMEOUT)))
2089
DBGPRINT(RT_DEBUG_OFF,
2090
("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
2093
pRxBlk->RxD.AMPDU));
2094
hex_dump("Dump the legacy Packet:",
2095
GET_OS_PKT_DATAPTR(pRxBlk->
2098
ba_flush_reordering_timeout_mpdus(pAd,
2105
#endif /* RTMP_MAC_USB // */
2107
wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2110
/* pass this 802.3 packet to upper layer or forward this packet to WM directly */
2112
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
2115
/* Normal, AMPDU or AMSDU */
2116
void CmmRxnonRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2117
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2119
if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
2120
&& (pAd->CommonCfg.bDisableReordering == 0)) {
2121
Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2123
if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
2125
Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
2127
Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
2132
void CmmRxRalinkFrameIndicate(struct rt_rtmp_adapter *pAd,
2133
struct rt_mac_table_entry *pEntry,
2134
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2136
u8 Header802_3[LENGTH_802_3];
2138
u16 Payload1Size, Payload2Size;
2140
void *pPacket2 = NULL;
2142
Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData + 1) << 8);
2144
if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize)) {
2145
/* skip two byte MSDU2 len */
2147
pRxBlk->DataSize -= 2;
2149
/* release packet */
2150
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2151
NDIS_STATUS_FAILURE);
2155
/* get 802.3 Header and remove LLC */
2156
RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
2158
ASSERT(pRxBlk->pRxPacket);
2160
/* Ralink Aggregation frame */
2161
pAd->RalinkCounters.OneSecRxAggregationCount++;
2162
Payload1Size = pRxBlk->DataSize - Msdu2Size;
2163
Payload2Size = Msdu2Size - LENGTH_802_3;
2165
pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
2168
duplicate_pkt(pAd, (pData2 - LENGTH_802_3), LENGTH_802_3, pData2,
2169
Payload2Size, FromWhichBSSID);
2172
/* release packet */
2173
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2174
NDIS_STATUS_FAILURE);
2177
/* update payload size of 1st packet */
2178
pRxBlk->DataSize = Payload1Size;
2179
wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
2181
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket,
2185
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
2189
#define RESET_FRAGFRAME(_fragFrame) \
2191
_fragFrame.RxSize = 0; \
2192
_fragFrame.Sequence = 0; \
2193
_fragFrame.LastFrag = 0; \
2194
_fragFrame.Flags = 0; \
2197
void *RTMPDeFragmentDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
2199
struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
2200
void *pRxPacket = pRxBlk->pRxPacket;
2201
u8 *pData = pRxBlk->pData;
2202
u16 DataSize = pRxBlk->DataSize;
2203
void *pRetPacket = NULL;
2204
u8 *pFragBuffer = NULL;
2205
BOOLEAN bReassDone = FALSE;
2210
HeaderRoom = pData - (u8 *) pHeader;
2212
/* Re-assemble the fragmented packets */
2213
if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt */
2215
/* the first pkt of fragment, record it. */
2216
if (pHeader->FC.MoreFrag) {
2217
ASSERT(pAd->FragFrame.pFragPacket);
2219
GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2220
pAd->FragFrame.RxSize = DataSize + HeaderRoom;
2221
NdisMoveMemory(pFragBuffer, pHeader,
2222
pAd->FragFrame.RxSize);
2223
pAd->FragFrame.Sequence = pHeader->Sequence;
2224
pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0 */
2225
ASSERT(pAd->FragFrame.LastFrag == 0);
2226
goto done; /* end of processing this frame */
2228
} else /*Middle & End of fragment */
2230
if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
2231
(pHeader->Frag != (pAd->FragFrame.LastFrag + 1))) {
2232
/* Fragment is not the same sequence or out of fragment number order */
2233
/* Reset Fragment control blk */
2234
RESET_FRAGFRAME(pAd->FragFrame);
2235
DBGPRINT(RT_DEBUG_ERROR,
2236
("Fragment is not the same sequence or out of fragment number order.\n"));
2237
goto done; /* give up this frame */
2238
} else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE) {
2239
/* Fragment frame is too large, it exeeds the maximum frame size. */
2240
/* Reset Fragment control blk */
2241
RESET_FRAGFRAME(pAd->FragFrame);
2242
DBGPRINT(RT_DEBUG_ERROR,
2243
("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2244
goto done; /* give up this frame */
2247
/* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment. */
2248
/* In this case, we will dropt it. */
2250
if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H))) {
2251
DBGPRINT(RT_DEBUG_ERROR,
2252
("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n",
2253
pHeader->Sequence, pHeader->Frag));
2254
goto done; /* give up this frame */
2257
pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
2259
/* concatenate this fragment into the re-assembly buffer */
2260
NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData,
2262
pAd->FragFrame.RxSize += DataSize;
2263
pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number */
2266
if (pHeader->FC.MoreFrag == FALSE) {
2272
/* always release rx fragmented packet */
2273
RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
2275
/* return defragmented packet if packet is reassembled completely */
2276
/* otherwise return NULL */
2278
void *pNewFragPacket;
2280
/* allocate a new packet buffer for fragment */
2282
RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
2283
if (pNewFragPacket) {
2285
pRetPacket = pAd->FragFrame.pFragPacket;
2286
pAd->FragFrame.pFragPacket = pNewFragPacket;
2288
(struct rt_header_802_11 *) GET_OS_PKT_DATAPTR(pRetPacket);
2289
pRxBlk->pData = (u8 *) pRxBlk->pHeader + HeaderRoom;
2290
pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
2291
pRxBlk->pRxPacket = pRetPacket;
2293
RESET_FRAGFRAME(pAd->FragFrame);
2300
void Indicate_AMSDU_Packet(struct rt_rtmp_adapter *pAd,
2301
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2305
update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
2306
RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
2308
deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData,
2312
void Indicate_EAPOL_Packet(struct rt_rtmp_adapter *pAd,
2313
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
2315
struct rt_mac_table_entry *pEntry = NULL;
2318
pEntry = &pAd->MacTab.Content[BSSID_WCID];
2319
STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
2323
if (pEntry == NULL) {
2324
DBGPRINT(RT_DEBUG_WARN,
2325
("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2326
/* release packet */
2327
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
2328
NDIS_STATUS_FAILURE);
2333
#define BCN_TBTT_OFFSET 64 /*defer 64 us */
2334
void ReSyncBeaconTime(struct rt_rtmp_adapter *pAd)
2339
Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
2341
pAd->TbttTickCount++;
2344
/* The updated BeaconInterval Value will affect Beacon Interval after two TBTT */
2345
/* beacasue the original BeaconInterval had been loaded into next TBTT_TIMER */
2347
if (Offset == (BCN_TBTT_OFFSET - 2)) {
2348
BCN_TIME_CFG_STRUC csr;
2349
RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2350
csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1; /* ASIC register in units of 1/16 TU = 64us */
2351
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
2353
if (Offset == (BCN_TBTT_OFFSET - 1)) {
2354
BCN_TIME_CFG_STRUC csr;
2356
RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
2357
csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU */
2358
RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);