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