| #include "core.h" |
| #include "debug.h" |
| #define MAC_FILE "ath6k/AR6003/hw2.1.1/softmac" |
| |
| /* Bleh, same offsets. */ |
| #define AR6003_MAC_ADDRESS_OFFSET 0x16 |
| #define AR6004_MAC_ADDRESS_OFFSET 0x16 |
| |
| /* Global variables, sane coding be damned. */ |
| u8 *ath6kl_softmac; |
| size_t ath6kl_softmac_len; |
| |
| static void ath6kl_calculate_crc(u32 target_type, u8 *data, size_t len) |
| { |
| u16 *crc, *data_idx; |
| u16 checksum; |
| int i; |
| |
| if (target_type == TARGET_TYPE_AR6003) { |
| crc = (u16 *)(data + 0x04); |
| } else if (target_type == TARGET_TYPE_AR6004) { |
| len = 1024; |
| crc = (u16 *)(data + 0x04); |
| } else { |
| ath6kl_err("Invalid target type\n"); |
| return; |
| } |
| |
| ath6kl_dbg(ATH6KL_DBG_BOOT, "Old Checksum: %u\n", *crc); |
| |
| *crc = 0; |
| checksum = 0; |
| data_idx = (u16 *)data; |
| |
| for (i = 0; i < len; i += 2) { |
| checksum = checksum ^ (*data_idx); |
| data_idx++; |
| } |
| |
| *crc = cpu_to_le16(checksum); |
| |
| ath6kl_dbg(ATH6KL_DBG_BOOT, "New Checksum: %u\n", checksum); |
| } |
| |
| static int ath6kl_fetch_mac_file(struct ath6kl *ar) |
| { |
| const struct firmware *fw_entry; |
| int ret = 0; |
| |
| |
| ret = request_firmware(&fw_entry, MAC_FILE, ar->dev); |
| if (ret) |
| return ret; |
| |
| ath6kl_softmac_len = fw_entry->size; |
| ath6kl_softmac = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL); |
| |
| if (ath6kl_softmac == NULL) |
| ret = -ENOMEM; |
| |
| release_firmware(fw_entry); |
| |
| return ret; |
| } |
| |
| void ath6kl_mangle_mac_address(struct ath6kl *ar) |
| { |
| u8 *ptr_mac; |
| int i, ret; |
| char mac_buf[128]; |
| unsigned int softmac[6]; |
| |
| switch (ar->target_type) { |
| case TARGET_TYPE_AR6003: |
| ptr_mac = ar->fw_board + AR6003_MAC_ADDRESS_OFFSET; |
| break; |
| case TARGET_TYPE_AR6004: |
| ptr_mac = ar->fw_board + AR6004_MAC_ADDRESS_OFFSET; |
| break; |
| default: |
| ath6kl_err("Invalid Target Type\n"); |
| return; |
| } |
| |
| printk( |
| "MAC from EEPROM %02X:%02X:%02X:%02X:%02X:%02X\n", |
| ptr_mac[0], ptr_mac[1], ptr_mac[2], |
| ptr_mac[3], ptr_mac[4], ptr_mac[5]); |
| |
| |
| ret = ath6kl_fetch_mac_file(ar); |
| if (ret) { |
| ath6kl_err("MAC address file not found\n"); |
| return; |
| } |
| |
| if (ath6kl_softmac_len > sizeof(mac_buf)) { |
| ath6kl_err("Invalid softmac file\n"); |
| return; |
| } |
| |
| memcpy(mac_buf, ath6kl_softmac, ath6kl_softmac_len); |
| mac_buf[ath6kl_softmac_len] = '\0'; |
| |
| if (sscanf(mac_buf, "%02x:%02x:%02x:%02x:%02x:%02x", |
| &softmac[0], &softmac[1], &softmac[2], |
| &softmac[3], &softmac[4], &softmac[5]) == 6) { |
| |
| for (i = 0; i < ETH_ALEN; ++i) { |
| ptr_mac[i] = softmac[i] & 0xff; |
| } |
| } |
| |
| printk( |
| "Soft MAC %02X:%02X:%02X:%02X:%02X:%02X\n", |
| ptr_mac[0], ptr_mac[1], ptr_mac[2], |
| ptr_mac[3], ptr_mac[4], ptr_mac[5]); |
| |
| |
| kfree(ath6kl_softmac); |
| |
| ath6kl_calculate_crc(ar->target_type, ar->fw_board, ar->fw_board_len); |
| } |