Annotation of sys/dev/ic/ar5212.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ar5212.c,v 1.40 2007/04/10 17:47:55 miod 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 the Atheros AR5001 Wireless LAN chipset
! 21: * (AR5212 + AR5111/AR5112).
! 22: */
! 23:
! 24: #include <dev/ic/ar5xxx.h>
! 25: #include <dev/ic/ar5212reg.h>
! 26: #include <dev/ic/ar5212var.h>
! 27:
! 28: HAL_BOOL ar5k_ar5212_nic_reset(struct ath_hal *, u_int32_t);
! 29: HAL_BOOL ar5k_ar5212_nic_wakeup(struct ath_hal *, u_int16_t);
! 30: u_int16_t ar5k_ar5212_radio_revision(struct ath_hal *, HAL_CHIP);
! 31: const void ar5k_ar5212_fill(struct ath_hal *);
! 32: HAL_BOOL ar5k_ar5212_txpower(struct ath_hal *, HAL_CHANNEL *, u_int);
! 33:
! 34: /*
! 35: * Initial register setting for the AR5212
! 36: */
! 37: static const struct ar5k_ar5212_ini ar5212_ini[] =
! 38: AR5K_AR5212_INI;
! 39: static const struct ar5k_ar5212_ini_mode ar5212_mode[] =
! 40: AR5K_AR5212_INI_MODE;
! 41:
! 42: AR5K_HAL_FUNCTIONS(extern, ar5k_ar5212,);
! 43:
! 44: const void
! 45: ar5k_ar5212_fill(struct ath_hal *hal)
! 46: {
! 47: hal->ah_magic = AR5K_AR5212_MAGIC;
! 48:
! 49: /*
! 50: * Init/Exit functions
! 51: */
! 52: AR5K_HAL_FUNCTION(hal, ar5212, get_rate_table);
! 53: AR5K_HAL_FUNCTION(hal, ar5212, detach);
! 54:
! 55: /*
! 56: * Reset functions
! 57: */
! 58: AR5K_HAL_FUNCTION(hal, ar5212, reset);
! 59: AR5K_HAL_FUNCTION(hal, ar5212, set_opmode);
! 60: AR5K_HAL_FUNCTION(hal, ar5212, calibrate);
! 61:
! 62: /*
! 63: * TX functions
! 64: */
! 65: AR5K_HAL_FUNCTION(hal, ar5212, update_tx_triglevel);
! 66: AR5K_HAL_FUNCTION(hal, ar5212, setup_tx_queue);
! 67: AR5K_HAL_FUNCTION(hal, ar5212, setup_tx_queueprops);
! 68: AR5K_HAL_FUNCTION(hal, ar5212, release_tx_queue);
! 69: AR5K_HAL_FUNCTION(hal, ar5212, reset_tx_queue);
! 70: AR5K_HAL_FUNCTION(hal, ar5212, get_tx_buf);
! 71: AR5K_HAL_FUNCTION(hal, ar5212, put_tx_buf);
! 72: AR5K_HAL_FUNCTION(hal, ar5212, tx_start);
! 73: AR5K_HAL_FUNCTION(hal, ar5212, stop_tx_dma);
! 74: AR5K_HAL_FUNCTION(hal, ar5212, setup_tx_desc);
! 75: AR5K_HAL_FUNCTION(hal, ar5212, setup_xtx_desc);
! 76: AR5K_HAL_FUNCTION(hal, ar5212, fill_tx_desc);
! 77: AR5K_HAL_FUNCTION(hal, ar5212, proc_tx_desc);
! 78: AR5K_HAL_FUNCTION(hal, ar5212, has_veol);
! 79:
! 80: /*
! 81: * RX functions
! 82: */
! 83: AR5K_HAL_FUNCTION(hal, ar5212, get_rx_buf);
! 84: AR5K_HAL_FUNCTION(hal, ar5212, put_rx_buf);
! 85: AR5K_HAL_FUNCTION(hal, ar5212, start_rx);
! 86: AR5K_HAL_FUNCTION(hal, ar5212, stop_rx_dma);
! 87: AR5K_HAL_FUNCTION(hal, ar5212, start_rx_pcu);
! 88: AR5K_HAL_FUNCTION(hal, ar5212, stop_pcu_recv);
! 89: AR5K_HAL_FUNCTION(hal, ar5212, set_mcast_filter);
! 90: AR5K_HAL_FUNCTION(hal, ar5212, set_mcast_filterindex);
! 91: AR5K_HAL_FUNCTION(hal, ar5212, clear_mcast_filter_idx);
! 92: AR5K_HAL_FUNCTION(hal, ar5212, get_rx_filter);
! 93: AR5K_HAL_FUNCTION(hal, ar5212, set_rx_filter);
! 94: AR5K_HAL_FUNCTION(hal, ar5212, setup_rx_desc);
! 95: AR5K_HAL_FUNCTION(hal, ar5212, proc_rx_desc);
! 96: AR5K_HAL_FUNCTION(hal, ar5212, set_rx_signal);
! 97:
! 98: /*
! 99: * Misc functions
! 100: */
! 101: AR5K_HAL_FUNCTION(hal, ar5212, dump_state);
! 102: AR5K_HAL_FUNCTION(hal, ar5212, get_diag_state);
! 103: AR5K_HAL_FUNCTION(hal, ar5212, get_lladdr);
! 104: AR5K_HAL_FUNCTION(hal, ar5212, set_lladdr);
! 105: AR5K_HAL_FUNCTION(hal, ar5212, set_regdomain);
! 106: AR5K_HAL_FUNCTION(hal, ar5212, set_ledstate);
! 107: AR5K_HAL_FUNCTION(hal, ar5212, set_associd);
! 108: AR5K_HAL_FUNCTION(hal, ar5212, set_gpio_input);
! 109: AR5K_HAL_FUNCTION(hal, ar5212, set_gpio_output);
! 110: AR5K_HAL_FUNCTION(hal, ar5212, get_gpio);
! 111: AR5K_HAL_FUNCTION(hal, ar5212, set_gpio);
! 112: AR5K_HAL_FUNCTION(hal, ar5212, set_gpio_intr);
! 113: AR5K_HAL_FUNCTION(hal, ar5212, get_tsf32);
! 114: AR5K_HAL_FUNCTION(hal, ar5212, get_tsf64);
! 115: AR5K_HAL_FUNCTION(hal, ar5212, reset_tsf);
! 116: AR5K_HAL_FUNCTION(hal, ar5212, get_regdomain);
! 117: AR5K_HAL_FUNCTION(hal, ar5212, detect_card_present);
! 118: AR5K_HAL_FUNCTION(hal, ar5212, update_mib_counters);
! 119: AR5K_HAL_FUNCTION(hal, ar5212, get_rf_gain);
! 120: AR5K_HAL_FUNCTION(hal, ar5212, set_slot_time);
! 121: AR5K_HAL_FUNCTION(hal, ar5212, get_slot_time);
! 122: AR5K_HAL_FUNCTION(hal, ar5212, set_ack_timeout);
! 123: AR5K_HAL_FUNCTION(hal, ar5212, get_ack_timeout);
! 124: AR5K_HAL_FUNCTION(hal, ar5212, set_cts_timeout);
! 125: AR5K_HAL_FUNCTION(hal, ar5212, get_cts_timeout);
! 126:
! 127: /*
! 128: * Key table (WEP) functions
! 129: */
! 130: AR5K_HAL_FUNCTION(hal, ar5212, is_cipher_supported);
! 131: AR5K_HAL_FUNCTION(hal, ar5212, get_keycache_size);
! 132: AR5K_HAL_FUNCTION(hal, ar5212, reset_key);
! 133: AR5K_HAL_FUNCTION(hal, ar5212, is_key_valid);
! 134: AR5K_HAL_FUNCTION(hal, ar5212, set_key);
! 135: AR5K_HAL_FUNCTION(hal, ar5212, set_key_lladdr);
! 136:
! 137: /*
! 138: * Power management functions
! 139: */
! 140: AR5K_HAL_FUNCTION(hal, ar5212, set_power);
! 141: AR5K_HAL_FUNCTION(hal, ar5212, get_power_mode);
! 142: AR5K_HAL_FUNCTION(hal, ar5212, query_pspoll_support);
! 143: AR5K_HAL_FUNCTION(hal, ar5212, init_pspoll);
! 144: AR5K_HAL_FUNCTION(hal, ar5212, enable_pspoll);
! 145: AR5K_HAL_FUNCTION(hal, ar5212, disable_pspoll);
! 146:
! 147: /*
! 148: * Beacon functions
! 149: */
! 150: AR5K_HAL_FUNCTION(hal, ar5212, init_beacon);
! 151: AR5K_HAL_FUNCTION(hal, ar5212, set_beacon_timers);
! 152: AR5K_HAL_FUNCTION(hal, ar5212, reset_beacon);
! 153: AR5K_HAL_FUNCTION(hal, ar5212, wait_for_beacon);
! 154:
! 155: /*
! 156: * Interrupt functions
! 157: */
! 158: AR5K_HAL_FUNCTION(hal, ar5212, is_intr_pending);
! 159: AR5K_HAL_FUNCTION(hal, ar5212, get_isr);
! 160: AR5K_HAL_FUNCTION(hal, ar5212, get_intr);
! 161: AR5K_HAL_FUNCTION(hal, ar5212, set_intr);
! 162:
! 163: /*
! 164: * Chipset functions (ar5k-specific, non-HAL)
! 165: */
! 166: AR5K_HAL_FUNCTION(hal, ar5212, get_capabilities);
! 167: AR5K_HAL_FUNCTION(hal, ar5212, radar_alert);
! 168:
! 169: /*
! 170: * EEPROM access
! 171: */
! 172: AR5K_HAL_FUNCTION(hal, ar5212, eeprom_is_busy);
! 173: AR5K_HAL_FUNCTION(hal, ar5212, eeprom_read);
! 174: AR5K_HAL_FUNCTION(hal, ar5212, eeprom_write);
! 175:
! 176: /*
! 177: * Unused functions or functions not implemented
! 178: */
! 179: AR5K_HAL_FUNCTION(hal, ar5212, set_bssid_mask);
! 180: AR5K_HAL_FUNCTION(hal, ar5212, get_tx_queueprops);
! 181: AR5K_HAL_FUNCTION(hal, ar5212, num_tx_pending);
! 182: AR5K_HAL_FUNCTION(hal, ar5212, phy_disable);
! 183: AR5K_HAL_FUNCTION(hal, ar5212, set_txpower_limit);
! 184: AR5K_HAL_FUNCTION(hal, ar5212, set_def_antenna);
! 185: AR5K_HAL_FUNCTION(hal, ar5212, get_def_antenna);
! 186: #ifdef notyet
! 187: AR5K_HAL_FUNCTION(hal, ar5212, set_capability);
! 188: AR5K_HAL_FUNCTION(hal, ar5212, proc_mib_event);
! 189: AR5K_HAL_FUNCTION(hal, ar5212, get_tx_inter_queue);
! 190: #endif
! 191: }
! 192:
! 193: struct ath_hal *
! 194: ar5k_ar5212_attach(u_int16_t device, void *sc, bus_space_tag_t st,
! 195: bus_space_handle_t sh, int *status)
! 196: {
! 197: struct ath_hal *hal = (struct ath_hal*) sc;
! 198: u_int8_t mac[IEEE80211_ADDR_LEN];
! 199: u_int32_t srev;
! 200:
! 201: ar5k_ar5212_fill(hal);
! 202:
! 203: /* Bring device out of sleep and reset its units */
! 204: if (ar5k_ar5212_nic_wakeup(hal, AR5K_INIT_MODE) != AH_TRUE)
! 205: return (NULL);
! 206:
! 207: /* Get MAC, PHY and RADIO revisions */
! 208: srev = AR5K_REG_READ(AR5K_AR5212_SREV);
! 209: hal->ah_mac_srev = srev;
! 210: hal->ah_mac_version = AR5K_REG_MS(srev, AR5K_AR5212_SREV_VER);
! 211: hal->ah_mac_revision = AR5K_REG_MS(srev, AR5K_AR5212_SREV_REV);
! 212: hal->ah_phy_revision = AR5K_REG_READ(AR5K_AR5212_PHY_CHIP_ID) &
! 213: 0x00ffffffff;
! 214: hal->ah_radio_5ghz_revision =
! 215: ar5k_ar5212_radio_revision(hal, HAL_CHIP_5GHZ);
! 216: hal->ah_radio_2ghz_revision =
! 217: ar5k_ar5212_radio_revision(hal, HAL_CHIP_2GHZ);
! 218:
! 219: /* Single chip radio */
! 220: if (hal->ah_radio_2ghz_revision == hal->ah_radio_5ghz_revision)
! 221: hal->ah_radio_2ghz_revision = 0;
! 222:
! 223: /* Identify the chipset (this has to be done in an early step) */
! 224: hal->ah_version = AR5K_AR5212;
! 225: hal->ah_radio = hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112 ?
! 226: AR5K_AR5111 : AR5K_AR5112;
! 227: hal->ah_phy = AR5K_AR5212_PHY(0);
! 228:
! 229: bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
! 230: ar5k_ar5212_set_associd(hal, mac, 0, 0);
! 231: ar5k_ar5212_get_lladdr(hal, mac);
! 232: ar5k_ar5212_set_opmode(hal);
! 233:
! 234: return (hal);
! 235: }
! 236:
! 237: HAL_BOOL
! 238: ar5k_ar5212_nic_reset(struct ath_hal *hal, u_int32_t val)
! 239: {
! 240: HAL_BOOL ret = AH_FALSE;
! 241: u_int32_t mask = val ? val : ~0;
! 242:
! 243: /* Read-and-clear */
! 244: AR5K_REG_READ(AR5K_AR5212_RXDP);
! 245:
! 246: /*
! 247: * Reset the device and wait until success
! 248: */
! 249: AR5K_REG_WRITE(AR5K_AR5212_RC, val);
! 250:
! 251: /* Wait at least 128 PCI clocks */
! 252: AR5K_DELAY(15);
! 253:
! 254: val &=
! 255: AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB;
! 256:
! 257: mask &=
! 258: AR5K_AR5212_RC_PCU | AR5K_AR5212_RC_BB;
! 259:
! 260: ret = ar5k_register_timeout(hal, AR5K_AR5212_RC, mask, val, AH_FALSE);
! 261:
! 262: /*
! 263: * Reset configuration register
! 264: */
! 265: if ((val & AR5K_AR5212_RC_PCU) == 0)
! 266: AR5K_REG_WRITE(AR5K_AR5212_CFG, AR5K_AR5212_INIT_CFG);
! 267:
! 268: return (ret);
! 269: }
! 270:
! 271: HAL_BOOL
! 272: ar5k_ar5212_nic_wakeup(struct ath_hal *hal, u_int16_t flags)
! 273: {
! 274: u_int32_t turbo, mode, clock;
! 275:
! 276: turbo = 0;
! 277: mode = 0;
! 278: clock = 0;
! 279:
! 280: /*
! 281: * Get channel mode flags
! 282: */
! 283:
! 284: if (hal->ah_radio >= AR5K_AR5112) {
! 285: mode = AR5K_AR5212_PHY_MODE_RAD_AR5112;
! 286: clock = AR5K_AR5212_PHY_PLL_AR5112;
! 287: } else {
! 288: mode = AR5K_AR5212_PHY_MODE_RAD_AR5111;
! 289: clock = AR5K_AR5212_PHY_PLL_AR5111;
! 290: }
! 291:
! 292: if (flags & IEEE80211_CHAN_2GHZ) {
! 293: mode |= AR5K_AR5212_PHY_MODE_FREQ_2GHZ;
! 294: clock |= AR5K_AR5212_PHY_PLL_44MHZ;
! 295: } else if (flags & IEEE80211_CHAN_5GHZ) {
! 296: mode |= AR5K_AR5212_PHY_MODE_FREQ_5GHZ;
! 297: clock |= AR5K_AR5212_PHY_PLL_40MHZ;
! 298: } else {
! 299: AR5K_PRINT("invalid radio frequency mode\n");
! 300: return (AH_FALSE);
! 301: }
! 302:
! 303: if (flags & IEEE80211_CHAN_CCK) {
! 304: mode |= AR5K_AR5212_PHY_MODE_MOD_CCK;
! 305: } else if (flags & IEEE80211_CHAN_OFDM) {
! 306: mode |= AR5K_AR5212_PHY_MODE_MOD_OFDM;
! 307: } else if (flags & IEEE80211_CHAN_DYN) {
! 308: mode |= AR5K_AR5212_PHY_MODE_MOD_DYN;
! 309: } else {
! 310: AR5K_PRINT("invalid radio frequency mode\n");
! 311: return (AH_FALSE);
! 312: }
! 313:
! 314: if (flags & IEEE80211_CHAN_TURBO) {
! 315: turbo = AR5K_AR5212_PHY_TURBO_MODE |
! 316: AR5K_AR5212_PHY_TURBO_SHORT;
! 317: }
! 318:
! 319: /*
! 320: * Reset and wakeup the device
! 321: */
! 322:
! 323: /* ...reset chipset and PCI device */
! 324: if (hal->ah_single_chip == AH_FALSE &&
! 325: ar5k_ar5212_nic_reset(hal,
! 326: AR5K_AR5212_RC_CHIP | AR5K_AR5212_RC_PCI) == AH_FALSE) {
! 327: AR5K_PRINT("failed to reset the AR5212 + PCI chipset\n");
! 328: return (AH_FALSE);
! 329: }
! 330:
! 331: /* ...wakeup */
! 332: if (ar5k_ar5212_set_power(hal,
! 333: HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
! 334: AR5K_PRINT("failed to resume the AR5212 (again)\n");
! 335: return (AH_FALSE);
! 336: }
! 337:
! 338: /* ...final warm reset */
! 339: if (ar5k_ar5212_nic_reset(hal, 0) == AH_FALSE) {
! 340: AR5K_PRINT("failed to warm reset the AR5212\n");
! 341: return (AH_FALSE);
! 342: }
! 343:
! 344: /* ...set the PHY operating mode */
! 345: AR5K_REG_WRITE(AR5K_AR5212_PHY_PLL, clock);
! 346: AR5K_DELAY(300);
! 347:
! 348: AR5K_REG_WRITE(AR5K_AR5212_PHY_MODE, mode);
! 349: AR5K_REG_WRITE(AR5K_AR5212_PHY_TURBO, turbo);
! 350:
! 351: return (AH_TRUE);
! 352: }
! 353:
! 354: u_int16_t
! 355: ar5k_ar5212_radio_revision(struct ath_hal *hal, HAL_CHIP chip)
! 356: {
! 357: int i;
! 358: u_int32_t srev;
! 359: u_int16_t ret;
! 360:
! 361: /*
! 362: * Set the radio chip access register
! 363: */
! 364: switch (chip) {
! 365: case HAL_CHIP_2GHZ:
! 366: AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_2GHZ);
! 367: break;
! 368: case HAL_CHIP_5GHZ:
! 369: AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ);
! 370: break;
! 371: default:
! 372: return (0);
! 373: }
! 374:
! 375: AR5K_DELAY(2000);
! 376:
! 377: /* ...wait until PHY is ready and read the selected radio revision */
! 378: AR5K_REG_WRITE(AR5K_AR5212_PHY(0x34), 0x00001c16);
! 379:
! 380: for (i = 0; i < 8; i++)
! 381: AR5K_REG_WRITE(AR5K_AR5212_PHY(0x20), 0x00010000);
! 382: srev = (AR5K_REG_READ(AR5K_AR5212_PHY(0x100)) >> 24) & 0xff;
! 383:
! 384: ret = ar5k_bitswap(((srev & 0xf0) >> 4) | ((srev & 0x0f) << 4), 8);
! 385:
! 386: /* Reset to the 5GHz mode */
! 387: AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ);
! 388:
! 389: return (ret);
! 390: }
! 391:
! 392: const HAL_RATE_TABLE *
! 393: ar5k_ar5212_get_rate_table(struct ath_hal *hal, u_int mode)
! 394: {
! 395: switch (mode) {
! 396: case HAL_MODE_11A:
! 397: return (&hal->ah_rt_11a);
! 398: case HAL_MODE_TURBO:
! 399: return (&hal->ah_rt_turbo);
! 400: case HAL_MODE_11B:
! 401: return (&hal->ah_rt_11b);
! 402: case HAL_MODE_11G:
! 403: case HAL_MODE_PUREG:
! 404: return (&hal->ah_rt_11g);
! 405: case HAL_MODE_XR:
! 406: return (&hal->ah_rt_xr);
! 407: default:
! 408: return (NULL);
! 409: }
! 410:
! 411: return (NULL);
! 412: }
! 413:
! 414: void
! 415: ar5k_ar5212_detach(struct ath_hal *hal)
! 416: {
! 417: if (hal->ah_rf_banks != NULL)
! 418: free(hal->ah_rf_banks, M_DEVBUF);
! 419:
! 420: /*
! 421: * Free HAL structure, assume interrupts are down
! 422: */
! 423: free(hal, M_DEVBUF);
! 424: }
! 425:
! 426: HAL_BOOL
! 427: ar5k_ar5212_phy_disable(struct ath_hal *hal)
! 428: {
! 429: AR5K_REG_WRITE(AR5K_AR5212_PHY_ACTIVE, AR5K_AR5212_PHY_DISABLE);
! 430: return (AH_TRUE);
! 431: }
! 432:
! 433: HAL_BOOL
! 434: ar5k_ar5212_reset(struct ath_hal *hal, HAL_OPMODE op_mode, HAL_CHANNEL *channel,
! 435: HAL_BOOL change_channel, HAL_STATUS *status)
! 436: {
! 437: struct ar5k_eeprom_info *ee = &hal->ah_capabilities.cap_eeprom;
! 438: u_int8_t mac[IEEE80211_ADDR_LEN];
! 439: u_int32_t data, s_seq, s_ant, s_led[3];
! 440: u_int i, phy, mode, freq, off, ee_mode, ant[2];
! 441: const HAL_RATE_TABLE *rt;
! 442:
! 443: /*
! 444: * Save some registers before a reset
! 445: */
! 446: if (change_channel == AH_TRUE) {
! 447: s_seq = AR5K_REG_READ(AR5K_AR5212_DCU_SEQNUM(0));
! 448: s_ant = AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
! 449: } else {
! 450: s_seq = 0;
! 451: s_ant = 1;
! 452: }
! 453:
! 454: s_led[0] = AR5K_REG_READ(AR5K_AR5212_PCICFG) &
! 455: AR5K_AR5212_PCICFG_LEDSTATE;
! 456: s_led[1] = AR5K_REG_READ(AR5K_AR5212_GPIOCR);
! 457: s_led[2] = AR5K_REG_READ(AR5K_AR5212_GPIODO);
! 458:
! 459: if (change_channel == AH_TRUE && hal->ah_rf_banks != NULL)
! 460: ar5k_ar5212_get_rf_gain(hal);
! 461:
! 462: if (ar5k_ar5212_nic_wakeup(hal, channel->c_channel_flags) == AH_FALSE)
! 463: return (AH_FALSE);
! 464:
! 465: /*
! 466: * Initialize operating mode
! 467: */
! 468: hal->ah_op_mode = op_mode;
! 469:
! 470: if (hal->ah_radio == AR5K_AR5111) {
! 471: phy = AR5K_INI_PHY_5111;
! 472: } else if (hal->ah_radio == AR5K_AR5112) {
! 473: phy = AR5K_INI_PHY_5112;
! 474: } else {
! 475: AR5K_PRINTF("invalid phy radio: %u\n", hal->ah_radio);
! 476: return (AH_FALSE);
! 477: }
! 478:
! 479: switch (channel->c_channel_flags & CHANNEL_MODES) {
! 480: case CHANNEL_A:
! 481: mode = AR5K_INI_VAL_11A;
! 482: freq = AR5K_INI_RFGAIN_5GHZ;
! 483: ee_mode = AR5K_EEPROM_MODE_11A;
! 484: break;
! 485: case CHANNEL_B:
! 486: mode = AR5K_INI_VAL_11B;
! 487: freq = AR5K_INI_RFGAIN_2GHZ;
! 488: ee_mode = AR5K_EEPROM_MODE_11B;
! 489: break;
! 490: case CHANNEL_G:
! 491: case CHANNEL_PUREG:
! 492: mode = AR5K_INI_VAL_11G;
! 493: freq = AR5K_INI_RFGAIN_2GHZ;
! 494: ee_mode = AR5K_EEPROM_MODE_11G;
! 495: break;
! 496: case CHANNEL_T:
! 497: mode = AR5K_INI_VAL_11A_TURBO;
! 498: freq = AR5K_INI_RFGAIN_5GHZ;
! 499: ee_mode = AR5K_EEPROM_MODE_11A;
! 500: break;
! 501: case CHANNEL_TG:
! 502: mode = AR5K_INI_VAL_11G_TURBO;
! 503: freq = AR5K_INI_RFGAIN_2GHZ;
! 504: ee_mode = AR5K_EEPROM_MODE_11G;
! 505: break;
! 506: case CHANNEL_XR:
! 507: mode = AR5K_INI_VAL_XR;
! 508: freq = AR5K_INI_RFGAIN_5GHZ;
! 509: ee_mode = AR5K_EEPROM_MODE_11A;
! 510: break;
! 511: default:
! 512: AR5K_PRINTF("invalid channel: %d\n", channel->c_channel);
! 513: return (AH_FALSE);
! 514: }
! 515:
! 516: /* PHY access enable */
! 517: AR5K_REG_WRITE(AR5K_AR5212_PHY(0), AR5K_AR5212_PHY_SHIFT_5GHZ);
! 518:
! 519: /*
! 520: * Write initial mode settings
! 521: */
! 522: for (i = 0; i < AR5K_ELEMENTS(ar5212_mode); i++) {
! 523: if (ar5212_mode[i].mode_flags == AR5K_INI_FLAG_511X)
! 524: off = AR5K_INI_PHY_511X;
! 525: else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5111 &&
! 526: hal->ah_radio == AR5K_AR5111)
! 527: off = AR5K_INI_PHY_5111;
! 528: else if (ar5212_mode[i].mode_flags & AR5K_INI_FLAG_5112 &&
! 529: hal->ah_radio == AR5K_AR5112)
! 530: off = AR5K_INI_PHY_5112;
! 531: else
! 532: continue;
! 533:
! 534: AR5K_REG_WAIT(i);
! 535: AR5K_REG_WRITE((u_int32_t)ar5212_mode[i].mode_register,
! 536: ar5212_mode[i].mode_value[off][mode]);
! 537: }
! 538:
! 539: /*
! 540: * Write initial register settings
! 541: */
! 542: for (i = 0; i < AR5K_ELEMENTS(ar5212_ini); i++) {
! 543: if (change_channel == AH_TRUE &&
! 544: ar5212_ini[i].ini_register >= AR5K_AR5212_PCU_MIN &&
! 545: ar5212_ini[i].ini_register <= AR5K_AR5212_PCU_MAX)
! 546: continue;
! 547:
! 548: if ((hal->ah_radio == AR5K_AR5111 &&
! 549: ar5212_ini[i].ini_flags & AR5K_INI_FLAG_5111) ||
! 550: (hal->ah_radio == AR5K_AR5112 &&
! 551: ar5212_ini[i].ini_flags & AR5K_INI_FLAG_5112)) {
! 552: AR5K_REG_WAIT(i);
! 553: AR5K_REG_WRITE((u_int32_t)ar5212_ini[i].ini_register,
! 554: ar5212_ini[i].ini_value);
! 555: }
! 556: }
! 557:
! 558: /*
! 559: * Write initial RF gain settings
! 560: */
! 561: if (ar5k_rfgain(hal, phy, freq) == AH_FALSE)
! 562: return (AH_FALSE);
! 563:
! 564: AR5K_DELAY(1000);
! 565:
! 566: /*
! 567: * Set rate duration table
! 568: */
! 569: rt = ar5k_ar5212_get_rate_table(hal,
! 570: channel->c_channel_flags & IEEE80211_CHAN_TURBO ?
! 571: HAL_MODE_TURBO : HAL_MODE_XR);
! 572:
! 573: for (i = 0; i < rt->rt_rate_count; i++) {
! 574: AR5K_REG_WRITE(AR5K_AR5212_RATE_DUR(rt->rt_info[i].r_rate_code),
! 575: ath_hal_computetxtime(hal, rt, 14,
! 576: rt->rt_info[i].r_control_rate, AH_FALSE));
! 577: }
! 578:
! 579: if ((channel->c_channel_flags & IEEE80211_CHAN_TURBO) == 0) {
! 580: rt = ar5k_ar5212_get_rate_table(hal, HAL_MODE_11B);
! 581: for (i = 0; i < rt->rt_rate_count; i++) {
! 582: data = AR5K_AR5212_RATE_DUR(rt->rt_info[i].r_rate_code);
! 583: AR5K_REG_WRITE(data,
! 584: ath_hal_computetxtime(hal, rt, 14,
! 585: rt->rt_info[i].r_control_rate, AH_FALSE));
! 586: if (rt->rt_info[i].r_short_preamble) {
! 587: AR5K_REG_WRITE(data +
! 588: (rt->rt_info[i].r_short_preamble << 2),
! 589: ath_hal_computetxtime(hal, rt, 14,
! 590: rt->rt_info[i].r_control_rate, AH_FALSE));
! 591: }
! 592: }
! 593: }
! 594:
! 595: /* Fix for first revision of the AR5112 RF chipset */
! 596: if (hal->ah_radio >= AR5K_AR5112 &&
! 597: hal->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
! 598: AR5K_REG_WRITE(AR5K_AR5212_PHY_CCKTXCTL,
! 599: AR5K_AR5212_PHY_CCKTXCTL_WORLD);
! 600: if (channel->c_channel_flags & IEEE80211_CHAN_OFDM)
! 601: data = 0xffb81020;
! 602: else
! 603: data = 0xffb80d20;
! 604: AR5K_REG_WRITE(AR5K_AR5212_PHY_FC, data);
! 605: }
! 606:
! 607: /*
! 608: * Set TX power (XXX use txpower from net80211)
! 609: */
! 610: if (ar5k_ar5212_txpower(hal, channel,
! 611: AR5K_TUNE_DEFAULT_TXPOWER) == AH_FALSE)
! 612: return (AH_FALSE);
! 613:
! 614: /*
! 615: * Write RF registers
! 616: */
! 617: if (ar5k_rfregs(hal, channel, mode) == AH_FALSE)
! 618: return (AH_FALSE);
! 619:
! 620: /*
! 621: * Configure additional registers
! 622: */
! 623:
! 624: /* OFDM timings */
! 625: if (channel->c_channel_flags & IEEE80211_CHAN_OFDM) {
! 626: u_int32_t coef_scaled, coef_exp, coef_man, ds_coef_exp,
! 627: ds_coef_man, clock;
! 628:
! 629: clock = channel->c_channel_flags & IEEE80211_CHAN_T ? 80 : 40;
! 630: coef_scaled = ((5 * (clock << 24)) / 2) / channel->c_channel;
! 631:
! 632: for (coef_exp = 31; coef_exp > 0; coef_exp--)
! 633: if ((coef_scaled >> coef_exp) & 0x1)
! 634: break;
! 635:
! 636: if (!coef_exp)
! 637: return (AH_FALSE);
! 638:
! 639: coef_exp = 14 - (coef_exp - 24);
! 640: coef_man = coef_scaled + (1 << (24 - coef_exp - 1));
! 641: ds_coef_man = coef_man >> (24 - coef_exp);
! 642: ds_coef_exp = coef_exp - 16;
! 643:
! 644: AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_TIMING_3,
! 645: AR5K_AR5212_PHY_TIMING_3_DSC_MAN, ds_coef_man);
! 646: AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_TIMING_3,
! 647: AR5K_AR5212_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
! 648: }
! 649:
! 650: if (hal->ah_radio == AR5K_AR5111) {
! 651: if (channel->c_channel_flags & IEEE80211_CHAN_B)
! 652: AR5K_REG_ENABLE_BITS(AR5K_AR5212_TXCFG,
! 653: AR5K_AR5212_TXCFG_B_MODE);
! 654: else
! 655: AR5K_REG_DISABLE_BITS(AR5K_AR5212_TXCFG,
! 656: AR5K_AR5212_TXCFG_B_MODE);
! 657: }
! 658:
! 659: /* Set antenna mode */
! 660: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x44),
! 661: hal->ah_antenna[ee_mode][0], 0xfffffc06);
! 662:
! 663: if (freq == AR5K_INI_RFGAIN_2GHZ)
! 664: ant[0] = ant[1] = HAL_ANT_FIXED_B;
! 665: else
! 666: ant[0] = ant[1] = HAL_ANT_FIXED_A;
! 667:
! 668: AR5K_REG_WRITE(AR5K_AR5212_PHY_ANT_SWITCH_TABLE_0,
! 669: hal->ah_antenna[ee_mode][ant[0]]);
! 670: AR5K_REG_WRITE(AR5K_AR5212_PHY_ANT_SWITCH_TABLE_1,
! 671: hal->ah_antenna[ee_mode][ant[1]]);
! 672:
! 673: /* Commit values from EEPROM */
! 674: if (hal->ah_radio == AR5K_AR5111)
! 675: AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_FC,
! 676: AR5K_AR5212_PHY_FC_TX_CLIP, ee->ee_tx_clip);
! 677:
! 678: AR5K_REG_WRITE(AR5K_AR5212_PHY(0x5a),
! 679: AR5K_AR5212_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]));
! 680:
! 681: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x11),
! 682: (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f);
! 683: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x12),
! 684: (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff);
! 685: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x14),
! 686: (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
! 687: ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000);
! 688:
! 689: AR5K_REG_WRITE(AR5K_AR5212_PHY(0x0d),
! 690: (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
! 691: (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
! 692: (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
! 693: (ee->ee_tx_frm2xpa_enable[ee_mode]));
! 694:
! 695: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x0a),
! 696: ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
! 697: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x19),
! 698: (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
! 699: AR5K_REG_MASKED_BITS(AR5K_AR5212_PHY(0x49), 4, 0xffffff01);
! 700:
! 701: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ,
! 702: AR5K_AR5212_PHY_IQ_CORR_ENABLE |
! 703: (ee->ee_i_cal[ee_mode] << AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF_S) |
! 704: ee->ee_q_cal[ee_mode]);
! 705:
! 706: if (hal->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
! 707: AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_GAIN_2GHZ,
! 708: AR5K_AR5212_PHY_GAIN_2GHZ_MARGIN_TXRX,
! 709: ee->ee_margin_tx_rx[ee_mode]);
! 710: }
! 711:
! 712: /*
! 713: * Restore saved values
! 714: */
! 715: AR5K_REG_WRITE(AR5K_AR5212_DCU_SEQNUM(0), s_seq);
! 716: AR5K_REG_WRITE(AR5K_AR5212_DEFAULT_ANTENNA, s_ant);
! 717: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG, s_led[0]);
! 718: AR5K_REG_WRITE(AR5K_AR5212_GPIOCR, s_led[1]);
! 719: AR5K_REG_WRITE(AR5K_AR5212_GPIODO, s_led[2]);
! 720:
! 721: /*
! 722: * Misc
! 723: */
! 724: bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
! 725: ar5k_ar5212_set_associd(hal, mac, 0, 0);
! 726: ar5k_ar5212_set_opmode(hal);
! 727: AR5K_REG_WRITE(AR5K_AR5212_PISR, 0xffffffff);
! 728: AR5K_REG_WRITE(AR5K_AR5212_RSSI_THR, AR5K_TUNE_RSSI_THRES);
! 729:
! 730: /*
! 731: * Set Rx/Tx DMA Configuration
! 732: */
! 733: AR5K_REG_WRITE_BITS(AR5K_AR5212_TXCFG, AR5K_AR5212_TXCFG_SDMAMR,
! 734: AR5K_AR5212_DMASIZE_512B | AR5K_AR5212_TXCFG_DMASIZE);
! 735: AR5K_REG_WRITE_BITS(AR5K_AR5212_RXCFG, AR5K_AR5212_RXCFG_SDMAMW,
! 736: AR5K_AR5212_DMASIZE_512B);
! 737:
! 738: /*
! 739: * Set channel and calibrate the PHY
! 740: */
! 741: if (ar5k_channel(hal, channel) == AH_FALSE)
! 742: return (AH_FALSE);
! 743:
! 744: /*
! 745: * Enable the PHY and wait until completion
! 746: */
! 747: AR5K_REG_WRITE(AR5K_AR5212_PHY_ACTIVE, AR5K_AR5212_PHY_ENABLE);
! 748:
! 749: data = AR5K_REG_READ(AR5K_AR5212_PHY_RX_DELAY) &
! 750: AR5K_AR5212_PHY_RX_DELAY_M;
! 751: data = (channel->c_channel_flags & IEEE80211_CHAN_CCK) ?
! 752: ((data << 2) / 22) : (data / 10);
! 753:
! 754: AR5K_DELAY(100 + data);
! 755:
! 756: /*
! 757: * Start calibration
! 758: */
! 759: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_AGCCTL,
! 760: AR5K_AR5212_PHY_AGCCTL_NF |
! 761: AR5K_AR5212_PHY_AGCCTL_CAL);
! 762:
! 763: hal->ah_calibration = AH_FALSE;
! 764: if ((channel->c_channel_flags & IEEE80211_CHAN_B) == 0) {
! 765: hal->ah_calibration = AH_TRUE;
! 766: AR5K_REG_WRITE_BITS(AR5K_AR5212_PHY_IQ,
! 767: AR5K_AR5212_PHY_IQ_CAL_NUM_LOG_MAX, 15);
! 768: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ,
! 769: AR5K_AR5212_PHY_IQ_RUN);
! 770: }
! 771:
! 772: /*
! 773: * Reset queues and start beacon timers at the end of the reset routine
! 774: */
! 775: for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) {
! 776: AR5K_REG_WRITE_Q(AR5K_AR5212_DCU_QCUMASK(i), i);
! 777: if (ar5k_ar5212_reset_tx_queue(hal, i) == AH_FALSE) {
! 778: AR5K_PRINTF("failed to reset TX queue #%d\n", i);
! 779: return (AH_FALSE);
! 780: }
! 781: }
! 782:
! 783: /* Pre-enable interrupts */
! 784: ar5k_ar5212_set_intr(hal, HAL_INT_RX | HAL_INT_TX | HAL_INT_FATAL);
! 785:
! 786: /*
! 787: * Set RF kill flags if supported by the device (read from the EEPROM)
! 788: */
! 789: if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) {
! 790: ar5k_ar5212_set_gpio_input(hal, 0);
! 791: if ((hal->ah_gpio[0] = ar5k_ar5212_get_gpio(hal, 0)) == 0)
! 792: ar5k_ar5212_set_gpio_intr(hal, 0, 1);
! 793: else
! 794: ar5k_ar5212_set_gpio_intr(hal, 0, 0);
! 795: }
! 796:
! 797: /*
! 798: * Set the 32MHz reference clock
! 799: */
! 800: AR5K_REG_WRITE(AR5K_AR5212_PHY_SCR, AR5K_AR5212_PHY_SCR_32MHZ);
! 801: AR5K_REG_WRITE(AR5K_AR5212_PHY_SLMT, AR5K_AR5212_PHY_SLMT_32MHZ);
! 802: AR5K_REG_WRITE(AR5K_AR5212_PHY_SCAL, AR5K_AR5212_PHY_SCAL_32MHZ);
! 803: AR5K_REG_WRITE(AR5K_AR5212_PHY_SCLOCK, AR5K_AR5212_PHY_SCLOCK_32MHZ);
! 804: AR5K_REG_WRITE(AR5K_AR5212_PHY_SDELAY, AR5K_AR5212_PHY_SDELAY_32MHZ);
! 805: AR5K_REG_WRITE(AR5K_AR5212_PHY_SPENDING, hal->ah_radio == AR5K_AR5111 ?
! 806: AR5K_AR5212_PHY_SPENDING_AR5111 : AR5K_AR5212_PHY_SPENDING_AR5112);
! 807:
! 808: /*
! 809: * Disable beacons and reset the register
! 810: */
! 811: AR5K_REG_DISABLE_BITS(AR5K_AR5212_BEACON,
! 812: AR5K_AR5212_BEACON_ENABLE | AR5K_AR5212_BEACON_RESET_TSF);
! 813:
! 814: return (AH_TRUE);
! 815: }
! 816:
! 817: void
! 818: ar5k_ar5212_set_def_antenna(struct ath_hal *hal, u_int ant)
! 819: {
! 820: AR5K_REG_WRITE(AR5K_AR5212_DEFAULT_ANTENNA, ant);
! 821: }
! 822:
! 823: u_int
! 824: ar5k_ar5212_get_def_antenna(struct ath_hal *hal)
! 825: {
! 826: return AR5K_REG_READ(AR5K_AR5212_DEFAULT_ANTENNA);
! 827: }
! 828:
! 829: void
! 830: ar5k_ar5212_set_opmode(struct ath_hal *hal)
! 831: {
! 832: u_int32_t pcu_reg, low_id, high_id;
! 833:
! 834: pcu_reg = 0;
! 835:
! 836: switch (hal->ah_op_mode) {
! 837: case IEEE80211_M_IBSS:
! 838: pcu_reg |= AR5K_AR5212_STA_ID1_ADHOC |
! 839: AR5K_AR5212_STA_ID1_DESC_ANTENNA;
! 840: break;
! 841:
! 842: case IEEE80211_M_HOSTAP:
! 843: pcu_reg |= AR5K_AR5212_STA_ID1_AP |
! 844: AR5K_AR5212_STA_ID1_RTS_DEFAULT_ANTENNA;
! 845: break;
! 846:
! 847: case IEEE80211_M_STA:
! 848: case IEEE80211_M_MONITOR:
! 849: pcu_reg |= AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA;
! 850: break;
! 851:
! 852: default:
! 853: return;
! 854: }
! 855:
! 856: /*
! 857: * Set PCU registers
! 858: */
! 859: low_id = AR5K_LOW_ID(hal->ah_sta_id);
! 860: high_id = AR5K_HIGH_ID(hal->ah_sta_id);
! 861: AR5K_REG_WRITE(AR5K_AR5212_STA_ID0, low_id);
! 862: AR5K_REG_WRITE(AR5K_AR5212_STA_ID1, pcu_reg | high_id);
! 863:
! 864: return;
! 865: }
! 866:
! 867: HAL_BOOL
! 868: ar5k_ar5212_calibrate(struct ath_hal *hal, HAL_CHANNEL *channel)
! 869: {
! 870: u_int32_t i_pwr, q_pwr;
! 871: int32_t iq_corr, i_coff, i_coffd, q_coff, q_coffd;
! 872:
! 873: if (hal->ah_calibration == AH_FALSE ||
! 874: AR5K_REG_READ(AR5K_AR5212_PHY_IQ) & AR5K_AR5212_PHY_IQ_RUN)
! 875: goto done;
! 876:
! 877: hal->ah_calibration = AH_FALSE;
! 878:
! 879: iq_corr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_CORR);
! 880: i_pwr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_PWR_I);
! 881: q_pwr = AR5K_REG_READ(AR5K_AR5212_PHY_IQRES_CAL_PWR_Q);
! 882: i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
! 883: q_coffd = q_pwr >> 6;
! 884:
! 885: if (i_coffd == 0 || q_coffd == 0)
! 886: goto done;
! 887:
! 888: i_coff = ((-iq_corr) / i_coffd) & 0x3f;
! 889: q_coff = (((int32_t)i_pwr / q_coffd) - 64) & 0x1f;
! 890:
! 891: /* Commit new IQ value */
! 892: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_IQ,
! 893: AR5K_AR5212_PHY_IQ_CORR_ENABLE |
! 894: ((u_int32_t)q_coff) |
! 895: ((u_int32_t)i_coff << AR5K_AR5212_PHY_IQ_CORR_Q_I_COFF_S));
! 896:
! 897: done:
! 898: /* Start noise floor calibration */
! 899: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PHY_AGCCTL,
! 900: AR5K_AR5212_PHY_AGCCTL_NF);
! 901:
! 902: /* Request RF gain */
! 903: if (channel->c_channel_flags & IEEE80211_CHAN_5GHZ) {
! 904: AR5K_REG_WRITE(AR5K_AR5212_PHY_PAPD_PROBE,
! 905: AR5K_REG_SM(hal->ah_txpower.txp_max,
! 906: AR5K_AR5212_PHY_PAPD_PROBE_TXPOWER) |
! 907: AR5K_AR5212_PHY_PAPD_PROBE_TX_NEXT);
! 908: hal->ah_rf_gain = HAL_RFGAIN_READ_REQUESTED;
! 909: }
! 910:
! 911: return (AH_TRUE);
! 912: }
! 913:
! 914: /*
! 915: * Transmit functions
! 916: */
! 917:
! 918: HAL_BOOL
! 919: ar5k_ar5212_update_tx_triglevel(struct ath_hal *hal, HAL_BOOL increase)
! 920: {
! 921: u_int32_t trigger_level, imr;
! 922: HAL_BOOL status = AH_FALSE;
! 923:
! 924: /*
! 925: * Disable interrupts by setting the mask
! 926: */
! 927: imr = ar5k_ar5212_set_intr(hal, hal->ah_imr & ~HAL_INT_GLOBAL);
! 928:
! 929: trigger_level = AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TXCFG),
! 930: AR5K_AR5212_TXCFG_TXFULL);
! 931:
! 932: if (increase == AH_FALSE) {
! 933: if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
! 934: goto done;
! 935: } else
! 936: trigger_level +=
! 937: ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
! 938:
! 939: /*
! 940: * Update trigger level on success
! 941: */
! 942: AR5K_REG_WRITE_BITS(AR5K_AR5212_TXCFG,
! 943: AR5K_AR5212_TXCFG_TXFULL, trigger_level);
! 944: status = AH_TRUE;
! 945:
! 946: done:
! 947: /*
! 948: * Restore interrupt mask
! 949: */
! 950: ar5k_ar5212_set_intr(hal, imr);
! 951:
! 952: return (status);
! 953: }
! 954:
! 955: int
! 956: ar5k_ar5212_setup_tx_queue(struct ath_hal *hal, HAL_TX_QUEUE queue_type,
! 957: const HAL_TXQ_INFO *queue_info)
! 958: {
! 959: u_int queue;
! 960:
! 961: /*
! 962: * Get queue by type
! 963: */
! 964: if (queue_type == HAL_TX_QUEUE_DATA) {
! 965: for (queue = HAL_TX_QUEUE_ID_DATA_MIN;
! 966: hal->ah_txq[queue].tqi_type != HAL_TX_QUEUE_INACTIVE;
! 967: queue++)
! 968: if (queue > HAL_TX_QUEUE_ID_DATA_MAX)
! 969: return (-1);
! 970: } else if (queue_type == HAL_TX_QUEUE_PSPOLL) {
! 971: queue = HAL_TX_QUEUE_ID_PSPOLL;
! 972: } else if (queue_type == HAL_TX_QUEUE_BEACON) {
! 973: queue = HAL_TX_QUEUE_ID_BEACON;
! 974: } else if (queue_type == HAL_TX_QUEUE_CAB) {
! 975: queue = HAL_TX_QUEUE_ID_CAB;
! 976: } else
! 977: return (-1);
! 978:
! 979: /*
! 980: * Setup internal queue structure
! 981: */
! 982: bzero(&hal->ah_txq[queue], sizeof(HAL_TXQ_INFO));
! 983: if (queue_info != NULL) {
! 984: if (ar5k_ar5212_setup_tx_queueprops(hal, queue, queue_info)
! 985: != AH_TRUE)
! 986: return (-1);
! 987: }
! 988: hal->ah_txq[queue].tqi_type = queue_type;
! 989:
! 990: AR5K_Q_ENABLE_BITS(hal->ah_txq_interrupts, queue);
! 991:
! 992: return (queue);
! 993: }
! 994:
! 995: HAL_BOOL
! 996: ar5k_ar5212_setup_tx_queueprops(struct ath_hal *hal, int queue,
! 997: const HAL_TXQ_INFO *queue_info)
! 998: {
! 999: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1000:
! 1001: if (hal->ah_txq[queue].tqi_type != HAL_TX_QUEUE_INACTIVE)
! 1002: return (AH_FALSE);
! 1003:
! 1004: bcopy(queue_info, &hal->ah_txq[queue], sizeof(HAL_TXQ_INFO));
! 1005:
! 1006: if (queue_info->tqi_type == HAL_TX_QUEUE_DATA &&
! 1007: (queue_info->tqi_subtype >= HAL_WME_AC_VI) &&
! 1008: (queue_info->tqi_subtype <= HAL_WME_UPSD))
! 1009: hal->ah_txq[queue].tqi_flags |=
! 1010: AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
! 1011:
! 1012: return (AH_TRUE);
! 1013: }
! 1014:
! 1015: HAL_BOOL
! 1016: ar5k_ar5212_get_tx_queueprops(struct ath_hal *hal, int queue,
! 1017: HAL_TXQ_INFO *queue_info)
! 1018: {
! 1019: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1020: bcopy(&hal->ah_txq[queue], queue_info, sizeof(HAL_TXQ_INFO));
! 1021: return (AH_TRUE);
! 1022: }
! 1023:
! 1024: HAL_BOOL
! 1025: ar5k_ar5212_release_tx_queue(struct ath_hal *hal, u_int queue)
! 1026: {
! 1027: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1028:
! 1029: /* This queue will be skipped in further operations */
! 1030: hal->ah_txq[queue].tqi_type = HAL_TX_QUEUE_INACTIVE;
! 1031: AR5K_Q_DISABLE_BITS(hal->ah_txq_interrupts, queue);
! 1032:
! 1033: return (AH_FALSE);
! 1034: }
! 1035:
! 1036: HAL_BOOL
! 1037: ar5k_ar5212_reset_tx_queue(struct ath_hal *hal, u_int queue)
! 1038: {
! 1039: u_int32_t cw_min, cw_max, retry_lg, retry_sh;
! 1040: struct ieee80211_channel *channel = (struct ieee80211_channel*)
! 1041: &hal->ah_current_channel;
! 1042: HAL_TXQ_INFO *tq;
! 1043:
! 1044: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1045:
! 1046: tq = &hal->ah_txq[queue];
! 1047:
! 1048: if (tq->tqi_type == HAL_TX_QUEUE_INACTIVE)
! 1049: return (AH_TRUE);
! 1050:
! 1051: /*
! 1052: * Set registers by channel mode
! 1053: */
! 1054: cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN;
! 1055: cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX;
! 1056: hal->ah_aifs = AR5K_TUNE_AIFS;
! 1057: if (IEEE80211_IS_CHAN_XR(channel)) {
! 1058: cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN_XR;
! 1059: cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX_XR;
! 1060: hal->ah_aifs = AR5K_TUNE_AIFS_XR;
! 1061: } else if (IEEE80211_IS_CHAN_B(channel)) {
! 1062: cw_min = hal->ah_cw_min = AR5K_TUNE_CWMIN_11B;
! 1063: cw_max = hal->ah_cw_max = AR5K_TUNE_CWMAX_11B;
! 1064: hal->ah_aifs = AR5K_TUNE_AIFS_11B;
! 1065: }
! 1066:
! 1067: /*
! 1068: * Set retry limits
! 1069: */
! 1070: if (hal->ah_software_retry == AH_TRUE) {
! 1071: /* XXX Need to test this */
! 1072: retry_lg = hal->ah_limit_tx_retries;
! 1073: retry_sh = retry_lg =
! 1074: retry_lg > AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY ?
! 1075: AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY : retry_lg;
! 1076: } else {
! 1077: retry_lg = AR5K_INIT_LG_RETRY;
! 1078: retry_sh = AR5K_INIT_SH_RETRY;
! 1079: }
! 1080:
! 1081: AR5K_REG_WRITE(AR5K_AR5212_DCU_RETRY_LMT(queue),
! 1082: AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
! 1083: AR5K_AR5212_DCU_RETRY_LMT_SLG_RETRY) |
! 1084: AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
! 1085: AR5K_AR5212_DCU_RETRY_LMT_SSH_RETRY) |
! 1086: AR5K_REG_SM(retry_lg, AR5K_AR5212_DCU_RETRY_LMT_LG_RETRY) |
! 1087: AR5K_REG_SM(retry_sh, AR5K_AR5212_DCU_RETRY_LMT_SH_RETRY));
! 1088:
! 1089: /*
! 1090: * Set initial content window (cw_min/cw_max)
! 1091: */
! 1092: cw_min = 1;
! 1093: while (cw_min < hal->ah_cw_min)
! 1094: cw_min = (cw_min << 1) | 1;
! 1095:
! 1096: cw_min = tq->tqi_cw_min < 0 ?
! 1097: (cw_min >> (-tq->tqi_cw_min)) :
! 1098: ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
! 1099: cw_max = tq->tqi_cw_max < 0 ?
! 1100: (cw_max >> (-tq->tqi_cw_max)) :
! 1101: ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
! 1102:
! 1103: AR5K_REG_WRITE(AR5K_AR5212_DCU_LCL_IFS(queue),
! 1104: AR5K_REG_SM(cw_min, AR5K_AR5212_DCU_LCL_IFS_CW_MIN) |
! 1105: AR5K_REG_SM(cw_max, AR5K_AR5212_DCU_LCL_IFS_CW_MAX) |
! 1106: AR5K_REG_SM(hal->ah_aifs + tq->tqi_aifs,
! 1107: AR5K_AR5212_DCU_LCL_IFS_AIFS));
! 1108:
! 1109: /*
! 1110: * Set misc registers
! 1111: */
! 1112: AR5K_REG_WRITE(AR5K_AR5212_QCU_MISC(queue),
! 1113: AR5K_AR5212_QCU_MISC_DCU_EARLY);
! 1114:
! 1115: if (tq->tqi_cbr_period) {
! 1116: AR5K_REG_WRITE(AR5K_AR5212_QCU_CBRCFG(queue),
! 1117: AR5K_REG_SM(tq->tqi_cbr_period,
! 1118: AR5K_AR5212_QCU_CBRCFG_INTVAL) |
! 1119: AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
! 1120: AR5K_AR5212_QCU_CBRCFG_ORN_THRES));
! 1121: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1122: AR5K_AR5212_QCU_MISC_FRSHED_CBR);
! 1123: if (tq->tqi_cbr_overflow_limit)
! 1124: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1125: AR5K_AR5212_QCU_MISC_CBR_THRES_ENABLE);
! 1126: }
! 1127:
! 1128: if (tq->tqi_ready_time) {
! 1129: AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue),
! 1130: AR5K_REG_SM(tq->tqi_ready_time,
! 1131: AR5K_AR5212_QCU_RDYTIMECFG_INTVAL) |
! 1132: AR5K_AR5212_QCU_RDYTIMECFG_ENABLE);
! 1133: }
! 1134:
! 1135: if (tq->tqi_burst_time) {
! 1136: AR5K_REG_WRITE(AR5K_AR5212_DCU_CHAN_TIME(queue),
! 1137: AR5K_REG_SM(tq->tqi_burst_time,
! 1138: AR5K_AR5212_DCU_CHAN_TIME_DUR) |
! 1139: AR5K_AR5212_DCU_CHAN_TIME_ENABLE);
! 1140:
! 1141: if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) {
! 1142: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1143: AR5K_AR5212_QCU_MISC_TXE);
! 1144: }
! 1145: }
! 1146:
! 1147: if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) {
! 1148: AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue),
! 1149: AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS);
! 1150: }
! 1151:
! 1152: if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
! 1153: AR5K_REG_WRITE(AR5K_AR5212_DCU_MISC(queue),
! 1154: AR5K_AR5212_DCU_MISC_BACKOFF_FRAG);
! 1155: }
! 1156:
! 1157: /*
! 1158: * Set registers by queue type
! 1159: */
! 1160: switch (tq->tqi_type) {
! 1161: case HAL_TX_QUEUE_BEACON:
! 1162: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1163: AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT |
! 1164: AR5K_AR5212_QCU_MISC_CBREXP_BCN |
! 1165: AR5K_AR5212_QCU_MISC_BCN_ENABLE);
! 1166:
! 1167: AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue),
! 1168: (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
! 1169: AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL) |
! 1170: AR5K_AR5212_DCU_MISC_POST_FR_BKOFF_DIS |
! 1171: AR5K_AR5212_DCU_MISC_BCN_ENABLE);
! 1172:
! 1173: AR5K_REG_WRITE(AR5K_AR5212_QCU_RDYTIMECFG(queue),
! 1174: ((AR5K_TUNE_BEACON_INTERVAL -
! 1175: (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) -
! 1176: AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
! 1177: AR5K_AR5212_QCU_RDYTIMECFG_ENABLE);
! 1178: break;
! 1179:
! 1180: case HAL_TX_QUEUE_CAB:
! 1181: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1182: AR5K_AR5212_QCU_MISC_FRSHED_DBA_GT |
! 1183: AR5K_AR5212_QCU_MISC_CBREXP |
! 1184: AR5K_AR5212_QCU_MISC_CBREXP_BCN);
! 1185:
! 1186: AR5K_REG_ENABLE_BITS(AR5K_AR5212_DCU_MISC(queue),
! 1187: (AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
! 1188: AR5K_AR5212_DCU_MISC_ARBLOCK_CTL_GLOBAL));
! 1189: break;
! 1190:
! 1191: case HAL_TX_QUEUE_PSPOLL:
! 1192: AR5K_REG_ENABLE_BITS(AR5K_AR5212_QCU_MISC(queue),
! 1193: AR5K_AR5212_QCU_MISC_CBREXP);
! 1194: break;
! 1195:
! 1196: case HAL_TX_QUEUE_DATA:
! 1197: default:
! 1198: break;
! 1199: }
! 1200:
! 1201: /*
! 1202: * Enable tx queue in the secondary interrupt mask registers
! 1203: */
! 1204: AR5K_REG_WRITE(AR5K_AR5212_SIMR0,
! 1205: AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXOK) |
! 1206: AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR0_QCU_TXDESC));
! 1207: AR5K_REG_WRITE(AR5K_AR5212_SIMR1,
! 1208: AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR1_QCU_TXERR));
! 1209: AR5K_REG_WRITE(AR5K_AR5212_SIMR2,
! 1210: AR5K_REG_SM(hal->ah_txq_interrupts, AR5K_AR5212_SIMR2_QCU_TXURN));
! 1211:
! 1212: return (AH_TRUE);
! 1213: }
! 1214:
! 1215: u_int32_t
! 1216: ar5k_ar5212_get_tx_buf(struct ath_hal *hal, u_int queue)
! 1217: {
! 1218: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1219:
! 1220: /*
! 1221: * Get the transmit queue descriptor pointer from the selected queue
! 1222: */
! 1223: return (AR5K_REG_READ(AR5K_AR5212_QCU_TXDP(queue)));
! 1224: }
! 1225:
! 1226: HAL_BOOL
! 1227: ar5k_ar5212_put_tx_buf(struct ath_hal *hal, u_int queue, u_int32_t phys_addr)
! 1228: {
! 1229: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1230:
! 1231: /*
! 1232: * Set the transmit queue descriptor pointer for the selected queue
! 1233: * (this won't work if the queue is still active)
! 1234: */
! 1235: if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXE, queue))
! 1236: return (AH_FALSE);
! 1237:
! 1238: AR5K_REG_WRITE(AR5K_AR5212_QCU_TXDP(queue), phys_addr);
! 1239:
! 1240: return (AH_TRUE);
! 1241: }
! 1242:
! 1243: u_int32_t
! 1244: ar5k_ar5212_num_tx_pending(struct ath_hal *hal, u_int queue)
! 1245: {
! 1246: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1247: return (AR5K_AR5212_QCU_STS(queue) & AR5K_AR5212_QCU_STS_FRMPENDCNT);
! 1248: }
! 1249:
! 1250: HAL_BOOL
! 1251: ar5k_ar5212_tx_start(struct ath_hal *hal, u_int queue)
! 1252: {
! 1253: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1254:
! 1255: /* Return if queue is disabled */
! 1256: if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXD, queue))
! 1257: return (AH_FALSE);
! 1258:
! 1259: /* Start queue */
! 1260: AR5K_REG_WRITE_Q(AR5K_AR5212_QCU_TXE, queue);
! 1261:
! 1262: return (AH_TRUE);
! 1263: }
! 1264:
! 1265: HAL_BOOL
! 1266: ar5k_ar5212_stop_tx_dma(struct ath_hal *hal, u_int queue)
! 1267: {
! 1268: int i = 100, pending;
! 1269:
! 1270: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 1271:
! 1272: /*
! 1273: * Schedule TX disable and wait until queue is empty
! 1274: */
! 1275: AR5K_REG_WRITE_Q(AR5K_AR5212_QCU_TXD, queue);
! 1276:
! 1277: do {
! 1278: pending = AR5K_REG_READ(AR5K_AR5212_QCU_STS(queue)) &
! 1279: AR5K_AR5212_QCU_STS_FRMPENDCNT;
! 1280: delay(100);
! 1281: } while (--i && pending);
! 1282:
! 1283: /* Clear register */
! 1284: AR5K_REG_WRITE(AR5K_AR5212_QCU_TXD, 0);
! 1285:
! 1286: return (AH_TRUE);
! 1287: }
! 1288:
! 1289: HAL_BOOL
! 1290: ar5k_ar5212_setup_tx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1291: u_int packet_length, u_int header_length, HAL_PKT_TYPE type, u_int tx_power,
! 1292: u_int tx_rate0, u_int tx_tries0, u_int key_index, u_int antenna_mode,
! 1293: u_int flags, u_int rtscts_rate, u_int rtscts_duration)
! 1294: {
! 1295: struct ar5k_ar5212_tx_desc *tx_desc;
! 1296:
! 1297: tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0;
! 1298:
! 1299: /*
! 1300: * Validate input
! 1301: */
! 1302: if (tx_tries0 == 0)
! 1303: return (AH_FALSE);
! 1304:
! 1305: if ((tx_desc->tx_control_0 = (packet_length &
! 1306: AR5K_AR5212_DESC_TX_CTL0_FRAME_LEN)) != packet_length)
! 1307: return (AH_FALSE);
! 1308:
! 1309: tx_desc->tx_control_0 |=
! 1310: AR5K_REG_SM(tx_power, AR5K_AR5212_DESC_TX_CTL0_XMIT_POWER) |
! 1311: AR5K_REG_SM(antenna_mode, AR5K_AR5212_DESC_TX_CTL0_ANT_MODE_XMIT);
! 1312: tx_desc->tx_control_1 =
! 1313: AR5K_REG_SM(type, AR5K_AR5212_DESC_TX_CTL1_FRAME_TYPE);
! 1314: tx_desc->tx_control_2 =
! 1315: AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
! 1316: AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES0);
! 1317: tx_desc->tx_control_3 =
! 1318: tx_rate0 & AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE0;
! 1319:
! 1320: #define _TX_FLAGS(_c, _flag) \
! 1321: if (flags & HAL_TXDESC_##_flag) \
! 1322: tx_desc->tx_control_##_c |= \
! 1323: AR5K_AR5212_DESC_TX_CTL##_c##_##_flag
! 1324:
! 1325: _TX_FLAGS(0, CLRDMASK);
! 1326: _TX_FLAGS(0, VEOL);
! 1327: _TX_FLAGS(0, INTREQ);
! 1328: _TX_FLAGS(0, RTSENA);
! 1329: _TX_FLAGS(0, CTSENA);
! 1330: _TX_FLAGS(1, NOACK);
! 1331:
! 1332: #undef _TX_FLAGS
! 1333:
! 1334: /*
! 1335: * WEP crap
! 1336: */
! 1337: if (key_index != HAL_TXKEYIX_INVALID) {
! 1338: tx_desc->tx_control_0 |=
! 1339: AR5K_AR5212_DESC_TX_CTL0_ENCRYPT_KEY_VALID;
! 1340: tx_desc->tx_control_1 |=
! 1341: AR5K_REG_SM(key_index,
! 1342: AR5K_AR5212_DESC_TX_CTL1_ENCRYPT_KEY_INDEX);
! 1343: }
! 1344:
! 1345: /*
! 1346: * RTS/CTS
! 1347: */
! 1348: if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
! 1349: if ((flags & HAL_TXDESC_RTSENA) &&
! 1350: (flags & HAL_TXDESC_CTSENA))
! 1351: return (AH_FALSE);
! 1352: tx_desc->tx_control_2 |=
! 1353: rtscts_duration & AR5K_AR5212_DESC_TX_CTL2_RTS_DURATION;
! 1354: tx_desc->tx_control_3 |=
! 1355: AR5K_REG_SM(rtscts_rate,
! 1356: AR5K_AR5212_DESC_TX_CTL3_RTS_CTS_RATE);
! 1357: }
! 1358:
! 1359: return (AH_TRUE);
! 1360: }
! 1361:
! 1362: HAL_BOOL
! 1363: ar5k_ar5212_fill_tx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1364: u_int segment_length, HAL_BOOL first_segment, HAL_BOOL last_segment)
! 1365: {
! 1366: struct ar5k_ar5212_tx_desc *tx_desc;
! 1367: struct ar5k_ar5212_tx_status *tx_status;
! 1368:
! 1369: tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0;
! 1370: tx_status = (struct ar5k_ar5212_tx_status*)&desc->ds_hw[2];
! 1371:
! 1372: /* Clear status descriptor */
! 1373: bzero(tx_status, sizeof(struct ar5k_ar5212_tx_status));
! 1374:
! 1375: /* Validate segment length and initialize the descriptor */
! 1376: if ((tx_desc->tx_control_1 = (segment_length &
! 1377: AR5K_AR5212_DESC_TX_CTL1_BUF_LEN)) != segment_length)
! 1378: return (AH_FALSE);
! 1379:
! 1380: if (first_segment != AH_TRUE)
! 1381: tx_desc->tx_control_0 &= ~AR5K_AR5212_DESC_TX_CTL0_FRAME_LEN;
! 1382:
! 1383: if (last_segment != AH_TRUE)
! 1384: tx_desc->tx_control_1 |= AR5K_AR5212_DESC_TX_CTL1_MORE;
! 1385:
! 1386: return (AH_TRUE);
! 1387: }
! 1388:
! 1389: HAL_BOOL
! 1390: ar5k_ar5212_setup_xtx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1391: u_int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
! 1392: u_int tx_rate3, u_int tx_tries3)
! 1393: {
! 1394: struct ar5k_ar5212_tx_desc *tx_desc;
! 1395:
! 1396: tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0;
! 1397:
! 1398: #define _XTX_TRIES(_n) \
! 1399: if (tx_tries##_n) { \
! 1400: tx_desc->tx_control_2 |= \
! 1401: AR5K_REG_SM(tx_tries##_n, \
! 1402: AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES##_n); \
! 1403: tx_desc->tx_control_3 |= \
! 1404: AR5K_REG_SM(tx_rate##_n, \
! 1405: AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE##_n); \
! 1406: }
! 1407:
! 1408: _XTX_TRIES(1);
! 1409: _XTX_TRIES(2);
! 1410: _XTX_TRIES(3);
! 1411:
! 1412: #undef _XTX_TRIES
! 1413:
! 1414: return (AH_TRUE);
! 1415: }
! 1416:
! 1417: HAL_STATUS
! 1418: ar5k_ar5212_proc_tx_desc(struct ath_hal *hal, struct ath_desc *desc)
! 1419: {
! 1420: struct ar5k_ar5212_tx_status *tx_status;
! 1421: struct ar5k_ar5212_tx_desc *tx_desc;
! 1422:
! 1423: tx_desc = (struct ar5k_ar5212_tx_desc*)&desc->ds_ctl0;
! 1424: tx_status = (struct ar5k_ar5212_tx_status*)&desc->ds_hw[2];
! 1425:
! 1426: /* No frame has been send or error */
! 1427: if ((tx_status->tx_status_1 & AR5K_AR5212_DESC_TX_STATUS1_DONE) == 0)
! 1428: return (HAL_EINPROGRESS);
! 1429:
! 1430: /*
! 1431: * Get descriptor status
! 1432: */
! 1433: desc->ds_us.tx.ts_tstamp =
! 1434: AR5K_REG_MS(tx_status->tx_status_0,
! 1435: AR5K_AR5212_DESC_TX_STATUS0_SEND_TIMESTAMP);
! 1436: desc->ds_us.tx.ts_shortretry =
! 1437: AR5K_REG_MS(tx_status->tx_status_0,
! 1438: AR5K_AR5212_DESC_TX_STATUS0_RTS_FAIL_COUNT);
! 1439: desc->ds_us.tx.ts_longretry =
! 1440: AR5K_REG_MS(tx_status->tx_status_0,
! 1441: AR5K_AR5212_DESC_TX_STATUS0_DATA_FAIL_COUNT);
! 1442: desc->ds_us.tx.ts_seqnum =
! 1443: AR5K_REG_MS(tx_status->tx_status_1,
! 1444: AR5K_AR5212_DESC_TX_STATUS1_SEQ_NUM);
! 1445: desc->ds_us.tx.ts_rssi =
! 1446: AR5K_REG_MS(tx_status->tx_status_1,
! 1447: AR5K_AR5212_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
! 1448: desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
! 1449: AR5K_AR5212_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
! 1450: desc->ds_us.tx.ts_status = 0;
! 1451:
! 1452: switch (AR5K_REG_MS(tx_status->tx_status_1,
! 1453: AR5K_AR5212_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
! 1454: case 0:
! 1455: desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
! 1456: AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE0;
! 1457: break;
! 1458: case 1:
! 1459: desc->ds_us.tx.ts_rate =
! 1460: AR5K_REG_MS(tx_desc->tx_control_3,
! 1461: AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE1);
! 1462: desc->ds_us.tx.ts_longretry +=
! 1463: AR5K_REG_MS(tx_desc->tx_control_2,
! 1464: AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES1);
! 1465: break;
! 1466: case 2:
! 1467: desc->ds_us.tx.ts_rate =
! 1468: AR5K_REG_MS(tx_desc->tx_control_3,
! 1469: AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE2);
! 1470: desc->ds_us.tx.ts_longretry +=
! 1471: AR5K_REG_MS(tx_desc->tx_control_2,
! 1472: AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES2);
! 1473: break;
! 1474: case 3:
! 1475: desc->ds_us.tx.ts_rate =
! 1476: AR5K_REG_MS(tx_desc->tx_control_3,
! 1477: AR5K_AR5212_DESC_TX_CTL3_XMIT_RATE3);
! 1478: desc->ds_us.tx.ts_longretry +=
! 1479: AR5K_REG_MS(tx_desc->tx_control_2,
! 1480: AR5K_AR5212_DESC_TX_CTL2_XMIT_TRIES3);
! 1481: break;
! 1482: }
! 1483:
! 1484: if ((tx_status->tx_status_0 &
! 1485: AR5K_AR5212_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0) {
! 1486: if (tx_status->tx_status_0 &
! 1487: AR5K_AR5212_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
! 1488: desc->ds_us.tx.ts_status |= HAL_TXERR_XRETRY;
! 1489:
! 1490: if (tx_status->tx_status_0 &
! 1491: AR5K_AR5212_DESC_TX_STATUS0_FIFO_UNDERRUN)
! 1492: desc->ds_us.tx.ts_status |= HAL_TXERR_FIFO;
! 1493:
! 1494: if (tx_status->tx_status_0 &
! 1495: AR5K_AR5212_DESC_TX_STATUS0_FILTERED)
! 1496: desc->ds_us.tx.ts_status |= HAL_TXERR_FILT;
! 1497: }
! 1498:
! 1499: return (HAL_OK);
! 1500: }
! 1501:
! 1502: HAL_BOOL
! 1503: ar5k_ar5212_has_veol(struct ath_hal *hal)
! 1504: {
! 1505: return (AH_TRUE);
! 1506: }
! 1507:
! 1508: /*
! 1509: * Receive functions
! 1510: */
! 1511:
! 1512: u_int32_t
! 1513: ar5k_ar5212_get_rx_buf(struct ath_hal *hal)
! 1514: {
! 1515: return (AR5K_REG_READ(AR5K_AR5212_RXDP));
! 1516: }
! 1517:
! 1518: void
! 1519: ar5k_ar5212_put_rx_buf(struct ath_hal *hal, u_int32_t phys_addr)
! 1520: {
! 1521: AR5K_REG_WRITE(AR5K_AR5212_RXDP, phys_addr);
! 1522: }
! 1523:
! 1524: void
! 1525: ar5k_ar5212_start_rx(struct ath_hal *hal)
! 1526: {
! 1527: AR5K_REG_WRITE(AR5K_AR5212_CR, AR5K_AR5212_CR_RXE);
! 1528: }
! 1529:
! 1530: HAL_BOOL
! 1531: ar5k_ar5212_stop_rx_dma(struct ath_hal *hal)
! 1532: {
! 1533: int i;
! 1534:
! 1535: AR5K_REG_WRITE(AR5K_AR5212_CR, AR5K_AR5212_CR_RXD);
! 1536:
! 1537: /*
! 1538: * It may take some time to disable the DMA receive unit
! 1539: */
! 1540: for (i = 2000;
! 1541: i > 0 && (AR5K_REG_READ(AR5K_AR5212_CR) & AR5K_AR5212_CR_RXE) != 0;
! 1542: i--)
! 1543: AR5K_DELAY(10);
! 1544:
! 1545: return (i > 0 ? AH_TRUE : AH_FALSE);
! 1546: }
! 1547:
! 1548: void
! 1549: ar5k_ar5212_start_rx_pcu(struct ath_hal *hal)
! 1550: {
! 1551: AR5K_REG_DISABLE_BITS(AR5K_AR5212_DIAG_SW, AR5K_AR5212_DIAG_SW_DIS_RX);
! 1552: }
! 1553:
! 1554: void
! 1555: ar5k_ar5212_stop_pcu_recv(struct ath_hal *hal)
! 1556: {
! 1557: AR5K_REG_ENABLE_BITS(AR5K_AR5212_DIAG_SW, AR5K_AR5212_DIAG_SW_DIS_RX);
! 1558: }
! 1559:
! 1560: void
! 1561: ar5k_ar5212_set_mcast_filter(struct ath_hal *hal, u_int32_t filter0,
! 1562: u_int32_t filter1)
! 1563: {
! 1564: /* Set the multicat filter */
! 1565: AR5K_REG_WRITE(AR5K_AR5212_MCAST_FIL0, filter0);
! 1566: AR5K_REG_WRITE(AR5K_AR5212_MCAST_FIL1, filter1);
! 1567: }
! 1568:
! 1569: HAL_BOOL
! 1570: ar5k_ar5212_set_mcast_filterindex(struct ath_hal *hal, u_int32_t index)
! 1571: {
! 1572: if (index >= 64) {
! 1573: return (AH_FALSE);
! 1574: } else if (index >= 32) {
! 1575: AR5K_REG_ENABLE_BITS(AR5K_AR5212_MCAST_FIL1,
! 1576: (1 << (index - 32)));
! 1577: } else {
! 1578: AR5K_REG_ENABLE_BITS(AR5K_AR5212_MCAST_FIL0,
! 1579: (1 << index));
! 1580: }
! 1581:
! 1582: return (AH_TRUE);
! 1583: }
! 1584:
! 1585: HAL_BOOL
! 1586: ar5k_ar5212_clear_mcast_filter_idx(struct ath_hal *hal, u_int32_t index)
! 1587: {
! 1588:
! 1589: if (index >= 64) {
! 1590: return (AH_FALSE);
! 1591: } else if (index >= 32) {
! 1592: AR5K_REG_DISABLE_BITS(AR5K_AR5212_MCAST_FIL1,
! 1593: (1 << (index - 32)));
! 1594: } else {
! 1595: AR5K_REG_DISABLE_BITS(AR5K_AR5212_MCAST_FIL0,
! 1596: (1 << index));
! 1597: }
! 1598:
! 1599: return (AH_TRUE);
! 1600: }
! 1601:
! 1602: u_int32_t
! 1603: ar5k_ar5212_get_rx_filter(struct ath_hal *hal)
! 1604: {
! 1605: u_int32_t data, filter = 0;
! 1606:
! 1607: filter = AR5K_REG_READ(AR5K_AR5212_RX_FILTER);
! 1608: data = AR5K_REG_READ(AR5K_AR5212_PHY_ERR_FIL);
! 1609:
! 1610: if (data & AR5K_AR5212_PHY_ERR_FIL_RADAR)
! 1611: filter |= HAL_RX_FILTER_PHYRADAR;
! 1612: if (data & (AR5K_AR5212_PHY_ERR_FIL_OFDM |
! 1613: AR5K_AR5212_PHY_ERR_FIL_CCK))
! 1614: filter |= HAL_RX_FILTER_PHYERR;
! 1615:
! 1616: return (filter);
! 1617: }
! 1618:
! 1619: void
! 1620: ar5k_ar5212_set_rx_filter(struct ath_hal *hal, u_int32_t filter)
! 1621: {
! 1622: u_int32_t data = 0;
! 1623:
! 1624: if (filter & HAL_RX_FILTER_PHYRADAR)
! 1625: data |= AR5K_AR5212_PHY_ERR_FIL_RADAR;
! 1626: if (filter & HAL_RX_FILTER_PHYERR)
! 1627: data |= AR5K_AR5212_PHY_ERR_FIL_OFDM |
! 1628: AR5K_AR5212_PHY_ERR_FIL_CCK;
! 1629:
! 1630: if (data) {
! 1631: AR5K_REG_ENABLE_BITS(AR5K_AR5212_RXCFG,
! 1632: AR5K_AR5212_RXCFG_ZLFDMA);
! 1633: } else {
! 1634: AR5K_REG_DISABLE_BITS(AR5K_AR5212_RXCFG,
! 1635: AR5K_AR5212_RXCFG_ZLFDMA);
! 1636: }
! 1637:
! 1638: AR5K_REG_WRITE(AR5K_AR5212_RX_FILTER, filter & 0xff);
! 1639: AR5K_REG_WRITE(AR5K_AR5212_PHY_ERR_FIL, data);
! 1640: }
! 1641:
! 1642: HAL_BOOL
! 1643: ar5k_ar5212_setup_rx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1644: u_int32_t size, u_int flags)
! 1645: {
! 1646: struct ar5k_ar5212_rx_desc *rx_desc;
! 1647:
! 1648: rx_desc = (struct ar5k_ar5212_rx_desc*)&desc->ds_ctl0;
! 1649:
! 1650: if ((rx_desc->rx_control_1 = (size &
! 1651: AR5K_AR5212_DESC_RX_CTL1_BUF_LEN)) != size)
! 1652: return (AH_FALSE);
! 1653:
! 1654: if (flags & HAL_RXDESC_INTREQ)
! 1655: rx_desc->rx_control_1 |= AR5K_AR5212_DESC_RX_CTL1_INTREQ;
! 1656:
! 1657: return (AH_TRUE);
! 1658: }
! 1659:
! 1660: HAL_STATUS
! 1661: ar5k_ar5212_proc_rx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1662: u_int32_t phys_addr, struct ath_desc *next)
! 1663: {
! 1664: struct ar5k_ar5212_rx_status *rx_status;
! 1665: struct ar5k_ar5212_rx_error *rx_err;
! 1666:
! 1667: rx_status = (struct ar5k_ar5212_rx_status*)&desc->ds_hw[0];
! 1668:
! 1669: /* Overlay on error */
! 1670: rx_err = (struct ar5k_ar5212_rx_error*)&desc->ds_hw[0];
! 1671:
! 1672: /* No frame received / not ready */
! 1673: if ((rx_status->rx_status_1 & AR5K_AR5212_DESC_RX_STATUS1_DONE) == 0)
! 1674: return (HAL_EINPROGRESS);
! 1675:
! 1676: /*
! 1677: * Frame receive status
! 1678: */
! 1679: desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
! 1680: AR5K_AR5212_DESC_RX_STATUS0_DATA_LEN;
! 1681: desc->ds_us.rx.rs_rssi =
! 1682: AR5K_REG_MS(rx_status->rx_status_0,
! 1683: AR5K_AR5212_DESC_RX_STATUS0_RECEIVE_SIGNAL);
! 1684: desc->ds_us.rx.rs_rate =
! 1685: AR5K_REG_MS(rx_status->rx_status_0,
! 1686: AR5K_AR5212_DESC_RX_STATUS0_RECEIVE_RATE);
! 1687: desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
! 1688: AR5K_AR5212_DESC_RX_STATUS0_RECEIVE_ANTENNA;
! 1689: desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
! 1690: AR5K_AR5212_DESC_RX_STATUS0_MORE;
! 1691: desc->ds_us.rx.rs_tstamp =
! 1692: AR5K_REG_MS(rx_status->rx_status_1,
! 1693: AR5K_AR5212_DESC_RX_STATUS1_RECEIVE_TIMESTAMP);
! 1694: desc->ds_us.rx.rs_status = 0;
! 1695:
! 1696: /*
! 1697: * Key table status
! 1698: */
! 1699: if (rx_status->rx_status_1 &
! 1700: AR5K_AR5212_DESC_RX_STATUS1_KEY_INDEX_VALID) {
! 1701: desc->ds_us.rx.rs_keyix =
! 1702: AR5K_REG_MS(rx_status->rx_status_1,
! 1703: AR5K_AR5212_DESC_RX_STATUS1_KEY_INDEX);
! 1704: } else {
! 1705: desc->ds_us.rx.rs_keyix = HAL_RXKEYIX_INVALID;
! 1706: }
! 1707:
! 1708: /*
! 1709: * Receive/descriptor errors
! 1710: */
! 1711: if ((rx_status->rx_status_1 &
! 1712: AR5K_AR5212_DESC_RX_STATUS1_FRAME_RECEIVE_OK) == 0) {
! 1713: if (rx_status->rx_status_1 &
! 1714: AR5K_AR5212_DESC_RX_STATUS1_CRC_ERROR)
! 1715: desc->ds_us.rx.rs_status |= HAL_RXERR_CRC;
! 1716:
! 1717: if (rx_status->rx_status_1 &
! 1718: AR5K_AR5212_DESC_RX_STATUS1_PHY_ERROR) {
! 1719: desc->ds_us.rx.rs_status |= HAL_RXERR_PHY;
! 1720: desc->ds_us.rx.rs_phyerr =
! 1721: AR5K_REG_MS(rx_err->rx_error_1,
! 1722: AR5K_AR5212_DESC_RX_ERROR1_PHY_ERROR_CODE);
! 1723: }
! 1724:
! 1725: if (rx_status->rx_status_1 &
! 1726: AR5K_AR5212_DESC_RX_STATUS1_DECRYPT_CRC_ERROR)
! 1727: desc->ds_us.rx.rs_status |= HAL_RXERR_DECRYPT;
! 1728:
! 1729: if (rx_status->rx_status_1 &
! 1730: AR5K_AR5212_DESC_RX_STATUS1_MIC_ERROR)
! 1731: desc->ds_us.rx.rs_status |= HAL_RXERR_MIC;
! 1732: }
! 1733:
! 1734: return (HAL_OK);
! 1735: }
! 1736:
! 1737: void
! 1738: ar5k_ar5212_set_rx_signal(struct ath_hal *hal)
! 1739: {
! 1740: /* Signal state monitoring is not yet supported */
! 1741: }
! 1742:
! 1743: /*
! 1744: * Misc functions
! 1745: */
! 1746:
! 1747: void
! 1748: ar5k_ar5212_dump_state(struct ath_hal *hal)
! 1749: {
! 1750: #ifdef AR5K_DEBUG
! 1751: #define AR5K_PRINT_REGISTER(_x) \
! 1752: printf("(%s: %08x) ", #_x, AR5K_REG_READ(AR5K_AR5212_##_x));
! 1753:
! 1754: printf("MAC registers:\n");
! 1755: AR5K_PRINT_REGISTER(CR);
! 1756: AR5K_PRINT_REGISTER(CFG);
! 1757: AR5K_PRINT_REGISTER(IER);
! 1758: AR5K_PRINT_REGISTER(TXCFG);
! 1759: AR5K_PRINT_REGISTER(RXCFG);
! 1760: AR5K_PRINT_REGISTER(MIBC);
! 1761: AR5K_PRINT_REGISTER(TOPS);
! 1762: AR5K_PRINT_REGISTER(RXNOFRM);
! 1763: AR5K_PRINT_REGISTER(RPGTO);
! 1764: AR5K_PRINT_REGISTER(RFCNT);
! 1765: AR5K_PRINT_REGISTER(MISC);
! 1766: AR5K_PRINT_REGISTER(PISR);
! 1767: AR5K_PRINT_REGISTER(SISR0);
! 1768: AR5K_PRINT_REGISTER(SISR1);
! 1769: AR5K_PRINT_REGISTER(SISR3);
! 1770: AR5K_PRINT_REGISTER(SISR4);
! 1771: AR5K_PRINT_REGISTER(DCM_ADDR);
! 1772: AR5K_PRINT_REGISTER(DCM_DATA);
! 1773: AR5K_PRINT_REGISTER(DCCFG);
! 1774: AR5K_PRINT_REGISTER(CCFG);
! 1775: AR5K_PRINT_REGISTER(CCFG_CUP);
! 1776: AR5K_PRINT_REGISTER(CPC0);
! 1777: AR5K_PRINT_REGISTER(CPC1);
! 1778: AR5K_PRINT_REGISTER(CPC2);
! 1779: AR5K_PRINT_REGISTER(CPCORN);
! 1780: AR5K_PRINT_REGISTER(QCU_TXE);
! 1781: AR5K_PRINT_REGISTER(QCU_TXD);
! 1782: AR5K_PRINT_REGISTER(DCU_GBL_IFS_SIFS);
! 1783: AR5K_PRINT_REGISTER(DCU_GBL_IFS_SLOT);
! 1784: AR5K_PRINT_REGISTER(DCU_FP);
! 1785: AR5K_PRINT_REGISTER(DCU_TXP);
! 1786: AR5K_PRINT_REGISTER(DCU_TX_FILTER);
! 1787: AR5K_PRINT_REGISTER(RC);
! 1788: AR5K_PRINT_REGISTER(SCR);
! 1789: AR5K_PRINT_REGISTER(INTPEND);
! 1790: AR5K_PRINT_REGISTER(PCICFG);
! 1791: AR5K_PRINT_REGISTER(GPIOCR);
! 1792: AR5K_PRINT_REGISTER(GPIODO);
! 1793: AR5K_PRINT_REGISTER(SREV);
! 1794: AR5K_PRINT_REGISTER(EEPROM_BASE);
! 1795: AR5K_PRINT_REGISTER(EEPROM_DATA);
! 1796: AR5K_PRINT_REGISTER(EEPROM_CMD);
! 1797: AR5K_PRINT_REGISTER(EEPROM_CFG);
! 1798: AR5K_PRINT_REGISTER(PCU_MIN);
! 1799: AR5K_PRINT_REGISTER(STA_ID0);
! 1800: AR5K_PRINT_REGISTER(STA_ID1);
! 1801: AR5K_PRINT_REGISTER(BSS_ID0);
! 1802: AR5K_PRINT_REGISTER(SLOT_TIME);
! 1803: AR5K_PRINT_REGISTER(TIME_OUT);
! 1804: AR5K_PRINT_REGISTER(RSSI_THR);
! 1805: AR5K_PRINT_REGISTER(BEACON);
! 1806: AR5K_PRINT_REGISTER(CFP_PERIOD);
! 1807: AR5K_PRINT_REGISTER(TIMER0);
! 1808: AR5K_PRINT_REGISTER(TIMER2);
! 1809: AR5K_PRINT_REGISTER(TIMER3);
! 1810: AR5K_PRINT_REGISTER(CFP_DUR);
! 1811: AR5K_PRINT_REGISTER(MCAST_FIL0);
! 1812: AR5K_PRINT_REGISTER(MCAST_FIL1);
! 1813: AR5K_PRINT_REGISTER(DIAG_SW);
! 1814: AR5K_PRINT_REGISTER(TSF_U32);
! 1815: AR5K_PRINT_REGISTER(ADDAC_TEST);
! 1816: AR5K_PRINT_REGISTER(DEFAULT_ANTENNA);
! 1817: AR5K_PRINT_REGISTER(LAST_TSTP);
! 1818: AR5K_PRINT_REGISTER(NAV);
! 1819: AR5K_PRINT_REGISTER(RTS_OK);
! 1820: AR5K_PRINT_REGISTER(ACK_FAIL);
! 1821: AR5K_PRINT_REGISTER(FCS_FAIL);
! 1822: AR5K_PRINT_REGISTER(BEACON_CNT);
! 1823: AR5K_PRINT_REGISTER(TSF_PARM);
! 1824: AR5K_PRINT_REGISTER(RATE_DUR_0);
! 1825: AR5K_PRINT_REGISTER(KEYTABLE_0);
! 1826: printf("\n");
! 1827:
! 1828: printf("PHY registers:\n");
! 1829: AR5K_PRINT_REGISTER(PHY_TURBO);
! 1830: AR5K_PRINT_REGISTER(PHY_AGC);
! 1831: AR5K_PRINT_REGISTER(PHY_TIMING_3);
! 1832: AR5K_PRINT_REGISTER(PHY_CHIP_ID);
! 1833: AR5K_PRINT_REGISTER(PHY_AGCCTL);
! 1834: AR5K_PRINT_REGISTER(PHY_NF);
! 1835: AR5K_PRINT_REGISTER(PHY_SCR);
! 1836: AR5K_PRINT_REGISTER(PHY_SLMT);
! 1837: AR5K_PRINT_REGISTER(PHY_SCAL);
! 1838: AR5K_PRINT_REGISTER(PHY_RX_DELAY);
! 1839: AR5K_PRINT_REGISTER(PHY_IQ);
! 1840: AR5K_PRINT_REGISTER(PHY_PAPD_PROBE);
! 1841: AR5K_PRINT_REGISTER(PHY_TXPOWER_RATE1);
! 1842: AR5K_PRINT_REGISTER(PHY_TXPOWER_RATE2);
! 1843: AR5K_PRINT_REGISTER(PHY_FC);
! 1844: AR5K_PRINT_REGISTER(PHY_RADAR);
! 1845: AR5K_PRINT_REGISTER(PHY_ANT_SWITCH_TABLE_0);
! 1846: AR5K_PRINT_REGISTER(PHY_ANT_SWITCH_TABLE_1);
! 1847: printf("\n");
! 1848: #endif
! 1849: }
! 1850:
! 1851: HAL_BOOL
! 1852: ar5k_ar5212_get_diag_state(struct ath_hal *hal, int id, void **device,
! 1853: u_int *size)
! 1854: {
! 1855: /*
! 1856: * We'll ignore this right now. This seems to be some kind of an obscure
! 1857: * debugging interface for the binary-only HAL.
! 1858: */
! 1859: return (AH_FALSE);
! 1860: }
! 1861:
! 1862: void
! 1863: ar5k_ar5212_get_lladdr(struct ath_hal *hal, u_int8_t *mac)
! 1864: {
! 1865: bcopy(hal->ah_sta_id, mac, IEEE80211_ADDR_LEN);
! 1866: }
! 1867:
! 1868: HAL_BOOL
! 1869: ar5k_ar5212_set_lladdr(struct ath_hal *hal, const u_int8_t *mac)
! 1870: {
! 1871: u_int32_t low_id, high_id;
! 1872:
! 1873: /* Set new station ID */
! 1874: bcopy(mac, hal->ah_sta_id, IEEE80211_ADDR_LEN);
! 1875:
! 1876: low_id = AR5K_LOW_ID(mac);
! 1877: high_id = 0x0000ffff & AR5K_HIGH_ID(mac);
! 1878:
! 1879: AR5K_REG_WRITE(AR5K_AR5212_STA_ID0, low_id);
! 1880: AR5K_REG_WRITE(AR5K_AR5212_STA_ID1, high_id);
! 1881:
! 1882: return (AH_TRUE);
! 1883: }
! 1884:
! 1885: HAL_BOOL
! 1886: ar5k_ar5212_set_regdomain(struct ath_hal *hal, u_int16_t regdomain,
! 1887: HAL_STATUS *status)
! 1888: {
! 1889: ieee80211_regdomain_t ieee_regdomain;
! 1890:
! 1891: ieee_regdomain = ar5k_regdomain_to_ieee(regdomain);
! 1892:
! 1893: if (ar5k_eeprom_regulation_domain(hal, AH_TRUE,
! 1894: &ieee_regdomain) == AH_TRUE) {
! 1895: *status = HAL_OK;
! 1896: return (AH_TRUE);
! 1897: }
! 1898:
! 1899: *status = EIO;
! 1900:
! 1901: return (AH_FALSE);
! 1902: }
! 1903:
! 1904: void
! 1905: ar5k_ar5212_set_ledstate(struct ath_hal *hal, HAL_LED_STATE state)
! 1906: {
! 1907: u_int32_t led;
! 1908:
! 1909: AR5K_REG_DISABLE_BITS(AR5K_AR5212_PCICFG,
! 1910: AR5K_AR5212_PCICFG_LEDMODE | AR5K_AR5212_PCICFG_LED);
! 1911:
! 1912: /*
! 1913: * Some blinking values, define at your wish
! 1914: */
! 1915: switch (state) {
! 1916: case IEEE80211_S_SCAN:
! 1917: case IEEE80211_S_AUTH:
! 1918: led = AR5K_AR5212_PCICFG_LEDMODE_PROP |
! 1919: AR5K_AR5212_PCICFG_LED_PEND;
! 1920: break;
! 1921:
! 1922: case IEEE80211_S_INIT:
! 1923: led = AR5K_AR5212_PCICFG_LEDMODE_PROP |
! 1924: AR5K_AR5212_PCICFG_LED_NONE;
! 1925: break;
! 1926:
! 1927: case IEEE80211_S_ASSOC:
! 1928: case IEEE80211_S_RUN:
! 1929: led = AR5K_AR5212_PCICFG_LEDMODE_PROP |
! 1930: AR5K_AR5212_PCICFG_LED_ASSOC;
! 1931: break;
! 1932:
! 1933: default:
! 1934: led = AR5K_AR5212_PCICFG_LEDMODE_PROM |
! 1935: AR5K_AR5212_PCICFG_LED_NONE;
! 1936: break;
! 1937: }
! 1938:
! 1939: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PCICFG, led);
! 1940: }
! 1941:
! 1942: void
! 1943: ar5k_ar5212_set_associd(struct ath_hal *hal, const u_int8_t *bssid,
! 1944: u_int16_t assoc_id, u_int16_t tim_offset)
! 1945: {
! 1946: u_int32_t low_id, high_id;
! 1947:
! 1948: /*
! 1949: * Set simple BSSID mask
! 1950: */
! 1951: AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM0, 0xfffffff);
! 1952: AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM1, 0xfffffff);
! 1953:
! 1954: /*
! 1955: * Set BSSID which triggers the "SME Join" operation
! 1956: */
! 1957: low_id = AR5K_LOW_ID(bssid);
! 1958: high_id = AR5K_HIGH_ID(bssid);
! 1959: AR5K_REG_WRITE(AR5K_AR5212_BSS_ID0, low_id);
! 1960: AR5K_REG_WRITE(AR5K_AR5212_BSS_ID1, high_id |
! 1961: ((assoc_id & 0x3fff) << AR5K_AR5212_BSS_ID1_AID_S));
! 1962: bcopy(bssid, &hal->ah_bssid, IEEE80211_ADDR_LEN);
! 1963:
! 1964: if (assoc_id == 0) {
! 1965: ar5k_ar5212_disable_pspoll(hal);
! 1966: return;
! 1967: }
! 1968:
! 1969: AR5K_REG_WRITE(AR5K_AR5212_BEACON,
! 1970: (AR5K_REG_READ(AR5K_AR5212_BEACON) &
! 1971: ~AR5K_AR5212_BEACON_TIM) |
! 1972: (((tim_offset ? tim_offset + 4 : 0) <<
! 1973: AR5K_AR5212_BEACON_TIM_S) &
! 1974: AR5K_AR5212_BEACON_TIM));
! 1975:
! 1976: ar5k_ar5212_enable_pspoll(hal, NULL, 0);
! 1977: }
! 1978:
! 1979: HAL_BOOL
! 1980: ar5k_ar5212_set_bssid_mask(struct ath_hal *hal, const u_int8_t* mask)
! 1981: {
! 1982: u_int32_t low_id, high_id;
! 1983:
! 1984: low_id = AR5K_LOW_ID(mask);
! 1985: high_id = 0x0000ffff & AR5K_HIGH_ID(mask);
! 1986:
! 1987: AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM0, low_id);
! 1988: AR5K_REG_WRITE(AR5K_AR5212_BSS_IDM1, high_id);
! 1989:
! 1990: return (AH_TRUE);
! 1991: }
! 1992:
! 1993: HAL_BOOL
! 1994: ar5k_ar5212_set_gpio_output(struct ath_hal *hal, u_int32_t gpio)
! 1995: {
! 1996: if (gpio > AR5K_AR5212_NUM_GPIO)
! 1997: return (AH_FALSE);
! 1998:
! 1999: AR5K_REG_WRITE(AR5K_AR5212_GPIOCR,
! 2000: (AR5K_REG_READ(AR5K_AR5212_GPIOCR) &~ AR5K_AR5212_GPIOCR_ALL(gpio))
! 2001: | AR5K_AR5212_GPIOCR_ALL(gpio));
! 2002:
! 2003: return (AH_TRUE);
! 2004: }
! 2005:
! 2006: HAL_BOOL
! 2007: ar5k_ar5212_set_gpio_input(struct ath_hal *hal, u_int32_t gpio)
! 2008: {
! 2009: if (gpio > AR5K_AR5212_NUM_GPIO)
! 2010: return (AH_FALSE);
! 2011:
! 2012: AR5K_REG_WRITE(AR5K_AR5212_GPIOCR,
! 2013: (AR5K_REG_READ(AR5K_AR5212_GPIOCR) &~ AR5K_AR5212_GPIOCR_ALL(gpio))
! 2014: | AR5K_AR5212_GPIOCR_NONE(gpio));
! 2015:
! 2016: return (AH_TRUE);
! 2017: }
! 2018:
! 2019: u_int32_t
! 2020: ar5k_ar5212_get_gpio(struct ath_hal *hal, u_int32_t gpio)
! 2021: {
! 2022: if (gpio > AR5K_AR5212_NUM_GPIO)
! 2023: return (0xffffffff);
! 2024:
! 2025: /* GPIO input magic */
! 2026: return (((AR5K_REG_READ(AR5K_AR5212_GPIODI) &
! 2027: AR5K_AR5212_GPIODI_M) >> gpio) & 0x1);
! 2028: }
! 2029:
! 2030: HAL_BOOL
! 2031: ar5k_ar5212_set_gpio(struct ath_hal *hal, u_int32_t gpio, u_int32_t val)
! 2032: {
! 2033: u_int32_t data;
! 2034:
! 2035: if (gpio > AR5K_AR5212_NUM_GPIO)
! 2036: return (0xffffffff);
! 2037:
! 2038: /* GPIO output magic */
! 2039: data = AR5K_REG_READ(AR5K_AR5212_GPIODO);
! 2040:
! 2041: data &= ~(1 << gpio);
! 2042: data |= (val&1) << gpio;
! 2043:
! 2044: AR5K_REG_WRITE(AR5K_AR5212_GPIODO, data);
! 2045:
! 2046: return (AH_TRUE);
! 2047: }
! 2048:
! 2049: void
! 2050: ar5k_ar5212_set_gpio_intr(struct ath_hal *hal, u_int gpio,
! 2051: u_int32_t interrupt_level)
! 2052: {
! 2053: u_int32_t data;
! 2054:
! 2055: if (gpio > AR5K_AR5212_NUM_GPIO)
! 2056: return;
! 2057:
! 2058: /*
! 2059: * Set the GPIO interrupt
! 2060: */
! 2061: data = (AR5K_REG_READ(AR5K_AR5212_GPIOCR) &
! 2062: ~(AR5K_AR5212_GPIOCR_INT_SEL(gpio) | AR5K_AR5212_GPIOCR_INT_SELH |
! 2063: AR5K_AR5212_GPIOCR_INT_ENA | AR5K_AR5212_GPIOCR_ALL(gpio))) |
! 2064: (AR5K_AR5212_GPIOCR_INT_SEL(gpio) | AR5K_AR5212_GPIOCR_INT_ENA);
! 2065:
! 2066: AR5K_REG_WRITE(AR5K_AR5212_GPIOCR,
! 2067: interrupt_level ? data : (data | AR5K_AR5212_GPIOCR_INT_SELH));
! 2068:
! 2069: hal->ah_imr |= AR5K_AR5212_PIMR_GPIO;
! 2070:
! 2071: /* Enable GPIO interrupts */
! 2072: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PIMR, AR5K_AR5212_PIMR_GPIO);
! 2073: }
! 2074:
! 2075: u_int32_t
! 2076: ar5k_ar5212_get_tsf32(struct ath_hal *hal)
! 2077: {
! 2078: return (AR5K_REG_READ(AR5K_AR5212_TSF_L32));
! 2079: }
! 2080:
! 2081: u_int64_t
! 2082: ar5k_ar5212_get_tsf64(struct ath_hal *hal)
! 2083: {
! 2084: u_int64_t tsf = AR5K_REG_READ(AR5K_AR5212_TSF_U32);
! 2085:
! 2086: return (AR5K_REG_READ(AR5K_AR5212_TSF_L32) | (tsf << 32));
! 2087: }
! 2088:
! 2089: void
! 2090: ar5k_ar5212_reset_tsf(struct ath_hal *hal)
! 2091: {
! 2092: AR5K_REG_ENABLE_BITS(AR5K_AR5212_BEACON,
! 2093: AR5K_AR5212_BEACON_RESET_TSF);
! 2094: }
! 2095:
! 2096: u_int16_t
! 2097: ar5k_ar5212_get_regdomain(struct ath_hal *hal)
! 2098: {
! 2099: return (ar5k_get_regdomain(hal));
! 2100: }
! 2101:
! 2102: HAL_BOOL
! 2103: ar5k_ar5212_detect_card_present(struct ath_hal *hal)
! 2104: {
! 2105: u_int16_t magic;
! 2106:
! 2107: /*
! 2108: * Checking the EEPROM's magic value could be an indication
! 2109: * if the card is still present. I didn't find another suitable
! 2110: * way to do this.
! 2111: */
! 2112: if (ar5k_ar5212_eeprom_read(hal, AR5K_EEPROM_MAGIC, &magic) != 0)
! 2113: return (AH_FALSE);
! 2114:
! 2115: return (magic == AR5K_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE);
! 2116: }
! 2117:
! 2118: void
! 2119: ar5k_ar5212_update_mib_counters(struct ath_hal *hal, HAL_MIB_STATS *statistics)
! 2120: {
! 2121: /* Read-And-Clear */
! 2122: statistics->ackrcv_bad += AR5K_REG_READ(AR5K_AR5212_ACK_FAIL);
! 2123: statistics->rts_bad += AR5K_REG_READ(AR5K_AR5212_RTS_FAIL);
! 2124: statistics->rts_good += AR5K_REG_READ(AR5K_AR5212_RTS_OK);
! 2125: statistics->fcs_bad += AR5K_REG_READ(AR5K_AR5212_FCS_FAIL);
! 2126: statistics->beacons += AR5K_REG_READ(AR5K_AR5212_BEACON_CNT);
! 2127:
! 2128: /* Reset profile count registers */
! 2129: AR5K_REG_WRITE(AR5K_AR5212_PROFCNT_TX, 0);
! 2130: AR5K_REG_WRITE(AR5K_AR5212_PROFCNT_RX, 0);
! 2131: AR5K_REG_WRITE(AR5K_AR5212_PROFCNT_RXCLR, 0);
! 2132: AR5K_REG_WRITE(AR5K_AR5212_PROFCNT_CYCLE, 0);
! 2133: }
! 2134:
! 2135: HAL_RFGAIN
! 2136: ar5k_ar5212_get_rf_gain(struct ath_hal *hal)
! 2137: {
! 2138: u_int32_t data, type;
! 2139:
! 2140: if ((hal->ah_rf_banks == NULL) || (!hal->ah_gain.g_active))
! 2141: return (HAL_RFGAIN_INACTIVE);
! 2142:
! 2143: if (hal->ah_rf_gain != HAL_RFGAIN_READ_REQUESTED)
! 2144: goto done;
! 2145:
! 2146: data = AR5K_REG_READ(AR5K_AR5212_PHY_PAPD_PROBE);
! 2147:
! 2148: if (!(data & AR5K_AR5212_PHY_PAPD_PROBE_TX_NEXT)) {
! 2149: hal->ah_gain.g_current =
! 2150: data >> AR5K_AR5212_PHY_PAPD_PROBE_GAINF_S;
! 2151: type = AR5K_REG_MS(data, AR5K_AR5212_PHY_PAPD_PROBE_TYPE);
! 2152:
! 2153: if (type == AR5K_AR5212_PHY_PAPD_PROBE_TYPE_CCK)
! 2154: hal->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR;
! 2155:
! 2156: if (hal->ah_radio == AR5K_AR5112) {
! 2157: ar5k_rfregs_gainf_corr(hal);
! 2158: hal->ah_gain.g_current =
! 2159: hal->ah_gain.g_current >= hal->ah_gain.g_f_corr ?
! 2160: (hal->ah_gain.g_current - hal->ah_gain.g_f_corr) :
! 2161: 0;
! 2162: }
! 2163:
! 2164: if (ar5k_rfregs_gain_readback(hal) &&
! 2165: AR5K_GAIN_CHECK_ADJUST(&hal->ah_gain) &&
! 2166: ar5k_rfregs_gain_adjust(hal))
! 2167: hal->ah_rf_gain = HAL_RFGAIN_NEED_CHANGE;
! 2168: }
! 2169:
! 2170: done:
! 2171: return (hal->ah_rf_gain);
! 2172: }
! 2173:
! 2174: HAL_BOOL
! 2175: ar5k_ar5212_set_slot_time(struct ath_hal *hal, u_int slot_time)
! 2176: {
! 2177: if (slot_time < HAL_SLOT_TIME_9 || slot_time > HAL_SLOT_TIME_MAX)
! 2178: return (AH_FALSE);
! 2179:
! 2180: AR5K_REG_WRITE(AR5K_AR5212_DCU_GBL_IFS_SLOT, slot_time);
! 2181:
! 2182: return (AH_TRUE);
! 2183: }
! 2184:
! 2185: u_int
! 2186: ar5k_ar5212_get_slot_time(struct ath_hal *hal)
! 2187: {
! 2188: return (AR5K_REG_READ(AR5K_AR5212_DCU_GBL_IFS_SLOT) & 0xffff);
! 2189: }
! 2190:
! 2191: HAL_BOOL
! 2192: ar5k_ar5212_set_ack_timeout(struct ath_hal *hal, u_int timeout)
! 2193: {
! 2194: if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5212_TIME_OUT_ACK),
! 2195: hal->ah_turbo) <= timeout)
! 2196: return (AH_FALSE);
! 2197:
! 2198: AR5K_REG_WRITE_BITS(AR5K_AR5212_TIME_OUT, AR5K_AR5212_TIME_OUT_ACK,
! 2199: ar5k_htoclock(timeout, hal->ah_turbo));
! 2200:
! 2201: return (AH_TRUE);
! 2202: }
! 2203:
! 2204: u_int
! 2205: ar5k_ar5212_get_ack_timeout(struct ath_hal *hal)
! 2206: {
! 2207: return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TIME_OUT),
! 2208: AR5K_AR5212_TIME_OUT_ACK), hal->ah_turbo));
! 2209: }
! 2210:
! 2211: HAL_BOOL
! 2212: ar5k_ar5212_set_cts_timeout(struct ath_hal *hal, u_int timeout)
! 2213: {
! 2214: if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5212_TIME_OUT_CTS),
! 2215: hal->ah_turbo) <= timeout)
! 2216: return (AH_FALSE);
! 2217:
! 2218: AR5K_REG_WRITE_BITS(AR5K_AR5212_TIME_OUT, AR5K_AR5212_TIME_OUT_CTS,
! 2219: ar5k_htoclock(timeout, hal->ah_turbo));
! 2220:
! 2221: return (AH_TRUE);
! 2222: }
! 2223:
! 2224: u_int
! 2225: ar5k_ar5212_get_cts_timeout(struct ath_hal *hal)
! 2226: {
! 2227: return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5212_TIME_OUT),
! 2228: AR5K_AR5212_TIME_OUT_CTS), hal->ah_turbo));
! 2229: }
! 2230:
! 2231: /*
! 2232: * Key table (WEP) functions
! 2233: */
! 2234:
! 2235: HAL_BOOL
! 2236: ar5k_ar5212_is_cipher_supported(struct ath_hal *hal, HAL_CIPHER cipher)
! 2237: {
! 2238: /*
! 2239: * The AR5212 only supports WEP
! 2240: */
! 2241: if (cipher == HAL_CIPHER_WEP)
! 2242: return (AH_TRUE);
! 2243:
! 2244: return (AH_FALSE);
! 2245: }
! 2246:
! 2247: u_int32_t
! 2248: ar5k_ar5212_get_keycache_size(struct ath_hal *hal)
! 2249: {
! 2250: return (AR5K_AR5212_KEYCACHE_SIZE);
! 2251: }
! 2252:
! 2253: HAL_BOOL
! 2254: ar5k_ar5212_reset_key(struct ath_hal *hal, u_int16_t entry)
! 2255: {
! 2256: int i;
! 2257:
! 2258: AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE);
! 2259:
! 2260: for (i = 0; i < AR5K_AR5212_KEYCACHE_SIZE; i++)
! 2261: AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE_OFF(entry, i), 0);
! 2262:
! 2263: /* Set NULL encryption */
! 2264: AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE_TYPE(entry),
! 2265: AR5K_AR5212_KEYTABLE_TYPE_NULL);
! 2266:
! 2267: return (AH_FALSE);
! 2268: }
! 2269:
! 2270: HAL_BOOL
! 2271: ar5k_ar5212_is_key_valid(struct ath_hal *hal, u_int16_t entry)
! 2272: {
! 2273: AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE);
! 2274:
! 2275: /*
! 2276: * Check the validation flag at the end of the entry
! 2277: */
! 2278: if (AR5K_REG_READ(AR5K_AR5212_KEYTABLE_MAC1(entry)) &
! 2279: AR5K_AR5212_KEYTABLE_VALID)
! 2280: return (AH_TRUE);
! 2281:
! 2282: return (AH_FALSE);
! 2283: }
! 2284:
! 2285: HAL_BOOL
! 2286: ar5k_ar5212_set_key(struct ath_hal *hal, u_int16_t entry,
! 2287: const HAL_KEYVAL *keyval, const u_int8_t *mac, int xor_notused)
! 2288: {
! 2289: int i;
! 2290: u_int32_t key_v[AR5K_AR5212_KEYCACHE_SIZE - 2];
! 2291:
! 2292: AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE);
! 2293:
! 2294: bzero(&key_v, sizeof(key_v));
! 2295:
! 2296: switch (keyval->wk_len) {
! 2297: case AR5K_KEYVAL_LENGTH_40:
! 2298: bcopy(keyval->wk_key, &key_v[0], 4);
! 2299: bcopy(keyval->wk_key + 4, &key_v[1], 1);
! 2300: key_v[5] = AR5K_AR5212_KEYTABLE_TYPE_40;
! 2301: break;
! 2302:
! 2303: case AR5K_KEYVAL_LENGTH_104:
! 2304: bcopy(keyval->wk_key, &key_v[0], 4);
! 2305: bcopy(keyval->wk_key + 4, &key_v[1], 2);
! 2306: bcopy(keyval->wk_key + 6, &key_v[2], 4);
! 2307: bcopy(keyval->wk_key + 10, &key_v[3], 2);
! 2308: bcopy(keyval->wk_key + 12, &key_v[4], 1);
! 2309: key_v[5] = AR5K_AR5212_KEYTABLE_TYPE_104;
! 2310: break;
! 2311:
! 2312: case AR5K_KEYVAL_LENGTH_128:
! 2313: bcopy(keyval->wk_key, &key_v[0], 4);
! 2314: bcopy(keyval->wk_key + 4, &key_v[1], 2);
! 2315: bcopy(keyval->wk_key + 6, &key_v[2], 4);
! 2316: bcopy(keyval->wk_key + 10, &key_v[3], 2);
! 2317: bcopy(keyval->wk_key + 12, &key_v[4], 4);
! 2318: key_v[5] = AR5K_AR5212_KEYTABLE_TYPE_128;
! 2319: break;
! 2320:
! 2321: default:
! 2322: /* Unsupported key length (not WEP40/104/128) */
! 2323: return (AH_FALSE);
! 2324: }
! 2325:
! 2326: for (i = 0; i < AR5K_ELEMENTS(key_v); i++)
! 2327: AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE_OFF(entry, i), key_v[i]);
! 2328:
! 2329: return (ar5k_ar5212_set_key_lladdr(hal, entry, mac));
! 2330: }
! 2331:
! 2332: HAL_BOOL
! 2333: ar5k_ar5212_set_key_lladdr(struct ath_hal *hal, u_int16_t entry,
! 2334: const u_int8_t *mac)
! 2335: {
! 2336: u_int32_t low_id, high_id;
! 2337: const u_int8_t *mac_v;
! 2338:
! 2339: /*
! 2340: * Invalid entry (key table overflow)
! 2341: */
! 2342: AR5K_ASSERT_ENTRY(entry, AR5K_AR5212_KEYTABLE_SIZE);
! 2343:
! 2344: /* MAC may be NULL if it's a broadcast key */
! 2345: mac_v = mac == NULL ? etherbroadcastaddr : mac;
! 2346:
! 2347: low_id = AR5K_LOW_ID(mac_v);
! 2348: high_id = AR5K_HIGH_ID(mac_v) | AR5K_AR5212_KEYTABLE_VALID;
! 2349:
! 2350: AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE_MAC0(entry), low_id);
! 2351: AR5K_REG_WRITE(AR5K_AR5212_KEYTABLE_MAC1(entry), high_id);
! 2352:
! 2353: return (AH_TRUE);
! 2354: }
! 2355:
! 2356: /*
! 2357: * Power management functions
! 2358: */
! 2359:
! 2360: HAL_BOOL
! 2361: ar5k_ar5212_set_power(struct ath_hal *hal, HAL_POWER_MODE mode,
! 2362: HAL_BOOL set_chip, u_int16_t sleep_duration)
! 2363: {
! 2364: u_int32_t staid;
! 2365: int i;
! 2366:
! 2367: staid = AR5K_REG_READ(AR5K_AR5212_STA_ID1);
! 2368:
! 2369: switch (mode) {
! 2370: case HAL_PM_AUTO:
! 2371: staid &= ~AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA;
! 2372: /* FALLTHROUGH */
! 2373: case HAL_PM_NETWORK_SLEEP:
! 2374: if (set_chip == AH_TRUE) {
! 2375: AR5K_REG_WRITE(AR5K_AR5212_SCR,
! 2376: AR5K_AR5212_SCR_SLE | sleep_duration);
! 2377: }
! 2378: staid |= AR5K_AR5212_STA_ID1_PWR_SV;
! 2379: break;
! 2380:
! 2381: case HAL_PM_FULL_SLEEP:
! 2382: if (set_chip == AH_TRUE) {
! 2383: AR5K_REG_WRITE(AR5K_AR5212_SCR,
! 2384: AR5K_AR5212_SCR_SLE_SLP);
! 2385: }
! 2386: staid |= AR5K_AR5212_STA_ID1_PWR_SV;
! 2387: break;
! 2388:
! 2389: case HAL_PM_AWAKE:
! 2390: if (set_chip == AH_FALSE)
! 2391: goto commit;
! 2392:
! 2393: AR5K_REG_WRITE(AR5K_AR5212_SCR, AR5K_AR5212_SCR_SLE_WAKE);
! 2394:
! 2395: for (i = 5000; i > 0; i--) {
! 2396: /* Check if the AR5212 did wake up */
! 2397: if ((AR5K_REG_READ(AR5K_AR5212_PCICFG) &
! 2398: AR5K_AR5212_PCICFG_SPWR_DN) == 0)
! 2399: break;
! 2400:
! 2401: /* Wait a bit and retry */
! 2402: AR5K_DELAY(200);
! 2403: AR5K_REG_WRITE(AR5K_AR5212_SCR,
! 2404: AR5K_AR5212_SCR_SLE_WAKE);
! 2405: }
! 2406:
! 2407: /* Fail if the AR5212 didn't wake up */
! 2408: if (i <= 0)
! 2409: return (AH_FALSE);
! 2410:
! 2411: staid &= ~AR5K_AR5212_STA_ID1_PWR_SV;
! 2412: break;
! 2413:
! 2414: default:
! 2415: return (AH_FALSE);
! 2416: }
! 2417:
! 2418: commit:
! 2419: hal->ah_power_mode = mode;
! 2420:
! 2421: AR5K_REG_WRITE(AR5K_AR5212_STA_ID1, staid);
! 2422:
! 2423: return (AH_TRUE);
! 2424: }
! 2425:
! 2426: HAL_POWER_MODE
! 2427: ar5k_ar5212_get_power_mode(struct ath_hal *hal)
! 2428: {
! 2429: return (hal->ah_power_mode);
! 2430: }
! 2431:
! 2432: HAL_BOOL
! 2433: ar5k_ar5212_query_pspoll_support(struct ath_hal *hal)
! 2434: {
! 2435: /* nope */
! 2436: return (AH_FALSE);
! 2437: }
! 2438:
! 2439: HAL_BOOL
! 2440: ar5k_ar5212_init_pspoll(struct ath_hal *hal)
! 2441: {
! 2442: /*
! 2443: * Not used on the AR5212
! 2444: */
! 2445: return (AH_FALSE);
! 2446: }
! 2447:
! 2448: HAL_BOOL
! 2449: ar5k_ar5212_enable_pspoll(struct ath_hal *hal, u_int8_t *bssid,
! 2450: u_int16_t assoc_id)
! 2451: {
! 2452: return (AH_FALSE);
! 2453: }
! 2454:
! 2455: HAL_BOOL
! 2456: ar5k_ar5212_disable_pspoll(struct ath_hal *hal)
! 2457: {
! 2458: return (AH_FALSE);
! 2459: }
! 2460:
! 2461: /*
! 2462: * Beacon functions
! 2463: */
! 2464:
! 2465: void
! 2466: ar5k_ar5212_init_beacon(struct ath_hal *hal, u_int32_t next_beacon,
! 2467: u_int32_t interval)
! 2468: {
! 2469: u_int32_t timer1, timer2, timer3;
! 2470:
! 2471: /*
! 2472: * Set the additional timers by mode
! 2473: */
! 2474: switch (hal->ah_op_mode) {
! 2475: case HAL_M_STA:
! 2476: timer1 = 0x0000ffff;
! 2477: timer2 = 0x0007ffff;
! 2478: break;
! 2479:
! 2480: default:
! 2481: timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) <<
! 2482: 0x00000003;
! 2483: timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) <<
! 2484: 0x00000003;
! 2485: }
! 2486:
! 2487: timer3 = next_beacon +
! 2488: (hal->ah_atim_window ? hal->ah_atim_window : 1);
! 2489:
! 2490: /*
! 2491: * Enable all timers and set the beacon register
! 2492: * (next beacon, DMA beacon, software beacon, ATIM window time)
! 2493: */
! 2494: AR5K_REG_WRITE(AR5K_AR5212_TIMER0, next_beacon);
! 2495: AR5K_REG_WRITE(AR5K_AR5212_TIMER1, timer1);
! 2496: AR5K_REG_WRITE(AR5K_AR5212_TIMER2, timer2);
! 2497: AR5K_REG_WRITE(AR5K_AR5212_TIMER3, timer3);
! 2498:
! 2499: AR5K_REG_WRITE(AR5K_AR5212_BEACON, interval &
! 2500: (AR5K_AR5212_BEACON_PERIOD | AR5K_AR5212_BEACON_RESET_TSF |
! 2501: AR5K_AR5212_BEACON_ENABLE));
! 2502: }
! 2503:
! 2504: void
! 2505: ar5k_ar5212_set_beacon_timers(struct ath_hal *hal,
! 2506: const HAL_BEACON_STATE *state, u_int32_t tsf, u_int32_t dtim_count,
! 2507: u_int32_t cfp_count)
! 2508: {
! 2509: u_int32_t cfp_period, next_cfp, dtim, interval, next_beacon;
! 2510:
! 2511: /* Return on an invalid beacon state */
! 2512: if (state->bs_interval < 1)
! 2513: return;
! 2514:
! 2515: interval = state->bs_intval;
! 2516: dtim = state->bs_dtimperiod;
! 2517:
! 2518: /*
! 2519: * PCF support?
! 2520: */
! 2521: if (state->bs_cfp_period > 0) {
! 2522: /* Enable CFP mode and set the CFP and timer registers */
! 2523: cfp_period = state->bs_cfp_period * state->bs_dtim_period *
! 2524: state->bs_interval;
! 2525: next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
! 2526: state->bs_interval;
! 2527:
! 2528: AR5K_REG_ENABLE_BITS(AR5K_AR5212_STA_ID1,
! 2529: AR5K_AR5212_STA_ID1_PCF);
! 2530: AR5K_REG_WRITE(AR5K_AR5212_CFP_PERIOD, cfp_period);
! 2531: AR5K_REG_WRITE(AR5K_AR5212_CFP_DUR, state->bs_cfp_max_duration);
! 2532: AR5K_REG_WRITE(AR5K_AR5212_TIMER2,
! 2533: (tsf + (next_cfp == 0 ? cfp_period : next_cfp)) << 3);
! 2534: } else {
! 2535: /* Disable PCF mode */
! 2536: AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1,
! 2537: AR5K_AR5212_STA_ID1_PCF);
! 2538: }
! 2539:
! 2540: /*
! 2541: * Enable the beacon timer register
! 2542: */
! 2543: AR5K_REG_WRITE(AR5K_AR5212_TIMER0, state->bs_next_beacon);
! 2544:
! 2545: /*
! 2546: * Start the beacon timers
! 2547: */
! 2548: AR5K_REG_WRITE(AR5K_AR5212_BEACON,
! 2549: (AR5K_REG_READ(AR5K_AR5212_BEACON) &~
! 2550: (AR5K_AR5212_BEACON_PERIOD | AR5K_AR5212_BEACON_TIM)) |
! 2551: AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
! 2552: AR5K_AR5212_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
! 2553: AR5K_AR5212_BEACON_PERIOD));
! 2554:
! 2555: /*
! 2556: * Write new beacon miss threshold, if it appears to be valid
! 2557: */
! 2558: if ((AR5K_AR5212_RSSI_THR_BMISS >> AR5K_AR5212_RSSI_THR_BMISS_S) <
! 2559: state->bs_bmiss_threshold)
! 2560: return;
! 2561:
! 2562: AR5K_REG_WRITE_BITS(AR5K_AR5212_RSSI_THR_M,
! 2563: AR5K_AR5212_RSSI_THR_BMISS, state->bs_bmiss_threshold);
! 2564:
! 2565: /*
! 2566: * Set sleep registers
! 2567: */
! 2568: if ((state->bs_sleepduration > state->bs_interval) &&
! 2569: (roundup(state->bs_sleepduration, interval) ==
! 2570: state->bs_sleepduration))
! 2571: interval = state->bs_sleepduration;
! 2572:
! 2573: if (state->bs_sleepduration > dtim &&
! 2574: (dtim == 0 || roundup(state->bs_sleepduration, dtim) ==
! 2575: state->bs_sleepduration))
! 2576: dtim = state->bs_sleepduration;
! 2577:
! 2578: if (interval > dtim)
! 2579: return;
! 2580:
! 2581: next_beacon = interval == dtim ?
! 2582: state->bs_nextdtim: state->bs_nexttbtt;
! 2583:
! 2584: AR5K_REG_WRITE(AR5K_AR5212_SLEEP0,
! 2585: AR5K_REG_SM((state->bs_nextdtim - 3) << 3,
! 2586: AR5K_AR5212_SLEEP0_NEXT_DTIM) |
! 2587: AR5K_REG_SM(10, AR5K_AR5212_SLEEP0_CABTO) |
! 2588: AR5K_AR5212_SLEEP0_ENH_SLEEP_EN |
! 2589: AR5K_AR5212_SLEEP0_ASSUME_DTIM);
! 2590: AR5K_REG_WRITE(AR5K_AR5212_SLEEP1,
! 2591: AR5K_REG_SM((next_beacon - 3) << 3,
! 2592: AR5K_AR5212_SLEEP1_NEXT_TIM) |
! 2593: AR5K_REG_SM(10, AR5K_AR5212_SLEEP1_BEACON_TO));
! 2594: AR5K_REG_WRITE(AR5K_AR5212_SLEEP2,
! 2595: AR5K_REG_SM(interval, AR5K_AR5212_SLEEP2_TIM_PER) |
! 2596: AR5K_REG_SM(dtim, AR5K_AR5212_SLEEP2_DTIM_PER));
! 2597: }
! 2598:
! 2599: void
! 2600: ar5k_ar5212_reset_beacon(struct ath_hal *hal)
! 2601: {
! 2602: /*
! 2603: * Disable beacon timer
! 2604: */
! 2605: AR5K_REG_WRITE(AR5K_AR5212_TIMER0, 0);
! 2606:
! 2607: /*
! 2608: * Disable some beacon register values
! 2609: */
! 2610: AR5K_REG_DISABLE_BITS(AR5K_AR5212_STA_ID1,
! 2611: AR5K_AR5212_STA_ID1_DEFAULT_ANTENNA | AR5K_AR5212_STA_ID1_PCF);
! 2612: AR5K_REG_WRITE(AR5K_AR5212_BEACON, AR5K_AR5212_BEACON_PERIOD);
! 2613: }
! 2614:
! 2615: HAL_BOOL
! 2616: ar5k_ar5212_wait_for_beacon(struct ath_hal *hal, bus_addr_t phys_addr)
! 2617: {
! 2618: HAL_BOOL ret;
! 2619:
! 2620: /*
! 2621: * Wait for beaconn queue to be done
! 2622: */
! 2623: ret = ar5k_register_timeout(hal,
! 2624: AR5K_AR5212_QCU_STS(HAL_TX_QUEUE_ID_BEACON),
! 2625: AR5K_AR5212_QCU_STS_FRMPENDCNT, 0, AH_FALSE);
! 2626:
! 2627: if (AR5K_REG_READ_Q(AR5K_AR5212_QCU_TXE, HAL_TX_QUEUE_ID_BEACON))
! 2628: return (AH_FALSE);
! 2629:
! 2630: return (ret);
! 2631: }
! 2632:
! 2633: /*
! 2634: * Interrupt handling
! 2635: */
! 2636:
! 2637: HAL_BOOL
! 2638: ar5k_ar5212_is_intr_pending(struct ath_hal *hal)
! 2639: {
! 2640: return (AR5K_REG_READ(AR5K_AR5212_INTPEND) == 0 ? AH_FALSE : AH_TRUE);
! 2641: }
! 2642:
! 2643: HAL_BOOL
! 2644: ar5k_ar5212_get_isr(struct ath_hal *hal, u_int32_t *interrupt_mask)
! 2645: {
! 2646: u_int32_t data;
! 2647:
! 2648: /*
! 2649: * Read interrupt status from the Read-And-Clear shadow register
! 2650: */
! 2651: data = AR5K_REG_READ(AR5K_AR5212_RAC_PISR);
! 2652:
! 2653: /*
! 2654: * Get abstract interrupt mask (HAL-compatible)
! 2655: */
! 2656: *interrupt_mask = (data & HAL_INT_COMMON) & hal->ah_imr;
! 2657:
! 2658: if (data == HAL_INT_NOCARD)
! 2659: return (AH_FALSE);
! 2660:
! 2661: if (data & (AR5K_AR5212_PISR_RXOK | AR5K_AR5212_PISR_RXERR))
! 2662: *interrupt_mask |= HAL_INT_RX;
! 2663:
! 2664: if (data & (AR5K_AR5212_PISR_TXOK | AR5K_AR5212_PISR_TXERR))
! 2665: *interrupt_mask |= HAL_INT_TX;
! 2666:
! 2667: if (data & (AR5K_AR5212_PISR_HIUERR))
! 2668: *interrupt_mask |= HAL_INT_FATAL;
! 2669:
! 2670: /*
! 2671: * Special interrupt handling (not caught by the driver)
! 2672: */
! 2673: if (((*interrupt_mask) & AR5K_AR5212_PISR_RXPHY) &&
! 2674: hal->ah_radar.r_enabled == AH_TRUE)
! 2675: ar5k_radar_alert(hal);
! 2676:
! 2677: if (*interrupt_mask == 0)
! 2678: AR5K_PRINTF("0x%08x\n", data);
! 2679:
! 2680: return (AH_TRUE);
! 2681: }
! 2682:
! 2683: u_int32_t
! 2684: ar5k_ar5212_get_intr(struct ath_hal *hal)
! 2685: {
! 2686: /* Return the interrupt mask stored previously */
! 2687: return (hal->ah_imr);
! 2688: }
! 2689:
! 2690: HAL_INT
! 2691: ar5k_ar5212_set_intr(struct ath_hal *hal, HAL_INT new_mask)
! 2692: {
! 2693: HAL_INT old_mask, int_mask;
! 2694:
! 2695: /*
! 2696: * Disable card interrupts to prevent any race conditions
! 2697: * (they will be re-enabled afterwards).
! 2698: */
! 2699: AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_DISABLE);
! 2700:
! 2701: old_mask = hal->ah_imr;
! 2702:
! 2703: /*
! 2704: * Add additional, chipset-dependent interrupt mask flags
! 2705: * and write them to the IMR (interrupt mask register).
! 2706: */
! 2707: int_mask = new_mask & HAL_INT_COMMON;
! 2708:
! 2709: if (new_mask & HAL_INT_RX)
! 2710: int_mask |=
! 2711: AR5K_AR5212_PIMR_RXOK |
! 2712: AR5K_AR5212_PIMR_RXERR |
! 2713: AR5K_AR5212_PIMR_RXORN |
! 2714: AR5K_AR5212_PIMR_RXDESC;
! 2715:
! 2716: if (new_mask & HAL_INT_TX)
! 2717: int_mask |=
! 2718: AR5K_AR5212_PIMR_TXOK |
! 2719: AR5K_AR5212_PIMR_TXERR |
! 2720: AR5K_AR5212_PIMR_TXDESC |
! 2721: AR5K_AR5212_PIMR_TXURN;
! 2722:
! 2723: if (new_mask & HAL_INT_FATAL) {
! 2724: int_mask |= AR5K_AR5212_PIMR_HIUERR;
! 2725: AR5K_REG_ENABLE_BITS(AR5K_AR5212_SIMR2,
! 2726: AR5K_AR5212_SIMR2_MCABT |
! 2727: AR5K_AR5212_SIMR2_SSERR |
! 2728: AR5K_AR5212_SIMR2_DPERR);
! 2729: }
! 2730:
! 2731: AR5K_REG_WRITE(AR5K_AR5212_PIMR, int_mask);
! 2732:
! 2733: /* Store new interrupt mask */
! 2734: hal->ah_imr = new_mask;
! 2735:
! 2736: /* ..re-enable interrupts */
! 2737: AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_ENABLE);
! 2738:
! 2739: return (old_mask);
! 2740: }
! 2741:
! 2742: /*
! 2743: * Misc internal functions
! 2744: */
! 2745:
! 2746: HAL_BOOL
! 2747: ar5k_ar5212_get_capabilities(struct ath_hal *hal)
! 2748: {
! 2749: u_int16_t ee_header;
! 2750:
! 2751: /* Capabilities stored in the EEPROM */
! 2752: ee_header = hal->ah_capabilities.cap_eeprom.ee_header;
! 2753:
! 2754: /*
! 2755: * XXX The AR5212 tranceiver supports frequencies from 4920 to 6100GHz
! 2756: * XXX and from 2312 to 2732GHz. There are problems with the current
! 2757: * XXX ieee80211 implementation because the IEEE channel mapping
! 2758: * XXX does not support negative channel numbers (2312MHz is channel
! 2759: * XXX -19). Of course, this doesn't matter because these channels
! 2760: * XXX are out of range but some regulation domains like MKK (Japan)
! 2761: * XXX will support frequencies somewhere around 4.8GHz.
! 2762: */
! 2763:
! 2764: /*
! 2765: * Set radio capabilities
! 2766: */
! 2767:
! 2768: if (AR5K_EEPROM_HDR_11A(ee_header)) {
! 2769: hal->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */
! 2770: hal->ah_capabilities.cap_range.range_5ghz_max = 6100;
! 2771:
! 2772: /* Set supported modes */
! 2773: hal->ah_capabilities.cap_mode =
! 2774: HAL_MODE_11A | HAL_MODE_TURBO | HAL_MODE_XR;
! 2775: }
! 2776:
! 2777: /* This chip will support 802.11b if the 2GHz radio is connected */
! 2778: if (AR5K_EEPROM_HDR_11B(ee_header) || AR5K_EEPROM_HDR_11G(ee_header)) {
! 2779: hal->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */
! 2780: hal->ah_capabilities.cap_range.range_2ghz_max = 2732;
! 2781:
! 2782: if (AR5K_EEPROM_HDR_11B(ee_header))
! 2783: hal->ah_capabilities.cap_mode |= HAL_MODE_11B;
! 2784: #if 0
! 2785: if (AR5K_EEPROM_HDR_11G(ee_header))
! 2786: hal->ah_capabilities.cap_mode |= HAL_MODE_11G;
! 2787: #endif
! 2788: }
! 2789:
! 2790: /* GPIO */
! 2791: hal->ah_gpio_npins = AR5K_AR5212_NUM_GPIO;
! 2792:
! 2793: /* Set number of supported TX queues */
! 2794: hal->ah_capabilities.cap_queues.q_tx_num = AR5K_AR5212_TX_NUM_QUEUES;
! 2795:
! 2796: return (AH_TRUE);
! 2797: }
! 2798:
! 2799: void
! 2800: ar5k_ar5212_radar_alert(struct ath_hal *hal, HAL_BOOL enable)
! 2801: {
! 2802: /*
! 2803: * Enable radar detection
! 2804: */
! 2805: AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_DISABLE);
! 2806:
! 2807: if (enable == AH_TRUE) {
! 2808: AR5K_REG_WRITE(AR5K_AR5212_PHY_RADAR,
! 2809: AR5K_AR5212_PHY_RADAR_ENABLE);
! 2810: AR5K_REG_ENABLE_BITS(AR5K_AR5212_PIMR,
! 2811: AR5K_AR5212_PIMR_RXPHY);
! 2812: } else {
! 2813: AR5K_REG_WRITE(AR5K_AR5212_PHY_RADAR,
! 2814: AR5K_AR5212_PHY_RADAR_DISABLE);
! 2815: AR5K_REG_DISABLE_BITS(AR5K_AR5212_PIMR,
! 2816: AR5K_AR5212_PIMR_RXPHY);
! 2817: }
! 2818:
! 2819: AR5K_REG_WRITE(AR5K_AR5212_IER, AR5K_AR5212_IER_ENABLE);
! 2820: }
! 2821:
! 2822: /*
! 2823: * EEPROM access functions
! 2824: */
! 2825:
! 2826: HAL_BOOL
! 2827: ar5k_ar5212_eeprom_is_busy(struct ath_hal *hal)
! 2828: {
! 2829: return (AR5K_REG_READ(AR5K_AR5212_CFG) & AR5K_AR5212_CFG_EEBS ?
! 2830: AH_TRUE : AH_FALSE);
! 2831: }
! 2832:
! 2833: int
! 2834: ar5k_ar5212_eeprom_read(struct ath_hal *hal, u_int32_t offset, u_int16_t *data)
! 2835: {
! 2836: u_int32_t status, i;
! 2837:
! 2838: /*
! 2839: * Initialize EEPROM access
! 2840: */
! 2841: AR5K_REG_WRITE(AR5K_AR5212_EEPROM_BASE, (u_int8_t)offset);
! 2842: AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD,
! 2843: AR5K_AR5212_EEPROM_CMD_READ);
! 2844:
! 2845: for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
! 2846: status = AR5K_REG_READ(AR5K_AR5212_EEPROM_STATUS);
! 2847: if (status & AR5K_AR5212_EEPROM_STAT_RDDONE) {
! 2848: if (status & AR5K_AR5212_EEPROM_STAT_RDERR)
! 2849: return (EIO);
! 2850: *data = (u_int16_t)
! 2851: (AR5K_REG_READ(AR5K_AR5212_EEPROM_DATA) & 0xffff);
! 2852: return (0);
! 2853: }
! 2854: AR5K_DELAY(15);
! 2855: }
! 2856:
! 2857: return (ETIMEDOUT);
! 2858: }
! 2859:
! 2860: int
! 2861: ar5k_ar5212_eeprom_write(struct ath_hal *hal, u_int32_t offset, u_int16_t data)
! 2862: {
! 2863: u_int32_t status, timeout;
! 2864:
! 2865: /* Enable eeprom access */
! 2866: AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD,
! 2867: AR5K_AR5212_EEPROM_CMD_RESET);
! 2868: AR5K_REG_ENABLE_BITS(AR5K_AR5212_EEPROM_CMD,
! 2869: AR5K_AR5212_EEPROM_CMD_WRITE);
! 2870:
! 2871: /*
! 2872: * Prime write pump
! 2873: */
! 2874: AR5K_REG_WRITE(AR5K_AR5212_EEPROM_BASE, (u_int8_t)offset - 1);
! 2875:
! 2876: for (timeout = 10000; timeout > 0; timeout--) {
! 2877: AR5K_DELAY(1);
! 2878: status = AR5K_REG_READ(AR5K_AR5212_EEPROM_STATUS);
! 2879: if (status & AR5K_AR5212_EEPROM_STAT_WRDONE) {
! 2880: if (status & AR5K_AR5212_EEPROM_STAT_WRERR)
! 2881: return (EIO);
! 2882: return (0);
! 2883: }
! 2884: }
! 2885:
! 2886: return (ETIMEDOUT);
! 2887: }
! 2888:
! 2889: /*
! 2890: * TX power setup
! 2891: */
! 2892:
! 2893: HAL_BOOL
! 2894: ar5k_ar5212_txpower(struct ath_hal *hal, HAL_CHANNEL *channel, u_int txpower)
! 2895: {
! 2896: HAL_BOOL tpc = hal->ah_txpower.txp_tpc;
! 2897: int i;
! 2898:
! 2899: if (txpower > AR5K_TUNE_MAX_TXPOWER) {
! 2900: AR5K_PRINTF("invalid tx power: %u\n", txpower);
! 2901: return (AH_FALSE);
! 2902: }
! 2903:
! 2904: /* Reset TX power values */
! 2905: bzero(&hal->ah_txpower, sizeof(hal->ah_txpower));
! 2906: hal->ah_txpower.txp_tpc = tpc;
! 2907:
! 2908: /* Initialize TX power table */
! 2909: ar5k_txpower_table(hal, channel, txpower);
! 2910:
! 2911: /*
! 2912: * Write TX power values
! 2913: */
! 2914: for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
! 2915: AR5K_REG_WRITE(AR5K_AR5212_PHY_PCDAC_TXPOWER(i),
! 2916: ((((hal->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) &
! 2917: 0xffff) << 16) | (((hal->ah_txpower.txp_pcdac[i << 1] << 8)
! 2918: | 0xff) & 0xffff));
! 2919: }
! 2920:
! 2921: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE1,
! 2922: AR5K_TXPOWER_OFDM(3, 24) | AR5K_TXPOWER_OFDM(2, 16)
! 2923: | AR5K_TXPOWER_OFDM(1, 8) | AR5K_TXPOWER_OFDM(0, 0));
! 2924:
! 2925: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE2,
! 2926: AR5K_TXPOWER_OFDM(7, 24) | AR5K_TXPOWER_OFDM(6, 16)
! 2927: | AR5K_TXPOWER_OFDM(5, 8) | AR5K_TXPOWER_OFDM(4, 0));
! 2928:
! 2929: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE3,
! 2930: AR5K_TXPOWER_CCK(10, 24) | AR5K_TXPOWER_CCK(9, 16)
! 2931: | AR5K_TXPOWER_CCK(15, 8) | AR5K_TXPOWER_CCK(8, 0));
! 2932:
! 2933: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE4,
! 2934: AR5K_TXPOWER_CCK(14, 24) | AR5K_TXPOWER_CCK(13, 16)
! 2935: | AR5K_TXPOWER_CCK(12, 8) | AR5K_TXPOWER_CCK(11, 0));
! 2936:
! 2937: if (hal->ah_txpower.txp_tpc == AH_TRUE) {
! 2938: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE_MAX,
! 2939: AR5K_AR5212_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
! 2940: AR5K_TUNE_MAX_TXPOWER);
! 2941: } else {
! 2942: AR5K_REG_WRITE(AR5K_AR5212_PHY_TXPOWER_RATE_MAX,
! 2943: AR5K_AR5212_PHY_TXPOWER_RATE_MAX |
! 2944: AR5K_TUNE_MAX_TXPOWER);
! 2945: }
! 2946:
! 2947: return (AH_TRUE);
! 2948: }
! 2949:
! 2950: HAL_BOOL
! 2951: ar5k_ar5212_set_txpower_limit(struct ath_hal *hal, u_int power)
! 2952: {
! 2953: HAL_CHANNEL *channel = &hal->ah_current_channel;
! 2954:
! 2955: AR5K_PRINTF("changing txpower to %d\n", power);
! 2956: return (ar5k_ar5212_txpower(hal, channel, power));
! 2957: }
CVSweb