mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 11:16:11 +00:00
firmware: convert acenic driver to request_firmware()
We store the firmware in its native big-endian form now, so the loop in ace_copy() is modified to use be32_to_cpup() when writing it out. We can forget the BSS,SBSS sections of the firmware, since we were clearing all the device's RAM anyway. And the text,rodata,data sections can all be loaded as a single chunk since they're contiguous (give or take a few dozen bytes in between). Signed-off-by: Jaswinder Singh <jaswinder@infradead.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org> Acked-by: Jes Sorensen <jes@sgi.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
14deae4156
commit
949b42544a
6 changed files with 9511 additions and 47 deletions
|
@ -66,6 +66,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
|
||||
#include <linux/if_vlan.h>
|
||||
|
@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
|
|||
#define MAX_RODATA_LEN 8*1024
|
||||
#define MAX_DATA_LEN 2*1024
|
||||
|
||||
#include "acenic_firmware.h"
|
||||
|
||||
#ifndef tigon2FwReleaseLocal
|
||||
#define tigon2FwReleaseLocal 0
|
||||
#endif
|
||||
|
@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
|
|||
MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
|
||||
#ifndef CONFIG_ACENIC_OMIT_TIGON_I
|
||||
MODULE_FIRMWARE("acenic/tg1.bin");
|
||||
#endif
|
||||
MODULE_FIRMWARE("acenic/tg2.bin");
|
||||
|
||||
module_param_array_named(link, link_state, int, NULL, 0);
|
||||
module_param_array(trace, int, NULL, 0);
|
||||
|
@ -943,8 +946,8 @@ static int __devinit ace_init(struct net_device *dev)
|
|||
case 4:
|
||||
case 5:
|
||||
printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ",
|
||||
tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor,
|
||||
tigonFwReleaseFix);
|
||||
tig_ver, ap->firmware_major, ap->firmware_minor,
|
||||
ap->firmware_fix);
|
||||
writel(0, ®s->LocalCtrl);
|
||||
ap->version = 1;
|
||||
ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
|
||||
|
@ -952,8 +955,8 @@ static int __devinit ace_init(struct net_device *dev)
|
|||
#endif
|
||||
case 6:
|
||||
printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
|
||||
tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
|
||||
tigon2FwReleaseFix);
|
||||
tig_ver, ap->firmware_major, ap->firmware_minor,
|
||||
ap->firmware_fix);
|
||||
writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl);
|
||||
readl(®s->CpuBCtrl); /* PCI write posting */
|
||||
/*
|
||||
|
@ -1205,7 +1208,9 @@ static int __devinit ace_init(struct net_device *dev)
|
|||
memset(ap->info, 0, sizeof(struct ace_info));
|
||||
memset(ap->skb, 0, sizeof(struct ace_skb));
|
||||
|
||||
ace_load_firmware(dev);
|
||||
if (ace_load_firmware(dev))
|
||||
goto init_error;
|
||||
|
||||
ap->fw_running = 0;
|
||||
|
||||
tmp_ptr = ap->info_dma;
|
||||
|
@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev)
|
|||
if (ap->version >= 2)
|
||||
writel(tmp, ®s->TuneFastLink);
|
||||
|
||||
if (ACE_IS_TIGON_I(ap))
|
||||
writel(tigonFwStartAddr, ®s->Pc);
|
||||
if (ap->version == 2)
|
||||
writel(tigon2FwStartAddr, ®s->Pc);
|
||||
writel(ap->firmware_start, ®s->Pc);
|
||||
|
||||
writel(0, ®s->Mb0Lo);
|
||||
|
||||
|
@ -2761,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev,
|
|||
|
||||
strlcpy(info->driver, "acenic", sizeof(info->driver));
|
||||
snprintf(info->version, sizeof(info->version), "%i.%i.%i",
|
||||
tigonFwReleaseMajor, tigonFwReleaseMinor,
|
||||
tigonFwReleaseFix);
|
||||
ap->firmware_major, ap->firmware_minor,
|
||||
ap->firmware_fix);
|
||||
|
||||
if (ap->pdev)
|
||||
strlcpy(info->bus_info, pci_name(ap->pdev),
|
||||
|
@ -2869,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
|
|||
}
|
||||
|
||||
|
||||
static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
|
||||
u32 dest, int size)
|
||||
static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
|
||||
u32 dest, int size)
|
||||
{
|
||||
void __iomem *tdest;
|
||||
u32 *wsrc;
|
||||
short tsize, i;
|
||||
|
||||
if (size <= 0)
|
||||
|
@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
|
|||
tdest = (void __iomem *) ®s->Window +
|
||||
(dest & (ACE_WINDOW_SIZE - 1));
|
||||
writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase);
|
||||
/*
|
||||
* This requires byte swapping on big endian, however
|
||||
* writel does that for us
|
||||
*/
|
||||
wsrc = src;
|
||||
for (i = 0; i < (tsize / 4); i++) {
|
||||
writel(wsrc[i], tdest + i*4);
|
||||
/* Firmware is big-endian */
|
||||
writel(be32_to_cpup(src), tdest);
|
||||
src++;
|
||||
tdest += 4;
|
||||
dest += 4;
|
||||
size -= 4;
|
||||
}
|
||||
dest += tsize;
|
||||
src += tsize;
|
||||
size -= tsize;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2937,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
|
|||
*/
|
||||
static int __devinit ace_load_firmware(struct net_device *dev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const char *fw_name = "acenic/tg2.bin";
|
||||
struct ace_private *ap = netdev_priv(dev);
|
||||
struct ace_regs __iomem *regs = ap->regs;
|
||||
const __be32 *fw_data;
|
||||
u32 load_addr;
|
||||
int ret;
|
||||
|
||||
if (!(readl(®s->CpuCtrl) & CPU_HALTED)) {
|
||||
printk(KERN_ERR "%s: trying to download firmware while the "
|
||||
|
@ -2946,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not try to clear more than 512KB or we end up seeing
|
||||
* funny things on NICs with only 512KB SRAM
|
||||
*/
|
||||
ace_clear(regs, 0x2000, 0x80000-0x2000);
|
||||
if (ACE_IS_TIGON_I(ap)) {
|
||||
ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen);
|
||||
ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen);
|
||||
ace_copy(regs, tigonFwRodata, tigonFwRodataAddr,
|
||||
tigonFwRodataLen);
|
||||
ace_clear(regs, tigonFwBssAddr, tigonFwBssLen);
|
||||
ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen);
|
||||
}else if (ap->version == 2) {
|
||||
ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen);
|
||||
ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen);
|
||||
ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen);
|
||||
ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr,
|
||||
tigon2FwRodataLen);
|
||||
ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen);
|
||||
if (ACE_IS_TIGON_I(ap))
|
||||
fw_name = "acenic/tg1.bin";
|
||||
|
||||
ret = request_firmware(&fw, fw_name, &ap->pdev->dev);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
|
||||
ap->name, fw_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fw_data = (void *)fw->data;
|
||||
|
||||
/* Firmware blob starts with version numbers, followed by
|
||||
load and start address. Remainder is the blob to be loaded
|
||||
contiguously from load address. We don't bother to represent
|
||||
the BSS/SBSS sections any more, since we were clearing the
|
||||
whole thing anyway. */
|
||||
ap->firmware_major = fw->data[0];
|
||||
ap->firmware_minor = fw->data[1];
|
||||
ap->firmware_fix = fw->data[2];
|
||||
|
||||
ap->firmware_start = be32_to_cpu(fw_data[1]);
|
||||
if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
|
||||
printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
|
||||
ap->name, ap->firmware_start, fw_name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
load_addr = be32_to_cpu(fw_data[2]);
|
||||
if (load_addr < 0x4000 || load_addr >= 0x80000) {
|
||||
printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
|
||||
ap->name, load_addr, fw_name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not try to clear more than 512KiB or we end up seeing
|
||||
* funny things on NICs with only 512KiB SRAM
|
||||
*/
|
||||
ace_clear(regs, 0x2000, 0x80000-0x2000);
|
||||
ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
|
||||
out:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -694,6 +694,10 @@ struct ace_private
|
|||
u32 last_tx, last_std_rx, last_mini_rx;
|
||||
#endif
|
||||
int pci_using_dac;
|
||||
u8 firmware_major;
|
||||
u8 firmware_minor;
|
||||
u8 firmware_fix;
|
||||
u32 firmware_start;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,13 @@ fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE))
|
|||
# accurate. In the latter case it doesn't matter -- it'll use $(fw-shipped-all).
|
||||
# But be aware that the config file might not be included at all.
|
||||
|
||||
ifdef CONFIG_ACENIC_OMIT_TIGON_I
|
||||
acenic-objs := acenic/tg2.bin
|
||||
fw-shipped- += acenic/tg1.bin
|
||||
else
|
||||
acenic-objs := acenic/tg1.bin acenic/tg2.bin
|
||||
endif
|
||||
fw-shipped-$(CONFIG_ACENIC) += $(acenic-objs)
|
||||
fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin
|
||||
fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
|
||||
fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin
|
||||
|
|
|
@ -360,3 +360,14 @@ License: GPLv2 or OpenIB.org BSD license, no source visible
|
|||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Driver: acenic -- Alteon AceNIC Gigabit Ethernet card
|
||||
|
||||
File: acenic/tg1.bin
|
||||
File: acenic/tg2.bin
|
||||
|
||||
Licence: Unknown
|
||||
|
||||
Found in hex form in kernel source, but source allegedly available at
|
||||
http://alteon.shareable.org/
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
|
4573
firmware/acenic/tg1.bin.ihex
Normal file
4573
firmware/acenic/tg1.bin.ihex
Normal file
File diff suppressed because it is too large
Load diff
4844
firmware/acenic/tg2.bin.ihex
Normal file
4844
firmware/acenic/tg2.bin.ihex
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue