📄 ar5xxx.c
字号:
/* $OpenBSD: ar5xxx.c,v 1.32 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 Atheros Wireless LAN devices. * (Please have a look at ar5xxx.h for further information) */#include "ah_devid.h"#include "ar5xxx.h"/* * Per chipset attach functions */extern ar5k_attach_t ar5k_ar5210_attach;extern ar5k_attach_t ar5k_ar5211_attach;extern ar5k_attach_t ar5k_ar5212_attach;static const struct { u_int16_t vendor; u_int16_t device; ar5k_attach_t (*attach);} ar5k_known_products[] = { /* * From pcidevs_data.h */ { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210, ar5k_ar5210_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_AP, ar5k_ar5210_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5210_DEFAULT, ar5k_ar5210_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_DEFAULT, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5311, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_FPGA11B, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5211_LEGACY, ar5k_ar5211_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_DEFAULT, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_FPGA, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_IBM, ar5k_ar5212_attach }, { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRDAG675, ar5k_ar5212_attach }, { PCI_VENDOR_3COM2, PCI_PRODUCT_3COM2_3CRPAG175, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_REV2, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_REV7, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_REV8, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0014, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0015, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0016, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0017, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0018, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR5212_0019, ar5k_ar5212_attach }, { PCI_VENDOR_ATHEROS, PCI_PRODUCT_ATHEROS_AR2413, ar5k_ar5212_attach }};static const HAL_RATE_TABLE ar5k_rt_11a = AR5K_RATES_11A;static const HAL_RATE_TABLE ar5k_rt_11b = AR5K_RATES_11B;static const HAL_RATE_TABLE ar5k_rt_11g = AR5K_RATES_11G;static const HAL_RATE_TABLE ar5k_rt_turbo = AR5K_RATES_TURBO;static const HAL_RATE_TABLE ar5k_rt_xr = AR5K_RATES_XR;int ar5k_eeprom_read_ants(struct ath_hal *, u_int32_t *, u_int);int ar5k_eeprom_read_modes(struct ath_hal *, u_int32_t *, u_int);u_int16_t ar5k_eeprom_bin2freq(struct ath_hal *, u_int16_t, u_int);HAL_BOOL ar5k_ar5110_channel(struct ath_hal *, HAL_CHANNEL *);u_int32_t ar5k_ar5110_chan2athchan(HAL_CHANNEL *);HAL_BOOL ar5k_ar5111_channel(struct ath_hal *, HAL_CHANNEL *);HAL_BOOL ar5k_ar5111_chan2athchan(u_int, struct ar5k_athchan_2ghz *);HAL_BOOL ar5k_ar5112_channel(struct ath_hal *, HAL_CHANNEL *);HAL_BOOL ar5k_check_channel(struct ath_hal *, u_int16_t, u_int flags);HAL_BOOL ar5k_ar5111_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);HAL_BOOL ar5k_ar5112_rfregs(struct ath_hal *, HAL_CHANNEL *, u_int);u_int ar5k_rfregs_op(u_int32_t *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, HAL_BOOL);/* * Supported channels */static const structieee80211_regchannel ar5k_5ghz_channels[] = IEEE80211_CHANNELS_5GHZ;static const structieee80211_regchannel ar5k_2ghz_channels[] = IEEE80211_CHANNELS_2GHZ;/* * Initial gain optimization values */static const struct ar5k_gain_opt ar5111_gain_opt = AR5K_AR5111_GAIN_OPT;static const struct ar5k_gain_opt ar5112_gain_opt = AR5K_AR5112_GAIN_OPT;/* * Initial register for the radio chipsets */static const struct ar5k_ini_rf ar5111_rf[] = AR5K_AR5111_INI_RF;static const struct ar5k_ini_rf ar5112_rf[] = AR5K_AR5112_INI_RF;static const struct ar5k_ini_rf ar5112a_rf[] = AR5K_AR5112A_INI_RF;static const struct ar5k_ini_rfgain ar5k_rfg[] = AR5K_INI_RFGAIN;/* * Enable to overwrite the country code (use "00" for debug) */#if 0#define COUNTRYCODE "00"#endif/* * Perform a lookup if the device is supported by the HAL */const char * /*O.K.*/ath_hal_probe(u_int16_t vendor, u_int16_t device){ int i; /* * Perform a linear search on the table of supported devices */ for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) { if (vendor == ar5k_known_products[i].vendor && device == ar5k_known_products[i].device) return (""); } return (NULL);}/* * Fills in the HAL structure and initialises the device */struct ath_hal * /*O.K. -added country code + get regdomain-*/ath_hal_attach(u_int16_t device, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status){ struct ath_hal *hal = NULL; ar5k_attach_t *attach = NULL; u_int8_t mac[IEEE80211_ADDR_LEN]; int i; *status = HAL_EINVAL; /* * Call the chipset-dependent attach routine by device id */ for (i = 0; i < AR5K_ELEMENTS(ar5k_known_products); i++) { if (device == ar5k_known_products[i].device && ar5k_known_products[i].attach != NULL) attach = ar5k_known_products[i].attach; } if (attach == NULL) { *status = HAL_ENXIO; AR5K_PRINTF("device not supported: 0x%04x\n", device); return (NULL); } if ((hal = malloc(sizeof(struct ath_hal), M_DEVBUF, M_NOWAIT)) == NULL) { *status = HAL_ENOMEM; AR5K_PRINT("out of memory\n"); return (NULL); } bzero(hal, sizeof(struct ath_hal)); hal->ah_sc = sc; hal->ah_st = st; hal->ah_sh = sh; hal->ah_device = device; hal->ah_sub_vendor = 0; /* XXX unknown?! */ /* * HAL information */ /* Regulation Stuff */ hal->ah_country_code = AR5K_TUNE_CTRY; ar5k_get_regdomain(hal); hal->ah_abi = HAL_ABI_VERSION; hal->ah_op_mode = HAL_M_STA; hal->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; hal->ah_turbo = AH_FALSE; hal->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; hal->ah_imr = 0; hal->ah_atim_window = 0; hal->ah_aifs = AR5K_TUNE_AIFS; hal->ah_cw_min = AR5K_TUNE_CWMIN; hal->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; hal->ah_software_retry = AH_FALSE; hal->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY; if ((attach)(device, hal, st, sh, status) == NULL) goto failed;#ifdef AR5K_DEBUG hal->ah_dump_state(hal);#endif /* * Get card capabilities, values, ... */ if (ar5k_eeprom_init(hal) != 0) { *status = HAL_EELOCKED; AR5K_PRINT("unable to init EEPROM\n"); goto failed; } /* Get misc capabilities */ if (hal->ah_get_capabilities(hal) != AH_TRUE) { *status = HAL_EEREAD; AR5K_PRINTF("unable to get device capabilities: 0x%04x\n", device); goto failed; } /* Get MAC address */ if ((*status = ar5k_eeprom_read_mac(hal, mac)) != 0) { *status = HAL_EEBADMAC; AR5K_PRINTF("unable to read address from EEPROM: 0x%04x\n", device); goto failed; } hal->ah_set_lladdr(hal, mac); /* Get rate tables */ if (hal->ah_capabilities.cap_mode & HAL_MODE_11A) ar5k_rt_copy(&hal->ah_rt_11a, &ar5k_rt_11a); if (hal->ah_capabilities.cap_mode & HAL_MODE_11B) ar5k_rt_copy(&hal->ah_rt_11b, &ar5k_rt_11b); if (hal->ah_capabilities.cap_mode & HAL_MODE_11G) ar5k_rt_copy(&hal->ah_rt_11g, &ar5k_rt_11g); if (hal->ah_capabilities.cap_mode & HAL_MODE_TURBO) ar5k_rt_copy(&hal->ah_rt_turbo, &ar5k_rt_turbo); if (hal->ah_capabilities.cap_mode & HAL_MODE_XR) ar5k_rt_copy(&hal->ah_rt_xr, &ar5k_rt_xr); /* Initialize the gain optimization values */ if (hal->ah_radio == AR5K_AR5111) { hal->ah_gain.g_step_idx = ar5111_gain_opt.go_default; hal->ah_gain.g_step = &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx]; hal->ah_gain.g_low = 20; hal->ah_gain.g_high = 35; hal->ah_gain.g_active = 1; } else if (hal->ah_radio == AR5K_AR5112) { hal->ah_gain.g_step_idx = ar5112_gain_opt.go_default; hal->ah_gain.g_step = &ar5111_gain_opt.go_step[hal->ah_gain.g_step_idx]; hal->ah_gain.g_low = 20; hal->ah_gain.g_high = 85; hal->ah_gain.g_active = 1; } *status = HAL_OK; return (hal); failed: free(hal, M_DEVBUF); return (NULL);}u_int16_t /*O.K.*/ath_hal_computetxtime(struct ath_hal *hal, const HAL_RATE_TABLE *rates, u_int32_t frame_length, u_int16_t rate_index, HAL_BOOL short_preamble){ const HAL_RATE *rate; u_int32_t value; AR5K_ASSERT_ENTRY(rate_index, rates->rateCount); /* * Get rate by index */ rate = &rates->info[rate_index]; /* * Calculate the transmission time by operation (PHY) mode */ switch (rate->phy) { case IEEE80211_T_CCK: /* * CCK / DS mode (802.11b) */ value = AR5K_CCK_TX_TIME(rate->rateKbps, frame_length, (short_preamble && rate->shortPreamble)); break; case IEEE80211_T_OFDM: /* * Orthogonal Frequency Division Multiplexing */ if (AR5K_OFDM_NUM_BITS_PER_SYM(rate->rateKbps) == 0) return (0); value = AR5K_OFDM_TX_TIME(rate->rateKbps, frame_length); break; case IEEE80211_T_TURBO: /* * Orthogonal Frequency Division Multiplexing * Atheros "Turbo Mode" (doubled rates) */ if (AR5K_TURBO_NUM_BITS_PER_SYM(rate->rateKbps) == 0) return (0); value = AR5K_TURBO_TX_TIME(rate->rateKbps, frame_length); break; case IEEE80211_T_XR: /* * Orthogonal Frequency Division Multiplexing * Atheros "eXtended Range" (XR) */ if (AR5K_XR_NUM_BITS_PER_SYM(rate->rateKbps) == 0) return (0); value = AR5K_XR_TX_TIME(rate->rateKbps, frame_length); break; default: return (0); } return (value);}/*Following 2 functions come from net80211 M.F.*/u_intath_hal_mhz2ieee(u_int mhz, u_int flags){ return (ieee80211_mhz2ieee(mhz, flags));}u_intath_hal_ieee2mhz(u_int ieee, u_int flags){ return (ieee80211_ieee2mhz(ieee, flags));}HAL_BOOL /*O.K.*/ar5k_check_channel(struct ath_hal *hal, u_int16_t freq, u_int flags){ /* Check if the channel is in our supported range */ if (flags & IEEE80211_CHAN_2GHZ) { if ((freq >= hal->ah_capabilities.cap_range.range_2ghz_min) && (freq <= hal->ah_capabilities.cap_range.range_2ghz_max)) return (AH_TRUE); } else if (flags & IEEE80211_CHAN_5GHZ) { if ((freq >= hal->ah_capabilities.cap_range.range_5ghz_min) && (freq <= hal->ah_capabilities.cap_range.range_5ghz_max)) return (AH_TRUE); } return (AH_FALSE);}HAL_BOOL /*Ported, added SUPERCHANNEL & country code + FIX in debug mode*/ath_hal_init_channels(struct ath_hal *hal, HAL_CHANNEL *channels, u_int max_channels, u_int *channels_size, HAL_CTRY_CODE country, u_int16_t mode, HAL_BOOL outdoor, HAL_BOOL extended){ u_int i, c; u_int32_t domain_current; u_int domain_5ghz, domain_2ghz; HAL_CHANNEL *all_channels; HAL_CTRY_CODE country_current; if ((all_channels = malloc(sizeof(HAL_CHANNEL) * max_channels, M_TEMP, M_NOWAIT)) == NULL) return (AH_FALSE); i = c = 0; domain_current = hal->ah_regdomain; hal->ah_country_code = country; country_current = hal->ah_country_code; /* * In debugging mode, enable all channels supported by the chipset */ if (domain_current == DMN_DEFAULT || SUPERCHANNEL == 1) { int min, max, freq; u_int flags; min = ath_hal_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MIN, IEEE80211_CHAN_2GHZ); max = ath_hal_mhz2ieee(IEEE80211_CHANNELS_2GHZ_MAX, IEEE80211_CHAN_2GHZ); flags = CHANNEL_B | CHANNEL_TG | (hal->ah_version == AR5K_AR5211 ? CHANNEL_PUREG : CHANNEL_G); debugchan: for (i = min; i <= max && c < max_channels; i++) { freq = ath_hal_ieee2mhz(i, flags); if (ar5k_check_channel(hal, freq, flags) == AH_FALSE) continue; all_channels[c].c_channel = freq; all_channels[c++].c_channel_flags = flags; } /* If is there to protect from infinite loop */ if (flags & IEEE80211_CHAN_2GHZ) {/* ath_hal_mhz2ieee returns 1 for IEEE80211_CHANNELS_5GHZ_MIN for loop starts from 1 and all channels are marked as 5GHz M.F.*/// min = ath_hal_mhz2ieee(IEEE80211_CHANNELS_5GHZ_MIN,// IEEE80211_CHAN_5GHZ);/* Continue from where we stoped, skip last 2GHz channel */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -