1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 4 * All rights reserved. 5 * 6 * File: card.c 7 * Purpose: Provide functions to setup NIC operation mode 8 * Functions: 9 * vnt_set_rspinf - Set RSPINF 10 * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS 11 * vnt_update_top_rates - Update BasicTopRate 12 * vnt_add_basic_rate - Add to BasicRateSet 13 * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet 14 * vnt_get_tsf_offset - Calculate TSFOffset 15 * vnt_get_current_tsf - Read Current NIC TSF counter 16 * vnt_get_next_tbtt - Calculate Next Beacon TSF counter 17 * vnt_reset_next_tbtt - Set NIC Beacon time 18 * vnt_update_next_tbtt - Sync. NIC Beacon time 19 * vnt_radio_power_off - Turn Off NIC Radio Power 20 * vnt_radio_power_on - Turn On NIC Radio Power 21 * 22 * Revision History: 23 * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. 24 * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. 25 * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs(). 26 * 27 */ 28 29 #include <linux/bitops.h> 30 #include <linux/errno.h> 31 #include "device.h" 32 #include "card.h" 33 #include "baseband.h" 34 #include "mac.h" 35 #include "desc.h" 36 #include "rf.h" 37 #include "power.h" 38 #include "key.h" 39 #include "usbpipe.h" 40 41 /* const u16 cw_rxbcntsf_off[MAX_RATE] = 42 * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; 43 */ 44 45 static const u16 cw_rxbcntsf_off[MAX_RATE] = { 46 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 47 }; 48 49 int vnt_set_channel(struct vnt_private *priv, u32 connection_channel) 50 { 51 int ret; 52 53 if (connection_channel > CB_MAX_CHANNEL || !connection_channel) 54 return -EINVAL; 55 56 /* clear NAV */ 57 vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV); 58 59 /* Set Channel[7] = 0 to tell H/W channel is changing now. */ 60 vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 61 (BIT(7) | BIT(5) | BIT(4))); 62 63 ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, 64 connection_channel, 0, 0, NULL); 65 if (ret) 66 return ret; 67 68 return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, 69 (u8)(connection_channel | 0x80)); 70 } 71 72 static const u8 vnt_rspinf_b_short_table[] = { 73 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00, 74 0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80 75 }; 76 77 static const u8 vnt_rspinf_b_long_table[] = { 78 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, 79 0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80 80 }; 81 82 static const u8 vnt_rspinf_a_table[] = { 83 0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99, 84 0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04 85 }; 86 87 static const u8 vnt_rspinf_gb_table[] = { 88 0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89, 89 0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a 90 }; 91 92 int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) 93 { 94 const u8 *data; 95 u16 len; 96 int ret; 97 98 if (priv->preamble_type) { 99 data = vnt_rspinf_b_short_table; 100 len = ARRAY_SIZE(vnt_rspinf_b_short_table); 101 } else { 102 data = vnt_rspinf_b_long_table; 103 len = ARRAY_SIZE(vnt_rspinf_b_long_table); 104 } 105 106 /* RSPINF_b_1 to RSPINF_b_11 */ 107 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, 108 MESSAGE_REQUEST_MACREG, len, data); 109 if (ret) 110 return ret; 111 112 if (bb_type == BB_TYPE_11A) { 113 data = vnt_rspinf_a_table; 114 len = ARRAY_SIZE(vnt_rspinf_a_table); 115 } else { 116 data = vnt_rspinf_gb_table; 117 len = ARRAY_SIZE(vnt_rspinf_gb_table); 118 } 119 120 /* RSPINF_a_6 to RSPINF_a_72 */ 121 return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6, 122 MESSAGE_REQUEST_MACREG, len, data); 123 } 124 125 int vnt_update_ifs(struct vnt_private *priv) 126 { 127 u8 max_min = 0; 128 u8 data[4]; 129 int ret; 130 131 if (priv->packet_type == PK_TYPE_11A) { 132 priv->slot = C_SLOT_SHORT; 133 priv->sifs = C_SIFS_A; 134 priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT; 135 max_min = 4; 136 } else { 137 priv->sifs = C_SIFS_BG; 138 139 if (priv->short_slot_time) { 140 priv->slot = C_SLOT_SHORT; 141 max_min = 4; 142 } else { 143 priv->slot = C_SLOT_LONG; 144 max_min = 5; 145 } 146 147 priv->difs = C_SIFS_BG + 2 * priv->slot; 148 } 149 150 priv->eifs = C_EIFS; 151 152 data[0] = (u8)priv->sifs; 153 data[1] = (u8)priv->difs; 154 data[2] = (u8)priv->eifs; 155 data[3] = (u8)priv->slot; 156 157 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, 158 MESSAGE_REQUEST_MACREG, 4, &data[0]); 159 if (ret) 160 return ret; 161 162 max_min |= 0xa0; 163 164 return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, 165 MESSAGE_REQUEST_MACREG, 1, &max_min); 166 } 167 168 void vnt_update_top_rates(struct vnt_private *priv) 169 { 170 int pos; 171 172 pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M)); 173 priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M; 174 175 pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M)); 176 priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M; 177 } 178 179 bool vnt_ofdm_min_rate(struct vnt_private *priv) 180 { 181 return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false; 182 } 183 184 u8 vnt_get_pkt_type(struct vnt_private *priv) 185 { 186 if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) 187 return (u8)priv->bb_type; 188 else if (vnt_ofdm_min_rate(priv)) 189 return PK_TYPE_11GA; 190 return PK_TYPE_11GB; 191 } 192 193 /* 194 * Description: Calculate TSF offset of two TSF input 195 * Get TSF Offset from RxBCN's TSF and local TSF 196 * 197 * Parameters: 198 * In: 199 * rx_rate - rx rate. 200 * tsf1 - Rx BCN's TSF 201 * tsf2 - Local TSF 202 * Out: 203 * none 204 * 205 * Return Value: TSF Offset value 206 * 207 */ 208 u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) 209 { 210 return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE]; 211 } 212 213 int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, 214 u64 time_stamp, u64 local_tsf) 215 { 216 u64 tsf_offset = 0; 217 u8 data[8]; 218 219 tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf); 220 221 data[0] = (u8)tsf_offset; 222 data[1] = (u8)(tsf_offset >> 8); 223 data[2] = (u8)(tsf_offset >> 16); 224 data[3] = (u8)(tsf_offset >> 24); 225 data[4] = (u8)(tsf_offset >> 32); 226 data[5] = (u8)(tsf_offset >> 40); 227 data[6] = (u8)(tsf_offset >> 48); 228 data[7] = (u8)(tsf_offset >> 56); 229 230 return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 231 MESSAGE_REQUEST_TSF, 0, 8, data); 232 } 233 234 /* 235 * Description: Read NIC TSF counter 236 * Get local TSF counter 237 * 238 * Parameters: 239 * In: 240 * priv - The adapter to be read 241 * Out: 242 * current_tsf - Current TSF counter 243 * 244 * Return Value: true if success; otherwise false 245 * 246 */ 247 bool vnt_get_current_tsf(struct vnt_private *priv, u64 *current_tsf) 248 { 249 *current_tsf = priv->current_tsf; 250 251 return true; 252 } 253 254 /* 255 * Description: Clear NIC TSF counter 256 * Clear local TSF counter 257 * 258 * Parameters: 259 * In: 260 * priv - The adapter to be read 261 * 262 * Return Value: true if success; otherwise false 263 * 264 */ 265 bool vnt_clear_current_tsf(struct vnt_private *priv) 266 { 267 vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); 268 269 priv->current_tsf = 0; 270 271 return true; 272 } 273 274 /* 275 * Description: Read NIC TSF counter 276 * Get NEXTTBTT from adjusted TSF and Beacon Interval 277 * 278 * Parameters: 279 * In: 280 * tsf - Current TSF counter 281 * beacon_interval - Beacon Interval 282 * Out: 283 * tsf - Current TSF counter 284 * 285 * Return Value: TSF value of next Beacon 286 * 287 */ 288 u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval) 289 { 290 u32 beacon_int; 291 292 beacon_int = beacon_interval * 1024; 293 294 /* Next TBTT = 295 * ((local_current_TSF / beacon_interval) + 1) * beacon_interval 296 */ 297 if (beacon_int) { 298 do_div(tsf, beacon_int); 299 tsf += 1; 300 tsf *= beacon_int; 301 } 302 303 return tsf; 304 } 305 306 int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) 307 { 308 u64 next_tbtt = 0; 309 u8 data[8]; 310 311 vnt_clear_current_tsf(priv); 312 313 next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval); 314 315 data[0] = (u8)next_tbtt; 316 data[1] = (u8)(next_tbtt >> 8); 317 data[2] = (u8)(next_tbtt >> 16); 318 data[3] = (u8)(next_tbtt >> 24); 319 data[4] = (u8)(next_tbtt >> 32); 320 data[5] = (u8)(next_tbtt >> 40); 321 data[6] = (u8)(next_tbtt >> 48); 322 data[7] = (u8)(next_tbtt >> 56); 323 324 return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 325 MESSAGE_REQUEST_TBTT, 0, 8, data); 326 } 327 328 int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, 329 u16 beacon_interval) 330 { 331 u8 data[8]; 332 int ret; 333 334 tsf = vnt_get_next_tbtt(tsf, beacon_interval); 335 336 data[0] = (u8)tsf; 337 data[1] = (u8)(tsf >> 8); 338 data[2] = (u8)(tsf >> 16); 339 data[3] = (u8)(tsf >> 24); 340 data[4] = (u8)(tsf >> 32); 341 data[5] = (u8)(tsf >> 40); 342 data[6] = (u8)(tsf >> 48); 343 data[7] = (u8)(tsf >> 56); 344 345 ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, 346 MESSAGE_REQUEST_TBTT, 0, 8, data); 347 if (ret) 348 return ret; 349 350 dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf); 351 return 0; 352 } 353 354 /* 355 * Description: Turn off Radio power 356 * 357 * Parameters: 358 * In: 359 * priv - The adapter to be turned off 360 * Out: 361 * none 362 * 363 * Return Value: true if success; otherwise false 364 * 365 */ 366 int vnt_radio_power_off(struct vnt_private *priv) 367 { 368 int ret = 0; 369 370 switch (priv->rf_type) { 371 case RF_AL2230: 372 case RF_AL2230S: 373 case RF_AIROHA7230: 374 case RF_VT3226: 375 case RF_VT3226D0: 376 case RF_VT3342A0: 377 ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, 378 (SOFTPWRCTL_SWPE2 | 379 SOFTPWRCTL_SWPE3)); 380 break; 381 } 382 383 if (ret) 384 goto end; 385 386 ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON); 387 if (ret) 388 goto end; 389 390 ret = vnt_set_deep_sleep(priv); 391 if (ret) 392 goto end; 393 394 ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); 395 396 end: 397 return ret; 398 } 399 400 /* 401 * Description: Turn on Radio power 402 * 403 * Parameters: 404 * In: 405 * priv - The adapter to be turned on 406 * Out: 407 * none 408 * 409 * Return Value: true if success; otherwise false 410 * 411 */ 412 int vnt_radio_power_on(struct vnt_private *priv) 413 { 414 int ret = 0; 415 416 ret = vnt_exit_deep_sleep(priv); 417 if (ret) 418 return ret; 419 420 ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON); 421 if (ret) 422 return ret; 423 424 switch (priv->rf_type) { 425 case RF_AL2230: 426 case RF_AL2230S: 427 case RF_AIROHA7230: 428 case RF_VT3226: 429 case RF_VT3226D0: 430 case RF_VT3342A0: 431 ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, 432 (SOFTPWRCTL_SWPE2 | 433 SOFTPWRCTL_SWPE3)); 434 if (ret) 435 return ret; 436 } 437 438 return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); 439 } 440 441 int vnt_set_bss_mode(struct vnt_private *priv) 442 { 443 int ret; 444 unsigned char type = priv->bb_type; 445 unsigned char data = 0; 446 unsigned char bb_vga_0 = 0x1c; 447 unsigned char bb_vga_2_3 = 0x00; 448 449 if (priv->rf_type == RF_AIROHA7230 && priv->bb_type == BB_TYPE_11A) 450 type = BB_TYPE_11G; 451 452 ret = vnt_mac_set_bb_type(priv, type); 453 if (ret) 454 return ret; 455 456 priv->packet_type = vnt_get_pkt_type(priv); 457 458 if (priv->bb_type == BB_TYPE_11A) { 459 data = 0x03; 460 bb_vga_0 = 0x20; 461 bb_vga_2_3 = 0x10; 462 } else if (priv->bb_type == BB_TYPE_11B) { 463 data = 0x02; 464 } else if (priv->bb_type == BB_TYPE_11G) { 465 data = 0x08; 466 } 467 468 if (data) { 469 ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 470 0x88, data); 471 if (ret) 472 return ret; 473 } 474 475 ret = vnt_update_ifs(priv); 476 if (ret) 477 return ret; 478 479 ret = vnt_set_rspinf(priv, priv->bb_type); 480 if (ret) 481 return ret; 482 483 if (priv->rf_type == RF_AIROHA7230) { 484 priv->bb_vga[0] = bb_vga_0; 485 486 ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 487 0xe7, priv->bb_vga[0]); 488 if (ret) 489 return ret; 490 } 491 492 priv->bb_vga[2] = bb_vga_2_3; 493 priv->bb_vga[3] = bb_vga_2_3; 494 495 return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); 496 } 497