Here is a method to change mac address or PID/VID on a Atheros 5414A Mini-PCI Card. I had two identical cards and one of them had severed problems to be detected, both on a Linux (openwrt) Router and on a Windows Laptop...
After inspection of the two eeproms content, i've seen the macaddress was not set on the bad card (ff:ff:ff:ff:ff:ff). I don't remember how that happened, maybe i had a special driver before which was ignoring this bad mac address... Or maybe this card came from a dual pci card router to support Dual Range 2.4Ghz + 5Ghz
For your information the mac address ff:ff:ff:ff:ff:ff is used for network broadcast.
I have modified the 2.6.35 ubuntu ath5k kernel module to add abilities to write to I2C eeprom.
I had to remove the Write Protect 10K Resistor from the wifi card (which is a bad thing ;), but you just have to connect WP pin to GND (this pin is protected in I²C eeprom to be connected directly to GND or VCC)
Click to enlarge
in /usr/src/linux-source-2.6.35/drivers/net/wireless/ath/ath5k/eeprom.c add :
/* * Write to eeprom */ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 *data) { u32 status, timeout; *data &= 0xffff; /* * Initialize EEPROM access */ if (ah->ah_version == AR5K_AR5210) { // AR5210 not tested here but... AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset)); } else { ath5k_hw_reg_write(ah, 0, AR5K_EEPROM_CMD); udelay(30); AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_RESET); udelay(30); ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); ath5k_hw_reg_write(ah, *data, AR5K_EEPROM_DATA); AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, AR5K_EEPROM_CMD_WRITE); udelay(30); } for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); if (status & AR5K_EEPROM_STAT_WRDONE) { if (status & AR5K_EEPROM_STAT_WRERR) { printk(KERN_ERR " TP: -EIO"); return -EIO; } ath5k_hw_eeprom_read(ah, offset, data); printk(KERN_INFO " Check: %04x", *data); return 0; } udelay(15); } status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); printk(KERN_ERR " status: %x", status); printk(KERN_ERR " TP: -ETIMEDOUT"); ath5k_hw_reg_write(ah, 0, AR5K_EEPROM_STATUS); ath5k_hw_eeprom_read(ah, offset, data); printk(KERN_ERR " Check: %x", (u32) *data); return -ETIMEDOUT; }
Then write the macaddress to eeprom, before the read... here is the modified procedure (last proc in eeprom.c) :
/* * Read the MAC address from eeprom */ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) { u8 mac_d[ETH_ALEN] = {}; u32 total, offset; u16 data; int octet, ret; printk(KERN_INFO "TP: writing eeprom mac addr..."); // mac address offset=0x00a5; data=0x0300; ret = ath5k_hw_eeprom_write(ah, offset, &data); offset=0x00a6; data=0x057f; ret = ath5k_hw_eeprom_write(ah, offset, &data); offset=0x00a7; data=0x1234; ret = ath5k_hw_eeprom_write(ah, offset, &data); // mac address is present at two places, this second offset is reversed (CRC ?) offset=0x001d; data=0x3412; ret = ath5k_hw_eeprom_write(ah, offset, &data); offset=0x001e; data=0x7f05; ret = ath5k_hw_eeprom_write(ah, offset, &data); offset=0x001f; data=0x0003; ret = ath5k_hw_eeprom_write(ah, offset, &data); printk(KERN_INFO "TP: reading eeprom mac addr..."); //DUMP EEPROM TO SYSLOG for (offset = 0; offset <= 0x2ff; offset++) { data = 0; ret = ath5k_hw_eeprom_read(ah, offset, &data); if (ret) printk (KERN_ERR "%04x:XXXX", offset); else printk (KERN_ERR "%04x:%04x", offset, data); } ret = ath5k_hw_eeprom_read(ah, 0x20, &data); if (ret) printk(KERN_ERR "TP: eeprom read error : %d", ret); for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { ret = ath5k_hw_eeprom_read(ah, offset, &data); if (ret) printk(KERN_ERR "TP: eeprom read error offset %x : %d", offset, ret); //return ret; total += data; mac_d[octet + 1] = data & 0xff; mac_d[octet] = data >> 8; octet += 2; } if (!total || total == 3 * 0xffff) { // prevent buggy ff:ff:ff:ff:ff:ff mac-address printk(KERN_ERR "TP: bad mac-adress = ff:ff:ff:ff:ff:ff"); mac_d[0]=0x30; //return -EINVAL; } memcpy(mac, mac_d, ETH_ALEN); return 0; }
Compile the module :
First, you need kernel sources and headers.
Go to your kernel base dir, here /usr/src/linux-source-2.6.35
make -C /lib/modules/2.6.35-27-generic/build \ SUBDIRS=/usr/src/linux-source-2.6.35/drivers/net/wireless/ath/ath5k modules
Check the module dependencies with modinfo or lsmod and load them in a wifi.sh script :
modprobe -r ath5k modprobe cfg80211 modprobe led_class modprobe mac80211 modprobe ath insmod /usr/src/linux-source-2.6.35/drivers/net/wireless/ath/ath5k/ath5k.ko
With this method, vermagic could also be different.... the make modules_install is useless because its for a oneshot write.
You can download the content of my two cards eeproms, the bad one was fixed by this procedure, but its the original eeprom content, before the change.
There is no CRC for the beginning of the EEPROM (offset 0x00 to 0xC0)
check file eeprom.h for more info...
Links :
- http://wireless.kernel.org/en/users/Drivers/ath5k
- http://wireless.kernel.org/en/users/Drivers/ath
- http://kerneltrap.org/mailarchive/linux-ath5k-devel/2008/11/18/4148304
- http://lxr.free-electrons.com/source/drivers/net/wireless/ath/ath5k/
- http://www.mobilnews.cz/blog/?p=36
Attachment | Size | Downloads | Last Download |
---|---|---|---|
bad_eeprom_AR5414A_v5002.hex_.txt | 11 KB | 4115 | 5 days 17 hours ago |
good_eeprom_AR5414A_v5003.hex_.txt | 11 KB | 4264 | 5 days 17 hours ago |
Recent comments
9 years 36 weeks ago
9 years 38 weeks ago
9 years 41 weeks ago
9 years 47 weeks ago
10 years 15 weeks ago
10 years 16 weeks ago
10 years 24 weeks ago
10 years 24 weeks ago
10 years 25 weeks ago
10 years 25 weeks ago