blob: 47c4161f071674c22a7ec17988a8ac0d07fa7a65 [file] [log] [blame]
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2008, Intel Corporation
* All rights reserved.
*/
/*
* Sun elects to have this file available under and governed by the BSD
* license (see below for full license text). However, the following
* notice accompanied the original version of this file:
*/
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU Geeral Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* James P. Ketrenos <ipw2100-admin@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IWK_CALIBRATION_H_
#define _IWK_CALIBRATION_H_
/*
* Most Tx and Rx calibration is done by uCode during the initialization
* phase of uCode boot. Driver must calibrate only:
*
* 1) Tx power (depends on temperature)
* 2) Receiver gain balance (and detect disconnected antennas)
* 3) Receiver sensitivity (to optimize signal detection)
*/
/* START TEMPERATURE */
/*
* 4965 temperature calculation.
*
* The driver must calculate the device temperature before calculating
* a txpower setting (amplifier gain is temperature dependent). The
* calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
* values used for the life of the driver, and one of which (R4) is the
* real-time temperature indicator.
*
* uCode provides all 4 values to the driver via the "initialize alive"
* notification (see struct iwk_init_alive_resp). After the runtime uCode
* image loads, uCode updates the R4 value via statistics notifications
* (see STATISTICS_NOTIFICATION), which occur after each received beacon
* when associated, or can be requested via REPLY_STATISTICS_CMD.
*
* NOTE: uCode provides the R4 value as a 23-bit signed value. Driver
* must sign-extend to 32 bits before applying formula below.
*
* Formula:
*
* degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
*
* NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is
* an additional correction, which should be centered around 0 degrees
* Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for
* centering the 97/100 correction around 0 degrees K.
*
* Add 273 to Kelvin value to find degrees Celsius, for comparing current
* temperature with factory-measured temperatures when calculating txpower
* settings.
*/
/* END TEMPERATURE */
/* START TXPOWER */
/*
* 4965 txpower calculations rely on information from three sources:
*
* 1) EEPROM
* 2) "initialize" alive notification
* 3) statistics notifications
*
* EEPROM data consists of:
*
* 1) Regulatory information (max txpower and channel usage flags) is provided
* separately for each channel that can possibly supported by 4965.
* 40 MHz wide (.11n fat) channels are listed separately from 20 MHz
* (legacy) channels.
*
* See struct iwk_eep_channel for format, and struct iwk_eep for
* locations in EEPROM.
*
* 2) Factory txpower calibration information is provided separately for
* sub-bands of contiguous channels. 2.4GHz has just one sub-band,
* but 5 GHz has several sub-bands.
*
* In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
*
* See struct iwk_eep_calib_info (and the tree of structures contained
* within it) for format, and struct iwk_eep for locations in EEPROM.
*
* "Initialization alive" notification (see struct iwk_init_alive_resp)
* consists of:
*
* 1) Temperature calculation parameters.
*
* 2) Power supply voltage measurement.
*
* 3) Tx gain compensation to balance 2 transmitters for MIMO use.
*
* Statistics notifications deliver:
*
* 1) Current values for temperature param R4.
*/
/*
* To calculate a txpower setting for a given desired target txpower, channel,
* modulation bit rate, and transmitter chain (4965 has 2 transmitters to
* support MIMO and transmit diversity), driver must do the following:
*
* 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
* Do not exceed regulatory limit; reduce target txpower if necessary.
*
* If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
* 2 transmitters will be used simultaneously; driver must reduce the
* regulatory limit by 3 dB (half-power) for each transmitter, so the
* combined total output of the 2 transmitters is within regulatory limits.
*
*
* 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by
* backoff for this bit rate*. Do not exceed (saturation - backoff[rate]);
* reduce target txpower if necessary.
*
* Backoff values below are in 1/2 dB units (equivalent to steps in
* txpower gain tables):
*
* OFDM 6 - 36 MBit: 10 steps (5 dB)
* OFDM 48 MBit: 15 steps (7.5 dB)
* OFDM 54 MBit: 17 steps (8.5 dB)
* OFDM 60 MBit: 20 steps (10 dB)
* CCK all rates: 10 steps (5 dB)
*
* Backoff values apply to saturation txpower on a per-transmitter basis;
* when using MIMO (2 transmitters), each transmitter uses the same
* saturation level provided in EEPROM, and the same backoff values;
* no reduction (such as with regulatory txpower limits) is required.
*
* Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
* widths and 40 Mhz (.11n fat) channel widths; there is no separate
* factory measurement for fat channels.
*
* The result of this step is the final target txpower. The rest of
* the steps figure out the proper settings for the device.
*
*
* 3) Determine (EEPROM) calibration subband for the target channel, by
* comparing against first and last channels in each subband
* (see struct iwk_eep_calib_subband_info).
*
*
* 4) Linearly interpolate (EEPROM) factory calibration measurement sets,
* referencing the 2 factory-measured (sample) channels within the subband.
*
* Interpolation is based on difference between target channel's frequency
* and the sample channels' frequencies. Since channel numbers are based
* on frequency (5 MHz between each channel number), this is equivalent
* to interpolating based on channel number differences.
*
* Note that the sample channels may or may not be the channels at the
* edges of the subband. The target channel may be "outside" of the
* span of the sampled channels.
*
* Driver may choose the pair (for 2 Tx chains) of measurements (see
* struct iwk_eep_calib_channel_info) for which the actual measured
* txpower comes closest to the desired txpower. Usually, though,
* the middle set of measurements is closest to the regulatory limits,
* and is therefore a good choice for all txpower calculations.
*
* Driver should interpolate both members of the chosen measurement pair,
* i.e. for both Tx chains (radio transmitters), unless the driver knows
* that only one of the chains will be used (e.g. only one tx antenna
* connected, but this should be unusual).
*
* Driver should interpolate factory values for temperature, gain table
* index, and actual power. The power amplifier detector values are
* not used by the driver.
*
* If the target channel happens to be one of the sample channels, the
* results should agree with the sample channel's measurements!
*
*
* 5) Find difference between desired txpower and (interpolated)
* factory-measured txpower. Using (interpolated) factory gain table index
* as a starting point, adjust this index lower to increase txpower,
* or higher to decrease txpower, until the target txpower is reached.
* Each step in the gain table is 1/2 dB.
*
* For example, if factory measured txpower is 16 dBm, and target txpower
* is 13 dBm, add 6 steps to the factory gain index to reduce txpower
* by 3 dB.
*
*
* 6) Find difference between current device temperature and (interpolated)
* factory-measured temperature for sub-band. Factory values are in
* degrees Celsius. To calculate current temperature, see comments for
* "4965 temperature calculation".
*
* If current temperature is higher than factory temperature, driver must
* increase gain (lower gain table index), and vice versa.
*
* Temperature affects gain differently for different channels:
*
* 2.4 GHz all channels: 3.5 degrees per half-dB step
* 5 GHz channels 34-43: 4.5 degrees per half-dB step
* 5 GHz channels >= 44: 4.0 degrees per half-dB step
*
* NOTE: Temperature can increase rapidly when transmitting, especially
* with heavy traffic at high txpowers. Driver should update
* temperature calculations often under these conditions to
* maintain strong txpower in the face of rising temperature.
*
*
* 7) Find difference between current power supply voltage indicator
* (from "initialize alive") and factory-measured power supply voltage
* indicator (EEPROM).
*
* If the current voltage is higher (indicator is lower) than factory
* voltage, gain should be reduced (gain table index increased) by:
*
* (eeprom - current) / 7
*
* If the current voltage is lower (indicator is higher) than factory
* voltage, gain should be increased (gain table index decreased) by:
*
* 2 * (current - eeprom) / 7
*
* If number of index steps in either direction turns out to be > 2,
* something is wrong ... just use 0.
*
* NOTE: Voltage compensation is independent of band/channel.
*
* NOTE: "Initialize" uCode measures current voltage, which is assumed
* to be constant after this initial measurement. Voltage
* compensation for txpower (number of steps in gain table)
* may be calculated once and used until the next uCode bootload.
*
*
* 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
* adjust txpower for each transmitter chain, so txpower is balanced
* between the two chains. There are 5 pairs of tx_atten[group][chain]
* values in "initialize alive", one pair for each of 5 channel ranges:
*
* Group 0: 5 GHz channel 34-43
* Group 1: 5 GHz channel 44-70
* Group 2: 5 GHz channel 71-124
* Group 3: 5 GHz channel 125-200
* Group 4: 2.4 GHz all channels
*
* Add the tx_atten[group][chain] value to the index for the target chain.
* The values are signed, but are in pairs of 0 and a non-negative number,
* so as to reduce gain (if necessary) of the "hotter" channel. This
* avoids any need to double-check for regulatory compliance after
* this step.
*
*
* 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation
* value to the index:
*
* Hardware rev B: 9 steps (4.5 dB)
* Hardware rev C: 5 steps (2.5 dB)
*
* Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
* bits [3:2], 1 = B, 2 = C.
*
* NOTE: This compensation is in addition to any saturation backoff that
* might have been applied in an earlier step.
*
*
* 10) Select the gain table, based on band (2.4 vs 5 GHz).
*
* Limit the adjusted index to stay within the table!
*
*
* 11) Read gain table entries for DSP and radio gain, place into appropriate
* location(s) in command.
*/
/* Temperature calibration offset is 3% 0C in Kelvin */
#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
#define TEMPERATURE_CALIB_A_VAL 259
#define KELVIN_TO_CELSIUS(x) ((x)-273)
#define CELSIUS_TO_KELVIN(x) ((x)+273)
/* First and last channels of all groups */
#define CALIB_IWK_TX_ATTEN_GR1_FCH 34
#define CALIB_IWK_TX_ATTEN_GR1_LCH 43
#define CALIB_IWK_TX_ATTEN_GR2_FCH 44
#define CALIB_IWK_TX_ATTEN_GR2_LCH 70
#define CALIB_IWK_TX_ATTEN_GR3_FCH 71
#define CALIB_IWK_TX_ATTEN_GR3_LCH 124
#define CALIB_IWK_TX_ATTEN_GR4_FCH 125
#define CALIB_IWK_TX_ATTEN_GR4_LCH 200
#define CALIB_IWK_TX_ATTEN_GR5_FCH 1
#define CALIB_IWK_TX_ATTEN_GR5_LCH 20
/* Limit range of txpower output target to be between these values */
#define IWK_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */
#define IWK_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */
#define TX_POWER_IWK_ILLEGAL_VOLTAGE (-10000)
/*
* 4965 power supply voltage compensation
*/
#define TX_POWER_IWK_VOLTAGE_CODES_PER_03V (7)
/* Limit range of calculated temperature to be between these Kelvin values */
#define IWK_TX_POWER_TEMPERATURE_MIN (263)
#define IWK_TX_POWER_TEMPERATURE_MAX (410)
union iwk_tx_power_dual_stream {
struct {
uint8_t radio_tx_gain[2];
uint8_t dsp_predis_atten[2];
} s;
uint32_t dw;
};
#define POWER_TABLE_NUM_ENTRIES (33)
#define POWER_TABLE_CCK_ENTRY (32)
/*
* When MIMO is used (2 transmitters operating simultaneously), driver should
* limit each transmitter to deliver a max of 3 dB below the regulatory limit
* for the device. That is, half power for each transmitter, so total power
* is within regulatory limits.
*
* The value "6" represents number of steps in gain table to reduce power.
* Each step is 1/2 dB.
*/
#define IWK_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
/*
* CCK gain compensation.
*
* When calculating txpowers for CCK, after making sure that the target power
* is within regulatory and saturation limits, driver must additionally
* back off gain by adding these values to the gain table index.
*/
#define IWK_TX_POWER_CCK_COMPENSATION_C_STEP (5)
/*
* Gain tables.
*
* The following tables contain pair of values for setting txpower, i.e.
* gain settings for the output of the device's digital signal processor (DSP),
* and for the analog gain structure of the transmitter.
*
* Each entry in the gain tables represents a step of 1/2 dB. Note that these
* are *relative* steps, not indications of absolute output power. Output
* power varies with temperature, voltage, and channel frequency, and also
* requires consideration of average power (to satisfy regulatory constraints),
* and peak power (to avoid distortion of the output signal).
*
* Each entry contains two values:
* 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained
* linear value that multiplies the output of the digital signal processor,
* before being sent to the analog radio.
* 2) Radio gain. This sets the analog gain of the radio Tx path.
* It is a coarser setting, and behaves in a logarithmic (dB) fashion.
*
* EEPROM contains factory calibration data for txpower. This maps actual
* measured txpower levels to gain settings in the "well known" tables
* below ("well-known" means here that both factory calibration *and* the
* driver work with the same table).
*
* There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table
* has an extension (into negative indexes), in case the driver needs to
* boost power setting for high device temperatures (higher than would be
* present during factory calibration). A 5 Ghz EEPROM index of "40"
* corresponds to the 49th entry in the table used by the driver.
*/
#define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */
#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */
struct gain_entry {
uint8_t dsp;
uint8_t radio;
};
static const struct gain_entry gains_table[2][108] = {
/* 5.2GHz power gain index table */
{
{123, 0x3F}, /* highest txpower */
{117, 0x3F},
{110, 0x3F},
{104, 0x3F},
{98, 0x3F},
{110, 0x3E},
{104, 0x3E},
{98, 0x3E},
{110, 0x3D},
{104, 0x3D},
{98, 0x3D},
{110, 0x3C},
{104, 0x3C},
{98, 0x3C},
{110, 0x3B},
{104, 0x3B},
{98, 0x3B},
{110, 0x3A},
{104, 0x3A},
{98, 0x3A},
{110, 0x39},
{104, 0x39},
{98, 0x39},
{110, 0x38},
{104, 0x38},
{98, 0x38},
{110, 0x37},
{104, 0x37},
{98, 0x37},
{110, 0x36},
{104, 0x36},
{98, 0x36},
{110, 0x35},
{104, 0x35},
{98, 0x35},
{110, 0x34},
{104, 0x34},
{98, 0x34},
{110, 0x33},
{104, 0x33},
{98, 0x33},
{110, 0x32},
{104, 0x32},
{98, 0x32},
{110, 0x31},
{104, 0x31},
{98, 0x31},
{110, 0x30},
{104, 0x30},
{98, 0x30},
{110, 0x25},
{104, 0x25},
{98, 0x25},
{110, 0x24},
{104, 0x24},
{98, 0x24},
{110, 0x23},
{104, 0x23},
{98, 0x23},
{110, 0x22},
{104, 0x18},
{98, 0x18},
{110, 0x17},
{104, 0x17},
{98, 0x17},
{110, 0x16},
{104, 0x16},
{98, 0x16},
{110, 0x15},
{104, 0x15},
{98, 0x15},
{110, 0x14},
{104, 0x14},
{98, 0x14},
{110, 0x13},
{104, 0x13},
{98, 0x13},
{110, 0x12},
{104, 0x08},
{98, 0x08},
{110, 0x07},
{104, 0x07},
{98, 0x07},
{110, 0x06},
{104, 0x06},
{98, 0x06},
{110, 0x05},
{104, 0x05},
{98, 0x05},
{110, 0x04},
{104, 0x04},
{98, 0x04},
{110, 0x03},
{104, 0x03},
{98, 0x03},
{110, 0x02},
{104, 0x02},
{98, 0x02},
{110, 0x01},
{104, 0x01},
{98, 0x01},
{110, 0x00},
{104, 0x00},
{98, 0x00},
{93, 0x00},
{88, 0x00},
{83, 0x00},
{78, 0x00},
},
/* 2.4GHz power gain index table */
{
{110, 0x3f}, /* highest txpower */
{104, 0x3f},
{98, 0x3f},
{110, 0x3e},
{104, 0x3e},
{98, 0x3e},
{110, 0x3d},
{104, 0x3d},
{98, 0x3d},
{110, 0x3c},
{104, 0x3c},
{98, 0x3c},
{110, 0x3b},
{104, 0x3b},
{98, 0x3b},
{110, 0x3a},
{104, 0x3a},
{98, 0x3a},
{110, 0x39},
{104, 0x39},
{98, 0x39},
{110, 0x38},
{104, 0x38},
{98, 0x38},
{110, 0x37},
{104, 0x37},
{98, 0x37},
{110, 0x36},
{104, 0x36},
{98, 0x36},
{110, 0x35},
{104, 0x35},
{98, 0x35},
{110, 0x34},
{104, 0x34},
{98, 0x34},
{110, 0x33},
{104, 0x33},
{98, 0x33},
{110, 0x32},
{104, 0x32},
{98, 0x32},
{110, 0x31},
{104, 0x31},
{98, 0x31},
{110, 0x30},
{104, 0x30},
{98, 0x30},
{110, 0x6},
{104, 0x6},
{98, 0x6},
{110, 0x5},
{104, 0x5},
{98, 0x5},
{110, 0x4},
{104, 0x4},
{98, 0x4},
{110, 0x3},
{104, 0x3},
{98, 0x3},
{110, 0x2},
{104, 0x2},
{98, 0x2},
{110, 0x1},
{104, 0x1},
{98, 0x1},
{110, 0x0},
{104, 0x0},
{98, 0x0},
{97, 0},
{96, 0},
{95, 0},
{94, 0},
{93, 0},
{92, 0},
{91, 0},
{90, 0},
{89, 0},
{88, 0},
{87, 0},
{86, 0},
{85, 0},
{84, 0},
{83, 0},
{82, 0},
{81, 0},
{80, 0},
{79, 0},
{78, 0},
{77, 0},
{76, 0},
{75, 0},
{74, 0},
{73, 0},
{72, 0},
{71, 0},
{70, 0},
{69, 0},
{68, 0},
{67, 0},
{66, 0},
{65, 0},
{64, 0},
{63, 0},
{62, 0},
{61, 0},
{60, 0},
{59, 0},
}
};
/* END TXPOWER */
struct statistics_div {
uint32_t tx_on_a;
uint32_t tx_on_b;
uint32_t exec_time;
uint32_t probe_time;
uint32_t reserved1;
uint32_t reserved2;
};
struct statistics_dbg {
uint32_t burst_check;
uint32_t burst_count;
uint32_t reserved[4];
};
struct statistics_general {
uint32_t temperature;
uint32_t temperature_m;
struct statistics_dbg dbg;
uint32_t sleep_time;
uint32_t slots_out;
uint32_t slots_idle;
uint32_t ttl_timestamp;
struct statistics_div div;
uint32_t rx_enable_counter;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
};
struct statistics_tx_non_phy_agg {
uint32_t ba_timeout;
uint32_t ba_reschedule_frames;
uint32_t scd_query_agg_frame_cnt;
uint32_t scd_query_no_agg;
uint32_t scd_query_agg;
uint32_t scd_query_mismatch;
uint32_t frame_not_ready;
uint32_t underrun;
uint32_t bt_prio_kill;
uint32_t rx_ba_rsp_cnt;
uint32_t reserved2;
uint32_t reserved3;
};
struct statistics_tx {
uint32_t preamble_cnt;
uint32_t rx_detected_cnt;
uint32_t bt_prio_defer_cnt;
uint32_t bt_prio_kill_cnt;
uint32_t few_bytes_cnt;
uint32_t cts_timeout;
uint32_t ack_timeout;
uint32_t expected_ack_cnt;
uint32_t actual_ack_cnt;
uint32_t dump_msdu_cnt;
uint32_t burst_abort_next_frame_mismatch_cnt;
uint32_t burst_abort_missing_next_frame_cnt;
uint32_t cts_timeout_collision;
uint32_t ack_or_ba_timeout_collision;
struct statistics_tx_non_phy_agg agg;
};
struct statistics_rx_ht_phy {
uint32_t plcp_err;
uint32_t overrun_err;
uint32_t early_overrun_err;
uint32_t crc32_good;
uint32_t crc32_err;
uint32_t mh_format_err;
uint32_t agg_crc32_good;
uint32_t agg_mpdu_cnt;
uint32_t agg_cnt;
uint32_t reserved2;
};
struct statistics_rx_non_phy {
uint32_t bogus_cts; /* CTS received when not expecting CTS */
uint32_t bogus_ack; /* ACK received when not expecting ACK */
uint32_t non_bssid_frames; /* number of frames with BSSID that */
/* doesn't belong to the STA BSSID */
uint32_t filtered_frames; /* count frames that were dumped in the */
/* filtering process */
uint32_t non_channel_beacons; /* beacons with our bss id but not on */
/* our serving channel */
uint32_t channel_beacons; /* beacons with our bss id and in our */
/* serving channel */
uint32_t num_missed_bcon; /* number of missed beacons */
uint32_t adc_rx_saturation_time; /* count in 0.8us units the time */
/* the ADC was in saturation */
uint32_t ina_detection_search_time; /* total time (in 0.8us) */
/* searched for INA */
uint32_t beacon_silence_rssi_a; /* RSSI silence after beacon frame */
uint32_t beacon_silence_rssi_b; /* RSSI silence after beacon frame */
uint32_t beacon_silence_rssi_c; /* RSSI silence after beacon frame */
uint32_t interference_data_flag; /* flag for interference data */
/* availability. 1 when data is */
/* available. */
uint32_t channel_load; /* counts RX Enable time */
uint32_t dsp_false_alarms; /* DSP false alarm (both OFDM */
/* and CCK) counter */
uint32_t beacon_rssi_a;
uint32_t beacon_rssi_b;
uint32_t beacon_rssi_c;
uint32_t beacon_energy_a;
uint32_t beacon_energy_b;
uint32_t beacon_energy_c;
};
struct statistics_rx_phy {
uint32_t ina_cnt;
uint32_t fina_cnt;
uint32_t plcp_err;
uint32_t crc32_err;
uint32_t overrun_err;
uint32_t early_overrun_err;
uint32_t crc32_good;
uint32_t false_alarm_cnt;
uint32_t fina_sync_err_cnt;
uint32_t sfd_timeout;
uint32_t fina_timeout;
uint32_t unresponded_rts;
uint32_t rxe_frame_limit_overrun;
uint32_t sent_ack_cnt;
uint32_t sent_cts_cnt;
uint32_t sent_ba_rsp_cnt;
uint32_t dsp_self_kill;
uint32_t mh_format_err;
uint32_t re_acq_main_rssi_sum;
uint32_t reserved3;
};
struct statistics_rx {
struct statistics_rx_phy ofdm;
struct statistics_rx_phy cck;
struct statistics_rx_non_phy general;
struct statistics_rx_ht_phy ofdm_ht;
};
struct iwk_notif_statistics {
uint32_t flag;
struct statistics_rx rx;
struct statistics_tx tx;
struct statistics_general general;
};
/* START Receiver gain balance */
/*
* REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
*
* This command sets the relative gains of 4965's 3 radio receiver chains.
*
* After the first association, driver should accumulate signal and noise
* statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
* beacons from the associated network (don't collect statistics that come
* in from scanning, or any other non-network source).
*
* DISCONNECTED ANTENNA:
*
* Driver should determine which antennas are actually connected, by comparing
* average beacon signal levels for the 3 Rx chains. Accumulate (add) the
* following values over 20 beacons, one accumulator for each of the chains
* a/b/c, from struct statistics_rx_non_phy:
*
* beacon_rssi_[abc] & 0x0FF (unsigned, units in dB)
*
* Find the strongest signal from among a/b/c. Compare the other two to the
* strongest. If any signal is more than 15 dB (times 20, unless you
* divide the accumulated values by 20) below the strongest, the driver
* considers that antenna to be disconnected, and should not try to use that
* antenna/chain for Rx or Tx. If both A and B seem to be disconnected,
* driver should declare the stronger one as connected, and attempt to use it
* (A and B are the only 2 Tx chains!).
*
*
* RX BALANCE:
*
* Driver should balance the 3 receivers (but just the ones that are connected
* to antennas, see above) for gain, by comparing the average signal levels
* detected during the silence after each beacon (background noise).
* Accumulate (add) the following values over 20 beacons, one accumulator for
* each of the chains a/b/c, from struct statistics_rx_non_phy:
*
* beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB)
*
* Find the weakest background noise level from among a/b/c. This Rx chain
* will be the reference, with 0 gain adjustment. Attenuate other channels by
* finding noise difference:
*
* (accum_noise[i] - accum_noise[reference]) / 30
*
* The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB.
* For use in diff_gain_[abc] fields of struct iwk_calibration_cmd, the
* driver should limit the difference results to a range of 0-3 (0-4.5 dB),
* and set bit 2 to indicate "reduce gain". The value for the reference
* (weakest) chain should be "0".
*
* diff_gain_[abc] bit fields:
* 2: (1) reduce gain, (0) increase gain
* 1-0: amount of gain, units of 1.5 dB
*/
#define RX_CHAINS_NUM (3)
#define CHAIN_GAIN_DIFF_INIT_VAL (4)
#define IWK_GAIN_DIFF_ALIVE (0)
#define IWK_GAIN_DIFF_ACCUMULATE (1)
#define IWK_GAIN_DIFF_CALIBRATED (2)
#define INTERFERENCE_DATA_AVAILABLE (1)
#define BEACON_NUM_20 (20)
#define MAX_ALLOWED_DIFF (15)
struct iwk_rx_gain_diff {
uint8_t state;
uint16_t beacon_count;
uint8_t gain_diff_send;
uint32_t beacon_stren_a;
uint32_t beacon_stren_b;
uint32_t beacon_stren_c;
uint32_t noise_stren_a;
uint32_t noise_stren_b;
uint32_t noise_stren_c;
uint8_t disconnect_chain[RX_CHAINS_NUM];
uint8_t connected_chains;
uint8_t gain_diff_chain[RX_CHAINS_NUM];
};
/* END Receiver gain balance */
/* START Receiver sensitivity */
/*
* SENSITIVITY_CMD = 0xa8
*
* This command sets up the Rx signal detector for a sensitivity level that
* is high enough to lock onto all signals within the associated network,
* but low enough to ignore signals that are below a certain threshold, so as
* not to have too many "false alarms". False alarms are signals that the
* Rx DSP tries to lock onto, but then discards after determining that they
* are noise.
*
* The optimum number of false alarms is between 5 and 50 per 200 TUs
* (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e.
* time listening, not transmitting). Driver must adjust sensitivity so that
* the ratio of actual false alarms to actual Rx time falls within this range.
*
* While associated, uCode delivers STATISTICS_NOTIFICATIONs after each
* received beacon. These provide information to the driver to analyze the
* sensitivity. Don't analyze statistics that come in from scanning, or any
* other non-associated-network source. Pertinent statistics include:
*
* From "general" statistics (struct statistics_rx_non_phy):
*
* (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level)
* Measure of energy of desired signal. Used for establishing a level
* below which the device does not detect signals.
*
* (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB)
* Measure of background noise in silent period after beacon.
*
* channel_load
* uSecs of actual Rx time during beacon period (varies according to
* how much time was spent transmitting).
*
* From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately:
*
* false_alarm_cnt
* Signal locks abandoned early (before phy-level header).
*
* plcp_err
* Signal locks abandoned late (during phy-level header).
*
* NOTE: Both false_alarm_cnt and plcp_err increment monotonically from
* beacon to beacon, i.e. each value is an accumulation of all errors
* before and including the latest beacon. Values will wrap around to 0
* after counting up to 2^32 - 1. Driver must differentiate vs.
* previous beacon's values to determine # false alarms in the current
* beacon period.
*
* Total number of false alarms = false_alarms + plcp_errs
*
* For OFDM, adjust the following table entries in struct iwk_rx_sensitivity_cmd
* (notice that the start points for OFDM are at or close to settings for
* maximum sensitivity):
*
* START / MIN / MAX
* HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX 90 / 85 / 120
* HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX 170 / 170 / 210
* HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX 105 / 105 / 140
* HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX 220 / 220 / 270
*
* If actual rate of OFDM false alarms (+ plcp_errors) is too high
* (greater than 50 for each 204.8 msecs listening), reduce sensitivity
* by *adding* 1 to all 4 of the table entries above, up to the max for
* each entry. Conversely, if false alarm rate is too low (less than 5
* for each 204.8 msecs listening), *subtract* 1 from each entry to
* increase sensitivity.
*
* For CCK sensitivity, keep track of the following:
*
* 1). 20-beacon history of maximum background noise, indicated by
* (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the
* 3 receivers. For any given beacon, the "silence reference" is
* the maximum of last 60 samples (20 beacons * 3 receivers).
*
* 2). 10-beacon history of strongest signal level, as indicated
* by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers,
* i.e. the strength of the signal through the best receiver at the
* moment. These measurements are "upside down", with lower values
* for stronger signals, so max energy will be *minimum* value.
*
* Then for any given beacon, the driver must determine the *weakest*
* of the strongest signals; this is the minimum level that needs to be
* successfully detected, when using the best receiver at the moment.
* "Max cck energy" is the maximum (higher value means lower energy!)
* of the last 10 minima. Once this is determined, driver must add
* a little margin by adding "6" to it.
*
* 3). Number of consecutive beacon periods with too few false alarms.
* Reset this to 0 at the first beacon period that falls within the
* "good" range (5 to 50 false alarms per 204.8 milliseconds rx).
*
* Then, adjust the following CCK table entries in struct iwk_rx_sensitivity_cmd
* (notice that the start points for CCK are at maximum sensitivity):
*
* START / MIN / MAX
* HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX 125 / 125 / 200
* HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX 200 / 200 / 400
* HD_MIN_ENERGY_CCK_DET_INDEX 100 / 0 / 100
*
* If actual rate of CCK false alarms (+ plcp_errors) is too high
* (greater than 50 for each 204.8 msecs listening), method for reducing
* sensitivity is:
*
* 1) *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
* up to max 400.
*
* 2) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160,
* sensitivity has been reduced a significant amount; bring it up to
* a moderate 161. Otherwise, *add* 3, up to max 200.
*
* 3) a) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160,
* sensitivity has been reduced only a moderate or small amount;
* *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX,
* down to min 0. Otherwise (if gain has been significantly reduced),
* don't change the HD_MIN_ENERGY_CCK_DET_INDEX value.
*
* b) Save a snapshot of the "silence reference".
*
* If actual rate of CCK false alarms (+ plcp_errors) is too low
* (less than 5 for each 204.8 msecs listening), method for increasing
* sensitivity is used only if:
*
* 1a) Previous beacon did not have too many false alarms
* 1b) AND difference between previous "silence reference" and current
* "silence reference" (prev - current) is 2 or more,
* OR 2) 100 or more consecutive beacon periods have had rate of
* less than 5 false alarms per 204.8 milliseconds rx time.
*
* Method for increasing sensitivity:
*
* 1) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX,
* down to min 125.
*
* 2) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
* down to min 200.
*
* 3) *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100.
*
* If actual rate of CCK false alarms (+ plcp_errors) is within good range
* (between 5 and 50 for each 204.8 msecs listening):
*
* 1) Save a snapshot of the silence reference.
*
* 2) If previous beacon had too many CCK false alarms (+ plcp_errors),
* give some extra margin to energy threshold by *subtracting* 8
* from value in HD_MIN_ENERGY_CCK_DET_INDEX.
*
* For all cases (too few, too many, good range), make sure that the CCK
* detection threshold (energy) is below the energy level for robust
* detection over the past 10 beacon periods, the "Max cck energy".
* Lower values mean higher energy; this means making sure that the value
* in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
*
* Driver should set the following entries to fixed values:
*
* HD_MIN_ENERGY_OFDM_DET_INDEX 100
* HD_BARKER_CORR_TH_ADD_MIN_INDEX 190
* HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390
* HD_OFDM_ENERGY_TH_IN_INDEX 62
*/
#define IWK_SENSITIVITY_CALIB_ALLOW_MSK (1 << 0)
#define IWK_SENSITIVITY_OFDM_UPDATE_MSK (1 << 1)
#define IWK_SENSITIVITY_CCK_UPDATE_MSK (1 << 2)
#define MIN_ENERGY_CCK_DET_IDX (0)
#define MIN_ENERGY_OFDM_DET_IDX (1)
#define AUTO_CORR32_X1_TH_ADD_MIN_IDX (2)
#define AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX (3)
#define AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX (4)
#define AUTO_CORR32_X4_TH_ADD_MIN_IDX (5)
#define AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX (6)
#define BARKER_CORR_TH_ADD_MIN_IDX (7)
#define BARKER_CORR_TH_ADD_MIN_MRC_IDX (8)
#define AUTO_CORR40_X4_TH_ADD_MIN_IDX (9)
#define PTAM_ENERGY_TH_IDX (10)
#define IWK_GOOD_RANGE_FALSE_ALARM (0)
#define IWK_TOO_MANY_FALSE_ALARM (1)
#define IWK_TOO_FEW_FALSE_ALARM (2)
#define IWK_SENSITIVITY_CONTROL_DEFAULT_TABLE (0)
#define IWK_SENSITIVITY_CONTROL_WORK_TABLE (1)
struct iwk_rx_sensitivity_cmd {
uint16_t control;
uint16_t table[11];
};
struct iwk_rx_sensitivity {
uint16_t auto_corr_ofdm_x4;
uint16_t auto_corr_mrc_ofdm_x4;
uint16_t auto_corr_ofdm_x1;
uint16_t auto_corr_mrc_ofdm_x1;
uint16_t auto_corr_cck_x4;
uint16_t auto_corr_mrc_cck_x4;
uint16_t min_energy_det_cck;
uint16_t flags;
uint32_t last_bad_plcp_cnt_ofdm;
uint32_t last_false_alarm_cnt_ofdm;
uint32_t last_bad_plcp_cnt_cck;
uint32_t last_false_alarm_cnt_cck;
uint32_t cck_curr_state;
uint32_t cck_prev_state;
uint32_t cck_beacon_min[10];
uint32_t cck_beacon_idx;
uint8_t cck_noise_max[20];
uint32_t cck_noise_ref;
uint32_t cck_noise_idx;
int32_t cck_noise_diff;
uint32_t cck_no_false_alarm_num;
};
/* END Receiver sensitivity */
#endif /* _IWK_CALIBRATION_H_ */