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/dev/ath/ath_hal/ah.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  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_devid.h"
   26 #include "ah_eeprom.h"                  /* for 5ghz fast clock flag */
   27 
   28 #include "ar5416/ar5416reg.h"           /* NB: includes ar5212reg.h */
   29 #include "ar9003/ar9300_devid.h"
   30 
   31 /* linker set of registered chips */
   32 OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
   33 TAILQ_HEAD(, ath_hal_chip) ah_chip_list = TAILQ_HEAD_INITIALIZER(ah_chip_list);
   34 
   35 int
   36 ath_hal_add_chip(struct ath_hal_chip *ahc)
   37 {
   38 
   39         TAILQ_INSERT_TAIL(&ah_chip_list, ahc, node);
   40         return (0);
   41 }
   42 
   43 int
   44 ath_hal_remove_chip(struct ath_hal_chip *ahc)
   45 {
   46 
   47         TAILQ_REMOVE(&ah_chip_list, ahc, node);
   48         return (0);
   49 }
   50 
   51 /*
   52  * Check the set of registered chips to see if any recognize
   53  * the device as one they can support.
   54  */
   55 const char*
   56 ath_hal_probe(uint16_t vendorid, uint16_t devid)
   57 {
   58         struct ath_hal_chip * const *pchip;
   59         struct ath_hal_chip *pc;
   60 
   61         /* Linker set */
   62         OS_SET_FOREACH(pchip, ah_chips) {
   63                 const char *name = (*pchip)->probe(vendorid, devid);
   64                 if (name != AH_NULL)
   65                         return name;
   66         }
   67 
   68         /* List */
   69         TAILQ_FOREACH(pc, &ah_chip_list, node) {
   70                 const char *name = pc->probe(vendorid, devid);
   71                 if (name != AH_NULL)
   72                         return name;
   73         }
   74 
   75         return AH_NULL;
   76 }
   77 
   78 /*
   79  * Attach detects device chip revisions, initializes the hwLayer
   80  * function list, reads EEPROM information,
   81  * selects reset vectors, and performs a short self test.
   82  * Any failures will return an error that should cause a hardware
   83  * disable.
   84  */
   85 struct ath_hal*
   86 ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
   87         HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
   88         HAL_OPS_CONFIG *ah_config,
   89         HAL_STATUS *error)
   90 {
   91         struct ath_hal_chip * const *pchip;
   92         struct ath_hal_chip *pc;
   93 
   94         OS_SET_FOREACH(pchip, ah_chips) {
   95                 struct ath_hal_chip *chip = *pchip;
   96                 struct ath_hal *ah;
   97 
   98                 /* XXX don't have vendorid, assume atheros one works */
   99                 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
  100                         continue;
  101                 ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
  102                     error);
  103                 if (ah != AH_NULL) {
  104                         /* copy back private state to public area */
  105                         ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
  106                         ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
  107                         ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
  108                         ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
  109                         ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
  110                         ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
  111                         ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
  112                         return ah;
  113                 }
  114         }
  115 
  116         /* List */
  117         TAILQ_FOREACH(pc, &ah_chip_list, node) {
  118                 struct ath_hal_chip *chip = pc;
  119                 struct ath_hal *ah;
  120 
  121                 /* XXX don't have vendorid, assume atheros one works */
  122                 if (chip->probe(ATHEROS_VENDOR_ID, devid) == AH_NULL)
  123                         continue;
  124                 ah = chip->attach(devid, sc, st, sh, eepromdata, ah_config,
  125                     error);
  126                 if (ah != AH_NULL) {
  127                         /* copy back private state to public area */
  128                         ah->ah_devid = AH_PRIVATE(ah)->ah_devid;
  129                         ah->ah_subvendorid = AH_PRIVATE(ah)->ah_subvendorid;
  130                         ah->ah_macVersion = AH_PRIVATE(ah)->ah_macVersion;
  131                         ah->ah_macRev = AH_PRIVATE(ah)->ah_macRev;
  132                         ah->ah_phyRev = AH_PRIVATE(ah)->ah_phyRev;
  133                         ah->ah_analog5GhzRev = AH_PRIVATE(ah)->ah_analog5GhzRev;
  134                         ah->ah_analog2GhzRev = AH_PRIVATE(ah)->ah_analog2GhzRev;
  135                         return ah;
  136                 }
  137         }
  138 
  139         return AH_NULL;
  140 }
  141 
  142 const char *
  143 ath_hal_mac_name(struct ath_hal *ah)
  144 {
  145         switch (ah->ah_macVersion) {
  146         case AR_SREV_VERSION_CRETE:
  147         case AR_SREV_VERSION_MAUI_1:
  148                 return "AR5210";
  149         case AR_SREV_VERSION_MAUI_2:
  150         case AR_SREV_VERSION_OAHU:
  151                 return "AR5211";
  152         case AR_SREV_VERSION_VENICE:
  153                 return "AR5212";
  154         case AR_SREV_VERSION_GRIFFIN:
  155                 return "AR2413";
  156         case AR_SREV_VERSION_CONDOR:
  157                 return "AR5424";
  158         case AR_SREV_VERSION_EAGLE:
  159                 return "AR5413";
  160         case AR_SREV_VERSION_COBRA:
  161                 return "AR2415";
  162         case AR_SREV_2425:      /* Swan */
  163                 return "AR2425";
  164         case AR_SREV_2417:      /* Nala */
  165                 return "AR2417";
  166         case AR_XSREV_VERSION_OWL_PCI:
  167                 return "AR5416";
  168         case AR_XSREV_VERSION_OWL_PCIE:
  169                 return "AR5418";
  170         case AR_XSREV_VERSION_HOWL:
  171                 return "AR9130";
  172         case AR_XSREV_VERSION_SOWL:
  173                 return "AR9160";
  174         case AR_XSREV_VERSION_MERLIN:
  175                 if (AH_PRIVATE(ah)->ah_ispcie)
  176                         return "AR9280";
  177                 return "AR9220";
  178         case AR_XSREV_VERSION_KITE:
  179                 return "AR9285";
  180         case AR_XSREV_VERSION_KIWI:
  181                 if (AH_PRIVATE(ah)->ah_ispcie)
  182                         return "AR9287";
  183                 return "AR9227";
  184         case AR_SREV_VERSION_AR9380:
  185                 if (ah->ah_macRev >= AR_SREV_REVISION_AR9580_10)
  186                         return "AR9580";
  187                 return "AR9380";
  188         case AR_SREV_VERSION_AR9460:
  189                 return "AR9460";
  190         case AR_SREV_VERSION_AR9330:
  191                 return "AR9330";
  192         case AR_SREV_VERSION_AR9340:
  193                 return "AR9340";
  194         case AR_SREV_VERSION_QCA9550:
  195                 return "QCA9550";
  196         case AR_SREV_VERSION_AR9485:
  197                 return "AR9485";
  198         case AR_SREV_VERSION_QCA9565:
  199                 return "QCA9565";
  200         case AR_SREV_VERSION_QCA9530:
  201                 return "QCA9530";
  202         }
  203         return "????";
  204 }
  205 
  206 /*
  207  * Return the mask of available modes based on the hardware capabilities.
  208  */
  209 u_int
  210 ath_hal_getwirelessmodes(struct ath_hal*ah)
  211 {
  212         return ath_hal_getWirelessModes(ah);
  213 }
  214 
  215 /* linker set of registered RF backends */
  216 OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
  217 TAILQ_HEAD(, ath_hal_rf) ah_rf_list = TAILQ_HEAD_INITIALIZER(ah_rf_list);
  218 
  219 int
  220 ath_hal_add_rf(struct ath_hal_rf *arf)
  221 {
  222 
  223         TAILQ_INSERT_TAIL(&ah_rf_list, arf, node);
  224         return (0);
  225 }
  226 
  227 int
  228 ath_hal_remove_rf(struct ath_hal_rf *arf)
  229 {
  230 
  231         TAILQ_REMOVE(&ah_rf_list, arf, node);
  232         return (0);
  233 }
  234 
  235 /*
  236  * Check the set of registered RF backends to see if
  237  * any recognize the device as one they can support.
  238  */
  239 struct ath_hal_rf *
  240 ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
  241 {
  242         struct ath_hal_rf * const *prf;
  243         struct ath_hal_rf * rf;
  244 
  245         OS_SET_FOREACH(prf, ah_rfs) {
  246                 struct ath_hal_rf *rf = *prf;
  247                 if (rf->probe(ah))
  248                         return rf;
  249         }
  250 
  251         TAILQ_FOREACH(rf, &ah_rf_list, node) {
  252                 if (rf->probe(ah))
  253                         return rf;
  254         }
  255         *ecode = HAL_ENOTSUPP;
  256         return AH_NULL;
  257 }
  258 
  259 const char *
  260 ath_hal_rf_name(struct ath_hal *ah)
  261 {
  262         switch (ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
  263         case 0:                 /* 5210 */
  264                 return "5110";  /* NB: made up */
  265         case AR_RAD5111_SREV_MAJOR:
  266         case AR_RAD5111_SREV_PROD:
  267                 return "5111";
  268         case AR_RAD2111_SREV_MAJOR:
  269                 return "2111";
  270         case AR_RAD5112_SREV_MAJOR:
  271         case AR_RAD5112_SREV_2_0:
  272         case AR_RAD5112_SREV_2_1:
  273                 return "5112";
  274         case AR_RAD2112_SREV_MAJOR:
  275         case AR_RAD2112_SREV_2_0:
  276         case AR_RAD2112_SREV_2_1:
  277                 return "2112";
  278         case AR_RAD2413_SREV_MAJOR:
  279                 return "2413";
  280         case AR_RAD5413_SREV_MAJOR:
  281                 return "5413";
  282         case AR_RAD2316_SREV_MAJOR:
  283                 return "2316";
  284         case AR_RAD2317_SREV_MAJOR:
  285                 return "2317";
  286         case AR_RAD5424_SREV_MAJOR:
  287                 return "5424";
  288 
  289         case AR_RAD5133_SREV_MAJOR:
  290                 return "5133";
  291         case AR_RAD2133_SREV_MAJOR:
  292                 return "2133";
  293         case AR_RAD5122_SREV_MAJOR:
  294                 return "5122";
  295         case AR_RAD2122_SREV_MAJOR:
  296                 return "2122";
  297         }
  298         return "????";
  299 }
  300 
  301 /*
  302  * Poll the register looking for a specific value.
  303  */
  304 HAL_BOOL
  305 ath_hal_wait(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val)
  306 {
  307 #define AH_TIMEOUT      5000
  308         return ath_hal_waitfor(ah, reg, mask, val, AH_TIMEOUT);
  309 #undef AH_TIMEOUT
  310 }
  311 
  312 HAL_BOOL
  313 ath_hal_waitfor(struct ath_hal *ah, u_int reg, uint32_t mask, uint32_t val, uint32_t timeout)
  314 {
  315         int i;
  316 
  317         for (i = 0; i < timeout; i++) {
  318                 if ((OS_REG_READ(ah, reg) & mask) == val)
  319                         return AH_TRUE;
  320                 OS_DELAY(10);
  321         }
  322         HALDEBUG(ah, HAL_DEBUG_REGIO | HAL_DEBUG_PHYIO,
  323             "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
  324             __func__, reg, OS_REG_READ(ah, reg), mask, val);
  325         return AH_FALSE;
  326 }
  327 
  328 /*
  329  * Reverse the bits starting at the low bit for a value of
  330  * bit_count in size
  331  */
  332 uint32_t
  333 ath_hal_reverseBits(uint32_t val, uint32_t n)
  334 {
  335         uint32_t retval;
  336         int i;
  337 
  338         for (i = 0, retval = 0; i < n; i++) {
  339                 retval = (retval << 1) | (val & 1);
  340                 val >>= 1;
  341         }
  342         return retval;
  343 }
  344 
  345 /* 802.11n related timing definitions */
  346 
  347 #define OFDM_PLCP_BITS  22
  348 #define HT_L_STF        8
  349 #define HT_L_LTF        8
  350 #define HT_L_SIG        4
  351 #define HT_SIG          8
  352 #define HT_STF          4
  353 #define HT_LTF(n)       ((n) * 4)
  354 
  355 #define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
  356 #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
  357 #define IS_HT_RATE(_rc)         ( (_rc) & IEEE80211_RATE_MCS)
  358 
  359 /*
  360  * Calculate the duration of a packet whether it is 11n or legacy.
  361  */
  362 uint32_t
  363 ath_hal_pkt_txtime(struct ath_hal *ah, const HAL_RATE_TABLE *rates, uint32_t frameLen,
  364     uint16_t rateix, HAL_BOOL isht40, HAL_BOOL shortPreamble,
  365     HAL_BOOL includeSifs)
  366 {
  367         uint8_t rc;
  368         int numStreams;
  369 
  370         rc = rates->info[rateix].rateCode;
  371 
  372         /* Legacy rate? Return the old way */
  373         if (! IS_HT_RATE(rc))
  374                 return ath_hal_computetxtime(ah, rates, frameLen, rateix,
  375                     shortPreamble, includeSifs);
  376 
  377         /* 11n frame - extract out the number of spatial streams */
  378         numStreams = HT_RC_2_STREAMS(rc);
  379         KASSERT(numStreams > 0 && numStreams <= 4,
  380             ("number of spatial streams needs to be 1..3: MCS rate 0x%x!",
  381             rateix));
  382 
  383         /* XXX TODO: Add SIFS */
  384         return ath_computedur_ht(frameLen, rc, numStreams, isht40,
  385             shortPreamble);
  386 }
  387 
  388 static const uint16_t ht20_bps[32] = {
  389     26, 52, 78, 104, 156, 208, 234, 260,
  390     52, 104, 156, 208, 312, 416, 468, 520,
  391     78, 156, 234, 312, 468, 624, 702, 780,
  392     104, 208, 312, 416, 624, 832, 936, 1040
  393 };
  394 static const uint16_t ht40_bps[32] = {
  395     54, 108, 162, 216, 324, 432, 486, 540,
  396     108, 216, 324, 432, 648, 864, 972, 1080,
  397     162, 324, 486, 648, 972, 1296, 1458, 1620,
  398     216, 432, 648, 864, 1296, 1728, 1944, 2160
  399 };
  400 
  401 /*
  402  * Calculate the transmit duration of an 11n frame.
  403  */
  404 uint32_t
  405 ath_computedur_ht(uint32_t frameLen, uint16_t rate, int streams,
  406     HAL_BOOL isht40, HAL_BOOL isShortGI)
  407 {
  408         uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
  409 
  410         KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
  411         KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
  412 
  413         if (isht40)
  414                 bitsPerSymbol = ht40_bps[HT_RC_2_MCS(rate)];
  415         else
  416                 bitsPerSymbol = ht20_bps[HT_RC_2_MCS(rate)];
  417         numBits = OFDM_PLCP_BITS + (frameLen << 3);
  418         numSymbols = howmany(numBits, bitsPerSymbol);
  419         if (isShortGI)
  420                 txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
  421         else
  422                 txTime = numSymbols * 4;                /* 4us */
  423         return txTime + HT_L_STF + HT_L_LTF +
  424             HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
  425 }
  426 
  427 /*
  428  * Compute the time to transmit a frame of length frameLen bytes
  429  * using the specified rate, phy, and short preamble setting.
  430  */
  431 uint16_t
  432 ath_hal_computetxtime(struct ath_hal *ah,
  433         const HAL_RATE_TABLE *rates, uint32_t frameLen, uint16_t rateix,
  434         HAL_BOOL shortPreamble, HAL_BOOL includeSifs)
  435 {
  436         uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
  437         uint32_t kbps;
  438 
  439         /* Warn if this function is called for 11n rates; it should not be! */
  440         if (IS_HT_RATE(rates->info[rateix].rateCode))
  441                 ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n",
  442                     __func__, rateix, rates->info[rateix].rateCode);
  443 
  444         kbps = rates->info[rateix].rateKbps;
  445         /*
  446          * index can be invalid during dynamic Turbo transitions. 
  447          * XXX
  448          */
  449         if (kbps == 0)
  450                 return 0;
  451         switch (rates->info[rateix].phy) {
  452         case IEEE80211_T_CCK:
  453                 phyTime         = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
  454                 if (shortPreamble && rates->info[rateix].shortPreamble)
  455                         phyTime >>= 1;
  456                 numBits         = frameLen << 3;
  457                 txTime          = phyTime
  458                                 + ((numBits * 1000)/kbps);
  459                 if (includeSifs)
  460                         txTime  += CCK_SIFS_TIME;
  461                 break;
  462         case IEEE80211_T_OFDM:
  463                 bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
  464                 HALASSERT(bitsPerSymbol != 0);
  465 
  466                 numBits         = OFDM_PLCP_BITS + (frameLen << 3);
  467                 numSymbols      = howmany(numBits, bitsPerSymbol);
  468                 txTime          = OFDM_PREAMBLE_TIME
  469                                 + (numSymbols * OFDM_SYMBOL_TIME);
  470                 if (includeSifs)
  471                         txTime  += OFDM_SIFS_TIME;
  472                 break;
  473         case IEEE80211_T_OFDM_HALF:
  474                 bitsPerSymbol   = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
  475                 HALASSERT(bitsPerSymbol != 0);
  476 
  477                 numBits         = OFDM_HALF_PLCP_BITS + (frameLen << 3);
  478                 numSymbols      = howmany(numBits, bitsPerSymbol);
  479                 txTime          = OFDM_HALF_PREAMBLE_TIME
  480                                 + (numSymbols * OFDM_HALF_SYMBOL_TIME);
  481                 if (includeSifs)
  482                         txTime  += OFDM_HALF_SIFS_TIME;
  483                 break;
  484         case IEEE80211_T_OFDM_QUARTER:
  485                 bitsPerSymbol   = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
  486                 HALASSERT(bitsPerSymbol != 0);
  487 
  488                 numBits         = OFDM_QUARTER_PLCP_BITS + (frameLen << 3);
  489                 numSymbols      = howmany(numBits, bitsPerSymbol);
  490                 txTime          = OFDM_QUARTER_PREAMBLE_TIME
  491                                 + (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
  492                 if (includeSifs)
  493                         txTime  += OFDM_QUARTER_SIFS_TIME;
  494                 break;
  495         case IEEE80211_T_TURBO:
  496                 bitsPerSymbol   = (kbps * TURBO_SYMBOL_TIME) / 1000;
  497                 HALASSERT(bitsPerSymbol != 0);
  498 
  499                 numBits         = TURBO_PLCP_BITS + (frameLen << 3);
  500                 numSymbols      = howmany(numBits, bitsPerSymbol);
  501                 txTime          = TURBO_PREAMBLE_TIME
  502                                 + (numSymbols * TURBO_SYMBOL_TIME);
  503                 if (includeSifs)
  504                         txTime  += TURBO_SIFS_TIME;
  505                 break;
  506         default:
  507                 HALDEBUG(ah, HAL_DEBUG_PHYIO,
  508                     "%s: unknown phy %u (rate ix %u)\n",
  509                     __func__, rates->info[rateix].phy, rateix);
  510                 txTime = 0;
  511                 break;
  512         }
  513         return txTime;
  514 }
  515 
  516 int
  517 ath_hal_get_curmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
  518 {
  519         /*
  520          * Pick a default mode at bootup. A channel change is inevitable.
  521          */
  522         if (!chan)
  523                 return HAL_MODE_11NG_HT20;
  524 
  525         if (IEEE80211_IS_CHAN_TURBO(chan))
  526                 return HAL_MODE_TURBO;
  527 
  528         /* check for NA_HT before plain A, since IS_CHAN_A includes NA_HT */
  529         if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
  530                 return HAL_MODE_11NA_HT20;
  531         if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
  532                 return HAL_MODE_11NA_HT40PLUS;
  533         if (IEEE80211_IS_CHAN_5GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
  534                 return HAL_MODE_11NA_HT40MINUS;
  535         if (IEEE80211_IS_CHAN_A(chan))
  536                 return HAL_MODE_11A;
  537 
  538         /* check for NG_HT before plain G, since IS_CHAN_G includes NG_HT */
  539         if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan))
  540                 return HAL_MODE_11NG_HT20;
  541         if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40U(chan))
  542                 return HAL_MODE_11NG_HT40PLUS;
  543         if (IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT40D(chan))
  544                 return HAL_MODE_11NG_HT40MINUS;
  545 
  546         /*
  547          * XXX For FreeBSD, will this work correctly given the DYN
  548          * chan mode (OFDM+CCK dynamic) ? We have pure-G versions DYN-BG..
  549          */
  550         if (IEEE80211_IS_CHAN_G(chan))
  551                 return HAL_MODE_11G;
  552         if (IEEE80211_IS_CHAN_B(chan))
  553                 return HAL_MODE_11B;
  554 
  555         HALASSERT(0);
  556         return HAL_MODE_11NG_HT20;
  557 }
  558 
  559 typedef enum {
  560         WIRELESS_MODE_11a   = 0,
  561         WIRELESS_MODE_TURBO = 1,
  562         WIRELESS_MODE_11b   = 2,
  563         WIRELESS_MODE_11g   = 3,
  564         WIRELESS_MODE_108g  = 4,
  565 
  566         WIRELESS_MODE_MAX
  567 } WIRELESS_MODE;
  568 
  569 /*
  570  * XXX TODO: for some (?) chips, an 11b mode still runs at 11bg.
  571  * Maybe AR5211 has separate 11b and 11g only modes, so 11b is 22MHz
  572  * and 11g is 44MHz, but AR5416 and later run 11b in 11bg mode, right?
  573  */
  574 static WIRELESS_MODE
  575 ath_hal_chan2wmode(struct ath_hal *ah, const struct ieee80211_channel *chan)
  576 {
  577         if (IEEE80211_IS_CHAN_B(chan))
  578                 return WIRELESS_MODE_11b;
  579         if (IEEE80211_IS_CHAN_G(chan))
  580                 return WIRELESS_MODE_11g;
  581         if (IEEE80211_IS_CHAN_108G(chan))
  582                 return WIRELESS_MODE_108g;
  583         if (IEEE80211_IS_CHAN_TURBO(chan))
  584                 return WIRELESS_MODE_TURBO;
  585         return WIRELESS_MODE_11a;
  586 }
  587 
  588 /*
  589  * Convert between microseconds and core system clocks.
  590  */
  591                                      /* 11a Turbo  11b  11g  108g */
  592 static const uint8_t CLOCK_RATE[]  = { 40,  80,   22,  44,   88  };
  593 
  594 #define CLOCK_FAST_RATE_5GHZ_OFDM       44
  595 
  596 u_int
  597 ath_hal_mac_clks(struct ath_hal *ah, u_int usecs)
  598 {
  599         const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
  600         u_int clks;
  601 
  602         /* NB: ah_curchan may be null when called attach time */
  603         /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
  604         if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
  605                 clks = usecs * CLOCK_FAST_RATE_5GHZ_OFDM;
  606                 if (IEEE80211_IS_CHAN_HT40(c))
  607                         clks <<= 1;
  608         } else if (c != AH_NULL) {
  609                 clks = usecs * CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
  610                 if (IEEE80211_IS_CHAN_HT40(c))
  611                         clks <<= 1;
  612         } else
  613                 clks = usecs * CLOCK_RATE[WIRELESS_MODE_11b];
  614 
  615         /* Compensate for half/quarter rate */
  616         if (c != AH_NULL && IEEE80211_IS_CHAN_HALF(c))
  617                 clks = clks / 2;
  618         else if (c != AH_NULL && IEEE80211_IS_CHAN_QUARTER(c))
  619                 clks = clks / 4;
  620 
  621         return clks;
  622 }
  623 
  624 u_int
  625 ath_hal_mac_usec(struct ath_hal *ah, u_int clks)
  626 {
  627         uint64_t psec;
  628 
  629         psec = ath_hal_mac_psec(ah, clks);
  630         return (psec / 1000000);
  631 }
  632 
  633 /*
  634  * XXX TODO: half, quarter rates.
  635  */
  636 uint64_t
  637 ath_hal_mac_psec(struct ath_hal *ah, u_int clks)
  638 {
  639         const struct ieee80211_channel *c = AH_PRIVATE(ah)->ah_curchan;
  640         uint64_t psec;
  641 
  642         /* NB: ah_curchan may be null when called attach time */
  643         /* XXX merlin and later specific workaround - 5ghz fast clock is 44 */
  644         if (c != AH_NULL && IS_5GHZ_FAST_CLOCK_EN(ah, c)) {
  645                 psec = (clks * 1000000ULL) / CLOCK_FAST_RATE_5GHZ_OFDM;
  646                 if (IEEE80211_IS_CHAN_HT40(c))
  647                         psec >>= 1;
  648         } else if (c != AH_NULL) {
  649                 psec = (clks * 1000000ULL) / CLOCK_RATE[ath_hal_chan2wmode(ah, c)];
  650                 if (IEEE80211_IS_CHAN_HT40(c))
  651                         psec >>= 1;
  652         } else
  653                 psec = (clks * 1000000ULL) / CLOCK_RATE[WIRELESS_MODE_11b];
  654         return psec;
  655 }
  656 
  657 /*
  658  * Setup a h/w rate table's reverse lookup table and
  659  * fill in ack durations.  This routine is called for
  660  * each rate table returned through the ah_getRateTable
  661  * method.  The reverse lookup tables are assumed to be
  662  * initialized to zero (or at least the first entry).
  663  * We use this as a key that indicates whether or not
  664  * we've previously setup the reverse lookup table.
  665  *
  666  * XXX not reentrant, but shouldn't matter
  667  */
  668 void
  669 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
  670 {
  671 #define N(a)    (sizeof(a)/sizeof(a[0]))
  672         int i;
  673 
  674         if (rt->rateCodeToIndex[0] != 0)        /* already setup */
  675                 return;
  676         for (i = 0; i < N(rt->rateCodeToIndex); i++)
  677                 rt->rateCodeToIndex[i] = (uint8_t) -1;
  678         for (i = 0; i < rt->rateCount; i++) {
  679                 uint8_t code = rt->info[i].rateCode;
  680                 uint8_t cix = rt->info[i].controlRate;
  681 
  682                 HALASSERT(code < N(rt->rateCodeToIndex));
  683                 rt->rateCodeToIndex[code] = i;
  684                 HALASSERT((code | rt->info[i].shortPreamble) <
  685                     N(rt->rateCodeToIndex));
  686                 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
  687                 /*
  688                  * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
  689                  *     depends on whether they are marked as basic rates;
  690                  *     the static tables are setup with an 11b-compatible
  691                  *     2Mb/s rate which will work but is suboptimal
  692                  */
  693                 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
  694                         WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE, AH_TRUE);
  695                 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
  696                         WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE, AH_TRUE);
  697         }
  698 #undef N
  699 }
  700 
  701 HAL_STATUS
  702 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
  703         uint32_t capability, uint32_t *result)
  704 {
  705         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
  706 
  707         switch (type) {
  708         case HAL_CAP_REG_DMN:           /* regulatory domain */
  709                 *result = AH_PRIVATE(ah)->ah_currentRD;
  710                 return HAL_OK;
  711         case HAL_CAP_DFS_DMN:           /* DFS Domain */
  712                 *result = AH_PRIVATE(ah)->ah_dfsDomain;
  713                 return HAL_OK;
  714         case HAL_CAP_CIPHER:            /* cipher handled in hardware */
  715         case HAL_CAP_TKIP_MIC:          /* handle TKIP MIC in hardware */
  716                 return HAL_ENOTSUPP;
  717         case HAL_CAP_TKIP_SPLIT:        /* hardware TKIP uses split keys */
  718                 return HAL_ENOTSUPP;
  719         case HAL_CAP_PHYCOUNTERS:       /* hardware PHY error counters */
  720                 return pCap->halHwPhyCounterSupport ? HAL_OK : HAL_ENXIO;
  721         case HAL_CAP_WME_TKIPMIC:   /* hardware can do TKIP MIC when WMM is turned on */
  722                 return HAL_ENOTSUPP;
  723         case HAL_CAP_DIVERSITY:         /* hardware supports fast diversity */
  724                 return HAL_ENOTSUPP;
  725         case HAL_CAP_KEYCACHE_SIZE:     /* hardware key cache size */
  726                 *result =  pCap->halKeyCacheSize;
  727                 return HAL_OK;
  728         case HAL_CAP_NUM_TXQUEUES:      /* number of hardware tx queues */
  729                 *result = pCap->halTotalQueues;
  730                 return HAL_OK;
  731         case HAL_CAP_VEOL:              /* hardware supports virtual EOL */
  732                 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
  733         case HAL_CAP_PSPOLL:            /* hardware PS-Poll support works */
  734                 return pCap->halPSPollBroken ? HAL_ENOTSUPP : HAL_OK;
  735         case HAL_CAP_COMPRESSION:
  736                 return pCap->halCompressSupport ? HAL_OK : HAL_ENOTSUPP;
  737         case HAL_CAP_BURST:
  738                 return pCap->halBurstSupport ? HAL_OK : HAL_ENOTSUPP;
  739         case HAL_CAP_FASTFRAME:
  740                 return pCap->halFastFramesSupport ? HAL_OK : HAL_ENOTSUPP;
  741         case HAL_CAP_DIAG:              /* hardware diagnostic support */
  742                 *result = AH_PRIVATE(ah)->ah_diagreg;
  743                 return HAL_OK;
  744         case HAL_CAP_TXPOW:             /* global tx power limit  */
  745                 switch (capability) {
  746                 case 0:                 /* facility is supported */
  747                         return HAL_OK;
  748                 case 1:                 /* current limit */
  749                         *result = AH_PRIVATE(ah)->ah_powerLimit;
  750                         return HAL_OK;
  751                 case 2:                 /* current max tx power */
  752                         *result = AH_PRIVATE(ah)->ah_maxPowerLevel;
  753                         return HAL_OK;
  754                 case 3:                 /* scale factor */
  755                         *result = AH_PRIVATE(ah)->ah_tpScale;
  756                         return HAL_OK;
  757                 }
  758                 return HAL_ENOTSUPP;
  759         case HAL_CAP_BSSIDMASK:         /* hardware supports bssid mask */
  760                 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
  761         case HAL_CAP_MCAST_KEYSRCH:     /* multicast frame keycache search */
  762                 return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENOTSUPP;
  763         case HAL_CAP_TSF_ADJUST:        /* hardware has beacon tsf adjust */
  764                 return HAL_ENOTSUPP;
  765         case HAL_CAP_RFSILENT:          /* rfsilent support  */
  766                 switch (capability) {
  767                 case 0:                 /* facility is supported */
  768                         return pCap->halRfSilentSupport ? HAL_OK : HAL_ENOTSUPP;
  769                 case 1:                 /* current setting */
  770                         return AH_PRIVATE(ah)->ah_rfkillEnabled ?
  771                                 HAL_OK : HAL_ENOTSUPP;
  772                 case 2:                 /* rfsilent config */
  773                         *result = AH_PRIVATE(ah)->ah_rfsilent;
  774                         return HAL_OK;
  775                 }
  776                 return HAL_ENOTSUPP;
  777         case HAL_CAP_11D:
  778                 return HAL_OK;
  779 
  780         case HAL_CAP_HT:
  781                 return pCap->halHTSupport ? HAL_OK : HAL_ENOTSUPP;
  782         case HAL_CAP_GTXTO:
  783                 return pCap->halGTTSupport ? HAL_OK : HAL_ENOTSUPP;
  784         case HAL_CAP_FAST_CC:
  785                 return pCap->halFastCCSupport ? HAL_OK : HAL_ENOTSUPP;
  786         case HAL_CAP_TX_CHAINMASK:      /* mask of TX chains supported */
  787                 *result = pCap->halTxChainMask;
  788                 return HAL_OK;
  789         case HAL_CAP_RX_CHAINMASK:      /* mask of RX chains supported */
  790                 *result = pCap->halRxChainMask;
  791                 return HAL_OK;
  792         case HAL_CAP_NUM_GPIO_PINS:
  793                 *result = pCap->halNumGpioPins;
  794                 return HAL_OK;
  795         case HAL_CAP_CST:
  796                 return pCap->halCSTSupport ? HAL_OK : HAL_ENOTSUPP;
  797         case HAL_CAP_RTS_AGGR_LIMIT:
  798                 *result = pCap->halRtsAggrLimit;
  799                 return HAL_OK;
  800         case HAL_CAP_4ADDR_AGGR:
  801                 return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
  802         case HAL_CAP_EXT_CHAN_DFS:
  803                 return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
  804         case HAL_CAP_RX_STBC:
  805                 return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
  806         case HAL_CAP_TX_STBC:
  807                 return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
  808         case HAL_CAP_COMBINED_RADAR_RSSI:
  809                 return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
  810         case HAL_CAP_AUTO_SLEEP:
  811                 return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
  812         case HAL_CAP_MBSSID_AGGR_SUPPORT:
  813                 return pCap->halMbssidAggrSupport ? HAL_OK : HAL_ENOTSUPP;
  814         case HAL_CAP_SPLIT_4KB_TRANS:   /* hardware handles descriptors straddling 4k page boundary */
  815                 return pCap->hal4kbSplitTransSupport ? HAL_OK : HAL_ENOTSUPP;
  816         case HAL_CAP_REG_FLAG:
  817                 *result = AH_PRIVATE(ah)->ah_currentRDext;
  818                 return HAL_OK;
  819         case HAL_CAP_ENHANCED_DMA_SUPPORT:
  820                 return pCap->halEnhancedDmaSupport ? HAL_OK : HAL_ENOTSUPP;
  821         case HAL_CAP_NUM_TXMAPS:
  822                 *result = pCap->halNumTxMaps;
  823                 return HAL_OK;
  824         case HAL_CAP_TXDESCLEN:
  825                 *result = pCap->halTxDescLen;
  826                 return HAL_OK;
  827         case HAL_CAP_TXSTATUSLEN:
  828                 *result = pCap->halTxStatusLen;
  829                 return HAL_OK;
  830         case HAL_CAP_RXSTATUSLEN:
  831                 *result = pCap->halRxStatusLen;
  832                 return HAL_OK;
  833         case HAL_CAP_RXFIFODEPTH:
  834                 switch (capability) {
  835                 case HAL_RX_QUEUE_HP:
  836                         *result = pCap->halRxHpFifoDepth;
  837                         return HAL_OK;
  838                 case HAL_RX_QUEUE_LP:
  839                         *result = pCap->halRxLpFifoDepth;
  840                         return HAL_OK;
  841                 default:
  842                         return HAL_ENOTSUPP;
  843         }
  844         case HAL_CAP_RXBUFSIZE:
  845         case HAL_CAP_NUM_MR_RETRIES:
  846                 *result = pCap->halNumMRRetries;
  847                 return HAL_OK;
  848         case HAL_CAP_BT_COEX:
  849                 return pCap->halBtCoexSupport ? HAL_OK : HAL_ENOTSUPP;
  850         case HAL_CAP_SPECTRAL_SCAN:
  851                 return pCap->halSpectralScanSupport ? HAL_OK : HAL_ENOTSUPP;
  852         case HAL_CAP_HT20_SGI:
  853                 return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP;
  854         case HAL_CAP_RXTSTAMP_PREC:     /* rx desc tstamp precision (bits) */
  855                 *result = pCap->halRxTstampPrecision;
  856                 return HAL_OK;
  857         case HAL_CAP_ANT_DIV_COMB:      /* AR9285/AR9485 LNA diversity */
  858                 return pCap->halAntDivCombSupport ? HAL_OK  : HAL_ENOTSUPP;
  859 
  860         case HAL_CAP_ENHANCED_DFS_SUPPORT:
  861                 return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
  862 
  863         /* FreeBSD-specific entries for now */
  864         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
  865                 return AH_PRIVATE(ah)->ah_rxornIsFatal ? HAL_OK : HAL_ENOTSUPP;
  866         case HAL_CAP_INTRMASK:          /* mask of supported interrupts */
  867                 *result = pCap->halIntrMask;
  868                 return HAL_OK;
  869         case HAL_CAP_BSSIDMATCH:        /* hardware has disable bssid match */
  870                 return pCap->halBssidMatchSupport ? HAL_OK : HAL_ENOTSUPP;
  871         case HAL_CAP_STREAMS:           /* number of 11n spatial streams */
  872                 switch (capability) {
  873                 case 0:                 /* TX */
  874                         *result = pCap->halTxStreams;
  875                         return HAL_OK;
  876                 case 1:                 /* RX */
  877                         *result = pCap->halRxStreams;
  878                         return HAL_OK;
  879                 default:
  880                         return HAL_ENOTSUPP;
  881                 }
  882         case HAL_CAP_RXDESC_SELFLINK:   /* hardware supports self-linked final RX descriptors correctly */
  883                 return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
  884         case HAL_CAP_BB_READ_WAR:               /* Baseband read WAR */
  885                 return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP;
  886         case HAL_CAP_SERIALISE_WAR:             /* PCI register serialisation */
  887                 return pCap->halSerialiseRegWar ? HAL_OK : HAL_ENOTSUPP;
  888         case HAL_CAP_MFP:                       /* Management frame protection setting */
  889                 *result = pCap->halMfpSupport;
  890                 return HAL_OK;
  891         case HAL_CAP_RX_LNA_MIXING:     /* Hardware uses an RX LNA mixer to map 2 antennas to a 1 stream receiver */
  892                 return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP;
  893         case HAL_CAP_DO_MYBEACON:       /* Hardware supports filtering my-beacons */
  894                 return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP;
  895         case HAL_CAP_TXTSTAMP_PREC:     /* tx desc tstamp precision (bits) */
  896                 *result = pCap->halTxTstampPrecision;
  897                 return HAL_OK;
  898         default:
  899                 return HAL_EINVAL;
  900         }
  901 }
  902 
  903 HAL_BOOL
  904 ath_hal_setcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
  905         uint32_t capability, uint32_t setting, HAL_STATUS *status)
  906 {
  907 
  908         switch (type) {
  909         case HAL_CAP_TXPOW:
  910                 switch (capability) {
  911                 case 3:
  912                         if (setting <= HAL_TP_SCALE_MIN) {
  913                                 AH_PRIVATE(ah)->ah_tpScale = setting;
  914                                 return AH_TRUE;
  915                         }
  916                         break;
  917                 }
  918                 break;
  919         case HAL_CAP_RFSILENT:          /* rfsilent support  */
  920                 /*
  921                  * NB: allow even if halRfSilentSupport is false
  922                  *     in case the EEPROM is misprogrammed.
  923                  */
  924                 switch (capability) {
  925                 case 1:                 /* current setting */
  926                         AH_PRIVATE(ah)->ah_rfkillEnabled = (setting != 0);
  927                         return AH_TRUE;
  928                 case 2:                 /* rfsilent config */
  929                         /* XXX better done per-chip for validation? */
  930                         AH_PRIVATE(ah)->ah_rfsilent = setting;
  931                         return AH_TRUE;
  932                 }
  933                 break;
  934         case HAL_CAP_REG_DMN:           /* regulatory domain */
  935                 AH_PRIVATE(ah)->ah_currentRD = setting;
  936                 return AH_TRUE;
  937         case HAL_CAP_RXORN_FATAL:       /* HAL_INT_RXORN treated as fatal  */
  938                 AH_PRIVATE(ah)->ah_rxornIsFatal = setting;
  939                 return AH_TRUE;
  940         default:
  941                 break;
  942         }
  943         if (status)
  944                 *status = HAL_EINVAL;
  945         return AH_FALSE;
  946 }
  947 
  948 /* 
  949  * Common support for getDiagState method.
  950  */
  951 
  952 static u_int
  953 ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
  954         void *dstbuf, int space)
  955 {
  956         uint32_t *dp = dstbuf;
  957         int i;
  958 
  959         for (i = 0; space >= 2*sizeof(uint32_t); i++) {
  960                 uint32_t r = regs[i].start;
  961                 uint32_t e = regs[i].end;
  962                 *dp++ = r;
  963                 *dp++ = e;
  964                 space -= 2*sizeof(uint32_t);
  965                 do {
  966                         *dp++ = OS_REG_READ(ah, r);
  967                         r += sizeof(uint32_t);
  968                         space -= sizeof(uint32_t);
  969                 } while (r <= e && space >= sizeof(uint32_t));
  970         }
  971         return (char *) dp - (char *) dstbuf;
  972 }
  973 
  974 static void
  975 ath_hal_setregs(struct ath_hal *ah, const HAL_REGWRITE *regs, int space)
  976 {
  977         while (space >= sizeof(HAL_REGWRITE)) {
  978                 OS_REG_WRITE(ah, regs->addr, regs->value);
  979                 regs++, space -= sizeof(HAL_REGWRITE);
  980         }
  981 }
  982 
  983 HAL_BOOL
  984 ath_hal_getdiagstate(struct ath_hal *ah, int request,
  985         const void *args, uint32_t argsize,
  986         void **result, uint32_t *resultsize)
  987 {
  988 
  989         switch (request) {
  990         case HAL_DIAG_REVS:
  991                 *result = &AH_PRIVATE(ah)->ah_devid;
  992                 *resultsize = sizeof(HAL_REVS);
  993                 return AH_TRUE;
  994         case HAL_DIAG_REGS:
  995                 *resultsize = ath_hal_getregdump(ah, args, *result,*resultsize);
  996                 return AH_TRUE;
  997         case HAL_DIAG_SETREGS:
  998                 ath_hal_setregs(ah, args, argsize);
  999                 *resultsize = 0;
 1000                 return AH_TRUE;
 1001         case HAL_DIAG_FATALERR:
 1002                 *result = &AH_PRIVATE(ah)->ah_fatalState[0];
 1003                 *resultsize = sizeof(AH_PRIVATE(ah)->ah_fatalState);
 1004                 return AH_TRUE;
 1005         case HAL_DIAG_EEREAD:
 1006                 if (argsize != sizeof(uint16_t))
 1007                         return AH_FALSE;
 1008                 if (!ath_hal_eepromRead(ah, *(const uint16_t *)args, *result))
 1009                         return AH_FALSE;
 1010                 *resultsize = sizeof(uint16_t);
 1011                 return AH_TRUE;
 1012 #ifdef AH_PRIVATE_DIAG
 1013         case HAL_DIAG_SETKEY: {
 1014                 const HAL_DIAG_KEYVAL *dk;
 1015 
 1016                 if (argsize != sizeof(HAL_DIAG_KEYVAL))
 1017                         return AH_FALSE;
 1018                 dk = (const HAL_DIAG_KEYVAL *)args;
 1019                 return ah->ah_setKeyCacheEntry(ah, dk->dk_keyix,
 1020                         &dk->dk_keyval, dk->dk_mac, dk->dk_xor);
 1021         }
 1022         case HAL_DIAG_RESETKEY:
 1023                 if (argsize != sizeof(uint16_t))
 1024                         return AH_FALSE;
 1025                 return ah->ah_resetKeyCacheEntry(ah, *(const uint16_t *)args);
 1026 #ifdef AH_SUPPORT_WRITE_EEPROM
 1027         case HAL_DIAG_EEWRITE: {
 1028                 const HAL_DIAG_EEVAL *ee;
 1029                 if (argsize != sizeof(HAL_DIAG_EEVAL))
 1030                         return AH_FALSE;
 1031                 ee = (const HAL_DIAG_EEVAL *)args;
 1032                 return ath_hal_eepromWrite(ah, ee->ee_off, ee->ee_data);
 1033         }
 1034 #endif /* AH_SUPPORT_WRITE_EEPROM */
 1035 #endif /* AH_PRIVATE_DIAG */
 1036         case HAL_DIAG_11NCOMPAT:
 1037                 if (argsize == 0) {
 1038                         *resultsize = sizeof(uint32_t);
 1039                         *((uint32_t *)(*result)) =
 1040                                 AH_PRIVATE(ah)->ah_11nCompat;
 1041                 } else if (argsize == sizeof(uint32_t)) {
 1042                         AH_PRIVATE(ah)->ah_11nCompat = *(const uint32_t *)args;
 1043                 } else
 1044                         return AH_FALSE;
 1045                 return AH_TRUE;
 1046         case HAL_DIAG_CHANSURVEY:
 1047                 *result = &AH_PRIVATE(ah)->ah_chansurvey;
 1048                 *resultsize = sizeof(HAL_CHANNEL_SURVEY);
 1049                 return AH_TRUE;
 1050         }
 1051         return AH_FALSE;
 1052 }
 1053 
 1054 /*
 1055  * Set the properties of the tx queue with the parameters
 1056  * from qInfo.
 1057  */
 1058 HAL_BOOL
 1059 ath_hal_setTxQProps(struct ath_hal *ah,
 1060         HAL_TX_QUEUE_INFO *qi, const HAL_TXQ_INFO *qInfo)
 1061 {
 1062         uint32_t cw;
 1063 
 1064         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
 1065                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
 1066                     "%s: inactive queue\n", __func__);
 1067                 return AH_FALSE;
 1068         }
 1069         /* XXX validate parameters */
 1070         qi->tqi_ver = qInfo->tqi_ver;
 1071         qi->tqi_subtype = qInfo->tqi_subtype;
 1072         qi->tqi_qflags = qInfo->tqi_qflags;
 1073         qi->tqi_priority = qInfo->tqi_priority;
 1074         if (qInfo->tqi_aifs != HAL_TXQ_USEDEFAULT)
 1075                 qi->tqi_aifs = AH_MIN(qInfo->tqi_aifs, 255);
 1076         else
 1077                 qi->tqi_aifs = INIT_AIFS;
 1078         if (qInfo->tqi_cwmin != HAL_TXQ_USEDEFAULT) {
 1079                 cw = AH_MIN(qInfo->tqi_cwmin, 1024);
 1080                 /* make sure that the CWmin is of the form (2^n - 1) */
 1081                 qi->tqi_cwmin = 1;
 1082                 while (qi->tqi_cwmin < cw)
 1083                         qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
 1084         } else
 1085                 qi->tqi_cwmin = qInfo->tqi_cwmin;
 1086         if (qInfo->tqi_cwmax != HAL_TXQ_USEDEFAULT) {
 1087                 cw = AH_MIN(qInfo->tqi_cwmax, 1024);
 1088                 /* make sure that the CWmax is of the form (2^n - 1) */
 1089                 qi->tqi_cwmax = 1;
 1090                 while (qi->tqi_cwmax < cw)
 1091                         qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
 1092         } else
 1093                 qi->tqi_cwmax = INIT_CWMAX;
 1094         /* Set retry limit values */
 1095         if (qInfo->tqi_shretry != 0)
 1096                 qi->tqi_shretry = AH_MIN(qInfo->tqi_shretry, 15);
 1097         else
 1098                 qi->tqi_shretry = INIT_SH_RETRY;
 1099         if (qInfo->tqi_lgretry != 0)
 1100                 qi->tqi_lgretry = AH_MIN(qInfo->tqi_lgretry, 15);
 1101         else
 1102                 qi->tqi_lgretry = INIT_LG_RETRY;
 1103         qi->tqi_cbrPeriod = qInfo->tqi_cbrPeriod;
 1104         qi->tqi_cbrOverflowLimit = qInfo->tqi_cbrOverflowLimit;
 1105         qi->tqi_burstTime = qInfo->tqi_burstTime;
 1106         qi->tqi_readyTime = qInfo->tqi_readyTime;
 1107 
 1108         switch (qInfo->tqi_subtype) {
 1109         case HAL_WME_UPSD:
 1110                 if (qi->tqi_type == HAL_TX_QUEUE_DATA)
 1111                         qi->tqi_intFlags = HAL_TXQ_USE_LOCKOUT_BKOFF_DIS;
 1112                 break;
 1113         default:
 1114                 break;          /* NB: silence compiler */
 1115         }
 1116         return AH_TRUE;
 1117 }
 1118 
 1119 HAL_BOOL
 1120 ath_hal_getTxQProps(struct ath_hal *ah,
 1121         HAL_TXQ_INFO *qInfo, const HAL_TX_QUEUE_INFO *qi)
 1122 {
 1123         if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) {
 1124                 HALDEBUG(ah, HAL_DEBUG_TXQUEUE,
 1125                     "%s: inactive queue\n", __func__);
 1126                 return AH_FALSE;
 1127         }
 1128 
 1129         qInfo->tqi_ver = qi->tqi_ver;
 1130         qInfo->tqi_subtype = qi->tqi_subtype;
 1131         qInfo->tqi_qflags = qi->tqi_qflags;
 1132         qInfo->tqi_priority = qi->tqi_priority;
 1133         qInfo->tqi_aifs = qi->tqi_aifs;
 1134         qInfo->tqi_cwmin = qi->tqi_cwmin;
 1135         qInfo->tqi_cwmax = qi->tqi_cwmax;
 1136         qInfo->tqi_shretry = qi->tqi_shretry;
 1137         qInfo->tqi_lgretry = qi->tqi_lgretry;
 1138         qInfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
 1139         qInfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
 1140         qInfo->tqi_burstTime = qi->tqi_burstTime;
 1141         qInfo->tqi_readyTime = qi->tqi_readyTime;
 1142         qInfo->tqi_compBuf = qi->tqi_physCompBuf;
 1143         return AH_TRUE;
 1144 }
 1145 
 1146                                      /* 11a Turbo  11b  11g  108g */
 1147 static const int16_t NOISE_FLOOR[] = { -96, -93,  -98, -96,  -93 };
 1148 
 1149 /*
 1150  * Read the current channel noise floor and return.
 1151  * If nf cal hasn't finished, channel noise floor should be 0
 1152  * and we return a nominal value based on band and frequency.
 1153  *
 1154  * NB: This is a private routine used by per-chip code to
 1155  *     implement the ah_getChanNoise method.
 1156  */
 1157 int16_t
 1158 ath_hal_getChanNoise(struct ath_hal *ah, const struct ieee80211_channel *chan)
 1159 {
 1160         HAL_CHANNEL_INTERNAL *ichan;
 1161 
 1162         ichan = ath_hal_checkchannel(ah, chan);
 1163         if (ichan == AH_NULL) {
 1164                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
 1165                     "%s: invalid channel %u/0x%x; no mapping\n",
 1166                     __func__, chan->ic_freq, chan->ic_flags);
 1167                 return 0;
 1168         }
 1169         if (ichan->rawNoiseFloor == 0) {
 1170                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
 1171 
 1172                 HALASSERT(mode < WIRELESS_MODE_MAX);
 1173                 return NOISE_FLOOR[mode] + ath_hal_getNfAdjust(ah, ichan);
 1174         } else
 1175                 return ichan->rawNoiseFloor + ichan->noiseFloorAdjust;
 1176 }
 1177 
 1178 /*
 1179  * Fetch the current setup of ctl/ext noise floor values.
 1180  *
 1181  * If the CHANNEL_MIMO_NF_VALID flag isn't set, the array is simply
 1182  * populated with values from NOISE_FLOOR[] + ath_hal_getNfAdjust().
 1183  *
 1184  * The caller must supply ctl/ext NF arrays which are at least
 1185  * AH_MAX_CHAINS entries long.
 1186  */
 1187 int
 1188 ath_hal_get_mimo_chan_noise(struct ath_hal *ah,
 1189     const struct ieee80211_channel *chan, int16_t *nf_ctl,
 1190     int16_t *nf_ext)
 1191 {
 1192         HAL_CHANNEL_INTERNAL *ichan;
 1193         int i;
 1194 
 1195         ichan = ath_hal_checkchannel(ah, chan);
 1196         if (ichan == AH_NULL) {
 1197                 HALDEBUG(ah, HAL_DEBUG_NFCAL,
 1198                     "%s: invalid channel %u/0x%x; no mapping\n",
 1199                     __func__, chan->ic_freq, chan->ic_flags);
 1200                 for (i = 0; i < AH_MAX_CHAINS; i++) {
 1201                         nf_ctl[i] = nf_ext[i] = 0;
 1202                 }
 1203                 return 0;
 1204         }
 1205 
 1206         /* Return 0 if there's no valid MIMO values (yet) */
 1207         if (! (ichan->privFlags & CHANNEL_MIMO_NF_VALID)) {
 1208                 for (i = 0; i < AH_MAX_CHAINS; i++) {
 1209                         nf_ctl[i] = nf_ext[i] = 0;
 1210                 }
 1211                 return 0;
 1212         }
 1213         if (ichan->rawNoiseFloor == 0) {
 1214                 WIRELESS_MODE mode = ath_hal_chan2wmode(ah, chan);
 1215                 HALASSERT(mode < WIRELESS_MODE_MAX);
 1216                 /*
 1217                  * See the comment below - this could cause issues for
 1218                  * stations which have a very low RSSI, below the
 1219                  * 'normalised' NF values in NOISE_FLOOR[].
 1220                  */
 1221                 for (i = 0; i < AH_MAX_CHAINS; i++) {
 1222                         nf_ctl[i] = nf_ext[i] = NOISE_FLOOR[mode] +
 1223                             ath_hal_getNfAdjust(ah, ichan);
 1224                 }
 1225                 return 1;
 1226         } else {
 1227                 /*
 1228                  * The value returned here from a MIMO radio is presumed to be
 1229                  * "good enough" as a NF calculation. As RSSI values are calculated
 1230                  * against this, an adjusted NF may be higher than the RSSI value
 1231                  * returned from a vary weak station, resulting in an obscenely
 1232                  * high signal strength calculation being returned.
 1233                  *
 1234                  * This should be re-evaluated at a later date, along with any
 1235                  * signal strength calculations which are made. Quite likely the
 1236                  * RSSI values will need to be adjusted to ensure the calculations
 1237                  * don't "wrap" when RSSI is less than the "adjusted" NF value.
 1238                  * ("Adjust" here is via ichan->noiseFloorAdjust.)
 1239                  */
 1240                 for (i = 0; i < AH_MAX_CHAINS; i++) {
 1241                         nf_ctl[i] = ichan->noiseFloorCtl[i] + ath_hal_getNfAdjust(ah, ichan);
 1242                         nf_ext[i] = ichan->noiseFloorExt[i] + ath_hal_getNfAdjust(ah, ichan);
 1243                 }
 1244                 return 1;
 1245         }
 1246 }
 1247 
 1248 /*
 1249  * Process all valid raw noise floors into the dBm noise floor values.
 1250  * Though our device has no reference for a dBm noise floor, we perform
 1251  * a relative minimization of NF's based on the lowest NF found across a
 1252  * channel scan.
 1253  */
 1254 void
 1255 ath_hal_process_noisefloor(struct ath_hal *ah)
 1256 {
 1257         HAL_CHANNEL_INTERNAL *c;
 1258         int16_t correct2, correct5;
 1259         int16_t lowest2, lowest5;
 1260         int i;
 1261 
 1262         /* 
 1263          * Find the lowest 2GHz and 5GHz noise floor values after adjusting
 1264          * for statistically recorded NF/channel deviation.
 1265          */
 1266         correct2 = lowest2 = 0;
 1267         correct5 = lowest5 = 0;
 1268         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
 1269                 WIRELESS_MODE mode;
 1270                 int16_t nf;
 1271 
 1272                 c = &AH_PRIVATE(ah)->ah_channels[i];
 1273                 if (c->rawNoiseFloor >= 0)
 1274                         continue;
 1275                 /* XXX can't identify proper mode */
 1276                 mode = IS_CHAN_5GHZ(c) ? WIRELESS_MODE_11a : WIRELESS_MODE_11g;
 1277                 nf = c->rawNoiseFloor + NOISE_FLOOR[mode] +
 1278                         ath_hal_getNfAdjust(ah, c);
 1279                 if (IS_CHAN_5GHZ(c)) {
 1280                         if (nf < lowest5) { 
 1281                                 lowest5 = nf;
 1282                                 correct5 = NOISE_FLOOR[mode] -
 1283                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
 1284                         }
 1285                 } else {
 1286                         if (nf < lowest2) { 
 1287                                 lowest2 = nf;
 1288                                 correct2 = NOISE_FLOOR[mode] -
 1289                                     (c->rawNoiseFloor + ath_hal_getNfAdjust(ah, c));
 1290                         }
 1291                 }
 1292         }
 1293 
 1294         /* Correct the channels to reach the expected NF value */
 1295         for (i = 0; i < AH_PRIVATE(ah)->ah_nchan; i++) {
 1296                 c = &AH_PRIVATE(ah)->ah_channels[i];
 1297                 if (c->rawNoiseFloor >= 0)
 1298                         continue;
 1299                 /* Apply correction factor */
 1300                 c->noiseFloorAdjust = ath_hal_getNfAdjust(ah, c) +
 1301                         (IS_CHAN_5GHZ(c) ? correct5 : correct2);
 1302                 HALDEBUG(ah, HAL_DEBUG_NFCAL, "%u raw nf %d adjust %d\n",
 1303                     c->channel, c->rawNoiseFloor, c->noiseFloorAdjust);
 1304         }
 1305 }
 1306 
 1307 /*
 1308  * INI support routines.
 1309  */
 1310 
 1311 int
 1312 ath_hal_ini_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
 1313         int col, int regWr)
 1314 {
 1315         int r;
 1316 
 1317         HALASSERT(col < ia->cols);
 1318         for (r = 0; r < ia->rows; r++) {
 1319                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0),
 1320                     HAL_INI_VAL(ia, r, col));
 1321 
 1322                 /* Analog shift register delay seems needed for Merlin - PR kern/154220 */
 1323                 if (HAL_INI_VAL(ia, r, 0) >= 0x7800 && HAL_INI_VAL(ia, r, 0) < 0x7900)
 1324                         OS_DELAY(100);
 1325 
 1326                 DMA_YIELD(regWr);
 1327         }
 1328         return regWr;
 1329 }
 1330 
 1331 void
 1332 ath_hal_ini_bank_setup(uint32_t data[], const HAL_INI_ARRAY *ia, int col)
 1333 {
 1334         int r;
 1335 
 1336         HALASSERT(col < ia->cols);
 1337         for (r = 0; r < ia->rows; r++)
 1338                 data[r] = HAL_INI_VAL(ia, r, col);
 1339 }
 1340 
 1341 int
 1342 ath_hal_ini_bank_write(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
 1343         const uint32_t data[], int regWr)
 1344 {
 1345         int r;
 1346 
 1347         for (r = 0; r < ia->rows; r++) {
 1348                 OS_REG_WRITE(ah, HAL_INI_VAL(ia, r, 0), data[r]);
 1349                 DMA_YIELD(regWr);
 1350         }
 1351         return regWr;
 1352 }
 1353 
 1354 /*
 1355  * These are EEPROM board related routines which should likely live in
 1356  * a helper library of some sort.
 1357  */
 1358 
 1359 /**************************************************************
 1360  * ath_ee_getLowerUppderIndex
 1361  *
 1362  * Return indices surrounding the value in sorted integer lists.
 1363  * Requirement: the input list must be monotonically increasing
 1364  *     and populated up to the list size
 1365  * Returns: match is set if an index in the array matches exactly
 1366  *     or a the target is before or after the range of the array.
 1367  */
 1368 HAL_BOOL
 1369 ath_ee_getLowerUpperIndex(uint8_t target, uint8_t *pList, uint16_t listSize,
 1370                    uint16_t *indexL, uint16_t *indexR)
 1371 {
 1372     uint16_t i;
 1373 
 1374     /*
 1375      * Check first and last elements for beyond ordered array cases.
 1376      */
 1377     if (target <= pList[0]) {
 1378         *indexL = *indexR = 0;
 1379         return AH_TRUE;
 1380     }
 1381     if (target >= pList[listSize-1]) {
 1382         *indexL = *indexR = (uint16_t)(listSize - 1);
 1383         return AH_TRUE;
 1384     }
 1385 
 1386     /* look for value being near or between 2 values in list */
 1387     for (i = 0; i < listSize - 1; i++) {
 1388         /*
 1389          * If value is close to the current value of the list
 1390          * then target is not between values, it is one of the values
 1391          */
 1392         if (pList[i] == target) {
 1393             *indexL = *indexR = i;
 1394             return AH_TRUE;
 1395         }
 1396         /*
 1397          * Look for value being between current value and next value
 1398          * if so return these 2 values
 1399          */
 1400         if (target < pList[i + 1]) {
 1401             *indexL = i;
 1402             *indexR = (uint16_t)(i + 1);
 1403             return AH_FALSE;
 1404         }
 1405     }
 1406     HALASSERT(0);
 1407     *indexL = *indexR = 0;
 1408     return AH_FALSE;
 1409 }
 1410 
 1411 /**************************************************************
 1412  * ath_ee_FillVpdTable
 1413  *
 1414  * Fill the Vpdlist for indices Pmax-Pmin
 1415  * Note: pwrMin, pwrMax and Vpdlist are all in dBm * 4
 1416  */
 1417 HAL_BOOL
 1418 ath_ee_FillVpdTable(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
 1419                    uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
 1420 {
 1421     uint16_t  i, k;
 1422     uint8_t   currPwr = pwrMin;
 1423     uint16_t  idxL, idxR;
 1424 
 1425     HALASSERT(pwrMax > pwrMin);
 1426     for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
 1427         ath_ee_getLowerUpperIndex(currPwr, pPwrList, numIntercepts,
 1428                            &(idxL), &(idxR));
 1429         if (idxR < 1)
 1430             idxR = 1;           /* extrapolate below */
 1431         if (idxL == numIntercepts - 1)
 1432             idxL = (uint16_t)(numIntercepts - 2);   /* extrapolate above */
 1433         if (pPwrList[idxL] == pPwrList[idxR])
 1434             k = pVpdList[idxL];
 1435         else
 1436             k = (uint16_t)( ((currPwr - pPwrList[idxL]) * pVpdList[idxR] + (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
 1437                   (pPwrList[idxR] - pPwrList[idxL]) );
 1438         HALASSERT(k < 256);
 1439         pRetVpdList[i] = (uint8_t)k;
 1440         currPwr += 2;               /* half dB steps */
 1441     }
 1442 
 1443     return AH_TRUE;
 1444 }
 1445 
 1446 /**************************************************************************
 1447  * ath_ee_interpolate
 1448  *
 1449  * Returns signed interpolated or the scaled up interpolated value
 1450  */
 1451 int16_t
 1452 ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
 1453             int16_t targetLeft, int16_t targetRight)
 1454 {
 1455     int16_t rv;
 1456 
 1457     if (srcRight == srcLeft) {
 1458         rv = targetLeft;
 1459     } else {
 1460         rv = (int16_t)( ((target - srcLeft) * targetRight +
 1461               (srcRight - target) * targetLeft) / (srcRight - srcLeft) );
 1462     }
 1463     return rv;
 1464 }
 1465 
 1466 /*
 1467  * Adjust the TSF.
 1468  */
 1469 void
 1470 ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
 1471 {
 1472         /* XXX handle wrap/overflow */
 1473         OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
 1474 }
 1475 
 1476 /*
 1477  * Enable or disable CCA.
 1478  */
 1479 void
 1480 ath_hal_setcca(struct ath_hal *ah, int ena)
 1481 {
 1482         /*
 1483          * NB: fill me in; this is not provided by default because disabling
 1484          *     CCA in most locales violates regulatory.
 1485          */
 1486 }
 1487 
 1488 /*
 1489  * Get CCA setting.
 1490  *
 1491  * XXX TODO: turn this and the above function into methods
 1492  * in case there are chipset differences in handling CCA.
 1493  */
 1494 int
 1495 ath_hal_getcca(struct ath_hal *ah)
 1496 {
 1497         u_int32_t diag;
 1498         if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
 1499                 return 1;
 1500         return ((diag & 0x500000) == 0);
 1501 }
 1502 
 1503 /*
 1504  * Set the current state of self-generated ACK and RTS/CTS frames.
 1505  *
 1506  * For correct DFS operation, the device should not even /ACK/ frames
 1507  * that are sent to it during CAC or CSA.
 1508  */
 1509 void
 1510 ath_hal_set_dfs_cac_tx_quiet(struct ath_hal *ah, HAL_BOOL ena)
 1511 {
 1512 
 1513         if (ah->ah_setDfsCacTxQuiet == NULL)
 1514                 return;
 1515         ah->ah_setDfsCacTxQuiet(ah, ena);
 1516 }
 1517 
 1518 /*
 1519  * This routine is only needed when supporting EEPROM-in-RAM setups
 1520  * (eg embedded SoCs and on-board PCI/PCIe devices.)
 1521  */
 1522 /* NB: This is in 16 bit words; not bytes */
 1523 /* XXX This doesn't belong here!  */
 1524 #define ATH_DATA_EEPROM_SIZE    2048
 1525 
 1526 HAL_BOOL
 1527 ath_hal_EepromDataRead(struct ath_hal *ah, u_int off, uint16_t *data)
 1528 {
 1529         if (ah->ah_eepromdata == AH_NULL) {
 1530                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: no eeprom data!\n", __func__);
 1531                 return AH_FALSE;
 1532         }
 1533         if (off > ATH_DATA_EEPROM_SIZE) {
 1534                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: offset %x > %x\n",
 1535                     __func__, off, ATH_DATA_EEPROM_SIZE);
 1536                 return AH_FALSE;
 1537         }
 1538         (*data) = ah->ah_eepromdata[off];
 1539         return AH_TRUE;
 1540 }
 1541 
 1542 /*
 1543  * Do a 2GHz specific MHz->IEEE based on the hardware
 1544  * frequency.
 1545  *
 1546  * This is the unmapped frequency which is programmed into the hardware.
 1547  */
 1548 int
 1549 ath_hal_mhz2ieee_2ghz(struct ath_hal *ah, int freq)
 1550 {
 1551 
 1552         if (freq == 2484)
 1553                 return 14;
 1554         if (freq < 2484)
 1555                 return ((int) freq - 2407) / 5;
 1556         else
 1557                 return 15 + ((freq - 2512) / 20);
 1558 }
 1559 
 1560 /*
 1561  * Clear the current survey data.
 1562  *
 1563  * This should be done during a channel change.
 1564  */
 1565 void
 1566 ath_hal_survey_clear(struct ath_hal *ah)
 1567 {
 1568 
 1569         OS_MEMZERO(&AH_PRIVATE(ah)->ah_chansurvey,
 1570             sizeof(AH_PRIVATE(ah)->ah_chansurvey));
 1571 }
 1572 
 1573 /*
 1574  * Add a sample to the channel survey.
 1575  */
 1576 void
 1577 ath_hal_survey_add_sample(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hs)
 1578 {
 1579         HAL_CHANNEL_SURVEY *cs;
 1580 
 1581         cs = &AH_PRIVATE(ah)->ah_chansurvey;
 1582 
 1583         OS_MEMCPY(&cs->samples[cs->cur_sample], hs, sizeof(*hs));
 1584         cs->samples[cs->cur_sample].seq_num = cs->cur_seq;
 1585         cs->cur_sample = (cs->cur_sample + 1) % CHANNEL_SURVEY_SAMPLE_COUNT;
 1586         cs->cur_seq++;
 1587 }

Cache object: fc0becf25574eafec6891ef87bb8960a


[ 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.