]>
Commit | Line | Data |
---|---|---|
92b96797 FB |
1 | /* |
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: | |
f77f13e2 | 28 | * s_vGenerateTxParameter - Generate tx dma required parameter. |
92b96797 FB |
29 | * csBeacon_xmit - beacon tx function |
30 | * csMgmt_xmit - management tx function | |
31 | * s_uGetDataDuration - get tx data required duration | |
32 | * s_uFillDataHead- fulfill tx data duration header | |
f77f13e2 | 33 | * s_uGetRTSCTSDuration- get rtx/cts required duration |
92b96797 FB |
34 | * s_uGetRTSCTSRsvTime- get rts/cts reserved time |
35 | * s_uGetTxRsvTime- get frame reserved time | |
36 | * s_vFillCTSHead- fulfill CTS ctl header | |
f77f13e2 | 37 | * s_vFillFragParameter- Set fragment ctl parameter. |
92b96797 | 38 | * s_vFillRTSHead- fulfill RTS ctl header |
92b96797 FB |
39 | * vDMA0_tx_80211- tx 802.11 frame via dma0 |
40 | * vGenerateFIFOHeader- Generate tx FIFO ctl header | |
41 | * | |
42 | * Revision History: | |
43 | * | |
44 | */ | |
45 | ||
92b96797 | 46 | #include "device.h" |
92b96797 | 47 | #include "rxtx.h" |
92b96797 | 48 | #include "card.h" |
92b96797 | 49 | #include "mac.h" |
92b96797 | 50 | #include "rf.h" |
92b96797 | 51 | #include "usbpipe.h" |
9d26d60f | 52 | |
4a499de2 | 53 | static int msglevel = MSG_LEVEL_INFO; |
92b96797 | 54 | |
3b138851 | 55 | static const u16 wTimeStampOff[2][MAX_RATE] = { |
92b96797 FB |
56 | {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, // Long Preamble |
57 | {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, // Short Preamble | |
58 | }; | |
59 | ||
3b138851 | 60 | static const u16 wFB_Opt0[2][5] = { |
92b96797 FB |
61 | {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, // fallback_rate0 |
62 | {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, // fallback_rate1 | |
63 | }; | |
3b138851 | 64 | static const u16 wFB_Opt1[2][5] = { |
92b96797 FB |
65 | {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, // fallback_rate0 |
66 | {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, // fallback_rate1 | |
67 | }; | |
68 | ||
92b96797 FB |
69 | #define RTSDUR_BB 0 |
70 | #define RTSDUR_BA 1 | |
71 | #define RTSDUR_AA 2 | |
72 | #define CTSDUR_BA 3 | |
73 | #define RTSDUR_BA_F0 4 | |
74 | #define RTSDUR_AA_F0 5 | |
75 | #define RTSDUR_BA_F1 6 | |
76 | #define RTSDUR_AA_F1 7 | |
77 | #define CTSDUR_BA_F0 8 | |
78 | #define CTSDUR_BA_F1 9 | |
79 | #define DATADUR_B 10 | |
80 | #define DATADUR_A 11 | |
81 | #define DATADUR_A_F0 12 | |
82 | #define DATADUR_A_F1 13 | |
83 | ||
b89f3b94 | 84 | static struct vnt_usb_send_context *s_vGetFreeContext(struct vnt_private *); |
d56131de | 85 | |
c2c32da3 | 86 | static u16 s_vGenerateTxParameter(struct vnt_usb_send_context *tx_context, |
8e344c88 | 87 | u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer, |
fa57560c | 88 | struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize, |
72bf8059 | 89 | int bNeedACK, bool need_rts); |
d56131de | 90 | |
d56131de MP |
91 | static unsigned int s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType, |
92 | u32 cbFrameLength, u16 wRate, int bNeedAck); | |
93 | ||
20338015 | 94 | static __le16 s_uGetRTSCTSRsvTime(struct vnt_private *priv, |
3b6cee7b | 95 | u8 rsv_type, u8 pkt_type, u32 frame_length, u16 current_rate); |
d56131de | 96 | |
c2c32da3 | 97 | static u16 s_vFillCTSHead(struct vnt_usb_send_context *tx_context, |
5fb8e412 | 98 | u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength, |
26e7362c | 99 | int bNeedAck, u16 wCurrentRate); |
d56131de | 100 | |
c2c32da3 | 101 | static u16 s_vFillRTSHead(struct vnt_usb_send_context *tx_context, u8 byPktType, |
5fb8e412 | 102 | union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck, |
26e7362c | 103 | u16 wCurrentRate); |
d56131de | 104 | |
5abe3d63 | 105 | static __le16 s_uGetDataDuration(struct vnt_private *pDevice, |
3ed210ef | 106 | u8 byPktType, int bNeedAck); |
d56131de | 107 | |
7f591a11 | 108 | static __le16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, |
d56131de | 109 | u8 byDurType, u32 cbFrameLength, u8 byPktType, u16 wRate, |
26e7362c | 110 | int bNeedAck); |
92b96797 | 111 | |
aceaf018 | 112 | static struct vnt_usb_send_context |
b89f3b94 | 113 | *s_vGetFreeContext(struct vnt_private *priv) |
92b96797 | 114 | { |
b89f3b94 | 115 | struct vnt_usb_send_context *context = NULL; |
d56131de | 116 | int ii; |
92b96797 | 117 | |
b89f3b94 MP |
118 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n"); |
119 | ||
120 | for (ii = 0; ii < priv->cbTD; ii++) { | |
121 | if (!priv->apTD[ii]) | |
122 | return NULL; | |
123 | ||
124 | context = priv->apTD[ii]; | |
30a05b39 MP |
125 | if (context->in_use == false) { |
126 | context->in_use = true; | |
127 | memset(context->data, 0, | |
b89f3b94 | 128 | MAX_TOTAL_SIZE_WITH_ALL_HEADERS); |
1622c8fc MP |
129 | |
130 | context->hdr = NULL; | |
131 | ||
b89f3b94 MP |
132 | return context; |
133 | } | |
134 | } | |
135 | ||
136 | if (ii == priv->cbTD) | |
137 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"No Free Tx Context\n"); | |
aceaf018 | 138 | |
5c851383 | 139 | return NULL; |
92b96797 FB |
140 | } |
141 | ||
dab085b1 | 142 | static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) |
f115e76a MP |
143 | { |
144 | return cpu_to_le16(wTimeStampOff[priv->byPreambleType % 2] | |
145 | [rate % MAX_RATE]); | |
146 | } | |
147 | ||
92b96797 FB |
148 | /*byPktType : PK_TYPE_11A 0 |
149 | PK_TYPE_11B 1 | |
150 | PK_TYPE_11GB 2 | |
151 | PK_TYPE_11GA 3 | |
152 | */ | |
3fd5620f MP |
153 | static u32 s_uGetTxRsvTime(struct vnt_private *priv, u8 pkt_type, |
154 | u32 frame_length, u16 rate, int need_ack) | |
92b96797 | 155 | { |
3fd5620f | 156 | u32 data_time, ack_time; |
92b96797 | 157 | |
d38ee5b2 | 158 | data_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
3fd5620f | 159 | frame_length, rate); |
92b96797 | 160 | |
3fd5620f | 161 | if (pkt_type == PK_TYPE_11B) |
d38ee5b2 MP |
162 | ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
163 | 14, (u16)priv->byTopCCKBasicRate); | |
3fd5620f | 164 | else |
d38ee5b2 MP |
165 | ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
166 | 14, (u16)priv->byTopOFDMBasicRate); | |
3fd5620f MP |
167 | |
168 | if (need_ack) | |
169 | return data_time + priv->uSIFS + ack_time; | |
170 | ||
171 | return data_time; | |
92b96797 FB |
172 | } |
173 | ||
2075f654 | 174 | static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type, |
9c3806d5 MP |
175 | u32 frame_length, u16 rate, int need_ack) |
176 | { | |
177 | return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type, | |
178 | frame_length, rate, need_ack)); | |
179 | } | |
180 | ||
92b96797 | 181 | //byFreqType: 0=>5GHZ 1=>2.4GHZ |
20338015 | 182 | static __le16 s_uGetRTSCTSRsvTime(struct vnt_private *priv, |
3b6cee7b | 183 | u8 rsv_type, u8 pkt_type, u32 frame_length, u16 current_rate) |
92b96797 | 184 | { |
342e2e20 | 185 | u32 rrv_time, rts_time, cts_time, ack_time, data_time; |
92b96797 | 186 | |
342e2e20 | 187 | rrv_time = rts_time = cts_time = ack_time = data_time = 0; |
92b96797 | 188 | |
d38ee5b2 | 189 | data_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
3b6cee7b | 190 | frame_length, current_rate); |
342e2e20 MP |
191 | |
192 | if (rsv_type == 0) { | |
d38ee5b2 | 193 | rts_time = vnt_get_frame_time(priv->byPreambleType, |
342e2e20 | 194 | pkt_type, 20, priv->byTopCCKBasicRate); |
d38ee5b2 | 195 | cts_time = ack_time = vnt_get_frame_time(priv->byPreambleType, |
342e2e20 MP |
196 | pkt_type, 14, priv->byTopCCKBasicRate); |
197 | } else if (rsv_type == 1) { | |
d38ee5b2 | 198 | rts_time = vnt_get_frame_time(priv->byPreambleType, |
342e2e20 | 199 | pkt_type, 20, priv->byTopCCKBasicRate); |
d38ee5b2 | 200 | cts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
342e2e20 | 201 | 14, priv->byTopCCKBasicRate); |
d38ee5b2 | 202 | ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
342e2e20 MP |
203 | 14, priv->byTopOFDMBasicRate); |
204 | } else if (rsv_type == 2) { | |
d38ee5b2 | 205 | rts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
342e2e20 | 206 | 20, priv->byTopOFDMBasicRate); |
d38ee5b2 | 207 | cts_time = ack_time = vnt_get_frame_time(priv->byPreambleType, |
342e2e20 MP |
208 | pkt_type, 14, priv->byTopOFDMBasicRate); |
209 | } else if (rsv_type == 3) { | |
d38ee5b2 | 210 | cts_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
342e2e20 | 211 | 14, priv->byTopCCKBasicRate); |
d38ee5b2 | 212 | ack_time = vnt_get_frame_time(priv->byPreambleType, pkt_type, |
342e2e20 MP |
213 | 14, priv->byTopOFDMBasicRate); |
214 | ||
215 | rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS; | |
216 | ||
20338015 | 217 | return cpu_to_le16((u16)rrv_time); |
342e2e20 MP |
218 | } |
219 | ||
220 | rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS; | |
92b96797 | 221 | |
342e2e20 | 222 | return cpu_to_le16((u16)rrv_time); |
92b96797 FB |
223 | } |
224 | ||
225 | //byFreqType 0: 5GHz, 1:2.4Ghz | |
5abe3d63 | 226 | static __le16 s_uGetDataDuration(struct vnt_private *pDevice, |
6b5ad9d2 | 227 | u8 byPktType, int bNeedAck) |
92b96797 | 228 | { |
0005cb00 | 229 | u32 uAckTime = 0; |
92b96797 | 230 | |
b02ccd59 | 231 | if (bNeedAck) { |
6b5ad9d2 | 232 | if (byPktType == PK_TYPE_11B) |
d38ee5b2 | 233 | uAckTime = vnt_get_frame_time(pDevice->byPreambleType, |
b02ccd59 MP |
234 | byPktType, 14, pDevice->byTopCCKBasicRate); |
235 | else | |
d38ee5b2 | 236 | uAckTime = vnt_get_frame_time(pDevice->byPreambleType, |
b02ccd59 | 237 | byPktType, 14, pDevice->byTopOFDMBasicRate); |
d5005955 | 238 | return cpu_to_le16((u16)(pDevice->uSIFS + uAckTime)); |
b02ccd59 | 239 | } |
92b96797 | 240 | |
92b96797 FB |
241 | return 0; |
242 | } | |
243 | ||
92b96797 | 244 | //byFreqType: 0=>5GHZ 1=>2.4GHZ |
7f591a11 | 245 | static __le16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType, |
26e7362c | 246 | u32 cbFrameLength, u8 byPktType, u16 wRate, int bNeedAck) |
92b96797 | 247 | { |
d56131de | 248 | u32 uCTSTime = 0, uDurTime = 0; |
92b96797 | 249 | |
ecd80240 MP |
250 | switch (byDurType) { |
251 | case RTSDUR_BB: | |
252 | case RTSDUR_BA: | |
253 | case RTSDUR_BA_F0: | |
254 | case RTSDUR_BA_F1: | |
d38ee5b2 MP |
255 | uCTSTime = vnt_get_frame_time(pDevice->byPreambleType, |
256 | byPktType, 14, pDevice->byTopCCKBasicRate); | |
ecd80240 MP |
257 | uDurTime = uCTSTime + 2 * pDevice->uSIFS + |
258 | s_uGetTxRsvTime(pDevice, byPktType, | |
259 | cbFrameLength, wRate, bNeedAck); | |
260 | break; | |
92b96797 | 261 | |
ecd80240 MP |
262 | case RTSDUR_AA: |
263 | case RTSDUR_AA_F0: | |
264 | case RTSDUR_AA_F1: | |
d38ee5b2 MP |
265 | uCTSTime = vnt_get_frame_time(pDevice->byPreambleType, |
266 | byPktType, 14, pDevice->byTopOFDMBasicRate); | |
ecd80240 MP |
267 | uDurTime = uCTSTime + 2 * pDevice->uSIFS + |
268 | s_uGetTxRsvTime(pDevice, byPktType, | |
269 | cbFrameLength, wRate, bNeedAck); | |
270 | break; | |
92b96797 | 271 | |
ecd80240 MP |
272 | case CTSDUR_BA: |
273 | case CTSDUR_BA_F0: | |
274 | case CTSDUR_BA_F1: | |
275 | uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, | |
f84cdf65 | 276 | byPktType, cbFrameLength, wRate, bNeedAck); |
ecd80240 | 277 | break; |
92b96797 | 278 | |
ecd80240 MP |
279 | default: |
280 | break; | |
281 | } | |
92b96797 | 282 | |
e34f9dbe | 283 | return cpu_to_le16((u16)uDurTime); |
92b96797 FB |
284 | } |
285 | ||
1622c8fc MP |
286 | static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context, |
287 | struct ieee80211_hdr *hdr) | |
288 | { | |
289 | u8 *head = tx_context->data + offsetof(struct vnt_tx_buffer, fifo_head); | |
290 | u8 *hdr_pos = (u8 *)hdr; | |
291 | ||
292 | tx_context->hdr = hdr; | |
293 | if (!tx_context->hdr) | |
294 | return 0; | |
295 | ||
296 | return (u16)(hdr_pos - head); | |
297 | } | |
298 | ||
c2c32da3 MP |
299 | static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, |
300 | u8 pkt_type, u16 rate, struct vnt_tx_datahead_g *buf, | |
301 | u32 frame_len, int need_ack) | |
78363fd1 | 302 | { |
c2c32da3 MP |
303 | |
304 | struct vnt_private *priv = tx_context->priv; | |
893cc709 MP |
305 | struct ieee80211_hdr *hdr = |
306 | (struct ieee80211_hdr *)tx_context->skb->data; | |
c2c32da3 | 307 | |
78363fd1 | 308 | /* Get SignalField,ServiceField,Length */ |
205056f3 MP |
309 | vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a); |
310 | vnt_get_phy_field(priv, frame_len, priv->byTopCCKBasicRate, | |
78363fd1 MP |
311 | PK_TYPE_11B, &buf->b); |
312 | ||
313 | /* Get Duration and TimeStamp */ | |
893cc709 MP |
314 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
315 | __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); | |
316 | ||
317 | buf->duration_a = dur; | |
318 | buf->duration_b = dur; | |
319 | } else { | |
320 | buf->duration_a = s_uGetDataDuration(priv, pkt_type, need_ack); | |
321 | buf->duration_b = s_uGetDataDuration(priv, | |
322 | PK_TYPE_11B, need_ack); | |
323 | } | |
78363fd1 | 324 | |
10bb39a0 MP |
325 | buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); |
326 | buf->time_stamp_off_b = vnt_time_stamp_off(priv, | |
78363fd1 MP |
327 | priv->byTopCCKBasicRate); |
328 | ||
1622c8fc MP |
329 | tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); |
330 | ||
c4cf6dfb | 331 | return le16_to_cpu(buf->duration_a); |
78363fd1 MP |
332 | } |
333 | ||
c2c32da3 MP |
334 | static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context, |
335 | u8 pkt_type, u16 rate, struct vnt_tx_datahead_g_fb *buf, | |
5b852f53 MP |
336 | u32 frame_len, int need_ack) |
337 | { | |
c2c32da3 MP |
338 | struct vnt_private *priv = tx_context->priv; |
339 | ||
5b852f53 | 340 | /* Get SignalField,ServiceField,Length */ |
205056f3 | 341 | vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a); |
5b852f53 | 342 | |
205056f3 | 343 | vnt_get_phy_field(priv, frame_len, priv->byTopCCKBasicRate, |
5b852f53 MP |
344 | PK_TYPE_11B, &buf->b); |
345 | ||
346 | /* Get Duration and TimeStamp */ | |
4e01117c MP |
347 | buf->duration_a = s_uGetDataDuration(priv, pkt_type, need_ack); |
348 | buf->duration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack); | |
5b852f53 | 349 | |
4e01117c MP |
350 | buf->duration_a_f0 = s_uGetDataDuration(priv, pkt_type, need_ack); |
351 | buf->duration_a_f1 = s_uGetDataDuration(priv, pkt_type, need_ack); | |
5b852f53 | 352 | |
10bb39a0 MP |
353 | buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); |
354 | buf->time_stamp_off_b = vnt_time_stamp_off(priv, | |
5b852f53 MP |
355 | priv->byTopCCKBasicRate); |
356 | ||
1622c8fc MP |
357 | tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); |
358 | ||
c4cf6dfb | 359 | return le16_to_cpu(buf->duration_a); |
5b852f53 MP |
360 | } |
361 | ||
c2c32da3 MP |
362 | static u16 vnt_rxtx_datahead_a_fb(struct vnt_usb_send_context *tx_context, |
363 | u8 pkt_type, u16 rate, struct vnt_tx_datahead_a_fb *buf, | |
bd3f51f1 MP |
364 | u32 frame_len, int need_ack) |
365 | { | |
c2c32da3 MP |
366 | struct vnt_private *priv = tx_context->priv; |
367 | ||
bd3f51f1 | 368 | /* Get SignalField,ServiceField,Length */ |
205056f3 | 369 | vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a); |
bd3f51f1 | 370 | /* Get Duration and TimeStampOff */ |
4e01117c | 371 | buf->duration = s_uGetDataDuration(priv, pkt_type, need_ack); |
bd3f51f1 | 372 | |
4e01117c MP |
373 | buf->duration_f0 = s_uGetDataDuration(priv, pkt_type, need_ack); |
374 | buf->duration_f1 = s_uGetDataDuration(priv, pkt_type, need_ack); | |
bd3f51f1 | 375 | |
10bb39a0 | 376 | buf->time_stamp_off = vnt_time_stamp_off(priv, rate); |
bd3f51f1 | 377 | |
1622c8fc MP |
378 | tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); |
379 | ||
c4cf6dfb | 380 | return le16_to_cpu(buf->duration); |
bd3f51f1 MP |
381 | } |
382 | ||
c2c32da3 MP |
383 | static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, |
384 | u8 pkt_type, u16 rate, struct vnt_tx_datahead_ab *buf, | |
5634a5ab MP |
385 | u32 frame_len, int need_ack) |
386 | { | |
c2c32da3 | 387 | struct vnt_private *priv = tx_context->priv; |
893cc709 MP |
388 | struct ieee80211_hdr *hdr = |
389 | (struct ieee80211_hdr *)tx_context->skb->data; | |
c2c32da3 | 390 | |
5634a5ab | 391 | /* Get SignalField,ServiceField,Length */ |
205056f3 | 392 | vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->ab); |
893cc709 | 393 | |
5634a5ab | 394 | /* Get Duration and TimeStampOff */ |
893cc709 MP |
395 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
396 | __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); | |
397 | ||
398 | buf->duration = dur; | |
399 | } else { | |
400 | buf->duration = s_uGetDataDuration(priv, pkt_type, need_ack); | |
401 | } | |
5634a5ab | 402 | |
10bb39a0 | 403 | buf->time_stamp_off = vnt_time_stamp_off(priv, rate); |
5634a5ab | 404 | |
1622c8fc MP |
405 | tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); |
406 | ||
c4cf6dfb | 407 | return le16_to_cpu(buf->duration); |
5634a5ab MP |
408 | } |
409 | ||
d38b13aa MP |
410 | static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context, |
411 | struct ieee80211_rts *rts, __le16 duration) | |
5e67ee49 | 412 | { |
d38b13aa MP |
413 | struct ieee80211_hdr *hdr = |
414 | (struct ieee80211_hdr *)tx_context->skb->data; | |
415 | ||
5e67ee49 | 416 | rts->duration = duration; |
f4554d3b MP |
417 | rts->frame_control = |
418 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); | |
5e67ee49 | 419 | |
d38b13aa MP |
420 | memcpy(rts->ra, hdr->addr1, ETH_ALEN); |
421 | memcpy(rts->ta, hdr->addr2, ETH_ALEN); | |
5e67ee49 MP |
422 | |
423 | return 0; | |
424 | } | |
425 | ||
c2c32da3 | 426 | static u16 vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context, |
72bf8059 | 427 | struct vnt_rts_g *buf, u8 pkt_type, u32 frame_len, int need_ack, |
26e7362c | 428 | u16 current_rate) |
5e67ee49 | 429 | { |
c2c32da3 | 430 | struct vnt_private *priv = tx_context->priv; |
5e67ee49 MP |
431 | u16 rts_frame_len = 20; |
432 | ||
205056f3 | 433 | vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate, |
5e67ee49 | 434 | PK_TYPE_11B, &buf->b); |
205056f3 | 435 | vnt_get_phy_field(priv, rts_frame_len, |
5e67ee49 MP |
436 | priv->byTopOFDMBasicRate, pkt_type, &buf->a); |
437 | ||
4e01117c | 438 | buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len, |
26e7362c | 439 | PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack); |
4e01117c | 440 | buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len, |
26e7362c | 441 | pkt_type, current_rate, need_ack); |
4e01117c | 442 | buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len, |
26e7362c | 443 | pkt_type, current_rate, need_ack); |
5e67ee49 | 444 | |
d38b13aa | 445 | vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa); |
5e67ee49 | 446 | |
c2c32da3 | 447 | return vnt_rxtx_datahead_g(tx_context, pkt_type, current_rate, |
78363fd1 | 448 | &buf->data_head, frame_len, need_ack); |
5e67ee49 MP |
449 | } |
450 | ||
c2c32da3 | 451 | static u16 vnt_rxtx_rts_g_fb_head(struct vnt_usb_send_context *tx_context, |
72bf8059 | 452 | struct vnt_rts_g_fb *buf, u8 pkt_type, u32 frame_len, int need_ack, |
26e7362c | 453 | u16 current_rate) |
ec91713a | 454 | { |
c2c32da3 | 455 | struct vnt_private *priv = tx_context->priv; |
ec91713a MP |
456 | u16 rts_frame_len = 20; |
457 | ||
205056f3 | 458 | vnt_get_phy_field(priv, rts_frame_len, priv->byTopCCKBasicRate, |
ec91713a | 459 | PK_TYPE_11B, &buf->b); |
205056f3 | 460 | vnt_get_phy_field(priv, rts_frame_len, |
ec91713a MP |
461 | priv->byTopOFDMBasicRate, pkt_type, &buf->a); |
462 | ||
463 | ||
4e01117c | 464 | buf->duration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len, |
26e7362c | 465 | PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack); |
4e01117c | 466 | buf->duration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len, |
26e7362c | 467 | pkt_type, current_rate, need_ack); |
4e01117c | 468 | buf->duration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len, |
26e7362c | 469 | pkt_type, current_rate, need_ack); |
ec91713a MP |
470 | |
471 | ||
fadc3bdf | 472 | buf->rts_duration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0, |
26e7362c | 473 | frame_len, pkt_type, priv->tx_rate_fb0, need_ack); |
fadc3bdf | 474 | buf->rts_duration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0, |
26e7362c | 475 | frame_len, pkt_type, priv->tx_rate_fb0, need_ack); |
fadc3bdf | 476 | buf->rts_duration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1, |
26e7362c | 477 | frame_len, pkt_type, priv->tx_rate_fb1, need_ack); |
fadc3bdf | 478 | buf->rts_duration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1, |
26e7362c | 479 | frame_len, pkt_type, priv->tx_rate_fb1, need_ack); |
ec91713a | 480 | |
d38b13aa | 481 | vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa); |
ec91713a | 482 | |
c2c32da3 | 483 | return vnt_rxtx_datahead_g_fb(tx_context, pkt_type, current_rate, |
5b852f53 | 484 | &buf->data_head, frame_len, need_ack); |
ec91713a MP |
485 | } |
486 | ||
c2c32da3 | 487 | static u16 vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context, |
72bf8059 | 488 | struct vnt_rts_ab *buf, u8 pkt_type, u32 frame_len, int need_ack, |
26e7362c | 489 | u16 current_rate) |
1712633d | 490 | { |
c2c32da3 | 491 | struct vnt_private *priv = tx_context->priv; |
1712633d MP |
492 | u16 rts_frame_len = 20; |
493 | ||
205056f3 | 494 | vnt_get_phy_field(priv, rts_frame_len, |
1712633d MP |
495 | priv->byTopOFDMBasicRate, pkt_type, &buf->ab); |
496 | ||
4e01117c | 497 | buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len, |
26e7362c | 498 | pkt_type, current_rate, need_ack); |
1712633d | 499 | |
d38b13aa | 500 | vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration); |
1712633d | 501 | |
c2c32da3 | 502 | return vnt_rxtx_datahead_ab(tx_context, pkt_type, current_rate, |
5634a5ab | 503 | &buf->data_head, frame_len, need_ack); |
1712633d MP |
504 | } |
505 | ||
c2c32da3 | 506 | static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context, |
72bf8059 | 507 | struct vnt_rts_a_fb *buf, u8 pkt_type, u32 frame_len, int need_ack, |
26e7362c | 508 | u16 current_rate) |
9d2578c1 | 509 | { |
c2c32da3 | 510 | struct vnt_private *priv = tx_context->priv; |
9d2578c1 MP |
511 | u16 rts_frame_len = 20; |
512 | ||
205056f3 | 513 | vnt_get_phy_field(priv, rts_frame_len, |
9d2578c1 MP |
514 | priv->byTopOFDMBasicRate, pkt_type, &buf->a); |
515 | ||
4e01117c | 516 | buf->duration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len, |
26e7362c | 517 | pkt_type, current_rate, need_ack); |
9d2578c1 | 518 | |
fadc3bdf | 519 | buf->rts_duration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0, |
26e7362c | 520 | frame_len, pkt_type, priv->tx_rate_fb0, need_ack); |
9d2578c1 | 521 | |
fadc3bdf | 522 | buf->rts_duration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1, |
26e7362c | 523 | frame_len, pkt_type, priv->tx_rate_fb1, need_ack); |
9d2578c1 | 524 | |
d38b13aa | 525 | vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration); |
9d2578c1 | 526 | |
c2c32da3 | 527 | return vnt_rxtx_datahead_a_fb(tx_context, pkt_type, current_rate, |
bd3f51f1 | 528 | &buf->data_head, frame_len, need_ack); |
9d2578c1 MP |
529 | } |
530 | ||
c2c32da3 | 531 | static u16 s_vFillRTSHead(struct vnt_usb_send_context *tx_context, u8 byPktType, |
5fb8e412 | 532 | union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck, |
26e7362c | 533 | u16 wCurrentRate) |
92b96797 | 534 | { |
92b96797 | 535 | |
13fe62ae | 536 | if (!head) |
0a0f4b69 | 537 | return 0; |
92b96797 | 538 | |
9d5829bf MP |
539 | /* Note: So far RTSHead doesn't appear in ATIM |
540 | * & Beacom DMA, so we don't need to take them | |
541 | * into account. | |
542 | * Otherwise, we need to modified codes for them. | |
543 | */ | |
0bddd303 | 544 | switch (byPktType) { |
0bddd303 | 545 | case PK_TYPE_11A: |
ce7b0db8 | 546 | if (tx_context->fb_option) { |
c2c32da3 | 547 | return vnt_rxtx_rts_a_fb_head(tx_context, |
72bf8059 | 548 | &head->rts_a_fb, byPktType, |
26e7362c | 549 | cbFrameLength, bNeedAck, wCurrentRate); |
2b83ebd0 MP |
550 | break; |
551 | } | |
0bddd303 | 552 | case PK_TYPE_11B: |
c2c32da3 | 553 | return vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab, |
72bf8059 | 554 | byPktType, cbFrameLength, bNeedAck, |
26e7362c | 555 | wCurrentRate); |
9d5829bf | 556 | } |
0a0f4b69 MP |
557 | |
558 | return 0; | |
92b96797 FB |
559 | } |
560 | ||
c2c32da3 | 561 | static u16 s_vFillCTSHead(struct vnt_usb_send_context *tx_context, |
5fb8e412 | 562 | u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength, |
26e7362c | 563 | int bNeedAck, u16 wCurrentRate) |
92b96797 | 564 | { |
c2c32da3 | 565 | struct vnt_private *pDevice = tx_context->priv; |
d56131de | 566 | u32 uCTSFrameLen = 14; |
92b96797 | 567 | |
27df3ebf | 568 | if (!head) |
0a0f4b69 | 569 | return 0; |
92b96797 | 570 | |
ce7b0db8 | 571 | if (tx_context->fb_option) { |
c921cc8c | 572 | /* Auto Fall back */ |
27df3ebf | 573 | struct vnt_cts_fb *pBuf = &head->cts_g_fb; |
aed387c7 | 574 | /* Get SignalField,ServiceField,Length */ |
205056f3 | 575 | vnt_get_phy_field(pDevice, uCTSFrameLen, |
aed387c7 | 576 | pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b); |
4e01117c | 577 | pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, |
e34f9dbe | 578 | cbFrameLength, byPktType, |
26e7362c | 579 | wCurrentRate, bNeedAck); |
e34f9dbe | 580 | /* Get CTSDuration_ba_f0 */ |
7fd5747f | 581 | pBuf->cts_duration_ba_f0 = s_uGetRTSCTSDuration(pDevice, |
f84cdf65 | 582 | CTSDUR_BA_F0, cbFrameLength, byPktType, |
26e7362c | 583 | pDevice->tx_rate_fb0, bNeedAck); |
e34f9dbe | 584 | /* Get CTSDuration_ba_f1 */ |
7fd5747f | 585 | pBuf->cts_duration_ba_f1 = s_uGetRTSCTSDuration(pDevice, |
f84cdf65 | 586 | CTSDUR_BA_F1, cbFrameLength, byPktType, |
26e7362c | 587 | pDevice->tx_rate_fb1, bNeedAck); |
14840cdd | 588 | /* Get CTS Frame body */ |
4e01117c | 589 | pBuf->data.duration = pBuf->duration_ba; |
d9560ae5 MP |
590 | pBuf->data.frame_control = |
591 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); | |
592 | ||
14840cdd | 593 | memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN); |
5b852f53 | 594 | |
c2c32da3 MP |
595 | return vnt_rxtx_datahead_g_fb(tx_context, byPktType, |
596 | wCurrentRate, &pBuf->data_head, cbFrameLength, | |
597 | bNeedAck); | |
c921cc8c | 598 | } else { |
27df3ebf | 599 | struct vnt_cts *pBuf = &head->cts_g; |
aed387c7 | 600 | /* Get SignalField,ServiceField,Length */ |
205056f3 | 601 | vnt_get_phy_field(pDevice, uCTSFrameLen, |
aed387c7 | 602 | pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b); |
e34f9dbe | 603 | /* Get CTSDuration_ba */ |
4e01117c | 604 | pBuf->duration_ba = s_uGetRTSCTSDuration(pDevice, |
e34f9dbe | 605 | CTSDUR_BA, cbFrameLength, byPktType, |
26e7362c | 606 | wCurrentRate, bNeedAck); |
14840cdd | 607 | /*Get CTS Frame body*/ |
4e01117c | 608 | pBuf->data.duration = pBuf->duration_ba; |
d9560ae5 MP |
609 | pBuf->data.frame_control = |
610 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); | |
611 | ||
14840cdd | 612 | memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN); |
78363fd1 | 613 | |
c2c32da3 | 614 | return vnt_rxtx_datahead_g(tx_context, byPktType, wCurrentRate, |
78363fd1 | 615 | &pBuf->data_head, cbFrameLength, bNeedAck); |
92b96797 | 616 | } |
0a0f4b69 MP |
617 | |
618 | return 0; | |
92b96797 FB |
619 | } |
620 | ||
24cdd90f MP |
621 | static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context, |
622 | union vnt_tx_head *tx_head, u8 pkt_type, u32 frame_size, | |
4f06c0dc | 623 | int need_ack, u16 current_rate, bool need_mic) |
24cdd90f MP |
624 | { |
625 | struct vnt_private *priv = tx_context->priv; | |
626 | struct vnt_rrv_time_rts *buf = &tx_head->tx_rts.rts; | |
4f06c0dc | 627 | union vnt_tx_data_head *head = &tx_head->tx_rts.tx.head; |
24cdd90f MP |
628 | |
629 | buf->rts_rrv_time_aa = s_uGetRTSCTSRsvTime(priv, 2, | |
630 | pkt_type, frame_size, current_rate); | |
631 | buf->rts_rrv_time_ba = s_uGetRTSCTSRsvTime(priv, 1, | |
632 | pkt_type, frame_size, current_rate); | |
633 | buf->rts_rrv_time_bb = s_uGetRTSCTSRsvTime(priv, 0, | |
634 | pkt_type, frame_size, current_rate); | |
635 | ||
636 | buf->rrv_time_a = vnt_rxtx_rsvtime_le16(priv, pkt_type, frame_size, | |
637 | current_rate, need_ack); | |
638 | buf->rrv_time_b = vnt_rxtx_rsvtime_le16(priv, PK_TYPE_11B, frame_size, | |
639 | priv->byTopCCKBasicRate, need_ack); | |
640 | ||
4f06c0dc MP |
641 | if (need_mic) |
642 | head = &tx_head->tx_rts.tx.mic.head; | |
643 | ||
644 | if (tx_context->fb_option) | |
645 | return vnt_rxtx_rts_g_fb_head(tx_context, &head->rts_g_fb, | |
646 | pkt_type, frame_size, need_ack, current_rate); | |
647 | ||
648 | return vnt_rxtx_rts_g_head(tx_context, &head->rts_g, | |
649 | pkt_type, frame_size, need_ack, current_rate); | |
24cdd90f MP |
650 | } |
651 | ||
bf9c0118 MP |
652 | static u16 vnt_rxtx_cts(struct vnt_usb_send_context *tx_context, |
653 | union vnt_tx_head *tx_head, u8 pkt_type, u32 frame_size, | |
b00cb684 | 654 | int need_ack, u16 current_rate, bool need_mic) |
bf9c0118 MP |
655 | { |
656 | struct vnt_private *priv = tx_context->priv; | |
657 | struct vnt_rrv_time_cts *buf = &tx_head->tx_cts.cts; | |
b00cb684 MP |
658 | union vnt_tx_data_head *head = &tx_head->tx_cts.tx.head; |
659 | ||
bf9c0118 MP |
660 | |
661 | buf->rrv_time_a = vnt_rxtx_rsvtime_le16(priv, pkt_type, | |
662 | frame_size, current_rate, need_ack); | |
663 | buf->rrv_time_b = vnt_rxtx_rsvtime_le16(priv, PK_TYPE_11B, | |
664 | frame_size, priv->byTopCCKBasicRate, need_ack); | |
665 | ||
666 | buf->cts_rrv_time_ba = s_uGetRTSCTSRsvTime(priv, 3, | |
667 | pkt_type, frame_size, current_rate); | |
668 | ||
b00cb684 MP |
669 | if (need_mic) |
670 | head = &tx_head->tx_cts.tx.mic.head; | |
671 | ||
672 | /* Fill CTS */ | |
673 | return s_vFillCTSHead(tx_context, pkt_type, head, frame_size, | |
674 | need_ack, current_rate); | |
bf9c0118 MP |
675 | } |
676 | ||
3b03fea2 MP |
677 | static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context, |
678 | union vnt_tx_head *tx_head, u8 pkt_type, u32 frame_size, | |
679 | int need_ack, u16 current_rate, bool need_rts) | |
680 | { | |
681 | struct vnt_private *priv = tx_context->priv; | |
682 | struct vnt_rrv_time_ab *buf = &tx_head->tx_ab.ab; | |
683 | ||
684 | buf->rrv_time = vnt_rxtx_rsvtime_le16(priv, pkt_type, | |
685 | frame_size, current_rate, need_ack); | |
686 | ||
687 | if (need_rts) { | |
688 | if (pkt_type == PK_TYPE_11B) | |
689 | buf->rts_rrv_time = s_uGetRTSCTSRsvTime(priv, 0, | |
690 | pkt_type, frame_size, current_rate); | |
691 | else /* PK_TYPE_11A */ | |
692 | buf->rts_rrv_time = s_uGetRTSCTSRsvTime(priv, 2, | |
693 | pkt_type, frame_size, current_rate); | |
694 | } | |
695 | ||
696 | return 0; | |
697 | } | |
698 | ||
92b96797 FB |
699 | /*+ |
700 | * | |
701 | * Description: | |
702 | * Generate FIFO control for MAC & Baseband controller | |
703 | * | |
704 | * Parameters: | |
705 | * In: | |
706 | * pDevice - Pointer to adpater | |
707 | * pTxDataHead - Transmit Data Buffer | |
708 | * pTxBufHead - pTxBufHead | |
709 | * pvRrvTime - pvRrvTime | |
710 | * pvRTS - RTS Buffer | |
711 | * pCTS - CTS Buffer | |
712 | * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) | |
713 | * bNeedACK - If need ACK | |
92b96797 FB |
714 | * Out: |
715 | * none | |
716 | * | |
717 | * Return Value: none | |
718 | * | |
719 | -*/ | |
cc856e61 | 720 | |
c2c32da3 | 721 | static u16 s_vGenerateTxParameter(struct vnt_usb_send_context *tx_context, |
8e344c88 | 722 | u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer, |
fa57560c | 723 | struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize, |
72bf8059 | 724 | int bNeedACK, bool need_rts) |
92b96797 | 725 | { |
b9cc2fc0 | 726 | union vnt_tx_data_head *head = NULL; |
92b96797 | 727 | |
92928f13 MP |
728 | if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { |
729 | if (need_rts) { | |
4f06c0dc | 730 | if (need_mic) |
92928f13 MP |
731 | *mic_hdr = &tx_buffer-> |
732 | tx_head.tx_rts.tx.mic.hdr; | |
f0e0d505 | 733 | |
4f06c0dc MP |
734 | return vnt_rxtx_rts(tx_context, &tx_buffer->tx_head, |
735 | byPktType, cbFrameSize, bNeedACK, | |
736 | wCurrentRate, need_mic); | |
92928f13 | 737 | } else { |
b00cb684 | 738 | if (need_mic) |
92928f13 MP |
739 | *mic_hdr = &tx_buffer-> |
740 | tx_head.tx_cts.tx.mic.hdr; | |
b00cb684 MP |
741 | |
742 | return vnt_rxtx_cts(tx_context, &tx_buffer->tx_head, | |
743 | byPktType, cbFrameSize, bNeedACK, | |
744 | wCurrentRate, need_mic); | |
92928f13 MP |
745 | } |
746 | } else if (byPktType == PK_TYPE_11A) { | |
b9cc2fc0 | 747 | if (need_mic) { |
92928f13 MP |
748 | *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; |
749 | head = &tx_buffer->tx_head.tx_ab.tx.mic.head; | |
b9cc2fc0 | 750 | } else { |
92928f13 | 751 | head = &tx_buffer->tx_head.tx_ab.tx.head; |
b9cc2fc0 | 752 | } |
f0e0d505 | 753 | |
92928f13 | 754 | if (need_rts) { |
3b03fea2 MP |
755 | vnt_rxtx_ab(tx_context, &tx_buffer->tx_head, byPktType, |
756 | cbFrameSize, bNeedACK, wCurrentRate, need_rts); | |
b9cc2fc0 | 757 | |
9e38a5c1 | 758 | |
92928f13 | 759 | /* Fill RTS */ |
c2c32da3 | 760 | return s_vFillRTSHead(tx_context, byPktType, head, |
72bf8059 | 761 | cbFrameSize, bNeedACK, |
26e7362c | 762 | wCurrentRate); |
92928f13 | 763 | } else { |
3b03fea2 MP |
764 | vnt_rxtx_ab(tx_context, &tx_buffer->tx_head, byPktType, |
765 | cbFrameSize, bNeedACK, wCurrentRate, need_rts); | |
c12dca09 | 766 | |
c2c32da3 | 767 | return vnt_rxtx_datahead_a_fb(tx_context, byPktType, |
92928f13 MP |
768 | wCurrentRate, &head->data_head_a_fb, |
769 | cbFrameSize, bNeedACK); | |
770 | } | |
771 | } else if (byPktType == PK_TYPE_11B) { | |
772 | if (need_mic) { | |
773 | *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; | |
774 | head = &tx_buffer->tx_head.tx_ab.tx.mic.head; | |
775 | } else { | |
776 | head = &tx_buffer->tx_head.tx_ab.tx.head; | |
777 | } | |
778 | ||
779 | if (need_rts) { | |
3b03fea2 MP |
780 | vnt_rxtx_ab(tx_context, &tx_buffer->tx_head, byPktType, |
781 | cbFrameSize, bNeedACK, wCurrentRate, need_rts); | |
92928f13 MP |
782 | |
783 | /* Fill RTS */ | |
c2c32da3 | 784 | return s_vFillRTSHead(tx_context, byPktType, head, |
72bf8059 | 785 | cbFrameSize, bNeedACK, |
26e7362c | 786 | wCurrentRate); |
92928f13 | 787 | } else { |
3b03fea2 MP |
788 | vnt_rxtx_ab(tx_context, &tx_buffer->tx_head, byPktType, |
789 | cbFrameSize, bNeedACK, wCurrentRate, need_rts); | |
c12dca09 | 790 | |
c2c32da3 | 791 | return vnt_rxtx_datahead_ab(tx_context, byPktType, |
92928f13 MP |
792 | wCurrentRate, &head->data_head_ab, |
793 | cbFrameSize, bNeedACK); | |
794 | } | |
795 | } | |
0a0f4b69 | 796 | |
30a05b39 | 797 | return 0; |
92b96797 | 798 | } |
d38b13aa MP |
799 | |
800 | static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context, | |
801 | u8 *key_buffer, struct ieee80211_key_conf *tx_key, struct sk_buff *skb, | |
802 | u16 payload_len, struct vnt_mic_hdr *mic_hdr) | |
803 | { | |
804 | struct ieee80211_hdr *hdr = tx_context->hdr; | |
805 | struct ieee80211_key_seq seq; | |
806 | u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb)); | |
807 | ||
808 | /* strip header and icv len from payload */ | |
809 | payload_len -= ieee80211_get_hdrlen_from_skb(skb); | |
810 | payload_len -= tx_key->icv_len; | |
811 | ||
812 | switch (tx_key->cipher) { | |
813 | case WLAN_CIPHER_SUITE_WEP40: | |
814 | case WLAN_CIPHER_SUITE_WEP104: | |
815 | memcpy(key_buffer, iv, 3); | |
816 | memcpy(key_buffer + 3, tx_key->key, tx_key->keylen); | |
817 | ||
818 | if (tx_key->keylen == WLAN_KEY_LEN_WEP40) { | |
819 | memcpy(key_buffer + 8, iv, 3); | |
820 | memcpy(key_buffer + 11, | |
821 | tx_key->key, WLAN_KEY_LEN_WEP40); | |
822 | } | |
823 | ||
824 | break; | |
825 | case WLAN_CIPHER_SUITE_TKIP: | |
826 | ieee80211_get_tkip_p2k(tx_key, skb, key_buffer); | |
827 | ||
828 | break; | |
829 | case WLAN_CIPHER_SUITE_CCMP: | |
830 | ||
831 | if (!mic_hdr) | |
832 | return; | |
833 | ||
834 | mic_hdr->id = 0x59; | |
835 | mic_hdr->payload_len = cpu_to_be16(payload_len); | |
836 | memcpy(mic_hdr->mic_addr2, hdr->addr2, ETH_ALEN); | |
837 | ||
838 | ieee80211_get_key_tx_seq(tx_key, &seq); | |
839 | ||
79f976dc | 840 | memcpy(mic_hdr->ccmp_pn, seq.ccmp.pn, IEEE80211_CCMP_PN_LEN); |
d38b13aa MP |
841 | |
842 | if (ieee80211_has_a4(hdr->frame_control)) | |
843 | mic_hdr->hlen = cpu_to_be16(28); | |
844 | else | |
845 | mic_hdr->hlen = cpu_to_be16(22); | |
846 | ||
847 | memcpy(mic_hdr->addr1, hdr->addr1, ETH_ALEN); | |
848 | memcpy(mic_hdr->addr2, hdr->addr2, ETH_ALEN); | |
849 | memcpy(mic_hdr->addr3, hdr->addr3, ETH_ALEN); | |
850 | ||
851 | mic_hdr->frame_control = cpu_to_le16( | |
852 | le16_to_cpu(hdr->frame_control) & 0xc78f); | |
853 | mic_hdr->seq_ctrl = cpu_to_le16( | |
854 | le16_to_cpu(hdr->seq_ctrl) & 0xf); | |
855 | ||
856 | if (ieee80211_has_a4(hdr->frame_control)) | |
857 | memcpy(mic_hdr->addr4, hdr->addr4, ETH_ALEN); | |
858 | ||
859 | ||
860 | memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP); | |
861 | ||
862 | break; | |
863 | default: | |
864 | break; | |
865 | } | |
866 | ||
867 | } | |
868 | ||
869 | int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) | |
870 | { | |
871 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | |
872 | struct ieee80211_tx_rate *tx_rate = &info->control.rates[0]; | |
873 | struct ieee80211_rate *rate; | |
874 | struct ieee80211_key_conf *tx_key; | |
875 | struct ieee80211_hdr *hdr; | |
876 | struct vnt_mic_hdr *mic_hdr = NULL; | |
877 | struct vnt_tx_buffer *tx_buffer; | |
878 | struct vnt_tx_fifo_head *tx_buffer_head; | |
879 | struct vnt_usb_send_context *tx_context; | |
880 | unsigned long flags; | |
881 | u32 frame_size = 0; | |
882 | u16 tx_bytes, tx_header_size, tx_body_size, current_rate, duration_id; | |
883 | u8 pkt_type, fb_option = AUTO_FB_NONE; | |
884 | bool need_rts = false, need_ack = false, is_pspoll = false; | |
885 | bool need_mic = false; | |
886 | ||
887 | hdr = (struct ieee80211_hdr *)(skb->data); | |
888 | ||
889 | rate = ieee80211_get_tx_rate(priv->hw, info); | |
890 | ||
891 | current_rate = rate->hw_value; | |
5091d963 MP |
892 | if (priv->wCurrentRate != current_rate && |
893 | !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { | |
d38b13aa MP |
894 | priv->wCurrentRate = current_rate; |
895 | bScheduleCommand(priv, WLAN_CMD_SETPOWER, NULL); | |
896 | } | |
897 | ||
898 | if (current_rate > RATE_11M) | |
899 | pkt_type = priv->byPacketType; | |
900 | else | |
901 | pkt_type = PK_TYPE_11B; | |
902 | ||
903 | spin_lock_irqsave(&priv->lock, flags); | |
904 | ||
905 | tx_context = s_vGetFreeContext(priv); | |
906 | if (!tx_context) { | |
907 | dev_dbg(&priv->usb->dev, "%s No free context\n", __func__); | |
908 | spin_unlock_irqrestore(&priv->lock, flags); | |
909 | return -ENOMEM; | |
910 | } | |
911 | ||
912 | tx_context->skb = skb; | |
913 | ||
914 | spin_unlock_irqrestore(&priv->lock, flags); | |
915 | ||
916 | tx_buffer = (struct vnt_tx_buffer *)tx_context->data; | |
917 | tx_buffer_head = &tx_buffer->fifo_head; | |
918 | tx_body_size = skb->len; | |
919 | ||
920 | frame_size = tx_body_size + 4; | |
921 | ||
d38b13aa MP |
922 | /*Set fifo controls */ |
923 | if (pkt_type == PK_TYPE_11A) | |
924 | tx_buffer_head->wFIFOCtl = 0; | |
925 | else if (pkt_type == PK_TYPE_11B) | |
926 | tx_buffer_head->wFIFOCtl = FIFOCTL_11B; | |
927 | else if (pkt_type == PK_TYPE_11GB) | |
928 | tx_buffer_head->wFIFOCtl = FIFOCTL_11GB; | |
929 | else if (pkt_type == PK_TYPE_11GA) | |
930 | tx_buffer_head->wFIFOCtl = FIFOCTL_11GA; | |
931 | ||
932 | if (!ieee80211_is_data(hdr->frame_control)) { | |
933 | tx_buffer_head->wFIFOCtl |= (FIFOCTL_GENINT | | |
934 | FIFOCTL_ISDMA0); | |
935 | tx_buffer_head->wFIFOCtl |= FIFOCTL_TMOEN; | |
936 | ||
937 | tx_buffer_head->time_stamp = | |
938 | cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); | |
939 | } else { | |
940 | tx_buffer_head->time_stamp = | |
941 | cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); | |
942 | } | |
943 | ||
944 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | |
945 | tx_buffer_head->wFIFOCtl |= FIFOCTL_NEEDACK; | |
946 | need_ack = true; | |
947 | } | |
948 | ||
949 | if (ieee80211_has_retry(hdr->frame_control)) | |
950 | tx_buffer_head->wFIFOCtl |= FIFOCTL_LRETRY; | |
951 | ||
952 | if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | |
953 | priv->byPreambleType = PREAMBLE_SHORT; | |
954 | else | |
955 | priv->byPreambleType = PREAMBLE_LONG; | |
956 | ||
957 | if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) { | |
958 | need_rts = true; | |
959 | tx_buffer_head->wFIFOCtl |= FIFOCTL_RTS; | |
960 | } | |
961 | ||
962 | if (ieee80211_has_a4(hdr->frame_control)) | |
963 | tx_buffer_head->wFIFOCtl |= FIFOCTL_LHEAD; | |
964 | ||
965 | if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) | |
966 | is_pspoll = true; | |
967 | ||
5deb1cfa MP |
968 | tx_buffer_head->frag_ctl = |
969 | cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10); | |
d38b13aa MP |
970 | |
971 | if (info->control.hw_key) { | |
972 | tx_key = info->control.hw_key; | |
973 | switch (info->control.hw_key->cipher) { | |
974 | case WLAN_CIPHER_SUITE_WEP40: | |
975 | case WLAN_CIPHER_SUITE_WEP104: | |
5deb1cfa | 976 | tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY); |
d38b13aa MP |
977 | break; |
978 | case WLAN_CIPHER_SUITE_TKIP: | |
5deb1cfa | 979 | tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP); |
d38b13aa MP |
980 | break; |
981 | case WLAN_CIPHER_SUITE_CCMP: | |
5deb1cfa | 982 | tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES); |
d38b13aa MP |
983 | need_mic = true; |
984 | default: | |
985 | break; | |
986 | } | |
987 | frame_size += tx_key->icv_len; | |
988 | } | |
989 | ||
cb8ee9de MP |
990 | tx_buffer_head->current_rate = cpu_to_le16(current_rate); |
991 | ||
d38b13aa MP |
992 | /* legacy rates TODO use ieee80211_tx_rate */ |
993 | if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) { | |
994 | if (priv->byAutoFBCtrl == AUTO_FB_0) { | |
995 | tx_buffer_head->wFIFOCtl |= FIFOCTL_AUTO_FB_0; | |
996 | ||
997 | priv->tx_rate_fb0 = | |
998 | wFB_Opt0[FB_RATE0][current_rate - RATE_18M]; | |
999 | priv->tx_rate_fb1 = | |
1000 | wFB_Opt0[FB_RATE1][current_rate - RATE_18M]; | |
1001 | ||
1002 | fb_option = AUTO_FB_0; | |
1003 | } else if (priv->byAutoFBCtrl == AUTO_FB_1) { | |
1004 | tx_buffer_head->wFIFOCtl |= FIFOCTL_AUTO_FB_1; | |
1005 | ||
1006 | priv->tx_rate_fb0 = | |
1007 | wFB_Opt1[FB_RATE0][current_rate - RATE_18M]; | |
1008 | priv->tx_rate_fb1 = | |
1009 | wFB_Opt1[FB_RATE1][current_rate - RATE_18M]; | |
1010 | ||
1011 | fb_option = AUTO_FB_1; | |
1012 | } | |
1013 | } | |
1014 | ||
71d764ae MP |
1015 | tx_context->fb_option = fb_option; |
1016 | ||
d38b13aa MP |
1017 | duration_id = s_vGenerateTxParameter(tx_context, pkt_type, current_rate, |
1018 | tx_buffer, &mic_hdr, need_mic, frame_size, | |
72bf8059 | 1019 | need_ack, need_rts); |
d38b13aa MP |
1020 | |
1021 | tx_header_size = tx_context->tx_hdr_size; | |
1022 | if (!tx_header_size) { | |
1023 | tx_context->in_use = false; | |
1024 | return -ENOMEM; | |
1025 | } | |
1026 | ||
5deb1cfa | 1027 | tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); |
d38b13aa MP |
1028 | |
1029 | tx_bytes = tx_header_size + tx_body_size; | |
1030 | ||
1031 | memcpy(tx_context->hdr, skb->data, tx_body_size); | |
1032 | ||
1033 | hdr->duration_id = cpu_to_le16(duration_id); | |
1034 | ||
1035 | if (info->control.hw_key) { | |
1036 | tx_key = info->control.hw_key; | |
1037 | if (tx_key->keylen > 0) | |
1038 | vnt_fill_txkey(tx_context, tx_buffer_head->tx_key, | |
1039 | tx_key, skb, tx_body_size, mic_hdr); | |
1040 | } | |
1041 | ||
1042 | priv->wSeqCounter = (le16_to_cpu(hdr->seq_ctrl) & | |
1043 | IEEE80211_SCTL_SEQ) >> 4; | |
1044 | ||
1045 | tx_buffer->tx_byte_count = cpu_to_le16(tx_bytes); | |
71d764ae | 1046 | tx_buffer->byPKTNO = tx_context->pkt_no; |
d38b13aa MP |
1047 | tx_buffer->byType = 0x00; |
1048 | ||
1049 | tx_bytes += 4; | |
1050 | ||
1051 | tx_context->type = CONTEXT_DATA_PACKET; | |
1052 | tx_context->buf_len = tx_bytes; | |
1053 | ||
1054 | spin_lock_irqsave(&priv->lock, flags); | |
1055 | ||
1056 | if (PIPEnsSendBulkOut(priv, tx_context) != STATUS_PENDING) { | |
1057 | spin_unlock_irqrestore(&priv->lock, flags); | |
1058 | return -EIO; | |
1059 | } | |
1060 | ||
1061 | spin_unlock_irqrestore(&priv->lock, flags); | |
1062 | ||
1063 | return 0; | |
1064 | } | |
1065 | ||
1066 | static int vnt_beacon_xmit(struct vnt_private *priv, | |
1067 | struct sk_buff *skb) | |
1068 | { | |
1069 | struct vnt_beacon_buffer *beacon_buffer; | |
1070 | struct vnt_tx_short_buf_head *short_head; | |
1071 | struct ieee80211_tx_info *info; | |
1072 | struct vnt_usb_send_context *context; | |
1073 | struct ieee80211_mgmt *mgmt_hdr; | |
1074 | unsigned long flags; | |
1075 | u32 frame_size = skb->len + 4; | |
1076 | u16 current_rate, count; | |
1077 | ||
1078 | spin_lock_irqsave(&priv->lock, flags); | |
1079 | ||
1080 | context = s_vGetFreeContext(priv); | |
1081 | if (!context) { | |
1082 | dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__); | |
1083 | spin_unlock_irqrestore(&priv->lock, flags); | |
1084 | return -ENOMEM; | |
1085 | } | |
1086 | ||
1087 | context->skb = skb; | |
1088 | ||
1089 | spin_unlock_irqrestore(&priv->lock, flags); | |
1090 | ||
1091 | beacon_buffer = (struct vnt_beacon_buffer *)&context->data[0]; | |
1092 | short_head = &beacon_buffer->short_head; | |
1093 | ||
1094 | if (priv->byBBType == BB_TYPE_11A) { | |
1095 | current_rate = RATE_6M; | |
1096 | ||
1097 | /* Get SignalField,ServiceField,Length */ | |
1098 | vnt_get_phy_field(priv, frame_size, current_rate, | |
1099 | PK_TYPE_11A, &short_head->ab); | |
1100 | ||
1101 | /* Get Duration and TimeStampOff */ | |
1102 | short_head->duration = s_uGetDataDuration(priv, | |
1103 | PK_TYPE_11A, false); | |
1104 | short_head->time_stamp_off = | |
1105 | vnt_time_stamp_off(priv, current_rate); | |
1106 | } else { | |
1107 | current_rate = RATE_1M; | |
1108 | short_head->fifo_ctl |= FIFOCTL_11B; | |
1109 | ||
1110 | /* Get SignalField,ServiceField,Length */ | |
1111 | vnt_get_phy_field(priv, frame_size, current_rate, | |
1112 | PK_TYPE_11B, &short_head->ab); | |
1113 | ||
1114 | /* Get Duration and TimeStampOff */ | |
1115 | short_head->duration = s_uGetDataDuration(priv, | |
1116 | PK_TYPE_11B, false); | |
1117 | short_head->time_stamp_off = | |
1118 | vnt_time_stamp_off(priv, current_rate); | |
1119 | } | |
1120 | ||
1121 | /* Generate Beacon Header */ | |
1122 | mgmt_hdr = &beacon_buffer->mgmt_hdr; | |
1123 | memcpy(mgmt_hdr, skb->data, skb->len); | |
1124 | ||
1125 | /* time stamp always 0 */ | |
1126 | mgmt_hdr->u.beacon.timestamp = 0; | |
1127 | ||
1128 | info = IEEE80211_SKB_CB(skb); | |
1129 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | |
1130 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr; | |
1131 | hdr->duration_id = 0; | |
1132 | hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4); | |
1133 | } | |
1134 | ||
1135 | priv->wSeqCounter++; | |
1136 | if (priv->wSeqCounter > 0x0fff) | |
1137 | priv->wSeqCounter = 0; | |
1138 | ||
1139 | count = sizeof(struct vnt_tx_short_buf_head) + skb->len; | |
1140 | ||
1141 | beacon_buffer->tx_byte_count = cpu_to_le16(count); | |
71d764ae | 1142 | beacon_buffer->byPKTNO = context->pkt_no; |
d38b13aa MP |
1143 | beacon_buffer->byType = 0x01; |
1144 | ||
1145 | context->type = CONTEXT_BEACON_PACKET; | |
1146 | context->buf_len = count + 4; /* USB header */ | |
1147 | ||
1148 | spin_lock_irqsave(&priv->lock, flags); | |
1149 | ||
1150 | if (PIPEnsSendBulkOut(priv, context) != STATUS_PENDING) | |
1151 | ieee80211_free_txskb(priv->hw, context->skb); | |
1152 | ||
1153 | spin_unlock_irqrestore(&priv->lock, flags); | |
1154 | ||
1155 | return 0; | |
1156 | } | |
1157 | ||
1158 | int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif) | |
1159 | { | |
1160 | struct sk_buff *beacon; | |
1161 | ||
1162 | beacon = ieee80211_beacon_get(priv->hw, vif); | |
1163 | if (!beacon) | |
1164 | return -ENOMEM; | |
1165 | ||
1166 | if (vnt_beacon_xmit(priv, beacon)) { | |
1167 | ieee80211_free_txskb(priv->hw, beacon); | |
1168 | return -ENODEV; | |
1169 | } | |
1170 | ||
1171 | return 0; | |
1172 | } | |
1173 | ||
1174 | int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, | |
1175 | struct ieee80211_bss_conf *conf) | |
1176 | { | |
1177 | int ret; | |
1178 | ||
1179 | vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1180 | ||
1181 | vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1182 | ||
1183 | vnt_mac_set_beacon_interval(priv, conf->beacon_int); | |
1184 | ||
1185 | vnt_clear_current_tsf(priv); | |
1186 | ||
1187 | vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1188 | ||
1189 | vnt_reset_next_tbtt(priv, conf->beacon_int); | |
1190 | ||
1191 | ret = vnt_beacon_make(priv, vif); | |
1192 | ||
1193 | return ret; | |
1194 | } |