*/
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/crc32.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/irq.h>
+#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/dma.h>
+#include <asm/system.h>
#define TX_BUFFERS 15
#define RX_BUFFERS 25
#include "am79c961a.h"
static irqreturn_t
-am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+am79c961_interrupt (int irq, void *dev_id);
static unsigned int net_debug = NET_DEBUG;
#ifdef __arm__
static void write_rreg(u_long base, u_int reg, u_int val)
{
- __asm__("str%?h %1, [%2] @ NET_RAP
- str%?h %0, [%2, #-4] @ NET_RDP
- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
+ __asm__(
+ "str%?h %1, [%2] @ NET_RAP\n\t"
+ "str%?h %0, [%2, #-4] @ NET_RDP"
+ :
+ : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
}
static inline unsigned short read_rreg(u_long base_addr, u_int reg)
{
unsigned short v;
- __asm__("str%?h %1, [%2] @ NET_RAP
- ldr%?h %0, [%2, #-4] @ NET_RDP
- " : "=r" (v): "r" (reg), "r" (ISAIO_BASE + 0x0464));
+ __asm__(
+ "str%?h %1, [%2] @ NET_RAP\n\t"
+ "ldr%?h %0, [%2, #-4] @ NET_RDP"
+ : "=r" (v)
+ : "r" (reg), "r" (ISAIO_BASE + 0x0464));
return v;
}
static inline void write_ireg(u_long base, u_int reg, u_int val)
{
- __asm__("str%?h %1, [%2] @ NET_RAP
- str%?h %0, [%2, #8] @ NET_IDP
- " : : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
+ __asm__(
+ "str%?h %1, [%2] @ NET_RAP\n\t"
+ "str%?h %0, [%2, #8] @ NET_IDP"
+ :
+ : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
}
static inline unsigned short read_ireg(u_long base_addr, u_int reg)
u_short v;
__asm__(
"str%?h %1, [%2] @ NAT_RAP\n\t"
- "str%?h %0, [%2, #8] @ NET_IDP\n\t"
+ "ldr%?h %0, [%2, #8] @ NET_IDP\n\t"
: "=r" (v)
: "r" (reg), "r" (ISAIO_BASE + 0x0464));
return v;
}
while (length > 8) {
unsigned int tmp, tmp2;
- __asm__ __volatile__("
- ldm%?ia %1!, {%2, %3}
- str%?h %2, [%0], #4
- mov%? %2, %2, lsr #16
- str%?h %2, [%0], #4
- str%?h %3, [%0], #4
- mov%? %3, %3, lsr #16
- str%?h %3, [%0], #4
- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
- : "0" (offset), "1" (buf));
+ __asm__ __volatile__(
+ "ldm%?ia %1!, {%2, %3}\n\t"
+ "str%?h %2, [%0], #4\n\t"
+ "mov%? %2, %2, lsr #16\n\t"
+ "str%?h %2, [%0], #4\n\t"
+ "str%?h %3, [%0], #4\n\t"
+ "mov%? %3, %3, lsr #16\n\t"
+ "str%?h %3, [%0], #4"
+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
+ : "0" (offset), "1" (buf));
length -= 8;
}
while (length > 0) {
length = (length + 1) & ~1;
if ((int)buf & 2) {
unsigned int tmp;
- __asm__ __volatile__("
- ldr%?h %2, [%0], #4
- str%?b %2, [%1], #1
- mov%? %2, %2, lsr #8
- str%?b %2, [%1], #1
- " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
+ __asm__ __volatile__(
+ "ldr%?h %2, [%0], #4\n\t"
+ "str%?b %2, [%1], #1\n\t"
+ "mov%? %2, %2, lsr #8\n\t"
+ "str%?b %2, [%1], #1"
+ : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
length -= 2;
}
while (length > 8) {
unsigned int tmp, tmp2, tmp3;
- __asm__ __volatile__("
- ldr%?h %2, [%0], #4
- ldr%?h %3, [%0], #4
- orr%? %2, %2, %3, lsl #16
- ldr%?h %3, [%0], #4
- ldr%?h %4, [%0], #4
- orr%? %3, %3, %4, lsl #16
- stm%?ia %1!, {%2, %3}
- " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
- : "0" (offset), "1" (buf));
+ __asm__ __volatile__(
+ "ldr%?h %2, [%0], #4\n\t"
+ "ldr%?h %3, [%0], #4\n\t"
+ "orr%? %2, %2, %3, lsl #16\n\t"
+ "ldr%?h %3, [%0], #4\n\t"
+ "ldr%?h %4, [%0], #4\n\t"
+ "orr%? %3, %3, %4, lsl #16\n\t"
+ "stm%?ia %1!, {%2, %3}"
+ : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
+ : "0" (offset), "1" (buf));
length -= 8;
}
while (length > 0) {
unsigned int tmp;
- __asm__ __volatile__("
- ldr%?h %2, [%0], #4
- str%?b %2, [%1], #1
- mov%? %2, %2, lsr #8
- str%?b %2, [%1], #1
- " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
+ __asm__ __volatile__(
+ "ldr%?h %2, [%0], #4\n\t"
+ "str%?b %2, [%1], #1\n\t"
+ "mov%? %2, %2, lsr #8\n\t"
+ "str%?b %2, [%1], #1"
+ : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
length -= 2;
}
}
lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
carrier = netif_carrier_ok(dev);
- if (lnkstat && !carrier)
+ if (lnkstat && !carrier) {
netif_carrier_on(dev);
- else if (!lnkstat && carrier)
+ printk("%s: link up\n", dev->name);
+ } else if (!lnkstat && carrier) {
netif_carrier_off(dev);
+ printk("%s: link down\n", dev->name);
+ }
- mod_timer(&priv->timer, jiffies + 5*HZ);
+ mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
}
/*
}
static irqreturn_t
-am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+am79c961_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct dev_priv *priv = netdev_priv(dev);
if (status & CSR0_CERR) {
handled = 1;
mod_timer(&priv->timer, jiffies);
+ }
} while (--n && status & (CSR0_RINT | CSR0_TINT));
return IRQ_RETVAL(handled);
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void am79c961_poll_controller(struct net_device *dev)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ am79c961_interrupt(dev->irq, dev, NULL);
+ local_irq_restore(flags);
+}
+#endif
+
/*
* Initialise the chip. Note that we always expect
* to be entered with interrupts enabled.
printk(KERN_INFO "%s", version);
}
-static int __init am79c961_init(void)
+static int __init am79c961_probe(struct platform_device *pdev)
{
+ struct resource *res;
struct net_device *dev;
struct dev_priv *priv;
int i, ret;
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -ENODEV;
+
dev = alloc_etherdev(sizeof(struct dev_priv));
ret = -ENOMEM;
if (!dev)
goto out;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
priv = netdev_priv(dev);
/*
* The PNP initialisation should have been
* done by the ether bootp loader.
*/
- dev->base_addr = 0x220;
- dev->irq = IRQ_EBSA110_ETHERNET;
+ dev->base_addr = res->start;
+ dev->irq = platform_get_irq(pdev, 0);
- ret = -ENODEV;
+ ret = -ENODEV;
+ if (dev->irq < 0)
+ goto nodev;
if (!request_region(dev->base_addr, 0x18, dev->name))
goto nodev;
inb(dev->base_addr + 4) != 0x2b)
goto release;
- am79c961_banner();
- printk(KERN_INFO "%s: ether address ", dev->name);
-
- /* Retrive and print the ethernet address. */
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
- printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
- }
+
+ am79c961_banner();
spin_lock_init(&priv->chip_lock);
init_timer(&priv->timer);
dev->get_stats = am79c961_getstats;
dev->set_multicast_list = am79c961_setmulticastlist;
dev->tx_timeout = am79c961_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = am79c961_poll_controller;
+#endif
ret = register_netdev(dev);
- if (ret == 0)
+ if (ret == 0) {
+ printk(KERN_INFO "%s: ether address ", dev->name);
+
+ /* Retrive and print the ethernet address. */
+ for (i = 0; i < 6; i++)
+ printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
+
return 0;
+ }
release:
release_region(dev->base_addr, 0x18);
return ret;
}
+static struct platform_driver am79c961_driver = {
+ .probe = am79c961_probe,
+ .driver = {
+ .name = "am79c961",
+ },
+};
+
+static int __init am79c961_init(void)
+{
+ return platform_driver_register(&am79c961_driver);
+}
+
__initcall(am79c961_init);