Annotation of sys/dev/ic/ar5210.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ar5210.c,v 1.39 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 AR5000 Wireless LAN chipset
! 21: * (AR5210 + AR5110).
! 22: */
! 23:
! 24: #include <dev/ic/ar5xxx.h>
! 25: #include <dev/ic/ar5210reg.h>
! 26: #include <dev/ic/ar5210var.h>
! 27:
! 28: HAL_BOOL ar5k_ar5210_nic_reset(struct ath_hal *, u_int32_t);
! 29: HAL_BOOL ar5k_ar5210_nic_wakeup(struct ath_hal *, HAL_BOOL, HAL_BOOL);
! 30: void ar5k_ar5210_init_tx_queue(struct ath_hal *, u_int, HAL_BOOL);
! 31: const void ar5k_ar5210_fill(struct ath_hal *);
! 32: HAL_BOOL ar5k_ar5210_do_calibrate(struct ath_hal *, HAL_CHANNEL *);
! 33: HAL_BOOL ar5k_ar5210_noise_floor(struct ath_hal *, HAL_CHANNEL *);
! 34:
! 35: /*
! 36: * Initial register setting for the AR5210
! 37: */
! 38: static const struct ar5k_ini ar5210_ini[] =
! 39: AR5K_AR5210_INI;
! 40:
! 41: AR5K_HAL_FUNCTIONS(extern, ar5k_ar5210,);
! 42:
! 43: const void
! 44: ar5k_ar5210_fill(struct ath_hal *hal)
! 45: {
! 46: hal->ah_magic = AR5K_AR5210_MAGIC;
! 47:
! 48: /*
! 49: * Init/Exit functions
! 50: */
! 51: AR5K_HAL_FUNCTION(hal, ar5210, get_rate_table);
! 52: AR5K_HAL_FUNCTION(hal, ar5210, detach);
! 53:
! 54: /*
! 55: * Reset functions
! 56: */
! 57: AR5K_HAL_FUNCTION(hal, ar5210, reset);
! 58: AR5K_HAL_FUNCTION(hal, ar5210, set_opmode);
! 59: AR5K_HAL_FUNCTION(hal, ar5210, calibrate);
! 60:
! 61: /*
! 62: * TX functions
! 63: */
! 64: AR5K_HAL_FUNCTION(hal, ar5210, update_tx_triglevel);
! 65: AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_queue);
! 66: AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_queueprops);
! 67: AR5K_HAL_FUNCTION(hal, ar5210, release_tx_queue);
! 68: AR5K_HAL_FUNCTION(hal, ar5210, reset_tx_queue);
! 69: AR5K_HAL_FUNCTION(hal, ar5210, get_tx_buf);
! 70: AR5K_HAL_FUNCTION(hal, ar5210, put_tx_buf);
! 71: AR5K_HAL_FUNCTION(hal, ar5210, tx_start);
! 72: AR5K_HAL_FUNCTION(hal, ar5210, stop_tx_dma);
! 73: AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_desc);
! 74: AR5K_HAL_FUNCTION(hal, ar5210, setup_xtx_desc);
! 75: AR5K_HAL_FUNCTION(hal, ar5210, fill_tx_desc);
! 76: AR5K_HAL_FUNCTION(hal, ar5210, proc_tx_desc);
! 77: AR5K_HAL_FUNCTION(hal, ar5210, has_veol);
! 78:
! 79: /*
! 80: * RX functions
! 81: */
! 82: AR5K_HAL_FUNCTION(hal, ar5210, get_rx_buf);
! 83: AR5K_HAL_FUNCTION(hal, ar5210, put_rx_buf);
! 84: AR5K_HAL_FUNCTION(hal, ar5210, start_rx);
! 85: AR5K_HAL_FUNCTION(hal, ar5210, stop_rx_dma);
! 86: AR5K_HAL_FUNCTION(hal, ar5210, start_rx_pcu);
! 87: AR5K_HAL_FUNCTION(hal, ar5210, stop_pcu_recv);
! 88: AR5K_HAL_FUNCTION(hal, ar5210, set_mcast_filter);
! 89: AR5K_HAL_FUNCTION(hal, ar5210, set_mcast_filterindex);
! 90: AR5K_HAL_FUNCTION(hal, ar5210, clear_mcast_filter_idx);
! 91: AR5K_HAL_FUNCTION(hal, ar5210, get_rx_filter);
! 92: AR5K_HAL_FUNCTION(hal, ar5210, set_rx_filter);
! 93: AR5K_HAL_FUNCTION(hal, ar5210, setup_rx_desc);
! 94: AR5K_HAL_FUNCTION(hal, ar5210, proc_rx_desc);
! 95: AR5K_HAL_FUNCTION(hal, ar5210, set_rx_signal);
! 96:
! 97: /*
! 98: * Misc functions
! 99: */
! 100: AR5K_HAL_FUNCTION(hal, ar5210, dump_state);
! 101: AR5K_HAL_FUNCTION(hal, ar5210, get_diag_state);
! 102: AR5K_HAL_FUNCTION(hal, ar5210, get_lladdr);
! 103: AR5K_HAL_FUNCTION(hal, ar5210, set_lladdr);
! 104: AR5K_HAL_FUNCTION(hal, ar5210, set_regdomain);
! 105: AR5K_HAL_FUNCTION(hal, ar5210, set_ledstate);
! 106: AR5K_HAL_FUNCTION(hal, ar5210, set_associd);
! 107: AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_input);
! 108: AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_output);
! 109: AR5K_HAL_FUNCTION(hal, ar5210, get_gpio);
! 110: AR5K_HAL_FUNCTION(hal, ar5210, set_gpio);
! 111: AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_intr);
! 112: AR5K_HAL_FUNCTION(hal, ar5210, get_tsf32);
! 113: AR5K_HAL_FUNCTION(hal, ar5210, get_tsf64);
! 114: AR5K_HAL_FUNCTION(hal, ar5210, reset_tsf);
! 115: AR5K_HAL_FUNCTION(hal, ar5210, get_regdomain);
! 116: AR5K_HAL_FUNCTION(hal, ar5210, detect_card_present);
! 117: AR5K_HAL_FUNCTION(hal, ar5210, update_mib_counters);
! 118: AR5K_HAL_FUNCTION(hal, ar5210, get_rf_gain);
! 119: AR5K_HAL_FUNCTION(hal, ar5210, set_slot_time);
! 120: AR5K_HAL_FUNCTION(hal, ar5210, get_slot_time);
! 121: AR5K_HAL_FUNCTION(hal, ar5210, set_ack_timeout);
! 122: AR5K_HAL_FUNCTION(hal, ar5210, get_ack_timeout);
! 123: AR5K_HAL_FUNCTION(hal, ar5210, set_cts_timeout);
! 124: AR5K_HAL_FUNCTION(hal, ar5210, get_cts_timeout);
! 125:
! 126: /*
! 127: * Key table (WEP) functions
! 128: */
! 129: AR5K_HAL_FUNCTION(hal, ar5210, is_cipher_supported);
! 130: AR5K_HAL_FUNCTION(hal, ar5210, get_keycache_size);
! 131: AR5K_HAL_FUNCTION(hal, ar5210, reset_key);
! 132: AR5K_HAL_FUNCTION(hal, ar5210, is_key_valid);
! 133: AR5K_HAL_FUNCTION(hal, ar5210, set_key);
! 134: AR5K_HAL_FUNCTION(hal, ar5210, set_key_lladdr);
! 135:
! 136: /*
! 137: * Power management functions
! 138: */
! 139: AR5K_HAL_FUNCTION(hal, ar5210, set_power);
! 140: AR5K_HAL_FUNCTION(hal, ar5210, get_power_mode);
! 141: AR5K_HAL_FUNCTION(hal, ar5210, query_pspoll_support);
! 142: AR5K_HAL_FUNCTION(hal, ar5210, init_pspoll);
! 143: AR5K_HAL_FUNCTION(hal, ar5210, enable_pspoll);
! 144: AR5K_HAL_FUNCTION(hal, ar5210, disable_pspoll);
! 145:
! 146: /*
! 147: * Beacon functions
! 148: */
! 149: AR5K_HAL_FUNCTION(hal, ar5210, init_beacon);
! 150: AR5K_HAL_FUNCTION(hal, ar5210, set_beacon_timers);
! 151: AR5K_HAL_FUNCTION(hal, ar5210, reset_beacon);
! 152: AR5K_HAL_FUNCTION(hal, ar5210, wait_for_beacon);
! 153:
! 154: /*
! 155: * Interrupt functions
! 156: */
! 157: AR5K_HAL_FUNCTION(hal, ar5210, is_intr_pending);
! 158: AR5K_HAL_FUNCTION(hal, ar5210, get_isr);
! 159: AR5K_HAL_FUNCTION(hal, ar5210, get_intr);
! 160: AR5K_HAL_FUNCTION(hal, ar5210, set_intr);
! 161:
! 162: /*
! 163: * Chipset functions (ar5k-specific, non-HAL)
! 164: */
! 165: AR5K_HAL_FUNCTION(hal, ar5210, get_capabilities);
! 166: AR5K_HAL_FUNCTION(hal, ar5210, radar_alert);
! 167:
! 168: /*
! 169: * EEPROM access
! 170: */
! 171: AR5K_HAL_FUNCTION(hal, ar5210, eeprom_is_busy);
! 172: AR5K_HAL_FUNCTION(hal, ar5210, eeprom_read);
! 173: AR5K_HAL_FUNCTION(hal, ar5210, eeprom_write);
! 174:
! 175: /*
! 176: * Unused functions or functions not implemented
! 177: */
! 178: AR5K_HAL_FUNCTION(hal, ar5210, set_bssid_mask);
! 179: AR5K_HAL_FUNCTION(hal, ar5210, get_tx_queueprops);
! 180: AR5K_HAL_FUNCTION(hal, ar5210, num_tx_pending);
! 181: AR5K_HAL_FUNCTION(hal, ar5210, phy_disable);
! 182: AR5K_HAL_FUNCTION(hal, ar5210, set_txpower_limit);
! 183: AR5K_HAL_FUNCTION(hal, ar5210, set_def_antenna);
! 184: AR5K_HAL_FUNCTION(hal, ar5210, get_def_antenna);
! 185: #ifdef notyet
! 186: AR5K_HAL_FUNCTION(hal, ar5210, set_capability);
! 187: AR5K_HAL_FUNCTION(hal, ar5210, proc_mib_event);
! 188: AR5K_HAL_FUNCTION(hal, ar5210, get_tx_inter_queue);
! 189: #endif
! 190: }
! 191:
! 192: struct ath_hal *
! 193: ar5k_ar5210_attach(u_int16_t device, void *sc, bus_space_tag_t st,
! 194: bus_space_handle_t sh, int *status)
! 195: {
! 196: int i;
! 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_ar5210_fill(hal);
! 202:
! 203: /* Bring device out of sleep and reset its units */
! 204: if (ar5k_ar5210_nic_wakeup(hal, AH_FALSE, AH_TRUE) != AH_TRUE)
! 205: return (NULL);
! 206:
! 207: /* Get MAC, PHY and RADIO revisions */
! 208: srev = AR5K_REG_READ(AR5K_AR5210_SREV);
! 209: hal->ah_mac_srev = srev;
! 210: hal->ah_mac_version = AR5K_REG_MS(srev, AR5K_AR5210_SREV_VER);
! 211: hal->ah_mac_revision = AR5K_REG_MS(srev, AR5K_AR5210_SREV_REV);
! 212: hal->ah_phy_revision = AR5K_REG_READ(AR5K_AR5210_PHY_CHIP_ID) &
! 213: 0x00ffffffff;
! 214:
! 215: /* ...wait until PHY is ready and read RADIO revision */
! 216: AR5K_REG_WRITE(AR5K_AR5210_PHY(0x34), 0x00001c16);
! 217: for (i = 0; i < 4; i++)
! 218: AR5K_REG_WRITE(AR5K_AR5210_PHY(0x20), 0x00010000);
! 219: hal->ah_radio_5ghz_revision = (u_int16_t)
! 220: (ar5k_bitswap((AR5K_REG_READ(AR5K_AR5210_PHY(256) >> 28) & 0xf), 4)
! 221: + 1);
! 222: hal->ah_radio_2ghz_revision = 0;
! 223:
! 224: /* Identify the chipset */
! 225: hal->ah_version = AR5K_AR5210;
! 226: hal->ah_radio = AR5K_AR5110;
! 227: hal->ah_phy = AR5K_AR5210_PHY(0);
! 228:
! 229: bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN);
! 230: ar5k_ar5210_set_associd(hal, mac, 0, 0);
! 231: ar5k_ar5210_get_lladdr(hal, mac);
! 232: ar5k_ar5210_set_opmode(hal);
! 233:
! 234: return (hal);
! 235: }
! 236:
! 237: HAL_BOOL
! 238: ar5k_ar5210_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: /*
! 244: * Reset the device and wait until success
! 245: */
! 246: AR5K_REG_WRITE(AR5K_AR5210_RC, val);
! 247:
! 248: /* Wait at least 128 PCI clocks */
! 249: AR5K_DELAY(15);
! 250:
! 251: val &=
! 252: AR5K_AR5210_RC_PCU | AR5K_AR5210_RC_MAC |
! 253: AR5K_AR5210_RC_PHY | AR5K_AR5210_RC_DMA;
! 254:
! 255: mask &=
! 256: AR5K_AR5210_RC_PCU | AR5K_AR5210_RC_MAC |
! 257: AR5K_AR5210_RC_PHY | AR5K_AR5210_RC_DMA;
! 258:
! 259: ret = ar5k_register_timeout(hal, AR5K_AR5210_RC, mask, val, AH_FALSE);
! 260:
! 261: /*
! 262: * Reset configuration register
! 263: */
! 264: if ((val & AR5K_AR5210_RC_MAC) == 0) {
! 265: AR5K_REG_WRITE(AR5K_AR5210_CFG, AR5K_AR5210_INIT_CFG);
! 266: }
! 267:
! 268: return (ret);
! 269: }
! 270:
! 271: HAL_BOOL
! 272: ar5k_ar5210_nic_wakeup(struct ath_hal *hal, HAL_BOOL turbo, HAL_BOOL initial)
! 273: {
! 274: /*
! 275: * Reset and wakeup the device
! 276: */
! 277:
! 278: if (initial == AH_TRUE) {
! 279: /* ...reset hardware */
! 280: if (ar5k_ar5210_nic_reset(hal,
! 281: AR5K_AR5210_RC_PCI) == AH_FALSE) {
! 282: AR5K_PRINT("failed to reset the PCI chipset\n");
! 283: return (AH_FALSE);
! 284: }
! 285:
! 286: AR5K_DELAY(1000);
! 287: }
! 288:
! 289: /* ...wakeup the device */
! 290: if (ar5k_ar5210_set_power(hal,
! 291: HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
! 292: AR5K_PRINT("failed to resume the AR5210 chipset\n");
! 293: return (AH_FALSE);
! 294: }
! 295:
! 296: /* ...enable Atheros turbo mode if requested */
! 297: AR5K_REG_WRITE(AR5K_AR5210_PHY_FC,
! 298: turbo == AH_TRUE ? AR5K_AR5210_PHY_FC_TURBO_MODE : 0);
! 299:
! 300: /* ...reset chipset */
! 301: if (ar5k_ar5210_nic_reset(hal, AR5K_AR5210_RC_CHIP) == AH_FALSE) {
! 302: AR5K_PRINT("failed to reset the AR5210 chipset\n");
! 303: return (AH_FALSE);
! 304: }
! 305:
! 306: AR5K_DELAY(1000);
! 307:
! 308: /* ...reset chipset and PCI device */
! 309: if (ar5k_ar5210_nic_reset(hal,
! 310: AR5K_AR5210_RC_CHIP | AR5K_AR5210_RC_PCI) == AH_FALSE) {
! 311: AR5K_PRINT("failed to reset the AR5210 + PCI chipset\n");
! 312: return (AH_FALSE);
! 313: }
! 314:
! 315: AR5K_DELAY(2300);
! 316:
! 317: /* ...wakeup (again) */
! 318: if (ar5k_ar5210_set_power(hal,
! 319: HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) {
! 320: AR5K_PRINT("failed to resume the AR5210 (again)\n");
! 321: return (AH_FALSE);
! 322: }
! 323:
! 324: /* ...final warm reset */
! 325: if (ar5k_ar5210_nic_reset(hal, 0) == AH_FALSE) {
! 326: AR5K_PRINT("failed to warm reset the AR5210\n");
! 327: return (AH_FALSE);
! 328: }
! 329:
! 330: return (AH_TRUE);
! 331: }
! 332:
! 333: const HAL_RATE_TABLE *
! 334: ar5k_ar5210_get_rate_table(struct ath_hal *hal, u_int mode)
! 335: {
! 336: switch (mode) {
! 337: case HAL_MODE_11A:
! 338: return (&hal->ah_rt_11a);
! 339: case HAL_MODE_TURBO:
! 340: return (&hal->ah_rt_turbo);
! 341: case HAL_MODE_11B:
! 342: case HAL_MODE_11G:
! 343: default:
! 344: return (NULL);
! 345: }
! 346:
! 347: return (NULL);
! 348: }
! 349:
! 350: void
! 351: ar5k_ar5210_detach(struct ath_hal *hal)
! 352: {
! 353: /*
! 354: * Free HAL structure, assume interrupts are down
! 355: */
! 356: free(hal, M_DEVBUF);
! 357: }
! 358:
! 359: HAL_BOOL
! 360: ar5k_ar5210_phy_disable(struct ath_hal *hal)
! 361: {
! 362: AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE);
! 363: return (AH_TRUE);
! 364: }
! 365:
! 366: HAL_BOOL
! 367: ar5k_ar5210_reset(struct ath_hal *hal, HAL_OPMODE op_mode, HAL_CHANNEL *channel,
! 368: HAL_BOOL change_channel, HAL_STATUS *status)
! 369: {
! 370: int i;
! 371:
! 372: /* Not used, keep for HAL compatibility */
! 373: *status = HAL_OK;
! 374:
! 375: if (ar5k_ar5210_nic_wakeup(hal,
! 376: channel->c_channel_flags & IEEE80211_CHAN_T ?
! 377: AH_TRUE : AH_FALSE, AH_FALSE) == AH_FALSE)
! 378: return (AH_FALSE);
! 379:
! 380: /*
! 381: * Initialize operating mode
! 382: */
! 383: hal->ah_op_mode = op_mode;
! 384: ar5k_ar5210_set_opmode(hal);
! 385:
! 386: /*
! 387: * Write initial mode register settings
! 388: */
! 389: for (i = 0; i < AR5K_ELEMENTS(ar5210_ini); i++) {
! 390: if (change_channel == AH_TRUE &&
! 391: ar5210_ini[i].ini_register >= AR5K_AR5210_PCU_MIN &&
! 392: ar5210_ini[i].ini_register <= AR5K_AR5210_PCU_MAX)
! 393: continue;
! 394:
! 395: switch (ar5210_ini[i].ini_mode) {
! 396: case AR5K_INI_READ:
! 397: /* Cleared on read */
! 398: AR5K_REG_READ(ar5210_ini[i].ini_register);
! 399: break;
! 400:
! 401: case AR5K_INI_WRITE:
! 402: default:
! 403: AR5K_REG_WRITE(ar5210_ini[i].ini_register,
! 404: ar5210_ini[i].ini_value);
! 405: }
! 406: }
! 407:
! 408: AR5K_DELAY(1000);
! 409:
! 410: /*
! 411: * Set channel and calibrate the PHY
! 412: */
! 413:
! 414: /* Disable phy and wait */
! 415: AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE);
! 416: AR5K_DELAY(1000);
! 417:
! 418: if (ar5k_channel(hal, channel) == AH_FALSE)
! 419: return (AH_FALSE);
! 420:
! 421: /*
! 422: * Activate phy and wait
! 423: */
! 424: AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE);
! 425: AR5K_DELAY(1000);
! 426:
! 427: ar5k_ar5210_do_calibrate(hal, channel);
! 428: if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE)
! 429: return (AH_FALSE);
! 430:
! 431: /*
! 432: * Set RF kill flags if supported by the device (read from the EEPROM)
! 433: */
! 434: if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) {
! 435: ar5k_ar5210_set_gpio_input(hal, 0);
! 436: if ((hal->ah_gpio[0] = ar5k_ar5210_get_gpio(hal, 0)) == 0) {
! 437: ar5k_ar5210_set_gpio_intr(hal, 0, 1);
! 438: } else {
! 439: ar5k_ar5210_set_gpio_intr(hal, 0, 0);
! 440: }
! 441: }
! 442:
! 443: /*
! 444: * Reset queues and start beacon timers at the end of the reset routine
! 445: */
! 446: for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) {
! 447: if (ar5k_ar5210_reset_tx_queue(hal, i) == AH_FALSE) {
! 448: AR5K_PRINTF("failed to reset TX queue #%d\n", i);
! 449: return (AH_FALSE);
! 450: }
! 451: }
! 452:
! 453: AR5K_REG_DISABLE_BITS(AR5K_AR5210_BEACON,
! 454: AR5K_AR5210_BEACON_EN | AR5K_AR5210_BEACON_RESET_TSF);
! 455:
! 456: return (AH_TRUE);
! 457: }
! 458:
! 459: void
! 460: ar5k_ar5210_set_def_antenna(struct ath_hal *hal, u_int ant)
! 461: {
! 462: /* Not available */
! 463: return;
! 464: }
! 465:
! 466: u_int
! 467: ar5k_ar5210_get_def_antenna(struct ath_hal *hal)
! 468: {
! 469: return (0);
! 470: }
! 471:
! 472: void
! 473: ar5k_ar5210_set_opmode(struct ath_hal *hal)
! 474: {
! 475: u_int32_t pcu_reg, beacon_reg, low_id, high_id;
! 476:
! 477: beacon_reg = 0;
! 478: pcu_reg = 0;
! 479:
! 480: switch (hal->ah_op_mode) {
! 481: case IEEE80211_M_STA:
! 482: pcu_reg |= AR5K_AR5210_STA_ID1_NO_PSPOLL |
! 483: AR5K_AR5210_STA_ID1_DESC_ANTENNA |
! 484: AR5K_AR5210_STA_ID1_PWR_SV;
! 485: break;
! 486:
! 487: case IEEE80211_M_IBSS:
! 488: pcu_reg |= AR5K_AR5210_STA_ID1_ADHOC |
! 489: AR5K_AR5210_STA_ID1_NO_PSPOLL |
! 490: AR5K_AR5210_STA_ID1_DESC_ANTENNA;
! 491: beacon_reg |= AR5K_AR5210_BCR_ADHOC;
! 492: break;
! 493:
! 494: case IEEE80211_M_HOSTAP:
! 495: pcu_reg |= AR5K_AR5210_STA_ID1_AP |
! 496: AR5K_AR5210_STA_ID1_NO_PSPOLL |
! 497: AR5K_AR5210_STA_ID1_DESC_ANTENNA;
! 498: beacon_reg |= AR5K_AR5210_BCR_AP;
! 499: break;
! 500:
! 501: case IEEE80211_M_MONITOR:
! 502: pcu_reg |= AR5K_AR5210_STA_ID1_NO_PSPOLL;
! 503: break;
! 504:
! 505: default:
! 506: return;
! 507: }
! 508:
! 509: /*
! 510: * Set PCU and BCR registers
! 511: */
! 512: low_id = AR5K_LOW_ID(hal->ah_sta_id);
! 513: high_id = AR5K_HIGH_ID(hal->ah_sta_id);
! 514: AR5K_REG_WRITE(AR5K_AR5210_STA_ID0, low_id);
! 515: AR5K_REG_WRITE(AR5K_AR5210_STA_ID1, pcu_reg | high_id);
! 516: AR5K_REG_WRITE(AR5K_AR5210_BCR, beacon_reg);
! 517:
! 518: return;
! 519: }
! 520:
! 521: HAL_BOOL
! 522: ar5k_ar5210_calibrate(struct ath_hal *hal, HAL_CHANNEL *channel)
! 523: {
! 524: HAL_BOOL ret = AH_TRUE;
! 525: u_int32_t phy_sig, phy_agc, phy_sat, beacon;
! 526:
! 527: #define AGC_DISABLE { \
! 528: AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGC, \
! 529: AR5K_AR5210_PHY_AGC_DISABLE); \
! 530: AR5K_DELAY(10); \
! 531: }
! 532:
! 533: #define AGC_ENABLE { \
! 534: AR5K_REG_DISABLE_BITS(AR5K_AR5210_PHY_AGC, \
! 535: AR5K_AR5210_PHY_AGC_DISABLE); \
! 536: }
! 537:
! 538: /*
! 539: * Disable beacons and RX/TX queues, wait
! 540: */
! 541: AR5K_REG_ENABLE_BITS(AR5K_AR5210_DIAG_SW,
! 542: AR5K_AR5210_DIAG_SW_DIS_TX | AR5K_AR5210_DIAG_SW_DIS_RX);
! 543: beacon = AR5K_REG_READ(AR5K_AR5210_BEACON);
! 544: AR5K_REG_WRITE(AR5K_AR5210_BEACON, beacon & ~AR5K_AR5210_BEACON_EN);
! 545:
! 546: AR5K_DELAY(2300);
! 547:
! 548: /*
! 549: * Set the channel (with AGC turned off)
! 550: */
! 551: AGC_DISABLE;
! 552: ret = ar5k_channel(hal, channel);
! 553:
! 554: /*
! 555: * Activate PHY and wait
! 556: */
! 557: AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE);
! 558: AR5K_DELAY(1000);
! 559:
! 560: AGC_ENABLE;
! 561:
! 562: if (ret == AH_FALSE)
! 563: return (ret);
! 564:
! 565: /*
! 566: * Calibrate the radio chip
! 567: */
! 568:
! 569: /* Remember normal state */
! 570: phy_sig = AR5K_REG_READ(AR5K_AR5210_PHY_SIG);
! 571: phy_agc = AR5K_REG_READ(AR5K_AR5210_PHY_AGCCOARSE);
! 572: phy_sat = AR5K_REG_READ(AR5K_AR5210_PHY_ADCSAT);
! 573:
! 574: /* Update radio registers */
! 575: AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG,
! 576: (phy_sig & ~(AR5K_AR5210_PHY_SIG_FIRPWR)) |
! 577: AR5K_REG_SM(-1, AR5K_AR5210_PHY_SIG_FIRPWR));
! 578:
! 579: AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE,
! 580: (phy_agc & ~(AR5K_AR5210_PHY_AGCCOARSE_HI |
! 581: AR5K_AR5210_PHY_AGCCOARSE_LO)) |
! 582: AR5K_REG_SM(-1, AR5K_AR5210_PHY_AGCCOARSE_HI) |
! 583: AR5K_REG_SM(-127, AR5K_AR5210_PHY_AGCCOARSE_LO));
! 584:
! 585: AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT,
! 586: (phy_sat & ~(AR5K_AR5210_PHY_ADCSAT_ICNT |
! 587: AR5K_AR5210_PHY_ADCSAT_THR)) |
! 588: AR5K_REG_SM(2, AR5K_AR5210_PHY_ADCSAT_ICNT) |
! 589: AR5K_REG_SM(12, AR5K_AR5210_PHY_ADCSAT_THR));
! 590:
! 591: AR5K_DELAY(20);
! 592:
! 593: AGC_DISABLE;
! 594: AR5K_REG_WRITE(AR5K_AR5210_PHY_RFSTG, AR5K_AR5210_PHY_RFSTG_DISABLE);
! 595: AGC_ENABLE;
! 596:
! 597: AR5K_DELAY(1000);
! 598:
! 599: ret = ar5k_ar5210_do_calibrate(hal, channel);
! 600:
! 601: /* Reset to normal state */
! 602: AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG, phy_sig);
! 603: AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE, phy_agc);
! 604: AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT, phy_sat);
! 605:
! 606: if (ret == AH_FALSE)
! 607: return (AH_FALSE);
! 608:
! 609: if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE)
! 610: return (AH_FALSE);
! 611:
! 612: /*
! 613: * Re-enable RX/TX and beacons
! 614: */
! 615: AR5K_REG_DISABLE_BITS(AR5K_AR5210_DIAG_SW,
! 616: AR5K_AR5210_DIAG_SW_DIS_TX | AR5K_AR5210_DIAG_SW_DIS_RX);
! 617: AR5K_REG_WRITE(AR5K_AR5210_BEACON, beacon);
! 618:
! 619: #undef AGC_ENABLE
! 620: #undef AGC_DISABLE
! 621:
! 622: return (AH_TRUE);
! 623: }
! 624:
! 625: HAL_BOOL
! 626: ar5k_ar5210_do_calibrate(struct ath_hal *hal, HAL_CHANNEL *channel)
! 627: {
! 628: /*
! 629: * Enable calibration and wait until completion
! 630: */
! 631: AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGCCTL,
! 632: AR5K_AR5210_PHY_AGCCTL_CAL);
! 633:
! 634: if (ar5k_register_timeout(hal, AR5K_AR5210_PHY_AGCCTL,
! 635: AR5K_AR5210_PHY_AGCCTL_CAL, 0, AH_FALSE) == AH_FALSE) {
! 636: AR5K_PRINTF("calibration timeout (%uMHz)\n",
! 637: channel->c_channel);
! 638: return (AH_FALSE);
! 639: }
! 640:
! 641: return (AH_TRUE);
! 642: }
! 643:
! 644: HAL_BOOL
! 645: ar5k_ar5210_noise_floor(struct ath_hal *hal, HAL_CHANNEL *channel)
! 646: {
! 647: int i;
! 648: u_int32_t noise_floor;
! 649:
! 650: /*
! 651: * Enable noise floor calibration and wait until completion
! 652: */
! 653: AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGCCTL,
! 654: AR5K_AR5210_PHY_AGCCTL_NF);
! 655:
! 656: if (ar5k_register_timeout(hal, AR5K_AR5210_PHY_AGCCTL,
! 657: AR5K_AR5210_PHY_AGCCTL_NF, 0, AH_FALSE) == AH_FALSE) {
! 658: AR5K_PRINTF("noise floor calibration timeout (%uMHz)\n",
! 659: channel->c_channel);
! 660: return (AH_FALSE);
! 661: }
! 662:
! 663: /* wait until the noise floor is calibrated */
! 664: for (i = 20; i > 0; i--) {
! 665: AR5K_DELAY(1000);
! 666: noise_floor = AR5K_REG_READ(AR5K_AR5210_PHY_NF);
! 667: if (AR5K_AR5210_PHY_NF_RVAL(noise_floor) &
! 668: AR5K_AR5210_PHY_NF_ACTIVE)
! 669: noise_floor = AR5K_AR5210_PHY_NF_AVAL(noise_floor);
! 670: if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
! 671: break;
! 672: }
! 673:
! 674: if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
! 675: AR5K_PRINTF("noise floor calibration failed (%uMHz)\n",
! 676: channel->c_channel);
! 677: return (AH_FALSE);
! 678: }
! 679:
! 680: return (AH_TRUE);
! 681: }
! 682:
! 683: /*
! 684: * Transmit functions
! 685: */
! 686:
! 687: HAL_BOOL
! 688: ar5k_ar5210_update_tx_triglevel(struct ath_hal *hal, HAL_BOOL increase)
! 689: {
! 690: u_int32_t trigger_level;
! 691: HAL_BOOL status = AH_FALSE;
! 692:
! 693: /*
! 694: * Disable interrupts by setting the mask
! 695: */
! 696: AR5K_REG_DISABLE_BITS(AR5K_AR5210_IMR, HAL_INT_GLOBAL);
! 697:
! 698: trigger_level = AR5K_REG_READ(AR5K_AR5210_TRIG_LVL);
! 699:
! 700: if (increase == AH_FALSE) {
! 701: if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
! 702: goto done;
! 703: } else {
! 704: trigger_level +=
! 705: ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
! 706: }
! 707:
! 708: /*
! 709: * Update trigger level on success
! 710: */
! 711: AR5K_REG_WRITE(AR5K_AR5210_TRIG_LVL, trigger_level);
! 712: status = AH_TRUE;
! 713:
! 714: done:
! 715: /*
! 716: * Restore interrupt mask
! 717: */
! 718: AR5K_REG_ENABLE_BITS(AR5K_AR5210_IMR, HAL_INT_GLOBAL);
! 719:
! 720: return (status);
! 721: }
! 722:
! 723: int
! 724: ar5k_ar5210_setup_tx_queue(struct ath_hal *hal, HAL_TX_QUEUE queue_type,
! 725: const HAL_TXQ_INFO *queue_info)
! 726: {
! 727: u_int queue;
! 728:
! 729: /*
! 730: * Get queue by type
! 731: */
! 732: switch (queue_type) {
! 733: case HAL_TX_QUEUE_DATA:
! 734: queue = 0;
! 735: break;
! 736: case HAL_TX_QUEUE_BEACON:
! 737: case HAL_TX_QUEUE_CAB:
! 738: queue = 1;
! 739: break;
! 740: default:
! 741: return (-1);
! 742: }
! 743:
! 744: /*
! 745: * Setup internal queue structure
! 746: */
! 747: bzero(&hal->ah_txq[queue], sizeof(HAL_TXQ_INFO));
! 748: hal->ah_txq[queue].tqi_type = queue_type;
! 749:
! 750: if (queue_info != NULL) {
! 751: if (ar5k_ar5210_setup_tx_queueprops(hal,
! 752: queue, queue_info) != AH_TRUE)
! 753: return (-1);
! 754: }
! 755:
! 756: return (queue);
! 757: }
! 758:
! 759: HAL_BOOL
! 760: ar5k_ar5210_setup_tx_queueprops(struct ath_hal *hal, int queue,
! 761: const HAL_TXQ_INFO *queue_info)
! 762: {
! 763: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 764:
! 765: if (hal->ah_txq[queue].tqi_type == HAL_TX_QUEUE_INACTIVE)
! 766: return (AH_FALSE);
! 767:
! 768: hal->ah_txq[queue].tqi_aifs = queue_info->tqi_aifs;
! 769: hal->ah_txq[queue].tqi_cw_max = queue_info->tqi_cw_max;
! 770: hal->ah_txq[queue].tqi_cw_min = queue_info->tqi_cw_min;
! 771: hal->ah_txq[queue].tqi_flags = queue_info->tqi_flags;
! 772:
! 773: return (AH_TRUE);
! 774: }
! 775:
! 776: HAL_BOOL
! 777: ar5k_ar5210_get_tx_queueprops(struct ath_hal *hal, int queue,
! 778: HAL_TXQ_INFO *queue_info)
! 779: {
! 780: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 781: bcopy(&hal->ah_txq[queue], queue_info, sizeof(HAL_TXQ_INFO));
! 782: return (AH_TRUE);
! 783: }
! 784:
! 785: HAL_BOOL
! 786: ar5k_ar5210_release_tx_queue(struct ath_hal *hal, u_int queue)
! 787: {
! 788: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 789:
! 790: /* This queue will be skipped in further operations */
! 791: hal->ah_txq[queue].tqi_type = HAL_TX_QUEUE_INACTIVE;
! 792:
! 793: return (AH_FALSE);
! 794: }
! 795:
! 796: void
! 797: ar5k_ar5210_init_tx_queue(struct ath_hal *hal, u_int aifs, HAL_BOOL turbo)
! 798: {
! 799: int i;
! 800: struct {
! 801: u_int16_t mode_register;
! 802: u_int32_t mode_base, mode_turbo;
! 803: } initial[] = AR5K_AR5210_INI_MODE(aifs);
! 804:
! 805: /*
! 806: * Write initial mode register settings
! 807: */
! 808: for (i = 0; i < AR5K_ELEMENTS(initial); i++)
! 809: AR5K_REG_WRITE((u_int32_t)initial[i].mode_register,
! 810: turbo == AH_TRUE ?
! 811: initial[i].mode_turbo : initial[i].mode_base);
! 812: }
! 813:
! 814: HAL_BOOL
! 815: ar5k_ar5210_reset_tx_queue(struct ath_hal *hal, u_int queue)
! 816: {
! 817: u_int32_t cw_min, retry_lg, retry_sh;
! 818: HAL_TXQ_INFO *tq;
! 819:
! 820: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 821:
! 822: tq = &hal->ah_txq[queue];
! 823:
! 824: /* Only handle data queues, others will be ignored */
! 825: if (tq->tqi_type != HAL_TX_QUEUE_DATA)
! 826: return (AH_TRUE);
! 827:
! 828: /* Set turbo/base mode parameters */
! 829: ar5k_ar5210_init_tx_queue(hal, hal->ah_aifs + tq->tqi_aifs,
! 830: hal->ah_turbo == AH_TRUE ? AH_TRUE : AH_FALSE);
! 831:
! 832: /*
! 833: * Set retry limits
! 834: */
! 835: if (hal->ah_software_retry == AH_TRUE) {
! 836: /* XXX Need to test this */
! 837: retry_lg = hal->ah_limit_tx_retries;
! 838: retry_sh = retry_lg =
! 839: retry_lg > AR5K_AR5210_RETRY_LMT_SH_RETRY ?
! 840: AR5K_AR5210_RETRY_LMT_SH_RETRY : retry_lg;
! 841: } else {
! 842: retry_lg = AR5K_INIT_LG_RETRY;
! 843: retry_sh = AR5K_INIT_SH_RETRY;
! 844: }
! 845:
! 846: /*
! 847: * Set initial content window (cw_min/cw_max)
! 848: */
! 849: cw_min = 1;
! 850: while (cw_min < hal->ah_cw_min)
! 851: cw_min = (cw_min << 1) | 1;
! 852:
! 853: cw_min = tq->tqi_cw_min < 0 ?
! 854: (cw_min >> (-tq->tqi_cw_min)) :
! 855: ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
! 856:
! 857: /* Commit values */
! 858: AR5K_REG_WRITE(AR5K_AR5210_RETRY_LMT,
! 859: (cw_min << AR5K_AR5210_RETRY_LMT_CW_MIN_S)
! 860: | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, AR5K_AR5210_RETRY_LMT_SLG_RETRY)
! 861: | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, AR5K_AR5210_RETRY_LMT_SSH_RETRY)
! 862: | AR5K_REG_SM(retry_lg, AR5K_AR5210_RETRY_LMT_LG_RETRY)
! 863: | AR5K_REG_SM(retry_sh, AR5K_AR5210_RETRY_LMT_SH_RETRY));
! 864:
! 865: return (AH_TRUE);
! 866: }
! 867:
! 868: u_int32_t
! 869: ar5k_ar5210_get_tx_buf(struct ath_hal *hal, u_int queue)
! 870: {
! 871: u_int16_t tx_reg;
! 872:
! 873: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 874:
! 875: /*
! 876: * Get the transmit queue descriptor pointer register by type
! 877: */
! 878: switch (hal->ah_txq[queue].tqi_type) {
! 879: case HAL_TX_QUEUE_DATA:
! 880: tx_reg = AR5K_AR5210_TXDP0;
! 881: break;
! 882: case HAL_TX_QUEUE_BEACON:
! 883: case HAL_TX_QUEUE_CAB:
! 884: tx_reg = AR5K_AR5210_TXDP1;
! 885: break;
! 886: default:
! 887: return (0xffffffff);
! 888: }
! 889:
! 890: return (AR5K_REG_READ(tx_reg));
! 891: }
! 892:
! 893: HAL_BOOL
! 894: ar5k_ar5210_put_tx_buf(struct ath_hal *hal, u_int queue, u_int32_t phys_addr)
! 895: {
! 896: u_int16_t tx_reg;
! 897:
! 898: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 899:
! 900: /*
! 901: * Get the transmit queue descriptor pointer register by type
! 902: */
! 903: switch (hal->ah_txq[queue].tqi_type) {
! 904: case HAL_TX_QUEUE_DATA:
! 905: tx_reg = AR5K_AR5210_TXDP0;
! 906: break;
! 907: case HAL_TX_QUEUE_BEACON:
! 908: case HAL_TX_QUEUE_CAB:
! 909: tx_reg = AR5K_AR5210_TXDP1;
! 910: break;
! 911: default:
! 912: return (AH_FALSE);
! 913: }
! 914:
! 915: /* Set descriptor pointer */
! 916: AR5K_REG_WRITE(tx_reg, phys_addr);
! 917:
! 918: return (AH_TRUE);
! 919: }
! 920:
! 921: u_int32_t
! 922: ar5k_ar5210_num_tx_pending(struct ath_hal *hal, u_int queue)
! 923: {
! 924: return (AH_FALSE);
! 925: }
! 926:
! 927: HAL_BOOL
! 928: ar5k_ar5210_tx_start(struct ath_hal *hal, u_int queue)
! 929: {
! 930: u_int32_t tx_queue;
! 931:
! 932: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 933:
! 934: tx_queue = AR5K_REG_READ(AR5K_AR5210_CR);
! 935:
! 936: /*
! 937: * Set the queue type
! 938: */
! 939: switch (hal->ah_txq[queue].tqi_type) {
! 940: case HAL_TX_QUEUE_DATA:
! 941: tx_queue |= AR5K_AR5210_CR_TXE0 & ~AR5K_AR5210_CR_TXD0;
! 942: break;
! 943:
! 944: case HAL_TX_QUEUE_BEACON:
! 945: tx_queue |= AR5K_AR5210_CR_TXE1 & ~AR5K_AR5210_CR_TXD1;
! 946: AR5K_REG_WRITE(AR5K_AR5210_BSR,
! 947: AR5K_AR5210_BCR_TQ1V | AR5K_AR5210_BCR_BDMAE);
! 948: break;
! 949:
! 950: case HAL_TX_QUEUE_CAB:
! 951: tx_queue |= AR5K_AR5210_CR_TXE1 & ~AR5K_AR5210_CR_TXD1;
! 952: AR5K_REG_WRITE(AR5K_AR5210_BSR,
! 953: AR5K_AR5210_BCR_TQ1FV | AR5K_AR5210_BCR_TQ1V |
! 954: AR5K_AR5210_BCR_BDMAE);
! 955: break;
! 956:
! 957: default:
! 958: return (AH_FALSE);
! 959: }
! 960:
! 961: /* Start queue */
! 962: AR5K_REG_WRITE(AR5K_AR5210_CR, tx_queue);
! 963:
! 964: return (AH_TRUE);
! 965: }
! 966:
! 967: HAL_BOOL
! 968: ar5k_ar5210_stop_tx_dma(struct ath_hal *hal, u_int queue)
! 969: {
! 970: u_int32_t tx_queue;
! 971:
! 972: AR5K_ASSERT_ENTRY(queue, hal->ah_capabilities.cap_queues.q_tx_num);
! 973:
! 974: tx_queue = AR5K_REG_READ(AR5K_AR5210_CR);
! 975:
! 976: /*
! 977: * Set by queue type
! 978: */
! 979: switch (hal->ah_txq[queue].tqi_type) {
! 980: case HAL_TX_QUEUE_DATA:
! 981: tx_queue |= AR5K_AR5210_CR_TXD0 & ~AR5K_AR5210_CR_TXE0;
! 982: break;
! 983:
! 984: case HAL_TX_QUEUE_BEACON:
! 985: case HAL_TX_QUEUE_CAB:
! 986: /* XXX Fix me... */
! 987: tx_queue |= AR5K_AR5210_CR_TXD1 & ~AR5K_AR5210_CR_TXD1;
! 988: AR5K_REG_WRITE(AR5K_AR5210_BSR, 0);
! 989: break;
! 990:
! 991: default:
! 992: return (AH_FALSE);
! 993: }
! 994:
! 995: /* Stop queue */
! 996: AR5K_REG_WRITE(AR5K_AR5210_CR, tx_queue);
! 997:
! 998: return (AH_TRUE);
! 999: }
! 1000:
! 1001: HAL_BOOL
! 1002: ar5k_ar5210_setup_tx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1003: u_int packet_length, u_int header_length, HAL_PKT_TYPE type, u_int tx_power,
! 1004: u_int tx_rate0, u_int tx_tries0, u_int key_index, u_int antenna_mode,
! 1005: u_int flags, u_int rtscts_rate, u_int rtscts_duration)
! 1006: {
! 1007: u_int32_t frame_type;
! 1008: struct ar5k_ar5210_tx_desc *tx_desc;
! 1009:
! 1010: tx_desc = (struct ar5k_ar5210_tx_desc*)&desc->ds_ctl0;
! 1011:
! 1012: /*
! 1013: * Validate input
! 1014: */
! 1015: if (tx_tries0 == 0)
! 1016: return (AH_FALSE);
! 1017:
! 1018: if ((tx_desc->tx_control_0 = (packet_length &
! 1019: AR5K_AR5210_DESC_TX_CTL0_FRAME_LEN)) != packet_length)
! 1020: return (AH_FALSE);
! 1021:
! 1022: if ((tx_desc->tx_control_0 = (header_length &
! 1023: AR5K_AR5210_DESC_TX_CTL0_HEADER_LEN)) != header_length)
! 1024: return (AH_FALSE);
! 1025:
! 1026: if (type == HAL_PKT_TYPE_BEACON || type == HAL_PKT_TYPE_PROBE_RESP)
! 1027: frame_type = AR5K_AR5210_DESC_TX_FRAME_TYPE_NO_DELAY;
! 1028: else if (type == HAL_PKT_TYPE_PIFS)
! 1029: frame_type = AR5K_AR5210_DESC_TX_FRAME_TYPE_PIFS;
! 1030: else
! 1031: frame_type = type;
! 1032:
! 1033: tx_desc->tx_control_0 =
! 1034: AR5K_REG_SM(frame_type, AR5K_AR5210_DESC_TX_CTL0_FRAME_TYPE);
! 1035: tx_desc->tx_control_0 |=
! 1036: AR5K_REG_SM(tx_rate0, AR5K_AR5210_DESC_TX_CTL0_XMIT_RATE);
! 1037:
! 1038: #define _TX_FLAGS(_c, _flag) \
! 1039: if (flags & HAL_TXDESC_##_flag) \
! 1040: tx_desc->tx_control_##_c |= \
! 1041: AR5K_AR5210_DESC_TX_CTL##_c##_##_flag
! 1042:
! 1043: _TX_FLAGS(0, CLRDMASK);
! 1044: _TX_FLAGS(0, INTREQ);
! 1045: _TX_FLAGS(0, RTSENA);
! 1046:
! 1047: #undef _TX_FLAGS
! 1048:
! 1049: /*
! 1050: * WEP crap
! 1051: */
! 1052: if (key_index != HAL_TXKEYIX_INVALID) {
! 1053: tx_desc->tx_control_0 |=
! 1054: AR5K_AR5210_DESC_TX_CTL0_ENCRYPT_KEY_VALID;
! 1055: tx_desc->tx_control_1 |=
! 1056: AR5K_REG_SM(key_index,
! 1057: AR5K_AR5210_DESC_TX_CTL1_ENCRYPT_KEY_INDEX);
! 1058: }
! 1059:
! 1060: /*
! 1061: * RTS/CTS
! 1062: */
! 1063: if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
! 1064: tx_desc->tx_control_1 |=
! 1065: rtscts_duration & AR5K_AR5210_DESC_TX_CTL1_RTS_DURATION;
! 1066: }
! 1067:
! 1068: return (AH_TRUE);
! 1069: }
! 1070:
! 1071: HAL_BOOL
! 1072: ar5k_ar5210_fill_tx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1073: u_int segment_length, HAL_BOOL first_segment, HAL_BOOL last_segment)
! 1074: {
! 1075: struct ar5k_ar5210_tx_desc *tx_desc;
! 1076:
! 1077: tx_desc = (struct ar5k_ar5210_tx_desc*)&desc->ds_ctl0;
! 1078:
! 1079: /* Clear status descriptor */
! 1080: bzero(desc->ds_hw, sizeof(desc->ds_hw));
! 1081:
! 1082: /* Validate segment length and initialize the descriptor */
! 1083: if ((tx_desc->tx_control_1 = (segment_length &
! 1084: AR5K_AR5210_DESC_TX_CTL1_BUF_LEN)) != segment_length)
! 1085: return (AH_FALSE);
! 1086:
! 1087: if (first_segment != AH_TRUE)
! 1088: tx_desc->tx_control_0 &= ~AR5K_AR5210_DESC_TX_CTL0_FRAME_LEN;
! 1089:
! 1090: if (last_segment != AH_TRUE)
! 1091: tx_desc->tx_control_1 |= AR5K_AR5210_DESC_TX_CTL1_MORE;
! 1092:
! 1093: return (AH_TRUE);
! 1094: }
! 1095:
! 1096: HAL_BOOL
! 1097: ar5k_ar5210_setup_xtx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1098: u_int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
! 1099: u_int tx_rate3, u_int tx_tries3)
! 1100: {
! 1101: /*
! 1102: * Does this function is for setting up XR? Not sure...
! 1103: * Nevertheless, I didn't find any information about XR support
! 1104: * by the AR5210. This seems to be a slightly new feature.
! 1105: */
! 1106: return (AH_FALSE);
! 1107: }
! 1108:
! 1109: HAL_STATUS
! 1110: ar5k_ar5210_proc_tx_desc(struct ath_hal *hal, struct ath_desc *desc)
! 1111: {
! 1112: struct ar5k_ar5210_tx_status *tx_status;
! 1113: struct ar5k_ar5210_tx_desc *tx_desc;
! 1114:
! 1115: tx_desc = (struct ar5k_ar5210_tx_desc*)&desc->ds_ctl0;
! 1116: tx_status = (struct ar5k_ar5210_tx_status*)&desc->ds_hw[0];
! 1117:
! 1118: /* No frame has been send or error */
! 1119: if ((tx_status->tx_status_1 & AR5K_AR5210_DESC_TX_STATUS1_DONE) == 0)
! 1120: return (HAL_EINPROGRESS);
! 1121:
! 1122: /*
! 1123: * Get descriptor status
! 1124: */
! 1125: desc->ds_us.tx.ts_tstamp =
! 1126: AR5K_REG_MS(tx_status->tx_status_0,
! 1127: AR5K_AR5210_DESC_TX_STATUS0_SEND_TIMESTAMP);
! 1128: desc->ds_us.tx.ts_shortretry =
! 1129: AR5K_REG_MS(tx_status->tx_status_0,
! 1130: AR5K_AR5210_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
! 1131: desc->ds_us.tx.ts_longretry =
! 1132: AR5K_REG_MS(tx_status->tx_status_0,
! 1133: AR5K_AR5210_DESC_TX_STATUS0_LONG_RETRY_COUNT);
! 1134: desc->ds_us.tx.ts_seqnum =
! 1135: AR5K_REG_MS(tx_status->tx_status_1,
! 1136: AR5K_AR5210_DESC_TX_STATUS1_SEQ_NUM);
! 1137: desc->ds_us.tx.ts_rssi =
! 1138: AR5K_REG_MS(tx_status->tx_status_1,
! 1139: AR5K_AR5210_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
! 1140: desc->ds_us.tx.ts_antenna = 1;
! 1141: desc->ds_us.tx.ts_status = 0;
! 1142: desc->ds_us.tx.ts_rate =
! 1143: AR5K_REG_MS(tx_desc->tx_control_0,
! 1144: AR5K_AR5210_DESC_TX_CTL0_XMIT_RATE);
! 1145:
! 1146: if ((tx_status->tx_status_0 &
! 1147: AR5K_AR5210_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0) {
! 1148: if (tx_status->tx_status_0 &
! 1149: AR5K_AR5210_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
! 1150: desc->ds_us.tx.ts_status |= HAL_TXERR_XRETRY;
! 1151:
! 1152: if (tx_status->tx_status_0 &
! 1153: AR5K_AR5210_DESC_TX_STATUS0_FIFO_UNDERRUN)
! 1154: desc->ds_us.tx.ts_status |= HAL_TXERR_FIFO;
! 1155:
! 1156: if (tx_status->tx_status_0 &
! 1157: AR5K_AR5210_DESC_TX_STATUS0_FILTERED)
! 1158: desc->ds_us.tx.ts_status |= HAL_TXERR_FILT;
! 1159: }
! 1160:
! 1161: return (HAL_OK);
! 1162: }
! 1163:
! 1164: HAL_BOOL
! 1165: ar5k_ar5210_has_veol(struct ath_hal *hal)
! 1166: {
! 1167: return (AH_FALSE);
! 1168: }
! 1169:
! 1170: /*
! 1171: * Receive functions
! 1172: */
! 1173:
! 1174: u_int32_t
! 1175: ar5k_ar5210_get_rx_buf(struct ath_hal *hal)
! 1176: {
! 1177: return (AR5K_REG_READ(AR5K_AR5210_RXDP));
! 1178: }
! 1179:
! 1180: void
! 1181: ar5k_ar5210_put_rx_buf(struct ath_hal *hal, u_int32_t phys_addr)
! 1182: {
! 1183: AR5K_REG_WRITE(AR5K_AR5210_RXDP, phys_addr);
! 1184: }
! 1185:
! 1186: void
! 1187: ar5k_ar5210_start_rx(struct ath_hal *hal)
! 1188: {
! 1189: AR5K_REG_WRITE(AR5K_AR5210_CR, AR5K_AR5210_CR_RXE);
! 1190: }
! 1191:
! 1192: HAL_BOOL
! 1193: ar5k_ar5210_stop_rx_dma(struct ath_hal *hal)
! 1194: {
! 1195: int i;
! 1196:
! 1197: AR5K_REG_WRITE(AR5K_AR5210_CR, AR5K_AR5210_CR_RXD);
! 1198:
! 1199: /*
! 1200: * It may take some time to disable the DMA receive unit
! 1201: */
! 1202: for (i = 2000;
! 1203: i > 0 && (AR5K_REG_READ(AR5K_AR5210_CR) & AR5K_AR5210_CR_RXE) != 0;
! 1204: i--)
! 1205: AR5K_DELAY(10);
! 1206:
! 1207: return (i > 0 ? AH_TRUE : AH_FALSE);
! 1208: }
! 1209:
! 1210: void
! 1211: ar5k_ar5210_start_rx_pcu(struct ath_hal *hal)
! 1212: {
! 1213: AR5K_REG_DISABLE_BITS(AR5K_AR5210_DIAG_SW, AR5K_AR5210_DIAG_SW_DIS_RX);
! 1214: }
! 1215:
! 1216: void
! 1217: ar5k_ar5210_stop_pcu_recv(struct ath_hal *hal)
! 1218: {
! 1219: AR5K_REG_ENABLE_BITS(AR5K_AR5210_DIAG_SW, AR5K_AR5210_DIAG_SW_DIS_RX);
! 1220: }
! 1221:
! 1222: void
! 1223: ar5k_ar5210_set_mcast_filter(struct ath_hal *hal, u_int32_t filter0,
! 1224: u_int32_t filter1)
! 1225: {
! 1226: /* Set the multicat filter */
! 1227: AR5K_REG_WRITE(AR5K_AR5210_MCAST_FIL0, filter0);
! 1228: AR5K_REG_WRITE(AR5K_AR5210_MCAST_FIL1, filter1);
! 1229: }
! 1230:
! 1231: HAL_BOOL
! 1232: ar5k_ar5210_set_mcast_filterindex(struct ath_hal *hal, u_int32_t index)
! 1233: {
! 1234: if (index >= 64) {
! 1235: return (AH_FALSE);
! 1236: } else if (index >= 32) {
! 1237: AR5K_REG_ENABLE_BITS(AR5K_AR5210_MCAST_FIL1,
! 1238: (1 << (index - 32)));
! 1239: } else {
! 1240: AR5K_REG_ENABLE_BITS(AR5K_AR5210_MCAST_FIL0,
! 1241: (1 << index));
! 1242: }
! 1243:
! 1244: return (AH_TRUE);
! 1245: }
! 1246:
! 1247: HAL_BOOL
! 1248: ar5k_ar5210_clear_mcast_filter_idx(struct ath_hal *hal, u_int32_t index)
! 1249: {
! 1250: if (index >= 64) {
! 1251: return (AH_FALSE);
! 1252: } else if (index >= 32) {
! 1253: AR5K_REG_DISABLE_BITS(AR5K_AR5210_MCAST_FIL1,
! 1254: (1 << (index - 32)));
! 1255: } else {
! 1256: AR5K_REG_DISABLE_BITS(AR5K_AR5210_MCAST_FIL0,
! 1257: (1 << index));
! 1258: }
! 1259:
! 1260: return (AH_TRUE);
! 1261: }
! 1262:
! 1263: u_int32_t
! 1264: ar5k_ar5210_get_rx_filter(struct ath_hal *hal)
! 1265: {
! 1266: return (AR5K_REG_READ(AR5K_AR5210_RX_FILTER));
! 1267: }
! 1268:
! 1269: void
! 1270: ar5k_ar5210_set_rx_filter(struct ath_hal *hal, u_int32_t filter)
! 1271: {
! 1272: /*
! 1273: * The AR5210 uses promiscous mode to detect radar activity
! 1274: */
! 1275: if (filter & HAL_RX_FILTER_PHYRADAR) {
! 1276: filter &= ~HAL_RX_FILTER_PHYRADAR;
! 1277: filter |= AR5K_AR5210_RX_FILTER_PROMISC;
! 1278: }
! 1279:
! 1280: AR5K_REG_WRITE(AR5K_AR5210_RX_FILTER, filter);
! 1281: }
! 1282:
! 1283: HAL_BOOL
! 1284: ar5k_ar5210_setup_rx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1285: u_int32_t size, u_int flags)
! 1286: {
! 1287: struct ar5k_ar5210_rx_desc *rx_desc;
! 1288:
! 1289: rx_desc = (struct ar5k_ar5210_rx_desc*)&desc->ds_ctl0;
! 1290:
! 1291: if ((rx_desc->rx_control_1 = (size &
! 1292: AR5K_AR5210_DESC_RX_CTL1_BUF_LEN)) != size)
! 1293: return (AH_FALSE);
! 1294:
! 1295: if (flags & HAL_RXDESC_INTREQ)
! 1296: rx_desc->rx_control_1 |= AR5K_AR5210_DESC_RX_CTL1_INTREQ;
! 1297:
! 1298: return (AH_TRUE);
! 1299: }
! 1300:
! 1301: HAL_STATUS
! 1302: ar5k_ar5210_proc_rx_desc(struct ath_hal *hal, struct ath_desc *desc,
! 1303: u_int32_t phys_addr, struct ath_desc *next)
! 1304: {
! 1305: struct ar5k_ar5210_rx_status *rx_status;
! 1306:
! 1307: rx_status = (struct ar5k_ar5210_rx_status*)&desc->ds_hw[0];
! 1308:
! 1309: /* No frame received / not ready */
! 1310: if ((rx_status->rx_status_1 & AR5K_AR5210_DESC_RX_STATUS1_DONE) == 0)
! 1311: return (HAL_EINPROGRESS);
! 1312:
! 1313: /*
! 1314: * Frame receive status
! 1315: */
! 1316: desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
! 1317: AR5K_AR5210_DESC_RX_STATUS0_DATA_LEN;
! 1318: desc->ds_us.rx.rs_rssi =
! 1319: AR5K_REG_MS(rx_status->rx_status_0,
! 1320: AR5K_AR5210_DESC_RX_STATUS0_RECEIVE_SIGNAL);
! 1321: desc->ds_us.rx.rs_rate =
! 1322: AR5K_REG_MS(rx_status->rx_status_0,
! 1323: AR5K_AR5210_DESC_RX_STATUS0_RECEIVE_RATE);
! 1324: desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
! 1325: AR5K_AR5210_DESC_RX_STATUS0_RECEIVE_ANTENNA;
! 1326: desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
! 1327: AR5K_AR5210_DESC_RX_STATUS0_MORE;
! 1328: desc->ds_us.rx.rs_tstamp =
! 1329: AR5K_REG_MS(rx_status->rx_status_1,
! 1330: AR5K_AR5210_DESC_RX_STATUS1_RECEIVE_TIMESTAMP);
! 1331: desc->ds_us.rx.rs_status = 0;
! 1332:
! 1333: /*
! 1334: * Key table status
! 1335: */
! 1336: if (rx_status->rx_status_1 &
! 1337: AR5K_AR5210_DESC_RX_STATUS1_KEY_INDEX_VALID) {
! 1338: desc->ds_us.rx.rs_keyix =
! 1339: AR5K_REG_MS(rx_status->rx_status_1,
! 1340: AR5K_AR5210_DESC_RX_STATUS1_KEY_INDEX);
! 1341: } else {
! 1342: desc->ds_us.rx.rs_keyix = HAL_RXKEYIX_INVALID;
! 1343: }
! 1344:
! 1345: /*
! 1346: * Receive/descriptor errors
! 1347: */
! 1348: if ((rx_status->rx_status_1 &
! 1349: AR5K_AR5210_DESC_RX_STATUS1_FRAME_RECEIVE_OK) == 0) {
! 1350: if (rx_status->rx_status_1 &
! 1351: AR5K_AR5210_DESC_RX_STATUS1_CRC_ERROR)
! 1352: desc->ds_us.rx.rs_status |= HAL_RXERR_CRC;
! 1353:
! 1354: if (rx_status->rx_status_1 &
! 1355: AR5K_AR5210_DESC_RX_STATUS1_FIFO_OVERRUN)
! 1356: desc->ds_us.rx.rs_status |= HAL_RXERR_FIFO;
! 1357:
! 1358: if (rx_status->rx_status_1 &
! 1359: AR5K_AR5210_DESC_RX_STATUS1_PHY_ERROR) {
! 1360: desc->ds_us.rx.rs_status |= HAL_RXERR_PHY;
! 1361: desc->ds_us.rx.rs_phyerr =
! 1362: AR5K_REG_MS(rx_status->rx_status_1,
! 1363: AR5K_AR5210_DESC_RX_STATUS1_PHY_ERROR);
! 1364: }
! 1365:
! 1366: if (rx_status->rx_status_1 &
! 1367: AR5K_AR5210_DESC_RX_STATUS1_DECRYPT_CRC_ERROR)
! 1368: desc->ds_us.rx.rs_status |= HAL_RXERR_DECRYPT;
! 1369: }
! 1370:
! 1371: return (HAL_OK);
! 1372: }
! 1373:
! 1374: void
! 1375: ar5k_ar5210_set_rx_signal(struct ath_hal *hal)
! 1376: {
! 1377: /* Signal state monitoring is not yet supported */
! 1378: }
! 1379:
! 1380: /*
! 1381: * Misc functions
! 1382: */
! 1383:
! 1384: void
! 1385: ar5k_ar5210_dump_state(struct ath_hal *hal)
! 1386: {
! 1387: #ifdef AR5K_DEBUG
! 1388: #define AR5K_PRINT_REGISTER(_x) \
! 1389: printf("(%s: %08x) ", #_x, AR5K_REG_READ(AR5K_AR5210_##_x));
! 1390:
! 1391: printf("DMA registers:\n");
! 1392: AR5K_PRINT_REGISTER(TXDP0);
! 1393: AR5K_PRINT_REGISTER(TXDP1);
! 1394: AR5K_PRINT_REGISTER(CR);
! 1395: AR5K_PRINT_REGISTER(RXDP);
! 1396: AR5K_PRINT_REGISTER(CFG);
! 1397: AR5K_PRINT_REGISTER(ISR);
! 1398: AR5K_PRINT_REGISTER(IMR);
! 1399: AR5K_PRINT_REGISTER(IER);
! 1400: AR5K_PRINT_REGISTER(BCR);
! 1401: AR5K_PRINT_REGISTER(BSR);
! 1402: AR5K_PRINT_REGISTER(TXCFG);
! 1403: AR5K_PRINT_REGISTER(RXCFG);
! 1404: AR5K_PRINT_REGISTER(MIBC);
! 1405: AR5K_PRINT_REGISTER(TOPS);
! 1406: AR5K_PRINT_REGISTER(RXNOFRM);
! 1407: AR5K_PRINT_REGISTER(TXNOFRM);
! 1408: AR5K_PRINT_REGISTER(RPGTO);
! 1409: AR5K_PRINT_REGISTER(RFCNT);
! 1410: AR5K_PRINT_REGISTER(MISC);
! 1411: AR5K_PRINT_REGISTER(RC);
! 1412: AR5K_PRINT_REGISTER(SCR);
! 1413: AR5K_PRINT_REGISTER(INTPEND);
! 1414: AR5K_PRINT_REGISTER(SFR);
! 1415: AR5K_PRINT_REGISTER(PCICFG);
! 1416: AR5K_PRINT_REGISTER(GPIOCR);
! 1417: AR5K_PRINT_REGISTER(GPIODO);
! 1418: AR5K_PRINT_REGISTER(GPIODI);
! 1419: AR5K_PRINT_REGISTER(SREV);
! 1420: printf("\n");
! 1421:
! 1422: printf("PCU registers:\n");
! 1423: AR5K_PRINT_REGISTER(STA_ID0);
! 1424: AR5K_PRINT_REGISTER(STA_ID1);
! 1425: AR5K_PRINT_REGISTER(BSS_ID0);
! 1426: AR5K_PRINT_REGISTER(BSS_ID1);
! 1427: AR5K_PRINT_REGISTER(SLOT_TIME);
! 1428: AR5K_PRINT_REGISTER(TIME_OUT);
! 1429: AR5K_PRINT_REGISTER(RSSI_THR);
! 1430: AR5K_PRINT_REGISTER(RETRY_LMT);
! 1431: AR5K_PRINT_REGISTER(USEC);
! 1432: AR5K_PRINT_REGISTER(BEACON);
! 1433: AR5K_PRINT_REGISTER(CFP_PERIOD);
! 1434: AR5K_PRINT_REGISTER(TIMER0);
! 1435: AR5K_PRINT_REGISTER(TIMER1);
! 1436: AR5K_PRINT_REGISTER(TIMER2);
! 1437: AR5K_PRINT_REGISTER(TIMER3);
! 1438: AR5K_PRINT_REGISTER(IFS0);
! 1439: AR5K_PRINT_REGISTER(IFS1);
! 1440: AR5K_PRINT_REGISTER(CFP_DUR);
! 1441: AR5K_PRINT_REGISTER(RX_FILTER);
! 1442: AR5K_PRINT_REGISTER(MCAST_FIL0);
! 1443: AR5K_PRINT_REGISTER(MCAST_FIL1);
! 1444: AR5K_PRINT_REGISTER(TX_MASK0);
! 1445: AR5K_PRINT_REGISTER(TX_MASK1);
! 1446: AR5K_PRINT_REGISTER(CLR_TMASK);
! 1447: AR5K_PRINT_REGISTER(TRIG_LVL);
! 1448: AR5K_PRINT_REGISTER(DIAG_SW);
! 1449: AR5K_PRINT_REGISTER(TSF_L32);
! 1450: AR5K_PRINT_REGISTER(TSF_U32);
! 1451: AR5K_PRINT_REGISTER(LAST_TSTP);
! 1452: AR5K_PRINT_REGISTER(RETRY_CNT);
! 1453: AR5K_PRINT_REGISTER(BACKOFF);
! 1454: AR5K_PRINT_REGISTER(NAV);
! 1455: AR5K_PRINT_REGISTER(RTS_OK);
! 1456: AR5K_PRINT_REGISTER(RTS_FAIL);
! 1457: AR5K_PRINT_REGISTER(ACK_FAIL);
! 1458: AR5K_PRINT_REGISTER(FCS_FAIL);
! 1459: AR5K_PRINT_REGISTER(BEACON_CNT);
! 1460: AR5K_PRINT_REGISTER(KEYTABLE_0);
! 1461: printf("\n");
! 1462:
! 1463: printf("PHY registers:\n");
! 1464: AR5K_PRINT_REGISTER(PHY(0));
! 1465: AR5K_PRINT_REGISTER(PHY_FC);
! 1466: AR5K_PRINT_REGISTER(PHY_AGC);
! 1467: AR5K_PRINT_REGISTER(PHY_CHIP_ID);
! 1468: AR5K_PRINT_REGISTER(PHY_ACTIVE);
! 1469: AR5K_PRINT_REGISTER(PHY_AGCCTL);
! 1470: printf("\n");
! 1471: #endif
! 1472: }
! 1473:
! 1474: HAL_BOOL
! 1475: ar5k_ar5210_get_diag_state(struct ath_hal *hal, int id, void **device,
! 1476: u_int *size)
! 1477: {
! 1478: /*
! 1479: * We'll ignore this right now. This seems to be some kind of an obscure
! 1480: * debugging interface for the binary-only HAL.
! 1481: */
! 1482: return (AH_FALSE);
! 1483: }
! 1484:
! 1485: void
! 1486: ar5k_ar5210_get_lladdr(struct ath_hal *hal, u_int8_t *mac)
! 1487: {
! 1488: bcopy(hal->ah_sta_id, mac, IEEE80211_ADDR_LEN);
! 1489: }
! 1490:
! 1491: HAL_BOOL
! 1492: ar5k_ar5210_set_lladdr(struct ath_hal *hal, const u_int8_t *mac)
! 1493: {
! 1494: u_int32_t low_id, high_id;
! 1495:
! 1496: /* Set new station ID */
! 1497: bcopy(mac, hal->ah_sta_id, IEEE80211_ADDR_LEN);
! 1498:
! 1499: low_id = AR5K_LOW_ID(mac);
! 1500: high_id = 0x0000ffff & AR5K_HIGH_ID(mac);
! 1501:
! 1502: AR5K_REG_WRITE(AR5K_AR5210_STA_ID0, low_id);
! 1503: AR5K_REG_WRITE(AR5K_AR5210_STA_ID1, high_id);
! 1504:
! 1505: return (AH_TRUE);
! 1506: }
! 1507:
! 1508: HAL_BOOL
! 1509: ar5k_ar5210_set_regdomain(struct ath_hal *hal, u_int16_t regdomain,
! 1510: HAL_STATUS *status)
! 1511: {
! 1512: ieee80211_regdomain_t ieee_regdomain;
! 1513:
! 1514: ieee_regdomain = ar5k_regdomain_to_ieee(regdomain);
! 1515:
! 1516: if (ar5k_eeprom_regulation_domain(hal, AH_TRUE,
! 1517: &ieee_regdomain) == AH_TRUE) {
! 1518: *status = HAL_OK;
! 1519: return (AH_TRUE);
! 1520: }
! 1521:
! 1522: *status = EIO;
! 1523:
! 1524: return (AH_FALSE);
! 1525: }
! 1526:
! 1527: void
! 1528: ar5k_ar5210_set_ledstate(struct ath_hal *hal, HAL_LED_STATE state)
! 1529: {
! 1530: u_int32_t led;
! 1531:
! 1532: led = AR5K_REG_READ(AR5K_AR5210_PCICFG);
! 1533:
! 1534: /*
! 1535: * Some blinking values, define at your wish
! 1536: */
! 1537: switch (state) {
! 1538: case IEEE80211_S_SCAN:
! 1539: case IEEE80211_S_INIT:
! 1540: led |=
! 1541: AR5K_AR5210_PCICFG_LED_PEND |
! 1542: AR5K_AR5210_PCICFG_LED_BCTL;
! 1543: break;
! 1544: case IEEE80211_S_RUN:
! 1545: led |=
! 1546: AR5K_AR5210_PCICFG_LED_ACT;
! 1547: break;
! 1548: default:
! 1549: led |=
! 1550: AR5K_AR5210_PCICFG_LED_ACT |
! 1551: AR5K_AR5210_PCICFG_LED_BCTL;
! 1552: break;
! 1553: }
! 1554:
! 1555: AR5K_REG_WRITE(AR5K_AR5210_PCICFG, led);
! 1556: }
! 1557:
! 1558: void
! 1559: ar5k_ar5210_set_associd(struct ath_hal *hal, const u_int8_t *bssid,
! 1560: u_int16_t assoc_id, u_int16_t tim_offset)
! 1561: {
! 1562: u_int32_t low_id, high_id;
! 1563:
! 1564: /*
! 1565: * Set BSSID which triggers the "SME Join" operation
! 1566: */
! 1567: low_id = AR5K_LOW_ID(bssid);
! 1568: high_id = AR5K_HIGH_ID(bssid);
! 1569: AR5K_REG_WRITE(AR5K_AR5210_BSS_ID0, low_id);
! 1570: AR5K_REG_WRITE(AR5K_AR5210_BSS_ID1, high_id |
! 1571: ((assoc_id & 0x3fff) << AR5K_AR5210_BSS_ID1_AID_S));
! 1572: bcopy(bssid, &hal->ah_bssid, IEEE80211_ADDR_LEN);
! 1573:
! 1574: if (assoc_id == 0) {
! 1575: ar5k_ar5210_disable_pspoll(hal);
! 1576: return;
! 1577: }
! 1578:
! 1579: AR5K_REG_WRITE_BITS(AR5K_AR5210_BEACON, AR5K_AR5210_BEACON_TIM,
! 1580: tim_offset ? tim_offset + 4 : 0);
! 1581:
! 1582: ar5k_ar5210_enable_pspoll(hal, NULL, 0);
! 1583: }
! 1584:
! 1585: HAL_BOOL
! 1586: ar5k_ar5210_set_bssid_mask(struct ath_hal *hal, const u_int8_t* mask)
! 1587: {
! 1588: /* Not supported in 5210 */
! 1589: return (AH_FALSE);
! 1590: }
! 1591:
! 1592: HAL_BOOL
! 1593: ar5k_ar5210_set_gpio_output(struct ath_hal *hal, u_int32_t gpio)
! 1594: {
! 1595: if (gpio > AR5K_AR5210_NUM_GPIO)
! 1596: return (AH_FALSE);
! 1597:
! 1598: AR5K_REG_WRITE(AR5K_AR5210_GPIOCR,
! 1599: (AR5K_REG_READ(AR5K_AR5210_GPIOCR) &~ AR5K_AR5210_GPIOCR_ALL(gpio))
! 1600: | AR5K_AR5210_GPIOCR_OUT1(gpio));
! 1601:
! 1602: return (AH_TRUE);
! 1603: }
! 1604:
! 1605: HAL_BOOL
! 1606: ar5k_ar5210_set_gpio_input(struct ath_hal *hal, u_int32_t gpio)
! 1607: {
! 1608: if (gpio > AR5K_AR5210_NUM_GPIO)
! 1609: return (AH_FALSE);
! 1610:
! 1611: AR5K_REG_WRITE(AR5K_AR5210_GPIOCR,
! 1612: (AR5K_REG_READ(AR5K_AR5210_GPIOCR) &~ AR5K_AR5210_GPIOCR_ALL(gpio))
! 1613: | AR5K_AR5210_GPIOCR_IN(gpio));
! 1614:
! 1615: return (AH_TRUE);
! 1616: }
! 1617:
! 1618: u_int32_t
! 1619: ar5k_ar5210_get_gpio(struct ath_hal *hal, u_int32_t gpio)
! 1620: {
! 1621: if (gpio > AR5K_AR5210_NUM_GPIO)
! 1622: return (0xffffffff);
! 1623:
! 1624: /* GPIO input magic */
! 1625: return (((AR5K_REG_READ(AR5K_AR5210_GPIODI) &
! 1626: AR5K_AR5210_GPIOD_MASK) >> gpio) & 0x1);
! 1627: }
! 1628:
! 1629: HAL_BOOL
! 1630: ar5k_ar5210_set_gpio(struct ath_hal *hal, u_int32_t gpio, u_int32_t val)
! 1631: {
! 1632: u_int32_t data;
! 1633:
! 1634: if (gpio > AR5K_AR5210_NUM_GPIO)
! 1635: return (0xffffffff);
! 1636:
! 1637: /* GPIO output magic */
! 1638: data = AR5K_REG_READ(AR5K_AR5210_GPIODO);
! 1639:
! 1640: data &= ~(1 << gpio);
! 1641: data |= (val&1) << gpio;
! 1642:
! 1643: AR5K_REG_WRITE(AR5K_AR5210_GPIODO, data);
! 1644:
! 1645: return (AH_TRUE);
! 1646: }
! 1647:
! 1648: void
! 1649: ar5k_ar5210_set_gpio_intr(struct ath_hal *hal, u_int gpio,
! 1650: u_int32_t interrupt_level)
! 1651: {
! 1652: u_int32_t data;
! 1653:
! 1654: if (gpio > AR5K_AR5210_NUM_GPIO)
! 1655: return;
! 1656:
! 1657: /*
! 1658: * Set the GPIO interrupt
! 1659: */
! 1660: data = (AR5K_REG_READ(AR5K_AR5210_GPIOCR) &
! 1661: ~(AR5K_AR5210_GPIOCR_INT_SEL(gpio) | AR5K_AR5210_GPIOCR_INT_SELH |
! 1662: AR5K_AR5210_GPIOCR_INT_ENA | AR5K_AR5210_GPIOCR_ALL(gpio))) |
! 1663: (AR5K_AR5210_GPIOCR_INT_SEL(gpio) | AR5K_AR5210_GPIOCR_INT_ENA);
! 1664:
! 1665: AR5K_REG_WRITE(AR5K_AR5210_GPIOCR,
! 1666: interrupt_level ? data : (data | AR5K_AR5210_GPIOCR_INT_SELH));
! 1667:
! 1668: hal->ah_imr |= AR5K_AR5210_IMR_GPIO;
! 1669:
! 1670: /* Enable GPIO interrupts */
! 1671: AR5K_REG_ENABLE_BITS(AR5K_AR5210_IMR, AR5K_AR5210_IMR_GPIO);
! 1672: }
! 1673:
! 1674: u_int32_t
! 1675: ar5k_ar5210_get_tsf32(struct ath_hal *hal)
! 1676: {
! 1677: return (AR5K_REG_READ(AR5K_AR5210_TSF_L32));
! 1678: }
! 1679:
! 1680: u_int64_t
! 1681: ar5k_ar5210_get_tsf64(struct ath_hal *hal)
! 1682: {
! 1683: u_int64_t tsf = AR5K_REG_READ(AR5K_AR5210_TSF_U32);
! 1684: return (AR5K_REG_READ(AR5K_AR5210_TSF_L32) | (tsf << 32));
! 1685: }
! 1686:
! 1687: void
! 1688: ar5k_ar5210_reset_tsf(struct ath_hal *hal)
! 1689: {
! 1690: AR5K_REG_ENABLE_BITS(AR5K_AR5210_BEACON,
! 1691: AR5K_AR5210_BEACON_RESET_TSF);
! 1692: }
! 1693:
! 1694: u_int16_t
! 1695: ar5k_ar5210_get_regdomain(struct ath_hal *hal)
! 1696: {
! 1697: return (ar5k_get_regdomain(hal));
! 1698: }
! 1699:
! 1700: HAL_BOOL
! 1701: ar5k_ar5210_detect_card_present(struct ath_hal *hal)
! 1702: {
! 1703: u_int16_t magic;
! 1704:
! 1705: /*
! 1706: * Checking the EEPROM's magic value could be an indication
! 1707: * if the card is still present. I didn't find another suitable
! 1708: * way to do this.
! 1709: */
! 1710: if (ar5k_ar5210_eeprom_read(hal, AR5K_EEPROM_MAGIC, &magic) != 0)
! 1711: return (AH_FALSE);
! 1712:
! 1713: return (magic == AR5K_EEPROM_MAGIC_VALUE ? AH_TRUE : AH_FALSE);
! 1714: }
! 1715:
! 1716: void
! 1717: ar5k_ar5210_update_mib_counters(struct ath_hal *hal, HAL_MIB_STATS *statistics)
! 1718: {
! 1719: statistics->ackrcv_bad += AR5K_REG_READ(AR5K_AR5210_ACK_FAIL);
! 1720: statistics->rts_bad += AR5K_REG_READ(AR5K_AR5210_RTS_FAIL);
! 1721: statistics->rts_good += AR5K_REG_READ(AR5K_AR5210_RTS_OK);
! 1722: statistics->fcs_bad += AR5K_REG_READ(AR5K_AR5210_FCS_FAIL);
! 1723: statistics->beacons += AR5K_REG_READ(AR5K_AR5210_BEACON_CNT);
! 1724: }
! 1725:
! 1726: HAL_RFGAIN
! 1727: ar5k_ar5210_get_rf_gain(struct ath_hal *hal)
! 1728: {
! 1729: return (HAL_RFGAIN_INACTIVE);
! 1730: }
! 1731:
! 1732: HAL_BOOL
! 1733: ar5k_ar5210_set_slot_time(struct ath_hal *hal, u_int slot_time)
! 1734: {
! 1735: if (slot_time < HAL_SLOT_TIME_9 || slot_time > HAL_SLOT_TIME_MAX)
! 1736: return (AH_FALSE);
! 1737:
! 1738: AR5K_REG_WRITE(AR5K_AR5210_SLOT_TIME,
! 1739: ar5k_htoclock(slot_time, hal->ah_turbo));
! 1740:
! 1741: return (AH_TRUE);
! 1742: }
! 1743:
! 1744: u_int
! 1745: ar5k_ar5210_get_slot_time(struct ath_hal *hal)
! 1746: {
! 1747: return (ar5k_clocktoh(AR5K_REG_READ(AR5K_AR5210_SLOT_TIME) &
! 1748: 0xffff, hal->ah_turbo));
! 1749: }
! 1750:
! 1751: HAL_BOOL
! 1752: ar5k_ar5210_set_ack_timeout(struct ath_hal *hal, u_int timeout)
! 1753: {
! 1754: if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5210_TIME_OUT_ACK),
! 1755: hal->ah_turbo) <= timeout)
! 1756: return (AH_FALSE);
! 1757:
! 1758: AR5K_REG_WRITE_BITS(AR5K_AR5210_TIME_OUT, AR5K_AR5210_TIME_OUT_ACK,
! 1759: ar5k_htoclock(timeout, hal->ah_turbo));
! 1760:
! 1761: return (AH_TRUE);
! 1762: }
! 1763:
! 1764: u_int
! 1765: ar5k_ar5210_get_ack_timeout(struct ath_hal *hal)
! 1766: {
! 1767: return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5210_TIME_OUT),
! 1768: AR5K_AR5210_TIME_OUT_ACK), hal->ah_turbo));
! 1769: }
! 1770:
! 1771: HAL_BOOL
! 1772: ar5k_ar5210_set_cts_timeout(struct ath_hal *hal, u_int timeout)
! 1773: {
! 1774: if (ar5k_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_AR5210_TIME_OUT_CTS),
! 1775: hal->ah_turbo) <= timeout)
! 1776: return (AH_FALSE);
! 1777:
! 1778: AR5K_REG_WRITE_BITS(AR5K_AR5210_TIME_OUT, AR5K_AR5210_TIME_OUT_CTS,
! 1779: ar5k_htoclock(timeout, hal->ah_turbo));
! 1780:
! 1781: return (AH_TRUE);
! 1782: }
! 1783:
! 1784: u_int
! 1785: ar5k_ar5210_get_cts_timeout(struct ath_hal *hal)
! 1786: {
! 1787: return (ar5k_clocktoh(AR5K_REG_MS(AR5K_REG_READ(AR5K_AR5210_TIME_OUT),
! 1788: AR5K_AR5210_TIME_OUT_CTS), hal->ah_turbo));
! 1789: }
! 1790:
! 1791: /*
! 1792: * Key table (WEP) functions
! 1793: */
! 1794:
! 1795: HAL_BOOL
! 1796: ar5k_ar5210_is_cipher_supported(struct ath_hal *hal, HAL_CIPHER cipher)
! 1797: {
! 1798: /*
! 1799: * The AR5210 only supports WEP
! 1800: */
! 1801: if (cipher == HAL_CIPHER_WEP)
! 1802: return (AH_TRUE);
! 1803:
! 1804: return (AH_FALSE);
! 1805: }
! 1806:
! 1807: u_int32_t
! 1808: ar5k_ar5210_get_keycache_size(struct ath_hal *hal)
! 1809: {
! 1810: return (AR5K_AR5210_KEYCACHE_SIZE);
! 1811: }
! 1812:
! 1813: HAL_BOOL
! 1814: ar5k_ar5210_reset_key(struct ath_hal *hal, u_int16_t entry)
! 1815: {
! 1816: int i;
! 1817:
! 1818: AR5K_ASSERT_ENTRY(entry, AR5K_AR5210_KEYTABLE_SIZE);
! 1819:
! 1820: for (i = 0; i < AR5K_AR5210_KEYCACHE_SIZE; i++)
! 1821: AR5K_REG_WRITE(AR5K_AR5210_KEYTABLE_OFF(entry, i), 0);
! 1822:
! 1823: return (AH_FALSE);
! 1824: }
! 1825:
! 1826: HAL_BOOL
! 1827: ar5k_ar5210_is_key_valid(struct ath_hal *hal, u_int16_t entry)
! 1828: {
! 1829: AR5K_ASSERT_ENTRY(entry, AR5K_AR5210_KEYTABLE_SIZE);
! 1830:
! 1831: /*
! 1832: * Check the validation flag at the end of the entry
! 1833: */
! 1834: if (AR5K_REG_READ(AR5K_AR5210_KEYTABLE_MAC1(entry)) &
! 1835: AR5K_AR5210_KEYTABLE_VALID)
! 1836: return (AH_TRUE);
! 1837:
! 1838: return (AH_FALSE);
! 1839: }
! 1840:
! 1841: HAL_BOOL
! 1842: ar5k_ar5210_set_key(struct ath_hal *hal, u_int16_t entry,
! 1843: const HAL_KEYVAL *keyval, const u_int8_t *mac, int xor_notused)
! 1844: {
! 1845: int i;
! 1846: u_int32_t key_v[AR5K_AR5210_KEYCACHE_SIZE - 2];
! 1847:
! 1848: AR5K_ASSERT_ENTRY(entry, AR5K_AR5210_KEYTABLE_SIZE);
! 1849:
! 1850: bzero(&key_v, sizeof(key_v));
! 1851:
! 1852: switch (keyval->wk_len) {
! 1853: case AR5K_KEYVAL_LENGTH_40:
! 1854: bcopy(keyval->wk_key, &key_v[0], 4);
! 1855: bcopy(keyval->wk_key + 4, &key_v[1], 1);
! 1856: key_v[5] = AR5K_AR5210_KEYTABLE_TYPE_40;
! 1857: break;
! 1858:
! 1859: case AR5K_KEYVAL_LENGTH_104:
! 1860: bcopy(keyval->wk_key, &key_v[0], 4);
! 1861: bcopy(keyval->wk_key + 4, &key_v[1], 2);
! 1862: bcopy(keyval->wk_key + 6, &key_v[2], 4);
! 1863: bcopy(keyval->wk_key + 10, &key_v[3], 2);
! 1864: bcopy(keyval->wk_key + 12, &key_v[4], 1);
! 1865: key_v[5] = AR5K_AR5210_KEYTABLE_TYPE_104;
! 1866: break;
! 1867:
! 1868: case AR5K_KEYVAL_LENGTH_128:
! 1869: bcopy(keyval->wk_key, &key_v[0], 4);
! 1870: bcopy(keyval->wk_key + 4, &key_v[1], 2);
! 1871: bcopy(keyval->wk_key + 6, &key_v[2], 4);
! 1872: bcopy(keyval->wk_key + 10, &key_v[3], 2);
! 1873: bcopy(keyval->wk_key + 12, &key_v[4], 4);
! 1874: key_v[5] = AR5K_AR5210_KEYTABLE_TYPE_128;
! 1875: break;
! 1876:
! 1877: default:
! 1878: /* Unsupported key length (not WEP40/104/128) */
! 1879: return (AH_FALSE);
! 1880: }
! 1881:
! 1882: for (i = 0; i < AR5K_ELEMENTS(key_v); i++)
! 1883: AR5K_REG_WRITE(AR5K_AR5210_KEYTABLE_OFF(entry, i), key_v[i]);
! 1884:
! 1885: return (ar5k_ar5210_set_key_lladdr(hal, entry, mac));
! 1886: }
! 1887:
! 1888: HAL_BOOL
! 1889: ar5k_ar5210_set_key_lladdr(struct ath_hal *hal, u_int16_t entry,
! 1890: const u_int8_t *mac)
! 1891: {
! 1892: u_int32_t low_id, high_id;
! 1893: const u_int8_t *mac_v;
! 1894:
! 1895: /*
! 1896: * Invalid entry (key table overflow)
! 1897: */
! 1898: AR5K_ASSERT_ENTRY(entry, AR5K_AR5210_KEYTABLE_SIZE);
! 1899:
! 1900: /* MAC may be NULL if it's a broadcast key */
! 1901: mac_v = mac == NULL ? etherbroadcastaddr : mac;
! 1902:
! 1903: low_id = AR5K_LOW_ID(mac_v);
! 1904: high_id = AR5K_HIGH_ID(mac_v) | AR5K_AR5210_KEYTABLE_VALID;
! 1905:
! 1906: AR5K_REG_WRITE(AR5K_AR5210_KEYTABLE_MAC0(entry), low_id);
! 1907: AR5K_REG_WRITE(AR5K_AR5210_KEYTABLE_MAC1(entry), high_id);
! 1908:
! 1909: return (AH_TRUE);
! 1910: }
! 1911:
! 1912: /*
! 1913: * Power management functions
! 1914: */
! 1915:
! 1916: HAL_BOOL
! 1917: ar5k_ar5210_set_power(struct ath_hal *hal, HAL_POWER_MODE mode,
! 1918: HAL_BOOL set_chip, u_int16_t sleep_duration)
! 1919: {
! 1920: u_int32_t staid;
! 1921: int i;
! 1922:
! 1923: staid = AR5K_REG_READ(AR5K_AR5210_STA_ID1);
! 1924:
! 1925: switch (mode) {
! 1926: case HAL_PM_AUTO:
! 1927: staid &= ~AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA;
! 1928: /* FALLTHROUGH */
! 1929: case HAL_PM_NETWORK_SLEEP:
! 1930: if (set_chip == AH_TRUE) {
! 1931: AR5K_REG_WRITE(AR5K_AR5210_SCR,
! 1932: AR5K_AR5210_SCR_SLE | sleep_duration);
! 1933: }
! 1934: staid |= AR5K_AR5210_STA_ID1_PWR_SV;
! 1935: break;
! 1936:
! 1937: case HAL_PM_FULL_SLEEP:
! 1938: if (set_chip == AH_TRUE) {
! 1939: AR5K_REG_WRITE(AR5K_AR5210_SCR,
! 1940: AR5K_AR5210_SCR_SLE_SLP);
! 1941: }
! 1942: staid |= AR5K_AR5210_STA_ID1_PWR_SV;
! 1943: break;
! 1944:
! 1945: case HAL_PM_AWAKE:
! 1946: if (set_chip == AH_FALSE)
! 1947: goto commit;
! 1948:
! 1949: AR5K_REG_WRITE(AR5K_AR5210_SCR, AR5K_AR5210_SCR_SLE_WAKE);
! 1950:
! 1951: for (i = 5000; i > 0; i--) {
! 1952: /* Check if the AR5210 did wake up */
! 1953: if ((AR5K_REG_READ(AR5K_AR5210_PCICFG) &
! 1954: AR5K_AR5210_PCICFG_SPWR_DN) == 0)
! 1955: break;
! 1956:
! 1957: /* Wait a bit and retry */
! 1958: AR5K_DELAY(200);
! 1959: AR5K_REG_WRITE(AR5K_AR5210_SCR,
! 1960: AR5K_AR5210_SCR_SLE_WAKE);
! 1961: }
! 1962:
! 1963: /* Fail if the AR5210 didn't wake up */
! 1964: if (i <= 0)
! 1965: return (AH_FALSE);
! 1966:
! 1967: staid &= ~AR5K_AR5210_STA_ID1_PWR_SV;
! 1968: break;
! 1969:
! 1970: default:
! 1971: return (AH_FALSE);
! 1972: }
! 1973:
! 1974: commit:
! 1975: hal->ah_power_mode = mode;
! 1976:
! 1977: AR5K_REG_WRITE(AR5K_AR5210_STA_ID1, staid);
! 1978:
! 1979: return (AH_TRUE);
! 1980: }
! 1981:
! 1982: HAL_POWER_MODE
! 1983: ar5k_ar5210_get_power_mode(struct ath_hal *hal)
! 1984: {
! 1985: return (hal->ah_power_mode);
! 1986: }
! 1987:
! 1988: HAL_BOOL
! 1989: ar5k_ar5210_query_pspoll_support(struct ath_hal *hal)
! 1990: {
! 1991: /* I think so, why not? */
! 1992: return (AH_TRUE);
! 1993: }
! 1994:
! 1995: HAL_BOOL
! 1996: ar5k_ar5210_init_pspoll(struct ath_hal *hal)
! 1997: {
! 1998: /*
! 1999: * Not used on the AR5210
! 2000: */
! 2001: return (AH_FALSE);
! 2002: }
! 2003:
! 2004: HAL_BOOL
! 2005: ar5k_ar5210_enable_pspoll(struct ath_hal *hal, u_int8_t *bssid,
! 2006: u_int16_t assoc_id)
! 2007: {
! 2008: AR5K_REG_DISABLE_BITS(AR5K_AR5210_STA_ID1,
! 2009: AR5K_AR5210_STA_ID1_NO_PSPOLL |
! 2010: AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA);
! 2011:
! 2012: return (AH_TRUE);
! 2013: }
! 2014:
! 2015: HAL_BOOL
! 2016: ar5k_ar5210_disable_pspoll(struct ath_hal *hal)
! 2017: {
! 2018: AR5K_REG_ENABLE_BITS(AR5K_AR5210_STA_ID1,
! 2019: AR5K_AR5210_STA_ID1_NO_PSPOLL |
! 2020: AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA);
! 2021:
! 2022: return (AH_TRUE);
! 2023: }
! 2024:
! 2025: /*
! 2026: * Beacon functions
! 2027: */
! 2028:
! 2029: void
! 2030: ar5k_ar5210_init_beacon(struct ath_hal *hal, u_int32_t next_beacon,
! 2031: u_int32_t interval)
! 2032: {
! 2033: u_int32_t timer1, timer2, timer3;
! 2034:
! 2035: /*
! 2036: * Set the additional timers by mode
! 2037: */
! 2038: switch (hal->ah_op_mode) {
! 2039: case HAL_M_STA:
! 2040: timer1 = 0xffffffff;
! 2041: timer2 = 0xffffffff;
! 2042: timer3 = 1;
! 2043: break;
! 2044:
! 2045: default:
! 2046: timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
! 2047: timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
! 2048: timer3 = next_beacon + hal->ah_atim_window;
! 2049: break;
! 2050: }
! 2051:
! 2052: /*
! 2053: * Enable all timers and set the beacon register
! 2054: * (next beacon, DMA beacon, software beacon, ATIM window time)
! 2055: */
! 2056: AR5K_REG_WRITE(AR5K_AR5210_TIMER0, next_beacon);
! 2057: AR5K_REG_WRITE(AR5K_AR5210_TIMER1, timer1);
! 2058: AR5K_REG_WRITE(AR5K_AR5210_TIMER2, timer2);
! 2059: AR5K_REG_WRITE(AR5K_AR5210_TIMER3, timer3);
! 2060:
! 2061: AR5K_REG_WRITE(AR5K_AR5210_BEACON, interval &
! 2062: (AR5K_AR5210_BEACON_PERIOD | AR5K_AR5210_BEACON_RESET_TSF |
! 2063: AR5K_AR5210_BEACON_EN));
! 2064: }
! 2065:
! 2066: void
! 2067: ar5k_ar5210_set_beacon_timers(struct ath_hal *hal,
! 2068: const HAL_BEACON_STATE *state, u_int32_t tsf, u_int32_t dtim_count,
! 2069: u_int32_t cfp_count)
! 2070: {
! 2071: u_int32_t cfp_period, next_cfp;
! 2072:
! 2073: /* Return on an invalid beacon state */
! 2074: if (state->bs_interval < 1)
! 2075: return;
! 2076:
! 2077: /*
! 2078: * PCF support?
! 2079: */
! 2080: if (state->bs_cfp_period > 0) {
! 2081: /* Enable CFP mode and set the CFP and timer registers */
! 2082: cfp_period = state->bs_cfp_period * state->bs_dtim_period *
! 2083: state->bs_interval;
! 2084: next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
! 2085: state->bs_interval;
! 2086:
! 2087: AR5K_REG_DISABLE_BITS(AR5K_AR5210_STA_ID1,
! 2088: AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA |
! 2089: AR5K_AR5210_STA_ID1_PCF);
! 2090: AR5K_REG_WRITE(AR5K_AR5210_CFP_PERIOD, cfp_period);
! 2091: AR5K_REG_WRITE(AR5K_AR5210_CFP_DUR, state->bs_cfp_max_duration);
! 2092: AR5K_REG_WRITE(AR5K_AR5210_TIMER2,
! 2093: (tsf + (next_cfp == 0 ? cfp_period : next_cfp)) << 3);
! 2094: } else {
! 2095: /* Disable PCF mode */
! 2096: AR5K_REG_DISABLE_BITS(AR5K_AR5210_STA_ID1,
! 2097: AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA |
! 2098: AR5K_AR5210_STA_ID1_PCF);
! 2099: }
! 2100:
! 2101: /*
! 2102: * Enable the beacon timer register
! 2103: */
! 2104: AR5K_REG_WRITE(AR5K_AR5210_TIMER0, state->bs_next_beacon);
! 2105:
! 2106: /*
! 2107: * Start the beacon timers
! 2108: */
! 2109: AR5K_REG_WRITE(AR5K_AR5210_BEACON,
! 2110: (AR5K_REG_READ(AR5K_AR5210_BEACON) &~
! 2111: (AR5K_AR5210_BEACON_PERIOD | AR5K_AR5210_BEACON_TIM)) |
! 2112: AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
! 2113: AR5K_AR5210_BEACON_TIM) |
! 2114: AR5K_REG_SM(state->bs_interval, AR5K_AR5210_BEACON_PERIOD));
! 2115:
! 2116: /*
! 2117: * Write new beacon miss threshold, if it appears to be valid
! 2118: */
! 2119: if (state->bs_bmiss_threshold <=
! 2120: (AR5K_AR5210_RSSI_THR_BM_THR >> AR5K_AR5210_RSSI_THR_BM_THR_S)) {
! 2121: AR5K_REG_WRITE_BITS(AR5K_AR5210_RSSI_THR,
! 2122: AR5K_AR5210_RSSI_THR_BM_THR, state->bs_bmiss_threshold);
! 2123: }
! 2124: }
! 2125:
! 2126: void
! 2127: ar5k_ar5210_reset_beacon(struct ath_hal *hal)
! 2128: {
! 2129: /*
! 2130: * Disable beacon timer
! 2131: */
! 2132: AR5K_REG_WRITE(AR5K_AR5210_TIMER0, 0);
! 2133:
! 2134: /*
! 2135: * Disable some beacon register values
! 2136: */
! 2137: AR5K_REG_DISABLE_BITS(AR5K_AR5210_STA_ID1,
! 2138: AR5K_AR5210_STA_ID1_DEFAULT_ANTENNA | AR5K_AR5210_STA_ID1_PCF);
! 2139: AR5K_REG_WRITE(AR5K_AR5210_BEACON, AR5K_AR5210_BEACON_PERIOD);
! 2140: }
! 2141:
! 2142: HAL_BOOL
! 2143: ar5k_ar5210_wait_for_beacon(struct ath_hal *hal, bus_addr_t phys_addr)
! 2144: {
! 2145: int i;
! 2146:
! 2147: /*
! 2148: * Wait for beaconn queue to be done
! 2149: */
! 2150: for (i = (AR5K_TUNE_BEACON_INTERVAL / 2); i > 0 &&
! 2151: (AR5K_REG_READ(AR5K_AR5210_BSR) &
! 2152: AR5K_AR5210_BSR_TXQ1F) != 0 &&
! 2153: (AR5K_REG_READ(AR5K_AR5210_CR) &
! 2154: AR5K_AR5210_CR_TXE1) != 0; i--);
! 2155:
! 2156: /* Timeout... */
! 2157: if (i <= 0) {
! 2158: /*
! 2159: * Re-schedule the beacon queue
! 2160: */
! 2161: AR5K_REG_WRITE(AR5K_AR5210_TXDP1, (u_int32_t)phys_addr);
! 2162: AR5K_REG_WRITE(AR5K_AR5210_BCR,
! 2163: AR5K_AR5210_BCR_TQ1V | AR5K_AR5210_BCR_BDMAE);
! 2164:
! 2165: return (AH_FALSE);
! 2166: }
! 2167:
! 2168: return (AH_TRUE);
! 2169: }
! 2170:
! 2171: /*
! 2172: * Interrupt handling
! 2173: */
! 2174:
! 2175: HAL_BOOL
! 2176: ar5k_ar5210_is_intr_pending(struct ath_hal *hal)
! 2177: {
! 2178: return (AR5K_REG_READ(AR5K_AR5210_INTPEND) == 0 ? AH_FALSE : AH_TRUE);
! 2179: }
! 2180:
! 2181: HAL_BOOL
! 2182: ar5k_ar5210_get_isr(struct ath_hal *hal, u_int32_t *interrupt_mask)
! 2183: {
! 2184: u_int32_t data;
! 2185:
! 2186: if ((data = AR5K_REG_READ(AR5K_AR5210_ISR)) == HAL_INT_NOCARD) {
! 2187: *interrupt_mask = data;
! 2188: return (AH_FALSE);
! 2189: }
! 2190:
! 2191: /*
! 2192: * Get abstract interrupt mask (HAL-compatible)
! 2193: */
! 2194: *interrupt_mask = (data & HAL_INT_COMMON) & hal->ah_imr;
! 2195:
! 2196: if (data & (AR5K_AR5210_ISR_RXOK | AR5K_AR5210_ISR_RXERR))
! 2197: *interrupt_mask |= HAL_INT_RX;
! 2198: if (data & (AR5K_AR5210_ISR_TXOK | AR5K_AR5210_ISR_TXERR))
! 2199: *interrupt_mask |= HAL_INT_TX;
! 2200: if (data & AR5K_AR5210_ISR_FATAL)
! 2201: *interrupt_mask |= HAL_INT_FATAL;
! 2202:
! 2203: /*
! 2204: * Special interrupt handling (not caught by the driver)
! 2205: */
! 2206: if (((*interrupt_mask) & AR5K_AR5210_ISR_RXPHY) &&
! 2207: hal->ah_radar.r_enabled == AH_TRUE)
! 2208: ar5k_radar_alert(hal);
! 2209:
! 2210: /* XXX BMISS interrupts may occur after association */
! 2211: *interrupt_mask &= ~HAL_INT_BMISS;
! 2212:
! 2213: return (AH_TRUE);
! 2214: }
! 2215:
! 2216: u_int32_t
! 2217: ar5k_ar5210_get_intr(struct ath_hal *hal)
! 2218: {
! 2219: /* Return the interrupt mask stored previously */
! 2220: return (hal->ah_imr);
! 2221: }
! 2222:
! 2223: HAL_INT
! 2224: ar5k_ar5210_set_intr(struct ath_hal *hal, HAL_INT new_mask)
! 2225: {
! 2226: HAL_INT old_mask, int_mask;
! 2227:
! 2228: /*
! 2229: * Disable card interrupts to prevent any race conditions
! 2230: * (they will be re-enabled afterwards).
! 2231: */
! 2232: AR5K_REG_WRITE(AR5K_AR5210_IER, AR5K_AR5210_IER_DISABLE);
! 2233:
! 2234: old_mask = hal->ah_imr;
! 2235:
! 2236: /*
! 2237: * Add additional, chipset-dependent interrupt mask flags
! 2238: * and write them to the IMR (interrupt mask register).
! 2239: */
! 2240: int_mask = new_mask & HAL_INT_COMMON;
! 2241:
! 2242: if (new_mask & HAL_INT_RX)
! 2243: int_mask |=
! 2244: AR5K_AR5210_IMR_RXOK |
! 2245: AR5K_AR5210_IMR_RXERR |
! 2246: AR5K_AR5210_IMR_RXORN;
! 2247:
! 2248: if (new_mask & HAL_INT_TX)
! 2249: int_mask |=
! 2250: AR5K_AR5210_IMR_TXOK |
! 2251: AR5K_AR5210_IMR_TXERR |
! 2252: AR5K_AR5210_IMR_TXURN;
! 2253:
! 2254: AR5K_REG_WRITE(AR5K_AR5210_IMR, int_mask);
! 2255:
! 2256: /* Store new interrupt mask */
! 2257: hal->ah_imr = new_mask;
! 2258:
! 2259: /* ..re-enable interrupts */
! 2260: if (int_mask) {
! 2261: AR5K_REG_WRITE(AR5K_AR5210_IER, AR5K_AR5210_IER_ENABLE);
! 2262: }
! 2263:
! 2264: return (old_mask);
! 2265: }
! 2266:
! 2267: /*
! 2268: * Misc internal functions
! 2269: */
! 2270:
! 2271: HAL_BOOL
! 2272: ar5k_ar5210_get_capabilities(struct ath_hal *hal)
! 2273: {
! 2274: /* Set number of supported TX queues */
! 2275: hal->ah_capabilities.cap_queues.q_tx_num = AR5K_AR5210_TX_NUM_QUEUES;
! 2276:
! 2277: /*
! 2278: * Set radio capabilities
! 2279: * (The AR5210 only supports the middle 5GHz band)
! 2280: */
! 2281: hal->ah_capabilities.cap_range.range_5ghz_min = 5120;
! 2282: hal->ah_capabilities.cap_range.range_5ghz_max = 5430;
! 2283: hal->ah_capabilities.cap_range.range_2ghz_min = 0;
! 2284: hal->ah_capabilities.cap_range.range_2ghz_max = 0;
! 2285:
! 2286: /* Set supported modes */
! 2287: hal->ah_capabilities.cap_mode = HAL_MODE_11A | HAL_MODE_TURBO;
! 2288:
! 2289: /* Set number of GPIO pins */
! 2290: hal->ah_gpio_npins = AR5K_AR5210_NUM_GPIO;
! 2291:
! 2292: return (AH_TRUE);
! 2293: }
! 2294:
! 2295: void
! 2296: ar5k_ar5210_radar_alert(struct ath_hal *hal, HAL_BOOL enable)
! 2297: {
! 2298: /*
! 2299: * Set the RXPHY interrupt to be able to detect
! 2300: * possible radar activity.
! 2301: */
! 2302: AR5K_REG_WRITE(AR5K_AR5210_IER, AR5K_AR5210_IER_DISABLE);
! 2303:
! 2304: if (enable == AH_TRUE) {
! 2305: AR5K_REG_ENABLE_BITS(AR5K_AR5210_IMR,
! 2306: AR5K_AR5210_IMR_RXPHY);
! 2307: } else {
! 2308: AR5K_REG_DISABLE_BITS(AR5K_AR5210_IMR,
! 2309: AR5K_AR5210_IMR_RXPHY);
! 2310: }
! 2311:
! 2312: AR5K_REG_WRITE(AR5K_AR5210_IER, AR5K_AR5210_IER_ENABLE);
! 2313: }
! 2314:
! 2315: /*
! 2316: * EEPROM access functions
! 2317: */
! 2318:
! 2319: HAL_BOOL
! 2320: ar5k_ar5210_eeprom_is_busy(struct ath_hal *hal)
! 2321: {
! 2322: return (AR5K_REG_READ(AR5K_AR5210_CFG) & AR5K_AR5210_CFG_EEBS ?
! 2323: AH_TRUE : AH_FALSE);
! 2324: }
! 2325:
! 2326: int
! 2327: ar5k_ar5210_eeprom_read(struct ath_hal *hal, u_int32_t offset, u_int16_t *data)
! 2328: {
! 2329: u_int32_t status, timeout;
! 2330:
! 2331: /* Enable eeprom access */
! 2332: AR5K_REG_ENABLE_BITS(AR5K_AR5210_PCICFG, AR5K_AR5210_PCICFG_EEAE);
! 2333:
! 2334: /*
! 2335: * Prime read pump
! 2336: */
! 2337: (void)AR5K_REG_READ(AR5K_AR5210_EEPROM_BASE + (4 * offset));
! 2338:
! 2339: for (timeout = 10000; timeout > 0; timeout--) {
! 2340: AR5K_DELAY(1);
! 2341: status = AR5K_REG_READ(AR5K_AR5210_EEPROM_STATUS);
! 2342: if (status & AR5K_AR5210_EEPROM_STAT_RDDONE) {
! 2343: if (status & AR5K_AR5210_EEPROM_STAT_RDERR)
! 2344: return (EIO);
! 2345: *data = (u_int16_t)
! 2346: (AR5K_REG_READ(AR5K_AR5210_EEPROM_RDATA) & 0xffff);
! 2347: return (0);
! 2348: }
! 2349: }
! 2350:
! 2351: return (ETIMEDOUT);
! 2352: }
! 2353:
! 2354: int
! 2355: ar5k_ar5210_eeprom_write(struct ath_hal *hal, u_int32_t offset, u_int16_t data)
! 2356: {
! 2357: u_int32_t status, timeout;
! 2358:
! 2359: /* Enable eeprom access */
! 2360: AR5K_REG_ENABLE_BITS(AR5K_AR5210_PCICFG, AR5K_AR5210_PCICFG_EEAE);
! 2361:
! 2362: /*
! 2363: * Prime write pump
! 2364: */
! 2365: AR5K_REG_WRITE(AR5K_AR5210_EEPROM_BASE + (4 * offset), data);
! 2366:
! 2367: for (timeout = 10000; timeout > 0; timeout--) {
! 2368: AR5K_DELAY(1);
! 2369: status = AR5K_REG_READ(AR5K_AR5210_EEPROM_STATUS);
! 2370: if (status & AR5K_AR5210_EEPROM_STAT_WRDONE) {
! 2371: if (status & AR5K_AR5210_EEPROM_STAT_WRERR)
! 2372: return (EIO);
! 2373: return (0);
! 2374: }
! 2375: }
! 2376:
! 2377: return (ETIMEDOUT);
! 2378: }
! 2379:
! 2380: HAL_BOOL
! 2381: ar5k_ar5210_set_txpower_limit(struct ath_hal *hal, u_int power)
! 2382: {
! 2383: /* Not implemented */
! 2384: return (AH_FALSE);
! 2385: }
CVSweb