diff options
Diffstat (limited to 'drivers/net/acenic.c')
-rw-r--r-- | drivers/net/acenic.c | 117 |
1 files changed, 71 insertions, 46 deletions
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 517fce48d94a..5b396ff6c83f 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/mm.h> | 66 | #include <linux/mm.h> |
67 | #include <linux/highmem.h> | 67 | #include <linux/highmem.h> |
68 | #include <linux/sockios.h> | 68 | #include <linux/sockios.h> |
69 | #include <linux/firmware.h> | ||
69 | 70 | ||
70 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 71 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
71 | #include <linux/if_vlan.h> | 72 | #include <linux/if_vlan.h> |
@@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); | |||
186 | #define MAX_RODATA_LEN 8*1024 | 187 | #define MAX_RODATA_LEN 8*1024 |
187 | #define MAX_DATA_LEN 2*1024 | 188 | #define MAX_DATA_LEN 2*1024 |
188 | 189 | ||
189 | #include "acenic_firmware.h" | ||
190 | |||
191 | #ifndef tigon2FwReleaseLocal | 190 | #ifndef tigon2FwReleaseLocal |
192 | #define tigon2FwReleaseLocal 0 | 191 | #define tigon2FwReleaseLocal 0 |
193 | #endif | 192 | #endif |
@@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; | |||
417 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); | 416 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); |
418 | MODULE_LICENSE("GPL"); | 417 | MODULE_LICENSE("GPL"); |
419 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); | 418 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); |
419 | #ifndef CONFIG_ACENIC_OMIT_TIGON_I | ||
420 | MODULE_FIRMWARE("acenic/tg1.bin"); | ||
421 | #endif | ||
422 | MODULE_FIRMWARE("acenic/tg2.bin"); | ||
420 | 423 | ||
421 | module_param_array_named(link, link_state, int, NULL, 0); | 424 | module_param_array_named(link, link_state, int, NULL, 0); |
422 | module_param_array(trace, int, NULL, 0); | 425 | module_param_array(trace, int, NULL, 0); |
@@ -943,8 +946,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
943 | case 4: | 946 | case 4: |
944 | case 5: | 947 | case 5: |
945 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", | 948 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", |
946 | tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor, | 949 | tig_ver, ap->firmware_major, ap->firmware_minor, |
947 | tigonFwReleaseFix); | 950 | ap->firmware_fix); |
948 | writel(0, ®s->LocalCtrl); | 951 | writel(0, ®s->LocalCtrl); |
949 | ap->version = 1; | 952 | ap->version = 1; |
950 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; | 953 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; |
@@ -952,8 +955,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
952 | #endif | 955 | #endif |
953 | case 6: | 956 | case 6: |
954 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", | 957 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", |
955 | tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor, | 958 | tig_ver, ap->firmware_major, ap->firmware_minor, |
956 | tigon2FwReleaseFix); | 959 | ap->firmware_fix); |
957 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); | 960 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); |
958 | readl(®s->CpuBCtrl); /* PCI write posting */ | 961 | readl(®s->CpuBCtrl); /* PCI write posting */ |
959 | /* | 962 | /* |
@@ -1205,7 +1208,9 @@ static int __devinit ace_init(struct net_device *dev) | |||
1205 | memset(ap->info, 0, sizeof(struct ace_info)); | 1208 | memset(ap->info, 0, sizeof(struct ace_info)); |
1206 | memset(ap->skb, 0, sizeof(struct ace_skb)); | 1209 | memset(ap->skb, 0, sizeof(struct ace_skb)); |
1207 | 1210 | ||
1208 | ace_load_firmware(dev); | 1211 | if (ace_load_firmware(dev)) |
1212 | goto init_error; | ||
1213 | |||
1209 | ap->fw_running = 0; | 1214 | ap->fw_running = 0; |
1210 | 1215 | ||
1211 | tmp_ptr = ap->info_dma; | 1216 | tmp_ptr = ap->info_dma; |
@@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev) | |||
1441 | if (ap->version >= 2) | 1446 | if (ap->version >= 2) |
1442 | writel(tmp, ®s->TuneFastLink); | 1447 | writel(tmp, ®s->TuneFastLink); |
1443 | 1448 | ||
1444 | if (ACE_IS_TIGON_I(ap)) | 1449 | writel(ap->firmware_start, ®s->Pc); |
1445 | writel(tigonFwStartAddr, ®s->Pc); | ||
1446 | if (ap->version == 2) | ||
1447 | writel(tigon2FwStartAddr, ®s->Pc); | ||
1448 | 1450 | ||
1449 | writel(0, ®s->Mb0Lo); | 1451 | writel(0, ®s->Mb0Lo); |
1450 | 1452 | ||
@@ -2761,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev, | |||
2761 | 2763 | ||
2762 | strlcpy(info->driver, "acenic", sizeof(info->driver)); | 2764 | strlcpy(info->driver, "acenic", sizeof(info->driver)); |
2763 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", | 2765 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", |
2764 | tigonFwReleaseMajor, tigonFwReleaseMinor, | 2766 | ap->firmware_major, ap->firmware_minor, |
2765 | tigonFwReleaseFix); | 2767 | ap->firmware_fix); |
2766 | 2768 | ||
2767 | if (ap->pdev) | 2769 | if (ap->pdev) |
2768 | strlcpy(info->bus_info, pci_name(ap->pdev), | 2770 | strlcpy(info->bus_info, pci_name(ap->pdev), |
@@ -2869,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) | |||
2869 | } | 2871 | } |
2870 | 2872 | ||
2871 | 2873 | ||
2872 | static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | 2874 | static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src, |
2873 | u32 dest, int size) | 2875 | u32 dest, int size) |
2874 | { | 2876 | { |
2875 | void __iomem *tdest; | 2877 | void __iomem *tdest; |
2876 | u32 *wsrc; | ||
2877 | short tsize, i; | 2878 | short tsize, i; |
2878 | 2879 | ||
2879 | if (size <= 0) | 2880 | if (size <= 0) |
@@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | |||
2885 | tdest = (void __iomem *) ®s->Window + | 2886 | tdest = (void __iomem *) ®s->Window + |
2886 | (dest & (ACE_WINDOW_SIZE - 1)); | 2887 | (dest & (ACE_WINDOW_SIZE - 1)); |
2887 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); | 2888 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); |
2888 | /* | ||
2889 | * This requires byte swapping on big endian, however | ||
2890 | * writel does that for us | ||
2891 | */ | ||
2892 | wsrc = src; | ||
2893 | for (i = 0; i < (tsize / 4); i++) { | 2889 | for (i = 0; i < (tsize / 4); i++) { |
2894 | writel(wsrc[i], tdest + i*4); | 2890 | /* Firmware is big-endian */ |
2891 | writel(be32_to_cpup(src), tdest); | ||
2892 | src++; | ||
2893 | tdest += 4; | ||
2894 | dest += 4; | ||
2895 | size -= 4; | ||
2895 | } | 2896 | } |
2896 | dest += tsize; | ||
2897 | src += tsize; | ||
2898 | size -= tsize; | ||
2899 | } | 2897 | } |
2900 | |||
2901 | return; | ||
2902 | } | 2898 | } |
2903 | 2899 | ||
2904 | 2900 | ||
@@ -2937,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz | |||
2937 | */ | 2933 | */ |
2938 | static int __devinit ace_load_firmware(struct net_device *dev) | 2934 | static int __devinit ace_load_firmware(struct net_device *dev) |
2939 | { | 2935 | { |
2936 | const struct firmware *fw; | ||
2937 | const char *fw_name = "acenic/tg2.bin"; | ||
2940 | struct ace_private *ap = netdev_priv(dev); | 2938 | struct ace_private *ap = netdev_priv(dev); |
2941 | struct ace_regs __iomem *regs = ap->regs; | 2939 | struct ace_regs __iomem *regs = ap->regs; |
2940 | const __be32 *fw_data; | ||
2941 | u32 load_addr; | ||
2942 | int ret; | ||
2942 | 2943 | ||
2943 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { | 2944 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { |
2944 | printk(KERN_ERR "%s: trying to download firmware while the " | 2945 | printk(KERN_ERR "%s: trying to download firmware while the " |
@@ -2946,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev) | |||
2946 | return -EFAULT; | 2947 | return -EFAULT; |
2947 | } | 2948 | } |
2948 | 2949 | ||
2950 | if (ACE_IS_TIGON_I(ap)) | ||
2951 | fw_name = "acenic/tg1.bin"; | ||
2952 | |||
2953 | ret = request_firmware(&fw, fw_name, &ap->pdev->dev); | ||
2954 | if (ret) { | ||
2955 | printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", | ||
2956 | ap->name, fw_name); | ||
2957 | return ret; | ||
2958 | } | ||
2959 | |||
2960 | fw_data = (void *)fw->data; | ||
2961 | |||
2962 | /* Firmware blob starts with version numbers, followed by | ||
2963 | load and start address. Remainder is the blob to be loaded | ||
2964 | contiguously from load address. We don't bother to represent | ||
2965 | the BSS/SBSS sections any more, since we were clearing the | ||
2966 | whole thing anyway. */ | ||
2967 | ap->firmware_major = fw->data[0]; | ||
2968 | ap->firmware_minor = fw->data[1]; | ||
2969 | ap->firmware_fix = fw->data[2]; | ||
2970 | |||
2971 | ap->firmware_start = be32_to_cpu(fw_data[1]); | ||
2972 | if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) { | ||
2973 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
2974 | ap->name, ap->firmware_start, fw_name); | ||
2975 | ret = -EINVAL; | ||
2976 | goto out; | ||
2977 | } | ||
2978 | |||
2979 | load_addr = be32_to_cpu(fw_data[2]); | ||
2980 | if (load_addr < 0x4000 || load_addr >= 0x80000) { | ||
2981 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
2982 | ap->name, load_addr, fw_name); | ||
2983 | ret = -EINVAL; | ||
2984 | goto out; | ||
2985 | } | ||
2986 | |||
2949 | /* | 2987 | /* |
2950 | * Do not try to clear more than 512KB or we end up seeing | 2988 | * Do not try to clear more than 512KiB or we end up seeing |
2951 | * funny things on NICs with only 512KB SRAM | 2989 | * funny things on NICs with only 512KiB SRAM |
2952 | */ | 2990 | */ |
2953 | ace_clear(regs, 0x2000, 0x80000-0x2000); | 2991 | ace_clear(regs, 0x2000, 0x80000-0x2000); |
2954 | if (ACE_IS_TIGON_I(ap)) { | 2992 | ace_copy(regs, &fw_data[3], load_addr, fw->size-12); |
2955 | ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen); | 2993 | out: |
2956 | ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen); | 2994 | release_firmware(fw); |
2957 | ace_copy(regs, tigonFwRodata, tigonFwRodataAddr, | 2995 | return ret; |
2958 | tigonFwRodataLen); | ||
2959 | ace_clear(regs, tigonFwBssAddr, tigonFwBssLen); | ||
2960 | ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen); | ||
2961 | }else if (ap->version == 2) { | ||
2962 | ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen); | ||
2963 | ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen); | ||
2964 | ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen); | ||
2965 | ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr, | ||
2966 | tigon2FwRodataLen); | ||
2967 | ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen); | ||
2968 | } | ||
2969 | |||
2970 | return 0; | ||
2971 | } | 2996 | } |
2972 | 2997 | ||
2973 | 2998 | ||