mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			2353 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			2353 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/tools/ath_info.c
 | |
| +++ b/tools/ath_info.c
 | |
| @@ -16,78 +16,8 @@
 | |
|   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
|   */
 | |
|  
 | |
| -/* So here is how it works:
 | |
| - *
 | |
| - * First compile...
 | |
| - *
 | |
| - * gcc ath_info.c -o ath_info
 | |
| - *
 | |
| - * then find card's physical address
 | |
| - *
 | |
| - * lspci -v
 | |
| - *
 | |
| - * 02:02.0 Ethernet controller: Atheros Communications, Inc. AR5212 802.11abg NIC (rev 01)
 | |
| - *         Subsystem: Fujitsu Limited. Unknown device 1234
 | |
| - *         Flags: bus master, medium devsel, latency 168, IRQ 23
 | |
| - *         Memory at c2000000 (32-bit, non-prefetchable) [size=64K]
 | |
| - *         Capabilities: [44] Power Management version 2
 | |
| - *
 | |
| - * address here is 0xc2000000
 | |
| - *
 | |
| - * load madwifi-ng or madwifi-old if not already loaded (be sure the
 | |
| - * interface is down!)
 | |
| - *
 | |
| - * modprobe ath_pci
 | |
| - *
 | |
| - * OR
 | |
| - *
 | |
| - * call:
 | |
| - * setpci -s 02:02.0 command=0x41f cache_line_size=0x10
 | |
| - *
 | |
| - * to enable access to the PCI device.
 | |
| - *
 | |
| - * and we run the thing...
 | |
| - *
 | |
| - * ./ath_info 0xc2000000
 | |
| - *
 | |
| - * In order to change the regdomain to 0, call:
 | |
| - *
 | |
| - * ./ath_info -w 0xc2000000 regdomain 0
 | |
| - *
 | |
| - * to change any PCI ID value, say:
 | |
| - *
 | |
| - * ./ath_info -w 0xc2000000 <name> X
 | |
| - *
 | |
| - * with <name> ::= pci_dev_id | pci_vendor_id | pci_class |
 | |
| - *                 pci_subsys_dev_id | pci_subsys_vendor_id
 | |
| - *
 | |
| - * With newer chipsets (>= AR5004x, i.e. MAC >= AR5213), Atheros introduced
 | |
| - * write protection on the EEPROM. On a GIGABYTE GN-WI01HT you can set GPIO 4
 | |
| - * to low to be able to write the EEPROM. This depends highly on the PCB layout,
 | |
| - * so there may be different GPIO used.
 | |
| - * This program currently sets GPIO 4 to low for a MAC >= AR5213, but you can
 | |
| - * override this with the -g option:
 | |
| - *
 | |
| - * ./ath_info -g 5:0 -w 0xc2000000 regdomain X
 | |
| - *
 | |
| - * would set GPIO 5 to low (and wouldn't touch GPIO 4). -g can be given several times.
 | |
| - *
 | |
| - * The write function is currently not tested with 5210 devices.
 | |
| - *
 | |
| - * Use at your own risk, entering a false device address will have really
 | |
| - * nasty results!
 | |
| - *
 | |
| - * Writing wrong values to the PCI id fields may prevent the driver from
 | |
| - * detecting the card!
 | |
| - *
 | |
| - * Transmitting on illegal frequencies may violate state laws. Stick to the local
 | |
| - * regulations!
 | |
| - *
 | |
| - * DISCLAIMER:
 | |
| - * The authors are in no case responsible for damaged hardware or violation of
 | |
| - * local laws by operating modified hardware.
 | |
| - *
 | |
| - */
 | |
| +/* Try accepting 64-bit device address even with 32-bit userspace */
 | |
| +#define _FILE_OFFSET_BITS 64
 | |
|  
 | |
|  #include <stdio.h>
 | |
|  #include <stdlib.h>
 | |
