linux/drivers/net/wireless/ath/ath5k/caps.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
   3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
   4 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
   5 *
   6 * Permission to use, copy, modify, and distribute this software for any
   7 * purpose with or without fee is hereby granted, provided that the above
   8 * copyright notice and this permission notice appear in all copies.
   9 *
  10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17 *
  18 */
  19
  20/**************\
  21* Capabilities *
  22\**************/
  23
  24#include "ath5k.h"
  25#include "reg.h"
  26#include "debug.h"
  27#include "base.h"
  28
  29/*
  30 * Fill the capabilities struct
  31 * TODO: Merge this with EEPROM code when we are done with it
  32 */
  33int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
  34{
  35        u16 ee_header;
  36
  37        /* Capabilities stored in the EEPROM */
  38        ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
  39
  40        if (ah->ah_version == AR5K_AR5210) {
  41                /*
  42                 * Set radio capabilities
  43                 * (The AR5110 only supports the middle 5GHz band)
  44                 */
  45                ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
  46                ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
  47                ah->ah_capabilities.cap_range.range_2ghz_min = 0;
  48                ah->ah_capabilities.cap_range.range_2ghz_max = 0;
  49
  50                /* Set supported modes */
  51                __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
  52        } else {
  53                /*
  54                 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
  55                 * XXX and from 2312 to 2732GHz. There are problems with the
  56                 * XXX current ieee80211 implementation because the IEEE
  57                 * XXX channel mapping does not support negative channel
  58                 * XXX numbers (2312MHz is channel -19). Of course, this
  59                 * XXX doesn't matter because these channels are out of range
  60                 * XXX but some regulation domains like MKK (Japan) will
  61                 * XXX support frequencies somewhere around 4.8GHz.
  62                 */
  63
  64                /*
  65                 * Set radio capabilities
  66                 */
  67
  68                if (AR5K_EEPROM_HDR_11A(ee_header)) {
  69                        /* 4920 */
  70                        ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
  71                        ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
  72
  73                        /* Set supported modes */
  74                        __set_bit(AR5K_MODE_11A,
  75                                        ah->ah_capabilities.cap_mode);
  76                }
  77
  78                /* Enable  802.11b if a 2GHz capable radio (2111/5112) is
  79                 * connected */
  80                if (AR5K_EEPROM_HDR_11B(ee_header) ||
  81                    (AR5K_EEPROM_HDR_11G(ee_header) &&
  82                     ah->ah_version != AR5K_AR5211)) {
  83                        /* 2312 */
  84                        ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
  85                        ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
  86
  87                        if (AR5K_EEPROM_HDR_11B(ee_header))
  88                                __set_bit(AR5K_MODE_11B,
  89                                                ah->ah_capabilities.cap_mode);
  90
  91                        if (AR5K_EEPROM_HDR_11G(ee_header) &&
  92                            ah->ah_version != AR5K_AR5211)
  93                                __set_bit(AR5K_MODE_11G,
  94                                                ah->ah_capabilities.cap_mode);
  95                }
  96        }
  97
  98        /* Set number of supported TX queues */
  99        if (ah->ah_version == AR5K_AR5210)
 100                ah->ah_capabilities.cap_queues.q_tx_num =
 101                        AR5K_NUM_TX_QUEUES_NOQCU;
 102        else
 103                ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
 104
 105        /* newer hardware has PHY error counters */
 106        if (ah->ah_mac_srev >= AR5K_SREV_AR5213A)
 107                ah->ah_capabilities.cap_has_phyerr_counters = true;
 108        else
 109                ah->ah_capabilities.cap_has_phyerr_counters = false;
 110
 111        return 0;
 112}
 113
 114/* Main function used by the driver part to check caps */
 115int ath5k_hw_get_capability(struct ath5k_hw *ah,
 116                enum ath5k_capability_type cap_type,
 117                u32 capability, u32 *result)
 118{
 119        switch (cap_type) {
 120        case AR5K_CAP_NUM_TXQUEUES:
 121                if (result) {
 122                        if (ah->ah_version == AR5K_AR5210)
 123                                *result = AR5K_NUM_TX_QUEUES_NOQCU;
 124                        else
 125                                *result = AR5K_NUM_TX_QUEUES;
 126                        goto yes;
 127                }
 128        case AR5K_CAP_VEOL:
 129                goto yes;
 130        case AR5K_CAP_COMPRESSION:
 131                if (ah->ah_version == AR5K_AR5212)
 132                        goto yes;
 133                else
 134                        goto no;
 135        case AR5K_CAP_BURST:
 136                goto yes;
 137        case AR5K_CAP_TPC:
 138                goto yes;
 139        case AR5K_CAP_BSSIDMASK:
 140                if (ah->ah_version == AR5K_AR5212)
 141                        goto yes;
 142                else
 143                        goto no;
 144        case AR5K_CAP_XR:
 145                if (ah->ah_version == AR5K_AR5212)
 146                        goto yes;
 147                else
 148                        goto no;
 149        default:
 150                goto no;
 151        }
 152
 153no:
 154        return -EINVAL;
 155yes:
 156        return 0;
 157}
 158
 159/*
 160 * TODO: Following functions should be part of a new function
 161 * set_capability
 162 */
 163
 164int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
 165                u16 assoc_id)
 166{
 167        if (ah->ah_version == AR5K_AR5210) {
 168                AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
 169                        AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
 170                return 0;
 171        }
 172
 173        return -EIO;
 174}
 175
 176int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
 177{
 178        if (ah->ah_version == AR5K_AR5210) {
 179                AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
 180                        AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
 181                return 0;
 182        }
 183
 184        return -EIO;
 185}
 186