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
*************************************************************************
35
Justin P. Mattock 11/07/2010 Fix typos
36
-------- ---------- ----------------------------------------------
38
#include "../rt_config.h"
39
#include <linux/kernel.h>
41
void STARxEAPOLFrameIndicate(struct rt_rtmp_adapter *pAd,
42
struct rt_mac_table_entry *pEntry,
43
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
45
PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
46
struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
49
if (pAd->StaCfg.WpaSupplicantUP) {
50
/* All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) */
51
/* TBD : process fragmented EAPol frames */
53
/* In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable */
54
if (pAd->StaCfg.IEEE8021X == TRUE &&
56
WpaCheckEapCode(pAd, pRxBlk->pData,
63
DBGPRINT_RAW(RT_DEBUG_TRACE,
64
("Receive EAP-SUCCESS Packet\n"));
65
/*pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; */
66
STA_PORT_SECURED(pAd);
68
if (pAd->StaCfg.IEEE8021x_required_keys ==
70
idx = pAd->StaCfg.DesireSharedKeyId;
72
pAd->StaCfg.DesireSharedKey[idx].
75
pAd->StaCfg.DesireSharedKey[idx].
78
if (pAd->StaCfg.DesireSharedKey[idx].
81
struct rt_mac_table_entry *pEntry =
85
/* Set key material and cipherAlg to Asic */
86
AsicAddSharedKeyEntry(pAd, BSS0,
92
/* Assign group key info */
93
RTMPAddWcidAttributeEntry(pAd,
99
/* Assign pairwise key info */
100
RTMPAddWcidAttributeEntry(pAd,
106
pAd->IndicateMediaState =
107
NdisMediaStateConnected;
110
#endif /* RTMP_MAC_PCI // */
114
(struct rt_ndis_802_11_wep)
118
struct rt_ndis_802_11_wep keyinfo;
123
NdisZeroMemory(&WepKey,
127
DesireSharedKey[idx].KeyLen;
129
NdisMoveMemory(WepKey.keyinfo.
138
WepKey.keyinfo.KeyIndex =
140
WepKey.keyinfo.KeyLength = len;
141
pAd->SharedKey[BSS0][idx].
143
(u8)(len <= 5 ? 5 : 13);
145
pAd->IndicateMediaState =
146
NdisMediaStateConnected;
149
/* need to enqueue cmd to thread */
150
RTUSBEnqueueCmdFromNdis(pAd,
159
#endif /* RTMP_MAC_USB // */
160
/* For Preventing ShardKey Table is cleared by remove key procedure. */
161
pAd->SharedKey[BSS0][idx].
162
CipherAlg = CipherAlg;
163
pAd->SharedKey[BSS0][idx].
166
DesireSharedKey[idx].KeyLen;
180
Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
184
/* Special DATA frame that has to pass to MLME */
185
/* 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process */
186
/* 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process */
188
pTmpBuf = pRxBlk->pData - LENGTH_802_11;
189
NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
190
REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID,
193
LENGTH_802_11, pRxWI->RSSI0,
194
pRxWI->RSSI1, pRxWI->RSSI2,
196
DBGPRINT_RAW(RT_DEBUG_TRACE,
197
("report EAPOL/AIRONET DATA to MLME (len=%d) !\n",
202
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
207
void STARxDataFrameAnnounce(struct rt_rtmp_adapter *pAd,
208
struct rt_mac_table_entry *pEntry,
209
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
213
if (!RTMPCheckWPAframe
214
(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) {
217
/* drop all non-EAP DATA frame before */
218
/* this client's Port-Access-Control is secured */
219
if (pRxBlk->pHeader->FC.Wep) {
220
/* unsupported cipher suite */
221
if (pAd->StaCfg.WepStatus ==
222
Ndis802_11EncryptionDisabled) {
224
RELEASE_NDIS_PACKET(pAd,
226
NDIS_STATUS_FAILURE);
230
/* encryption in-use but receive a non-EAPOL clear text frame, drop it */
231
if ((pAd->StaCfg.WepStatus !=
232
Ndis802_11EncryptionDisabled)
233
&& (pAd->StaCfg.PortSecured ==
234
WPA_802_1X_PORT_NOT_SECURED)) {
236
RELEASE_NDIS_PACKET(pAd,
238
NDIS_STATUS_FAILURE);
243
RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
244
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) {
245
/* Normal legacy, AMPDU or AMSDU */
246
CmmRxnonRalinkFrameIndicate(pAd, pRxBlk,
251
CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk,
255
RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
257
if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU)
258
&& (pAd->CommonCfg.bDisableReordering == 0)) {
259
Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
261
/* Determine the destination of the EAP frame */
262
/* to WPA state machine or upper layer */
263
STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk,
269
/* For TKIP frame, calculate the MIC value */
270
BOOLEAN STACheckTkipMICValue(struct rt_rtmp_adapter *pAd,
271
struct rt_mac_table_entry *pEntry, struct rt_rx_blk *pRxBlk)
273
struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
274
u8 *pData = pRxBlk->pData;
275
u16 DataSize = pRxBlk->DataSize;
276
u8 UserPriority = pRxBlk->UserPriority;
277
struct rt_cipher_key *pWpaKey;
280
pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
282
pDA = pHeader->Addr1;
283
if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) {
284
pSA = pHeader->Addr3;
286
pSA = pHeader->Addr2;
289
if (RTMPTkipCompareMICValue(pAd,
294
UserPriority, DataSize) == FALSE) {
295
DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n"));
297
if (pAd->StaCfg.WpaSupplicantUP) {
298
WpaSendMicFailureToWpaSupplicant(pAd,
300
PAIRWISEKEY) ? TRUE :
303
RTMPReportMicError(pAd, pWpaKey);
307
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
308
NDIS_STATUS_FAILURE);
316
/* All Rx routines use struct rt_rx_blk structure to hande rx events */
317
/* It is very important to build pRxBlk attributes */
318
/* 1. pHeader pointer to 802.11 Header */
319
/* 2. pData pointer to payload including LLC (just skip Header) */
320
/* 3. set payload size including LLC to DataSize */
321
/* 4. set some flags with RX_BLK_SET_FLAG() */
323
void STAHandleRxDataFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
325
PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
326
struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
327
struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
328
void *pRxPacket = pRxBlk->pRxPacket;
329
BOOLEAN bFragment = FALSE;
330
struct rt_mac_table_entry *pEntry = NULL;
331
u8 FromWhichBSSID = BSS0;
335
/* before LINK UP, all DATA frames are rejected */
336
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
338
RELEASE_NDIS_PACKET(pAd, pRxPacket,
339
NDIS_STATUS_FAILURE);
342
/* Drop not my BSS frames */
343
if (pRxD->MyBss == 0) {
346
RELEASE_NDIS_PACKET(pAd, pRxPacket,
347
NDIS_STATUS_FAILURE);
352
pAd->RalinkCounters.RxCountSinceLastNULL++;
353
if (pAd->CommonCfg.bAPSDCapable
354
&& pAd->CommonCfg.APEdcaParm.bAPSDCapable
355
&& (pHeader->FC.SubType & 0x08)) {
357
DBGPRINT(RT_DEBUG_INFO, ("bAPSDCapable\n"));
360
pData = (u8 *)pHeader + LENGTH_802_11;
361
if ((*pData >> 4) & 0x01) {
362
DBGPRINT(RT_DEBUG_INFO,
363
("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
364
pAd->CommonCfg.bInServicePeriod = FALSE;
366
/* Force driver to fall into sleep mode when rcv EOSP frame */
367
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
368
u16 TbttNumToNextWakeUp;
370
pAd->StaCfg.DtimPeriod;
373
NdisGetSystemUpTime(&Now);
378
pAd->CommonCfg.BeaconPeriod;
380
TbttNumToNextWakeUp =
381
pAd->StaCfg.DefaultListenCount;
382
if (OPSTATUS_TEST_FLAG
383
(pAd, fOP_STATUS_RECEIVE_DTIM)
384
&& (TbttNumToNextWakeUp > NextDtim))
385
TbttNumToNextWakeUp = NextDtim;
387
RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
388
/* if WMM-APSD is failed, try to disable following line */
389
AsicSleepThenAutoWakeup(pAd,
390
TbttNumToNextWakeUp);
394
if ((pHeader->FC.MoreData)
395
&& (pAd->CommonCfg.bInServicePeriod)) {
396
DBGPRINT(RT_DEBUG_TRACE,
397
("Sending another trigger frame when More Data bit is set to 1\n"));
400
/* Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame */
401
if ((pHeader->FC.SubType & 0x04)) /* bit 2 : no DATA */
404
RELEASE_NDIS_PACKET(pAd, pRxPacket,
405
NDIS_STATUS_FAILURE);
408
/* Drop not my BSS frame (we can not only check the MyBss bit in RxD) */
411
/* Infrastructure mode, check address 2 for BSSID */
413
(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) {
414
/* Receive frame not my BSSID */
416
RELEASE_NDIS_PACKET(pAd, pRxPacket,
417
NDIS_STATUS_FAILURE);
420
} else /* Ad-Hoc mode or Not associated */
422
/* Ad-Hoc mode, check address 3 for BSSID */
424
(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) {
425
/* Receive frame not my BSSID */
427
RELEASE_NDIS_PACKET(pAd, pRxPacket,
428
NDIS_STATUS_FAILURE);
436
if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) {
437
pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
439
/* 1. release packet if infra mode */
440
/* 2. new a pEntry if ad-hoc mode */
441
RELEASE_NDIS_PACKET(pAd, pRxPacket,
442
NDIS_STATUS_FAILURE);
446
/* infra or ad-hoc */
448
RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
449
ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
451
/* check Atheros Client */
452
if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1)
453
&& (pHeader->FC.Retry)) {
454
pEntry->bIAmBadAtheros = TRUE;
455
pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
456
pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
457
if (!STA_AES_ON(pAd)) {
458
AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE,
464
pRxBlk->pData = (u8 *) pHeader;
467
/* update RxBlk->pData, DataSize */
468
/* 802.11 Header, QOS, HTC, Hw Padding */
471
/* 1. skip 802.11 HEADER */
473
pRxBlk->pData += LENGTH_802_11;
474
pRxBlk->DataSize -= LENGTH_802_11;
478
if (pHeader->FC.SubType & 0x08) {
479
RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
480
UserPriority = *(pRxBlk->pData) & 0x0f;
481
/* bit 7 in QoS Control field signals the HT A-MSDU format */
482
if ((*pRxBlk->pData) & 0x80) {
483
RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
485
/* skip QOS contorl field */
487
pRxBlk->DataSize -= 2;
489
pRxBlk->UserPriority = UserPriority;
491
/* check if need to resend PS Poll when received packet with MoreData = 1 */
492
if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) {
493
if ((((UserPriority == 0) || (UserPriority == 3)) &&
494
pAd->CommonCfg.bAPSDAC_BE == 0) ||
495
(((UserPriority == 1) || (UserPriority == 2)) &&
496
pAd->CommonCfg.bAPSDAC_BK == 0) ||
497
(((UserPriority == 4) || (UserPriority == 5)) &&
498
pAd->CommonCfg.bAPSDAC_VI == 0) ||
499
(((UserPriority == 6) || (UserPriority == 7)) &&
500
pAd->CommonCfg.bAPSDAC_VO == 0)) {
501
/* non-UAPSD delivery-enabled AC */
502
RTMP_PS_POLL_ENQUEUE(pAd);
505
/* 3. Order bit: A-Ralink or HTC+ */
506
if (pHeader->FC.Order) {
507
#ifdef AGGREGATION_SUPPORT
508
if ((pRxWI->PHYMODE <= MODE_OFDM)
509
&& (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
511
RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
513
#endif /* AGGREGATION_SUPPORT // */
515
RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
516
/* skip HTC contorl field */
518
pRxBlk->DataSize -= 4;
521
/* 4. skip HW padding */
523
/* just move pData pointer */
524
/* because DataSize excluding HW padding */
525
RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
530
RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
533
/* Case I Process Broadcast & Multicast data frame */
535
if (pRxD->Bcast || pRxD->Mcast) {
536
INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
538
/* Drop Mcast/Bcast frame with fragment bit on */
539
if (pHeader->FC.MoreFrag) {
541
RELEASE_NDIS_PACKET(pAd, pRxPacket,
542
NDIS_STATUS_FAILURE);
545
/* Filter out Bcast frame which AP relayed for us */
547
&& MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) {
549
RELEASE_NDIS_PACKET(pAd, pRxPacket,
550
NDIS_STATUS_FAILURE);
554
Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
556
} else if (pRxD->U2M) {
558
(u16)((pRxWI->MCS) + (pRxWI->BW << 7) +
559
(pRxWI->ShortGI << 8) + (pRxWI->PHYMODE << 14));
562
pEntry = MacTableLookup(pAd, pHeader->Addr2);
564
Update_Rssi_Sample(pAd, &pEntry->RssiSample,
568
Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
570
pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
571
pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
573
pAd->RalinkCounters.OneSecRxOkDataCnt++;
575
if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) {
576
/* re-assemble the fragmented packets */
577
/* return complete frame (pRxPacket) or NULL */
579
pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
583
pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
585
/* process complete frame */
586
if (bFragment && (pRxD->Decrypted)
587
&& (pEntry->WepStatus ==
588
Ndis802_11Encryption2Enabled)) {
589
/* Minus MIC length */
590
pRxBlk->DataSize -= 8;
592
/* For TKIP frame, calculate the MIC value */
593
if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) ==
599
STARxDataFrameAnnounce(pAd, pEntry, pRxBlk,
604
/* because RTMPDeFragmentDataFrame() will release rx packet, */
605
/* if packet is fragmented */
612
RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
615
void STAHandleRxMgmtFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
617
PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
618
struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
619
struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
620
void *pRxPacket = pRxBlk->pRxPacket;
624
/* check if need to resend PS Poll when received packet with MoreData = 1 */
625
if ((pAd->StaCfg.Psm == PWR_SAVE)
626
&& (pHeader->FC.MoreData == 1)) {
627
/* for UAPSD, all management frames will be VO priority */
628
if (pAd->CommonCfg.bAPSDAC_VO == 0) {
629
/* non-UAPSD delivery-enabled AC */
630
RTMP_PS_POLL_ENQUEUE(pAd);
634
/* TODO: if MoreData == 0, station can go to sleep */
636
/* We should collect RSSI not only U2M data but also my beacon */
637
if ((pHeader->FC.SubType == SUBTYPE_BEACON)
638
&& (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
639
&& (pAd->RxAnt.EvaluatePeriod == 0)) {
640
Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
642
pAd->StaCfg.LastSNR0 = (u8)(pRxWI->SNR0);
643
pAd->StaCfg.LastSNR1 = (u8)(pRxWI->SNR1);
646
/* First check the size, it MUST not exceed the mlme queue size */
647
if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE) {
648
DBGPRINT_ERR("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount);
652
REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader,
653
pRxWI->MPDUtotalByteCount,
654
pRxWI->RSSI0, pRxWI->RSSI1,
655
pRxWI->RSSI2, pRxD->PlcpSignal);
658
RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
661
void STAHandleRxControlFrame(struct rt_rtmp_adapter *pAd, struct rt_rx_blk *pRxBlk)
663
struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
664
struct rt_header_802_11 * pHeader = pRxBlk->pHeader;
665
void *pRxPacket = pRxBlk->pRxPacket;
667
switch (pHeader->FC.SubType) {
668
case SUBTYPE_BLOCK_ACK_REQ:
670
CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID,
671
(pRxWI->MPDUtotalByteCount),
672
(struct rt_frame_ba_req *) pHeader);
675
case SUBTYPE_BLOCK_ACK:
681
RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
685
========================================================================
688
Process RxDone interrupt, running in DPC level
691
pAd Pointer to our adapter
696
IRQL = DISPATCH_LEVEL
699
This routine has to maintain Rx ring read pointer.
700
Need to consider QOS DATA format when converting to 802.3
701
========================================================================
703
BOOLEAN STARxDoneInterruptHandle(struct rt_rtmp_adapter *pAd, IN BOOLEAN argc)
706
u32 RxProcessed, RxPending;
707
BOOLEAN bReschedule = FALSE;
708
PRT28XX_RXD_STRUC pRxD;
710
struct rt_rxwi * pRxWI;
712
struct rt_header_802_11 * pHeader;
713
struct rt_rx_blk RxCell;
715
RxProcessed = RxPending = 0;
717
/* process whole rx ring */
720
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
721
fRTMP_ADAPTER_RESET_IN_PROGRESS |
722
fRTMP_ADAPTER_HALT_IN_PROGRESS |
723
fRTMP_ADAPTER_NIC_NOT_EXIST) ||
724
!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) {
728
if (RxProcessed++ > MAX_RX_PROCESS_CNT) {
729
/* need to reschedule rx handle */
733
#endif /* RTMP_MAC_PCI // */
735
RxProcessed++; /* test */
737
/* 1. allocate a new data packet into rx ring to replace received packet */
738
/* then processing the received packet */
739
/* 2. the callee must take charge of release of packet */
740
/* 3. As far as driver is concerned , */
741
/* the rx packet must */
742
/* a. be indicated to upper layer or */
743
/* b. be released if it is discarded */
745
GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule,
747
if (pRxPacket == NULL) {
748
/* no more packet to process */
751
/* get rx ring descriptor */
752
pRxD = &(RxCell.RxD);
753
/* get rx data buffer */
754
pData = GET_OS_PKT_DATAPTR(pRxPacket);
755
pRxWI = (struct rt_rxwi *) pData;
756
pHeader = (struct rt_header_802_11 *) (pData + RXWI_SIZE);
759
RxCell.pRxWI = pRxWI;
760
RxCell.pHeader = pHeader;
761
RxCell.pRxPacket = pRxPacket;
762
RxCell.pData = (u8 *) pHeader;
763
RxCell.DataSize = pRxWI->MPDUtotalByteCount;
766
/* Increase Total receive byte counter after real data received no mater any error or not */
767
pAd->RalinkCounters.ReceivedByteCount +=
768
pRxWI->MPDUtotalByteCount;
769
pAd->RalinkCounters.OneSecReceivedByteCount +=
770
pRxWI->MPDUtotalByteCount;
771
pAd->RalinkCounters.RxCount++;
773
INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
775
if (pRxWI->MPDUtotalByteCount < 14)
776
Status = NDIS_STATUS_FAILURE;
778
if (MONITOR_ON(pAd)) {
779
send_monitor_packets(pAd, &RxCell);
783
/* STARxDoneInterruptHandle() is called in rtusb_bulk.c */
785
/* Check for all RxD errors */
786
Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
788
/* Handle the received frame */
789
if (Status == NDIS_STATUS_SUCCESS) {
790
switch (pHeader->FC.Type) {
791
/* CASE I, receive a DATA frame */
794
/* process DATA frame */
795
STAHandleRxDataFrame(pAd, &RxCell);
798
/* CASE II, receive a MGMT frame */
801
STAHandleRxMgmtFrame(pAd, &RxCell);
804
/* CASE III. receive a CNTL frame */
807
STAHandleRxControlFrame(pAd, &RxCell);
810
/* discard other type */
812
RELEASE_NDIS_PACKET(pAd, pRxPacket,
813
NDIS_STATUS_FAILURE);
817
pAd->Counters8023.RxErrors++;
818
/* discard this frame */
819
RELEASE_NDIS_PACKET(pAd, pRxPacket,
820
NDIS_STATUS_FAILURE);
828
========================================================================
832
pAd Pointer to our adapter
834
IRQL = DISPATCH_LEVEL
836
========================================================================
838
void RTMPHandleTwakeupInterrupt(struct rt_rtmp_adapter *pAd)
840
AsicForceWakeup(pAd, FALSE);
844
========================================================================
846
Early checking and OS-depened parsing for Tx packet send to our STA driver.
849
void * MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
850
void ** ppPacketArray The packet array need to do transmission.
851
u32 NumberOfPackets Number of packet in packet array.
857
This function does early checking and classification for send-out packet.
858
You only can put OS-depened & STA related code in here.
859
========================================================================
861
void STASendPackets(void *MiniportAdapterContext,
862
void **ppPacketArray, u32 NumberOfPackets)
865
struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)MiniportAdapterContext;
867
BOOLEAN allowToSend = FALSE;
869
for (Index = 0; Index < NumberOfPackets; Index++) {
870
pPacket = ppPacketArray[Index];
873
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)
874
|| RTMP_TEST_FLAG(pAd,
875
fRTMP_ADAPTER_HALT_IN_PROGRESS)
876
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) {
877
/* Drop send request since hardware is in reset state */
879
} else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd)) {
880
/* Drop send request since there are no physical connection yet */
883
/* Record that orignal packet source is from NDIS layer,so that */
884
/* later on driver knows how to release this NDIS PACKET */
885
RTMP_SET_PACKET_WCID(pPacket, 0); /* this field is useless when in STA mode */
886
RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
887
NDIS_SET_PACKET_STATUS(pPacket,
888
NDIS_STATUS_PENDING);
889
pAd->RalinkCounters.PendingNdisPacketCount++;
895
if (allowToSend == TRUE)
896
STASendPacket(pAd, pPacket);
898
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
901
/* Dequeue outgoing frames from TxSwQueue[] and process it */
902
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
907
========================================================================
909
This routine is used to do packet parsing and classification for Tx packet
910
to STA device, and it will en-queue packets to our TxSwQueue depends on AC
914
pAd Pointer to our adapter
915
pPacket Pointer to send packet
918
NDIS_STATUS_SUCCESS If success to queue the packet into TxSwQueue.
919
NDIS_STATUS_FAILURE If failed to do en-queue.
922
You only can put OS-indepened & STA related code in here.
923
========================================================================
925
int STASendPacket(struct rt_rtmp_adapter *pAd, void *pPacket)
927
struct rt_packet_info PacketInfo;
933
u8 QueIdx, UserPriority;
934
struct rt_mac_table_entry *pEntry = NULL;
935
unsigned int IrqFlags;
939
/* Prepare packet information structure for buffer descriptor */
940
/* chained within a single NDIS packet. */
941
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
943
if (pSrcBufVA == NULL) {
944
DBGPRINT(RT_DEBUG_ERROR,
945
("STASendPacket --> pSrcBufVA == NULL !SrcBufLen=%x\n",
947
/* Resource is low, system did not allocate virtual address */
948
/* return NDIS_STATUS_FAILURE directly to upper layer */
949
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
950
return NDIS_STATUS_FAILURE;
953
if (SrcBufLen < 14) {
954
DBGPRINT(RT_DEBUG_ERROR,
955
("STASendPacket --> Ndis Packet buffer error!\n"));
956
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
957
return (NDIS_STATUS_FAILURE);
959
/* In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. */
960
/* Note multicast packets in adhoc also use BSSID_WCID index. */
964
pEntry = &pAd->MacTab.Content[BSSID_WCID];
965
RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
966
Rate = pAd->CommonCfg.TxRate;
968
} else if (ADHOC_ON(pAd)) {
969
if (*pSrcBufVA & 0x01) {
970
RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
971
pEntry = &pAd->MacTab.Content[MCAST_WCID];
973
pEntry = MacTableLookup(pAd, pSrcBufVA);
975
Rate = pAd->CommonCfg.TxRate;
980
DBGPRINT(RT_DEBUG_ERROR,
981
("STASendPacket->Cannot find pEntry(%pM) in MacTab!\n",
983
/* Resource is low, system did not allocate virtual address */
984
/* return NDIS_STATUS_FAILURE directly to upper layer */
985
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
986
return NDIS_STATUS_FAILURE;
991
RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
994
/* Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. */
995
/* Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). */
996
RTMPCheckEtherType(pAd, pPacket);
999
/* WPA 802.1x secured port control - drop all non-802.1x frame before port secured */
1001
if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1002
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1003
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1004
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1005
|| (pAd->StaCfg.IEEE8021X == TRUE)
1007
&& ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
1008
|| (pAd->StaCfg.MicErrCnt >= 2))
1009
&& (RTMP_GET_PACKET_EAPOL(pPacket) == FALSE)
1011
DBGPRINT(RT_DEBUG_TRACE,
1012
("STASendPacket --> Drop packet before port secured!\n"));
1013
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1015
return (NDIS_STATUS_FAILURE);
1018
/* STEP 1. Decide number of fragments required to deliver this MSDU. */
1019
/* The estimation here is not very accurate because difficult to */
1020
/* take encryption overhead into consideration here. The result */
1021
/* "NumberOfFrag" is then just used to pre-check if enough free */
1022
/* TXD are available to hold this MSDU. */
1024
if (*pSrcBufVA & 0x01) /* fragmentation not allowed on multicast & broadcast */
1026
else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
1027
NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1028
else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
1029
NumberOfFrag = 1; /* Aggregation overwhelms fragmentation */
1030
else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX)
1031
|| (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
1032
NumberOfFrag = 1; /* MIMO RATE overwhelms fragmentation */
1034
/* The calculated "NumberOfFrag" is a rough estimation because of various */
1035
/* encryption/encapsulation overhead not taken into consideration. This number is just */
1036
/* used to make sure enough free TXD are available before fragmentation takes place. */
1037
/* In case the actual required number of fragments of an NDIS packet */
1038
/* excceeds "NumberOfFrag"caculated here and not enough free TXD available, the */
1039
/* last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of */
1040
/* resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should */
1041
/* rarely happen and the penalty is just like a TX RETRY fail. Affordable. */
1044
(pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 -
1047
((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1048
LENGTH_802_1_H) / AllowFragSize) + 1;
1049
/* To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size */
1050
if (((PacketInfo.TotalPacketLength - LENGTH_802_3 +
1051
LENGTH_802_1_H) % AllowFragSize) == 0) {
1056
/* Save fragment number to Ndis packet reserved field */
1057
RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1059
/* STEP 2. Check the requirement of RTS: */
1060
/* If multiple fragment required, RTS is required only for the first fragment */
1061
/* if the fragment size is larger than RTS threshold */
1062
/* For RT28xx, Let ASIC send RTS/CTS */
1063
/* RTMP_SET_PACKET_RTS(pPacket, 0); */
1064
if (NumberOfFrag > 1)
1066
(pAd->CommonCfg.FragmentThreshold >
1067
pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1070
(PacketInfo.TotalPacketLength >
1071
pAd->CommonCfg.RtsThreshold) ? 1 : 0;
1073
/* Save RTS requirement to Ndis packet reserved field */
1074
RTMP_SET_PACKET_RTS(pPacket, RTSRequired);
1075
RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1078
/* STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> */
1082
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1083
CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) {
1085
u8 LlcSnapLen = 0, Byte0, Byte1;
1087
/* get Ethernet protocol field */
1089
(u16)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1090
if (Protocol <= 1500) {
1091
/* get Ethernet protocol field from LLC/SNAP */
1092
if (Sniff2BytesFromNdisBuffer
1093
(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6,
1094
&Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1097
Protocol = (u16)((Byte0 << 8) + Byte1);
1100
/* always AC_BE for non-IP packet */
1101
if (Protocol != 0x0800)
1105
if (Sniff2BytesFromNdisBuffer
1106
(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen,
1107
&Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1110
/* return AC_BE if packet is not IPv4 */
1111
if ((Byte0 & 0xf0) != 0x40)
1115
UserPriority = (Byte1 & 0xe0) >> 5;
1116
QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1118
/* TODO: have to check ACM bit. apply TSPEC if ACM is ON */
1119
/* TODO: downgrade UP & QueIdx before passing ACM */
1121
Under WMM ACM control, we dont need to check the bit;
1122
Or when a TSPEC is built for VO but we will change to issue
1123
BA session for BE here, so we will not use BA to send VO packets.
1125
if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) {
1132
RTMP_SET_PACKET_UP(pPacket, UserPriority);
1134
/* Make sure SendTxWait queue resource won't be used by other threads */
1135
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1136
if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) {
1137
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1138
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1140
return NDIS_STATUS_FAILURE;
1142
InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx],
1143
PACKET_TO_QUEUE_ENTRY(pPacket));
1145
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1147
if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE) &&
1148
IS_HT_STA(pEntry)) {
1149
/*struct rt_mac_table_entry *pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; */
1150
if (((pEntry->TXBAbitmap & (1 << UserPriority)) == 0) &&
1151
((pEntry->BADeclineBitmap & (1 << UserPriority)) == 0) &&
1152
(pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1153
/* For IOT compatibility, if */
1154
/* 1. It is Ralink chip or */
1155
/* 2. It is OPEN or AES mode, */
1156
/* then BA session can be bulit. */
1157
&& ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0)
1158
|| (pEntry->WepStatus != Ndis802_11WEPEnabled
1159
&& pEntry->WepStatus !=
1160
Ndis802_11Encryption2Enabled))
1162
BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10,
1167
pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; /* TODO: for debug only. to be removed */
1168
return NDIS_STATUS_SUCCESS;
1172
========================================================================
1174
Routine Description:
1175
This subroutine will scan through relative ring descriptor to find
1176
out available free ring descriptor and compare with request size.
1179
pAd Pointer to our adapter
1180
QueIdx Selected TX Ring
1183
NDIS_STATUS_FAILURE Not enough free descriptor
1184
NDIS_STATUS_SUCCESS Enough free descriptor
1186
IRQL = PASSIVE_LEVEL
1187
IRQL = DISPATCH_LEVEL
1191
========================================================================
1194
int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1196
u8 NumberRequired, u8 *FreeNumberIs)
1198
unsigned long FreeNumber = 0;
1199
int Status = NDIS_STATUS_FAILURE;
1206
if (pAd->TxRing[QueIdx].TxSwFreeIdx >
1207
pAd->TxRing[QueIdx].TxCpuIdx)
1209
pAd->TxRing[QueIdx].TxSwFreeIdx -
1210
pAd->TxRing[QueIdx].TxCpuIdx - 1;
1213
pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE -
1214
pAd->TxRing[QueIdx].TxCpuIdx - 1;
1216
if (FreeNumber >= NumberRequired)
1217
Status = NDIS_STATUS_SUCCESS;
1221
if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
1223
pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx -
1227
pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE -
1228
pAd->MgmtRing.TxCpuIdx - 1;
1230
if (FreeNumber >= NumberRequired)
1231
Status = NDIS_STATUS_SUCCESS;
1235
DBGPRINT(RT_DEBUG_ERROR,
1236
("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1239
*FreeNumberIs = (u8)FreeNumber;
1243
#endif /* RTMP_MAC_PCI // */
1246
Actually, this function used to check if the TxHardware Queue still has frame need to send.
1247
If no frame need to send, go to sleep, else, still wake up.
1249
int RTMPFreeTXDRequest(struct rt_rtmp_adapter *pAd,
1251
u8 NumberRequired, u8 *FreeNumberIs)
1253
/*unsigned long FreeNumber = 0; */
1254
int Status = NDIS_STATUS_FAILURE;
1255
unsigned long IrqFlags;
1256
struct rt_ht_tx_context *pHTTXContext;
1264
pHTTXContext = &pAd->TxContext[QueIdx];
1265
RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx],
1267
if ((pHTTXContext->CurWritePosition !=
1268
pHTTXContext->ENextBulkOutPosition)
1269
|| (pHTTXContext->IRPPending == TRUE)) {
1270
Status = NDIS_STATUS_FAILURE;
1272
Status = NDIS_STATUS_SUCCESS;
1274
RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx],
1279
if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1280
Status = NDIS_STATUS_FAILURE;
1282
Status = NDIS_STATUS_SUCCESS;
1285
DBGPRINT(RT_DEBUG_ERROR,
1286
("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1292
#endif /* RTMP_MAC_USB // */
1294
void RTMPSendDisassociationFrame(struct rt_rtmp_adapter *pAd)
1298
void RTMPSendNullFrame(struct rt_rtmp_adapter *pAd,
1299
u8 TxRate, IN BOOLEAN bQosNull)
1302
unsigned long Length;
1303
struct rt_header_802_11 * pHeader_802_11;
1305
/* WPA 802.1x secured port control */
1306
if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1307
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1308
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1309
(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1310
|| (pAd->StaCfg.IEEE8021X == TRUE)
1311
) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) {
1315
NdisZeroMemory(NullFrame, 48);
1316
Length = sizeof(struct rt_header_802_11);
1318
pHeader_802_11 = (struct rt_header_802_11 *) NullFrame;
1320
pHeader_802_11->FC.Type = BTYPE_DATA;
1321
pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1322
pHeader_802_11->FC.ToDs = 1;
1323
COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1324
COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1325
COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1327
if (pAd->CommonCfg.bAPSDForcePowerSave) {
1328
pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1330
pHeader_802_11->FC.PwrMgmt =
1331
(pAd->StaCfg.Psm == PWR_SAVE) ? 1 : 0;
1333
pHeader_802_11->Duration =
1334
pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1337
pHeader_802_11->Sequence = pAd->Sequence;
1339
/* Prepare QosNull function frame */
1341
pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1343
/* copy QOS control bytes */
1344
NullFrame[Length] = 0;
1345
NullFrame[Length + 1] = 0;
1346
Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
1349
HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1353
/* IRQL = DISPATCH_LEVEL */
1354
void RTMPSendRTSFrame(struct rt_rtmp_adapter *pAd,
1356
IN unsigned int NextMpduSize,
1359
u16 AckDuration, u8 QueIdx, u8 FrameGap)
1363
/* -------------------------------------------------------- */
1364
/* FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM */
1365
/* Find the WPA key, either Group or Pairwise Key */
1366
/* LEAP + TKIP also use WPA key. */
1367
/* -------------------------------------------------------- */
1368
/* Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst */
1369
/* In Cisco CCX 2.0 Leap Authentication */
1370
/* WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey */
1371
/* Instead of the SharedKey, SharedKey Length may be Zero. */
1372
void STAFindCipherAlgorithm(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1374
NDIS_802_11_ENCRYPTION_STATUS Cipher; /* To indicate cipher used for this packet */
1375
u8 CipherAlg = CIPHER_NONE; /* cipher alogrithm */
1378
struct rt_cipher_key *pKey = NULL;
1380
pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1384
if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1385
Cipher = pAd->StaCfg.GroupCipher; /* Cipher for Multicast or Broadcast */
1387
Cipher = pAd->StaCfg.PairCipher; /* Cipher for Unicast */
1389
if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) {
1390
ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <=
1393
/* 4-way handshaking frame must be clear */
1394
if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))
1395
&& (pAd->SharedKey[BSS0][0].CipherAlg)
1396
&& (pAd->SharedKey[BSS0][0].KeyLen)) {
1397
CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1400
} else if (Cipher == Ndis802_11Encryption1Enabled) {
1401
KeyIdx = pAd->StaCfg.DefaultKeyId;
1402
} else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1403
(Cipher == Ndis802_11Encryption3Enabled)) {
1404
if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) /* multicast */
1405
KeyIdx = pAd->StaCfg.DefaultKeyId;
1406
else if (pAd->SharedKey[BSS0][0].KeyLen)
1409
KeyIdx = pAd->StaCfg.DefaultKeyId;
1413
CipherAlg = CIPHER_NONE;
1414
else if ((Cipher == Ndis802_11EncryptionDisabled)
1415
|| (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1416
CipherAlg = CIPHER_NONE;
1417
else if (pAd->StaCfg.WpaSupplicantUP &&
1418
(Cipher == Ndis802_11Encryption1Enabled) &&
1419
(pAd->StaCfg.IEEE8021X == TRUE) &&
1420
(pAd->StaCfg.PortSecured ==
1421
WPA_802_1X_PORT_NOT_SECURED))
1422
CipherAlg = CIPHER_NONE;
1424
/*Header_802_11.FC.Wep = 1; */
1425
CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1426
pKey = &pAd->SharedKey[BSS0][KeyIdx];
1430
pTxBlk->CipherAlg = CipherAlg;
1431
pTxBlk->pKey = pKey;
1434
void STABuildCommon802_11Header(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1436
struct rt_header_802_11 *pHeader_802_11;
1439
/* MAKE A COMMON 802.11 HEADER */
1442
/* normal wlan header size : 24 octets */
1443
pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1446
(struct rt_header_802_11 *) & pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1448
NdisZeroMemory(pHeader_802_11, sizeof(struct rt_header_802_11));
1450
pHeader_802_11->FC.FrDs = 0;
1451
pHeader_802_11->FC.Type = BTYPE_DATA;
1452
pHeader_802_11->FC.SubType =
1453
((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA :
1456
if (pTxBlk->pMacEntry) {
1457
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS)) {
1458
pHeader_802_11->Sequence =
1459
pTxBlk->pMacEntry->NonQosDataSeq;
1460
pTxBlk->pMacEntry->NonQosDataSeq =
1461
(pTxBlk->pMacEntry->NonQosDataSeq + 1) & MAXSEQ;
1464
pHeader_802_11->Sequence =
1465
pTxBlk->pMacEntry->TxSeq[pTxBlk->
1467
pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] =
1468
(pTxBlk->pMacEntry->
1469
TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1473
pHeader_802_11->Sequence = pAd->Sequence;
1474
pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
1477
pHeader_802_11->Frag = 0;
1479
pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1482
if (INFRA_ON(pAd)) {
1484
COPY_MAC_ADDR(pHeader_802_11->Addr1,
1485
pAd->CommonCfg.Bssid);
1486
COPY_MAC_ADDR(pHeader_802_11->Addr2,
1487
pAd->CurrentAddress);
1488
COPY_MAC_ADDR(pHeader_802_11->Addr3,
1489
pTxBlk->pSrcBufHeader);
1490
pHeader_802_11->FC.ToDs = 1;
1492
} else if (ADHOC_ON(pAd)) {
1493
COPY_MAC_ADDR(pHeader_802_11->Addr1,
1494
pTxBlk->pSrcBufHeader);
1495
COPY_MAC_ADDR(pHeader_802_11->Addr2,
1496
pAd->CurrentAddress);
1497
COPY_MAC_ADDR(pHeader_802_11->Addr3,
1498
pAd->CommonCfg.Bssid);
1499
pHeader_802_11->FC.ToDs = 0;
1503
if (pTxBlk->CipherAlg != CIPHER_NONE)
1504
pHeader_802_11->FC.Wep = 1;
1506
/* ----------------------------------------------------------------- */
1507
/* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1508
/* ----------------------------------------------------------------- */
1509
if (pAd->CommonCfg.bAPSDForcePowerSave)
1510
pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1512
pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1515
void STABuildCache802_11Header(struct rt_rtmp_adapter *pAd,
1516
struct rt_tx_blk *pTxBlk, u8 * pHeader)
1518
struct rt_mac_table_entry *pMacEntry;
1519
struct rt_header_802_11 * pHeader80211;
1521
pHeader80211 = (struct rt_header_802_11 *) pHeader;
1522
pMacEntry = pTxBlk->pMacEntry;
1525
/* Update the cached 802.11 HEADER */
1528
/* normal wlan header size : 24 octets */
1529
pTxBlk->MpduHeaderLen = sizeof(struct rt_header_802_11);
1532
pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1535
pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1536
pMacEntry->TxSeq[pTxBlk->UserPriority] =
1537
(pMacEntry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ;
1540
/* Check if the frame can be sent through DLS direct link interface */
1541
/* If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability) */
1543
/* The addr3 of normal packet send from DS is Dest Mac address. */
1545
COPY_MAC_ADDR(pHeader80211->Addr3,
1546
pAd->CommonCfg.Bssid);
1548
COPY_MAC_ADDR(pHeader80211->Addr3,
1549
pTxBlk->pSrcBufHeader);
1552
/* ----------------------------------------------------------------- */
1553
/* STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. */
1554
/* ----------------------------------------------------------------- */
1555
if (pAd->CommonCfg.bAPSDForcePowerSave)
1556
pHeader80211->FC.PwrMgmt = PWR_SAVE;
1558
pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1561
static inline u8 *STA_Build_ARalink_Frame_Header(struct rt_rtmp_adapter *pAd,
1562
struct rt_tx_blk *pTxBlk)
1565
struct rt_header_802_11 *pHeader_802_11;
1568
struct rt_queue_entry *pQEntry;
1570
STAFindCipherAlgorithm(pAd, pTxBlk);
1571
STABuildCommon802_11Header(pAd, pTxBlk);
1573
pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1574
pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1576
/* steal "order" bit to mark "aggregation" */
1577
pHeader_802_11->FC.Order = 1;
1579
/* skip common header */
1580
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1582
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
1584
/* build QOS Control bytes */
1586
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1588
*(pHeaderBufPtr + 1) = 0;
1590
pTxBlk->MpduHeaderLen += 2;
1592
/* padding at front of LLC header. LLC header should at 4-bytes alignment. */
1593
pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1594
pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1595
pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1597
/* For RA Aggregation, */
1598
/* put the 2nd MSDU length(extra 2-byte field) after struct rt_qos_control in little endian format */
1599
pQEntry = pTxBlk->TxPacketList.Head;
1600
pNextPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1601
nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1602
if (RTMP_GET_PACKET_VLAN(pNextPacket))
1603
nextBufLen -= LENGTH_802_1Q;
1605
*pHeaderBufPtr = (u8)nextBufLen & 0xff;
1606
*(pHeaderBufPtr + 1) = (u8)(nextBufLen >> 8);
1609
pTxBlk->MpduHeaderLen += 2;
1611
return pHeaderBufPtr;
1615
static inline u8 *STA_Build_AMSDU_Frame_Header(struct rt_rtmp_adapter *pAd,
1616
struct rt_tx_blk *pTxBlk)
1618
u8 *pHeaderBufPtr; /*, pSaveBufPtr; */
1619
struct rt_header_802_11 *pHeader_802_11;
1621
STAFindCipherAlgorithm(pAd, pTxBlk);
1622
STABuildCommon802_11Header(pAd, pTxBlk);
1624
pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1625
pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1627
/* skip common header */
1628
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1631
/* build QOS Control bytes */
1633
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1638
*pHeaderBufPtr |= 0x80;
1640
*(pHeaderBufPtr + 1) = 0;
1642
pTxBlk->MpduHeaderLen += 2;
1644
/*pSaveBufPtr = pHeaderBufPtr; */
1647
/* padding at front of LLC header */
1648
/* LLC header should locate at 4-octets aligment */
1650
/* @@@ MpduHeaderLen excluding padding @@@ */
1652
pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1653
pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1654
pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1656
return pHeaderBufPtr;
1660
void STA_AMPDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1662
struct rt_header_802_11 *pHeader_802_11;
1665
struct rt_mac_table_entry *pMacEntry;
1667
struct rt_queue_entry *pQEntry;
1671
while (pTxBlk->TxPacketList.Head) {
1672
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1673
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1674
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1675
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1676
NDIS_STATUS_FAILURE);
1681
(RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1683
pMacEntry = pTxBlk->pMacEntry;
1684
if (pMacEntry->isCached) {
1685
/* NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]! */
1686
NdisMoveMemory((u8 *)& pTxBlk->
1687
HeaderBuf[TXINFO_SIZE],
1688
(u8 *)& pMacEntry->CachedBuf[0],
1689
TXWI_SIZE + sizeof(struct rt_header_802_11));
1692
HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1693
STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1695
STAFindCipherAlgorithm(pAd, pTxBlk);
1696
STABuildCommon802_11Header(pAd, pTxBlk);
1699
&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1702
pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
1704
/* skip common header */
1705
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1708
/* build QOS Control bytes */
1710
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1711
*(pHeaderBufPtr + 1) = 0;
1713
pTxBlk->MpduHeaderLen += 2;
1717
/* HTC control filed following QoS field */
1719
if ((pAd->CommonCfg.bRdg == TRUE)
1720
&& CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry,
1721
fCLIENT_STATUS_RDG_CAPABLE)) {
1722
if (pMacEntry->isCached == FALSE) {
1724
pHeader_802_11->FC.Order = 1;
1726
NdisZeroMemory(pHeaderBufPtr, 4);
1727
*(pHeaderBufPtr + 3) |= 0x80;
1730
pTxBlk->MpduHeaderLen += 4;
1732
/*pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE; */
1733
ASSERT(pTxBlk->MpduHeaderLen >= 24);
1735
/* skip 802.3 header */
1736
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1737
pTxBlk->SrcBufLen -= LENGTH_802_3;
1741
pTxBlk->pSrcBufData += LENGTH_802_1Q;
1742
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1745
/* padding at front of LLC header */
1746
/* LLC header should locate at 4-octets aligment */
1748
/* @@@ MpduHeaderLen excluding padding @@@ */
1750
pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
1751
pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
1752
pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1757
/* Insert LLC-SNAP encapsulation - 8 octets */
1759
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
1762
pExtraLlcSnapEncap);
1763
if (pTxBlk->pExtraLlcSnapEncap) {
1764
NdisMoveMemory(pHeaderBufPtr,
1765
pTxBlk->pExtraLlcSnapEncap, 6);
1767
/* get 2 octets (TypeofLen) */
1768
NdisMoveMemory(pHeaderBufPtr,
1769
pTxBlk->pSrcBufData - 2, 2);
1771
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1776
if (pMacEntry->isCached) {
1777
RTMPWriteTxWI_Cache(pAd,
1778
(struct rt_txwi *) (&pTxBlk->
1783
RTMPWriteTxWI_Data(pAd,
1784
(struct rt_txwi *) (&pTxBlk->
1789
NdisZeroMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1790
sizeof(pMacEntry->CachedBuf));
1791
NdisMoveMemory((u8 *)(&pMacEntry->CachedBuf[0]),
1793
HeaderBuf[TXINFO_SIZE]),
1796
HeaderBuf[TXINFO_SIZE])));
1797
pMacEntry->isCached = TRUE;
1800
/* calculate Transmitted AMPDU count and ByteCount */
1802
pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.
1804
pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.
1805
QuadPart += pTxBlk->SrcBufLen;
1808
/*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
1810
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1815
if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1816
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1818
pAd->RalinkCounters.KickTxCount++;
1819
pAd->RalinkCounters.OneSecTxDoneCount++;
1824
void STA_AMSDU_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1828
u16 subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding. */
1829
u16 totalMPDUSize = 0;
1832
u16 FirstTx = 0, LastTxIdx = 0;
1835
struct rt_queue_entry *pQEntry;
1839
ASSERT((pTxBlk->TxPacketList.Number > 1));
1841
while (pTxBlk->TxPacketList.Head) {
1842
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1843
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1844
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1845
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
1846
NDIS_STATUS_FAILURE);
1851
(RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1853
/* skip 802.3 header */
1854
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1855
pTxBlk->SrcBufLen -= LENGTH_802_3;
1859
pTxBlk->pSrcBufData += LENGTH_802_1Q;
1860
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1863
if (frameNum == 0) {
1865
STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1867
/* NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled. */
1868
RTMPWriteTxWI_Data(pAd,
1869
(struct rt_txwi *) (&pTxBlk->
1874
pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1876
ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD +
1878
4) - (LENGTH_AMSDU_SUBFRAMEHEAD +
1879
subFramePayloadLen);
1880
NdisZeroMemory(pHeaderBufPtr,
1881
padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1882
pHeaderBufPtr += padding;
1883
pTxBlk->MpduHeaderLen = padding;
1887
/* A-MSDU subframe */
1888
/* DA(6)+SA(6)+Length(2) + LLC/SNAP Encap */
1890
subFrameHeader = pHeaderBufPtr;
1891
subFramePayloadLen = pTxBlk->SrcBufLen;
1893
NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1895
pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1896
pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1899
/* Insert LLC-SNAP encapsulation - 8 octets */
1901
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2,
1902
pTxBlk->pExtraLlcSnapEncap);
1904
subFramePayloadLen = pTxBlk->SrcBufLen;
1906
if (pTxBlk->pExtraLlcSnapEncap) {
1907
NdisMoveMemory(pHeaderBufPtr,
1908
pTxBlk->pExtraLlcSnapEncap, 6);
1910
/* get 2 octets (TypeofLen) */
1911
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
1914
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1915
subFramePayloadLen += LENGTH_802_1_H;
1917
/* update subFrame Length field */
1918
subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1919
subFrameHeader[13] = subFramePayloadLen & 0xFF;
1921
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1925
HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1929
HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
1934
pAd->RalinkCounters.KickTxCount++;
1935
pAd->RalinkCounters.OneSecTxDoneCount++;
1937
/* calculate Transmitted AMSDU Count and ByteCount */
1939
pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart++;
1940
pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart +=
1946
HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1947
HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1952
if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
1953
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1956
void STA_Legacy_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
1958
struct rt_header_802_11 *pHeader_802_11;
1962
struct rt_queue_entry *pQEntry;
1966
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1967
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1968
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
1969
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1973
if (pTxBlk->TxFrameType == TX_MCAST_FRAME) {
1974
INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1977
if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1978
TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1980
TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1982
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1984
if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1985
pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1987
STAFindCipherAlgorithm(pAd, pTxBlk);
1988
STABuildCommon802_11Header(pAd, pTxBlk);
1990
/* skip 802.3 header */
1991
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1992
pTxBlk->SrcBufLen -= LENGTH_802_3;
1996
pTxBlk->pSrcBufData += LENGTH_802_1Q;
1997
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2000
pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2001
pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2003
/* skip common header */
2004
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2006
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2008
/* build QOS Control bytes */
2011
((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.
2014
*(pHeaderBufPtr + 1) = 0;
2016
pTxBlk->MpduHeaderLen += 2;
2018
/* The remaining content of MPDU header should locate at 4-octets alignment */
2019
pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2020
pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2021
pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2026
/* Insert LLC-SNAP encapsulation - 8 octets */
2029
/* if original Ethernet frame contains no LLC/SNAP, */
2030
/* then an extra LLC/SNAP encap is required */
2032
EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2033
pTxBlk->pExtraLlcSnapEncap);
2034
if (pTxBlk->pExtraLlcSnapEncap) {
2037
NdisMoveMemory(pHeaderBufPtr,
2038
pTxBlk->pExtraLlcSnapEncap, 6);
2041
vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2042
/* get 2 octets (TypeofLen) */
2043
NdisMoveMemory(pHeaderBufPtr,
2044
pTxBlk->pSrcBufHeader + 12 + vlan_size,
2047
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2053
/* prepare for TXWI */
2054
/* use Wcid as Key Index */
2057
RTMPWriteTxWI_Data(pAd, (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]),
2060
/*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2062
HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
2064
pAd->RalinkCounters.KickTxCount++;
2065
pAd->RalinkCounters.OneSecTxDoneCount++;
2070
if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2071
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2074
void STA_ARalink_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2078
u16 totalMPDUSize = 0;
2079
u16 FirstTx, LastTxIdx;
2082
struct rt_queue_entry *pQEntry;
2086
ASSERT((pTxBlk->TxPacketList.Number == 2));
2088
FirstTx = LastTxIdx = 0; /* Is it ok init they as 0? */
2089
while (pTxBlk->TxPacketList.Head) {
2090
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2091
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2093
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2094
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket,
2095
NDIS_STATUS_FAILURE);
2100
(RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2102
/* skip 802.3 header */
2103
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2104
pTxBlk->SrcBufLen -= LENGTH_802_3;
2108
pTxBlk->pSrcBufData += LENGTH_802_1Q;
2109
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2112
if (frameNum == 0) { /* For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header */
2115
STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2117
/* It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount */
2118
/* will be updated after final frame was handled. */
2119
RTMPWriteTxWI_Data(pAd,
2120
(struct rt_txwi *) (&pTxBlk->
2126
/* Insert LLC-SNAP encapsulation - 8 octets */
2128
EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->
2131
pExtraLlcSnapEncap);
2133
if (pTxBlk->pExtraLlcSnapEncap) {
2134
NdisMoveMemory(pHeaderBufPtr,
2135
pTxBlk->pExtraLlcSnapEncap, 6);
2137
/* get 2 octets (TypeofLen) */
2138
NdisMoveMemory(pHeaderBufPtr,
2139
pTxBlk->pSrcBufData - 2, 2);
2141
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2143
} else { /* For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0. */
2145
pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2146
pTxBlk->MpduHeaderLen = 0;
2148
/* A-Ralink sub-sequent frame header is the same as 802.3 header. */
2149
/* DA(6)+SA(6)+FrameType(2) */
2150
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader,
2152
pHeaderBufPtr += 12;
2153
/* get 2 octets (TypeofLen) */
2154
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2,
2157
pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2160
totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2162
/*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */
2165
HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2169
HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum,
2174
pAd->RalinkCounters.OneSecTxAggregationCount++;
2175
pAd->RalinkCounters.KickTxCount++;
2176
pAd->RalinkCounters.OneSecTxDoneCount++;
2180
HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2181
HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2186
if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2187
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2191
void STA_Fragment_Frame_Tx(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk)
2193
struct rt_header_802_11 *pHeader_802_11;
2197
struct rt_packet_info PacketInfo;
2198
u16 EncryptionOverhead = 0;
2199
u32 FreeMpduSize, SrcRemainingBytes;
2203
struct rt_queue_entry *pQEntry;
2204
HTTRANSMIT_SETTING *pTransmit;
2208
pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2209
pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2210
if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) {
2211
RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2215
ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2216
bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2218
STAFindCipherAlgorithm(pAd, pTxBlk);
2219
STABuildCommon802_11Header(pAd, pTxBlk);
2221
if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2223
duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2224
if (pTxBlk->pPacket == NULL)
2226
RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo,
2227
&pTxBlk->pSrcBufHeader,
2228
&pTxBlk->SrcBufLen);
2230
/* skip 802.3 header */
2231
pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2232
pTxBlk->SrcBufLen -= LENGTH_802_3;
2236
pTxBlk->pSrcBufData += LENGTH_802_1Q;
2237
pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2240
pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2241
pHeader_802_11 = (struct rt_header_802_11 *) pHeaderBufPtr;
2243
/* skip common header */
2244
pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2246
if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) {
2248
/* build QOS Control bytes */
2250
*pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2252
*(pHeaderBufPtr + 1) = 0;
2254
pTxBlk->MpduHeaderLen += 2;
2257
/* padding at front of LLC header */
2258
/* LLC header should locate at 4-octets aligment */
2260
pTxBlk->HdrPadLen = (unsigned long)pHeaderBufPtr;
2261
pHeaderBufPtr = (u8 *)ROUND_UP(pHeaderBufPtr, 4);
2262
pTxBlk->HdrPadLen = (unsigned long)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2265
/* Insert LLC-SNAP encapsulation - 8 octets */
2268
/* if original Ethernet frame contains no LLC/SNAP, */
2269
/* then an extra LLC/SNAP encap is required */
2271
EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader,
2272
pTxBlk->pExtraLlcSnapEncap);
2273
if (pTxBlk->pExtraLlcSnapEncap) {
2276
NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2279
vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2280
/* get 2 octets (TypeofLen) */
2281
NdisMoveMemory(pHeaderBufPtr,
2282
pTxBlk->pSrcBufHeader + 12 + vlan_size, 2);
2284
pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2287
/* If TKIP is used and fragmentation is required. Driver has to */
2288
/* append TKIP MIC at tail of the scatter buffer */
2289
/* MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */
2290
if (pTxBlk->CipherAlg == CIPHER_TKIP) {
2291
RTMPCalculateMICValue(pAd, pTxBlk->pPacket,
2292
pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey,
2295
/* NOTE: DON'T refer the skb->len directly after following copy. Because the length is not adjusted */
2296
/* to correct length, refer to pTxBlk->SrcBufLen for the packet length in following progress. */
2297
NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen,
2298
&pAd->PrivateInfo.Tx.MIC[0], 8);
2299
/*skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8); */
2300
pTxBlk->SrcBufLen += 8;
2301
pTxBlk->TotalFrameLen += 8;
2302
pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2305
/* calculate the overhead bytes that encryption algorithm may add. This */
2306
/* affects the calculate of "duration" field */
2308
if ((pTxBlk->CipherAlg == CIPHER_WEP64)
2309
|| (pTxBlk->CipherAlg == CIPHER_WEP128))
2310
EncryptionOverhead = 8; /*WEP: IV[4] + ICV[4]; */
2311
else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2312
EncryptionOverhead = 12; /*TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength */
2313
else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2314
EncryptionOverhead = 20; /*TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] */
2315
else if (pTxBlk->CipherAlg == CIPHER_AES)
2316
EncryptionOverhead = 16; /* AES: IV[4] + EIV[4] + MIC[8] */
2318
EncryptionOverhead = 0;
2320
pTransmit = pTxBlk->pTransmit;
2321
/* Decide the TX rate */
2322
if (pTransmit->field.MODE == MODE_CCK)
2323
pTxBlk->TxRate = pTransmit->field.MCS;
2324
else if (pTransmit->field.MODE == MODE_OFDM)
2325
pTxBlk->TxRate = pTransmit->field.MCS + RATE_FIRST_OFDM_RATE;
2327
pTxBlk->TxRate = RATE_6_5;
2329
/* decide how much time an ACK/CTS frame will consume in the air */
2330
if (pTxBlk->TxRate <= RATE_LAST_OFDM_RATE)
2332
RTMPCalcDuration(pAd,
2333
pAd->CommonCfg.ExpectedACKRate[pTxBlk->
2337
AckDuration = RTMPCalcDuration(pAd, RATE_6_5, 14);
2339
/* Init the total payload length of this frame. */
2340
SrcRemainingBytes = pTxBlk->SrcBufLen;
2342
pTxBlk->TotalFragNum = 0xff;
2346
FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2348
FreeMpduSize -= pTxBlk->MpduHeaderLen;
2350
if (SrcRemainingBytes <= FreeMpduSize) { /* this is the last or only fragment */
2352
pTxBlk->SrcBufLen = SrcRemainingBytes;
2354
pHeader_802_11->FC.MoreFrag = 0;
2355
pHeader_802_11->Duration =
2356
pAd->CommonCfg.Dsifs + AckDuration;
2358
/* Indicate the lower layer that this's the last fragment. */
2359
pTxBlk->TotalFragNum = fragNum;
2360
} else { /* more fragment is required */
2362
pTxBlk->SrcBufLen = FreeMpduSize;
2365
min(((u32)SrcRemainingBytes - pTxBlk->SrcBufLen),
2366
((u32)pAd->CommonCfg.FragmentThreshold));
2367
pHeader_802_11->FC.MoreFrag = 1;
2368
pHeader_802_11->Duration =
2369
(3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) +
2370
RTMPCalcDuration(pAd, pTxBlk->TxRate,
2371
NextMpduSize + EncryptionOverhead);
2375
pTxBlk->FrameGap = IFS_HTTXOP;
2377
pTxBlk->FrameGap = IFS_SIFS;
2379
RTMPWriteTxWI_Data(pAd,
2380
(struct rt_txwi *) (&pTxBlk->
2381
HeaderBuf[TXINFO_SIZE]),
2384
HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2386
pAd->RalinkCounters.KickTxCount++;
2387
pAd->RalinkCounters.OneSecTxDoneCount++;
2389
/* Update the frame number, remaining size of the NDIS packet payload. */
2391
/* space for 802.11 header. */
2392
if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2393
pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2396
SrcRemainingBytes -= pTxBlk->SrcBufLen;
2397
pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2399
pHeader_802_11->Frag++; /* increase Frag # */
2401
} while (SrcRemainingBytes > 0);
2406
if (!RTMP_TEST_PSFLAG(pAd, fRTMP_PS_DISABLE_TX))
2407
HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2410
#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2411
while(_pTxBlk->TxPacketList.Head) \
2413
_pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2414
RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2418
========================================================================
2420
Routine Description:
2421
Copy frame from waiting queue into relative ring buffer and set
2422
appropriate ASIC register to kick hardware encryption before really
2426
pAd Pointer to our adapter
2427
void * Pointer to outgoing Ndis frame
2428
NumberOfFrag Number of fragment required
2433
IRQL = DISPATCH_LEVEL
2437
========================================================================
2439
int STAHardTransmit(struct rt_rtmp_adapter *pAd,
2440
struct rt_tx_blk *pTxBlk, u8 QueIdx)
2443
struct rt_queue_entry *pQEntry;
2445
/* --------------------------------------------- */
2446
/* STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION. */
2447
/* --------------------------------------------- */
2449
ASSERT(pTxBlk->TxPacketList.Number);
2450
if (pTxBlk->TxPacketList.Head == NULL) {
2451
DBGPRINT(RT_DEBUG_ERROR,
2452
("pTxBlk->TotalFrameNum == %ld!\n",
2453
pTxBlk->TxPacketList.Number));
2454
return NDIS_STATUS_FAILURE;
2457
pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2459
/* ------------------------------------------------------------------ */
2460
/* STEP 1. WAKE UP PHY */
2461
/* outgoing frame always wakeup PHY to prevent frame lost and */
2462
/* turn off PSM bit to improve performance */
2463
/* ------------------------------------------------------------------ */
2464
/* not to change PSM bit, just send this frame out? */
2465
if ((pAd->StaCfg.Psm == PWR_SAVE)
2466
&& OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
2467
DBGPRINT_RAW(RT_DEBUG_INFO, ("AsicForceWakeup At HardTx\n"));
2469
AsicForceWakeup(pAd, TRUE);
2470
#endif /* RTMP_MAC_PCI // */
2472
RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_FORCE_WAKE_UP, NULL, 0);
2473
#endif /* RTMP_MAC_USB // */
2475
/* It should not change PSM bit, when APSD turn on. */
2477
(pAd->CommonCfg.bAPSDCapable
2478
&& pAd->CommonCfg.APEdcaParm.bAPSDCapable)
2479
&& (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2480
|| (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2481
|| (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))) {
2482
if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2483
(pAd->StaCfg.WindowsPowerMode ==
2484
Ndis802_11PowerModeFast_PSP))
2485
RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
2488
switch (pTxBlk->TxFrameType) {
2489
case TX_AMPDU_FRAME:
2490
STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2492
case TX_AMSDU_FRAME:
2493
STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2495
case TX_LEGACY_FRAME:
2496
STA_Legacy_Frame_Tx(pAd, pTxBlk);
2498
case TX_MCAST_FRAME:
2499
STA_Legacy_Frame_Tx(pAd, pTxBlk);
2501
case TX_RALINK_FRAME:
2502
STA_ARalink_Frame_Tx(pAd, pTxBlk);
2505
STA_Fragment_Frame_Tx(pAd, pTxBlk);
2509
/* It should not happened! */
2510
DBGPRINT(RT_DEBUG_ERROR,
2511
("Send a packet was not classified! It should not happen!\n"));
2512
while (pTxBlk->TxPacketList.Number) {
2514
RemoveHeadQueue(&pTxBlk->TxPacketList);
2515
pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2517
RELEASE_NDIS_PACKET(pAd, pPacket,
2518
NDIS_STATUS_FAILURE);
2524
return (NDIS_STATUS_SUCCESS);
2528
unsigned long HashBytesPolynomial(u8 * value, unsigned int len)
2530
unsigned char *word = value;
2531
unsigned int ret = 0;
2534
for (i = 0; i < len; i++) {
2536
ret ^= (unsigned int)(word[i]) << mod;
2537
ret ^= (unsigned int)(word[i]) >> (32 - mod);
2542
void Sta_Announce_or_Forward_802_3_Packet(struct rt_rtmp_adapter *pAd,
2547
announce_802_3_packet(pAd, pPacket);
2549
/* release packet */
2550
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);