| @@ -130,109 +60,103 @@ fprintf(stderr, "#ERR %s: " fmt "\n", __
 | |
|   */
 | |
|  #define AR5K_GPIODI	0x401c
 | |
|  
 | |
| -/*
 | |
| - * Common silicon revision/version values
 | |
| - */
 | |
| -enum ath5k_srev_type {
 | |
| -	AR5K_VERSION_VER,
 | |
| -	AR5K_VERSION_REV,
 | |
| -	AR5K_VERSION_RAD,
 | |
| -};
 | |
| -
 | |
|  struct ath5k_srev_name {
 | |
|  	const char *sr_name;
 | |
| -	enum ath5k_srev_type sr_type;
 | |
| -	u_int sr_val;
 | |
| +	u_int8_t sr_val;
 | |
|  };
 | |
|  
 | |
| -#define AR5K_SREV_UNKNOWN	0xffff
 | |
| -
 | |
|  /* Known MAC revision numbers */
 | |
| -#define AR5K_SREV_VER_AR5210	0x00
 | |
| -#define AR5K_SREV_VER_AR5311	0x10
 | |
| -#define AR5K_SREV_VER_AR5311A	0x20
 | |
| -#define AR5K_SREV_VER_AR5311B	0x30
 | |
| -#define AR5K_SREV_VER_AR5211	0x40
 | |
| -#define AR5K_SREV_VER_AR5212	0x50
 | |
| -#define AR5K_SREV_VER_AR5213	0x55
 | |
| -#define AR5K_SREV_VER_AR5213A	0x59
 | |
| -#define	AR5K_SREV_VER_AR2424	0xa0
 | |
| -#define	AR5K_SREV_VER_AR5424	0xa3
 | |
| -#define	AR5K_SREV_VER_AR5413	0xa4
 | |
| -#define AR5K_SREV_VER_AR5414	0xa5
 | |
| -#define	AR5K_SREV_VER_AR5416	0xc0
 | |
| -#define	AR5K_SREV_VER_AR5418	0xca
 | |
| -#define	AR5K_SREV_VER_AR2425	0xe0
 | |
| -
 | |
| -/* Known PHY revision nymbers */
 | |
| -#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_2112	0x40
 | |
| -#define AR5K_SREV_RAD_2112A	0x45
 | |
| -#define AR5K_SREV_RAD_SC1	0x63	/* Found on 5413/5414 */
 | |
| -#define	AR5K_SREV_RAD_SC2	0xa2	/* Found on 2424/5424 */
 | |
| -#define	AR5K_SREV_RAD_5133	0xc0	/* MIMO found on 5418 */
 | |
| -
 | |
| -static const struct ath5k_srev_name ath5k_srev_names[] = {
 | |
| -	{"5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210},
 | |
| -	{"5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311},
 | |
| -	{"5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A},
 | |
| -	{"5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B},
 | |
| -	{"5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211},
 | |
| -	{"5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212},
 | |
| -	{"5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213},
 | |
| -	{"5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A},
 | |
| -	{"2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424},
 | |
| -	{"5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424},
 | |
| -	{"5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413},
 | |
| -	{"5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414},
 | |
| -	{"5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416},
 | |
| -	{"5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418},
 | |
| -	{"2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425},
 | |
| -	{"xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN},
 | |
| -	{"5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110},
 | |
| -	{"5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111},
 | |
| -	{"2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111},
 | |
| -	{"5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112},
 | |
| -	{"5112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A},
 | |
| -	{"2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112},
 | |
| -	{"2112a", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A},
 | |
| -	{"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1},
 | |
| -	{"SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2},
 | |
| -	{"5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133},
 | |
| -	{"xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN},
 | |
| +#define AR5K_SREV_MAC_AR5210	0x00
 | |
| +#define AR5K_SREV_MAC_AR5311	0x10
 | |
| +#define AR5K_SREV_MAC_AR5311A	0x20
 | |
| +#define AR5K_SREV_MAC_AR5311B	0x30
 | |
| +#define AR5K_SREV_MAC_AR5211	0x40
 | |
| +#define AR5K_SREV_MAC_AR5212	0x50
 | |
| +#define AR5K_SREV_MAC_AR5213	0x55
 | |
| +#define AR5K_SREV_MAC_AR5213A	0x59
 | |
| +#define AR5K_SREV_MAC_AR5513	0x61
 | |
| +#define AR5K_SREV_MAC_AR2413	0x78
 | |
| +#define AR5K_SREV_MAC_AR2414	0x79
 | |
| +#define AR5K_SREV_MAC_AR2424	0xa0
 | |
| +#define AR5K_SREV_MAC_AR5424	0xa3
 | |
| +#define AR5K_SREV_MAC_AR5413	0xa4
 | |
| +#define AR5K_SREV_MAC_AR5414	0xa5
 | |
| +#define AR5K_SREV_MAC_AR5416	0xc0
 | |
| +#define AR5K_SREV_MAC_AR5418	0xca
 | |
| +#define AR5K_SREV_MAC_AR2425	0xe2
 | |
| +
 | |
| +/* Known PHY revision numbers */
 | |
| +#define AR5K_SREV_PHY_5110	0x00
 | |
| +#define AR5K_SREV_PHY_5111	0x10
 | |
| +#define AR5K_SREV_PHY_5111A	0x15
 | |
| +#define AR5K_SREV_PHY_2111	0x20
 | |
| +#define AR5K_SREV_PHY_5112	0x30
 | |
| +#define AR5K_SREV_PHY_5112A	0x35
 | |
| +#define AR5K_SREV_PHY_2112	0x40
 | |
| +#define AR5K_SREV_PHY_2112A	0x45
 | |
| +#define AR5K_SREV_PHY_SC0	0x56	/* Found on 2413/2414 */
 | |
| +#define AR5K_SREV_PHY_SC1	0x63	/* Found on 5413/5414 */
 | |
| +#define AR5K_SREV_PHY_SC2	0xa2	/* Found on 2424/5424 */
 | |
| +#define AR5K_SREV_PHY_5133	0xc0	/* MIMO found on 5418 */
 | |
| +
 | |
| +static const struct ath5k_srev_name ath5k_mac_names[] = {
 | |
| +	{"5210", AR5K_SREV_MAC_AR5210},
 | |
| +	{"5311", AR5K_SREV_MAC_AR5311},
 | |
| +	{"5311A", AR5K_SREV_MAC_AR5311A},
 | |
| +	{"5311B", AR5K_SREV_MAC_AR5311B},
 | |
| +	{"5211", AR5K_SREV_MAC_AR5211},
 | |
| +	{"5212", AR5K_SREV_MAC_AR5212},
 | |
| +	{"5213", AR5K_SREV_MAC_AR5213},
 | |
| +	{"5213A", AR5K_SREV_MAC_AR5213A},
 | |
| +	{"2413", AR5K_SREV_MAC_AR2413},
 | |
| +	{"2414", AR5K_SREV_MAC_AR2414},
 | |
| +	{"2424", AR5K_SREV_MAC_AR2424},
 | |
| +	{"5424", AR5K_SREV_MAC_AR5424},
 | |
| +	{"5413", AR5K_SREV_MAC_AR5413},
 | |
| +	{"5414", AR5K_SREV_MAC_AR5414},
 | |
| +	{"5416", AR5K_SREV_MAC_AR5416},
 | |
| +	{"5418", AR5K_SREV_MAC_AR5418},
 | |
| +	{"2425", AR5K_SREV_MAC_AR2425},
 | |
| +};
 | |
| +
 | |
| +static const struct ath5k_srev_name ath5k_phy_names[] = {
 | |
| +	{"5110", AR5K_SREV_PHY_5110},
 | |
| +	{"5111", AR5K_SREV_PHY_5111},
 | |
| +	{"2111", AR5K_SREV_PHY_2111},
 | |
| +	{"5112", AR5K_SREV_PHY_5112},
 | |
| +	{"5112A", AR5K_SREV_PHY_5112A},
 | |
| +	{"2112", AR5K_SREV_PHY_2112},
 | |
| +	{"2112A", AR5K_SREV_PHY_2112A},
 | |
| +	{"SChip", AR5K_SREV_PHY_SC0},
 | |
| +	{"SChip", AR5K_SREV_PHY_SC1},
 | |
| +	{"SChip", AR5K_SREV_PHY_SC2},
 | |
| +	{"5133", AR5K_SREV_PHY_5133},
 | |
|  };
 | |
|  
 | |
|  /*
 | |
|   * Silicon revision register
 | |
|   */
 | |
|  #define AR5K_SREV		0x4020	/* Register Address */
 | |
| -#define AR5K_SREV_REV		0x0000000f	/* Mask for revision */
 | |
| -#define AR5K_SREV_REV_S		0
 | |
| -#define AR5K_SREV_VER		0x000000ff	/* Mask for version */
 | |
| -#define AR5K_SREV_VER_S		4
 | |
| +#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
 | |
| +#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_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_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) */
 | |
| @@ -253,7 +177,7 @@ static const struct ath5k_srev_name ath5
 | |
|  #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_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
 | |
| @@ -264,26 +188,118 @@ static const struct ath5k_srev_name ath5
 | |
|  
 | |
|  #define AR5K_PCICFG_SPWR_DN		0x00010000	/* Mask for power status (5210) */
 | |
|  
 | |
| -#define AR5K_EEPROM_BASE		0x6000
 | |
| +#define AR5K_EEPROM_BASE	0x6000
 | |
|  
 | |
| -#define AR5K_EEPROM_MAGIC		0x003d	/* Offset for EEPROM Magic number */
 | |
| +/*
 | |
| + * Common AR5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
 | |
| + */
 | |
| +#define AR5K_EEPROM_MAGIC		0x003d	/* EEPROM Magic number */
 | |
|  #define AR5K_EEPROM_MAGIC_VALUE		0x5aa5	/* Default - found on EEPROM */
 | |
|  #define AR5K_EEPROM_MAGIC_5212		0x0000145c	/* 5212 */
 | |
|  #define AR5K_EEPROM_MAGIC_5211		0x0000145b	/* 5211 */
 | |
|  #define AR5K_EEPROM_MAGIC_5210		0x0000145a	/* 5210 */
 | |
|  
 | |
| +#define AR5K_EEPROM_PROTECT		0x003f	/* EEPROM protect status */
 | |
| +#define AR5K_EEPROM_PROTECT_RD_0_31	0x0001	/* Read protection bit for offsets 0x0 - 0x1f */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_0_31	0x0002	/* Write protection bit for offsets 0x0 - 0x1f */
 | |
| +#define AR5K_EEPROM_PROTECT_RD_32_63	0x0004	/* 0x20 - 0x3f */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_32_63	0x0008
 | |
| +#define AR5K_EEPROM_PROTECT_RD_64_127	0x0010	/* 0x40 - 0x7f */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_64_127	0x0020
 | |
| +#define AR5K_EEPROM_PROTECT_RD_128_191	0x0040	/* 0x80 - 0xbf (regdom) */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_128_191	0x0080
 | |
| +#define AR5K_EEPROM_PROTECT_RD_192_207	0x0100	/* 0xc0 - 0xcf */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_192_207	0x0200
 | |
| +#define AR5K_EEPROM_PROTECT_RD_208_223	0x0400	/* 0xd0 - 0xdf */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_208_223	0x0800
 | |
| +#define AR5K_EEPROM_PROTECT_RD_224_239	0x1000	/* 0xe0 - 0xef */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_224_239	0x2000
 | |
| +#define AR5K_EEPROM_PROTECT_RD_240_255	0x4000	/* 0xf0 - 0xff */
 | |
| +#define AR5K_EEPROM_PROTECT_WR_240_255	0x8000
 | |
| +#define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* EEPROM regdom */
 | |
| +#define AR5K_EEPROM_INFO_BASE		0x00c0	/* EEPROM header */
 | |
| +#define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
 | |
| +#define AR5K_EEPROM_INFO_CKSUM		0xffff
 | |
| +#define AR5K_EEPROM_INFO(_n)		(AR5K_EEPROM_INFO_BASE + (_n))
 | |
| +
 | |
| +#define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */
 | |
| +#define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */
 | |
| +#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2GHz (AR5211_rfregs) */
 | |
| +#define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */
 | |
| +#define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
 | |
| +#define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
 | |
| +#define AR5K_EEPROM_VERSION_4_0		0x4000	/* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
 | |
| +#define AR5K_EEPROM_VERSION_4_1		0x4001	/* has ee_margin_tx_rx (eeprom_init) */
 | |
| +#define AR5K_EEPROM_VERSION_4_2		0x4002	/* has ee_cck_ofdm_gain_delta (eeprom_init) */
 | |
| +#define AR5K_EEPROM_VERSION_4_3		0x4003
 | |
| +#define AR5K_EEPROM_VERSION_4_4		0x4004
 | |
| +#define AR5K_EEPROM_VERSION_4_5		0x4005
 | |
| +#define AR5K_EEPROM_VERSION_4_6		0x4006	/* has ee_scaled_cck_delta */
 | |
| +#define AR5K_EEPROM_VERSION_4_7		0x3007
 | |
| +
 | |
| +#define AR5K_EEPROM_MODE_11A		0
 | |
| +#define AR5K_EEPROM_MODE_11B		1
 | |
| +#define AR5K_EEPROM_MODE_11G		2
 | |
| +
 | |
| +#define AR5K_EEPROM_HDR			AR5K_EEPROM_INFO(2)	/* Header that contains the device caps */
 | |
| +#define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
 | |
| +#define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
 | |
| +#define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
 | |
| +#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2GHz (?) */
 | |
| +#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for a/XR mode (eeprom_init) */
 | |
| +#define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)
 | |
| +#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5GHz (?) */
 | |
| +#define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
 | |
| +
 | |
| +/* Misc values available since EEPROM 4.0 */
 | |
| +#define AR5K_EEPROM_MISC0		AR5K_EEPROM_INFO(4)
 | |
| +#define AR5K_EEPROM_EARSTART(_v)	((_v) & 0xfff)
 | |
| +#define AR5K_EEPROM_HDR_XR2_DIS(_v)	(((_v) >> 12) & 0x1)
 | |
| +#define AR5K_EEPROM_HDR_XR5_DIS(_v)	(((_v) >> 13) & 0x1)
 | |
| +#define AR5K_EEPROM_EEMAP(_v)		(((_v) >> 14) & 0x3)
 | |
| +#define AR5K_EEPROM_MISC1		AR5K_EEPROM_INFO(5)
 | |
| +#define AR5K_EEPROM_TARGET_PWRSTART(_v)	((_v) & 0xfff)
 | |
| +#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)	(((_v) >> 14) & 0x1)
 | |
| +
 | |
| +#define AR5K_EEPROM_RFKILL_GPIO_SEL	0x0000001c
 | |
| +#define AR5K_EEPROM_RFKILL_GPIO_SEL_S	2
 | |
| +#define AR5K_EEPROM_RFKILL_POLARITY	0x00000002
 | |
| +#define AR5K_EEPROM_RFKILL_POLARITY_S	1
 | |
| +
 | |
| +/* Newer EEPROMs are using a different offset */
 | |
| +#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
 | |
| +	(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
 | |
| +
 | |
| +#define AR5K_EEPROM_ANT_GAIN(_v)	AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
 | |
| +#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v)	((int8_t)(((_v) >> 8) & 0xff))
 | |
| +#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v)	((int8_t)((_v) & 0xff))
 | |
| +
 | |
| +/* calibration settings */
 | |
| +#define AR5K_EEPROM_MODES_11A(_v)	AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
 | |
| +#define AR5K_EEPROM_MODES_11B(_v)	AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
 | |
| +#define AR5K_EEPROM_MODES_11G(_v)	AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
 | |
| +#define AR5K_EEPROM_CTL(_v)		AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128)	/* Conformance test limits */
 | |
| +#define AR5K_EEPROM_CHANNELS_5GHZ(_v)	AR5K_EEPROM_OFF(_v, 0x0100, 0x0150)	/* List of calibrated 5GHz chans */
 | |
| +#define	AR5K_EEPROM_TARGET_PWR_OFF_11A(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0055, 0x0000)
 | |
| +#define	AR5K_EEPROM_TARGET_PWR_OFF_11B(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0065, 0x0010)
 | |
| +#define	AR5K_EEPROM_TARGET_PWR_OFF_11G(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_CHANNELS_5GHZ(_v) + 0x0069, 0x0014)
 | |
| +
 | |
| +/* [3.1 - 3.3] */
 | |
| +#define AR5K_EEPROM_OBDB0_2GHZ		0x00ec
 | |
| +#define AR5K_EEPROM_OBDB1_2GHZ		0x00ed
 | |
| +
 | |
|  /*
 | |
|   * EEPROM data register
 | |
|   */
 | |
|  #define AR5K_EEPROM_DATA_5211	0x6004
 | |
|  #define AR5K_EEPROM_DATA_5210	0x6800
 | |
| -#define	AR5K_EEPROM_DATA	(mac_version == AR5K_SREV_VER_AR5210 ? \
 | |
| +#define AR5K_EEPROM_DATA	(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
|  				AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
 | |
|  
 | |
|  /*
 | |
|   * EEPROM command register
 | |
|   */
 | |
| -#define AR5K_EEPROM_CMD		0x6008	/* Register Addres */
 | |
| +#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 */
 | |
| @@ -291,43 +307,163 @@ static const struct ath5k_srev_name ath5
 | |
|  /*
 | |
|   * 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	(mac_version == AR5K_SREV_VER_AR5210 ? \
 | |
| +#define AR5K_EEPROM_STAT_5210	0x6c00			/* Register Address [5210] */
 | |
| +#define AR5K_EEPROM_STAT_5211	0x600c			/* Register Address [5211+] */
 | |
| +#define AR5K_EEPROM_STATUS	(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
|  				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 */
 | |
|  
 | |
| -#define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* Offset for EEPROM regulatory domain */
 | |
| -#define AR5K_EEPROM_INFO_BASE		0x00c0	/* Offset for EEPROM header */
 | |
| -#define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
 | |
| -#define AR5K_EEPROM_INFO_CKSUM		0xffff
 | |
| -#define AR5K_EEPROM_INFO(_n)		(AR5K_EEPROM_INFO_BASE + (_n))
 | |
| -#define AR5K_EEPROM_MODE_11A		0
 | |
| -#define AR5K_EEPROM_MODE_11B		1
 | |
| -#define AR5K_EEPROM_MODE_11G		2
 | |
| +/*
 | |
| + * EEPROM config register (?)
 | |
| + */
 | |
| +#define AR5K_EEPROM_CFG	0x6010
 | |
|  
 | |
| -#define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)
 | |
| +/* Some EEPROM defines */
 | |
| +#define AR5K_EEPROM_EEP_SCALE		100
 | |
| +#define AR5K_EEPROM_EEP_DELTA		10
 | |
| +#define AR5K_EEPROM_N_MODES		3
 | |
| +#define AR5K_EEPROM_N_5GHZ_CHAN		10
 | |
| +#define AR5K_EEPROM_N_2GHZ_CHAN		3
 | |
| +#define AR5K_EEPROM_MAX_CHAN		10
 | |
| +#define AR5K_EEPROM_N_PCDAC		11
 | |
| +#define AR5K_EEPROM_N_TEST_FREQ		8
 | |
| +#define AR5K_EEPROM_N_EDGES		8
 | |
| +#define AR5K_EEPROM_N_INTERCEPTS	11
 | |
| +#define AR5K_EEPROM_FREQ_M(_v)		AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
 | |
| +#define AR5K_EEPROM_PCDAC_M		0x3f
 | |
| +#define AR5K_EEPROM_PCDAC_START		1
 | |
| +#define AR5K_EEPROM_PCDAC_STOP		63
 | |
| +#define AR5K_EEPROM_PCDAC_STEP		1
 | |
| +#define AR5K_EEPROM_NON_EDGE_M		0x40
 | |
| +#define AR5K_EEPROM_CHANNEL_POWER	8
 | |
| +#define AR5K_EEPROM_N_OBDB		4
 | |
| +#define AR5K_EEPROM_OBDB_DIS		0xffff
 | |
| +#define AR5K_EEPROM_CHANNEL_DIS		0xff
 | |
| +#define AR5K_EEPROM_SCALE_OC_DELTA(_x)	(((_x) * 2) / 10)
 | |
| +#define AR5K_EEPROM_N_CTLS(_v)		AR5K_EEPROM_OFF(_v, 16, 32)
 | |
| +#define AR5K_EEPROM_MAX_CTLS		32
 | |
| +#define AR5K_EEPROM_N_XPD_PER_CHANNEL	4
 | |
| +#define AR5K_EEPROM_N_XPD0_POINTS	4
 | |
| +#define AR5K_EEPROM_N_XPD3_POINTS	3
 | |
| +#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ	35
 | |
| +#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ	55
 | |
| +#define AR5K_EEPROM_POWER_M		0x3f
 | |
| +#define AR5K_EEPROM_POWER_MIN		0
 | |
| +#define AR5K_EEPROM_POWER_MAX		3150
 | |
| +#define AR5K_EEPROM_POWER_STEP		50
 | |
| +#define AR5K_EEPROM_POWER_TABLE_SIZE	64
 | |
| +#define AR5K_EEPROM_N_POWER_LOC_11B	4
 | |
| +#define AR5K_EEPROM_N_POWER_LOC_11G	6
 | |
| +#define AR5K_EEPROM_I_GAIN		10
 | |
| +#define AR5K_EEPROM_CCK_OFDM_DELTA	15
 | |
| +#define AR5K_EEPROM_N_IQ_CAL		2
 | |
| +
 | |
| +enum ath5k_ant_setting {
 | |
| +	AR5K_ANT_VARIABLE	= 0,	/* variable by programming */
 | |
| +	AR5K_ANT_FIXED_A	= 1,	/* fixed to 11a frequencies */
 | |
| +	AR5K_ANT_FIXED_B	= 2,	/* fixed to 11b frequencies */
 | |
| +	AR5K_ANT_MAX		= 3,
 | |
| +};
 | |
|  
 | |
| -#define AR5K_EEPROM_HDR			AR5K_EEPROM_INFO(2)	/* Header that contains the device caps */
 | |
| -#define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)	/* Device has a support */
 | |
| -#define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)	/* Device has b support */
 | |
| -#define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)	/* Device has g support */
 | |
| -#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz (?) */
 | |
| -#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for a/XR mode (eeprom_init) */
 | |
| -#define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)
 | |
| -#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz (?) */
 | |
| -#define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
 | |
| +/* Per channel calibration data, used for power table setup */
 | |
| +struct ath5k_chan_pcal_info {
 | |
| +	u_int16_t	freq; /* Frequency */
 | |
| +	/* Power levels in dBm * 4 units */
 | |
| +	int16_t		pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
 | |
| +	int16_t		pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
 | |
| +	/* PCDAC tables in dBm * 2 units */
 | |
| +	u_int16_t	pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
 | |
| +	u_int16_t	pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
 | |
| +	/* Max available power */
 | |
| +	u_int16_t	max_pwr;
 | |
| +};
 | |
|  
 | |
| -/* Misc values available since EEPROM 4.0 */
 | |
| -#define AR5K_EEPROM_MISC0		0x00c4
 | |
| -#define AR5K_EEPROM_EARSTART(_v)	((_v) & 0xfff)
 | |
| -#define AR5K_EEPROM_EEMAP(_v)		(((_v) >> 14) & 0x3)
 | |
| -#define AR5K_EEPROM_MISC1		0x00c5
 | |
| -#define AR5K_EEPROM_TARGET_PWRSTART(_v)	((_v) & 0xfff)
 | |
| -#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)	(((_v) >> 14) & 0x1)
 | |
| +/* Per rate calibration data for each mode, used for power table setup */
 | |
| +struct ath5k_rate_pcal_info {
 | |
| +	u_int16_t	freq; /* Frequency */
 | |
| +	/* Power level for 6-24Mbit/s rates */
 | |
| +	u_int16_t	target_power_6to24;
 | |
| +	/* Power level for 36Mbit rate */
 | |
| +	u_int16_t	target_power_36;
 | |
| +	/* Power level for 48Mbit rate */
 | |
| +	u_int16_t	target_power_48;
 | |
| +	/* Power level for 54Mbit rate */
 | |
| +	u_int16_t	target_power_54;
 | |
| +};
 | |
| +
 | |
| +/* EEPROM calibration data */
 | |
| +struct ath5k_eeprom_info {
 | |
| +
 | |
| +	/* Header information */
 | |
| +	u_int16_t	ee_magic;
 | |
| +	u_int16_t	ee_protect;
 | |
| +	u_int16_t	ee_regdomain;
 | |
| +	u_int16_t	ee_version;
 | |
| +	u_int16_t	ee_header;
 | |
| +	u_int16_t	ee_ant_gain;
 | |
| +	u_int16_t	ee_misc0;
 | |
| +	u_int16_t	ee_misc1;
 | |
| +	u_int16_t	ee_cck_ofdm_gain_delta;
 | |
| +	u_int16_t	ee_cck_ofdm_power_delta;
 | |
| +	u_int16_t	ee_scaled_cck_delta;
 | |
| +
 | |
| +	/* Used for tx thermal adjustment (eeprom_init, rfregs) */
 | |
| +	u_int16_t	ee_tx_clip;
 | |
| +	u_int16_t	ee_pwd_84;
 | |
| +	u_int16_t	ee_pwd_90;
 | |
| +	u_int16_t	ee_gain_select;
 | |
| +
 | |
| +	/* RF Calibration settings (reset, rfregs) */
 | |
| +	u_int16_t	ee_i_cal[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_q_cal[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_fixed_bias[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_turbo_max_power[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_xr_power[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_switch_settling[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
 | |
| +	u_int16_t	ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
 | |
| +	u_int16_t	ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
 | |
| +	u_int16_t	ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_thr_62[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_xlna_gain[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_xpd[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_x_gain[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_i_gain[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
 | |
| +
 | |
| +	/* Power calibration data */
 | |
| +	u_int16_t	ee_false_detect[AR5K_EEPROM_N_MODES];
 | |
| +	u_int16_t	ee_cal_piers_a;
 | |
| +	struct ath5k_chan_pcal_info	ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
 | |
| +	u_int16_t	ee_cal_piers_b;
 | |
| +	struct ath5k_chan_pcal_info	ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN];
 | |
| +	u_int16_t	ee_cal_piers_g;
 | |
| +	struct ath5k_chan_pcal_info	ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN];
 | |
| +	/* Per rate target power levels */
 | |
| +	u_int16_t	ee_rate_target_pwr_num_a;
 | |
| +	struct ath5k_rate_pcal_info	ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
 | |
| +	u_int16_t	ee_rate_target_pwr_num_b;
 | |
| +	struct ath5k_rate_pcal_info	ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN];
 | |
| +	u_int16_t	ee_rate_target_pwr_num_g;
 | |
| +	struct ath5k_rate_pcal_info	ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN];
 | |
| +
 | |
| +	/* Conformance test limits (Unused) */
 | |
| +	u_int16_t	ee_ctls;
 | |
| +	u_int16_t	ee_ctl[AR5K_EEPROM_MAX_CTLS];
 | |
| +
 | |
| +	/* Noise Floor Calibration settings */
 | |
| +	int16_t		ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
 | |
| +	int8_t		ee_adc_desired_size[AR5K_EEPROM_N_MODES];
 | |
| +	int8_t		ee_pga_desired_size[AR5K_EEPROM_N_MODES];
 | |
| +
 | |
| +	u_int32_t	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
 | |
| +};
 | |
|  
 | |
|  /*
 | |
|   * Read data by masking
 | |
| @@ -350,7 +486,6 @@ static const struct ath5k_srev_name ath5
 | |
|  	(*((volatile u_int32_t *)(mem + (_reg))) = (_val))
 | |
|  #endif
 | |
|  
 | |
| -
 | |
|  #define AR5K_REG_ENABLE_BITS(_reg, _flags)	\
 | |
|  	AR5K_REG_WRITE(_reg, AR5K_REG_READ(_reg) | (_flags))
 | |
|  
 | |
| @@ -359,7 +494,12 @@ static const struct ath5k_srev_name ath5
 | |
|  
 | |
|  #define AR5K_TUNE_REGISTER_TIMEOUT		20000
 | |
|  
 | |
| -/* names for eeprom fields */
 | |
| +#define AR5K_EEPROM_READ(_o, _v) do {					\
 | |
| +	if ((ret = ath5k_hw_eeprom_read(mem, (_o), &(_v), mac_version)) != 0)	\
 | |
| +		return (ret);						\
 | |
| +} while (0)
 | |
| +
 | |
| +/* Names for EEPROM fields */
 | |
|  struct eeprom_entry {
 | |
|  	const char *name;
 | |
|  	int addr;
 | |
| @@ -375,8 +515,6 @@ static const struct eeprom_entry eeprom_
 | |
|  	{"regdomain", AR5K_EEPROM_REG_DOMAIN},
 | |
|  };
 | |
|  
 | |
| -static const int eeprom_addr_len = sizeof(eeprom_addr) / sizeof(eeprom_addr[0]);
 | |
| -
 | |
|  static int force_write = 0;
 | |
|  static int verbose = 0;
 | |
|  
 | |
| @@ -398,8 +536,8 @@ static u_int32_t ath5k_hw_bitswap(u_int3
 | |
|  /*
 | |
|   * Get the PHY Chip revision
 | |
|   */
 | |
| -static u_int16_t
 | |
| -ath5k_hw_radio_revision(u_int16_t mac_version, void *mem, u_int8_t chip)
 | |
| +static u_int16_t ath5k_hw_radio_revision(u_int16_t mac_version, void *mem,
 | |
| +					 u_int8_t chip)
 | |
|  {
 | |
|  	int i;
 | |
|  	u_int32_t srev;
 | |
| @@ -427,7 +565,7 @@ ath5k_hw_radio_revision(u_int16_t mac_ve
 | |
|  	for (i = 0; i < 8; i++)
 | |
|  		AR5K_REG_WRITE(AR5K_PHY(0x20), 0x00010000);
 | |
|  
 | |
| -	if (mac_version == AR5K_SREV_VER_AR5210) {
 | |
| +	if (mac_version == AR5K_SREV_MAC_AR5210) {
 | |
|  		srev = AR5K_REG_READ(AR5K_PHY(256) >> 28) & 0xf;
 | |
|  
 | |
|  		ret = (u_int16_t)ath5k_hw_bitswap(srev, 4) + 1;
 | |
| @@ -447,9 +585,8 @@ ath5k_hw_radio_revision(u_int16_t mac_ve
 | |
|  /*
 | |
|   * Write to EEPROM
 | |
|   */
 | |
| -static int
 | |
| -ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data,
 | |
| -		      u_int8_t mac_version)
 | |
| +static int ath5k_hw_eeprom_write(void *mem, u_int32_t offset, u_int16_t data,
 | |
| +				 u_int8_t mac_version)
 | |
|  {
 | |
|  	u_int32_t status, timeout;
 | |
|  
 | |
| @@ -457,7 +594,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
 | |
|  	 * Initialize EEPROM access
 | |
|  	 */
 | |
|  
 | |
| -	if (mac_version == AR5K_SREV_VER_AR5210) {
 | |
| +	if (mac_version == AR5K_SREV_MAC_AR5210) {
 | |
|  
 | |
|  		AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE);
 | |
|  
 | |
| @@ -466,7 +603,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
 | |
|  
 | |
|  	} else {
 | |
|  		/* not 5210 */
 | |
| -		/* reset eeprom access */
 | |
| +		/* reset EEPROM access */
 | |
|  		AR5K_REG_WRITE(AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_RESET);
 | |
|  		usleep(5);
 | |
|  
 | |
| @@ -484,7 +621,7 @@ ath5k_hw_eeprom_write(void *mem, u_int32
 | |
|  		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",
 | |
| +				err("EEPROM write access to 0x%04x failed",
 | |
|  				    offset);
 | |
|  				return 1;
 | |
|  			}
 | |
| @@ -499,16 +636,15 @@ ath5k_hw_eeprom_write(void *mem, u_int32
 | |
|  /*
 | |
|   * Read from EEPROM
 | |
|   */
 | |
| -static int
 | |
| -ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data,
 | |
| -		     u_int8_t mac_version)
 | |
| +static int ath5k_hw_eeprom_read(void *mem, u_int32_t offset, u_int16_t *data,
 | |
| +				u_int8_t mac_version)
 | |
|  {
 | |
|  	u_int32_t status, timeout;
 | |
|  
 | |
|  	/*
 | |
|  	 * Initialize EEPROM access
 | |
|  	 */
 | |
| -	if (mac_version == AR5K_SREV_VER_AR5210) {
 | |
| +	if (mac_version == AR5K_SREV_MAC_AR5210) {
 | |
|  		AR5K_REG_ENABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_EEAE);
 | |
|  		(void)AR5K_REG_READ(AR5K_EEPROM_BASE + (4 * offset));
 | |
|  	} else {
 | |
| @@ -531,50 +667,701 @@ ath5k_hw_eeprom_read(void *mem, u_int32_
 | |
|  	return 1;
 | |
|  }
 | |
|  
 | |
| -static const char *ath5k_hw_get_part_name(enum ath5k_srev_type type,
 | |
| -					  u_int32_t val)
 | |
| +/*
 | |
| + * Translate binary channel representation in EEPROM to frequency
 | |
| + */
 | |
| +static u_int16_t ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee,
 | |
| +				       u_int16_t bin, unsigned int mode)
 | |
|  {
 | |
| -	const char *name = "xxxxx";
 | |
| -	int i;
 | |
| +	u_int16_t val;
 | |
|  
 | |
| -	for (i = 0; i < ARRAY_SIZE(ath5k_srev_names); i++) {
 | |
| -		if (ath5k_srev_names[i].sr_type != type ||
 | |
| -		    ath5k_srev_names[i].sr_val == AR5K_SREV_UNKNOWN)
 | |
| -			continue;
 | |
| -		if ((val & 0xff) < ath5k_srev_names[i + 1].sr_val) {
 | |
| -			name = ath5k_srev_names[i].sr_name;
 | |
| +	if (bin == AR5K_EEPROM_CHANNEL_DIS)
 | |
| +		return bin;
 | |
| +
 | |
| +	if (mode == AR5K_EEPROM_MODE_11A) {
 | |
| +		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
 | |
| +			val = (5 * bin) + 4800;
 | |
| +		else
 | |
| +			val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
 | |
| +			    (bin * 10) + 5100;
 | |
| +	} else {
 | |
| +		if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
 | |
| +			val = bin + 2300;
 | |
| +		else
 | |
| +			val = bin + 2400;
 | |
| +	}
 | |
| +
 | |
| +	return val;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Read antenna info from EEPROM
 | |
| + */
 | |
| +static int ath5k_eeprom_read_ants(void *mem, u_int8_t mac_version,
 | |
| +				  struct ath5k_eeprom_info *ee,
 | |
| +				  u_int32_t *offset, unsigned int mode)
 | |
| +{
 | |
| +	u_int32_t o = *offset;
 | |
| +	u_int16_t val;
 | |
| +	int ret, i = 0;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_switch_settling[mode]	= (val >> 8) & 0x7f;
 | |
| +	ee->ee_ant_tx_rx[mode]		= (val >> 2) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i++]	= val & 0x3f;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 10) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 4) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i]	= (val << 2) & 0x3f;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_ant_control[mode][i++]	|= (val >> 14) & 0x3;
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 8) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 2) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i]	= (val << 4) & 0x3f;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_ant_control[mode][i++]	|= (val >> 12) & 0xf;
 | |
| +	ee->ee_ant_control[mode][i++]	= (val >> 6) & 0x3f;
 | |
| +	ee->ee_ant_control[mode][i++]	= val & 0x3f;
 | |
| +
 | |
| +	/* Get antenna modes */
 | |
| +	ee->ee_antenna[mode][0] =
 | |
| +	    (ee->ee_ant_control[mode][0] << 4) | 0x1;
 | |
| +	ee->ee_antenna[mode][AR5K_ANT_FIXED_A] =
 | |
| +	     ee->ee_ant_control[mode][1]	|
 | |
| +	    (ee->ee_ant_control[mode][2] << 6)	|
 | |
| +	    (ee->ee_ant_control[mode][3] << 12) |
 | |
| +	    (ee->ee_ant_control[mode][4] << 18) |
 | |
| +	    (ee->ee_ant_control[mode][5] << 24);
 | |
| +	ee->ee_antenna[mode][AR5K_ANT_FIXED_B] =
 | |
| +	     ee->ee_ant_control[mode][6]	|
 | |
| +	    (ee->ee_ant_control[mode][7] << 6)	|
 | |
| +	    (ee->ee_ant_control[mode][8] << 12) |
 | |
| +	    (ee->ee_ant_control[mode][9] << 18) |
 | |
| +	    (ee->ee_ant_control[mode][10] << 24);
 | |
| +
 | |
| +	/* return new offset */
 | |
| +	*offset = o;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Read supported modes from EEPROM
 | |
| + */
 | |
| +static int ath5k_eeprom_read_modes(void *mem, u_int8_t mac_version,
 | |
| +				   struct ath5k_eeprom_info *ee,
 | |
| +				   u_int32_t *offset, unsigned int mode)
 | |
| +{
 | |
| +	u_int32_t o = *offset;
 | |
| +	u_int16_t val;
 | |
| +	int ret;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_tx_end2xlna_enable[mode]	= (val >> 8) & 0xff;
 | |
| +	ee->ee_thr_62[mode]		= val & 0xff;
 | |
| +
 | |
| +	if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2)
 | |
| +		ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_tx_end2xpa_disable[mode]	= (val >> 8) & 0xff;
 | |
| +	ee->ee_tx_frm2xpa_enable[mode]	= val & 0xff;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_pga_desired_size[mode]	= (val >> 8) & 0xff;
 | |
| +
 | |
| +	if ((val & 0xff) & 0x80)
 | |
| +		ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
 | |
| +	else
 | |
| +		ee->ee_noise_floor_thr[mode] = val & 0xff;
 | |
| +
 | |
| +	if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2)
 | |
| +		ee->ee_noise_floor_thr[mode] =
 | |
| +		    mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(o++, val);
 | |
| +	ee->ee_xlna_gain[mode]		= (val >> 5) & 0xff;
 | |
| +	ee->ee_x_gain[mode]		= (val >> 1) & 0xf;
 | |
| +	ee->ee_xpd[mode]		= val & 0x1;
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
 | |
| +		ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
 | |
| +		AR5K_EEPROM_READ(o++, val);
 | |
| +		ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
 | |
| +
 | |
| +		if (mode == AR5K_EEPROM_MODE_11A)
 | |
| +			ee->ee_xr_power[mode] = val & 0x3f;
 | |
| +		else {
 | |
| +			ee->ee_ob[mode][0] = val & 0x7;
 | |
| +			ee->ee_db[mode][0] = (val >> 3) & 0x7;
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
| +	if (ee->ee_version < AR5K_EEPROM_VERSION_3_4) {
 | |
| +		ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
 | |
| +		ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
 | |
| +	} else {
 | |
| +		ee->ee_i_gain[mode] = (val >> 13) & 0x7;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(o++, val);
 | |
| +		ee->ee_i_gain[mode] |= (val << 3) & 0x38;
 | |
| +
 | |
| +		if (mode == AR5K_EEPROM_MODE_11G)
 | |
| +			ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
 | |
| +	}
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0 &&
 | |
| +	    mode == AR5K_EEPROM_MODE_11A) {
 | |
| +		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
 | |
| +		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
 | |
| +	}
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_6 &&
 | |
| +	    mode == AR5K_EEPROM_MODE_11G)
 | |
| +		ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
 | |
| +
 | |
| +	/* return new offset */
 | |
| +	*offset = o;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Read per channel calibration info from EEPROM
 | |
| + * This doesn't work on 2112+ chips (EEPROM versions >= 4.6),
 | |
| + * I only tested it on 5213 + 5112. This is still work in progress...
 | |
| + *
 | |
| + * This info is used to calibrate the baseband power table. Imagine
 | |
| + * that for each channel there is a power curve that's hw specific
 | |
| + * (depends on amplifier) and we try to "correct" this curve using offests
 | |
| + * we pass on to phy chip (baseband -> before amplifier) so that it can
 | |
| + * use acurate power values when setting tx power (takes amplifier's performance
 | |
| + * on each channel into account).
 | |
| + *
 | |
| + * EEPROM provides us with the offsets for some pre-calibrated channels
 | |
| + * and we have to scale (to create the full table for these channels) and
 | |
| + * interpolate (in order to create the table for any channel).
 | |
| + */
 | |
| +static int ath5k_eeprom_read_pcal_info(void *mem, u_int8_t mac_version,
 | |
| +				       struct ath5k_eeprom_info *ee,
 | |
| +				       u_int32_t *offset, unsigned int mode)
 | |
| +{
 | |
| +	u_int32_t o = *offset;
 | |
| +	unsigned int i, c;
 | |
| +	int ret;
 | |
| +	u_int16_t val;
 | |
| +	struct ath5k_chan_pcal_info *chan_pcal_info;
 | |
| +	u_int16_t cal_piers;
 | |
| +
 | |
| +	switch (mode) {
 | |
| +	case AR5K_EEPROM_MODE_11A:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_a;
 | |
| +		cal_piers = ee->ee_cal_piers_a;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11B:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_b;
 | |
| +		cal_piers = ee->ee_cal_piers_b;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11G:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_g;
 | |
| +		cal_piers = ee->ee_cal_piers_g;
 | |
| +		break;
 | |
| +	default:
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
| +	for (i = 0; i < cal_piers; i++) {
 | |
| +		/* Power values in dBm * 4 */
 | |
| +		for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
 | |
| +			AR5K_EEPROM_READ(o++, val);
 | |
| +			chan_pcal_info[i].pwr_x0[c] = (val & 0xff);
 | |
| +			chan_pcal_info[i].pwr_x0[++c] = ((val >> 8) & 0xff);
 | |
| +		}
 | |
| +
 | |
| +		/* PCDAC steps (dBm * 2) */
 | |
| +		AR5K_EEPROM_READ(o++, val);
 | |
| +		chan_pcal_info[i].pcdac_x0[1] = (val & 0x1f);
 | |
| +		chan_pcal_info[i].pcdac_x0[2] = ((val >> 5) & 0x1f);
 | |
| +		chan_pcal_info[i].pcdac_x0[3] = ((val >> 10) & 0x1f);
 | |
| +
 | |
| +		/* No idea what these power levels are for (4 xpds ?)
 | |
| +		   I got zeroes on my card and the EEPROM info
 | |
| +		   dumps we found on the net also have weird values */
 | |
| +		AR5K_EEPROM_READ(o++, val);
 | |
| +		chan_pcal_info[i].pwr_x3[0] = (val & 0xff);
 | |
| +		chan_pcal_info[i].pwr_x3[1] = ((val >> 8) & 0xff);
 | |
| +
 | |
| +		AR5K_EEPROM_READ(o++, val);
 | |
| +		chan_pcal_info[i].pwr_x3[2] = (val & 0xff);
 | |
| +		/* It's weird but they put it here, that's the
 | |
| +		   PCDAC starting step */
 | |
| +		chan_pcal_info[i].pcdac_x0[0] = ((val >> 8) & 0xff);
 | |
| +
 | |
| +		/* Static values seen on EEPROM info dumps */
 | |
| +		chan_pcal_info[i].pcdac_x3[0] = 20;
 | |
| +		chan_pcal_info[i].pcdac_x3[1] = 35;
 | |
| +		chan_pcal_info[i].pcdac_x3[2] = 63;
 | |
| +
 | |
| +		/* Last xpd0 power level is also channel maximum */
 | |
| +		chan_pcal_info[i].max_pwr = chan_pcal_info[i].pwr_x0[3];
 | |
| +
 | |
| +		/* Recreate pcdac_x0 table for this channel using pcdac steps */
 | |
| +		chan_pcal_info[i].pcdac_x0[1] += chan_pcal_info[i].pcdac_x0[0];
 | |
| +		chan_pcal_info[i].pcdac_x0[2] += chan_pcal_info[i].pcdac_x0[1];
 | |
| +		chan_pcal_info[i].pcdac_x0[3] += chan_pcal_info[i].pcdac_x0[2];
 | |
| +	}
 | |
| +
 | |
| +	/* return new offset */
 | |
| +	(*offset) = o;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Read per rate target power (this is the maximum tx power
 | |
| + * supported by the card). This info is used when setting
 | |
| + * tx power, no matter the channel.
 | |
| + *
 | |
| + * This also works for v5 EEPROMs.
 | |
| + */
 | |
| +static int ath5k_eeprom_read_target_rate_pwr_info(void *mem,
 | |
| +						  u_int8_t mac_version,
 | |
| +						  struct ath5k_eeprom_info *ee,
 | |
| +						  u_int32_t *offset,
 | |
| +						  unsigned int mode)
 | |
| +{
 | |
| +	u_int32_t o = *offset;
 | |
| +	u_int16_t val;
 | |
| +	struct ath5k_rate_pcal_info *rate_pcal_info;
 | |
| +	u_int16_t *rate_target_pwr_num;
 | |
| +	int ret, i;
 | |
| +
 | |
| +	switch (mode) {
 | |
| +	case AR5K_EEPROM_MODE_11A:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_a;
 | |
| +		ee->ee_rate_target_pwr_num_a = AR5K_EEPROM_N_5GHZ_CHAN;
 | |
| +		rate_target_pwr_num = &ee->ee_rate_target_pwr_num_a;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11B:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_b;
 | |
| +		ee->ee_rate_target_pwr_num_b = 2; /* 3rd is g mode'ss 1st */
 | |
| +		rate_target_pwr_num = &ee->ee_rate_target_pwr_num_b;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11G:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_g;
 | |
| +		ee->ee_rate_target_pwr_num_g = AR5K_EEPROM_N_2GHZ_CHAN;
 | |
| +		rate_target_pwr_num = &ee->ee_rate_target_pwr_num_g;
 | |
| +		break;
 | |
| +	default:
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
| +	/* Different freq mask for older eeproms (<= v3.2) */
 | |
| +	if(ee->ee_version <= 0x3002){
 | |
| +		for (i = 0; i < (*rate_target_pwr_num); i++) {
 | |
| +			AR5K_EEPROM_READ(o++, val);
 | |
| +			rate_pcal_info[i].freq =
 | |
| +			    ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
 | |
| +	
 | |
| +			rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
 | |
| +			rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
 | |
| +	
 | |
| +			AR5K_EEPROM_READ(o++, val);
 | |
| +	
 | |
| +			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
 | |
| +			    val == 0) {
 | |
| +				(*rate_target_pwr_num) = i;
 | |
| +				break;
 | |
| +			}
 | |
| +
 | |
| +			rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
 | |
| +			rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
 | |
| +			rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
 | |
| +		}
 | |
| +	} else {
 | |
| +		for (i = 0; i < (*rate_target_pwr_num); i++) {
 | |
| +			AR5K_EEPROM_READ(o++, val);
 | |
| +			rate_pcal_info[i].freq =
 | |
| +			    ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
 | |
| +	
 | |
| +			rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
 | |
| +			rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
 | |
| +	
 | |
| +			AR5K_EEPROM_READ(o++, val);
 | |
| +	
 | |
| +			if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
 | |
| +			    val == 0) {
 | |
| +				(*rate_target_pwr_num) = i;
 | |
| +				break;
 | |
| +			}
 | |
| +
 | |
| +			rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
 | |
| +			rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
 | |
| +			rate_pcal_info[i].target_power_54 = (val & 0x3f);
 | |
| +		}
 | |
| +	}
 | |
| +	/* return new offset */
 | |
| +	(*offset) = o;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +/*
 | |
| + * Initialize EEPROM & capabilities data
 | |
| + */
 | |
| +static int ath5k_eeprom_init(void *mem, u_int8_t mac_version,
 | |
| +			     struct ath5k_eeprom_info *ee)
 | |
| +{
 | |
| +	unsigned int mode, i;
 | |
| +	int ret;
 | |
| +	u_int32_t offset;
 | |
| +	u_int16_t val;
 | |
| +
 | |
| +	/* Initial TX thermal adjustment values */
 | |
| +	ee->ee_tx_clip = 4;
 | |
| +	ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
 | |
| +	ee->ee_gain_select = 1;
 | |
| +
 | |
| +	/*
 | |
| +	 * Read values from EEPROM and store them in the capability structure
 | |
| +	 */
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_MAGIC, ee->ee_magic);
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_PROTECT, ee->ee_protect);
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_REG_DOMAIN, ee->ee_regdomain);
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_VERSION, ee->ee_version);
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_HDR, ee->ee_header);
 | |
| +
 | |
| +	/* Return if we have an old EEPROM */
 | |
| +	if (ee->ee_version < AR5K_EEPROM_VERSION_3_0)
 | |
| +		return 0;
 | |
| +
 | |
| +#ifdef notyet
 | |
| +	/*
 | |
| +	 * Validate the checksum of the EEPROM date. There are some
 | |
| +	 * devices with invalid EEPROMs.
 | |
| +	 */
 | |
| +	for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
 | |
| +		AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
 | |
| +		cksum ^= val;
 | |
| +	}
 | |
| +	if (cksum != AR5K_EEPROM_INFO_CKSUM) {
 | |
| +		AR5K_PRINTF("Invalid EEPROM checksum 0x%04x\n", cksum);
 | |
| +		return -EIO;
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
| +	AR5K_EEPROM_READ(AR5K_EEPROM_ANT_GAIN(ee->ee_version), ee->ee_ant_gain);
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
 | |
| +		AR5K_EEPROM_READ(AR5K_EEPROM_MISC0, ee->ee_misc0);
 | |
| +		AR5K_EEPROM_READ(AR5K_EEPROM_MISC1, ee->ee_misc1);
 | |
| +	}
 | |
| +
 | |
| +	if (ee->ee_version < AR5K_EEPROM_VERSION_3_3) {
 | |
| +		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
 | |
| +		ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
 | |
| +		ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
 | |
| +		ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
 | |
| +		ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * Get conformance test limit values
 | |
| +	 */
 | |
| +	offset = AR5K_EEPROM_CTL(ee->ee_version);
 | |
| +	ee->ee_ctls = 0;
 | |
| +
 | |
| +	for (i = 0; i < AR5K_EEPROM_N_CTLS(ee->ee_version); i++) {
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +
 | |
| +		if (((val >> 8) & 0xff) == 0)
 | |
| +			break;
 | |
| +
 | |
| +		ee->ee_ctl[i] = (val >> 8) & 0xff;
 | |
| +		ee->ee_ctls++;
 | |
| +
 | |
| +		if ((val & 0xff) == 0)
 | |
|  			break;
 | |
| +
 | |
| +		ee->ee_ctl[i + 1] = val & 0xff;
 | |
| +		ee->ee_ctls++;
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * Get values for 802.11a (5GHz)
 | |
| +	 */
 | |
| +	mode = AR5K_EEPROM_MODE_11A;
 | |
| +
 | |
| +	ee->ee_turbo_max_power[mode] =
 | |
| +	    AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
 | |
| +
 | |
| +	offset = AR5K_EEPROM_MODES_11A(ee->ee_version);
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(offset++, val);
 | |
| +	ee->ee_adc_desired_size[mode]	= (int8_t)((val >> 8) & 0xff);
 | |
| +	ee->ee_ob[mode][3]		= (val >> 5) & 0x7;
 | |
| +	ee->ee_db[mode][3]		= (val >> 2) & 0x7;
 | |
| +	ee->ee_ob[mode][2]		= (val << 1) & 0x7;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(offset++, val);
 | |
| +	ee->ee_ob[mode][2]		|= (val >> 15) & 0x1;
 | |
| +	ee->ee_db[mode][2]		= (val >> 12) & 0x7;
 | |
| +	ee->ee_ob[mode][1]		= (val >> 9) & 0x7;
 | |
| +	ee->ee_db[mode][1]		= (val >> 6) & 0x7;
 | |
| +	ee->ee_ob[mode][0]		= (val >> 3) & 0x7;
 | |
| +	ee->ee_db[mode][0]		= val & 0x7;
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1) {
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +		ee->ee_margin_tx_rx[mode] = val & 0x3f;
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * Get values for 802.11b (2.4GHz)
 | |
| +	 */
 | |
| +	mode = AR5K_EEPROM_MODE_11B;
 | |
| +	offset = AR5K_EEPROM_MODES_11B(ee->ee_version);
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(offset++, val);
 | |
| +	ee->ee_adc_desired_size[mode]	= (int8_t)((val >> 8) & 0xff);
 | |
| +	ee->ee_ob[mode][1]		= (val >> 4) & 0x7;
 | |
| +	ee->ee_db[mode][1]		= val & 0x7;
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +
 | |
| +		ee->ee_cal_piers_b = 0;
 | |
| +
 | |
| +		ee->ee_pwr_cal_b[0].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_b++;
 | |
| +
 | |
| +		ee->ee_pwr_cal_b[1].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_b++;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +		ee->ee_pwr_cal_b[2].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_b++;
 | |
| +	}
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1)
 | |
| +		ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
 | |
| +
 | |
| +	/*
 | |
| +	 * Get values for 802.11g (2.4GHz)
 | |
| +	 */
 | |
| +	mode = AR5K_EEPROM_MODE_11G;
 | |
| +	offset = AR5K_EEPROM_MODES_11G(ee->ee_version);
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_ants(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	AR5K_EEPROM_READ(offset++, val);
 | |
| +	ee->ee_adc_desired_size[mode]	= (signed short int)((val >> 8) & 0xff);
 | |
| +	ee->ee_ob[mode][1]		= (val >> 4) & 0x7;
 | |
| +	ee->ee_db[mode][1]		= val & 0x7;
 | |
| +
 | |
| +	ret = ath5k_eeprom_read_modes(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) {
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +
 | |
| +		ee->ee_cal_piers_g = 0;
 | |
| +
 | |
| +		ee->ee_pwr_cal_g[0].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_g++;
 | |
| +
 | |
| +		ee->ee_pwr_cal_g[1].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_g++;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +		ee->ee_turbo_max_power[mode] = val & 0x7f;
 | |
| +		ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +		ee->ee_pwr_cal_g[2].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
 | |
| +		if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
 | |
| +			ee->ee_cal_piers_g++;
 | |
| +
 | |
| +		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_1)
 | |
| +			ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
 | |
| +
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +		ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
 | |
| +		ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
 | |
| +
 | |
| +		if (ee->ee_version >= AR5K_EEPROM_VERSION_4_2) {
 | |
| +			AR5K_EEPROM_READ(offset++, val);
 | |
| +			ee->ee_cck_ofdm_gain_delta = val & 0xff;
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| -	return (name);
 | |
| +	/*
 | |
| +	 * Read 5GHz EEPROM channels
 | |
| +	 */
 | |
| +	offset = AR5K_EEPROM_CHANNELS_5GHZ(ee->ee_version);
 | |
| +	ee->ee_cal_piers_a = 0;
 | |
| +	for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
 | |
| +		AR5K_EEPROM_READ(offset++, val);
 | |
| +
 | |
| +		if ((val & 0xff) == 0)
 | |
| +			break;
 | |
| +
 | |
| +		ee->ee_pwr_cal_a[i].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, val & 0xff, AR5K_EEPROM_MODE_11A);
 | |
| +		ee->ee_cal_piers_a++;
 | |
| +
 | |
| +		if (((val >> 8) & 0xff) == 0)
 | |
| +			break;
 | |
| +
 | |
| +		ee->ee_pwr_cal_a[++i].freq =
 | |
| +			ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, AR5K_EEPROM_MODE_11A);
 | |
| +		ee->ee_cal_piers_a++;
 | |
| +
 | |
| +	}
 | |
| +
 | |
| +	/*
 | |
| +	 * Read power calibration info
 | |
| +	 */
 | |
| +	mode = AR5K_EEPROM_MODE_11A;
 | |
| +	ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	mode = AR5K_EEPROM_MODE_11B;
 | |
| +	ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	mode = AR5K_EEPROM_MODE_11G;
 | |
| +	ret = ath5k_eeprom_read_pcal_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +
 | |
| +	/*
 | |
| +	 * Read per rate target power info
 | |
| +	 */
 | |
| +	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
 | |
| +	mode = AR5K_EEPROM_MODE_11A;
 | |
| +	ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
 | |
| +	mode = AR5K_EEPROM_MODE_11B;
 | |
| +	ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) + AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
 | |
| +	mode = AR5K_EEPROM_MODE_11G;
 | |
| +	ret = ath5k_eeprom_read_target_rate_pwr_info(mem, mac_version, ee, &offset, mode);
 | |
| +	if (ret)
 | |
| +		return ret;
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static const char *ath5k_hw_get_mac_name(u_int8_t val)
 | |
| +{
 | |
| +	static char name[16];
 | |
| +	unsigned int i;
 | |
| +
 | |
| +	for (i = 0; i < ARRAY_SIZE(ath5k_mac_names); i++) {
 | |
| +		if (val <= ath5k_mac_names[i].sr_val)
 | |
| +			break;
 | |
| +	}
 | |
| +
 | |
| +	if (val == ath5k_mac_names[i].sr_val)
 | |
| +		return ath5k_mac_names[i].sr_name;
 | |
| +
 | |
| +	snprintf(name, sizeof(name), "%s+", ath5k_mac_names[i - 1].sr_name);
 | |
| +	return name;
 | |
| +}
 | |
| +
 | |
| +static const char *ath5k_hw_get_phy_name(u_int8_t val)
 | |
| +{
 | |
| +	const char *name = "?????";
 | |
| +	unsigned int i;
 | |
| +
 | |
| +	for (i = 0; i < ARRAY_SIZE(ath5k_phy_names); i++) {
 | |
| +		if (val < ath5k_phy_names[i + 1].sr_val) {
 | |
| +			name = ath5k_phy_names[i].sr_name;
 | |
| +			break;
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
| +	return name;
 | |
|  }
 | |
|  
 | |
|  /* returns -1 on unknown name */
 | |
|  static int eeprom_name2addr(const char *name)
 | |
|  {
 | |
| -	int i;
 | |
| +	unsigned int i;
 | |
| +
 | |
|  	if (!name || !name[0])
 | |
|  		return -1;
 | |
| -	for (i = 0; i < eeprom_addr_len; i++)
 | |
| +	for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
 | |
|  		if (!strcmp(name, eeprom_addr[i].name))
 | |
|  			return eeprom_addr[i].addr;
 | |
|  	return -1;
 | |
| -}				/* eeprom_name2addr */
 | |
| +}
 | |
|  
 | |
|  /* returns "<unknown>" on unknown address */
 | |
|  static const char *eeprom_addr2name(int addr)
 | |
|  {
 | |
| -	int i;
 | |
| -	for (i = 0; i < eeprom_addr_len; i++)
 | |
| +	unsigned int i;
 | |
| +
 | |
| +	for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
 | |
|  		if (eeprom_addr[i].addr == addr)
 | |
|  			return eeprom_addr[i].name;
 | |
|  	return "<unknown>";
 | |
| -}				/* eeprom_addr2name */
 | |
| +}
 | |
|  
 | |
| -static int
 | |
| -do_write_pairs(int anr, int argc, char **argv, unsigned char *mem,
 | |
| -	       int mac_version)
 | |
| +static int do_write_pairs(int anr, int argc, char **argv, unsigned char *mem,
 | |
| +			  int mac_version)
 | |
|  {
 | |
|  #define MAX_NR_WRITES 16
 | |
|  	struct {
 | |
| @@ -635,7 +1422,7 @@ do_write_pairs(int anr, int argc, char *
 | |
|  		}
 | |
|  		anr++;
 | |
|  		i++;
 | |
| -	}			/* while (anr < (argc-1)) */
 | |
| +	}
 | |
|  
 | |
|  	if (!(wr_ops_len = i)) {
 | |
|  		err("no (addr,val) pairs given");
 | |
| @@ -702,20 +1489,22 @@ do_write_pairs(int anr, int argc, char *
 | |
|  	}
 | |
|  
 | |
|  	return errors ? 11 : 0;
 | |
| -}				/* do_write_pairs */
 | |
| +}
 | |
|  
 | |
|  static void usage(const char *n)
 | |
|  {
 | |
| -	int i;
 | |
| +	unsigned int i;
 | |
|  
 | |
| -	fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] <base_address> "
 | |
| +	fprintf(stderr, "%s [-w [-g N:M]] [-v] [-f] [-d] [-R addr] [-W addr val] <base_address> "
 | |
|  		"[<name1> <val1> [<name2> <val2> ...]]\n\n", n);
 | |
|  	fprintf(stderr,
 | |
|  		"-w      write values into EEPROM\n"
 | |
|  		"-g N:M  set GPIO N to level M (only used with -w)\n"
 | |
|  		"-v      verbose output\n"
 | |
|  		"-f      force; suppress question before writing\n"
 | |
| -		"-d      dump eeprom (file 'ath-eeprom-dump.bin' and screen)\n"
 | |
| +		"-d      dump EEPROM (file 'ath-eeprom-dump.bin' and screen)\n"
 | |
| +		"-R <addr>       read register at <addr> (hex)\n"
 | |
| +		"-W <addr> <val> write <val> (hex) into register at <addr> (hex)\n"
 | |
|  		"<base_address>  device base address (see lspci output)\n\n");
 | |
|  
 | |
|  	fprintf(stderr,
 | |
| @@ -725,8 +1514,8 @@ static void usage(const char *n)
 | |
|  		"  %s -w <base_address> regdomain N\n\n"
 | |
|  		"- set a PCI id field to value N:\n"
 | |
|  		"  %s -w <base_address> <field> N\n"
 | |
| -		"  where <field> is on of:\n    ", n, n, n);
 | |
| -	for (i = 0; i < eeprom_addr_len; i++)
 | |
| +		"  where <field> is one of:\n    ", n, n, n);
 | |
| +	for (i = 0; i < ARRAY_SIZE(eeprom_addr); i++)
 | |
|  		fprintf(stderr, " %s", eeprom_addr[i].name);
 | |
|  	fprintf(stderr, "\n\n");
 | |
|  	fprintf(stderr,
 | |
| @@ -739,19 +1528,457 @@ static void usage(const char *n)
 | |
|  		"unlawful radio transmissions!\n\n");
 | |
|  }
 | |
|  
 | |
| +static void dump_capabilities(struct ath5k_eeprom_info *ee)
 | |
| +{
 | |
| +	u_int8_t has_a, has_b, has_g, has_rfkill, turbog_dis, turboa_dis;
 | |
| +	u_int8_t xr2_dis, xr5_dis, has_crystal;
 | |
| +
 | |
| +	has_a = AR5K_EEPROM_HDR_11A(ee->ee_header);
 | |
| +	has_b = AR5K_EEPROM_HDR_11B(ee->ee_header);
 | |
| +	has_g = AR5K_EEPROM_HDR_11G(ee->ee_header);
 | |
| +	has_rfkill = AR5K_EEPROM_HDR_RFKILL(ee->ee_header);
 | |
| +	has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1);
 | |
| +	turbog_dis = AR5K_EEPROM_HDR_T_2GHZ_DIS(ee->ee_header);
 | |
| +	turboa_dis = AR5K_EEPROM_HDR_T_5GHZ_DIS(ee->ee_header);
 | |
| +	xr2_dis = AR5K_EEPROM_HDR_XR2_DIS(ee->ee_misc0);
 | |
| +	xr5_dis = AR5K_EEPROM_HDR_XR5_DIS(ee->ee_misc0);
 | |
| +
 | |
| +	printf("|================= Capabilities ================|\n");
 | |
| +
 | |
| +	printf("| 802.11a Support: ");
 | |
| +	if (has_a)
 | |
| +		printf(" yes |");
 | |
| +	else
 | |
| +		printf(" no  |");
 | |
| +
 | |
| +	printf(" Turbo-A disabled:");
 | |
| +	if (turboa_dis)
 | |
| +		printf(" yes |\n");
 | |
| +	else
 | |
| +		printf(" no  |\n");
 | |
| +
 | |
| +	printf("| 802.11b Support: ");
 | |
| +	if (has_b)
 | |
| +		printf(" yes |");
 | |
| +	else
 | |
| +		printf(" no  |");
 | |
| +
 | |
| +	printf(" Turbo-G disabled:");
 | |
| +	if (turbog_dis)
 | |
| +		printf(" yes |\n");
 | |
| +	else
 | |
| +		printf(" no  |\n");
 | |
| +
 | |
| +	printf("| 802.11g Support: ");
 | |
| +	if (has_g)
 | |
| +		printf(" yes |");
 | |
| +	else
 | |
| +		printf(" no  |");
 | |
| +
 | |
| +	printf(" 2GHz XR disabled:");
 | |
| +	if (xr2_dis)
 | |
| +		printf(" yes |\n");
 | |
| +	else
 | |
| +		printf(" no  |\n");
 | |
| +
 | |
| +	printf("| RFKill  Support: ");
 | |
| +	if (has_rfkill)
 | |
| +		printf(" yes |");
 | |
| +	else
 | |
| +		printf(" no  |");
 | |
| +
 | |
| +	printf(" 5GHz XR disabled:");
 | |
| +	if (xr5_dis)
 | |
| +		printf(" yes |\n");
 | |
| +	else
 | |
| +		printf(" no  |\n");
 | |
| +
 | |
| +	if (has_crystal != 2) {
 | |
| +		printf("| 32kHz   Crystal: ");
 | |
| +		if (has_crystal)
 | |
| +			printf(" yes |");
 | |
| +		else
 | |
| +			printf(" no  |");
 | |
| +
 | |
| +		printf("                       |\n");
 | |
| +	}
 | |
| +
 | |
| +	printf("\\===============================================/\n");
 | |
| +}
 | |
| +
 | |
| +static void dump_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
 | |
| +{
 | |
| +	int i;
 | |
| +
 | |
| +	printf("|=========================================================|\n");
 | |
| +	printf("| I power:              0x%02x |", ee->ee_i_cal[mode]);
 | |
| +	printf(" Q power:              0x%02x |\n", ee->ee_q_cal[mode]);
 | |
| +	printf("| Use fixed bias:       0x%02x |", ee->ee_fixed_bias[mode]);
 | |
| +	printf(" Max turbo power:      0x%02x |\n", ee->ee_turbo_max_power[mode]);
 | |
| +	printf("| Max XR power:         0x%02x |", ee->ee_xr_power[mode]);
 | |
| +	printf(" Switch Settling Time: 0x%02x |\n", ee->ee_switch_settling[mode]);
 | |
| +	printf("| Tx/Rx attenuation:    0x%02x |", ee->ee_ant_tx_rx[mode]);
 | |
| +	printf(" TX end to XLNA On:    0x%02x |\n", ee->ee_tx_end2xlna_enable[mode]);
 | |
| +	printf("| TX end to XPA Off:    0x%02x |", ee->ee_tx_end2xpa_disable[mode]);
 | |
| +	printf(" TX end to XPA On:     0x%02x |\n", ee->ee_tx_frm2xpa_enable[mode]);
 | |
| +	printf("| 62db Threshold:       0x%02x |", ee->ee_thr_62[mode]);
 | |
| +	printf(" XLNA gain:            0x%02x |\n", ee->ee_xlna_gain[mode]);
 | |
| +	printf("| XPD:                  0x%02x |", ee->ee_xpd[mode]);
 | |
| +	printf(" XPD gain:             0x%02x |\n", ee->ee_x_gain[mode]);
 | |
| +	printf("| I gain:               0x%02x |", ee->ee_i_gain[mode]);
 | |
| +	printf(" Tx/Rx margin:         0x%02x |\n", ee->ee_margin_tx_rx[mode]);
 | |
| +	printf("| False detect backoff: 0x%02x |", ee->ee_false_detect[mode]);
 | |
| +	printf(" Noise Floor Threshold: %3d |\n", ee->ee_noise_floor_thr[mode]);
 | |
| +	printf("| ADC desired size:      %3d |", ee->ee_adc_desired_size[mode]);
 | |
| +	printf(" PGA desired size:      %3d |\n", ee->ee_pga_desired_size[mode]);
 | |
| +	printf("|=========================================================|\n");
 | |
| +	for (i = 0; i < AR5K_EEPROM_N_PCDAC; i++) {
 | |
| +		printf("| Antenna control  %2i:  0x%02x |", i, ee->ee_ant_control[mode][i]);
 | |
| +		i++;
 | |
| +		printf(" Antenna control  %2i:  0x%02x |\n", i, ee->ee_ant_control[mode][i]);
 | |
| +	}
 | |
| +	printf("|=========================================================|\n");
 | |
| +	for (i = 0; i < AR5K_EEPROM_N_OBDB; i++) {
 | |
| +		printf("| Octave Band %i:          %2i |", i, ee->ee_ob[mode][i]);
 | |
| +		printf(" db %i:                   %2i |\n", i, ee->ee_db[mode][i]);
 | |
| +	}
 | |
| +	printf("\\=========================================================/\n");
 | |
| +}
 | |
| +
 | |
| +static void dump_power_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
 | |
| +{
 | |
| +	struct ath5k_chan_pcal_info *chan_pcal_info;
 | |
| +	u_int16_t cal_piers;
 | |
| +	int i, c;
 | |
| +
 | |
| +	switch (mode) {
 | |
| +	case AR5K_EEPROM_MODE_11A:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_a;
 | |
| +		cal_piers = ee->ee_cal_piers_a;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11B:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_b;
 | |
| +		cal_piers = ee->ee_cal_piers_b;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11G:
 | |
| +		chan_pcal_info = ee->ee_pwr_cal_g;
 | |
| +		cal_piers = ee->ee_cal_piers_g;
 | |
| +		break;
 | |
| +	default:
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	printf("/=================== Per channel power calibration ====================\\\n");
 | |
| +	printf("| Freq | pwr_0 | pwr_1 | pwr_2 | pwr_3 |pwrx3_0|pwrx3_1|pwrx3_2|max_pwr|\n");
 | |
| +	printf("|      | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac | pcdac |       |\n");
 | |
| +
 | |
| +	for (i = 0; i < cal_piers; i++) {
 | |
| +		char buf[16];
 | |
| +
 | |
| +		printf("|======|=======|=======|=======|=======|=======|=======|=======|=======|\n");
 | |
| +		printf("| %4i |", chan_pcal_info[i].freq);
 | |
| +		for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
 | |
| +			printf(" %2i.%02i |", chan_pcal_info[i].pwr_x0[c] / 4,
 | |
| +			       chan_pcal_info[i].pwr_x0[c] % 4);
 | |
| +		}
 | |
| +		for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
 | |
| +			printf(" %2i.%02i |", chan_pcal_info[i].pwr_x3[c] / 4,
 | |
| +			       chan_pcal_info[i].pwr_x3[c] % 4);
 | |
| +		}
 | |
| +		printf(" %2i.%02i |\n", chan_pcal_info[i].max_pwr / 4,
 | |
| +		       chan_pcal_info[i].max_pwr % 4);
 | |
| +
 | |
| +		printf("|      |");
 | |
| +		for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
 | |
| +			snprintf(buf, sizeof(buf), "[%i]",
 | |
| +				 chan_pcal_info[i].pcdac_x0[c]);
 | |
| +			printf("%6s |", buf);
 | |
| +		}
 | |
| +		for (c = 0; c < AR5K_EEPROM_N_XPD3_POINTS; c++) {
 | |
| +			snprintf(buf, sizeof(buf), "[%i]",
 | |
| +				 chan_pcal_info[i].pcdac_x3[c]);
 | |
| +			printf("%6s |", buf);
 | |
| +		}
 | |
| +		printf("       |\n");
 | |
| +
 | |
| +	}
 | |
| +	printf("\\======================================================================/\n");
 | |
| +}
 | |
| +
 | |
| +static void dump_rate_calinfo_for_mode(int mode, struct ath5k_eeprom_info *ee)
 | |
| +{
 | |
| +	int i;
 | |
| +	struct ath5k_rate_pcal_info *rate_pcal_info;
 | |
| +	u_int16_t rate_target_pwr_num;
 | |
| +
 | |
| +	switch (mode) {
 | |
| +	case AR5K_EEPROM_MODE_11A:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_a;
 | |
| +		rate_target_pwr_num = ee->ee_rate_target_pwr_num_a;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11B:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_b;
 | |
| +		rate_target_pwr_num = ee->ee_rate_target_pwr_num_b;
 | |
| +		break;
 | |
| +	case AR5K_EEPROM_MODE_11G:
 | |
| +		rate_pcal_info = ee->ee_rate_tpwr_g;
 | |
| +		rate_target_pwr_num = ee->ee_rate_target_pwr_num_g;
 | |
| +		break;
 | |
| +	default:
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	printf("/============== Per rate power calibration ===========\\\n");
 | |
| +	if (mode == AR5K_EEPROM_MODE_11B)
 | |
| +		printf("| Freq |   1Mbit/s  | 2Mbit/s  | 5.5Mbit/s | 11Mbit/s |\n");
 | |
| +	else
 | |
| +		printf("| Freq | 6-24Mbit/s | 36Mbit/s |  48Mbit/s | 54Mbit/s |\n");
 | |
| +
 | |
| +	for (i = 0; i < rate_target_pwr_num; i++) {
 | |
| +
 | |
| +		printf("|======|============|==========|===========|==========|\n");
 | |
| +		printf("| %4i |", rate_pcal_info[i].freq);
 | |
| +		printf("    %2i.%02i   |",rate_pcal_info[i].target_power_6to24 /2,
 | |
| +					rate_pcal_info[i].target_power_6to24 % 2);
 | |
| +		printf("  %2i.%02i   |",rate_pcal_info[i].target_power_36 /2,
 | |
| +					rate_pcal_info[i].target_power_36 % 2);
 | |
| +		printf("   %2i.%02i   |",rate_pcal_info[i].target_power_48 /2,
 | |
| +					rate_pcal_info[i].target_power_48 % 2);
 | |
| +		printf("  %2i.%02i   |\n",rate_pcal_info[i].target_power_54 /2,
 | |
| +					rate_pcal_info[i].target_power_54 % 2);
 | |
| +	}
 | |
| +	printf("\\=====================================================/\n");
 | |
| +}
 | |
| +
 | |
| +static u_int32_t extend_tu(u_int32_t base_tu, u_int32_t val, u_int32_t mask)
 | |
| +{
 | |
| +	u_int32_t result;
 | |
| +
 | |
| +	result = (base_tu & ~mask) | (val & mask);
 | |
| +	if ((base_tu & mask) > (val & mask))
 | |
| +		result += mask + 1;
 | |
| +	return result;
 | |
| +}
 | |
| +
 | |
| +static void dump_timers_register(void *mem, u_int16_t mac_version)
 | |
| +{
 | |
| +#define AR5K_TIMER0_5210		0x802c	/* next TBTT */
 | |
| +#define AR5K_TIMER0_5211		0x8028
 | |
| +#define AR5K_TIMER0			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
 | |
| +
 | |
| +#define AR5K_TIMER1_5210		0x8030	/* next DMA beacon */
 | |
| +#define AR5K_TIMER1_5211		0x802c
 | |
| +#define AR5K_TIMER1			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
 | |
| +
 | |
| +#define AR5K_TIMER2_5210		0x8034	/* next SWBA interrupt */
 | |
| +#define AR5K_TIMER2_5211		0x8030
 | |
| +#define AR5K_TIMER2			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
 | |
| +
 | |
| +#define AR5K_TIMER3_5210		0x8038	/* next ATIM window */
 | |
| +#define AR5K_TIMER3_5211		0x8034
 | |
| +#define AR5K_TIMER3			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
 | |
| +
 | |
| +#define AR5K_TSF_L32_5210		0x806c	/* TSF (lower 32 bits) */
 | |
| +#define AR5K_TSF_L32_5211		0x804c
 | |
| +#define AR5K_TSF_L32			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
 | |
| +
 | |
| +#define AR5K_TSF_U32_5210		0x8070
 | |
| +#define AR5K_TSF_U32_5211		0x8050
 | |
| +#define AR5K_TSF_U32			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
 | |
| +
 | |
| +#define AR5K_BEACON_5210		0x8024
 | |
| +#define AR5K_BEACON_5211		0x8020
 | |
| +#define AR5K_BEACON			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_BEACON_5210 : AR5K_BEACON_5211)
 | |
| +
 | |
| +#define AR5K_LAST_TSTP			0x8080
 | |
| +
 | |
| +	const int timer_mask = 0xffff;
 | |
| +
 | |
| +	u_int32_t timer0, timer1, timer2, timer3, now_tu;
 | |
| +	u_int32_t timer0_tu, timer1_tu, timer2_tu, timer3_tu;
 | |
| +	u_int64_t now_tsf;
 | |
| +
 | |
| +	timer0 = AR5K_REG_READ(AR5K_TIMER0);		/* 0x0000ffff */
 | |
| +	timer1 = AR5K_REG_READ(AR5K_TIMER1_5211);	/* 0x0007ffff */
 | |
| +	timer2 = AR5K_REG_READ(AR5K_TIMER2_5211);	/* 0x?1ffffff */
 | |
| +	timer3 = AR5K_REG_READ(AR5K_TIMER3_5211);	/* 0x0000ffff */
 | |
| +
 | |
| +	now_tsf = ((u_int64_t)AR5K_REG_READ(AR5K_TSF_U32_5211) << 32)
 | |
| +		| (u_int64_t)AR5K_REG_READ(AR5K_TSF_L32_5211);
 | |
| +
 | |
| +	now_tu = now_tsf >> 10;
 | |
| +
 | |
| +	timer0_tu = extend_tu(now_tu, timer0, 0xffff);
 | |
| +	printf("TIMER0: 0x%08x, TBTT: %5u, TU: 0x%08x\n", timer0,
 | |
| +	       timer0 & timer_mask, timer0_tu);
 | |
| +	timer1_tu = extend_tu(now_tu, timer1 >> 3, 0x7ffff >> 3);
 | |
| +	printf("TIMER1: 0x%08x, DMAb: %5u, TU: 0x%08x (%+d)\n", timer1,
 | |
| +	       (timer1 >> 3) & timer_mask, timer1_tu, timer1_tu - timer0_tu);
 | |
| +	timer2_tu = extend_tu(now_tu, timer2 >> 3, 0x1ffffff >> 3);
 | |
| +	printf("TIMER2: 0x%08x, SWBA: %5u, TU: 0x%08x (%+d)\n", timer2,
 | |
| +	       (timer2 >> 3) & timer_mask, timer2_tu, timer2_tu - timer0_tu);
 | |
| +	timer3_tu = extend_tu(now_tu, timer3, 0xffff);
 | |
| +	printf("TIMER3: 0x%08x, ATIM: %5u, TU: 0x%08x (%+d)\n", timer3,
 | |
| +	       timer3 & timer_mask, timer3_tu, timer3_tu - timer0_tu);
 | |
| +	printf("TSF: 0x%016llx, TSFTU: %5u, TU: 0x%08x\n",
 | |
| +	       (unsigned long long)now_tsf, now_tu & timer_mask, now_tu);
 | |
| +
 | |
| +	printf("BEACON: 0x%08x\n", AR5K_REG_READ(AR5K_BEACON));
 | |
| +	printf("LAST_TSTP: 0x%08x\n", AR5K_REG_READ(AR5K_LAST_TSTP));
 | |
| +}
 | |
| +
 | |
| +#define AR5K_KEYTABLE_0_5210		0x9000
 | |
| +#define AR5K_KEYTABLE_0_5211		0x8800
 | |
| +#define AR5K_KEYTABLE_0			(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_KEYTABLE_0_5210 : \
 | |
| +					AR5K_KEYTABLE_0_5211)
 | |
| +
 | |
| +#define AR5K_KEYTABLE(_n)		(AR5K_KEYTABLE_0_5211 + ((_n) << 5))
 | |
| +#define AR5K_KEYTABLE_OFF(_n, x)	(AR5K_KEYTABLE(_n) + ((x) << 2))
 | |
| +#define AR5K_KEYTABLE_VALID		0x00008000
 | |
| +
 | |
| +#define AR5K_KEYTABLE_SIZE_5210		64
 | |
| +#define AR5K_KEYTABLE_SIZE_5211		128
 | |
| +#define AR5K_KEYTABLE_SIZE		(mac_version == AR5K_SREV_MAC_AR5210 ? \
 | |
| +					AR5K_KEYTABLE_SIZE_5210 : \
 | |
| +					AR5K_KEYTABLE_SIZE_5211)
 | |
| +
 | |
| +static void keycache_dump(void *mem, u_int16_t mac_version)
 | |
| +{
 | |
| +	int i, keylen;
 | |
| +	u_int32_t val0, val1, val2, val3, val4, keytype, ant, mac0, mac1;
 | |
| +
 | |
| +	/* dump all 128 entries */
 | |
| +	printf("Dumping keycache entries...\n");
 | |
| +	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) {
 | |
| +		mac1 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 7));
 | |
| +		if (mac1 & AR5K_KEYTABLE_VALID) {
 | |
| +			val0    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 0));
 | |
| +			val1    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 1));
 | |
| +			val2    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 2));
 | |
| +			val3    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 3));
 | |
| +			val4    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 4));
 | |
| +			keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 5));
 | |
| +			ant = keytype & 8;
 | |
| +			keytype &= ~8;
 | |
| +			switch (keytype) {
 | |
| +			case 0: /* WEP40  */ keylen =  40 / 8; break;
 | |
| +			case 1: /* WEP104 */ keylen = 104 / 8; break;
 | |
| +			case 3: /* WEP128 */ keylen = 128 / 8; break;
 | |
| +			case 4: /* TKIP   */ keylen = 128 / 8; break;
 | |
| +			case 5: /* AES    */ keylen = 128 / 8; break;
 | |
| +			case 6: /* CCM    */ keylen = 128 / 8; break;
 | |
| +			default:             keylen = 0;       break;
 | |
| +			}
 | |
| +			mac0 = AR5K_REG_READ(AR5K_KEYTABLE_OFF(i, 6));
 | |
| +
 | |
| +			printf("[%3u] keytype %d [%s%s%s%s%s%s%s%s] mac %02x:%02x:%02x:%02x:%02x:%02x key:%08x-%08x-%08x-%08x-%08x\n",
 | |
| +			       i,
 | |
| +			       keytype,
 | |
| +			       keytype == 0 ? "WEP40 " : "",
 | |
| +			       keytype == 1 ? "WEP104" : "",
 | |
| +			       keytype == 3 ? "WEP128" : "",
 | |
| +			       keytype == 4 ? "TKIP  " : "",
 | |
| +			       keytype == 5 ? "AES   " : "",
 | |
| +			       keytype == 6 ? "CCM   " : "",
 | |
| +			       keytype == 7 ? "NULL  " : "",
 | |
| +			       ant     == 8 ? "+ANT"   : "",
 | |
| +			       ((mac0 <<  1) & 0xff),
 | |
| +			       ((mac0 >>  7) & 0xff),
 | |
| +			       ((mac0 >> 15) & 0xff),
 | |
| +			       ((mac0 >> 23) & 0xff),
 | |
| +			       ((mac1 <<  1) & 0xff) | (mac0 >> 31),
 | |
| +			       ((mac1 >>  7) & 0xff),
 | |
| +			       val0, val1, val2, val3, val4);
 | |
| +		}
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +/* copy key index (0) to key index (idx) */
 | |
| +
 | |
| +static void keycache_copy(void *mem, u_int16_t mac_version, int idx)
 | |
| +{
 | |
| +	u_int32_t val0, val1, val2, val3, val4, keytype, mac0, mac1;
 | |
| +
 | |
| +	printf("Copying keycache entry 0 to %d\n", idx);
 | |
| +	if (idx < 0 || idx >= AR5K_KEYTABLE_SIZE) {
 | |
| +		printf("invalid keycache index\n");
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	val0    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 0));
 | |
| +	val1    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 1));
 | |
| +	val2    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 2));
 | |
| +	val3    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 3));
 | |
| +	val4    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 4));
 | |
| +	keytype = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 5));
 | |
| +	mac0    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 6));
 | |
