diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/staging/vt6655 | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/staging/vt6655')
28 files changed, 10370 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig new file mode 100644 index 000000000..d1cd5de46 --- /dev/null +++ b/drivers/staging/vt6655/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +config VT6655 + tristate "VIA Technologies VT6655 support" + depends on PCI && MAC80211 && m + help + This is a vendor-written driver for VIA VT6655. diff --git a/drivers/staging/vt6655/Makefile b/drivers/staging/vt6655/Makefile new file mode 100644 index 000000000..e70357ec0 --- /dev/null +++ b/drivers/staging/vt6655/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +vt6655_stage-y += device_main.o \ + card.o \ + channel.o \ + mac.o \ + baseband.o \ + rxtx.o \ + dpc.o \ + power.o \ + srom.o \ + key.o \ + rf.o + +obj-$(CONFIG_VT6655) += vt6655_stage.o diff --git a/drivers/staging/vt6655/TODO b/drivers/staging/vt6655/TODO new file mode 100644 index 000000000..63607ef9c --- /dev/null +++ b/drivers/staging/vt6655/TODO @@ -0,0 +1,21 @@ +TODO: +- remove __cplusplus ifdefs -- done +- prepare for merge with vt6656 driver: + - rename DEVICE_PRT() to DBG_PRT() -- done + - share 80211*.h includes + - split rf.c + - remove dead code + - abstract VT3253 chipset specific code +- add common vt665x infrastructure +- kill ttype.h +- switch to use LIB80211 +- switch to use MAC80211 +- verify unsigned long usage for x86-64 arch +- reduce .data footprint +- use kernel coding style +- checkpatch.pl fixes +- sparse fixes +- integrate with drivers/net/wireless + +Please send any patches to Greg Kroah-Hartman <greg@kroah.com> +and Forest Bond <forest@alittletooquiet.net>. diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c new file mode 100644 index 000000000..6ce41983d --- /dev/null +++ b/drivers/staging/vt6655/baseband.c @@ -0,0 +1,2301 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Implement functions to access baseband + * + * Author: Kyle Hsu + * + * Date: Aug.22, 2002 + * + * Functions: + * bb_get_frame_time - Calculate data frame transmitting time + * bb_read_embedded - Embedded read baseband register via MAC + * bb_write_embedded - Embedded write baseband register via MAC + * bb_vt3253_init - VIA VT3253 baseband chip init code + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support. + * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and + * BBvCalculateParameter(). + * cancel the setting of MAC_REG_SOFTPWRCTL on + * BBbVT3253Init(). + * Add the comments. + * 09-01-2003 Bryan YC Fan: RF & BB tables updated. + * Modified BBvLoopbackOn & BBvLoopbackOff(). + * + * + */ + +#include "mac.h" +#include "baseband.h" +#include "srom.h" +#include "rf.h" + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +#define CB_VT3253_INIT_FOR_RFMD 446 +static const unsigned char by_vt3253_init_tab_rfmd[CB_VT3253_INIT_FOR_RFMD][2] = { + {0x00, 0x30}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x00}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x70}, + {0x09, 0x45}, + {0x0a, 0x2a}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x01}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x9d}, + {0x1c, 0x05}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0xa8}, + {0x2e, 0x1a}, + {0x2f, 0x0c}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x0d}, + {0x3e, 0x51}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x06}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x08}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x80}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x14}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x44}, + {0x61, 0x04}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x04}, + {0x67, 0xb7}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x0b}, + {0x81, 0x00}, + {0x82, 0x3c}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x08}, + {0x8b, 0xa6}, + {0x8c, 0x84}, + {0x8d, 0x47}, + {0x8e, 0xbb}, + {0x8f, 0x02}, + {0x90, 0x21}, + {0x91, 0x0c}, + {0x92, 0x04}, + {0x93, 0x22}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x04}, + {0xa8, 0x10}, + {0xa9, 0x00}, + {0xaa, 0x8f}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x80}, + {0xb0, 0x38}, + {0xb1, 0x00}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0xee}, + {0xb5, 0xff}, + {0xb6, 0x10}, + {0xb7, 0x00}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x00}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x10}, + {0xc2, 0x18}, + {0xc3, 0x20}, + {0xc4, 0x10}, + {0xc5, 0x00}, + {0xc6, 0x22}, + {0xc7, 0x14}, + {0xc8, 0x0f}, + {0xc9, 0x08}, + {0xca, 0xa4}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x20}, + {0xcf, 0x00}, + {0xd0, 0x00}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x33}, + {0xd6, 0x70}, + {0xd7, 0x01}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0x00}, + {0xe2, 0xcc}, + {0xe3, 0x04}, + {0xe4, 0x08}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x0e}, + {0xe8, 0x88}, + {0xe9, 0xd4}, + {0xea, 0x05}, + {0xeb, 0xf0}, + {0xec, 0x79}, + {0xed, 0x0f}, + {0xee, 0x04}, + {0xef, 0x04}, + {0xf0, 0x00}, + {0xf1, 0x00}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xF0, 0x00}, + {0xF1, 0xF8}, + {0xF0, 0x80}, + {0xF0, 0x00}, + {0xF1, 0xF4}, + {0xF0, 0x81}, + {0xF0, 0x01}, + {0xF1, 0xF0}, + {0xF0, 0x82}, + {0xF0, 0x02}, + {0xF1, 0xEC}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0xE8}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0xE4}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0xE0}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0xDC}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0xD8}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0xD4}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0xD0}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0xCC}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0xC8}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0xC4}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0xC0}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0xBC}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0xB8}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0xB4}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0xB0}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0xAC}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0xA8}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0xA4}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0xA0}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x9C}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x98}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x94}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x90}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x8C}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x88}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x84}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x80}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x7C}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x78}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x74}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x70}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x6C}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x68}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x64}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x60}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x5C}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x58}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x54}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x50}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x4C}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x48}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x44}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x40}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x3C}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x38}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x34}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x30}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x2C}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x28}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x24}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x20}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x1C}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x18}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x14}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x10}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x0C}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x08}, + {0xF0, 0x00}, + {0xF0, 0x3C}, + {0xF1, 0x04}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x00}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x00}, + {0xF0, 0xBF}, + {0xF0, 0x3F}, + {0xF1, 0x00}, + {0xF0, 0xC0}, + {0xF0, 0x00}, +}; + +#define CB_VT3253B0_INIT_FOR_RFMD 256 +static const unsigned char byVT3253B0_RFMD[CB_VT3253B0_INIT_FOR_RFMD][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x81}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x38}, + {0x09, 0x45}, + {0x0a, 0x2a}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8e}, + {0x1c, 0x06}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x34}, + {0x2e, 0x18}, + {0x2f, 0x0c}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0xf8}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x09}, + {0x3e, 0x0d}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x08}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x80}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x14}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0x39}, + {0x61, 0x83}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0xc0}, + {0x67, 0x49}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x89}, + {0x81, 0x00}, + {0x82, 0x0e}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0e}, + {0x8b, 0xa7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x23}, + {0x91, 0x0c}, + {0x92, 0x06}, + {0x93, 0x08}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0xcd}, + {0xa4, 0x07}, + {0xa5, 0x33}, + {0xa6, 0x18}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x28}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x38}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0x00}, + {0xb5, 0x00}, + {0xb6, 0x84}, + {0xb7, 0xfd}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x00}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x20}, + {0xc2, 0x18}, + {0xc3, 0x20}, + {0xc4, 0x10}, + {0xc5, 0x2c}, + {0xc6, 0x1e}, + {0xc7, 0x10}, + {0xc8, 0x12}, + {0xc9, 0x01}, + {0xca, 0x6f}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x00}, + {0xcf, 0x22}, + {0xd0, 0x00}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x33}, + {0xd6, 0x80}, + {0xd7, 0x21}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xB3}, + {0xe2, 0x00}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x18}, + {0xe8, 0x08}, + {0xe9, 0xd4}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x10}, + {0xee, 0x30}, + {0xef, 0x02}, + {0xf0, 0x00}, + {0xf1, 0x09}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + +#define CB_VT3253B0_AGC_FOR_RFMD2959 195 +/* For RFMD2959 */ +static +unsigned char byVT3253B0_AGC4_RFMD2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = { + {0xF0, 0x00}, + {0xF1, 0x3E}, + {0xF0, 0x80}, + {0xF0, 0x00}, + {0xF1, 0x3E}, + {0xF0, 0x81}, + {0xF0, 0x01}, + {0xF1, 0x3E}, + {0xF0, 0x82}, + {0xF0, 0x02}, + {0xF1, 0x3E}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0x3B}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0x39}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0x38}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0x37}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0x36}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0x35}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0x35}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0x34}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0x34}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0x33}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0x32}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0x31}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0x30}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0x2F}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0x2F}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0x2E}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0x2D}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0x2C}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0x2B}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x2B}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x2A}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x29}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x28}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x27}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x26}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x25}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x24}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x24}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x23}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x22}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x21}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x20}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x20}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x1F}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x1E}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x1D}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x1C}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x1B}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x1B}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x1A}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x1A}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x19}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x18}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x17}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x16}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x15}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x15}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x15}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x14}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x13}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x12}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x11}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x10}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x0F}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x0E}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x0D}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x0C}, + {0xF0, 0xBC}, + {0xF0, 0x3C}, + {0xF1, 0x0B}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x0B}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x0A}, + {0xF0, 0xBF}, + {0xF0, 0x3F}, + {0xF1, 0x09}, + {0xF0, 0x00}, +}; + +#define CB_VT3253B0_INIT_FOR_AIROHA2230 256 +/* For AIROHA */ +static +unsigned char byVT3253B0_AIROHA2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x80}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x70}, + {0x09, 0x41}, + {0x0a, 0x2A}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8f}, + {0x1c, 0x09}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x4a}, + {0x2e, 0x00}, + {0x2f, 0x0a}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x79}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x0b}, + {0x3e, 0x48}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x09}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x73}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x15}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0xe4}, + {0x61, 0x80}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x98}, + {0x67, 0x0a}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */ + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x8c}, + {0x81, 0x01}, + {0x82, 0x09}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0f}, + {0x8b, 0xb7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x22}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xeb}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x01}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x00}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x38}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0xff}, + {0xb5, 0x0f}, + {0xb6, 0xe4}, + {0xb7, 0xe2}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x01}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x18}, + {0xc1, 0x20}, + {0xc2, 0x07}, + {0xc3, 0x18}, + {0xc4, 0xff}, + {0xc5, 0x2c}, + {0xc6, 0x0c}, + {0xc7, 0x0a}, + {0xc8, 0x0e}, + {0xc9, 0x01}, + {0xca, 0x68}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x10}, + {0xce, 0x00}, + {0xcf, 0x25}, + {0xd0, 0x40}, + {0xd1, 0x12}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x10}, + {0xd5, 0x28}, + {0xd6, 0x80}, + {0xd7, 0x2A}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xB3}, + {0xe2, 0x00}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x1C}, + {0xe8, 0x00}, + {0xe9, 0xf4}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x20}, + {0xee, 0x30}, + {0xef, 0x01}, + {0xf0, 0x00}, + {0xf1, 0x3e}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + +#define CB_VT3253B0_INIT_FOR_UW2451 256 +/* For UW2451 */ +static unsigned char byVT3253B0_UW2451[CB_VT3253B0_INIT_FOR_UW2451][2] = { + {0x00, 0x31}, + {0x01, 0x00}, + {0x02, 0x00}, + {0x03, 0x00}, + {0x04, 0x00}, + {0x05, 0x81}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x38}, + {0x09, 0x45}, + {0x0a, 0x28}, + {0x0b, 0x76}, + {0x0c, 0x00}, + {0x0d, 0x00}, + {0x0e, 0x80}, + {0x0f, 0x00}, + {0x10, 0x00}, + {0x11, 0x00}, + {0x12, 0x00}, + {0x13, 0x00}, + {0x14, 0x00}, + {0x15, 0x00}, + {0x16, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1a, 0x00}, + {0x1b, 0x8f}, + {0x1c, 0x0f}, + {0x1d, 0x00}, + {0x1e, 0x00}, + {0x1f, 0x00}, + {0x20, 0x00}, + {0x21, 0x00}, + {0x22, 0x00}, + {0x23, 0x00}, + {0x24, 0x00}, + {0x25, 0x4a}, + {0x26, 0x00}, + {0x27, 0x00}, + {0x28, 0x00}, + {0x29, 0x00}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2c, 0x00}, + {0x2d, 0x18}, + {0x2e, 0x00}, + {0x2f, 0x0a}, + {0x30, 0x26}, + {0x31, 0x5b}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x34, 0x00}, + {0x35, 0x00}, + {0x36, 0xaa}, + {0x37, 0xaa}, + {0x38, 0xff}, + {0x39, 0xff}, + {0x3a, 0x00}, + {0x3b, 0x00}, + {0x3c, 0x00}, + {0x3d, 0x03}, + {0x3e, 0x1d}, + {0x3f, 0x04}, + {0x40, 0x00}, + {0x41, 0x08}, + {0x42, 0x00}, + {0x43, 0x08}, + {0x44, 0x08}, + {0x45, 0x14}, + {0x46, 0x05}, + {0x47, 0x09}, + {0x48, 0x00}, + {0x49, 0x00}, + {0x4a, 0x00}, + {0x4b, 0x00}, + {0x4c, 0x09}, + {0x4d, 0x90}, + {0x4e, 0x00}, + {0x4f, 0xc5}, + {0x50, 0x15}, + {0x51, 0x19}, + {0x52, 0x00}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x58, 0x00}, + {0x59, 0xb0}, + {0x5a, 0x00}, + {0x5b, 0x00}, + {0x5c, 0x00}, + {0x5d, 0x00}, + {0x5e, 0x00}, + {0x5f, 0x00}, + {0x60, 0xb3}, + {0x61, 0x81}, + {0x62, 0x00}, + {0x63, 0x00}, + {0x64, 0x00}, + {0x65, 0x00}, + {0x66, 0x57}, + {0x67, 0x6c}, + {0x68, 0x00}, + {0x69, 0x00}, + {0x6a, 0x00}, + {0x6b, 0x00}, + {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */ + {0x6d, 0x03}, + {0x6e, 0x01}, + {0x6f, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x00}, + {0x78, 0x00}, + {0x79, 0x00}, + {0x7a, 0x00}, + {0x7b, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7e, 0x00}, + {0x7f, 0x00}, + {0x80, 0x8c}, + {0x81, 0x00}, + {0x82, 0x0e}, + {0x83, 0x00}, + {0x84, 0x00}, + {0x85, 0x00}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x08}, + {0x89, 0x00}, + {0x8a, 0x0e}, + {0x8b, 0xa7}, + {0x8c, 0x88}, + {0x8d, 0x47}, + {0x8e, 0xaa}, + {0x8f, 0x02}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0x00}, + {0x97, 0xe3}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x9a, 0x00}, + {0x9b, 0x00}, + {0x9c, 0x00}, + {0x9d, 0x00}, + {0x9e, 0x00}, + {0x9f, 0x00}, + {0xa0, 0x00}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x00}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0x10}, + {0xa7, 0x00}, + {0xa8, 0x18}, + {0xa9, 0x00}, + {0xaa, 0x00}, + {0xab, 0x00}, + {0xac, 0x00}, + {0xad, 0x00}, + {0xae, 0x00}, + {0xaf, 0x18}, + {0xb0, 0x18}, + {0xb1, 0x30}, + {0xb2, 0x00}, + {0xb3, 0x00}, + {0xb4, 0x00}, + {0xb5, 0x00}, + {0xb6, 0x00}, + {0xb7, 0x00}, + {0xb8, 0x00}, + {0xb9, 0x00}, + {0xba, 0x00}, + {0xbb, 0x03}, + {0xbc, 0x01}, + {0xbd, 0x00}, + {0xbe, 0x00}, + {0xbf, 0x00}, + {0xc0, 0x10}, + {0xc1, 0x20}, + {0xc2, 0x00}, + {0xc3, 0x20}, + {0xc4, 0x00}, + {0xc5, 0x2c}, + {0xc6, 0x1c}, + {0xc7, 0x10}, + {0xc8, 0x10}, + {0xc9, 0x01}, + {0xca, 0x68}, + {0xcb, 0xa7}, + {0xcc, 0x3c}, + {0xcd, 0x09}, + {0xce, 0x00}, + {0xcf, 0x20}, + {0xd0, 0x40}, + {0xd1, 0x10}, + {0xd2, 0x00}, + {0xd3, 0x00}, + {0xd4, 0x20}, + {0xd5, 0x28}, + {0xd6, 0xa0}, + {0xd7, 0x2a}, + {0xd8, 0x00}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xdb, 0x00}, + {0xdc, 0x00}, + {0xdd, 0x00}, + {0xde, 0x00}, + {0xdf, 0x00}, + {0xe0, 0x00}, + {0xe1, 0xd3}, + {0xe2, 0xc0}, + {0xe3, 0x00}, + {0xe4, 0x00}, + {0xe5, 0x10}, + {0xe6, 0x00}, + {0xe7, 0x12}, + {0xe8, 0x12}, + {0xe9, 0x34}, + {0xea, 0x00}, + {0xeb, 0xff}, + {0xec, 0x79}, + {0xed, 0x20}, + {0xee, 0x30}, + {0xef, 0x01}, + {0xf0, 0x00}, + {0xf1, 0x3e}, + {0xf2, 0x00}, + {0xf3, 0x00}, + {0xf4, 0x00}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf7, 0x00}, + {0xf8, 0x00}, + {0xf9, 0x00}, + {0xfa, 0x00}, + {0xfb, 0x00}, + {0xfc, 0x00}, + {0xfd, 0x00}, + {0xfe, 0x00}, + {0xff, 0x00}, +}; + +#define CB_VT3253B0_AGC 193 +/* For AIROHA */ +static unsigned char byVT3253B0_AGC[CB_VT3253B0_AGC][2] = { + {0xF0, 0x00}, + {0xF1, 0x00}, + {0xF0, 0x80}, + {0xF0, 0x01}, + {0xF1, 0x00}, + {0xF0, 0x81}, + {0xF0, 0x02}, + {0xF1, 0x02}, + {0xF0, 0x82}, + {0xF0, 0x03}, + {0xF1, 0x04}, + {0xF0, 0x83}, + {0xF0, 0x03}, + {0xF1, 0x04}, + {0xF0, 0x84}, + {0xF0, 0x04}, + {0xF1, 0x06}, + {0xF0, 0x85}, + {0xF0, 0x05}, + {0xF1, 0x06}, + {0xF0, 0x86}, + {0xF0, 0x06}, + {0xF1, 0x06}, + {0xF0, 0x87}, + {0xF0, 0x07}, + {0xF1, 0x08}, + {0xF0, 0x88}, + {0xF0, 0x08}, + {0xF1, 0x08}, + {0xF0, 0x89}, + {0xF0, 0x09}, + {0xF1, 0x0A}, + {0xF0, 0x8A}, + {0xF0, 0x0A}, + {0xF1, 0x0A}, + {0xF0, 0x8B}, + {0xF0, 0x0B}, + {0xF1, 0x0C}, + {0xF0, 0x8C}, + {0xF0, 0x0C}, + {0xF1, 0x0C}, + {0xF0, 0x8D}, + {0xF0, 0x0D}, + {0xF1, 0x0E}, + {0xF0, 0x8E}, + {0xF0, 0x0E}, + {0xF1, 0x0E}, + {0xF0, 0x8F}, + {0xF0, 0x0F}, + {0xF1, 0x10}, + {0xF0, 0x90}, + {0xF0, 0x10}, + {0xF1, 0x10}, + {0xF0, 0x91}, + {0xF0, 0x11}, + {0xF1, 0x12}, + {0xF0, 0x92}, + {0xF0, 0x12}, + {0xF1, 0x12}, + {0xF0, 0x93}, + {0xF0, 0x13}, + {0xF1, 0x14}, + {0xF0, 0x94}, + {0xF0, 0x14}, + {0xF1, 0x14}, + {0xF0, 0x95}, + {0xF0, 0x15}, + {0xF1, 0x16}, + {0xF0, 0x96}, + {0xF0, 0x16}, + {0xF1, 0x16}, + {0xF0, 0x97}, + {0xF0, 0x17}, + {0xF1, 0x18}, + {0xF0, 0x98}, + {0xF0, 0x18}, + {0xF1, 0x18}, + {0xF0, 0x99}, + {0xF0, 0x19}, + {0xF1, 0x1A}, + {0xF0, 0x9A}, + {0xF0, 0x1A}, + {0xF1, 0x1A}, + {0xF0, 0x9B}, + {0xF0, 0x1B}, + {0xF1, 0x1C}, + {0xF0, 0x9C}, + {0xF0, 0x1C}, + {0xF1, 0x1C}, + {0xF0, 0x9D}, + {0xF0, 0x1D}, + {0xF1, 0x1E}, + {0xF0, 0x9E}, + {0xF0, 0x1E}, + {0xF1, 0x1E}, + {0xF0, 0x9F}, + {0xF0, 0x1F}, + {0xF1, 0x20}, + {0xF0, 0xA0}, + {0xF0, 0x20}, + {0xF1, 0x20}, + {0xF0, 0xA1}, + {0xF0, 0x21}, + {0xF1, 0x22}, + {0xF0, 0xA2}, + {0xF0, 0x22}, + {0xF1, 0x22}, + {0xF0, 0xA3}, + {0xF0, 0x23}, + {0xF1, 0x24}, + {0xF0, 0xA4}, + {0xF0, 0x24}, + {0xF1, 0x24}, + {0xF0, 0xA5}, + {0xF0, 0x25}, + {0xF1, 0x26}, + {0xF0, 0xA6}, + {0xF0, 0x26}, + {0xF1, 0x26}, + {0xF0, 0xA7}, + {0xF0, 0x27}, + {0xF1, 0x28}, + {0xF0, 0xA8}, + {0xF0, 0x28}, + {0xF1, 0x28}, + {0xF0, 0xA9}, + {0xF0, 0x29}, + {0xF1, 0x2A}, + {0xF0, 0xAA}, + {0xF0, 0x2A}, + {0xF1, 0x2A}, + {0xF0, 0xAB}, + {0xF0, 0x2B}, + {0xF1, 0x2C}, + {0xF0, 0xAC}, + {0xF0, 0x2C}, + {0xF1, 0x2C}, + {0xF0, 0xAD}, + {0xF0, 0x2D}, + {0xF1, 0x2E}, + {0xF0, 0xAE}, + {0xF0, 0x2E}, + {0xF1, 0x2E}, + {0xF0, 0xAF}, + {0xF0, 0x2F}, + {0xF1, 0x30}, + {0xF0, 0xB0}, + {0xF0, 0x30}, + {0xF1, 0x30}, + {0xF0, 0xB1}, + {0xF0, 0x31}, + {0xF1, 0x32}, + {0xF0, 0xB2}, + {0xF0, 0x32}, + {0xF1, 0x32}, + {0xF0, 0xB3}, + {0xF0, 0x33}, + {0xF1, 0x34}, + {0xF0, 0xB4}, + {0xF0, 0x34}, + {0xF1, 0x34}, + {0xF0, 0xB5}, + {0xF0, 0x35}, + {0xF1, 0x36}, + {0xF0, 0xB6}, + {0xF0, 0x36}, + {0xF1, 0x36}, + {0xF0, 0xB7}, + {0xF0, 0x37}, + {0xF1, 0x38}, + {0xF0, 0xB8}, + {0xF0, 0x38}, + {0xF1, 0x38}, + {0xF0, 0xB9}, + {0xF0, 0x39}, + {0xF1, 0x3A}, + {0xF0, 0xBA}, + {0xF0, 0x3A}, + {0xF1, 0x3A}, + {0xF0, 0xBB}, + {0xF0, 0x3B}, + {0xF1, 0x3C}, + {0xF0, 0xBC}, + {0xF0, 0x3C}, + {0xF1, 0x3C}, + {0xF0, 0xBD}, + {0xF0, 0x3D}, + {0xF1, 0x3E}, + {0xF0, 0xBE}, + {0xF0, 0x3E}, + {0xF1, 0x3E}, + {0xF0, 0xBF}, + {0xF0, 0x00}, +}; + +static const unsigned short awc_frame_time[MAX_RATE] = { + 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216 +}; + +/*--------------------- Export Variables --------------------------*/ +/* + * Description: Calculate data frame transmitting time + * + * Parameters: + * In: + * preamble_type - Preamble Type + * by_pkt_type - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA + * cb_frame_length - Baseband Type + * tx_rate - Tx Rate + * Out: + * + * Return Value: FrameTime + * + */ +unsigned int bb_get_frame_time(unsigned char preamble_type, + unsigned char by_pkt_type, + unsigned int cb_frame_length, + unsigned short tx_rate) +{ + unsigned int frame_time; + unsigned int preamble; + unsigned int tmp; + unsigned int rate_idx = (unsigned int)tx_rate; + unsigned int rate = 0; + + if (rate_idx > RATE_54M) + return 0; + + rate = (unsigned int)awc_frame_time[rate_idx]; + + if (rate_idx <= 3) { /* CCK mode */ + if (preamble_type == PREAMBLE_SHORT) + preamble = 96; + else + preamble = 192; + frame_time = (cb_frame_length * 80) / rate; /* ????? */ + tmp = (frame_time * rate) / 80; + if (cb_frame_length != tmp) + frame_time++; + + return preamble + frame_time; + } + frame_time = (cb_frame_length * 8 + 22) / rate; /* ???????? */ + tmp = ((frame_time * rate) - 22) / 8; + if (cb_frame_length != tmp) + frame_time++; + + frame_time = frame_time * 4; /* ??????? */ + if (by_pkt_type != PK_TYPE_11A) + frame_time += 6; /* ?????? */ + + return 20 + frame_time; /* ?????? */ +} + +/* + * Description: Calculate Length, Service, and Signal fields of Phy for Tx + * + * Parameters: + * In: + * priv - Device Structure + * frame_length - Tx Frame Length + * tx_rate - Tx Rate + * Out: + * struct vnt_phy_field *phy + * - pointer to Phy Length field + * - pointer to Phy Service field + * - pointer to Phy Signal field + * + * Return Value: none + * + */ +void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, + u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy) +{ + u32 bit_count; + u32 count = 0; + u32 tmp; + int ext_bit; + u8 preamble_type = priv->preamble_type; + + bit_count = frame_length * 8; + ext_bit = false; + + switch (tx_rate) { + case RATE_1M: + count = bit_count; + + phy->signal = 0x00; + + break; + case RATE_2M: + count = bit_count / 2; + + if (preamble_type == PREAMBLE_SHORT) + phy->signal = 0x09; + else + phy->signal = 0x01; + + break; + case RATE_5M: + count = (bit_count * 10) / 55; + tmp = (count * 55) / 10; + + if (tmp != bit_count) + count++; + + if (preamble_type == PREAMBLE_SHORT) + phy->signal = 0x0a; + else + phy->signal = 0x02; + + break; + case RATE_11M: + count = bit_count / 11; + tmp = count * 11; + + if (tmp != bit_count) { + count++; + + if ((bit_count - tmp) <= 3) + ext_bit = true; + } + + if (preamble_type == PREAMBLE_SHORT) + phy->signal = 0x0b; + else + phy->signal = 0x03; + + break; + case RATE_6M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9b; + else + phy->signal = 0x8b; + + break; + case RATE_9M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9f; + else + phy->signal = 0x8f; + + break; + case RATE_12M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9a; + else + phy->signal = 0x8a; + + break; + case RATE_18M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9e; + else + phy->signal = 0x8e; + + break; + case RATE_24M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x99; + else + phy->signal = 0x89; + + break; + case RATE_36M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9d; + else + phy->signal = 0x8d; + + break; + case RATE_48M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x98; + else + phy->signal = 0x88; + + break; + case RATE_54M: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9c; + else + phy->signal = 0x8c; + break; + default: + if (pkt_type == PK_TYPE_11A) + phy->signal = 0x9c; + else + phy->signal = 0x8c; + break; + } + + if (pkt_type == PK_TYPE_11B) { + phy->service = 0x00; + if (ext_bit) + phy->service |= 0x80; + phy->len = cpu_to_le16((u16)count); + } else { + phy->service = 0x00; + phy->len = cpu_to_le16((u16)frame_length); + } +} + +/* + * Description: Read a byte from BASEBAND, by embedded programming + * + * Parameters: + * In: + * iobase - I/O base address + * by_bb_addr - address of register in Baseband + * Out: + * pby_data - data read + * + * Return Value: true if succeeded; false if failed. + * + */ +bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr, + unsigned char *pby_data) +{ + void __iomem *iobase = priv->port_offset; + unsigned short ww; + unsigned char by_value; + + /* BB reg offset */ + iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR); + + /* turn on REGR */ + vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGR); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + by_value = ioread8(iobase + MAC_REG_BBREGCTL); + if (by_value & BBREGCTL_DONE) + break; + } + + /* get BB data */ + *pby_data = ioread8(iobase + MAC_REG_BBREGDATA); + + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x30)\n"); + return false; + } + return true; +} + +/* + * Description: Write a Byte to BASEBAND, by embedded programming + * + * Parameters: + * In: + * iobase - I/O base address + * by_bb_addr - address of register in Baseband + * by_data - data to write + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr, + unsigned char by_data) +{ + void __iomem *iobase = priv->port_offset; + unsigned short ww; + unsigned char by_value; + + /* BB reg offset */ + iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR); + /* set BB data */ + iowrite8(by_data, iobase + MAC_REG_BBREGDATA); + + /* turn on BBREGCTL_REGW */ + vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGW); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + by_value = ioread8(iobase + MAC_REG_BBREGCTL); + if (by_value & BBREGCTL_DONE) + break; + } + + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x31)\n"); + return false; + } + return true; +} + +/* + * Description: VIA VT3253 Baseband chip init function + * + * Parameters: + * In: + * iobase - I/O base address + * byRevId - Revision ID + * byRFType - RF type + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ + +bool bb_vt3253_init(struct vnt_private *priv) +{ + bool result = true; + int ii; + void __iomem *iobase = priv->port_offset; + unsigned char by_rf_type = priv->byRFType; + unsigned char by_local_id = priv->local_id; + + if (by_rf_type == RF_RFMD2959) { + if (by_local_id <= REV_ID_VT3253_A1) { + for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) + result &= bb_write_embedded(priv, + by_vt3253_init_tab_rfmd[ii][0], + by_vt3253_init_tab_rfmd[ii][1]); + + } else { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_RFMD[ii][0], + byVT3253B0_RFMD[ii][1]); + + for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AGC4_RFMD2959[ii][0], + byVT3253B0_AGC4_RFMD2959[ii][1]); + + iowrite32(0x23, iobase + MAC_REG_ITRTMSET); + vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0)); + } + priv->abyBBVGA[0] = 0x18; + priv->abyBBVGA[1] = 0x0A; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->dbm_threshold[0] = -70; + priv->dbm_threshold[1] = -50; + priv->dbm_threshold[2] = 0; + priv->dbm_threshold[3] = 0; + } else if ((by_rf_type == RF_AIROHA) || (by_rf_type == RF_AL2230S)) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AIROHA2230[ii][0], + byVT3253B0_AIROHA2230[ii][1]); + + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]); + + priv->abyBBVGA[0] = 0x1C; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->dbm_threshold[0] = -70; + priv->dbm_threshold[1] = -48; + priv->dbm_threshold[2] = 0; + priv->dbm_threshold[3] = 0; + } else if (by_rf_type == RF_UW2451) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_UW2451[ii][0], + byVT3253B0_UW2451[ii][1]); + + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AGC[ii][0], + byVT3253B0_AGC[ii][1]); + + iowrite8(0x23, iobase + MAC_REG_ITRTMSET); + vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0)); + + priv->abyBBVGA[0] = 0x14; + priv->abyBBVGA[1] = 0x0A; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->dbm_threshold[0] = -60; + priv->dbm_threshold[1] = -50; + priv->dbm_threshold[2] = 0; + priv->dbm_threshold[3] = 0; + } else if (by_rf_type == RF_VT3226) { + for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AIROHA2230[ii][0], + byVT3253B0_AIROHA2230[ii][1]); + + for (ii = 0; ii < CB_VT3253B0_AGC; ii++) + result &= bb_write_embedded(priv, + byVT3253B0_AGC[ii][0], byVT3253B0_AGC[ii][1]); + + priv->abyBBVGA[0] = 0x1C; + priv->abyBBVGA[1] = 0x10; + priv->abyBBVGA[2] = 0x0; + priv->abyBBVGA[3] = 0x0; + priv->dbm_threshold[0] = -70; + priv->dbm_threshold[1] = -48; + priv->dbm_threshold[2] = 0; + priv->dbm_threshold[3] = 0; + /* Fix VT3226 DFC system timing issue */ + vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT); + /* {{ RobertYu: 20050104 */ + } else { + /* No VGA Table now */ + priv->bUpdateBBVGA = false; + priv->abyBBVGA[0] = 0x1C; + } + + if (by_local_id > REV_ID_VT3253_A1) { + bb_write_embedded(priv, 0x04, 0x7F); + bb_write_embedded(priv, 0x0D, 0x01); + } + + return result; +} + +/* + * Description: Set ShortSlotTime mode + * + * Parameters: + * In: + * priv - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +void +bb_set_short_slot_time(struct vnt_private *priv) +{ + unsigned char by_bb_rx_conf = 0; + unsigned char by_bb_vga = 0; + + bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ + + if (priv->short_slot_time) + by_bb_rx_conf &= 0xDF; /* 1101 1111 */ + else + by_bb_rx_conf |= 0x20; /* 0010 0000 */ + + /* patch for 3253B0 Baseband with Cardbus module */ + bb_read_embedded(priv, 0xE7, &by_bb_vga); + if (by_bb_vga == priv->abyBBVGA[0]) + by_bb_rx_conf |= 0x20; /* 0010 0000 */ + + bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ +} + +void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data) +{ + unsigned char by_bb_rx_conf = 0; + + bb_write_embedded(priv, 0xE7, by_data); + + bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ + /* patch for 3253B0 Baseband with Cardbus module */ + if (by_data == priv->abyBBVGA[0]) + by_bb_rx_conf |= 0x20; /* 0010 0000 */ + else if (priv->short_slot_time) + by_bb_rx_conf &= 0xDF; /* 1101 1111 */ + else + by_bb_rx_conf |= 0x20; /* 0010 0000 */ + priv->byBBVGACurrent = by_data; + bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ +} + +/* + * Description: Baseband SoftwareReset + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +void +bb_software_reset(struct vnt_private *priv) +{ + bb_write_embedded(priv, 0x50, 0x40); + bb_write_embedded(priv, 0x50, 0); + bb_write_embedded(priv, 0x9C, 0x01); + bb_write_embedded(priv, 0x9C, 0); +} + +/* + * Description: Baseband Power Save Mode ON + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +void +bb_power_save_mode_on(struct vnt_private *priv) +{ + unsigned char by_org_data; + + bb_read_embedded(priv, 0x0D, &by_org_data); + by_org_data |= BIT(0); + bb_write_embedded(priv, 0x0D, by_org_data); +} + +/* + * Description: Baseband Power Save Mode OFF + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * none + * + * Return Value: none + * + */ +void +bb_power_save_mode_off(struct vnt_private *priv) +{ + unsigned char by_org_data; + + bb_read_embedded(priv, 0x0D, &by_org_data); + by_org_data &= ~(BIT(0)); + bb_write_embedded(priv, 0x0D, by_org_data); +} + +/* + * Description: Set Tx Antenna mode + * + * Parameters: + * In: + * priv - Device Structure + * by_antenna_mode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ + +void +bb_set_tx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode) +{ + unsigned char by_bb_tx_conf; + + bb_read_embedded(priv, 0x09, &by_bb_tx_conf); /* CR09 */ + if (by_antenna_mode == ANT_DIVERSITY) { + /* bit 1 is diversity */ + by_bb_tx_conf |= 0x02; + } else if (by_antenna_mode == ANT_A) { + /* bit 2 is ANTSEL */ + by_bb_tx_conf &= 0xF9; /* 1111 1001 */ + } else if (by_antenna_mode == ANT_B) { + by_bb_tx_conf &= 0xFD; /* 1111 1101 */ + by_bb_tx_conf |= 0x04; + } + bb_write_embedded(priv, 0x09, by_bb_tx_conf); /* CR09 */ +} + +/* + * Description: Set Rx Antenna mode + * + * Parameters: + * In: + * priv - Device Structure + * by_antenna_mode - Antenna Mode + * Out: + * none + * + * Return Value: none + * + */ + +void +bb_set_rx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode) +{ + unsigned char by_bb_rx_conf; + + bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ + if (by_antenna_mode == ANT_DIVERSITY) { + by_bb_rx_conf |= 0x01; + + } else if (by_antenna_mode == ANT_A) { + by_bb_rx_conf &= 0xFC; /* 1111 1100 */ + } else if (by_antenna_mode == ANT_B) { + by_bb_rx_conf &= 0xFE; /* 1111 1110 */ + by_bb_rx_conf |= 0x02; + } + bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ +} + +/* + * Description: bb_set_deep_sleep + * + * Parameters: + * In: + * priv - Device Structure + * Out: + * none + * + * Return Value: none + * + */ +void +bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id) +{ + bb_write_embedded(priv, 0x0C, 0x17); /* CR12 */ + bb_write_embedded(priv, 0x0D, 0xB9); /* CR13 */ +} + diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h new file mode 100644 index 000000000..15b2802ed --- /dev/null +++ b/drivers/staging/vt6655/baseband.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Implement functions to access baseband + * + * Author: Jerry Chen + * + * Date: Jun. 5, 2002 + * + */ + +#ifndef __BASEBAND_H__ +#define __BASEBAND_H__ + +#include "device.h" + +/* + * Registers in the BASEBAND + */ +#define BB_MAX_CONTEXT_SIZE 256 + +/* + * Baseband RF pair definition in eeprom (Bits 6..0) + */ + +#define PREAMBLE_LONG 0 +#define PREAMBLE_SHORT 1 + +#define F5G 0 +#define F2_4G 1 + +#define TOP_RATE_54M 0x80000000 +#define TOP_RATE_48M 0x40000000 +#define TOP_RATE_36M 0x20000000 +#define TOP_RATE_24M 0x10000000 +#define TOP_RATE_18M 0x08000000 +#define TOP_RATE_12M 0x04000000 +#define TOP_RATE_11M 0x02000000 +#define TOP_RATE_9M 0x01000000 +#define TOP_RATE_6M 0x00800000 +#define TOP_RATE_55M 0x00400000 +#define TOP_RATE_2M 0x00200000 +#define TOP_RATE_1M 0x00100000 + +unsigned int bb_get_frame_time(unsigned char preamble_type, + unsigned char by_pkt_type, + unsigned int cb_frame_length, + unsigned short w_rate); + +void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, + u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy); + +bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr, + unsigned char *pby_data); +bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr, + unsigned char by_data); + +void bb_set_short_slot_time(struct vnt_private *priv); +void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data); + +/* VT3253 Baseband */ +bool bb_vt3253_init(struct vnt_private *priv); +void bb_software_reset(struct vnt_private *priv); +void bb_power_save_mode_on(struct vnt_private *priv); +void bb_power_save_mode_off(struct vnt_private *priv); +void bb_set_tx_antenna_mode(struct vnt_private *priv, + unsigned char by_antenna_mode); +void bb_set_rx_antenna_mode(struct vnt_private *priv, + unsigned char by_antenna_mode); +void bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id); + +#endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c new file mode 100644 index 000000000..c680925b9 --- /dev/null +++ b/drivers/staging/vt6655/card.c @@ -0,0 +1,836 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Provide functions to setup NIC operation mode + * Functions: + * s_vSafeResetTx - Rest Tx + * CARDvSetRSPINF - Set RSPINF + * CARDvUpdateBasicTopRate - Update BasicTopRate + * CARDbAddBasicRate - Add to BasicRateSet + * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet + * CARDqGetTSFOffset - Calculate TSFOffset + * vt6655_get_current_tsf - Read Current NIC TSF counter + * CARDqGetNextTBTT - Calculate Next Beacon TSF counter + * CARDvSetFirstNextTBTT - Set NIC Beacon time + * CARDvUpdateNextTBTT - Sync. NIC Beacon time + * CARDbRadioPowerOff - Turn Off NIC Radio Power + * + * Revision History: + * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-26-2003 Kyle Hsu: Modify the definition type of iobase. + * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). + * + */ + +#include "card.h" +#include "baseband.h" +#include "mac.h" +#include "desc.h" +#include "rf.h" +#include "power.h" + +/*--------------------- Static Definitions -------------------------*/ + +#define C_SIFS_A 16 /* micro sec. */ +#define C_SIFS_BG 10 + +#define C_EIFS 80 /* micro sec. */ + +#define C_SLOT_SHORT 9 /* micro sec. */ +#define C_SLOT_LONG 20 + +#define C_CWMIN_A 15 /* slot time */ +#define C_CWMIN_B 31 + +#define C_CWMAX 1023 /* slot time */ + +#define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */ + +/*--------------------- Static Variables --------------------------*/ + +static const unsigned short cwRXBCNTSFOff[MAX_RATE] = { + 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; + +/*--------------------- Static Functions --------------------------*/ + +static void vt6655_mac_set_bb_type(void __iomem *iobase, u32 mask) +{ + u32 reg_value; + + reg_value = ioread32(iobase + MAC_REG_ENCFG); + reg_value = reg_value & ~ENCFG_BBTYPE_MASK; + reg_value = reg_value | mask; + iowrite32(reg_value, iobase + MAC_REG_ENCFG); +} + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. + * + * Parameters: + * In: + * wRate - Tx Rate + * byPktType - Tx Packet type + * Out: + * pbyTxRate - pointer to RSPINF TxRate field + * pbyRsvTime - pointer to RSPINF RsvTime field + * + * Return Value: none + */ +static void s_vCalculateOFDMRParameter(unsigned char rate, + u8 bb_type, + unsigned char *pbyTxRate, + unsigned char *pbyRsvTime) +{ + switch (rate) { + case RATE_6M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9B; + *pbyRsvTime = 44; + } else { + *pbyTxRate = 0x8B; + *pbyRsvTime = 50; + } + break; + + case RATE_9M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9F; + *pbyRsvTime = 36; + } else { + *pbyTxRate = 0x8F; + *pbyRsvTime = 42; + } + break; + + case RATE_12M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9A; + *pbyRsvTime = 32; + } else { + *pbyTxRate = 0x8A; + *pbyRsvTime = 38; + } + break; + + case RATE_18M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9E; + *pbyRsvTime = 28; + } else { + *pbyTxRate = 0x8E; + *pbyRsvTime = 34; + } + break; + + case RATE_36M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9D; + *pbyRsvTime = 24; + } else { + *pbyTxRate = 0x8D; + *pbyRsvTime = 30; + } + break; + + case RATE_48M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x98; + *pbyRsvTime = 24; + } else { + *pbyTxRate = 0x88; + *pbyRsvTime = 30; + } + break; + + case RATE_54M: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x9C; + *pbyRsvTime = 24; + } else { + *pbyTxRate = 0x8C; + *pbyRsvTime = 30; + } + break; + + case RATE_24M: + default: + if (bb_type == BB_TYPE_11A) { /* 5GHZ */ + *pbyTxRate = 0x99; + *pbyRsvTime = 28; + } else { + *pbyTxRate = 0x89; + *pbyRsvTime = 34; + } + break; + } +} + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: Update IFS + * + * Parameters: + * In: + * priv - The adapter to be set + * Out: + * none + * + * Return Value: None. + */ +bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type) +{ + unsigned char byCWMaxMin = 0; + unsigned char bySlot = 0; + unsigned char bySIFS = 0; + unsigned char byDIFS = 0; + int i; + + /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */ + if (bb_type == BB_TYPE_11A) { + vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11A); + bb_write_embedded(priv, 0x88, 0x03); + bySlot = C_SLOT_SHORT; + bySIFS = C_SIFS_A; + byDIFS = C_SIFS_A + 2 * C_SLOT_SHORT; + byCWMaxMin = 0xA4; + } else if (bb_type == BB_TYPE_11B) { + vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11B); + bb_write_embedded(priv, 0x88, 0x02); + bySlot = C_SLOT_LONG; + bySIFS = C_SIFS_BG; + byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG; + byCWMaxMin = 0xA5; + } else { /* PK_TYPE_11GA & PK_TYPE_11GB */ + vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11G); + bb_write_embedded(priv, 0x88, 0x08); + bySIFS = C_SIFS_BG; + + if (priv->short_slot_time) { + bySlot = C_SLOT_SHORT; + byDIFS = C_SIFS_BG + 2 * C_SLOT_SHORT; + } else { + bySlot = C_SLOT_LONG; + byDIFS = C_SIFS_BG + 2 * C_SLOT_LONG; + } + + byCWMaxMin = 0xa4; + + for (i = RATE_54M; i >= RATE_6M; i--) { + if (priv->basic_rates & ((u32)(0x1 << i))) { + byCWMaxMin |= 0x1; + break; + } + } + } + + if (priv->byRFType == RF_RFMD2959) { + /* + * bcs TX_PE will reserve 3 us hardware's processing + * time here is 2 us. + */ + bySIFS -= 3; + byDIFS -= 3; + /* + * TX_PE will reserve 3 us for MAX2829 A mode only, it is for + * better TX throughput; MAC will need 2 us to process, so the + * SIFS, DIFS can be shorter by 2 us. + */ + } + + if (priv->bySIFS != bySIFS) { + priv->bySIFS = bySIFS; + iowrite8(priv->bySIFS, priv->port_offset + MAC_REG_SIFS); + } + if (priv->byDIFS != byDIFS) { + priv->byDIFS = byDIFS; + iowrite8(priv->byDIFS, priv->port_offset + MAC_REG_DIFS); + } + if (priv->byEIFS != C_EIFS) { + priv->byEIFS = C_EIFS; + iowrite8(priv->byEIFS, priv->port_offset + MAC_REG_EIFS); + } + if (priv->bySlot != bySlot) { + priv->bySlot = bySlot; + iowrite8(priv->bySlot, priv->port_offset + MAC_REG_SLOT); + + bb_set_short_slot_time(priv); + } + if (priv->byCWMaxMin != byCWMaxMin) { + priv->byCWMaxMin = byCWMaxMin; + iowrite8(priv->byCWMaxMin, priv->port_offset + MAC_REG_CWMAXMIN0); + } + + priv->byPacketType = CARDbyGetPktType(priv); + + CARDvSetRSPINF(priv, bb_type); + + return true; +} + +/* + * Description: Sync. TSF counter to BSS + * Get TSF offset and write to HW + * + * Parameters: + * In: + * priv - The adapter to be sync. + * byRxRate - data rate of receive beacon + * qwBSSTimestamp - Rx BCN's TSF + * qwLocalTSF - Local TSF + * Out: + * none + * + * Return Value: none + */ +bool CARDbUpdateTSF(struct vnt_private *priv, unsigned char byRxRate, + u64 qwBSSTimestamp) +{ + u64 local_tsf; + u64 qwTSFOffset = 0; + + local_tsf = vt6655_get_current_tsf(priv); + + if (qwBSSTimestamp != local_tsf) { + qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, + local_tsf); + /* adjust TSF, HW's TSF add TSF Offset reg */ + qwTSFOffset = le64_to_cpu(qwTSFOffset); + iowrite32((u32)qwTSFOffset, priv->port_offset + MAC_REG_TSFOFST); + iowrite32((u32)(qwTSFOffset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4); + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN); + } + return true; +} + +/* + * Description: Set NIC TSF counter for first Beacon time + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * priv - The adapter to be set. + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: true if succeed; otherwise false + */ +bool CARDbSetBeaconPeriod(struct vnt_private *priv, + unsigned short wBeaconInterval) +{ + u64 qwNextTBTT; + + qwNextTBTT = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ + + qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); + + /* set HW beacon interval */ + iowrite16(wBeaconInterval, priv->port_offset + MAC_REG_BI); + priv->wBeaconInterval = wBeaconInterval; + /* Set NextTBTT */ + qwNextTBTT = le64_to_cpu(qwNextTBTT); + iowrite32((u32)qwNextTBTT, priv->port_offset + MAC_REG_NEXTTBTT); + iowrite32((u32)(qwNextTBTT >> 32), priv->port_offset + MAC_REG_NEXTTBTT + 4); + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + + return true; +} + +/* + * Description: Turn off Radio power + * + * Parameters: + * In: + * priv - The adapter to be turned off + * Out: + * none + * + */ +void CARDbRadioPowerOff(struct vnt_private *priv) +{ + if (priv->radio_off) + return; + + switch (priv->byRFType) { + case RF_RFMD2959: + vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_TXPEINV); + vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE1); + break; + + case RF_AIROHA: + case RF_AL2230S: + vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE2); + vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, + SOFTPWRCTL_SWPE3); + break; + } + + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON); + + bb_set_deep_sleep(priv, priv->local_id); + + priv->radio_off = true; + pr_debug("chester power off\n"); + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */ +} + +void CARDvSafeResetTx(struct vnt_private *priv) +{ + unsigned int uu; + struct vnt_tx_desc *pCurrTD; + + /* initialize TD index */ + priv->apTailTD[0] = &priv->apTD0Rings[0]; + priv->apCurrTD[0] = &priv->apTD0Rings[0]; + + priv->apTailTD[1] = &priv->apTD1Rings[0]; + priv->apCurrTD[1] = &priv->apTD1Rings[0]; + + for (uu = 0; uu < TYPE_MAXTD; uu++) + priv->iTDUsed[uu] = 0; + + for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) { + pCurrTD = &priv->apTD0Rings[uu]; + pCurrTD->td0.owner = OWNED_BY_HOST; + /* init all Tx Packet pointer to NULL */ + } + for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) { + pCurrTD = &priv->apTD1Rings[uu]; + pCurrTD->td0.owner = OWNED_BY_HOST; + /* init all Tx Packet pointer to NULL */ + } + + /* set MAC TD pointer */ + vt6655_mac_set_curr_tx_desc_addr(TYPE_TXDMA0, priv, priv->td0_pool_dma); + + vt6655_mac_set_curr_tx_desc_addr(TYPE_AC0DMA, priv, priv->td1_pool_dma); + + /* set MAC Beacon TX pointer */ + iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR); +} + +/* + * Description: + * Reset Rx + * + * Parameters: + * In: + * priv - Pointer to the adapter + * Out: + * none + * + * Return Value: none + */ +void CARDvSafeResetRx(struct vnt_private *priv) +{ + unsigned int uu; + struct vnt_rx_desc *pDesc; + + /* initialize RD index */ + priv->pCurrRD[0] = &priv->aRD0Ring[0]; + priv->pCurrRD[1] = &priv->aRD1Ring[0]; + + /* init state, all RD is chip's */ + for (uu = 0; uu < priv->opts.rx_descs0; uu++) { + pDesc = &priv->aRD0Ring[uu]; + pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); + pDesc->rd0.owner = OWNED_BY_NIC; + pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); + } + + /* init state, all RD is chip's */ + for (uu = 0; uu < priv->opts.rx_descs1; uu++) { + pDesc = &priv->aRD1Ring[uu]; + pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); + pDesc->rd0.owner = OWNED_BY_NIC; + pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); + } + + /* set perPkt mode */ + iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL0); + iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL1); + /* set MAC RD pointer */ + vt6655_mac_set_curr_rx_0_desc_addr(priv, priv->rd0_pool_dma); + + vt6655_mac_set_curr_rx_1_desc_addr(priv, priv->rd1_pool_dma); +} + +/* + * Description: Get response Control frame rate in CCK mode + * + * Parameters: + * In: + * priv - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + */ +static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, + unsigned short wRateIdx) +{ + unsigned int ui = (unsigned int)wRateIdx; + + while (ui > RATE_1M) { + if (priv->basic_rates & ((u32)0x1 << ui)) + return (unsigned short)ui; + + ui--; + } + return (unsigned short)RATE_1M; +} + +/* + * Description: Get response Control frame rate in OFDM mode + * + * Parameters: + * In: + * priv - The adapter to be set + * wRateIdx - Receiving data rate + * Out: + * none + * + * Return Value: response Control frame rate + */ +static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv, + unsigned short wRateIdx) +{ + unsigned int ui = (unsigned int)wRateIdx; + + pr_debug("BASIC RATE: %X\n", priv->basic_rates); + + if (!CARDbIsOFDMinBasicRate((void *)priv)) { + pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx); + if (wRateIdx > RATE_24M) + wRateIdx = RATE_24M; + return wRateIdx; + } + while (ui > RATE_11M) { + if (priv->basic_rates & ((u32)0x1 << ui)) { + pr_debug("%s : %d\n", __func__, ui); + return (unsigned short)ui; + } + ui--; + } + pr_debug("%s: 6M\n", __func__); + return (unsigned short)RATE_24M; +} + +/* + * Description: Set RSPINF + * + * Parameters: + * In: + * priv - The adapter to be set + * Out: + * none + * + * Return Value: None. + */ +void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type) +{ + union vnt_phy_field_swap phy; + unsigned char byTxRate, byRsvTime; /* For OFDM */ + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + /* Set to Page1 */ + VT6655_MAC_SELECT_PAGE1(priv->port_offset); + + /* RSPINF_b_1 */ + vnt_get_phy_field(priv, 14, + CARDwGetCCKControlRate(priv, RATE_1M), + PK_TYPE_11B, &phy.field_read); + + /* swap over to get correct write order */ + swap(phy.swap[0], phy.swap[1]); + + iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_1); + + /* RSPINF_b_2 */ + vnt_get_phy_field(priv, 14, + CARDwGetCCKControlRate(priv, RATE_2M), + PK_TYPE_11B, &phy.field_read); + + swap(phy.swap[0], phy.swap[1]); + + iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_2); + + /* RSPINF_b_5 */ + vnt_get_phy_field(priv, 14, + CARDwGetCCKControlRate(priv, RATE_5M), + PK_TYPE_11B, &phy.field_read); + + swap(phy.swap[0], phy.swap[1]); + + iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_5); + + /* RSPINF_b_11 */ + vnt_get_phy_field(priv, 14, + CARDwGetCCKControlRate(priv, RATE_11M), + PK_TYPE_11B, &phy.field_read); + + swap(phy.swap[0], phy.swap[1]); + + iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_11); + + /* RSPINF_a_6 */ + s_vCalculateOFDMRParameter(RATE_6M, + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_6); + /* RSPINF_a_9 */ + s_vCalculateOFDMRParameter(RATE_9M, + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_9); + /* RSPINF_a_12 */ + s_vCalculateOFDMRParameter(RATE_12M, + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_12); + /* RSPINF_a_18 */ + s_vCalculateOFDMRParameter(RATE_18M, + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_18); + /* RSPINF_a_24 */ + s_vCalculateOFDMRParameter(RATE_24M, + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_24); + /* RSPINF_a_36 */ + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, + RATE_36M), + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_36); + /* RSPINF_a_48 */ + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, + RATE_48M), + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_48); + /* RSPINF_a_54 */ + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, + RATE_54M), + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_54); + /* RSPINF_a_72 */ + s_vCalculateOFDMRParameter(CARDwGetOFDMControlRate((void *)priv, + RATE_54M), + bb_type, + &byTxRate, + &byRsvTime); + iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_72); + /* Set to Page0 */ + VT6655_MAC_SELECT_PAGE0(priv->port_offset); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +void CARDvUpdateBasicTopRate(struct vnt_private *priv) +{ + unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M; + unsigned char ii; + + /* Determines the highest basic rate. */ + for (ii = RATE_54M; ii >= RATE_6M; ii--) { + if ((priv->basic_rates) & ((u32)(1 << ii))) { + byTopOFDM = ii; + break; + } + } + priv->byTopOFDMBasicRate = byTopOFDM; + + for (ii = RATE_11M;; ii--) { + if ((priv->basic_rates) & ((u32)(1 << ii))) { + byTopCCK = ii; + break; + } + if (ii == RATE_1M) + break; + } + priv->byTopCCKBasicRate = byTopCCK; +} + +bool CARDbIsOFDMinBasicRate(struct vnt_private *priv) +{ + int ii; + + for (ii = RATE_54M; ii >= RATE_6M; ii--) { + if ((priv->basic_rates) & ((u32)BIT(ii))) + return true; + } + return false; +} + +unsigned char CARDbyGetPktType(struct vnt_private *priv) +{ + if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B) + return (unsigned char)priv->byBBType; + else if (CARDbIsOFDMinBasicRate((void *)priv)) + return PK_TYPE_11GA; + else + return PK_TYPE_11GB; +} + +/* + * Description: Calculate TSF offset of two TSF input + * Get TSF Offset from RxBCN's TSF and local TSF + * + * Parameters: + * In: + * priv - The adapter to be sync. + * qwTSF1 - Rx BCN's TSF + * qwTSF2 - Local TSF + * Out: + * none + * + * Return Value: TSF Offset value + */ +u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2) +{ + unsigned short wRxBcnTSFOffst; + + wRxBcnTSFOffst = cwRXBCNTSFOff[byRxRate % MAX_RATE]; + + qwTSF2 += (u64)wRxBcnTSFOffst; + + return qwTSF1 - qwTSF2; +} + +/* + * Description: Read NIC TSF counter + * Get local TSF counter + * + * Parameters: + * In: + * priv - The adapter to be read + * Out: + * none + * + * Return Value: Current TSF counter + */ +u64 vt6655_get_current_tsf(struct vnt_private *priv) +{ + void __iomem *iobase = priv->port_offset; + unsigned short ww; + unsigned char data; + u32 low, high; + + vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + data = ioread8(iobase + MAC_REG_TFTCTL); + if (!(data & TFTCTL_TSFCNTRRD)) + break; + } + if (ww == W_MAX_TIMEOUT) + return 0; + low = ioread32(iobase + MAC_REG_TSFCNTR); + high = ioread32(iobase + MAC_REG_TSFCNTR + 4); + return le64_to_cpu(low + ((u64)high << 32)); +} + +/* + * Description: Read NIC TSF counter + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * qwTSF - Current TSF counter + * wbeaconInterval - Beacon Interval + * Out: + * qwCurrTSF - Current TSF counter + * + * Return Value: TSF value of next Beacon + */ +u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval) +{ + u32 beacon_int; + + beacon_int = wBeaconInterval * 1024; + if (beacon_int) { + do_div(qwTSF, beacon_int); + qwTSF += 1; + qwTSF *= beacon_int; + } + + return qwTSF; +} + +/* + * Description: Set NIC TSF counter for first Beacon time + * Get NEXTTBTT from adjusted TSF and Beacon Interval + * + * Parameters: + * In: + * iobase - IO Base + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + */ +void CARDvSetFirstNextTBTT(struct vnt_private *priv, + unsigned short wBeaconInterval) +{ + void __iomem *iobase = priv->port_offset; + u64 qwNextTBTT; + + qwNextTBTT = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ + + qwNextTBTT = CARDqGetNextTBTT(qwNextTBTT, wBeaconInterval); + /* Set NextTBTT */ + qwNextTBTT = le64_to_cpu(qwNextTBTT); + iowrite32((u32)qwNextTBTT, iobase + MAC_REG_NEXTTBTT); + iowrite32((u32)(qwNextTBTT >> 32), iobase + MAC_REG_NEXTTBTT + 4); + vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); +} + +/* + * Description: Sync NIC TSF counter for Beacon time + * Get NEXTTBTT and write to HW + * + * Parameters: + * In: + * priv - The adapter to be set + * qwTSF - Current TSF counter + * wBeaconInterval - Beacon Interval + * Out: + * none + * + * Return Value: none + */ +void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, + unsigned short wBeaconInterval) +{ + void __iomem *iobase = priv->port_offset; + + qwTSF = CARDqGetNextTBTT(qwTSF, wBeaconInterval); + /* Set NextTBTT */ + qwTSF = le64_to_cpu(qwTSF); + iowrite32((u32)qwTSF, iobase + MAC_REG_NEXTTBTT); + iowrite32((u32)(qwTSF >> 32), iobase + MAC_REG_NEXTTBTT + 4); + vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); + pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF); +} diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h new file mode 100644 index 000000000..22dc359a6 --- /dev/null +++ b/drivers/staging/vt6655/card.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Provide functions to setup NIC operation mode + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __CARD_H__ +#define __CARD_H__ + +#include <linux/types.h> +#include <linux/nl80211.h> + +/* + * Loopback mode + * + * LOBYTE is MAC LB mode, HIBYTE is MII LB mode + */ +#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0) +/* PHY must ISO, avoid MAC loopback packet go out */ +#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0) +#define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0) + +#define DEFAULT_MSDU_LIFETIME 512 /* ms */ +#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */ + +#define DEFAULT_MGN_LIFETIME 8 /* ms */ +#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */ + +#define CB_MAX_CHANNEL_24G 14 +#define CB_MAX_CHANNEL_5G 42 +#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G) + +struct vnt_private; + +void CARDvSetRSPINF(struct vnt_private *priv, u8 bb_type); +void CARDvUpdateBasicTopRate(struct vnt_private *priv); +bool CARDbIsOFDMinBasicRate(struct vnt_private *priv); +void CARDvSetFirstNextTBTT(struct vnt_private *priv, + unsigned short wBeaconInterval); +void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, + unsigned short wBeaconInterval); +u64 vt6655_get_current_tsf(struct vnt_private *priv); +u64 CARDqGetNextTBTT(u64 qwTSF, unsigned short wBeaconInterval); +u64 CARDqGetTSFOffset(unsigned char byRxRate, u64 qwTSF1, u64 qwTSF2); +unsigned char CARDbyGetPktType(struct vnt_private *priv); +void CARDvSafeResetTx(struct vnt_private *priv); +void CARDvSafeResetRx(struct vnt_private *priv); +void CARDbRadioPowerOff(struct vnt_private *priv); +bool CARDbSetPhyParameter(struct vnt_private *priv, u8 bb_type); +bool CARDbUpdateTSF(struct vnt_private *priv, unsigned char byRxRate, + u64 qwBSSTimestamp); +bool CARDbSetBeaconPeriod(struct vnt_private *priv, + unsigned short wBeaconInterval); + +#endif /* __CARD_H__ */ diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c new file mode 100644 index 000000000..4122875eb --- /dev/null +++ b/drivers/staging/vt6655/channel.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + */ + +#include "baseband.h" +#include "channel.h" +#include "device.h" +#include "rf.h" + +static struct ieee80211_rate vnt_rates_bg[] = { + { .bitrate = 10, .hw_value = RATE_1M }, + { .bitrate = 20, .hw_value = RATE_2M }, + { .bitrate = 55, .hw_value = RATE_5M }, + { .bitrate = 110, .hw_value = RATE_11M }, + { .bitrate = 60, .hw_value = RATE_6M }, + { .bitrate = 90, .hw_value = RATE_9M }, + { .bitrate = 120, .hw_value = RATE_12M }, + { .bitrate = 180, .hw_value = RATE_18M }, + { .bitrate = 240, .hw_value = RATE_24M }, + { .bitrate = 360, .hw_value = RATE_36M }, + { .bitrate = 480, .hw_value = RATE_48M }, + { .bitrate = 540, .hw_value = RATE_54M }, +}; + +static struct ieee80211_channel vnt_channels_2ghz[] = { + { .center_freq = 2412, .hw_value = 1 }, + { .center_freq = 2417, .hw_value = 2 }, + { .center_freq = 2422, .hw_value = 3 }, + { .center_freq = 2427, .hw_value = 4 }, + { .center_freq = 2432, .hw_value = 5 }, + { .center_freq = 2437, .hw_value = 6 }, + { .center_freq = 2442, .hw_value = 7 }, + { .center_freq = 2447, .hw_value = 8 }, + { .center_freq = 2452, .hw_value = 9 }, + { .center_freq = 2457, .hw_value = 10 }, + { .center_freq = 2462, .hw_value = 11 }, + { .center_freq = 2467, .hw_value = 12 }, + { .center_freq = 2472, .hw_value = 13 }, + { .center_freq = 2484, .hw_value = 14 } +}; + +static struct ieee80211_supported_band vnt_supported_2ghz_band = { + .channels = vnt_channels_2ghz, + .n_channels = ARRAY_SIZE(vnt_channels_2ghz), + .bitrates = vnt_rates_bg, + .n_bitrates = ARRAY_SIZE(vnt_rates_bg), +}; + +static void vnt_init_band(struct vnt_private *priv, + struct ieee80211_supported_band *supported_band, + enum nl80211_band band) +{ + int i; + + for (i = 0; i < supported_band->n_channels; i++) { + supported_band->channels[i].max_power = 0x3f; + supported_band->channels[i].flags = + IEEE80211_CHAN_NO_HT40; + } + + priv->hw->wiphy->bands[band] = supported_band; +} + +void vnt_init_bands(struct vnt_private *priv) +{ + vnt_init_band(priv, &vnt_supported_2ghz_band, NL80211_BAND_2GHZ); +} + +/** + * set_channel() - Set NIC media channel + * + * @priv: The adapter to be set + * @ch: Channel to be set + * + * Return Value: true if succeeded; false if failed. + * + */ +bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) +{ + bool ret = true; + + if (priv->byCurrentCh == ch->hw_value) + return ret; + + /* Set VGA to max sensitivity */ + if (priv->bUpdateBBVGA && + priv->byBBVGACurrent != priv->abyBBVGA[0]) { + priv->byBBVGACurrent = priv->abyBBVGA[0]; + + bb_set_vga_gain_offset(priv, priv->byBBVGACurrent); + } + + /* clear NAV */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_MACCR, MACCR_CLRNAV); + + /* TX_PE will reserve 3 us for MAX2829 A mode only, + * it is for better TX throughput + */ + + priv->byCurrentCh = ch->hw_value; + ret &= RFbSelectChannel(priv, priv->byRFType, + ch->hw_value); + + /* Init Synthesizer Table */ + if (priv->bEnablePSMode) + rf_write_wake_prog_syn(priv, priv->byRFType, ch->hw_value); + + bb_software_reset(priv); + + if (priv->local_id > REV_ID_VT3253_B1) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + /* set HW default power register */ + VT6655_MAC_SELECT_PAGE1(priv->port_offset); + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); + iowrite8(priv->byCurPwr, priv->port_offset + MAC_REG_PWRCCK); + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); + iowrite8(priv->byCurPwr, priv->port_offset + MAC_REG_PWROFDM); + VT6655_MAC_SELECT_PAGE0(priv->port_offset); + + spin_unlock_irqrestore(&priv->lock, flags); + } + + if (priv->byBBType == BB_TYPE_11B) + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); + else + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); + + return ret; +} diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h new file mode 100644 index 000000000..78b2d8231 --- /dev/null +++ b/drivers/staging/vt6655/channel.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + */ + +#ifndef _CHANNEL_H_ +#define _CHANNEL_H_ + +#include "card.h" + +void vnt_init_bands(struct vnt_private *priv); + +bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch); + +#endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h new file mode 100644 index 000000000..17a40c53b --- /dev/null +++ b/drivers/staging/vt6655/desc.h @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose:The header file of descriptor + * + * Revision History: + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + */ + +#ifndef __DESC_H__ +#define __DESC_H__ + +#include <linux/types.h> +#include <linux/mm.h> +#include "linux/ieee80211.h" + +#define B_OWNED_BY_CHIP 1 +#define B_OWNED_BY_HOST 0 + +/* Bits in the RSR register */ +#define RSR_ADDRBROAD 0x80 +#define RSR_ADDRMULTI 0x40 +#define RSR_ADDRUNI 0x00 +#define RSR_IVLDTYP 0x20 +#define RSR_IVLDLEN 0x10 /* invalid len (> 2312 byte) */ +#define RSR_BSSIDOK 0x08 +#define RSR_CRCOK 0x04 +#define RSR_BCNSSIDOK 0x02 +#define RSR_ADDROK 0x01 + +/* Bits in the new RSR register */ +#define NEWRSR_DECRYPTOK 0x10 +#define NEWRSR_CFPIND 0x08 +#define NEWRSR_HWUTSF 0x04 +#define NEWRSR_BCNHITAID 0x02 +#define NEWRSR_BCNHITAID0 0x01 + +/* Bits in the TSR0 register */ +#define TSR0_PWRSTS1_2 0xC0 +#define TSR0_PWRSTS7 0x20 +#define TSR0_NCR 0x1F + +/* Bits in the TSR1 register */ +#define TSR1_TERR 0x80 +#define TSR1_PWRSTS4_6 0x70 +#define TSR1_RETRYTMO 0x08 +#define TSR1_TMO 0x04 +#define TSR1_PWRSTS3 0x02 +#define ACK_DATA 0x01 + +/* Bits in the TCR register */ +#define EDMSDU 0x04 /* end of sdu */ +#define TCR_EDP 0x02 /* end of packet */ +#define TCR_STP 0x01 /* start of packet */ + +/* max transmit or receive buffer size */ +#define CB_MAX_BUF_SIZE 2900U + /* NOTE: must be multiple of 4 */ +#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE +#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE + +#define CB_BEACON_BUF_SIZE 512U + +#define CB_MAX_RX_DESC 128 +#define CB_MIN_RX_DESC 16 +#define CB_MAX_TX_DESC 64 +#define CB_MIN_TX_DESC 16 + +#define CB_MAX_RECEIVED_PACKETS 16 + /* + * limit our receive routine to indicating + * this many at a time for 2 reasons: + * 1. driver flow control to protocol layer + * 2. limit the time used in ISR routine + */ + +#define CB_EXTRA_RD_NUM 32 +#define CB_RD_NUM 32 +#define CB_TD_NUM 32 + +/* + * max number of physical segments in a single NDIS packet. Above this + * threshold, the packet is copied into a single physically contiguous buffer + */ +#define CB_MAX_SEGMENT 4 + +#define CB_MIN_MAP_REG_NUM 4 +#define CB_MAX_MAP_REG_NUM CB_MAX_TX_DESC + +#define CB_PROTOCOL_RESERVED_SECTION 16 + +/* + * if retrys excess 15 times , tx will abort, and if tx fifo underflow, + * tx will fail, we should try to resend it + */ +#define CB_MAX_TX_ABORT_RETRY 3 + +/* WMAC definition FIFO Control */ +#define FIFOCTL_AUTO_FB_1 0x1000 +#define FIFOCTL_AUTO_FB_0 0x0800 +#define FIFOCTL_GRPACK 0x0400 +#define FIFOCTL_11GA 0x0300 +#define FIFOCTL_11GB 0x0200 +#define FIFOCTL_11B 0x0100 +#define FIFOCTL_11A 0x0000 +#define FIFOCTL_RTS 0x0080 +#define FIFOCTL_ISDMA0 0x0040 +#define FIFOCTL_GENINT 0x0020 +#define FIFOCTL_TMOEN 0x0010 +#define FIFOCTL_LRETRY 0x0008 +#define FIFOCTL_CRCDIS 0x0004 +#define FIFOCTL_NEEDACK 0x0002 +#define FIFOCTL_LHEAD 0x0001 + +/* WMAC definition Frag Control */ +#define FRAGCTL_AES 0x0300 +#define FRAGCTL_TKIP 0x0200 +#define FRAGCTL_LEGACY 0x0100 +#define FRAGCTL_NONENCRYPT 0x0000 +#define FRAGCTL_ENDFRAG 0x0003 +#define FRAGCTL_MIDFRAG 0x0002 +#define FRAGCTL_STAFRAG 0x0001 +#define FRAGCTL_NONFRAG 0x0000 + +#define TYPE_TXDMA0 0 +#define TYPE_AC0DMA 1 +#define TYPE_ATIMDMA 2 +#define TYPE_SYNCDMA 3 +#define TYPE_MAXTD 2 + +#define TYPE_BEACONDMA 4 + +#define TYPE_RXDMA0 0 +#define TYPE_RXDMA1 1 +#define TYPE_MAXRD 2 + +/* TD_INFO flags control bit */ +#define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */ +/* check if called from private skb (hostap) */ +#define TD_FLAGS_PRIV_SKB 0x02 +#define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */ + +/* + * ref_sk_buff is used for mapping the skb structure between pre-built + * driver-obj & running kernel. Since different kernel version (2.4x) may + * change skb structure, i.e. pre-built driver-obj may link to older skb that + * leads error. + */ + +struct vnt_rd_info { + struct sk_buff *skb; + dma_addr_t skb_dma; +}; + +struct vnt_rdes0 { + volatile __le16 res_count; +#ifdef __BIG_ENDIAN + union { + volatile u16 f15_reserved; + struct { + volatile u8 f8_reserved1; + volatile u8 owner:1; + volatile u8 f7_reserved:7; + } __packed; + } __packed; +#else + u16 f15_reserved:15; + u16 owner:1; +#endif +} __packed; + +struct vnt_rdes1 { + __le16 req_count; + u16 reserved; +} __packed; + +/* Rx descriptor*/ +struct vnt_rx_desc { + volatile struct vnt_rdes0 rd0; + volatile struct vnt_rdes1 rd1; + volatile __le32 buff_addr; + volatile __le32 next_desc; + struct vnt_rx_desc *next __aligned(8); + struct vnt_rd_info *rd_info __aligned(8); +} __packed; + +struct vnt_tdes0 { + volatile u8 tsr0; + volatile u8 tsr1; +#ifdef __BIG_ENDIAN + union { + volatile u16 f15_txtime; + struct { + volatile u8 f8_reserved; + volatile u8 owner:1; + volatile u8 f7_reserved:7; + } __packed; + } __packed; +#else + volatile u16 f15_txtime:15; + volatile u16 owner:1; +#endif +} __packed; + +struct vnt_tdes1 { + volatile __le16 req_count; + volatile u8 tcr; + volatile u8 reserved; +} __packed; + +struct vnt_td_info { + void *mic_hdr; + struct sk_buff *skb; + unsigned char *buf; + dma_addr_t buf_dma; + u16 req_count; + u8 flags; +}; + +/* transmit descriptor */ +struct vnt_tx_desc { + volatile struct vnt_tdes0 td0; + volatile struct vnt_tdes1 td1; + volatile __le32 buff_addr; + volatile __le32 next_desc; + struct vnt_tx_desc *next __aligned(8); + struct vnt_td_info *td_info __aligned(8); +} __packed; + +/* Length, Service, and Signal fields of Phy for Tx */ +struct vnt_phy_field { + u8 signal; + u8 service; + __le16 len; +} __packed; + +union vnt_phy_field_swap { + struct vnt_phy_field field_read; + u16 swap[2]; + u32 field_write; +}; + +#endif /* __DESC_H__ */ diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h new file mode 100644 index 000000000..c272a4ab2 --- /dev/null +++ b/drivers/staging/vt6655/device.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: MAC Data structure + * + * Author: Tevin Chen + * + * Date: Mar 17, 1997 + * + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/interrupt.h> +#include <linux/crc32.h> +#include <net/mac80211.h> + +/* device specific */ + +#include "device_cfg.h" +#include "card.h" +#include "srom.h" +#include "desc.h" +#include "key.h" +#include "mac.h" + +/*--------------------- Export Definitions -------------------------*/ + +#define RATE_1M 0 +#define RATE_2M 1 +#define RATE_5M 2 +#define RATE_11M 3 +#define RATE_6M 4 +#define RATE_9M 5 +#define RATE_12M 6 +#define RATE_18M 7 +#define RATE_24M 8 +#define RATE_36M 9 +#define RATE_48M 10 +#define RATE_54M 11 +#define MAX_RATE 12 + +#define AUTO_FB_NONE 0 +#define AUTO_FB_0 1 +#define AUTO_FB_1 2 + +#define FB_RATE0 0 +#define FB_RATE1 1 + +/* Antenna Mode */ +#define ANT_A 0 +#define ANT_B 1 +#define ANT_DIVERSITY 2 +#define ANT_RXD_TXA 3 +#define ANT_RXD_TXB 4 +#define ANT_UNKNOWN 0xFF + +#define BB_VGA_LEVEL 4 +#define BB_VGA_CHANGE_THRESHOLD 16 + +#define MAKE_BEACON_RESERVED 10 /* (us) */ + +/* BUILD OBJ mode */ + +#define AVAIL_TD(p, q) ((p)->opts.tx_descs[(q)] - ((p)->iTDUsed[(q)])) + +/* 0:11A 1:11B 2:11G */ +#define BB_TYPE_11A 0 +#define BB_TYPE_11B 1 +#define BB_TYPE_11G 2 + +/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */ +#define PK_TYPE_11A 0 +#define PK_TYPE_11B 1 +#define PK_TYPE_11GB 2 +#define PK_TYPE_11GA 3 + +#define OWNED_BY_HOST 0 +#define OWNED_BY_NIC 1 + +struct vnt_options { + int rx_descs0; /* Number of RX descriptors0 */ + int rx_descs1; /* Number of RX descriptors1 */ + int tx_descs[2]; /* Number of TX descriptors 0, 1 */ + int int_works; /* interrupt limits */ + int short_retry; + int long_retry; + int bbp_type; + u32 flags; +}; + +struct vnt_private { + struct pci_dev *pcid; + /* mac80211 */ + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + unsigned long key_entry_inuse; + u32 basic_rates; + u16 current_aid; + int mc_list_count; + u8 mac_hw; + +/* dma addr, rx/tx pool */ + dma_addr_t pool_dma; + dma_addr_t rd0_pool_dma; + dma_addr_t rd1_pool_dma; + + dma_addr_t td0_pool_dma; + dma_addr_t td1_pool_dma; + + dma_addr_t tx_bufs_dma0; + dma_addr_t tx_bufs_dma1; + dma_addr_t tx_beacon_dma; + + unsigned char *tx0_bufs; + unsigned char *tx1_bufs; + unsigned char *tx_beacon_bufs; + + void __iomem *port_offset; + u32 memaddr; + u32 ioaddr; + + spinlock_t lock; + + volatile int iTDUsed[TYPE_MAXTD]; + + struct vnt_tx_desc *apCurrTD[TYPE_MAXTD]; + struct vnt_tx_desc *apTailTD[TYPE_MAXTD]; + + struct vnt_tx_desc *apTD0Rings; + struct vnt_tx_desc *apTD1Rings; + + struct vnt_rx_desc *aRD0Ring; + struct vnt_rx_desc *aRD1Ring; + struct vnt_rx_desc *pCurrRD[TYPE_MAXRD]; + + struct vnt_options opts; + + u32 flags; + + u32 rx_buf_sz; + u8 rx_rate; + + u32 rx_bytes; + + /* Version control */ + unsigned char local_id; + unsigned char byRFType; + + unsigned char max_pwr_level; + unsigned char byZoneType; + bool bZoneRegExist; + unsigned char byOriginalZonetype; + + unsigned char abyCurrentNetAddr[ETH_ALEN]; __aligned(2) + bool bLinkPass; /* link status: OK or fail */ + + unsigned int current_rssi; + unsigned char byCurrSQ; + + unsigned long dwTxAntennaSel; + unsigned long dwRxAntennaSel; + unsigned char byAntennaCount; + unsigned char byRxAntennaMode; + unsigned char byTxAntennaMode; + bool bTxRxAntInv; + + unsigned char *pbyTmpBuff; + unsigned int uSIFS; /* Current SIFS */ + unsigned int uDIFS; /* Current DIFS */ + unsigned int uEIFS; /* Current EIFS */ + unsigned int uSlot; /* Current SlotTime */ + unsigned int uCwMin; /* Current CwMin */ + unsigned int uCwMax; /* CwMax is fixed on 1023. */ + /* PHY parameter */ + unsigned char bySIFS; + unsigned char byDIFS; + unsigned char byEIFS; + unsigned char bySlot; + unsigned char byCWMaxMin; + + u8 byBBType; /* 0:11A, 1:11B, 2:11G */ + u8 byPacketType; /* + * 0:11a,1:11b,2:11gb (only CCK + * in BasicRate), 3:11ga (OFDM in + * Basic Rate) + */ + unsigned short wBasicRate; + unsigned char byACKRate; + unsigned char byTopOFDMBasicRate; + unsigned char byTopCCKBasicRate; + + unsigned char byMinChannel; + unsigned char byMaxChannel; + + unsigned char preamble_type; + unsigned char byShortPreamble; + + unsigned short wCurrentRate; + unsigned char byShortRetryLimit; + unsigned char byLongRetryLimit; + enum nl80211_iftype op_mode; + bool bBSSIDFilter; + unsigned short wMaxTransmitMSDULifetime; + + bool bEncryptionEnable; + bool bLongHeader; + bool short_slot_time; + bool bProtectMode; + bool bNonERPPresent; + bool bBarkerPreambleMd; + + bool bRadioControlOff; + bool radio_off; + bool bEnablePSMode; + unsigned short wListenInterval; + bool bPWBitOn; + + /* GPIO Radio Control */ + unsigned char byRadioCtl; + unsigned char byGPIO; + bool hw_radio_off; + bool bPrvActive4RadioOFF; + bool bGPIOBlockRead; + + /* Beacon related */ + unsigned short wSeqCounter; + unsigned short wBCNBufLen; + bool bBeaconBufReady; + bool bBeaconSent; + bool bIsBeaconBufReadySet; + unsigned int cbBeaconBufReadySetCnt; + bool bFixRate; + u16 byCurrentCh; + + bool bAES; + + unsigned char byAutoFBCtrl; + + /* For Update BaseBand VGA Gain Offset */ + bool bUpdateBBVGA; + unsigned int uBBVGADiffCount; + unsigned char byBBVGANew; + unsigned char byBBVGACurrent; + unsigned char abyBBVGA[BB_VGA_LEVEL]; + long dbm_threshold[BB_VGA_LEVEL]; + + unsigned char byBBPreEDRSSI; + unsigned char byBBPreEDIndex; + + unsigned long dwDiagRefCount; + + /* For FOE Tuning */ + unsigned char byFOETuning; + + /* For RF Power table */ + unsigned char byCCKPwr; + unsigned char byOFDMPwrG; + unsigned char byCurPwr; + char byCurPwrdBm; + unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G + 1]; + unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL + 1]; + char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G + 1]; + char abyOFDMDefaultPwr[CB_MAX_CHANNEL + 1]; + char abyRegPwr[CB_MAX_CHANNEL + 1]; + char abyLocalPwr[CB_MAX_CHANNEL + 1]; + + /* BaseBand Loopback Use */ + unsigned char byBBCR4d; + unsigned char byBBCRc9; + unsigned char byBBCR88; + unsigned char byBBCR09; + + unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */ + + unsigned short wBeaconInterval; + u16 wake_up_count; + + struct work_struct interrupt_work; + + struct ieee80211_low_level_stats low_stats; +}; + +#endif diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h new file mode 100644 index 000000000..2d647a361 --- /dev/null +++ b/drivers/staging/vt6655/device_cfg.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Driver configuration header + * Author: Lyndon Chen + * + * Date: Dec 17, 2002 + * + */ + +#ifndef __DEVICE_CONFIG_H +#define __DEVICE_CONFIG_H + +#include <linux/types.h> + +#define VID_TABLE_SIZE 64 +#define MCAST_TABLE_SIZE 64 +#define MCAM_SIZE 32 +#define VCAM_SIZE 32 +#define TX_QUEUE_NO 8 + +#define DEVICE_NAME "vt6655" +#define DEVICE_FULL_DRV_NAM "VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver" + +#ifndef MAJOR_VERSION +#define MAJOR_VERSION 1 +#endif + +#ifndef MINOR_VERSION +#define MINOR_VERSION 17 +#endif + +#ifndef DEVICE_VERSION +#define DEVICE_VERSION "1.19.12" +#endif + +#include <linux/fs.h> +#include <linux/fcntl.h> + +#define PKT_BUF_SZ 2390 + +#endif diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c new file mode 100644 index 000000000..56c3cf3ba --- /dev/null +++ b/drivers/staging/vt6655/device_main.c @@ -0,0 +1,1863 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: driver entry for initial, open, close, tx and rx. + * + * Author: Lyndon Chen + * + * Date: Jan 8, 2003 + * + * Functions: + * + * vt6655_probe - module initial (insmod) driver entry + * vt6655_remove - module remove entry + * device_free_info - device structure resource free function + * device_print_info - print out resource + * device_rx_srv - rx service function + * device_alloc_rx_buf - rx buffer pre-allocated function + * device_free_rx_buf - free rx buffer function + * device_free_tx_buf - free tx buffer function + * device_init_rd0_ring - initial rd dma0 ring + * device_init_rd1_ring - initial rd dma1 ring + * device_init_td0_ring - initial tx dma0 ring buffer + * device_init_td1_ring - initial tx dma1 ring buffer + * device_init_registers - initial MAC & BBP & RF internal registers. + * device_init_rings - initial tx/rx ring buffer + * device_free_rings - free all allocated ring buffer + * device_tx_srv - tx interrupt service function + * + * Revision History: + */ + +#include <linux/file.h> +#include "device.h" +#include "card.h" +#include "channel.h" +#include "baseband.h" +#include "mac.h" +#include "power.h" +#include "rxtx.h" +#include "dpc.h" +#include "rf.h" +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/slab.h> + +/*--------------------- Static Definitions -------------------------*/ +/* + * Define module options + */ +MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); + +#define DEVICE_PARAM(N, D) + +#define RX_DESC_MIN0 16 +#define RX_DESC_MAX0 128 +#define RX_DESC_DEF0 32 +DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0"); + +#define RX_DESC_MIN1 16 +#define RX_DESC_MAX1 128 +#define RX_DESC_DEF1 32 +DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1"); + +#define TX_DESC_MIN0 16 +#define TX_DESC_MAX0 128 +#define TX_DESC_DEF0 32 +DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0"); + +#define TX_DESC_MIN1 16 +#define TX_DESC_MAX1 128 +#define TX_DESC_DEF1 64 +DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1"); + +#define INT_WORKS_DEF 20 +#define INT_WORKS_MIN 10 +#define INT_WORKS_MAX 64 + +DEVICE_PARAM(int_works, "Number of packets per interrupt services"); + +#define RTS_THRESH_DEF 2347 + +#define FRAG_THRESH_DEF 2346 + +#define SHORT_RETRY_MIN 0 +#define SHORT_RETRY_MAX 31 +#define SHORT_RETRY_DEF 8 + +DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); + +#define LONG_RETRY_MIN 0 +#define LONG_RETRY_MAX 15 +#define LONG_RETRY_DEF 4 + +DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); + +/* BasebandType[] baseband type selected + * 0: indicate 802.11a type + * 1: indicate 802.11b type + * 2: indicate 802.11g type + */ +#define BBP_TYPE_MIN 0 +#define BBP_TYPE_MAX 2 +#define BBP_TYPE_DEF 2 + +DEVICE_PARAM(BasebandType, "baseband type"); + +/* + * Static vars definitions + */ +static const struct pci_device_id vt6655_pci_id_table[] = { + { PCI_VDEVICE(VIA, 0x3253) }, + { 0, } +}; + +/*--------------------- Static Functions --------------------------*/ + +static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); +static void device_free_info(struct vnt_private *priv); +static void device_print_info(struct vnt_private *priv); + +static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr); +static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr); + +static int device_init_rd0_ring(struct vnt_private *priv); +static int device_init_rd1_ring(struct vnt_private *priv); +static int device_init_td0_ring(struct vnt_private *priv); +static int device_init_td1_ring(struct vnt_private *priv); + +static int device_rx_srv(struct vnt_private *priv, unsigned int idx); +static int device_tx_srv(struct vnt_private *priv, unsigned int idx); +static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *); +static void device_free_rx_buf(struct vnt_private *priv, + struct vnt_rx_desc *rd); +static void device_init_registers(struct vnt_private *priv); +static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *); +static void device_free_td0_ring(struct vnt_private *priv); +static void device_free_td1_ring(struct vnt_private *priv); +static void device_free_rd0_ring(struct vnt_private *priv); +static void device_free_rd1_ring(struct vnt_private *priv); +static void device_free_rings(struct vnt_private *priv); + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +static void vt6655_remove(struct pci_dev *pcid) +{ + struct vnt_private *priv = pci_get_drvdata(pcid); + + if (!priv) + return; + device_free_info(priv); +} + +static void device_get_options(struct vnt_private *priv) +{ + struct vnt_options *opts = &priv->opts; + + opts->rx_descs0 = RX_DESC_DEF0; + opts->rx_descs1 = RX_DESC_DEF1; + opts->tx_descs[0] = TX_DESC_DEF0; + opts->tx_descs[1] = TX_DESC_DEF1; + opts->int_works = INT_WORKS_DEF; + + opts->short_retry = SHORT_RETRY_DEF; + opts->long_retry = LONG_RETRY_DEF; + opts->bbp_type = BBP_TYPE_DEF; +} + +static void +device_set_options(struct vnt_private *priv) +{ + priv->byShortRetryLimit = priv->opts.short_retry; + priv->byLongRetryLimit = priv->opts.long_retry; + priv->byBBType = priv->opts.bbp_type; + priv->byPacketType = priv->byBBType; + priv->byAutoFBCtrl = AUTO_FB_0; + priv->bUpdateBBVGA = true; + priv->preamble_type = 0; + + pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit); + pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit); + pr_debug(" preamble_type= %d\n", (int)priv->preamble_type); + pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble); + pr_debug(" byBBType= %d\n", (int)priv->byBBType); +} + +static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr) +{ + iowrite8(1, iobase + MAC_REG_PAGE1SEL); + for (int i = 0; i < 6; i++) + iowrite8(mac_addr[i], iobase + MAC_REG_BSSID0 + i); + iowrite8(0, iobase + MAC_REG_PAGE1SEL); +} + +static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr) +{ + iowrite8(1, iobase + MAC_REG_PAGE1SEL); + for (int i = 0; i < 6; i++) + mac_addr[i] = ioread8(iobase + MAC_REG_PAR0 + i); + iowrite8(0, iobase + MAC_REG_PAGE1SEL); +} + +static void vt6655_mac_dma_ctl(void __iomem *iobase, u8 reg_index) +{ + u32 reg_value; + + reg_value = ioread32(iobase + reg_index); + if (reg_value & DMACTL_RUN) + iowrite32(DMACTL_WAKE, iobase + reg_index); + else + iowrite32(DMACTL_RUN, iobase + reg_index); +} + +static void vt6655_mac_set_bits(void __iomem *iobase, u32 mask) +{ + u32 reg_value; + + reg_value = ioread32(iobase + MAC_REG_ENCFG); + reg_value = reg_value | mask; + iowrite32(reg_value, iobase + MAC_REG_ENCFG); +} + +static void vt6655_mac_clear_bits(void __iomem *iobase, u32 mask) +{ + u32 reg_value; + + reg_value = ioread32(iobase + MAC_REG_ENCFG); + reg_value = reg_value & ~mask; + iowrite32(reg_value, iobase + MAC_REG_ENCFG); +} + +static void vt6655_mac_en_protect_md(void __iomem *iobase) +{ + vt6655_mac_set_bits(iobase, ENCFG_PROTECTMD); +} + +static void vt6655_mac_dis_protect_md(void __iomem *iobase) +{ + vt6655_mac_clear_bits(iobase, ENCFG_PROTECTMD); +} + +static void vt6655_mac_en_barker_preamble_md(void __iomem *iobase) +{ + vt6655_mac_set_bits(iobase, ENCFG_BARKERPREAM); +} + +static void vt6655_mac_dis_barker_preamble_md(void __iomem *iobase) +{ + vt6655_mac_clear_bits(iobase, ENCFG_BARKERPREAM); +} + +/* + * Initialisation of MAC & BBP registers + */ + +static void device_init_registers(struct vnt_private *priv) +{ + unsigned long flags; + unsigned int ii; + unsigned char byValue; + unsigned char byCCKPwrdBm = 0; + unsigned char byOFDMPwrdBm = 0; + + MACbShutdown(priv); + bb_software_reset(priv); + + /* Do MACbSoftwareReset in MACvInitialize */ + MACbSoftwareReset(priv); + + priv->bAES = false; + + /* Only used in 11g type, sync with ERP IE */ + priv->bProtectMode = false; + + priv->bNonERPPresent = false; + priv->bBarkerPreambleMd = false; + priv->wCurrentRate = RATE_1M; + priv->byTopOFDMBasicRate = RATE_24M; + priv->byTopCCKBasicRate = RATE_1M; + + /* init MAC */ + MACvInitialize(priv); + + /* Get Local ID */ + priv->local_id = ioread8(priv->port_offset + MAC_REG_LOCALID); + + spin_lock_irqsave(&priv->lock, flags); + + SROMvReadAllContents(priv->port_offset, priv->abyEEPROM); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Get Channel range */ + priv->byMinChannel = 1; + priv->byMaxChannel = CB_MAX_CHANNEL; + + /* Get Antena */ + byValue = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_ANTENNA); + if (byValue & EEP_ANTINV) + priv->bTxRxAntInv = true; + else + priv->bTxRxAntInv = false; + + byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + /* if not set default is All */ + if (byValue == 0) + byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + + if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { + priv->byAntennaCount = 2; + priv->byTxAntennaMode = ANT_B; + priv->dwTxAntennaSel = 1; + priv->dwRxAntennaSel = 1; + + if (priv->bTxRxAntInv) + priv->byRxAntennaMode = ANT_A; + else + priv->byRxAntennaMode = ANT_B; + } else { + priv->byAntennaCount = 1; + priv->dwTxAntennaSel = 0; + priv->dwRxAntennaSel = 0; + + if (byValue & EEP_ANTENNA_AUX) { + priv->byTxAntennaMode = ANT_A; + + if (priv->bTxRxAntInv) + priv->byRxAntennaMode = ANT_B; + else + priv->byRxAntennaMode = ANT_A; + } else { + priv->byTxAntennaMode = ANT_B; + + if (priv->bTxRxAntInv) + priv->byRxAntennaMode = ANT_A; + else + priv->byRxAntennaMode = ANT_B; + } + } + + /* Set initial antenna mode */ + bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode); + bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode); + + /* zonetype initial */ + priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE]; + + if (!priv->bZoneRegExist) + priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE]; + + pr_debug("priv->byZoneType = %x\n", priv->byZoneType); + + /* Init RF module */ + RFbInit(priv); + + /* Get Desire Power Value */ + priv->byCurPwr = 0xFF; + priv->byCCKPwr = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_PWR_CCK); + priv->byOFDMPwrG = SROMbyReadEmbedded(priv->port_offset, + EEP_OFS_PWR_OFDMG); + + /* Load power Table */ + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + priv->abyCCKPwrTbl[ii + 1] = + SROMbyReadEmbedded(priv->port_offset, + (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL)); + if (priv->abyCCKPwrTbl[ii + 1] == 0) + priv->abyCCKPwrTbl[ii + 1] = priv->byCCKPwr; + + priv->abyOFDMPwrTbl[ii + 1] = + SROMbyReadEmbedded(priv->port_offset, + (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL)); + if (priv->abyOFDMPwrTbl[ii + 1] == 0) + priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG; + + priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm; + priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm; + } + + /* recover 12,13 ,14channel for EUROPE by 11 channel */ + for (ii = 11; ii < 14; ii++) { + priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10]; + priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10]; + } + + /* Load OFDM A Power Table */ + for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { + priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = + SROMbyReadEmbedded(priv->port_offset, + (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL)); + + priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = + SROMbyReadEmbedded(priv->port_offset, + (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm)); + } + + if (priv->local_id > REV_ID_VT3253_B1) { + VT6655_MAC_SELECT_PAGE1(priv->port_offset); + + iowrite8(MSRCTL1_TXPWR | MSRCTL1_CSAPAREN, priv->port_offset + MAC_REG_MSRCTL + 1); + + VT6655_MAC_SELECT_PAGE0(priv->port_offset); + } + + /* use relative tx timeout and 802.11i D4 */ + vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_CFG, + (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); + + /* set performance parameter by registry */ + vt6655_mac_set_short_retry_limit(priv, priv->byShortRetryLimit); + MACvSetLongRetryLimit(priv, priv->byLongRetryLimit); + + /* reset TSF counter */ + iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); + /* enable TSF counter */ + iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); + + /* initialize BBP registers */ + bb_vt3253_init(priv); + + if (priv->bUpdateBBVGA) { + priv->byBBVGACurrent = priv->abyBBVGA[0]; + priv->byBBVGANew = priv->byBBVGACurrent; + bb_set_vga_gain_offset(priv, priv->abyBBVGA[0]); + } + + bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode); + bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode); + + /* Set BB and packet type at the same time. */ + /* Set Short Slot Time, xIFS, and RSPINF. */ + priv->wCurrentRate = RATE_54M; + + priv->radio_off = false; + + priv->byRadioCtl = SROMbyReadEmbedded(priv->port_offset, + EEP_OFS_RADIOCTL); + priv->hw_radio_off = false; + + if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) { + /* Get GPIO */ + priv->byGPIO = ioread8(priv->port_offset + MAC_REG_GPIOCTL1); + + if (((priv->byGPIO & GPIO0_DATA) && + !(priv->byRadioCtl & EEP_RADIOCTL_INV)) || + (!(priv->byGPIO & GPIO0_DATA) && + (priv->byRadioCtl & EEP_RADIOCTL_INV))) + priv->hw_radio_off = true; + } + + if (priv->hw_radio_off || priv->bRadioControlOff) + CARDbRadioPowerOff(priv); + + /* get Permanent network address */ + SROMvReadEtherAddress(priv->port_offset, priv->abyCurrentNetAddr); + pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr); + + /* reset Tx pointer */ + CARDvSafeResetRx(priv); + /* reset Rx pointer */ + CARDvSafeResetTx(priv); + + if (priv->local_id <= REV_ID_VT3253_A1) + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_RCR, RCR_WPAERR); + + /* Turn On Rx DMA */ + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0); + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1); + + /* start the adapter */ + iowrite8(HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON, priv->port_offset + MAC_REG_HOSTCR); +} + +static void device_print_info(struct vnt_private *priv) +{ + dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n", + priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr, + (unsigned long)priv->port_offset, priv->pcid->irq); +} + +static void device_free_info(struct vnt_private *priv) +{ + if (!priv) + return; + + if (priv->mac_hw) + ieee80211_unregister_hw(priv->hw); + + if (priv->port_offset) + iounmap(priv->port_offset); + + if (priv->pcid) + pci_release_regions(priv->pcid); + + if (priv->hw) + ieee80211_free_hw(priv->hw); +} + +static bool device_init_rings(struct vnt_private *priv) +{ + void *vir_pool; + + /*allocate all RD/TD rings a single pool*/ + vir_pool = dma_alloc_coherent(&priv->pcid->dev, + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), + &priv->pool_dma, GFP_ATOMIC); + if (!vir_pool) { + dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n"); + return false; + } + + priv->aRD0Ring = vir_pool; + priv->aRD1Ring = vir_pool + + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); + + priv->rd0_pool_dma = priv->pool_dma; + priv->rd1_pool_dma = priv->rd0_pool_dma + + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); + + priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev, + priv->opts.tx_descs[0] * PKT_BUF_SZ + + priv->opts.tx_descs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + &priv->tx_bufs_dma0, GFP_ATOMIC); + if (!priv->tx0_bufs) { + dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); + + dma_free_coherent(&priv->pcid->dev, + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), + vir_pool, priv->pool_dma); + return false; + } + + priv->td0_pool_dma = priv->rd1_pool_dma + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); + + priv->td1_pool_dma = priv->td0_pool_dma + + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); + + /* vir_pool: pvoid type */ + priv->apTD0Rings = vir_pool + + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); + + priv->apTD1Rings = vir_pool + + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); + + priv->tx1_bufs = priv->tx0_bufs + + priv->opts.tx_descs[0] * PKT_BUF_SZ; + + priv->tx_beacon_bufs = priv->tx1_bufs + + priv->opts.tx_descs[1] * PKT_BUF_SZ; + + priv->pbyTmpBuff = priv->tx_beacon_bufs + + CB_BEACON_BUF_SIZE; + + priv->tx_bufs_dma1 = priv->tx_bufs_dma0 + + priv->opts.tx_descs[0] * PKT_BUF_SZ; + + priv->tx_beacon_dma = priv->tx_bufs_dma1 + + priv->opts.tx_descs[1] * PKT_BUF_SZ; + + return true; +} + +static void device_free_rings(struct vnt_private *priv) +{ + dma_free_coherent(&priv->pcid->dev, + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), + priv->aRD0Ring, priv->pool_dma); + + dma_free_coherent(&priv->pcid->dev, + priv->opts.tx_descs[0] * PKT_BUF_SZ + + priv->opts.tx_descs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + priv->tx0_bufs, priv->tx_bufs_dma0); +} + +static int device_init_rd0_ring(struct vnt_private *priv) +{ + int i; + dma_addr_t curr = priv->rd0_pool_dma; + struct vnt_rx_desc *desc; + int ret; + + /* Init the RD0 ring entries */ + for (i = 0; i < priv->opts.rx_descs0; + i ++, curr += sizeof(struct vnt_rx_desc)) { + desc = &priv->aRD0Ring[i]; + desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); + if (!desc->rd_info) { + ret = -ENOMEM; + goto err_free_desc; + } + + if (!device_alloc_rx_buf(priv, desc)) { + dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); + ret = -ENOMEM; + goto err_free_rd; + } + + desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0]; + desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); + } + + if (i > 0) + priv->aRD0Ring[i - 1].next_desc = cpu_to_le32(priv->rd0_pool_dma); + priv->pCurrRD[0] = &priv->aRD0Ring[0]; + + return 0; + +err_free_rd: + kfree(desc->rd_info); + +err_free_desc: + while (i--) { + desc = &priv->aRD0Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } + + return ret; +} + +static int device_init_rd1_ring(struct vnt_private *priv) +{ + int i; + dma_addr_t curr = priv->rd1_pool_dma; + struct vnt_rx_desc *desc; + int ret; + + /* Init the RD1 ring entries */ + for (i = 0; i < priv->opts.rx_descs1; + i ++, curr += sizeof(struct vnt_rx_desc)) { + desc = &priv->aRD1Ring[i]; + desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); + if (!desc->rd_info) { + ret = -ENOMEM; + goto err_free_desc; + } + + if (!device_alloc_rx_buf(priv, desc)) { + dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); + ret = -ENOMEM; + goto err_free_rd; + } + + desc->next = &priv->aRD1Ring[(i + 1) % priv->opts.rx_descs1]; + desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); + } + + if (i > 0) + priv->aRD1Ring[i - 1].next_desc = cpu_to_le32(priv->rd1_pool_dma); + priv->pCurrRD[1] = &priv->aRD1Ring[0]; + + return 0; + +err_free_rd: + kfree(desc->rd_info); + +err_free_desc: + while (i--) { + desc = &priv->aRD1Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } + + return ret; +} + +static void device_free_rd0_ring(struct vnt_private *priv) +{ + int i; + + for (i = 0; i < priv->opts.rx_descs0; i++) { + struct vnt_rx_desc *desc = &priv->aRD0Ring[i]; + + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } +} + +static void device_free_rd1_ring(struct vnt_private *priv) +{ + int i; + + for (i = 0; i < priv->opts.rx_descs1; i++) { + struct vnt_rx_desc *desc = &priv->aRD1Ring[i]; + + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } +} + +static int device_init_td0_ring(struct vnt_private *priv) +{ + int i; + dma_addr_t curr; + struct vnt_tx_desc *desc; + int ret; + + curr = priv->td0_pool_dma; + for (i = 0; i < priv->opts.tx_descs[0]; + i++, curr += sizeof(struct vnt_tx_desc)) { + desc = &priv->apTD0Rings[i]; + desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); + if (!desc->td_info) { + ret = -ENOMEM; + goto err_free_desc; + } + + desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ; + desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ; + + desc->next = &(priv->apTD0Rings[(i + 1) % priv->opts.tx_descs[0]]); + desc->next_desc = cpu_to_le32(curr + + sizeof(struct vnt_tx_desc)); + } + + if (i > 0) + priv->apTD0Rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma); + priv->apTailTD[0] = priv->apCurrTD[0] = &priv->apTD0Rings[0]; + + return 0; + +err_free_desc: + while (i--) { + desc = &priv->apTD0Rings[i]; + kfree(desc->td_info); + } + + return ret; +} + +static int device_init_td1_ring(struct vnt_private *priv) +{ + int i; + dma_addr_t curr; + struct vnt_tx_desc *desc; + int ret; + + /* Init the TD ring entries */ + curr = priv->td1_pool_dma; + for (i = 0; i < priv->opts.tx_descs[1]; + i++, curr += sizeof(struct vnt_tx_desc)) { + desc = &priv->apTD1Rings[i]; + desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); + if (!desc->td_info) { + ret = -ENOMEM; + goto err_free_desc; + } + + desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ; + desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ; + + desc->next = &(priv->apTD1Rings[(i + 1) % priv->opts.tx_descs[1]]); + desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc)); + } + + if (i > 0) + priv->apTD1Rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma); + priv->apTailTD[1] = priv->apCurrTD[1] = &priv->apTD1Rings[0]; + + return 0; + +err_free_desc: + while (i--) { + desc = &priv->apTD1Rings[i]; + kfree(desc->td_info); + } + + return ret; +} + +static void device_free_td0_ring(struct vnt_private *priv) +{ + int i; + + for (i = 0; i < priv->opts.tx_descs[0]; i++) { + struct vnt_tx_desc *desc = &priv->apTD0Rings[i]; + struct vnt_td_info *td_info = desc->td_info; + + dev_kfree_skb(td_info->skb); + kfree(desc->td_info); + } +} + +static void device_free_td1_ring(struct vnt_private *priv) +{ + int i; + + for (i = 0; i < priv->opts.tx_descs[1]; i++) { + struct vnt_tx_desc *desc = &priv->apTD1Rings[i]; + struct vnt_td_info *td_info = desc->td_info; + + dev_kfree_skb(td_info->skb); + kfree(desc->td_info); + } +} + +/*-----------------------------------------------------------------*/ + +static int device_rx_srv(struct vnt_private *priv, unsigned int idx) +{ + struct vnt_rx_desc *rd; + int works = 0; + + for (rd = priv->pCurrRD[idx]; + rd->rd0.owner == OWNED_BY_HOST; + rd = rd->next) { + if (works++ > 15) + break; + + if (!rd->rd_info->skb) + break; + + if (vnt_receive_frame(priv, rd)) { + if (!device_alloc_rx_buf(priv, rd)) { + dev_err(&priv->pcid->dev, + "can not allocate rx buf\n"); + break; + } + } + rd->rd0.owner = OWNED_BY_NIC; + } + + priv->pCurrRD[idx] = rd; + + return works; +} + +static bool device_alloc_rx_buf(struct vnt_private *priv, + struct vnt_rx_desc *rd) +{ + struct vnt_rd_info *rd_info = rd->rd_info; + + rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz); + if (!rd_info->skb) + return false; + + rd_info->skb_dma = + dma_map_single(&priv->pcid->dev, + skb_put(rd_info->skb, skb_tailroom(rd_info->skb)), + priv->rx_buf_sz, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) { + dev_kfree_skb(rd_info->skb); + rd_info->skb = NULL; + return false; + } + + *((unsigned int *)&rd->rd0) = 0; /* FIX cast */ + + rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); + rd->rd0.owner = OWNED_BY_NIC; + rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); + rd->buff_addr = cpu_to_le32(rd_info->skb_dma); + + return true; +} + +static void device_free_rx_buf(struct vnt_private *priv, + struct vnt_rx_desc *rd) +{ + struct vnt_rd_info *rd_info = rd->rd_info; + + dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, + priv->rx_buf_sz, DMA_FROM_DEVICE); + dev_kfree_skb(rd_info->skb); +} + +static const u8 fallback_rate0[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, + {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, + {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} +}; + +static const u8 fallback_rate1[5][5] = { + {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, + {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, + {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, + {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} +}; + +static int vnt_int_report_rate(struct vnt_private *priv, + struct vnt_td_info *context, u8 tsr0, u8 tsr1) +{ + struct vnt_tx_fifo_head *fifo_head; + struct ieee80211_tx_info *info; + struct ieee80211_rate *rate; + u16 fb_option; + u8 tx_retry = (tsr0 & TSR0_NCR); + s8 idx; + + if (!context) + return -ENOMEM; + + if (!context->skb) + return -EINVAL; + + fifo_head = (struct vnt_tx_fifo_head *)context->buf; + fb_option = (le16_to_cpu(fifo_head->fifo_ctl) & + (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1)); + + info = IEEE80211_SKB_CB(context->skb); + idx = info->control.rates[0].idx; + + if (fb_option && !(tsr1 & TSR1_TERR)) { + u8 tx_rate; + u8 retry = tx_retry; + + rate = ieee80211_get_tx_rate(priv->hw, info); + tx_rate = rate->hw_value - RATE_18M; + + if (retry > 4) + retry = 4; + + if (fb_option & FIFOCTL_AUTO_FB_0) + tx_rate = fallback_rate0[tx_rate][retry]; + else if (fb_option & FIFOCTL_AUTO_FB_1) + tx_rate = fallback_rate1[tx_rate][retry]; + + if (info->band == NL80211_BAND_5GHZ) + idx = tx_rate - RATE_6M; + else + idx = tx_rate; + } + + ieee80211_tx_info_clear_status(info); + + info->status.rates[0].count = tx_retry; + + if (!(tsr1 & TSR1_TERR)) { + info->status.rates[0].idx = idx; + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + else + info->flags |= IEEE80211_TX_STAT_ACK; + } + + return 0; +} + +static int device_tx_srv(struct vnt_private *priv, unsigned int idx) +{ + struct vnt_tx_desc *desc; + int works = 0; + unsigned char byTsr0; + unsigned char byTsr1; + + for (desc = priv->apTailTD[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) { + if (desc->td0.owner == OWNED_BY_NIC) + break; + if (works++ > 15) + break; + + byTsr0 = desc->td0.tsr0; + byTsr1 = desc->td0.tsr1; + + /* Only the status of first TD in the chain is correct */ + if (desc->td1.tcr & TCR_STP) { + if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) { + if (!(byTsr1 & TSR1_TERR)) { + if (byTsr0 != 0) { + pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n", + (int)idx, byTsr1, + byTsr0); + } + } else { + pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n", + (int)idx, byTsr1, byTsr0); + } + } + + if (byTsr1 & TSR1_TERR) { + if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) { + pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n", + (int)idx, byTsr1, byTsr0); + } + } + + vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1); + + device_free_tx_buf(priv, desc); + priv->iTDUsed[idx]--; + } + } + + priv->apTailTD[idx] = desc; + + return works; +} + +static void device_error(struct vnt_private *priv, unsigned short status) +{ + if (status & ISR_FETALERR) { + dev_err(&priv->pcid->dev, "Hardware fatal error\n"); + + MACbShutdown(priv); + return; + } +} + +static void device_free_tx_buf(struct vnt_private *priv, + struct vnt_tx_desc *desc) +{ + struct vnt_td_info *td_info = desc->td_info; + struct sk_buff *skb = td_info->skb; + + if (skb) + ieee80211_tx_status_irqsafe(priv->hw, skb); + + td_info->skb = NULL; + td_info->flags = 0; +} + +static void vnt_check_bb_vga(struct vnt_private *priv) +{ + long dbm; + int i; + + if (!priv->bUpdateBBVGA) + return; + + if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + if (!(priv->vif->cfg.assoc && priv->current_rssi)) + return; + + RFvRSSITodBm(priv, (u8)priv->current_rssi, &dbm); + + for (i = 0; i < BB_VGA_LEVEL; i++) { + if (dbm < priv->dbm_threshold[i]) { + priv->byBBVGANew = priv->abyBBVGA[i]; + break; + } + } + + if (priv->byBBVGANew == priv->byBBVGACurrent) { + priv->uBBVGADiffCount = 1; + return; + } + + priv->uBBVGADiffCount++; + + if (priv->uBBVGADiffCount == 1) { + /* first VGA diff gain */ + bb_set_vga_gain_offset(priv, priv->byBBVGANew); + + dev_dbg(&priv->pcid->dev, + "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + } + + if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + dev_dbg(&priv->pcid->dev, + "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + + bb_set_vga_gain_offset(priv, priv->byBBVGANew); + } +} + +static void vnt_interrupt_process(struct vnt_private *priv) +{ + struct ieee80211_low_level_stats *low_stats = &priv->low_stats; + int max_count = 0; + u32 mib_counter; + u32 isr; + unsigned long flags; + + isr = ioread32(priv->port_offset + MAC_REG_ISR); + + if (isr == 0) + return; + + if (isr == 0xffffffff) { + pr_debug("isr = 0xffff\n"); + return; + } + + spin_lock_irqsave(&priv->lock, flags); + + /* Read low level stats */ + mib_counter = ioread32(priv->port_offset + MAC_REG_MIBCNTR); + + low_stats->dot11RTSSuccessCount += mib_counter & 0xff; + low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff; + low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff; + low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff; + + /* + * TBD.... + * Must do this after doing rx/tx, cause ISR bit is slow + * than RD/TD write back + * update ISR counter + */ + while (isr && priv->vif) { + iowrite32(isr, priv->port_offset + MAC_REG_ISR); + + if (isr & ISR_FETALERR) { + pr_debug(" ISR_FETALERR\n"); + iowrite8(0, priv->port_offset + MAC_REG_SOFTPWRCTL); + iowrite16(SOFTPWRCTL_SWPECTI, priv->port_offset + MAC_REG_SOFTPWRCTL); + device_error(priv, isr); + } + + if (isr & ISR_TBTT) { + if (priv->op_mode != NL80211_IFTYPE_ADHOC) + vnt_check_bb_vga(priv); + + priv->bBeaconSent = false; + if (priv->bEnablePSMode) + PSbIsNextTBTTWakeUp((void *)priv); + + if ((priv->op_mode == NL80211_IFTYPE_AP || + priv->op_mode == NL80211_IFTYPE_ADHOC) && + priv->vif->bss_conf.enable_beacon) + MACvOneShotTimer1MicroSec(priv, + (priv->vif->bss_conf.beacon_int - + MAKE_BEACON_RESERVED) << 10); + + /* TODO: adhoc PS mode */ + } + + if (isr & ISR_BNTX) { + if (priv->op_mode == NL80211_IFTYPE_ADHOC) { + priv->bIsBeaconBufReadySet = false; + priv->cbBeaconBufReadySetCnt = 0; + } + + priv->bBeaconSent = true; + } + + if (isr & ISR_RXDMA0) + max_count += device_rx_srv(priv, TYPE_RXDMA0); + + if (isr & ISR_RXDMA1) + max_count += device_rx_srv(priv, TYPE_RXDMA1); + + if (isr & ISR_TXDMA0) + max_count += device_tx_srv(priv, TYPE_TXDMA0); + + if (isr & ISR_AC0DMA) + max_count += device_tx_srv(priv, TYPE_AC0DMA); + + if (isr & ISR_SOFTTIMER1) { + if (priv->vif->bss_conf.enable_beacon) + vnt_beacon_make(priv, priv->vif); + } + + /* If both buffers available wake the queue */ + if (AVAIL_TD(priv, TYPE_TXDMA0) && + AVAIL_TD(priv, TYPE_AC0DMA) && + ieee80211_queue_stopped(priv->hw, 0)) + ieee80211_wake_queues(priv->hw); + + isr = ioread32(priv->port_offset + MAC_REG_ISR); + + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0); + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1); + + if (max_count > priv->opts.int_works) + break; + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void vnt_interrupt_work(struct work_struct *work) +{ + struct vnt_private *priv = + container_of(work, struct vnt_private, interrupt_work); + + if (priv->vif) + vnt_interrupt_process(priv); + + iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR); +} + +static irqreturn_t vnt_interrupt(int irq, void *arg) +{ + struct vnt_private *priv = arg; + + schedule_work(&priv->interrupt_work); + + iowrite32(0, priv->port_offset + MAC_REG_IMR); + + return IRQ_HANDLED; +} + +static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct vnt_tx_desc *head_td; + u32 dma_idx; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + if (ieee80211_is_data(hdr->frame_control)) + dma_idx = TYPE_AC0DMA; + else + dma_idx = TYPE_TXDMA0; + + if (AVAIL_TD(priv, dma_idx) < 1) { + spin_unlock_irqrestore(&priv->lock, flags); + ieee80211_stop_queues(priv->hw); + return -ENOMEM; + } + + head_td = priv->apCurrTD[dma_idx]; + + head_td->td1.tcr = 0; + + head_td->td_info->skb = skb; + + if (dma_idx == TYPE_AC0DMA) + head_td->td_info->flags = TD_FLAGS_NETIF_SKB; + + priv->apCurrTD[dma_idx] = head_td->next; + + spin_unlock_irqrestore(&priv->lock, flags); + + vnt_generate_fifo_header(priv, dma_idx, head_td, skb); + + spin_lock_irqsave(&priv->lock, flags); + + priv->bPWBitOn = false; + + /* Set TSR1 & ReqCount in TxDescHead */ + head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU); + head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count); + + head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma); + + /* Poll Transmit the adapter */ + wmb(); + head_td->td0.owner = OWNED_BY_NIC; + wmb(); /* second memory barrier */ + + if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB) + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_AC0DMACTL); + else + vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_TXDMACTL0); + + priv->iTDUsed[dma_idx]++; + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static void vnt_tx_80211(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct vnt_private *priv = hw->priv; + + if (vnt_tx_packet(priv, skb)) + ieee80211_free_txskb(hw, skb); +} + +static int vnt_start(struct ieee80211_hw *hw) +{ + struct vnt_private *priv = hw->priv; + int ret; + + priv->rx_buf_sz = PKT_BUF_SZ; + if (!device_init_rings(priv)) + return -ENOMEM; + + ret = request_irq(priv->pcid->irq, vnt_interrupt, + IRQF_SHARED, "vt6655", priv); + if (ret) { + dev_dbg(&priv->pcid->dev, "failed to start irq\n"); + goto err_free_rings; + } + + dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n"); + ret = device_init_rd0_ring(priv); + if (ret) + goto err_free_irq; + ret = device_init_rd1_ring(priv); + if (ret) + goto err_free_rd0_ring; + ret = device_init_td0_ring(priv); + if (ret) + goto err_free_rd1_ring; + ret = device_init_td1_ring(priv); + if (ret) + goto err_free_td0_ring; + + device_init_registers(priv); + + dev_dbg(&priv->pcid->dev, "enable MAC interrupt\n"); + iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR); + + ieee80211_wake_queues(hw); + + return 0; + +err_free_td0_ring: + device_free_td0_ring(priv); +err_free_rd1_ring: + device_free_rd1_ring(priv); +err_free_rd0_ring: + device_free_rd0_ring(priv); +err_free_irq: + free_irq(priv->pcid->irq, priv); +err_free_rings: + device_free_rings(priv); + return ret; +} + +static void vnt_stop(struct ieee80211_hw *hw) +{ + struct vnt_private *priv = hw->priv; + + ieee80211_stop_queues(hw); + + cancel_work_sync(&priv->interrupt_work); + + MACbShutdown(priv); + MACbSoftwareReset(priv); + CARDbRadioPowerOff(priv); + + device_free_td0_ring(priv); + device_free_td1_ring(priv); + device_free_rd0_ring(priv); + device_free_rd1_ring(priv); + device_free_rings(priv); + + free_irq(priv->pcid->irq, priv); +} + +static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct vnt_private *priv = hw->priv; + + priv->vif = vif; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_ADHOC: + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST); + + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC); + + break; + case NL80211_IFTYPE_AP: + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST); + + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP); + + break; + default: + return -EOPNOTSUPP; + } + + priv->op_mode = vif->type; + + return 0; +} + +static void vnt_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct vnt_private *priv = hw->priv; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_ADHOC: + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); + vt6655_mac_reg_bits_off(priv->port_offset, + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC); + break; + case NL80211_IFTYPE_AP: + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); + vt6655_mac_reg_bits_off(priv->port_offset, + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP); + break; + default: + break; + } + + priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; +} + +static int vnt_config(struct ieee80211_hw *hw, u32 changed) +{ + struct vnt_private *priv = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + u8 bb_type; + + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (conf->flags & IEEE80211_CONF_PS) + PSvEnablePowerSaving(priv, conf->listen_interval); + else + PSvDisablePowerSaving(priv); + } + + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || + (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { + set_channel(priv, conf->chandef.chan); + + if (conf->chandef.chan->band == NL80211_BAND_5GHZ) + bb_type = BB_TYPE_11A; + else + bb_type = BB_TYPE_11G; + + if (priv->byBBType != bb_type) { + priv->byBBType = bb_type; + + CARDbSetPhyParameter(priv, priv->byBBType); + } + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + if (priv->byBBType == BB_TYPE_11B) + priv->wCurrentRate = RATE_1M; + else + priv->wCurrentRate = RATE_54M; + + RFbSetPower(priv, priv->wCurrentRate, + conf->chandef.chan->hw_value); + } + + return 0; +} + +static void vnt_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf, u64 changed) +{ + struct vnt_private *priv = hw->priv; + + priv->current_aid = vif->cfg.aid; + + if (changed & BSS_CHANGED_BSSID && conf->bssid) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + vt6655_mac_write_bssid_addr(priv->port_offset, conf->bssid); + + spin_unlock_irqrestore(&priv->lock, flags); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + priv->basic_rates = conf->basic_rates; + + CARDvUpdateBasicTopRate(priv); + + dev_dbg(&priv->pcid->dev, + "basic rates %x\n", conf->basic_rates); + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + if (conf->use_short_preamble) { + vt6655_mac_en_barker_preamble_md(priv->port_offset); + priv->preamble_type = true; + } else { + vt6655_mac_dis_barker_preamble_md(priv->port_offset); + priv->preamble_type = false; + } + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + if (conf->use_cts_prot) + vt6655_mac_en_protect_md(priv->port_offset); + else + vt6655_mac_dis_protect_md(priv->port_offset); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + if (conf->use_short_slot) + priv->short_slot_time = true; + else + priv->short_slot_time = false; + + CARDbSetPhyParameter(priv, priv->byBBType); + bb_set_vga_gain_offset(priv, priv->abyBBVGA[0]); + } + + if (changed & BSS_CHANGED_TXPOWER) + RFbSetPower(priv, priv->wCurrentRate, + conf->chandef.chan->hw_value); + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + dev_dbg(&priv->pcid->dev, + "Beacon enable %d\n", conf->enable_beacon); + + if (conf->enable_beacon) { + vnt_beacon_enable(priv, vif, conf); + + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); + } else { + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, + TCR_AUTOBCNTX); + } + } + + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) && + priv->op_mode != NL80211_IFTYPE_AP) { + if (vif->cfg.assoc && conf->beacon_rate) { + CARDbUpdateTSF(priv, conf->beacon_rate->hw_value, + conf->sync_tsf); + + CARDbSetBeaconPeriod(priv, conf->beacon_int); + + CARDvSetFirstNextTBTT(priv, conf->beacon_int); + } else { + iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); + iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); + } + } +} + +static u64 vnt_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + struct vnt_private *priv = hw->priv; + struct netdev_hw_addr *ha; + u64 mc_filter = 0; + u32 bit_nr = 0; + + netdev_hw_addr_list_for_each(ha, mc_list) { + bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + + mc_filter |= 1ULL << (bit_nr & 0x3f); + } + + priv->mc_list_count = mc_list->count; + + return mc_filter; +} + +static void vnt_configure(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast) +{ + struct vnt_private *priv = hw->priv; + u8 rx_mode = 0; + + *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC; + + rx_mode = ioread8(priv->port_offset + MAC_REG_RCR); + + dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode); + + if (changed_flags & FIF_ALLMULTI) { + if (*total_flags & FIF_ALLMULTI) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->mc_list_count > 2) { + VT6655_MAC_SELECT_PAGE1(priv->port_offset); + + iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0); + iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0 + 4); + + VT6655_MAC_SELECT_PAGE0(priv->port_offset); + } else { + VT6655_MAC_SELECT_PAGE1(priv->port_offset); + + multicast = le64_to_cpu(multicast); + iowrite32((u32)multicast, priv->port_offset + MAC_REG_MAR0); + iowrite32((u32)(multicast >> 32), + priv->port_offset + MAC_REG_MAR0 + 4); + + VT6655_MAC_SELECT_PAGE0(priv->port_offset); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + rx_mode |= RCR_MULTICAST | RCR_BROADCAST; + } else { + rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); + } + } + + if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) { + rx_mode |= RCR_MULTICAST | RCR_BROADCAST; + + if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) + rx_mode &= ~RCR_BSSID; + else + rx_mode |= RCR_BSSID; + } + + iowrite8(rx_mode, priv->port_offset + MAC_REG_RCR); + + dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode); +} + +static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct vnt_private *priv = hw->priv; + + switch (cmd) { + case SET_KEY: + if (vnt_set_keys(hw, sta, vif, key)) + return -EOPNOTSUPP; + break; + case DISABLE_KEY: + if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) + clear_bit(key->hw_key_idx, &priv->key_entry_inuse); + break; + default: + break; + } + + return 0; +} + +static int vnt_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct vnt_private *priv = hw->priv; + + memcpy(stats, &priv->low_stats, sizeof(*stats)); + + return 0; +} + +static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct vnt_private *priv = hw->priv; + u64 tsf; + + tsf = vt6655_get_current_tsf(priv); + + return tsf; +} + +static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 tsf) +{ + struct vnt_private *priv = hw->priv; + + CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int); +} + +static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct vnt_private *priv = hw->priv; + + /* reset TSF counter */ + iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); +} + +static const struct ieee80211_ops vnt_mac_ops = { + .tx = vnt_tx_80211, + .start = vnt_start, + .stop = vnt_stop, + .add_interface = vnt_add_interface, + .remove_interface = vnt_remove_interface, + .config = vnt_config, + .bss_info_changed = vnt_bss_info_changed, + .prepare_multicast = vnt_prepare_multicast, + .configure_filter = vnt_configure, + .set_key = vnt_set_key, + .get_stats = vnt_get_stats, + .get_tsf = vnt_get_tsf, + .set_tsf = vnt_set_tsf, + .reset_tsf = vnt_reset_tsf, +}; + +static int vnt_init(struct vnt_private *priv) +{ + SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); + + vnt_init_bands(priv); + + if (ieee80211_register_hw(priv->hw)) + return -ENODEV; + + priv->mac_hw = true; + + CARDbRadioPowerOff(priv); + + return 0; +} + +static int +vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) +{ + struct vnt_private *priv; + struct ieee80211_hw *hw; + struct wiphy *wiphy; + int rc; + + dev_notice(&pcid->dev, + "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); + + dev_notice(&pcid->dev, + "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); + + hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops); + if (!hw) { + dev_err(&pcid->dev, "could not register ieee80211_hw\n"); + return -ENOMEM; + } + + priv = hw->priv; + priv->pcid = pcid; + + spin_lock_init(&priv->lock); + + priv->hw = hw; + + SET_IEEE80211_DEV(priv->hw, &pcid->dev); + + if (pci_enable_device(pcid)) { + device_free_info(priv); + return -ENODEV; + } + + dev_dbg(&pcid->dev, + "Before get pci_info memaddr is %x\n", priv->memaddr); + + pci_set_master(pcid); + + priv->memaddr = pci_resource_start(pcid, 0); + priv->ioaddr = pci_resource_start(pcid, 1); + priv->port_offset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK, + 256); + if (!priv->port_offset) { + dev_err(&pcid->dev, ": Failed to IO remapping ..\n"); + device_free_info(priv); + return -ENODEV; + } + + rc = pci_request_regions(pcid, DEVICE_NAME); + if (rc) { + dev_err(&pcid->dev, ": Failed to find PCI device\n"); + device_free_info(priv); + return -ENODEV; + } + + if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) { + dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n"); + device_free_info(priv); + return -ENODEV; + } + + INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); + + /* do reset */ + if (!MACbSoftwareReset(priv)) { + dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); + device_free_info(priv); + return -ENODEV; + } + /* initial to reload eeprom */ + MACvInitialize(priv); + vt6655_mac_read_ether_addr(priv->port_offset, priv->abyCurrentNetAddr); + + /* Get RFType */ + priv->byRFType = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_RFTYPE); + priv->byRFType &= RF_MASK; + + dev_dbg(&pcid->dev, "RF Type = %x\n", priv->byRFType); + + device_get_options(priv); + device_set_options(priv); + + wiphy = priv->hw->wiphy; + + wiphy->frag_threshold = FRAG_THRESH_DEF; + wiphy->rts_threshold = RTS_THRESH_DEF; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + + ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY); + ieee80211_hw_set(priv->hw, SIGNAL_DBM); + ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); + ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(priv->hw, SUPPORTS_PS); + + priv->hw->max_signal = 100; + + if (vnt_init(priv)) { + device_free_info(priv); + return -ENODEV; + } + + device_print_info(priv); + pci_set_drvdata(pcid, priv); + + return 0; +} + +/*------------------------------------------------------------------*/ + +static int __maybe_unused vt6655_suspend(struct device *dev_d) +{ + struct vnt_private *priv = dev_get_drvdata(dev_d); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + MACbShutdown(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int __maybe_unused vt6655_resume(struct device *dev_d) +{ + device_wakeup_disable(dev_d); + + return 0; +} + +MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); + +static SIMPLE_DEV_PM_OPS(vt6655_pm_ops, vt6655_suspend, vt6655_resume); + +static struct pci_driver device_driver = { + .name = DEVICE_NAME, + .id_table = vt6655_pci_id_table, + .probe = vt6655_probe, + .remove = vt6655_remove, + .driver.pm = &vt6655_pm_ops, +}; + +module_pci_driver(device_driver); diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c new file mode 100644 index 000000000..c6ed3537f --- /dev/null +++ b/drivers/staging/vt6655/dpc.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: handle dpc rx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + +#include "device.h" +#include "baseband.h" +#include "rf.h" +#include "dpc.h" + +static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, + u16 bytes_received) +{ + struct ieee80211_hw *hw = priv->hw; + struct ieee80211_supported_band *sband; + struct ieee80211_rx_status rx_status = { 0 }; + struct ieee80211_hdr *hdr; + __le16 fc; + u8 *rsr, *new_rsr, *rssi; + __le64 *tsf_time; + u16 frame_size; + int ii, r; + u8 *rx_rate; + u8 *skb_data; + u8 rate_idx = 0; + u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; + long rx_dbm; + + /* [31:16]RcvByteCount ( not include 4-byte Status ) */ + frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2))); + if (frame_size > 2346 || frame_size < 14) { + dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n"); + return false; + } + + skb_data = (u8 *)skb->data; + + rx_rate = skb_data + 1; + + sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; + + for (r = RATE_1M; r < MAX_RATE; r++) { + if (*rx_rate == rate[r]) + break; + } + + priv->rx_rate = r; + + for (ii = 0; ii < sband->n_bitrates; ii++) { + if (sband->bitrates[ii].hw_value == r) { + rate_idx = ii; + break; + } + } + + if (ii == sband->n_bitrates) { + dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate); + return false; + } + + tsf_time = (__le64 *)(skb_data + bytes_received - 12); + new_rsr = skb_data + bytes_received - 3; + rssi = skb_data + bytes_received - 2; + rsr = skb_data + bytes_received - 1; + if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) + return false; + + RFvRSSITodBm(priv, *rssi, &rx_dbm); + + priv->byBBPreEDRSSI = (u8)rx_dbm + 1; + priv->current_rssi = *rssi; + + skb_pull(skb, 4); + skb_trim(skb, frame_size); + + rx_status.mactime = le64_to_cpu(*tsf_time); + rx_status.band = hw->conf.chandef.chan->band; + rx_status.signal = rx_dbm; + rx_status.flag = 0; + rx_status.freq = hw->conf.chandef.chan->center_freq; + + if (!(*rsr & RSR_CRCOK)) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + + hdr = (struct ieee80211_hdr *)(skb->data); + fc = hdr->frame_control; + + rx_status.rate_idx = rate_idx; + + if (ieee80211_has_protected(fc)) { + if (priv->local_id > REV_ID_VT3253_A1) + rx_status.flag |= RX_FLAG_DECRYPTED; + + /* Drop packet */ + if (!(*new_rsr & NEWRSR_DECRYPTOK)) + return false; + } + + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + + ieee80211_rx_irqsafe(priv->hw, skb); + + return true; +} + +bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd) +{ + struct vnt_rd_info *rd_info = curr_rd->rd_info; + struct sk_buff *skb; + u16 frame_size; + + skb = rd_info->skb; + + dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, + priv->rx_buf_sz, DMA_FROM_DEVICE); + + frame_size = le16_to_cpu(curr_rd->rd1.req_count) + - le16_to_cpu(curr_rd->rd0.res_count); + + if ((frame_size > 2364) || (frame_size < 33)) { + /* Frame Size error drop this packet.*/ + dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size); + dev_kfree_skb_irq(skb); + return true; + } + + if (vnt_rx_data(priv, skb, frame_size)) + return true; + + dev_kfree_skb_irq(skb); + + return true; +} diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h new file mode 100644 index 000000000..40364c0ab --- /dev/null +++ b/drivers/staging/vt6655/dpc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + +#ifndef __DPC_H__ +#define __DPC_H__ + +#include "device.h" + +bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd); + +#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c new file mode 100644 index 000000000..1469015eb --- /dev/null +++ b/drivers/staging/vt6655/key.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + */ + +#include "key.h" +#include "mac.h" + +static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, + struct ieee80211_key_conf *key, u32 key_type, + u32 mode, bool onfly_latch) +{ + struct vnt_private *priv = hw->priv; + u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u16 key_mode = 0; + u32 entry = 0; + u8 *bssid; + u8 key_inx = key->keyidx; + u8 i; + + if (mac_addr) + bssid = mac_addr; + else + bssid = &broadcast[0]; + + if (key_type != VNT_KEY_DEFAULTKEY) { + for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { + if (!test_bit(i, &priv->key_entry_inuse)) { + set_bit(i, &priv->key_entry_inuse); + + key->hw_key_idx = i; + entry = key->hw_key_idx; + break; + } + } + } + + switch (key_type) { + case VNT_KEY_DEFAULTKEY: + /* default key last entry */ + entry = MAX_KEY_TABLE - 1; + key->hw_key_idx = entry; + fallthrough; + case VNT_KEY_ALLGROUP: + key_mode |= VNT_KEY_ALLGROUP; + if (onfly_latch) + key_mode |= VNT_KEY_ONFLY_ALL; + fallthrough; + case VNT_KEY_GROUP_ADDRESS: + key_mode |= mode; + fallthrough; + case VNT_KEY_GROUP: + key_mode |= (mode << 4); + key_mode |= VNT_KEY_GROUP; + break; + case VNT_KEY_PAIRWISE: + key_mode |= mode; + key_inx = 4; + break; + default: + return -EINVAL; + } + + if (onfly_latch) + key_mode |= VNT_KEY_ONFLY; + + if (mode == KEY_CTL_WEP) { + if (key->keylen == WLAN_KEY_LEN_WEP40) + key->key[15] &= 0x7f; + if (key->keylen == WLAN_KEY_LEN_WEP104) + key->key[15] |= 0x80; + } + + MACvSetKeyEntry(priv, key_mode, entry, key_inx, + bssid, (u32 *)key->key, priv->local_id); + + return 0; +} + +int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct ieee80211_vif *vif, struct ieee80211_key_conf *key) +{ + struct ieee80211_bss_conf *conf = &vif->bss_conf; + struct vnt_private *priv = hw->priv; + u8 *mac_addr = NULL; + u8 key_dec_mode = 0; + int ret = 0; + u32 u; + + if (sta) + mac_addr = &sta->addr[0]; + + switch (key->cipher) { + case 0: + for (u = 0 ; u < MAX_KEY_TABLE; u++) + MACvDisableKeyEntry(priv, u); + return ret; + + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + for (u = 0; u < MAX_KEY_TABLE; u++) + MACvDisableKeyEntry(priv, u); + + vnt_set_keymode(hw, mac_addr, + key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); + + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + + return ret; + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + + key_dec_mode = KEY_CTL_TKIP; + + break; + case WLAN_CIPHER_SUITE_CCMP: + key_dec_mode = KEY_CTL_CCMP; + + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + } + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + vnt_set_keymode(hw, mac_addr, + key, VNT_KEY_PAIRWISE, key_dec_mode, true); + } else { + vnt_set_keymode(hw, mac_addr, + key, VNT_KEY_DEFAULTKEY, key_dec_mode, true); + + vnt_set_keymode(hw, (u8 *)conf->bssid, + key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); + } + + return 0; +} diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h new file mode 100644 index 000000000..d88da9dfb --- /dev/null +++ b/drivers/staging/vt6655/key.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Implement functions for 802.11i Key management + * + * Author: Jerry Chen + * + * Date: May 29, 2003 + * + */ + +#ifndef __KEY_H__ +#define __KEY_H__ + +#include <net/mac80211.h> + +/*--------------------- Export Definitions -------------------------*/ +#define MAX_GROUP_KEY 4 +#define MAX_KEY_TABLE 11 +#define MAX_KEY_LEN 32 +#define AES_KEY_LEN 16 + +#define AUTHENTICATOR_KEY 0x10000000 +#define USE_KEYRSC 0x20000000 +#define PAIRWISE_KEY 0x40000000 +#define TRANSMIT_KEY 0x80000000 + +#define GROUP_KEY 0x00000000 + +#define KEY_CTL_WEP 0x00 +#define KEY_CTL_NONE 0x01 +#define KEY_CTL_TKIP 0x02 +#define KEY_CTL_CCMP 0x03 +#define KEY_CTL_INVALID 0xFF + +#define VNT_KEY_DEFAULTKEY 0x1 +#define VNT_KEY_GROUP_ADDRESS 0x2 +#define VNT_KEY_ALLGROUP 0x4 +#define VNT_KEY_GROUP 0x40 +#define VNT_KEY_PAIRWISE 0x00 +#define VNT_KEY_ONFLY 0x8000 +#define VNT_KEY_ONFLY_ALL 0x4000 + +struct vnt_private; + +int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + struct ieee80211_vif *vif, struct ieee80211_key_conf *key); + +#endif /* __KEY_H__ */ diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c new file mode 100644 index 000000000..b4ebc7d31 --- /dev/null +++ b/drivers/staging/vt6655/mac.c @@ -0,0 +1,851 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Functions: + * vt6655_mac_is_reg_bits_off - Test if All test Bits Off + * vt6655_mac_set_short_retry_limit - Set 802.11 Short Retry limit + * MACvSetLongRetryLimit - Set 802.11 Long Retry limit + * vt6655_mac_set_loopback_mode - Set MAC Loopback Mode + * vt6655_mac_save_context - Save Context of MAC Registers + * vt6655_mac_restore_context - Restore Context of MAC Registers + * MACbSoftwareReset - Software Reset MAC + * vt6655_mac_safe_rx_off - Turn Off MAC Rx + * vt6655_mac_safe_tx_off - Turn Off MAC Tx + * vt6655_mac_safe_stop - Stop MAC function + * MACbShutdown - Shut down MAC + * MACvInitialize - Initialize MAC + * MACvSetCurrRxDescAddr - Set Rx Descriptors Address + * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address + * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address + * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC + * + * Revision History: + * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53 + * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()& + * MACvEnableBusSusEn() + * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry + * + */ + +#include "mac.h" + +void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask) +{ + unsigned char reg_value; + + reg_value = ioread8(iobase + reg_offset); + iowrite8(reg_value | bit_mask, iobase + reg_offset); +} + +void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask) +{ + unsigned short reg_value; + + reg_value = ioread16(iobase + reg_offset); + iowrite16(reg_value | (bit_mask), iobase + reg_offset); +} + +void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask) +{ + unsigned char reg_value; + + reg_value = ioread8(iobase + reg_offset); + iowrite8(reg_value & ~(bit_mask), iobase + reg_offset); +} + +void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask) +{ + unsigned short reg_value; + + reg_value = ioread16(iobase + reg_offset); + iowrite16(reg_value & ~(bit_mask), iobase + reg_offset); +} + +static void vt6655_mac_clear_stck_ds(void __iomem *iobase) +{ + u8 reg_value; + + reg_value = ioread8(iobase + MAC_REG_STICKHW); + reg_value = reg_value & 0xFC; + iowrite8(reg_value, iobase + MAC_REG_STICKHW); +} + +/* + * Description: + * Test if all test bits off + * + * Parameters: + * In: + * io_base - Base Address for MAC + * reg_offset - Offset of MAC Register + * mask - Test bits + * Out: + * none + * + * Return Value: true if all test bits Off; otherwise false + * + */ +static bool vt6655_mac_is_reg_bits_off(struct vnt_private *priv, + unsigned char reg_offset, + unsigned char mask) +{ + void __iomem *io_base = priv->port_offset; + + return !(ioread8(io_base + reg_offset) & mask); +} + +/* + * Description: + * Set 802.11 Short Retry Limit + * + * Parameters: + * In: + * io_base - Base Address for MAC + * retry_limit - Retry Limit + * Out: + * none + * + * Return Value: none + * + */ +void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit) +{ + void __iomem *io_base = priv->port_offset; + /* set SRT */ + iowrite8(retry_limit, io_base + MAC_REG_SRT); +} + +/* + * Description: + * Set 802.11 Long Retry Limit + * + * Parameters: + * In: + * io_base - Base Address for MAC + * byRetryLimit- Retry Limit + * Out: + * none + * + * Return Value: none + * + */ +void MACvSetLongRetryLimit(struct vnt_private *priv, + unsigned char byRetryLimit) +{ + void __iomem *io_base = priv->port_offset; + /* set LRT */ + iowrite8(byRetryLimit, io_base + MAC_REG_LRT); +} + +/* + * Description: + * Set MAC Loopback mode + * + * Parameters: + * In: + * io_base - Base Address for MAC + * loopback_mode - Loopback Mode + * Out: + * none + * + * Return Value: none + * + */ +static void vt6655_mac_set_loopback_mode(struct vnt_private *priv, u8 loopback_mode) +{ + void __iomem *io_base = priv->port_offset; + + loopback_mode <<= 6; + /* set TCR */ + iowrite8((ioread8(io_base + MAC_REG_TEST) & 0x3f) | loopback_mode, io_base + MAC_REG_TEST); +} + +/* + * Description: + * Save MAC registers to context buffer + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * cxt_buf - Context buffer + * + * Return Value: none + * + */ +static void vt6655_mac_save_context(struct vnt_private *priv, u8 *cxt_buf) +{ + void __iomem *io_base = priv->port_offset; + + /* read page0 register */ + memcpy_fromio(cxt_buf, io_base, MAC_MAX_CONTEXT_SIZE_PAGE0); + + VT6655_MAC_SELECT_PAGE1(io_base); + + /* read page1 register */ + memcpy_fromio(cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, io_base, + MAC_MAX_CONTEXT_SIZE_PAGE1); + + VT6655_MAC_SELECT_PAGE0(io_base); +} + +/* + * Description: + * Restore MAC registers from context buffer + * + * Parameters: + * In: + * io_base - Base Address for MAC + * cxt_buf - Context buffer + * Out: + * none + * + * Return Value: none + * + */ +static void vt6655_mac_restore_context(struct vnt_private *priv, u8 *cxt_buf) +{ + void __iomem *io_base = priv->port_offset; + + VT6655_MAC_SELECT_PAGE1(io_base); + /* restore page1 */ + memcpy_toio(io_base, cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, + MAC_MAX_CONTEXT_SIZE_PAGE1); + + VT6655_MAC_SELECT_PAGE0(io_base); + + /* restore RCR,TCR,IMR... */ + memcpy_toio(io_base + MAC_REG_RCR, cxt_buf + MAC_REG_RCR, + MAC_REG_ISR - MAC_REG_RCR); + + /* restore MAC Config. */ + memcpy_toio(io_base + MAC_REG_LRT, cxt_buf + MAC_REG_LRT, + MAC_REG_PAGE1SEL - MAC_REG_LRT); + + iowrite8(*(cxt_buf + MAC_REG_CFG), io_base + MAC_REG_CFG); + + /* restore PS Config. */ + memcpy_toio(io_base + MAC_REG_PSCFG, cxt_buf + MAC_REG_PSCFG, + MAC_REG_BBREGCTL - MAC_REG_PSCFG); + + /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */ + iowrite32(*(u32 *)(cxt_buf + MAC_REG_TXDMAPTR0), + io_base + MAC_REG_TXDMAPTR0); + iowrite32(*(u32 *)(cxt_buf + MAC_REG_AC0DMAPTR), + io_base + MAC_REG_AC0DMAPTR); + iowrite32(*(u32 *)(cxt_buf + MAC_REG_BCNDMAPTR), + io_base + MAC_REG_BCNDMAPTR); + iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR0), + io_base + MAC_REG_RXDMAPTR0); + iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR1), + io_base + MAC_REG_RXDMAPTR1); +} + +/* + * Description: + * Software Reset MAC + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if Reset Success; otherwise false + * + */ +bool MACbSoftwareReset(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + + /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */ + iowrite8(0x01, io_base + MAC_REG_HOSTCR); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_SOFTRST)) + break; + } + if (ww == W_MAX_TIMEOUT) + return false; + return true; +} + +/* + * Description: + * save some important register's value, then do reset, then restore + * register's value + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +static void vt6655_mac_save_soft_reset(struct vnt_private *priv) +{ + u8 tmp_reg_data[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1]; + + /* PATCH.... + * save some important register's value, then do + * reset, then restore register's value + */ + /* save MAC context */ + vt6655_mac_save_context(priv, tmp_reg_data); + /* do reset */ + MACbSoftwareReset(priv); + /* restore MAC context, except CR0 */ + vt6655_mac_restore_context(priv, tmp_reg_data); +} + +/* + * Description: + * Turn Off MAC Rx + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +static bool vt6655_mac_safe_rx_off(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + + /* turn off wow temp for turn off Rx safely */ + + /* Clear RX DMA0,1 */ + iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL0); + iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL1); + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread32(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x10)\n"); + return false; + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread32(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x11)\n"); + return false; + } + + /* try to safe shutdown RX */ + vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_RXON); + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_RXONST)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x12)\n"); + return false; + } + return true; +} + +/* + * Description: + * Turn Off MAC Tx + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +static bool vt6655_mac_safe_tx_off(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + + /* Clear TX DMA */ + /* Tx0 */ + iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_TXDMACTL0); + /* AC0 */ + iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_AC0DMACTL); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread32(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x20)\n"); + return false; + } + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread32(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x21)\n"); + return false; + } + + /* try to safe shutdown TX */ + vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_TXON); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_TXONST)) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x24)\n"); + return false; + } + return true; +} + +/* + * Description: + * Stop MAC function + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +static bool vt6655_mac_safe_stop(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + + vt6655_mac_reg_bits_off(io_base, MAC_REG_TCR, TCR_AUTOBCNTX); + + if (!vt6655_mac_safe_rx_off(priv)) { + pr_debug(" vt6655_mac_safe_rx_off == false)\n"); + vt6655_mac_save_soft_reset(priv); + return false; + } + if (!vt6655_mac_safe_tx_off(priv)) { + pr_debug(" vt6655_mac_safe_tx_off == false)\n"); + vt6655_mac_save_soft_reset(priv); + return false; + } + + vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_MACEN); + + return true; +} + +/* + * Description: + * Shut Down MAC + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: true if success; otherwise false + * + */ +bool MACbShutdown(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + /* disable MAC IMR */ + iowrite32(0, io_base + MAC_REG_IMR); + vt6655_mac_set_loopback_mode(priv, MAC_LB_INTERNAL); + /* stop the adapter */ + if (!vt6655_mac_safe_stop(priv)) { + vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE); + return false; + } + vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE); + return true; +} + +/* + * Description: + * Initialize MAC + * + * Parameters: + * In: + * io_base - Base Address for MAC + * Out: + * none + * + * Return Value: none + * + */ +void MACvInitialize(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + /* clear sticky bits */ + vt6655_mac_clear_stck_ds(io_base); + /* disable force PME-enable */ + iowrite8(PME_OVR, io_base + MAC_REG_PMC1); + /* only 3253 A */ + + /* do reset */ + MACbSoftwareReset(priv); + + /* reset TSF counter */ + iowrite8(TFTCTL_TSFCNTRST, io_base + MAC_REG_TFTCTL); + /* enable TSF counter */ + iowrite8(TFTCTL_TSFCNTREN, io_base + MAC_REG_TFTCTL); +} + +/* + * Description: + * Set the chip with current rx descriptor address + * + * Parameters: + * In: + * io_base - Base Address for MAC + * curr_desc_addr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + unsigned char org_dma_ctl; + + org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL0); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0 + 2); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN)) + break; + } + + iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR0); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0); +} + +/* + * Description: + * Set the chip with current rx descriptor address + * + * Parameters: + * In: + * io_base - Base Address for MAC + * curr_desc_addr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + unsigned char org_dma_ctl; + + org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL1); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1 + 2); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN)) + break; + } + + iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR1); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1); +} + +/* + * Description: + * Set the chip with current tx0 descriptor address + * + * Parameters: + * In: + * io_base - Base Address for MAC + * curr_desc_addr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +static void vt6655_mac_set_curr_tx_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + unsigned char org_dma_ctl; + + org_dma_ctl = ioread8(io_base + MAC_REG_TXDMACTL0); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0 + 2); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN)) + break; + } + + iowrite32(curr_desc_addr, io_base + MAC_REG_TXDMAPTR0); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0); +} + +/* + * Description: + * Set the chip with current AC0 descriptor address + * + * Parameters: + * In: + * io_base - Base Address for MAC + * curr_desc_addr - Descriptor Address + * Out: + * none + * + * Return Value: none + * + */ +/* TxDMA1 = AC0DMA */ +static void vt6655_mac_set_curr_ac_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr) +{ + void __iomem *io_base = priv->port_offset; + unsigned short ww; + unsigned char org_dma_ctl; + + org_dma_ctl = ioread8(io_base + MAC_REG_AC0DMACTL); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL + 2); + + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (!(ioread8(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN)) + break; + } + if (ww == W_MAX_TIMEOUT) + pr_debug(" DBG_PORT80(0x26)\n"); + iowrite32(curr_desc_addr, io_base + MAC_REG_AC0DMAPTR); + if (org_dma_ctl & DMACTL_RUN) + iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL); +} + +void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr) +{ + if (tx_type == TYPE_AC0DMA) + vt6655_mac_set_curr_ac_0_desc_addr_ex(priv, curr_desc_addr); + else if (tx_type == TYPE_TXDMA0) + vt6655_mac_set_curr_tx_0_desc_addr_ex(priv, curr_desc_addr); +} + +/* + * Description: + * Micro Second Delay via MAC + * + * Parameters: + * In: + * io_base - Base Address for MAC + * uDelay - Delay time (timer resolution is 4 us) + * Out: + * none + * + * Return Value: none + * + */ +void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay) +{ + void __iomem *io_base = priv->port_offset; + unsigned char byValue; + unsigned int uu, ii; + + iowrite8(0, io_base + MAC_REG_TMCTL0); + iowrite32(uDelay, io_base + MAC_REG_TMDATA0); + iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL0); + for (ii = 0; ii < 66; ii++) { /* assume max PCI clock is 66Mhz */ + for (uu = 0; uu < uDelay; uu++) { + byValue = ioread8(io_base + MAC_REG_TMCTL0); + if ((byValue == 0) || + (byValue & TMCTL_TSUSP)) { + iowrite8(0, io_base + MAC_REG_TMCTL0); + return; + } + } + } + iowrite8(0, io_base + MAC_REG_TMCTL0); +} + +/* + * Description: + * Micro Second One shot timer via MAC + * + * Parameters: + * In: + * io_base - Base Address for MAC + * uDelay - Delay time + * Out: + * none + * + * Return Value: none + * + */ +void MACvOneShotTimer1MicroSec(struct vnt_private *priv, + unsigned int uDelayTime) +{ + void __iomem *io_base = priv->port_offset; + + iowrite8(0, io_base + MAC_REG_TMCTL1); + iowrite32(uDelayTime, io_base + MAC_REG_TMDATA1); + iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL1); +} + +void MACvSetMISCFifo(struct vnt_private *priv, unsigned short offset, + u32 data) +{ + void __iomem *io_base = priv->port_offset; + + if (offset > 273) + return; + iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); + iowrite32(data, io_base + MAC_REG_MISCFFDATA); + iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); +} + +bool MACbPSWakeup(struct vnt_private *priv) +{ + void __iomem *io_base = priv->port_offset; + unsigned int ww; + /* Read PSCTL */ + if (vt6655_mac_is_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_PS)) + return true; + + /* Disable PS */ + vt6655_mac_reg_bits_off(io_base, MAC_REG_PSCTL, PSCTL_PSEN); + + /* Check if SyncFlushOK */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + if (ioread8(io_base + MAC_REG_PSCTL) & PSCTL_WAKEDONE) + break; + } + if (ww == W_MAX_TIMEOUT) { + pr_debug(" DBG_PORT80(0x33)\n"); + return false; + } + return true; +} + +/* + * Description: + * Set the Key by MISCFIFO + * + * Parameters: + * In: + * io_base - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ + +void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, + unsigned int uEntryIdx, unsigned int uKeyIdx, + unsigned char *pbyAddr, u32 *pdwKey, + unsigned char local_id) +{ + void __iomem *io_base = priv->port_offset; + unsigned short offset; + u32 data; + int ii; + + if (local_id <= 1) + return; + + offset = MISCFIFO_KEYETRY0; + offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + data = 0; + data |= wKeyCtl; + data <<= 16; + data |= MAKEWORD(*(pbyAddr + 4), *(pbyAddr + 5)); + pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n", + offset, data, wKeyCtl); + + iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); + iowrite32(data, io_base + MAC_REG_MISCFFDATA); + iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); + offset++; + + data = 0; + data |= *(pbyAddr + 3); + data <<= 8; + data |= *(pbyAddr + 2); + data <<= 8; + data |= *(pbyAddr + 1); + data <<= 8; + data |= *pbyAddr; + pr_debug("2. offset: %d, Data: %X\n", offset, data); + + iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); + iowrite32(data, io_base + MAC_REG_MISCFFDATA); + iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); + offset++; + + offset += (uKeyIdx * 4); + for (ii = 0; ii < 4; ii++) { + /* always push 128 bits */ + pr_debug("3.(%d) offset: %d, Data: %X\n", + ii, offset + ii, *pdwKey); + iowrite16(offset + ii, io_base + MAC_REG_MISCFFNDEX); + iowrite32(*pdwKey++, io_base + MAC_REG_MISCFFDATA); + iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); + } +} + +/* + * Description: + * Disable the Key Entry by MISCFIFO + * + * Parameters: + * In: + * io_base - Base Address for MAC + * + * Out: + * none + * + * Return Value: none + * + */ +void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx) +{ + void __iomem *io_base = priv->port_offset; + unsigned short offset; + + offset = MISCFIFO_KEYETRY0; + offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); + + iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); + iowrite32(0, io_base + MAC_REG_MISCFFDATA); + iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); +} diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h new file mode 100644 index 000000000..acf931c3f --- /dev/null +++ b/drivers/staging/vt6655/mac.h @@ -0,0 +1,580 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: MAC routines + * + * Author: Tevin Chen + * + * Date: May 21, 1996 + * + * Revision History: + * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. + * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53. + * 09-03-2003 Bryan YC Fan: Add vt6655_mac_dis_protect_md & vt6655_mac_en_protect_md + */ + +#ifndef __MAC_H__ +#define __MAC_H__ + +#include "device.h" + +/*--------------------- Export Definitions -------------------------*/ +/* Registers in the MAC */ +#define MAC_MAX_CONTEXT_SIZE_PAGE0 256 +#define MAC_MAX_CONTEXT_SIZE_PAGE1 128 + +/* Registers not related to 802.11b */ +#define MAC_REG_BCFG0 0x00 +#define MAC_REG_BCFG1 0x01 +#define MAC_REG_FCR0 0x02 +#define MAC_REG_FCR1 0x03 +#define MAC_REG_BISTCMD 0x04 +#define MAC_REG_BISTSR0 0x05 +#define MAC_REG_BISTSR1 0x06 +#define MAC_REG_BISTSR2 0x07 +#define MAC_REG_I2MCSR 0x08 +#define MAC_REG_I2MTGID 0x09 +#define MAC_REG_I2MTGAD 0x0A +#define MAC_REG_I2MCFG 0x0B +#define MAC_REG_I2MDIPT 0x0C +#define MAC_REG_I2MDOPT 0x0E +#define MAC_REG_PMC0 0x10 +#define MAC_REG_PMC1 0x11 +#define MAC_REG_STICKHW 0x12 +#define MAC_REG_LOCALID 0x14 +#define MAC_REG_TESTCFG 0x15 +#define MAC_REG_JUMPER0 0x16 +#define MAC_REG_JUMPER1 0x17 +#define MAC_REG_TMCTL0 0x18 +#define MAC_REG_TMCTL1 0x19 +#define MAC_REG_TMDATA0 0x1C + +/* MAC Parameter related */ +#define MAC_REG_LRT 0x20 +#define MAC_REG_SRT 0x21 +#define MAC_REG_SIFS 0x22 +#define MAC_REG_DIFS 0x23 +#define MAC_REG_EIFS 0x24 +#define MAC_REG_SLOT 0x25 +#define MAC_REG_BI 0x26 +#define MAC_REG_CWMAXMIN0 0x28 +#define MAC_REG_LINKOFFTOTM 0x2A +#define MAC_REG_SWTMOT 0x2B +#define MAC_REG_MIBCNTR 0x2C +#define MAC_REG_RTSOKCNT 0x2C +#define MAC_REG_RTSFAILCNT 0x2D +#define MAC_REG_ACKFAILCNT 0x2E +#define MAC_REG_FCSERRCNT 0x2F + +/* TSF Related */ +#define MAC_REG_TSFCNTR 0x30 +#define MAC_REG_NEXTTBTT 0x38 +#define MAC_REG_TSFOFST 0x40 +#define MAC_REG_TFTCTL 0x48 + +/* WMAC Control/Status Related */ +#define MAC_REG_ENCFG 0x4C +#define MAC_REG_PAGE1SEL 0x4F +#define MAC_REG_CFG 0x50 +#define MAC_REG_TEST 0x52 +#define MAC_REG_HOSTCR 0x54 +#define MAC_REG_MACCR 0x55 +#define MAC_REG_RCR 0x56 +#define MAC_REG_TCR 0x57 +#define MAC_REG_IMR 0x58 +#define MAC_REG_ISR 0x5C + +/* Power Saving Related */ +#define MAC_REG_PSCFG 0x60 +#define MAC_REG_PSCTL 0x61 +#define MAC_REG_PSPWRSIG 0x62 +#define MAC_REG_BBCR13 0x63 +#define MAC_REG_AIDATIM 0x64 +#define MAC_REG_PWBT 0x66 +#define MAC_REG_WAKEOKTMR 0x68 +#define MAC_REG_CALTMR 0x69 +#define MAC_REG_SYNSPACCNT 0x6A +#define MAC_REG_WAKSYNOPT 0x6B + +/* Baseband/IF Control Group */ +#define MAC_REG_BBREGCTL 0x6C +#define MAC_REG_CHANNEL 0x6D +#define MAC_REG_BBREGADR 0x6E +#define MAC_REG_BBREGDATA 0x6F +#define MAC_REG_IFREGCTL 0x70 +#define MAC_REG_IFDATA 0x71 +#define MAC_REG_ITRTMSET 0x74 +#define MAC_REG_PAPEDELAY 0x77 +#define MAC_REG_SOFTPWRCTL 0x78 +#define MAC_REG_GPIOCTL0 0x7A +#define MAC_REG_GPIOCTL1 0x7B + +/* MAC DMA Related Group */ +#define MAC_REG_TXDMACTL0 0x7C +#define MAC_REG_TXDMAPTR0 0x80 +#define MAC_REG_AC0DMACTL 0x84 +#define MAC_REG_AC0DMAPTR 0x88 +#define MAC_REG_BCNDMACTL 0x8C +#define MAC_REG_BCNDMAPTR 0x90 +#define MAC_REG_RXDMACTL0 0x94 +#define MAC_REG_RXDMAPTR0 0x98 +#define MAC_REG_RXDMACTL1 0x9C +#define MAC_REG_RXDMAPTR1 0xA0 +#define MAC_REG_SYNCDMACTL 0xA4 +#define MAC_REG_SYNCDMAPTR 0xA8 +#define MAC_REG_ATIMDMACTL 0xAC +#define MAC_REG_ATIMDMAPTR 0xB0 + +/* MiscFF PIO related */ +#define MAC_REG_MISCFFNDEX 0xB4 +#define MAC_REG_MISCFFCTL 0xB6 +#define MAC_REG_MISCFFDATA 0xB8 + +/* Extend SW Timer */ +#define MAC_REG_TMDATA1 0xBC + +/* WOW Related Group */ +#define MAC_REG_WAKEUPEN0 0xC0 +#define MAC_REG_WAKEUPEN1 0xC1 +#define MAC_REG_WAKEUPSR0 0xC2 +#define MAC_REG_WAKEUPSR1 0xC3 +#define MAC_REG_WAKE128_0 0xC4 +#define MAC_REG_WAKE128_1 0xD4 +#define MAC_REG_WAKE128_2 0xE4 +#define MAC_REG_WAKE128_3 0xF4 + +/************** Page 1 ******************/ +#define MAC_REG_CRC_128_0 0x04 +#define MAC_REG_CRC_128_1 0x06 +#define MAC_REG_CRC_128_2 0x08 +#define MAC_REG_CRC_128_3 0x0A + +/* MAC Configuration Group */ +#define MAC_REG_PAR0 0x0C +#define MAC_REG_PAR4 0x10 +#define MAC_REG_BSSID0 0x14 +#define MAC_REG_BSSID4 0x18 +#define MAC_REG_MAR0 0x1C +#define MAC_REG_MAR4 0x20 + +/* MAC RSPPKT INFO Group */ +#define MAC_REG_RSPINF_B_1 0x24 +#define MAC_REG_RSPINF_B_2 0x28 +#define MAC_REG_RSPINF_B_5 0x2C +#define MAC_REG_RSPINF_B_11 0x30 +#define MAC_REG_RSPINF_A_6 0x34 +#define MAC_REG_RSPINF_A_9 0x36 +#define MAC_REG_RSPINF_A_12 0x38 +#define MAC_REG_RSPINF_A_18 0x3A +#define MAC_REG_RSPINF_A_24 0x3C +#define MAC_REG_RSPINF_A_36 0x3E +#define MAC_REG_RSPINF_A_48 0x40 +#define MAC_REG_RSPINF_A_54 0x42 +#define MAC_REG_RSPINF_A_72 0x44 + +/* 802.11h relative */ +#define MAC_REG_QUIETINIT 0x60 +#define MAC_REG_QUIETGAP 0x62 +#define MAC_REG_QUIETDUR 0x64 +#define MAC_REG_MSRCTL 0x66 +#define MAC_REG_MSRBBSTS 0x67 +#define MAC_REG_MSRSTART 0x68 +#define MAC_REG_MSRDURATION 0x70 +#define MAC_REG_CCAFRACTION 0x72 +#define MAC_REG_PWRCCK 0x73 +#define MAC_REG_PWROFDM 0x7C + +/* Bits in the BCFG0 register */ +#define BCFG0_PERROFF 0x40 +#define BCFG0_MRDMDIS 0x20 +#define BCFG0_MRDLDIS 0x10 +#define BCFG0_MWMEN 0x08 +#define BCFG0_VSERREN 0x02 +#define BCFG0_LATMEN 0x01 + +/* Bits in the BCFG1 register */ +#define BCFG1_CFUNOPT 0x80 +#define BCFG1_CREQOPT 0x40 +#define BCFG1_DMA8 0x10 +#define BCFG1_ARBITOPT 0x08 +#define BCFG1_PCIMEN 0x04 +#define BCFG1_MIOEN 0x02 +#define BCFG1_CISDLYEN 0x01 + +/* Bits in RAMBIST registers */ +#define BISTCMD_TSTPAT5 0x00 +#define BISTCMD_TSTPATA 0x80 +#define BISTCMD_TSTERR 0x20 +#define BISTCMD_TSTPATF 0x18 +#define BISTCMD_TSTPAT0 0x10 +#define BISTCMD_TSTMODE 0x04 +#define BISTCMD_TSTITTX 0x03 +#define BISTCMD_TSTATRX 0x02 +#define BISTCMD_TSTATTX 0x01 +#define BISTCMD_TSTRX 0x00 +#define BISTSR0_BISTGO 0x01 +#define BISTSR1_TSTSR 0x01 +#define BISTSR2_CMDPRTEN 0x02 +#define BISTSR2_RAMTSTEN 0x01 + +/* Bits in the I2MCFG EEPROM register */ +#define I2MCFG_BOUNDCTL 0x80 +#define I2MCFG_WAITCTL 0x20 +#define I2MCFG_SCLOECTL 0x10 +#define I2MCFG_WBUSYCTL 0x08 +#define I2MCFG_NORETRY 0x04 +#define I2MCFG_I2MLDSEQ 0x02 +#define I2MCFG_I2CMFAST 0x01 + +/* Bits in the I2MCSR EEPROM register */ +#define I2MCSR_EEMW 0x80 +#define I2MCSR_EEMR 0x40 +#define I2MCSR_AUTOLD 0x08 +#define I2MCSR_NACK 0x02 +#define I2MCSR_DONE 0x01 + +/* Bits in the PMC1 register */ +#define SPS_RST 0x80 +#define PCISTIKY 0x40 +#define PME_OVR 0x02 + +/* Bits in the STICKYHW register */ +#define STICKHW_DS1_SHADOW 0x02 +#define STICKHW_DS0_SHADOW 0x01 + +/* Bits in the TMCTL register */ +#define TMCTL_TSUSP 0x04 +#define TMCTL_TMD 0x02 +#define TMCTL_TE 0x01 + +/* Bits in the TFTCTL register */ +#define TFTCTL_HWUTSF 0x80 +#define TFTCTL_TBTTSYNC 0x40 +#define TFTCTL_HWUTSFEN 0x20 +#define TFTCTL_TSFCNTRRD 0x10 +#define TFTCTL_TBTTSYNCEN 0x08 +#define TFTCTL_TSFSYNCEN 0x04 +#define TFTCTL_TSFCNTRST 0x02 +#define TFTCTL_TSFCNTREN 0x01 + +/* Bits in the EnhanceCFG register */ +#define ENCFG_BARKERPREAM 0x00020000 +#define ENCFG_NXTBTTCFPSTR 0x00010000 +#define ENCFG_BCNSUSCLR 0x00000200 +#define ENCFG_BCNSUSIND 0x00000100 +#define ENCFG_CFP_PROTECTEN 0x00000040 +#define ENCFG_PROTECTMD 0x00000020 +#define ENCFG_HWPARCFP 0x00000010 +#define ENCFG_CFNULRSP 0x00000004 +#define ENCFG_BBTYPE_MASK 0x00000003 +#define ENCFG_BBTYPE_G 0x00000002 +#define ENCFG_BBTYPE_B 0x00000001 +#define ENCFG_BBTYPE_A 0x00000000 + +/* Bits in the Page1Sel register */ +#define PAGE1_SEL 0x01 + +/* Bits in the CFG register */ +#define CFG_TKIPOPT 0x80 +#define CFG_RXDMAOPT 0x40 +#define CFG_TMOT_SW 0x20 +#define CFG_TMOT_HWLONG 0x10 +#define CFG_TMOT_HW 0x00 +#define CFG_CFPENDOPT 0x08 +#define CFG_BCNSUSEN 0x04 +#define CFG_NOTXTIMEOUT 0x02 +#define CFG_NOBUFOPT 0x01 + +/* Bits in the TEST register */ +#define TEST_LBEXT 0x80 +#define TEST_LBINT 0x40 +#define TEST_LBNONE 0x00 +#define TEST_SOFTINT 0x20 +#define TEST_CONTTX 0x10 +#define TEST_TXPE 0x08 +#define TEST_NAVDIS 0x04 +#define TEST_NOCTS 0x02 +#define TEST_NOACK 0x01 + +/* Bits in the HOSTCR register */ +#define HOSTCR_TXONST 0x80 +#define HOSTCR_RXONST 0x40 +#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ +#define HOSTCR_AP 0x10 /* Port Type 1 = AP */ +#define HOSTCR_TXON 0x08 /* 0000 1000 */ +#define HOSTCR_RXON 0x04 /* 0000 0100 */ +#define HOSTCR_MACEN 0x02 /* 0000 0010 */ +#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ + +/* Bits in the MACCR register */ +#define MACCR_SYNCFLUSHOK 0x04 +#define MACCR_SYNCFLUSH 0x02 +#define MACCR_CLRNAV 0x01 + +/* Bits in the MAC_REG_GPIOCTL0 register */ +#define LED_ACTSET 0x01 +#define LED_RFOFF 0x02 +#define LED_NOCONNECT 0x04 + +/* Bits in the RCR register */ +#define RCR_SSID 0x80 +#define RCR_RXALLTYPE 0x40 +#define RCR_UNICAST 0x20 +#define RCR_BROADCAST 0x10 +#define RCR_MULTICAST 0x08 +#define RCR_WPAERR 0x04 +#define RCR_ERRCRC 0x02 +#define RCR_BSSID 0x01 + +/* Bits in the TCR register */ +#define TCR_SYNCDCFOPT 0x02 +#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ + +/* Bits in the IMR register */ +#define IMR_MEASURESTART 0x80000000 +#define IMR_QUIETSTART 0x20000000 +#define IMR_RADARDETECT 0x10000000 +#define IMR_MEASUREEND 0x08000000 +#define IMR_SOFTTIMER1 0x00200000 +#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ +#define IMR_RXNOBUF 0x00000800 +#define IMR_MIBNEARFULL 0x00000400 +#define IMR_SOFTINT 0x00000200 +#define IMR_FETALERR 0x00000100 +#define IMR_WATCHDOG 0x00000080 +#define IMR_SOFTTIMER 0x00000040 +#define IMR_GPIO 0x00000020 +#define IMR_TBTT 0x00000010 +#define IMR_RXDMA0 0x00000008 +#define IMR_BNTX 0x00000004 +#define IMR_AC0DMA 0x00000002 +#define IMR_TXDMA0 0x00000001 + +/* Bits in the ISR register */ +#define ISR_MEASURESTART 0x80000000 +#define ISR_QUIETSTART 0x20000000 +#define ISR_RADARDETECT 0x10000000 +#define ISR_MEASUREEND 0x08000000 +#define ISR_SOFTTIMER1 0x00200000 +#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ +#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */ +#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */ +#define ISR_SOFTINT 0x00000200 +#define ISR_FETALERR 0x00000100 +#define ISR_WATCHDOG 0x00000080 +#define ISR_SOFTTIMER 0x00000040 +#define ISR_GPIO 0x00000020 +#define ISR_TBTT 0x00000010 +#define ISR_RXDMA0 0x00000008 +#define ISR_BNTX 0x00000004 +#define ISR_AC0DMA 0x00000002 +#define ISR_TXDMA0 0x00000001 + +/* Bits in the PSCFG register */ +#define PSCFG_PHILIPMD 0x40 +#define PSCFG_WAKECALEN 0x20 +#define PSCFG_WAKETMREN 0x10 +#define PSCFG_BBPSPROG 0x08 +#define PSCFG_WAKESYN 0x04 +#define PSCFG_SLEEPSYN 0x02 +#define PSCFG_AUTOSLEEP 0x01 + +/* Bits in the PSCTL register */ +#define PSCTL_WAKEDONE 0x20 +#define PSCTL_PS 0x10 +#define PSCTL_GO2DOZE 0x08 +#define PSCTL_LNBCN 0x04 +#define PSCTL_ALBCN 0x02 +#define PSCTL_PSEN 0x01 + +/* Bits in the PSPWSIG register */ +#define PSSIG_WPE3 0x80 +#define PSSIG_WPE2 0x40 +#define PSSIG_WPE1 0x20 +#define PSSIG_WRADIOPE 0x10 +#define PSSIG_SPE3 0x08 +#define PSSIG_SPE2 0x04 +#define PSSIG_SPE1 0x02 +#define PSSIG_SRADIOPE 0x01 + +/* Bits in the BBREGCTL register */ +#define BBREGCTL_DONE 0x04 +#define BBREGCTL_REGR 0x02 +#define BBREGCTL_REGW 0x01 + +/* Bits in the IFREGCTL register */ +#define IFREGCTL_DONE 0x04 +#define IFREGCTL_IFRF 0x02 +#define IFREGCTL_REGW 0x01 + +/* Bits in the SOFTPWRCTL register */ +#define SOFTPWRCTL_RFLEOPT 0x0800 +#define SOFTPWRCTL_TXPEINV 0x0200 +#define SOFTPWRCTL_SWPECTI 0x0100 +#define SOFTPWRCTL_SWPAPE 0x0020 +#define SOFTPWRCTL_SWCALEN 0x0010 +#define SOFTPWRCTL_SWRADIO_PE 0x0008 +#define SOFTPWRCTL_SWPE2 0x0004 +#define SOFTPWRCTL_SWPE1 0x0002 +#define SOFTPWRCTL_SWPE3 0x0001 + +/* Bits in the GPIOCTL1 register */ +#define GPIO1_DATA1 0x20 +#define GPIO1_MD1 0x10 +#define GPIO1_DATA0 0x02 +#define GPIO1_MD0 0x01 + +/* Bits in the DMACTL register */ +#define DMACTL_CLRRUN 0x00080000 +#define DMACTL_RUN 0x00000008 +#define DMACTL_WAKE 0x00000004 +#define DMACTL_DEAD 0x00000002 +#define DMACTL_ACTIVE 0x00000001 + +/* Bits in the RXDMACTL0 register */ +#define RX_PERPKT 0x00000100 +#define RX_PERPKTCLR 0x01000000 + +/* Bits in the BCNDMACTL register */ +#define BEACON_READY 0x01 + +/* Bits in the MISCFFCTL register */ +#define MISCFFCTL_WRITE 0x0001 + +/* Bits in WAKEUPEN0 */ +#define WAKEUPEN0_DIRPKT 0x10 +#define WAKEUPEN0_LINKOFF 0x08 +#define WAKEUPEN0_ATIMEN 0x04 +#define WAKEUPEN0_TIMEN 0x02 +#define WAKEUPEN0_MAGICEN 0x01 + +/* Bits in WAKEUPEN1 */ +#define WAKEUPEN1_128_3 0x08 +#define WAKEUPEN1_128_2 0x04 +#define WAKEUPEN1_128_1 0x02 +#define WAKEUPEN1_128_0 0x01 + +/* Bits in WAKEUPSR0 */ +#define WAKEUPSR0_DIRPKT 0x10 +#define WAKEUPSR0_LINKOFF 0x08 +#define WAKEUPSR0_ATIMEN 0x04 +#define WAKEUPSR0_TIMEN 0x02 +#define WAKEUPSR0_MAGICEN 0x01 + +/* Bits in WAKEUPSR1 */ +#define WAKEUPSR1_128_3 0x08 +#define WAKEUPSR1_128_2 0x04 +#define WAKEUPSR1_128_1 0x02 +#define WAKEUPSR1_128_0 0x01 + +/* Bits in the MAC_REG_GPIOCTL register */ +#define GPIO0_MD 0x01 +#define GPIO0_DATA 0x02 +#define GPIO0_INTMD 0x04 +#define GPIO1_MD 0x10 +#define GPIO1_DATA 0x20 + +/* Bits in the MSRCTL register */ +#define MSRCTL_FINISH 0x80 +#define MSRCTL_READY 0x40 +#define MSRCTL_RADARDETECT 0x20 +#define MSRCTL_EN 0x10 +#define MSRCTL_QUIETTXCHK 0x08 +#define MSRCTL_QUIETRPT 0x04 +#define MSRCTL_QUIETINT 0x02 +#define MSRCTL_QUIETEN 0x01 + +/* Bits in the MSRCTL1 register */ +#define MSRCTL1_TXPWR 0x08 +#define MSRCTL1_CSAPAREN 0x04 +#define MSRCTL1_TXPAUSE 0x01 + +/* Loopback mode */ +#define MAC_LB_EXT 0x02 +#define MAC_LB_INTERNAL 0x01 +#define MAC_LB_NONE 0x00 + +#define DEFAULT_BI 0x200 + +/* MiscFIFO Offset */ +#define MISCFIFO_KEYETRY0 32 +#define MISCFIFO_KEYENTRYSIZE 22 +#define MISCFIFO_SYNINFO_IDX 10 +#define MISCFIFO_SYNDATA_IDX 11 +#define MISCFIFO_SYNDATASIZE 21 + +/* enabled mask value of irq */ +#define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \ + IMR_RXDMA1 | \ + IMR_RXNOBUF | \ + IMR_MIBNEARFULL | \ + IMR_SOFTINT | \ + IMR_FETALERR | \ + IMR_WATCHDOG | \ + IMR_SOFTTIMER | \ + IMR_GPIO | \ + IMR_TBTT | \ + IMR_RXDMA0 | \ + IMR_BNTX | \ + IMR_AC0DMA | \ + IMR_TXDMA0) + +/* max time out delay time */ +#define W_MAX_TIMEOUT 0xFFF0U + +/* wait time within loop */ +#define CB_DELAY_LOOP_WAIT 10 /* 10ms */ + +/* revision id */ +#define REV_ID_VT3253_A0 0x00 +#define REV_ID_VT3253_A1 0x01 +#define REV_ID_VT3253_B0 0x08 +#define REV_ID_VT3253_B1 0x09 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +#define VT6655_MAC_SELECT_PAGE0(iobase) iowrite8(0, iobase + MAC_REG_PAGE1SEL) + +#define VT6655_MAC_SELECT_PAGE1(iobase) iowrite8(1, iobase + MAC_REG_PAGE1SEL) + +#define MAKEWORD(lb, hb) \ + ((unsigned short)(((unsigned char)(lb)) | (((unsigned short)((unsigned char)(hb))) << 8))) + +void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask); +void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask); +void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask); +void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask); + +void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit); + +void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit); + +bool MACbSoftwareReset(struct vnt_private *priv); +bool MACbShutdown(struct vnt_private *priv); +void MACvInitialize(struct vnt_private *priv); +void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr); +void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr); +void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr); +void MACvSetCurrSyncDescAddrEx(struct vnt_private *priv, + u32 curr_desc_addr); +void MACvSetCurrATIMDescAddrEx(struct vnt_private *priv, + u32 curr_desc_addr); +void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay); +void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime); + +void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset, + u32 dwData); + +bool MACbPSWakeup(struct vnt_private *priv); + +void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, + unsigned int uEntryIdx, unsigned int uKeyIdx, + unsigned char *pbyAddr, u32 *pdwKey, + unsigned char local_id); +void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx); + +#endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c new file mode 100644 index 000000000..8527ad3ef --- /dev/null +++ b/drivers/staging/vt6655/power.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Handles 802.11 power management functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + * Functions: + * PSvEnablePowerSaving - Enable Power Saving Mode + * PSvDiasblePowerSaving - Disable Power Saving Mode + * PSbConsiderPowerDown - Decide if we can Power Down + * PSvSendPSPOLL - Send PS-POLL packet + * PSbSendNullPacket - Send Null packet + * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon + * + * Revision History: + * + */ + +#include "mac.h" +#include "device.h" +#include "power.h" +#include "card.h" + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* + * + * Routine Description: + * Enable hw power saving functions + * + * Return Value: + * None. + * + */ + +void PSvEnablePowerSaving(struct vnt_private *priv, + unsigned short wListenInterval) +{ + u16 wAID = priv->current_aid | BIT(14) | BIT(15); + + /* set period of power up before TBTT */ + iowrite16(C_PWBT, priv->port_offset + MAC_REG_PWBT); + if (priv->op_mode != NL80211_IFTYPE_ADHOC) { + /* set AID */ + iowrite16(wAID, priv->port_offset + MAC_REG_AIDATIM); + } + + /* Set AutoSleep */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + + /* Set HWUTSF */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + + if (wListenInterval >= 2) { + /* clear always listen beacon */ + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); + /* first time set listen next beacon */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN); + } else { + /* always listen beacon */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); + } + + /* enable power saving hw function */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_PSEN); + priv->bEnablePSMode = true; + + priv->bPWBitOn = true; + pr_debug("PS:Power Saving Mode Enable...\n"); +} + +/* + * + * Routine Description: + * Disable hw power saving functions + * + * Return Value: + * None. + * + */ + +void PSvDisablePowerSaving(struct vnt_private *priv) +{ + /* disable power saving hw function */ + MACbPSWakeup(priv); + + /* clear AutoSleep */ + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + + /* clear HWUTSF */ + vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + + /* set always listen beacon */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); + + priv->bEnablePSMode = false; + + priv->bPWBitOn = false; +} + +/* + * + * Routine Description: + * Check if Next TBTT must wake up + * + * Return Value: + * None. + * + */ + +bool PSbIsNextTBTTWakeUp(struct vnt_private *priv) +{ + struct ieee80211_hw *hw = priv->hw; + struct ieee80211_conf *conf = &hw->conf; + bool wake_up = false; + + if (conf->listen_interval > 1) { + if (!priv->wake_up_count) + priv->wake_up_count = conf->listen_interval; + + --priv->wake_up_count; + + if (priv->wake_up_count == 1) { + /* Turn on wake up to listen next beacon */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN); + wake_up = true; + } + } + + return wake_up; +} diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h new file mode 100644 index 000000000..060516f81 --- /dev/null +++ b/drivers/staging/vt6655/power.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Handles 802.11 power management functions + * + * Author: Lyndon Chen + * + * Date: July 17, 2002 + * + */ + +#ifndef __POWER_H__ +#define __POWER_H__ + +#include "device.h" + +#define C_PWBT 1000 /* micro sec. power up before TBTT */ +#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */ +#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */ + +void PSvDisablePowerSaving(struct vnt_private *priv); + +void PSvEnablePowerSaving(struct vnt_private *priv, unsigned short wListenInterval); + +bool PSbIsNextTBTTWakeUp(struct vnt_private *priv); + +#endif /* __POWER_H__ */ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c new file mode 100644 index 000000000..1fadc2fc4 --- /dev/null +++ b/drivers/staging/vt6655/rf.c @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: rf function code + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + * Functions: + * IFRFbWriteEmbedded - Embedded write RF register via MAC + * + * Revision History: + * RobertYu 2005 + * chester 2008 + * + */ + +#include "mac.h" +#include "srom.h" +#include "rf.h" +#include "baseband.h" + +#define BY_AL2230_REG_LEN 23 /* 24bit */ +#define CB_AL2230_INIT_SEQ 15 +#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */ +#define AL2230_PWR_IDX_LEN 64 + +#define BY_AL7230_REG_LEN 23 /* 24bit */ +#define CB_AL7230_INIT_SEQ 16 +#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */ +#define AL7230_PWR_IDX_LEN 64 + +static const unsigned long al2230_init_table[CB_AL2230_INIT_SEQ] = { + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x01A00200 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00FFF300 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0F4DC500 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0805B600 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0146C700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00068800 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0403B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00DBBA00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0BDFFC00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00000D00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x00580F00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW +}; + +static const unsigned long al2230_channel_table0[CB_MAX_CHANNEL] = { + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03F7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x03E7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ +}; + +static const unsigned long al2230_channel_table1[CB_MAX_CHANNEL] = { + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ + 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ + 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ + 0x06666100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ +}; + +static unsigned long al2230_power_table[AL2230_PWR_IDX_LEN] = { + 0x04040900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04041900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04042900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04043900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04044900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04045900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04046900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04047900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04048900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04049900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0404F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04050900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04051900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04052900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04053900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04054900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04055900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04056900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04057900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04058900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04059900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0405F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04060900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04061900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04062900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04063900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04064900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04065900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04066900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04067900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04068900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04069900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0406F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04070900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04071900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04072900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04073900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04074900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04075900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04076900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04077900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04078900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x04079900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, + 0x0407F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW +}; + +/* + * Description: Write to IF/RF, by embedded programming + * + * Parameters: + * In: + * iobase - I/O base address + * dwData - data to write + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData) +{ + void __iomem *iobase = priv->port_offset; + unsigned short ww; + unsigned long dwValue; + + iowrite32((u32)dwData, iobase + MAC_REG_IFREGCTL); + + /* W_MAX_TIMEOUT is the timeout period */ + for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { + dwValue = ioread32(iobase + MAC_REG_IFREGCTL); + if (dwValue & IFREGCTL_DONE) + break; + } + + if (ww == W_MAX_TIMEOUT) + return false; + + return true; +} + +/* + * Description: AIROHA IFRF chip init function + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +static bool RFbAL2230Init(struct vnt_private *priv) +{ + void __iomem *iobase = priv->port_offset; + int ii; + bool ret; + + ret = true; + + /* 3-wire control for normal mode */ + iowrite8(0, iobase + MAC_REG_SOFTPWRCTL); + + vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, + (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); + /* PLL Off */ + vt6655_mac_word_reg_bits_off(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + /* patch abnormal AL2230 frequency output */ + IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); + + for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) + ret &= IFRFbWriteEmbedded(priv, al2230_init_table[ii]); + MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */ + + /* PLL On */ + vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); + + MACvTimer0MicroSDelay(priv, 150);/* 150us */ + ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); + MACvTimer0MicroSDelay(priv, 30);/* 30us */ + ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); + MACvTimer0MicroSDelay(priv, 30);/* 30us */ + ret &= IFRFbWriteEmbedded(priv, + al2230_init_table[CB_AL2230_INIT_SEQ - 1]); + + vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | + SOFTPWRCTL_SWPE2 | + SOFTPWRCTL_SWPECTI | + SOFTPWRCTL_TXPEINV)); + + /* 3-wire control for power saving mode */ + iowrite8(PSSIG_WPE3 | PSSIG_WPE2, iobase + MAC_REG_PSPWRSIG); + + return ret; +} + +static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel) +{ + void __iomem *iobase = priv->port_offset; + bool ret; + + ret = true; + + ret &= IFRFbWriteEmbedded(priv, al2230_channel_table0[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, al2230_channel_table1[byChannel - 1]); + + /* Set Channel[7] = 0 to tell H/W channel is changing now. */ + iowrite8(byChannel & 0x7F, iobase + MAC_REG_CHANNEL); + MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230); + /* Set Channel[7] = 1 to tell H/W channel change is done. */ + iowrite8(byChannel | 0x80, iobase + MAC_REG_CHANNEL); + + return ret; +} + +/* + * Description: RF init function + * + * Parameters: + * In: + * byBBType + * byRFType + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +bool RFbInit(struct vnt_private *priv) +{ + bool ret = true; + + switch (priv->byRFType) { + case RF_AIROHA: + case RF_AL2230S: + priv->max_pwr_level = AL2230_PWR_IDX_LEN; + ret = RFbAL2230Init(priv); + break; + case RF_NOTHING: + ret = true; + break; + default: + ret = false; + break; + } + return ret; +} + +/* + * Description: Select channel + * + * Parameters: + * In: + * byRFType + * byChannel - Channel number + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, + u16 byChannel) +{ + bool ret = true; + + switch (byRFType) { + case RF_AIROHA: + case RF_AL2230S: + ret = RFbAL2230SelectChannel(priv, byChannel); + break; + /*{{ RobertYu: 20050104 */ + case RF_NOTHING: + ret = true; + break; + default: + ret = false; + break; + } + return ret; +} + +/* + * Description: Write WakeProgSyn + * + * Parameters: + * In: + * priv - Device Structure + * rf_type - RF type + * channel - Channel number + * + * Return Value: true if succeeded; false if failed. + * + */ +bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, + u16 channel) +{ + void __iomem *iobase = priv->port_offset; + int i; + unsigned char init_count = 0; + unsigned char sleep_count = 0; + unsigned short idx = MISCFIFO_SYNDATA_IDX; + + iowrite16(0, iobase + MAC_REG_MISCFFNDEX); + switch (rf_type) { + case RF_AIROHA: + case RF_AL2230S: + + if (channel > CB_MAX_CHANNEL_24G) + return false; + + /* Init Reg + Channel Reg (2) */ + init_count = CB_AL2230_INIT_SEQ + 2; + sleep_count = 0; + + for (i = 0; i < CB_AL2230_INIT_SEQ; i++) + MACvSetMISCFifo(priv, idx++, al2230_init_table[i]); + + MACvSetMISCFifo(priv, idx++, al2230_channel_table0[channel - 1]); + MACvSetMISCFifo(priv, idx++, al2230_channel_table1[channel - 1]); + break; + + /* Need to check, PLLON need to be low for channel setting */ + + case RF_NOTHING: + return true; + + default: + return false; + } + + MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(sleep_count, init_count)); + + return true; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * iobase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ +bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH) +{ + bool ret; + unsigned char byPwr = 0; + unsigned char byDec = 0; + + if (priv->dwDiagRefCount != 0) + return true; + + if ((uCH < 1) || (uCH > CB_MAX_CHANNEL)) + return false; + + switch (rate) { + case RATE_1M: + case RATE_2M: + case RATE_5M: + case RATE_11M: + if (uCH > CB_MAX_CHANNEL_24G) + return false; + + byPwr = priv->abyCCKPwrTbl[uCH]; + break; + case RATE_6M: + case RATE_9M: + case RATE_12M: + case RATE_18M: + byPwr = priv->abyOFDMPwrTbl[uCH]; + byDec = byPwr + 10; + + if (byDec >= priv->max_pwr_level) + byDec = priv->max_pwr_level - 1; + + byPwr = byDec; + break; + case RATE_24M: + case RATE_36M: + case RATE_48M: + case RATE_54M: + byPwr = priv->abyOFDMPwrTbl[uCH]; + break; + } + + if (priv->byCurPwr == byPwr) + return true; + + ret = RFbRawSetPower(priv, byPwr, rate); + if (ret) + priv->byCurPwr = byPwr; + + return ret; +} + +/* + * Description: Set Tx power + * + * Parameters: + * In: + * iobase - I/O base address + * dwRFPowerTable - RF Tx Power Setting + * Out: + * none + * + * Return Value: true if succeeded; false if failed. + * + */ + +bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr, + unsigned int rate) +{ + bool ret = true; + + if (byPwr >= priv->max_pwr_level) + return false; + + switch (priv->byRFType) { + case RF_AIROHA: + ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]); + if (rate <= RATE_11M) + ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + else + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + + break; + + case RF_AL2230S: + ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]); + if (rate <= RATE_11M) { + ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + } else { + ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); + } + + break; + + default: + break; + } + return ret; +} + +/* + * + * Routine Description: + * Translate RSSI to dBm + * + * Parameters: + * In: + * priv - The adapter to be translated + * byCurrRSSI - RSSI to be translated + * Out: + * pdwdbm - Translated dbm number + * + * Return Value: none + * + */ +void +RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, long *pldBm) +{ + unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03); + long b = (byCurrRSSI & 0x3F); + long a = 0; + unsigned char abyAIROHARF[4] = {0, 18, 0, 40}; + + switch (priv->byRFType) { + case RF_AIROHA: + case RF_AL2230S: + a = abyAIROHARF[byIdx]; + break; + default: + break; + } + + *pldBm = -1 * (a + b * 2); +} + diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h new file mode 100644 index 000000000..9fef81846 --- /dev/null +++ b/drivers/staging/vt6655/rf.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Feb. 19, 2004 + * + */ + +#ifndef __RF_H__ +#define __RF_H__ + +#include "device.h" + +/*--------------------- Export Definitions -------------------------*/ +/* + * Baseband RF pair definition in eeprom (Bits 6..0) + */ +#define RF_RFMD2959 0x01 +#define RF_MAXIMAG 0x02 +#define RF_AIROHA 0x03 + +#define RF_UW2451 0x05 +#define RF_MAXIMG 0x06 +#define RF_MAXIM2829 0x07 /* RobertYu: 20041118 */ +#define RF_UW2452 0x08 /* RobertYu: 20041210 */ +#define RF_AIROHA7230 0x0a /* RobertYu: 20050104 */ +#define RF_UW2453 0x0b + +#define RF_VT3226 0x09 +#define RF_AL2230S 0x0e + +#define RF_NOTHING 0x7E +#define RF_EMU 0x80 +#define RF_MASK 0x7F + +#define ZONE_FCC 0 +#define ZONE_MKK1 1 +#define ZONE_ETSI 2 +#define ZONE_IC 3 +#define ZONE_SPAIN 4 +#define ZONE_FRANCE 5 +#define ZONE_MKK 6 +#define ZONE_ISRAEL 7 + +/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */ +#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */ +#define CB_UW2452_CHANNEL_5G_HIGH 41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData); +bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, u16 byChannel); +bool RFbInit(struct vnt_private *priv); +bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, u16 channel); +bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH); +bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr, + unsigned int rate); + +void RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, + long *pldBm); + +/* {{ RobertYu: 20050104 */ +bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel); +/* }} RobertYu */ + +#endif /* __RF_H__ */ diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c new file mode 100644 index 000000000..5bdb51767 --- /dev/null +++ b/drivers/staging/vt6655/rxtx.c @@ -0,0 +1,1462 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: handle WMAC/802.3/802.11 rx & tx functions + * + * Author: Lyndon Chen + * + * Date: May 20, 2003 + * + * Functions: + * s_vGenerateTxParameter - Generate tx dma required parameter. + * vGenerateMACHeader - Translate 802.3 to 802.11 header + * cbGetFragCount - Calculate fragment number count + * csBeacon_xmit - beacon tx function + * csMgmt_xmit - management tx function + * s_cbFillTxBufHead - fulfill tx dma buffer header + * s_uGetDataDuration - get tx data required duration + * s_uFillDataHead- fulfill tx data duration header + * s_uGetRTSCTSDuration- get rtx/cts required duration + * get_rtscts_time- get rts/cts reserved time + * s_uGetTxRsvTime- get frame reserved time + * s_vFillCTSHead- fulfill CTS ctl header + * s_vFillFragParameter- Set fragment ctl parameter. + * s_vFillRTSHead- fulfill RTS ctl header + * s_vFillTxKey- fulfill tx encrypt key + * s_vSWencryption- Software encrypt header + * vDMA0_tx_80211- tx 802.11 frame via dma0 + * vGenerateFIFOHeader- Generate tx FIFO ctl header + * + * Revision History: + * + */ + +#include "device.h" +#include "rxtx.h" +#include "card.h" +#include "mac.h" +#include "baseband.h" +#include "rf.h" + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Static Definitions -------------------------*/ +/* if packet size < 256 -> in-direct send + * vpacket size >= 256 -> direct send + */ +#define CRITICAL_PACKET_LEN 256 + +static const unsigned short wTimeStampOff[2][MAX_RATE] = { + {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */ + {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, /* Short Preamble */ +}; + +static const unsigned short wFB_Opt0[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */ + {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */ +}; + +static const unsigned short wFB_Opt1[2][5] = { + {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */ + {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ +}; + +#define RTSDUR_BB 0 +#define RTSDUR_BA 1 +#define RTSDUR_AA 2 +#define CTSDUR_BA 3 +#define RTSDUR_BA_F0 4 +#define RTSDUR_AA_F0 5 +#define RTSDUR_BA_F1 6 +#define RTSDUR_AA_F1 7 +#define CTSDUR_BA_F0 8 +#define CTSDUR_BA_F1 9 +#define DATADUR_B 10 +#define DATADUR_A 11 +#define DATADUR_A_F0 12 +#define DATADUR_A_F1 13 + +/*--------------------- Static Functions --------------------------*/ +static +void +s_vFillRTSHead( + struct vnt_private *pDevice, + unsigned char byPktType, + void *pvRTS, + unsigned int cbFrameLength, + bool bNeedAck, + bool bDisCRC, + struct ieee80211_hdr *hdr, + unsigned short wCurrentRate, + unsigned char byFBOption +); + +static +void +s_vGenerateTxParameter( + struct vnt_private *pDevice, + unsigned char byPktType, + struct vnt_tx_fifo_head *, + void *pvRrvTime, + void *pvRTS, + void *pvCTS, + unsigned int cbFrameSize, + bool bNeedACK, + unsigned int uDMAIdx, + void *psEthHeader, + unsigned short wCurrentRate +); + +static unsigned int +s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, + unsigned char *pbyTxBufferAddr, + unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD, + unsigned int uNodeIndex); + +static +__le16 +s_uFillDataHead( + struct vnt_private *pDevice, + unsigned char byPktType, + void *pTxDataHead, + unsigned int cbFrameLength, + unsigned int uDMAIdx, + bool bNeedAck, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, + unsigned char byFBOption, + unsigned short wCurrentRate, + bool is_pspoll +); + +/*--------------------- Export Variables --------------------------*/ + +static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) +{ + return cpu_to_le16(wTimeStampOff[priv->preamble_type % 2] + [rate % MAX_RATE]); +} + +/* byPktType : PK_TYPE_11A 0 + * PK_TYPE_11B 1 + * PK_TYPE_11GB 2 + * PK_TYPE_11GA 3 + */ +static +unsigned int +s_uGetTxRsvTime( + struct vnt_private *pDevice, + unsigned char byPktType, + unsigned int cbFrameLength, + unsigned short wRate, + bool bNeedAck +) +{ + unsigned int uDataTime, uAckTime; + + uDataTime = bb_get_frame_time(pDevice->preamble_type, byPktType, cbFrameLength, wRate); + + if (!bNeedAck) + return uDataTime; + + /* + * CCK mode - 11b + * OFDM mode - 11g 2.4G & 11a 5G + */ + uAckTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, + byPktType == PK_TYPE_11B ? + pDevice->byTopCCKBasicRate : + pDevice->byTopOFDMBasicRate); + + return uDataTime + pDevice->uSIFS + uAckTime; +} + +static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type, + u32 frame_length, u16 rate, bool need_ack) +{ + return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type, + frame_length, rate, need_ack)); +} + +/* byFreqType: 0=>5GHZ 1=>2.4GHZ */ +static __le16 get_rtscts_time(struct vnt_private *priv, + unsigned char rts_rsvtype, + unsigned char pkt_type, + unsigned int frame_length, + unsigned short current_rate) +{ + unsigned int rrv_time = 0; + unsigned int rts_time = 0; + unsigned int cts_time = 0; + unsigned int ack_time = 0; + unsigned int data_time = 0; + + data_time = bb_get_frame_time(priv->preamble_type, pkt_type, frame_length, current_rate); + if (rts_rsvtype == 0) { /* RTSTxRrvTime_bb */ + rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); + cts_time = ack_time; + } else if (rts_rsvtype == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */ + rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate); + cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); + } else if (rts_rsvtype == 2) { /* RTSTxRrvTime_aa */ + rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopOFDMBasicRate); + ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); + cts_time = ack_time; + } else if (rts_rsvtype == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */ + cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); + ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); + rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS; + return cpu_to_le16((u16)rrv_time); + } + + /* RTSRrvTime */ + rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS; + return cpu_to_le16((u16)rrv_time); +} + +/* byFreqType 0: 5GHz, 1:2.4Ghz */ +static +unsigned int +s_uGetDataDuration( + struct vnt_private *pDevice, + unsigned char byDurType, + unsigned int cbFrameLength, + unsigned char byPktType, + unsigned short wRate, + bool bNeedAck, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, + unsigned char byFBOption +) +{ + bool bLastFrag = false; + unsigned int uAckTime = 0, uNextPktTime = 0, len; + + if (uFragIdx == (uMACfragNum - 1)) + bLastFrag = true; + + if (uFragIdx == (uMACfragNum - 2)) + len = cbLastFragmentSize; + else + len = cbFrameLength; + + switch (byDurType) { + case DATADUR_B: /* DATADUR_B */ + if (bNeedAck) { + uAckTime = bb_get_frame_time(pDevice->preamble_type, + byPktType, 14, + pDevice->byTopCCKBasicRate); + } + /* Non Frag or Last Frag */ + if ((uMACfragNum == 1) || bLastFrag) { + if (!bNeedAck) + return 0; + } else { + /* First Frag or Mid Frag */ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, + len, wRate, bNeedAck); + } + + return pDevice->uSIFS + uAckTime + uNextPktTime; + + case DATADUR_A: /* DATADUR_A */ + if (bNeedAck) { + uAckTime = bb_get_frame_time(pDevice->preamble_type, + byPktType, 14, + pDevice->byTopOFDMBasicRate); + } + /* Non Frag or Last Frag */ + if ((uMACfragNum == 1) || bLastFrag) { + if (!bNeedAck) + return 0; + } else { + /* First Frag or Mid Frag */ + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, + len, wRate, bNeedAck); + } + + return pDevice->uSIFS + uAckTime + uNextPktTime; + + case DATADUR_A_F0: /* DATADUR_A_F0 */ + case DATADUR_A_F1: /* DATADUR_A_F1 */ + if (bNeedAck) { + uAckTime = bb_get_frame_time(pDevice->preamble_type, + byPktType, 14, + pDevice->byTopOFDMBasicRate); + } + /* Non Frag or Last Frag */ + if ((uMACfragNum == 1) || bLastFrag) { + if (!bNeedAck) + return 0; + } else { + /* First Frag or Mid Frag */ + if (wRate < RATE_18M) + wRate = RATE_18M; + else if (wRate > RATE_54M) + wRate = RATE_54M; + + wRate -= RATE_18M; + + if (byFBOption == AUTO_FB_0) + wRate = wFB_Opt0[FB_RATE0][wRate]; + else + wRate = wFB_Opt1[FB_RATE0][wRate]; + + uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, + len, wRate, bNeedAck); + } + + return pDevice->uSIFS + uAckTime + uNextPktTime; + + default: + break; + } + + return 0; +} + +/* byFreqType: 0=>5GHZ 1=>2.4GHZ */ +static +__le16 +s_uGetRTSCTSDuration( + struct vnt_private *pDevice, + unsigned char byDurType, + unsigned int cbFrameLength, + unsigned char byPktType, + unsigned short wRate, + bool bNeedAck, + unsigned char byFBOption +) +{ + unsigned int uCTSTime = 0, uDurTime = 0; + + switch (byDurType) { + case RTSDUR_BB: /* RTSDuration_bb */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA: /* RTSDuration_ba */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_AA: /* RTSDuration_aa */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case CTSDUR_BA: /* CTSDuration_ba */ + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); + break; + + case RTSDUR_BA_F0: /* RTSDuration_ba_f0 */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); + + break; + + case RTSDUR_AA_F0: /* RTSDuration_aa_f0 */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); + + break; + + case RTSDUR_BA_F1: /* RTSDuration_ba_f1 */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); + + break; + + case RTSDUR_AA_F1: /* RTSDuration_aa_f1 */ + uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); + + break; + + case CTSDUR_BA_F0: /* CTSDuration_ba_f0 */ + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); + + break; + + case CTSDUR_BA_F1: /* CTSDuration_ba_f1 */ + if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); + else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); + + break; + + default: + break; + } + + return cpu_to_le16((u16)uDurTime); +} + +static +__le16 +s_uFillDataHead( + struct vnt_private *pDevice, + unsigned char byPktType, + void *pTxDataHead, + unsigned int cbFrameLength, + unsigned int uDMAIdx, + bool bNeedAck, + unsigned int uFragIdx, + unsigned int cbLastFragmentSize, + unsigned int uMACfragNum, + unsigned char byFBOption, + unsigned short wCurrentRate, + bool is_pspoll +) +{ + struct vnt_tx_datahead_ab *buf = pTxDataHead; + + if (!pTxDataHead) + return 0; + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + /* Auto Fallback */ + struct vnt_tx_datahead_g_fb *buf = pTxDataHead; + + if (byFBOption == AUTO_FB_NONE) { + struct vnt_tx_datahead_g *buf = pTxDataHead; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, + byPktType, &buf->a); + + vnt_get_phy_field(pDevice, cbFrameLength, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + + if (is_pspoll) { + __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); + + buf->duration_a = dur; + buf->duration_b = dur; + } else { + /* Get Duration and TimeStamp */ + buf->duration_a = + cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, + byPktType, wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); + buf->duration_b = + cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, + PK_TYPE_11B, pDevice->byTopCCKBasicRate, + bNeedAck, uFragIdx, cbLastFragmentSize, + uMACfragNum, byFBOption)); + } + + buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate); + buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate); + + return buf->duration_a; + } + + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, + byPktType, &buf->a); + + vnt_get_phy_field(pDevice, cbFrameLength, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + /* Get Duration and TimeStamp */ + buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, + pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + + buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate); + buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate); + + return buf->duration_a; + /* if (byFBOption == AUTO_FB_NONE) */ + } else if (byPktType == PK_TYPE_11A) { + struct vnt_tx_datahead_ab *buf = pTxDataHead; + + if (byFBOption != AUTO_FB_NONE) { + /* Auto Fallback */ + struct vnt_tx_datahead_a_fb *buf = pTxDataHead; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, + byPktType, &buf->a); + + /* Get Duration and TimeStampOff */ + buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); + buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); + return buf->duration; + } + + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, + byPktType, &buf->ab); + + if (is_pspoll) { + __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); + + buf->duration = dur; + } else { + /* Get Duration and TimeStampOff */ + buf->duration = + cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); + } + + buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); + return buf->duration; + } + + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, + byPktType, &buf->ab); + + if (is_pspoll) { + __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); + + buf->duration = dur; + } else { + /* Get Duration and TimeStampOff */ + buf->duration = + cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType, + wCurrentRate, bNeedAck, uFragIdx, + cbLastFragmentSize, uMACfragNum, + byFBOption)); + } + + buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); + return buf->duration; +} + +static +void +s_vFillRTSHead( + struct vnt_private *pDevice, + unsigned char byPktType, + void *pvRTS, + unsigned int cbFrameLength, + bool bNeedAck, + bool bDisCRC, + struct ieee80211_hdr *hdr, + unsigned short wCurrentRate, + unsigned char byFBOption +) +{ + unsigned int uRTSFrameLen = 20; + + if (!pvRTS) + return; + + if (bDisCRC) { + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * RTS frame, in this case we need to decrease its length by 4. + */ + uRTSFrameLen -= 4; + } + + /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, + * so we don't need to take them into account. + * Otherwise, we need to modify codes for them. + */ + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (byFBOption == AUTO_FB_NONE) { + struct vnt_rts_g *buf = pvRTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopOFDMBasicRate, + byPktType, &buf->a); + /* Get Duration */ + buf->duration_bb = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, + cbFrameLength, PK_TYPE_11B, + pDevice->byTopCCKBasicRate, + bNeedAck, byFBOption); + buf->duration_aa = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->duration_ba = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + + buf->data.duration = buf->duration_aa; + /* Get RTS Frame body */ + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_RTS); + + ether_addr_copy(buf->data.ra, hdr->addr1); + ether_addr_copy(buf->data.ta, hdr->addr2); + } else { + struct vnt_rts_g_fb *buf = pvRTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopOFDMBasicRate, + byPktType, &buf->a); + /* Get Duration */ + buf->duration_bb = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, + cbFrameLength, PK_TYPE_11B, + pDevice->byTopCCKBasicRate, + bNeedAck, byFBOption); + buf->duration_aa = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->duration_ba = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_ba_f0 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_aa_f0 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_ba_f1 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_aa_f1 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->data.duration = buf->duration_aa; + /* Get RTS Frame body */ + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_RTS); + + ether_addr_copy(buf->data.ra, hdr->addr1); + ether_addr_copy(buf->data.ta, hdr->addr2); + } /* if (byFBOption == AUTO_FB_NONE) */ + } else if (byPktType == PK_TYPE_11A) { + if (byFBOption == AUTO_FB_NONE) { + struct vnt_rts_ab *buf = pvRTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopOFDMBasicRate, + byPktType, &buf->ab); + /* Get Duration */ + buf->duration = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->data.duration = buf->duration; + /* Get RTS Frame body */ + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_RTS); + + ether_addr_copy(buf->data.ra, hdr->addr1); + ether_addr_copy(buf->data.ta, hdr->addr2); + } else { + struct vnt_rts_a_fb *buf = pvRTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopOFDMBasicRate, + byPktType, &buf->a); + /* Get Duration */ + buf->duration = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_f0 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->rts_duration_f1 = + s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + buf->data.duration = buf->duration; + /* Get RTS Frame body */ + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_RTS); + + ether_addr_copy(buf->data.ra, hdr->addr1); + ether_addr_copy(buf->data.ta, hdr->addr2); + } + } else if (byPktType == PK_TYPE_11B) { + struct vnt_rts_ab *buf = pvRTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uRTSFrameLen, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->ab); + /* Get Duration */ + buf->duration = + s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, + byPktType, wCurrentRate, bNeedAck, + byFBOption); + + buf->data.duration = buf->duration; + /* Get RTS Frame body */ + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); + + ether_addr_copy(buf->data.ra, hdr->addr1); + ether_addr_copy(buf->data.ta, hdr->addr2); + } +} + +static +void +s_vFillCTSHead( + struct vnt_private *pDevice, + unsigned int uDMAIdx, + unsigned char byPktType, + void *pvCTS, + unsigned int cbFrameLength, + bool bNeedAck, + bool bDisCRC, + unsigned short wCurrentRate, + unsigned char byFBOption +) +{ + unsigned int uCTSFrameLen = 14; + + if (!pvCTS) + return; + + if (bDisCRC) { + /* When CRCDIS bit is on, H/W forgot to generate FCS for + * CTS frame, in this case we need to decrease its length by 4. + */ + uCTSFrameLen -= 4; + } + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) { + /* Auto Fall back */ + struct vnt_cts_fb *buf = pvCTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uCTSFrameLen, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + + buf->duration_ba = + s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + + /* Get CTSDuration_ba_f0 */ + buf->cts_duration_ba_f0 = + s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + + /* Get CTSDuration_ba_f1 */ + buf->cts_duration_ba_f1 = + s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + + /* Get CTS Frame body */ + buf->data.duration = buf->duration_ba; + + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_CTS); + + buf->reserved2 = 0x0; + + ether_addr_copy(buf->data.ra, + pDevice->abyCurrentNetAddr); + } else { /* if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) */ + struct vnt_cts *buf = pvCTS; + /* Get SignalField, ServiceField & Length */ + vnt_get_phy_field(pDevice, uCTSFrameLen, + pDevice->byTopCCKBasicRate, + PK_TYPE_11B, &buf->b); + + /* Get CTSDuration_ba */ + buf->duration_ba = + s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, + cbFrameLength, byPktType, + wCurrentRate, bNeedAck, + byFBOption); + + /* Get CTS Frame body */ + buf->data.duration = buf->duration_ba; + + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_CTS); + + buf->reserved2 = 0x0; + ether_addr_copy(buf->data.ra, + pDevice->abyCurrentNetAddr); + } + } +} + +/* + * + * Description: + * Generate FIFO control for MAC & Baseband controller + * + * Parameters: + * In: + * pDevice - Pointer to adapter + * pTxDataHead - Transmit Data Buffer + * pTxBufHead - pTxBufHead + * pvRrvTime - pvRrvTime + * pvRTS - RTS Buffer + * pCTS - CTS Buffer + * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) + * bNeedACK - If need ACK + * uDescIdx - Desc Index + * Out: + * none + * + * Return Value: none + * + - + * unsigned int cbFrameSize, Hdr+Payload+FCS + */ +static +void +s_vGenerateTxParameter( + struct vnt_private *pDevice, + unsigned char byPktType, + struct vnt_tx_fifo_head *tx_buffer_head, + void *pvRrvTime, + void *pvRTS, + void *pvCTS, + unsigned int cbFrameSize, + bool bNeedACK, + unsigned int uDMAIdx, + void *psEthHeader, + unsigned short wCurrentRate +) +{ + u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl); + bool bDisCRC = false; + unsigned char byFBOption = AUTO_FB_NONE; + + tx_buffer_head->current_rate = cpu_to_le16(wCurrentRate); + + if (fifo_ctl & FIFOCTL_CRCDIS) + bDisCRC = true; + + if (fifo_ctl & FIFOCTL_AUTO_FB_0) + byFBOption = AUTO_FB_0; + else if (fifo_ctl & FIFOCTL_AUTO_FB_1) + byFBOption = AUTO_FB_1; + + if (!pvRrvTime) + return; + + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (pvRTS) { /* RTS_need */ + /* Fill RsvTime */ + struct vnt_rrv_time_rts *buf = pvRrvTime; + + buf->rts_rrv_time_aa = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time_ba = get_rtscts_time(pDevice, 1, byPktType, cbFrameSize, wCurrentRate); + buf->rts_rrv_time_bb = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); + buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); + buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); + + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } else {/* RTS_needless, PCF mode */ + struct vnt_rrv_time_cts *buf = pvRrvTime; + + buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); + buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); + buf->cts_rrv_time_ba = get_rtscts_time(pDevice, 3, byPktType, cbFrameSize, wCurrentRate); + + /* Fill CTS */ + s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); + } + } else if (byPktType == PK_TYPE_11A) { + if (pvRTS) {/* RTS_need, non PCF mode */ + struct vnt_rrv_time_ab *buf = pvRrvTime; + + buf->rts_rrv_time = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); + buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); + + /* Fill RTS */ + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } else if (!pvRTS) {/* RTS_needless, non PCF mode */ + struct vnt_rrv_time_ab *buf = pvRrvTime; + + buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK); + } + } else if (byPktType == PK_TYPE_11B) { + if (pvRTS) {/* RTS_need, non PCF mode */ + struct vnt_rrv_time_ab *buf = pvRrvTime; + + buf->rts_rrv_time = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); + buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK); + + /* Fill RTS */ + s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); + } else { /* RTS_needless, non PCF mode */ + struct vnt_rrv_time_ab *buf = pvRrvTime; + + buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK); + } + } +} + +static unsigned int +s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, + unsigned char *pbyTxBufferAddr, + unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD, + unsigned int is_pspoll) +{ + struct vnt_td_info *td_info = pHeadTD->td_info; + struct sk_buff *skb = td_info->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct vnt_tx_fifo_head *tx_buffer_head = + (struct vnt_tx_fifo_head *)td_info->buf; + u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl); + unsigned int cbFrameSize; + __le16 uDuration; + unsigned char *pbyBuffer; + unsigned int uLength = 0; + unsigned int cbMICHDR = 0; + unsigned int uMACfragNum = 1; + unsigned int uPadding = 0; + unsigned int cbReqCount = 0; + bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK); + bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS); + struct vnt_tx_desc *ptdCurr; + unsigned int cbHeaderLength = 0; + void *pvRrvTime = NULL; + struct vnt_mic_hdr *pMICHDR = NULL; + void *pvRTS = NULL; + void *pvCTS = NULL; + void *pvTxDataHd = NULL; + unsigned short wTxBufSize; /* FFinfo size */ + unsigned char byFBOption = AUTO_FB_NONE; + + cbFrameSize = skb->len + 4; + + if (info->control.hw_key) { + switch (info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + cbMICHDR = sizeof(struct vnt_mic_hdr); + break; + default: + break; + } + + cbFrameSize += info->control.hw_key->icv_len; + + if (pDevice->local_id > REV_ID_VT3253_A1) { + /* MAC Header should be padding 0 to DW alignment. */ + uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4); + uPadding %= 4; + } + } + + /* + * Use for AUTO FALL BACK + */ + if (fifo_ctl & FIFOCTL_AUTO_FB_0) + byFBOption = AUTO_FB_0; + else if (fifo_ctl & FIFOCTL_AUTO_FB_1) + byFBOption = AUTO_FB_1; + + /* Set RrvTime/RTS/CTS Buffer */ + wTxBufSize = sizeof(struct vnt_tx_fifo_head); + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */ + + if (byFBOption == AUTO_FB_NONE) { + if (bRTS) {/* RTS_need */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); + pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + + cbMICHDR + sizeof(struct vnt_rts_g)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + + cbMICHDR + sizeof(struct vnt_rts_g) + + sizeof(struct vnt_tx_datahead_g); + } else { /* RTS_needless */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); + pvRTS = NULL; + pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + + sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + + cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g); + } + } else { + /* Auto Fall Back */ + if (bRTS) {/* RTS_need */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); + pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + + cbMICHDR + sizeof(struct vnt_rts_g_fb)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + + cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb); + } else { /* RTS_needless */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); + pvRTS = NULL; + pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + + cbMICHDR + sizeof(struct vnt_cts_fb)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + + cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb); + } + } /* Auto Fall Back */ + } else {/* 802.11a/b packet */ + + if (byFBOption == AUTO_FB_NONE) { + if (bRTS) { + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); + pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + + cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab); + } else { /* RTS_needless, need MICHDR */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + + cbMICHDR + sizeof(struct vnt_tx_datahead_ab); + } + } else { + /* Auto Fall Back */ + if (bRTS) { /* RTS_need */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); + pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb)); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + + cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb); + } else { /* RTS_needless */ + pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); + pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); + pvRTS = NULL; + pvCTS = NULL; + pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); + cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + + cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb); + } + } /* Auto Fall Back */ + } + + td_info->mic_hdr = pMICHDR; + + memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize)); + + /* Fill FIFO,RrvTime,RTS,and CTS */ + s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS, + cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate); + /* Fill DataHead */ + uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, + 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll); + + hdr->duration_id = uDuration; + + cbReqCount = cbHeaderLength + uPadding + skb->len; + pbyBuffer = (unsigned char *)pHeadTD->td_info->buf; + uLength = cbHeaderLength + uPadding; + + /* Copy the Packet into a tx Buffer */ + memcpy((pbyBuffer + uLength), skb->data, skb->len); + + ptdCurr = pHeadTD; + + ptdCurr->td_info->req_count = (u16)cbReqCount; + + return cbHeaderLength; +} + +static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer, + struct ieee80211_key_conf *tx_key, + struct sk_buff *skb, u16 payload_len, + struct vnt_mic_hdr *mic_hdr) +{ + u64 pn64; + u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb)); + + /* strip header and icv len from payload */ + payload_len -= ieee80211_get_hdrlen_from_skb(skb); + payload_len -= tx_key->icv_len; + + switch (tx_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + memcpy(key_buffer, iv, 3); + memcpy(key_buffer + 3, tx_key->key, tx_key->keylen); + + if (tx_key->keylen == WLAN_KEY_LEN_WEP40) { + memcpy(key_buffer + 8, iv, 3); + memcpy(key_buffer + 11, + tx_key->key, WLAN_KEY_LEN_WEP40); + } + + break; + case WLAN_CIPHER_SUITE_TKIP: + ieee80211_get_tkip_p2k(tx_key, skb, key_buffer); + + break; + case WLAN_CIPHER_SUITE_CCMP: + + if (!mic_hdr) + return; + + mic_hdr->id = 0x59; + mic_hdr->payload_len = cpu_to_be16(payload_len); + ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); + + pn64 = atomic64_read(&tx_key->tx_pn); + mic_hdr->ccmp_pn[5] = pn64; + mic_hdr->ccmp_pn[4] = pn64 >> 8; + mic_hdr->ccmp_pn[3] = pn64 >> 16; + mic_hdr->ccmp_pn[2] = pn64 >> 24; + mic_hdr->ccmp_pn[1] = pn64 >> 32; + mic_hdr->ccmp_pn[0] = pn64 >> 40; + + if (ieee80211_has_a4(hdr->frame_control)) + mic_hdr->hlen = cpu_to_be16(28); + else + mic_hdr->hlen = cpu_to_be16(22); + + ether_addr_copy(mic_hdr->addr1, hdr->addr1); + ether_addr_copy(mic_hdr->addr2, hdr->addr2); + ether_addr_copy(mic_hdr->addr3, hdr->addr3); + + mic_hdr->frame_control = cpu_to_le16( + le16_to_cpu(hdr->frame_control) & 0xc78f); + mic_hdr->seq_ctrl = cpu_to_le16( + le16_to_cpu(hdr->seq_ctrl) & 0xf); + + if (ieee80211_has_a4(hdr->frame_control)) + ether_addr_copy(mic_hdr->addr4, hdr->addr4); + + memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP); + + break; + default: + break; + } +} + +int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, + struct vnt_tx_desc *head_td, struct sk_buff *skb) +{ + struct vnt_td_info *td_info = head_td->td_info; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *tx_rate = &info->control.rates[0]; + struct ieee80211_rate *rate; + struct ieee80211_key_conf *tx_key; + struct ieee80211_hdr *hdr; + struct vnt_tx_fifo_head *tx_buffer_head = + (struct vnt_tx_fifo_head *)td_info->buf; + u16 tx_body_size = skb->len, current_rate; + u8 pkt_type; + bool is_pspoll = false; + + memset(tx_buffer_head, 0, sizeof(*tx_buffer_head)); + + hdr = (struct ieee80211_hdr *)(skb->data); + + rate = ieee80211_get_tx_rate(priv->hw, info); + + current_rate = rate->hw_value; + if (priv->wCurrentRate != current_rate && + !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { + priv->wCurrentRate = current_rate; + + RFbSetPower(priv, priv->wCurrentRate, + priv->hw->conf.chandef.chan->hw_value); + } + + if (current_rate > RATE_11M) { + if (info->band == NL80211_BAND_5GHZ) { + pkt_type = PK_TYPE_11A; + } else { + if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) + pkt_type = PK_TYPE_11GB; + else + pkt_type = PK_TYPE_11GA; + } + } else { + pkt_type = PK_TYPE_11B; + } + + /*Set fifo controls */ + if (pkt_type == PK_TYPE_11A) + tx_buffer_head->fifo_ctl = 0; + else if (pkt_type == PK_TYPE_11B) + tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B); + else if (pkt_type == PK_TYPE_11GB) + tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB); + else if (pkt_type == PK_TYPE_11GA) + tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA); + + /* generate interrupt */ + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT); + + if (!ieee80211_is_data(hdr->frame_control)) { + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN); + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0); + tx_buffer_head->time_stamp = + cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); + } else { + tx_buffer_head->time_stamp = + cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); + } + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK); + + if (ieee80211_has_retry(hdr->frame_control)) + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY); + + if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + priv->preamble_type = PREAMBLE_SHORT; + else + priv->preamble_type = PREAMBLE_LONG; + + if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS); + + if (ieee80211_has_a4(hdr->frame_control)) { + tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD); + priv->bLongHeader = true; + } + + if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) + is_pspoll = true; + + tx_buffer_head->frag_ctl = + cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10); + + if (info->control.hw_key) { + switch (info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY); + break; + case WLAN_CIPHER_SUITE_TKIP: + tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP); + break; + case WLAN_CIPHER_SUITE_CCMP: + tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES); + break; + default: + break; + } + } + + tx_buffer_head->current_rate = cpu_to_le16(current_rate); + + /* legacy rates TODO use ieee80211_tx_rate */ + if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) { + if (priv->byAutoFBCtrl == AUTO_FB_0) + tx_buffer_head->fifo_ctl |= + cpu_to_le16(FIFOCTL_AUTO_FB_0); + else if (priv->byAutoFBCtrl == AUTO_FB_1) + tx_buffer_head->fifo_ctl |= + cpu_to_le16(FIFOCTL_AUTO_FB_1); + } + + tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); + + s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head, + dma_idx, head_td, is_pspoll); + + if (info->control.hw_key) { + tx_key = info->control.hw_key; + if (tx_key->keylen > 0) + vnt_fill_txkey(hdr, tx_buffer_head->tx_key, + tx_key, skb, tx_body_size, + td_info->mic_hdr); + } + + return 0; +} + +static int vnt_beacon_xmit(struct vnt_private *priv, + struct sk_buff *skb) +{ + struct vnt_tx_short_buf_head *short_head = + (struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs; + struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *) + (priv->tx_beacon_bufs + sizeof(*short_head)); + struct ieee80211_tx_info *info; + u32 frame_size = skb->len + 4; + u16 current_rate; + + memset(priv->tx_beacon_bufs, 0, sizeof(*short_head)); + + if (priv->byBBType == BB_TYPE_11A) { + current_rate = RATE_6M; + + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, frame_size, current_rate, + PK_TYPE_11A, &short_head->ab); + + /* Get Duration and TimeStampOff */ + short_head->duration = + cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B, + frame_size, PK_TYPE_11A, current_rate, + false, 0, 0, 1, AUTO_FB_NONE)); + + short_head->time_stamp_off = + vnt_time_stamp_off(priv, current_rate); + } else { + current_rate = RATE_1M; + short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B); + + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, frame_size, current_rate, + PK_TYPE_11B, &short_head->ab); + + /* Get Duration and TimeStampOff */ + short_head->duration = + cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B, + frame_size, PK_TYPE_11B, current_rate, + false, 0, 0, 1, AUTO_FB_NONE)); + + short_head->time_stamp_off = + vnt_time_stamp_off(priv, current_rate); + } + + short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT); + + /* Copy Beacon */ + memcpy(mgmt_hdr, skb->data, skb->len); + + /* time stamp always 0 */ + mgmt_hdr->u.beacon.timestamp = 0; + + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr; + + hdr->duration_id = 0; + hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4); + } + + priv->wSeqCounter++; + if (priv->wSeqCounter > 0x0fff) + priv->wSeqCounter = 0; + + priv->wBCNBufLen = sizeof(*short_head) + skb->len; + + iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR); + + iowrite16(priv->wBCNBufLen, priv->port_offset + MAC_REG_BCNDMACTL + 2); + /* Set auto Transmit on */ + vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); + /* Poll Transmit the adapter */ + iowrite8(BEACON_READY, priv->port_offset + MAC_REG_BCNDMACTL); + + return 0; +} + +int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif) +{ + struct sk_buff *beacon; + + beacon = ieee80211_beacon_get(priv->hw, vif, 0); + if (!beacon) + return -ENOMEM; + + if (vnt_beacon_xmit(priv, beacon)) { + ieee80211_free_txskb(priv->hw, beacon); + return -ENODEV; + } + + return 0; +} + +int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf) +{ + iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); + + iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); + + CARDvSetFirstNextTBTT(priv, conf->beacon_int); + + CARDbSetBeaconPeriod(priv, conf->beacon_int); + + return vnt_beacon_make(priv, vif); +} diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h new file mode 100644 index 000000000..a67757c9b --- /dev/null +++ b/drivers/staging/vt6655/rxtx.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: + * + * Author: Jerry Chen + * + * Date: Jun. 27, 2002 + * + */ + +#ifndef __RXTX_H__ +#define __RXTX_H__ + +#include "device.h" + +#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */ +#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */ + + +/*--------------------- Export Definitions -------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* MIC HDR data header */ +struct vnt_mic_hdr { + u8 id; + u8 tx_priority; + u8 mic_addr2[ETH_ALEN]; + u8 ccmp_pn[IEEE80211_CCMP_PN_LEN]; + __be16 payload_len; + __be16 hlen; + __le16 frame_control; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctrl; + u8 addr4[ETH_ALEN]; + u16 packing; /* packing to 48 bytes */ +} __packed; + +/* RsvTime buffer header */ +struct vnt_rrv_time_rts { + __le16 rts_rrv_time_ba; + __le16 rts_rrv_time_aa; + __le16 rts_rrv_time_bb; + u16 reserved; + __le16 rrv_time_b; + __le16 rrv_time_a; +} __packed; + +struct vnt_rrv_time_cts { + __le16 cts_rrv_time_ba; + u16 reserved; + __le16 rrv_time_b; + __le16 rrv_time_a; +} __packed; + +struct vnt_rrv_time_ab { + __le16 rts_rrv_time; + __le16 rrv_time; +} __packed; + +/* TX data header */ +struct vnt_tx_datahead_g { + struct vnt_phy_field b; + struct vnt_phy_field a; + __le16 duration_b; + __le16 duration_a; + __le16 time_stamp_off_b; + __le16 time_stamp_off_a; +} __packed; + +struct vnt_tx_datahead_g_fb { + struct vnt_phy_field b; + struct vnt_phy_field a; + __le16 duration_b; + __le16 duration_a; + __le16 duration_a_f0; + __le16 duration_a_f1; + __le16 time_stamp_off_b; + __le16 time_stamp_off_a; +} __packed; + +struct vnt_tx_datahead_ab { + struct vnt_phy_field ab; + __le16 duration; + __le16 time_stamp_off; +} __packed; + +struct vnt_tx_datahead_a_fb { + struct vnt_phy_field a; + __le16 duration; + __le16 time_stamp_off; + __le16 duration_f0; + __le16 duration_f1; +} __packed; + +/* RTS buffer header */ +struct vnt_rts_g { + struct vnt_phy_field b; + struct vnt_phy_field a; + __le16 duration_ba; + __le16 duration_aa; + __le16 duration_bb; + u16 reserved; + struct ieee80211_rts data; +} __packed __aligned(2); + +struct vnt_rts_g_fb { + struct vnt_phy_field b; + struct vnt_phy_field a; + __le16 duration_ba; + __le16 duration_aa; + __le16 duration_bb; + u16 wReserved; + __le16 rts_duration_ba_f0; + __le16 rts_duration_aa_f0; + __le16 rts_duration_ba_f1; + __le16 rts_duration_aa_f1; + struct ieee80211_rts data; +} __packed __aligned(2); + +struct vnt_rts_ab { + struct vnt_phy_field ab; + __le16 duration; + u16 reserved; + struct ieee80211_rts data; +} __packed __aligned(2); + +struct vnt_rts_a_fb { + struct vnt_phy_field a; + __le16 duration; + u16 reserved; + __le16 rts_duration_f0; + __le16 rts_duration_f1; + struct ieee80211_rts data; +} __packed __aligned(2); + +/* CTS buffer header */ +struct vnt_cts { + struct vnt_phy_field b; + __le16 duration_ba; + u16 reserved; + struct ieee80211_cts data; + u16 reserved2; +} __packed __aligned(2); + +struct vnt_cts_fb { + struct vnt_phy_field b; + __le16 duration_ba; + u16 reserved; + __le16 cts_duration_ba_f0; + __le16 cts_duration_ba_f1; + struct ieee80211_cts data; + u16 reserved2; +} __packed __aligned(2); + +struct vnt_tx_fifo_head { + u8 tx_key[WLAN_KEY_LEN_CCMP]; + __le16 fifo_ctl; + __le16 time_stamp; + __le16 frag_ctl; + __le16 current_rate; +} __packed; + +struct vnt_tx_short_buf_head { + __le16 fifo_ctl; + u16 time_stamp; + struct vnt_phy_field ab; + __le16 duration; + __le16 time_stamp_off; +} __packed; + +int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, + struct vnt_tx_desc *head_td, struct sk_buff *skb); +int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif); +int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *conf); + +#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c new file mode 100644 index 000000000..ee5ca4db7 --- /dev/null +++ b/drivers/staging/vt6655/srom.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose:Implement functions to access eeprom + * + * Author: Jerry Chen + * + * Date: Jan 29, 2003 + * + * Functions: + * SROMbyReadEmbedded - Embedded read eeprom via MAC + * SROMbWriteEmbedded - Embedded write eeprom via MAC + * SROMvRegBitsOn - Set Bits On in eeprom + * SROMvRegBitsOff - Clear Bits Off in eeprom + * SROMbIsRegBitsOn - Test if Bits On in eeprom + * SROMbIsRegBitsOff - Test if Bits Off in eeprom + * SROMvReadAllContents - Read all contents in eeprom + * SROMvWriteAllContents - Write all contents in eeprom + * SROMvReadEtherAddress - Read Ethernet Address in eeprom + * SROMvWriteEtherAddress - Write Ethernet Address in eeprom + * SROMvReadSubSysVenId - Read Sub_VID and Sub_SysId in eeprom + * SROMbAutoLoad - Auto Load eeprom to MAC register + * + * Revision History: + * + */ + +#include "device.h" +#include "mac.h" +#include "srom.h" + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +/* + * Description: Read a byte from EEPROM, by MAC I2C + * + * Parameters: + * In: + * iobase - I/O base address + * byContntOffset - address of EEPROM + * Out: + * none + * + * Return Value: data read + * + */ +unsigned char SROMbyReadEmbedded(void __iomem *iobase, + unsigned char byContntOffset) +{ + unsigned short wDelay, wNoACK; + unsigned char byWait; + unsigned char byData; + unsigned char byOrg; + + byData = 0xFF; + byOrg = ioread8(iobase + MAC_REG_I2MCFG); + /* turn off hardware retry for getting NACK */ + iowrite8(byOrg & (~I2MCFG_NORETRY), iobase + MAC_REG_I2MCFG); + for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) { + iowrite8(EEP_I2C_DEV_ID, iobase + MAC_REG_I2MTGID); + iowrite8(byContntOffset, iobase + MAC_REG_I2MTGAD); + + /* issue read command */ + iowrite8(I2MCSR_EEMR, iobase + MAC_REG_I2MCSR); + /* wait DONE be set */ + for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) { + byWait = ioread8(iobase + MAC_REG_I2MCSR); + if (byWait & (I2MCSR_DONE | I2MCSR_NACK)) + break; + udelay(CB_DELAY_LOOP_WAIT); + } + if ((wDelay < W_MAX_TIMEOUT) && + (!(byWait & I2MCSR_NACK))) { + break; + } + } + byData = ioread8(iobase + MAC_REG_I2MDIPT); + iowrite8(byOrg, iobase + MAC_REG_I2MCFG); + return byData; +} + +/* + * Description: Read all contents of eeprom to buffer + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * pbyEepromRegs - EEPROM content Buffer + * + * Return Value: none + * + */ +void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs) +{ + int ii; + + /* ii = Rom Address */ + for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { + *pbyEepromRegs = SROMbyReadEmbedded(iobase, + (unsigned char)ii); + pbyEepromRegs++; + } +} + +/* + * Description: Read Ethernet Address from eeprom to buffer + * + * Parameters: + * In: + * iobase - I/O base address + * Out: + * pbyEtherAddress - Ethernet Address buffer + * + * Return Value: none + * + */ +void SROMvReadEtherAddress(void __iomem *iobase, + unsigned char *pbyEtherAddress) +{ + unsigned char ii; + + /* ii = Rom Address */ + for (ii = 0; ii < ETH_ALEN; ii++) { + *pbyEtherAddress = SROMbyReadEmbedded(iobase, ii); + pbyEtherAddress++; + } +} diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h new file mode 100644 index 000000000..b03073ffa --- /dev/null +++ b/drivers/staging/vt6655/srom.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * Purpose: Implement functions to access eeprom + * + * Author: Jerry Chen + * + * Date: Jan 29, 2003 + */ + +#ifndef __SROM_H__ +#define __SROM_H__ + +/*--------------------- Export Definitions -------------------------*/ + +#define EEP_MAX_CONTEXT_SIZE 256 + +#define CB_EEPROM_READBYTE_WAIT 900 /* us */ + +#define W_MAX_I2CRETRY 0x0fff + +/* Contents in the EEPROM */ +#define EEP_OFS_PAR 0x00 /* physical address */ +#define EEP_OFS_ANTENNA 0x16 +#define EEP_OFS_RADIOCTL 0x17 +#define EEP_OFS_RFTYPE 0x1B /* for select RF */ +#define EEP_OFS_MINCHANNEL 0x1C /* Min Channel # */ +#define EEP_OFS_MAXCHANNEL 0x1D /* Max Channel # */ +#define EEP_OFS_SIGNATURE 0x1E +#define EEP_OFS_ZONETYPE 0x1F +#define EEP_OFS_RFTABLE 0x20 /* RF POWER TABLE */ +#define EEP_OFS_PWR_CCK 0x20 +#define EEP_OFS_SETPT_CCK 0x21 +#define EEP_OFS_PWR_OFDMG 0x23 +#define EEP_OFS_SETPT_OFDMG 0x24 +#define EEP_OFS_PWR_FORMULA_OST 0x26 +#define EEP_OFS_MAJOR_VER 0x2E +#define EEP_OFS_MINOR_VER 0x2F +#define EEP_OFS_CCK_PWR_TBL 0x30 +#define EEP_OFS_CCK_PWR_dBm 0x3F +#define EEP_OFS_OFDM_PWR_TBL 0x40 +#define EEP_OFS_OFDM_PWR_dBm 0x4F +/*{{ RobertYu: 20041124 */ +#define EEP_OFS_SETPT_OFDMA 0x4E +#define EEP_OFS_OFDMA_PWR_TBL 0x50 +/*}}*/ +#define EEP_OFS_OFDMA_PWR_dBm 0xD2 + +/*----------need to remove --------------------*/ +#define EEP_OFS_BBTAB_LEN 0x70 /* BB Table Length */ +#define EEP_OFS_BBTAB_ADR 0x71 /* BB Table Offset */ +#define EEP_OFS_CHECKSUM 0xFF /* reserved area for baseband 28h~78h */ + +#define EEP_I2C_DEV_ID 0x50 /* EEPROM device address on I2C bus */ + +/* Bits in EEP_OFS_ANTENNA */ +#define EEP_ANTENNA_MAIN 0x01 +#define EEP_ANTENNA_AUX 0x02 +#define EEP_ANTINV 0x04 + +/* Bits in EEP_OFS_RADIOCTL */ +#define EEP_RADIOCTL_ENABLE 0x80 +#define EEP_RADIOCTL_INV 0x01 + +/*--------------------- Export Types ------------------------------*/ + +/*--------------------- Export Macros ------------------------------*/ + +/*--------------------- Export Classes ----------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +unsigned char SROMbyReadEmbedded(void __iomem *iobase, + unsigned char byContntOffset); + +void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs); + +void SROMvReadEtherAddress(void __iomem *iobase, + unsigned char *pbyEtherAddress); + +#endif /* __EEPROM_H__*/ diff --git a/drivers/staging/vt6655/test b/drivers/staging/vt6655/test new file mode 100644 index 000000000..ba6dec774 --- /dev/null +++ b/drivers/staging/vt6655/test @@ -0,0 +1,9 @@ +KSP := /lib/modules/$(shell uname -r)/build \ + /usr/src/linux-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ +# /usr/src/kernel-headers-$(shell uname -r) \ +# /usr/src/kernel-source-$(shell uname -r) \ +# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ +# /usr/src/linux /home/plice +test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) +KSP := $(foreach dir, $(KSP), $(test_dir)) |