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 #define MAX_TX_IN_TBTT (16)
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 */
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
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
56 UCHAR 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
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
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"};
69 UCHAR default_cwmin
[]={CW_MIN_IN_BITS
, CW_MIN_IN_BITS
, CW_MIN_IN_BITS
-1, CW_MIN_IN_BITS
-2};
70 UCHAR default_sta_aifsn
[]={3,7,2,2};
72 UCHAR MapUserPriorityToAccessCategory
[8] = {QID_AC_BE
, QID_AC_BK
, QID_AC_BK
, QID_AC_BE
, QID_AC_VI
, QID_AC_VI
, QID_AC_VO
, QID_AC_VO
};
76 ========================================================================
79 API for MLME to transmit management frame to AP (BSS Mode)
80 or station (IBSS Mode)
83 pAd Pointer to our adapter
84 pData Pointer to the outgoing 802.11 frame
85 Length Size of outgoing management frame
97 ========================================================================
99 NDIS_STATUS
MiniportMMRequest(
100 IN PRTMP_ADAPTER pAd
,
105 PNDIS_PACKET pPacket
;
106 NDIS_STATUS Status
= NDIS_STATUS_SUCCESS
;
109 unsigned long IrqFlags
= 0;
112 UCHAR rtmpHwHdr
[TXINFO_SIZE
+ TXWI_SIZE
]; //RTMP_HW_HDR_LEN];
114 ASSERT(Length
<= MGMT_DMA_BUFFER_SIZE
);
120 IrqState
= pAd
->irq_disabled
;
123 if ((pAd
->MACVersion
== 0x28600100) && (!IrqState
))
124 RTMP_IRQ_LOCK(&pAd
->irq_lock
, IrqFlags
);
128 // Reset is in progress, stop immediately
129 if ( RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_RESET_IN_PROGRESS
) ||
130 RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
)||
131 !RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_START_UP
))
133 Status
= NDIS_STATUS_FAILURE
;
137 // Check Free priority queue
138 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
141 if (pAd
->MACVersion
== 0x28600100)
143 FreeNum
= GET_TXRING_FREENO(pAd
, QueIdx
);
147 FreeNum
= GET_MGMTRING_FREENO(pAd
);
152 // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
153 NdisZeroMemory(&rtmpHwHdr
, (TXINFO_SIZE
+ TXWI_SIZE
));
154 Status
= RTMPAllocateNdisPacket(pAd
, &pPacket
, (PUCHAR
)&rtmpHwHdr
, (TXINFO_SIZE
+ TXWI_SIZE
), pData
, Length
);
155 if (Status
!= NDIS_STATUS_SUCCESS
)
157 DBGPRINT(RT_DEBUG_WARN
, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
161 //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
162 //pAd->CommonCfg.MlmeRate = RATE_2;
165 Status
= MlmeHardTransmit(pAd
, QueIdx
, pPacket
);
166 if (Status
!= NDIS_STATUS_SUCCESS
)
167 RTMPFreeNdisPacket(pAd
, pPacket
);
171 pAd
->RalinkCounters
.MgmtRingFullCount
++;
172 DBGPRINT(RT_DEBUG_ERROR
, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
173 QueIdx
, pAd
->RalinkCounters
.MgmtRingFullCount
));
180 if ((pAd
->MACVersion
== 0x28600100) && (!IrqState
))
181 RTMP_IRQ_UNLOCK(&pAd
->irq_lock
, IrqFlags
);
187 NDIS_STATUS
MiniportMMRequestUnlock(
188 IN PRTMP_ADAPTER pAd
,
193 PNDIS_PACKET pPacket
;
194 NDIS_STATUS Status
= NDIS_STATUS_SUCCESS
;
201 ASSERT(Length
<= MGMT_DMA_BUFFER_SIZE
);
205 // Reset is in progress, stop immediately
206 if ( RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_RESET_IN_PROGRESS
) ||
207 RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
)||
208 !RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_START_UP
))
210 Status
= NDIS_STATUS_FAILURE
;
214 // Check Free priority queue
215 // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
217 if (pAd
->MACVersion
== 0x28600100)
219 FreeNum
= GET_TXRING_FREENO(pAd
, QueIdx
);
220 SW_TX_IDX
= pAd
->TxRing
[QueIdx
].TxCpuIdx
;
221 pTxD
= (PTXD_STRUC
) pAd
->TxRing
[QueIdx
].Cell
[SW_TX_IDX
].AllocVa
;
225 FreeNum
= GET_MGMTRING_FREENO(pAd
);
226 SW_TX_IDX
= pAd
->MgmtRing
.TxCpuIdx
;
227 pTxD
= (PTXD_STRUC
) pAd
->MgmtRing
.Cell
[SW_TX_IDX
].AllocVa
;
231 NdisZeroMemory(&TXWI
, TXWI_SIZE
);
232 Status
= RTMPAllocateNdisPacket(pAd
, &pPacket
, (PUCHAR
)&TXWI
, TXWI_SIZE
, pData
, Length
);
233 if (Status
!= NDIS_STATUS_SUCCESS
)
235 DBGPRINT(RT_DEBUG_WARN
, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
239 Status
= MlmeHardTransmit(pAd
, QueIdx
, pPacket
);
240 if (Status
!= NDIS_STATUS_SUCCESS
)
241 RTMPFreeNdisPacket(pAd
, pPacket
);
245 pAd
->RalinkCounters
.MgmtRingFullCount
++;
246 DBGPRINT(RT_DEBUG_ERROR
, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx
));
257 ========================================================================
260 Copy frame from waiting queue into relative ring buffer and set
261 appropriate ASIC register to kick hardware transmit function
264 pAd Pointer to our adapter
265 pBuffer Pointer to memory of outgoing frame
266 Length Size of outgoing management frame
274 IRQL = DISPATCH_LEVEL
278 ========================================================================
280 NDIS_STATUS
MlmeHardTransmit(
281 IN PRTMP_ADAPTER pAd
,
283 IN PNDIS_PACKET pPacket
)
285 if (pAd
->CommonCfg
.RadarDetect
.RDMode
!= RD_NORMAL_MODE
)
287 return NDIS_STATUS_FAILURE
;
291 if ( pAd
->MACVersion
== 0x28600100 )
292 return MlmeHardTransmitTxRing(pAd
,QueIdx
,pPacket
);
295 return MlmeHardTransmitMgmtRing(pAd
,QueIdx
,pPacket
);
300 NDIS_STATUS
MlmeHardTransmitTxRing(
301 IN PRTMP_ADAPTER pAd
,
303 IN PNDIS_PACKET pPacket
)
305 PACKET_INFO PacketInfo
;
309 PHEADER_802_11 pHeader_802_11
;
310 BOOLEAN bAckRequired
, bInsertTimestamp
;
313 ULONG SwIdx
= pAd
->TxRing
[QueIdx
].TxCpuIdx
;
314 PTXWI_STRUC pFirstTxWI
;
316 MAC_TABLE_ENTRY
*pMacEntry
= NULL
;
319 RTMP_QueryPacketInfo(pPacket
, &PacketInfo
, &pSrcBufVA
, &SrcBufLen
);
321 if (pSrcBufVA
== NULL
)
323 // The buffer shouldn't be NULL
324 return NDIS_STATUS_FAILURE
;
327 // Make sure MGMT ring resource won't be used by other threads
328 //NdisAcquireSpinLock(&pAd->TxRingLock);
330 FreeNum
= GET_TXRING_FREENO(pAd
, QueIdx
);
334 //NdisReleaseSpinLock(&pAd->TxRingLock);
335 return NDIS_STATUS_FAILURE
;
338 SwIdx
= pAd
->TxRing
[QueIdx
].TxCpuIdx
;
340 pTxD
= (PTXD_STRUC
) pAd
->TxRing
[QueIdx
].Cell
[SwIdx
].AllocVa
;
342 if (pAd
->TxRing
[QueIdx
].Cell
[SwIdx
].pNdisPacket
)
344 printk("MlmeHardTransmit Error\n");
345 return NDIS_STATUS_FAILURE
;
348 // outgoing frame always wakeup PHY to prevent frame lost
349 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
350 AsicForceWakeup(pAd
, FROM_TX
);
352 pFirstTxWI
=(PTXWI_STRUC
)pSrcBufVA
;
354 pHeader_802_11
= (PHEADER_802_11
) (pSrcBufVA
+ TXWI_SIZE
);
355 if (pHeader_802_11
->Addr1
[0] & 0x01)
357 MlmeRate
= pAd
->CommonCfg
.BasicMlmeRate
;
361 MlmeRate
= pAd
->CommonCfg
.MlmeRate
;
364 if ((pHeader_802_11
->FC
.Type
== BTYPE_DATA
) &&
365 (pHeader_802_11
->FC
.SubType
== SUBTYPE_QOS_NULL
))
367 pMacEntry
= MacTableLookup(pAd
, pHeader_802_11
->Addr1
);
370 // Verify Mlme rate for a / g bands.
371 if ((pAd
->LatchRfRegs
.Channel
> 14) && (MlmeRate
< RATE_6
)) // 11A band
375 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
376 // Snice it's been set to 0 while on MgtMacHeaderInit
377 // By the way this will cause frame to be send on PWR_SAVE failed.
380 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
382 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
383 if (pHeader_802_11
->FC
.Type
!= BTYPE_DATA
)
385 if ((pHeader_802_11
->FC
.SubType
== SUBTYPE_PROBE_REQ
) || !(pAd
->CommonCfg
.bAPSDCapable
&& pAd
->CommonCfg
.APEdcaParm
.bAPSDCapable
))
387 pHeader_802_11
->FC
.PwrMgmt
= PWR_ACTIVE
;
391 pHeader_802_11
->FC
.PwrMgmt
= pAd
->CommonCfg
.bAPSDForcePowerSave
;
395 bInsertTimestamp
= FALSE
;
396 if (pHeader_802_11
->FC
.Type
== BTYPE_CNTL
) // must be PS-POLL
398 bAckRequired
= FALSE
;
400 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
402 if (pHeader_802_11
->Addr1
[0] & 0x01) // MULTICAST, BROADCAST
404 bAckRequired
= FALSE
;
405 pHeader_802_11
->Duration
= 0;
410 pHeader_802_11
->Duration
= RTMPCalcDuration(pAd
, MlmeRate
, 14);
411 if (pHeader_802_11
->FC
.SubType
== SUBTYPE_PROBE_RSP
)
413 bInsertTimestamp
= TRUE
;
417 pHeader_802_11
->Sequence
= pAd
->Sequence
++;
418 if (pAd
->Sequence
> 0xfff)
420 // Before radar detection done, mgmt frame can not be sent but probe req
421 // Because we need to use probe req to trigger driver to send probe req in passive scan
422 if ((pHeader_802_11
->FC
.SubType
!= SUBTYPE_PROBE_REQ
)
423 && (pAd
->CommonCfg
.bIEEE80211H
== 1)
424 && (pAd
->CommonCfg
.RadarDetect
.RDMode
!= RD_NORMAL_MODE
))
426 DBGPRINT(RT_DEBUG_ERROR
,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
427 return (NDIS_STATUS_FAILURE
);
431 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
432 // should always has only one ohysical buffer, and the whole frame size equals
433 // to the first scatter buffer size
436 // Initialize TX Descriptor
437 // For inter-frame gap, the number is for this frame and next frame
438 // For MLME rate, we will fix as 2Mb to match other vendor's implement
440 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
441 // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
442 if (pMacEntry
== NULL
)
444 RTMPWriteTxWI(pAd
, pFirstTxWI
, FALSE
, FALSE
, bInsertTimestamp
, FALSE
, bAckRequired
, FALSE
,
445 0, RESERVED_WCID
, (SrcBufLen
- TXWI_SIZE
), PID_MGMT
, 0, (UCHAR
)pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
, IFS_BACKOFF
, FALSE
, &pAd
->CommonCfg
.MlmeTransmit
);
449 RTMPWriteTxWI(pAd
, pFirstTxWI
, FALSE
, FALSE
,
450 bInsertTimestamp
, FALSE
, bAckRequired
, FALSE
,
451 0, pMacEntry
->Aid
, (SrcBufLen
- TXWI_SIZE
),
452 pMacEntry
->MaxHTPhyMode
.field
.MCS
, 0,
453 (UCHAR
)pMacEntry
->MaxHTPhyMode
.field
.MCS
,
454 IFS_BACKOFF
, FALSE
, &pMacEntry
->MaxHTPhyMode
);
457 pAd
->TxRing
[QueIdx
].Cell
[SwIdx
].pNdisPacket
= pPacket
;
458 pAd
->TxRing
[QueIdx
].Cell
[SwIdx
].pNextNdisPacket
= NULL
;
460 SrcBufPA
= PCI_MAP_SINGLE(pAd
, pSrcBufVA
, SrcBufLen
, 0, PCI_DMA_TODEVICE
);
463 RTMPWriteTxDescriptor(pAd
, pTxD
, TRUE
, FIFO_EDCA
);
466 pTxD
->SDLen0
= SrcBufLen
;
468 pTxD
->SDPtr0
= SrcBufPA
;
471 pAd
->RalinkCounters
.KickTxCount
++;
472 pAd
->RalinkCounters
.OneSecTxDoneCount
++;
474 // Increase TX_CTX_IDX, but write to register later.
475 INC_RING_INDEX(pAd
->TxRing
[QueIdx
].TxCpuIdx
, TX_RING_SIZE
);
477 RTMP_IO_WRITE32(pAd
, TX_CTX_IDX0
+ QueIdx
*0x10, pAd
->TxRing
[QueIdx
].TxCpuIdx
);
479 return NDIS_STATUS_SUCCESS
;
483 NDIS_STATUS
MlmeHardTransmitMgmtRing(
484 IN PRTMP_ADAPTER pAd
,
486 IN PNDIS_PACKET pPacket
)
488 PACKET_INFO PacketInfo
;
491 PHEADER_802_11 pHeader_802_11
;
492 BOOLEAN bAckRequired
, bInsertTimestamp
;
494 PTXWI_STRUC pFirstTxWI
;
495 MAC_TABLE_ENTRY
*pMacEntry
= NULL
;
497 RTMP_QueryPacketInfo(pPacket
, &PacketInfo
, &pSrcBufVA
, &SrcBufLen
);
498 RTMP_SEM_LOCK(&pAd
->MgmtRingLock
);
501 if (pSrcBufVA
== NULL
)
503 RTMP_SEM_UNLOCK(&pAd
->MgmtRingLock
);
504 return NDIS_STATUS_FAILURE
;
507 // outgoing frame always wakeup PHY to prevent frame lost
508 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
510 AsicForceWakeup(pAd
, FROM_TX
);
513 AsicForceWakeup(pAd
, TRUE
);
516 pFirstTxWI
= (PTXWI_STRUC
)(pSrcBufVA
+ TXINFO_SIZE
);
517 pHeader_802_11
= (PHEADER_802_11
) (pSrcBufVA
+ TXINFO_SIZE
+ TXWI_SIZE
); //TXWI_SIZE);
519 if (pHeader_802_11
->Addr1
[0] & 0x01)
521 MlmeRate
= pAd
->CommonCfg
.BasicMlmeRate
;
525 MlmeRate
= pAd
->CommonCfg
.MlmeRate
;
528 // Verify Mlme rate for a / g bands.
529 if ((pAd
->LatchRfRegs
.Channel
> 14) && (MlmeRate
< RATE_6
)) // 11A band
532 if ((pHeader_802_11
->FC
.Type
== BTYPE_DATA
) &&
533 (pHeader_802_11
->FC
.SubType
== SUBTYPE_QOS_NULL
))
535 pMacEntry
= MacTableLookup(pAd
, pHeader_802_11
->Addr1
);
539 // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
540 if (pAd
->CommonCfg
.PhyMode
== PHY_11ABG_MIXED
541 || pAd
->CommonCfg
.PhyMode
== PHY_11ABGN_MIXED
544 if (pAd
->LatchRfRegs
.Channel
> 14)
545 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= 1;
547 pAd
->CommonCfg
.MlmeTransmit
.field
.MODE
= 0;
552 // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
553 // Snice it's been set to 0 while on MgtMacHeaderInit
554 // By the way this will cause frame to be send on PWR_SAVE failed.
556 // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
558 // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
560 // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
561 if ((pHeader_802_11
->FC
.Type
!= BTYPE_DATA
) && (pHeader_802_11
->FC
.Type
!= BTYPE_CNTL
))
563 if ((pAd
->StaCfg
.Psm
== PWR_SAVE
) &&
564 (pHeader_802_11
->FC
.SubType
== SUBTYPE_ACTION
))
565 pHeader_802_11
->FC
.PwrMgmt
= PWR_SAVE
;
567 pHeader_802_11
->FC
.PwrMgmt
= PWR_ACTIVE
;
570 bInsertTimestamp
= FALSE
;
571 if (pHeader_802_11
->FC
.Type
== BTYPE_CNTL
) // must be PS-POLL
573 //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
574 if ((pAd
->OpMode
== OPMODE_STA
) && (pHeader_802_11
->FC
.SubType
== SUBTYPE_PS_POLL
))
576 pHeader_802_11
->FC
.PwrMgmt
= PWR_SAVE
;
578 bAckRequired
= FALSE
;
580 else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
582 if (pHeader_802_11
->Addr1
[0] & 0x01) // MULTICAST, BROADCAST
584 bAckRequired
= FALSE
;
585 pHeader_802_11
->Duration
= 0;
590 pHeader_802_11
->Duration
= RTMPCalcDuration(pAd
, MlmeRate
, 14);
591 if (pHeader_802_11
->FC
.SubType
== SUBTYPE_PROBE_RSP
)
593 bInsertTimestamp
= TRUE
;
598 pHeader_802_11
->Sequence
= pAd
->Sequence
++;
599 if (pAd
->Sequence
>0xfff)
602 // Before radar detection done, mgmt frame can not be sent but probe req
603 // Because we need to use probe req to trigger driver to send probe req in passive scan
604 if ((pHeader_802_11
->FC
.SubType
!= SUBTYPE_PROBE_REQ
)
605 && (pAd
->CommonCfg
.bIEEE80211H
== 1)
606 && (pAd
->CommonCfg
.RadarDetect
.RDMode
!= RD_NORMAL_MODE
))
608 DBGPRINT(RT_DEBUG_ERROR
,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
609 RTMP_SEM_UNLOCK(&pAd
->MgmtRingLock
);
610 return (NDIS_STATUS_FAILURE
);
614 // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
615 // should always has only one ohysical buffer, and the whole frame size equals
616 // to the first scatter buffer size
619 // Initialize TX Descriptor
620 // For inter-frame gap, the number is for this frame and next frame
621 // For MLME rate, we will fix as 2Mb to match other vendor's implement
623 // management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
624 if (pMacEntry
== NULL
)
626 RTMPWriteTxWI(pAd
, pFirstTxWI
, FALSE
, FALSE
, bInsertTimestamp
, FALSE
, bAckRequired
, FALSE
,
627 0, RESERVED_WCID
, (SrcBufLen
- TXINFO_SIZE
- TXWI_SIZE
), PID_MGMT
, 0, (UCHAR
)pAd
->CommonCfg
.MlmeTransmit
.field
.MCS
, IFS_BACKOFF
, FALSE
, &pAd
->CommonCfg
.MlmeTransmit
);
631 RTMPWriteTxWI(pAd
, pFirstTxWI
, FALSE
, FALSE
,
632 bInsertTimestamp
, FALSE
, bAckRequired
, FALSE
,
633 0, pMacEntry
->Aid
, (SrcBufLen
- TXINFO_SIZE
- TXWI_SIZE
),
634 pMacEntry
->MaxHTPhyMode
.field
.MCS
, 0,
635 (UCHAR
)pMacEntry
->MaxHTPhyMode
.field
.MCS
,
636 IFS_BACKOFF
, FALSE
, &pMacEntry
->MaxHTPhyMode
);
639 // Now do hardware-depened kick out.
640 HAL_KickOutMgmtTx(pAd
, QueIdx
, pPacket
, pSrcBufVA
, SrcBufLen
);
642 // Make sure to release MGMT ring resource
643 RTMP_SEM_UNLOCK(&pAd
->MgmtRingLock
);
644 return NDIS_STATUS_SUCCESS
;
648 /********************************************************************************
650 New DeQueue Procedures.
652 ********************************************************************************/
654 #define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
656 if (bIntContext == FALSE) \
657 RTMP_IRQ_LOCK((lock), IrqFlags); \
660 #define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
662 if (bIntContext == FALSE) \
663 RTMP_IRQ_UNLOCK((lock), IrqFlags); \
667 ========================================================================
668 Tx Path design algorithm:
669 Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
670 Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
671 Classification Rule=>
672 Multicast: (*addr1 & 0x01) == 0x01
673 Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
674 11N Rate : If peer support HT
675 (1).AMPDU -- If TXBA is negotiated.
676 (2).AMSDU -- If AMSDU is capable for both peer and ourself.
677 *). AMSDU can embedded in a AMPDU, but now we didn't support it.
678 (3).Normal -- Other packets which send as 11n rate.
680 B/G Rate : If peer is b/g only.
681 (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
682 (2).Normal -- Other packets which send as b/g rate.
684 The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
686 Classified Packet Handle Rule=>
688 No ACK, //pTxBlk->bAckRequired = FALSE;
689 No WMM, //pTxBlk->bWMM = FALSE;
690 No piggyback, //pTxBlk->bPiggyBack = FALSE;
691 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
692 Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
693 the same policy to handle it.
694 Force LowRate, //pTxBlk->bForceLowRate = TRUE;
697 No piggyback, //pTxBlk->bPiggyBack = FALSE;
709 ========================================================================
711 static UCHAR
TxPktClassification(
712 IN RTMP_ADAPTER
*pAd
,
713 IN PNDIS_PACKET pPacket
)
715 UCHAR TxFrameType
= TX_UNKOWN_FRAME
;
717 MAC_TABLE_ENTRY
*pMacEntry
= NULL
;
718 BOOLEAN bHTRate
= FALSE
;
720 Wcid
= RTMP_GET_PACKET_WCID(pPacket
);
721 if (Wcid
== MCAST_WCID
)
722 { // Handle for RA is Broadcast/Multicast Address.
723 return TX_MCAST_FRAME
;
726 // Handle for unicast packets
727 pMacEntry
= &pAd
->MacTab
.Content
[Wcid
];
728 if (RTMP_GET_PACKET_LOWRATE(pPacket
))
729 { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
730 TxFrameType
= TX_LEGACY_FRAME
;
732 else if (IS_HT_RATE(pMacEntry
))
733 { // it's a 11n capable packet
735 // Depends on HTPhyMode to check if the peer support the HTRate transmission.
736 // Currently didn't support A-MSDU embedded in A-MPDU
738 if (RTMP_GET_PACKET_MOREDATA(pPacket
) || (pMacEntry
->PsMode
== PWR_SAVE
))
739 TxFrameType
= TX_LEGACY_FRAME
;
740 #ifdef UAPSD_AP_SUPPORT
741 else if (RTMP_GET_PACKET_EOSP(pPacket
))
742 TxFrameType
= TX_LEGACY_FRAME
;
743 #endif // UAPSD_AP_SUPPORT //
744 else if((pMacEntry
->TXBAbitmap
& (1<<(RTMP_GET_PACKET_UP(pPacket
)))) != 0)
745 return TX_AMPDU_FRAME
;
746 else if(CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_AMSDU_INUSED
))
747 return TX_AMSDU_FRAME
;
749 TxFrameType
= TX_LEGACY_FRAME
;
752 { // it's a legacy b/g packet.
753 if ((CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_AGGREGATION_CAPABLE
) && pAd
->CommonCfg
.bAggregationCapable
) &&
754 (RTMP_GET_PACKET_TXRATE(pPacket
) >= RATE_6
) &&
755 (!(OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_WMM_INUSED
) && CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_WMM_CAPABLE
))))
756 { // if peer support Ralink Aggregation, we use it.
757 TxFrameType
= TX_RALINK_FRAME
;
761 TxFrameType
= TX_LEGACY_FRAME
;
765 // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
766 if ((RTMP_GET_PACKET_FRAGMENTS(pPacket
) > 1) && (TxFrameType
== TX_LEGACY_FRAME
))
767 TxFrameType
= TX_FRAG_FRAME
;
773 BOOLEAN
RTMP_FillTxBlkInfo(
774 IN RTMP_ADAPTER
*pAd
,
777 PACKET_INFO PacketInfo
;
778 PNDIS_PACKET pPacket
;
779 PMAC_TABLE_ENTRY pMacEntry
= NULL
;
781 pPacket
= pTxBlk
->pPacket
;
782 RTMP_QueryPacketInfo(pPacket
, &PacketInfo
, &pTxBlk
->pSrcBufHeader
, &pTxBlk
->SrcBufLen
);
784 pTxBlk
->Wcid
= RTMP_GET_PACKET_WCID(pPacket
);
785 pTxBlk
->apidx
= RTMP_GET_PACKET_IF(pPacket
);
786 pTxBlk
->UserPriority
= RTMP_GET_PACKET_UP(pPacket
);
787 pTxBlk
->FrameGap
= IFS_HTTXOP
; // ASIC determine Frame Gap
789 if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk
->pPacket
))
790 TX_BLK_SET_FLAG(pTxBlk
, fTX_bClearEAPFrame
);
792 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bClearEAPFrame
);
794 // Default to clear this flag
795 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bForceNonQoS
);
798 if (pTxBlk
->Wcid
== MCAST_WCID
)
800 pTxBlk
->pMacEntry
= NULL
;
802 #ifdef MCAST_RATE_SPECIFIC
803 PUCHAR pDA
= GET_OS_PKT_DATAPTR(pPacket
);
804 if (((*pDA
& 0x01) == 0x01) && (*pDA
!= 0xff))
805 pTxBlk
->pTransmit
= &pAd
->CommonCfg
.MCastPhyMode
;
807 #endif // MCAST_RATE_SPECIFIC //
808 pTxBlk
->pTransmit
= &pAd
->MacTab
.Content
[MCAST_WCID
].HTPhyMode
;
811 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bAckRequired
); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
812 //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
813 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bAllowFrag
);
814 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bWMM
);
815 if (RTMP_GET_PACKET_MOREDATA(pPacket
))
817 TX_BLK_SET_FLAG(pTxBlk
, fTX_bMoreData
);
823 pTxBlk
->pMacEntry
= &pAd
->MacTab
.Content
[pTxBlk
->Wcid
];
824 pTxBlk
->pTransmit
= &pTxBlk
->pMacEntry
->HTPhyMode
;
826 pMacEntry
= pTxBlk
->pMacEntry
;
829 // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
830 if (pAd
->CommonCfg
.AckPolicy
[pTxBlk
->QueIdx
] != NORMAL_ACK
)
831 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bAckRequired
);
833 TX_BLK_SET_FLAG(pTxBlk
, fTX_bAckRequired
);
836 // If support WMM, enable it.
838 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_WMM_INUSED
))
841 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_WMM_INUSED
) &&
842 CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_WMM_CAPABLE
))
844 TX_BLK_SET_FLAG(pTxBlk
, fTX_bWMM
);
847 if (pTxBlk
->TxFrameType
== TX_LEGACY_FRAME
)
849 if ( (RTMP_GET_PACKET_LOWRATE(pPacket
)) ||
850 ((pAd
->OpMode
== OPMODE_AP
) && (pMacEntry
->MaxHTPhyMode
.field
.MODE
== MODE_CCK
) && (pMacEntry
->MaxHTPhyMode
.field
.MCS
== RATE_1
)))
851 { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
852 pTxBlk
->pTransmit
= &pAd
->MacTab
.Content
[MCAST_WCID
].HTPhyMode
;
854 // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
855 if (IS_HT_STA(pTxBlk
->pMacEntry
) &&
856 (CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_RALINK_CHIPSET
)) &&
857 ((pAd
->CommonCfg
.bRdg
== TRUE
) && CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_RDG_CAPABLE
)))
859 TX_BLK_CLEAR_FLAG(pTxBlk
, fTX_bWMM
);
860 TX_BLK_SET_FLAG(pTxBlk
, fTX_bForceNonQoS
);
864 if ( (IS_HT_RATE(pMacEntry
) == FALSE
) &&
865 (CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_PIGGYBACK_CAPABLE
)))
866 { // Currently piggy-back only support when peer is operate in b/g mode.
867 TX_BLK_SET_FLAG(pTxBlk
, fTX_bPiggyBack
);
870 if (RTMP_GET_PACKET_MOREDATA(pPacket
))
872 TX_BLK_SET_FLAG(pTxBlk
, fTX_bMoreData
);
874 #ifdef UAPSD_AP_SUPPORT
875 if (RTMP_GET_PACKET_EOSP(pPacket
))
877 TX_BLK_SET_FLAG(pTxBlk
, fTX_bWMM_UAPSD_EOSP
);
879 #endif // UAPSD_AP_SUPPORT //
881 else if (pTxBlk
->TxFrameType
== TX_FRAG_FRAME
)
883 TX_BLK_SET_FLAG(pTxBlk
, fTX_bAllowFrag
);
886 pMacEntry
->DebugTxCount
++;
893 BOOLEAN
CanDoAggregateTransmit(
894 IN RTMP_ADAPTER
*pAd
,
895 IN NDIS_PACKET
*pPacket
,
899 //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
901 if (RTMP_GET_PACKET_WCID(pPacket
) == MCAST_WCID
)
904 if (RTMP_GET_PACKET_DHCP(pPacket
) ||
905 RTMP_GET_PACKET_EAPOL(pPacket
) ||
906 RTMP_GET_PACKET_WAI(pPacket
))
909 if ((pTxBlk
->TxFrameType
== TX_AMSDU_FRAME
) &&
910 ((pTxBlk
->TotalFrameLen
+ GET_OS_PKT_LEN(pPacket
))> (RX_BUFFER_AGGRESIZE
- 100)))
911 { // For AMSDU, allow the packets with total length < max-amsdu size
915 if ((pTxBlk
->TxFrameType
== TX_RALINK_FRAME
) &&
916 (pTxBlk
->TxPacketList
.Number
== 2))
917 { // For RALINK-Aggregation, allow two frames in one batch.
921 if ((INFRA_ON(pAd
)) && (pAd
->OpMode
== OPMODE_STA
)) // must be unicast to AP
929 ========================================================================
932 To do the enqueue operation and extract the first item of waiting
933 list. If a number of available shared memory segments could meet
934 the request of extracted item, the extracted item will be fragmented
935 into shared memory segments.
938 pAd Pointer to our adapter
939 pQueue Pointer to Waiting Queue
944 IRQL = DISPATCH_LEVEL
948 ========================================================================
950 VOID
RTMPDeQueuePacket(
951 IN PRTMP_ADAPTER pAd
,
952 IN BOOLEAN bIntContext
,
953 IN UCHAR QIdx
, /* BulkOutPipeId */
954 IN UCHAR Max_Tx_Packets
)
956 PQUEUE_ENTRY pEntry
= NULL
;
957 PNDIS_PACKET pPacket
;
958 NDIS_STATUS Status
= NDIS_STATUS_SUCCESS
;
960 PQUEUE_HEADER pQueue
;
961 ULONG FreeNumber
[NUM_OF_TX_RING
];
962 UCHAR QueIdx
, sQIdx
, eQIdx
;
963 unsigned long IrqFlags
= 0;
964 BOOLEAN hasTxDesc
= FALSE
;
970 if (QIdx
== NUM_OF_TX_RING
)
973 //PS packets use HCCA queue when dequeue from PS unicast queue (WiFi WPA2 MA9_DT1 for Marvell B STA)
974 eQIdx
= 3; // 4 ACs, start from 0.
978 sQIdx
= eQIdx
= QIdx
;
981 for (QueIdx
=sQIdx
; QueIdx
<= eQIdx
; QueIdx
++)
985 RT28XX_START_DEQUEUE(pAd
, QueIdx
, IrqFlags
);
990 if ((RTMP_TEST_FLAG(pAd
, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
|
991 fRTMP_ADAPTER_RADIO_OFF
|
992 fRTMP_ADAPTER_RESET_IN_PROGRESS
|
993 fRTMP_ADAPTER_HALT_IN_PROGRESS
|
994 fRTMP_ADAPTER_NIC_NOT_EXIST
))))
996 RT28XX_STOP_DEQUEUE(pAd
, QueIdx
, IrqFlags
);
1000 if (Count
>= Max_Tx_Packets
)
1003 DEQUEUE_LOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1004 if (&pAd
->TxSwQueue
[QueIdx
] == NULL
)
1006 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1010 FreeNumber
[QueIdx
] = GET_TXRING_FREENO(pAd
, QueIdx
);
1013 if (FreeNumber
[QueIdx
] <= 5)
1015 // free Tx(QueIdx) resources
1016 RTMPFreeTXDUponTxDmaDone(pAd
, QueIdx
);
1017 FreeNumber
[QueIdx
] = GET_TXRING_FREENO(pAd
, QueIdx
);
1020 // probe the Queue Head
1021 pQueue
= &pAd
->TxSwQueue
[QueIdx
];
1022 if ((pEntry
= pQueue
->Head
) == NULL
)
1024 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1029 NdisZeroMemory((PUCHAR
)pTxBlk
, sizeof(TX_BLK
));
1030 pTxBlk
->QueIdx
= QueIdx
;
1032 pPacket
= QUEUE_ENTRY_TO_PKT(pEntry
);
1034 // Early check to make sure we have enoguh Tx Resource.
1035 hasTxDesc
= RT28XX_HAS_ENOUGH_FREE_DESC(pAd
, pTxBlk
, FreeNumber
[QueIdx
], pPacket
);
1038 pAd
->PrivateInfo
.TxRingFullCnt
++;
1040 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1045 pTxBlk
->TxFrameType
= TxPktClassification(pAd
, pPacket
);
1046 pEntry
= RemoveHeadQueue(pQueue
);
1047 pTxBlk
->TotalFrameNum
++;
1048 pTxBlk
->TotalFragNum
+= RTMP_GET_PACKET_FRAGMENTS(pPacket
); // The real fragment number maybe vary
1049 pTxBlk
->TotalFrameLen
+= GET_OS_PKT_LEN(pPacket
);
1050 pTxBlk
->pPacket
= pPacket
;
1051 InsertTailQueue(&pTxBlk
->TxPacketList
, PACKET_TO_QUEUE_ENTRY(pPacket
));
1053 if (pTxBlk
->TxFrameType
== TX_RALINK_FRAME
|| pTxBlk
->TxFrameType
== TX_AMSDU_FRAME
)
1055 // Enhance SW Aggregation Mechanism
1056 if (NEED_QUEUE_BACK_FOR_AGG(pAd
, QueIdx
, FreeNumber
[QueIdx
], pTxBlk
->TxFrameType
))
1058 InsertHeadQueue(pQueue
, PACKET_TO_QUEUE_ENTRY(pPacket
));
1059 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1064 if((pEntry
= pQueue
->Head
) == NULL
)
1067 // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
1068 pPacket
= QUEUE_ENTRY_TO_PKT(pEntry
);
1069 FreeNumber
[QueIdx
] = GET_TXRING_FREENO(pAd
, QueIdx
);
1070 hasTxDesc
= RT28XX_HAS_ENOUGH_FREE_DESC(pAd
, pTxBlk
, FreeNumber
[QueIdx
], pPacket
);
1071 if ((hasTxDesc
== FALSE
) || (CanDoAggregateTransmit(pAd
, pPacket
, pTxBlk
) == FALSE
))
1074 //Remove the packet from the TxSwQueue and insert into pTxBlk
1075 pEntry
= RemoveHeadQueue(pQueue
);
1077 pPacket
= QUEUE_ENTRY_TO_PKT(pEntry
);
1078 pTxBlk
->TotalFrameNum
++;
1079 pTxBlk
->TotalFragNum
+= RTMP_GET_PACKET_FRAGMENTS(pPacket
); // The real fragment number maybe vary
1080 pTxBlk
->TotalFrameLen
+= GET_OS_PKT_LEN(pPacket
);
1081 InsertTailQueue(&pTxBlk
->TxPacketList
, PACKET_TO_QUEUE_ENTRY(pPacket
));
1084 if (pTxBlk
->TxPacketList
.Number
== 1)
1085 pTxBlk
->TxFrameType
= TX_LEGACY_FRAME
;
1089 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1092 Count
+= pTxBlk
->TxPacketList
.Number
;
1094 // Do HardTransmit now.
1095 Status
= STAHardTransmit(pAd
, pTxBlk
, QueIdx
);
1098 DEQUEUE_UNLOCK(&pAd
->irq_lock
, bIntContext
, IrqFlags
);
1099 // static rate also need NICUpdateFifoStaCounters() function.
1100 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1101 NICUpdateFifoStaCounters(pAd
);
1105 RT28XX_STOP_DEQUEUE(pAd
, QueIdx
, IrqFlags
);
1109 RTUSBKickBulkOut(pAd
);
1117 ========================================================================
1119 Routine Description:
1120 Calculates the duration which is required to transmit out frames
1121 with given size and specified rate.
1124 pAd Pointer to our adapter
1126 Size Frame size in units of byte
1129 Duration number in units of usec
1131 IRQL = PASSIVE_LEVEL
1132 IRQL = DISPATCH_LEVEL
1136 ========================================================================
1138 USHORT
RTMPCalcDuration(
1139 IN PRTMP_ADAPTER pAd
,
1145 if (Rate
< RATE_FIRST_OFDM_RATE
) // CCK
1147 if ((Rate
> RATE_1
) && OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
))
1148 Duration
= 96; // 72+24 preamble+plcp
1150 Duration
= 192; // 144+48 preamble+plcp
1152 Duration
+= (USHORT
)((Size
<< 4) / RateIdTo500Kbps
[Rate
]);
1153 if ((Size
<< 4) % RateIdTo500Kbps
[Rate
])
1156 else if (Rate
<= RATE_LAST_OFDM_RATE
)// OFDM rates
1158 Duration
= 20 + 6; // 16+4 preamble+plcp + Signal Extension
1159 Duration
+= 4 * (USHORT
)((11 + Size
* 4) / RateIdTo500Kbps
[Rate
]);
1160 if ((11 + Size
* 4) % RateIdTo500Kbps
[Rate
])
1165 Duration
= 20 + 6; // 16+4 preamble+plcp + Signal Extension
1168 return (USHORT
)Duration
;
1173 ========================================================================
1175 Routine Description:
1176 Calculates the duration which is required to transmit out frames
1177 with given size and specified rate.
1180 pTxWI Pointer to head of each MPDU to HW.
1181 Ack Setting for Ack requirement bit
1182 Fragment Setting for Fragment bit
1183 RetryMode Setting for retry mode
1184 Ifs Setting for IFS gap
1185 Rate Setting for transmit rate
1186 Service Setting for service
1188 TxPreamble Short or Long preamble when using CCK rates
1189 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1194 IRQL = PASSIVE_LEVEL
1195 IRQL = DISPATCH_LEVEL
1197 See also : BASmartHardTransmit() !!!
1199 ========================================================================
1202 IN PRTMP_ADAPTER pAd
,
1203 IN PTXWI_STRUC pOutTxWI
,
1206 IN BOOLEAN InsTimestamp
,
1209 IN BOOLEAN NSeq
, // HW new a sequence.
1218 IN HTTRANSMIT_SETTING
*pTransmit
)
1220 PMAC_TABLE_ENTRY pMac
= NULL
;
1224 if (WCID
< MAX_LEN_OF_MAC_TABLE
)
1225 pMac
= &pAd
->MacTab
.Content
[WCID
];
1228 // Always use Long preamble before verifiation short preamble functionality works well.
1229 // Todo: remove the following line if short preamble functionality works
1231 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
);
1232 NdisZeroMemory(&TxWI
, TXWI_SIZE
);
1237 pTxWI
->CFACK
= CFACK
;
1238 pTxWI
->TS
= InsTimestamp
;
1239 pTxWI
->AMPDU
= AMPDU
;
1241 pTxWI
->txop
= Txopmode
;
1244 // John tune the performace with Intel Client in 20 MHz performance
1245 BASize
= pAd
->CommonCfg
.TxBASize
;
1249 pTxWI
->BAWinSize
= BASize
;
1250 pTxWI
->ShortGI
= pTransmit
->field
.ShortGI
;
1251 pTxWI
->STBC
= pTransmit
->field
.STBC
;
1253 pTxWI
->WirelessCliID
= WCID
;
1254 pTxWI
->MPDUtotalByteCount
= Length
;
1255 pTxWI
->PacketId
= PID
;
1257 // If CCK or OFDM, BW must be 20
1258 pTxWI
->BW
= (pTransmit
->field
.MODE
<= MODE_OFDM
) ? (BW_20
) : (pTransmit
->field
.BW
);
1260 pTxWI
->MCS
= pTransmit
->field
.MCS
;
1261 pTxWI
->PHYMODE
= pTransmit
->field
.MODE
;
1262 pTxWI
->CFACK
= CfAck
;
1266 if (pAd
->CommonCfg
.bMIMOPSEnable
)
1268 if ((pMac
->MmpsMode
== MMPS_DYNAMIC
) && (pTransmit
->field
.MCS
> 7))
1270 // Dynamic MIMO Power Save Mode
1273 else if (pMac
->MmpsMode
== MMPS_STATIC
)
1275 // Static MIMO Power Save Mode
1276 if (pTransmit
->field
.MODE
>= MODE_HTMIX
&& pTransmit
->field
.MCS
> 7)
1283 //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
1284 if (pMac
->bIAmBadAtheros
&& (pMac
->WepStatus
!= Ndis802_11WEPDisabled
))
1286 pTxWI
->MpduDensity
= 7;
1290 pTxWI
->MpduDensity
= pMac
->MpduDensity
;
1294 pTxWI
->PacketId
= pTxWI
->MCS
;
1295 NdisMoveMemory(pOutTxWI
, &TxWI
, sizeof(TXWI_STRUC
));
1299 VOID
RTMPWriteTxWI_Data(
1300 IN PRTMP_ADAPTER pAd
,
1301 IN OUT PTXWI_STRUC pTxWI
,
1304 HTTRANSMIT_SETTING
*pTransmit
;
1305 PMAC_TABLE_ENTRY pMacEntry
;
1310 pTransmit
= pTxBlk
->pTransmit
;
1311 pMacEntry
= pTxBlk
->pMacEntry
;
1315 // Always use Long preamble before verifiation short preamble functionality works well.
1316 // Todo: remove the following line if short preamble functionality works
1318 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
);
1319 NdisZeroMemory(pTxWI
, TXWI_SIZE
);
1321 pTxWI
->FRAG
= TX_BLK_TEST_FLAG(pTxBlk
, fTX_bAllowFrag
);
1322 pTxWI
->ACK
= TX_BLK_TEST_FLAG(pTxBlk
, fTX_bAckRequired
);
1323 pTxWI
->txop
= pTxBlk
->FrameGap
;
1325 pTxWI
->WirelessCliID
= pTxBlk
->Wcid
;
1327 pTxWI
->MPDUtotalByteCount
= pTxBlk
->MpduHeaderLen
+ pTxBlk
->SrcBufLen
;
1328 pTxWI
->CFACK
= TX_BLK_TEST_FLAG(pTxBlk
, fTX_bPiggyBack
);
1330 // If CCK or OFDM, BW must be 20
1331 pTxWI
->BW
= (pTransmit
->field
.MODE
<= MODE_OFDM
) ? (BW_20
) : (pTransmit
->field
.BW
);
1332 pTxWI
->AMPDU
= ((pTxBlk
->TxFrameType
== TX_AMPDU_FRAME
) ? TRUE
: FALSE
);
1334 // John tune the performace with Intel Client in 20 MHz performance
1335 BASize
= pAd
->CommonCfg
.TxBASize
;
1336 if((pTxBlk
->TxFrameType
== TX_AMPDU_FRAME
) && (pMacEntry
))
1338 UCHAR RABAOriIdx
= 0; //The RA's BA Originator table index.
1340 RABAOriIdx
= pTxBlk
->pMacEntry
->BAOriWcidArray
[pTxBlk
->UserPriority
];
1341 BASize
= pAd
->BATable
.BAOriEntry
[RABAOriIdx
].BAWinSize
;
1344 pTxWI
->TxBF
= pTransmit
->field
.TxBF
;
1345 pTxWI
->BAWinSize
= BASize
;
1346 pTxWI
->ShortGI
= pTransmit
->field
.ShortGI
;
1347 pTxWI
->STBC
= pTransmit
->field
.STBC
;
1349 pTxWI
->MCS
= pTransmit
->field
.MCS
;
1350 pTxWI
->PHYMODE
= pTransmit
->field
.MODE
;
1354 if ((pMacEntry
->MmpsMode
== MMPS_DYNAMIC
) && (pTransmit
->field
.MCS
> 7))
1356 // Dynamic MIMO Power Save Mode
1359 else if (pMacEntry
->MmpsMode
== MMPS_STATIC
)
1361 // Static MIMO Power Save Mode
1362 if (pTransmit
->field
.MODE
>= MODE_HTMIX
&& pTransmit
->field
.MCS
> 7)
1369 if (pMacEntry
->bIAmBadAtheros
&& (pMacEntry
->WepStatus
!= Ndis802_11WEPDisabled
))
1371 pTxWI
->MpduDensity
= 7;
1375 pTxWI
->MpduDensity
= pMacEntry
->MpduDensity
;
1380 // for rate adapation
1381 pTxWI
->PacketId
= pTxWI
->MCS
;
1385 VOID
RTMPWriteTxWI_Cache(
1386 IN PRTMP_ADAPTER pAd
,
1387 IN OUT PTXWI_STRUC pTxWI
,
1390 PHTTRANSMIT_SETTING pTransmit
;
1391 PMAC_TABLE_ENTRY pMacEntry
;
1396 pMacEntry
= pTxBlk
->pMacEntry
;
1397 pTransmit
= pTxBlk
->pTransmit
;
1399 if (pMacEntry
->bAutoTxRateSwitch
)
1401 pTxWI
->txop
= IFS_HTTXOP
;
1403 // If CCK or OFDM, BW must be 20
1404 pTxWI
->BW
= (pTransmit
->field
.MODE
<= MODE_OFDM
) ? (BW_20
) : (pTransmit
->field
.BW
);
1405 pTxWI
->ShortGI
= pTransmit
->field
.ShortGI
;
1406 pTxWI
->STBC
= pTransmit
->field
.STBC
;
1408 pTxWI
->MCS
= pTransmit
->field
.MCS
;
1409 pTxWI
->PHYMODE
= pTransmit
->field
.MODE
;
1411 // set PID for TxRateSwitching
1412 pTxWI
->PacketId
= pTransmit
->field
.MCS
;
1415 pTxWI
->AMPDU
= ((pMacEntry
->NoBADataCountDown
== 0) ? TRUE
: FALSE
);
1418 if (pAd
->CommonCfg
.bMIMOPSEnable
)
1420 // MIMO Power Save Mode
1421 if ((pMacEntry
->MmpsMode
== MMPS_DYNAMIC
) && (pTransmit
->field
.MCS
> 7))
1423 // Dynamic MIMO Power Save Mode
1426 else if (pMacEntry
->MmpsMode
== MMPS_STATIC
)
1428 // Static MIMO Power Save Mode
1429 if ((pTransmit
->field
.MODE
>= MODE_HTMIX
) && (pTransmit
->field
.MCS
> 7))
1438 pTxWI
->MPDUtotalByteCount
= pTxBlk
->MpduHeaderLen
+ pTxBlk
->SrcBufLen
;
1444 ========================================================================
1446 Routine Description:
1447 Calculates the duration which is required to transmit out frames
1448 with given size and specified rate.
1451 pTxD Pointer to transmit descriptor
1452 Ack Setting for Ack requirement bit
1453 Fragment Setting for Fragment bit
1454 RetryMode Setting for retry mode
1455 Ifs Setting for IFS gap
1456 Rate Setting for transmit rate
1457 Service Setting for service
1459 TxPreamble Short or Long preamble when using CCK rates
1460 QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1465 IRQL = PASSIVE_LEVEL
1466 IRQL = DISPATCH_LEVEL
1468 ========================================================================
1470 VOID
RTMPWriteTxDescriptor(
1471 IN PRTMP_ADAPTER pAd
,
1477 // Always use Long preamble before verifiation short preamble functionality works well.
1478 // Todo: remove the following line if short preamble functionality works
1480 OPSTATUS_CLEAR_FLAG(pAd
, fOP_STATUS_SHORT_PREAMBLE_INUSED
);
1482 pTxD
->WIV
= (bWIV
) ? 1: 0;
1483 pTxD
->QSEL
= (QueueSEL
);
1484 if (pAd
->bGenOneHCCA
== TRUE
)
1485 pTxD
->QSEL
= FIFO_HCCA
;
1490 // should be called only when -
1491 // 1. MEADIA_CONNECTED
1492 // 2. AGGREGATION_IN_USED
1493 // 3. Fragmentation not in used
1494 // 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
1495 BOOLEAN
TxFrameIsAggregatible(
1496 IN PRTMP_ADAPTER pAd
,
1497 IN PUCHAR pPrevAddr1
,
1501 // can't aggregate EAPOL (802.1x) frame
1502 if ((p8023hdr
[12] == 0x88) && (p8023hdr
[13] == 0x8e))
1505 // can't aggregate multicast/broadcast frame
1506 if (p8023hdr
[0] & 0x01)
1509 if (INFRA_ON(pAd
)) // must be unicast to AP
1511 else if ((pPrevAddr1
== NULL
) || MAC_ADDR_EQUAL(pPrevAddr1
, p8023hdr
)) // unicast to same STA
1519 ========================================================================
1521 Routine Description:
1522 Check the MSDU Aggregation policy
1523 1.HT aggregation is A-MSDU
1524 2.legaacy rate aggregation is software aggregation by Ralink.
1532 ========================================================================
1534 BOOLEAN
PeerIsAggreOn(
1535 IN PRTMP_ADAPTER pAd
,
1537 IN PMAC_TABLE_ENTRY pMacEntry
)
1539 ULONG AFlags
= (fCLIENT_STATUS_AMSDU_INUSED
| fCLIENT_STATUS_AGGREGATION_CAPABLE
);
1541 if (pMacEntry
!= NULL
&& CLIENT_STATUS_TEST_FLAG(pMacEntry
, AFlags
))
1543 if (pMacEntry
->HTPhyMode
.field
.MODE
>= MODE_HTMIX
)
1548 #ifdef AGGREGATION_SUPPORT
1549 if (TxRate
>= RATE_6
&& pAd
->CommonCfg
.bAggregationCapable
&& (!(OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_WMM_INUSED
) && CLIENT_STATUS_TEST_FLAG(pMacEntry
, fCLIENT_STATUS_WMM_CAPABLE
))))
1550 { // legacy Ralink Aggregation support
1553 #endif // AGGREGATION_SUPPORT //
1562 ========================================================================
1564 Routine Description:
1565 Check and fine the packet waiting in SW queue with highest priority
1568 pAd Pointer to our adapter
1571 pQueue Pointer to Waiting Queue
1573 IRQL = DISPATCH_LEVEL
1577 ========================================================================
1579 PQUEUE_HEADER
RTMPCheckTxSwQueue(
1580 IN PRTMP_ADAPTER pAd
,
1586 Number
= pAd
->TxSwQueue
[QID_AC_BK
].Number
1587 + pAd
->TxSwQueue
[QID_AC_BE
].Number
1588 + pAd
->TxSwQueue
[QID_AC_VI
].Number
1589 + pAd
->TxSwQueue
[QID_AC_VO
].Number
1590 + pAd
->TxSwQueue
[QID_HCCA
].Number
;
1592 if (pAd
->TxSwQueue
[QID_AC_VO
].Head
!= NULL
)
1594 *pQueIdx
= QID_AC_VO
;
1595 return (&pAd
->TxSwQueue
[QID_AC_VO
]);
1597 else if (pAd
->TxSwQueue
[QID_AC_VI
].Head
!= NULL
)
1599 *pQueIdx
= QID_AC_VI
;
1600 return (&pAd
->TxSwQueue
[QID_AC_VI
]);
1602 else if (pAd
->TxSwQueue
[QID_AC_BE
].Head
!= NULL
)
1604 *pQueIdx
= QID_AC_BE
;
1605 return (&pAd
->TxSwQueue
[QID_AC_BE
]);
1607 else if (pAd
->TxSwQueue
[QID_AC_BK
].Head
!= NULL
)
1609 *pQueIdx
= QID_AC_BK
;
1610 return (&pAd
->TxSwQueue
[QID_AC_BK
]);
1612 else if (pAd
->TxSwQueue
[QID_HCCA
].Head
!= NULL
)
1614 *pQueIdx
= QID_HCCA
;
1615 return (&pAd
->TxSwQueue
[QID_HCCA
]);
1618 // No packet pending in Tx Sw queue
1619 *pQueIdx
= QID_AC_BK
;
1625 BOOLEAN
RTMPFreeTXDUponTxDmaDone(
1626 IN PRTMP_ADAPTER pAd
,
1629 PRTMP_TX_RING pTxRing
;
1631 PNDIS_PACKET pPacket
;
1633 TXD_STRUC TxD
, *pOriTxD
;
1635 BOOLEAN bReschedule
= FALSE
;
1638 ASSERT(QueIdx
< NUM_OF_TX_RING
);
1639 pTxRing
= &pAd
->TxRing
[QueIdx
];
1641 RTMP_IO_READ32(pAd
, TX_DTX_IDX0
+ QueIdx
* RINGREG_DIFF
, &pTxRing
->TxDmaIdx
);
1642 while (pTxRing
->TxSwFreeIdx
!= pTxRing
->TxDmaIdx
)
1644 // static rate also need NICUpdateFifoStaCounters() function.
1645 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
1646 NICUpdateFifoStaCounters(pAd
);
1648 /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
1650 pTxD
= (PTXD_STRUC
) (pTxRing
->Cell
[pTxRing
->TxSwFreeIdx
].AllocVa
);
1652 NdisMoveMemory(&TxD
, pTxD
, sizeof(TXD_STRUC
));
1657 /*====================================================================*/
1659 pPacket
= pTxRing
->Cell
[pTxRing
->TxSwFreeIdx
].pNdisPacket
;
1662 #ifdef CONFIG_5VT_ENHANCE
1663 if (RTMP_GET_PACKET_5VT(pPacket
))
1664 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr1
, 16, PCI_DMA_TODEVICE
);
1666 #endif // CONFIG_5VT_ENHANCE //
1667 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr1
, pTxD
->SDLen1
, PCI_DMA_TODEVICE
);
1668 RELEASE_NDIS_PACKET(pAd
, pPacket
, NDIS_STATUS_SUCCESS
);
1670 //Always assign pNdisPacket as NULL after clear
1671 pTxRing
->Cell
[pTxRing
->TxSwFreeIdx
].pNdisPacket
= NULL
;
1673 pPacket
= pTxRing
->Cell
[pTxRing
->TxSwFreeIdx
].pNextNdisPacket
;
1675 ASSERT(pPacket
== NULL
);
1678 #ifdef CONFIG_5VT_ENHANCE
1679 if (RTMP_GET_PACKET_5VT(pPacket
))
1680 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr1
, 16, PCI_DMA_TODEVICE
);
1682 #endif // CONFIG_5VT_ENHANCE //
1683 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr1
, pTxD
->SDLen1
, PCI_DMA_TODEVICE
);
1684 RELEASE_NDIS_PACKET(pAd
, pPacket
, NDIS_STATUS_SUCCESS
);
1686 //Always assign pNextNdisPacket as NULL after clear
1687 pTxRing
->Cell
[pTxRing
->TxSwFreeIdx
].pNextNdisPacket
= NULL
;
1689 /*====================================================================*/
1691 pAd
->RalinkCounters
.TransmittedByteCount
+= (pTxD
->SDLen1
+ pTxD
->SDLen0
);
1692 pAd
->RalinkCounters
.OneSecDmaDoneCount
[QueIdx
] ++;
1693 INC_RING_INDEX(pTxRing
->TxSwFreeIdx
, TX_RING_SIZE
);
1694 /* get tx_tdx_idx again */
1695 RTMP_IO_READ32(pAd
, TX_DTX_IDX0
+ QueIdx
* RINGREG_DIFF
, &pTxRing
->TxDmaIdx
);
1697 NdisMoveMemory(pOriTxD
, pTxD
, sizeof(TXD_STRUC
));
1707 ========================================================================
1709 Routine Description:
1710 Process TX Rings DMA Done interrupt, running in DPC level
1713 Adapter Pointer to our adapter
1718 IRQL = DISPATCH_LEVEL
1720 ========================================================================
1722 BOOLEAN
RTMPHandleTxRingDmaDoneInterrupt(
1723 IN PRTMP_ADAPTER pAd
,
1724 IN INT_SOURCE_CSR_STRUC TxRingBitmap
)
1726 unsigned long IrqFlags
;
1727 BOOLEAN bReschedule
= FALSE
;
1729 // Make sure Tx ring resource won't be used by other threads
1731 RTMP_IRQ_LOCK(&pAd
->irq_lock
, IrqFlags
);
1733 if (TxRingBitmap
.field
.Ac0DmaDone
)
1734 bReschedule
= RTMPFreeTXDUponTxDmaDone(pAd
, QID_AC_BE
);
1736 if (TxRingBitmap
.field
.HccaDmaDone
)
1737 bReschedule
|= RTMPFreeTXDUponTxDmaDone(pAd
, QID_HCCA
);
1739 if (TxRingBitmap
.field
.Ac3DmaDone
)
1740 bReschedule
|= RTMPFreeTXDUponTxDmaDone(pAd
, QID_AC_VO
);
1742 if (TxRingBitmap
.field
.Ac2DmaDone
)
1743 bReschedule
|= RTMPFreeTXDUponTxDmaDone(pAd
, QID_AC_VI
);
1745 if (TxRingBitmap
.field
.Ac1DmaDone
)
1746 bReschedule
|= RTMPFreeTXDUponTxDmaDone(pAd
, QID_AC_BK
);
1748 // Make sure to release Tx ring resource
1749 RTMP_IRQ_UNLOCK(&pAd
->irq_lock
, IrqFlags
);
1751 // Dequeue outgoing frames from TxSwQueue[] and process it
1752 RTMPDeQueuePacket(pAd
, FALSE
, NUM_OF_TX_RING
, MAX_TX_PROCESS
);
1759 ========================================================================
1761 Routine Description:
1762 Process MGMT ring DMA done interrupt, running in DPC level
1765 pAd Pointer to our adapter
1770 IRQL = DISPATCH_LEVEL
1774 ========================================================================
1776 VOID
RTMPHandleMgmtRingDmaDoneInterrupt(
1777 IN PRTMP_ADAPTER pAd
)
1780 PNDIS_PACKET pPacket
;
1782 PRTMP_MGMT_RING pMgmtRing
= &pAd
->MgmtRing
;
1784 NdisAcquireSpinLock(&pAd
->MgmtRingLock
);
1786 RTMP_IO_READ32(pAd
, TX_MGMTDTX_IDX
, &pMgmtRing
->TxDmaIdx
);
1787 while (pMgmtRing
->TxSwFreeIdx
!= pMgmtRing
->TxDmaIdx
)
1790 pTxD
= (PTXD_STRUC
) (pMgmtRing
->Cell
[pAd
->MgmtRing
.TxSwFreeIdx
].AllocVa
);
1792 pPacket
= pMgmtRing
->Cell
[pMgmtRing
->TxSwFreeIdx
].pNdisPacket
;
1797 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr0
, pTxD
->SDLen0
, PCI_DMA_TODEVICE
);
1798 RELEASE_NDIS_PACKET(pAd
, pPacket
, NDIS_STATUS_SUCCESS
);
1800 pMgmtRing
->Cell
[pMgmtRing
->TxSwFreeIdx
].pNdisPacket
= NULL
;
1802 pPacket
= pMgmtRing
->Cell
[pMgmtRing
->TxSwFreeIdx
].pNextNdisPacket
;
1805 PCI_UNMAP_SINGLE(pAd
, pTxD
->SDPtr1
, pTxD
->SDLen1
, PCI_DMA_TODEVICE
);
1806 RELEASE_NDIS_PACKET(pAd
, pPacket
, NDIS_STATUS_SUCCESS
);
1808 pMgmtRing
->Cell
[pMgmtRing
->TxSwFreeIdx
].pNextNdisPacket
= NULL
;
1809 INC_RING_INDEX(pMgmtRing
->TxSwFreeIdx
, MGMT_RING_SIZE
);
1811 NdisReleaseSpinLock(&pAd
->MgmtRingLock
);
1817 ========================================================================
1819 Routine Description:
1821 Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
1823 IRQL = DISPATCH_LEVEL
1825 ========================================================================
1827 VOID
RTMPHandleTBTTInterrupt(
1828 IN PRTMP_ADAPTER pAd
)
1831 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
1839 ========================================================================
1841 Routine Description:
1843 Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
1845 IRQL = DISPATCH_LEVEL
1847 ========================================================================
1849 VOID
RTMPHandlePreTBTTInterrupt(
1850 IN PRTMP_ADAPTER pAd
)
1853 if (OPSTATUS_TEST_FLAG(pAd
, fOP_STATUS_DOZE
))
1855 DBGPRINT(RT_DEBUG_TRACE
, ("RTMPHandlePreTBTTInterrupt...\n"));
1862 VOID
RTMPHandleRxCoherentInterrupt(
1863 IN PRTMP_ADAPTER pAd
)
1865 WPDMA_GLO_CFG_STRUC GloCfg
;
1869 DBGPRINT(RT_DEBUG_TRACE
, ("====> pAd is NULL, return.\n"));
1873 DBGPRINT(RT_DEBUG_TRACE
, ("==> RTMPHandleRxCoherentInterrupt \n"));
1875 RTMP_IO_READ32(pAd
, WPDMA_GLO_CFG
, &GloCfg
.word
);
1877 GloCfg
.field
.EnTXWriteBackDDONE
= 0;
1878 GloCfg
.field
.EnableRxDMA
= 0;
1879 GloCfg
.field
.EnableTxDMA
= 0;
1880 RTMP_IO_WRITE32(pAd
, WPDMA_GLO_CFG
, GloCfg
.word
);
1882 RTMPRingCleanUp(pAd
, QID_AC_BE
);
1883 RTMPRingCleanUp(pAd
, QID_AC_BK
);
1884 RTMPRingCleanUp(pAd
, QID_AC_VI
);
1885 RTMPRingCleanUp(pAd
, QID_AC_VO
);
1886 RTMPRingCleanUp(pAd
, QID_HCCA
);
1887 RTMPRingCleanUp(pAd
, QID_MGMT
);
1888 RTMPRingCleanUp(pAd
, QID_RX
);
1890 RTMPEnableRxTx(pAd
);
1892 DBGPRINT(RT_DEBUG_TRACE
, ("<== RTMPHandleRxCoherentInterrupt \n"));
1897 ========================================================================
1899 Routine Description:
1900 Suspend MSDU transmission
1903 pAd Pointer to our adapter
1910 ========================================================================
1912 VOID
RTMPSuspendMsduTransmission(
1913 IN PRTMP_ADAPTER pAd
)
1915 DBGPRINT(RT_DEBUG_TRACE
,("SCANNING, suspend MSDU transmission ...\n"));
1919 // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
1920 // use Lowbound as R66 value on ScanNextChannel(...)
1922 RTMP_BBP_IO_READ8_BY_REG_ID(pAd
, BBP_R66
, &pAd
->BbpTuning
.R66CurrentValue
);
1924 // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
1925 RTMPSetAGCInitValue(pAd
, BW_20
);
1927 RTMP_SET_FLAG(pAd
, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
);
1932 ========================================================================
1934 Routine Description:
1935 Resume MSDU transmission
1938 pAd Pointer to our adapter
1943 IRQL = DISPATCH_LEVEL
1947 ========================================================================
1949 VOID
RTMPResumeMsduTransmission(
1950 IN PRTMP_ADAPTER pAd
)
1952 DBGPRINT(RT_DEBUG_TRACE
,("SCAN done, resume MSDU transmission ...\n"));
1954 // After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
1955 // R66 should not be 0
1956 if (pAd
->BbpTuning
.R66CurrentValue
== 0)
1958 pAd
->BbpTuning
.R66CurrentValue
= 0x38;
1959 DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
1962 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd
, BBP_R66
, pAd
->BbpTuning
.R66CurrentValue
);
1964 RTMP_CLEAR_FLAG(pAd
, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS
);
1965 RTMPDeQueuePacket(pAd
, FALSE
, NUM_OF_TX_RING
, MAX_TX_PROCESS
);
1969 UINT
deaggregate_AMSDU_announce(
1970 IN PRTMP_ADAPTER pAd
,
1971 PNDIS_PACKET pPacket
,
1976 USHORT SubFrameSize
;
1977 PHEADER_802_3 pAMSDUsubheader
;
1979 UCHAR Header802_3
[14];
1981 PUCHAR pPayload
, pDA
, pSA
, pRemovedLLCSNAP
;
1982 PNDIS_PACKET pClonePacket
;
1988 while (DataSize
> LENGTH_802_3
)
1993 pAMSDUsubheader
= (PHEADER_802_3
)pData
;
1994 PayloadSize
= pAMSDUsubheader
->Octet
[1] + (pAMSDUsubheader
->Octet
[0]<<8);
1995 SubFrameSize
= PayloadSize
+ LENGTH_802_3
;
1998 if ((DataSize
< SubFrameSize
) || (PayloadSize
> 1518 ))
2003 pPayload
= pData
+ LENGTH_802_3
;
2005 pSA
= pData
+ MAC_ADDR_LEN
;
2007 // convert to 802.3 header
2008 CONVERT_TO_802_3(Header802_3
, pDA
, pSA
, pPayload
, PayloadSize
, pRemovedLLCSNAP
);
2010 if ((Header802_3
[12] == 0x88) && (Header802_3
[13] == 0x8E) )
2012 // avoid local heap overflow, use dyanamic allocation
2013 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
2016 memmove(Elem
->Msg
+(LENGTH_802_11
+ LENGTH_802_1_H
), pPayload
, PayloadSize
);
2017 Elem
->MsgLen
= LENGTH_802_11
+ LENGTH_802_1_H
+ PayloadSize
;
2018 WpaEAPOLKeyAction(pAd
, Elem
);
2023 if (pRemovedLLCSNAP
)
2025 pPayload
-= LENGTH_802_3
;
2026 PayloadSize
+= LENGTH_802_3
;
2027 NdisMoveMemory(pPayload
, &Header802_3
[0], LENGTH_802_3
);
2031 pClonePacket
= ClonePacket(pAd
, pPacket
, pPayload
, PayloadSize
);
2034 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pClonePacket
, RTMP_GET_PACKET_IF(pPacket
));
2038 // A-MSDU has padding to multiple of 4 including subframe header.
2039 // align SubFrameSize up to multiple of 4
2040 SubFrameSize
= (SubFrameSize
+3)&(~0x3);
2043 if (SubFrameSize
> 1528 || SubFrameSize
< 32)
2048 if (DataSize
> SubFrameSize
)
2050 pData
+= SubFrameSize
;
2051 DataSize
-= SubFrameSize
;
2060 // finally release original rx packet
2061 RELEASE_NDIS_PACKET(pAd
, pPacket
, NDIS_STATUS_SUCCESS
);
2067 UINT
BA_Reorder_AMSDU_Annnounce(
2068 IN PRTMP_ADAPTER pAd
,
2069 IN PNDIS_PACKET pPacket
)
2075 pData
= (PUCHAR
) GET_OS_PKT_DATAPTR(pPacket
);
2076 DataSize
= (USHORT
) GET_OS_PKT_LEN(pPacket
);
2078 nMSDU
= deaggregate_AMSDU_announce(pAd
, pPacket
, pData
, DataSize
);
2085 ==========================================================================
2087 Look up the MAC address in the MAC table. Return NULL if not found.
2089 pEntry - pointer to the MAC entry; NULL is not found
2090 ==========================================================================
2092 MAC_TABLE_ENTRY
*MacTableLookup(
2093 IN PRTMP_ADAPTER pAd
,
2097 MAC_TABLE_ENTRY
*pEntry
= NULL
;
2099 HashIdx
= MAC_ADDR_HASH_INDEX(pAddr
);
2100 pEntry
= pAd
->MacTab
.Hash
[HashIdx
];
2102 while (pEntry
&& (pEntry
->ValidAsCLI
|| pEntry
->ValidAsWDS
|| pEntry
->ValidAsApCli
|| pEntry
->ValidAsMesh
))
2104 if (MAC_ADDR_EQUAL(pEntry
->Addr
, pAddr
))
2109 pEntry
= pEntry
->pNext
;
2115 MAC_TABLE_ENTRY
*MacTableInsertEntry(
2116 IN PRTMP_ADAPTER pAd
,
2119 IN BOOLEAN CleanAll
)
2123 MAC_TABLE_ENTRY
*pEntry
= NULL
, *pCurrEntry
;
2126 if (pAd
->MacTab
.Size
>= MAX_LEN_OF_MAC_TABLE
)
2131 if (pAd
->StaCfg
.BssType
== BSS_INFRA
)
2134 // allocate one MAC entry
2135 NdisAcquireSpinLock(&pAd
->MacTabLock
);
2136 for (i
= FirstWcid
; i
< MAX_LEN_OF_MAC_TABLE
; i
++) // skip entry#0 so that "entry index == AID" for fast lookup
2138 // pick up the first available vacancy
2139 if ((pAd
->MacTab
.Content
[i
].ValidAsCLI
== FALSE
) &&
2140 (pAd
->MacTab
.Content
[i
].ValidAsWDS
== FALSE
) &&
2141 (pAd
->MacTab
.Content
[i
].ValidAsApCli
== FALSE
) &&
2142 (pAd
->MacTab
.Content
[i
].ValidAsMesh
== FALSE
)
2145 pEntry
= &pAd
->MacTab
.Content
[i
];
2146 if (CleanAll
== TRUE
)
2148 pEntry
->MaxSupportedRate
= RATE_11
;
2149 pEntry
->CurrTxRate
= RATE_11
;
2150 NdisZeroMemory(pEntry
, sizeof(MAC_TABLE_ENTRY
));
2151 pEntry
->PairwiseKey
.KeyLen
= 0;
2152 pEntry
->PairwiseKey
.CipherAlg
= CIPHER_NONE
;
2156 pEntry
->ValidAsCLI
= TRUE
;
2157 pEntry
->ValidAsWDS
= FALSE
;
2158 pEntry
->ValidAsApCli
= FALSE
;
2159 pEntry
->ValidAsMesh
= FALSE
;
2160 pEntry
->ValidAsDls
= FALSE
;
2164 pEntry
->bIAmBadAtheros
= FALSE
;
2166 pEntry
->CMTimerRunning
= FALSE
;
2167 pEntry
->EnqueueEapolStartTimerRunning
= EAPOL_START_DISABLE
;
2168 pEntry
->RSNIE_Len
= 0;
2169 NdisZeroMemory(pEntry
->R_Counter
, sizeof(pEntry
->R_Counter
));
2170 pEntry
->ReTryCounter
= PEER_MSG1_RETRY_TIMER_CTR
;
2172 if (pEntry
->ValidAsMesh
)
2173 pEntry
->apidx
= (apidx
- MIN_NET_DEVICE_FOR_MESH
);
2174 else if (pEntry
->ValidAsApCli
)
2175 pEntry
->apidx
= (apidx
- MIN_NET_DEVICE_FOR_APCLI
);
2176 else if (pEntry
->ValidAsWDS
)
2177 pEntry
->apidx
= (apidx
- MIN_NET_DEVICE_FOR_WDS
);
2179 pEntry
->apidx
= apidx
;
2183 pEntry
->AuthMode
= pAd
->StaCfg
.AuthMode
;
2184 pEntry
->WepStatus
= pAd
->StaCfg
.WepStatus
;
2185 pEntry
->PrivacyFilter
= Ndis802_11PrivFilterAcceptAll
;
2187 AsicRemovePairwiseKeyEntry(pAd
, pEntry
->apidx
, (UCHAR
)i
);
2192 pEntry
->GTKState
= REKEY_NEGOTIATING
;
2193 pEntry
->PairwiseKey
.KeyLen
= 0;
2194 pEntry
->PairwiseKey
.CipherAlg
= CIPHER_NONE
;
2197 if ((pAd
->OpMode
== OPMODE_STA
) &&
2198 (pAd
->StaCfg
.BssType
== BSS_ADHOC
))
2199 pEntry
->PortSecured
= WPA_802_1X_PORT_SECURED
;
2202 pEntry
->PortSecured
= WPA_802_1X_PORT_NOT_SECURED
;
2204 pEntry
->PMKID_CacheIdx
= ENTRY_NOT_FOUND
;
2205 COPY_MAC_ADDR(pEntry
->Addr
, pAddr
);
2206 pEntry
->Sst
= SST_NOT_AUTH
;
2207 pEntry
->AuthState
= AS_NOT_AUTH
;
2208 pEntry
->Aid
= (USHORT
)i
; //0;
2209 pEntry
->CapabilityInfo
= 0;
2210 pEntry
->PsMode
= PWR_ACTIVE
;
2211 pEntry
->PsQIdleCount
= 0;
2212 pEntry
->NoDataIdleCount
= 0;
2213 pEntry
->ContinueTxFailCnt
= 0;
2214 InitializeQueueHeader(&pEntry
->PsQueue
);
2217 pAd
->MacTab
.Size
++;
2218 // Add this entry into ASIC RX WCID search table
2219 RT28XX_STA_ENTRY_ADD(pAd
, pEntry
);
2223 DBGPRINT(RT_DEBUG_TRACE
, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i
, pAd
->MacTab
.Size
));
2228 // add this MAC entry into HASH table
2231 HashIdx
= MAC_ADDR_HASH_INDEX(pAddr
);
2232 if (pAd
->MacTab
.Hash
[HashIdx
] == NULL
)
2234 pAd
->MacTab
.Hash
[HashIdx
] = pEntry
;
2238 pCurrEntry
= pAd
->MacTab
.Hash
[HashIdx
];
2239 while (pCurrEntry
->pNext
!= NULL
)
2240 pCurrEntry
= pCurrEntry
->pNext
;
2241 pCurrEntry
->pNext
= pEntry
;
2245 NdisReleaseSpinLock(&pAd
->MacTabLock
);
2250 ==========================================================================
2252 Delete a specified client from MAC table
2253 ==========================================================================
2255 BOOLEAN
MacTableDeleteEntry(
2256 IN PRTMP_ADAPTER pAd
,
2261 MAC_TABLE_ENTRY
*pEntry
, *pPrevEntry
, *pProbeEntry
;
2264 if (wcid
>= MAX_LEN_OF_MAC_TABLE
)
2267 NdisAcquireSpinLock(&pAd
->MacTabLock
);
2269 HashIdx
= MAC_ADDR_HASH_INDEX(pAddr
);
2270 pEntry
= &pAd
->MacTab
.Content
[wcid
];
2272 if (pEntry
&& (pEntry
->ValidAsCLI
|| pEntry
->ValidAsApCli
|| pEntry
->ValidAsWDS
|| pEntry
->ValidAsMesh
2275 if (MAC_ADDR_EQUAL(pEntry
->Addr
, pAddr
))
2278 // Delete this entry from ASIC on-chip WCID Table
2279 RT28XX_STA_ENTRY_MAC_RESET(pAd
, wcid
);
2281 // free resources of BA
2282 BASessionTearDownALL(pAd
, pEntry
->Aid
);
2285 pProbeEntry
= pAd
->MacTab
.Hash
[HashIdx
];
2286 ASSERT(pProbeEntry
);
2291 if (pProbeEntry
== pEntry
)
2293 if (pPrevEntry
== NULL
)
2295 pAd
->MacTab
.Hash
[HashIdx
] = pEntry
->pNext
;
2299 pPrevEntry
->pNext
= pEntry
->pNext
;
2304 pPrevEntry
= pProbeEntry
;
2305 pProbeEntry
= pProbeEntry
->pNext
;
2306 } while (pProbeEntry
);
2309 ASSERT(pProbeEntry
!= NULL
);
2311 RT28XX_STA_ENTRY_KEY_DEL(pAd
, BSS0
, wcid
);
2314 if (pEntry
->EnqueueEapolStartTimerRunning
!= EAPOL_START_DISABLE
)
2316 RTMPCancelTimer(&pEntry
->EnqueueStartForPSKTimer
, &Cancelled
);
2317 pEntry
->EnqueueEapolStartTimerRunning
= EAPOL_START_DISABLE
;
2321 NdisZeroMemory(pEntry
, sizeof(MAC_TABLE_ENTRY
));
2322 pAd
->MacTab
.Size
--;
2323 DBGPRINT(RT_DEBUG_TRACE
, ("MacTableDeleteEntry1 - Total= %d\n", pAd
->MacTab
.Size
));
2327 printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__
, wcid
);
2331 NdisReleaseSpinLock(&pAd
->MacTabLock
);
2333 //Reset operating mode when no Sta.
2334 if (pAd
->MacTab
.Size
== 0)
2336 pAd
->CommonCfg
.AddHTInfo
.AddHtInfo2
.OperaionMode
= 0;
2338 AsicUpdateProtect(pAd
, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT
), TRUE
, 0 /*pAd->MacTab.fAnyStationNonGF*/);
2340 // edit by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet
2341 // Set MAC register value according operation mode
2342 RTUSBEnqueueInternalCmd(pAd
, CMDTHREAD_UPDATE_PROTECT
, NULL
, 0);
2351 ==========================================================================
2353 This routine reset the entire MAC table. All packets pending in
2354 the power-saving queues are freed here.
2355 ==========================================================================
2358 IN PRTMP_ADAPTER pAd
)
2362 DBGPRINT(RT_DEBUG_TRACE
, ("MacTableReset\n"));
2363 //NdisAcquireSpinLock(&pAd->MacTabLock);
2365 for (i
=1; i
<MAX_LEN_OF_MAC_TABLE
; i
++)
2368 RT28XX_STA_ENTRY_MAC_RESET(pAd
, i
);
2370 if (pAd
->MacTab
.Content
[i
].ValidAsCLI
== TRUE
)
2372 // free resources of BA
2373 BASessionTearDownALL(pAd
, i
);
2375 pAd
->MacTab
.Content
[i
].ValidAsCLI
= FALSE
;
2380 NdisZeroMemory(pAd
->MacTab
.Content
[i
].Addr
, 6);
2381 RT28XX_STA_ENTRY_MAC_RESET(pAd
, i
);
2384 //AsicDelWcidTab(pAd, i);
2392 ==========================================================================
2395 IRQL = DISPATCH_LEVEL
2397 ==========================================================================
2400 IN PRTMP_ADAPTER pAd
,
2401 IN OUT MLME_ASSOC_REQ_STRUCT
*AssocReq
,
2403 IN USHORT CapabilityInfo
,
2405 IN USHORT ListenIntv
)
2407 COPY_MAC_ADDR(AssocReq
->Addr
, pAddr
);
2408 // Add mask to support 802.11b mode only
2409 AssocReq
->CapabilityInfo
= CapabilityInfo
& SUPPORTED_CAPABILITY_INFO
; // not cf-pollable, not cf-poll-request
2410 AssocReq
->Timeout
= Timeout
;
2411 AssocReq
->ListenIntv
= ListenIntv
;
2416 ==========================================================================
2419 IRQL = DISPATCH_LEVEL
2421 ==========================================================================
2423 VOID
DisassocParmFill(
2424 IN PRTMP_ADAPTER pAd
,
2425 IN OUT MLME_DISASSOC_REQ_STRUCT
*DisassocReq
,
2429 COPY_MAC_ADDR(DisassocReq
->Addr
, pAddr
);
2430 DisassocReq
->Reason
= Reason
;
2435 ========================================================================
2437 Routine Description:
2438 Check the out going frame, if this is an DHCP or ARP datagram
2439 will be duplicate another frame at low data rate transmit.
2442 pAd Pointer to our adapter
2443 pPacket Pointer to outgoing Ndis frame
2446 TRUE To be duplicate at Low data rate transmit. (1mb)
2449 IRQL = DISPATCH_LEVEL
2453 MAC header + IP Header + UDP Header
2457 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
2459 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
2462 port 0x43 means Bootstrap Protocol, server.
2463 Port 0x44 means Bootstrap Protocol, client.
2465 ========================================================================
2468 BOOLEAN
RTMPCheckDHCPFrame(
2469 IN PRTMP_ADAPTER pAd
,
2470 IN PNDIS_PACKET pPacket
)
2472 PACKET_INFO PacketInfo
;
2473 ULONG NumberOfBytesRead
= 0;
2474 ULONG CurrentOffset
= 0;
2475 PVOID pVirtualAddress
= NULL
;
2476 UINT NdisBufferLength
;
2479 UCHAR ByteOffset36
= 0;
2480 UCHAR ByteOffset38
= 0;
2481 BOOLEAN ReadFirstParm
= TRUE
;
2483 RTMP_QueryPacketInfo(pPacket
, &PacketInfo
, (PUCHAR
*)&pVirtualAddress
, &NdisBufferLength
);
2485 NumberOfBytesRead
+= NdisBufferLength
;
2486 pSrc
= (PUCHAR
) pVirtualAddress
;
2487 Protocol
= *(pSrc
+ 12) * 256 + *(pSrc
+ 13);
2490 // Check DHCP & BOOTP protocol
2492 while (NumberOfBytesRead
<= PacketInfo
.TotalPacketLength
)
2494 if ((NumberOfBytesRead
>= 35) && (ReadFirstParm
== TRUE
))
2496 CurrentOffset
= 35 - (NumberOfBytesRead
- NdisBufferLength
);
2497 ByteOffset36
= *(pSrc
+ CurrentOffset
);
2498 ReadFirstParm
= FALSE
;
2501 if (NumberOfBytesRead
>= 37)
2503 CurrentOffset
= 37 - (NumberOfBytesRead
- NdisBufferLength
);
2504 ByteOffset38
= *(pSrc
+ CurrentOffset
);
2511 // Check for DHCP & BOOTP protocol
2512 if ((ByteOffset36
!= 0x44) || (ByteOffset38
!= 0x43))
2515 // 2054 (hex 0806) for ARP datagrams
2516 // if this packet is not ARP datagrams, then do nothing
2517 // ARP datagrams will also be duplicate at 1mb broadcast frames
2519 if (Protocol
!= 0x0806 )
2527 BOOLEAN
RTMPCheckEtherType(
2528 IN PRTMP_ADAPTER pAd
,
2529 IN PNDIS_PACKET pPacket
)
2535 UINT16 srcPort
, dstPort
;
2536 BOOLEAN status
= TRUE
;
2539 pSrcBuf
= GET_OS_PKT_DATAPTR(pPacket
);
2540 pktLen
= GET_OS_PKT_LEN(pPacket
);
2544 RTMP_SET_PACKET_SPECIFIC(pPacket
, 0);
2546 // get Ethernet protocol field
2547 TypeLen
= (pSrcBuf
[12] << 8) + pSrcBuf
[13];
2549 pSrcBuf
+= LENGTH_802_3
; // Skip the Ethernet Header.
2551 if (TypeLen
<= 1500)
2552 { // 802.3, 802.3 LLC
2554 DestMAC(6) + SrcMAC(6) + Lenght(2) +
2555 DSAP(1) + SSAP(1) + Control(1) +
2556 if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
2557 => + SNAP (5, OriginationID(3) + etherType(2))
2559 if (pSrcBuf
[0] == 0xAA && pSrcBuf
[1] == 0xAA && pSrcBuf
[2] == 0x03)
2561 Sniff2BytesFromNdisBuffer(pSrcBuf
, 6, &Byte0
, &Byte1
);
2562 RTMP_SET_PACKET_LLCSNAP(pPacket
, 1);
2563 TypeLen
= (USHORT
)((Byte0
<< 8) + Byte1
);
2564 pSrcBuf
+= 8; // Skip this LLC/SNAP header
2568 //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
2572 // If it's a VLAN packet, get the real Type/Length field.
2573 if (TypeLen
== 0x8100)
2575 /* 0x8100 means VLAN packets */
2577 /* Dest. MAC Address (6-bytes) +
2578 Source MAC Address (6-bytes) +
2579 Length/Type = 802.1Q Tag Type (2-byte) +
2580 Tag Control Information (2-bytes) +
2581 Length / Type (2-bytes) +
2582 data payload (0-n bytes) +
2584 Frame Check Sequence (4-bytes) */
2586 RTMP_SET_PACKET_VLAN(pPacket
, 1);
2587 Sniff2BytesFromNdisBuffer(pSrcBuf
, 2, &Byte0
, &Byte1
);
2588 TypeLen
= (USHORT
)((Byte0
<< 8) + Byte1
);
2590 pSrcBuf
+= 4; // Skip the VLAN Header.
2597 ASSERT((pktLen
> 34));
2598 if (*(pSrcBuf
+ 9) == 0x11)
2600 ASSERT((pktLen
> 34)); // 14 for ethernet header, 20 for IP header
2602 pSrcBuf
+= 20; // Skip the IP header
2603 srcPort
= OS_NTOHS(*((UINT16
*)pSrcBuf
));
2604 dstPort
= OS_NTOHS(*((UINT16
*)(pSrcBuf
+2)));
2606 if ((srcPort
==0x44 && dstPort
==0x43) || (srcPort
==0x43 && dstPort
==0x44))
2607 { //It's a BOOTP/DHCP packet
2608 RTMP_SET_PACKET_DHCP(pPacket
, 1);
2616 RTMP_SET_PACKET_DHCP(pPacket
, 1);
2622 RTMP_SET_PACKET_EAPOL(pPacket
, 1);
2636 VOID
Update_Rssi_Sample(
2637 IN PRTMP_ADAPTER pAd
,
2638 IN RSSI_SAMPLE
*pRssi
,
2639 IN PRXWI_STRUC pRxWI
)
2641 CHAR rssi0
= pRxWI
->RSSI0
;
2642 CHAR rssi1
= pRxWI
->RSSI1
;
2643 CHAR rssi2
= pRxWI
->RSSI2
;
2647 pRssi
->LastRssi0
= ConvertToRssi(pAd
, (CHAR
)rssi0
, RSSI_0
);
2648 pRssi
->AvgRssi0X8
= (pRssi
->AvgRssi0X8
- pRssi
->AvgRssi0
) + pRssi
->LastRssi0
;
2649 pRssi
->AvgRssi0
= pRssi
->AvgRssi0X8
>> 3;
2654 pRssi
->LastRssi1
= ConvertToRssi(pAd
, (CHAR
)rssi1
, RSSI_1
);
2655 pRssi
->AvgRssi1X8
= (pRssi
->AvgRssi1X8
- pRssi
->AvgRssi1
) + pRssi
->LastRssi1
;
2656 pRssi
->AvgRssi1
= pRssi
->AvgRssi1X8
>> 3;
2661 pRssi
->LastRssi2
= ConvertToRssi(pAd
, (CHAR
)rssi2
, RSSI_2
);
2662 pRssi
->AvgRssi2X8
= (pRssi
->AvgRssi2X8
- pRssi
->AvgRssi2
) + pRssi
->LastRssi2
;
2663 pRssi
->AvgRssi2
= pRssi
->AvgRssi2X8
>> 3;
2669 // Normal legacy Rx packet indication
2670 VOID
Indicate_Legacy_Packet(
2671 IN PRTMP_ADAPTER pAd
,
2673 IN UCHAR FromWhichBSSID
)
2675 PNDIS_PACKET pRxPacket
= pRxBlk
->pRxPacket
;
2676 UCHAR Header802_3
[LENGTH_802_3
];
2678 // 1. get 802.3 Header
2680 // a. pointer pRxBlk->pData to payload
2681 // b. modify pRxBlk->DataSize
2682 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
2684 if (pRxBlk
->DataSize
> MAX_RX_PKT_LEN
)
2688 RELEASE_NDIS_PACKET(pAd
, pRxPacket
, NDIS_STATUS_FAILURE
);
2693 STATS_INC_RX_PACKETS(pAd
, FromWhichBSSID
);
2696 if (pAd
->CommonCfg
.bDisableReordering
== 0)
2698 PBA_REC_ENTRY pBAEntry
;
2700 UCHAR Wcid
= pRxBlk
->pRxWI
->WirelessCliID
;
2701 UCHAR TID
= pRxBlk
->pRxWI
->TID
;
2704 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
2706 if (Wcid
< MAX_LEN_OF_MAC_TABLE
)
2708 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
2711 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
2712 // update last rx time
2713 NdisGetSystemUpTime(&Now32
);
2714 if ((pBAEntry
->list
.qlen
> 0) &&
2715 RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(REORDERING_PACKET_TIMEOUT
)))
2718 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
);
2719 hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk
->pRxPacket
), 64);
2720 ba_flush_reordering_timeout_mpdus(pAd
, pBAEntry
, Now32
);
2727 wlan_802_11_to_802_3_packet(pAd
, pRxBlk
, Header802_3
, FromWhichBSSID
);
2730 // pass this 802.3 packet to upper layer or forward this packet to WM directly
2732 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pRxPacket
, FromWhichBSSID
);
2736 // Normal, AMPDU or AMSDU
2737 VOID
CmmRxnonRalinkFrameIndicate(
2738 IN PRTMP_ADAPTER pAd
,
2740 IN UCHAR FromWhichBSSID
)
2742 if (RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMPDU
) && (pAd
->CommonCfg
.bDisableReordering
== 0))
2744 Indicate_AMPDU_Packet(pAd
, pRxBlk
, FromWhichBSSID
);
2748 if (RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
))
2751 Indicate_AMSDU_Packet(pAd
, pRxBlk
, FromWhichBSSID
);
2755 Indicate_Legacy_Packet(pAd
, pRxBlk
, FromWhichBSSID
);
2761 VOID
CmmRxRalinkFrameIndicate(
2762 IN PRTMP_ADAPTER pAd
,
2763 IN MAC_TABLE_ENTRY
*pEntry
,
2765 IN UCHAR FromWhichBSSID
)
2767 UCHAR Header802_3
[LENGTH_802_3
];
2769 UINT16 Payload1Size
, Payload2Size
;
2771 PNDIS_PACKET pPacket2
= NULL
;
2775 Msdu2Size
= *(pRxBlk
->pData
) + (*(pRxBlk
->pData
+1) << 8);
2777 if ((Msdu2Size
<= 1536) && (Msdu2Size
< pRxBlk
->DataSize
))
2779 /* skip two byte MSDU2 len */
2781 pRxBlk
->DataSize
-= 2;
2786 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
2790 // get 802.3 Header and remove LLC
2791 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
2793 ASSERT(pRxBlk
->pRxPacket
);
2795 // Ralink Aggregation frame
2796 pAd
->RalinkCounters
.OneSecRxAggregationCount
++;
2797 Payload1Size
= pRxBlk
->DataSize
- Msdu2Size
;
2798 Payload2Size
= Msdu2Size
- LENGTH_802_3
;
2800 pData2
= pRxBlk
->pData
+ Payload1Size
+ LENGTH_802_3
;
2802 pPacket2
= duplicate_pkt(pAd
, (pData2
-LENGTH_802_3
), LENGTH_802_3
, pData2
, Payload2Size
, FromWhichBSSID
);
2807 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
2811 // update payload size of 1st packet
2812 pRxBlk
->DataSize
= Payload1Size
;
2813 wlan_802_11_to_802_3_packet(pAd
, pRxBlk
, Header802_3
, FromWhichBSSID
);
2815 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pRxBlk
->pRxPacket
, FromWhichBSSID
);
2819 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pPacket2
, FromWhichBSSID
);
2824 #define RESET_FRAGFRAME(_fragFrame) \
2826 _fragFrame.RxSize = 0; \
2827 _fragFrame.Sequence = 0; \
2828 _fragFrame.LastFrag = 0; \
2829 _fragFrame.Flags = 0; \
2833 PNDIS_PACKET
RTMPDeFragmentDataFrame(
2834 IN PRTMP_ADAPTER pAd
,
2837 PHEADER_802_11 pHeader
= pRxBlk
->pHeader
;
2838 PNDIS_PACKET pRxPacket
= pRxBlk
->pRxPacket
;
2839 UCHAR
*pData
= pRxBlk
->pData
;
2840 USHORT DataSize
= pRxBlk
->DataSize
;
2841 PNDIS_PACKET pRetPacket
= NULL
;
2842 UCHAR
*pFragBuffer
= NULL
;
2843 BOOLEAN bReassDone
= FALSE
;
2844 UCHAR HeaderRoom
= 0;
2849 HeaderRoom
= pData
- (UCHAR
*)pHeader
;
2851 // Re-assemble the fragmented packets
2852 if (pHeader
->Frag
== 0) // Frag. Number is 0 : First frag or only one pkt
2854 // the first pkt of fragment, record it.
2855 if (pHeader
->FC
.MoreFrag
)
2857 ASSERT(pAd
->FragFrame
.pFragPacket
);
2858 pFragBuffer
= GET_OS_PKT_DATAPTR(pAd
->FragFrame
.pFragPacket
);
2859 pAd
->FragFrame
.RxSize
= DataSize
+ HeaderRoom
;
2860 NdisMoveMemory(pFragBuffer
, pHeader
, pAd
->FragFrame
.RxSize
);
2861 pAd
->FragFrame
.Sequence
= pHeader
->Sequence
;
2862 pAd
->FragFrame
.LastFrag
= pHeader
->Frag
; // Should be 0
2863 ASSERT(pAd
->FragFrame
.LastFrag
== 0);
2864 goto done
; // end of processing this frame
2867 else //Middle & End of fragment
2869 if ((pHeader
->Sequence
!= pAd
->FragFrame
.Sequence
) ||
2870 (pHeader
->Frag
!= (pAd
->FragFrame
.LastFrag
+ 1)))
2872 // Fragment is not the same sequence or out of fragment number order
2873 // Reset Fragment control blk
2874 RESET_FRAGFRAME(pAd
->FragFrame
);
2875 DBGPRINT(RT_DEBUG_ERROR
, ("Fragment is not the same sequence or out of fragment number order.\n"));
2876 goto done
; // give up this frame
2878 else if ((pAd
->FragFrame
.RxSize
+ DataSize
) > MAX_FRAME_SIZE
)
2880 // Fragment frame is too large, it exeeds the maximum frame size.
2881 // Reset Fragment control blk
2882 RESET_FRAGFRAME(pAd
->FragFrame
);
2883 DBGPRINT(RT_DEBUG_ERROR
, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
2884 goto done
; // give up this frame
2888 // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
2889 // In this case, we will dropt it.
2891 if (NdisEqualMemory(pData
, SNAP_802_1H
, sizeof(SNAP_802_1H
)))
2893 DBGPRINT(RT_DEBUG_ERROR
, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader
->Sequence
, pHeader
->Frag
));
2894 goto done
; // give up this frame
2897 pFragBuffer
= GET_OS_PKT_DATAPTR(pAd
->FragFrame
.pFragPacket
);
2899 // concatenate this fragment into the re-assembly buffer
2900 NdisMoveMemory((pFragBuffer
+ pAd
->FragFrame
.RxSize
), pData
, DataSize
);
2901 pAd
->FragFrame
.RxSize
+= DataSize
;
2902 pAd
->FragFrame
.LastFrag
= pHeader
->Frag
; // Update fragment number
2905 if (pHeader
->FC
.MoreFrag
== FALSE
)
2912 // always release rx fragmented packet
2913 RELEASE_NDIS_PACKET(pAd
, pRxPacket
, NDIS_STATUS_FAILURE
);
2915 // return defragmented packet if packet is reassembled completely
2916 // otherwise return NULL
2919 PNDIS_PACKET pNewFragPacket
;
2921 // allocate a new packet buffer for fragment
2922 pNewFragPacket
= RTMP_AllocateFragPacketBuffer(pAd
, RX_BUFFER_NORMSIZE
);
2926 pRetPacket
= pAd
->FragFrame
.pFragPacket
;
2927 pAd
->FragFrame
.pFragPacket
= pNewFragPacket
;
2928 pRxBlk
->pHeader
= (PHEADER_802_11
) GET_OS_PKT_DATAPTR(pRetPacket
);
2929 pRxBlk
->pData
= (UCHAR
*)pRxBlk
->pHeader
+ HeaderRoom
;
2930 pRxBlk
->DataSize
= pAd
->FragFrame
.RxSize
- HeaderRoom
;
2931 pRxBlk
->pRxPacket
= pRetPacket
;
2935 RESET_FRAGFRAME(pAd
->FragFrame
);
2943 VOID
Indicate_AMSDU_Packet(
2944 IN PRTMP_ADAPTER pAd
,
2946 IN UCHAR FromWhichBSSID
)
2950 update_os_packet_info(pAd
, pRxBlk
, FromWhichBSSID
);
2951 RTMP_SET_PACKET_IF(pRxBlk
->pRxPacket
, FromWhichBSSID
);
2952 nMSDU
= deaggregate_AMSDU_announce(pAd
, pRxBlk
->pRxPacket
, pRxBlk
->pData
, pRxBlk
->DataSize
);
2955 VOID
Indicate_EAPOL_Packet(
2956 IN PRTMP_ADAPTER pAd
,
2958 IN UCHAR FromWhichBSSID
)
2960 MAC_TABLE_ENTRY
*pEntry
= NULL
;
2963 pEntry
= &pAd
->MacTab
.Content
[BSSID_WCID
];
2964 STARxEAPOLFrameIndicate(pAd
, pEntry
, pRxBlk
, FromWhichBSSID
);
2970 DBGPRINT(RT_DEBUG_WARN
, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
2972 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
2977 #define BCN_TBTT_OFFSET 64 //defer 64 us
2978 VOID
ReSyncBeaconTime(
2979 IN PRTMP_ADAPTER pAd
)
2985 Offset
= (pAd
->TbttTickCount
) % (BCN_TBTT_OFFSET
);
2987 pAd
->TbttTickCount
++;
2990 // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
2991 // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
2993 if (Offset
== (BCN_TBTT_OFFSET
-2))
2995 BCN_TIME_CFG_STRUC csr
;
2996 RTMP_IO_READ32(pAd
, BCN_TIME_CFG
, &csr
.word
);
2997 csr
.field
.BeaconInterval
= (pAd
->CommonCfg
.BeaconPeriod
<< 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
2998 RTMP_IO_WRITE32(pAd
, BCN_TIME_CFG
, csr
.word
);
3002 if (Offset
== (BCN_TBTT_OFFSET
-1))
3004 BCN_TIME_CFG_STRUC csr
;
3006 RTMP_IO_READ32(pAd
, BCN_TIME_CFG
, &csr
.word
);
3007 csr
.field
.BeaconInterval
= (pAd
->CommonCfg
.BeaconPeriod
) << 4; // ASIC register in units of 1/16 TU
3008 RTMP_IO_WRITE32(pAd
, BCN_TIME_CFG
, csr
.word
);