| +	mac1    = AR5K_REG_READ(AR5K_KEYTABLE_OFF(0, 7));
 | |
| +
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 0), val0);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 1), val1);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 2), val2);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 3), val3);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 4), val4);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 5), keytype);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 6), mac0);
 | |
| +	AR5K_REG_WRITE(AR5K_KEYTABLE_OFF(idx, 7), mac1);
 | |
| +}
 | |
| +
 | |
| +static void sta_id0_id1_dump(void *mem)
 | |
| +{
 | |
| +#define AR5K_STA_ID0			0x8000
 | |
| +#define AR5K_STA_ID1			0x8004
 | |
| +#define AR5K_STA_ID1_AP                 0x00010000
 | |
| +#define AR5K_STA_ID1_ADHOC              0x00020000
 | |
| +#define AR5K_STA_ID1_NO_KEYSRCH		0x00080000
 | |
| +
 | |
| +	u_int32_t sta_id0, sta_id1;
 | |
| +
 | |
| +	sta_id0 = AR5K_REG_READ(AR5K_STA_ID0);
 | |
| +	sta_id1 = AR5K_REG_READ(AR5K_STA_ID1);
 | |
| +	printf("STA_ID0: %02x:%02x:%02x:%02x:%02x:%02x\n",
 | |
| +	       (sta_id0 >>  0) & 0xff,
 | |
| +	       (sta_id0 >>  8) & 0xff,
 | |
| +	       (sta_id0 >> 16) & 0xff,
 | |
| +	       (sta_id0 >> 24) & 0xff,
 | |
| +	       (sta_id1 >>  0) & 0xff,
 | |
| +	       (sta_id1 >>  8) & 0xff);
 | |
| +	printf("STA_ID1: 0x%08x, AP: %d, IBSS: %d, KeyCache Disable: %d\n",
 | |
| +	       sta_id1,
 | |
| +	       sta_id1 & AR5K_STA_ID1_AP ? 1 : 0,
 | |
| +	       sta_id1 & AR5K_STA_ID1_ADHOC ? 1 : 0,
 | |
| +	       sta_id1 & AR5K_STA_ID1_NO_KEYSRCH ? 1 : 0);
 | |
| +}
 | |
