📄 ar5210.c
字号:
/* $OpenBSD: ar5210.c,v 1.33 2005/12/18 17:59:58 reyk Exp $ *//* * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *//* * HAL interface for the Atheros AR5000 Wireless LAN chipset * (AR5210 + AR5110). */#include "ar5xxx.h"#include "ar5210reg.h"#include "ar5210var.h"HAL_BOOL ar5k_ar5210_nic_reset(struct ath_hal *, u_int32_t);HAL_BOOL ar5k_ar5210_nic_wakeup(struct ath_hal *, HAL_BOOL, HAL_BOOL);void ar5k_ar5210_init_tx_queue(struct ath_hal *, u_int, HAL_BOOL);void ar5k_ar5210_fill(struct ath_hal *);HAL_BOOL ar5k_ar5210_do_calibrate(struct ath_hal *, HAL_CHANNEL *);HAL_BOOL ar5k_ar5210_noise_floor(struct ath_hal *, HAL_CHANNEL *);/* * Initial register setting for the AR5210 */static const struct ar5k_ini ar5210_ini[] = AR5K_AR5210_INI;AR5K_HAL_FUNCTIONS(extern, ar5k_ar5210,);voidar5k_ar5210_fill(struct ath_hal *hal){ hal->ah_magic = AR5K_AR5210_MAGIC; /* * Init/Exit functions */ AR5K_HAL_FUNCTION(hal, ar5210, get_rate_table); AR5K_HAL_FUNCTION(hal, ar5210, detach); /* * Reset functions */ AR5K_HAL_FUNCTION(hal, ar5210, reset); AR5K_HAL_FUNCTION(hal, ar5210, set_opmode); AR5K_HAL_FUNCTION(hal, ar5210, calibrate); /* * TX functions */ AR5K_HAL_FUNCTION(hal, ar5210, update_tx_triglevel); AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_queue); AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_queueprops); AR5K_HAL_FUNCTION(hal, ar5210, release_tx_queue); AR5K_HAL_FUNCTION(hal, ar5210, reset_tx_queue); AR5K_HAL_FUNCTION(hal, ar5210, get_tx_buf); AR5K_HAL_FUNCTION(hal, ar5210, put_tx_buf); AR5K_HAL_FUNCTION(hal, ar5210, tx_start); AR5K_HAL_FUNCTION(hal, ar5210, stop_tx_dma); AR5K_HAL_FUNCTION(hal, ar5210, setup_tx_desc); AR5K_HAL_FUNCTION(hal, ar5210, setup_xtx_desc); AR5K_HAL_FUNCTION(hal, ar5210, fill_tx_desc); AR5K_HAL_FUNCTION(hal, ar5210, proc_tx_desc); AR5K_HAL_FUNCTION(hal, ar5210, has_veol); /* * RX functions */ AR5K_HAL_FUNCTION(hal, ar5210, get_rx_buf); AR5K_HAL_FUNCTION(hal, ar5210, put_rx_buf); AR5K_HAL_FUNCTION(hal, ar5210, start_rx); AR5K_HAL_FUNCTION(hal, ar5210, stop_rx_dma); AR5K_HAL_FUNCTION(hal, ar5210, start_rx_pcu); AR5K_HAL_FUNCTION(hal, ar5210, stop_pcu_recv); AR5K_HAL_FUNCTION(hal, ar5210, set_mcast_filter); AR5K_HAL_FUNCTION(hal, ar5210, set_mcast_filterindex); AR5K_HAL_FUNCTION(hal, ar5210, clear_mcast_filter_idx); AR5K_HAL_FUNCTION(hal, ar5210, get_rx_filter); AR5K_HAL_FUNCTION(hal, ar5210, set_rx_filter); AR5K_HAL_FUNCTION(hal, ar5210, setup_rx_desc); AR5K_HAL_FUNCTION(hal, ar5210, proc_rx_desc); AR5K_HAL_FUNCTION(hal, ar5210, set_rx_signal); /* * Misc functions */ AR5K_HAL_FUNCTION(hal, ar5210, dump_state); AR5K_HAL_FUNCTION(hal, ar5210, get_diag_state); AR5K_HAL_FUNCTION(hal, ar5210, get_lladdr); AR5K_HAL_FUNCTION(hal, ar5210, set_lladdr); AR5K_HAL_FUNCTION(hal, ar5210, set_regdomain); AR5K_HAL_FUNCTION(hal, ar5210, set_ledstate); AR5K_HAL_FUNCTION(hal, ar5210, set_associd); AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_input); AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_output); AR5K_HAL_FUNCTION(hal, ar5210, get_gpio); AR5K_HAL_FUNCTION(hal, ar5210, set_gpio); AR5K_HAL_FUNCTION(hal, ar5210, set_gpio_intr); AR5K_HAL_FUNCTION(hal, ar5210, get_tsf32); AR5K_HAL_FUNCTION(hal, ar5210, get_tsf64); AR5K_HAL_FUNCTION(hal, ar5210, reset_tsf); AR5K_HAL_FUNCTION(hal, ar5210, get_regdomain); AR5K_HAL_FUNCTION(hal, ar5210, detect_card_present); AR5K_HAL_FUNCTION(hal, ar5210, update_mib_counters); AR5K_HAL_FUNCTION(hal, ar5210, get_rf_gain); AR5K_HAL_FUNCTION(hal, ar5210, set_slot_time); AR5K_HAL_FUNCTION(hal, ar5210, get_slot_time); AR5K_HAL_FUNCTION(hal, ar5210, set_ack_timeout); AR5K_HAL_FUNCTION(hal, ar5210, get_ack_timeout); AR5K_HAL_FUNCTION(hal, ar5210, set_cts_timeout); AR5K_HAL_FUNCTION(hal, ar5210, get_cts_timeout); /* * Key table (WEP) functions */ AR5K_HAL_FUNCTION(hal, ar5210, is_cipher_supported); AR5K_HAL_FUNCTION(hal, ar5210, get_keycache_size); AR5K_HAL_FUNCTION(hal, ar5210, reset_key); AR5K_HAL_FUNCTION(hal, ar5210, is_key_valid); AR5K_HAL_FUNCTION(hal, ar5210, set_key); AR5K_HAL_FUNCTION(hal, ar5210, set_key_lladdr); /* * Power management functions */ AR5K_HAL_FUNCTION(hal, ar5210, set_power); AR5K_HAL_FUNCTION(hal, ar5210, get_power_mode); AR5K_HAL_FUNCTION(hal, ar5210, query_pspoll_support); AR5K_HAL_FUNCTION(hal, ar5210, init_pspoll); AR5K_HAL_FUNCTION(hal, ar5210, enable_pspoll); AR5K_HAL_FUNCTION(hal, ar5210, disable_pspoll); /* * Beacon functions */ AR5K_HAL_FUNCTION(hal, ar5210, init_beacon); AR5K_HAL_FUNCTION(hal, ar5210, set_beacon_timers); AR5K_HAL_FUNCTION(hal, ar5210, reset_beacon); AR5K_HAL_FUNCTION(hal, ar5210, wait_for_beacon); /* * Interrupt functions */ AR5K_HAL_FUNCTION(hal, ar5210, is_intr_pending); AR5K_HAL_FUNCTION(hal, ar5210, get_isr); AR5K_HAL_FUNCTION(hal, ar5210, get_intr); AR5K_HAL_FUNCTION(hal, ar5210, set_intr); /* * Chipset functions (ar5k-specific, non-HAL) */ AR5K_HAL_FUNCTION(hal, ar5210, get_capabilities); AR5K_HAL_FUNCTION(hal, ar5210, radar_alert); /* * EEPROM access */ AR5K_HAL_FUNCTION(hal, ar5210, eeprom_is_busy); AR5K_HAL_FUNCTION(hal, ar5210, eeprom_read); AR5K_HAL_FUNCTION(hal, ar5210, eeprom_write); /* Functions not found in OpenBSD */ AR5K_HAL_FUNCTION(hal, ar5210, get_tx_queueprops); AR5K_HAL_FUNCTION(hal, ar5210, get_capability); AR5K_HAL_FUNCTION(hal, ar5210, num_tx_pending); AR5K_HAL_FUNCTION(hal, ar5210, phy_disable); AR5K_HAL_FUNCTION(hal, ar5210, set_pcu_config); /*Totaly unimplemented*/ AR5K_HAL_FUNCTION(hal, ar5210, set_capability); AR5K_HAL_FUNCTION(hal, ar5210, proc_mib_event); AR5K_HAL_FUNCTION(hal, ar5210, get_tx_inter_queue); AR5K_HAL_FUNCTION(hal, ar5210, set_txpower_limit); AR5K_HAL_FUNCTION(hal, ar5210, set_def_antenna); AR5K_HAL_FUNCTION(hal, ar5210, get_def_antenna);}struct ath_hal * /*Ported & removed an arg from call to set_associd*/ar5k_ar5210_attach(u_int16_t device, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status){ int i; struct ath_hal *hal = (struct ath_hal*) sc; u_int8_t mac[IEEE80211_ADDR_LEN]; u_int32_t srev; ar5k_ar5210_fill(hal); /* Bring device out of sleep and reset it's units */ if (ar5k_ar5210_nic_wakeup(hal, AH_FALSE, AH_TRUE) != AH_TRUE) return (NULL); /* Get MAC, PHY and RADIO revisions */ srev = AR5K_REG_READ(AR5K_AR5210_SREV); hal->ah_mac_srev = srev; hal->ah_mac_version = AR5K_REG_MS(srev, AR5K_AR5210_SREV_VER); hal->ah_mac_revision = AR5K_REG_MS(srev, AR5K_AR5210_SREV_REV); hal->ah_phy_revision = AR5K_REG_READ(AR5K_AR5210_PHY_CHIP_ID) & 0x00ffffffff; /* ...wait until PHY is ready and read RADIO revision */ AR5K_REG_WRITE(AR5K_AR5210_PHY(0x34), 0x00001c16); for (i = 0; i < 4; i++) AR5K_REG_WRITE(AR5K_AR5210_PHY(0x20), 0x00010000); hal->ah_radio_5ghz_revision = (u_int16_t) (ar5k_bitswap((AR5K_REG_READ(AR5K_AR5210_PHY(256) >> 28) & 0xf), 4) + 1); hal->ah_radio_2ghz_revision = 0; /* Identify the chipset */ hal->ah_version = AR5K_AR5210; hal->ah_radio = AR5K_AR5110; hal->ah_phy = AR5K_AR5210_PHY(0); bcopy(etherbroadcastaddr, mac, IEEE80211_ADDR_LEN); ar5k_ar5210_set_associd(hal, mac, 0); ar5k_ar5210_get_lladdr(hal, mac); ar5k_ar5210_set_opmode(hal); return (hal);}HAL_BOOLar5k_ar5210_nic_reset(struct ath_hal *hal, u_int32_t val){ HAL_BOOL ret = AH_FALSE; u_int32_t mask = val ? val : ~0; /* * Reset the device and wait until success */ AR5K_REG_WRITE(AR5K_AR5210_RC, val); /* Wait at least 128 PCI clocks */ AR5K_DELAY(15); val &= AR5K_AR5210_RC_PCU | AR5K_AR5210_RC_MAC | AR5K_AR5210_RC_PHY | AR5K_AR5210_RC_DMA; mask &= AR5K_AR5210_RC_PCU | AR5K_AR5210_RC_MAC | AR5K_AR5210_RC_PHY | AR5K_AR5210_RC_DMA; ret = ar5k_register_timeout(hal, AR5K_AR5210_RC, mask, val, AH_FALSE); /* * Reset configuration register */ if ((val & AR5K_AR5210_RC_MAC) == 0) { AR5K_REG_WRITE(AR5K_AR5210_CFG, AR5K_AR5210_INIT_CFG); } return (ret);}HAL_BOOLar5k_ar5210_nic_wakeup(struct ath_hal *hal, HAL_BOOL turbo, HAL_BOOL initial){ /* * Reset and wakeup the device */ if (initial == AH_TRUE) { /* ...reset hardware */ if (ar5k_ar5210_nic_reset(hal, AR5K_AR5210_RC_PCI) == AH_FALSE) { AR5K_PRINT("failed to reset the PCI chipset\n"); return (AH_FALSE); } AR5K_DELAY(1000); } /* ...wakeup the device */ if (ar5k_ar5210_set_power(hal, HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) { AR5K_PRINT("failed to resume the AR5210 chipset\n"); return (AH_FALSE); } /* ...enable Atheros turbo mode if requested */ AR5K_REG_WRITE(AR5K_AR5210_PHY_FC, turbo == AH_TRUE ? AR5K_AR5210_PHY_FC_TURBO_MODE : 0); /* ...reset chipset */ if (ar5k_ar5210_nic_reset(hal, AR5K_AR5210_RC_CHIP) == AH_FALSE) { AR5K_PRINT("failed to reset the AR5210 chipset\n"); return (AH_FALSE); } AR5K_DELAY(1000); /* ...reset chipset and PCI device */ if (ar5k_ar5210_nic_reset(hal, AR5K_AR5210_RC_CHIP | AR5K_AR5210_RC_PCI) == AH_FALSE) { AR5K_PRINT("failed to reset the AR5210 + PCI chipset\n"); return (AH_FALSE); } AR5K_DELAY(2300); /* ...wakeup (again) */ if (ar5k_ar5210_set_power(hal, HAL_PM_AWAKE, AH_TRUE, 0) == AH_FALSE) { AR5K_PRINT("failed to resume the AR5210 (again)\n"); return (AH_FALSE); } /* ...final warm reset */ if (ar5k_ar5210_nic_reset(hal, 0) == AH_FALSE) { AR5K_PRINT("failed to warm reset the AR5210\n"); return (AH_FALSE); } return (AH_TRUE);}const HAL_RATE_TABLE *ar5k_ar5210_get_rate_table(struct ath_hal *hal, u_int mode){ switch (mode) { case HAL_MODE_11A: return (&hal->ah_rt_11a); case HAL_MODE_TURBO: return (&hal->ah_rt_turbo); case HAL_MODE_11B: case HAL_MODE_11G: default: return (NULL); } return (NULL);}void /*Ported*/ar5k_ar5210_detach(struct ath_hal *hal){ /* * Free HAL structure, assume interrupts are down */ free(hal, M_DEVBUF);}HAL_BOOL /*New*/ar5k_ar5210_phy_disable(struct ath_hal *hal){ AR5K_TRACE; /*Just a try M.F.*/ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE); return AH_TRUE;}HAL_BOOLar5k_ar5210_reset(struct ath_hal *hal, HAL_OPMODE op_mode, HAL_CHANNEL *channel, HAL_BOOL change_channel, HAL_STATUS *status){ int i; /* Not used, keep for HAL compatibility */ *status = HAL_OK; if (ar5k_ar5210_nic_wakeup(hal, channel->c_channel_flags & IEEE80211_CHAN_T ? AH_TRUE : AH_FALSE, AH_FALSE) == AH_FALSE) return (AH_FALSE); /* * Initialize operating mode */ hal->ah_op_mode = op_mode; ar5k_ar5210_set_opmode(hal); /* * Write initial mode register settings */ for (i = 0; i < AR5K_ELEMENTS(ar5210_ini); i++) { if (change_channel == AH_TRUE && ar5210_ini[i].ini_register >= AR5K_AR5210_PCU_MIN && ar5210_ini[i].ini_register <= AR5K_AR5210_PCU_MAX) continue; switch (ar5210_ini[i].ini_mode) { case AR5K_INI_READ: /* Cleared on read */ AR5K_REG_READ(ar5210_ini[i].ini_register); break; case AR5K_INI_WRITE: default: AR5K_REG_WRITE(ar5210_ini[i].ini_register, ar5210_ini[i].ini_value); } } AR5K_DELAY(1000); /* * Set channel and calibrate the PHY */ /* Disable phy and wait */ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_DISABLE); AR5K_DELAY(1000); if (ar5k_channel(hal, channel) == AH_FALSE) return (AH_FALSE); /* * Activate phy and wait */ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE); AR5K_DELAY(1000); ar5k_ar5210_do_calibrate(hal, channel); if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE) return (AH_FALSE); /* * Set RF kill flags if supported by the device (read from the EEPROM) */ if (AR5K_EEPROM_HDR_RFKILL(hal->ah_capabilities.cap_eeprom.ee_header)) { ar5k_ar5210_set_gpio_input(hal, 0); if ((hal->ah_gpio[0] = ar5k_ar5210_get_gpio(hal, 0)) == 0) { ar5k_ar5210_set_gpio_intr(hal, 0, 1); } else { ar5k_ar5210_set_gpio_intr(hal, 0, 0); } } /* * Reset queues and start beacon timers at the end of the reset routine */ for (i = 0; i < hal->ah_capabilities.cap_queues.q_tx_num; i++) { if (ar5k_ar5210_reset_tx_queue(hal, i) == AH_FALSE) { AR5K_PRINTF("failed to reset TX queue #%d\n", i); return (AH_FALSE); } } AR5K_REG_DISABLE_BITS(AR5K_AR5210_BEACON, AR5K_AR5210_BEACON_EN | AR5K_AR5210_BEACON_RESET_TSF); return (AH_TRUE);}void /*Unimplemented*/ar5k_ar5210_set_def_antenna(struct ath_hal *hal, u_int ant){ AR5K_TRACE; return;}u_int/*Unimplemented*/ar5k_ar5210_get_def_antenna(struct ath_hal *hal){ AR5K_TRACE; return 0;}voidar5k_ar5210_set_opmode(struct ath_hal *hal){ u_int32_t pcu_reg, beacon_reg, low_id, high_id; beacon_reg = 0; pcu_reg = 0; switch (hal->ah_op_mode) { case IEEE80211_M_STA: pcu_reg |= AR5K_AR5210_STA_ID1_NO_PSPOLL | AR5K_AR5210_STA_ID1_DESC_ANTENNA | AR5K_AR5210_STA_ID1_PWR_SV; break; case IEEE80211_M_IBSS: pcu_reg |= AR5K_AR5210_STA_ID1_ADHOC | AR5K_AR5210_STA_ID1_NO_PSPOLL | AR5K_AR5210_STA_ID1_DESC_ANTENNA; beacon_reg |= AR5K_AR5210_BCR_ADHOC; break; case IEEE80211_M_HOSTAP: pcu_reg |= AR5K_AR5210_STA_ID1_AP | AR5K_AR5210_STA_ID1_NO_PSPOLL | AR5K_AR5210_STA_ID1_DESC_ANTENNA; beacon_reg |= AR5K_AR5210_BCR_AP; break; case IEEE80211_M_MONITOR: pcu_reg |= AR5K_AR5210_STA_ID1_NO_PSPOLL; break; default: return; } /* * Set PCU and BCR registers */ bcopy(&(hal->ah_sta_id[0]), &low_id, 4); bcopy(&(hal->ah_sta_id[4]), &high_id, 2); AR5K_REG_WRITE(AR5K_AR5210_STA_ID0, low_id); AR5K_REG_WRITE(AR5K_AR5210_STA_ID1, pcu_reg | high_id); AR5K_REG_WRITE(AR5K_AR5210_BCR, beacon_reg); return;}void /*New*/ar5k_ar5210_set_pcu_config(struct ath_hal *hal){ AR5K_TRACE; ar5k_ar5210_set_opmode(hal); return;}HAL_BOOLar5k_ar5210_calibrate(struct ath_hal *hal, HAL_CHANNEL *channel){ HAL_BOOL ret = AH_TRUE; u_int32_t phy_sig, phy_agc, phy_sat, beacon;#define AGC_DISABLE { \ AR5K_REG_ENABLE_BITS(AR5K_AR5210_PHY_AGC, \ AR5K_AR5210_PHY_AGC_DISABLE); \ AR5K_DELAY(10); \}#define AGC_ENABLE { \ AR5K_REG_DISABLE_BITS(AR5K_AR5210_PHY_AGC, \ AR5K_AR5210_PHY_AGC_DISABLE); \} /* * Disable beacons and RX/TX queues, wait */ AR5K_REG_ENABLE_BITS(AR5K_AR5210_DIAG_SW, AR5K_AR5210_DIAG_SW_DIS_TX | AR5K_AR5210_DIAG_SW_DIS_RX); beacon = AR5K_REG_READ(AR5K_AR5210_BEACON); AR5K_REG_WRITE(AR5K_AR5210_BEACON, beacon & ~AR5K_AR5210_BEACON_EN); AR5K_DELAY(2300); /* * Set the channel (with AGC turned off) */ AGC_DISABLE; ret = ar5k_channel(hal, channel); /* * Activate PHY and wait */ AR5K_REG_WRITE(AR5K_AR5210_PHY_ACTIVE, AR5K_AR5210_PHY_ENABLE); AR5K_DELAY(1000); AGC_ENABLE; if (ret == AH_FALSE) return (ret); /* * Calibrate the radio chip */ /* Remember normal state */ phy_sig = AR5K_REG_READ(AR5K_AR5210_PHY_SIG); phy_agc = AR5K_REG_READ(AR5K_AR5210_PHY_AGCCOARSE); phy_sat = AR5K_REG_READ(AR5K_AR5210_PHY_ADCSAT); /* Update radio registers */ AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG, (phy_sig & ~(AR5K_AR5210_PHY_SIG_FIRPWR)) | AR5K_REG_SM(-1, AR5K_AR5210_PHY_SIG_FIRPWR)); AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE, (phy_agc & ~(AR5K_AR5210_PHY_AGCCOARSE_HI | AR5K_AR5210_PHY_AGCCOARSE_LO)) | AR5K_REG_SM(-1, AR5K_AR5210_PHY_AGCCOARSE_HI) | AR5K_REG_SM(-127, AR5K_AR5210_PHY_AGCCOARSE_LO)); AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT, (phy_sat & ~(AR5K_AR5210_PHY_ADCSAT_ICNT | AR5K_AR5210_PHY_ADCSAT_THR)) | AR5K_REG_SM(2, AR5K_AR5210_PHY_ADCSAT_ICNT) | AR5K_REG_SM(12, AR5K_AR5210_PHY_ADCSAT_THR)); AR5K_DELAY(20); AGC_DISABLE; AR5K_REG_WRITE(AR5K_AR5210_PHY_RFSTG, AR5K_AR5210_PHY_RFSTG_DISABLE); AGC_ENABLE; AR5K_DELAY(1000); ret = ar5k_ar5210_do_calibrate(hal, channel); /* Reset to normal state */ AR5K_REG_WRITE(AR5K_AR5210_PHY_SIG, phy_sig); AR5K_REG_WRITE(AR5K_AR5210_PHY_AGCCOARSE, phy_agc); AR5K_REG_WRITE(AR5K_AR5210_PHY_ADCSAT, phy_sat); if (ret == AH_FALSE) return (AH_FALSE); if (ar5k_ar5210_noise_floor(hal, channel) == AH_FALSE) return (AH_FALSE); /* * Re-enable RX/TX and beacons
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -