The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
    3  *
    4  * Permission to use, copy, modify, and/or distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   14  * PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include "opt_ah.h"
   18 
   19 #include "ah.h"
   20 #include "ah_internal.h"
   21 
   22 #include "ar9300/ar9300.h"
   23 
   24 /* shorthands to compact tables for readability */
   25 #define    OFDM    IEEE80211_T_OFDM
   26 #define    CCK    IEEE80211_T_CCK
   27 #define    TURBO    IEEE80211_T_TURBO
   28 #define    XR    ATHEROS_T_XR
   29 #define HT      IEEE80211_T_HT
   30 
   31 #define AR9300_NUM_OFDM_RATES   8
   32 #define AR9300_NUM_HT_SS_RATES  8
   33 #define AR9300_NUM_HT_DS_RATES  8
   34 #define AR9300_NUM_HT_TS_RATES  8
   35 
   36 /* Array Gain defined for TxBF */
   37 #define AR9300_TXBF_2TX_ARRAY_GAIN  6  /* 2TX/SS 3 */
   38 #define AR9300_TXBF_3TX_ARRAY_GAIN  10 /* 3TX/SS or 3TX/DS 4.8 */
   39 #define AR9300_STBC_3TX_ARRAY_GAIN  10 /* 3TX/SS or 3TX/DS 4.8 */
   40 
   41 /* MCS RATE CODES - first and last */
   42 #define AR9300_MCS0_RATE_CODE   0x80
   43 #define AR9300_MCS23_RATE_CODE  0x97
   44 
   45 static inline void ar9300_init_rate_txpower_cck(struct ath_hal *ah,
   46        const HAL_RATE_TABLE *rt, u_int8_t rates_array[], u_int8_t chainmask);
   47 static inline void ar9300_init_rate_txpower_ofdm(struct ath_hal* ah,
   48        const HAL_RATE_TABLE *rt, u_int8_t rates_array[], int rt_offset,
   49        u_int8_t chainmask);
   50 static inline void ar9300_init_rate_txpower_ht(struct ath_hal *ah,
   51        const HAL_RATE_TABLE *rt, HAL_BOOL is40, u_int8_t rates_array[],
   52        int rt_ss_offset, int rt_ds_offset,
   53        int rt_ts_offset, u_int8_t chainmask);
   54 static inline void ar9300_init_rate_txpower_stbc(struct ath_hal *ah,
   55        const HAL_RATE_TABLE *rt, HAL_BOOL is40,
   56        int rt_ss_offset, int rt_ds_offset,
   57        int rt_ts_offset, u_int8_t chainmask);
   58 #if 0
   59 static inline void ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah,
   60        const HAL_RATE_TABLE *rt, HAL_BOOL is40,
   61        int rt_ss_offset, int rt_ds_offset,
   62        int rt_ts_offset, u_int8_t chainmask);
   63 #endif
   64 
   65 #define AR9300_11A_RT_OFDM_OFFSET    0
   66 HAL_RATE_TABLE ar9300_11a_table = {
   67     8,  /* number of rates */
   68     { 0 },
   69     {
   70 /*                                                  short            ctrl */
   71 /*             valid                 rate_code Preamble    dot11Rate Rate */
   72 /*   6 Mb */ {  AH_TRUE, OFDM,    6000,     0x0b,    0x00, (0x80 | 12),   0 },
   73 /*   9 Mb */ {  AH_TRUE, OFDM,    9000,     0x0f,    0x00,          18,   0 },
   74 /*  12 Mb */ {  AH_TRUE, OFDM,   12000,     0x0a,    0x00, (0x80 | 24),   2 },
   75 /*  18 Mb */ {  AH_TRUE, OFDM,   18000,     0x0e,    0x00,          36,   2 },
   76 /*  24 Mb */ {  AH_TRUE, OFDM,   24000,     0x09,    0x00, (0x80 | 48),   4 },
   77 /*  36 Mb */ {  AH_TRUE, OFDM,   36000,     0x0d,    0x00,          72,   4 },
   78 /*  48 Mb */ {  AH_TRUE, OFDM,   48000,     0x08,    0x00,          96,   4 },
   79 /*  54 Mb */ {  AH_TRUE, OFDM,   54000,     0x0c,    0x00,         108,   4 },
   80     },
   81 };
   82 
   83 HAL_RATE_TABLE ar9300_11a_half_table = {
   84     8,  /* number of rates */
   85     { 0 },
   86     {
   87 /*                                                  short            ctrl */
   88 /*             valid                 rate_code Preamble    dot11Rate Rate */
   89 /*   6 Mb */ {  AH_TRUE, OFDM,    3000,     0x0b,    0x00, (0x80 |  6),   0 },
   90 /*   9 Mb */ {  AH_TRUE, OFDM,    4500,     0x0f,    0x00,           9,   0 },
   91 /*  12 Mb */ {  AH_TRUE, OFDM,    6000,     0x0a,    0x00, (0x80 | 12),   2 },
   92 /*  18 Mb */ {  AH_TRUE, OFDM,    9000,     0x0e,    0x00,          18,   2 },
   93 /*  24 Mb */ {  AH_TRUE, OFDM,   12000,     0x09,    0x00, (0x80 | 24),   4 },
   94 /*  36 Mb */ {  AH_TRUE, OFDM,   18000,     0x0d,    0x00,          36,   4 },
   95 /*  48 Mb */ {  AH_TRUE, OFDM,   24000,     0x08,    0x00,          48,   4 },
   96 /*  54 Mb */ {  AH_TRUE, OFDM,   27000,     0x0c,    0x00,          54,   4 },
   97     },
   98 };
   99 
  100 HAL_RATE_TABLE ar9300_11a_quarter_table = {
  101     8,  /* number of rates */
  102     { 0 },
  103     {
  104 /*                                                  short           ctrl */
  105 /*            valid                 rate_code Preamble    dot11Rate Rate */
  106 /*  6 Mb */ {  AH_TRUE, OFDM,    1500,     0x0b,    0x00, (0x80 |  3),   0 },
  107 /*  9 Mb */ {  AH_TRUE, OFDM,    2250,     0x0f,    0x00,          4 ,   0 },
  108 /* 12 Mb */ {  AH_TRUE, OFDM,    3000,     0x0a,    0x00, (0x80 |  6),   2 },
  109 /* 18 Mb */ {  AH_TRUE, OFDM,    4500,     0x0e,    0x00,           9,   2 },
  110 /* 24 Mb */ {  AH_TRUE, OFDM,    6000,     0x09,    0x00, (0x80 | 12),   4 },
  111 /* 36 Mb */ {  AH_TRUE, OFDM,    9000,     0x0d,    0x00,          18,   4 },
  112 /* 48 Mb */ {  AH_TRUE, OFDM,   12000,     0x08,    0x00,          24,   4 },
  113 /* 54 Mb */ {  AH_TRUE, OFDM,   13500,     0x0c,    0x00,          27,   4 },
  114     },
  115 };
  116 
  117 HAL_RATE_TABLE ar9300_turbo_table = {
  118     8,  /* number of rates */
  119     { 0 },
  120     {
  121 /*                                                 short            ctrl */
  122 /*             valid                rate_code Preamble    dot11Rate Rate */
  123 /*   6 Mb */ {  AH_TRUE, TURBO,   6000,    0x0b,    0x00, (0x80 | 12),   0 },
  124 /*   9 Mb */ {  AH_TRUE, TURBO,   9000,    0x0f,    0x00,          18,   0 },
  125 /*  12 Mb */ {  AH_TRUE, TURBO,  12000,    0x0a,    0x00, (0x80 | 24),   2 },
  126 /*  18 Mb */ {  AH_TRUE, TURBO,  18000,    0x0e,    0x00,          36,   2 },
  127 /*  24 Mb */ {  AH_TRUE, TURBO,  24000,    0x09,    0x00, (0x80 | 48),   4 },
  128 /*  36 Mb */ {  AH_TRUE, TURBO,  36000,    0x0d,    0x00,          72,   4 },
  129 /*  48 Mb */ {  AH_TRUE, TURBO,  48000,    0x08,    0x00,          96,   4 },
  130 /*  54 Mb */ {  AH_TRUE, TURBO,  54000,    0x0c,    0x00,         108,   4 },
  131     },
  132 };
  133 
  134 HAL_RATE_TABLE ar9300_11b_table = {
  135     4,  /* number of rates */
  136     { 0 },
  137     {
  138 /*                                                 short            ctrl */
  139 /*             valid                rate_code Preamble    dot11Rate Rate */
  140 /*   1 Mb */ {  AH_TRUE,  CCK,    1000,    0x1b,    0x00, (0x80 |  2),   0 },
  141 /*   2 Mb */ {  AH_TRUE,  CCK,    2000,    0x1a,    0x04, (0x80 |  4),   1 },
  142 /* 5.5 Mb */ {  AH_TRUE,  CCK,    5500,    0x19,    0x04, (0x80 | 11),   1 },
  143 /*  11 Mb */ {  AH_TRUE,  CCK,   11000,    0x18,    0x04, (0x80 | 22),   1 },
  144     },
  145 };
  146 
  147 
  148 /* Venice TODO: round_up_rate() is broken when the rate table does not represent
  149  * rates in increasing order  e.g.  5.5, 11, 6, 9.
  150  * An average rate of 6 Mbps will currently map to 11 Mbps.
  151  */
  152 #define AR9300_11G_RT_OFDM_OFFSET    4
  153 HAL_RATE_TABLE ar9300_11g_table = {
  154     12,  /* number of rates */
  155     { 0 },
  156     {
  157 /*                                                 short            ctrl */
  158 /*             valid                rate_code Preamble    dot11Rate Rate */
  159 /*   1 Mb */ {  AH_TRUE, CCK,     1000,    0x1b,    0x00, (0x80 |  2),   0 },
  160 /*   2 Mb */ {  AH_TRUE, CCK,     2000,    0x1a,    0x04, (0x80 |  4),   1 },
  161 /* 5.5 Mb */ {  AH_TRUE, CCK,     5500,    0x19,    0x04, (0x80 | 11),   2 },
  162 /*  11 Mb */ {  AH_TRUE, CCK,    11000,    0x18,    0x04, (0x80 | 22),   3 },
  163 /* Hardware workaround - remove rates 6, 9 from rate ctrl */
  164 /*   6 Mb */ {  AH_TRUE, OFDM,    6000,    0x0b,    0x00,          12,   4 },
  165 /*   9 Mb */ {  AH_TRUE, OFDM,    9000,    0x0f,    0x00,          18,   4 },
  166 /*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00,          24,   6 },
  167 /*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,          36,   6 },
  168 /*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00,          48,   8 },
  169 /*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,          72,   8 },
  170 /*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,          96,   8 },
  171 /*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,         108,   8 },
  172     },
  173 };
  174 
  175 #if 0
  176 HAL_RATE_TABLE ar9300_xr_table = {
  177     13,        /* number of rates */
  178     { 0 },
  179     {
  180 /*                                                 short     ctrl */
  181 /*            valid          rate_code Preamble    dot11Rate Rate */
  182 /* 0.25 Mb */ {AH_TRUE,   XR,   250, 0x03,   0x00, (0x80 |  1),   0, 612, 612 },
  183 /*  0.5 Mb */ {AH_TRUE,   XR,   500, 0x07,   0x00, (0x80 |  1),   0, 457, 457 },
  184 /*    1 Mb */ {AH_TRUE,   XR,  1000, 0x02,   0x00, (0x80 |  2),   1, 228, 228 },
  185 /*    2 Mb */ {AH_TRUE,   XR,  2000, 0x06,   0x00, (0x80 |  4),   2, 160, 160 },
  186 /*    3 Mb */ {AH_TRUE,   XR,  3000, 0x01,   0x00, (0x80 |  6),   3, 140, 140 },
  187 /*    6 Mb */ {AH_TRUE, OFDM,  6000, 0x0b,   0x00, (0x80 | 12),   4, 60,  60  },
  188 /*    9 Mb */ {AH_TRUE, OFDM,  9000, 0x0f,   0x00,          18,   4, 60,  60  },
  189 /*   12 Mb */ {AH_TRUE, OFDM, 12000, 0x0a,   0x00, (0x80 | 24),   6, 48,  48  },
  190 /*   18 Mb */ {AH_TRUE, OFDM, 18000, 0x0e,   0x00,          36,   6, 48,  48  },
  191 /*   24 Mb */ {AH_TRUE, OFDM, 24000, 0x09,   0x00,          48,   8, 44,  44  },
  192 /*   36 Mb */ {AH_TRUE, OFDM, 36000, 0x0d,   0x00,          72,   8, 44,  44  },
  193 /*   48 Mb */ {AH_TRUE, OFDM, 48000, 0x08,   0x00,          96,   8, 44,  44  },
  194 /*   54 Mb */ {AH_TRUE, OFDM, 54000, 0x0c,   0x00,         108,   8, 44,  44  },
  195     },
  196 };
  197 #endif
  198 
  199 #define AR9300_11NG_RT_OFDM_OFFSET       4
  200 #define AR9300_11NG_RT_HT_SS_OFFSET      12
  201 #define AR9300_11NG_RT_HT_DS_OFFSET      20
  202 #define AR9300_11NG_RT_HT_TS_OFFSET      28
  203 HAL_RATE_TABLE ar9300_11ng_table = {
  204 
  205     36,  /* number of rates */
  206     { 0 },
  207     {
  208 /*                                                 short            ctrl */
  209 /*             valid                rate_code Preamble    dot11Rate Rate */
  210 /*   1 Mb */ {  AH_TRUE, CCK,     1000,    0x1b,    0x00, (0x80 |  2),   0 },
  211 /*   2 Mb */ {  AH_TRUE, CCK,     2000,    0x1a,    0x04, (0x80 |  4),   1 },
  212 /* 5.5 Mb */ {  AH_TRUE, CCK,     5500,    0x19,    0x04, (0x80 | 11),   2 },
  213 /*  11 Mb */ {  AH_TRUE, CCK,    11000,    0x18,    0x04, (0x80 | 22),   3 },
  214 /* Hardware workaround - remove rates 6, 9 from rate ctrl */
  215 /*   6 Mb */ {  AH_FALSE, OFDM,    6000,    0x0b,    0x00,          12,   4 },
  216 /*   9 Mb */ {  AH_FALSE, OFDM,    9000,    0x0f,    0x00,          18,   4 },
  217 /*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00,          24,   6 },
  218 /*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,          36,   6 },
  219 /*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00,          48,   8 },
  220 /*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,          72,   8 },
  221 /*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,          96,   8 },
  222 /*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,         108,   8 },
  223 /*--- HT SS rates ---*/
  224 /* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,           0,   4 },
  225 /*  13 Mb */ {  AH_TRUE, HT,     13000,    0x81,    0x00,           1,   6 },
  226 /*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,           2,   6 },
  227 /*  26 Mb */ {  AH_TRUE, HT,     26000,    0x83,    0x00,           3,   8 },
  228 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x84,    0x00,           4,   8 },
  229 /*  52 Mb */ {  AH_TRUE, HT,     52000,    0x85,    0x00,           5,   8 },
  230 /*58.5 Mb */ {  AH_TRUE, HT,     58500,    0x86,    0x00,           6,   8 },
  231 /*  65 Mb */ {  AH_TRUE, HT,     65000,    0x87,    0x00,           7,   8 },
  232 /*--- HT DS rates ---*/
  233 /*  13 Mb */ {  AH_TRUE, HT,     13000,    0x88,    0x00,           8,   4 },
  234 /*  26 Mb */ {  AH_TRUE, HT,     26000,    0x89,    0x00,           9,   6 },
  235 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x8a,    0x00,          10,   6 },
  236 /*  52 Mb */ {  AH_TRUE, HT,     52000,    0x8b,    0x00,          11,   8 },
  237 /*  78 Mb */ {  AH_TRUE, HT,     78000,    0x8c,    0x00,          12,   8 },
  238 /* 104 Mb */ {  AH_TRUE, HT,    104000,    0x8d,    0x00,          13,   8 },
  239 /* 117 Mb */ {  AH_TRUE, HT,    117000,    0x8e,    0x00,          14,   8 },
  240 /* 130 Mb */ {  AH_TRUE, HT,    130000,    0x8f,    0x00,          15,   8 },
  241 /*--- HT TS rates ---*/
  242 /*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x90,    0x00,          16,   4 },
  243 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x91,    0x00,          17,   6 },
  244 /*58.5 Mb */ {  AH_TRUE, HT,     58500,    0x92,    0x00,          18,   6 },
  245 /*  78 Mb */ {  AH_TRUE, HT,     78000,    0x93,    0x00,          19,   8 },
  246 /* 117 Mb */ {  AH_TRUE, HT,    117000,    0x94,    0x00,          20,   8 },
  247 /* 156 Mb */ {  AH_TRUE, HT,    156000,    0x95,    0x00,          21,   8 },
  248 /*175.5Mb */ {  AH_TRUE, HT,    175500,    0x96,    0x00,          22,   8 },
  249 /* 195 Mb */ {  AH_TRUE, HT,    195000,    0x97,    0x00,          23,   8 },
  250     },
  251 };
  252 
  253 #define AR9300_11NA_RT_OFDM_OFFSET       0
  254 #define AR9300_11NA_RT_HT_SS_OFFSET      8
  255 #define AR9300_11NA_RT_HT_DS_OFFSET      16
  256 #define AR9300_11NA_RT_HT_TS_OFFSET      24
  257 static HAL_RATE_TABLE ar9300_11na_table = {
  258 
  259     32,  /* number of rates */
  260     { 0 },
  261     {
  262 /*                                                 short            ctrl */
  263 /*             valid                rate_code Preamble    dot11Rate Rate */
  264 /*   6 Mb */ {  AH_TRUE, OFDM,    6000,    0x0b,    0x00, (0x80 | 12),   0 },
  265 /*   9 Mb */ {  AH_TRUE, OFDM,    9000,    0x0f,    0x00,          18,   0 },
  266 /*  12 Mb */ {  AH_TRUE, OFDM,   12000,    0x0a,    0x00, (0x80 | 24),   2 },
  267 /*  18 Mb */ {  AH_TRUE, OFDM,   18000,    0x0e,    0x00,          36,   2 },
  268 /*  24 Mb */ {  AH_TRUE, OFDM,   24000,    0x09,    0x00, (0x80 | 48),   4 },
  269 /*  36 Mb */ {  AH_TRUE, OFDM,   36000,    0x0d,    0x00,          72,   4 },
  270 /*  48 Mb */ {  AH_TRUE, OFDM,   48000,    0x08,    0x00,          96,   4 },
  271 /*  54 Mb */ {  AH_TRUE, OFDM,   54000,    0x0c,    0x00,         108,   4 },
  272 /*--- HT SS rates ---*/
  273 /* 6.5 Mb */ {  AH_TRUE, HT,      6500,    0x80,    0x00,           0,   0 },
  274 /*  13 Mb */ {  AH_TRUE, HT,     13000,    0x81,    0x00,           1,   2 },
  275 /*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x82,    0x00,           2,   2 },
  276 /*  26 Mb */ {  AH_TRUE, HT,     26000,    0x83,    0x00,           3,   4 },
  277 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x84,    0x00,           4,   4 },
  278 /*  52 Mb */ {  AH_TRUE, HT,     52000,    0x85,    0x00,           5,   4 },
  279 /*58.5 Mb */ {  AH_TRUE, HT,     58500,    0x86,    0x00,           6,   4 },
  280 /*  65 Mb */ {  AH_TRUE, HT,     65000,    0x87,    0x00,           7,   4 },
  281 /*--- HT DS rates ---*/
  282 /*  13 Mb */ {  AH_TRUE, HT,     13000,    0x88,    0x00,           8,   0 },
  283 /*  26 Mb */ {  AH_TRUE, HT,     26000,    0x89,    0x00,           9,   2 },
  284 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x8a,    0x00,          10,   2 },
  285 /*  52 Mb */ {  AH_TRUE, HT,     52000,    0x8b,    0x00,          11,   4 },
  286 /*  78 Mb */ {  AH_TRUE, HT,     78000,    0x8c,    0x00,          12,   4 },
  287 /* 104 Mb */ {  AH_TRUE, HT,    104000,    0x8d,    0x00,          13,   4 },
  288 /* 117 Mb */ {  AH_TRUE, HT,    117000,    0x8e,    0x00,          14,   4 },
  289 /* 130 Mb */ {  AH_TRUE, HT,    130000,    0x8f,    0x00,          15,   4 },
  290 /*--- HT TS rates ---*/
  291 /*19.5 Mb */ {  AH_TRUE, HT,     19500,    0x90,    0x00,          16,   0 },
  292 /*  39 Mb */ {  AH_TRUE, HT,     39000,    0x91,    0x00,          17,   2 },
  293 /*58.5 Mb */ {  AH_TRUE, HT,     58500,    0x92,    0x00,          18,   2 },
  294 /*  78 Mb */ {  AH_TRUE, HT,     78000,    0x93,    0x00,          19,   4 },
  295 /* 117 Mb */ {  AH_TRUE, HT,    117000,    0x94,    0x00,          20,   4 },
  296 /* 156 Mb */ {  AH_TRUE, HT,    156000,    0x95,    0x00,          21,   4 },
  297 /*175.5Mb */ {  AH_TRUE, HT,    175500,    0x96,    0x00,          22,   4 },
  298 /* 195 Mb */ {  AH_TRUE, HT,    195000,    0x97,    0x00,          23,   4 },
  299     },
  300 };
  301 
  302 #undef    OFDM
  303 #undef    CCK
  304 #undef    TURBO
  305 #undef    XR
  306 #undef    HT
  307 #undef    HT_HGI
  308 
  309 const HAL_RATE_TABLE *
  310 ar9300_get_rate_table(struct ath_hal *ah, u_int mode)
  311 {
  312     struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
  313     HAL_CAPABILITIES *p_cap = &ahpriv->ah_caps;
  314     HAL_RATE_TABLE *rt;
  315 
  316     switch (mode) {
  317     case HAL_MODE_11A:
  318         rt = &ar9300_11a_table;
  319         break;
  320     case HAL_MODE_11A_HALF_RATE:
  321         if (p_cap->halChanHalfRate) {
  322             rt = &ar9300_11a_half_table;
  323             break;
  324         }
  325         return AH_NULL;
  326     case HAL_MODE_11A_QUARTER_RATE:
  327         if (p_cap->halChanQuarterRate) {
  328             rt = &ar9300_11a_quarter_table;
  329             break;
  330         }
  331         return AH_NULL;
  332     case HAL_MODE_11B:
  333         rt = &ar9300_11b_table;
  334         break;
  335     case HAL_MODE_11G:
  336         rt =  &ar9300_11g_table;
  337         break;
  338     case HAL_MODE_TURBO:
  339     case HAL_MODE_108G:
  340         rt =  &ar9300_turbo_table;
  341         break;
  342 #if 0
  343     case HAL_MODE_XR:
  344         rt = &ar9300_xr_table;
  345         break;
  346 #endif
  347     case HAL_MODE_11NG_HT20:
  348     case HAL_MODE_11NG_HT40PLUS:
  349     case HAL_MODE_11NG_HT40MINUS:
  350         rt = &ar9300_11ng_table;
  351         break;
  352     case HAL_MODE_11NA_HT20:
  353     case HAL_MODE_11NA_HT40PLUS:
  354     case HAL_MODE_11NA_HT40MINUS:
  355         rt = &ar9300_11na_table;
  356         break;
  357     default:
  358         HALDEBUG(ah, HAL_DEBUG_CHANNEL,
  359             "%s: invalid mode 0x%x\n", __func__, mode);
  360         return AH_NULL;
  361     }
  362     ath_hal_setupratetable(ah, rt);
  363     return rt;
  364 }
  365 
  366 static HAL_BOOL
  367 ar9300_invalid_stbc_cfg(int tx_chains, u_int8_t rate_code)
  368 {
  369     switch (tx_chains) {
  370     case 0: /* Single Chain */
  371         return AH_TRUE;
  372 
  373     case 1: /* 2 Chains */
  374         if ((rate_code < 0x80) || (rate_code > 0x87)) {
  375             return AH_TRUE;
  376         } else {
  377             return AH_FALSE;
  378         }
  379 
  380     case 2: /* 3 Chains */
  381         if ((rate_code < 0x80) || (rate_code > 0x87)) {
  382             return AH_TRUE;
  383         } else {
  384             return AH_FALSE;
  385         }
  386 
  387     default:
  388         HALASSERT(0);
  389         break;
  390     } 
  391 
  392     return AH_TRUE;
  393 }
  394 
  395 int16_t
  396 ar9300_get_rate_txpower(struct ath_hal *ah, u_int mode, u_int8_t rate_index,
  397                      u_int8_t chainmask, u_int8_t xmit_mode)
  398 {
  399     struct ath_hal_9300 *ahp = AH9300(ah);
  400     int num_chains = ar9300_get_ntxchains(chainmask);
  401 
  402     switch (xmit_mode) {
  403     case AR9300_DEF_MODE:
  404         return ahp->txpower[rate_index][num_chains-1];
  405 
  406     
  407     case AR9300_STBC_MODE:
  408         return ahp->txpower_stbc[rate_index][num_chains-1];
  409        
  410     default:
  411         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",
  412              __func__, xmit_mode);
  413         HALASSERT(0);
  414         break;
  415     }
  416 
  417     return ahp->txpower[rate_index][num_chains-1];
  418 }
  419 
  420 extern void
  421 ar9300_adjust_reg_txpower_cdd(struct ath_hal *ah, 
  422                       u_int8_t power_per_rate[])
  423                       
  424 {
  425     struct ath_hal_9300 *ahp = AH9300(ah);
  426     int16_t twice_array_gain, cdd_power = 0;
  427     int i;
  428 
  429     /*
  430      *  Adjust the upper limit for CDD factoring in the array gain .
  431      *  The array gain is the same as TxBF, hence reuse the same defines. 
  432      */
  433     switch (ahp->ah_tx_chainmask) {
  434 
  435     case OSPREY_1_CHAINMASK:
  436         cdd_power = ahp->upper_limit[0];
  437         break;
  438   
  439     case OSPREY_2LOHI_CHAINMASK:
  440     case OSPREY_2LOMID_CHAINMASK:
  441         twice_array_gain =
  442            (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  443            -(AR9300_TXBF_2TX_ARRAY_GAIN) :
  444            ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  445            (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
  446         cdd_power = ahp->upper_limit[1] + twice_array_gain;
  447 
  448         HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 2 chain; cdd_power=%d", __func__, cdd_power);
  449         /* Adjust OFDM legacy rates as well */
  450         for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {
  451             if (power_per_rate[i] > cdd_power) {
  452                 power_per_rate[i] = cdd_power; 
  453             } 
  454         }
  455             
  456         /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7  HT 20*/
  457         for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_7; i++) {
  458             if (power_per_rate[i] > cdd_power) {
  459                 power_per_rate[i] = cdd_power; 
  460             } 
  461         } 
  462 
  463         /* 2Tx/(n-1) stream Adjust rates MCS0 through MCS 7  HT 40*/
  464         for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_7; i++) {
  465             if (power_per_rate[i] > cdd_power) {
  466                 power_per_rate[i] = cdd_power; 
  467             } 
  468         } 
  469         break;
  470         
  471     case OSPREY_3_CHAINMASK:
  472         twice_array_gain =
  473             (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  474             -(AR9300_TXBF_3TX_ARRAY_GAIN) :
  475             ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  476             (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
  477         cdd_power = ahp->upper_limit[2] + twice_array_gain;
  478         HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: 3 chain; cdd_power=%d", __func__, cdd_power);
  479         /* Adjust OFDM legacy rates as well */
  480         for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {
  481             if (power_per_rate[i] > cdd_power) {
  482                 power_per_rate[i] = cdd_power; 
  483             } 
  484         }
  485         /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT20 */
  486         for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_15; i++) {
  487             if (power_per_rate[i] > cdd_power) {
  488                 power_per_rate[i] = cdd_power;
  489             }
  490         }
  491 
  492         /* 3Tx/(n-1)streams Adjust rates MCS0 through MCS 15 HT40 */
  493         for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_15; i++) {
  494             if (power_per_rate[i] > cdd_power) {
  495                 power_per_rate[i] = cdd_power;
  496             }
  497         }
  498 
  499         break;
  500 
  501     default:
  502         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  503                  __func__, ahp->ah_tx_chainmask);
  504         break;
  505     }
  506 
  507     return;
  508 }
  509 
  510 extern void
  511 ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode,
  512                       const struct ieee80211_channel *chan,
  513                       u_int8_t power_per_rate[], u_int8_t chainmask)
  514 {
  515     const HAL_RATE_TABLE *rt;
  516     HAL_BOOL is40 = IEEE80211_IS_CHAN_HT40(chan);
  517 
  518     rt = ar9300_get_rate_table(ah, mode);
  519     HALASSERT(rt != NULL);
  520 
  521     switch (mode) {
  522     case HAL_MODE_11A:
  523         ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
  524                               AR9300_11A_RT_OFDM_OFFSET, chainmask);
  525         break;
  526     case HAL_MODE_11NA_HT20:
  527     case HAL_MODE_11NA_HT40PLUS:
  528     case HAL_MODE_11NA_HT40MINUS:
  529         ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
  530                               AR9300_11NA_RT_OFDM_OFFSET, chainmask);
  531         ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
  532                             AR9300_11NA_RT_HT_SS_OFFSET,
  533                             AR9300_11NA_RT_HT_DS_OFFSET,
  534                             AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
  535         ar9300_init_rate_txpower_stbc(ah, rt, is40,
  536                             AR9300_11NA_RT_HT_SS_OFFSET,
  537                             AR9300_11NA_RT_HT_DS_OFFSET,
  538                             AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
  539 #if 0
  540         /* For FCC the array gain has to be factored for CDD mode */
  541         if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {
  542             ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 
  543                             AR9300_11NA_RT_HT_SS_OFFSET,
  544                             AR9300_11NA_RT_HT_DS_OFFSET,
  545                             AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
  546         }
  547 #endif
  548         break;
  549     case HAL_MODE_11G:
  550         ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
  551         ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
  552                               AR9300_11G_RT_OFDM_OFFSET, chainmask);
  553         break;
  554     case HAL_MODE_11B:
  555         ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
  556         break;
  557     case HAL_MODE_11NG_HT20:
  558     case HAL_MODE_11NG_HT40PLUS:
  559     case HAL_MODE_11NG_HT40MINUS:
  560         ar9300_init_rate_txpower_cck(ah, rt, power_per_rate,  chainmask);
  561         ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
  562                               AR9300_11NG_RT_OFDM_OFFSET, chainmask);
  563         ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
  564                             AR9300_11NG_RT_HT_SS_OFFSET,
  565                             AR9300_11NG_RT_HT_DS_OFFSET,
  566                             AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
  567         ar9300_init_rate_txpower_stbc(ah, rt, is40,
  568                             AR9300_11NG_RT_HT_SS_OFFSET,
  569                             AR9300_11NG_RT_HT_DS_OFFSET,
  570                             AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
  571 #if 0
  572         /* For FCC the array gain needs to be factored for CDD mode */
  573         if (is_reg_dmn_fcc(ath_hal_getctl(ah, chan))) {
  574             ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 
  575                             AR9300_11NG_RT_HT_SS_OFFSET,
  576                             AR9300_11NG_RT_HT_DS_OFFSET,
  577                             AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
  578         }
  579 #endif
  580         break;
  581     default:
  582         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",
  583              __func__, mode);
  584         HALASSERT(0);
  585         break;
  586     }
  587 
  588 }
  589 
  590 static inline void
  591 ar9300_init_rate_txpower_cck(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
  592                          u_int8_t rates_array[], u_int8_t chainmask)
  593 {
  594     struct ath_hal_9300 *ahp = AH9300(ah);
  595     /*
  596      * Pick the lower of the long-preamble txpower, and short-preamble tx power.
  597      * Unfortunately, the rate table doesn't have separate entries for these!.
  598      */
  599     switch (chainmask) {
  600     case OSPREY_1_CHAINMASK:
  601         ahp->txpower[0][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  602         ahp->txpower[1][0] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  603         ahp->txpower[2][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
  604                                   rates_array[ALL_TARGET_LEGACY_5S]);
  605         ahp->txpower[3][0] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
  606                                       rates_array[ALL_TARGET_LEGACY_11S]);
  607         break;
  608     case OSPREY_2LOHI_CHAINMASK:
  609     case OSPREY_2LOMID_CHAINMASK:
  610         ahp->txpower[0][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  611         ahp->txpower[1][1] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  612         ahp->txpower[2][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
  613                                   rates_array[ALL_TARGET_LEGACY_5S]);
  614         ahp->txpower[3][1] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
  615                                   rates_array[ALL_TARGET_LEGACY_11S]);
  616         break;
  617     case OSPREY_3_CHAINMASK:
  618         ahp->txpower[0][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  619         ahp->txpower[1][2] = rates_array[ALL_TARGET_LEGACY_1L_5L];
  620         ahp->txpower[2][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_1L_5L],
  621                                    rates_array[ALL_TARGET_LEGACY_5S]);
  622         ahp->txpower[3][2] = AH_MIN(rates_array[ALL_TARGET_LEGACY_11L],
  623                                        rates_array[ALL_TARGET_LEGACY_11S]);
  624         break;
  625     default:
  626         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  627                  __func__, chainmask);
  628         break;
  629     }
  630 }
  631 
  632 static inline void
  633 ar9300_init_rate_txpower_ofdm(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
  634                           u_int8_t rates_array[], int rt_offset,
  635                           u_int8_t chainmask)
  636 {
  637     struct ath_hal_9300 *ahp = AH9300(ah);
  638     int16_t twice_array_gain, cdd_power = 0;
  639     int i, j;
  640     u_int8_t ofdm_rt_2_pwr_idx[8] =
  641     {
  642         ALL_TARGET_LEGACY_6_24,
  643         ALL_TARGET_LEGACY_6_24,
  644         ALL_TARGET_LEGACY_6_24,
  645         ALL_TARGET_LEGACY_6_24,
  646         ALL_TARGET_LEGACY_6_24,
  647         ALL_TARGET_LEGACY_36,
  648         ALL_TARGET_LEGACY_48,
  649         ALL_TARGET_LEGACY_54,
  650     };
  651 
  652     /*
  653      *  For FCC adjust the upper limit for CDD factoring in the array gain.
  654      *  The array gain is the same as TxBF, hence reuse the same defines. 
  655      */
  656     for (i = rt_offset; i < rt_offset + AR9300_NUM_OFDM_RATES; i++) {
  657 
  658         /* Get the correct OFDM rate to Power table Index */
  659         j = ofdm_rt_2_pwr_idx[i- rt_offset]; 
  660 
  661         switch (chainmask) {
  662         case OSPREY_1_CHAINMASK:
  663             ahp->txpower[i][0] = rates_array[j];
  664             break;
  665         case OSPREY_2LOHI_CHAINMASK:
  666         case OSPREY_2LOMID_CHAINMASK:
  667             ahp->txpower[i][1] = rates_array[j];
  668             if (is_reg_dmn_fcc(ahp->reg_dmn)){
  669                 twice_array_gain = (ahp->twice_antenna_gain >=
  670                 ahp->twice_antenna_reduction)?
  671                 -(AR9300_TXBF_2TX_ARRAY_GAIN) :
  672                 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  673                (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
  674                 cdd_power = ahp->upper_limit[1] + twice_array_gain;
  675                 if (ahp->txpower[i][1] > cdd_power){
  676                     ahp->txpower[i][1] = cdd_power;
  677                 }
  678             }
  679             break;
  680         case OSPREY_3_CHAINMASK:
  681             ahp->txpower[i][2] = rates_array[j];
  682             if (is_reg_dmn_fcc(ahp->reg_dmn)) {
  683                 twice_array_gain =
  684                 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  685                 -(AR9300_TXBF_3TX_ARRAY_GAIN):
  686                 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  687                 (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
  688                 cdd_power = ahp->upper_limit[2] + twice_array_gain;
  689                 if (ahp->txpower[i][2] > cdd_power){
  690                     ahp->txpower[i][2] = cdd_power;
  691                 }
  692             } 
  693             break;
  694         default:
  695             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  696                      __func__, chainmask);
  697             break;
  698         }
  699     }
  700 }
  701 
  702 static  u_int8_t mcs_rate_2_pwr_idx_ht20[24] =
  703     {
  704         ALL_TARGET_HT20_0_8_16,
  705         ALL_TARGET_HT20_1_3_9_11_17_19,
  706         ALL_TARGET_HT20_1_3_9_11_17_19,
  707         ALL_TARGET_HT20_1_3_9_11_17_19,
  708         ALL_TARGET_HT20_4,
  709         ALL_TARGET_HT20_5,
  710         ALL_TARGET_HT20_6,
  711         ALL_TARGET_HT20_7,
  712         ALL_TARGET_HT20_0_8_16,
  713         ALL_TARGET_HT20_1_3_9_11_17_19,
  714         ALL_TARGET_HT20_1_3_9_11_17_19,
  715         ALL_TARGET_HT20_1_3_9_11_17_19,
  716         ALL_TARGET_HT20_12,
  717         ALL_TARGET_HT20_13,
  718         ALL_TARGET_HT20_14,
  719         ALL_TARGET_HT20_15,
  720         ALL_TARGET_HT20_0_8_16,
  721         ALL_TARGET_HT20_1_3_9_11_17_19,
  722         ALL_TARGET_HT20_1_3_9_11_17_19,
  723         ALL_TARGET_HT20_1_3_9_11_17_19,
  724         ALL_TARGET_HT20_20,
  725         ALL_TARGET_HT20_21,
  726         ALL_TARGET_HT20_22,
  727         ALL_TARGET_HT20_23
  728     };
  729 
  730 static   u_int8_t mcs_rate_2_pwr_idx_ht40[24] =
  731     {
  732         ALL_TARGET_HT40_0_8_16,
  733         ALL_TARGET_HT40_1_3_9_11_17_19,
  734         ALL_TARGET_HT40_1_3_9_11_17_19,
  735         ALL_TARGET_HT40_1_3_9_11_17_19,
  736         ALL_TARGET_HT40_4,
  737         ALL_TARGET_HT40_5,
  738         ALL_TARGET_HT40_6,
  739         ALL_TARGET_HT40_7,
  740         ALL_TARGET_HT40_0_8_16,
  741         ALL_TARGET_HT40_1_3_9_11_17_19,
  742         ALL_TARGET_HT40_1_3_9_11_17_19,
  743         ALL_TARGET_HT40_1_3_9_11_17_19,
  744         ALL_TARGET_HT40_12,
  745         ALL_TARGET_HT40_13,
  746         ALL_TARGET_HT40_14,
  747         ALL_TARGET_HT40_15,
  748         ALL_TARGET_HT40_0_8_16,
  749         ALL_TARGET_HT40_1_3_9_11_17_19,
  750         ALL_TARGET_HT40_1_3_9_11_17_19,
  751         ALL_TARGET_HT40_1_3_9_11_17_19,
  752         ALL_TARGET_HT40_20,
  753         ALL_TARGET_HT40_21,
  754         ALL_TARGET_HT40_22,
  755         ALL_TARGET_HT40_23,
  756     };
  757 
  758 static inline void
  759 ar9300_init_rate_txpower_ht(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
  760                         HAL_BOOL is40,
  761                         u_int8_t rates_array[],
  762                         int rt_ss_offset, int rt_ds_offset,
  763                         int rt_ts_offset, u_int8_t chainmask)
  764 {
  765 
  766     struct ath_hal_9300 *ahp = AH9300(ah);
  767     int i, j;
  768     u_int8_t mcs_index = 0;
  769 
  770 
  771     for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
  772         /* Get the correct MCS rate to Power table Index */
  773         j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
  774                           mcs_rate_2_pwr_idx_ht20[mcs_index];
  775         switch (chainmask) {
  776         case OSPREY_1_CHAINMASK:
  777             ahp->txpower[i][0] = rates_array[j];
  778             break;
  779         case OSPREY_2LOHI_CHAINMASK:
  780         case OSPREY_2LOMID_CHAINMASK:
  781             ahp->txpower[i][1] = rates_array[j];
  782             break;
  783         case OSPREY_3_CHAINMASK:
  784             ahp->txpower[i][2] = rates_array[j];
  785             break;
  786         default:
  787             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  788                      __func__, chainmask);
  789             break;
  790         }
  791         mcs_index++;
  792     }
  793 
  794     for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
  795         /* Get the correct MCS rate to Power table Index */
  796         j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
  797                                        mcs_rate_2_pwr_idx_ht20[mcs_index];
  798         switch (chainmask) {
  799         case OSPREY_1_CHAINMASK:
  800             ahp->txpower[i][0] = rates_array[j];
  801             break;
  802         case OSPREY_2LOHI_CHAINMASK:
  803         case OSPREY_2LOMID_CHAINMASK:
  804             ahp->txpower[i][1] = rates_array[j];
  805             break;
  806         case OSPREY_3_CHAINMASK:
  807             ahp->txpower[i][2] = rates_array[j];
  808             break;
  809         default:
  810             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  811                          __func__, chainmask);
  812             break;
  813         }
  814         mcs_index++;
  815     }
  816 
  817     for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {
  818         /* Get the correct MCS rate to Power table Index */
  819         j = (is40) ? mcs_rate_2_pwr_idx_ht40[mcs_index] :
  820                                   mcs_rate_2_pwr_idx_ht20[mcs_index];
  821         switch (chainmask) {
  822         case OSPREY_1_CHAINMASK:
  823             ahp->txpower[i][0] = rates_array[j];
  824             break;
  825         case OSPREY_2LOHI_CHAINMASK:
  826         case OSPREY_2LOMID_CHAINMASK:
  827             ahp->txpower[i][1] = rates_array[j];
  828             break;
  829         case OSPREY_3_CHAINMASK:
  830             ahp->txpower[i][2] = rates_array[j];
  831             break;
  832         default:
  833             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  834                  __func__, chainmask);
  835             break;
  836         }
  837         mcs_index++;
  838     }
  839 }
  840 
  841 static inline void
  842 ar9300_init_rate_txpower_stbc(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
  843                         HAL_BOOL is40,
  844                         int rt_ss_offset, int rt_ds_offset,
  845                         int rt_ts_offset, u_int8_t chainmask)
  846 {
  847 
  848     struct ath_hal_9300 *ahp = AH9300(ah);
  849     int i;
  850     int16_t twice_array_gain, stbc_power = 0;
  851     u_int8_t mcs_index = 0;
  852 
  853     /* Upper Limit with STBC */
  854     switch (chainmask) {
  855     case OSPREY_1_CHAINMASK:
  856         stbc_power = ahp->upper_limit[0];
  857         break;
  858     case OSPREY_2LOHI_CHAINMASK:
  859     case OSPREY_2LOMID_CHAINMASK:
  860         stbc_power = ahp->upper_limit[1];
  861         break;
  862     case OSPREY_3_CHAINMASK:
  863         stbc_power = ahp->upper_limit[2];
  864         /* Ony FCC requires that we back off with 3 transmit chains */
  865         if (is_reg_dmn_fcc(ahp->reg_dmn)) {
  866             twice_array_gain =
  867                 (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  868                 -(AR9300_STBC_3TX_ARRAY_GAIN) :
  869                 ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  870                 (ahp->twice_antenna_gain + AR9300_STBC_3TX_ARRAY_GAIN)), 0));
  871             stbc_power = ahp->upper_limit[2] + twice_array_gain;
  872         }
  873         break;
  874 
  875     default:
  876         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  877                  __func__, chainmask);
  878         break;
  879     }
  880 
  881 
  882     for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
  883         switch (chainmask) {
  884         case OSPREY_1_CHAINMASK:
  885             ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
  886             break;
  887         case OSPREY_2LOHI_CHAINMASK:
  888         case OSPREY_2LOMID_CHAINMASK:
  889             ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
  890             break;
  891         case OSPREY_3_CHAINMASK:
  892             ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
  893             /* 3 TX/1 stream  STBC gain adjustment */
  894             if (ahp->txpower_stbc[i][2] > stbc_power){
  895                 ahp->txpower_stbc[i][2] = stbc_power;
  896             }
  897             break;
  898         default:
  899             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  900                      __func__, chainmask);
  901             break;
  902         }
  903         mcs_index++;
  904     }
  905 
  906     for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
  907         switch (chainmask) {
  908         case OSPREY_1_CHAINMASK:
  909             ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
  910             break;
  911         case OSPREY_2LOHI_CHAINMASK:
  912         case OSPREY_2LOMID_CHAINMASK:
  913             ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
  914             break;
  915         case OSPREY_3_CHAINMASK:
  916             ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
  917             /* 3 TX/2 stream  STBC gain adjustment */
  918             if (ahp->txpower_stbc[i][2] > stbc_power){
  919                 ahp->txpower_stbc[i][2] = stbc_power;
  920             } 
  921             break;
  922         default:
  923             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  924                      __func__, chainmask);
  925             break;
  926         }
  927         mcs_index++;
  928     }
  929 
  930     for (i = rt_ts_offset; i < rt_ts_offset + AR9300_NUM_HT_TS_RATES; i++) {
  931         switch (chainmask) {
  932         case OSPREY_1_CHAINMASK:
  933             ahp->txpower_stbc[i][0] = ahp->txpower[i][0];
  934             break;
  935         case OSPREY_2LOHI_CHAINMASK:
  936         case OSPREY_2LOMID_CHAINMASK:
  937             ahp->txpower_stbc[i][1] = ahp->txpower[i][1];
  938             break;
  939         case OSPREY_3_CHAINMASK:
  940             ahp->txpower_stbc[i][2] = ahp->txpower[i][2];
  941             break;
  942         default:
  943             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  944                      __func__, chainmask);
  945             break;
  946         }
  947         mcs_index++;
  948     }
  949 
  950     return;
  951 }
  952 
  953 /*
  954  * To see why this is disabled, look at ar9300_eeprom.c for FCC/OET 13TR1003.
  955  */
  956 #if 0
  957 static inline void
  958 ar9300_adjust_rate_txpower_cdd(struct ath_hal *ah, const HAL_RATE_TABLE *rt,
  959                         HAL_BOOL is40,
  960                         int rt_ss_offset, int rt_ds_offset,
  961                         int rt_ts_offset, u_int8_t chainmask)
  962 {
  963 
  964     struct ath_hal_9300 *ahp = AH9300(ah);
  965     int i;
  966     int16_t twice_array_gain, cdd_power = 0;
  967     u_int8_t mcs_index = 0;
  968 
  969     /*
  970      *  Adjust the upper limit for CDD factoring in the array gain .
  971      *  The array gain is the same as TxBF, hence reuse the same defines. 
  972      */
  973     switch (chainmask) {
  974     case OSPREY_1_CHAINMASK:
  975         cdd_power = ahp->upper_limit[0];
  976         break;
  977   
  978     case OSPREY_2LOHI_CHAINMASK:
  979     case OSPREY_2LOMID_CHAINMASK:
  980         twice_array_gain =
  981             (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  982             -(AR9300_TXBF_2TX_ARRAY_GAIN) :
  983             ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  984             (ahp->twice_antenna_gain + AR9300_TXBF_2TX_ARRAY_GAIN)), 0));
  985         cdd_power = ahp->upper_limit[1] + twice_array_gain;
  986         break;
  987         
  988     case OSPREY_3_CHAINMASK:
  989         twice_array_gain =
  990             (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)?
  991             -(AR9300_TXBF_3TX_ARRAY_GAIN) :
  992             ((int16_t)AH_MIN((ahp->twice_antenna_reduction -
  993             (ahp->twice_antenna_gain + AR9300_TXBF_3TX_ARRAY_GAIN)), 0));
  994         cdd_power = ahp->upper_limit[2] + twice_array_gain;
  995         break;
  996 
  997     default:
  998         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
  999                      __func__, chainmask);
 1000         break;
 1001     }
 1002 
 1003 
 1004     for (i = rt_ss_offset; i < rt_ss_offset + AR9300_NUM_HT_SS_RATES; i++) {
 1005         switch (chainmask) {
 1006         case OSPREY_1_CHAINMASK:
 1007             break;
 1008 
 1009         case OSPREY_2LOHI_CHAINMASK:
 1010         case OSPREY_2LOMID_CHAINMASK:
 1011             /* 2 TX/1 stream  CDD gain adjustment */
 1012             if (ahp->txpower[i][1] > cdd_power){
 1013                 ahp->txpower[i][1] = cdd_power;
 1014             } 
 1015             break;
 1016         case OSPREY_3_CHAINMASK:
 1017             /* 3 TX/1 stream  CDD gain adjustment */
 1018             if (ahp->txpower[i][2] > cdd_power){
 1019                 ahp->txpower[i][2] = cdd_power;
 1020             }
 1021             break;
 1022         default:
 1023             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
 1024                      __func__, chainmask);
 1025             break;
 1026         }
 1027         mcs_index++;
 1028     }
 1029 
 1030     for (i = rt_ds_offset; i < rt_ds_offset + AR9300_NUM_HT_DS_RATES; i++) {
 1031         switch (chainmask) {
 1032         case OSPREY_1_CHAINMASK:
 1033         case OSPREY_2LOHI_CHAINMASK:
 1034         case OSPREY_2LOMID_CHAINMASK:
 1035             break;
 1036         case OSPREY_3_CHAINMASK:
 1037         /* 3 TX/2 stream  TxBF gain adjustment */
 1038             if (ahp->txpower[i][2] > cdd_power){
 1039                 ahp->txpower[i][2] = cdd_power;
 1040             } 
 1041             break;
 1042         default:
 1043             HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid chainmask 0x%x\n",
 1044                  __func__, chainmask);
 1045             break;
 1046         }
 1047         mcs_index++;
 1048     }
 1049 
 1050     return;
 1051 
 1052 }
 1053 #endif
 1054 
 1055 void ar9300_disp_tpc_tables(struct ath_hal *ah)
 1056 {
 1057     struct ath_hal_9300 *ahp = AH9300(ah);
 1058     const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
 1059     u_int mode = ath_hal_get_curmode(ah, chan);
 1060     const HAL_RATE_TABLE *rt;
 1061     int i, j;
 1062 
 1063     /* Check whether TPC is enabled */
 1064     if (!ah->ah_config.ath_hal_desc_tpc) {
 1065         ath_hal_printf(ah, "\n TPC Register method in use\n");
 1066         return;
 1067     }
 1068     
 1069     rt = ar9300_get_rate_table(ah, mode);
 1070     HALASSERT(rt != NULL);
 1071 
 1072     ath_hal_printf(ah, "\n===TARGET POWER TABLE===\n");
 1073     for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
 1074         for (i = 0; i < rt->rateCount; i++) {
 1075             int16_t txpower[AR9300_MAX_CHAINS]; 
 1076             txpower[j] = ahp->txpower[i][j];
 1077             ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "
 1078                        "Power (%d Chain) [%2d.%1d dBm]\n",
 1079                        i, rt->info[i].rateCode, rt->info[i].rateKbps,
 1080                        j + 1, txpower[j] / 2, txpower[j]%2 * 5);
 1081         }
 1082     }
 1083     ath_hal_printf(ah, "\n");
 1084 
 1085     ath_hal_printf(ah, "\n\n===TARGET POWER TABLE with STBC===\n");
 1086     for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
 1087         for (i = 0; i < rt->rateCount; i++) {
 1088             int16_t txpower[AR9300_MAX_CHAINS]; 
 1089             txpower[j] = ahp->txpower_stbc[i][j];
 1090 
 1091             /* Do not display invalid configurations */
 1092             if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||
 1093                 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||
 1094                 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {
 1095                 continue;
 1096             }
 1097 
 1098             ath_hal_printf(ah, " Index[%2d] Rate[0x%02x] %6d kbps "
 1099                        "Power (%d Chain) [%2d.%1d dBm]\n",
 1100                        i, rt->info[i].rateCode , rt->info[i].rateKbps,
 1101                        j + 1, txpower[j] / 2, txpower[j]%2 * 5);
 1102         }
 1103     }
 1104     ath_hal_printf(ah, "\n");
 1105 }
 1106 
 1107 /*
 1108  * The followings are customer specific APIs for querying power limit.
 1109  * Power limit is based on regulatory domain, chipset, and transmission rate.
 1110  * Here we only consider EEPROM values, no array gain/CTL considered here.
 1111  */
 1112 
 1113 struct rate_power_tbl {
 1114     u_int8_t    rateIdx;        /* rate index in the rate table */
 1115     u_int32_t   rateKbps;       /* transfer rate in kbs */
 1116     u_int8_t    rateCode;      /* rate for h/w descriptors */
 1117     u_int8_t    txbf:   1,      /* txbf eligible */
 1118                 stbc:   1,      /* stbc eligible */
 1119                 chain1: 1,      /* one-chain eligible */
 1120                 chain2: 1,      /* two-chain eligible */
 1121                 chain3: 1;      /* three-chain eligible */
 1122     int16_t     txpower[AR9300_MAX_CHAINS];     /* txpower for different chainmasks */
 1123     int16_t     txpower_stbc[AR9300_MAX_CHAINS];
 1124 };
 1125 
 1126 u_int8_t *ar9300_get_tpc_tables(struct ath_hal *ah)
 1127 {
 1128     struct ath_hal_9300 *ahp = AH9300(ah);
 1129     const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
 1130     u_int mode = ath_hal_get_curmode(ah, chan);
 1131     const HAL_RATE_TABLE *rt;
 1132     u_int8_t *data;
 1133     struct rate_power_tbl *table;
 1134     int i, j;
 1135 
 1136     /* Check whether TPC is enabled */
 1137     if (! ah->ah_config.ath_hal_desc_tpc) {
 1138         ath_hal_printf(ah, "\n TPC Register method in use\n");
 1139         return NULL;
 1140     }
 1141     
 1142     rt = (const HAL_RATE_TABLE *)ar9300_get_rate_table(ah, mode);
 1143     HALASSERT(rt != NULL);
 1144 
 1145     data = (u_int8_t *)ath_hal_malloc(
 1146                        1 + rt->rateCount * sizeof(struct rate_power_tbl));
 1147     if (data == NULL)
 1148         return NULL;
 1149 
 1150     OS_MEMZERO(data, 1 + rt->rateCount * sizeof(struct rate_power_tbl));
 1151     /* store the rate count at the beginning */
 1152     *data = rt->rateCount;
 1153     table = (struct rate_power_tbl *)&data[1];
 1154 
 1155     for (j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
 1156         for (i = 0; i < rt->rateCount; i++) {
 1157             table[i].rateIdx = i;
 1158             table[i].rateCode = rt->info[i].rateCode;
 1159             table[i].rateKbps = rt->info[i].rateKbps;
 1160             switch (j) {
 1161             case 0:
 1162                 table[i].chain1 = rt->info[i].rateCode <= 0x87 ? 1 : 0;
 1163                 break;
 1164             case 1:
 1165                 table[i].chain2 = rt->info[i].rateCode <= 0x8f ? 1 : 0;
 1166                 break;
 1167             case 2:
 1168                 table[i].chain3 = 1;
 1169                 break;
 1170             default:
 1171                 break;
 1172             }
 1173             if ((j == 0 && table[i].chain1) ||
 1174                 (j == 1 && table[i].chain2) ||
 1175                 (j == 2 && table[i].chain3))
 1176                 table[i].txpower[j] = ahp->txpower[i][j];
 1177         }
 1178     }
 1179 
 1180     for ( j = 0 ; j < ar9300_get_ntxchains(ahp->ah_tx_chainmask) ; j++ ) {
 1181         for (i = 0; i < rt->rateCount; i++) {
 1182             /* Do not display invalid configurations */
 1183             if ((rt->info[i].rateCode < AR9300_MCS0_RATE_CODE) ||
 1184                 (rt->info[i].rateCode > AR9300_MCS23_RATE_CODE) ||
 1185                 ar9300_invalid_stbc_cfg(j, rt->info[i].rateCode) == AH_TRUE) {
 1186                 continue;
 1187             }
 1188 
 1189             table[i].stbc = 1;
 1190             table[i].txpower_stbc[j] = ahp->txpower_stbc[i][j];
 1191         }
 1192     }
 1193 
 1194     return data;
 1195     /* the caller is responsible to free data */
 1196 }
 1197 
 1198 HAL_STATUS
 1199 ath_hal_get_rate_power_limit_from_eeprom(struct ath_hal *ah, u_int16_t freq,
 1200                                         int8_t *max_rate_power, int8_t *min_rate_power)
 1201 {
 1202     /*
 1203      * Used for AR9300 series chip only
 1204      */
 1205     if (ah->ah_magic == AR9300_MAGIC) {
 1206         u_int8_t target_rate_power_limit_val_t2[ar9300_rate_size];
 1207         int i;
 1208 
 1209         *max_rate_power = 0;
 1210         *min_rate_power = AR9300_MAX_RATE_POWER;
 1211 
 1212         ar9300_set_target_power_from_eeprom(ah, freq, target_rate_power_limit_val_t2);
 1213 
 1214         for (i=0; i<ar9300_rate_size; i++) {
 1215             if (target_rate_power_limit_val_t2[i] > *max_rate_power)
 1216                 *max_rate_power = target_rate_power_limit_val_t2[i];
 1217             if (target_rate_power_limit_val_t2[i] < *min_rate_power)
 1218                 *min_rate_power = target_rate_power_limit_val_t2[i];
 1219         }
 1220     } else {
 1221         *max_rate_power = 0;
 1222         *min_rate_power = 0;
 1223     }
 1224 
 1225     return HAL_OK;
 1226 }

Cache object: 3ccb06672151c3ea2e60bf4c1f6014ff


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.