| +
 | |
|  int
 | |
|  CMD(athinfo)(int argc, char *argv[])
 | |
|  {
 | |
| -	u_int32_t dev_addr;
 | |
| -	u_int16_t eeprom_header, srev, phy_rev_5ghz, phy_rev_2ghz;
 | |
| -	u_int16_t eeprom_version, mac_version, regdomain, has_crystal, ee_magic;
 | |
| -	u_int8_t error, has_a, has_b, has_g, has_rfkill, eeprom_size;
 | |
| -	int byte_size = 0;
 | |
| +	unsigned long long dev_addr;
 | |
| +	u_int16_t srev, phy_rev_5ghz, phy_rev_2ghz, ee_magic;
 | |
| +	u_int8_t mac_version, mac_revision;
 | |
| +	u_int8_t error, eeprom_size, dev_type, eemap;
 | |
| +	struct ath5k_eeprom_info *ee;
 | |
| +	unsigned int byte_size = 0;
 | |
|  	void *mem;
 | |
|  	int fd;
 | |
| -	int i, anr = 1;
 | |
| +	unsigned int i;
 | |
| +	int anr = 1;
 | |
|  	int do_write = 0;	/* default: read only */
 | |
|  	int do_dump = 0;
 | |
| +	int reg_read = 0;
 | |
| +	int reg_write = 0;
 | |
| +	unsigned int reg_write_val = 0;
 | |
| +	unsigned int timer_count = 1;
 | |
| +	int do_keycache_dump = 0;
 | |
| +	int keycache_copy_idx = 0;
 | |
|  
 | |
|  	struct {
 | |
|  		int valid;
 | |
| @@ -759,7 +1986,7 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  	} gpio_set[AR5K_NUM_GPIO];
 | |
|  	int nr_gpio_set = 0;
 | |
|  
 | |
| -	for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++)
 | |
