blob: 61c39dd7ad013c9e40b784c70414fac62bac908b [file] [log] [blame]
Forest Bond5449c682009-04-25 10:30:44 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: rxtx.c
20 *
21 * Purpose: handle WMAC/802.3/802.11 rx & tx functions
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: May 20, 2003
26 *
27 * Functions:
Gilles Espinassef77f13e2010-03-29 15:41:47 +020028 * s_vGenerateTxParameter - Generate tx dma required parameter.
Forest Bond5449c682009-04-25 10:30:44 -040029 * vGenerateMACHeader - Translate 802.3 to 802.11 header
Justin P. Mattock7664ec82012-08-20 08:43:15 -070030 * cbGetFragCount - Calculate fragment number count
Forest Bond5449c682009-04-25 10:30:44 -040031 * csBeacon_xmit - beacon tx function
32 * csMgmt_xmit - management tx function
33 * s_cbFillTxBufHead - fulfill tx dma buffer header
34 * s_uGetDataDuration - get tx data required duration
35 * s_uFillDataHead- fulfill tx data duration header
Gilles Espinassef77f13e2010-03-29 15:41:47 +020036 * s_uGetRTSCTSDuration- get rtx/cts required duration
Forest Bond5449c682009-04-25 10:30:44 -040037 * s_uGetRTSCTSRsvTime- get rts/cts reserved time
38 * s_uGetTxRsvTime- get frame reserved time
39 * s_vFillCTSHead- fulfill CTS ctl header
Gilles Espinassef77f13e2010-03-29 15:41:47 +020040 * s_vFillFragParameter- Set fragment ctl parameter.
Forest Bond5449c682009-04-25 10:30:44 -040041 * s_vFillRTSHead- fulfill RTS ctl header
42 * s_vFillTxKey- fulfill tx encrypt key
43 * s_vSWencryption- Software encrypt header
44 * vDMA0_tx_80211- tx 802.11 frame via dma0
45 * vGenerateFIFOHeader- Generate tx FIFO ctl header
46 *
47 * Revision History:
48 *
49 */
50
Forest Bond5449c682009-04-25 10:30:44 -040051#include "device.h"
Forest Bond5449c682009-04-25 10:30:44 -040052#include "rxtx.h"
Forest Bond5449c682009-04-25 10:30:44 -040053#include "card.h"
Forest Bond5449c682009-04-25 10:30:44 -040054#include "mac.h"
Forest Bond5449c682009-04-25 10:30:44 -040055#include "baseband.h"
Forest Bond5449c682009-04-25 10:30:44 -040056#include "rf.h"
Forest Bond5449c682009-04-25 10:30:44 -040057
58/*--------------------- Static Definitions -------------------------*/
59
60/*--------------------- Static Classes ----------------------------*/
61
62/*--------------------- Static Variables --------------------------*/
Forest Bond5449c682009-04-25 10:30:44 -040063
Forest Bond5449c682009-04-25 10:30:44 -040064/*--------------------- Static Functions --------------------------*/
65
66/*--------------------- Static Definitions -------------------------*/
67#define CRITICAL_PACKET_LEN 256 // if packet size < 256 -> in-direct send
68 // packet size >= 256 -> direct send
69
Anton Protopopov83e771f2014-07-01 21:06:29 +040070static const unsigned short wTimeStampOff[2][MAX_RATE] = {
Joe Perches547f1cf2013-03-18 10:45:01 -070071 {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble
72 {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble
73};
Forest Bond5449c682009-04-25 10:30:44 -040074
Anton Protopopov83e771f2014-07-01 21:06:29 +040075static const unsigned short wFB_Opt0[2][5] = {
Joe Perches547f1cf2013-03-18 10:45:01 -070076 {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0
77 {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1
78};
Anton Protopopov83e771f2014-07-01 21:06:29 +040079static const unsigned short wFB_Opt1[2][5] = {
Joe Perches547f1cf2013-03-18 10:45:01 -070080 {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0
81 {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1
82};
Forest Bond5449c682009-04-25 10:30:44 -040083
Forest Bond5449c682009-04-25 10:30:44 -040084#define RTSDUR_BB 0
85#define RTSDUR_BA 1
86#define RTSDUR_AA 2
87#define CTSDUR_BA 3
88#define RTSDUR_BA_F0 4
89#define RTSDUR_AA_F0 5
90#define RTSDUR_BA_F1 6
91#define RTSDUR_AA_F1 7
92#define CTSDUR_BA_F0 8
93#define CTSDUR_BA_F1 9
94#define DATADUR_B 10
95#define DATADUR_A 11
96#define DATADUR_A_F0 12
97#define DATADUR_A_F1 13
98
99/*--------------------- Static Functions --------------------------*/
Forest Bond5449c682009-04-25 10:30:44 -0400100static
Charles Clément6b35b7b2010-05-07 12:30:19 -0700101void
Forest Bond5449c682009-04-25 10:30:44 -0400102s_vFillRTSHead(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100103 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700104 unsigned char byPktType,
105 void *pvRTS,
106 unsigned int cbFrameLength,
107 bool bNeedAck,
108 bool bDisCRC,
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000109 struct ieee80211_hdr *hdr,
Joe Perches547f1cf2013-03-18 10:45:01 -0700110 unsigned short wCurrentRate,
111 unsigned char byFBOption
112);
Forest Bond5449c682009-04-25 10:30:44 -0400113
114static
Charles Clément6b35b7b2010-05-07 12:30:19 -0700115void
Forest Bond5449c682009-04-25 10:30:44 -0400116s_vGenerateTxParameter(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100117 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700118 unsigned char byPktType,
119 void *pTxBufHead,
120 void *pvRrvTime,
121 void *pvRTS,
122 void *pvCTS,
123 unsigned int cbFrameSize,
124 bool bNeedACK,
125 unsigned int uDMAIdx,
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +0000126 void *psEthHeader,
Joe Perches547f1cf2013-03-18 10:45:01 -0700127 unsigned short wCurrentRate
128);
Forest Bond5449c682009-04-25 10:30:44 -0400129
Charles Clémentfe4f34b2010-06-25 10:48:53 -0700130static unsigned int
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100131s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
Malcolm Priestley19f3ed32014-11-29 00:02:03 +0000132 unsigned char *pbyTxBufferAddr,
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100133 unsigned int uDMAIdx, PSTxDesc pHeadTD,
Malcolm Priestley154bb8b2014-11-29 00:02:02 +0000134 unsigned int uNodeIndex);
Forest Bond5449c682009-04-25 10:30:44 -0400135
Forest Bond5449c682009-04-25 10:30:44 -0400136static
Malcolm Priestleya479ffc2014-08-30 22:25:38 +0100137__le16
Joe Perches547f1cf2013-03-18 10:45:01 -0700138s_uFillDataHead(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100139 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700140 unsigned char byPktType,
141 void *pTxDataHead,
142 unsigned int cbFrameLength,
143 unsigned int uDMAIdx,
144 bool bNeedAck,
145 unsigned int uFragIdx,
146 unsigned int cbLastFragmentSize,
147 unsigned int uMACfragNum,
148 unsigned char byFBOption,
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000149 unsigned short wCurrentRate,
150 bool is_pspoll
Joe Perches547f1cf2013-03-18 10:45:01 -0700151);
Forest Bond5449c682009-04-25 10:30:44 -0400152
Forest Bond5449c682009-04-25 10:30:44 -0400153/*--------------------- Export Variables --------------------------*/
154
Malcolm Priestleyd6b95c02014-08-30 22:25:33 +0100155static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
156{
157 return cpu_to_le16(wTimeStampOff[priv->byPreambleType % 2]
158 [rate % MAX_RATE]);
159}
160
Jim Lieb7e809a92009-07-30 10:27:21 -0700161/*byPktType : PK_TYPE_11A 0
Joe Perches547f1cf2013-03-18 10:45:01 -0700162 PK_TYPE_11B 1
163 PK_TYPE_11GB 2
164 PK_TYPE_11GA 3
Forest Bond5449c682009-04-25 10:30:44 -0400165*/
166static
Charles Clémentb6e95cd2010-06-02 09:52:01 -0700167unsigned int
Joe Perches547f1cf2013-03-18 10:45:01 -0700168s_uGetTxRsvTime(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100169 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700170 unsigned char byPktType,
171 unsigned int cbFrameLength,
172 unsigned short wRate,
173 bool bNeedAck
174)
Forest Bond5449c682009-04-25 10:30:44 -0400175{
Joe Perches547f1cf2013-03-18 10:45:01 -0700176 unsigned int uDataTime, uAckTime;
Forest Bond5449c682009-04-25 10:30:44 -0400177
Joe Perches547f1cf2013-03-18 10:45:01 -0700178 uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300179 if (byPktType == PK_TYPE_11B) //llb,CCK mode
Joe Perches547f1cf2013-03-18 10:45:01 -0700180 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopCCKBasicRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300181 else //11g 2.4G OFDM mode & 11a 5G OFDM mode
Joe Perches547f1cf2013-03-18 10:45:01 -0700182 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, (unsigned short)pDevice->byTopOFDMBasicRate);
Forest Bond5449c682009-04-25 10:30:44 -0400183
Guido Martínezbc5cf652014-04-19 16:45:00 -0300184 if (bNeedAck)
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700185 return uDataTime + pDevice->uSIFS + uAckTime;
Guido Martínezbc5cf652014-04-19 16:45:00 -0300186 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700187 return uDataTime;
Forest Bond5449c682009-04-25 10:30:44 -0400188}
189
Malcolm Priestleye7a3481b2014-08-30 22:25:30 +0100190static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
191 u32 frame_length, u16 rate, bool need_ack)
192{
193 return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type,
194 frame_length, rate, need_ack));
195}
196
Forest Bond5449c682009-04-25 10:30:44 -0400197//byFreqType: 0=>5GHZ 1=>2.4GHZ
198static
Malcolm Priestley853532d2014-08-30 22:25:31 +0100199__le16
Joe Perches547f1cf2013-03-18 10:45:01 -0700200s_uGetRTSCTSRsvTime(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100201 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700202 unsigned char byRTSRsvType,
203 unsigned char byPktType,
204 unsigned int cbFrameLength,
205 unsigned short wCurrentRate
206)
Forest Bond5449c682009-04-25 10:30:44 -0400207{
Joe Perches547f1cf2013-03-18 10:45:01 -0700208 unsigned int uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime;
Forest Bond5449c682009-04-25 10:30:44 -0400209
Joe Perches547f1cf2013-03-18 10:45:01 -0700210 uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400211
Joe Perches547f1cf2013-03-18 10:45:01 -0700212 uDataTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, cbFrameLength, wCurrentRate);
213 if (byRTSRsvType == 0) { //RTSTxRrvTime_bb
214 uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
215 uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700216 } else if (byRTSRsvType == 1) { //RTSTxRrvTime_ba, only in 2.4GHZ
Joe Perches547f1cf2013-03-18 10:45:01 -0700217 uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopCCKBasicRate);
218 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
219 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700220 } else if (byRTSRsvType == 2) { //RTSTxRrvTime_aa
Joe Perches547f1cf2013-03-18 10:45:01 -0700221 uRTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 20, pDevice->byTopOFDMBasicRate);
222 uCTSTime = uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700223 } else if (byRTSRsvType == 3) { //CTSTxRrvTime_ba, only in 2.4GHZ
Joe Perches547f1cf2013-03-18 10:45:01 -0700224 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
225 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
226 uRrvTime = uCTSTime + uAckTime + uDataTime + 2*pDevice->uSIFS;
Malcolm Priestley853532d2014-08-30 22:25:31 +0100227 return cpu_to_le16((u16)uRrvTime);
Joe Perches547f1cf2013-03-18 10:45:01 -0700228 }
Forest Bond5449c682009-04-25 10:30:44 -0400229
Joe Perches547f1cf2013-03-18 10:45:01 -0700230 //RTSRrvTime
231 uRrvTime = uRTSTime + uCTSTime + uAckTime + uDataTime + 3*pDevice->uSIFS;
Malcolm Priestley853532d2014-08-30 22:25:31 +0100232 return cpu_to_le16((u16)uRrvTime);
Forest Bond5449c682009-04-25 10:30:44 -0400233}
234
235//byFreqType 0: 5GHz, 1:2.4Ghz
236static
Charles Clémentb6e95cd2010-06-02 09:52:01 -0700237unsigned int
Joe Perches547f1cf2013-03-18 10:45:01 -0700238s_uGetDataDuration(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100239 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700240 unsigned char byDurType,
241 unsigned int cbFrameLength,
242 unsigned char byPktType,
243 unsigned short wRate,
244 bool bNeedAck,
245 unsigned int uFragIdx,
246 unsigned int cbLastFragmentSize,
247 unsigned int uMACfragNum,
248 unsigned char byFBOption
249)
Forest Bond5449c682009-04-25 10:30:44 -0400250{
Joe Perches547f1cf2013-03-18 10:45:01 -0700251 bool bLastFrag = 0;
252 unsigned int uAckTime = 0, uNextPktTime = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400253
Guido Martínezbc5cf652014-04-19 16:45:00 -0300254 if (uFragIdx == (uMACfragNum-1))
Joe Perches547f1cf2013-03-18 10:45:01 -0700255 bLastFrag = 1;
Forest Bond5449c682009-04-25 10:30:44 -0400256
Joe Perches547f1cf2013-03-18 10:45:01 -0700257 switch (byDurType) {
Joe Perches547f1cf2013-03-18 10:45:01 -0700258 case DATADUR_B: //DATADUR_B
Teodora Baluta649520b2013-11-10 17:12:44 +0200259 if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700260 if (bNeedAck) {
261 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700262 return pDevice->uSIFS + uAckTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700263 } else {
264 return 0;
265 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700266 } else {//First Frag or Mid Frag
Guido Martínezbc5cf652014-04-19 16:45:00 -0300267 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700268 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300269 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700270 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300271
Joe Perches547f1cf2013-03-18 10:45:01 -0700272 if (bNeedAck) {
273 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700274 return pDevice->uSIFS + uAckTime + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700275 } else {
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700276 return pDevice->uSIFS + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700277 }
278 }
279 break;
Forest Bond5449c682009-04-25 10:30:44 -0400280
Joe Perches547f1cf2013-03-18 10:45:01 -0700281 case DATADUR_A: //DATADUR_A
Teodora Baluta649520b2013-11-10 17:12:44 +0200282 if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700283 if (bNeedAck) {
284 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700285 return pDevice->uSIFS + uAckTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700286 } else {
287 return 0;
288 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700289 } else {//First Frag or Mid Frag
Guido Martínezbc5cf652014-04-19 16:45:00 -0300290 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700291 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wRate, bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300292 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700293 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300294
Joe Perches547f1cf2013-03-18 10:45:01 -0700295 if (bNeedAck) {
296 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700297 return pDevice->uSIFS + uAckTime + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700298 } else {
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700299 return pDevice->uSIFS + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700300 }
301 }
302 break;
Forest Bond5449c682009-04-25 10:30:44 -0400303
Joe Perches547f1cf2013-03-18 10:45:01 -0700304 case DATADUR_A_F0: //DATADUR_A_F0
Teodora Baluta649520b2013-11-10 17:12:44 +0200305 if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700306 if (bNeedAck) {
307 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700308 return pDevice->uSIFS + uAckTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700309 } else {
310 return 0;
311 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700312 } else { //First Frag or Mid Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700313 if (byFBOption == AUTO_FB_0) {
314 if (wRate < RATE_18M)
315 wRate = RATE_18M;
316 else if (wRate > RATE_54M)
317 wRate = RATE_54M;
Forest Bond5449c682009-04-25 10:30:44 -0400318
Guido Martínezbc5cf652014-04-19 16:45:00 -0300319 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700320 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300321 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700322 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300323
Joe Perches547f1cf2013-03-18 10:45:01 -0700324 } else { // (byFBOption == AUTO_FB_1)
325 if (wRate < RATE_18M)
326 wRate = RATE_18M;
327 else if (wRate > RATE_54M)
328 wRate = RATE_54M;
Forest Bond5449c682009-04-25 10:30:44 -0400329
Guido Martínezbc5cf652014-04-19 16:45:00 -0300330 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700331 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300332 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700333 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300334
Joe Perches547f1cf2013-03-18 10:45:01 -0700335 }
Forest Bond5449c682009-04-25 10:30:44 -0400336
Joe Perches547f1cf2013-03-18 10:45:01 -0700337 if (bNeedAck) {
338 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700339 return pDevice->uSIFS + uAckTime + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700340 } else {
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700341 return pDevice->uSIFS + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700342 }
343 }
344 break;
Forest Bond5449c682009-04-25 10:30:44 -0400345
Joe Perches547f1cf2013-03-18 10:45:01 -0700346 case DATADUR_A_F1: //DATADUR_A_F1
Teodora Baluta649520b2013-11-10 17:12:44 +0200347 if (((uMACfragNum == 1)) || bLastFrag) {//Non Frag or Last Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700348 if (bNeedAck) {
349 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700350 return pDevice->uSIFS + uAckTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700351 } else {
352 return 0;
353 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700354 } else { //First Frag or Mid Frag
Joe Perches547f1cf2013-03-18 10:45:01 -0700355 if (byFBOption == AUTO_FB_0) {
356 if (wRate < RATE_18M)
357 wRate = RATE_18M;
358 else if (wRate > RATE_54M)
359 wRate = RATE_54M;
Forest Bond5449c682009-04-25 10:30:44 -0400360
Guido Martínezbc5cf652014-04-19 16:45:00 -0300361 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700362 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300363 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700364 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
Forest Bond5449c682009-04-25 10:30:44 -0400365
Joe Perches547f1cf2013-03-18 10:45:01 -0700366 } else { // (byFBOption == AUTO_FB_1)
367 if (wRate < RATE_18M)
368 wRate = RATE_18M;
369 else if (wRate > RATE_54M)
370 wRate = RATE_54M;
Forest Bond5449c682009-04-25 10:30:44 -0400371
Guido Martínezbc5cf652014-04-19 16:45:00 -0300372 if (uFragIdx == (uMACfragNum-2))
Joe Perches547f1cf2013-03-18 10:45:01 -0700373 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbLastFragmentSize, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300374 else
Joe Perches547f1cf2013-03-18 10:45:01 -0700375 uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
Joe Perches547f1cf2013-03-18 10:45:01 -0700376 }
377 if (bNeedAck) {
378 uAckTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700379 return pDevice->uSIFS + uAckTime + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700380 } else {
Joe Perchesa4ef27a2013-03-18 20:55:38 -0700381 return pDevice->uSIFS + uNextPktTime;
Joe Perches547f1cf2013-03-18 10:45:01 -0700382 }
383 }
384 break;
Forest Bond5449c682009-04-25 10:30:44 -0400385
Joe Perches547f1cf2013-03-18 10:45:01 -0700386 default:
387 break;
388 }
Forest Bond5449c682009-04-25 10:30:44 -0400389
Charles Clément5a5a2a62010-08-01 17:15:49 +0200390 ASSERT(false);
Forest Bond5449c682009-04-25 10:30:44 -0400391 return 0;
392}
393
Forest Bond5449c682009-04-25 10:30:44 -0400394//byFreqType: 0=>5GHZ 1=>2.4GHZ
395static
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100396__le16
Joe Perches547f1cf2013-03-18 10:45:01 -0700397s_uGetRTSCTSDuration(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100398 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700399 unsigned char byDurType,
400 unsigned int cbFrameLength,
401 unsigned char byPktType,
402 unsigned short wRate,
403 bool bNeedAck,
404 unsigned char byFBOption
405)
Forest Bond5449c682009-04-25 10:30:44 -0400406{
Joe Perches547f1cf2013-03-18 10:45:01 -0700407 unsigned int uCTSTime = 0, uDurTime = 0;
Forest Bond5449c682009-04-25 10:30:44 -0400408
Joe Perches547f1cf2013-03-18 10:45:01 -0700409 switch (byDurType) {
Joe Perches547f1cf2013-03-18 10:45:01 -0700410 case RTSDUR_BB: //RTSDuration_bb
411 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
412 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
413 break;
Forest Bond5449c682009-04-25 10:30:44 -0400414
Joe Perches547f1cf2013-03-18 10:45:01 -0700415 case RTSDUR_BA: //RTSDuration_ba
416 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
417 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
418 break;
Forest Bond5449c682009-04-25 10:30:44 -0400419
Joe Perches547f1cf2013-03-18 10:45:01 -0700420 case RTSDUR_AA: //RTSDuration_aa
421 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
422 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
423 break;
Forest Bond5449c682009-04-25 10:30:44 -0400424
Joe Perches547f1cf2013-03-18 10:45:01 -0700425 case CTSDUR_BA: //CTSDuration_ba
426 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
427 break;
Forest Bond5449c682009-04-25 10:30:44 -0400428
Joe Perches547f1cf2013-03-18 10:45:01 -0700429 case RTSDUR_BA_F0: //RTSDuration_ba_f0
430 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300431 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700432 uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300433 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700434 uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300435
Joe Perches547f1cf2013-03-18 10:45:01 -0700436 break;
Forest Bond5449c682009-04-25 10:30:44 -0400437
Joe Perches547f1cf2013-03-18 10:45:01 -0700438 case RTSDUR_AA_F0: //RTSDuration_aa_f0
439 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300440 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700441 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300442 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700443 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300444
Joe Perches547f1cf2013-03-18 10:45:01 -0700445 break;
Forest Bond5449c682009-04-25 10:30:44 -0400446
Joe Perches547f1cf2013-03-18 10:45:01 -0700447 case RTSDUR_BA_F1: //RTSDuration_ba_f1
448 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300449 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700450 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300451 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700452 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300453
Joe Perches547f1cf2013-03-18 10:45:01 -0700454 break;
Forest Bond5449c682009-04-25 10:30:44 -0400455
Joe Perches547f1cf2013-03-18 10:45:01 -0700456 case RTSDUR_AA_F1: //RTSDuration_aa_f1
457 uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300458 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700459 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300460 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700461 uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300462
Joe Perches547f1cf2013-03-18 10:45:01 -0700463 break;
Forest Bond5449c682009-04-25 10:30:44 -0400464
Joe Perches547f1cf2013-03-18 10:45:01 -0700465 case CTSDUR_BA_F0: //CTSDuration_ba_f0
Guido Martínezbc5cf652014-04-19 16:45:00 -0300466 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700467 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300468 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700469 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300470
Joe Perches547f1cf2013-03-18 10:45:01 -0700471 break;
Forest Bond5449c682009-04-25 10:30:44 -0400472
Joe Perches547f1cf2013-03-18 10:45:01 -0700473 case CTSDUR_BA_F1: //CTSDuration_ba_f1
Guido Martínezbc5cf652014-04-19 16:45:00 -0300474 if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700475 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300476 else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
Joe Perches547f1cf2013-03-18 10:45:01 -0700477 uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
Guido Martínezbc5cf652014-04-19 16:45:00 -0300478
Joe Perches547f1cf2013-03-18 10:45:01 -0700479 break;
Forest Bond5449c682009-04-25 10:30:44 -0400480
Joe Perches547f1cf2013-03-18 10:45:01 -0700481 default:
482 break;
483 }
Forest Bond5449c682009-04-25 10:30:44 -0400484
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100485 return cpu_to_le16((u16)uDurTime);
Forest Bond5449c682009-04-25 10:30:44 -0400486}
487
Forest Bond5449c682009-04-25 10:30:44 -0400488static
Malcolm Priestleya479ffc2014-08-30 22:25:38 +0100489__le16
Joe Perches547f1cf2013-03-18 10:45:01 -0700490s_uFillDataHead(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100491 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700492 unsigned char byPktType,
493 void *pTxDataHead,
494 unsigned int cbFrameLength,
495 unsigned int uDMAIdx,
496 bool bNeedAck,
497 unsigned int uFragIdx,
498 unsigned int cbLastFragmentSize,
499 unsigned int uMACfragNum,
500 unsigned char byFBOption,
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000501 unsigned short wCurrentRate,
502 bool is_pspoll
Joe Perches547f1cf2013-03-18 10:45:01 -0700503)
Forest Bond5449c682009-04-25 10:30:44 -0400504{
Forest Bond5449c682009-04-25 10:30:44 -0400505
Guido Martínezbc5cf652014-04-19 16:45:00 -0300506 if (pTxDataHead == NULL)
Joe Perches547f1cf2013-03-18 10:45:01 -0700507 return 0;
Guido Martínezbc5cf652014-04-19 16:45:00 -0300508
Forest Bond5449c682009-04-25 10:30:44 -0400509
Joe Perches547f1cf2013-03-18 10:45:01 -0700510 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
511 if (byFBOption == AUTO_FB_NONE) {
Malcolm Priestley72edb7e2014-08-30 22:25:34 +0100512 struct vnt_tx_datahead_g *buf = pTxDataHead;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100513 /* Get SignalField, ServiceField & Length */
514 vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
Malcolm Priestley72edb7e2014-08-30 22:25:34 +0100515 byPktType, &buf->a);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100516
517 vnt_get_phy_field(pDevice, cbFrameLength,
518 pDevice->byTopCCKBasicRate,
Malcolm Priestley72edb7e2014-08-30 22:25:34 +0100519 PK_TYPE_11B, &buf->b);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100520
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000521 if (is_pspoll) {
522 __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
523
524 buf->duration_a = dur;
525 buf->duration_b = dur;
526 } else {
527 /* Get Duration and TimeStamp */
528 buf->duration_a =
529 cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
530 byPktType, wCurrentRate, bNeedAck, uFragIdx,
531 cbLastFragmentSize, uMACfragNum,
532 byFBOption));
533 buf->duration_b =
534 cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
535 PK_TYPE_11B, pDevice->byTopCCKBasicRate,
536 bNeedAck, uFragIdx, cbLastFragmentSize,
537 uMACfragNum, byFBOption));
538 }
Forest Bond5449c682009-04-25 10:30:44 -0400539
Malcolm Priestley72edb7e2014-08-30 22:25:34 +0100540 buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
541 buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
Forest Bond5449c682009-04-25 10:30:44 -0400542
Malcolm Priestley72edb7e2014-08-30 22:25:34 +0100543 return buf->duration_a;
Joe Perches547f1cf2013-03-18 10:45:01 -0700544 } else {
Malcolm Priestley2dd76672014-08-30 22:25:35 +0100545 /* Auto Fallback */
546 struct vnt_tx_datahead_g_fb *buf = pTxDataHead;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100547 /* Get SignalField, ServiceField & Length */
548 vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
Malcolm Priestley2dd76672014-08-30 22:25:35 +0100549 byPktType, &buf->a);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100550
551 vnt_get_phy_field(pDevice, cbFrameLength,
552 pDevice->byTopCCKBasicRate,
Malcolm Priestley2dd76672014-08-30 22:25:35 +0100553 PK_TYPE_11B, &buf->b);
554 /* Get Duration and TimeStamp */
555 buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
556 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
557 buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
558 pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
559 buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
560 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
561 buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
562 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
Forest Bond5449c682009-04-25 10:30:44 -0400563
Malcolm Priestley2dd76672014-08-30 22:25:35 +0100564 buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
565 buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
Forest Bond5449c682009-04-25 10:30:44 -0400566
Malcolm Priestley2dd76672014-08-30 22:25:35 +0100567 return buf->duration_a;
Joe Perches547f1cf2013-03-18 10:45:01 -0700568 } //if (byFBOption == AUTO_FB_NONE)
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700569 } else if (byPktType == PK_TYPE_11A) {
Joe Perches547f1cf2013-03-18 10:45:01 -0700570 if ((byFBOption != AUTO_FB_NONE)) {
Malcolm Priestley9c62c7a2014-08-30 22:25:37 +0100571 /* Auto Fallback */
572 struct vnt_tx_datahead_a_fb *buf = pTxDataHead;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100573 /* Get SignalField, ServiceField & Length */
574 vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
Malcolm Priestley9c62c7a2014-08-30 22:25:37 +0100575 byPktType, &buf->a);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100576
Malcolm Priestley9c62c7a2014-08-30 22:25:37 +0100577 /* Get Duration and TimeStampOff */
578 buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
579 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
580 buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
581 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
582 buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
583 wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
584 buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
585 return buf->duration;
Joe Perches547f1cf2013-03-18 10:45:01 -0700586 } else {
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100587 struct vnt_tx_datahead_ab *buf = pTxDataHead;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100588 /* Get SignalField, ServiceField & Length */
589 vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100590 byPktType, &buf->ab);
Forest Bond5449c682009-04-25 10:30:44 -0400591
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000592 if (is_pspoll) {
593 __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
594
595 buf->duration = dur;
596 } else {
597 /* Get Duration and TimeStampOff */
598 buf->duration =
599 cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100600 wCurrentRate, bNeedAck, uFragIdx,
601 cbLastFragmentSize, uMACfragNum,
602 byFBOption));
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000603 }
Forest Bond5449c682009-04-25 10:30:44 -0400604
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100605 buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
606 return buf->duration;
Joe Perches547f1cf2013-03-18 10:45:01 -0700607 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700608 } else {
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100609 struct vnt_tx_datahead_ab *buf = pTxDataHead;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100610 /* Get SignalField, ServiceField & Length */
611 vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100612 byPktType, &buf->ab);
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000613
614 if (is_pspoll) {
615 __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
616
617 buf->duration = dur;
618 } else {
619 /* Get Duration and TimeStampOff */
620 buf->duration =
621 cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100622 wCurrentRate, bNeedAck, uFragIdx,
623 cbLastFragmentSize, uMACfragNum,
624 byFBOption));
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000625 }
626
Malcolm Priestley9ce842a2014-08-30 22:25:36 +0100627 buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
628 return buf->duration;
Joe Perches547f1cf2013-03-18 10:45:01 -0700629 }
630 return 0;
Forest Bond5449c682009-04-25 10:30:44 -0400631}
632
Malcolm Priestley89cf9be2014-10-29 17:43:42 +0000633
Forest Bond5449c682009-04-25 10:30:44 -0400634static
Charles Clément6b35b7b2010-05-07 12:30:19 -0700635void
Joe Perches547f1cf2013-03-18 10:45:01 -0700636s_vFillRTSHead(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100637 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700638 unsigned char byPktType,
639 void *pvRTS,
640 unsigned int cbFrameLength,
641 bool bNeedAck,
642 bool bDisCRC,
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000643 struct ieee80211_hdr *hdr,
Joe Perches547f1cf2013-03-18 10:45:01 -0700644 unsigned short wCurrentRate,
645 unsigned char byFBOption
646)
Forest Bond5449c682009-04-25 10:30:44 -0400647{
Joe Perches547f1cf2013-03-18 10:45:01 -0700648 unsigned int uRTSFrameLen = 20;
Forest Bond5449c682009-04-25 10:30:44 -0400649
Joe Perches547f1cf2013-03-18 10:45:01 -0700650 if (pvRTS == NULL)
651 return;
Forest Bond5449c682009-04-25 10:30:44 -0400652
Joe Perches547f1cf2013-03-18 10:45:01 -0700653 if (bDisCRC) {
654 // When CRCDIS bit is on, H/W forgot to generate FCS for RTS frame,
655 // in this case we need to decrease its length by 4.
656 uRTSFrameLen -= 4;
657 }
Forest Bond5449c682009-04-25 10:30:44 -0400658
Joe Perches547f1cf2013-03-18 10:45:01 -0700659 // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
660 // Otherwise, we need to modify codes for them.
661 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
662 if (byFBOption == AUTO_FB_NONE) {
Malcolm Priestley17434f02014-08-30 22:25:41 +0100663 struct vnt_rts_g *buf = pvRTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100664 /* Get SignalField, ServiceField & Length */
665 vnt_get_phy_field(pDevice, uRTSFrameLen,
666 pDevice->byTopCCKBasicRate,
Malcolm Priestley17434f02014-08-30 22:25:41 +0100667 PK_TYPE_11B, &buf->b);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100668
669 vnt_get_phy_field(pDevice, uRTSFrameLen,
670 pDevice->byTopOFDMBasicRate,
Malcolm Priestley17434f02014-08-30 22:25:41 +0100671 byPktType, &buf->a);
672 /* Get Duration */
673 buf->duration_bb =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100674 s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
675 cbFrameLength, PK_TYPE_11B,
676 pDevice->byTopCCKBasicRate,
677 bNeedAck, byFBOption);
Malcolm Priestley17434f02014-08-30 22:25:41 +0100678 buf->duration_aa =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100679 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
680 cbFrameLength, byPktType,
681 wCurrentRate, bNeedAck,
682 byFBOption);
Malcolm Priestley17434f02014-08-30 22:25:41 +0100683 buf->duration_ba =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100684 s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
685 cbFrameLength, byPktType,
686 wCurrentRate, bNeedAck,
687 byFBOption);
Forest Bond5449c682009-04-25 10:30:44 -0400688
Malcolm Priestley17434f02014-08-30 22:25:41 +0100689 buf->data.duration = buf->duration_aa;
Malcolm Priestley52c41302014-08-30 22:25:39 +0100690 /* Get RTS Frame body */
Malcolm Priestley17434f02014-08-30 22:25:41 +0100691 buf->data.frame_control =
Malcolm Priestley52c41302014-08-30 22:25:39 +0100692 cpu_to_le16(IEEE80211_FTYPE_CTL |
693 IEEE80211_STYPE_RTS);
694
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000695 ether_addr_copy(buf->data.ra, hdr->addr1);
696 ether_addr_copy(buf->data.ta, hdr->addr2);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700697 } else {
Malcolm Priestley9587b092014-08-30 22:25:42 +0100698 struct vnt_rts_g_fb *buf = pvRTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100699 /* Get SignalField, ServiceField & Length */
700 vnt_get_phy_field(pDevice, uRTSFrameLen,
701 pDevice->byTopCCKBasicRate,
Malcolm Priestley9587b092014-08-30 22:25:42 +0100702 PK_TYPE_11B, &buf->b);
Forest Bond5449c682009-04-25 10:30:44 -0400703
Malcolm Priestley429a2472014-08-20 22:30:29 +0100704 vnt_get_phy_field(pDevice, uRTSFrameLen,
705 pDevice->byTopOFDMBasicRate,
Malcolm Priestley9587b092014-08-30 22:25:42 +0100706 byPktType, &buf->a);
707 /* Get Duration */
708 buf->duration_bb =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100709 s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
710 cbFrameLength, PK_TYPE_11B,
711 pDevice->byTopCCKBasicRate,
712 bNeedAck, byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100713 buf->duration_aa =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100714 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
715 cbFrameLength, byPktType,
716 wCurrentRate, bNeedAck,
717 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100718 buf->duration_ba =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100719 s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
720 cbFrameLength, byPktType,
721 wCurrentRate, bNeedAck,
722 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100723 buf->rts_duration_ba_f0 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100724 s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0,
725 cbFrameLength, byPktType,
726 wCurrentRate, bNeedAck,
727 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100728 buf->rts_duration_aa_f0 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100729 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
730 cbFrameLength, byPktType,
731 wCurrentRate, bNeedAck,
732 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100733 buf->rts_duration_ba_f1 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100734 s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1,
735 cbFrameLength, byPktType,
736 wCurrentRate, bNeedAck,
737 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100738 buf->rts_duration_aa_f1 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100739 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
740 cbFrameLength, byPktType,
741 wCurrentRate, bNeedAck,
742 byFBOption);
Malcolm Priestley9587b092014-08-30 22:25:42 +0100743 buf->data.duration = buf->duration_aa;
Malcolm Priestley52c41302014-08-30 22:25:39 +0100744 /* Get RTS Frame body */
Malcolm Priestley9587b092014-08-30 22:25:42 +0100745 buf->data.frame_control =
Malcolm Priestley52c41302014-08-30 22:25:39 +0100746 cpu_to_le16(IEEE80211_FTYPE_CTL |
747 IEEE80211_STYPE_RTS);
748
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000749 ether_addr_copy(buf->data.ra, hdr->addr1);
750 ether_addr_copy(buf->data.ta, hdr->addr2);
Joe Perches547f1cf2013-03-18 10:45:01 -0700751 } // if (byFBOption == AUTO_FB_NONE)
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700752 } else if (byPktType == PK_TYPE_11A) {
Joe Perches547f1cf2013-03-18 10:45:01 -0700753 if (byFBOption == AUTO_FB_NONE) {
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100754 struct vnt_rts_ab *buf = pvRTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100755 /* Get SignalField, ServiceField & Length */
756 vnt_get_phy_field(pDevice, uRTSFrameLen,
757 pDevice->byTopOFDMBasicRate,
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100758 byPktType, &buf->ab);
759 /* Get Duration */
760 buf->duration =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100761 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
762 cbFrameLength, byPktType,
763 wCurrentRate, bNeedAck,
764 byFBOption);
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100765 buf->data.duration = buf->duration;
Malcolm Priestley52c41302014-08-30 22:25:39 +0100766 /* Get RTS Frame body */
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100767 buf->data.frame_control =
Malcolm Priestley52c41302014-08-30 22:25:39 +0100768 cpu_to_le16(IEEE80211_FTYPE_CTL |
769 IEEE80211_STYPE_RTS);
770
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000771 ether_addr_copy(buf->data.ra, hdr->addr1);
772 ether_addr_copy(buf->data.ta, hdr->addr2);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700773 } else {
Malcolm Priestley8e448042014-08-30 22:25:44 +0100774 struct vnt_rts_a_fb *buf = pvRTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100775 /* Get SignalField, ServiceField & Length */
776 vnt_get_phy_field(pDevice, uRTSFrameLen,
777 pDevice->byTopOFDMBasicRate,
Malcolm Priestley8e448042014-08-30 22:25:44 +0100778 byPktType, &buf->a);
779 /* Get Duration */
780 buf->duration =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100781 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
782 cbFrameLength, byPktType,
783 wCurrentRate, bNeedAck,
784 byFBOption);
Malcolm Priestley8e448042014-08-30 22:25:44 +0100785 buf->rts_duration_f0 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100786 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
787 cbFrameLength, byPktType,
788 wCurrentRate, bNeedAck,
789 byFBOption);
Malcolm Priestley8e448042014-08-30 22:25:44 +0100790 buf->rts_duration_f1 =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100791 s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
792 cbFrameLength, byPktType,
793 wCurrentRate, bNeedAck,
794 byFBOption);
Malcolm Priestley8e448042014-08-30 22:25:44 +0100795 buf->data.duration = buf->duration;
Malcolm Priestley52c41302014-08-30 22:25:39 +0100796 /* Get RTS Frame body */
Malcolm Priestley8e448042014-08-30 22:25:44 +0100797 buf->data.frame_control =
Malcolm Priestley52c41302014-08-30 22:25:39 +0100798 cpu_to_le16(IEEE80211_FTYPE_CTL |
799 IEEE80211_STYPE_RTS);
800
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000801 ether_addr_copy(buf->data.ra, hdr->addr1);
802 ether_addr_copy(buf->data.ta, hdr->addr2);
Joe Perches547f1cf2013-03-18 10:45:01 -0700803 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700804 } else if (byPktType == PK_TYPE_11B) {
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100805 struct vnt_rts_ab *buf = pvRTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100806 /* Get SignalField, ServiceField & Length */
807 vnt_get_phy_field(pDevice, uRTSFrameLen,
808 pDevice->byTopCCKBasicRate,
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100809 PK_TYPE_11B, &buf->ab);
810 /* Get Duration */
811 buf->duration =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100812 s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength,
813 byPktType, wCurrentRate, bNeedAck,
814 byFBOption);
815
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100816 buf->data.duration = buf->duration;
Malcolm Priestley52c41302014-08-30 22:25:39 +0100817 /* Get RTS Frame body */
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +0100818 buf->data.frame_control =
Malcolm Priestley52c41302014-08-30 22:25:39 +0100819 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
Forest Bond5449c682009-04-25 10:30:44 -0400820
Malcolm Priestley7c0496d2014-10-29 17:43:41 +0000821 ether_addr_copy(buf->data.ra, hdr->addr1);
822 ether_addr_copy(buf->data.ta, hdr->addr2);
Joe Perches547f1cf2013-03-18 10:45:01 -0700823 }
Forest Bond5449c682009-04-25 10:30:44 -0400824}
825
826static
Charles Clément6b35b7b2010-05-07 12:30:19 -0700827void
Joe Perches547f1cf2013-03-18 10:45:01 -0700828s_vFillCTSHead(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100829 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700830 unsigned int uDMAIdx,
831 unsigned char byPktType,
832 void *pvCTS,
833 unsigned int cbFrameLength,
834 bool bNeedAck,
835 bool bDisCRC,
836 unsigned short wCurrentRate,
837 unsigned char byFBOption
838)
Forest Bond5449c682009-04-25 10:30:44 -0400839{
Joe Perches547f1cf2013-03-18 10:45:01 -0700840 unsigned int uCTSFrameLen = 14;
Forest Bond5449c682009-04-25 10:30:44 -0400841
Guido Martínezbc5cf652014-04-19 16:45:00 -0300842 if (pvCTS == NULL)
Joe Perches547f1cf2013-03-18 10:45:01 -0700843 return;
Forest Bond5449c682009-04-25 10:30:44 -0400844
Joe Perches547f1cf2013-03-18 10:45:01 -0700845 if (bDisCRC) {
846 // When CRCDIS bit is on, H/W forgot to generate FCS for CTS frame,
847 // in this case we need to decrease its length by 4.
848 uCTSFrameLen -= 4;
849 }
Forest Bond5449c682009-04-25 10:30:44 -0400850
Joe Perches547f1cf2013-03-18 10:45:01 -0700851 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
852 if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
853 // Auto Fall back
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100854 struct vnt_cts_fb *buf = pvCTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100855 /* Get SignalField, ServiceField & Length */
856 vnt_get_phy_field(pDevice, uCTSFrameLen,
857 pDevice->byTopCCKBasicRate,
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100858 PK_TYPE_11B, &buf->b);
Forest Bond5449c682009-04-25 10:30:44 -0400859
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100860 buf->duration_ba =
861 s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
862 cbFrameLength, byPktType,
863 wCurrentRate, bNeedAck,
864 byFBOption);
865
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100866 /* Get CTSDuration_ba_f0 */
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100867 buf->cts_duration_ba_f0 =
868 s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0,
869 cbFrameLength, byPktType,
870 wCurrentRate, bNeedAck,
871 byFBOption);
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100872
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100873 /* Get CTSDuration_ba_f1 */
874 buf->cts_duration_ba_f1 =
875 s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1,
876 cbFrameLength, byPktType,
877 wCurrentRate, bNeedAck,
878 byFBOption);
Malcolm Priestley0864db12014-08-30 22:25:40 +0100879
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100880 /* Get CTS Frame body */
881 buf->data.duration = buf->duration_ba;
882
883 buf->data.frame_control =
Malcolm Priestley0864db12014-08-30 22:25:40 +0100884 cpu_to_le16(IEEE80211_FTYPE_CTL |
885 IEEE80211_STYPE_CTS);
886
Malcolm Priestleydb1afd12014-08-30 22:25:46 +0100887 buf->reserved2 = 0x0;
Forest Bond5449c682009-04-25 10:30:44 -0400888
Aya Mahfouz2359b5c2014-10-11 02:42:45 +0200889 ether_addr_copy(buf->data.ra,
890 pDevice->abyCurrentNetAddr);
Joe Perches547f1cf2013-03-18 10:45:01 -0700891 } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100892 struct vnt_cts *buf = pvCTS;
Malcolm Priestley429a2472014-08-20 22:30:29 +0100893 /* Get SignalField, ServiceField & Length */
894 vnt_get_phy_field(pDevice, uCTSFrameLen,
895 pDevice->byTopCCKBasicRate,
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100896 PK_TYPE_11B, &buf->b);
Malcolm Priestley429a2472014-08-20 22:30:29 +0100897
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100898 /* Get CTSDuration_ba */
899 buf->duration_ba =
Malcolm Priestley96372bd2014-08-30 22:25:48 +0100900 s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
901 cbFrameLength, byPktType,
902 wCurrentRate, bNeedAck,
903 byFBOption);
Forest Bond5449c682009-04-25 10:30:44 -0400904
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100905 /* Get CTS Frame body */
906 buf->data.duration = buf->duration_ba;
Malcolm Priestley0864db12014-08-30 22:25:40 +0100907
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100908 buf->data.frame_control =
Malcolm Priestley0864db12014-08-30 22:25:40 +0100909 cpu_to_le16(IEEE80211_FTYPE_CTL |
910 IEEE80211_STYPE_CTS);
911
Malcolm Priestleyf5172b02014-08-30 22:25:45 +0100912 buf->reserved2 = 0x0;
Aya Mahfouz2359b5c2014-10-11 02:42:45 +0200913 ether_addr_copy(buf->data.ra,
914 pDevice->abyCurrentNetAddr);
Joe Perches547f1cf2013-03-18 10:45:01 -0700915 }
916 }
Forest Bond5449c682009-04-25 10:30:44 -0400917}
918
Forest Bond5449c682009-04-25 10:30:44 -0400919/*+
920 *
921 * Description:
922 * Generate FIFO control for MAC & Baseband controller
923 *
924 * Parameters:
925 * In:
Gilles Espinassef77f13e2010-03-29 15:41:47 +0200926 * pDevice - Pointer to adapter
Forest Bond5449c682009-04-25 10:30:44 -0400927 * pTxDataHead - Transmit Data Buffer
928 * pTxBufHead - pTxBufHead
929 * pvRrvTime - pvRrvTime
930 * pvRTS - RTS Buffer
931 * pCTS - CTS Buffer
932 * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS)
933 * bNeedACK - If need ACK
934 * uDescIdx - Desc Index
935 * Out:
936 * none
937 *
938 * Return Value: none
939 *
Joe Perches547f1cf2013-03-18 10:45:01 -0700940 -*/
Charles Clémentb6e95cd2010-06-02 09:52:01 -0700941// unsigned int cbFrameSize,//Hdr+Payload+FCS
Forest Bond5449c682009-04-25 10:30:44 -0400942static
Charles Clément6b35b7b2010-05-07 12:30:19 -0700943void
Joe Perches547f1cf2013-03-18 10:45:01 -0700944s_vGenerateTxParameter(
Malcolm Priestleycf76dc42014-08-10 15:46:59 +0100945 struct vnt_private *pDevice,
Joe Perches547f1cf2013-03-18 10:45:01 -0700946 unsigned char byPktType,
947 void *pTxBufHead,
948 void *pvRrvTime,
949 void *pvRTS,
950 void *pvCTS,
951 unsigned int cbFrameSize,
952 bool bNeedACK,
953 unsigned int uDMAIdx,
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +0000954 void *psEthHeader,
Joe Perches547f1cf2013-03-18 10:45:01 -0700955 unsigned short wCurrentRate
956)
Forest Bond5449c682009-04-25 10:30:44 -0400957{
Joe Perches547f1cf2013-03-18 10:45:01 -0700958 unsigned short wFifoCtl;
959 bool bDisCRC = false;
960 unsigned char byFBOption = AUTO_FB_NONE;
Forest Bond5449c682009-04-25 10:30:44 -0400961
Joe Perches547f1cf2013-03-18 10:45:01 -0700962 PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
Guillaume Clement6b711272014-07-25 01:06:16 +0200963
Joe Perches547f1cf2013-03-18 10:45:01 -0700964 pFifoHead->wReserved = wCurrentRate;
965 wFifoCtl = pFifoHead->wFIFOCtl;
Forest Bond5449c682009-04-25 10:30:44 -0400966
Guido Martínezbc5cf652014-04-19 16:45:00 -0300967 if (wFifoCtl & FIFOCTL_CRCDIS)
Joe Perches547f1cf2013-03-18 10:45:01 -0700968 bDisCRC = true;
Forest Bond5449c682009-04-25 10:30:44 -0400969
Guido Martínezbc5cf652014-04-19 16:45:00 -0300970 if (wFifoCtl & FIFOCTL_AUTO_FB_0)
Joe Perches547f1cf2013-03-18 10:45:01 -0700971 byFBOption = AUTO_FB_0;
Guido Martínezbc5cf652014-04-19 16:45:00 -0300972 else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
Joe Perches547f1cf2013-03-18 10:45:01 -0700973 byFBOption = AUTO_FB_1;
Forest Bond5449c682009-04-25 10:30:44 -0400974
Malcolm Priestleyc00a3782014-08-30 22:25:32 +0100975 if (!pvRrvTime)
976 return;
977
Joe Perches547f1cf2013-03-18 10:45:01 -0700978 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
Joe Perches547f1cf2013-03-18 10:45:01 -0700979 if (pvRTS != NULL) { //RTS_need
Malcolm Priestleyc00a3782014-08-30 22:25:32 +0100980 /* Fill RsvTime */
981 struct vnt_rrv_time_rts *buf = pvRrvTime;
Guillaume Clement6b711272014-07-25 01:06:16 +0200982
Malcolm Priestleyc00a3782014-08-30 22:25:32 +0100983 buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
984 buf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 1, byPktType, cbFrameSize, wCurrentRate);
985 buf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
986 buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
987 buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
988
Joe Perches547f1cf2013-03-18 10:45:01 -0700989 s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
Joe Perches5e0cc8a2013-03-18 20:55:37 -0700990 } else {//RTS_needless, PCF mode
Malcolm Priestleyc00a3782014-08-30 22:25:32 +0100991 struct vnt_rrv_time_cts *buf = pvRrvTime;
Forest Bond5449c682009-04-25 10:30:44 -0400992
Malcolm Priestleyc00a3782014-08-30 22:25:32 +0100993 buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
994 buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
995 buf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(pDevice, 3, byPktType, cbFrameSize, wCurrentRate);
Forest Bond5449c682009-04-25 10:30:44 -0400996
Joe Perches547f1cf2013-03-18 10:45:01 -0700997 //Fill CTS
998 s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
999 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001000 } else if (byPktType == PK_TYPE_11A) {
Joe Perches547f1cf2013-03-18 10:45:01 -07001001 if (pvRTS != NULL) {//RTS_need, non PCF mode
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001002 struct vnt_rrv_time_ab *buf = pvRrvTime;
Guillaume Clement6b711272014-07-25 01:06:16 +02001003
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001004 buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
1005 buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
1006
Joe Perches547f1cf2013-03-18 10:45:01 -07001007 //Fill RTS
1008 s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001009 } else if (pvRTS == NULL) {//RTS_needless, non PCF mode
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001010 struct vnt_rrv_time_ab *buf = pvRrvTime;
Guillaume Clement6b711272014-07-25 01:06:16 +02001011
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001012 buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK);
Joe Perches547f1cf2013-03-18 10:45:01 -07001013 }
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001014 } else if (byPktType == PK_TYPE_11B) {
Joe Perches547f1cf2013-03-18 10:45:01 -07001015 if ((pvRTS != NULL)) {//RTS_need, non PCF mode
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001016 struct vnt_rrv_time_ab *buf = pvRrvTime;
Guillaume Clement6b711272014-07-25 01:06:16 +02001017
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001018 buf->rts_rrv_time = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
1019 buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
1020
Joe Perches547f1cf2013-03-18 10:45:01 -07001021 //Fill RTS
1022 s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001023 } else { //RTS_needless, non PCF mode
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001024 struct vnt_rrv_time_ab *buf = pvRrvTime;
Guillaume Clement6b711272014-07-25 01:06:16 +02001025
Malcolm Priestleyc00a3782014-08-30 22:25:32 +01001026 buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
Joe Perches547f1cf2013-03-18 10:45:01 -07001027 }
1028 }
Forest Bond5449c682009-04-25 10:30:44 -04001029}
Guido Martínez4e8a7e52014-04-19 16:44:59 -03001030
Charles Clémentfe4f34b2010-06-25 10:48:53 -07001031static unsigned int
Malcolm Priestleycf76dc42014-08-10 15:46:59 +01001032s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
Malcolm Priestley19f3ed32014-11-29 00:02:03 +00001033 unsigned char *pbyTxBufferAddr,
Malcolm Priestleycf76dc42014-08-10 15:46:59 +01001034 unsigned int uDMAIdx, PSTxDesc pHeadTD,
Malcolm Priestley154bb8b2014-11-29 00:02:02 +00001035 unsigned int is_pspoll)
Forest Bond5449c682009-04-25 10:30:44 -04001036{
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001037 PDEVICE_TD_INFO td_info = pHeadTD->pTDInfo;
1038 struct sk_buff *skb = td_info->skb;
1039 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1040 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1041 struct vnt_tx_fifo_head *tx_buffer_head =
1042 (struct vnt_tx_fifo_head *)td_info->buf;
1043 u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
Joe Perches547f1cf2013-03-18 10:45:01 -07001044 unsigned int cbFrameSize;
Malcolm Priestleya479ffc2014-08-30 22:25:38 +01001045 __le16 uDuration;
Joe Perches547f1cf2013-03-18 10:45:01 -07001046 unsigned char *pbyBuffer;
Joe Perches547f1cf2013-03-18 10:45:01 -07001047 unsigned int uLength = 0;
Joe Perches547f1cf2013-03-18 10:45:01 -07001048 unsigned int cbMICHDR = 0;
Joe Perches547f1cf2013-03-18 10:45:01 -07001049 unsigned int uMACfragNum = 1;
1050 unsigned int uPadding = 0;
1051 unsigned int cbReqCount = 0;
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001052 bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
1053 bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
Joe Perches547f1cf2013-03-18 10:45:01 -07001054 PSTxDesc ptdCurr;
Joe Perches547f1cf2013-03-18 10:45:01 -07001055 unsigned int cbHeaderLength = 0;
1056 void *pvRrvTime;
Malcolm Priestley11a72e52014-08-09 20:15:56 +01001057 struct vnt_mic_hdr *pMICHDR;
Joe Perches547f1cf2013-03-18 10:45:01 -07001058 void *pvRTS;
1059 void *pvCTS;
1060 void *pvTxDataHd;
1061 unsigned short wTxBufSize; // FFinfo size
Joe Perches547f1cf2013-03-18 10:45:01 -07001062 unsigned char byFBOption = AUTO_FB_NONE;
Forest Bond5449c682009-04-25 10:30:44 -04001063
Joe Perches547f1cf2013-03-18 10:45:01 -07001064 pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL;
Forest Bond5449c682009-04-25 10:30:44 -04001065
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001066 cbFrameSize = skb->len + 4;
Forest Bond5449c682009-04-25 10:30:44 -04001067
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001068 if (info->control.hw_key) {
1069 switch (info->control.hw_key->cipher) {
1070 case WLAN_CIPHER_SUITE_CCMP:
Malcolm Priestley11a72e52014-08-09 20:15:56 +01001071 cbMICHDR = sizeof(struct vnt_mic_hdr);
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001072 default:
1073 break;
Joe Perches547f1cf2013-03-18 10:45:01 -07001074 }
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001075
1076 cbFrameSize += info->control.hw_key->icv_len;
1077
Joe Perches547f1cf2013-03-18 10:45:01 -07001078 if (pDevice->byLocalID > REV_ID_VT3253_A1) {
1079 //MAC Header should be padding 0 to DW alignment.
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001080 uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4);
Joe Perches547f1cf2013-03-18 10:45:01 -07001081 uPadding %= 4;
1082 }
1083 }
Forest Bond5449c682009-04-25 10:30:44 -04001084
Joe Perches547f1cf2013-03-18 10:45:01 -07001085 //
1086 // Use for AUTO FALL BACK
1087 //
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001088 if (fifo_ctl & FIFOCTL_AUTO_FB_0)
Joe Perches547f1cf2013-03-18 10:45:01 -07001089 byFBOption = AUTO_FB_0;
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001090 else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
Joe Perches547f1cf2013-03-18 10:45:01 -07001091 byFBOption = AUTO_FB_1;
Forest Bond5449c682009-04-25 10:30:44 -04001092
Joe Perches547f1cf2013-03-18 10:45:01 -07001093 //////////////////////////////////////////////////////
1094 //Set RrvTime/RTS/CTS Buffer
1095 wTxBufSize = sizeof(STxBufHead);
1096 if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
Forest Bond5449c682009-04-25 10:30:44 -04001097
Joe Perches547f1cf2013-03-18 10:45:01 -07001098 if (byFBOption == AUTO_FB_NONE) {
1099 if (bRTS == true) {//RTS_need
Malcolm Priestleya9e6a2d2014-08-30 22:25:27 +01001100 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1101 pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
Malcolm Priestley17434f02014-08-30 22:25:41 +01001102 pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
Joe Perches547f1cf2013-03-18 10:45:01 -07001103 pvCTS = NULL;
Malcolm Priestley17434f02014-08-30 22:25:41 +01001104 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
1105 cbMICHDR + sizeof(struct vnt_rts_g));
Malcolm Priestley72edb7e2014-08-30 22:25:34 +01001106 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
Malcolm Priestley17434f02014-08-30 22:25:41 +01001107 cbMICHDR + sizeof(struct vnt_rts_g) +
1108 sizeof(struct vnt_tx_datahead_g);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001109 } else { //RTS_needless
Malcolm Priestleyd66a5a72014-08-30 22:25:28 +01001110 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1111 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
Joe Perches547f1cf2013-03-18 10:45:01 -07001112 pvRTS = NULL;
Malcolm Priestleyf5172b02014-08-30 22:25:45 +01001113 pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
1114 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
1115 sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts));
Malcolm Priestley72edb7e2014-08-30 22:25:34 +01001116 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
Malcolm Priestleyf5172b02014-08-30 22:25:45 +01001117 cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
Joe Perches547f1cf2013-03-18 10:45:01 -07001118 }
1119 } else {
1120 // Auto Fall Back
1121 if (bRTS == true) {//RTS_need
Malcolm Priestleya9e6a2d2014-08-30 22:25:27 +01001122 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1123 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
Malcolm Priestley9587b092014-08-30 22:25:42 +01001124 pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
Joe Perches547f1cf2013-03-18 10:45:01 -07001125 pvCTS = NULL;
Malcolm Priestley9587b092014-08-30 22:25:42 +01001126 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
1127 cbMICHDR + sizeof(struct vnt_rts_g_fb));
Malcolm Priestley2dd76672014-08-30 22:25:35 +01001128 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
Malcolm Priestley9587b092014-08-30 22:25:42 +01001129 cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001130 } else { //RTS_needless
Malcolm Priestleyd66a5a72014-08-30 22:25:28 +01001131 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1132 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
Joe Perches547f1cf2013-03-18 10:45:01 -07001133 pvRTS = NULL;
Malcolm Priestleydb1afd12014-08-30 22:25:46 +01001134 pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
1135 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
1136 cbMICHDR + sizeof(struct vnt_cts_fb));
Malcolm Priestley2dd76672014-08-30 22:25:35 +01001137 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
Malcolm Priestleydb1afd12014-08-30 22:25:46 +01001138 cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb);
Joe Perches547f1cf2013-03-18 10:45:01 -07001139 }
1140 } // Auto Fall Back
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001141 } else {//802.11a/b packet
Forest Bond5449c682009-04-25 10:30:44 -04001142
Joe Perches547f1cf2013-03-18 10:45:01 -07001143 if (byFBOption == AUTO_FB_NONE) {
1144 if (bRTS == true) {
Malcolm Priestleyf6a634c2014-08-30 22:25:29 +01001145 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1146 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +01001147 pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
Joe Perches547f1cf2013-03-18 10:45:01 -07001148 pvCTS = NULL;
Malcolm Priestley9ce842a2014-08-30 22:25:36 +01001149 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +01001150 sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab));
Malcolm Priestley9ce842a2014-08-30 22:25:36 +01001151 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
Malcolm Priestleye21eb1c2014-08-30 22:25:43 +01001152 cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001153 } else { //RTS_needless, need MICHDR
Malcolm Priestleyf6a634c2014-08-30 22:25:29 +01001154 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1155 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
Joe Perches547f1cf2013-03-18 10:45:01 -07001156 pvRTS = NULL;
1157 pvCTS = NULL;
Malcolm Priestley9ce842a2014-08-30 22:25:36 +01001158 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
1159 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
1160 cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
Joe Perches547f1cf2013-03-18 10:45:01 -07001161 }
1162 } else {
1163 // Auto Fall Back
1164 if (bRTS == true) {//RTS_need
Malcolm Priestleyf6a634c2014-08-30 22:25:29 +01001165 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1166 pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
Malcolm Priestley8e448042014-08-30 22:25:44 +01001167 pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
Joe Perches547f1cf2013-03-18 10:45:01 -07001168 pvCTS = NULL;
Malcolm Priestley8e448042014-08-30 22:25:44 +01001169 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
1170 sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb));
Malcolm Priestley9c62c7a2014-08-30 22:25:37 +01001171 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
Malcolm Priestley8e448042014-08-30 22:25:44 +01001172 cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb);
Joe Perches5e0cc8a2013-03-18 20:55:37 -07001173 } else { //RTS_needless
Malcolm Priestleyf6a634c2014-08-30 22:25:29 +01001174 pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
1175 pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
Joe Perches547f1cf2013-03-18 10:45:01 -07001176 pvRTS = NULL;
1177 pvCTS = NULL;
Malcolm Priestley9c62c7a2014-08-30 22:25:37 +01001178 pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
1179 cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
1180 cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
Joe Perches547f1cf2013-03-18 10:45:01 -07001181 }
1182 } // Auto Fall Back
1183 }
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001184
1185 td_info->mic_hdr = pMICHDR;
1186
Joe Perches547f1cf2013-03-18 10:45:01 -07001187 memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));
Forest Bond5449c682009-04-25 10:30:44 -04001188
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001189 /* Fill FIFO,RrvTime,RTS,and CTS */
1190 s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS,
1191 cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate);
1192 /* Fill DataHead */
1193 uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
Malcolm Priestley89cf9be2014-10-29 17:43:42 +00001194 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll);
Forest Bond5449c682009-04-25 10:30:44 -04001195
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001196 hdr->duration_id = uDuration;
Forest Bond5449c682009-04-25 10:30:44 -04001197
Malcolm Priestley19f3ed32014-11-29 00:02:03 +00001198 cbReqCount = cbHeaderLength + uPadding + skb->len;
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001199 pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
1200 uLength = cbHeaderLength + uPadding;
Forest Bond5449c682009-04-25 10:30:44 -04001201
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001202 /* Copy the Packet into a tx Buffer */
Malcolm Priestley19f3ed32014-11-29 00:02:03 +00001203 memcpy((pbyBuffer + uLength), skb->data, skb->len);
Guido Martínezbc5cf652014-04-19 16:45:00 -03001204
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001205 ptdCurr = (PSTxDesc)pHeadTD;
Forest Bond5449c682009-04-25 10:30:44 -04001206
Malcolm Priestleycfd9f0d2014-10-29 17:43:39 +00001207 ptdCurr->pTDInfo->dwReqCount = cbReqCount - uPadding;
1208 ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
1209 ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
1210 ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma);
1211 /* Set TSR1 & ReqCount in TxDescHead */
1212 ptdCurr->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
1213 ptdCurr->m_td1TD1.wReqCount = cpu_to_le16((unsigned short)(cbReqCount));
Forest Bond5449c682009-04-25 10:30:44 -04001214
Joe Perches547f1cf2013-03-18 10:45:01 -07001215 return cbHeaderLength;
Forest Bond5449c682009-04-25 10:30:44 -04001216}
1217
Malcolm Priestley01eec152014-10-29 17:43:38 +00001218static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
1219 struct ieee80211_key_conf *tx_key,
1220 struct sk_buff *skb, u16 payload_len,
1221 struct vnt_mic_hdr *mic_hdr)
1222{
1223 struct ieee80211_key_seq seq;
1224 u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
1225
1226 /* strip header and icv len from payload */
1227 payload_len -= ieee80211_get_hdrlen_from_skb(skb);
1228 payload_len -= tx_key->icv_len;
1229
1230 switch (tx_key->cipher) {
1231 case WLAN_CIPHER_SUITE_WEP40:
1232 case WLAN_CIPHER_SUITE_WEP104:
1233 memcpy(key_buffer, iv, 3);
1234 memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);
1235
1236 if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
1237 memcpy(key_buffer + 8, iv, 3);
1238 memcpy(key_buffer + 11,
1239 tx_key->key, WLAN_KEY_LEN_WEP40);
1240 }
1241
1242 break;
1243 case WLAN_CIPHER_SUITE_TKIP:
1244 ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);
1245
1246 break;
1247 case WLAN_CIPHER_SUITE_CCMP:
1248
1249 if (!mic_hdr)
1250 return;
1251
1252 mic_hdr->id = 0x59;
1253 mic_hdr->payload_len = cpu_to_be16(payload_len);
1254 ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
1255
1256 ieee80211_get_key_tx_seq(tx_key, &seq);
1257
1258 memcpy(mic_hdr->ccmp_pn, seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
1259
1260 if (ieee80211_has_a4(hdr->frame_control))
1261 mic_hdr->hlen = cpu_to_be16(28);
1262 else
1263 mic_hdr->hlen = cpu_to_be16(22);
1264
1265 ether_addr_copy(mic_hdr->addr1, hdr->addr1);
1266 ether_addr_copy(mic_hdr->addr2, hdr->addr2);
1267 ether_addr_copy(mic_hdr->addr3, hdr->addr3);
1268
1269 mic_hdr->frame_control = cpu_to_le16(
1270 le16_to_cpu(hdr->frame_control) & 0xc78f);
1271 mic_hdr->seq_ctrl = cpu_to_le16(
1272 le16_to_cpu(hdr->seq_ctrl) & 0xf);
1273
1274 if (ieee80211_has_a4(hdr->frame_control))
1275 ether_addr_copy(mic_hdr->addr4, hdr->addr4);
1276
1277 memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
1278
1279 break;
1280 default:
1281 break;
1282 }
1283}
1284
1285int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
1286 PSTxDesc head_td, struct sk_buff *skb)
1287{
1288 PDEVICE_TD_INFO td_info = head_td->pTDInfo;
1289 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1290 struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
1291 struct ieee80211_rate *rate;
1292 struct ieee80211_key_conf *tx_key;
1293 struct ieee80211_hdr *hdr;
1294 struct vnt_tx_fifo_head *tx_buffer_head =
1295 (struct vnt_tx_fifo_head *)td_info->buf;
Malcolm Priestley01eec152014-10-29 17:43:38 +00001296 u16 tx_body_size = skb->len, current_rate;
1297 u8 pkt_type;
1298 bool is_pspoll = false;
1299
1300 memset(tx_buffer_head, 0, sizeof(*tx_buffer_head));
1301
1302 hdr = (struct ieee80211_hdr *)(skb->data);
1303
1304 rate = ieee80211_get_tx_rate(priv->hw, info);
1305
1306 current_rate = rate->hw_value;
1307 if (priv->wCurrentRate != current_rate &&
1308 !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
1309 priv->wCurrentRate = current_rate;
1310
1311 RFbSetPower(priv, priv->wCurrentRate,
1312 priv->hw->conf.chandef.chan->hw_value);
1313 }
1314
1315 if (current_rate > RATE_11M)
1316 pkt_type = (u8)priv->byPacketType;
1317 else
1318 pkt_type = PK_TYPE_11B;
1319
1320 /*Set fifo controls */
1321 if (pkt_type == PK_TYPE_11A)
1322 tx_buffer_head->fifo_ctl = 0;
1323 else if (pkt_type == PK_TYPE_11B)
1324 tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
1325 else if (pkt_type == PK_TYPE_11GB)
1326 tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
1327 else if (pkt_type == PK_TYPE_11GA)
1328 tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
1329
1330 /* generate interrupt */
1331 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
1332
1333 if (!ieee80211_is_data(hdr->frame_control)) {
1334 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
1335 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0);
1336 tx_buffer_head->time_stamp =
1337 cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
1338 } else {
1339 tx_buffer_head->time_stamp =
1340 cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
1341 }
1342
1343 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
1344 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
1345
1346 if (ieee80211_has_retry(hdr->frame_control))
1347 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
1348
1349 if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1350 priv->byPreambleType = PREAMBLE_SHORT;
1351 else
1352 priv->byPreambleType = PREAMBLE_LONG;
1353
1354 if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
1355 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
1356
1357 if (ieee80211_has_a4(hdr->frame_control)) {
1358 tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
1359 priv->bLongHeader = true;
1360 }
1361
1362 if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)
1363 is_pspoll = true;
1364
1365 tx_buffer_head->frag_ctl =
1366 cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10);
1367
1368 if (info->control.hw_key) {
1369 tx_key = info->control.hw_key;
1370
1371 switch (info->control.hw_key->cipher) {
1372 case WLAN_CIPHER_SUITE_WEP40:
1373 case WLAN_CIPHER_SUITE_WEP104:
1374 tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
1375 break;
1376 case WLAN_CIPHER_SUITE_TKIP:
1377 tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
1378 break;
1379 case WLAN_CIPHER_SUITE_CCMP:
1380 tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
1381 default:
1382 break;
1383 }
1384 }
1385
1386 tx_buffer_head->current_rate = cpu_to_le16(current_rate);
1387
1388 /* legacy rates TODO use ieee80211_tx_rate */
1389 if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
1390 if (priv->byAutoFBCtrl == AUTO_FB_0)
1391 tx_buffer_head->fifo_ctl |=
1392 cpu_to_le16(FIFOCTL_AUTO_FB_0);
1393 else if (priv->byAutoFBCtrl == AUTO_FB_1)
1394 tx_buffer_head->fifo_ctl |=
1395 cpu_to_le16(FIFOCTL_AUTO_FB_1);
1396
1397 }
1398
1399 tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
1400
Malcolm Priestley19f3ed32014-11-29 00:02:03 +00001401 s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head,
Malcolm Priestley154bb8b2014-11-29 00:02:02 +00001402 dma_idx, head_td, is_pspoll);
Malcolm Priestley01eec152014-10-29 17:43:38 +00001403
1404 if (info->control.hw_key) {
1405 tx_key = info->control.hw_key;
1406 if (tx_key->keylen > 0)
1407 vnt_fill_txkey(hdr, tx_buffer_head->tx_key,
1408 tx_key, skb, tx_body_size, td_info->mic_hdr);
1409 }
1410
1411 return 0;
1412}
1413
1414static int vnt_beacon_xmit(struct vnt_private *priv,
1415 struct sk_buff *skb)
1416{
1417 struct vnt_tx_short_buf_head *short_head =
1418 (struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs;
1419 struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *)
1420 (priv->tx_beacon_bufs + sizeof(*short_head));
1421 struct ieee80211_tx_info *info;
1422 u32 frame_size = skb->len + 4;
1423 u16 current_rate;
1424
1425 memset(priv->tx_beacon_bufs, 0, sizeof(*short_head));
1426
1427 if (priv->byBBType == BB_TYPE_11A) {
1428 current_rate = RATE_6M;
1429
1430 /* Get SignalField,ServiceField,Length */
1431 vnt_get_phy_field(priv, frame_size, current_rate,
1432 PK_TYPE_11A, &short_head->ab);
1433
1434 /* Get Duration and TimeStampOff */
1435 short_head->duration =
1436 cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
1437 frame_size, PK_TYPE_11A, current_rate,
1438 false, 0, 0, 1, AUTO_FB_NONE));
1439
1440 short_head->time_stamp_off =
1441 vnt_time_stamp_off(priv, current_rate);
1442 } else {
1443 current_rate = RATE_1M;
1444 short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
1445
1446 /* Get SignalField,ServiceField,Length */
1447 vnt_get_phy_field(priv, frame_size, current_rate,
1448 PK_TYPE_11B, &short_head->ab);
1449
1450 /* Get Duration and TimeStampOff */
1451 short_head->duration =
1452 cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
1453 frame_size, PK_TYPE_11B, current_rate,
1454 false, 0, 0, 1, AUTO_FB_NONE));
1455
1456 short_head->time_stamp_off =
1457 vnt_time_stamp_off(priv, current_rate);
1458 }
1459
1460 short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
1461
1462 /* Copy Beacon */
1463 memcpy(mgmt_hdr, skb->data, skb->len);
1464
1465 /* time stamp always 0 */
1466 mgmt_hdr->u.beacon.timestamp = 0;
1467
1468 info = IEEE80211_SKB_CB(skb);
1469 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1470 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
1471
1472 hdr->duration_id = 0;
1473 hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4);
1474 }
1475
1476 priv->wSeqCounter++;
1477 if (priv->wSeqCounter > 0x0fff)
1478 priv->wSeqCounter = 0;
1479
1480 priv->wBCNBufLen = sizeof(*short_head) + skb->len;
1481
1482 MACvSetCurrBCNTxDescAddr(priv->PortOffset, priv->tx_beacon_dma);
1483
1484 MACvSetCurrBCNLength(priv->PortOffset, priv->wBCNBufLen);
1485 /* Set auto Transmit on */
1486 MACvRegBitsOn(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
1487 /* Poll Transmit the adapter */
1488 MACvTransmitBCN(priv->PortOffset);
1489
1490 return 0;
1491}
1492
1493int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
1494{
1495 struct sk_buff *beacon;
1496
1497 beacon = ieee80211_beacon_get(priv->hw, vif);
1498 if (!beacon)
1499 return -ENOMEM;
1500
1501 if (vnt_beacon_xmit(priv, beacon)) {
1502 ieee80211_free_txskb(priv->hw, beacon);
1503 return -ENODEV;
1504 }
1505
1506 return 0;
1507}
1508
1509int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
1510 struct ieee80211_bss_conf *conf)
1511{
1512 int ret;
1513
1514 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
1515
1516 VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1517
Malcolm Priestley738487f2014-11-12 21:11:09 +00001518 CARDvSetFirstNextTBTT(priv, conf->beacon_int);
Malcolm Priestley01eec152014-10-29 17:43:38 +00001519
1520 CARDbSetBeaconPeriod(priv, conf->beacon_int);
1521
1522 ret = vnt_beacon_make(priv, vif);
1523
1524 return ret;
1525}