📄 ath_info.c.svn-base
字号:
/* -*- linux-c -*- *//*- * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com> * Copyright (c) 2007 Joerg Albert <jal2 *at* gmx.de> * * This program is free software you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY, without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *//* Try accepting 64-bit device address even with 32-bit userspace */#define _FILE_OFFSET_BITS 64#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <fcntl.h>#include <sys/mman.h>#include <endian.h>#include <byteswap.h>#include "eeprom.h"#undef ARRAY_SIZE#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))#define dbg(...) \do { \ if (verbose) \ printf("#DBG %s: ", __func__); \ printf(__VA_ARGS__); \ printf("\n"); \ } while (0)#define err(...) \do { \ printf("#ERR %s: ", __func__); \ printf(__VA_ARGS__); \ printf("\n"); \ } while (0)#define AR5K_PCI_MEM_SIZE 0x10000#define AR5K_NUM_GPIO 6#define AR5K_GPIOCR 0x4014 /* Register Address */#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n *//* * GPIO (General Purpose Input/Output) data output register */#define AR5K_GPIODO 0x4018/* * GPIO (General Purpose Input/Output) data input register */#define AR5K_GPIODI 0x401cstruct ath5k_srev_name { const char *sr_name; u_int8_t sr_val;};#define AR5K_SREV_UNKNOWN 0xff#define AR5K_SREV_AR5210 0x00 /* Crete */#define AR5K_SREV_AR5311 0x10 /* Maui 1 */#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */#define AR5K_SREV_AR5311B 0x30 /* Spirit */#define AR5K_SREV_AR5211 0x40 /* Oahu */#define AR5K_SREV_AR5212 0x50 /* Venice */#define AR5K_SREV_AR5213 0x55 /* ??? */#define AR5K_SREV_AR5213A 0x59 /* Hainan */#define AR5K_SREV_AR2413 0x78 /* Griffin lite */#define AR5K_SREV_AR2414 0x70 /* Griffin */#define AR5K_SREV_AR5424 0x90 /* Condor */#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */#define AR5K_SREV_AR5414 0xa0 /* Eagle */#define AR5K_SREV_AR2415 0xb0 /* Cobra */#define AR5K_SREV_AR5416 0xc0 /* PCI-E */#define AR5K_SREV_AR5418 0xca /* PCI-E */#define AR5K_SREV_AR2425 0xe0 /* Swan */#define AR5K_SREV_AR2417 0xf0 /* Nala */#define AR5K_SREV_RAD_5110 0x00#define AR5K_SREV_RAD_5111 0x10#define AR5K_SREV_RAD_5111A 0x15#define AR5K_SREV_RAD_2111 0x20#define AR5K_SREV_RAD_5112 0x30#define AR5K_SREV_RAD_5112A 0x35#define AR5K_SREV_RAD_5112B 0x36#define AR5K_SREV_RAD_2112 0x40#define AR5K_SREV_RAD_2112A 0x45#define AR5K_SREV_RAD_2112B 0x46#define AR5K_SREV_RAD_2413 0x50#define AR5K_SREV_RAD_5413 0x60#define AR5K_SREV_RAD_2316 0x70#define AR5K_SREV_RAD_2317 0x80#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */#define AR5K_SREV_RAD_2425 0xa2#define AR5K_SREV_RAD_5133 0xc0#define AR5K_SREV_PHY_5211 0x30#define AR5K_SREV_PHY_5212 0x41#define AR5K_SREV_PHY_2112B 0x43#define AR5K_SREV_PHY_2413 0x45#define AR5K_SREV_PHY_5413 0x61#define AR5K_SREV_PHY_2425 0x70static const struct ath5k_srev_name ath5k_mac_names[] = { { "5210", AR5K_SREV_AR5210 }, { "5311", AR5K_SREV_AR5311 }, { "5311A", AR5K_SREV_AR5311A }, { "5311B", AR5K_SREV_AR5311B }, { "5211", AR5K_SREV_AR5211 }, { "5212", AR5K_SREV_AR5212 }, { "5213", AR5K_SREV_AR5213 }, { "5213A", AR5K_SREV_AR5213A }, { "2413", AR5K_SREV_AR2413 }, { "2414", AR5K_SREV_AR2414 }, { "5424", AR5K_SREV_AR5424 }, { "5413", AR5K_SREV_AR5413 }, { "5414", AR5K_SREV_AR5414 }, { "2415", AR5K_SREV_AR2415 }, { "5416", AR5K_SREV_AR5416 }, { "5418", AR5K_SREV_AR5418 }, { "2425", AR5K_SREV_AR2425 }, { "2417", AR5K_SREV_AR2417 }, { "xxxxx", AR5K_SREV_UNKNOWN },};static const struct ath5k_srev_name ath5k_phy_names[] = { { "5110", AR5K_SREV_RAD_5110 }, { "5111", AR5K_SREV_RAD_5111 }, { "5111A", AR5K_SREV_RAD_5111A }, { "2111", AR5K_SREV_RAD_2111 }, { "5112", AR5K_SREV_RAD_5112 }, { "5112A", AR5K_SREV_RAD_5112A }, { "5112B", AR5K_SREV_RAD_5112B }, { "2112", AR5K_SREV_RAD_2112 }, { "2112A", AR5K_SREV_RAD_2112A }, { "2112B", AR5K_SREV_RAD_2112B }, { "2413", AR5K_SREV_RAD_2413 }, { "5413", AR5K_SREV_RAD_5413 }, { "2316", AR5K_SREV_RAD_2316 }, { "2317", AR5K_SREV_RAD_2317 }, { "5424", AR5K_SREV_RAD_5424 }, { "5133", AR5K_SREV_RAD_5133 }, { "xxxxx", AR5K_SREV_UNKNOWN },};/* * Silicon revision register */#define AR5K_SREV 0x4020 /* Register Address */#define AR5K_SREV_VER 0x000000f0 /* Mask for version */#define AR5K_SREV_REV 0x000000ff /* Mask for revision *//* * PHY chip revision register */#define AR5K_PHY_CHIP_ID 0x9818/* * PHY register */#define AR5K_PHY_BASE 0x9800#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))#define AR5K_PHY_SHIFT_2GHZ 0x00004007#define AR5K_PHY_SHIFT_5GHZ 0x00000007#define AR5K_RESET_CTL 0x4000 /* Register Address */#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset -5210 only */#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset (5211/5212) */#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband?) -5210 only */#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset -5210 only */#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY)/* * Sleep control register */#define AR5K_SLEEP_CTL 0x4004 /* Register Address */#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */#define AR5K_SLEEP_CTL_SLDUR_S 0#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */#define AR5K_SLEEP_CTL_SLE_S 16#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* not on 5210 */#define AR5K_PCICFG 0x4010 /* Register Address */#define AR5K_PCICFG_EEAE 0x00000001 /* EEPROM access enable [5210] */#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */#define AR5K_PCICFG_EESIZE_S 3#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status (5210) */#define AR5K_EEPROM_BASE 0x6000/* * EEPROM data register */#define AR5K_EEPROM_DATA_5211 0x6004#define AR5K_EEPROM_DATA_5210 0x6800#define AR5K_EEPROM_DATA (eeprom_access == AR5K_EEPROM_ACCESS_5210 ? \ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)/* * EEPROM command register */#define AR5K_EEPROM_CMD 0x6008 /* Register Address */#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset *//* * EEPROM status register */#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */#define AR5K_EEPROM_STATUS (eeprom_access == AR5K_EEPROM_ACCESS_5210 ? \ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful *//* * EEPROM config register (?) */#define AR5K_EEPROM_CFG 0x6010/* * Read data by masking */#define AR5K_REG_MS(_val, _flags) \ (((_val) & (_flags)) >> _flags##_S)/* * Access device registers */#if __BYTE_ORDER == __BIG_ENDIAN#define AR5K_REG_READ(_reg) \ __bswap_32(*((volatile u_int32_t *)(mem + (_reg))))#define AR5K_REG_WRITE(_reg, _val) \ (*((volatile u_int32_t *)(mem + (_reg))) = __bswap_32(_val))#else#define AR5K_REG_READ(_reg) \ (*((volatile u_int32_t *)(mem + (_reg))))#define AR5K_REG_WRITE(_reg, _val) \ (*((volatile u_int32_t *)(mem + (_reg))) = (_val))#endif#define AR5K_REG_ENABLE_BITS(_reg, _flags) \ AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) | (_flags))#define AR5K_REG_DISABLE_BITS(_reg, _flags) \ AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) & ~(_flags))#define AR5K_TUNE_REGISTER_TIMEOUT 20000#define AR5K_EEPROM_READ(_o, _v) do { \ if ((ret = ath5k_hw_eeprom_read((_o), &(_v))) != 0) \ return (ret); \} while (0)/* Names for EEPROM fields */struct eeprom_entry { const char *name; int addr;};static const struct eeprom_entry eeprom_addr[] = { {"pci_dev_id", 0}, {"pci_vendor_id", 1}, {"pci_class", 2}, {"pci_rev_id", 3}, {"pci_subsys_dev_id", 7}, {"pci_subsys_vendor_id", 8}, {"regdomain", AR5K_EEPROM_REG_DOMAIN},};/* Command line settings */static int force_write = 0;static int verbose = 0;/* Global device characteristics */static enum { AR5K_EEPROM_ACCESS_5210, AR5K_EEPROM_ACCESS_5211, AR5K_EEPROM_ACCESS_5416} eeprom_access;static unsigned int eeprom_size;static int mac_revision;static void *mem;/* forward decl. */static void usage(const char *n);static u_int32_t ath5k_hw_bitswap(u_int32_t val, u_int bits){ u_int32_t retval = 0, bit, i; for (i = 0; i < bits; i++) { bit = (val >> i) & 1; retval = (retval << 1) | bit; } return (retval);}/* * Get the PHY Chip revision */static u_int16_t ath5k_hw_radio_revision(u_int8_t chip){ int i; u_int32_t srev; u_int16_t ret; /* * Set the radio chip access register */ switch (chip) { case 0: AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_2GHZ); break; case 1: AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_5GHZ); break; default: return (0); } usleep(2000); /* ...wait until PHY is ready and read the selected radio revision */ AR5K_REG_WRITE(AR5K_PHY(0x34), 0x00001c16); for (i = 0; i < 8; i++) AR5K_REG_WRITE(AR5K_PHY(0x20), 0x00010000); if (mac_revision == AR5K_SREV_AR5210) { srev = AR5K_REG_READ(AR5K_PHY(256) >> 28) & 0xf; ret = (u_int16_t)ath5k_hw_bitswap(srev, 4) + 1; } else { srev = (AR5K_REG_READ(AR5K_PHY(0x100)) >> 24) & 0xff; ret = (u_int16_t)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | ((srev & 0x0f) << 4), 8); } /* Reset to the 5GHz mode */ AR5K_REG_WRITE(AR5K_PHY(0), AR5K_PHY_SHIFT_5GHZ); return (ret);}/* * Write to EEPROM */static int ath5k_hw_eeprom_write(u_int32_t offset, u_int16_t data){ u_int32_t status, timeout; /* * Initialize EEPROM access */ if (eeprom_access == AR5K_EEPROM_ACCESS_5210) { AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE); /* data to write */ (void)AR5K_REG_WRITE(AR5K_EEPROM_BASE + (4 * offset), data); } else { /* not 5210 */ /* reset EEPROM access */ AR5K_REG_WRITE(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_RESET); usleep(5); AR5K_REG_WRITE(AR5K_EEPROM_DATA, data); /* set offset in EEPROM to write to */ AR5K_REG_WRITE(AR5K_EEPROM_BASE, offset); usleep(5); /* issue write command */ AR5K_REG_WRITE(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_WRITE); } for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { status = AR5K_REG_READ(AR5K_EEPROM_STATUS); if (status & AR5K_EEPROM_STAT_WRDONE) { if (status & AR5K_EEPROM_STAT_WRERR) { err("EEPROM write access to 0x%04x failed", offset); return 1; } return 0; } usleep(15); } return 1;}/* * Read from EEPROM */static int ath5k_hw_eeprom_read(u_int32_t offset, u_int16_t *data){ u_int32_t status, timeout; /* * Initialize EEPROM access */ if (eeprom_access == AR5K_EEPROM_ACCESS_5210) { AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE); (void)AR5K_REG_READ(AR5K_EEPROM_BASE + (4 * offset)); } else { AR5K_REG_WRITE(AR5K_EEPROM_BASE, offset); AR5K_REG_ENABLE_BITS(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_READ); } for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { status = AR5K_REG_READ(AR5K_EEPROM_STATUS); if (status & AR5K_EEPROM_STAT_RDDONE) { if (status & AR5K_EEPROM_STAT_RDERR) return 1; *data = (u_int16_t) (AR5K_REG_READ(AR5K_EEPROM_DATA) & 0xffff); return (0); } usleep(15); } return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -