#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/firmware.h>
#include <net/dst.h>
#include <net/arp.h>
#include <asm/irq.h>
#include "myri_sbus.h"
-#include "myri_code.h"
/* #define DEBUG_DETECT */
/* #define DEBUG_IRQ */
#define DHDR(x)
#endif
+/* Firmware name */
+#define FWNAME "myricom/lanai.bin"
+
static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
{
/* Clear IRQ mask. */
static int __devinit myri_load_lanai(struct myri_eth *mp)
{
+ const struct firmware *fw;
struct net_device *dev = mp->dev;
struct myri_shmem __iomem *shmem = mp->shmem;
void __iomem *rptr;
- int i;
+ int i, lanai4_data_size;
myri_disable_irq(mp->lregs, mp->cregs);
myri_reset_on(mp->cregs);
if (mp->eeprom.cpuvers >= CPUVERS_3_0)
sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
+ i = request_firmware(&fw, FWNAME, &mp->myri_op->dev);
+ if (i) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ FWNAME, i);
+ return i;
+ }
+ if (fw->size < 2) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, FWNAME);
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ lanai4_data_size = fw->data[0] << 8 | fw->data[1];
+
/* Load executable code. */
- for (i = 0; i < sizeof(lanai4_code); i++)
- sbus_writeb(lanai4_code[i], rptr + (lanai4_code_off * 2) + i);
+ for (i = 2; i < fw->size; i++)
+ sbus_writeb(fw->data[i], rptr++);
/* Load data segment. */
- for (i = 0; i < sizeof(lanai4_data); i++)
- sbus_writeb(lanai4_data[i], rptr + (lanai4_data_off * 2) + i);
+ for (i = 0; i < lanai4_data_size; i++)
+ sbus_writeb(0, rptr++);
/* Set device address. */
sbus_writeb(0, &shmem->addr[0]);
if (mp->eeprom.cpuvers == CPUVERS_4_0)
sbus_writel(0, mp->lregs + LANAI_VERS);
+ release_firmware(fw);
return i;
}
.cache_update = myri_header_cache_update,
};
+static const struct net_device_ops myri_ops = {
+ .ndo_open = myri_open,
+ .ndo_stop = myri_close,
+ .ndo_start_xmit = myri_start_xmit,
+ .ndo_set_multicast_list = myri_set_multicast,
+ .ndo_tx_timeout = myri_tx_timeout,
+ .ndo_change_mtu = myri_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match)
{
struct device_node *dp = op->node;
sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
mp->dev = dev;
- dev->open = &myri_open;
- dev->stop = &myri_close;
- dev->hard_start_xmit = &myri_start_xmit;
- dev->tx_timeout = &myri_tx_timeout;
dev->watchdog_timeo = 5*HZ;
- dev->set_multicast_list = &myri_set_multicast;
dev->irq = op->irqs[0];
+ dev->netdev_ops = &myri_ops;
/* Register interrupt handler now. */
DET(("Requesting MYRIcom IRQ line.\n"));
}
dev->mtu = MYRINET_MTU;
- dev->change_mtu = myri_change_mtu;
dev->header_ops = &myri_header_ops;
dev->hard_header_len = (ETH_HLEN + MYRI_PAD_LEN);
/* Load code onto the LANai. */
DET(("Loading LANAI firmware\n"));
- myri_load_lanai(mp);
+ if (myri_load_lanai(mp)) {
+ printk(KERN_ERR "MyriCOM: Cannot Load LANAI firmware.\n");
+ goto err_free_irq;
+ }
if (register_netdev(dev)) {
printk("MyriCOM: Cannot register device.\n");
module_exit(myri_sbus_exit);
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(FWNAME);