| +	for (i = 0; i < ARRAY_SIZE(gpio_set); i++)
 | |
|  		gpio_set[i].valid = 0;
 | |
|  
 | |
|  	if (argc < 2) {
 | |
| @@ -769,6 +1996,15 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  
 | |
|  	while (anr < argc && argv[anr][0] == '-') {
 | |
|  		switch (argv[anr][1]) {
 | |
| +		case 't':
 | |
| +			if (++anr < argc) {
 | |
| +				timer_count = atoi(argv[anr]);
 | |
| +				printf("timer_count:%d\n", timer_count);
 | |
| +			} else {
 | |
| +				usage(argv[0]);
 | |
| +				return 0;
 | |
| +			}
 | |
| +			break;
 | |
|  		case 'w':
 | |
|  			do_write = 1;
 | |
|  			break;
 | |
| @@ -777,7 +2013,7 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  			if (strlen(argv[anr]) != 3 || argv[anr][1] != ':' ||
 | |
|  			    argv[anr][0] < '0' || argv[anr][0] > '5' ||
 | |
|  			    (argv[anr][2] != '0' && argv[anr][2] != '1')) {
 | |
| -				err("invalid gpio spec. %s", argv[anr]);
 | |
| +				err("invalid GPIO spec. %s", argv[anr]);
 | |
|  				return 2;
 | |
|  			}
 | |
|  			gpio_set[argv[anr][0] - '0'].valid = 1;
 | |
| @@ -797,6 +2033,25 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  			do_dump = 1;
 | |
|  			break;
 | |
|  
 | |
| +		case 'R':
 | |
| +			anr++;
 | |
| +			reg_read = strtoul(argv[anr], NULL, 16);
 | |
| +			break;
 | |
| +
 | |
| +		case 'W':
 | |
| +			anr++;
 | |
| +			reg_write = strtoul(argv[anr++], NULL, 16);
 | |
| +			reg_write_val = strtoul(argv[anr], NULL, 16);
 | |
| +			break;
 | |
| +
 | |
| +		case 'k':
 | |
| +			do_keycache_dump = 1;
 | |
| +			break;
 | |
| +
 | |
| +		case 'K':
 | |
| +			keycache_copy_idx = atoi(argv[++anr]);
 | |
| +			break;
 | |
| +
 | |
|  		case 'h':
 | |
|  			usage(argv[0]);
 | |
|  			return 0;
 | |
| @@ -805,10 +2060,10 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		default:
 | |
|  			err("unknown option %s", argv[anr]);
 | |
|  			return 2;
 | |
| -		}		/* switch (argv[anr][1]) */
 | |
| +		}
 | |
|  
 | |
|  		anr++;
 | |
| -	}			/* while (anr < argc && ...) */
 | |
| +	}
 | |
|  
 | |
|  	if (anr >= argc) {
 | |
|  		err("missing device address");
 | |
| @@ -816,7 +2071,7 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		return 3;
 | |
|  	}
 | |
|  
 | |
| -	dev_addr = strtoul(argv[anr], NULL, 16);
 | |
| +	dev_addr = strtoull(argv[anr], NULL, 16);
 | |
|  
 | |
|  	fd = open("/dev/mem", O_RDWR);
 | |
|  	if (fd < 0) {
 | |
| @@ -828,7 +2083,7 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		   MAP_SHARED | MAP_FILE, fd, dev_addr);
 | |
|  
 | |
|  	if (mem == MAP_FAILED) {
 | |
| -		printf("Mmap of device at 0x%08X for 0x%X bytes failed - "
 | |
| +		printf("mmap of device at 0x%08llX for 0x%X bytes failed - "
 | |
|  		       "%s\n", dev_addr, AR5K_PCI_MEM_SIZE, strerror(errno));
 | |
|  		return -3;
 | |
|  	}
 | |
| @@ -856,10 +2111,31 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  	AR5K_REG_DISABLE_BITS(AR5K_PCICFG, AR5K_PCICFG_SPWR_DN);
 | |
|  	usleep(500);
 | |
|  
 | |
| +	if (reg_read) {
 | |
| +		printf("READ %04x = %08x\n", reg_read, AR5K_REG_READ(reg_read));
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
| +	if (reg_write) {
 | |
| +		printf("WRITE %04x = %08x\n", reg_write, reg_write_val);
 | |
| +		AR5K_REG_WRITE(reg_write, reg_write_val);
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
|  	srev = AR5K_REG_READ(AR5K_SREV);
 | |
| -	mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER) << 4;
 | |
| +	if (srev >= 0x0100) {
 | |
| +		printf("MAC revision 0x%04x is not supported!\n", srev);
 | |
| +		return -1;
 | |
| +	}
 | |
| +	mac_version = srev & AR5K_SREV_VER;
 | |
| +	mac_revision = srev & AR5K_SREV_REV;
 | |
|  
 | |
| -	/* Verify eeprom magic value first */
 | |
| +	printf(" -==Device Information==-\n");
 | |
| +
 | |
| +	printf("MAC Revision: %-5s (0x%02x)\n",
 | |
| +	       ath5k_hw_get_mac_name(mac_revision), mac_revision);
 | |
| +
 | |
| +	/* Verify EEPROM magic value first */
 | |
|  	error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MAGIC, &ee_magic,
 | |
|  				     mac_version);
 | |
|  
 | |
| @@ -872,157 +2148,114 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		printf("Warning: Invalid EEPROM Magic number!\n");
 | |
|  	}
 | |
