Annotation of sys/dev/ic/ar5xxx.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ar5xxx.c,v 1.42 2007/06/26 10:53:01 tom Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
! 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: * HAL interface for Atheros Wireless LAN devices.
! 21: * (Please have a look at ar5xxx.h for further information)
! 22: */
! 23:
! 24: #include <dev/pci/pcidevs.h>
! 25: #include <dev/ic/ar5xxx.h>
! 26:
! 27: extern ar5k_attach_t ar5k_ar5210_attach;
! 28: extern ar5k_attach_t ar5k_ar5211_attach;
! 29: extern ar5k_attach_t ar5k_ar5212_attach;
! 30:
! 31: static const struct {
! 32: u_int16_t vendor;
! 33: u_int16_t device;
! 34: ar5k_attach_t (*attach);
! 35: } ar5k_known_products[] = {
! 36: /*
! 37: * From pcidevs_data.h
! 38: */
! 39: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210,
! 40: ar5k_ar5210_attach },
! 41: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_AP,
! 42: ar5k_ar5210_attach },
! 43: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT,
! 44: ar5k_ar5210_attach },
! 45: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211,
! 46: ar5k_ar5211_attach },
! 47: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_DEFAULT,
! 48: ar5k_ar5211_attach },
! 49: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5311,
! 50: ar5k_ar5211_attach },
! 51: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_FPGA11B,
! 52: ar5k_ar5211_attach },
! 53: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_LEGACY,
! 54: ar5k_ar5211_attach },
! 55: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212,
! 56: ar5k_ar5212_attach },
! 57: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_DEFAULT,
! 58: ar5k_ar5212_attach },
! 59: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_FPGA,
! 60: ar5k_ar5212_attach },
! 61: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_IBM,
! 62: ar5k_ar5212_attach },
! 63: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2413,
! 64: ar5k_ar5212_attach },
! 65: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5413,
! 66: ar5k_ar5212_attach },
! 67: { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5424,
! 68: ar5k_ar5212_attach },
! 69: { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRDAG675,
! 70: ar5k_ar5212_attach },
! 71: { PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175,
! 72: ar5k_ar5212_attach }
! 73: };
! 74:
! 75: static const HAL_RATE_TABLE ar5k_rt_11a = AR5K_RATES_11A;
! 76: static const HAL_RATE_TABLE ar5k_rt_11b = AR5K_RATES_11B;
! 77: static const HAL_RATE_TABLE ar5k_rt_11g = AR5K_RATES_11G;
! 78: static const HAL_RATE_TABLE ar5k_rt_turbo = AR5K_RATES_TURBO;
! 79: static const HAL_RATE_TABLE ar5k_rt_xr = AR5K_RATES_XR;
! 80:
! 81: int ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int);
! 82: int ar5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, u_int);
! 83: u_int16_t ar5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, u_int);
! 84:
! 85: HAL_BOOL ar5k_ar5110_channel(struct ath_hal *, HAL_CHANNEL *);
! 86: u_int32_t ar5k_ar5110_chan2athchan(HAL_CHANNEL *);
! 87: HAL_BOOL ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);
! 88: HAL_BOOL ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);
! 89: HAL_BOOL ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);
! 90: HAL_BOOL ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);
! 91:
! 92: HAL_BOOL ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
! 93: HAL_BOOL ar5k_ar5112_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);
! 94: u_int ar5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, u_int32_t,
! 95: u_int32_t, u_int32_t, HAL_BOOL);
! 96:
! 97: /*
! 98: * Supported channels
! 99: */
! 100: static const struct
! 101: ieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;
! 102: static const struct
! 103: ieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;
! 104:
! 105: /*
! 106: * Initial gain optimization values
! 107: */
! 108: static const struct ar5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;
! 109: static const struct ar5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;
! 110:
! 111: /*
! 112: * Initial register for the radio chipsets
! 113: */
! 114: static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;
! 115: static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;
! 116: static const struct ar5k_ini_rf ar5112a_rf[] = AR5K_AR5112A_INI_RF;
! 117: static const struct ar5k_ini_rfgain ar5k_rfg[] = AR5K_INI_RFGAIN;
! 118:
! 119: /*
! 120: * Enable to overwrite the country code (use "00" for debug)
! 121: */
! 122: #if 0
! 123: #define COUNTRYCODE "00"
! 124: #endif
! 125:
! 126: /*
! 127: * Perform a lookup if the device is supported by the HAL
! 128: */
! 129: const char *
! 130: ath_hal_probe(u_int16_t vendor, u_int16_t device)
! 131: {
! 132: int i;
! 133:
! 134: /*
! 135: * Perform a linear search on the table of supported devices
! 136: */
! 137: for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
! 138: if (vendor == ar5k_known_products[i].vendor &&
! 139: device == ar5k_known_products[i].device)
! 140: return ("");
! 141: }
! 142:
! 143: return (NULL);
! 144: }
! 145:
! 146: /*
! 147: * Fills in the HAL structure and initialises the device
! 148: */
! 149: struct ath_hal *
! 150: ath_hal_attach(u_int16_t device, void *arg, bus_space_tag_t st,
! 151: bus_space_handle_t sh, u_int is_64bit, int *status)
! 152: {
! 153: struct ath_softc *sc = (struct ath_softc *)arg;
! 154: struct ath_hal *hal = NULL;
! 155: ar5k_attach_t *attach = NULL;
! 156: u_int8_t mac[IEEE80211_ADDR_LEN];
! 157: int i;
! 158:
! 159: *status = EINVAL;
! 160:
! 161: /*
! 162: * Call the chipset-dependent attach routine by device id
! 163: */
! 164: for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) {
! 165: if (device == ar5k_known_products[i].device &&
! 166: ar5k_known_products[i].attach != NULL)
! 167: attach = ar5k_known_products[i].attach;
! 168: }
! 169:
! 170: if (attach == NULL) {
! 171: *status = ENXIO;
! 172: AR5K_PRINTF("device not supported: 0x%04x\n", device);
! 173: return (NULL);
! 174: }
! 175:
! 176: if ((hal = malloc(sizeof(struct ath_hal),
! 177: M_DEVBUF, M_NOWAIT)) == NULL) {
! 178: *status = ENOMEM;
! 179: AR5K_PRINT("out of memory\n");
! 180: return (NULL);
! 181: }
! 182:
! 183: bzero(hal, sizeof(struct ath_hal));
! 184:
! 185: hal->ah_sc = sc;
! 186: hal->ah_st = st;
! 187: hal->ah_sh = sh;
! 188: hal->ah_device = device;
! 189: hal->ah_sub_vendor = 0; /* XXX unknown?! */
! 190:
! 191: /*
! 192: * HAL information
! 193: */
! 194: hal->ah_abi = HAL_ABI_VERSION;
! 195: hal->ah_op_mode = HAL_M_STA;
! 196: hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
! 197: hal->ah_turbo = AH_FALSE;
! 198: hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
! 199: hal->ah_imr = 0;
! 200: hal->ah_atim_window = 0;
! 201: hal->ah_aifs = AR5K_TUNE_AIFS;
! 202: hal->ah_cw_min = AR5K_TUNE_CWMIN;
! 203: hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
! 204: hal->ah_software_retry = AH_FALSE;
! 205: hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
! 206:
! 207: switch (device) {
! 208: case PCI_PRODUCT_ATHEROS_AR2413:
! 209: case PCI_PRODUCT_ATHEROS_AR5413:
! 210: case PCI_PRODUCT_ATHEROS_AR5424:
! 211: /*
! 212: * Known single chip solutions
! 213: */
! 214: hal->ah_single_chip = AH_TRUE;
! 215: break;
! 216: case PCI_PRODUCT_ATHEROS_AR5212_IBM:
! 217: /*
! 218: * IBM ThinkPads use the same device ID for different
! 219: * chipset versions. Ugh.
! 220: */
! 221: if (is_64bit) {
! 222: /*
! 223: * PCI Express "Mini Card" interface based on the
! 224: * AR5424 chipset
! 225: */
! 226: hal->ah_single_chip = AH_TRUE;
! 227: } else {
! 228: /* Classic Mini PCI interface based on AR5212 */
! 229: hal->ah_single_chip = AH_FALSE;
! 230: }
! 231: break;
! 232: default:
! 233: /*
! 234: * Multi chip solutions
! 235: */
! 236: hal->ah_single_chip = AH_FALSE;
! 237: break;
! 238: }
! 239:
! 240: if ((attach)(device, hal, st, sh, status) == NULL)
! 241: goto failed;
! 242:
! 243: #ifdef AR5K_DEBUG
! 244: hal->ah_dump_state(hal);
! 245: #endif
! 246:
! 247: /*
! 248: * Get card capabilities, values, ...
! 249: */
! 250:
! 251: if (ar5k_eeprom_init(hal) != 0) {
! 252: AR5K_PRINT("unable to init EEPROM\n");
! 253: goto failed;
! 254: }
! 255:
! 256: /* Get misc capabilities */
! 257: if (hal->ah_get_capabilities(hal) != AH_TRUE) {
! 258: AR5K_PRINTF("unable to get device capabilities: 0x%04x\n",
! 259: device);
! 260: goto failed;
! 261: }
! 262:
! 263: /* Get MAC address */
! 264: if ((*status = ar5k_eeprom_read_mac(hal, mac)) != 0) {
! 265: AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n",
! 266: device);
! 267: goto failed;
! 268: }
! 269:
! 270: hal->ah_set_lladdr(hal, mac);
! 271:
! 272: /* Get rate tables */
! 273: if (hal->ah_capabilities.cap_mode & HAL_MODE_11A)
! 274: ar5k_rt_copy(&hal->ah_rt_11a, &ar5k_rt_11a);
! 275: if (hal->ah_capabilities.cap_mode & HAL_MODE_11B)
! 276: ar5k_rt_copy(&hal->ah_rt_11b, &ar5k_rt_11b);
! 277: if (hal->ah_capabilities.cap_mode & HAL_MODE_11G)
! 278: ar5k_rt_copy(&hal->ah_rt_11g, &ar5k_rt_11g);
! 279: if (hal->ah_capabilities.cap_mode & HAL_MODE_TURBO)
! 280: ar5k_rt_copy(&hal->ah_rt_turbo, &ar5k_rt_turbo);
! 281: if (hal->ah_capabilities.cap_mode & HAL_MODE_XR)
! 282: ar5k_rt_copy(&hal->ah_rt_xr, &ar5k_rt_xr);
! 283:
! 284: /* Initialize the gain optimization values */
! 285: if (hal->ah_radio == AR5K_AR5111) {
! 286: hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default;
! 287: hal->ah_gain.g_step =
! 288: &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
! 289: hal->ah_gain.g_low = 20;
! 290: hal->ah_gain.g_high = 35;
! 291: hal->ah_gain.g_active = 1;
! 292: } else if (hal->ah_radio == AR5K_AR5112) {
! 293: hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default;
! 294: hal->ah_gain.g_step =
! 295: &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx];
! 296: hal->ah_gain.g_low = 20;
! 297: hal->ah_gain.g_high = 85;
! 298: hal->ah_gain.g_active = 1;
! 299: }
! 300:
! 301: *status = HAL_OK;
! 302:
! 303: return (hal);
! 304:
! 305: failed:
! 306: free(hal, M_DEVBUF);
! 307: return (NULL);
! 308: }
! 309:
! 310: u_int16_t
! 311: ath_hal_computetxtime(struct ath_hal *hal, const HAL_RATE_TABLE *rates,
! 312: u_int32_t frame_length, u_int16_t rate_index, HAL_BOOL short_preamble)
! 313: {
! 314: const HAL_RATE *rate;
! 315: u_int32_t value;
! 316:
! 317: AR5K_ASSERT_ENTRY(rate_index, rates->rateCount);
! 318:
! 319: /*
! 320: * Get rate by index
! 321: */
! 322: rate = &rates->info[rate_index];
! 323:
! 324: /*
! 325: * Calculate the transmission time by operation (PHY) mode
! 326: */
! 327: switch (rate->phy) {
! 328: case IEEE80211_T_CCK:
! 329: /*
! 330: * CCK / DS mode (802.11b)
! 331: */
! 332: value = AR5K_CCK_TX_TIME(rate->rateKbps, frame_length,
! 333: (short_preamble && rate->shortPreamble));
! 334: break;
! 335:
! 336: case IEEE80211_T_OFDM:
! 337: /*
! 338: * Orthogonal Frequency Division Multiplexing
! 339: */
! 340: if (AR5K_OFDM_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
! 341: return (0);
! 342: value = AR5K_OFDM_TX_TIME(rate->rateKbps, frame_length);
! 343: break;
! 344:
! 345: case IEEE80211_T_TURBO:
! 346: /*
! 347: * Orthogonal Frequency Division Multiplexing
! 348: * Atheros "Turbo Mode" (doubled rates)
! 349: */
! 350: if (AR5K_TURBO_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
! 351: return (0);
! 352: value = AR5K_TURBO_TX_TIME(rate->rateKbps, frame_length);
! 353: break;
! 354:
! 355: case IEEE80211_T_XR:
! 356: /*
! 357: * Orthogonal Frequency Division Multiplexing
! 358: * Atheros "eXtended Range" (XR)
! 359: */
! 360: if (AR5K_XR_NUM_BITS_PER_SYM(rate->rateKbps) == 0)
! 361: return (0);
! 362: value = AR5K_XR_TX_TIME(rate->rateKbps, frame_length);
! 363: break;
! 364:
! 365: default:
! 366: return (0);
! 367: }
! 368:
! 369: return (value);
! 370: }
! 371:
! 372: HAL_BOOL
! 373: ar5k_check_channel(struct ath_hal *hal, u_int16_t freq, u_int flags)
! 374: {
! 375: /* Check if the channel is in our supported range */
! 376: if (flags & IEEE80211_CHAN_2GHZ) {
! 377: if ((freq >= hal->ah_capabilities.cap_range.range_2ghz_min) &&
! 378: (freq <= hal->ah_capabilities.cap_range.range_2ghz_max))
! 379: return (AH_TRUE);
! 380: } else if (flags & IEEE80211_CHAN_5GHZ) {
! 381: if ((freq >= hal->ah_capabilities.cap_range.range_5ghz_min) &&
! 382: (freq <= hal->ah_capabilities.cap_range.range_5ghz_max))
! 383: return (AH_TRUE);
! 384: }
! 385:
! 386: return (AH_FALSE);
! 387: }
! 388:
! 389: HAL_BOOL
! 390: ath_hal_init_channels(struct ath_hal *hal, HAL_CHANNEL *channels,
! 391: u_int max_channels, u_int *channels_size, u_int16_t mode,
! 392: HAL_BOOL outdoor, HAL_BOOL extended)
! 393: {
! 394: u_int i, c;
! 395: u_int32_t domain_current;
! 396: u_int domain_5ghz, domain_2ghz;
! 397: HAL_CHANNEL *all_channels;
! 398:
! 399: if ((all_channels = malloc(sizeof(HAL_CHANNEL) * max_channels,
! 400: M_TEMP, M_NOWAIT)) == NULL)
! 401: return (AH_FALSE);
! 402:
! 403: i = c = 0;
! 404: domain_current = hal->ah_regdomain;
! 405:
! 406: /*
! 407: * In debugging mode, enable all channels supported by the chipset
! 408: */
! 409: if (domain_current == DMN_DEFAULT) {
! 410: int min, max, freq;
! 411: u_int flags;
! 412:
! 413: min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MIN,
! 414: IEEE80211_CHAN_2GHZ);
! 415: max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MAX,
! 416: IEEE80211_CHAN_2GHZ);
! 417: flags = CHANNEL_B | CHANNEL_TG |
! 418: (hal->ah_version == AR5K_AR5211 ?
! 419: CHANNEL_PUREG : CHANNEL_G);
! 420:
! 421: debugchan:
! 422: for (i = min; i <= max && c < max_channels; i++) {
! 423: freq = ieee80211_ieee2mhz(i, flags);
! 424: if (ar5k_check_channel(hal, freq, flags) == AH_FALSE)
! 425: continue;
! 426: all_channels[c].c_channel = freq;
! 427: all_channels[c++].c_channel_flags = flags;
! 428: }
! 429:
! 430: if (flags & IEEE80211_CHAN_2GHZ) {
! 431: min = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MIN,
! 432: IEEE80211_CHAN_5GHZ);
! 433: max = ieee80211_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MAX,
! 434: IEEE80211_CHAN_5GHZ);
! 435: flags = CHANNEL_A | CHANNEL_T | CHANNEL_XR;
! 436: goto debugchan;
! 437: }
! 438:
! 439: goto done;
! 440: }
! 441:
! 442: domain_5ghz = ieee80211_regdomain2flag(domain_current,
! 443: IEEE80211_CHANNELS_5GHZ_MIN);
! 444: domain_2ghz = ieee80211_regdomain2flag(domain_current,
! 445: IEEE80211_CHANNELS_2GHZ_MIN);
! 446:
! 447: /*
! 448: * Create channel list based on chipset capabilities, regulation domain
! 449: * and mode. 5GHz...
! 450: */
! 451: for (i = 0; (hal->ah_capabilities.cap_range.range_5ghz_max > 0) &&
! 452: (i < AR5K_ELEMENTS(ar5k_5ghz_channels)) &&
! 453: (c < max_channels); i++) {
! 454: /* Check if channel is supported by the chipset */
! 455: if (ar5k_check_channel(hal,
! 456: ar5k_5ghz_channels[i].rc_channel,
! 457: IEEE80211_CHAN_5GHZ) == AH_FALSE)
! 458: continue;
! 459:
! 460: /* Match regulation domain */
! 461: if ((IEEE80211_DMN(ar5k_5ghz_channels[i].rc_domain) &
! 462: IEEE80211_DMN(domain_5ghz)) == 0)
! 463: continue;
! 464:
! 465: /* Match modes */
! 466: if (ar5k_5ghz_channels[i].rc_mode & IEEE80211_CHAN_TURBO) {
! 467: all_channels[c].c_channel_flags = CHANNEL_T;
! 468: } else if (ar5k_5ghz_channels[i].rc_mode &
! 469: IEEE80211_CHAN_OFDM) {
! 470: all_channels[c].c_channel_flags = CHANNEL_A;
! 471: } else
! 472: continue;
! 473:
! 474: /* Write channel and increment counter */
! 475: all_channels[c++].channel = ar5k_5ghz_channels[i].rc_channel;
! 476: }
! 477:
! 478: /*
! 479: * ...and 2GHz.
! 480: */
! 481: for (i = 0; (hal->ah_capabilities.cap_range.range_2ghz_max > 0) &&
! 482: (i < AR5K_ELEMENTS(ar5k_2ghz_channels)) &&
! 483: (c < max_channels); i++) {
! 484: /* Check if channel is supported by the chipset */
! 485: if (ar5k_check_channel(hal,
! 486: ar5k_2ghz_channels[i].rc_channel,
! 487: IEEE80211_CHAN_2GHZ) == AH_FALSE)
! 488: continue;
! 489:
! 490: /* Match regulation domain */
! 491: if ((IEEE80211_DMN(ar5k_2ghz_channels[i].rc_domain) &
! 492: IEEE80211_DMN(domain_2ghz)) == 0)
! 493: continue;
! 494:
! 495: /* Match modes */
! 496: if ((hal->ah_capabilities.cap_mode & HAL_MODE_11B) &&
! 497: (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_CCK))
! 498: all_channels[c].c_channel_flags = CHANNEL_B;
! 499:
! 500: if ((hal->ah_capabilities.cap_mode & HAL_MODE_11G) &&
! 501: (ar5k_2ghz_channels[i].rc_mode & IEEE80211_CHAN_OFDM)) {
! 502: all_channels[c].c_channel_flags |=
! 503: hal->ah_version == AR5K_AR5211 ?
! 504: CHANNEL_PUREG : CHANNEL_G;
! 505: if (ar5k_2ghz_channels[i].rc_mode &
! 506: IEEE80211_CHAN_TURBO)
! 507: all_channels[c].c_channel_flags |= CHANNEL_TG;
! 508: }
! 509:
! 510: /* Write channel and increment counter */
! 511: all_channels[c++].channel = ar5k_2ghz_channels[i].rc_channel;
! 512: }
! 513:
! 514: done:
! 515: bcopy(all_channels, channels, sizeof(HAL_CHANNEL) * max_channels);
! 516: *channels_size = c;
! 517: free(all_channels, M_TEMP);
! 518: return (AH_TRUE);
! 519: }
! 520:
! 521: /*
! 522: * Common internal functions
! 523: */
! 524:
! 525: const char *
! 526: ar5k_printver(enum ar5k_srev_type type, u_int32_t val)
! 527: {
! 528: struct ar5k_srev_name names[] = AR5K_SREV_NAME;
! 529: const char *name = "xxxx";
! 530: int i;
! 531:
! 532: for (i = 0; i < AR5K_ELEMENTS(names); i++) {
! 533: if (type == AR5K_VERSION_DEV) {
! 534: if (names[i].sr_type == type &&
! 535: names[i].sr_val == val) {
! 536: name = names[i].sr_name;
! 537: break;
! 538: }
! 539: continue;
! 540: }
! 541: if (names[i].sr_type != type ||
! 542: names[i].sr_val == AR5K_SREV_UNKNOWN)
! 543: continue;
! 544: if ((val & 0xff) < names[i + 1].sr_val) {
! 545: name = names[i].sr_name;
! 546: break;
! 547: }
! 548: }
! 549:
! 550: return (name);
! 551: }
! 552:
! 553: void
! 554: ar5k_radar_alert(struct ath_hal *hal)
! 555: {
! 556: /*
! 557: * Limit ~1/s
! 558: */
! 559: if (hal->ah_radar.r_last_channel.channel ==
! 560: hal->ah_current_channel.channel &&
! 561: tick < (hal->ah_radar.r_last_alert + hz))
! 562: return;
! 563:
! 564: hal->ah_radar.r_last_channel.channel =
! 565: hal->ah_current_channel.channel;
! 566: hal->ah_radar.r_last_channel.c_channel_flags =
! 567: hal->ah_current_channel.c_channel_flags;
! 568: hal->ah_radar.r_last_alert = tick;
! 569:
! 570: AR5K_PRINTF("Possible radar activity detected at %u MHz (tick %u)\n",
! 571: hal->ah_radar.r_last_alert, hal->ah_current_channel.channel);
! 572: }
! 573:
! 574: u_int16_t
! 575: ar5k_regdomain_from_ieee(ieee80211_regdomain_t ieee)
! 576: {
! 577: u_int32_t regdomain = (u_int32_t)ieee;
! 578:
! 579: /*
! 580: * Use the default regulation domain if the value is empty
! 581: * or not supported by the net80211 regulation code.
! 582: */
! 583: if (ieee80211_regdomain2flag(regdomain,
! 584: IEEE80211_CHANNELS_5GHZ_MIN) == DMN_DEBUG)
! 585: return ((u_int16_t)AR5K_TUNE_REGDOMAIN);
! 586:
! 587: /* It is supported, just return the value */
! 588: return (regdomain);
! 589: }
! 590:
! 591: ieee80211_regdomain_t
! 592: ar5k_regdomain_to_ieee(u_int16_t regdomain)
! 593: {
! 594: ieee80211_regdomain_t ieee = (ieee80211_regdomain_t)regdomain;
! 595:
! 596: return (ieee);
! 597: }
! 598:
! 599: u_int16_t
! 600: ar5k_get_regdomain(struct ath_hal *hal)
! 601: {
! 602: u_int16_t regdomain;
! 603: ieee80211_regdomain_t ieee_regdomain;
! 604: #ifdef COUNTRYCODE
! 605: u_int16_t code;
! 606: #endif
! 607:
! 608: ar5k_eeprom_regulation_domain(hal, AH_FALSE, &ieee_regdomain);
! 609: hal->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
! 610:
! 611: #ifdef COUNTRYCODE
! 612: /*
! 613: * Get the regulation domain by country code. This will ignore
! 614: * the settings found in the EEPROM.
! 615: */
! 616: code = ieee80211_name2countrycode(COUNTRYCODE);
! 617: ieee_regdomain = ieee80211_countrycode2regdomain(code);
! 618: #endif
! 619:
! 620: regdomain = ar5k_regdomain_from_ieee(ieee_regdomain);
! 621: hal->ah_capabilities.cap_regdomain.reg_current = regdomain;
! 622:
! 623: return (regdomain);
! 624: }
! 625:
! 626: u_int32_t
! 627: ar5k_bitswap(u_int32_t val, u_int bits)
! 628: {
! 629: if (bits == 8) {
! 630: val = ((val & 0xF0) >> 4) | ((val & 0x0F) << 4);
! 631: val = ((val & 0xCC) >> 2) | ((val & 0x33) << 2);
! 632: val = ((val & 0xAA) >> 1) | ((val & 0x55) << 1);
! 633:
! 634: return val;
! 635: } else {
! 636: u_int32_t retval = 0, bit, i;
! 637:
! 638: for (i = 0; i < bits; i++) {
! 639: bit = (val >> i) & 1;
! 640: retval = (retval << 1) | bit;
! 641: }
! 642:
! 643: return retval;
! 644: }
! 645: }
! 646:
! 647: u_int
! 648: ar5k_htoclock(u_int usec, HAL_BOOL turbo)
! 649: {
! 650: return (turbo == AH_TRUE ? (usec * 80) : (usec * 40));
! 651: }
! 652:
! 653: u_int
! 654: ar5k_clocktoh(u_int clock, HAL_BOOL turbo)
! 655: {
! 656: return (turbo == AH_TRUE ? (clock / 80) : (clock / 40));
! 657: }
! 658:
! 659: void
! 660: ar5k_rt_copy(HAL_RATE_TABLE *dst, const HAL_RATE_TABLE *src)
! 661: {
! 662: bzero(dst, sizeof(HAL_RATE_TABLE));
! 663: dst->rateCount = src->rateCount;
! 664: bcopy(src->info, dst->info, sizeof(dst->info));
! 665: }
! 666:
! 667: HAL_BOOL
! 668: ar5k_register_timeout(struct ath_hal *hal, u_int32_t reg, u_int32_t flag,
! 669: u_int32_t val, HAL_BOOL is_set)
! 670: {
! 671: int i;
! 672: u_int32_t data;
! 673:
! 674: for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
! 675: data = AR5K_REG_READ(reg);
! 676: if ((is_set == AH_TRUE) && (data & flag))
! 677: break;
! 678: else if ((data & flag) == val)
! 679: break;
! 680: AR5K_DELAY(15);
! 681: }
! 682:
! 683: if (i <= 0)
! 684: return (AH_FALSE);
! 685:
! 686: return (AH_TRUE);
! 687: }
! 688:
! 689: /*
! 690: * Common ar5xx EEPROM access functions
! 691: */
! 692:
! 693: u_int16_t
! 694: ar5k_eeprom_bin2freq(struct ath_hal *hal, u_int16_t bin, u_int mode)
! 695: {
! 696: u_int16_t val;
! 697:
! 698: if (bin == AR5K_EEPROM_CHANNEL_DIS)
! 699: return (bin);
! 700:
! 701: if (mode == AR5K_EEPROM_MODE_11A) {
! 702: if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
! 703: val = (5 * bin) + 4800;
! 704: else
! 705: val = bin > 62 ?
! 706: (10 * 62) + (5 * (bin - 62)) + 5100 :
! 707: (bin * 10) + 5100;
! 708: } else {
! 709: if (hal->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
! 710: val = bin + 2300;
! 711: else
! 712: val = bin + 2400;
! 713: }
! 714:
! 715: return (val);
! 716: }
! 717:
! 718: int
! 719: ar5k_eeprom_read_ants(struct ath_hal *hal, u_int32_t *offset, u_int mode)
! 720: {
! 721: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 722: u_int32_t o = *offset;
! 723: u_int16_t val;
! 724: int ret, i = 0;
! 725:
! 726: AR5K_EEPROM_READ(o++, val);
! 727: ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
! 728: ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
! 729: ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
! 730:
! 731: AR5K_EEPROM_READ(o++, val);
! 732: ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
! 733: ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
! 734: ee->ee_ant_control[mode][i++] = val & 0x3f;
! 735:
! 736: AR5K_EEPROM_READ(o++, val);
! 737: ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
! 738: ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
! 739: ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
! 740:
! 741: AR5K_EEPROM_READ(o++, val);
! 742: ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
! 743: ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
! 744: ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
! 745: ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
! 746:
! 747: AR5K_EEPROM_READ(o++, val);
! 748: ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
! 749: ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
! 750: ee->ee_ant_control[mode][i++] = val & 0x3f;
! 751:
! 752: /* Get antenna modes */
! 753: hal->ah_antenna[mode][0] =
! 754: (ee->ee_ant_control[mode][0] << 4) | 0x1;
! 755: hal->ah_antenna[mode][HAL_ANT_FIXED_A] =
! 756: ee->ee_ant_control[mode][1] |
! 757: (ee->ee_ant_control[mode][2] << 6) |
! 758: (ee->ee_ant_control[mode][3] << 12) |
! 759: (ee->ee_ant_control[mode][4] << 18) |
! 760: (ee->ee_ant_control[mode][5] << 24);
! 761: hal->ah_antenna[mode][HAL_ANT_FIXED_B] =
! 762: ee->ee_ant_control[mode][6] |
! 763: (ee->ee_ant_control[mode][7] << 6) |
! 764: (ee->ee_ant_control[mode][8] << 12) |
! 765: (ee->ee_ant_control[mode][9] << 18) |
! 766: (ee->ee_ant_control[mode][10] << 24);
! 767:
! 768: /* return new offset */
! 769: *offset = o;
! 770:
! 771: return (0);
! 772: }
! 773:
! 774: int
! 775: ar5k_eeprom_read_modes(struct ath_hal *hal, u_int32_t *offset, u_int mode)
! 776: {
! 777: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 778: u_int32_t o = *offset;
! 779: u_int16_t val;
! 780: int ret;
! 781:
! 782: AR5K_EEPROM_READ(o++, val);
! 783: ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
! 784: ee->ee_thr_62[mode] = val & 0xff;
! 785:
! 786: if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
! 787: ee->ee_thr_62[mode] =
! 788: mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
! 789:
! 790: AR5K_EEPROM_READ(o++, val);
! 791: ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
! 792: ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
! 793:
! 794: AR5K_EEPROM_READ(o++, val);
! 795: ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
! 796:
! 797: if ((val & 0xff) & 0x80)
! 798: ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
! 799: else
! 800: ee->ee_noise_floor_thr[mode] = val & 0xff;
! 801:
! 802: if (hal->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
! 803: ee->ee_noise_floor_thr[mode] =
! 804: mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
! 805:
! 806: AR5K_EEPROM_READ(o++, val);
! 807: ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
! 808: ee->ee_x_gain[mode] = (val >> 1) & 0xf;
! 809: ee->ee_xpd[mode] = val & 0x1;
! 810:
! 811: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
! 812: ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
! 813:
! 814: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
! 815: AR5K_EEPROM_READ(o++, val);
! 816: ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
! 817:
! 818: if (mode == AR5K_EEPROM_MODE_11A)
! 819: ee->ee_xr_power[mode] = val & 0x3f;
! 820: else {
! 821: ee->ee_ob[mode][0] = val & 0x7;
! 822: ee->ee_db[mode][0] = (val >> 3) & 0x7;
! 823: }
! 824: }
! 825:
! 826: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
! 827: ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
! 828: ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
! 829: } else {
! 830: ee->ee_i_gain[mode] = (val >> 13) & 0x7;
! 831:
! 832: AR5K_EEPROM_READ(o++, val);
! 833: ee->ee_i_gain[mode] |= (val << 3) & 0x38;
! 834:
! 835: if (mode == AR5K_EEPROM_MODE_11G)
! 836: ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
! 837: }
! 838:
! 839: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
! 840: mode == AR5K_EEPROM_MODE_11A) {
! 841: ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
! 842: ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
! 843: }
! 844:
! 845: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
! 846: mode == AR5K_EEPROM_MODE_11G)
! 847: ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
! 848:
! 849: /* return new offset */
! 850: *offset = o;
! 851:
! 852: return (0);
! 853: }
! 854:
! 855: int
! 856: ar5k_eeprom_init(struct ath_hal *hal)
! 857: {
! 858: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 859: u_int32_t offset;
! 860: u_int16_t val;
! 861: int ret, i;
! 862: u_int mode;
! 863:
! 864: /* Initial TX thermal adjustment values */
! 865: ee->ee_tx_clip = 4;
! 866: ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
! 867: ee->ee_gain_select = 1;
! 868:
! 869: /*
! 870: * Read values from EEPROM and store them in the capability structure
! 871: */
! 872: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
! 873: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
! 874: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
! 875: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
! 876: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
! 877:
! 878: /* Return if we have an old EEPROM */
! 879: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
! 880: return (0);
! 881:
! 882: #ifdef notyet
! 883: /*
! 884: * Validate the checksum of the EEPROM date. There are some
! 885: * devices with invalid EEPROMs.
! 886: */
! 887: for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
! 888: AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
! 889: cksum ^= val;
! 890: }
! 891: if (cksum != AR5K_EEPROM_INFO_CKSUM) {
! 892: AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
! 893: return (EINVAL);
! 894: }
! 895: #endif
! 896:
! 897: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(hal->ah_ee_version),
! 898: ee_ant_gain);
! 899:
! 900: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
! 901: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
! 902: AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
! 903: }
! 904:
! 905: if (hal->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
! 906: AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
! 907: ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
! 908: ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
! 909:
! 910: AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
! 911: ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
! 912: ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
! 913: }
! 914:
! 915: /*
! 916: * Get conformance test limit values
! 917: */
! 918: offset = AR5K_EEPROM_CTL(hal->ah_ee_version);
! 919: ee->ee_ctls = AR5K_EEPROM_N_CTLS(hal->ah_ee_version);
! 920:
! 921: for (i = 0; i < ee->ee_ctls; i++) {
! 922: AR5K_EEPROM_READ(offset++, val);
! 923: ee->ee_ctl[i] = (val >> 8) & 0xff;
! 924: ee->ee_ctl[i + 1] = val & 0xff;
! 925: }
! 926:
! 927: /*
! 928: * Get values for 802.11a (5GHz)
! 929: */
! 930: mode = AR5K_EEPROM_MODE_11A;
! 931:
! 932: ee->ee_turbo_max_power[mode] =
! 933: AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
! 934:
! 935: offset = AR5K_EEPROM_MODES_11A(hal->ah_ee_version);
! 936:
! 937: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
! 938: return (ret);
! 939:
! 940: AR5K_EEPROM_READ(offset++, val);
! 941: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
! 942: ee->ee_ob[mode][3] = (val >> 5) & 0x7;
! 943: ee->ee_db[mode][3] = (val >> 2) & 0x7;
! 944: ee->ee_ob[mode][2] = (val << 1) & 0x7;
! 945:
! 946: AR5K_EEPROM_READ(offset++, val);
! 947: ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
! 948: ee->ee_db[mode][2] = (val >> 12) & 0x7;
! 949: ee->ee_ob[mode][1] = (val >> 9) & 0x7;
! 950: ee->ee_db[mode][1] = (val >> 6) & 0x7;
! 951: ee->ee_ob[mode][0] = (val >> 3) & 0x7;
! 952: ee->ee_db[mode][0] = val & 0x7;
! 953:
! 954: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
! 955: return (ret);
! 956:
! 957: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
! 958: AR5K_EEPROM_READ(offset++, val);
! 959: ee->ee_margin_tx_rx[mode] = val & 0x3f;
! 960: }
! 961:
! 962: /*
! 963: * Get values for 802.11b (2.4GHz)
! 964: */
! 965: mode = AR5K_EEPROM_MODE_11B;
! 966: offset = AR5K_EEPROM_MODES_11B(hal->ah_ee_version);
! 967:
! 968: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
! 969: return (ret);
! 970:
! 971: AR5K_EEPROM_READ(offset++, val);
! 972: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
! 973: ee->ee_ob[mode][1] = (val >> 4) & 0x7;
! 974: ee->ee_db[mode][1] = val & 0x7;
! 975:
! 976: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
! 977: return (ret);
! 978:
! 979: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
! 980: AR5K_EEPROM_READ(offset++, val);
! 981: ee->ee_cal_pier[mode][0] =
! 982: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
! 983: ee->ee_cal_pier[mode][1] =
! 984: ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
! 985:
! 986: AR5K_EEPROM_READ(offset++, val);
! 987: ee->ee_cal_pier[mode][2] =
! 988: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
! 989: }
! 990:
! 991: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
! 992: ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
! 993: }
! 994:
! 995: /*
! 996: * Get values for 802.11g (2.4GHz)
! 997: */
! 998: mode = AR5K_EEPROM_MODE_11G;
! 999: offset = AR5K_EEPROM_MODES_11G(hal->ah_ee_version);
! 1000:
! 1001: if ((ret = ar5k_eeprom_read_ants(hal, &offset, mode)) != 0)
! 1002: return (ret);
! 1003:
! 1004: AR5K_EEPROM_READ(offset++, val);
! 1005: ee->ee_adc_desired_size[mode] = (int8_t)((val >> 8) & 0xff);
! 1006: ee->ee_ob[mode][1] = (val >> 4) & 0x7;
! 1007: ee->ee_db[mode][1] = val & 0x7;
! 1008:
! 1009: if ((ret = ar5k_eeprom_read_modes(hal, &offset, mode)) != 0)
! 1010: return (ret);
! 1011:
! 1012: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
! 1013: AR5K_EEPROM_READ(offset++, val);
! 1014: ee->ee_cal_pier[mode][0] =
! 1015: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
! 1016: ee->ee_cal_pier[mode][1] =
! 1017: ar5k_eeprom_bin2freq(hal, (val >> 8) & 0xff, mode);
! 1018:
! 1019: AR5K_EEPROM_READ(offset++, val);
! 1020: ee->ee_turbo_max_power[mode] = val & 0x7f;
! 1021: ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
! 1022:
! 1023: AR5K_EEPROM_READ(offset++, val);
! 1024: ee->ee_cal_pier[mode][2] =
! 1025: ar5k_eeprom_bin2freq(hal, val & 0xff, mode);
! 1026:
! 1027: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
! 1028: ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
! 1029: }
! 1030:
! 1031: AR5K_EEPROM_READ(offset++, val);
! 1032: ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
! 1033: ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
! 1034:
! 1035: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
! 1036: AR5K_EEPROM_READ(offset++, val);
! 1037: ee->ee_cck_ofdm_gain_delta = val & 0xff;
! 1038: }
! 1039: }
! 1040:
! 1041: /*
! 1042: * Read 5GHz EEPROM channels
! 1043: */
! 1044:
! 1045: return (0);
! 1046: }
! 1047:
! 1048: int
! 1049: ar5k_eeprom_read_mac(struct ath_hal *hal, u_int8_t *mac)
! 1050: {
! 1051: u_int32_t total, offset;
! 1052: u_int16_t data;
! 1053: int octet;
! 1054: u_int8_t mac_d[IEEE80211_ADDR_LEN];
! 1055:
! 1056: bzero(mac, IEEE80211_ADDR_LEN);
! 1057: bzero(&mac_d, IEEE80211_ADDR_LEN);
! 1058:
! 1059: if (hal->ah_eeprom_read(hal, 0x20, &data) != 0)
! 1060: return (EIO);
! 1061:
! 1062: for (offset = 0x1f, octet = 0, total = 0;
! 1063: offset >= 0x1d; offset--) {
! 1064: if (hal->ah_eeprom_read(hal, offset, &data) != 0)
! 1065: return (EIO);
! 1066:
! 1067: total += data;
! 1068: mac_d[octet + 1] = data & 0xff;
! 1069: mac_d[octet] = data >> 8;
! 1070: octet += 2;
! 1071: }
! 1072:
! 1073: bcopy(mac_d, mac, IEEE80211_ADDR_LEN);
! 1074:
! 1075: if ((!total) || total == (3 * 0xffff))
! 1076: return (EINVAL);
! 1077:
! 1078: return (0);
! 1079: }
! 1080:
! 1081: HAL_BOOL
! 1082: ar5k_eeprom_regulation_domain(struct ath_hal *hal, HAL_BOOL write,
! 1083: ieee80211_regdomain_t *regdomain)
! 1084: {
! 1085: u_int16_t ee_regdomain;
! 1086:
! 1087: /* Read current value */
! 1088: if (write != AH_TRUE) {
! 1089: ee_regdomain = hal->ah_capabilities.cap_eeprom.ee_regdomain;
! 1090: *regdomain = ar5k_regdomain_to_ieee(ee_regdomain);
! 1091: return (AH_TRUE);
! 1092: }
! 1093:
! 1094: ee_regdomain = ar5k_regdomain_from_ieee(*regdomain);
! 1095:
! 1096: /* Try to write a new value */
! 1097: if (hal->ah_capabilities.cap_eeprom.ee_protect &
! 1098: AR5K_EEPROM_PROTECT_WR_128_191)
! 1099: return (AH_FALSE);
! 1100: if (hal->ah_eeprom_write(hal, AR5K_EEPROM_REG_DOMAIN,
! 1101: ee_regdomain) != 0)
! 1102: return (AH_FALSE);
! 1103:
! 1104: hal->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
! 1105:
! 1106: return (AH_TRUE);
! 1107: }
! 1108:
! 1109: /*
! 1110: * PHY/RF access functions
! 1111: */
! 1112:
! 1113: HAL_BOOL
! 1114: ar5k_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
! 1115: {
! 1116: HAL_BOOL ret;
! 1117:
! 1118: /*
! 1119: * Check bounds supported by the PHY
! 1120: * (don't care about regulation restrictions at this point)
! 1121: */
! 1122: if ((channel->channel < hal->ah_capabilities.cap_range.range_2ghz_min ||
! 1123: channel->channel > hal->ah_capabilities.cap_range.range_2ghz_max) &&
! 1124: (channel->channel < hal->ah_capabilities.cap_range.range_5ghz_min ||
! 1125: channel->channel > hal->ah_capabilities.cap_range.range_5ghz_max)) {
! 1126: AR5K_PRINTF("channel out of supported range (%u MHz)\n",
! 1127: channel->channel);
! 1128: return (AH_FALSE);
! 1129: }
! 1130:
! 1131: /*
! 1132: * Set the channel and wait
! 1133: */
! 1134: if (hal->ah_radio == AR5K_AR5110)
! 1135: ret = ar5k_ar5110_channel(hal, channel);
! 1136: else if (hal->ah_radio == AR5K_AR5111)
! 1137: ret = ar5k_ar5111_channel(hal, channel);
! 1138: else
! 1139: ret = ar5k_ar5112_channel(hal, channel);
! 1140:
! 1141: if (ret == AH_FALSE)
! 1142: return (ret);
! 1143:
! 1144: hal->ah_current_channel.c_channel = channel->c_channel;
! 1145: hal->ah_current_channel.c_channel_flags = channel->c_channel_flags;
! 1146: hal->ah_turbo = channel->c_channel_flags == CHANNEL_T ?
! 1147: AH_TRUE : AH_FALSE;
! 1148:
! 1149: return (AH_TRUE);
! 1150: }
! 1151:
! 1152: u_int32_t
! 1153: ar5k_ar5110_chan2athchan(HAL_CHANNEL *channel)
! 1154: {
! 1155: u_int32_t athchan;
! 1156:
! 1157: /*
! 1158: * Convert IEEE channel/MHz to an internal channel value used
! 1159: * by the AR5210 chipset. This has not been verified with
! 1160: * newer chipsets like the AR5212A who have a completely
! 1161: * different RF/PHY part.
! 1162: */
! 1163: athchan = (ar5k_bitswap((ieee80211_mhz2ieee(channel->c_channel,
! 1164: channel->c_channel_flags) - 24) / 2, 5) << 1) |
! 1165: (1 << 6) | 0x1;
! 1166:
! 1167: return (athchan);
! 1168: }
! 1169:
! 1170: HAL_BOOL
! 1171: ar5k_ar5110_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
! 1172: {
! 1173: u_int32_t data;
! 1174:
! 1175: /*
! 1176: * Set the channel and wait
! 1177: */
! 1178: data = ar5k_ar5110_chan2athchan(channel);
! 1179: AR5K_PHY_WRITE(0x27, data);
! 1180: AR5K_PHY_WRITE(0x30, 0);
! 1181: AR5K_DELAY(1000);
! 1182:
! 1183: return (AH_TRUE);
! 1184: }
! 1185:
! 1186: HAL_BOOL
! 1187: ar5k_ar5111_chan2athchan(u_int ieee, struct ar5k_athchan_2ghz *athchan)
! 1188: {
! 1189: int channel;
! 1190:
! 1191: /* Cast this value to catch negative channel numbers (>= -19) */
! 1192: channel = (int)ieee;
! 1193:
! 1194: /*
! 1195: * Map 2GHz IEEE channel to 5GHz Atheros channel
! 1196: */
! 1197: if (channel <= 13) {
! 1198: athchan->a2_athchan = 115 + channel;
! 1199: athchan->a2_flags = 0x46;
! 1200: } else if (channel == 14) {
! 1201: athchan->a2_athchan = 124;
! 1202: athchan->a2_flags = 0x44;
! 1203: } else if (channel >= 15 && channel <= 26) {
! 1204: athchan->a2_athchan = ((channel - 14) * 4) + 132;
! 1205: athchan->a2_flags = 0x46;
! 1206: } else
! 1207: return (AH_FALSE);
! 1208:
! 1209: return (AH_TRUE);
! 1210: }
! 1211:
! 1212: HAL_BOOL
! 1213: ar5k_ar5111_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
! 1214: {
! 1215: u_int ieee_channel, ath_channel;
! 1216: u_int32_t data0, data1, clock;
! 1217: struct ar5k_athchan_2ghz ath_channel_2ghz;
! 1218:
! 1219: /*
! 1220: * Set the channel on the AR5111 radio
! 1221: */
! 1222: data0 = data1 = 0;
! 1223: ath_channel = ieee_channel = ieee80211_mhz2ieee(channel->c_channel,
! 1224: channel->c_channel_flags);
! 1225:
! 1226: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
! 1227: /* Map 2GHz channel to 5GHz Atheros channel ID */
! 1228: if (ar5k_ar5111_chan2athchan(ieee_channel,
! 1229: &ath_channel_2ghz) == AH_FALSE)
! 1230: return (AH_FALSE);
! 1231:
! 1232: ath_channel = ath_channel_2ghz.a2_athchan;
! 1233: data0 = ((ar5k_bitswap(ath_channel_2ghz.a2_flags, 8) & 0xff)
! 1234: << 5) | (1 << 4);
! 1235: }
! 1236:
! 1237: if (ath_channel < 145 || !(ath_channel & 1)) {
! 1238: clock = 1;
! 1239: data1 = ((ar5k_bitswap(ath_channel - 24, 8) & 0xff) << 2)
! 1240: | (clock << 1) | (1 << 10) | 1;
! 1241: } else {
! 1242: clock = 0;
! 1243: data1 = ((ar5k_bitswap((ath_channel - 24) / 2, 8) & 0xff) << 2)
! 1244: | (clock << 1) | (1 << 10) | 1;
! 1245: }
! 1246:
! 1247: AR5K_PHY_WRITE(0x27, (data1 & 0xff) | ((data0 & 0xff) << 8));
! 1248: AR5K_PHY_WRITE(0x34, ((data1 >> 8) & 0xff) | (data0 & 0xff00));
! 1249:
! 1250: return (AH_TRUE);
! 1251: }
! 1252:
! 1253: HAL_BOOL
! 1254: ar5k_ar5112_channel(struct ath_hal *hal, HAL_CHANNEL *channel)
! 1255: {
! 1256: u_int32_t data, data0, data1, data2;
! 1257: u_int16_t c;
! 1258:
! 1259: data = data0 = data1 = data2 = 0;
! 1260: c = channel->c_channel;
! 1261:
! 1262: /*
! 1263: * Set the channel on the AR5112 or newer
! 1264: */
! 1265: if (c < 4800) {
! 1266: if (!((c - 2224) % 5)) {
! 1267: data0 = ((2 * (c - 704)) - 3040) / 10;
! 1268: data1 = 1;
! 1269: } else if (!((c - 2192) % 5)) {
! 1270: data0 = ((2 * (c - 672)) - 3040) / 10;
! 1271: data1 = 0;
! 1272: } else
! 1273: return (AH_FALSE);
! 1274:
! 1275: data0 = ar5k_bitswap((data0 << 2) & 0xff, 8);
! 1276: } else {
! 1277: if (!(c % 20) && c >= 5120) {
! 1278: data0 = ar5k_bitswap(((c - 4800) / 20 << 2), 8);
! 1279: data2 = ar5k_bitswap(3, 2);
! 1280: } else if (!(c % 10)) {
! 1281: data0 = ar5k_bitswap(((c - 4800) / 10 << 1), 8);
! 1282: data2 = ar5k_bitswap(2, 2);
! 1283: } else if (!(c % 5)) {
! 1284: data0 = ar5k_bitswap((c - 4800) / 5, 8);
! 1285: data2 = ar5k_bitswap(1, 2);
! 1286: } else
! 1287: return (AH_FALSE);
! 1288: }
! 1289:
! 1290: data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
! 1291:
! 1292: AR5K_PHY_WRITE(0x27, data & 0xff);
! 1293: AR5K_PHY_WRITE(0x36, (data >> 8) & 0x7f);
! 1294:
! 1295: return (AH_TRUE);
! 1296: }
! 1297:
! 1298: u_int
! 1299: ar5k_rfregs_op(u_int32_t *rf, u_int32_t offset, u_int32_t reg, u_int32_t bits,
! 1300: u_int32_t first, u_int32_t col, HAL_BOOL set)
! 1301: {
! 1302: u_int32_t mask, entry, last, data, shift, position;
! 1303: int32_t left;
! 1304: int i;
! 1305:
! 1306: if (rf == NULL) {
! 1307: /* should not happen */
! 1308: return (0);
! 1309: }
! 1310:
! 1311: if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
! 1312: AR5K_PRINTF("invalid values at offset %u\n", offset);
! 1313: return (0);
! 1314: }
! 1315:
! 1316: entry = ((first - 1) / 8) + offset;
! 1317: position = (first - 1) % 8;
! 1318:
! 1319: if (set == AH_TRUE)
! 1320: data = ar5k_bitswap(reg, bits);
! 1321:
! 1322: for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
! 1323: last = (position + left > 8) ? 8 : position + left;
! 1324: mask = (((1 << last) - 1) ^ ((1 << position) - 1)) <<
! 1325: (col * 8);
! 1326:
! 1327: if (set == AH_TRUE) {
! 1328: rf[entry] &= ~mask;
! 1329: rf[entry] |= ((data << position) << (col * 8)) & mask;
! 1330: data >>= (8 - position);
! 1331: } else {
! 1332: data = (((rf[entry] & mask) >> (col * 8)) >>
! 1333: position) << shift;
! 1334: shift += last - position;
! 1335: }
! 1336:
! 1337: left -= 8 - position;
! 1338: }
! 1339:
! 1340: data = set == AH_TRUE ? 1 : ar5k_bitswap(data, bits);
! 1341:
! 1342: return (data);
! 1343: }
! 1344:
! 1345: u_int32_t
! 1346: ar5k_rfregs_gainf_corr(struct ath_hal *hal)
! 1347: {
! 1348: u_int32_t mix, step;
! 1349: u_int32_t *rf;
! 1350:
! 1351: if (hal->ah_rf_banks == NULL)
! 1352: return (0);
! 1353:
! 1354: rf = hal->ah_rf_banks;
! 1355: hal->ah_gain.g_f_corr = 0;
! 1356:
! 1357: if (ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 1, 36, 0, AH_FALSE) != 1)
! 1358: return (0);
! 1359:
! 1360: step = ar5k_rfregs_op(rf, hal->ah_offset[7], 0, 4, 32, 0, AH_FALSE);
! 1361: mix = hal->ah_gain.g_step->gos_param[0];
! 1362:
! 1363: switch (mix) {
! 1364: case 3:
! 1365: hal->ah_gain.g_f_corr = step * 2;
! 1366: break;
! 1367: case 2:
! 1368: hal->ah_gain.g_f_corr = (step - 5) * 2;
! 1369: break;
! 1370: case 1:
! 1371: hal->ah_gain.g_f_corr = step;
! 1372: break;
! 1373: default:
! 1374: hal->ah_gain.g_f_corr = 0;
! 1375: break;
! 1376: }
! 1377:
! 1378: return (hal->ah_gain.g_f_corr);
! 1379: }
! 1380:
! 1381: HAL_BOOL
! 1382: ar5k_rfregs_gain_readback(struct ath_hal *hal)
! 1383: {
! 1384: u_int32_t step, mix, level[4];
! 1385: u_int32_t *rf;
! 1386:
! 1387: if (hal->ah_rf_banks == NULL)
! 1388: return (0);
! 1389:
! 1390: rf = hal->ah_rf_banks;
! 1391:
! 1392: if (hal->ah_radio == AR5K_AR5111) {
! 1393: step = ar5k_rfregs_op(rf, hal->ah_offset[7],
! 1394: 0, 6, 37, 0, AH_FALSE);
! 1395: level[0] = 0;
! 1396: level[1] = (step == 0x3f) ? 0x32 : step + 4;
! 1397: level[2] = (step != 0x3f) ? 0x40 : level[0];
! 1398: level[3] = level[2] + 0x32;
! 1399:
! 1400: hal->ah_gain.g_high = level[3] -
! 1401: (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
! 1402: hal->ah_gain.g_low = level[0] +
! 1403: (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
! 1404: } else {
! 1405: mix = ar5k_rfregs_op(rf, hal->ah_offset[7],
! 1406: 0, 1, 36, 0, AH_FALSE);
! 1407: level[0] = level[2] = 0;
! 1408:
! 1409: if (mix == 1) {
! 1410: level[1] = level[3] = 83;
! 1411: } else {
! 1412: level[1] = level[3] = 107;
! 1413: hal->ah_gain.g_high = 55;
! 1414: }
! 1415: }
! 1416:
! 1417: return ((hal->ah_gain.g_current >= level[0] &&
! 1418: hal->ah_gain.g_current <= level[1]) ||
! 1419: (hal->ah_gain.g_current >= level[2] &&
! 1420: hal->ah_gain.g_current <= level[3]));
! 1421: }
! 1422:
! 1423: int32_t
! 1424: ar5k_rfregs_gain_adjust(struct ath_hal *hal)
! 1425: {
! 1426: int ret = 0;
! 1427: const struct ar5k_gain_opt *go;
! 1428:
! 1429: go = hal->ah_radio == AR5K_AR5111 ?
! 1430: &ar5111_gain_opt : &ar5112_gain_opt;
! 1431:
! 1432: hal->ah_gain.g_step = &go->go_step[hal->ah_gain.g_step_idx];
! 1433:
! 1434: if (hal->ah_gain.g_current >= hal->ah_gain.g_high) {
! 1435: if (hal->ah_gain.g_step_idx == 0)
! 1436: return (-1);
! 1437: for (hal->ah_gain.g_target = hal->ah_gain.g_current;
! 1438: hal->ah_gain.g_target >= hal->ah_gain.g_high &&
! 1439: hal->ah_gain.g_step_idx > 0;
! 1440: hal->ah_gain.g_step =
! 1441: &go->go_step[hal->ah_gain.g_step_idx]) {
! 1442: hal->ah_gain.g_target -= 2 *
! 1443: (go->go_step[--(hal->ah_gain.g_step_idx)].gos_gain -
! 1444: hal->ah_gain.g_step->gos_gain);
! 1445: }
! 1446:
! 1447: ret = 1;
! 1448: goto done;
! 1449: }
! 1450:
! 1451: if (hal->ah_gain.g_current <= hal->ah_gain.g_low) {
! 1452: if (hal->ah_gain.g_step_idx == (go->go_steps_count - 1))
! 1453: return (-2);
! 1454: for (hal->ah_gain.g_target = hal->ah_gain.g_current;
! 1455: hal->ah_gain.g_target <= hal->ah_gain.g_low &&
! 1456: hal->ah_gain.g_step_idx < (go->go_steps_count - 1);
! 1457: hal->ah_gain.g_step =
! 1458: &go->go_step[hal->ah_gain.g_step_idx]) {
! 1459: hal->ah_gain.g_target -= 2 *
! 1460: (go->go_step[++(hal->ah_gain.g_step_idx)].gos_gain -
! 1461: hal->ah_gain.g_step->gos_gain);
! 1462: }
! 1463:
! 1464: ret = 2;
! 1465: goto done;
! 1466: }
! 1467:
! 1468: done:
! 1469: #ifdef AR5K_DEBUG
! 1470: AR5K_PRINTF("ret %d, gain step %u, current gain %u, target gain %u\n",
! 1471: ret,
! 1472: hal->ah_gain.g_step_idx,
! 1473: hal->ah_gain.g_current,
! 1474: hal->ah_gain.g_target);
! 1475: #endif
! 1476:
! 1477: return (ret);
! 1478: }
! 1479:
! 1480: HAL_BOOL
! 1481: ar5k_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
! 1482: {
! 1483: ar5k_rfgain_t *func = NULL;
! 1484: HAL_BOOL ret;
! 1485:
! 1486: if (hal->ah_radio == AR5K_AR5111) {
! 1487: hal->ah_rf_banks_size = sizeof(ar5111_rf);
! 1488: func = ar5k_ar5111_rfregs;
! 1489: } else if (hal->ah_radio == AR5K_AR5112) {
! 1490: if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
! 1491: hal->ah_rf_banks_size = sizeof(ar5112a_rf);
! 1492: else
! 1493: hal->ah_rf_banks_size = sizeof(ar5112_rf);
! 1494: func = ar5k_ar5112_rfregs;
! 1495: } else
! 1496: return (AH_FALSE);
! 1497:
! 1498: if (hal->ah_rf_banks == NULL) {
! 1499: /* XXX do extra checks? */
! 1500: if ((hal->ah_rf_banks = malloc(hal->ah_rf_banks_size,
! 1501: M_DEVBUF, M_NOWAIT)) == NULL) {
! 1502: AR5K_PRINT("out of memory\n");
! 1503: return (AH_FALSE);
! 1504: }
! 1505: }
! 1506:
! 1507: ret = (func)(hal, channel, mode);
! 1508:
! 1509: if (ret == AH_TRUE)
! 1510: hal->ah_rf_gain = HAL_RFGAIN_INACTIVE;
! 1511:
! 1512: return (ret);
! 1513: }
! 1514:
! 1515: HAL_BOOL
! 1516: ar5k_ar5111_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
! 1517: {
! 1518: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 1519: const u_int rf_size = AR5K_ELEMENTS(ar5111_rf);
! 1520: u_int32_t *rf;
! 1521: int i, obdb = -1, bank = -1;
! 1522: u_int32_t ee_mode;
! 1523:
! 1524: AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
! 1525:
! 1526: rf = hal->ah_rf_banks;
! 1527:
! 1528: /* Copy values to modify them */
! 1529: for (i = 0; i < rf_size; i++) {
! 1530: if (ar5111_rf[i].rf_bank >=
! 1531: AR5K_AR5111_INI_RF_MAX_BANKS) {
! 1532: AR5K_PRINT("invalid bank\n");
! 1533: return (AH_FALSE);
! 1534: }
! 1535:
! 1536: if (bank != ar5111_rf[i].rf_bank) {
! 1537: bank = ar5111_rf[i].rf_bank;
! 1538: hal->ah_offset[bank] = i;
! 1539: }
! 1540:
! 1541: rf[i] = ar5111_rf[i].rf_value[mode];
! 1542: }
! 1543:
! 1544: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
! 1545: if (channel->c_channel_flags & IEEE80211_CHAN_B)
! 1546: ee_mode = AR5K_EEPROM_MODE_11B;
! 1547: else
! 1548: ee_mode = AR5K_EEPROM_MODE_11G;
! 1549: obdb = 0;
! 1550:
! 1551: if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
! 1552: ee->ee_ob[ee_mode][obdb], 3, 119, 0, AH_TRUE))
! 1553: return (AH_FALSE);
! 1554:
! 1555: if (!ar5k_rfregs_op(rf, hal->ah_offset[0],
! 1556: ee->ee_ob[ee_mode][obdb], 3, 122, 0, AH_TRUE))
! 1557: return (AH_FALSE);
! 1558:
! 1559: obdb = 1;
! 1560: } else {
! 1561: /* For 11a, Turbo and XR */
! 1562: ee_mode = AR5K_EEPROM_MODE_11A;
! 1563: obdb = channel->c_channel >= 5725 ? 3 :
! 1564: (channel->c_channel >= 5500 ? 2 :
! 1565: (channel->c_channel >= 5260 ? 1 :
! 1566: (channel->c_channel > 4000 ? 0 : -1)));
! 1567:
! 1568: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1569: ee->ee_pwd_84, 1, 51, 3, AH_TRUE))
! 1570: return (AH_FALSE);
! 1571:
! 1572: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1573: ee->ee_pwd_90, 1, 45, 3, AH_TRUE))
! 1574: return (AH_FALSE);
! 1575: }
! 1576:
! 1577: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1578: !ee->ee_xpd[ee_mode], 1, 95, 0, AH_TRUE))
! 1579: return (AH_FALSE);
! 1580:
! 1581: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1582: ee->ee_x_gain[ee_mode], 4, 96, 0, AH_TRUE))
! 1583: return (AH_FALSE);
! 1584:
! 1585: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1586: obdb >= 0 ? ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, AH_TRUE))
! 1587: return (AH_FALSE);
! 1588:
! 1589: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1590: obdb >= 0 ? ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, AH_TRUE))
! 1591: return (AH_FALSE);
! 1592:
! 1593: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
! 1594: ee->ee_i_gain[ee_mode], 6, 29, 0, AH_TRUE))
! 1595: return (AH_FALSE);
! 1596:
! 1597: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
! 1598: ee->ee_xpd[ee_mode], 1, 4, 0, AH_TRUE))
! 1599: return (AH_FALSE);
! 1600:
! 1601: /* Write RF values */
! 1602: for (i = 0; i < rf_size; i++) {
! 1603: AR5K_REG_WAIT(i);
! 1604: AR5K_REG_WRITE(ar5111_rf[i].rf_register, rf[i]);
! 1605: }
! 1606:
! 1607: return (AH_TRUE);
! 1608: }
! 1609:
! 1610: HAL_BOOL
! 1611: ar5k_ar5112_rfregs(struct ath_hal *hal, HAL_CHANNEL *channel, u_int mode)
! 1612: {
! 1613: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 1614: u_int rf_size;
! 1615: u_int32_t *rf;
! 1616: int i, obdb = -1, bank = -1;
! 1617: u_int32_t ee_mode;
! 1618: const struct ar5k_ini_rf *rf_ini;
! 1619:
! 1620: AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
! 1621:
! 1622: rf = hal->ah_rf_banks;
! 1623:
! 1624: if (hal->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
! 1625: rf_ini = ar5112a_rf;
! 1626: rf_size = AR5K_ELEMENTS(ar5112a_rf);
! 1627: } else {
! 1628: rf_ini = ar5112_rf;
! 1629: rf_size = AR5K_ELEMENTS(ar5112_rf);
! 1630: }
! 1631:
! 1632: /* Copy values to modify them */
! 1633: for (i = 0; i < rf_size; i++) {
! 1634: if (rf_ini[i].rf_bank >=
! 1635: AR5K_AR5112_INI_RF_MAX_BANKS) {
! 1636: AR5K_PRINT("invalid bank\n");
! 1637: return (AH_FALSE);
! 1638: }
! 1639:
! 1640: if (bank != rf_ini[i].rf_bank) {
! 1641: bank = rf_ini[i].rf_bank;
! 1642: hal->ah_offset[bank] = i;
! 1643: }
! 1644:
! 1645: rf[i] = rf_ini[i].rf_value[mode];
! 1646: }
! 1647:
! 1648: if (channel->c_channel_flags & IEEE80211_CHAN_2GHZ) {
! 1649: if (channel->c_channel_flags & IEEE80211_CHAN_B)
! 1650: ee_mode = AR5K_EEPROM_MODE_11B;
! 1651: else
! 1652: ee_mode = AR5K_EEPROM_MODE_11G;
! 1653: obdb = 0;
! 1654:
! 1655: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1656: ee->ee_ob[ee_mode][obdb], 3, 287, 0, AH_TRUE))
! 1657: return (AH_FALSE);
! 1658:
! 1659: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1660: ee->ee_ob[ee_mode][obdb], 3, 290, 0, AH_TRUE))
! 1661: return (AH_FALSE);
! 1662: } else {
! 1663: /* For 11a, Turbo and XR */
! 1664: ee_mode = AR5K_EEPROM_MODE_11A;
! 1665: obdb = channel->c_channel >= 5725 ? 3 :
! 1666: (channel->c_channel >= 5500 ? 2 :
! 1667: (channel->c_channel >= 5260 ? 1 :
! 1668: (channel->c_channel > 4000 ? 0 : -1)));
! 1669:
! 1670: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1671: ee->ee_ob[ee_mode][obdb], 3, 279, 0, AH_TRUE))
! 1672: return (AH_FALSE);
! 1673:
! 1674: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1675: ee->ee_ob[ee_mode][obdb], 3, 282, 0, AH_TRUE))
! 1676: return (AH_FALSE);
! 1677: }
! 1678:
! 1679: #ifdef notyet
! 1680: ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1681: ee->ee_x_gain[ee_mode], 2, 270, 0, AH_TRUE);
! 1682: ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1683: ee->ee_x_gain[ee_mode], 2, 257, 0, AH_TRUE);
! 1684: #endif
! 1685:
! 1686: if (!ar5k_rfregs_op(rf, hal->ah_offset[6],
! 1687: ee->ee_xpd[ee_mode], 1, 302, 0, AH_TRUE))
! 1688: return (AH_FALSE);
! 1689:
! 1690: if (!ar5k_rfregs_op(rf, hal->ah_offset[7],
! 1691: ee->ee_i_gain[ee_mode], 6, 14, 0, AH_TRUE))
! 1692: return (AH_FALSE);
! 1693:
! 1694: /* Write RF values */
! 1695: for (i = 0; i < rf_size; i++)
! 1696: AR5K_REG_WRITE(ar5112_rf[i].rf_register, rf[i]);
! 1697:
! 1698: return (AH_TRUE);
! 1699: }
! 1700:
! 1701: HAL_BOOL
! 1702: ar5k_rfgain(struct ath_hal *hal, u_int phy, u_int freq)
! 1703: {
! 1704: int i;
! 1705:
! 1706: switch (phy) {
! 1707: case AR5K_INI_PHY_5111:
! 1708: case AR5K_INI_PHY_5112:
! 1709: break;
! 1710: default:
! 1711: return (AH_FALSE);
! 1712: }
! 1713:
! 1714: switch (freq) {
! 1715: case AR5K_INI_RFGAIN_2GHZ:
! 1716: case AR5K_INI_RFGAIN_5GHZ:
! 1717: break;
! 1718: default:
! 1719: return (AH_FALSE);
! 1720: }
! 1721:
! 1722: for (i = 0; i < AR5K_ELEMENTS(ar5k_rfg); i++) {
! 1723: AR5K_REG_WAIT(i);
! 1724: AR5K_REG_WRITE((u_int32_t)ar5k_rfg[i].rfg_register,
! 1725: ar5k_rfg[i].rfg_value[phy][freq]);
! 1726: }
! 1727:
! 1728: return (AH_TRUE);
! 1729: }
! 1730:
! 1731: /*
! 1732: * Common TX power setup
! 1733: */
! 1734: void
! 1735: ar5k_txpower_table(struct ath_hal *hal, HAL_CHANNEL *channel, int16_t max_power)
! 1736: {
! 1737: u_int16_t txpower, *rates;
! 1738: int i, min, max, n;
! 1739:
! 1740: rates = hal->ah_txpower.txp_rates;
! 1741:
! 1742: txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
! 1743: if (max_power > txpower) {
! 1744: txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
! 1745: AR5K_TUNE_MAX_TXPOWER : max_power;
! 1746: }
! 1747:
! 1748: for (i = 0; i < AR5K_MAX_RATES; i++)
! 1749: rates[i] = txpower;
! 1750:
! 1751: /* XXX setup target powers by rate */
! 1752:
! 1753: hal->ah_txpower.txp_min = rates[7];
! 1754: hal->ah_txpower.txp_max = rates[0];
! 1755: hal->ah_txpower.txp_ofdm = rates[0];
! 1756:
! 1757: /* Calculate the power table */
! 1758: n = AR5K_ELEMENTS(hal->ah_txpower.txp_pcdac);
! 1759: min = AR5K_EEPROM_PCDAC_START;
! 1760: max = AR5K_EEPROM_PCDAC_STOP;
! 1761: for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
! 1762: hal->ah_txpower.txp_pcdac[i] =
! 1763: #ifdef notyet
! 1764: min + ((i * (max - min)) / n);
! 1765: #else
! 1766: min;
! 1767: #endif
! 1768: }
CVSweb