blob: 00e9756da9c1542cd600abeff13a87355fc46c86 [file] [log] [blame]
Pekka Enberg80aba532008-10-30 13:04:29 +02001#include "mds_f.h"
Pekka Enberg64328c82009-01-07 17:33:45 +02002#include "mto.h"
Pekka Enbergb5ef0762010-11-01 21:50:06 +02003#include "wbhal.h"
Pekka Enberg80aba532008-10-30 13:04:29 +02004#include "wblinux_f.h"
Pekka Enberg72ca8812010-11-01 21:50:05 +02005#include "wb35tx_f.h"
Pavel Machek66101de2008-10-01 14:36:56 +02006
Pavel Machek66101de2008-10-01 14:36:56 +02007unsigned char
Adam Latham973267a2010-05-15 09:38:44 +01008Mds_initial(struct wbsoft_priv *adapter)
Pavel Machek66101de2008-10-01 14:36:56 +02009{
Pekka Enbergb7caf942009-08-12 11:03:33 +030010 struct wb35_mds *pMds = &adapter->Mds;
Pavel Machek66101de2008-10-01 14:36:56 +020011
Pekka Enberg279b6cc2008-10-27 22:46:39 +020012 pMds->TxPause = false;
Pavel Machek66101de2008-10-01 14:36:56 +020013 pMds->TxRTSThreshold = DEFAULT_RTSThreshold;
14 pMds->TxFragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD;
15
Victor Rosalesa1b09252010-09-19 17:53:00 -030016 return hal_get_tx_buffer(&adapter->sHwData, &pMds->pTxBuffer);
Pavel Machek66101de2008-10-01 14:36:56 +020017}
18
Pekka Enberg27d46422009-08-12 11:03:36 +030019static void Mds_DurationSet(struct wbsoft_priv *adapter, struct wb35_descriptor *pDes, u8 *buffer)
Pekka Enberg6261ab32008-10-30 19:04:50 +020020{
Pekka Enbergc4d562a2010-09-19 12:28:38 +030021 struct T00_descriptor *pT00;
22 struct T01_descriptor *pT01;
Pekka Enberg6261ab32008-10-30 19:04:50 +020023 u16 Duration, NextBodyLen, OffsetSize;
24 u8 Rate, i;
25 unsigned char CTS_on = false, RTS_on = false;
Pekka Enbergc4d562a2010-09-19 12:28:38 +030026 struct T00_descriptor *pNextT00;
Pekka Enberg6261ab32008-10-30 19:04:50 +020027 u16 BodyLen = 0;
28 unsigned char boGroupAddr = false;
29
30 OffsetSize = pDes->FragmentThreshold + 32 + 3;
31 OffsetSize &= ~0x03;
32 Rate = pDes->TxRate >> 1;
33 if (!Rate)
34 Rate = 1;
35
Pekka Enbergc4d562a2010-09-19 12:28:38 +030036 pT00 = (struct T00_descriptor *)buffer;
37 pT01 = (struct T01_descriptor *)(buffer+4);
38 pNextT00 = (struct T00_descriptor *)(buffer+OffsetSize);
Pekka Enberg6261ab32008-10-30 19:04:50 +020039
Victor Rosalesa1b09252010-09-19 17:53:00 -030040 if (buffer[DOT_11_DA_OFFSET+8] & 0x1) /* +8 for USB hdr */
Pekka Enberg6261ab32008-10-30 19:04:50 +020041 boGroupAddr = true;
42
Mike Sheldonb1facee2010-03-10 13:32:01 +000043 /******************************************
44 * Set RTS/CTS mechanism
45 ******************************************/
Victor Rosalesa1b09252010-09-19 17:53:00 -030046 if (!boGroupAddr) {
Mike Sheldonb1facee2010-03-10 13:32:01 +000047 /* NOTE : If the protection mode is enabled and the MSDU will be fragmented,
48 * the tx rates of MPDUs will all be DSSS rates. So it will not use
49 * CTS-to-self in this case. CTS-To-self will only be used when without
50 * fragmentation. -- 20050112 */
51 BodyLen = (u16)pT00->T00_frame_length; /* include 802.11 header */
52 BodyLen += 4; /* CRC */
Pekka Enberg6261ab32008-10-30 19:04:50 +020053
Victor Rosalesa1b09252010-09-19 17:53:00 -030054 if (BodyLen >= CURRENT_RTS_THRESHOLD)
Mike Sheldonb1facee2010-03-10 13:32:01 +000055 RTS_on = true; /* Using RTS */
Victor Rosalesa1b09252010-09-19 17:53:00 -030056 else {
57 if (pT01->T01_modulation_type) { /* Is using OFDM */
58 if (CURRENT_PROTECT_MECHANISM) /* Is using protect */
Mike Sheldonb1facee2010-03-10 13:32:01 +000059 CTS_on = true; /* Using CTS */
Pekka Enberg6261ab32008-10-30 19:04:50 +020060 }
61 }
62 }
63
Victor Rosalesa1b09252010-09-19 17:53:00 -030064 if (RTS_on || CTS_on) {
65 if (pT01->T01_modulation_type) { /* Is using OFDM */
66 /* CTS duration
Mike Sheldonb1facee2010-03-10 13:32:01 +000067 * 2 SIFS + DATA transmit time + 1 ACK
68 * ACK Rate : 24 Mega bps
69 * ACK frame length = 14 bytes */
Pekka Enberg6261ab32008-10-30 19:04:50 +020070 Duration = 2*DEFAULT_SIFSTIME +
71 2*PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
72 ((BodyLen*8 + 22 + Rate*4 - 1)/(Rate*4))*Tsym +
73 ((112 + 22 + 95)/96)*Tsym;
Victor Rosalesa1b09252010-09-19 17:53:00 -030074 } else { /* DSSS */
Mike Sheldonb1facee2010-03-10 13:32:01 +000075 /* CTS duration
76 * 2 SIFS + DATA transmit time + 1 ACK
77 * Rate : ?? Mega bps
78 * ACK frame length = 14 bytes */
Victor Rosalesa1b09252010-09-19 17:53:00 -030079 if (pT01->T01_plcp_header_length) /* long preamble */
Pekka Enberg6261ab32008-10-30 19:04:50 +020080 Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
81 else
82 Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*2;
83
Victor Rosalesa1b09252010-09-19 17:53:00 -030084 Duration += (((BodyLen + 14)*8 + Rate-1) / Rate +
85 DEFAULT_SIFSTIME*2);
Pekka Enberg6261ab32008-10-30 19:04:50 +020086 }
87
Victor Rosalesa1b09252010-09-19 17:53:00 -030088 if (RTS_on) {
89 if (pT01->T01_modulation_type) { /* Is using OFDM */
Mike Sheldonb1facee2010-03-10 13:32:01 +000090 /* CTS + 1 SIFS + CTS duration
91 * CTS Rate : 24 Mega bps
92 * CTS frame length = 14 bytes */
Pekka Enberg6261ab32008-10-30 19:04:50 +020093 Duration += (DEFAULT_SIFSTIME +
94 PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION +
95 ((112 + 22 + 95)/96)*Tsym);
Victor Rosalesa1b09252010-09-19 17:53:00 -030096 } else {
Mike Sheldonb1facee2010-03-10 13:32:01 +000097 /* CTS + 1 SIFS + CTS duration
98 * CTS Rate : ?? Mega bps
99 * CTS frame length = 14 bytes */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300100 if (pT01->T01_plcp_header_length) /* long preamble */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200101 Duration += LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
102 else
103 Duration += SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
104
Victor Rosalesa1b09252010-09-19 17:53:00 -0300105 Duration += (((112 + Rate-1) / Rate) + DEFAULT_SIFSTIME);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200106 }
107 }
108
Mike Sheldonb1facee2010-03-10 13:32:01 +0000109 /* Set the value into USB descriptor */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200110 pT01->T01_add_rts = RTS_on ? 1 : 0;
111 pT01->T01_add_cts = CTS_on ? 1 : 0;
112 pT01->T01_rts_cts_duration = Duration;
113 }
114
Mike Sheldonb1facee2010-03-10 13:32:01 +0000115 /******************************************
116 * Fill the more fragment descriptor
117 ******************************************/
Victor Rosalesa1b09252010-09-19 17:53:00 -0300118 if (boGroupAddr)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200119 Duration = 0;
Victor Rosalesa1b09252010-09-19 17:53:00 -0300120 else {
121 for (i = pDes->FragmentCount-1; i > 0; i--) {
Pekka Enberg6261ab32008-10-30 19:04:50 +0200122 NextBodyLen = (u16)pNextT00->T00_frame_length;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000123 NextBodyLen += 4; /* CRC */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200124
Victor Rosalesa1b09252010-09-19 17:53:00 -0300125 if (pT01->T01_modulation_type) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000126 /* OFDM
127 * data transmit time + 3 SIFS + 2 ACK
128 * Rate : ??Mega bps
129 * ACK frame length = 14 bytes, tx rate = 24M */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200130 Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION * 3;
131 Duration += (((NextBodyLen*8 + 22 + Rate*4 - 1)/(Rate*4)) * Tsym +
132 (((2*14)*8 + 22 + 95)/96)*Tsym +
133 DEFAULT_SIFSTIME*3);
Victor Rosalesa1b09252010-09-19 17:53:00 -0300134 } else {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000135 /* DSSS
136 * data transmit time + 2 ACK + 3 SIFS
137 * Rate : ??Mega bps
138 * ACK frame length = 14 bytes
139 * TODO : */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300140 if (pT01->T01_plcp_header_length) /* long preamble */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200141 Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
142 else
143 Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME*3;
144
Victor Rosalesa1b09252010-09-19 17:53:00 -0300145 Duration += (((NextBodyLen + (2*14))*8 + Rate-1) / Rate +
146 DEFAULT_SIFSTIME*3);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200147 }
148
Mike Sheldonb1facee2010-03-10 13:32:01 +0000149 ((u16 *)buffer)[5] = cpu_to_le16(Duration); /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200150
Mike Sheldonb1facee2010-03-10 13:32:01 +0000151 /* ----20061009 add by anson's endian */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200152 pNextT00->value = cpu_to_le32(pNextT00->value);
Victor Rosalesa1b09252010-09-19 17:53:00 -0300153 pT01->value = cpu_to_le32(pT01->value);
Mike Sheldonb1facee2010-03-10 13:32:01 +0000154 /* ----end 20061009 add by anson's endian */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200155
156 buffer += OffsetSize;
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300157 pT01 = (struct T01_descriptor *)(buffer+4);
Mike Sheldonb1facee2010-03-10 13:32:01 +0000158 if (i != 1) /* The last fragment will not have the next fragment */
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300159 pNextT00 = (struct T00_descriptor *)(buffer+OffsetSize);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200160 }
161
Mike Sheldonb1facee2010-03-10 13:32:01 +0000162 /*******************************************
163 * Fill the last fragment descriptor
164 *******************************************/
Victor Rosalesa1b09252010-09-19 17:53:00 -0300165 if (pT01->T01_modulation_type) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000166 /* OFDM
167 * 1 SIFS + 1 ACK
168 * Rate : 24 Mega bps
169 * ACK frame length = 14 bytes */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200170 Duration = PREAMBLE_PLUS_SIGNAL_PLUS_SIGNALEXTENSION;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000171 /* The Tx rate of ACK use 24M */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300172 Duration += (((112 + 22 + 95)/96)*Tsym + DEFAULT_SIFSTIME);
173 } else {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000174 /* DSSS
175 * 1 ACK + 1 SIFS
176 * Rate : ?? Mega bps
177 * ACK frame length = 14 bytes(112 bits) */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300178 if (pT01->T01_plcp_header_length) /* long preamble */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200179 Duration = LONG_PREAMBLE_PLUS_PLCPHEADER_TIME;
180 else
181 Duration = SHORT_PREAMBLE_PLUS_PLCPHEADER_TIME;
182
Victor Rosalesa1b09252010-09-19 17:53:00 -0300183 Duration += ((112 + Rate-1)/Rate + DEFAULT_SIFSTIME);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200184 }
185 }
186
Mike Sheldonb1facee2010-03-10 13:32:01 +0000187 ((u16 *)buffer)[5] = cpu_to_le16(Duration); /* 4 USHOR for skip 8B USB, 2USHORT=FC + Duration */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200188 pT00->value = cpu_to_le32(pT00->value);
189 pT01->value = cpu_to_le32(pT01->value);
Mike Sheldonb1facee2010-03-10 13:32:01 +0000190 /* --end 20061009 add */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200191
192}
193
Mike Sheldonb1facee2010-03-10 13:32:01 +0000194/* The function return the 4n size of usb pk */
Pekka Enberg27d46422009-08-12 11:03:36 +0300195static u16 Mds_BodyCopy(struct wbsoft_priv *adapter, struct wb35_descriptor *pDes, u8 *TargetBuffer)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200196{
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300197 struct T00_descriptor *pT00;
Pekka Enbergb7caf942009-08-12 11:03:33 +0300198 struct wb35_mds *pMds = &adapter->Mds;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200199 u8 *buffer;
200 u8 *src_buffer;
201 u8 *pctmp;
202 u16 Size = 0;
203 u16 SizeLeft, CopySize, CopyLeft, stmp;
204 u8 buf_index, FragmentCount = 0;
205
206
Mike Sheldonb1facee2010-03-10 13:32:01 +0000207 /* Copy fragment body */
208 buffer = TargetBuffer; /* shift 8B usb + 24B 802.11 */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200209 SizeLeft = pDes->buffer_total_size;
210 buf_index = pDes->buffer_start_index;
211
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300212 pT00 = (struct T00_descriptor *)buffer;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200213 while (SizeLeft) {
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300214 pT00 = (struct T00_descriptor *)buffer;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200215 CopySize = SizeLeft;
216 if (SizeLeft > pDes->FragmentThreshold) {
217 CopySize = pDes->FragmentThreshold;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000218 pT00->T00_frame_length = 24 + CopySize; /* Set USB length */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200219 } else
Mike Sheldonb1facee2010-03-10 13:32:01 +0000220 pT00->T00_frame_length = 24 + SizeLeft; /* Set USB length */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200221
222 SizeLeft -= CopySize;
223
Mike Sheldonb1facee2010-03-10 13:32:01 +0000224 /* 1 Byte operation */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300225 pctmp = (u8 *)(buffer + 8 + DOT_11_SEQUENCE_OFFSET);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200226 *pctmp &= 0xf0;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000227 *pctmp |= FragmentCount; /* 931130.5.m */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300228 if (!FragmentCount)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200229 pT00->T00_first_mpdu = 1;
230
Mike Sheldonb1facee2010-03-10 13:32:01 +0000231 buffer += 32; /* 8B usb + 24B 802.11 header */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200232 Size += 32;
233
Mike Sheldonb1facee2010-03-10 13:32:01 +0000234 /* Copy into buffer */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200235 stmp = CopySize + 3;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000236 stmp &= ~0x03; /* 4n Alignment */
237 Size += stmp; /* Current 4n offset of mpdu */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200238
239 while (CopySize) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000240 /* Copy body */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200241 src_buffer = pDes->buffer_address[buf_index];
242 CopyLeft = CopySize;
243 if (CopySize >= pDes->buffer_size[buf_index]) {
244 CopyLeft = pDes->buffer_size[buf_index];
245
Mike Sheldonb1facee2010-03-10 13:32:01 +0000246 /* Get the next buffer of descriptor */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200247 buf_index++;
248 buf_index %= MAX_DESCRIPTOR_BUFFER_INDEX;
249 } else {
250 u8 *pctmp = pDes->buffer_address[buf_index];
251 pctmp += CopySize;
252 pDes->buffer_address[buf_index] = pctmp;
253 pDes->buffer_size[buf_index] -= CopySize;
254 }
255
256 memcpy(buffer, src_buffer, CopyLeft);
257 buffer += CopyLeft;
258 CopySize -= CopyLeft;
259 }
260
Mike Sheldonb1facee2010-03-10 13:32:01 +0000261 /* 931130.5.n */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200262 if (pMds->MicAdd) {
263 if (!SizeLeft) {
Victor Rosalesa1b09252010-09-19 17:53:00 -0300264 pMds->MicWriteAddress[pMds->MicWriteIndex] = buffer - pMds->MicAdd;
265 pMds->MicWriteSize[pMds->MicWriteIndex] = pMds->MicAdd;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200266 pMds->MicAdd = 0;
Victor Rosalesa1b09252010-09-19 17:53:00 -0300267 } else if (SizeLeft < 8) { /* 931130.5.p */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200268 pMds->MicAdd = SizeLeft;
Victor Rosalesa1b09252010-09-19 17:53:00 -0300269 pMds->MicWriteAddress[pMds->MicWriteIndex] = buffer - (8 - SizeLeft);
270 pMds->MicWriteSize[pMds->MicWriteIndex] = 8 - SizeLeft;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200271 pMds->MicWriteIndex++;
272 }
273 }
274
Mike Sheldonb1facee2010-03-10 13:32:01 +0000275 /* Does it need to generate the new header for next mpdu? */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200276 if (SizeLeft) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000277 buffer = TargetBuffer + Size; /* Get the next 4n start address */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300278 memcpy(buffer, TargetBuffer, 32); /* Copy 8B USB +24B 802.11 */
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300279 pT00 = (struct T00_descriptor *)buffer;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200280 pT00->T00_first_mpdu = 0;
281 }
282
283 FragmentCount++;
284 }
285
286 pT00->T00_last_mpdu = 1;
287 pT00->T00_IsLastMpdu = 1;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000288 buffer = (u8 *)pT00 + 8; /* +8 for USB hdr */
289 buffer[1] &= ~0x04; /* Clear more frag bit of 802.11 frame control */
290 pDes->FragmentCount = FragmentCount; /* Update the correct fragment number */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200291 return Size;
292}
293
Adam Latham973267a2010-05-15 09:38:44 +0100294static void Mds_HeaderCopy(struct wbsoft_priv *adapter, struct wb35_descriptor *pDes, u8 *TargetBuffer)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200295{
Pekka Enbergb7caf942009-08-12 11:03:33 +0300296 struct wb35_mds *pMds = &adapter->Mds;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000297 u8 *src_buffer = pDes->buffer_address[0]; /* 931130.5.g */
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300298 struct T00_descriptor *pT00;
299 struct T01_descriptor *pT01;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200300 u16 stmp;
301 u8 i, ctmp1, ctmp2, ctmpf;
302 u16 FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
303
304
305 stmp = pDes->buffer_total_size;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000306 /*
307 * Set USB header 8 byte
308 */
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300309 pT00 = (struct T00_descriptor *)TargetBuffer;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200310 TargetBuffer += 4;
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300311 pT01 = (struct T01_descriptor *)TargetBuffer;
Pekka Enberg6261ab32008-10-30 19:04:50 +0200312 TargetBuffer += 4;
313
Mike Sheldonb1facee2010-03-10 13:32:01 +0000314 pT00->value = 0; /* Clear */
315 pT01->value = 0; /* Clear */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200316
Mike Sheldonb1facee2010-03-10 13:32:01 +0000317 pT00->T00_tx_packet_id = pDes->Descriptor_ID; /* Set packet ID */
318 pT00->T00_header_length = 24; /* Set header length */
319 pT01->T01_retry_abort_ebable = 1; /* 921013 931130.5.h */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200320
Mike Sheldonb1facee2010-03-10 13:32:01 +0000321 /* Key ID setup */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200322 pT01->T01_wep_id = 0;
323
Mike Sheldonb1facee2010-03-10 13:32:01 +0000324 FragmentThreshold = DEFAULT_FRAGMENT_THRESHOLD; /* Do not fragment */
325 /* Copy full data, the 1'st buffer contain all the data 931130.5.j */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300326 memcpy(TargetBuffer, src_buffer, DOT_11_MAC_HEADER_SIZE); /* Copy header */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200327 pDes->buffer_address[0] = src_buffer + DOT_11_MAC_HEADER_SIZE;
328 pDes->buffer_total_size -= DOT_11_MAC_HEADER_SIZE;
329 pDes->buffer_size[0] = pDes->buffer_total_size;
330
Mike Sheldonb1facee2010-03-10 13:32:01 +0000331 /* Set fragment threshold */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200332 FragmentThreshold -= (DOT_11_MAC_HEADER_SIZE + 4);
333 pDes->FragmentThreshold = FragmentThreshold;
334
Mike Sheldonb1facee2010-03-10 13:32:01 +0000335 /* Set more frag bit */
336 TargetBuffer[1] |= 0x04; /* Set more frag bit */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200337
Mike Sheldonb1facee2010-03-10 13:32:01 +0000338 /*
339 * Set tx rate
340 */
341 stmp = *(u16 *)(TargetBuffer+30); /* 2n alignment address */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200342
Mike Sheldonb1facee2010-03-10 13:32:01 +0000343 /* Use basic rate */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200344 ctmp1 = ctmpf = CURRENT_TX_RATE_FOR_MNG;
345
346 pDes->TxRate = ctmp1;
Pekka Enberg2855bb72010-11-28 23:00:00 +0200347 pr_debug("Tx rate =%x\n", ctmp1);
Pekka Enberg6261ab32008-10-30 19:04:50 +0200348
349 pT01->T01_modulation_type = (ctmp1%3) ? 0 : 1;
350
Victor Rosalesa1b09252010-09-19 17:53:00 -0300351 for (i = 0; i < 2; i++) {
352 if (i == 1)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200353 ctmp1 = ctmpf;
354
Mike Sheldonb1facee2010-03-10 13:32:01 +0000355 pMds->TxRate[pDes->Descriptor_ID][i] = ctmp1; /* backup the ta rate and fall back rate */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200356
Victor Rosalesa1b09252010-09-19 17:53:00 -0300357 if (ctmp1 == 108)
358 ctmp2 = 7;
359 else if (ctmp1 == 96)
360 ctmp2 = 6; /* Rate convert for USB */
361 else if (ctmp1 == 72)
362 ctmp2 = 5;
363 else if (ctmp1 == 48)
364 ctmp2 = 4;
365 else if (ctmp1 == 36)
366 ctmp2 = 3;
367 else if (ctmp1 == 24)
368 ctmp2 = 2;
369 else if (ctmp1 == 18)
370 ctmp2 = 1;
371 else if (ctmp1 == 12)
372 ctmp2 = 0;
373 else if (ctmp1 == 22)
374 ctmp2 = 3;
375 else if (ctmp1 == 11)
376 ctmp2 = 2;
377 else if (ctmp1 == 4)
378 ctmp2 = 1;
379 else
380 ctmp2 = 0; /* if( ctmp1 == 2 ) or default */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200381
Victor Rosalesa1b09252010-09-19 17:53:00 -0300382 if (i == 0)
Pekka Enberg6261ab32008-10-30 19:04:50 +0200383 pT01->T01_transmit_rate = ctmp2;
384 else
385 pT01->T01_fall_back_rate = ctmp2;
386 }
387
Mike Sheldonb1facee2010-03-10 13:32:01 +0000388 /*
389 * Set preamble type
390 */
391 if ((pT01->T01_modulation_type == 0) && (pT01->T01_transmit_rate == 0)) /* RATE_1M */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200392 pDes->PreambleMode = WLAN_PREAMBLE_TYPE_LONG;
393 else
394 pDes->PreambleMode = CURRENT_PREAMBLE_MODE;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000395 pT01->T01_plcp_header_length = pDes->PreambleMode; /* Set preamble */
Pekka Enberg6261ab32008-10-30 19:04:50 +0200396
397}
398
Pekka Enberg01b5cee2010-11-28 23:00:05 +0200399static void MLME_GetNextPacket(struct wbsoft_priv *adapter, struct wb35_descriptor *desc)
400{
401 desc->InternalUsed = desc->buffer_start_index + desc->buffer_number;
402 desc->InternalUsed %= MAX_DESCRIPTOR_BUFFER_INDEX;
403 desc->buffer_address[desc->InternalUsed] = adapter->sMlmeFrame.pMMPDU;
404 desc->buffer_size[desc->InternalUsed] = adapter->sMlmeFrame.len;
405 desc->buffer_total_size += adapter->sMlmeFrame.len;
406 desc->buffer_number++;
407 desc->Type = adapter->sMlmeFrame.DataType;
408}
409
410static void MLMEfreeMMPDUBuffer(struct wbsoft_priv *adapter, s8 *pData)
411{
412 int i;
413
414 /* Reclaim the data buffer */
415 for (i = 0; i < MAX_NUM_TX_MMPDU; i++) {
416 if (pData == (s8 *)&(adapter->sMlmeFrame.TxMMPDU[i]))
417 break;
418 }
419 if (adapter->sMlmeFrame.TxMMPDUInUse[i])
420 adapter->sMlmeFrame.TxMMPDUInUse[i] = false;
421 else {
422 /* Something wrong
423 PD43 Add debug code here??? */
424 }
425}
426
427static void MLME_SendComplete(struct wbsoft_priv *adapter, u8 PacketID, unsigned char SendOK)
428{
429 /* Reclaim the data buffer */
430 adapter->sMlmeFrame.len = 0;
431 MLMEfreeMMPDUBuffer(adapter, adapter->sMlmeFrame.pMMPDU);
432
433 /* Return resource */
434 adapter->sMlmeFrame.IsInUsed = PACKET_FREE_TO_USE;
435}
436
Pavel Machek66101de2008-10-01 14:36:56 +0200437void
Adam Latham973267a2010-05-15 09:38:44 +0100438Mds_Tx(struct wbsoft_priv *adapter)
Pavel Machek66101de2008-10-01 14:36:56 +0200439{
Adam Latham973267a2010-05-15 09:38:44 +0100440 struct hw_data *pHwData = &adapter->sHwData;
Pekka Enbergb7caf942009-08-12 11:03:33 +0300441 struct wb35_mds *pMds = &adapter->Mds;
Pekka Enberg27d46422009-08-12 11:03:36 +0300442 struct wb35_descriptor TxDes;
443 struct wb35_descriptor *pTxDes = &TxDes;
Pekka Enberg8b384e02008-10-21 00:03:41 +0300444 u8 *XmitBufAddress;
Pavel Machek66101de2008-10-01 14:36:56 +0200445 u16 XmitBufSize, PacketSize, stmp, CurrentSize, FragmentThreshold;
446 u8 FillIndex, TxDesIndex, FragmentCount, FillCount;
Pekka Enberg3b055742009-03-02 12:19:57 +0200447 unsigned char BufferFilled = false;
Pavel Machek66101de2008-10-01 14:36:56 +0200448
449
450 if (pMds->TxPause)
451 return;
452 if (!hal_driver_init_OK(pHwData))
453 return;
454
Mike Sheldonb1facee2010-03-10 13:32:01 +0000455 /* Only one thread can be run here */
Diego Liziero290d4c22009-04-14 04:33:54 +0200456 if (atomic_inc_return(&pMds->TxThreadCount) != 1)
Pavel Machek66101de2008-10-01 14:36:56 +0200457 goto cleanup;
458
Mike Sheldonb1facee2010-03-10 13:32:01 +0000459 /* Start to fill the data */
Pavel Machek66101de2008-10-01 14:36:56 +0200460 do {
461 FillIndex = pMds->TxFillIndex;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000462 if (pMds->TxOwner[FillIndex]) { /* Is owned by software 0:Yes 1:No */
Pekka Enberg2855bb72010-11-28 23:00:00 +0200463 pr_debug("[Mds_Tx] Tx Owner is H/W.\n");
Pavel Machek66101de2008-10-01 14:36:56 +0200464 break;
465 }
466
Mike Sheldonb1facee2010-03-10 13:32:01 +0000467 XmitBufAddress = pMds->pTxBuffer + (MAX_USB_TX_BUFFER * FillIndex); /* Get buffer */
Pavel Machek66101de2008-10-01 14:36:56 +0200468 XmitBufSize = 0;
469 FillCount = 0;
470 do {
Pekka Enberg88ebc4b2008-10-22 11:03:19 +0300471 PacketSize = adapter->sMlmeFrame.len;
Pavel Machek66101de2008-10-01 14:36:56 +0200472 if (!PacketSize)
473 break;
474
Mike Sheldonb1facee2010-03-10 13:32:01 +0000475 /* For Check the buffer resource */
Pavel Machek66101de2008-10-01 14:36:56 +0200476 FragmentThreshold = CURRENT_FRAGMENT_THRESHOLD;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000477 /* 931130.5.b */
Pavel Machek66101de2008-10-01 14:36:56 +0200478 FragmentCount = PacketSize/FragmentThreshold + 1;
Mike Sheldonb1facee2010-03-10 13:32:01 +0000479 stmp = PacketSize + FragmentCount*32 + 8; /* 931130.5.c 8:MIC */
Pavel Machek66101de2008-10-01 14:36:56 +0200480 if ((XmitBufSize + stmp) >= MAX_USB_TX_BUFFER) {
481 printk("[Mds_Tx] Excess max tx buffer.\n");
Mike Sheldonb1facee2010-03-10 13:32:01 +0000482 break; /* buffer is not enough */
Pavel Machek66101de2008-10-01 14:36:56 +0200483 }
484
485
Mike Sheldonb1facee2010-03-10 13:32:01 +0000486 /*
487 * Start transmitting
488 */
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200489 BufferFilled = true;
Pavel Machek66101de2008-10-01 14:36:56 +0200490
491 /* Leaves first u8 intact */
Pekka Enberg27d46422009-08-12 11:03:36 +0300492 memset((u8 *)pTxDes + 1, 0, sizeof(struct wb35_descriptor) - 1);
Pavel Machek66101de2008-10-01 14:36:56 +0200493
Mike Sheldonb1facee2010-03-10 13:32:01 +0000494 TxDesIndex = pMds->TxDesIndex; /* Get the current ID */
Pavel Machek66101de2008-10-01 14:36:56 +0200495 pTxDes->Descriptor_ID = TxDesIndex;
Victor Rosalesa1b09252010-09-19 17:53:00 -0300496 pMds->TxDesFrom[TxDesIndex] = 2; /* Storing the information of source comming from */
Pavel Machek66101de2008-10-01 14:36:56 +0200497 pMds->TxDesIndex++;
498 pMds->TxDesIndex %= MAX_USB_TX_DESCRIPTOR;
499
Victor Rosalesa1b09252010-09-19 17:53:00 -0300500 MLME_GetNextPacket(adapter, pTxDes);
Pavel Machek66101de2008-10-01 14:36:56 +0200501
Mike Sheldonb1facee2010-03-10 13:32:01 +0000502 /* Copy header. 8byte USB + 24byte 802.11Hdr. Set TxRate, Preamble type */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300503 Mds_HeaderCopy(adapter, pTxDes, XmitBufAddress);
Pavel Machek66101de2008-10-01 14:36:56 +0200504
Mike Sheldonb1facee2010-03-10 13:32:01 +0000505 /* For speed up Key setting */
Pavel Machek66101de2008-10-01 14:36:56 +0200506 if (pTxDes->EapFix) {
Pekka Enberg2855bb72010-11-28 23:00:00 +0200507 pr_debug("35: EPA 4th frame detected. Size = %d\n", PacketSize);
Pavel Machek66101de2008-10-01 14:36:56 +0200508 pHwData->IsKeyPreSet = 1;
509 }
510
Mike Sheldonb1facee2010-03-10 13:32:01 +0000511 /* Copy (fragment) frame body, and set USB, 802.11 hdr flag */
Pekka Enberg88ebc4b2008-10-22 11:03:19 +0300512 CurrentSize = Mds_BodyCopy(adapter, pTxDes, XmitBufAddress);
Pavel Machek66101de2008-10-01 14:36:56 +0200513
Mike Sheldonb1facee2010-03-10 13:32:01 +0000514 /* Set RTS/CTS and Normal duration field into buffer */
Pekka Enberg88ebc4b2008-10-22 11:03:19 +0300515 Mds_DurationSet(adapter, pTxDes, XmitBufAddress);
Pavel Machek66101de2008-10-01 14:36:56 +0200516
Mike Sheldonb1facee2010-03-10 13:32:01 +0000517 /* Shift to the next address */
Pavel Machek66101de2008-10-01 14:36:56 +0200518 XmitBufSize += CurrentSize;
519 XmitBufAddress += CurrentSize;
520
Mike Sheldonb1facee2010-03-10 13:32:01 +0000521 /* Get packet to transmit completed, 1:TESTSTA 2:MLME 3: Ndis data */
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200522 MLME_SendComplete(adapter, 0, true);
Pavel Machek66101de2008-10-01 14:36:56 +0200523
Mike Sheldonb1facee2010-03-10 13:32:01 +0000524 /* Software TSC count 20060214 */
Pavel Machek66101de2008-10-01 14:36:56 +0200525 pMds->TxTsc++;
526 if (pMds->TxTsc == 0)
527 pMds->TxTsc_2++;
528
Mike Sheldonb1facee2010-03-10 13:32:01 +0000529 FillCount++; /* 20060928 */
530 } while (HAL_USB_MODE_BURST(pHwData)); /* End of multiple MSDU copy loop. false = single true = multiple sending */
Pavel Machek66101de2008-10-01 14:36:56 +0200531
Mike Sheldonb1facee2010-03-10 13:32:01 +0000532 /* Move to the next one, if necessary */
Pavel Machek66101de2008-10-01 14:36:56 +0200533 if (BufferFilled) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000534 /* size setting */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300535 pMds->TxBufferSize[FillIndex] = XmitBufSize;
Pavel Machek66101de2008-10-01 14:36:56 +0200536
Mike Sheldonb1facee2010-03-10 13:32:01 +0000537 /* 20060928 set Tx count */
Pavel Machek66101de2008-10-01 14:36:56 +0200538 pMds->TxCountInBuffer[FillIndex] = FillCount;
539
Mike Sheldonb1facee2010-03-10 13:32:01 +0000540 /* Set owner flag */
Pavel Machek66101de2008-10-01 14:36:56 +0200541 pMds->TxOwner[FillIndex] = 1;
542
543 pMds->TxFillIndex++;
544 pMds->TxFillIndex %= MAX_USB_TX_BUFFER_NUMBER;
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200545 BufferFilled = false;
Pavel Machek66101de2008-10-01 14:36:56 +0200546 } else
547 break;
548
Mike Sheldonb1facee2010-03-10 13:32:01 +0000549 if (!PacketSize) /* No more pk for transmitting */
Pavel Machek66101de2008-10-01 14:36:56 +0200550 break;
551
Victor Rosalesa1b09252010-09-19 17:53:00 -0300552 } while (true);
Pavel Machek66101de2008-10-01 14:36:56 +0200553
Mike Sheldonb1facee2010-03-10 13:32:01 +0000554 /*
555 * Start to send by lower module
556 */
Pavel Machek66101de2008-10-01 14:36:56 +0200557 if (!pHwData->IsKeyPreSet)
Pekka Enberg42c84bb2008-10-30 16:14:36 +0200558 Wb35Tx_start(adapter);
Pavel Machek66101de2008-10-01 14:36:56 +0200559
Victor Rosalesa1b09252010-09-19 17:53:00 -0300560cleanup:
561 atomic_dec(&pMds->TxThreadCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200562}
563
564void
Pekka Enbergc4d562a2010-09-19 12:28:38 +0300565Mds_SendComplete(struct wbsoft_priv *adapter, struct T02_descriptor *pT02)
Pavel Machek66101de2008-10-01 14:36:56 +0200566{
Pekka Enbergb7caf942009-08-12 11:03:33 +0300567 struct wb35_mds *pMds = &adapter->Mds;
Adam Latham973267a2010-05-15 09:38:44 +0100568 struct hw_data *pHwData = &adapter->sHwData;
Pavel Machek66101de2008-10-01 14:36:56 +0200569 u8 PacketId = (u8)pT02->T02_Tx_PktID;
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200570 unsigned char SendOK = true;
Pavel Machek66101de2008-10-01 14:36:56 +0200571 u8 RetryCount, TxRate;
572
Mike Sheldonb1facee2010-03-10 13:32:01 +0000573 if (pT02->T02_IgnoreResult) /* Don't care the result */
Pavel Machek66101de2008-10-01 14:36:56 +0200574 return;
575 if (pT02->T02_IsLastMpdu) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000576 /* TODO: DTO -- get the retry count and fragment count */
577 /* Tx rate */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300578 TxRate = pMds->TxRate[PacketId][0];
Pavel Machek66101de2008-10-01 14:36:56 +0200579 RetryCount = (u8)pT02->T02_MPDU_Cnt;
580 if (pT02->value & FLAG_ERROR_TX_MASK) {
Pekka Enberg279b6cc2008-10-27 22:46:39 +0200581 SendOK = false;
Pavel Machek66101de2008-10-01 14:36:56 +0200582
583 if (pT02->T02_transmit_abort || pT02->T02_out_of_MaxTxMSDULiftTime) {
Mike Sheldonb1facee2010-03-10 13:32:01 +0000584 /* retry error */
Pavel Machek66101de2008-10-01 14:36:56 +0200585 pHwData->dto_tx_retry_count += (RetryCount+1);
Mike Sheldonb1facee2010-03-10 13:32:01 +0000586 /* [for tx debug] */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300587 if (RetryCount < 7)
Pavel Machek66101de2008-10-01 14:36:56 +0200588 pHwData->tx_retry_count[RetryCount] += RetryCount;
589 else
590 pHwData->tx_retry_count[7] += RetryCount;
Pekka Enberg2855bb72010-11-28 23:00:00 +0200591 pr_debug("dto_tx_retry_count =%d\n", pHwData->dto_tx_retry_count);
Pekka Enberg88ebc4b2008-10-22 11:03:19 +0300592 MTO_SetTxCount(adapter, TxRate, RetryCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200593 }
594 pHwData->dto_tx_frag_count += (RetryCount+1);
595
Mike Sheldonb1facee2010-03-10 13:32:01 +0000596 /* [for tx debug] */
Pavel Machek66101de2008-10-01 14:36:56 +0200597 if (pT02->T02_transmit_abort_due_to_TBTT)
598 pHwData->tx_TBTT_start_count++;
599 if (pT02->T02_transmit_without_encryption_due_to_wep_on_false)
600 pHwData->tx_WepOn_false_count++;
601 if (pT02->T02_discard_due_to_null_wep_key)
602 pHwData->tx_Null_key_count++;
603 } else {
604 if (pT02->T02_effective_transmission_rate)
605 pHwData->tx_ETR_count++;
Pekka Enberg88ebc4b2008-10-22 11:03:19 +0300606 MTO_SetTxCount(adapter, TxRate, RetryCount);
Pavel Machek66101de2008-10-01 14:36:56 +0200607 }
608
Mike Sheldonb1facee2010-03-10 13:32:01 +0000609 /* Clear send result buffer */
Victor Rosalesa1b09252010-09-19 17:53:00 -0300610 pMds->TxResult[PacketId] = 0;
Pavel Machek66101de2008-10-01 14:36:56 +0200611 } else
Victor Rosalesa1b09252010-09-19 17:53:00 -0300612 pMds->TxResult[PacketId] |= ((u16)(pT02->value & 0x0ffff));
Pavel Machek66101de2008-10-01 14:36:56 +0200613}