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