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 | * | |
92b96797 FB |
15 | * |
16 | * File: card.c | |
17 | * Purpose: Provide functions to setup NIC operation mode | |
18 | * Functions: | |
1a792943 | 19 | * vnt_set_rspinf - Set RSPINF |
c7ee9eeb | 20 | * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS |
47203c49 | 21 | * vnt_update_top_rates - Update BasicTopRate |
9a2cffd4 | 22 | * vnt_add_basic_rate - Add to BasicRateSet |
cfa4d8d2 | 23 | * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet |
ecbc0a1e | 24 | * vnt_get_tsf_offset - Calculate TSFOffset |
4a9f4c65 | 25 | * vnt_get_current_tsf - Read Current NIC TSF counter |
75ef1b51 | 26 | * vnt_get_next_tbtt - Calculate Next Beacon TSF counter |
6964cd12 | 27 | * vnt_reset_next_tbtt - Set NIC Beacon time |
88ec2f7e | 28 | * vnt_update_next_tbtt - Sync. NIC Beacon time |
fa26e0bd | 29 | * vnt_radio_power_off - Turn Off NIC Radio Power |
8a5e6c8c | 30 | * vnt_radio_power_on - Turn On NIC Radio Power |
92b96797 FB |
31 | * |
32 | * Revision History: | |
33 | * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. | |
a0a1f61a | 34 | * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. |
c7ee9eeb | 35 | * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs(). |
92b96797 FB |
36 | * |
37 | */ | |
38 | ||
dd0a774f | 39 | #include "device.h" |
92b96797 | 40 | #include "card.h" |
92b96797 | 41 | #include "baseband.h" |
92b96797 | 42 | #include "mac.h" |
92b96797 | 43 | #include "desc.h" |
92b96797 | 44 | #include "rf.h" |
92b96797 | 45 | #include "power.h" |
92b96797 | 46 | #include "key.h" |
62c8526d | 47 | #include "usbpipe.h" |
92b96797 | 48 | |
e7c85655 | 49 | /* const u16 cw_rxbcntsf_off[MAX_RATE] = |
b01a5d71 RP |
50 | * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; |
51 | */ | |
92b96797 | 52 | |
e7c85655 | 53 | static const u16 cw_rxbcntsf_off[MAX_RATE] = { |
42b138d9 PST |
54 | 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 |
55 | }; | |
92b96797 | 56 | |
92b96797 FB |
57 | /* |
58 | * Description: Set NIC media channel | |
59 | * | |
60 | * Parameters: | |
61 | * In: | |
62 | * pDevice - The adapter to be set | |
7387f438 | 63 | * connection_channel - Channel to be set |
92b96797 FB |
64 | * Out: |
65 | * none | |
92b96797 | 66 | */ |
084fc8f3 | 67 | void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) |
92b96797 | 68 | { |
04f2ff16 MP |
69 | if (connection_channel > CB_MAX_CHANNEL || !connection_channel) |
70 | return; | |
92b96797 | 71 | |
7387f438 | 72 | /* clear NAV */ |
36957537 | 73 | vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV); |
7387f438 MP |
74 | |
75 | /* Set Channel[7] = 0 to tell H/W channel is changing now. */ | |
a9bed1df | 76 | vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 0xb0); |
7387f438 | 77 | |
733b3b07 | 78 | vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, |
a9f47a45 | 79 | connection_channel, 0, 0, NULL); |
7387f438 | 80 | |
285d58c4 | 81 | vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, |
a9f47a45 | 82 | (u8)(connection_channel | 0x80)); |
92b96797 FB |
83 | } |
84 | ||
85 | /* | |
86 | * Description: Get CCK mode basic rate | |
87 | * | |
88 | * Parameters: | |
89 | * In: | |
3d2988c7 MP |
90 | * priv - The adapter to be set |
91 | * rate_idx - Receiving data rate | |
92b96797 FB |
92 | * Out: |
93 | * none | |
94 | * | |
95 | * Return Value: response Control frame rate | |
96 | * | |
97 | */ | |
073d02eb | 98 | static u16 vnt_get_cck_rate(struct vnt_private *priv, u16 rate_idx) |
92b96797 | 99 | { |
3d2988c7 | 100 | u16 ui = rate_idx; |
dd0a774f MP |
101 | |
102 | while (ui > RATE_1M) { | |
93a73558 | 103 | if (priv->basic_rates & (1 << ui)) |
dd0a774f MP |
104 | return ui; |
105 | ui--; | |
106 | } | |
107 | ||
108 | return RATE_1M; | |
92b96797 FB |
109 | } |
110 | ||
111 | /* | |
112 | * Description: Get OFDM mode basic rate | |
113 | * | |
114 | * Parameters: | |
115 | * In: | |
a5a7c439 MP |
116 | * priv - The adapter to be set |
117 | * rate_idx - Receiving data rate | |
92b96797 FB |
118 | * Out: |
119 | * none | |
120 | * | |
121 | * Return Value: response Control frame rate | |
122 | * | |
123 | */ | |
15fa7ce2 | 124 | static u16 vnt_get_ofdm_rate(struct vnt_private *priv, u16 rate_idx) |
92b96797 | 125 | { |
a5a7c439 | 126 | u16 ui = rate_idx; |
dd0a774f | 127 | |
842e3ecc | 128 | dev_dbg(&priv->usb->dev, "%s basic rate: %d\n", |
a9f47a45 | 129 | __func__, priv->basic_rates); |
dd0a774f | 130 | |
cfa4d8d2 | 131 | if (!vnt_ofdm_min_rate(priv)) { |
842e3ecc | 132 | dev_dbg(&priv->usb->dev, "%s (NO OFDM) %d\n", |
a9f47a45 | 133 | __func__, rate_idx); |
a5a7c439 MP |
134 | if (rate_idx > RATE_24M) |
135 | rate_idx = RATE_24M; | |
136 | return rate_idx; | |
dd0a774f MP |
137 | } |
138 | ||
139 | while (ui > RATE_11M) { | |
93a73558 | 140 | if (priv->basic_rates & (1 << ui)) { |
842e3ecc | 141 | dev_dbg(&priv->usb->dev, "%s rate: %d\n", |
a9f47a45 | 142 | __func__, ui); |
dd0a774f MP |
143 | return ui; |
144 | } | |
145 | ui--; | |
146 | } | |
147 | ||
842e3ecc | 148 | dev_dbg(&priv->usb->dev, "%s basic rate: 24M\n", __func__); |
dd0a774f MP |
149 | |
150 | return RATE_24M; | |
92b96797 FB |
151 | } |
152 | ||
153 | /* | |
a0a1f61a | 154 | * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. |
92b96797 FB |
155 | * |
156 | * Parameters: | |
3605f84e MP |
157 | * In: |
158 | * rate - Tx Rate | |
159 | * bb_type - Tx Packet type | |
160 | * Out: | |
161 | * tx_rate - pointer to RSPINF TxRate field | |
162 | * rsv_time- pointer to RSPINF RsvTime field | |
92b96797 FB |
163 | * |
164 | * Return Value: none | |
165 | * | |
166 | */ | |
c9a04877 | 167 | static void vnt_calculate_ofdm_rate(u16 rate, u8 bb_type, |
a9f47a45 | 168 | u8 *tx_rate, u8 *rsv_time) |
92b96797 | 169 | { |
3605f84e MP |
170 | switch (rate) { |
171 | case RATE_6M: | |
172 | if (bb_type == BB_TYPE_11A) { | |
173 | *tx_rate = 0x9b; | |
174 | *rsv_time = 24; | |
175 | } else { | |
176 | *tx_rate = 0x8b; | |
177 | *rsv_time = 30; | |
178 | } | |
179 | break; | |
180 | case RATE_9M: | |
181 | if (bb_type == BB_TYPE_11A) { | |
182 | *tx_rate = 0x9f; | |
183 | *rsv_time = 16; | |
184 | } else { | |
185 | *tx_rate = 0x8f; | |
186 | *rsv_time = 22; | |
187 | } | |
188 | break; | |
189 | case RATE_12M: | |
190 | if (bb_type == BB_TYPE_11A) { | |
191 | *tx_rate = 0x9a; | |
192 | *rsv_time = 12; | |
193 | } else { | |
194 | *tx_rate = 0x8a; | |
195 | *rsv_time = 18; | |
196 | } | |
197 | break; | |
198 | case RATE_18M: | |
199 | if (bb_type == BB_TYPE_11A) { | |
200 | *tx_rate = 0x9e; | |
201 | *rsv_time = 8; | |
202 | } else { | |
203 | *tx_rate = 0x8e; | |
204 | *rsv_time = 14; | |
205 | } | |
206 | break; | |
207 | case RATE_36M: | |
208 | if (bb_type == BB_TYPE_11A) { | |
209 | *tx_rate = 0x9d; | |
210 | *rsv_time = 4; | |
211 | } else { | |
212 | *tx_rate = 0x8d; | |
213 | *rsv_time = 10; | |
214 | } | |
215 | break; | |
216 | case RATE_48M: | |
217 | if (bb_type == BB_TYPE_11A) { | |
218 | *tx_rate = 0x98; | |
219 | *rsv_time = 4; | |
220 | } else { | |
221 | *tx_rate = 0x88; | |
fd4859f6 | 222 | *rsv_time = 10; |
3605f84e MP |
223 | } |
224 | break; | |
225 | case RATE_54M: | |
226 | if (bb_type == BB_TYPE_11A) { | |
227 | *tx_rate = 0x9c; | |
228 | *rsv_time = 4; | |
229 | } else { | |
230 | *tx_rate = 0x8c; | |
231 | *rsv_time = 10; | |
232 | } | |
233 | break; | |
234 | case RATE_24M: | |
235 | default: | |
236 | if (bb_type == BB_TYPE_11A) { | |
237 | *tx_rate = 0x99; | |
238 | *rsv_time = 8; | |
239 | } else { | |
240 | *tx_rate = 0x89; | |
241 | *rsv_time = 14; | |
242 | } | |
243 | break; | |
244 | } | |
92b96797 FB |
245 | } |
246 | ||
247 | /* | |
248 | * Description: Set RSPINF | |
249 | * | |
250 | * Parameters: | |
251 | * In: | |
252 | * pDevice - The adapter to be set | |
253 | * Out: | |
254 | * none | |
255 | * | |
256 | * Return Value: None. | |
257 | * | |
258 | */ | |
652d0f00 | 259 | |
1a792943 | 260 | void vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) |
92b96797 | 261 | { |
aed387c7 | 262 | struct vnt_phy_field phy[4]; |
652d0f00 MP |
263 | u8 tx_rate[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; /* For OFDM */ |
264 | u8 rsv_time[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
265 | u8 data[34]; | |
dd0a774f | 266 | int i; |
92b96797 | 267 | |
652d0f00 | 268 | /*RSPINF_b_1*/ |
a9f47a45 RP |
269 | vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_1M), |
270 | PK_TYPE_11B, &phy[0]); | |
652d0f00 MP |
271 | |
272 | /*RSPINF_b_2*/ | |
a9f47a45 RP |
273 | vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_2M), |
274 | PK_TYPE_11B, &phy[1]); | |
652d0f00 MP |
275 | |
276 | /*RSPINF_b_5*/ | |
a9f47a45 RP |
277 | vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_5M), |
278 | PK_TYPE_11B, &phy[2]); | |
652d0f00 MP |
279 | |
280 | /*RSPINF_b_11*/ | |
a9f47a45 RP |
281 | vnt_get_phy_field(priv, 14, vnt_get_cck_rate(priv, RATE_11M), |
282 | PK_TYPE_11B, &phy[3]); | |
652d0f00 | 283 | |
652d0f00 | 284 | /*RSPINF_a_6*/ |
c9a04877 | 285 | vnt_calculate_ofdm_rate(RATE_6M, bb_type, &tx_rate[0], &rsv_time[0]); |
652d0f00 MP |
286 | |
287 | /*RSPINF_a_9*/ | |
c9a04877 | 288 | vnt_calculate_ofdm_rate(RATE_9M, bb_type, &tx_rate[1], &rsv_time[1]); |
652d0f00 MP |
289 | |
290 | /*RSPINF_a_12*/ | |
c9a04877 | 291 | vnt_calculate_ofdm_rate(RATE_12M, bb_type, &tx_rate[2], &rsv_time[2]); |
652d0f00 MP |
292 | |
293 | /*RSPINF_a_18*/ | |
c9a04877 | 294 | vnt_calculate_ofdm_rate(RATE_18M, bb_type, &tx_rate[3], &rsv_time[3]); |
92b96797 | 295 | |
652d0f00 | 296 | /*RSPINF_a_24*/ |
c9a04877 | 297 | vnt_calculate_ofdm_rate(RATE_24M, bb_type, &tx_rate[4], &rsv_time[4]); |
652d0f00 MP |
298 | |
299 | /*RSPINF_a_36*/ | |
c9a04877 | 300 | vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_36M), |
a9f47a45 | 301 | bb_type, &tx_rate[5], &rsv_time[5]); |
652d0f00 MP |
302 | |
303 | /*RSPINF_a_48*/ | |
c9a04877 | 304 | vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_48M), |
a9f47a45 | 305 | bb_type, &tx_rate[6], &rsv_time[6]); |
652d0f00 MP |
306 | |
307 | /*RSPINF_a_54*/ | |
c9a04877 | 308 | vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), |
a9f47a45 | 309 | bb_type, &tx_rate[7], &rsv_time[7]); |
652d0f00 MP |
310 | |
311 | /*RSPINF_a_72*/ | |
c9a04877 | 312 | vnt_calculate_ofdm_rate(vnt_get_ofdm_rate(priv, RATE_54M), |
a9f47a45 | 313 | bb_type, &tx_rate[8], &rsv_time[8]); |
652d0f00 MP |
314 | |
315 | put_unaligned(phy[0].len, (u16 *)&data[0]); | |
316 | data[2] = phy[0].signal; | |
317 | data[3] = phy[0].service; | |
318 | ||
319 | put_unaligned(phy[1].len, (u16 *)&data[4]); | |
320 | data[6] = phy[1].signal; | |
321 | data[7] = phy[1].service; | |
322 | ||
323 | put_unaligned(phy[2].len, (u16 *)&data[8]); | |
324 | data[10] = phy[2].signal; | |
325 | data[11] = phy[2].service; | |
326 | ||
327 | put_unaligned(phy[3].len, (u16 *)&data[12]); | |
328 | data[14] = phy[3].signal; | |
329 | data[15] = phy[3].service; | |
330 | ||
331 | for (i = 0; i < 9; i++) { | |
332 | data[16 + i * 2] = tx_rate[i]; | |
333 | data[16 + i * 2 + 1] = rsv_time[i]; | |
334 | } | |
92b96797 | 335 | |
a9f47a45 RP |
336 | vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, |
337 | MESSAGE_REQUEST_MACREG, 34, &data[0]); | |
92b96797 FB |
338 | } |
339 | ||
340 | /* | |
341 | * Description: Update IFS | |
342 | * | |
343 | * Parameters: | |
344 | * In: | |
5ebc46d6 MP |
345 | * priv - The adapter to be set |
346 | * Out: | |
347 | * none | |
92b96797 FB |
348 | * |
349 | * Return Value: None. | |
350 | * | |
351 | */ | |
c7ee9eeb | 352 | void vnt_update_ifs(struct vnt_private *priv) |
92b96797 | 353 | { |
5ebc46d6 MP |
354 | u8 max_min = 0; |
355 | u8 data[4]; | |
356 | ||
e12471db | 357 | if (priv->packet_type == PK_TYPE_11A) { |
ff5fee22 MP |
358 | priv->slot = C_SLOT_SHORT; |
359 | priv->sifs = C_SIFS_A; | |
360 | priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT; | |
5ebc46d6 | 361 | max_min = 4; |
e12471db | 362 | } else if (priv->packet_type == PK_TYPE_11B) { |
ff5fee22 MP |
363 | priv->slot = C_SLOT_LONG; |
364 | priv->sifs = C_SIFS_BG; | |
365 | priv->difs = C_SIFS_BG + 2 * C_SLOT_LONG; | |
5ebc46d6 MP |
366 | max_min = 5; |
367 | } else {/* PK_TYPE_11GA & PK_TYPE_11GB */ | |
5ebc46d6 MP |
368 | bool ofdm_rate = false; |
369 | unsigned int ii = 0; | |
5ebc46d6 | 370 | |
ff5fee22 | 371 | priv->sifs = C_SIFS_BG; |
5ebc46d6 | 372 | |
a641c9ec | 373 | if (priv->short_slot_time) |
ff5fee22 | 374 | priv->slot = C_SLOT_SHORT; |
5ebc46d6 | 375 | else |
ff5fee22 | 376 | priv->slot = C_SLOT_LONG; |
5ebc46d6 | 377 | |
ff5fee22 | 378 | priv->difs = C_SIFS_BG + 2 * priv->slot; |
5ebc46d6 | 379 | |
ee61fde2 | 380 | for (ii = RATE_54M; ii >= RATE_6M; ii--) { |
93a73558 | 381 | if (priv->basic_rates & ((u32)(0x1 << ii))) { |
5ebc46d6 MP |
382 | ofdm_rate = true; |
383 | break; | |
384 | } | |
385 | } | |
386 | ||
5699c0f4 | 387 | if (ofdm_rate) |
5ebc46d6 | 388 | max_min = 4; |
995c91e0 | 389 | else |
5ebc46d6 | 390 | max_min = 5; |
5ebc46d6 MP |
391 | } |
392 | ||
ff5fee22 | 393 | priv->eifs = C_EIFS; |
5ebc46d6 | 394 | |
6242ecae | 395 | switch (priv->rf_type) { |
9fe109c1 | 396 | case RF_VT3226D0: |
65df77e2 | 397 | if (priv->bb_type != BB_TYPE_11B) { |
ff5fee22 MP |
398 | priv->sifs -= 1; |
399 | priv->difs -= 1; | |
9fe109c1 MP |
400 | break; |
401 | } | |
402 | case RF_AIROHA7230: | |
403 | case RF_AL2230: | |
404 | case RF_AL2230S: | |
65df77e2 | 405 | if (priv->bb_type != BB_TYPE_11B) |
9fe109c1 MP |
406 | break; |
407 | case RF_RFMD2959: | |
408 | case RF_VT3226: | |
409 | case RF_VT3342A0: | |
ff5fee22 MP |
410 | priv->sifs -= 3; |
411 | priv->difs -= 3; | |
9fe109c1 MP |
412 | break; |
413 | case RF_MAXIM2829: | |
65df77e2 | 414 | if (priv->bb_type == BB_TYPE_11A) { |
ff5fee22 MP |
415 | priv->sifs -= 5; |
416 | priv->difs -= 5; | |
9fe109c1 | 417 | } else { |
ff5fee22 MP |
418 | priv->sifs -= 2; |
419 | priv->difs -= 2; | |
9fe109c1 MP |
420 | } |
421 | ||
422 | break; | |
423 | } | |
424 | ||
ff5fee22 MP |
425 | data[0] = (u8)priv->sifs; |
426 | data[1] = (u8)priv->difs; | |
427 | data[2] = (u8)priv->eifs; | |
428 | data[3] = (u8)priv->slot; | |
5ebc46d6 | 429 | |
1390b02a | 430 | vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, |
a9f47a45 | 431 | MESSAGE_REQUEST_MACREG, 4, &data[0]); |
5ebc46d6 MP |
432 | |
433 | max_min |= 0xa0; | |
434 | ||
1390b02a | 435 | vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, |
a9f47a45 | 436 | MESSAGE_REQUEST_MACREG, 1, &max_min); |
92b96797 FB |
437 | } |
438 | ||
47203c49 | 439 | void vnt_update_top_rates(struct vnt_private *priv) |
92b96797 | 440 | { |
dcce9e0b MP |
441 | u8 top_ofdm = RATE_24M, top_cck = RATE_1M; |
442 | u8 i; | |
443 | ||
444 | /*Determines the highest basic rate.*/ | |
445 | for (i = RATE_54M; i >= RATE_6M; i--) { | |
93a73558 | 446 | if (priv->basic_rates & (u16)(1 << i)) { |
dcce9e0b MP |
447 | top_ofdm = i; |
448 | break; | |
449 | } | |
450 | } | |
451 | ||
3c8a5b25 | 452 | priv->top_ofdm_basic_rate = top_ofdm; |
dcce9e0b MP |
453 | |
454 | for (i = RATE_11M;; i--) { | |
93a73558 | 455 | if (priv->basic_rates & (u16)(1 << i)) { |
dcce9e0b MP |
456 | top_cck = i; |
457 | break; | |
458 | } | |
459 | if (i == RATE_1M) | |
460 | break; | |
461 | } | |
462 | ||
d80bf43c | 463 | priv->top_cck_basic_rate = top_cck; |
42b138d9 | 464 | } |
92b96797 | 465 | |
cfa4d8d2 | 466 | int vnt_ofdm_min_rate(struct vnt_private *priv) |
92b96797 | 467 | { |
dd0a774f | 468 | int ii; |
92b96797 | 469 | |
de0eb9ef | 470 | for (ii = RATE_54M; ii >= RATE_6M; ii--) { |
574dddc6 | 471 | if ((priv->basic_rates) & ((u16)BIT(ii))) |
de0eb9ef MP |
472 | return true; |
473 | } | |
474 | ||
475 | return false; | |
92b96797 FB |
476 | } |
477 | ||
e809c96e | 478 | u8 vnt_get_pkt_type(struct vnt_private *priv) |
92b96797 | 479 | { |
65df77e2 MP |
480 | if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) |
481 | return (u8)priv->bb_type; | |
cfa4d8d2 | 482 | else if (vnt_ofdm_min_rate(priv)) |
1f44238f | 483 | return PK_TYPE_11GA; |
3e46587e | 484 | return PK_TYPE_11GB; |
92b96797 FB |
485 | } |
486 | ||
92b96797 | 487 | /* |
a0a1f61a | 488 | * Description: Calculate TSF offset of two TSF input |
92b96797 FB |
489 | * Get TSF Offset from RxBCN's TSF and local TSF |
490 | * | |
491 | * Parameters: | |
492 | * In: | |
3fd2a69c MP |
493 | * rx_rate - rx rate. |
494 | * tsf1 - Rx BCN's TSF | |
495 | * tsf2 - Local TSF | |
92b96797 FB |
496 | * Out: |
497 | * none | |
498 | * | |
499 | * Return Value: TSF Offset value | |
500 | * | |
501 | */ | |
ecbc0a1e | 502 | u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) |
92b96797 | 503 | { |
3fd2a69c | 504 | u64 tsf_offset = 0; |
4b1443a2 | 505 | u16 rx_bcn_offset; |
92b96797 | 506 | |
e7c85655 | 507 | rx_bcn_offset = cw_rxbcntsf_off[rx_rate % MAX_RATE]; |
92b96797 | 508 | |
3fd2a69c | 509 | tsf2 += (u64)rx_bcn_offset; |
7c65fa2a | 510 | |
3fd2a69c | 511 | tsf_offset = tsf1 - tsf2; |
7c65fa2a | 512 | |
3fd2a69c | 513 | return tsf_offset; |
92b96797 FB |
514 | } |
515 | ||
92b96797 FB |
516 | /* |
517 | * Description: Sync. TSF counter to BSS | |
518 | * Get TSF offset and write to HW | |
519 | * | |
520 | * Parameters: | |
521 | * In: | |
302361d4 MP |
522 | * priv - The adapter to be sync. |
523 | * time_stamp - Rx BCN's TSF | |
524 | * local_tsf - Local TSF | |
92b96797 FB |
525 | * Out: |
526 | * none | |
527 | * | |
528 | * Return Value: none | |
529 | * | |
530 | */ | |
14c68c56 | 531 | void vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, |
a9f47a45 | 532 | u64 time_stamp, u64 local_tsf) |
92b96797 | 533 | { |
302361d4 MP |
534 | u64 tsf_offset = 0; |
535 | u8 data[8]; | |
536 | ||
ecbc0a1e | 537 | tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf); |
302361d4 MP |
538 | |
539 | data[0] = (u8)tsf_offset; | |
540 | data[1] = (u8)(tsf_offset >> 8); | |
541 | data[2] = (u8)(tsf_offset >> 16); | |
542 | data[3] = (u8)(tsf_offset >> 24); | |
543 | data[4] = (u8)(tsf_offset >> 32); | |
544 | data[5] = (u8)(tsf_offset >> 40); | |
545 | data[6] = (u8)(tsf_offset >> 48); | |
546 | data[7] = (u8)(tsf_offset >> 56); | |
92b96797 | 547 | |
1390b02a | 548 | vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, |
a9f47a45 | 549 | MESSAGE_REQUEST_TSF, 0, 8, data); |
92b96797 | 550 | } |
6d898d69 | 551 | |
92b96797 FB |
552 | /* |
553 | * Description: Read NIC TSF counter | |
554 | * Get local TSF counter | |
555 | * | |
556 | * Parameters: | |
557 | * In: | |
2092dfa4 | 558 | * priv - The adapter to be read |
92b96797 | 559 | * Out: |
2092dfa4 | 560 | * current_tsf - Current TSF counter |
92b96797 | 561 | * |
4e9b5e2b | 562 | * Return Value: true if success; otherwise false |
92b96797 FB |
563 | * |
564 | */ | |
4a9f4c65 | 565 | bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) |
92b96797 | 566 | { |
113f0b91 | 567 | *current_tsf = priv->current_tsf; |
92b96797 | 568 | |
4e9b5e2b | 569 | return true; |
92b96797 FB |
570 | } |
571 | ||
92b96797 FB |
572 | /* |
573 | * Description: Clear NIC TSF counter | |
574 | * Clear local TSF counter | |
575 | * | |
576 | * Parameters: | |
577 | * In: | |
e151e478 | 578 | * priv - The adapter to be read |
92b96797 | 579 | * |
4e9b5e2b | 580 | * Return Value: true if success; otherwise false |
92b96797 FB |
581 | * |
582 | */ | |
dba066e9 | 583 | bool vnt_clear_current_tsf(struct vnt_private *priv) |
92b96797 | 584 | { |
36957537 | 585 | vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); |
92b96797 | 586 | |
113f0b91 | 587 | priv->current_tsf = 0; |
92b96797 | 588 | |
4e9b5e2b | 589 | return true; |
92b96797 FB |
590 | } |
591 | ||
592 | /* | |
593 | * Description: Read NIC TSF counter | |
594 | * Get NEXTTBTT from adjusted TSF and Beacon Interval | |
595 | * | |
596 | * Parameters: | |
597 | * In: | |
5f4dfb66 MP |
598 | * tsf - Current TSF counter |
599 | * beacon_interval - Beacon Interval | |
92b96797 | 600 | * Out: |
5f4dfb66 | 601 | * tsf - Current TSF counter |
92b96797 FB |
602 | * |
603 | * Return Value: TSF value of next Beacon | |
604 | * | |
605 | */ | |
75ef1b51 | 606 | u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval) |
92b96797 | 607 | { |
5f4dfb66 | 608 | u32 beacon_int; |
92b96797 | 609 | |
5f4dfb66 | 610 | beacon_int = beacon_interval * 1024; |
92b96797 | 611 | |
6e28024e MP |
612 | /* Next TBTT = |
613 | * ((local_current_TSF / beacon_interval) + 1) * beacon_interval | |
614 | */ | |
5f4dfb66 MP |
615 | if (beacon_int) { |
616 | do_div(tsf, beacon_int); | |
617 | tsf += 1; | |
618 | tsf *= beacon_int; | |
6e28024e | 619 | } |
92b96797 | 620 | |
5f4dfb66 | 621 | return tsf; |
92b96797 FB |
622 | } |
623 | ||
92b96797 FB |
624 | /* |
625 | * Description: Set NIC TSF counter for first Beacon time | |
626 | * Get NEXTTBTT from adjusted TSF and Beacon Interval | |
627 | * | |
628 | * Parameters: | |
629 | * In: | |
630 | * dwIoBase - IO Base | |
414475f6 | 631 | * beacon_interval - Beacon Interval |
92b96797 FB |
632 | * Out: |
633 | * none | |
634 | * | |
635 | * Return Value: none | |
636 | * | |
637 | */ | |
6964cd12 | 638 | void vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) |
92b96797 | 639 | { |
414475f6 MP |
640 | u64 next_tbtt = 0; |
641 | u8 data[8]; | |
642 | ||
dba066e9 | 643 | vnt_clear_current_tsf(priv); |
414475f6 | 644 | |
75ef1b51 | 645 | next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval); |
414475f6 MP |
646 | |
647 | data[0] = (u8)next_tbtt; | |
648 | data[1] = (u8)(next_tbtt >> 8); | |
649 | data[2] = (u8)(next_tbtt >> 16); | |
650 | data[3] = (u8)(next_tbtt >> 24); | |
651 | data[4] = (u8)(next_tbtt >> 32); | |
652 | data[5] = (u8)(next_tbtt >> 40); | |
653 | data[6] = (u8)(next_tbtt >> 48); | |
654 | data[7] = (u8)(next_tbtt >> 56); | |
655 | ||
1390b02a | 656 | vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, |
a9f47a45 | 657 | MESSAGE_REQUEST_TBTT, 0, 8, data); |
92b96797 FB |
658 | } |
659 | ||
92b96797 FB |
660 | /* |
661 | * Description: Sync NIC TSF counter for Beacon time | |
662 | * Get NEXTTBTT and write to HW | |
663 | * | |
664 | * Parameters: | |
665 | * In: | |
8b515de7 MP |
666 | * priv - The adapter to be set |
667 | * tsf - Current TSF counter | |
668 | * beacon_interval - Beacon Interval | |
92b96797 FB |
669 | * Out: |
670 | * none | |
671 | * | |
672 | * Return Value: none | |
673 | * | |
674 | */ | |
88ec2f7e | 675 | void vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, |
a9f47a45 | 676 | u16 beacon_interval) |
92b96797 | 677 | { |
8b515de7 | 678 | u8 data[8]; |
92b96797 | 679 | |
75ef1b51 | 680 | tsf = vnt_get_next_tbtt(tsf, beacon_interval); |
7c65fa2a | 681 | |
8b515de7 MP |
682 | data[0] = (u8)tsf; |
683 | data[1] = (u8)(tsf >> 8); | |
684 | data[2] = (u8)(tsf >> 16); | |
685 | data[3] = (u8)(tsf >> 24); | |
686 | data[4] = (u8)(tsf >> 32); | |
687 | data[5] = (u8)(tsf >> 40); | |
688 | data[6] = (u8)(tsf >> 48); | |
689 | data[7] = (u8)(tsf >> 56); | |
92b96797 | 690 | |
1390b02a | 691 | vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, |
42b138d9 | 692 | MESSAGE_REQUEST_TBTT, 0, 8, data); |
92b96797 | 693 | |
842e3ecc | 694 | dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf); |
92b96797 FB |
695 | } |
696 | ||
697 | /* | |
698 | * Description: Turn off Radio power | |
699 | * | |
700 | * Parameters: | |
701 | * In: | |
07deb710 | 702 | * priv - The adapter to be turned off |
92b96797 FB |
703 | * Out: |
704 | * none | |
705 | * | |
4e9b5e2b | 706 | * Return Value: true if success; otherwise false |
92b96797 FB |
707 | * |
708 | */ | |
fa26e0bd | 709 | int vnt_radio_power_off(struct vnt_private *priv) |
92b96797 | 710 | { |
07deb710 MP |
711 | int ret = true; |
712 | ||
6242ecae | 713 | switch (priv->rf_type) { |
07deb710 MP |
714 | case RF_AL2230: |
715 | case RF_AL2230S: | |
716 | case RF_AIROHA7230: | |
717 | case RF_VT3226: | |
718 | case RF_VT3226D0: | |
719 | case RF_VT3342A0: | |
a9bed1df | 720 | vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, |
a9f47a45 | 721 | (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); |
07deb710 MP |
722 | break; |
723 | } | |
92b96797 | 724 | |
a9bed1df | 725 | vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON); |
92b96797 | 726 | |
e8e072da | 727 | vnt_set_deep_sleep(priv); |
92b96797 | 728 | |
d7f2d8f6 MP |
729 | vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); |
730 | ||
07deb710 | 731 | return ret; |
92b96797 FB |
732 | } |
733 | ||
92b96797 FB |
734 | /* |
735 | * Description: Turn on Radio power | |
736 | * | |
737 | * Parameters: | |
738 | * In: | |
f3203144 | 739 | * priv - The adapter to be turned on |
92b96797 FB |
740 | * Out: |
741 | * none | |
742 | * | |
4e9b5e2b | 743 | * Return Value: true if success; otherwise false |
92b96797 FB |
744 | * |
745 | */ | |
8a5e6c8c | 746 | int vnt_radio_power_on(struct vnt_private *priv) |
92b96797 | 747 | { |
f3203144 | 748 | int ret = true; |
92b96797 | 749 | |
0e951753 | 750 | vnt_exit_deep_sleep(priv); |
92b96797 | 751 | |
36957537 | 752 | vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON); |
92b96797 | 753 | |
6242ecae | 754 | switch (priv->rf_type) { |
f3203144 MP |
755 | case RF_AL2230: |
756 | case RF_AL2230S: | |
757 | case RF_AIROHA7230: | |
758 | case RF_VT3226: | |
759 | case RF_VT3226D0: | |
760 | case RF_VT3342A0: | |
36957537 | 761 | vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, |
a9f47a45 | 762 | (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3)); |
f3203144 MP |
763 | break; |
764 | } | |
92b96797 | 765 | |
d7f2d8f6 MP |
766 | vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); |
767 | ||
f3203144 | 768 | return ret; |
92b96797 FB |
769 | } |
770 | ||
bc240f54 | 771 | void vnt_set_bss_mode(struct vnt_private *priv) |
92b96797 | 772 | { |
65df77e2 | 773 | if (priv->rf_type == RF_AIROHA7230 && priv->bb_type == BB_TYPE_11A) |
05089fbc | 774 | vnt_mac_set_bb_type(priv, BB_TYPE_11G); |
1efb8fac | 775 | else |
65df77e2 | 776 | vnt_mac_set_bb_type(priv, priv->bb_type); |
1efb8fac | 777 | |
e12471db | 778 | priv->packet_type = vnt_get_pkt_type(priv); |
1efb8fac | 779 | |
65df77e2 | 780 | if (priv->bb_type == BB_TYPE_11A) |
285d58c4 | 781 | vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x88, 0x03); |
65df77e2 | 782 | else if (priv->bb_type == BB_TYPE_11B) |
285d58c4 | 783 | vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x88, 0x02); |
65df77e2 | 784 | else if (priv->bb_type == BB_TYPE_11G) |
285d58c4 | 785 | vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x88, 0x08); |
1efb8fac | 786 | |
c7ee9eeb | 787 | vnt_update_ifs(priv); |
65df77e2 | 788 | vnt_set_rspinf(priv, (u8)priv->bb_type); |
1efb8fac | 789 | |
65df77e2 | 790 | if (priv->bb_type == BB_TYPE_11A) { |
6242ecae | 791 | if (priv->rf_type == RF_AIROHA7230) { |
c37cbd37 | 792 | priv->bb_vga[0] = 0x20; |
1efb8fac | 793 | |
285d58c4 | 794 | vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, |
a9f47a45 | 795 | 0xe7, priv->bb_vga[0]); |
1efb8fac MP |
796 | } |
797 | ||
c37cbd37 MP |
798 | priv->bb_vga[2] = 0x10; |
799 | priv->bb_vga[3] = 0x10; | |
1efb8fac | 800 | } else { |
6242ecae | 801 | if (priv->rf_type == RF_AIROHA7230) { |
c37cbd37 | 802 | priv->bb_vga[0] = 0x1c; |
1efb8fac | 803 | |
285d58c4 | 804 | vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, |
a9f47a45 | 805 | 0xe7, priv->bb_vga[0]); |
1efb8fac MP |
806 | } |
807 | ||
c37cbd37 MP |
808 | priv->bb_vga[2] = 0x0; |
809 | priv->bb_vga[3] = 0x0; | |
1efb8fac | 810 | } |
d3584775 | 811 | |
c37cbd37 | 812 | vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); |
92b96797 | 813 | } |