cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

card.c (10812B)


      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}