Commit | Line | Data |
---|---|---|
d7c43082 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
5449c685 FB |
2 | /* |
3 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | |
4 | * All rights reserved. | |
5 | * | |
5449c685 FB |
6 | * Purpose: Provide functions to setup NIC operation mode |
7 | * Functions: | |
8 | * s_vSafeResetTx - Rest Tx | |
c97dbf1d | 9 | * card_set_rspinf - Set RSPINF |
5449c685 FB |
10 | * CARDvUpdateBasicTopRate - Update BasicTopRate |
11 | * CARDbAddBasicRate - Add to BasicRateSet | |
5449c685 | 12 | * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet |
314b805e | 13 | * card_get_tsf_offset - Calculate TSFOffset |
fed5b533 | 14 | * vt6655_get_current_tsf - Read Current NIC TSF counter |
862aa279 | 15 | * card_get_next_tbtt - Calculate Next Beacon TSF counter |
5449c685 FB |
16 | * CARDvSetFirstNextTBTT - Set NIC Beacon time |
17 | * CARDvUpdateNextTBTT - Sync. NIC Beacon time | |
ac491ce1 | 18 | * card_radio_power_off - Turn Off NIC Radio Power |
5449c685 FB |
19 | * |
20 | * Revision History: | |
21 | * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. | |
36f18e74 | 22 | * 08-26-2003 Kyle Hsu: Modify the definition type of iobase. |
5449c685 FB |
23 | * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). |
24 | * | |
25 | */ | |
26 | ||
5449c685 | 27 | #include "card.h" |
5449c685 | 28 | #include "baseband.h" |
5449c685 | 29 | #include "mac.h" |
5449c685 | 30 | #include "desc.h" |
5449c685 | 31 | #include "rf.h" |
5449c685 | 32 | #include "power.h" |
5449c685 FB |
33 | |
34 | /*--------------------- Static Definitions -------------------------*/ | |
35 | ||
77b6a6a3 | 36 | #define C_SIFS_A 16 /* micro sec. */ |
5449c685 FB |
37 | #define C_SIFS_BG 10 |
38 | ||
77b6a6a3 | 39 | #define C_EIFS 80 /* micro sec. */ |
5449c685 | 40 | |
77b6a6a3 | 41 | #define C_SLOT_SHORT 9 /* micro sec. */ |
5449c685 FB |
42 | #define C_SLOT_LONG 20 |
43 | ||
77b6a6a3 | 44 | #define C_CWMIN_A 15 /* slot time */ |
5449c685 FB |
45 | #define C_CWMIN_B 31 |
46 | ||
77b6a6a3 | 47 | #define C_CWMAX 1023 /* slot time */ |
5449c685 | 48 | |
77b6a6a3 | 49 | #define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */ |
5449c685 | 50 | |
5449c685 FB |
51 | /*--------------------- Static Variables --------------------------*/ |
52 | ||
6c149083 | 53 | static const unsigned short rx_bcn_tsf_off[MAX_RATE] = { |
1167ff91 | 54 | 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; |
5449c685 | 55 | |
5449c685 FB |
56 | /*--------------------- Static Functions --------------------------*/ |
57 | ||
b1d3ecbf | 58 | static void vt6655_mac_set_bb_type(void __iomem *iobase, u32 mask) |
52b735c9 PH |
59 | { |
60 | u32 reg_value; | |
61 | ||
62 | reg_value = ioread32(iobase + MAC_REG_ENCFG); | |
63 | reg_value = reg_value & ~ENCFG_BBTYPE_MASK; | |
64 | reg_value = reg_value | mask; | |
65 | iowrite32(reg_value, iobase + MAC_REG_ENCFG); | |
66 | } | |
67 | ||
5449c685 FB |
68 | /*--------------------- Export Functions --------------------------*/ |
69 | ||
5449c685 | 70 | /* |
7664ec86 | 71 | * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. |
5449c685 FB |
72 | * |
73 | * Parameters: | |
74 | * In: | |
75 | * wRate - Tx Rate | |
76 | * byPktType - Tx Packet type | |
77 | * Out: | |
eb88265f | 78 | * tx_rate - pointer to RSPINF TxRate field |
cb1fe713 | 79 | * rsv_time - pointer to RSPINF RsvTime field |
5449c685 FB |
80 | * |
81 | * Return Value: none | |
5449c685 | 82 | */ |
8b46d9ff | 83 | static void calculate_ofdmr_parameter(unsigned char rate, |
6e0afa35 | 84 | u8 bb_type, |
eb88265f | 85 | unsigned char *tx_rate, |
cb1fe713 | 86 | unsigned char *rsv_time) |
5449c685 | 87 | { |
6ac113f7 | 88 | switch (rate) { |
d4945f09 | 89 | case RATE_6M: |
d1ab5201 | 90 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 91 | *tx_rate = 0x9B; |
cb1fe713 | 92 | *rsv_time = 44; |
5e0cc8a2 | 93 | } else { |
eb88265f | 94 | *tx_rate = 0x8B; |
cb1fe713 | 95 | *rsv_time = 50; |
d4945f09 JP |
96 | } |
97 | break; | |
98 | ||
99 | case RATE_9M: | |
d1ab5201 | 100 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 101 | *tx_rate = 0x9F; |
cb1fe713 | 102 | *rsv_time = 36; |
5e0cc8a2 | 103 | } else { |
eb88265f | 104 | *tx_rate = 0x8F; |
cb1fe713 | 105 | *rsv_time = 42; |
d4945f09 JP |
106 | } |
107 | break; | |
108 | ||
109 | case RATE_12M: | |
d1ab5201 | 110 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 111 | *tx_rate = 0x9A; |
cb1fe713 | 112 | *rsv_time = 32; |
5e0cc8a2 | 113 | } else { |
eb88265f | 114 | *tx_rate = 0x8A; |
cb1fe713 | 115 | *rsv_time = 38; |
d4945f09 JP |
116 | } |
117 | break; | |
118 | ||
119 | case RATE_18M: | |
d1ab5201 | 120 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 121 | *tx_rate = 0x9E; |
cb1fe713 | 122 | *rsv_time = 28; |
5e0cc8a2 | 123 | } else { |
eb88265f | 124 | *tx_rate = 0x8E; |
cb1fe713 | 125 | *rsv_time = 34; |
d4945f09 JP |
126 | } |
127 | break; | |
128 | ||
129 | case RATE_36M: | |
d1ab5201 | 130 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 131 | *tx_rate = 0x9D; |
cb1fe713 | 132 | *rsv_time = 24; |
5e0cc8a2 | 133 | } else { |
eb88265f | 134 | *tx_rate = 0x8D; |
cb1fe713 | 135 | *rsv_time = 30; |
d4945f09 JP |
136 | } |
137 | break; | |
138 | ||
139 | case RATE_48M: | |
d1ab5201 | 140 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 141 | *tx_rate = 0x98; |
cb1fe713 | 142 | *rsv_time = 24; |
5e0cc8a2 | 143 | } else { |
eb88265f | 144 | *tx_rate = 0x88; |
cb1fe713 | 145 | *rsv_time = 30; |
d4945f09 JP |
146 | } |
147 | break; | |
148 | ||
149 | case RATE_54M: | |
d1ab5201 | 150 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 151 | *tx_rate = 0x9C; |
cb1fe713 | 152 | *rsv_time = 24; |
5e0cc8a2 | 153 | } else { |
eb88265f | 154 | *tx_rate = 0x8C; |
cb1fe713 | 155 | *rsv_time = 30; |
d4945f09 JP |
156 | } |
157 | break; | |
158 | ||
159 | case RATE_24M: | |
160 | default: | |
d1ab5201 | 161 | if (bb_type == BB_TYPE_11A) { /* 5GHZ */ |
eb88265f | 162 | *tx_rate = 0x99; |
cb1fe713 | 163 | *rsv_time = 28; |
5e0cc8a2 | 164 | } else { |
eb88265f | 165 | *tx_rate = 0x89; |
cb1fe713 | 166 | *rsv_time = 34; |
d4945f09 JP |
167 | } |
168 | break; | |
169 | } | |
5449c685 FB |
170 | } |
171 | ||
5449c685 | 172 | /*--------------------- Export Functions --------------------------*/ |
5449c685 | 173 | |
5449c685 FB |
174 | /* |
175 | * Description: Update IFS | |
176 | * | |
177 | * Parameters: | |
178 | * In: | |
91961244 | 179 | * priv - The adapter to be set |
5449c685 FB |
180 | * Out: |
181 | * none | |
182 | * | |
183 | * Return Value: None. | |
5449c685 | 184 | */ |
4922f5d1 | 185 | bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type) |
5449c685 | 186 | { |
25b8c77e | 187 | unsigned char cw_max_min = 0; |
e59314b6 | 188 | unsigned char slot = 0; |
d988a485 | 189 | unsigned char sifs = 0; |
30af3e57 | 190 | unsigned char difs = 0; |
0614a0e8 | 191 | int i; |
d4945f09 | 192 | |
77b6a6a3 | 193 | /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */ |
a558e3dc | 194 | if (bb_type == BB_TYPE_11A) { |
b1d3ecbf | 195 | vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11A); |
af93096e | 196 | bb_write_embedded(priv, 0x88, 0x03); |
e59314b6 | 197 | slot = C_SLOT_SHORT; |
d988a485 | 198 | sifs = C_SIFS_A; |
30af3e57 | 199 | difs = C_SIFS_A + 2 * C_SLOT_SHORT; |
25b8c77e | 200 | cw_max_min = 0xA4; |
a558e3dc | 201 | } else if (bb_type == BB_TYPE_11B) { |
b1d3ecbf | 202 | vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11B); |
af93096e | 203 | bb_write_embedded(priv, 0x88, 0x02); |
e59314b6 | 204 | slot = C_SLOT_LONG; |
d988a485 | 205 | sifs = C_SIFS_BG; |
30af3e57 | 206 | difs = C_SIFS_BG + 2 * C_SLOT_LONG; |
25b8c77e | 207 | cw_max_min = 0xA5; |
77b6a6a3 | 208 | } else { /* PK_TYPE_11GA & PK_TYPE_11GB */ |
b1d3ecbf | 209 | vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11G); |
af93096e | 210 | bb_write_embedded(priv, 0x88, 0x08); |
d988a485 | 211 | sifs = C_SIFS_BG; |
0614a0e8 | 212 | |
e4a9e1d8 | 213 | if (priv->short_slot_time) { |
e59314b6 | 214 | slot = C_SLOT_SHORT; |
30af3e57 | 215 | difs = C_SIFS_BG + 2 * C_SLOT_SHORT; |
d4945f09 | 216 | } else { |
e59314b6 | 217 | slot = C_SLOT_LONG; |
30af3e57 | 218 | difs = C_SIFS_BG + 2 * C_SLOT_LONG; |
d4945f09 | 219 | } |
bc5cf656 | 220 | |
25b8c77e | 221 | cw_max_min = 0xa4; |
0614a0e8 MP |
222 | |
223 | for (i = RATE_54M; i >= RATE_6M; i--) { | |
91961244 | 224 | if (priv->basic_rates & ((u32)(0x1 << i))) { |
25b8c77e | 225 | cw_max_min |= 0x1; |
0614a0e8 MP |
226 | break; |
227 | } | |
d4945f09 JP |
228 | } |
229 | } | |
230 | ||
eb507641 | 231 | if (priv->rf_type == RF_RFMD2959) { |
77b6a6a3 VK |
232 | /* |
233 | * bcs TX_PE will reserve 3 us hardware's processing | |
234 | * time here is 2 us. | |
235 | */ | |
d988a485 | 236 | sifs -= 3; |
30af3e57 | 237 | difs -= 3; |
77b6a6a3 VK |
238 | /* |
239 | * TX_PE will reserve 3 us for MAX2829 A mode only, it is for | |
240 | * better TX throughput; MAC will need 2 us to process, so the | |
241 | * SIFS, DIFS can be shorter by 2 us. | |
242 | */ | |
d4945f09 JP |
243 | } |
244 | ||
d988a485 GA |
245 | if (priv->sifs != sifs) { |
246 | priv->sifs = sifs; | |
247 | iowrite8(priv->sifs, priv->port_offset + MAC_REG_SIFS); | |
d4945f09 | 248 | } |
30af3e57 GA |
249 | if (priv->difs != difs) { |
250 | priv->difs = difs; | |
251 | iowrite8(priv->difs, priv->port_offset + MAC_REG_DIFS); | |
d4945f09 | 252 | } |
5d9f6f26 GA |
253 | if (priv->eifs != C_EIFS) { |
254 | priv->eifs = C_EIFS; | |
255 | iowrite8(priv->eifs, priv->port_offset + MAC_REG_EIFS); | |
d4945f09 | 256 | } |
e59314b6 GA |
257 | if (priv->slot != slot) { |
258 | priv->slot = slot; | |
259 | iowrite8(priv->slot, priv->port_offset + MAC_REG_SLOT); | |
bc5cf656 | 260 | |
af93096e | 261 | bb_set_short_slot_time(priv); |
d4945f09 | 262 | } |
25b8c77e GA |
263 | if (priv->cw_max_min != cw_max_min) { |
264 | priv->cw_max_min = cw_max_min; | |
265 | iowrite8(priv->cw_max_min, priv->port_offset + MAC_REG_CWMAXMIN0); | |
d4945f09 | 266 | } |
0614a0e8 | 267 | |
1904b721 | 268 | priv->packet_type = card_get_pkt_type(priv); |
61b90995 | 269 | |
c97dbf1d | 270 | card_set_rspinf(priv, bb_type); |
0614a0e8 | 271 | |
a4ef27ad | 272 | return true; |
5449c685 FB |
273 | } |
274 | ||
275 | /* | |
276 | * Description: Sync. TSF counter to BSS | |
277 | * Get TSF offset and write to HW | |
278 | * | |
279 | * Parameters: | |
280 | * In: | |
41196b0b PB |
281 | * priv - The adapter to be sync. |
282 | * rx_rate - data rate of receive beacon | |
89abfc0a | 283 | * bss_timestamp - Rx BCN's TSF |
5449c685 FB |
284 | * qwLocalTSF - Local TSF |
285 | * Out: | |
286 | * none | |
287 | * | |
288 | * Return Value: none | |
5449c685 | 289 | */ |
41196b0b | 290 | bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate, |
89abfc0a | 291 | u64 bss_timestamp) |
5449c685 | 292 | { |
032ed34a | 293 | u64 local_tsf; |
efafcb55 | 294 | u64 tsf_offset = 0; |
d4945f09 | 295 | |
60a16985 | 296 | local_tsf = vt6655_get_current_tsf(priv); |
032ed34a | 297 | |
89abfc0a | 298 | if (bss_timestamp != local_tsf) { |
314b805e | 299 | tsf_offset = card_get_tsf_offset(rx_rate, bss_timestamp, |
032ed34a | 300 | local_tsf); |
77b6a6a3 | 301 | /* adjust TSF, HW's TSF add TSF Offset reg */ |
efafcb55 PB |
302 | tsf_offset = le64_to_cpu(tsf_offset); |
303 | iowrite32((u32)tsf_offset, priv->port_offset + MAC_REG_TSFOFST); | |
304 | iowrite32((u32)(tsf_offset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4); | |
67ec5576 | 305 | vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN); |
d4945f09 | 306 | } |
a4ef27ad | 307 | return true; |
5449c685 FB |
308 | } |
309 | ||
5449c685 FB |
310 | /* |
311 | * Description: Set NIC TSF counter for first Beacon time | |
312 | * Get NEXTTBTT from adjusted TSF and Beacon Interval | |
313 | * | |
314 | * Parameters: | |
315 | * In: | |
91961244 | 316 | * priv - The adapter to be set. |
272b281a | 317 | * beacon_interval - Beacon Interval |
5449c685 FB |
318 | * Out: |
319 | * none | |
320 | * | |
5a5a2a6a | 321 | * Return Value: true if succeed; otherwise false |
5449c685 | 322 | */ |
b6f0032e | 323 | bool card_set_beacon_period(struct vnt_private *priv, |
272b281a | 324 | unsigned short beacon_interval) |
5449c685 | 325 | { |
4ef985fa | 326 | u64 next_tbtt; |
d4945f09 | 327 | |
4ef985fa | 328 | next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ |
4a5f7184 | 329 | |
862aa279 | 330 | next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval); |
d4945f09 | 331 | |
77b6a6a3 | 332 | /* set HW beacon interval */ |
272b281a PB |
333 | iowrite16(beacon_interval, priv->port_offset + MAC_REG_BI); |
334 | priv->beacon_interval = beacon_interval; | |
77b6a6a3 | 335 | /* Set NextTBTT */ |
4ef985fa PB |
336 | next_tbtt = le64_to_cpu(next_tbtt); |
337 | iowrite32((u32)next_tbtt, priv->port_offset + MAC_REG_NEXTTBTT); | |
338 | iowrite32((u32)(next_tbtt >> 32), priv->port_offset + MAC_REG_NEXTTBTT + 4); | |
67ec5576 | 339 | vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); |
d4945f09 | 340 | |
a4ef27ad | 341 | return true; |
5449c685 FB |
342 | } |
343 | ||
5449c685 FB |
344 | /* |
345 | * Description: Turn off Radio power | |
346 | * | |
347 | * Parameters: | |
348 | * In: | |
91961244 | 349 | * priv - The adapter to be turned off |
5449c685 FB |
350 | * Out: |
351 | * none | |
352 | * | |
5449c685 | 353 | */ |
ac491ce1 | 354 | void card_radio_power_off(struct vnt_private *priv) |
5449c685 | 355 | { |
fca00dc4 | 356 | if (priv->radio_off) |
d7255ba4 | 357 | return; |
5449c685 | 358 | |
eb507641 | 359 | switch (priv->rf_type) { |
d4945f09 | 360 | case RF_RFMD2959: |
28d4e692 PH |
361 | vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, |
362 | SOFTPWRCTL_TXPEINV); | |
ee67fe63 PH |
363 | vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_SOFTPWRCTL, |
364 | SOFTPWRCTL_SWPE1); | |
d4945f09 | 365 | break; |
5449c685 | 366 | |
d4945f09 JP |
367 | case RF_AIROHA: |
368 | case RF_AL2230S: | |
28d4e692 PH |
369 | vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, |
370 | SOFTPWRCTL_SWPE2); | |
371 | vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, | |
372 | SOFTPWRCTL_SWPE3); | |
d4945f09 | 373 | break; |
d4945f09 | 374 | } |
5449c685 | 375 | |
5327d71d | 376 | vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON); |
5449c685 | 377 | |
e9c1caea | 378 | bb_set_deep_sleep(priv, priv->local_id); |
5449c685 | 379 | |
fca00dc4 | 380 | priv->radio_off = true; |
941ead9a | 381 | pr_debug("chester power off\n"); |
67ec5576 | 382 | vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */ |
5449c685 FB |
383 | } |
384 | ||
157327d0 | 385 | void card_safe_reset_tx(struct vnt_private *priv) |
5449c685 | 386 | { |
d4945f09 | 387 | unsigned int uu; |
e2357271 | 388 | struct vnt_tx_desc *pCurrTD; |
d4945f09 | 389 | |
77b6a6a3 | 390 | /* initialize TD index */ |
6c9769cf SM |
391 | priv->apTailTD[0] = &priv->apTD0Rings[0]; |
392 | priv->apCurrTD[0] = &priv->apTD0Rings[0]; | |
ffbad99a | 393 | |
6c9769cf SM |
394 | priv->apTailTD[1] = &priv->apTD1Rings[0]; |
395 | priv->apCurrTD[1] = &priv->apTD1Rings[0]; | |
d4945f09 JP |
396 | |
397 | for (uu = 0; uu < TYPE_MAXTD; uu++) | |
91961244 | 398 | priv->iTDUsed[uu] = 0; |
d4945f09 | 399 | |
91961244 | 400 | for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) { |
6c9769cf | 401 | pCurrTD = &priv->apTD0Rings[uu]; |
5235ff6a | 402 | pCurrTD->td0.owner = OWNED_BY_HOST; |
77b6a6a3 | 403 | /* init all Tx Packet pointer to NULL */ |
d4945f09 | 404 | } |
91961244 | 405 | for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) { |
6c9769cf | 406 | pCurrTD = &priv->apTD1Rings[uu]; |
5235ff6a | 407 | pCurrTD->td0.owner = OWNED_BY_HOST; |
77b6a6a3 | 408 | /* init all Tx Packet pointer to NULL */ |
d4945f09 JP |
409 | } |
410 | ||
77b6a6a3 | 411 | /* set MAC TD pointer */ |
8bd2a9f1 | 412 | vt6655_mac_set_curr_tx_desc_addr(TYPE_TXDMA0, priv, priv->td0_pool_dma); |
d4945f09 | 413 | |
8bd2a9f1 | 414 | vt6655_mac_set_curr_tx_desc_addr(TYPE_AC0DMA, priv, priv->td1_pool_dma); |
d4945f09 | 415 | |
77b6a6a3 | 416 | /* set MAC Beacon TX pointer */ |
a18263eb | 417 | iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR); |
5449c685 FB |
418 | } |
419 | ||
77b6a6a3 | 420 | /* |
5449c685 FB |
421 | * Description: |
422 | * Reset Rx | |
423 | * | |
424 | * Parameters: | |
425 | * In: | |
91961244 | 426 | * priv - Pointer to the adapter |
5449c685 FB |
427 | * Out: |
428 | * none | |
429 | * | |
430 | * Return Value: none | |
77b6a6a3 | 431 | */ |
009bdc15 | 432 | void CARDvSafeResetRx(struct vnt_private *priv) |
5449c685 | 433 | { |
d4945f09 | 434 | unsigned int uu; |
9cb693f6 | 435 | struct vnt_rx_desc *pDesc; |
d4945f09 | 436 | |
77b6a6a3 | 437 | /* initialize RD index */ |
6c9769cf SM |
438 | priv->pCurrRD[0] = &priv->aRD0Ring[0]; |
439 | priv->pCurrRD[1] = &priv->aRD1Ring[0]; | |
d4945f09 | 440 | |
77b6a6a3 | 441 | /* init state, all RD is chip's */ |
91961244 | 442 | for (uu = 0; uu < priv->opts.rx_descs0; uu++) { |
6c9769cf | 443 | pDesc = &priv->aRD0Ring[uu]; |
91961244 | 444 | pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); |
de1c1862 | 445 | pDesc->rd0.owner = OWNED_BY_NIC; |
91961244 | 446 | pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); |
d4945f09 JP |
447 | } |
448 | ||
77b6a6a3 | 449 | /* init state, all RD is chip's */ |
91961244 | 450 | for (uu = 0; uu < priv->opts.rx_descs1; uu++) { |
6c9769cf | 451 | pDesc = &priv->aRD1Ring[uu]; |
91961244 | 452 | pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); |
de1c1862 | 453 | pDesc->rd0.owner = OWNED_BY_NIC; |
91961244 | 454 | pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); |
d4945f09 JP |
455 | } |
456 | ||
77b6a6a3 | 457 | /* set perPkt mode */ |
a18263eb PH |
458 | iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL0); |
459 | iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL1); | |
77b6a6a3 | 460 | /* set MAC RD pointer */ |
253fa9b5 | 461 | vt6655_mac_set_curr_rx_0_desc_addr(priv, priv->rd0_pool_dma); |
d4945f09 | 462 | |
b5e0bd41 | 463 | vt6655_mac_set_curr_rx_1_desc_addr(priv, priv->rd1_pool_dma); |
5449c685 FB |
464 | } |
465 | ||
5449c685 FB |
466 | /* |
467 | * Description: Get response Control frame rate in CCK mode | |
468 | * | |
469 | * Parameters: | |
470 | * In: | |
91961244 | 471 | * priv - The adapter to be set |
5449c685 FB |
472 | * wRateIdx - Receiving data rate |
473 | * Out: | |
474 | * none | |
475 | * | |
476 | * Return Value: response Control frame rate | |
5449c685 | 477 | */ |
91961244 | 478 | static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, |
d052270b | 479 | unsigned short wRateIdx) |
5449c685 | 480 | { |
58d44745 | 481 | unsigned int ui = (unsigned int)wRateIdx; |
d4945f09 JP |
482 | |
483 | while (ui > RATE_1M) { | |
91961244 | 484 | if (priv->basic_rates & ((u32)0x1 << ui)) |
d4945f09 | 485 | return (unsigned short)ui; |
bc5cf656 | 486 | |
d4945f09 JP |
487 | ui--; |
488 | } | |
489 | return (unsigned short)RATE_1M; | |
5449c685 FB |
490 | } |
491 | ||
492 | /* | |
493 | * Description: Get response Control frame rate in OFDM mode | |
494 | * | |
495 | * Parameters: | |
496 | * In: | |
91961244 | 497 | * priv - The adapter to be set |
5449c685 FB |
498 | * wRateIdx - Receiving data rate |
499 | * Out: | |
500 | * none | |
501 | * | |
502 | * Return Value: response Control frame rate | |
5449c685 | 503 | */ |
91961244 | 504 | static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv, |
d052270b | 505 | unsigned short wRateIdx) |
5449c685 | 506 | { |
58d44745 | 507 | unsigned int ui = (unsigned int)wRateIdx; |
d4945f09 | 508 | |
91961244 | 509 | pr_debug("BASIC RATE: %X\n", priv->basic_rates); |
d4945f09 | 510 | |
91961244 | 511 | if (!CARDbIsOFDMinBasicRate((void *)priv)) { |
6f675264 | 512 | pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx); |
d4945f09 JP |
513 | if (wRateIdx > RATE_24M) |
514 | wRateIdx = RATE_24M; | |
515 | return wRateIdx; | |
516 | } | |
517 | while (ui > RATE_11M) { | |
91961244 | 518 | if (priv->basic_rates & ((u32)0x1 << ui)) { |
6f675264 | 519 | pr_debug("%s : %d\n", __func__, ui); |
d4945f09 JP |
520 | return (unsigned short)ui; |
521 | } | |
522 | ui--; | |
523 | } | |
6f675264 | 524 | pr_debug("%s: 6M\n", __func__); |
d4945f09 | 525 | return (unsigned short)RATE_24M; |
5449c685 FB |
526 | } |
527 | ||
5449c685 FB |
528 | /* |
529 | * Description: Set RSPINF | |
530 | * | |
531 | * Parameters: | |
532 | * In: | |
91961244 | 533 | * priv - The adapter to be set |
5449c685 FB |
534 | * Out: |
535 | * none | |
536 | * | |
537 | * Return Value: None. | |
5449c685 | 538 | */ |
c97dbf1d | 539 | void card_set_rspinf(struct vnt_private *priv, u8 bb_type) |
5449c685 | 540 | { |
864a5a37 | 541 | union vnt_phy_field_swap phy; |
77b6a6a3 | 542 | unsigned char byTxRate, byRsvTime; /* For OFDM */ |
95775d12 MP |
543 | unsigned long flags; |
544 | ||
91961244 | 545 | spin_lock_irqsave(&priv->lock, flags); |
d4945f09 | 546 | |
77b6a6a3 | 547 | /* Set to Page1 */ |
8809cc88 | 548 | VT6655_MAC_SELECT_PAGE1(priv->port_offset); |
d4945f09 | 549 | |
864a5a37 | 550 | /* RSPINF_b_1 */ |
91961244 MP |
551 | vnt_get_phy_field(priv, 14, |
552 | CARDwGetCCKControlRate(priv, RATE_1M), | |
864a5a37 | 553 | PK_TYPE_11B, &phy.field_read); |
d4945f09 | 554 | |
864a5a37 MP |
555 | /* swap over to get correct write order */ |
556 | swap(phy.swap[0], phy.swap[1]); | |
d4945f09 | 557 | |
a18263eb | 558 | iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_1); |
d4945f09 | 559 | |
864a5a37 | 560 | /* RSPINF_b_2 */ |
91961244 MP |
561 | vnt_get_phy_field(priv, 14, |
562 | CARDwGetCCKControlRate(priv, RATE_2M), | |
864a5a37 MP |
563 | PK_TYPE_11B, &phy.field_read); |
564 | ||
565 | swap(phy.swap[0], phy.swap[1]); | |
566 | ||
a18263eb | 567 | iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_2); |
864a5a37 MP |
568 | |
569 | /* RSPINF_b_5 */ | |
91961244 MP |
570 | vnt_get_phy_field(priv, 14, |
571 | CARDwGetCCKControlRate(priv, RATE_5M), | |
864a5a37 MP |
572 | PK_TYPE_11B, &phy.field_read); |
573 | ||
574 | swap(phy.swap[0], phy.swap[1]); | |
575 | ||
a18263eb | 576 | iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_5); |
864a5a37 MP |
577 | |
578 | /* RSPINF_b_11 */ | |
91961244 MP |
579 | vnt_get_phy_field(priv, 14, |
580 | CARDwGetCCKControlRate(priv, RATE_11M), | |
864a5a37 MP |
581 | PK_TYPE_11B, &phy.field_read); |
582 | ||
583 | swap(phy.swap[0], phy.swap[1]); | |
584 | ||
a18263eb | 585 | iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_11); |
d4945f09 | 586 | |
77b6a6a3 | 587 | /* RSPINF_a_6 */ |
8b46d9ff | 588 | calculate_ofdmr_parameter(RATE_6M, |
6e1d14a5 | 589 | bb_type, |
d4945f09 JP |
590 | &byTxRate, |
591 | &byRsvTime); | |
33028eea | 592 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_6); |
77b6a6a3 | 593 | /* RSPINF_a_9 */ |
8b46d9ff | 594 | calculate_ofdmr_parameter(RATE_9M, |
6e1d14a5 | 595 | bb_type, |
d4945f09 JP |
596 | &byTxRate, |
597 | &byRsvTime); | |
33028eea | 598 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_9); |
77b6a6a3 | 599 | /* RSPINF_a_12 */ |
8b46d9ff | 600 | calculate_ofdmr_parameter(RATE_12M, |
6e1d14a5 | 601 | bb_type, |
d4945f09 JP |
602 | &byTxRate, |
603 | &byRsvTime); | |
33028eea | 604 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_12); |
77b6a6a3 | 605 | /* RSPINF_a_18 */ |
8b46d9ff | 606 | calculate_ofdmr_parameter(RATE_18M, |
6e1d14a5 | 607 | bb_type, |
d4945f09 JP |
608 | &byTxRate, |
609 | &byRsvTime); | |
33028eea | 610 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_18); |
77b6a6a3 | 611 | /* RSPINF_a_24 */ |
8b46d9ff | 612 | calculate_ofdmr_parameter(RATE_24M, |
6e1d14a5 | 613 | bb_type, |
d4945f09 JP |
614 | &byTxRate, |
615 | &byRsvTime); | |
33028eea | 616 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_24); |
77b6a6a3 | 617 | /* RSPINF_a_36 */ |
8b46d9ff | 618 | calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, |
5150d01e | 619 | RATE_36M), |
6e1d14a5 | 620 | bb_type, |
d4945f09 JP |
621 | &byTxRate, |
622 | &byRsvTime); | |
33028eea | 623 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_36); |
77b6a6a3 | 624 | /* RSPINF_a_48 */ |
8b46d9ff | 625 | calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, |
5150d01e | 626 | RATE_48M), |
6e1d14a5 | 627 | bb_type, |
d4945f09 JP |
628 | &byTxRate, |
629 | &byRsvTime); | |
33028eea | 630 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_48); |
77b6a6a3 | 631 | /* RSPINF_a_54 */ |
8b46d9ff | 632 | calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, |
5150d01e | 633 | RATE_54M), |
6e1d14a5 | 634 | bb_type, |
d4945f09 JP |
635 | &byTxRate, |
636 | &byRsvTime); | |
33028eea | 637 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_54); |
77b6a6a3 | 638 | /* RSPINF_a_72 */ |
8b46d9ff | 639 | calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, |
5150d01e | 640 | RATE_54M), |
6e1d14a5 | 641 | bb_type, |
d4945f09 JP |
642 | &byTxRate, |
643 | &byRsvTime); | |
33028eea | 644 | iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_72); |
77b6a6a3 | 645 | /* Set to Page0 */ |
54765727 | 646 | VT6655_MAC_SELECT_PAGE0(priv->port_offset); |
95775d12 | 647 | |
91961244 | 648 | spin_unlock_irqrestore(&priv->lock, flags); |
5449c685 FB |
649 | } |
650 | ||
91961244 | 651 | void CARDvUpdateBasicTopRate(struct vnt_private *priv) |
5449c685 | 652 | { |
d4945f09 JP |
653 | unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M; |
654 | unsigned char ii; | |
655 | ||
77b6a6a3 | 656 | /* Determines the highest basic rate. */ |
d4945f09 | 657 | for (ii = RATE_54M; ii >= RATE_6M; ii--) { |
91961244 | 658 | if ((priv->basic_rates) & ((u32)(1 << ii))) { |
d4945f09 JP |
659 | byTopOFDM = ii; |
660 | break; | |
661 | } | |
662 | } | |
91961244 | 663 | priv->byTopOFDMBasicRate = byTopOFDM; |
d4945f09 JP |
664 | |
665 | for (ii = RATE_11M;; ii--) { | |
91961244 | 666 | if ((priv->basic_rates) & ((u32)(1 << ii))) { |
d4945f09 JP |
667 | byTopCCK = ii; |
668 | break; | |
669 | } | |
670 | if (ii == RATE_1M) | |
671 | break; | |
672 | } | |
91961244 | 673 | priv->byTopCCKBasicRate = byTopCCK; |
5449c685 FB |
674 | } |
675 | ||
91961244 | 676 | bool CARDbIsOFDMinBasicRate(struct vnt_private *priv) |
5449c685 | 677 | { |
d4945f09 JP |
678 | int ii; |
679 | ||
680 | for (ii = RATE_54M; ii >= RATE_6M; ii--) { | |
91961244 | 681 | if ((priv->basic_rates) & ((u32)BIT(ii))) |
d4945f09 JP |
682 | return true; |
683 | } | |
684 | return false; | |
5449c685 FB |
685 | } |
686 | ||
1904b721 | 687 | unsigned char card_get_pkt_type(struct vnt_private *priv) |
5449c685 | 688 | { |
91961244 MP |
689 | if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B) |
690 | return (unsigned char)priv->byBBType; | |
691 | else if (CARDbIsOFDMinBasicRate((void *)priv)) | |
d4945f09 | 692 | return PK_TYPE_11GA; |
bc5cf656 | 693 | else |
d4945f09 | 694 | return PK_TYPE_11GB; |
5449c685 FB |
695 | } |
696 | ||
5449c685 | 697 | /* |
7664ec86 | 698 | * Description: Calculate TSF offset of two TSF input |
5449c685 FB |
699 | * Get TSF Offset from RxBCN's TSF and local TSF |
700 | * | |
701 | * Parameters: | |
702 | * In: | |
91961244 | 703 | * priv - The adapter to be sync. |
5449c685 FB |
704 | * qwTSF1 - Rx BCN's TSF |
705 | * qwTSF2 - Local TSF | |
706 | * Out: | |
707 | * none | |
708 | * | |
709 | * Return Value: TSF Offset value | |
5449c685 | 710 | */ |
314b805e | 711 | u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2) |
5449c685 | 712 | { |
5309c5b8 | 713 | unsigned short wRxBcnTSFOffst; |
d4945f09 | 714 | |
41196b0b | 715 | wRxBcnTSFOffst = rx_bcn_tsf_off[rx_rate % MAX_RATE]; |
0fc2a76e MP |
716 | |
717 | qwTSF2 += (u64)wRxBcnTSFOffst; | |
718 | ||
57ce4df9 | 719 | return qwTSF1 - qwTSF2; |
5449c685 FB |
720 | } |
721 | ||
5449c685 FB |
722 | /* |
723 | * Description: Read NIC TSF counter | |
724 | * Get local TSF counter | |
725 | * | |
726 | * Parameters: | |
727 | * In: | |
91961244 | 728 | * priv - The adapter to be read |
5449c685 | 729 | * Out: |
a0daad77 | 730 | * none |
5449c685 | 731 | * |
a0daad77 | 732 | * Return Value: Current TSF counter |
5449c685 | 733 | */ |
60a16985 | 734 | u64 vt6655_get_current_tsf(struct vnt_private *priv) |
5449c685 | 735 | { |
1977dcf0 | 736 | void __iomem *iobase = priv->port_offset; |
d4945f09 | 737 | unsigned short ww; |
eb3bdf59 | 738 | unsigned char data; |
79ffde57 | 739 | u32 low, high; |
d4945f09 | 740 | |
67ec5576 | 741 | vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); |
d4945f09 | 742 | for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { |
08bea7da | 743 | data = ioread8(iobase + MAC_REG_TFTCTL); |
eb3bdf59 | 744 | if (!(data & TFTCTL_TSFCNTRRD)) |
d4945f09 JP |
745 | break; |
746 | } | |
747 | if (ww == W_MAX_TIMEOUT) | |
60a16985 | 748 | return 0; |
79ffde57 PH |
749 | low = ioread32(iobase + MAC_REG_TSFCNTR); |
750 | high = ioread32(iobase + MAC_REG_TSFCNTR + 4); | |
60a16985 | 751 | return le64_to_cpu(low + ((u64)high << 32)); |
5449c685 FB |
752 | } |
753 | ||
5449c685 FB |
754 | /* |
755 | * Description: Read NIC TSF counter | |
756 | * Get NEXTTBTT from adjusted TSF and Beacon Interval | |
757 | * | |
758 | * Parameters: | |
759 | * In: | |
760 | * qwTSF - Current TSF counter | |
761 | * wbeaconInterval - Beacon Interval | |
762 | * Out: | |
763 | * qwCurrTSF - Current TSF counter | |
764 | * | |
765 | * Return Value: TSF value of next Beacon | |
5449c685 | 766 | */ |
862aa279 | 767 | u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval) |
5449c685 | 768 | { |
989ae860 | 769 | u32 beacon_int; |
5449c685 | 770 | |
272b281a | 771 | beacon_int = beacon_interval * 1024; |
989ae860 MP |
772 | if (beacon_int) { |
773 | do_div(qwTSF, beacon_int); | |
774 | qwTSF += 1; | |
775 | qwTSF *= beacon_int; | |
776 | } | |
5449c685 | 777 | |
a4ef27ad | 778 | return qwTSF; |
5449c685 FB |
779 | } |
780 | ||
5449c685 FB |
781 | /* |
782 | * Description: Set NIC TSF counter for first Beacon time | |
783 | * Get NEXTTBTT from adjusted TSF and Beacon Interval | |
784 | * | |
785 | * Parameters: | |
786 | * In: | |
26f64a6b | 787 | * iobase - IO Base |
272b281a | 788 | * beacon_interval - Beacon Interval |
5449c685 FB |
789 | * Out: |
790 | * none | |
791 | * | |
792 | * Return Value: none | |
5449c685 | 793 | */ |
5150d01e | 794 | void CARDvSetFirstNextTBTT(struct vnt_private *priv, |
272b281a | 795 | unsigned short beacon_interval) |
5449c685 | 796 | { |
1977dcf0 | 797 | void __iomem *iobase = priv->port_offset; |
4ef985fa | 798 | u64 next_tbtt; |
d4945f09 | 799 | |
4ef985fa | 800 | next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ |
0fc2a76e | 801 | |
862aa279 | 802 | next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval); |
77b6a6a3 | 803 | /* Set NextTBTT */ |
4ef985fa PB |
804 | next_tbtt = le64_to_cpu(next_tbtt); |
805 | iowrite32((u32)next_tbtt, iobase + MAC_REG_NEXTTBTT); | |
806 | iowrite32((u32)(next_tbtt >> 32), iobase + MAC_REG_NEXTTBTT + 4); | |
67ec5576 | 807 | vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); |
5449c685 FB |
808 | } |
809 | ||
5449c685 FB |
810 | /* |
811 | * Description: Sync NIC TSF counter for Beacon time | |
812 | * Get NEXTTBTT and write to HW | |
813 | * | |
814 | * Parameters: | |
815 | * In: | |
91961244 | 816 | * priv - The adapter to be set |
5449c685 | 817 | * qwTSF - Current TSF counter |
272b281a | 818 | * beacon_interval - Beacon Interval |
5449c685 FB |
819 | * Out: |
820 | * none | |
821 | * | |
822 | * Return Value: none | |
5449c685 | 823 | */ |
5150d01e | 824 | void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, |
272b281a | 825 | unsigned short beacon_interval) |
5449c685 | 826 | { |
1977dcf0 | 827 | void __iomem *iobase = priv->port_offset; |
738487ff | 828 | |
862aa279 | 829 | qwTSF = card_get_next_tbtt(qwTSF, beacon_interval); |
77b6a6a3 | 830 | /* Set NextTBTT */ |
6f58936e | 831 | qwTSF = le64_to_cpu(qwTSF); |
a18263eb PH |
832 | iowrite32((u32)qwTSF, iobase + MAC_REG_NEXTTBTT); |
833 | iowrite32((u32)(qwTSF >> 32), iobase + MAC_REG_NEXTTBTT + 4); | |
67ec5576 | 834 | vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); |
48caf5a0 | 835 | pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF); |
5449c685 | 836 | } |