|  
 | |
| -	error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_HDR, &eeprom_header,
 | |
| -				     mac_version);
 | |
| -
 | |
| -	if (error) {
 | |
| -		printf("Unable to read EEPROM Header!\n");
 | |
| -		return -1;
 | |
| -	}
 | |
| -
 | |
| -	error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_VERSION, &eeprom_version,
 | |
| -				     mac_version);
 | |
| -
 | |
| -	if (error) {
 | |
| -		printf("Unable to read EEPROM version!\n");
 | |
| +	ee = calloc(sizeof(struct ath5k_eeprom_info), 1);
 | |
| +	if (!ee) {
 | |
| +		printf("Cannot allocate memory for EEPROM information\n");
 | |
|  		return -1;
 | |
|  	}
 | |
|  
 | |
| -	error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_REG_DOMAIN, ®domain,
 | |
| -				     mac_version);
 | |
| -
 | |
| -	if (error) {
 | |
| -		printf("Unable to read Regdomain!\n");
 | |
| +	if (ath5k_eeprom_init(mem, mac_version, ee)) {
 | |
| +		printf("EEPROM init failed\n");
 | |
|  		return -1;
 | |
|  	}
 | |
|  
 | |
| -	if (eeprom_version >= 0x4000) {
 | |
| -		error = ath5k_hw_eeprom_read(mem, AR5K_EEPROM_MISC0,
 | |
| -					     &has_crystal, mac_version);
 | |
| -
 | |
| -		if (error) {
 | |
| -			printf("Unable to read EEPROM Misc data!\n");
 | |
| -			return -1;
 | |
| -		}
 | |
| -
 | |
| -		has_crystal = AR5K_EEPROM_HAS32KHZCRYSTAL(has_crystal);
 | |
| -	} else {
 | |
| -		has_crystal = 2;
 | |
| -	}
 | |
| -
 | |
|  	eeprom_size = AR5K_REG_MS(AR5K_REG_READ(AR5K_PCICFG),
 | |
|  				  AR5K_PCICFG_EESIZE);
 | |
|  
 | |
| -	has_a = AR5K_EEPROM_HDR_11A(eeprom_header);
 | |
| -	has_b = AR5K_EEPROM_HDR_11B(eeprom_header);
 | |
| -	has_g = AR5K_EEPROM_HDR_11G(eeprom_header);
 | |
| -	has_rfkill = AR5K_EEPROM_HDR_RFKILL(eeprom_header);
 | |
| +	dev_type = AR5K_EEPROM_HDR_DEVICE(ee->ee_header);
 | |
| +	eemap = AR5K_EEPROM_EEMAP(ee->ee_misc0);
 | |
|  
 | |
| -	if (has_a)
 | |
| +	/* 1 = ?? 2 = ?? 3 = card 4 = wmac */
 | |
| +	printf("Device type:  %1i\n", dev_type);
 | |
| +
 | |
| +	if (AR5K_EEPROM_HDR_11A(ee->ee_header))
 | |
|  		phy_rev_5ghz = ath5k_hw_radio_revision(mac_version, mem, 1);
 | |
|  	else
 | |
|  		phy_rev_5ghz = 0;
 | |
|  
 | |
| -	if (has_b)
 | |
| +	if (AR5K_EEPROM_HDR_11B(ee->ee_header))
 | |
|  		phy_rev_2ghz = ath5k_hw_radio_revision(mac_version, mem, 0);
 | |
|  	else
 | |
|  		phy_rev_2ghz = 0;
 | |
|  
 | |
| -	printf(" -==Device Information==-\n");
 | |
| -
 | |
| -	printf("MAC Version:  %-5s (0x%02x)\n",
 | |
| -	       ath5k_hw_get_part_name(AR5K_VERSION_VER, mac_version),
 | |
| -	       mac_version);
 | |
| -
 | |
| -	printf("MAC Revision: %-5s (0x%02x)\n",
 | |
| -	       ath5k_hw_get_part_name(AR5K_VERSION_VER, srev), srev);
 | |
| -
 | |
| -	/* Single-chip PHY with a/b/g support */
 | |
| -	if (has_b && !phy_rev_2ghz) {
 | |
| -		printf("PHY Revision: %-5s (0x%02x)\n",
 | |
| -		       ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz),
 | |
| -		       phy_rev_5ghz);
 | |
| -		phy_rev_5ghz = 0;
 | |
| -	}
 | |
| -
 | |
| -	/* Single-chip PHY with b/g support */
 | |
| -	if (!has_a) {
 | |
| -		printf("PHY Revision: %-5s (0x%02x)\n",
 | |
| -		       ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz),
 | |
| -		       phy_rev_2ghz);
 | |
| -		phy_rev_2ghz = 0;
 | |
| -	}
 | |
| -
 | |
| -	/* Different chip for 5Ghz and 2Ghz */
 | |
|  	if (phy_rev_5ghz) {
 | |
| -		printf("5Ghz PHY Revision: %-5s (0x%2x)\n",
 | |
| -		       ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_5ghz),
 | |
| -		       phy_rev_5ghz);
 | |
| +		printf("5GHz PHY Revision: %-5s (0x%02x)\n",
 | |
| +		       ath5k_hw_get_phy_name(phy_rev_5ghz), phy_rev_5ghz);
 | |
|  	}
 | |
|  	if (phy_rev_2ghz) {
 | |
| -		printf("2Ghz PHY Revision: %-5s (0x%2x)\n",
 | |
| -		       ath5k_hw_get_part_name(AR5K_VERSION_RAD, phy_rev_2ghz),
 | |
| -		       phy_rev_2ghz);
 | |
| +		printf("2GHz PHY Revision: %-5s (0x%02x)\n",
 | |
| +		       ath5k_hw_get_phy_name(phy_rev_2ghz), phy_rev_2ghz);
 | |
|  	}
 | |
|  
 | |
| -	printf(" -==EEPROM Information==-\n");
 | |
| -
 | |
| -	printf("EEPROM Version:     %x.%x\n",
 | |
| -	       (eeprom_version & 0xF000) >> 12, eeprom_version & 0xFFF);
 | |
| +	printf("\n");
 | |
| +	printf("/============== EEPROM Information =============\\\n");
 | |
| +	printf("| EEPROM Version:   %1x.%1x |",
 | |
| +	       (ee->ee_version & 0xF000) >> 12, ee->ee_version & 0xFFF);
 | |
|  
 | |
| -	printf("EEPROM Size: ");
 | |
| +	printf(" EEPROM Size: ");
 | |
|  
 | |
|  	if (eeprom_size == 0) {
 | |
| -		printf("       4K\n");
 | |
| -		byte_size = 4096;
 | |
| +		printf("  4 kbit |\n");
 | |
| +		byte_size = 4096 / 8;
 | |
|  	} else if (eeprom_size == 1) {
 | |
| -		printf("       8K\n");
 | |
| -		byte_size = 8192;
 | |
| +		printf("  8 kbit |\n");
 | |
| +		byte_size = 8192 / 8;
 | |
|  	} else if (eeprom_size == 2) {
 | |
| -		printf("       16K\n");
 | |
| -		byte_size = 16384;
 | |
| +		printf(" 16 kbit |\n");
 | |
| +		byte_size = 16384 / 8;
 | |
|  	} else
 | |
| -		printf("       ??\n");
 | |
| +		printf(" unknown |\n");
 | |
|  
 | |
| -	printf("Regulatory Domain:  0x%X\n", regdomain);
 | |
| -
 | |
| -	printf(" -==== Capabilities ====-\n");
 | |
| -
 | |
| -	printf("|  802.11a Support: ");
 | |
| -	if (has_a)
 | |
| -		printf("yes  |\n");
 | |
| -	else
 | |
| -		printf("no   |\n");
 | |
| -
 | |
| -	printf("|  802.11b Support: ");
 | |
| -	if (has_b)
 | |
| -		printf("yes  |\n");
 | |
| -	else
 | |
| -		printf("no   |\n");
 | |
| +	printf("| EEMAP:              %i |", eemap);
 | |
|  
 | |
| -	printf("|  802.11g Support: ");
 | |
| -	if (has_g)
 | |
| -		printf("yes  |\n");
 | |
| -	else
 | |
| -		printf("no   |\n");
 | |
| +	printf(" Reg. Domain:     0x%02X |\n", ee->ee_regdomain);
 | |
|  
 | |
| -	printf("|  RFKill  Support: ");
 | |
| -	if (has_rfkill)
 | |
| -		printf("yes  |\n");
 | |
| -	else
 | |
| -		printf("no   |\n");
 | |
| +	dump_capabilities(ee);
 | |
| +	printf("\n");
 | |
|  
 | |
| -	if (has_crystal != 2) {
 | |
| -		printf("|  32KHz   Crystal: ");
 | |
| -		if (has_crystal)
 | |
| -			printf("yes  |\n");
 | |
| -		else
 | |
| -			printf("no   |\n");
 | |
| +	printf("/=========================================================\\\n");
 | |
| +	printf("|          Calibration data common for all modes          |\n");
 | |
| +	printf("|=========================================================|\n");
 | |
| +	printf("|          CCK/OFDM gain delta:            %2i             |\n", ee->ee_cck_ofdm_gain_delta);
 | |
| +	printf("|          CCK/OFDM power delta:           %2i             |\n", ee->ee_cck_ofdm_power_delta);
 | |
| +	printf("|          Scaled CCK delta:               %2i             |\n", ee->ee_scaled_cck_delta);
 | |
| +	printf("|          2GHz Antenna gain:              %2i             |\n", AR5K_EEPROM_ANT_GAIN_2GHZ(ee->ee_ant_gain));
 | |
| +	printf("|          5GHz Antenna gain:              %2i             |\n", AR5K_EEPROM_ANT_GAIN_5GHZ(ee->ee_ant_gain));
 | |
| +	printf("|          Turbo 2W maximum dBm:           %2i             |\n", AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header));
 | |
| +	printf("|          Target power start:          0x%03x             |\n", AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1));
 | |
| +	printf("|          EAR Start:                   0x%03x             |\n", AR5K_EEPROM_EARSTART(ee->ee_misc0));
 | |
| +	printf("\\=========================================================/\n");
 | |
| +
 | |
| +	printf("\n");
 | |
| +	if (AR5K_EEPROM_HDR_11A(ee->ee_header)) {
 | |
| +		printf("/=========================================================\\\n");
 | |
| +		printf("|          Calibration data for 802.11a operation         |\n");
 | |
| +		dump_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
 | |
| +		dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
 | |
| +		dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11A, ee);
 | |
| +		printf("\n");
 | |
| +	}
 | |
| +
 | |
| +	if (AR5K_EEPROM_HDR_11B(ee->ee_header)) {
 | |
| +		printf("/=========================================================\\\n");
 | |
| +		printf("|          Calibration data for 802.11b operation         |\n");
 | |
| +		dump_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
 | |
| +		dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
 | |
| +		dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11B, ee);
 | |
| +		printf("\n");
 | |
| +	}
 | |
| +
 | |
| +	if (AR5K_EEPROM_HDR_11G(ee->ee_header)) {
 | |
| +		printf("/=========================================================\\\n");
 | |
| +		printf("|          Calibration data for 802.11g operation         |\n");
 | |
| +		dump_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
 | |
| +		dump_rate_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
 | |
| +		dump_power_calinfo_for_mode(AR5K_EEPROM_MODE_11G, ee);
 | |
| +		printf("\n");
 | |
|  	}
 | |
| -	printf(" ========================\n");
 | |
|  
 | |
|  	/* print current GPIO settings */
 | |
| -	printf("GPIO registers: CR %08x DO %08x DI %08x\n",
 | |
| +	printf("GPIO registers: CR 0x%08x, DO 0x%08x, DI 0x%08x\n",
 | |
|  	       AR5K_REG_READ(AR5K_GPIOCR), AR5K_REG_READ(AR5K_GPIODO),
 | |
|  	       AR5K_REG_READ(AR5K_GPIODI));
 | |
|  
 | |
| @@ -1030,18 +2263,18 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		u_int16_t data;
 | |
|  		FILE *dumpfile = fopen("ath-eeprom-dump.bin", "w");
 | |
|  
 | |
| -		printf("\nEEPROM dump (%d byte)\n", byte_size);
 | |
| +		printf("\nEEPROM dump (%d bytes)\n", byte_size);
 | |
|  		printf("==============================================");
 | |
| -		for (i = 1; i <= (byte_size / 2); i++) {
 | |
| +		for (i = 0; i < byte_size / 2; i++) {
 | |
|  			error =
 | |
|  			    ath5k_hw_eeprom_read(mem, i, &data, mac_version);
 | |
|  			if (error) {
 | |
|  				printf("\nUnable to read at %04x\n", i);
 | |
|  				continue;
 | |
|  			}
 | |
| -			if (!((i - 1) % 8))
 | |
| -				printf("\n%04x:  ", i);
 | |
| -			printf("%04x ", data);
 | |
| +			if (!(i % 8))
 | |
| +				printf("\n%04x: ", i);
 | |
| +			printf(" %04x", data);
 | |
|  			fwrite(&data, 2, 1, dumpfile);
 | |
|  		}
 | |
|  		printf("\n==============================================\n");
 | |
| @@ -1054,18 +2287,18 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  		u_int32_t old_cr = rcr, old_do = rdo;
 | |
|  		int rc;
 | |
|  
 | |
| -		if (mac_version >= AR5K_SREV_VER_AR5213 && !nr_gpio_set) {
 | |
| -			dbg("new MAC %x (>= AR5213) set gpio4 to low",
 | |
| +		if (mac_version >= AR5K_SREV_MAC_AR5213 && !nr_gpio_set) {
 | |
| +			dbg("new MAC %x (>= AR5213) set GPIO4 to low",
 | |
|  			    mac_version);
 | |
|  			gpio_set[4].valid = 1;
 | |
|  			gpio_set[4].value = 0;
 | |
|  		}
 | |
|  
 | |
| -		/* set gpios */
 | |
| +		/* set GPIOs */
 | |
|  		dbg("old GPIO CR %08x DO %08x DI %08x",
 | |
|  		    rcr, rdo, AR5K_REG_READ(AR5K_GPIODI));
 | |
|  
 | |
| -		for (i = 0; i < sizeof(gpio_set) / sizeof(gpio_set[0]); i++) {
 | |
| +		for (i = 0; i < ARRAY_SIZE(gpio_set); i++) {
 | |
|  			if (gpio_set[i].valid) {
 | |
|  				rcr |= AR5K_GPIOCR_OUT(i);	/* we use mode 3 */
 | |
|  				rcr &= ~AR5K_GPIOCR_INT_SEL(i);
 | |
| @@ -1111,5 +2344,17 @@ CMD(athinfo)(int argc, char *argv[])
 | |
|  
 | |
|  		return rc;
 | |
|  	}
 | |
| +
 | |
| +	sta_id0_id1_dump(mem);
 | |
| +
 | |
| +	for (i = 0; i < timer_count; i++)
 | |
| +		dump_timers_register(mem, mac_version);
 | |
| +
 | |
| +	if (do_keycache_dump)
 | |
| +		keycache_dump(mem, mac_version);
 | |
| +
 | |
| +	if (keycache_copy_idx > 0)
 | |
| +		keycache_copy(mem, mac_version, keycache_copy_idx);
 | |
| +
 | |
|  	return 0;
 | |
|  }
 |