diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
| commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
| tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/net/arm | |
| parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) | |
Diffstat (limited to 'drivers/net/arm')
| -rw-r--r-- | drivers/net/arm/Kconfig | 74 | ||||
| -rw-r--r-- | drivers/net/arm/Makefile | 14 | ||||
| -rw-r--r-- | drivers/net/arm/am79c961a.c | 770 | ||||
| -rw-r--r-- | drivers/net/arm/am79c961a.h | 145 | ||||
| -rw-r--r-- | drivers/net/arm/at91_ether.c | 1254 | ||||
| -rw-r--r-- | drivers/net/arm/at91_ether.h | 109 | ||||
| -rw-r--r-- | drivers/net/arm/ep93xx_eth.c | 904 | ||||
| -rw-r--r-- | drivers/net/arm/ether1.c | 1094 | ||||
| -rw-r--r-- | drivers/net/arm/ether1.h | 280 | ||||
| -rw-r--r-- | drivers/net/arm/ether3.c | 918 | ||||
| -rw-r--r-- | drivers/net/arm/ether3.h | 176 | ||||
| -rw-r--r-- | drivers/net/arm/etherh.c | 866 | ||||
| -rw-r--r-- | drivers/net/arm/ixp4xx_eth.c | 1489 | ||||
| -rw-r--r-- | drivers/net/arm/ks8695net.c | 1656 | ||||
| -rw-r--r-- | drivers/net/arm/ks8695net.h | 107 | ||||
| -rw-r--r-- | drivers/net/arm/w90p910_ether.c | 1123 |
16 files changed, 10979 insertions, 0 deletions
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig new file mode 100644 index 00000000000..39e1c0d3947 --- /dev/null +++ b/drivers/net/arm/Kconfig | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | # | ||
| 2 | # Acorn Network device configuration | ||
| 3 | # These are for Acorn's Expansion card network interfaces | ||
| 4 | # | ||
| 5 | config ARM_AM79C961A | ||
| 6 | bool "ARM EBSA110 AM79C961A support" | ||
| 7 | depends on ARM && ARCH_EBSA110 | ||
| 8 | select CRC32 | ||
| 9 | help | ||
| 10 | If you wish to compile a kernel for the EBSA-110, then you should | ||
| 11 | always answer Y to this. | ||
| 12 | |||
| 13 | config ARM_ETHER1 | ||
| 14 | tristate "Acorn Ether1 support" | ||
| 15 | depends on ARM && ARCH_ACORN | ||
| 16 | help | ||
| 17 | If you have an Acorn system with one of these (AKA25) network cards, | ||
| 18 | you should say Y to this option if you wish to use it with Linux. | ||
| 19 | |||
| 20 | config ARM_ETHER3 | ||
| 21 | tristate "Acorn/ANT Ether3 support" | ||
| 22 | depends on ARM && ARCH_ACORN | ||
| 23 | help | ||
| 24 | If you have an Acorn system with one of these network cards, you | ||
| 25 | should say Y to this option if you wish to use it with Linux. | ||
| 26 | |||
| 27 | config ARM_ETHERH | ||
| 28 | tristate "I-cubed EtherH/ANT EtherM support" | ||
| 29 | depends on ARM && ARCH_ACORN | ||
| 30 | select CRC32 | ||
| 31 | help | ||
| 32 | If you have an Acorn system with one of these network cards, you | ||
| 33 | should say Y to this option if you wish to use it with Linux. | ||
| 34 | |||
| 35 | config ARM_AT91_ETHER | ||
| 36 | tristate "AT91RM9200 Ethernet support" | ||
| 37 | depends on ARM && ARCH_AT91RM9200 | ||
| 38 | select MII | ||
| 39 | help | ||
| 40 | If you wish to compile a kernel for the AT91RM9200 and enable | ||
| 41 | ethernet support, then you should always answer Y to this. | ||
| 42 | |||
| 43 | config ARM_KS8695_ETHER | ||
| 44 | tristate "KS8695 Ethernet support" | ||
| 45 | depends on ARM && ARCH_KS8695 | ||
| 46 | select MII | ||
| 47 | help | ||
| 48 | If you wish to compile a kernel for the KS8695 and want to | ||
| 49 | use the internal ethernet then you should answer Y to this. | ||
| 50 | |||
| 51 | config EP93XX_ETH | ||
| 52 | tristate "EP93xx Ethernet support" | ||
| 53 | depends on ARM && ARCH_EP93XX | ||
| 54 | select MII | ||
| 55 | help | ||
| 56 | This is a driver for the ethernet hardware included in EP93xx CPUs. | ||
| 57 | Say Y if you are building a kernel for EP93xx based devices. | ||
| 58 | |||
| 59 | config IXP4XX_ETH | ||
| 60 | tristate "Intel IXP4xx Ethernet support" | ||
| 61 | depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR | ||
| 62 | select PHYLIB | ||
| 63 | help | ||
| 64 | Say Y here if you want to use built-in Ethernet ports | ||
| 65 | on IXP4xx processor. | ||
| 66 | |||
| 67 | config W90P910_ETH | ||
| 68 | tristate "Nuvoton w90p910 Ethernet support" | ||
| 69 | depends on ARM && ARCH_W90X900 | ||
| 70 | select PHYLIB | ||
| 71 | select MII | ||
| 72 | help | ||
| 73 | Say Y here if you want to use built-in Ethernet ports | ||
| 74 | on w90p910 processor. | ||
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile new file mode 100644 index 00000000000..303171f589e --- /dev/null +++ b/drivers/net/arm/Makefile | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | # File: drivers/net/arm/Makefile | ||
| 2 | # | ||
| 3 | # Makefile for the ARM network device drivers | ||
| 4 | # | ||
| 5 | |||
| 6 | obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o | ||
| 7 | obj-$(CONFIG_ARM_ETHERH) += etherh.o | ||
| 8 | obj-$(CONFIG_ARM_ETHER3) += ether3.o | ||
| 9 | obj-$(CONFIG_ARM_ETHER1) += ether1.o | ||
| 10 | obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o | ||
| 11 | obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o | ||
| 12 | obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o | ||
| 13 | obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o | ||
| 14 | obj-$(CONFIG_W90P910_ETH) += w90p910_ether.o | ||
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c new file mode 100644 index 00000000000..3b1416e3d21 --- /dev/null +++ b/drivers/net/arm/am79c961a.c | |||
| @@ -0,0 +1,770 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/net/am79c961.c | ||
| 3 | * | ||
| 4 | * by Russell King <rmk@arm.linux.org.uk> 1995-2001. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Derived from various things including skeleton.c | ||
| 11 | * | ||
| 12 | * This is a special driver for the am79c961A Lance chip used in the | ||
| 13 | * Intel (formally Digital Equipment Corp) EBSA110 platform. Please | ||
| 14 | * note that this can not be built as a module (it doesn't make sense). | ||
| 15 | */ | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/ioport.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/netdevice.h> | ||
| 24 | #include <linux/etherdevice.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/crc32.h> | ||
| 28 | #include <linux/bitops.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/io.h> | ||
| 31 | |||
| 32 | #include <mach/hardware.h> | ||
| 33 | #include <asm/system.h> | ||
| 34 | |||
| 35 | #define TX_BUFFERS 15 | ||
| 36 | #define RX_BUFFERS 25 | ||
| 37 | |||
| 38 | #include "am79c961a.h" | ||
| 39 | |||
| 40 | static irqreturn_t | ||
| 41 | am79c961_interrupt (int irq, void *dev_id); | ||
| 42 | |||
| 43 | static unsigned int net_debug = NET_DEBUG; | ||
| 44 | |||
| 45 | static const char version[] = | ||
| 46 | "am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n"; | ||
| 47 | |||
| 48 | /* --------------------------------------------------------------------------- */ | ||
| 49 | |||
| 50 | #ifdef __arm__ | ||
| 51 | static void write_rreg(u_long base, u_int reg, u_int val) | ||
| 52 | { | ||
| 53 | asm volatile( | ||
| 54 | "str%?h %1, [%2] @ NET_RAP\n\t" | ||
| 55 | "str%?h %0, [%2, #-4] @ NET_RDP" | ||
| 56 | : | ||
| 57 | : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline unsigned short read_rreg(u_long base_addr, u_int reg) | ||
| 61 | { | ||
| 62 | unsigned short v; | ||
| 63 | asm volatile( | ||
| 64 | "str%?h %1, [%2] @ NET_RAP\n\t" | ||
| 65 | "ldr%?h %0, [%2, #-4] @ NET_RDP" | ||
| 66 | : "=r" (v) | ||
| 67 | : "r" (reg), "r" (ISAIO_BASE + 0x0464)); | ||
| 68 | return v; | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void write_ireg(u_long base, u_int reg, u_int val) | ||
| 72 | { | ||
| 73 | asm volatile( | ||
| 74 | "str%?h %1, [%2] @ NET_RAP\n\t" | ||
| 75 | "str%?h %0, [%2, #8] @ NET_IDP" | ||
| 76 | : | ||
| 77 | : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464)); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline unsigned short read_ireg(u_long base_addr, u_int reg) | ||
| 81 | { | ||
| 82 | u_short v; | ||
| 83 | asm volatile( | ||
| 84 | "str%?h %1, [%2] @ NAT_RAP\n\t" | ||
| 85 | "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" | ||
| 86 | : "=r" (v) | ||
| 87 | : "r" (reg), "r" (ISAIO_BASE + 0x0464)); | ||
| 88 | return v; | ||
| 89 | } | ||
| 90 | |||
| 91 | #define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1)) | ||
| 92 | #define am_readword(dev,off) __raw_readw(ISAMEM_BASE + ((off) << 1)) | ||
| 93 | |||
| 94 | static void | ||
| 95 | am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) | ||
| 96 | { | ||
| 97 | offset = ISAMEM_BASE + (offset << 1); | ||
| 98 | length = (length + 1) & ~1; | ||
| 99 | if ((int)buf & 2) { | ||
| 100 | asm volatile("str%?h %2, [%0], #4" | ||
| 101 | : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); | ||
| 102 | buf += 2; | ||
| 103 | length -= 2; | ||
| 104 | } | ||
| 105 | while (length > 8) { | ||
| 106 | register unsigned int tmp asm("r2"), tmp2 asm("r3"); | ||
| 107 | asm volatile( | ||
| 108 | "ldm%?ia %0!, {%1, %2}" | ||
| 109 | : "+r" (buf), "=&r" (tmp), "=&r" (tmp2)); | ||
| 110 | length -= 8; | ||
| 111 | asm volatile( | ||
| 112 | "str%?h %1, [%0], #4\n\t" | ||
| 113 | "mov%? %1, %1, lsr #16\n\t" | ||
| 114 | "str%?h %1, [%0], #4\n\t" | ||
| 115 | "str%?h %2, [%0], #4\n\t" | ||
| 116 | "mov%? %2, %2, lsr #16\n\t" | ||
| 117 | "str%?h %2, [%0], #4" | ||
| 118 | : "+r" (offset), "=&r" (tmp), "=&r" (tmp2)); | ||
| 119 | } | ||
| 120 | while (length > 0) { | ||
| 121 | asm volatile("str%?h %2, [%0], #4" | ||
| 122 | : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8))); | ||
| 123 | buf += 2; | ||
| 124 | length -= 2; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | static void | ||
| 129 | am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length) | ||
| 130 | { | ||
| 131 | offset = ISAMEM_BASE + (offset << 1); | ||
| 132 | length = (length + 1) & ~1; | ||
| 133 | if ((int)buf & 2) { | ||
| 134 | unsigned int tmp; | ||
| 135 | asm volatile( | ||
| 136 | "ldr%?h %2, [%0], #4\n\t" | ||
| 137 | "str%?b %2, [%1], #1\n\t" | ||
| 138 | "mov%? %2, %2, lsr #8\n\t" | ||
| 139 | "str%?b %2, [%1], #1" | ||
| 140 | : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf)); | ||
| 141 | length -= 2; | ||
| 142 | } | ||
| 143 | while (length > 8) { | ||
| 144 | register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3; | ||
| 145 | asm volatile( | ||
| 146 | "ldr%?h %2, [%0], #4\n\t" | ||
| 147 | "ldr%?h %4, [%0], #4\n\t" | ||
| 148 | "ldr%?h %3, [%0], #4\n\t" | ||
| 149 | "orr%? %2, %2, %4, lsl #16\n\t" | ||
| 150 | "ldr%?h %4, [%0], #4\n\t" | ||
| 151 | "orr%? %3, %3, %4, lsl #16\n\t" | ||
| 152 | "stm%?ia %1!, {%2, %3}" | ||
| 153 | : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3) | ||
| 154 | : "0" (offset), "1" (buf)); | ||
| 155 | length -= 8; | ||
| 156 | } | ||
| 157 | while (length > 0) { | ||
| 158 | unsigned int tmp; | ||
| 159 | asm volatile( | ||
| 160 | "ldr%?h %2, [%0], #4\n\t" | ||
| 161 | "str%?b %2, [%1], #1\n\t" | ||
| 162 | "mov%? %2, %2, lsr #8\n\t" | ||
| 163 | "str%?b %2, [%1], #1" | ||
| 164 | : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf)); | ||
| 165 | length -= 2; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | #else | ||
| 169 | #error Not compatible | ||
| 170 | #endif | ||
| 171 | |||
| 172 | static int | ||
| 173 | am79c961_ramtest(struct net_device *dev, unsigned int val) | ||
| 174 | { | ||
| 175 | unsigned char *buffer = kmalloc (65536, GFP_KERNEL); | ||
| 176 | int i, error = 0, errorcount = 0; | ||
| 177 | |||
| 178 | if (!buffer) | ||
| 179 | return 0; | ||
| 180 | memset (buffer, val, 65536); | ||
| 181 | am_writebuffer(dev, 0, buffer, 65536); | ||
| 182 | memset (buffer, val ^ 255, 65536); | ||
| 183 | am_readbuffer(dev, 0, buffer, 65536); | ||
| 184 | for (i = 0; i < 65536; i++) { | ||
| 185 | if (buffer[i] != val && !error) { | ||
| 186 | printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i); | ||
| 187 | error = 1; | ||
| 188 | errorcount ++; | ||
| 189 | } else if (error && buffer[i] == val) { | ||
| 190 | printk ("%05X\n", i); | ||
| 191 | error = 0; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | if (error) | ||
| 195 | printk ("10000\n"); | ||
| 196 | kfree (buffer); | ||
| 197 | return errorcount; | ||
| 198 | } | ||
| 199 | |||
| 200 | static void am79c961_mc_hash(char *addr, u16 *hash) | ||
| 201 | { | ||
| 202 | int idx, bit; | ||
| 203 | u32 crc; | ||
| 204 | |||
| 205 | crc = ether_crc_le(ETH_ALEN, addr); | ||
| 206 | |||
| 207 | idx = crc >> 30; | ||
| 208 | bit = (crc >> 26) & 15; | ||
| 209 | |||
| 210 | hash[idx] |= 1 << bit; | ||
| 211 | } | ||
| 212 | |||
| 213 | static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash) | ||
| 214 | { | ||
| 215 | unsigned int mode = MODE_PORT_10BT; | ||
| 216 | |||
| 217 | if (dev->flags & IFF_PROMISC) { | ||
| 218 | mode |= MODE_PROMISC; | ||
| 219 | memset(hash, 0xff, 4 * sizeof(*hash)); | ||
| 220 | } else if (dev->flags & IFF_ALLMULTI) { | ||
| 221 | memset(hash, 0xff, 4 * sizeof(*hash)); | ||
| 222 | } else { | ||
| 223 | struct netdev_hw_addr *ha; | ||
| 224 | |||
| 225 | memset(hash, 0, 4 * sizeof(*hash)); | ||
| 226 | |||
| 227 | netdev_for_each_mc_addr(ha, dev) | ||
| 228 | am79c961_mc_hash(ha->addr, hash); | ||
| 229 | } | ||
| 230 | |||
| 231 | return mode; | ||
| 232 | } | ||
| 233 | |||
| 234 | static void | ||
| 235 | am79c961_init_for_open(struct net_device *dev) | ||
| 236 | { | ||
| 237 | struct dev_priv *priv = netdev_priv(dev); | ||
| 238 | unsigned long flags; | ||
| 239 | unsigned char *p; | ||
| 240 | u_int hdr_addr, first_free_addr; | ||
| 241 | u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); | ||
| 242 | int i; | ||
| 243 | |||
| 244 | /* | ||
| 245 | * Stop the chip. | ||
| 246 | */ | ||
| 247 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 248 | write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP); | ||
| 249 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 250 | |||
| 251 | write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */ | ||
| 252 | write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */ | ||
| 253 | write_ireg (dev->base_addr, 7, 0x0090); /* XMIT LED */ | ||
| 254 | write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */ | ||
| 255 | |||
| 256 | for (i = LADRL; i <= LADRH; i++) | ||
| 257 | write_rreg (dev->base_addr, i, multi_hash[i - LADRL]); | ||
| 258 | |||
| 259 | for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2) | ||
| 260 | write_rreg (dev->base_addr, i, p[0] | (p[1] << 8)); | ||
| 261 | |||
| 262 | write_rreg (dev->base_addr, MODE, mode); | ||
| 263 | write_rreg (dev->base_addr, POLLINT, 0); | ||
| 264 | write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS); | ||
| 265 | write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS); | ||
| 266 | |||
| 267 | first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16; | ||
| 268 | hdr_addr = 0; | ||
| 269 | |||
| 270 | priv->rxhead = 0; | ||
| 271 | priv->rxtail = 0; | ||
| 272 | priv->rxhdr = hdr_addr; | ||
| 273 | |||
| 274 | for (i = 0; i < RX_BUFFERS; i++) { | ||
| 275 | priv->rxbuffer[i] = first_free_addr; | ||
| 276 | am_writeword (dev, hdr_addr, first_free_addr); | ||
| 277 | am_writeword (dev, hdr_addr + 2, RMD_OWN); | ||
| 278 | am_writeword (dev, hdr_addr + 4, (-1600)); | ||
| 279 | am_writeword (dev, hdr_addr + 6, 0); | ||
| 280 | first_free_addr += 1600; | ||
| 281 | hdr_addr += 8; | ||
| 282 | } | ||
| 283 | priv->txhead = 0; | ||
| 284 | priv->txtail = 0; | ||
| 285 | priv->txhdr = hdr_addr; | ||
| 286 | for (i = 0; i < TX_BUFFERS; i++) { | ||
| 287 | priv->txbuffer[i] = first_free_addr; | ||
| 288 | am_writeword (dev, hdr_addr, first_free_addr); | ||
| 289 | am_writeword (dev, hdr_addr + 2, TMD_STP|TMD_ENP); | ||
| 290 | am_writeword (dev, hdr_addr + 4, 0xf000); | ||
| 291 | am_writeword (dev, hdr_addr + 6, 0); | ||
| 292 | first_free_addr += 1600; | ||
| 293 | hdr_addr += 8; | ||
| 294 | } | ||
| 295 | |||
| 296 | write_rreg (dev->base_addr, BASERXL, priv->rxhdr); | ||
| 297 | write_rreg (dev->base_addr, BASERXH, 0); | ||
| 298 | write_rreg (dev->base_addr, BASETXL, priv->txhdr); | ||
| 299 | write_rreg (dev->base_addr, BASERXH, 0); | ||
| 300 | write_rreg (dev->base_addr, CSR0, CSR0_STOP); | ||
| 301 | write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO); | ||
| 302 | write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM); | ||
| 303 | write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT); | ||
| 304 | } | ||
| 305 | |||
| 306 | static void am79c961_timer(unsigned long data) | ||
| 307 | { | ||
| 308 | struct net_device *dev = (struct net_device *)data; | ||
| 309 | struct dev_priv *priv = netdev_priv(dev); | ||
| 310 | unsigned int lnkstat, carrier; | ||
| 311 | unsigned long flags; | ||
| 312 | |||
| 313 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 314 | lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST; | ||
| 315 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 316 | carrier = netif_carrier_ok(dev); | ||
| 317 | |||
| 318 | if (lnkstat && !carrier) { | ||
| 319 | netif_carrier_on(dev); | ||
| 320 | printk("%s: link up\n", dev->name); | ||
| 321 | } else if (!lnkstat && carrier) { | ||
| 322 | netif_carrier_off(dev); | ||
| 323 | printk("%s: link down\n", dev->name); | ||
| 324 | } | ||
| 325 | |||
| 326 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500)); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * Open/initialize the board. | ||
| 331 | */ | ||
| 332 | static int | ||
| 333 | am79c961_open(struct net_device *dev) | ||
| 334 | { | ||
| 335 | struct dev_priv *priv = netdev_priv(dev); | ||
| 336 | int ret; | ||
| 337 | |||
| 338 | ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev); | ||
| 339 | if (ret) | ||
| 340 | return ret; | ||
| 341 | |||
| 342 | am79c961_init_for_open(dev); | ||
| 343 | |||
| 344 | netif_carrier_off(dev); | ||
| 345 | |||
| 346 | priv->timer.expires = jiffies; | ||
| 347 | add_timer(&priv->timer); | ||
| 348 | |||
| 349 | netif_start_queue(dev); | ||
| 350 | |||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* | ||
| 355 | * The inverse routine to am79c961_open(). | ||
| 356 | */ | ||
| 357 | static int | ||
| 358 | am79c961_close(struct net_device *dev) | ||
| 359 | { | ||
| 360 | struct dev_priv *priv = netdev_priv(dev); | ||
| 361 | unsigned long flags; | ||
| 362 | |||
| 363 | del_timer_sync(&priv->timer); | ||
| 364 | |||
| 365 | netif_stop_queue(dev); | ||
| 366 | netif_carrier_off(dev); | ||
| 367 | |||
| 368 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 369 | write_rreg (dev->base_addr, CSR0, CSR0_STOP); | ||
| 370 | write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); | ||
| 371 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 372 | |||
| 373 | free_irq (dev->irq, dev); | ||
| 374 | |||
| 375 | return 0; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* | ||
| 379 | * Set or clear promiscuous/multicast mode filter for this adapter. | ||
| 380 | */ | ||
| 381 | static void am79c961_setmulticastlist (struct net_device *dev) | ||
| 382 | { | ||
| 383 | struct dev_priv *priv = netdev_priv(dev); | ||
| 384 | unsigned long flags; | ||
| 385 | u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash); | ||
| 386 | int i, stopped; | ||
| 387 | |||
| 388 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 389 | |||
| 390 | stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP; | ||
| 391 | |||
| 392 | if (!stopped) { | ||
| 393 | /* | ||
| 394 | * Put the chip into suspend mode | ||
| 395 | */ | ||
| 396 | write_rreg(dev->base_addr, CTRL1, CTRL1_SPND); | ||
| 397 | |||
| 398 | /* | ||
| 399 | * Spin waiting for chip to report suspend mode | ||
| 400 | */ | ||
| 401 | while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) { | ||
| 402 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 403 | nop(); | ||
| 404 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * Update the multicast hash table | ||
| 410 | */ | ||
| 411 | for (i = 0; i < ARRAY_SIZE(multi_hash); i++) | ||
| 412 | write_rreg(dev->base_addr, i + LADRL, multi_hash[i]); | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Write the mode register | ||
| 416 | */ | ||
| 417 | write_rreg(dev->base_addr, MODE, mode); | ||
| 418 | |||
| 419 | if (!stopped) { | ||
| 420 | /* | ||
| 421 | * Put the chip back into running mode | ||
| 422 | */ | ||
| 423 | write_rreg(dev->base_addr, CTRL1, 0); | ||
| 424 | } | ||
| 425 | |||
| 426 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 427 | } | ||
| 428 | |||
| 429 | static void am79c961_timeout(struct net_device *dev) | ||
| 430 | { | ||
| 431 | printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n", | ||
| 432 | dev->name); | ||
| 433 | |||
| 434 | /* | ||
| 435 | * ought to do some setup of the tx side here | ||
| 436 | */ | ||
| 437 | |||
| 438 | netif_wake_queue(dev); | ||
| 439 | } | ||
| 440 | |||
| 441 | /* | ||
| 442 | * Transmit a packet | ||
| 443 | */ | ||
| 444 | static int | ||
| 445 | am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev) | ||
| 446 | { | ||
| 447 | struct dev_priv *priv = netdev_priv(dev); | ||
| 448 | unsigned int hdraddr, bufaddr; | ||
| 449 | unsigned int head; | ||
| 450 | unsigned long flags; | ||
| 451 | |||
| 452 | head = priv->txhead; | ||
| 453 | hdraddr = priv->txhdr + (head << 3); | ||
| 454 | bufaddr = priv->txbuffer[head]; | ||
| 455 | head += 1; | ||
| 456 | if (head >= TX_BUFFERS) | ||
| 457 | head = 0; | ||
| 458 | |||
| 459 | am_writebuffer (dev, bufaddr, skb->data, skb->len); | ||
| 460 | am_writeword (dev, hdraddr + 4, -skb->len); | ||
| 461 | am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP); | ||
| 462 | priv->txhead = head; | ||
| 463 | |||
| 464 | spin_lock_irqsave(&priv->chip_lock, flags); | ||
| 465 | write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA); | ||
| 466 | spin_unlock_irqrestore(&priv->chip_lock, flags); | ||
| 467 | |||
| 468 | /* | ||
| 469 | * If the next packet is owned by the ethernet device, | ||
| 470 | * then the tx ring is full and we can't add another | ||
| 471 | * packet. | ||
| 472 | */ | ||
| 473 | if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN) | ||
| 474 | netif_stop_queue(dev); | ||
| 475 | |||
| 476 | dev_kfree_skb(skb); | ||
| 477 | |||
| 478 | return NETDEV_TX_OK; | ||
| 479 | } | ||
| 480 | |||
| 481 | /* | ||
| 482 | * If we have a good packet(s), get it/them out of the buffers. | ||
| 483 | */ | ||
| 484 | static void | ||
| 485 | am79c961_rx(struct net_device *dev, struct dev_priv *priv) | ||
| 486 | { | ||
| 487 | do { | ||
| 488 | struct sk_buff *skb; | ||
| 489 | u_int hdraddr; | ||
| 490 | u_int pktaddr; | ||
| 491 | u_int status; | ||
| 492 | int len; | ||
| 493 | |||
| 494 | hdraddr = priv->rxhdr + (priv->rxtail << 3); | ||
| 495 | pktaddr = priv->rxbuffer[priv->rxtail]; | ||
| 496 | |||
| 497 | status = am_readword (dev, hdraddr + 2); | ||
| 498 | if (status & RMD_OWN) /* do we own it? */ | ||
| 499 | break; | ||
| 500 | |||
| 501 | priv->rxtail ++; | ||
| 502 | if (priv->rxtail >= RX_BUFFERS) | ||
| 503 | priv->rxtail = 0; | ||
| 504 | |||
| 505 | if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) { | ||
| 506 | am_writeword (dev, hdraddr + 2, RMD_OWN); | ||
| 507 | dev->stats.rx_errors++; | ||
| 508 | if (status & RMD_ERR) { | ||
| 509 | if (status & RMD_FRAM) | ||
| 510 | dev->stats.rx_frame_errors++; | ||
| 511 | if (status & RMD_CRC) | ||
| 512 | dev->stats.rx_crc_errors++; | ||
| 513 | } else if (status & RMD_STP) | ||
| 514 | dev->stats.rx_length_errors++; | ||
| 515 | continue; | ||
| 516 | } | ||
| 517 | |||
| 518 | len = am_readword(dev, hdraddr + 6); | ||
| 519 | skb = dev_alloc_skb(len + 2); | ||
| 520 | |||
| 521 | if (skb) { | ||
| 522 | skb_reserve(skb, 2); | ||
| 523 | |||
| 524 | am_readbuffer(dev, pktaddr, skb_put(skb, len), len); | ||
| 525 | am_writeword(dev, hdraddr + 2, RMD_OWN); | ||
| 526 | skb->protocol = eth_type_trans(skb, dev); | ||
| 527 | netif_rx(skb); | ||
| 528 | dev->stats.rx_bytes += len; | ||
| 529 | dev->stats.rx_packets++; | ||
| 530 | } else { | ||
| 531 | am_writeword (dev, hdraddr + 2, RMD_OWN); | ||
| 532 | printk (KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name); | ||
| 533 | dev->stats.rx_dropped++; | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | } while (1); | ||
| 537 | } | ||
| 538 | |||
| 539 | /* | ||
| 540 | * Update stats for the transmitted packet | ||
| 541 | */ | ||
| 542 | static void | ||
| 543 | am79c961_tx(struct net_device *dev, struct dev_priv *priv) | ||
| 544 | { | ||
| 545 | do { | ||
| 546 | short len; | ||
| 547 | u_int hdraddr; | ||
| 548 | u_int status; | ||
| 549 | |||
| 550 | hdraddr = priv->txhdr + (priv->txtail << 3); | ||
| 551 | status = am_readword (dev, hdraddr + 2); | ||
| 552 | if (status & TMD_OWN) | ||
| 553 | break; | ||
| 554 | |||
| 555 | priv->txtail ++; | ||
| 556 | if (priv->txtail >= TX_BUFFERS) | ||
| 557 | priv->txtail = 0; | ||
| 558 | |||
| 559 | if (status & TMD_ERR) { | ||
| 560 | u_int status2; | ||
| 561 | |||
| 562 | dev->stats.tx_errors++; | ||
| 563 | |||
| 564 | status2 = am_readword (dev, hdraddr + 6); | ||
| 565 | |||
| 566 | /* | ||
| 567 | * Clear the error byte | ||
| 568 | */ | ||
| 569 | am_writeword (dev, hdraddr + 6, 0); | ||
| 570 | |||
| 571 | if (status2 & TST_RTRY) | ||
| 572 | dev->stats.collisions += 16; | ||
| 573 | if (status2 & TST_LCOL) | ||
| 574 | dev->stats.tx_window_errors++; | ||
| 575 | if (status2 & TST_LCAR) | ||
| 576 | dev->stats.tx_carrier_errors++; | ||
| 577 | if (status2 & TST_UFLO) | ||
| 578 | dev->stats.tx_fifo_errors++; | ||
| 579 | continue; | ||
| 580 | } | ||
| 581 | dev->stats.tx_packets++; | ||
| 582 | len = am_readword (dev, hdraddr + 4); | ||
| 583 | dev->stats.tx_bytes += -len; | ||
| 584 | } while (priv->txtail != priv->txhead); | ||
| 585 | |||
| 586 | netif_wake_queue(dev); | ||
| 587 | } | ||
| 588 | |||
| 589 | static irqreturn_t | ||
| 590 | am79c961_interrupt(int irq, void *dev_id) | ||
| 591 | { | ||
| 592 | struct net_device *dev = (struct net_device *)dev_id; | ||
| 593 | struct dev_priv *priv = netdev_priv(dev); | ||
| 594 | u_int status, n = 100; | ||
| 595 | int handled = 0; | ||
| 596 | |||
| 597 | do { | ||
| 598 | status = read_rreg(dev->base_addr, CSR0); | ||
| 599 | write_rreg(dev->base_addr, CSR0, status & | ||
| 600 | (CSR0_IENA|CSR0_TINT|CSR0_RINT| | ||
| 601 | CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL)); | ||
| 602 | |||
| 603 | if (status & CSR0_RINT) { | ||
| 604 | handled = 1; | ||
| 605 | am79c961_rx(dev, priv); | ||
| 606 | } | ||
| 607 | if (status & CSR0_TINT) { | ||
| 608 | handled = 1; | ||
| 609 | am79c961_tx(dev, priv); | ||
| 610 | } | ||
| 611 | if (status & CSR0_MISS) { | ||
| 612 | handled = 1; | ||
| 613 | dev->stats.rx_dropped++; | ||
| 614 | } | ||
| 615 | if (status & CSR0_CERR) { | ||
| 616 | handled = 1; | ||
| 617 | mod_timer(&priv->timer, jiffies); | ||
| 618 | } | ||
| 619 | } while (--n && status & (CSR0_RINT | CSR0_TINT)); | ||
| 620 | |||
| 621 | return IRQ_RETVAL(handled); | ||
| 622 | } | ||
| 623 | |||
| 624 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 625 | static void am79c961_poll_controller(struct net_device *dev) | ||
| 626 | { | ||
| 627 | unsigned long flags; | ||
| 628 | local_irq_save(flags); | ||
| 629 | am79c961_interrupt(dev->irq, dev); | ||
| 630 | local_irq_restore(flags); | ||
| 631 | } | ||
| 632 | #endif | ||
| 633 | |||
| 634 | /* | ||
| 635 | * Initialise the chip. Note that we always expect | ||
| 636 | * to be entered with interrupts enabled. | ||
| 637 | */ | ||
| 638 | static int | ||
| 639 | am79c961_hw_init(struct net_device *dev) | ||
| 640 | { | ||
| 641 | struct dev_priv *priv = netdev_priv(dev); | ||
| 642 | |||
| 643 | spin_lock_irq(&priv->chip_lock); | ||
| 644 | write_rreg (dev->base_addr, CSR0, CSR0_STOP); | ||
| 645 | write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); | ||
| 646 | spin_unlock_irq(&priv->chip_lock); | ||
| 647 | |||
| 648 | am79c961_ramtest(dev, 0x66); | ||
| 649 | am79c961_ramtest(dev, 0x99); | ||
| 650 | |||
| 651 | return 0; | ||
| 652 | } | ||
| 653 | |||
| 654 | static void __init am79c961_banner(void) | ||
| 655 | { | ||
| 656 | static unsigned version_printed; | ||
| 657 | |||
| 658 | if (net_debug && version_printed++ == 0) | ||
| 659 | printk(KERN_INFO "%s", version); | ||
| 660 | } | ||
| 661 | static const struct net_device_ops am79c961_netdev_ops = { | ||
| 662 | .ndo_open = am79c961_open, | ||
| 663 | .ndo_stop = am79c961_close, | ||
| 664 | .ndo_start_xmit = am79c961_sendpacket, | ||
| 665 | .ndo_set_multicast_list = am79c961_setmulticastlist, | ||
| 666 | .ndo_tx_timeout = am79c961_timeout, | ||
| 667 | .ndo_validate_addr = eth_validate_addr, | ||
| 668 | .ndo_change_mtu = eth_change_mtu, | ||
| 669 | .ndo_set_mac_address = eth_mac_addr, | ||
| 670 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 671 | .ndo_poll_controller = am79c961_poll_controller, | ||
| 672 | #endif | ||
| 673 | }; | ||
| 674 | |||
| 675 | static int __devinit am79c961_probe(struct platform_device *pdev) | ||
| 676 | { | ||
| 677 | struct resource *res; | ||
| 678 | struct net_device *dev; | ||
| 679 | struct dev_priv *priv; | ||
| 680 | int i, ret; | ||
| 681 | |||
| 682 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 683 | if (!res) | ||
| 684 | return -ENODEV; | ||
| 685 | |||
| 686 | dev = alloc_etherdev(sizeof(struct dev_priv)); | ||
| 687 | ret = -ENOMEM; | ||
| 688 | if (!dev) | ||
| 689 | goto out; | ||
| 690 | |||
| 691 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
| 692 | |||
| 693 | priv = netdev_priv(dev); | ||
| 694 | |||
| 695 | /* | ||
| 696 | * Fixed address and IRQ lines here. | ||
| 697 | * The PNP initialisation should have been | ||
| 698 | * done by the ether bootp loader. | ||
| 699 | */ | ||
| 700 | dev->base_addr = res->start; | ||
| 701 | ret = platform_get_irq(pdev, 0); | ||
| 702 | |||
| 703 | if (ret < 0) { | ||
| 704 | ret = -ENODEV; | ||
| 705 | goto nodev; | ||
| 706 | } | ||
| 707 | dev->irq = ret; | ||
| 708 | |||
| 709 | ret = -ENODEV; | ||
| 710 | if (!request_region(dev->base_addr, 0x18, dev->name)) | ||
| 711 | goto nodev; | ||
| 712 | |||
| 713 | /* | ||
| 714 | * Reset the device. | ||
| 715 | */ | ||
| 716 | inb(dev->base_addr + NET_RESET); | ||
| 717 | udelay(5); | ||
| 718 | |||
| 719 | /* | ||
| 720 | * Check the manufacturer part of the | ||
| 721 | * ether address. | ||
| 722 | */ | ||
| 723 | if (inb(dev->base_addr) != 0x08 || | ||
| 724 | inb(dev->base_addr + 2) != 0x00 || | ||
| 725 | inb(dev->base_addr + 4) != 0x2b) | ||
| 726 | goto release; | ||
| 727 | |||
| 728 | for (i = 0; i < 6; i++) | ||
| 729 | dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff; | ||
| 730 | |||
| 731 | am79c961_banner(); | ||
| 732 | |||
| 733 | spin_lock_init(&priv->chip_lock); | ||
| 734 | init_timer(&priv->timer); | ||
| 735 | priv->timer.data = (unsigned long)dev; | ||
| 736 | priv->timer.function = am79c961_timer; | ||
| 737 | |||
| 738 | if (am79c961_hw_init(dev)) | ||
| 739 | goto release; | ||
| 740 | |||
| 741 | dev->netdev_ops = &am79c961_netdev_ops; | ||
| 742 | |||
| 743 | ret = register_netdev(dev); | ||
| 744 | if (ret == 0) { | ||
| 745 | printk(KERN_INFO "%s: ether address %pM\n", | ||
| 746 | dev->name, dev->dev_addr); | ||
| 747 | return 0; | ||
| 748 | } | ||
| 749 | |||
| 750 | release: | ||
| 751 | release_region(dev->base_addr, 0x18); | ||
| 752 | nodev: | ||
| 753 | free_netdev(dev); | ||
| 754 | out: | ||
| 755 | return ret; | ||
| 756 | } | ||
| 757 | |||
| 758 | static struct platform_driver am79c961_driver = { | ||
| 759 | .probe = am79c961_probe, | ||
| 760 | .driver = { | ||
| 761 | .name = "am79c961", | ||
| 762 | }, | ||
| 763 | }; | ||
| 764 | |||
| 765 | static int __init am79c961_init(void) | ||
| 766 | { | ||
| 767 | return platform_driver_register(&am79c961_driver); | ||
| 768 | } | ||
| 769 | |||
| 770 | __initcall(am79c961_init); | ||
diff --git a/drivers/net/arm/am79c961a.h b/drivers/net/arm/am79c961a.h new file mode 100644 index 00000000000..fd634d32756 --- /dev/null +++ b/drivers/net/arm/am79c961a.h | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/net/arm/am79c961a.h | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _LINUX_am79c961a_H | ||
| 10 | #define _LINUX_am79c961a_H | ||
| 11 | |||
| 12 | /* use 0 for production, 1 for verification, >2 for debug. debug flags: */ | ||
| 13 | #define DEBUG_TX 2 | ||
| 14 | #define DEBUG_RX 4 | ||
| 15 | #define DEBUG_INT 8 | ||
| 16 | #define DEBUG_IC 16 | ||
| 17 | #ifndef NET_DEBUG | ||
| 18 | #define NET_DEBUG 0 | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #define NET_UID 0 | ||
| 22 | #define NET_RDP 0x10 | ||
| 23 | #define NET_RAP 0x12 | ||
| 24 | #define NET_RESET 0x14 | ||
| 25 | #define NET_IDP 0x16 | ||
| 26 | |||
| 27 | /* | ||
| 28 | * RAP registers | ||
| 29 | */ | ||
| 30 | #define CSR0 0 | ||
| 31 | #define CSR0_INIT 0x0001 | ||
| 32 | #define CSR0_STRT 0x0002 | ||
| 33 | #define CSR0_STOP 0x0004 | ||
| 34 | #define CSR0_TDMD 0x0008 | ||
| 35 | #define CSR0_TXON 0x0010 | ||
| 36 | #define CSR0_RXON 0x0020 | ||
| 37 | #define CSR0_IENA 0x0040 | ||
| 38 | #define CSR0_INTR 0x0080 | ||
| 39 | #define CSR0_IDON 0x0100 | ||
| 40 | #define CSR0_TINT 0x0200 | ||
| 41 | #define CSR0_RINT 0x0400 | ||
| 42 | #define CSR0_MERR 0x0800 | ||
| 43 | #define CSR0_MISS 0x1000 | ||
| 44 | #define CSR0_CERR 0x2000 | ||
| 45 | #define CSR0_BABL 0x4000 | ||
| 46 | #define CSR0_ERR 0x8000 | ||
| 47 | |||
| 48 | #define CSR3 3 | ||
| 49 | #define CSR3_EMBA 0x0008 | ||
| 50 | #define CSR3_DXMT2PD 0x0010 | ||
| 51 | #define CSR3_LAPPEN 0x0020 | ||
| 52 | #define CSR3_DXSUFLO 0x0040 | ||
| 53 | #define CSR3_IDONM 0x0100 | ||
| 54 | #define CSR3_TINTM 0x0200 | ||
| 55 | #define CSR3_RINTM 0x0400 | ||
| 56 | #define CSR3_MERRM 0x0800 | ||
| 57 | #define CSR3_MISSM 0x1000 | ||
| 58 | #define CSR3_BABLM 0x4000 | ||
| 59 | #define CSR3_MASKALL 0x5F00 | ||
| 60 | |||
| 61 | #define CSR4 4 | ||
| 62 | #define CSR4_JABM 0x0001 | ||
| 63 | #define CSR4_JAB 0x0002 | ||
| 64 | #define CSR4_TXSTRTM 0x0004 | ||
| 65 | #define CSR4_TXSTRT 0x0008 | ||
| 66 | #define CSR4_RCVCCOM 0x0010 | ||
| 67 | #define CSR4_RCVCCO 0x0020 | ||
| 68 | #define CSR4_MFCOM 0x0100 | ||
| 69 | #define CSR4_MFCO 0x0200 | ||
| 70 | #define CSR4_ASTRP_RCV 0x0400 | ||
| 71 | #define CSR4_APAD_XMIT 0x0800 | ||
| 72 | |||
| 73 | #define CTRL1 5 | ||
| 74 | #define CTRL1_SPND 0x0001 | ||
| 75 | |||
| 76 | #define LADRL 8 | ||
| 77 | #define LADRM1 9 | ||
| 78 | #define LADRM2 10 | ||
| 79 | #define LADRH 11 | ||
| 80 | #define PADRL 12 | ||
| 81 | #define PADRM 13 | ||
| 82 | #define PADRH 14 | ||
| 83 | |||
| 84 | #define MODE 15 | ||
| 85 | #define MODE_DISRX 0x0001 | ||
| 86 | #define MODE_DISTX 0x0002 | ||
| 87 | #define MODE_LOOP 0x0004 | ||
| 88 | #define MODE_DTCRC 0x0008 | ||
| 89 | #define MODE_COLL 0x0010 | ||
| 90 | #define MODE_DRETRY 0x0020 | ||
| 91 | #define MODE_INTLOOP 0x0040 | ||
| 92 | #define MODE_PORT_AUI 0x0000 | ||
| 93 | #define MODE_PORT_10BT 0x0080 | ||
| 94 | #define MODE_DRXPA 0x2000 | ||
| 95 | #define MODE_DRXBA 0x4000 | ||
| 96 | #define MODE_PROMISC 0x8000 | ||
| 97 | |||
| 98 | #define BASERXL 24 | ||
| 99 | #define BASERXH 25 | ||
| 100 | #define BASETXL 30 | ||
| 101 | #define BASETXH 31 | ||
| 102 | |||
| 103 | #define POLLINT 47 | ||
| 104 | |||
| 105 | #define SIZERXR 76 | ||
| 106 | #define SIZETXR 78 | ||
| 107 | |||
| 108 | #define CSR_MFC 112 | ||
| 109 | |||
| 110 | #define RMD_ENP 0x0100 | ||
| 111 | #define RMD_STP 0x0200 | ||
| 112 | #define RMD_CRC 0x0800 | ||
| 113 | #define RMD_FRAM 0x2000 | ||
| 114 | #define RMD_ERR 0x4000 | ||
| 115 | #define RMD_OWN 0x8000 | ||
| 116 | |||
| 117 | #define TMD_ENP 0x0100 | ||
| 118 | #define TMD_STP 0x0200 | ||
| 119 | #define TMD_MORE 0x1000 | ||
| 120 | #define TMD_ERR 0x4000 | ||
| 121 | #define TMD_OWN 0x8000 | ||
| 122 | |||
| 123 | #define TST_RTRY 0x0400 | ||
| 124 | #define TST_LCAR 0x0800 | ||
| 125 | #define TST_LCOL 0x1000 | ||
| 126 | #define TST_UFLO 0x4000 | ||
| 127 | #define TST_BUFF 0x8000 | ||
| 128 | |||
| 129 | #define ISALED0 0x0004 | ||
| 130 | #define ISALED0_LNKST 0x8000 | ||
| 131 | |||
| 132 | struct dev_priv { | ||
| 133 | unsigned long rxbuffer[RX_BUFFERS]; | ||
| 134 | unsigned long txbuffer[TX_BUFFERS]; | ||
| 135 | unsigned char txhead; | ||
| 136 | unsigned char txtail; | ||
| 137 | unsigned char rxhead; | ||
| 138 | unsigned char rxtail; | ||
| 139 | unsigned long rxhdr; | ||
| 140 | unsigned long txhdr; | ||
| 141 | spinlock_t chip_lock; | ||
| 142 | struct timer_list timer; | ||
| 143 | }; | ||
| 144 | |||
| 145 | #endif | ||
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c new file mode 100644 index 00000000000..29dc43523ce --- /dev/null +++ b/drivers/net/arm/at91_ether.c | |||
| @@ -0,0 +1,1254 @@ | |||
| 1 | /* | ||
| 2 | * Ethernet driver for the Atmel AT91RM9200 (Thunder) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003 SAN People (Pty) Ltd | ||
| 5 | * | ||
| 6 | * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. | ||
| 7 | * Initial version by Rick Bronson 01/11/2003 | ||
| 8 | * | ||
| 9 | * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker | ||
| 10 | * (Polaroid Corporation) | ||
| 11 | * | ||
| 12 | * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru> | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or | ||
| 15 | * modify it under the terms of the GNU General Public License | ||
| 16 | * as published by the Free Software Foundation; either version | ||
| 17 | * 2 of the License, or (at your option) any later version. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/mii.h> | ||
| 24 | #include <linux/netdevice.h> | ||
| 25 | #include <linux/etherdevice.h> | ||
| 26 | #include <linux/skbuff.h> | ||
| 27 | #include <linux/dma-mapping.h> | ||
| 28 | #include <linux/ethtool.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/clk.h> | ||
| 31 | #include <linux/gfp.h> | ||
| 32 | |||
| 33 | #include <asm/io.h> | ||
| 34 | #include <asm/uaccess.h> | ||
| 35 | #include <asm/mach-types.h> | ||
| 36 | |||
| 37 | #include <mach/at91rm9200_emac.h> | ||
| 38 | #include <mach/gpio.h> | ||
| 39 | #include <mach/board.h> | ||
| 40 | |||
| 41 | #include "at91_ether.h" | ||
| 42 | |||
| 43 | #define DRV_NAME "at91_ether" | ||
| 44 | #define DRV_VERSION "1.0" | ||
| 45 | |||
| 46 | #define LINK_POLL_INTERVAL (HZ) | ||
| 47 | |||
| 48 | /* ..................................................................... */ | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Read from a EMAC register. | ||
| 52 | */ | ||
| 53 | static inline unsigned long at91_emac_read(unsigned int reg) | ||
| 54 | { | ||
| 55 | void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; | ||
| 56 | |||
| 57 | return __raw_readl(emac_base + reg); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Write to a EMAC register. | ||
| 62 | */ | ||
| 63 | static inline void at91_emac_write(unsigned int reg, unsigned long value) | ||
| 64 | { | ||
| 65 | void __iomem *emac_base = (void __iomem *)AT91_VA_BASE_EMAC; | ||
| 66 | |||
| 67 | __raw_writel(value, emac_base + reg); | ||
| 68 | } | ||
| 69 | |||
| 70 | /* ........................... PHY INTERFACE ........................... */ | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Enable the MDIO bit in MAC control register | ||
| 74 | * When not called from an interrupt-handler, access to the PHY must be | ||
| 75 | * protected by a spinlock. | ||
| 76 | */ | ||
| 77 | static void enable_mdi(void) | ||
| 78 | { | ||
| 79 | unsigned long ctl; | ||
| 80 | |||
| 81 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 82 | at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_MPE); /* enable management port */ | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Disable the MDIO bit in the MAC control register | ||
| 87 | */ | ||
| 88 | static void disable_mdi(void) | ||
| 89 | { | ||
| 90 | unsigned long ctl; | ||
| 91 | |||
| 92 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 93 | at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE); /* disable management port */ | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Wait until the PHY operation is complete. | ||
| 98 | */ | ||
| 99 | static inline void at91_phy_wait(void) { | ||
| 100 | unsigned long timeout = jiffies + 2; | ||
| 101 | |||
| 102 | while (!(at91_emac_read(AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) { | ||
| 103 | if (time_after(jiffies, timeout)) { | ||
| 104 | printk("at91_ether: MIO timeout\n"); | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | cpu_relax(); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Write value to the a PHY register | ||
| 113 | * Note: MDI interface is assumed to already have been enabled. | ||
| 114 | */ | ||
| 115 | static void write_phy(unsigned char phy_addr, unsigned char address, unsigned int value) | ||
| 116 | { | ||
| 117 | at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W | ||
| 118 | | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA)); | ||
| 119 | |||
| 120 | /* Wait until IDLE bit in Network Status register is cleared */ | ||
| 121 | at91_phy_wait(); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Read value stored in a PHY register. | ||
| 126 | * Note: MDI interface is assumed to already have been enabled. | ||
| 127 | */ | ||
| 128 | static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int *value) | ||
| 129 | { | ||
| 130 | at91_emac_write(AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R | ||
| 131 | | ((phy_addr & 0x1f) << 23) | (address << 18)); | ||
| 132 | |||
| 133 | /* Wait until IDLE bit in Network Status register is cleared */ | ||
| 134 | at91_phy_wait(); | ||
| 135 | |||
| 136 | *value = at91_emac_read(AT91_EMAC_MAN) & AT91_EMAC_DATA; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* ........................... PHY MANAGEMENT .......................... */ | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Access the PHY to determine the current link speed and mode, and update the | ||
| 143 | * MAC accordingly. | ||
| 144 | * If no link or auto-negotiation is busy, then no changes are made. | ||
| 145 | */ | ||
| 146 | static void update_linkspeed(struct net_device *dev, int silent) | ||
| 147 | { | ||
| 148 | struct at91_private *lp = netdev_priv(dev); | ||
| 149 | unsigned int bmsr, bmcr, lpa, mac_cfg; | ||
| 150 | unsigned int speed, duplex; | ||
| 151 | |||
| 152 | if (!mii_link_ok(&lp->mii)) { /* no link */ | ||
| 153 | netif_carrier_off(dev); | ||
| 154 | if (!silent) | ||
| 155 | printk(KERN_INFO "%s: Link down.\n", dev->name); | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* Link up, or auto-negotiation still in progress */ | ||
| 160 | read_phy(lp->phy_address, MII_BMSR, &bmsr); | ||
| 161 | read_phy(lp->phy_address, MII_BMCR, &bmcr); | ||
| 162 | if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */ | ||
| 163 | if (!(bmsr & BMSR_ANEGCOMPLETE)) | ||
| 164 | return; /* Do nothing - another interrupt generated when negotiation complete */ | ||
| 165 | |||
| 166 | read_phy(lp->phy_address, MII_LPA, &lpa); | ||
| 167 | if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100; | ||
| 168 | else speed = SPEED_10; | ||
| 169 | if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL; | ||
| 170 | else duplex = DUPLEX_HALF; | ||
| 171 | } else { | ||
| 172 | speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; | ||
| 173 | duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* Update the MAC */ | ||
| 177 | mac_cfg = at91_emac_read(AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD); | ||
| 178 | if (speed == SPEED_100) { | ||
| 179 | if (duplex == DUPLEX_FULL) /* 100 Full Duplex */ | ||
| 180 | mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD; | ||
| 181 | else /* 100 Half Duplex */ | ||
| 182 | mac_cfg |= AT91_EMAC_SPD; | ||
| 183 | } else { | ||
| 184 | if (duplex == DUPLEX_FULL) /* 10 Full Duplex */ | ||
| 185 | mac_cfg |= AT91_EMAC_FD; | ||
| 186 | else {} /* 10 Half Duplex */ | ||
| 187 | } | ||
| 188 | at91_emac_write(AT91_EMAC_CFG, mac_cfg); | ||
| 189 | |||
| 190 | if (!silent) | ||
| 191 | printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); | ||
| 192 | netif_carrier_on(dev); | ||
| 193 | } | ||
| 194 | |||
| 195 | /* | ||
| 196 | * Handle interrupts from the PHY | ||
| 197 | */ | ||
| 198 | static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) | ||
| 199 | { | ||
| 200 | struct net_device *dev = (struct net_device *) dev_id; | ||
| 201 | struct at91_private *lp = netdev_priv(dev); | ||
| 202 | unsigned int phy; | ||
| 203 | |||
| 204 | /* | ||
| 205 | * This hander is triggered on both edges, but the PHY chips expect | ||
| 206 | * level-triggering. We therefore have to check if the PHY actually has | ||
| 207 | * an IRQ pending. | ||
| 208 | */ | ||
| 209 | enable_mdi(); | ||
| 210 | if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { | ||
| 211 | read_phy(lp->phy_address, MII_DSINTR_REG, &phy); /* ack interrupt in Davicom PHY */ | ||
| 212 | if (!(phy & (1 << 0))) | ||
| 213 | goto done; | ||
| 214 | } | ||
| 215 | else if (lp->phy_type == MII_LXT971A_ID) { | ||
| 216 | read_phy(lp->phy_address, MII_ISINTS_REG, &phy); /* ack interrupt in Intel PHY */ | ||
| 217 | if (!(phy & (1 << 2))) | ||
| 218 | goto done; | ||
| 219 | } | ||
| 220 | else if (lp->phy_type == MII_BCM5221_ID) { | ||
| 221 | read_phy(lp->phy_address, MII_BCMINTR_REG, &phy); /* ack interrupt in Broadcom PHY */ | ||
| 222 | if (!(phy & (1 << 0))) | ||
| 223 | goto done; | ||
| 224 | } | ||
| 225 | else if (lp->phy_type == MII_KS8721_ID) { | ||
| 226 | read_phy(lp->phy_address, MII_TPISTATUS, &phy); /* ack interrupt in Micrel PHY */ | ||
| 227 | if (!(phy & ((1 << 2) | 1))) | ||
| 228 | goto done; | ||
| 229 | } | ||
| 230 | else if (lp->phy_type == MII_T78Q21x3_ID) { /* ack interrupt in Teridian PHY */ | ||
| 231 | read_phy(lp->phy_address, MII_T78Q21INT_REG, &phy); | ||
| 232 | if (!(phy & ((1 << 2) | 1))) | ||
| 233 | goto done; | ||
| 234 | } | ||
| 235 | else if (lp->phy_type == MII_DP83848_ID) { | ||
| 236 | read_phy(lp->phy_address, MII_DPPHYSTS_REG, &phy); /* ack interrupt in DP83848 PHY */ | ||
| 237 | if (!(phy & (1 << 7))) | ||
| 238 | goto done; | ||
| 239 | } | ||
| 240 | |||
| 241 | update_linkspeed(dev, 0); | ||
| 242 | |||
| 243 | done: | ||
| 244 | disable_mdi(); | ||
| 245 | |||
| 246 | return IRQ_HANDLED; | ||
| 247 | } | ||
| 248 | |||
| 249 | /* | ||
| 250 | * Initialize and enable the PHY interrupt for link-state changes | ||
| 251 | */ | ||
| 252 | static void enable_phyirq(struct net_device *dev) | ||
| 253 | { | ||
| 254 | struct at91_private *lp = netdev_priv(dev); | ||
| 255 | unsigned int dsintr, irq_number; | ||
| 256 | int status; | ||
| 257 | |||
| 258 | irq_number = lp->board_data.phy_irq_pin; | ||
| 259 | if (!irq_number) { | ||
| 260 | /* | ||
| 261 | * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), | ||
| 262 | * or board does not have it connected. | ||
| 263 | */ | ||
| 264 | mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | |||
| 268 | status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); | ||
| 269 | if (status) { | ||
| 270 | printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); | ||
| 271 | return; | ||
| 272 | } | ||
| 273 | |||
| 274 | spin_lock_irq(&lp->lock); | ||
| 275 | enable_mdi(); | ||
| 276 | |||
| 277 | if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ | ||
| 278 | read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); | ||
| 279 | dsintr = dsintr & ~0xf00; /* clear bits 8..11 */ | ||
| 280 | write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); | ||
| 281 | } | ||
| 282 | else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ | ||
| 283 | read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); | ||
| 284 | dsintr = dsintr | 0xf2; /* set bits 1, 4..7 */ | ||
| 285 | write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); | ||
| 286 | } | ||
| 287 | else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ | ||
| 288 | dsintr = (1 << 15) | ( 1 << 14); | ||
| 289 | write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); | ||
| 290 | } | ||
| 291 | else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ | ||
| 292 | dsintr = (1 << 10) | ( 1 << 8); | ||
| 293 | write_phy(lp->phy_address, MII_TPISTATUS, dsintr); | ||
| 294 | } | ||
| 295 | else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ | ||
| 296 | read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); | ||
| 297 | dsintr = dsintr | 0x500; /* set bits 8, 10 */ | ||
| 298 | write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); | ||
| 299 | } | ||
| 300 | else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ | ||
| 301 | read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); | ||
| 302 | dsintr = dsintr | 0x3c; /* set bits 2..5 */ | ||
| 303 | write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); | ||
| 304 | read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); | ||
| 305 | dsintr = dsintr | 0x3; /* set bits 0,1 */ | ||
| 306 | write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); | ||
| 307 | } | ||
| 308 | |||
| 309 | disable_mdi(); | ||
| 310 | spin_unlock_irq(&lp->lock); | ||
| 311 | } | ||
| 312 | |||
| 313 | /* | ||
| 314 | * Disable the PHY interrupt | ||
| 315 | */ | ||
| 316 | static void disable_phyirq(struct net_device *dev) | ||
| 317 | { | ||
| 318 | struct at91_private *lp = netdev_priv(dev); | ||
| 319 | unsigned int dsintr; | ||
| 320 | unsigned int irq_number; | ||
| 321 | |||
| 322 | irq_number = lp->board_data.phy_irq_pin; | ||
| 323 | if (!irq_number) { | ||
| 324 | del_timer_sync(&lp->check_timer); | ||
| 325 | return; | ||
| 326 | } | ||
| 327 | |||
| 328 | spin_lock_irq(&lp->lock); | ||
| 329 | enable_mdi(); | ||
| 330 | |||
| 331 | if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { /* for Davicom PHY */ | ||
| 332 | read_phy(lp->phy_address, MII_DSINTR_REG, &dsintr); | ||
| 333 | dsintr = dsintr | 0xf00; /* set bits 8..11 */ | ||
| 334 | write_phy(lp->phy_address, MII_DSINTR_REG, dsintr); | ||
| 335 | } | ||
| 336 | else if (lp->phy_type == MII_LXT971A_ID) { /* for Intel PHY */ | ||
| 337 | read_phy(lp->phy_address, MII_ISINTE_REG, &dsintr); | ||
| 338 | dsintr = dsintr & ~0xf2; /* clear bits 1, 4..7 */ | ||
| 339 | write_phy(lp->phy_address, MII_ISINTE_REG, dsintr); | ||
| 340 | } | ||
| 341 | else if (lp->phy_type == MII_BCM5221_ID) { /* for Broadcom PHY */ | ||
| 342 | read_phy(lp->phy_address, MII_BCMINTR_REG, &dsintr); | ||
| 343 | dsintr = ~(1 << 14); | ||
| 344 | write_phy(lp->phy_address, MII_BCMINTR_REG, dsintr); | ||
| 345 | } | ||
| 346 | else if (lp->phy_type == MII_KS8721_ID) { /* for Micrel PHY */ | ||
| 347 | read_phy(lp->phy_address, MII_TPISTATUS, &dsintr); | ||
| 348 | dsintr = ~((1 << 10) | (1 << 8)); | ||
| 349 | write_phy(lp->phy_address, MII_TPISTATUS, dsintr); | ||
| 350 | } | ||
| 351 | else if (lp->phy_type == MII_T78Q21x3_ID) { /* for Teridian PHY */ | ||
| 352 | read_phy(lp->phy_address, MII_T78Q21INT_REG, &dsintr); | ||
| 353 | dsintr = dsintr & ~0x500; /* clear bits 8, 10 */ | ||
| 354 | write_phy(lp->phy_address, MII_T78Q21INT_REG, dsintr); | ||
| 355 | } | ||
| 356 | else if (lp->phy_type == MII_DP83848_ID) { /* National Semiconductor DP83848 PHY */ | ||
| 357 | read_phy(lp->phy_address, MII_DPMICR_REG, &dsintr); | ||
| 358 | dsintr = dsintr & ~0x3; /* clear bits 0, 1 */ | ||
| 359 | write_phy(lp->phy_address, MII_DPMICR_REG, dsintr); | ||
| 360 | read_phy(lp->phy_address, MII_DPMISR_REG, &dsintr); | ||
| 361 | dsintr = dsintr & ~0x3c; /* clear bits 2..5 */ | ||
| 362 | write_phy(lp->phy_address, MII_DPMISR_REG, dsintr); | ||
| 363 | } | ||
| 364 | |||
| 365 | disable_mdi(); | ||
| 366 | spin_unlock_irq(&lp->lock); | ||
| 367 | |||
| 368 | free_irq(irq_number, dev); /* Free interrupt handler */ | ||
| 369 | } | ||
| 370 | |||
| 371 | /* | ||
| 372 | * Perform a software reset of the PHY. | ||
| 373 | */ | ||
| 374 | #if 0 | ||
| 375 | static void reset_phy(struct net_device *dev) | ||
| 376 | { | ||
| 377 | struct at91_private *lp = netdev_priv(dev); | ||
| 378 | unsigned int bmcr; | ||
| 379 | |||
| 380 | spin_lock_irq(&lp->lock); | ||
| 381 | enable_mdi(); | ||
| 382 | |||
| 383 | /* Perform PHY reset */ | ||
| 384 | write_phy(lp->phy_address, MII_BMCR, BMCR_RESET); | ||
| 385 | |||
| 386 | /* Wait until PHY reset is complete */ | ||
| 387 | do { | ||
| 388 | read_phy(lp->phy_address, MII_BMCR, &bmcr); | ||
| 389 | } while (!(bmcr & BMCR_RESET)); | ||
| 390 | |||
| 391 | disable_mdi(); | ||
| 392 | spin_unlock_irq(&lp->lock); | ||
| 393 | } | ||
| 394 | #endif | ||
| 395 | |||
| 396 | static void at91ether_check_link(unsigned long dev_id) | ||
| 397 | { | ||
| 398 | struct net_device *dev = (struct net_device *) dev_id; | ||
| 399 | struct at91_private *lp = netdev_priv(dev); | ||
| 400 | |||
| 401 | enable_mdi(); | ||
| 402 | update_linkspeed(dev, 1); | ||
| 403 | disable_mdi(); | ||
| 404 | |||
| 405 | mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); | ||
| 406 | } | ||
| 407 | |||
| 408 | /* ......................... ADDRESS MANAGEMENT ........................ */ | ||
| 409 | |||
| 410 | /* | ||
| 411 | * NOTE: Your bootloader must always set the MAC address correctly before | ||
| 412 | * booting into Linux. | ||
| 413 | * | ||
| 414 | * - It must always set the MAC address after reset, even if it doesn't | ||
| 415 | * happen to access the Ethernet while it's booting. Some versions of | ||
| 416 | * U-Boot on the AT91RM9200-DK do not do this. | ||
| 417 | * | ||
| 418 | * - Likewise it must store the addresses in the correct byte order. | ||
| 419 | * MicroMonitor (uMon) on the CSB337 does this incorrectly (and | ||
| 420 | * continues to do so, for bug-compatibility). | ||
| 421 | */ | ||
| 422 | |||
| 423 | static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo) | ||
| 424 | { | ||
| 425 | char addr[6]; | ||
| 426 | |||
| 427 | if (machine_is_csb337()) { | ||
| 428 | addr[5] = (lo & 0xff); /* The CSB337 bootloader stores the MAC the wrong-way around */ | ||
| 429 | addr[4] = (lo & 0xff00) >> 8; | ||
| 430 | addr[3] = (lo & 0xff0000) >> 16; | ||
| 431 | addr[2] = (lo & 0xff000000) >> 24; | ||
| 432 | addr[1] = (hi & 0xff); | ||
| 433 | addr[0] = (hi & 0xff00) >> 8; | ||
| 434 | } | ||
| 435 | else { | ||
| 436 | addr[0] = (lo & 0xff); | ||
| 437 | addr[1] = (lo & 0xff00) >> 8; | ||
| 438 | addr[2] = (lo & 0xff0000) >> 16; | ||
| 439 | addr[3] = (lo & 0xff000000) >> 24; | ||
| 440 | addr[4] = (hi & 0xff); | ||
| 441 | addr[5] = (hi & 0xff00) >> 8; | ||
| 442 | } | ||
| 443 | |||
| 444 | if (is_valid_ether_addr(addr)) { | ||
| 445 | memcpy(dev->dev_addr, &addr, 6); | ||
| 446 | return 1; | ||
| 447 | } | ||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | /* | ||
| 452 | * Set the ethernet MAC address in dev->dev_addr | ||
| 453 | */ | ||
| 454 | static void __init get_mac_address(struct net_device *dev) | ||
| 455 | { | ||
| 456 | /* Check Specific-Address 1 */ | ||
| 457 | if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA1H), at91_emac_read(AT91_EMAC_SA1L))) | ||
| 458 | return; | ||
| 459 | /* Check Specific-Address 2 */ | ||
| 460 | if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA2H), at91_emac_read(AT91_EMAC_SA2L))) | ||
| 461 | return; | ||
| 462 | /* Check Specific-Address 3 */ | ||
| 463 | if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA3H), at91_emac_read(AT91_EMAC_SA3L))) | ||
| 464 | return; | ||
| 465 | /* Check Specific-Address 4 */ | ||
| 466 | if (unpack_mac_address(dev, at91_emac_read(AT91_EMAC_SA4H), at91_emac_read(AT91_EMAC_SA4L))) | ||
| 467 | return; | ||
| 468 | |||
| 469 | printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n"); | ||
| 470 | } | ||
| 471 | |||
| 472 | /* | ||
| 473 | * Program the hardware MAC address from dev->dev_addr. | ||
| 474 | */ | ||
| 475 | static void update_mac_address(struct net_device *dev) | ||
| 476 | { | ||
| 477 | at91_emac_write(AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0])); | ||
| 478 | at91_emac_write(AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4])); | ||
| 479 | |||
| 480 | at91_emac_write(AT91_EMAC_SA2L, 0); | ||
| 481 | at91_emac_write(AT91_EMAC_SA2H, 0); | ||
| 482 | } | ||
| 483 | |||
| 484 | /* | ||
| 485 | * Store the new hardware address in dev->dev_addr, and update the MAC. | ||
| 486 | */ | ||
| 487 | static int set_mac_address(struct net_device *dev, void* addr) | ||
| 488 | { | ||
| 489 | struct sockaddr *address = addr; | ||
| 490 | |||
| 491 | if (!is_valid_ether_addr(address->sa_data)) | ||
| 492 | return -EADDRNOTAVAIL; | ||
| 493 | |||
| 494 | memcpy(dev->dev_addr, address->sa_data, dev->addr_len); | ||
| 495 | update_mac_address(dev); | ||
| 496 | |||
| 497 | printk("%s: Setting MAC address to %pM\n", dev->name, | ||
| 498 | dev->dev_addr); | ||
| 499 | |||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | static int inline hash_bit_value(int bitnr, __u8 *addr) | ||
| 504 | { | ||
| 505 | if (addr[bitnr / 8] & (1 << (bitnr % 8))) | ||
| 506 | return 1; | ||
| 507 | return 0; | ||
| 508 | } | ||
| 509 | |||
| 510 | /* | ||
| 511 | * The hash address register is 64 bits long and takes up two locations in the memory map. | ||
| 512 | * The least significant bits are stored in EMAC_HSL and the most significant | ||
| 513 | * bits in EMAC_HSH. | ||
| 514 | * | ||
| 515 | * The unicast hash enable and the multicast hash enable bits in the network configuration | ||
| 516 | * register enable the reception of hash matched frames. The destination address is | ||
| 517 | * reduced to a 6 bit index into the 64 bit hash register using the following hash function. | ||
| 518 | * The hash function is an exclusive or of every sixth bit of the destination address. | ||
| 519 | * hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] | ||
| 520 | * hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] | ||
| 521 | * hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] | ||
| 522 | * hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] | ||
| 523 | * hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] | ||
| 524 | * hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] | ||
| 525 | * da[0] represents the least significant bit of the first byte received, that is, the multicast/ | ||
| 526 | * unicast indicator, and da[47] represents the most significant bit of the last byte | ||
| 527 | * received. | ||
| 528 | * If the hash index points to a bit that is set in the hash register then the frame will be | ||
| 529 | * matched according to whether the frame is multicast or unicast. | ||
| 530 | * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and | ||
| 531 | * the hash index points to a bit set in the hash register. | ||
| 532 | * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the | ||
| 533 | * hash index points to a bit set in the hash register. | ||
| 534 | * To receive all multicast frames, the hash register should be set with all ones and the | ||
| 535 | * multicast hash enable bit should be set in the network configuration register. | ||
| 536 | */ | ||
| 537 | |||
| 538 | /* | ||
| 539 | * Return the hash index value for the specified address. | ||
| 540 | */ | ||
| 541 | static int hash_get_index(__u8 *addr) | ||
| 542 | { | ||
| 543 | int i, j, bitval; | ||
| 544 | int hash_index = 0; | ||
| 545 | |||
| 546 | for (j = 0; j < 6; j++) { | ||
| 547 | for (i = 0, bitval = 0; i < 8; i++) | ||
| 548 | bitval ^= hash_bit_value(i*6 + j, addr); | ||
| 549 | |||
| 550 | hash_index |= (bitval << j); | ||
| 551 | } | ||
| 552 | |||
| 553 | return hash_index; | ||
| 554 | } | ||
| 555 | |||
| 556 | /* | ||
| 557 | * Add multicast addresses to the internal multicast-hash table. | ||
| 558 | */ | ||
| 559 | static void at91ether_sethashtable(struct net_device *dev) | ||
| 560 | { | ||
| 561 | struct netdev_hw_addr *ha; | ||
| 562 | unsigned long mc_filter[2]; | ||
| 563 | unsigned int bitnr; | ||
| 564 | |||
| 565 | mc_filter[0] = mc_filter[1] = 0; | ||
| 566 | |||
| 567 | netdev_for_each_mc_addr(ha, dev) { | ||
| 568 | bitnr = hash_get_index(ha->addr); | ||
| 569 | mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); | ||
| 570 | } | ||
| 571 | |||
| 572 | at91_emac_write(AT91_EMAC_HSL, mc_filter[0]); | ||
| 573 | at91_emac_write(AT91_EMAC_HSH, mc_filter[1]); | ||
| 574 | } | ||
| 575 | |||
| 576 | /* | ||
| 577 | * Enable/Disable promiscuous and multicast modes. | ||
| 578 | */ | ||
| 579 | static void at91ether_set_multicast_list(struct net_device *dev) | ||
| 580 | { | ||
| 581 | unsigned long cfg; | ||
| 582 | |||
| 583 | cfg = at91_emac_read(AT91_EMAC_CFG); | ||
| 584 | |||
| 585 | if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */ | ||
| 586 | cfg |= AT91_EMAC_CAF; | ||
| 587 | else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */ | ||
| 588 | cfg &= ~AT91_EMAC_CAF; | ||
| 589 | |||
| 590 | if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ | ||
| 591 | at91_emac_write(AT91_EMAC_HSH, -1); | ||
| 592 | at91_emac_write(AT91_EMAC_HSL, -1); | ||
| 593 | cfg |= AT91_EMAC_MTI; | ||
| 594 | } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ | ||
| 595 | at91ether_sethashtable(dev); | ||
| 596 | cfg |= AT91_EMAC_MTI; | ||
| 597 | } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ | ||
| 598 | at91_emac_write(AT91_EMAC_HSH, 0); | ||
| 599 | at91_emac_write(AT91_EMAC_HSL, 0); | ||
| 600 | cfg &= ~AT91_EMAC_MTI; | ||
| 601 | } | ||
| 602 | |||
| 603 | at91_emac_write(AT91_EMAC_CFG, cfg); | ||
| 604 | } | ||
| 605 | |||
| 606 | /* ......................... ETHTOOL SUPPORT ........................... */ | ||
| 607 | |||
| 608 | static int mdio_read(struct net_device *dev, int phy_id, int location) | ||
| 609 | { | ||
| 610 | unsigned int value; | ||
| 611 | |||
| 612 | read_phy(phy_id, location, &value); | ||
| 613 | return value; | ||
| 614 | } | ||
| 615 | |||
| 616 | static void mdio_write(struct net_device *dev, int phy_id, int location, int value) | ||
| 617 | { | ||
| 618 | write_phy(phy_id, location, value); | ||
| 619 | } | ||
| 620 | |||
| 621 | static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 622 | { | ||
| 623 | struct at91_private *lp = netdev_priv(dev); | ||
| 624 | int ret; | ||
| 625 | |||
| 626 | spin_lock_irq(&lp->lock); | ||
| 627 | enable_mdi(); | ||
| 628 | |||
| 629 | ret = mii_ethtool_gset(&lp->mii, cmd); | ||
| 630 | |||
| 631 | disable_mdi(); | ||
| 632 | spin_unlock_irq(&lp->lock); | ||
| 633 | |||
| 634 | if (lp->phy_media == PORT_FIBRE) { /* override media type since mii.c doesn't know */ | ||
| 635 | cmd->supported = SUPPORTED_FIBRE; | ||
| 636 | cmd->port = PORT_FIBRE; | ||
| 637 | } | ||
| 638 | |||
| 639 | return ret; | ||
| 640 | } | ||
| 641 | |||
| 642 | static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 643 | { | ||
| 644 | struct at91_private *lp = netdev_priv(dev); | ||
| 645 | int ret; | ||
| 646 | |||
| 647 | spin_lock_irq(&lp->lock); | ||
| 648 | enable_mdi(); | ||
| 649 | |||
| 650 | ret = mii_ethtool_sset(&lp->mii, cmd); | ||
| 651 | |||
| 652 | disable_mdi(); | ||
| 653 | spin_unlock_irq(&lp->lock); | ||
| 654 | |||
| 655 | return ret; | ||
| 656 | } | ||
| 657 | |||
| 658 | static int at91ether_nwayreset(struct net_device *dev) | ||
| 659 | { | ||
| 660 | struct at91_private *lp = netdev_priv(dev); | ||
| 661 | int ret; | ||
| 662 | |||
| 663 | spin_lock_irq(&lp->lock); | ||
| 664 | enable_mdi(); | ||
| 665 | |||
| 666 | ret = mii_nway_restart(&lp->mii); | ||
| 667 | |||
| 668 | disable_mdi(); | ||
| 669 | spin_unlock_irq(&lp->lock); | ||
| 670 | |||
| 671 | return ret; | ||
| 672 | } | ||
| 673 | |||
| 674 | static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | ||
| 675 | { | ||
| 676 | strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); | ||
| 677 | strlcpy(info->version, DRV_VERSION, sizeof(info->version)); | ||
| 678 | strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); | ||
| 679 | } | ||
| 680 | |||
| 681 | static const struct ethtool_ops at91ether_ethtool_ops = { | ||
| 682 | .get_settings = at91ether_get_settings, | ||
| 683 | .set_settings = at91ether_set_settings, | ||
| 684 | .get_drvinfo = at91ether_get_drvinfo, | ||
| 685 | .nway_reset = at91ether_nwayreset, | ||
| 686 | .get_link = ethtool_op_get_link, | ||
| 687 | }; | ||
| 688 | |||
| 689 | static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
| 690 | { | ||
| 691 | struct at91_private *lp = netdev_priv(dev); | ||
| 692 | int res; | ||
| 693 | |||
| 694 | if (!netif_running(dev)) | ||
| 695 | return -EINVAL; | ||
| 696 | |||
| 697 | spin_lock_irq(&lp->lock); | ||
| 698 | enable_mdi(); | ||
| 699 | res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL); | ||
| 700 | disable_mdi(); | ||
| 701 | spin_unlock_irq(&lp->lock); | ||
| 702 | |||
| 703 | return res; | ||
| 704 | } | ||
| 705 | |||
| 706 | /* ................................ MAC ................................ */ | ||
| 707 | |||
| 708 | /* | ||
| 709 | * Initialize and start the Receiver and Transmit subsystems | ||
| 710 | */ | ||
| 711 | static void at91ether_start(struct net_device *dev) | ||
| 712 | { | ||
| 713 | struct at91_private *lp = netdev_priv(dev); | ||
| 714 | struct recv_desc_bufs *dlist, *dlist_phys; | ||
| 715 | int i; | ||
| 716 | unsigned long ctl; | ||
| 717 | |||
| 718 | dlist = lp->dlist; | ||
| 719 | dlist_phys = lp->dlist_phys; | ||
| 720 | |||
| 721 | for (i = 0; i < MAX_RX_DESCR; i++) { | ||
| 722 | dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0]; | ||
| 723 | dlist->descriptors[i].size = 0; | ||
| 724 | } | ||
| 725 | |||
| 726 | /* Set the Wrap bit on the last descriptor */ | ||
| 727 | dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP; | ||
| 728 | |||
| 729 | /* Reset buffer index */ | ||
| 730 | lp->rxBuffIndex = 0; | ||
| 731 | |||
| 732 | /* Program address of descriptor list in Rx Buffer Queue register */ | ||
| 733 | at91_emac_write(AT91_EMAC_RBQP, (unsigned long) dlist_phys); | ||
| 734 | |||
| 735 | /* Enable Receive and Transmit */ | ||
| 736 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 737 | at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE); | ||
| 738 | } | ||
| 739 | |||
| 740 | /* | ||
| 741 | * Open the ethernet interface | ||
| 742 | */ | ||
| 743 | static int at91ether_open(struct net_device *dev) | ||
| 744 | { | ||
| 745 | struct at91_private *lp = netdev_priv(dev); | ||
| 746 | unsigned long ctl; | ||
| 747 | |||
| 748 | if (!is_valid_ether_addr(dev->dev_addr)) | ||
| 749 | return -EADDRNOTAVAIL; | ||
| 750 | |||
| 751 | clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */ | ||
| 752 | |||
| 753 | /* Clear internal statistics */ | ||
| 754 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 755 | at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_CSR); | ||
| 756 | |||
| 757 | /* Update the MAC address (incase user has changed it) */ | ||
| 758 | update_mac_address(dev); | ||
| 759 | |||
| 760 | /* Enable PHY interrupt */ | ||
| 761 | enable_phyirq(dev); | ||
| 762 | |||
| 763 | /* Enable MAC interrupts */ | ||
| 764 | at91_emac_write(AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA | ||
| 765 | | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM | ||
| 766 | | AT91_EMAC_ROVR | AT91_EMAC_ABT); | ||
| 767 | |||
| 768 | /* Determine current link speed */ | ||
| 769 | spin_lock_irq(&lp->lock); | ||
| 770 | enable_mdi(); | ||
| 771 | update_linkspeed(dev, 0); | ||
| 772 | disable_mdi(); | ||
| 773 | spin_unlock_irq(&lp->lock); | ||
| 774 | |||
| 775 | at91ether_start(dev); | ||
| 776 | netif_start_queue(dev); | ||
| 777 | return 0; | ||
| 778 | } | ||
| 779 | |||
| 780 | /* | ||
| 781 | * Close the interface | ||
| 782 | */ | ||
| 783 | static int at91ether_close(struct net_device *dev) | ||
| 784 | { | ||
| 785 | struct at91_private *lp = netdev_priv(dev); | ||
| 786 | unsigned long ctl; | ||
| 787 | |||
| 788 | /* Disable Receiver and Transmitter */ | ||
| 789 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 790 | at91_emac_write(AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE)); | ||
| 791 | |||
| 792 | /* Disable PHY interrupt */ | ||
| 793 | disable_phyirq(dev); | ||
| 794 | |||
| 795 | /* Disable MAC interrupts */ | ||
| 796 | at91_emac_write(AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA | ||
| 797 | | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM | ||
| 798 | | AT91_EMAC_ROVR | AT91_EMAC_ABT); | ||
| 799 | |||
| 800 | netif_stop_queue(dev); | ||
| 801 | |||
| 802 | clk_disable(lp->ether_clk); /* Disable Peripheral clock */ | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | /* | ||
| 808 | * Transmit packet. | ||
| 809 | */ | ||
| 810 | static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 811 | { | ||
| 812 | struct at91_private *lp = netdev_priv(dev); | ||
| 813 | |||
| 814 | if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) { | ||
| 815 | netif_stop_queue(dev); | ||
| 816 | |||
| 817 | /* Store packet information (to free when Tx completed) */ | ||
| 818 | lp->skb = skb; | ||
| 819 | lp->skb_length = skb->len; | ||
| 820 | lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); | ||
| 821 | dev->stats.tx_bytes += skb->len; | ||
| 822 | |||
| 823 | /* Set address of the data in the Transmit Address register */ | ||
| 824 | at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr); | ||
| 825 | /* Set length of the packet in the Transmit Control register */ | ||
| 826 | at91_emac_write(AT91_EMAC_TCR, skb->len); | ||
| 827 | |||
| 828 | } else { | ||
| 829 | printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n"); | ||
| 830 | return NETDEV_TX_BUSY; /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb) | ||
| 831 | on this skb, he also reports -ENETDOWN and printk's, so either | ||
| 832 | we free and return(0) or don't free and return 1 */ | ||
| 833 | } | ||
| 834 | |||
| 835 | return NETDEV_TX_OK; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* | ||
| 839 | * Update the current statistics from the internal statistics registers. | ||
| 840 | */ | ||
| 841 | static struct net_device_stats *at91ether_stats(struct net_device *dev) | ||
| 842 | { | ||
| 843 | int ale, lenerr, seqe, lcol, ecol; | ||
| 844 | |||
| 845 | if (netif_running(dev)) { | ||
| 846 | dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK); /* Good frames received */ | ||
| 847 | ale = at91_emac_read(AT91_EMAC_ALE); | ||
| 848 | dev->stats.rx_frame_errors += ale; /* Alignment errors */ | ||
| 849 | lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF); | ||
| 850 | dev->stats.rx_length_errors += lenerr; /* Excessive Length or Undersize Frame error */ | ||
| 851 | seqe = at91_emac_read(AT91_EMAC_SEQE); | ||
| 852 | dev->stats.rx_crc_errors += seqe; /* CRC error */ | ||
| 853 | dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC); /* Receive buffer not available */ | ||
| 854 | dev->stats.rx_errors += (ale + lenerr + seqe | ||
| 855 | + at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB)); | ||
| 856 | |||
| 857 | dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA); /* Frames successfully transmitted */ | ||
| 858 | dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE); /* Transmit FIFO underruns */ | ||
| 859 | dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE); /* Carrier Sense errors */ | ||
| 860 | dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */ | ||
| 861 | |||
| 862 | lcol = at91_emac_read(AT91_EMAC_LCOL); | ||
| 863 | ecol = at91_emac_read(AT91_EMAC_ECOL); | ||
| 864 | dev->stats.tx_window_errors += lcol; /* Late collisions */ | ||
| 865 | dev->stats.tx_aborted_errors += ecol; /* 16 collisions */ | ||
| 866 | |||
| 867 | dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol); | ||
| 868 | } | ||
| 869 | return &dev->stats; | ||
| 870 | } | ||
| 871 | |||
| 872 | /* | ||
| 873 | * Extract received frame from buffer descriptors and sent to upper layers. | ||
| 874 | * (Called from interrupt context) | ||
| 875 | */ | ||
| 876 | static void at91ether_rx(struct net_device *dev) | ||
| 877 | { | ||
| 878 | struct at91_private *lp = netdev_priv(dev); | ||
| 879 | struct recv_desc_bufs *dlist; | ||
| 880 | unsigned char *p_recv; | ||
| 881 | struct sk_buff *skb; | ||
| 882 | unsigned int pktlen; | ||
| 883 | |||
| 884 | dlist = lp->dlist; | ||
| 885 | while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { | ||
| 886 | p_recv = dlist->recv_buf[lp->rxBuffIndex]; | ||
| 887 | pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ | ||
| 888 | skb = dev_alloc_skb(pktlen + 2); | ||
| 889 | if (skb != NULL) { | ||
| 890 | skb_reserve(skb, 2); | ||
| 891 | memcpy(skb_put(skb, pktlen), p_recv, pktlen); | ||
| 892 | |||
| 893 | skb->protocol = eth_type_trans(skb, dev); | ||
| 894 | dev->stats.rx_bytes += pktlen; | ||
| 895 | netif_rx(skb); | ||
| 896 | } | ||
| 897 | else { | ||
| 898 | dev->stats.rx_dropped += 1; | ||
| 899 | printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); | ||
| 900 | } | ||
| 901 | |||
| 902 | if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST) | ||
| 903 | dev->stats.multicast++; | ||
| 904 | |||
| 905 | dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ | ||
| 906 | if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ | ||
| 907 | lp->rxBuffIndex = 0; | ||
| 908 | else | ||
| 909 | lp->rxBuffIndex++; | ||
| 910 | } | ||
| 911 | } | ||
| 912 | |||
| 913 | /* | ||
| 914 | * MAC interrupt handler | ||
| 915 | */ | ||
| 916 | static irqreturn_t at91ether_interrupt(int irq, void *dev_id) | ||
| 917 | { | ||
| 918 | struct net_device *dev = (struct net_device *) dev_id; | ||
| 919 | struct at91_private *lp = netdev_priv(dev); | ||
| 920 | unsigned long intstatus, ctl; | ||
| 921 | |||
| 922 | /* MAC Interrupt Status register indicates what interrupts are pending. | ||
| 923 | It is automatically cleared once read. */ | ||
| 924 | intstatus = at91_emac_read(AT91_EMAC_ISR); | ||
| 925 | |||
| 926 | if (intstatus & AT91_EMAC_RCOM) /* Receive complete */ | ||
| 927 | at91ether_rx(dev); | ||
| 928 | |||
| 929 | if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */ | ||
| 930 | /* The TCOM bit is set even if the transmission failed. */ | ||
| 931 | if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY)) | ||
| 932 | dev->stats.tx_errors += 1; | ||
| 933 | |||
| 934 | if (lp->skb) { | ||
| 935 | dev_kfree_skb_irq(lp->skb); | ||
| 936 | lp->skb = NULL; | ||
| 937 | dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); | ||
| 938 | } | ||
| 939 | netif_wake_queue(dev); | ||
| 940 | } | ||
| 941 | |||
| 942 | /* Work-around for Errata #11 */ | ||
| 943 | if (intstatus & AT91_EMAC_RBNA) { | ||
| 944 | ctl = at91_emac_read(AT91_EMAC_CTL); | ||
| 945 | at91_emac_write(AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE); | ||
| 946 | at91_emac_write(AT91_EMAC_CTL, ctl | AT91_EMAC_RE); | ||
| 947 | } | ||
| 948 | |||
| 949 | if (intstatus & AT91_EMAC_ROVR) | ||
| 950 | printk("%s: ROVR error\n", dev->name); | ||
| 951 | |||
| 952 | return IRQ_HANDLED; | ||
| 953 | } | ||
| 954 | |||
| 955 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 956 | static void at91ether_poll_controller(struct net_device *dev) | ||
| 957 | { | ||
| 958 | unsigned long flags; | ||
| 959 | |||
| 960 | local_irq_save(flags); | ||
| 961 | at91ether_interrupt(dev->irq, dev); | ||
| 962 | local_irq_restore(flags); | ||
| 963 | } | ||
| 964 | #endif | ||
| 965 | |||
| 966 | static const struct net_device_ops at91ether_netdev_ops = { | ||
| 967 | .ndo_open = at91ether_open, | ||
| 968 | .ndo_stop = at91ether_close, | ||
| 969 | .ndo_start_xmit = at91ether_start_xmit, | ||
| 970 | .ndo_get_stats = at91ether_stats, | ||
| 971 | .ndo_set_multicast_list = at91ether_set_multicast_list, | ||
| 972 | .ndo_set_mac_address = set_mac_address, | ||
| 973 | .ndo_do_ioctl = at91ether_ioctl, | ||
| 974 | .ndo_validate_addr = eth_validate_addr, | ||
| 975 | .ndo_change_mtu = eth_change_mtu, | ||
| 976 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 977 | .ndo_poll_controller = at91ether_poll_controller, | ||
| 978 | #endif | ||
| 979 | }; | ||
| 980 | |||
| 981 | /* | ||
| 982 | * Initialize the ethernet interface | ||
| 983 | */ | ||
| 984 | static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, | ||
| 985 | struct platform_device *pdev, struct clk *ether_clk) | ||
| 986 | { | ||
| 987 | struct at91_eth_data *board_data = pdev->dev.platform_data; | ||
| 988 | struct net_device *dev; | ||
| 989 | struct at91_private *lp; | ||
| 990 | unsigned int val; | ||
| 991 | int res; | ||
| 992 | |||
| 993 | dev = alloc_etherdev(sizeof(struct at91_private)); | ||
| 994 | if (!dev) | ||
| 995 | return -ENOMEM; | ||
| 996 | |||
| 997 | dev->base_addr = AT91_VA_BASE_EMAC; | ||
| 998 | dev->irq = AT91RM9200_ID_EMAC; | ||
| 999 | |||
| 1000 | /* Install the interrupt handler */ | ||
| 1001 | if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) { | ||
| 1002 | free_netdev(dev); | ||
| 1003 | return -EBUSY; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | /* Allocate memory for DMA Receive descriptors */ | ||
| 1007 | lp = netdev_priv(dev); | ||
| 1008 | lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL); | ||
| 1009 | if (lp->dlist == NULL) { | ||
| 1010 | free_irq(dev->irq, dev); | ||
| 1011 | free_netdev(dev); | ||
| 1012 | return -ENOMEM; | ||
| 1013 | } | ||
| 1014 | lp->board_data = *board_data; | ||
| 1015 | lp->ether_clk = ether_clk; | ||
| 1016 | platform_set_drvdata(pdev, dev); | ||
| 1017 | |||
| 1018 | spin_lock_init(&lp->lock); | ||
| 1019 | |||
| 1020 | ether_setup(dev); | ||
| 1021 | dev->netdev_ops = &at91ether_netdev_ops; | ||
| 1022 | dev->ethtool_ops = &at91ether_ethtool_ops; | ||
| 1023 | |||
| 1024 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
| 1025 | |||
| 1026 | get_mac_address(dev); /* Get ethernet address and store it in dev->dev_addr */ | ||
| 1027 | update_mac_address(dev); /* Program ethernet address into MAC */ | ||
| 1028 | |||
| 1029 | at91_emac_write(AT91_EMAC_CTL, 0); | ||
| 1030 | |||
| 1031 | if (lp->board_data.is_rmii) | ||
| 1032 | at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII); | ||
| 1033 | else | ||
| 1034 | at91_emac_write(AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG); | ||
| 1035 | |||
| 1036 | /* Perform PHY-specific initialization */ | ||
| 1037 | spin_lock_irq(&lp->lock); | ||
| 1038 | enable_mdi(); | ||
| 1039 | if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) { | ||
| 1040 | read_phy(phy_address, MII_DSCR_REG, &val); | ||
| 1041 | if ((val & (1 << 10)) == 0) /* DSCR bit 10 is 0 -- fiber mode */ | ||
| 1042 | lp->phy_media = PORT_FIBRE; | ||
| 1043 | } else if (machine_is_csb337()) { | ||
| 1044 | /* mix link activity status into LED2 link state */ | ||
| 1045 | write_phy(phy_address, MII_LEDCTRL_REG, 0x0d22); | ||
| 1046 | } else if (machine_is_ecbat91()) | ||
| 1047 | write_phy(phy_address, MII_LEDCTRL_REG, 0x156A); | ||
| 1048 | |||
| 1049 | disable_mdi(); | ||
| 1050 | spin_unlock_irq(&lp->lock); | ||
| 1051 | |||
| 1052 | lp->mii.dev = dev; /* Support for ethtool */ | ||
| 1053 | lp->mii.mdio_read = mdio_read; | ||
| 1054 | lp->mii.mdio_write = mdio_write; | ||
| 1055 | lp->mii.phy_id = phy_address; | ||
| 1056 | lp->mii.phy_id_mask = 0x1f; | ||
| 1057 | lp->mii.reg_num_mask = 0x1f; | ||
| 1058 | |||
| 1059 | lp->phy_type = phy_type; /* Type of PHY connected */ | ||
| 1060 | lp->phy_address = phy_address; /* MDI address of PHY */ | ||
| 1061 | |||
| 1062 | /* Register the network interface */ | ||
| 1063 | res = register_netdev(dev); | ||
| 1064 | if (res) { | ||
| 1065 | free_irq(dev->irq, dev); | ||
| 1066 | free_netdev(dev); | ||
| 1067 | dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); | ||
| 1068 | return res; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | /* Determine current link speed */ | ||
| 1072 | spin_lock_irq(&lp->lock); | ||
| 1073 | enable_mdi(); | ||
| 1074 | update_linkspeed(dev, 0); | ||
| 1075 | disable_mdi(); | ||
| 1076 | spin_unlock_irq(&lp->lock); | ||
| 1077 | netif_carrier_off(dev); /* will be enabled in open() */ | ||
| 1078 | |||
| 1079 | /* If board has no PHY IRQ, use a timer to poll the PHY */ | ||
| 1080 | if (!lp->board_data.phy_irq_pin) { | ||
| 1081 | init_timer(&lp->check_timer); | ||
| 1082 | lp->check_timer.data = (unsigned long)dev; | ||
| 1083 | lp->check_timer.function = at91ether_check_link; | ||
| 1084 | } else if (lp->board_data.phy_irq_pin >= 32) | ||
| 1085 | gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy"); | ||
| 1086 | |||
| 1087 | /* Display ethernet banner */ | ||
| 1088 | printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n", | ||
| 1089 | dev->name, (uint) dev->base_addr, dev->irq, | ||
| 1090 | at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-", | ||
| 1091 | at91_emac_read(AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex", | ||
| 1092 | dev->dev_addr); | ||
| 1093 | if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) | ||
| 1094 | printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)"); | ||
| 1095 | else if (phy_type == MII_LXT971A_ID) | ||
| 1096 | printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name); | ||
| 1097 | else if (phy_type == MII_RTL8201_ID) | ||
| 1098 | printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name); | ||
| 1099 | else if (phy_type == MII_BCM5221_ID) | ||
| 1100 | printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name); | ||
| 1101 | else if (phy_type == MII_DP83847_ID) | ||
| 1102 | printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name); | ||
| 1103 | else if (phy_type == MII_DP83848_ID) | ||
| 1104 | printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name); | ||
| 1105 | else if (phy_type == MII_AC101L_ID) | ||
| 1106 | printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name); | ||
| 1107 | else if (phy_type == MII_KS8721_ID) | ||
| 1108 | printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name); | ||
| 1109 | else if (phy_type == MII_T78Q21x3_ID) | ||
| 1110 | printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name); | ||
| 1111 | else if (phy_type == MII_LAN83C185_ID) | ||
| 1112 | printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name); | ||
| 1113 | |||
| 1114 | return 0; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | /* | ||
| 1118 | * Detect MAC and PHY and perform initialization | ||
| 1119 | */ | ||
| 1120 | static int __init at91ether_probe(struct platform_device *pdev) | ||
| 1121 | { | ||
| 1122 | unsigned int phyid1, phyid2; | ||
| 1123 | int detected = -1; | ||
| 1124 | unsigned long phy_id; | ||
| 1125 | unsigned short phy_address = 0; | ||
| 1126 | struct clk *ether_clk; | ||
| 1127 | |||
| 1128 | ether_clk = clk_get(&pdev->dev, "ether_clk"); | ||
| 1129 | if (IS_ERR(ether_clk)) { | ||
| 1130 | printk(KERN_ERR "at91_ether: no clock defined\n"); | ||
| 1131 | return -ENODEV; | ||
| 1132 | } | ||
| 1133 | clk_enable(ether_clk); /* Enable Peripheral clock */ | ||
| 1134 | |||
| 1135 | while ((detected != 0) && (phy_address < 32)) { | ||
| 1136 | /* Read the PHY ID registers */ | ||
| 1137 | enable_mdi(); | ||
| 1138 | read_phy(phy_address, MII_PHYSID1, &phyid1); | ||
| 1139 | read_phy(phy_address, MII_PHYSID2, &phyid2); | ||
| 1140 | disable_mdi(); | ||
| 1141 | |||
| 1142 | phy_id = (phyid1 << 16) | (phyid2 & 0xfff0); | ||
| 1143 | switch (phy_id) { | ||
| 1144 | case MII_DM9161_ID: /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ | ||
| 1145 | case MII_DM9161A_ID: /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */ | ||
| 1146 | case MII_LXT971A_ID: /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ | ||
| 1147 | case MII_RTL8201_ID: /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ | ||
| 1148 | case MII_BCM5221_ID: /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ | ||
| 1149 | case MII_DP83847_ID: /* National Semiconductor DP83847: */ | ||
| 1150 | case MII_DP83848_ID: /* National Semiconductor DP83848: */ | ||
| 1151 | case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */ | ||
| 1152 | case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */ | ||
| 1153 | case MII_T78Q21x3_ID: /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */ | ||
| 1154 | case MII_LAN83C185_ID: /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */ | ||
| 1155 | detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk); | ||
| 1156 | break; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | phy_address++; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | clk_disable(ether_clk); /* Disable Peripheral clock */ | ||
| 1163 | |||
| 1164 | return detected; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | static int __devexit at91ether_remove(struct platform_device *pdev) | ||
| 1168 | { | ||
| 1169 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1170 | struct at91_private *lp = netdev_priv(dev); | ||
| 1171 | |||
| 1172 | if (lp->board_data.phy_irq_pin >= 32) | ||
| 1173 | gpio_free(lp->board_data.phy_irq_pin); | ||
| 1174 | |||
| 1175 | unregister_netdev(dev); | ||
| 1176 | free_irq(dev->irq, dev); | ||
| 1177 | dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); | ||
| 1178 | clk_put(lp->ether_clk); | ||
| 1179 | |||
| 1180 | platform_set_drvdata(pdev, NULL); | ||
| 1181 | free_netdev(dev); | ||
| 1182 | return 0; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | #ifdef CONFIG_PM | ||
| 1186 | |||
| 1187 | static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
| 1188 | { | ||
| 1189 | struct net_device *net_dev = platform_get_drvdata(pdev); | ||
| 1190 | struct at91_private *lp = netdev_priv(net_dev); | ||
| 1191 | int phy_irq = lp->board_data.phy_irq_pin; | ||
| 1192 | |||
| 1193 | if (netif_running(net_dev)) { | ||
| 1194 | if (phy_irq) | ||
| 1195 | disable_irq(phy_irq); | ||
| 1196 | |||
| 1197 | netif_stop_queue(net_dev); | ||
| 1198 | netif_device_detach(net_dev); | ||
| 1199 | |||
| 1200 | clk_disable(lp->ether_clk); | ||
| 1201 | } | ||
| 1202 | return 0; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static int at91ether_resume(struct platform_device *pdev) | ||
| 1206 | { | ||
| 1207 | struct net_device *net_dev = platform_get_drvdata(pdev); | ||
| 1208 | struct at91_private *lp = netdev_priv(net_dev); | ||
| 1209 | int phy_irq = lp->board_data.phy_irq_pin; | ||
| 1210 | |||
| 1211 | if (netif_running(net_dev)) { | ||
| 1212 | clk_enable(lp->ether_clk); | ||
| 1213 | |||
| 1214 | netif_device_attach(net_dev); | ||
| 1215 | netif_start_queue(net_dev); | ||
| 1216 | |||
| 1217 | if (phy_irq) | ||
| 1218 | enable_irq(phy_irq); | ||
| 1219 | } | ||
| 1220 | return 0; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | #else | ||
| 1224 | #define at91ether_suspend NULL | ||
| 1225 | #define at91ether_resume NULL | ||
| 1226 | #endif | ||
| 1227 | |||
| 1228 | static struct platform_driver at91ether_driver = { | ||
| 1229 | .remove = __devexit_p(at91ether_remove), | ||
| 1230 | .suspend = at91ether_suspend, | ||
| 1231 | .resume = at91ether_resume, | ||
| 1232 | .driver = { | ||
| 1233 | .name = DRV_NAME, | ||
| 1234 | .owner = THIS_MODULE, | ||
| 1235 | }, | ||
| 1236 | }; | ||
| 1237 | |||
| 1238 | static int __init at91ether_init(void) | ||
| 1239 | { | ||
| 1240 | return platform_driver_probe(&at91ether_driver, at91ether_probe); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | static void __exit at91ether_exit(void) | ||
| 1244 | { | ||
| 1245 | platform_driver_unregister(&at91ether_driver); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | module_init(at91ether_init) | ||
| 1249 | module_exit(at91ether_exit) | ||
| 1250 | |||
| 1251 | MODULE_LICENSE("GPL"); | ||
| 1252 | MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); | ||
| 1253 | MODULE_AUTHOR("Andrew Victor"); | ||
| 1254 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h new file mode 100644 index 00000000000..353f4dab62b --- /dev/null +++ b/drivers/net/arm/at91_ether.h | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | /* | ||
| 2 | * Ethernet driver for the Atmel AT91RM9200 (Thunder) | ||
| 3 | * | ||
| 4 | * Copyright (C) SAN People (Pty) Ltd | ||
| 5 | * | ||
| 6 | * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. | ||
| 7 | * Initial version by Rick Bronson. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version | ||
| 12 | * 2 of the License, or (at your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef AT91_ETHERNET | ||
| 16 | #define AT91_ETHERNET | ||
| 17 | |||
| 18 | |||
| 19 | /* Davicom 9161 PHY */ | ||
| 20 | #define MII_DM9161_ID 0x0181b880 | ||
| 21 | #define MII_DM9161A_ID 0x0181b8a0 | ||
| 22 | #define MII_DSCR_REG 16 | ||
| 23 | #define MII_DSCSR_REG 17 | ||
| 24 | #define MII_DSINTR_REG 21 | ||
| 25 | |||
| 26 | /* Intel LXT971A PHY */ | ||
| 27 | #define MII_LXT971A_ID 0x001378E0 | ||
| 28 | #define MII_ISINTE_REG 18 | ||
| 29 | #define MII_ISINTS_REG 19 | ||
| 30 | #define MII_LEDCTRL_REG 20 | ||
| 31 | |||
| 32 | /* Realtek RTL8201 PHY */ | ||
| 33 | #define MII_RTL8201_ID 0x00008200 | ||
| 34 | |||
| 35 | /* Broadcom BCM5221 PHY */ | ||
| 36 | #define MII_BCM5221_ID 0x004061e0 | ||
| 37 | #define MII_BCMINTR_REG 26 | ||
| 38 | |||
| 39 | /* National Semiconductor DP83847 */ | ||
| 40 | #define MII_DP83847_ID 0x20005c30 | ||
| 41 | |||
| 42 | /* National Semiconductor DP83848 */ | ||
| 43 | #define MII_DP83848_ID 0x20005c90 | ||
| 44 | #define MII_DPPHYSTS_REG 16 | ||
| 45 | #define MII_DPMICR_REG 17 | ||
| 46 | #define MII_DPMISR_REG 18 | ||
| 47 | |||
| 48 | /* Altima AC101L PHY */ | ||
| 49 | #define MII_AC101L_ID 0x00225520 | ||
| 50 | |||
| 51 | /* Micrel KS8721 PHY */ | ||
| 52 | #define MII_KS8721_ID 0x00221610 | ||
| 53 | |||
| 54 | /* Teridian 78Q2123/78Q2133 */ | ||
| 55 | #define MII_T78Q21x3_ID 0x000e7230 | ||
| 56 | #define MII_T78Q21INT_REG 17 | ||
| 57 | |||
| 58 | /* SMSC LAN83C185 */ | ||
| 59 | #define MII_LAN83C185_ID 0x0007C0A0 | ||
| 60 | |||
| 61 | /* ........................................................................ */ | ||
| 62 | |||
| 63 | #define MAX_RBUFF_SZ 0x600 /* 1518 rounded up */ | ||
| 64 | #define MAX_RX_DESCR 9 /* max number of receive buffers */ | ||
| 65 | |||
| 66 | #define EMAC_DESC_DONE 0x00000001 /* bit for if DMA is done */ | ||
| 67 | #define EMAC_DESC_WRAP 0x00000002 /* bit for wrap */ | ||
| 68 | |||
| 69 | #define EMAC_BROADCAST 0x80000000 /* broadcast address */ | ||
| 70 | #define EMAC_MULTICAST 0x40000000 /* multicast address */ | ||
| 71 | #define EMAC_UNICAST 0x20000000 /* unicast address */ | ||
| 72 | |||
| 73 | struct rbf_t | ||
| 74 | { | ||
| 75 | unsigned int addr; | ||
| 76 | unsigned long size; | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct recv_desc_bufs | ||
| 80 | { | ||
| 81 | struct rbf_t descriptors[MAX_RX_DESCR]; /* must be on sizeof (rbf_t) boundary */ | ||
| 82 | char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ]; /* must be on long boundary */ | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct at91_private | ||
| 86 | { | ||
| 87 | struct mii_if_info mii; /* ethtool support */ | ||
| 88 | struct at91_eth_data board_data; /* board-specific configuration */ | ||
| 89 | struct clk *ether_clk; /* clock */ | ||
| 90 | |||
| 91 | /* PHY */ | ||
| 92 | unsigned long phy_type; /* type of PHY (PHY_ID) */ | ||
| 93 | spinlock_t lock; /* lock for MDI interface */ | ||
| 94 | short phy_media; /* media interface type */ | ||
| 95 | unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */ | ||
| 96 | struct timer_list check_timer; /* Poll link status */ | ||
| 97 | |||
| 98 | /* Transmit */ | ||
| 99 | struct sk_buff *skb; /* holds skb until xmit interrupt completes */ | ||
| 100 | dma_addr_t skb_physaddr; /* phys addr from pci_map_single */ | ||
| 101 | int skb_length; /* saved skb length for pci_unmap_single */ | ||
| 102 | |||
| 103 | /* Receive */ | ||
| 104 | int rxBuffIndex; /* index into receive descriptor list */ | ||
| 105 | struct recv_desc_bufs *dlist; /* descriptor list address */ | ||
| 106 | struct recv_desc_bufs *dlist_phys; /* descriptor list physical address */ | ||
| 107 | }; | ||
| 108 | |||
| 109 | #endif | ||
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c new file mode 100644 index 00000000000..4317af8d2f0 --- /dev/null +++ b/drivers/net/arm/ep93xx_eth.c | |||
| @@ -0,0 +1,904 @@ | |||
| 1 | /* | ||
| 2 | * EP93xx ethernet network device driver | ||
| 3 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> | ||
| 4 | * Dedicated to Marija Kulikova. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ | ||
| 13 | |||
| 14 | #include <linux/dma-mapping.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/mii.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/ethtool.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/moduleparam.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | |||
| 29 | #include <mach/hardware.h> | ||
| 30 | |||
| 31 | #define DRV_MODULE_NAME "ep93xx-eth" | ||
| 32 | #define DRV_MODULE_VERSION "0.1" | ||
| 33 | |||
| 34 | #define RX_QUEUE_ENTRIES 64 | ||
| 35 | #define TX_QUEUE_ENTRIES 8 | ||
| 36 | |||
| 37 | #define MAX_PKT_SIZE 2044 | ||
| 38 | #define PKT_BUF_SIZE 2048 | ||
| 39 | |||
| 40 | #define REG_RXCTL 0x0000 | ||
| 41 | #define REG_RXCTL_DEFAULT 0x00073800 | ||
| 42 | #define REG_TXCTL 0x0004 | ||
| 43 | #define REG_TXCTL_ENABLE 0x00000001 | ||
| 44 | #define REG_MIICMD 0x0010 | ||
| 45 | #define REG_MIICMD_READ 0x00008000 | ||
| 46 | #define REG_MIICMD_WRITE 0x00004000 | ||
| 47 | #define REG_MIIDATA 0x0014 | ||
| 48 | #define REG_MIISTS 0x0018 | ||
| 49 | #define REG_MIISTS_BUSY 0x00000001 | ||
| 50 | #define REG_SELFCTL 0x0020 | ||
| 51 | #define REG_SELFCTL_RESET 0x00000001 | ||
| 52 | #define REG_INTEN 0x0024 | ||
| 53 | #define REG_INTEN_TX 0x00000008 | ||
| 54 | #define REG_INTEN_RX 0x00000007 | ||
| 55 | #define REG_INTSTSP 0x0028 | ||
| 56 | #define REG_INTSTS_TX 0x00000008 | ||
| 57 | #define REG_INTSTS_RX 0x00000004 | ||
| 58 | #define REG_INTSTSC 0x002c | ||
| 59 | #define REG_AFP 0x004c | ||
| 60 | #define REG_INDAD0 0x0050 | ||
| 61 | #define REG_INDAD1 0x0051 | ||
| 62 | #define REG_INDAD2 0x0052 | ||
| 63 | #define REG_INDAD3 0x0053 | ||
| 64 | #define REG_INDAD4 0x0054 | ||
| 65 | #define REG_INDAD5 0x0055 | ||
| 66 | #define REG_GIINTMSK 0x0064 | ||
| 67 | #define REG_GIINTMSK_ENABLE 0x00008000 | ||
| 68 | #define REG_BMCTL 0x0080 | ||
| 69 | #define REG_BMCTL_ENABLE_TX 0x00000100 | ||
| 70 | #define REG_BMCTL_ENABLE_RX 0x00000001 | ||
| 71 | #define REG_BMSTS 0x0084 | ||
| 72 | #define REG_BMSTS_RX_ACTIVE 0x00000008 | ||
| 73 | #define REG_RXDQBADD 0x0090 | ||
| 74 | #define REG_RXDQBLEN 0x0094 | ||
| 75 | #define REG_RXDCURADD 0x0098 | ||
| 76 | #define REG_RXDENQ 0x009c | ||
| 77 | #define REG_RXSTSQBADD 0x00a0 | ||
| 78 | #define REG_RXSTSQBLEN 0x00a4 | ||
| 79 | #define REG_RXSTSQCURADD 0x00a8 | ||
| 80 | #define REG_RXSTSENQ 0x00ac | ||
| 81 | #define REG_TXDQBADD 0x00b0 | ||
| 82 | #define REG_TXDQBLEN 0x00b4 | ||
| 83 | #define REG_TXDQCURADD 0x00b8 | ||
| 84 | #define REG_TXDENQ 0x00bc | ||
| 85 | #define REG_TXSTSQBADD 0x00c0 | ||
| 86 | #define REG_TXSTSQBLEN 0x00c4 | ||
| 87 | #define REG_TXSTSQCURADD 0x00c8 | ||
| 88 | #define REG_MAXFRMLEN 0x00e8 | ||
| 89 | |||
| 90 | struct ep93xx_rdesc | ||
| 91 | { | ||
| 92 | u32 buf_addr; | ||
| 93 | u32 rdesc1; | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define RDESC1_NSOF 0x80000000 | ||
| 97 | #define RDESC1_BUFFER_INDEX 0x7fff0000 | ||
| 98 | #define RDESC1_BUFFER_LENGTH 0x0000ffff | ||
| 99 | |||
| 100 | struct ep93xx_rstat | ||
| 101 | { | ||
| 102 | u32 rstat0; | ||
| 103 | u32 rstat1; | ||
| 104 | }; | ||
| 105 | |||
| 106 | #define RSTAT0_RFP 0x80000000 | ||
| 107 | #define RSTAT0_RWE 0x40000000 | ||
| 108 | #define RSTAT0_EOF 0x20000000 | ||
| 109 | #define RSTAT0_EOB 0x10000000 | ||
| 110 | #define RSTAT0_AM 0x00c00000 | ||
| 111 | #define RSTAT0_RX_ERR 0x00200000 | ||
| 112 | #define RSTAT0_OE 0x00100000 | ||
| 113 | #define RSTAT0_FE 0x00080000 | ||
| 114 | #define RSTAT0_RUNT 0x00040000 | ||
| 115 | #define RSTAT0_EDATA 0x00020000 | ||
| 116 | #define RSTAT0_CRCE 0x00010000 | ||
| 117 | #define RSTAT0_CRCI 0x00008000 | ||
| 118 | #define RSTAT0_HTI 0x00003f00 | ||
| 119 | #define RSTAT1_RFP 0x80000000 | ||
| 120 | #define RSTAT1_BUFFER_INDEX 0x7fff0000 | ||
| 121 | #define RSTAT1_FRAME_LENGTH 0x0000ffff | ||
| 122 | |||
| 123 | struct ep93xx_tdesc | ||
| 124 | { | ||
| 125 | u32 buf_addr; | ||
| 126 | u32 tdesc1; | ||
| 127 | }; | ||
| 128 | |||
| 129 | #define TDESC1_EOF 0x80000000 | ||
| 130 | #define TDESC1_BUFFER_INDEX 0x7fff0000 | ||
| 131 | #define TDESC1_BUFFER_ABORT 0x00008000 | ||
| 132 | #define TDESC1_BUFFER_LENGTH 0x00000fff | ||
| 133 | |||
| 134 | struct ep93xx_tstat | ||
| 135 | { | ||
| 136 | u32 tstat0; | ||
| 137 | }; | ||
| 138 | |||
| 139 | #define TSTAT0_TXFP 0x80000000 | ||
| 140 | #define TSTAT0_TXWE 0x40000000 | ||
| 141 | #define TSTAT0_FA 0x20000000 | ||
| 142 | #define TSTAT0_LCRS 0x10000000 | ||
| 143 | #define TSTAT0_OW 0x04000000 | ||
| 144 | #define TSTAT0_TXU 0x02000000 | ||
| 145 | #define TSTAT0_ECOLL 0x01000000 | ||
| 146 | #define TSTAT0_NCOLL 0x001f0000 | ||
| 147 | #define TSTAT0_BUFFER_INDEX 0x00007fff | ||
| 148 | |||
| 149 | struct ep93xx_descs | ||
| 150 | { | ||
| 151 | struct ep93xx_rdesc rdesc[RX_QUEUE_ENTRIES]; | ||
| 152 | struct ep93xx_tdesc tdesc[TX_QUEUE_ENTRIES]; | ||
| 153 | struct ep93xx_rstat rstat[RX_QUEUE_ENTRIES]; | ||
| 154 | struct ep93xx_tstat tstat[TX_QUEUE_ENTRIES]; | ||
| 155 | }; | ||
| 156 | |||
| 157 | struct ep93xx_priv | ||
| 158 | { | ||
| 159 | struct resource *res; | ||
| 160 | void __iomem *base_addr; | ||
| 161 | int irq; | ||
| 162 | |||
| 163 | struct ep93xx_descs *descs; | ||
| 164 | dma_addr_t descs_dma_addr; | ||
| 165 | |||
| 166 | void *rx_buf[RX_QUEUE_ENTRIES]; | ||
| 167 | void *tx_buf[TX_QUEUE_ENTRIES]; | ||
| 168 | |||
| 169 | spinlock_t rx_lock; | ||
| 170 | unsigned int rx_pointer; | ||
| 171 | unsigned int tx_clean_pointer; | ||
| 172 | unsigned int tx_pointer; | ||
| 173 | spinlock_t tx_pending_lock; | ||
| 174 | unsigned int tx_pending; | ||
| 175 | |||
| 176 | struct net_device *dev; | ||
| 177 | struct napi_struct napi; | ||
| 178 | |||
| 179 | struct mii_if_info mii; | ||
| 180 | u8 mdc_divisor; | ||
| 181 | }; | ||
| 182 | |||
| 183 | #define rdb(ep, off) __raw_readb((ep)->base_addr + (off)) | ||
| 184 | #define rdw(ep, off) __raw_readw((ep)->base_addr + (off)) | ||
| 185 | #define rdl(ep, off) __raw_readl((ep)->base_addr + (off)) | ||
| 186 | #define wrb(ep, off, val) __raw_writeb((val), (ep)->base_addr + (off)) | ||
| 187 | #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off)) | ||
| 188 | #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off)) | ||
| 189 | |||
| 190 | static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg) | ||
| 191 | { | ||
| 192 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 193 | int data; | ||
| 194 | int i; | ||
| 195 | |||
| 196 | wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg); | ||
| 197 | |||
| 198 | for (i = 0; i < 10; i++) { | ||
| 199 | if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) | ||
| 200 | break; | ||
| 201 | msleep(1); | ||
| 202 | } | ||
| 203 | |||
| 204 | if (i == 10) { | ||
| 205 | pr_info("mdio read timed out\n"); | ||
| 206 | data = 0xffff; | ||
| 207 | } else { | ||
| 208 | data = rdl(ep, REG_MIIDATA); | ||
| 209 | } | ||
| 210 | |||
| 211 | return data; | ||
| 212 | } | ||
| 213 | |||
| 214 | static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data) | ||
| 215 | { | ||
| 216 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 217 | int i; | ||
| 218 | |||
| 219 | wrl(ep, REG_MIIDATA, data); | ||
| 220 | wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg); | ||
| 221 | |||
| 222 | for (i = 0; i < 10; i++) { | ||
| 223 | if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) | ||
| 224 | break; | ||
| 225 | msleep(1); | ||
| 226 | } | ||
| 227 | |||
| 228 | if (i == 10) | ||
| 229 | pr_info("mdio write timed out\n"); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int ep93xx_rx(struct net_device *dev, int processed, int budget) | ||
| 233 | { | ||
| 234 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 235 | |||
| 236 | while (processed < budget) { | ||
| 237 | int entry; | ||
| 238 | struct ep93xx_rstat *rstat; | ||
| 239 | u32 rstat0; | ||
| 240 | u32 rstat1; | ||
| 241 | int length; | ||
| 242 | struct sk_buff *skb; | ||
| 243 | |||
| 244 | entry = ep->rx_pointer; | ||
| 245 | rstat = ep->descs->rstat + entry; | ||
| 246 | |||
| 247 | rstat0 = rstat->rstat0; | ||
| 248 | rstat1 = rstat->rstat1; | ||
| 249 | if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) | ||
| 250 | break; | ||
| 251 | |||
| 252 | rstat->rstat0 = 0; | ||
| 253 | rstat->rstat1 = 0; | ||
| 254 | |||
| 255 | if (!(rstat0 & RSTAT0_EOF)) | ||
| 256 | pr_crit("not end-of-frame %.8x %.8x\n", rstat0, rstat1); | ||
| 257 | if (!(rstat0 & RSTAT0_EOB)) | ||
| 258 | pr_crit("not end-of-buffer %.8x %.8x\n", rstat0, rstat1); | ||
| 259 | if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry) | ||
| 260 | pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1); | ||
| 261 | |||
| 262 | if (!(rstat0 & RSTAT0_RWE)) { | ||
| 263 | dev->stats.rx_errors++; | ||
| 264 | if (rstat0 & RSTAT0_OE) | ||
| 265 | dev->stats.rx_fifo_errors++; | ||
| 266 | if (rstat0 & RSTAT0_FE) | ||
| 267 | dev->stats.rx_frame_errors++; | ||
| 268 | if (rstat0 & (RSTAT0_RUNT | RSTAT0_EDATA)) | ||
| 269 | dev->stats.rx_length_errors++; | ||
| 270 | if (rstat0 & RSTAT0_CRCE) | ||
| 271 | dev->stats.rx_crc_errors++; | ||
| 272 | goto err; | ||
| 273 | } | ||
| 274 | |||
| 275 | length = rstat1 & RSTAT1_FRAME_LENGTH; | ||
| 276 | if (length > MAX_PKT_SIZE) { | ||
| 277 | pr_notice("invalid length %.8x %.8x\n", rstat0, rstat1); | ||
| 278 | goto err; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Strip FCS. */ | ||
| 282 | if (rstat0 & RSTAT0_CRCI) | ||
| 283 | length -= 4; | ||
| 284 | |||
| 285 | skb = dev_alloc_skb(length + 2); | ||
| 286 | if (likely(skb != NULL)) { | ||
| 287 | struct ep93xx_rdesc *rxd = &ep->descs->rdesc[entry]; | ||
| 288 | skb_reserve(skb, 2); | ||
| 289 | dma_sync_single_for_cpu(dev->dev.parent, rxd->buf_addr, | ||
| 290 | length, DMA_FROM_DEVICE); | ||
| 291 | skb_copy_to_linear_data(skb, ep->rx_buf[entry], length); | ||
| 292 | dma_sync_single_for_device(dev->dev.parent, | ||
| 293 | rxd->buf_addr, length, | ||
| 294 | DMA_FROM_DEVICE); | ||
| 295 | skb_put(skb, length); | ||
| 296 | skb->protocol = eth_type_trans(skb, dev); | ||
| 297 | |||
| 298 | netif_receive_skb(skb); | ||
| 299 | |||
| 300 | dev->stats.rx_packets++; | ||
| 301 | dev->stats.rx_bytes += length; | ||
| 302 | } else { | ||
| 303 | dev->stats.rx_dropped++; | ||
| 304 | } | ||
| 305 | |||
| 306 | err: | ||
| 307 | ep->rx_pointer = (entry + 1) & (RX_QUEUE_ENTRIES - 1); | ||
| 308 | processed++; | ||
| 309 | } | ||
| 310 | |||
| 311 | return processed; | ||
| 312 | } | ||
| 313 | |||
| 314 | static int ep93xx_have_more_rx(struct ep93xx_priv *ep) | ||
| 315 | { | ||
| 316 | struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer; | ||
| 317 | return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP)); | ||
| 318 | } | ||
| 319 | |||
| 320 | static int ep93xx_poll(struct napi_struct *napi, int budget) | ||
| 321 | { | ||
| 322 | struct ep93xx_priv *ep = container_of(napi, struct ep93xx_priv, napi); | ||
| 323 | struct net_device *dev = ep->dev; | ||
| 324 | int rx = 0; | ||
| 325 | |||
| 326 | poll_some_more: | ||
| 327 | rx = ep93xx_rx(dev, rx, budget); | ||
| 328 | if (rx < budget) { | ||
| 329 | int more = 0; | ||
| 330 | |||
| 331 | spin_lock_irq(&ep->rx_lock); | ||
| 332 | __napi_complete(napi); | ||
| 333 | wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX); | ||
| 334 | if (ep93xx_have_more_rx(ep)) { | ||
| 335 | wrl(ep, REG_INTEN, REG_INTEN_TX); | ||
| 336 | wrl(ep, REG_INTSTSP, REG_INTSTS_RX); | ||
| 337 | more = 1; | ||
| 338 | } | ||
| 339 | spin_unlock_irq(&ep->rx_lock); | ||
| 340 | |||
| 341 | if (more && napi_reschedule(napi)) | ||
| 342 | goto poll_some_more; | ||
| 343 | } | ||
| 344 | |||
| 345 | if (rx) { | ||
| 346 | wrw(ep, REG_RXDENQ, rx); | ||
| 347 | wrw(ep, REG_RXSTSENQ, rx); | ||
| 348 | } | ||
| 349 | |||
| 350 | return rx; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 354 | { | ||
| 355 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 356 | struct ep93xx_tdesc *txd; | ||
| 357 | int entry; | ||
| 358 | |||
| 359 | if (unlikely(skb->len > MAX_PKT_SIZE)) { | ||
| 360 | dev->stats.tx_dropped++; | ||
| 361 | dev_kfree_skb(skb); | ||
| 362 | return NETDEV_TX_OK; | ||
| 363 | } | ||
| 364 | |||
| 365 | entry = ep->tx_pointer; | ||
| 366 | ep->tx_pointer = (ep->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1); | ||
| 367 | |||
| 368 | txd = &ep->descs->tdesc[entry]; | ||
| 369 | |||
| 370 | txd->tdesc1 = TDESC1_EOF | (entry << 16) | (skb->len & 0xfff); | ||
| 371 | dma_sync_single_for_cpu(dev->dev.parent, txd->buf_addr, skb->len, | ||
| 372 | DMA_TO_DEVICE); | ||
| 373 | skb_copy_and_csum_dev(skb, ep->tx_buf[entry]); | ||
| 374 | dma_sync_single_for_device(dev->dev.parent, txd->buf_addr, skb->len, | ||
| 375 | DMA_TO_DEVICE); | ||
| 376 | dev_kfree_skb(skb); | ||
| 377 | |||
| 378 | spin_lock_irq(&ep->tx_pending_lock); | ||
| 379 | ep->tx_pending++; | ||
| 380 | if (ep->tx_pending == TX_QUEUE_ENTRIES) | ||
| 381 | netif_stop_queue(dev); | ||
| 382 | spin_unlock_irq(&ep->tx_pending_lock); | ||
| 383 | |||
| 384 | wrl(ep, REG_TXDENQ, 1); | ||
| 385 | |||
| 386 | return NETDEV_TX_OK; | ||
| 387 | } | ||
| 388 | |||
| 389 | static void ep93xx_tx_complete(struct net_device *dev) | ||
| 390 | { | ||
| 391 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 392 | int wake; | ||
| 393 | |||
| 394 | wake = 0; | ||
| 395 | |||
| 396 | spin_lock(&ep->tx_pending_lock); | ||
| 397 | while (1) { | ||
| 398 | int entry; | ||
| 399 | struct ep93xx_tstat *tstat; | ||
| 400 | u32 tstat0; | ||
| 401 | |||
| 402 | entry = ep->tx_clean_pointer; | ||
| 403 | tstat = ep->descs->tstat + entry; | ||
| 404 | |||
| 405 | tstat0 = tstat->tstat0; | ||
| 406 | if (!(tstat0 & TSTAT0_TXFP)) | ||
| 407 | break; | ||
| 408 | |||
| 409 | tstat->tstat0 = 0; | ||
| 410 | |||
| 411 | if (tstat0 & TSTAT0_FA) | ||
| 412 | pr_crit("frame aborted %.8x\n", tstat0); | ||
| 413 | if ((tstat0 & TSTAT0_BUFFER_INDEX) != entry) | ||
| 414 | pr_crit("entry mismatch %.8x\n", tstat0); | ||
| 415 | |||
| 416 | if (tstat0 & TSTAT0_TXWE) { | ||
| 417 | int length = ep->descs->tdesc[entry].tdesc1 & 0xfff; | ||
| 418 | |||
| 419 | dev->stats.tx_packets++; | ||
| 420 | dev->stats.tx_bytes += length; | ||
| 421 | } else { | ||
| 422 | dev->stats.tx_errors++; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (tstat0 & TSTAT0_OW) | ||
| 426 | dev->stats.tx_window_errors++; | ||
| 427 | if (tstat0 & TSTAT0_TXU) | ||
| 428 | dev->stats.tx_fifo_errors++; | ||
| 429 | dev->stats.collisions += (tstat0 >> 16) & 0x1f; | ||
| 430 | |||
| 431 | ep->tx_clean_pointer = (entry + 1) & (TX_QUEUE_ENTRIES - 1); | ||
| 432 | if (ep->tx_pending == TX_QUEUE_ENTRIES) | ||
| 433 | wake = 1; | ||
| 434 | ep->tx_pending--; | ||
| 435 | } | ||
| 436 | spin_unlock(&ep->tx_pending_lock); | ||
| 437 | |||
| 438 | if (wake) | ||
| 439 | netif_wake_queue(dev); | ||
| 440 | } | ||
| 441 | |||
| 442 | static irqreturn_t ep93xx_irq(int irq, void *dev_id) | ||
| 443 | { | ||
| 444 | struct net_device *dev = dev_id; | ||
| 445 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 446 | u32 status; | ||
| 447 | |||
| 448 | status = rdl(ep, REG_INTSTSC); | ||
| 449 | if (status == 0) | ||
| 450 | return IRQ_NONE; | ||
| 451 | |||
| 452 | if (status & REG_INTSTS_RX) { | ||
| 453 | spin_lock(&ep->rx_lock); | ||
| 454 | if (likely(napi_schedule_prep(&ep->napi))) { | ||
| 455 | wrl(ep, REG_INTEN, REG_INTEN_TX); | ||
| 456 | __napi_schedule(&ep->napi); | ||
| 457 | } | ||
| 458 | spin_unlock(&ep->rx_lock); | ||
| 459 | } | ||
| 460 | |||
| 461 | if (status & REG_INTSTS_TX) | ||
| 462 | ep93xx_tx_complete(dev); | ||
| 463 | |||
| 464 | return IRQ_HANDLED; | ||
| 465 | } | ||
| 466 | |||
| 467 | static void ep93xx_free_buffers(struct ep93xx_priv *ep) | ||
| 468 | { | ||
| 469 | struct device *dev = ep->dev->dev.parent; | ||
| 470 | int i; | ||
| 471 | |||
| 472 | for (i = 0; i < RX_QUEUE_ENTRIES; i++) { | ||
| 473 | dma_addr_t d; | ||
| 474 | |||
| 475 | d = ep->descs->rdesc[i].buf_addr; | ||
| 476 | if (d) | ||
| 477 | dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 478 | |||
| 479 | if (ep->rx_buf[i] != NULL) | ||
| 480 | kfree(ep->rx_buf[i]); | ||
| 481 | } | ||
| 482 | |||
| 483 | for (i = 0; i < TX_QUEUE_ENTRIES; i++) { | ||
| 484 | dma_addr_t d; | ||
| 485 | |||
| 486 | d = ep->descs->tdesc[i].buf_addr; | ||
| 487 | if (d) | ||
| 488 | dma_unmap_single(dev, d, PKT_BUF_SIZE, DMA_TO_DEVICE); | ||
| 489 | |||
| 490 | if (ep->tx_buf[i] != NULL) | ||
| 491 | kfree(ep->tx_buf[i]); | ||
| 492 | } | ||
| 493 | |||
| 494 | dma_free_coherent(dev, sizeof(struct ep93xx_descs), ep->descs, | ||
| 495 | ep->descs_dma_addr); | ||
| 496 | } | ||
| 497 | |||
| 498 | static int ep93xx_alloc_buffers(struct ep93xx_priv *ep) | ||
| 499 | { | ||
| 500 | struct device *dev = ep->dev->dev.parent; | ||
| 501 | int i; | ||
| 502 | |||
| 503 | ep->descs = dma_alloc_coherent(dev, sizeof(struct ep93xx_descs), | ||
| 504 | &ep->descs_dma_addr, GFP_KERNEL); | ||
| 505 | if (ep->descs == NULL) | ||
| 506 | return 1; | ||
| 507 | |||
| 508 | for (i = 0; i < RX_QUEUE_ENTRIES; i++) { | ||
| 509 | void *buf; | ||
| 510 | dma_addr_t d; | ||
| 511 | |||
| 512 | buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); | ||
| 513 | if (buf == NULL) | ||
| 514 | goto err; | ||
| 515 | |||
| 516 | d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_FROM_DEVICE); | ||
| 517 | if (dma_mapping_error(dev, d)) { | ||
| 518 | kfree(buf); | ||
| 519 | goto err; | ||
| 520 | } | ||
| 521 | |||
| 522 | ep->rx_buf[i] = buf; | ||
| 523 | ep->descs->rdesc[i].buf_addr = d; | ||
| 524 | ep->descs->rdesc[i].rdesc1 = (i << 16) | PKT_BUF_SIZE; | ||
| 525 | } | ||
| 526 | |||
| 527 | for (i = 0; i < TX_QUEUE_ENTRIES; i++) { | ||
| 528 | void *buf; | ||
| 529 | dma_addr_t d; | ||
| 530 | |||
| 531 | buf = kmalloc(PKT_BUF_SIZE, GFP_KERNEL); | ||
| 532 | if (buf == NULL) | ||
| 533 | goto err; | ||
| 534 | |||
| 535 | d = dma_map_single(dev, buf, PKT_BUF_SIZE, DMA_TO_DEVICE); | ||
| 536 | if (dma_mapping_error(dev, d)) { | ||
| 537 | kfree(buf); | ||
| 538 | goto err; | ||
| 539 | } | ||
| 540 | |||
| 541 | ep->tx_buf[i] = buf; | ||
| 542 | ep->descs->tdesc[i].buf_addr = d; | ||
| 543 | } | ||
| 544 | |||
| 545 | return 0; | ||
| 546 | |||
| 547 | err: | ||
| 548 | ep93xx_free_buffers(ep); | ||
| 549 | return 1; | ||
| 550 | } | ||
| 551 | |||
| 552 | static int ep93xx_start_hw(struct net_device *dev) | ||
| 553 | { | ||
| 554 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 555 | unsigned long addr; | ||
| 556 | int i; | ||
| 557 | |||
| 558 | wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET); | ||
| 559 | for (i = 0; i < 10; i++) { | ||
| 560 | if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0) | ||
| 561 | break; | ||
| 562 | msleep(1); | ||
| 563 | } | ||
| 564 | |||
| 565 | if (i == 10) { | ||
| 566 | pr_crit("hw failed to reset\n"); | ||
| 567 | return 1; | ||
| 568 | } | ||
| 569 | |||
| 570 | wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9)); | ||
| 571 | |||
| 572 | /* Does the PHY support preamble suppress? */ | ||
| 573 | if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0) | ||
| 574 | wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8)); | ||
| 575 | |||
| 576 | /* Receive descriptor ring. */ | ||
| 577 | addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc); | ||
| 578 | wrl(ep, REG_RXDQBADD, addr); | ||
| 579 | wrl(ep, REG_RXDCURADD, addr); | ||
| 580 | wrw(ep, REG_RXDQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rdesc)); | ||
| 581 | |||
| 582 | /* Receive status ring. */ | ||
| 583 | addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rstat); | ||
| 584 | wrl(ep, REG_RXSTSQBADD, addr); | ||
| 585 | wrl(ep, REG_RXSTSQCURADD, addr); | ||
| 586 | wrw(ep, REG_RXSTSQBLEN, RX_QUEUE_ENTRIES * sizeof(struct ep93xx_rstat)); | ||
| 587 | |||
| 588 | /* Transmit descriptor ring. */ | ||
| 589 | addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tdesc); | ||
| 590 | wrl(ep, REG_TXDQBADD, addr); | ||
| 591 | wrl(ep, REG_TXDQCURADD, addr); | ||
| 592 | wrw(ep, REG_TXDQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tdesc)); | ||
| 593 | |||
| 594 | /* Transmit status ring. */ | ||
| 595 | addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, tstat); | ||
| 596 | wrl(ep, REG_TXSTSQBADD, addr); | ||
| 597 | wrl(ep, REG_TXSTSQCURADD, addr); | ||
| 598 | wrw(ep, REG_TXSTSQBLEN, TX_QUEUE_ENTRIES * sizeof(struct ep93xx_tstat)); | ||
| 599 | |||
| 600 | wrl(ep, REG_BMCTL, REG_BMCTL_ENABLE_TX | REG_BMCTL_ENABLE_RX); | ||
| 601 | wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX); | ||
| 602 | wrl(ep, REG_GIINTMSK, 0); | ||
| 603 | |||
| 604 | for (i = 0; i < 10; i++) { | ||
| 605 | if ((rdl(ep, REG_BMSTS) & REG_BMSTS_RX_ACTIVE) != 0) | ||
| 606 | break; | ||
| 607 | msleep(1); | ||
| 608 | } | ||
| 609 | |||
| 610 | if (i == 10) { | ||
| 611 | pr_crit("hw failed to start\n"); | ||
| 612 | return 1; | ||
| 613 | } | ||
| 614 | |||
| 615 | wrl(ep, REG_RXDENQ, RX_QUEUE_ENTRIES); | ||
| 616 | wrl(ep, REG_RXSTSENQ, RX_QUEUE_ENTRIES); | ||
| 617 | |||
| 618 | wrb(ep, REG_INDAD0, dev->dev_addr[0]); | ||
| 619 | wrb(ep, REG_INDAD1, dev->dev_addr[1]); | ||
| 620 | wrb(ep, REG_INDAD2, dev->dev_addr[2]); | ||
| 621 | wrb(ep, REG_INDAD3, dev->dev_addr[3]); | ||
| 622 | wrb(ep, REG_INDAD4, dev->dev_addr[4]); | ||
| 623 | wrb(ep, REG_INDAD5, dev->dev_addr[5]); | ||
| 624 | wrl(ep, REG_AFP, 0); | ||
| 625 | |||
| 626 | wrl(ep, REG_MAXFRMLEN, (MAX_PKT_SIZE << 16) | MAX_PKT_SIZE); | ||
| 627 | |||
| 628 | wrl(ep, REG_RXCTL, REG_RXCTL_DEFAULT); | ||
| 629 | wrl(ep, REG_TXCTL, REG_TXCTL_ENABLE); | ||
| 630 | |||
| 631 | return 0; | ||
| 632 | } | ||
| 633 | |||
| 634 | static void ep93xx_stop_hw(struct net_device *dev) | ||
| 635 | { | ||
| 636 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 637 | int i; | ||
| 638 | |||
| 639 | wrl(ep, REG_SELFCTL, REG_SELFCTL_RESET); | ||
| 640 | for (i = 0; i < 10; i++) { | ||
| 641 | if ((rdl(ep, REG_SELFCTL) & REG_SELFCTL_RESET) == 0) | ||
| 642 | break; | ||
| 643 | msleep(1); | ||
| 644 | } | ||
| 645 | |||
| 646 | if (i == 10) | ||
| 647 | pr_crit("hw failed to reset\n"); | ||
| 648 | } | ||
| 649 | |||
| 650 | static int ep93xx_open(struct net_device *dev) | ||
| 651 | { | ||
| 652 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 653 | int err; | ||
| 654 | |||
| 655 | if (ep93xx_alloc_buffers(ep)) | ||
| 656 | return -ENOMEM; | ||
| 657 | |||
| 658 | napi_enable(&ep->napi); | ||
| 659 | |||
| 660 | if (ep93xx_start_hw(dev)) { | ||
| 661 | napi_disable(&ep->napi); | ||
| 662 | ep93xx_free_buffers(ep); | ||
| 663 | return -EIO; | ||
| 664 | } | ||
| 665 | |||
| 666 | spin_lock_init(&ep->rx_lock); | ||
| 667 | ep->rx_pointer = 0; | ||
| 668 | ep->tx_clean_pointer = 0; | ||
| 669 | ep->tx_pointer = 0; | ||
| 670 | spin_lock_init(&ep->tx_pending_lock); | ||
| 671 | ep->tx_pending = 0; | ||
| 672 | |||
| 673 | err = request_irq(ep->irq, ep93xx_irq, IRQF_SHARED, dev->name, dev); | ||
| 674 | if (err) { | ||
| 675 | napi_disable(&ep->napi); | ||
| 676 | ep93xx_stop_hw(dev); | ||
| 677 | ep93xx_free_buffers(ep); | ||
| 678 | return err; | ||
| 679 | } | ||
| 680 | |||
| 681 | wrl(ep, REG_GIINTMSK, REG_GIINTMSK_ENABLE); | ||
| 682 | |||
| 683 | netif_start_queue(dev); | ||
| 684 | |||
| 685 | return 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | static int ep93xx_close(struct net_device *dev) | ||
| 689 | { | ||
| 690 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 691 | |||
| 692 | napi_disable(&ep->napi); | ||
| 693 | netif_stop_queue(dev); | ||
| 694 | |||
| 695 | wrl(ep, REG_GIINTMSK, 0); | ||
| 696 | free_irq(ep->irq, dev); | ||
| 697 | ep93xx_stop_hw(dev); | ||
| 698 | ep93xx_free_buffers(ep); | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
| 704 | { | ||
| 705 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 706 | struct mii_ioctl_data *data = if_mii(ifr); | ||
| 707 | |||
| 708 | return generic_mii_ioctl(&ep->mii, data, cmd, NULL); | ||
| 709 | } | ||
| 710 | |||
| 711 | static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | ||
| 712 | { | ||
| 713 | strcpy(info->driver, DRV_MODULE_NAME); | ||
| 714 | strcpy(info->version, DRV_MODULE_VERSION); | ||
| 715 | } | ||
| 716 | |||
| 717 | static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 718 | { | ||
| 719 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 720 | return mii_ethtool_gset(&ep->mii, cmd); | ||
| 721 | } | ||
| 722 | |||
| 723 | static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 724 | { | ||
| 725 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 726 | return mii_ethtool_sset(&ep->mii, cmd); | ||
| 727 | } | ||
| 728 | |||
| 729 | static int ep93xx_nway_reset(struct net_device *dev) | ||
| 730 | { | ||
| 731 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 732 | return mii_nway_restart(&ep->mii); | ||
| 733 | } | ||
| 734 | |||
| 735 | static u32 ep93xx_get_link(struct net_device *dev) | ||
| 736 | { | ||
| 737 | struct ep93xx_priv *ep = netdev_priv(dev); | ||
| 738 | return mii_link_ok(&ep->mii); | ||
| 739 | } | ||
| 740 | |||
| 741 | static const struct ethtool_ops ep93xx_ethtool_ops = { | ||
| 742 | .get_drvinfo = ep93xx_get_drvinfo, | ||
| 743 | .get_settings = ep93xx_get_settings, | ||
| 744 | .set_settings = ep93xx_set_settings, | ||
| 745 | .nway_reset = ep93xx_nway_reset, | ||
| 746 | .get_link = ep93xx_get_link, | ||
| 747 | }; | ||
| 748 | |||
| 749 | static const struct net_device_ops ep93xx_netdev_ops = { | ||
| 750 | .ndo_open = ep93xx_open, | ||
| 751 | .ndo_stop = ep93xx_close, | ||
| 752 | .ndo_start_xmit = ep93xx_xmit, | ||
| 753 | .ndo_do_ioctl = ep93xx_ioctl, | ||
| 754 | .ndo_validate_addr = eth_validate_addr, | ||
| 755 | .ndo_change_mtu = eth_change_mtu, | ||
| 756 | .ndo_set_mac_address = eth_mac_addr, | ||
| 757 | }; | ||
| 758 | |||
| 759 | static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data) | ||
| 760 | { | ||
| 761 | struct net_device *dev; | ||
| 762 | |||
| 763 | dev = alloc_etherdev(sizeof(struct ep93xx_priv)); | ||
| 764 | if (dev == NULL) | ||
| 765 | return NULL; | ||
| 766 | |||
| 767 | memcpy(dev->dev_addr, data->dev_addr, ETH_ALEN); | ||
| 768 | |||
| 769 | dev->ethtool_ops = &ep93xx_ethtool_ops; | ||
| 770 | dev->netdev_ops = &ep93xx_netdev_ops; | ||
| 771 | |||
| 772 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | ||
| 773 | |||
| 774 | return dev; | ||
| 775 | } | ||
| 776 | |||
| 777 | |||
| 778 | static int ep93xx_eth_remove(struct platform_device *pdev) | ||
| 779 | { | ||
| 780 | struct net_device *dev; | ||
| 781 | struct ep93xx_priv *ep; | ||
| 782 | |||
| 783 | dev = platform_get_drvdata(pdev); | ||
| 784 | if (dev == NULL) | ||
| 785 | return 0; | ||
| 786 | platform_set_drvdata(pdev, NULL); | ||
| 787 | |||
| 788 | ep = netdev_priv(dev); | ||
| 789 | |||
| 790 | /* @@@ Force down. */ | ||
| 791 | unregister_netdev(dev); | ||
| 792 | ep93xx_free_buffers(ep); | ||
| 793 | |||
| 794 | if (ep->base_addr != NULL) | ||
| 795 | iounmap(ep->base_addr); | ||
| 796 | |||
| 797 | if (ep->res != NULL) { | ||
| 798 | release_resource(ep->res); | ||
| 799 | kfree(ep->res); | ||
| 800 | } | ||
| 801 | |||
| 802 | free_netdev(dev); | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | static int ep93xx_eth_probe(struct platform_device *pdev) | ||
| 808 | { | ||
| 809 | struct ep93xx_eth_data *data; | ||
| 810 | struct net_device *dev; | ||
| 811 | struct ep93xx_priv *ep; | ||
| 812 | struct resource *mem; | ||
| 813 | int irq; | ||
| 814 | int err; | ||
| 815 | |||
| 816 | if (pdev == NULL) | ||
| 817 | return -ENODEV; | ||
| 818 | data = pdev->dev.platform_data; | ||
| 819 | |||
| 820 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 821 | irq = platform_get_irq(pdev, 0); | ||
| 822 | if (!mem || irq < 0) | ||
| 823 | return -ENXIO; | ||
| 824 | |||
| 825 | dev = ep93xx_dev_alloc(data); | ||
| 826 | if (dev == NULL) { | ||
| 827 | err = -ENOMEM; | ||
| 828 | goto err_out; | ||
| 829 | } | ||
| 830 | ep = netdev_priv(dev); | ||
| 831 | ep->dev = dev; | ||
| 832 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
| 833 | netif_napi_add(dev, &ep->napi, ep93xx_poll, 64); | ||
| 834 | |||
| 835 | platform_set_drvdata(pdev, dev); | ||
| 836 | |||
| 837 | ep->res = request_mem_region(mem->start, resource_size(mem), | ||
| 838 | dev_name(&pdev->dev)); | ||
| 839 | if (ep->res == NULL) { | ||
| 840 | dev_err(&pdev->dev, "Could not reserve memory region\n"); | ||
| 841 | err = -ENOMEM; | ||
| 842 | goto err_out; | ||
| 843 | } | ||
| 844 | |||
| 845 | ep->base_addr = ioremap(mem->start, resource_size(mem)); | ||
| 846 | if (ep->base_addr == NULL) { | ||
| 847 | dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); | ||
| 848 | err = -EIO; | ||
| 849 | goto err_out; | ||
| 850 | } | ||
| 851 | ep->irq = irq; | ||
| 852 | |||
| 853 | ep->mii.phy_id = data->phy_id; | ||
| 854 | ep->mii.phy_id_mask = 0x1f; | ||
| 855 | ep->mii.reg_num_mask = 0x1f; | ||
| 856 | ep->mii.dev = dev; | ||
| 857 | ep->mii.mdio_read = ep93xx_mdio_read; | ||
| 858 | ep->mii.mdio_write = ep93xx_mdio_write; | ||
| 859 | ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */ | ||
| 860 | |||
| 861 | if (is_zero_ether_addr(dev->dev_addr)) | ||
| 862 | random_ether_addr(dev->dev_addr); | ||
| 863 | |||
| 864 | err = register_netdev(dev); | ||
| 865 | if (err) { | ||
| 866 | dev_err(&pdev->dev, "Failed to register netdev\n"); | ||
| 867 | goto err_out; | ||
| 868 | } | ||
| 869 | |||
| 870 | printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n", | ||
| 871 | dev->name, ep->irq, dev->dev_addr); | ||
| 872 | |||
| 873 | return 0; | ||
| 874 | |||
| 875 | err_out: | ||
| 876 | ep93xx_eth_remove(pdev); | ||
| 877 | return err; | ||
| 878 | } | ||
| 879 | |||
| 880 | |||
| 881 | static struct platform_driver ep93xx_eth_driver = { | ||
| 882 | .probe = ep93xx_eth_probe, | ||
| 883 | .remove = ep93xx_eth_remove, | ||
| 884 | .driver = { | ||
| 885 | .name = "ep93xx-eth", | ||
| 886 | .owner = THIS_MODULE, | ||
| 887 | }, | ||
| 888 | }; | ||
| 889 | |||
| 890 | static int __init ep93xx_eth_init_module(void) | ||
| 891 | { | ||
| 892 | printk(KERN_INFO DRV_MODULE_NAME " version " DRV_MODULE_VERSION " loading\n"); | ||
| 893 | return platform_driver_register(&ep93xx_eth_driver); | ||
| 894 | } | ||
| 895 | |||
| 896 | static void __exit ep93xx_eth_cleanup_module(void) | ||
| 897 | { | ||
| 898 | platform_driver_unregister(&ep93xx_eth_driver); | ||
| 899 | } | ||
| 900 | |||
| 901 | module_init(ep93xx_eth_init_module); | ||
| 902 | module_exit(ep93xx_eth_cleanup_module); | ||
| 903 | MODULE_LICENSE("GPL"); | ||
| 904 | MODULE_ALIAS("platform:ep93xx-eth"); | ||
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c new file mode 100644 index 00000000000..b00781c02d5 --- /dev/null +++ b/drivers/net/arm/ether1.c | |||
| @@ -0,0 +1,1094 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/acorn/net/ether1.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1996-2000 Russell King | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Acorn ether1 driver (82586 chip) for Acorn machines | ||
| 11 | * | ||
| 12 | * We basically keep two queues in the cards memory - one for transmit | ||
| 13 | * and one for receive. Each has a head and a tail. The head is where | ||
| 14 | * we/the chip adds packets to be transmitted/received, and the tail | ||
| 15 | * is where the transmitter has got to/where the receiver will stop. | ||
| 16 | * Both of these queues are circular, and since the chip is running | ||
| 17 | * all the time, we have to be careful when we modify the pointers etc | ||
| 18 | * so that the buffer memory contents is valid all the time. | ||
| 19 | * | ||
| 20 | * Change log: | ||
| 21 | * 1.00 RMK Released | ||
| 22 | * 1.01 RMK 19/03/1996 Transfers the last odd byte onto/off of the card now. | ||
| 23 | * 1.02 RMK 25/05/1997 Added code to restart RU if it goes not ready | ||
| 24 | * 1.03 RMK 14/09/1997 Cleaned up the handling of a reset during the TX interrupt. | ||
| 25 | * Should prevent lockup. | ||
| 26 | * 1.04 RMK 17/09/1997 Added more info when initialsation of chip goes wrong. | ||
| 27 | * TDR now only reports failure when chip reports non-zero | ||
| 28 | * TDR time-distance. | ||
| 29 | * 1.05 RMK 31/12/1997 Removed calls to dev_tint for 2.1 | ||
| 30 | * 1.06 RMK 10/02/2000 Updated for 2.3.43 | ||
| 31 | * 1.07 RMK 13/05/2000 Updated for 2.3.99-pre8 | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/types.h> | ||
| 37 | #include <linux/fcntl.h> | ||
| 38 | #include <linux/interrupt.h> | ||
| 39 | #include <linux/ioport.h> | ||
| 40 | #include <linux/in.h> | ||
| 41 | #include <linux/slab.h> | ||
| 42 | #include <linux/string.h> | ||
| 43 | #include <linux/errno.h> | ||
| 44 | #include <linux/device.h> | ||
| 45 | #include <linux/init.h> | ||
| 46 | #include <linux/netdevice.h> | ||
| 47 | #include <linux/etherdevice.h> | ||
| 48 | #include <linux/skbuff.h> | ||
| 49 | #include <linux/bitops.h> | ||
| 50 | |||
| 51 | #include <asm/system.h> | ||
| 52 | #include <asm/io.h> | ||
| 53 | #include <asm/dma.h> | ||
| 54 | #include <asm/ecard.h> | ||
| 55 | |||
| 56 | #define __ETHER1_C | ||
| 57 | #include "ether1.h" | ||
| 58 | |||
| 59 | static unsigned int net_debug = NET_DEBUG; | ||
| 60 | |||
| 61 | #define BUFFER_SIZE 0x10000 | ||
| 62 | #define TX_AREA_START 0x00100 | ||
| 63 | #define TX_AREA_END 0x05000 | ||
| 64 | #define RX_AREA_START 0x05000 | ||
| 65 | #define RX_AREA_END 0x0fc00 | ||
| 66 | |||
| 67 | static int ether1_open(struct net_device *dev); | ||
| 68 | static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev); | ||
| 69 | static irqreturn_t ether1_interrupt(int irq, void *dev_id); | ||
| 70 | static int ether1_close(struct net_device *dev); | ||
| 71 | static void ether1_setmulticastlist(struct net_device *dev); | ||
| 72 | static void ether1_timeout(struct net_device *dev); | ||
| 73 | |||
| 74 | /* ------------------------------------------------------------------------- */ | ||
| 75 | |||
| 76 | static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; | ||
| 77 | |||
| 78 | #define BUS_16 16 | ||
| 79 | #define BUS_8 8 | ||
| 80 | |||
| 81 | /* ------------------------------------------------------------------------- */ | ||
| 82 | |||
| 83 | #define DISABLEIRQS 1 | ||
| 84 | #define NORMALIRQS 0 | ||
| 85 | |||
| 86 | #define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs) | ||
| 87 | #define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs) | ||
| 88 | |||
| 89 | static inline unsigned short | ||
| 90 | ether1_inw_p (struct net_device *dev, int addr, int svflgs) | ||
| 91 | { | ||
| 92 | unsigned long flags; | ||
| 93 | unsigned short ret; | ||
| 94 | |||
| 95 | if (svflgs) | ||
| 96 | local_irq_save (flags); | ||
| 97 | |||
| 98 | writeb(addr >> 12, REG_PAGE); | ||
| 99 | ret = readw(ETHER1_RAM + ((addr & 4095) << 1)); | ||
| 100 | if (svflgs) | ||
| 101 | local_irq_restore (flags); | ||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline void | ||
| 106 | ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs) | ||
| 107 | { | ||
| 108 | unsigned long flags; | ||
| 109 | |||
| 110 | if (svflgs) | ||
| 111 | local_irq_save (flags); | ||
| 112 | |||
| 113 | writeb(addr >> 12, REG_PAGE); | ||
| 114 | writew(val, ETHER1_RAM + ((addr & 4095) << 1)); | ||
| 115 | if (svflgs) | ||
| 116 | local_irq_restore (flags); | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Some inline assembler to allow fast transfers on to/off of the card. | ||
| 121 | * Since this driver depends on some features presented by the ARM | ||
| 122 | * specific architecture, and that you can't configure this driver | ||
| 123 | * without specifiing ARM mode, this is not a problem. | ||
| 124 | * | ||
| 125 | * This routine is essentially an optimised memcpy from the card's | ||
| 126 | * onboard RAM to kernel memory. | ||
| 127 | */ | ||
| 128 | static void | ||
| 129 | ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length) | ||
| 130 | { | ||
| 131 | unsigned int page, thislen, offset; | ||
| 132 | void __iomem *addr; | ||
| 133 | |||
| 134 | offset = start & 4095; | ||
| 135 | page = start >> 12; | ||
| 136 | addr = ETHER1_RAM + (offset << 1); | ||
| 137 | |||
| 138 | if (offset + length > 4096) | ||
| 139 | thislen = 4096 - offset; | ||
| 140 | else | ||
| 141 | thislen = length; | ||
| 142 | |||
| 143 | do { | ||
| 144 | int used; | ||
| 145 | |||
| 146 | writeb(page, REG_PAGE); | ||
| 147 | length -= thislen; | ||
| 148 | |||
| 149 | __asm__ __volatile__( | ||
| 150 | "subs %3, %3, #2\n\ | ||
| 151 | bmi 2f\n\ | ||
| 152 | 1: ldr %0, [%1], #2\n\ | ||
| 153 | mov %0, %0, lsl #16\n\ | ||
| 154 | orr %0, %0, %0, lsr #16\n\ | ||
| 155 | str %0, [%2], #4\n\ | ||
| 156 | subs %3, %3, #2\n\ | ||
| 157 | bmi 2f\n\ | ||
| 158 | ldr %0, [%1], #2\n\ | ||
| 159 | mov %0, %0, lsl #16\n\ | ||
| 160 | orr %0, %0, %0, lsr #16\n\ | ||
| 161 | str %0, [%2], #4\n\ | ||
| 162 | subs %3, %3, #2\n\ | ||
| 163 | bmi 2f\n\ | ||
| 164 | ldr %0, [%1], #2\n\ | ||
| 165 | mov %0, %0, lsl #16\n\ | ||
| 166 | orr %0, %0, %0, lsr #16\n\ | ||
| 167 | str %0, [%2], #4\n\ | ||
| 168 | subs %3, %3, #2\n\ | ||
| 169 | bmi 2f\n\ | ||
| 170 | ldr %0, [%1], #2\n\ | ||
| 171 | mov %0, %0, lsl #16\n\ | ||
| 172 | orr %0, %0, %0, lsr #16\n\ | ||
| 173 | str %0, [%2], #4\n\ | ||
| 174 | subs %3, %3, #2\n\ | ||
| 175 | bpl 1b\n\ | ||
| 176 | 2: adds %3, %3, #1\n\ | ||
| 177 | ldreqb %0, [%1]\n\ | ||
| 178 | streqb %0, [%2]" | ||
| 179 | : "=&r" (used), "=&r" (data) | ||
| 180 | : "r" (addr), "r" (thislen), "1" (data)); | ||
| 181 | |||
| 182 | addr = ETHER1_RAM; | ||
| 183 | |||
| 184 | thislen = length; | ||
| 185 | if (thislen > 4096) | ||
| 186 | thislen = 4096; | ||
| 187 | page++; | ||
| 188 | } while (thislen); | ||
| 189 | } | ||
| 190 | |||
| 191 | static void | ||
| 192 | ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length) | ||
| 193 | { | ||
| 194 | unsigned int page, thislen, offset; | ||
| 195 | void __iomem *addr; | ||
| 196 | |||
| 197 | offset = start & 4095; | ||
| 198 | page = start >> 12; | ||
| 199 | addr = ETHER1_RAM + (offset << 1); | ||
| 200 | |||
| 201 | if (offset + length > 4096) | ||
| 202 | thislen = 4096 - offset; | ||
| 203 | else | ||
| 204 | thislen = length; | ||
| 205 | |||
| 206 | do { | ||
| 207 | int used; | ||
| 208 | |||
| 209 | writeb(page, REG_PAGE); | ||
| 210 | length -= thislen; | ||
| 211 | |||
| 212 | __asm__ __volatile__( | ||
| 213 | "subs %3, %3, #2\n\ | ||
| 214 | bmi 2f\n\ | ||
| 215 | 1: ldr %0, [%2], #4\n\ | ||
| 216 | strb %0, [%1], #1\n\ | ||
| 217 | mov %0, %0, lsr #8\n\ | ||
| 218 | strb %0, [%1], #1\n\ | ||
| 219 | subs %3, %3, #2\n\ | ||
| 220 | bmi 2f\n\ | ||
| 221 | ldr %0, [%2], #4\n\ | ||
| 222 | strb %0, [%1], #1\n\ | ||
| 223 | mov %0, %0, lsr #8\n\ | ||
| 224 | strb %0, [%1], #1\n\ | ||
| 225 | subs %3, %3, #2\n\ | ||
| 226 | bmi 2f\n\ | ||
| 227 | ldr %0, [%2], #4\n\ | ||
| 228 | strb %0, [%1], #1\n\ | ||
| 229 | mov %0, %0, lsr #8\n\ | ||
| 230 | strb %0, [%1], #1\n\ | ||
| 231 | subs %3, %3, #2\n\ | ||
| 232 | bmi 2f\n\ | ||
| 233 | ldr %0, [%2], #4\n\ | ||
| 234 | strb %0, [%1], #1\n\ | ||
| 235 | mov %0, %0, lsr #8\n\ | ||
| 236 | strb %0, [%1], #1\n\ | ||
| 237 | subs %3, %3, #2\n\ | ||
| 238 | bpl 1b\n\ | ||
| 239 | 2: adds %3, %3, #1\n\ | ||
| 240 | ldreqb %0, [%2]\n\ | ||
| 241 | streqb %0, [%1]" | ||
| 242 | : "=&r" (used), "=&r" (data) | ||
| 243 | : "r" (addr), "r" (thislen), "1" (data)); | ||
| 244 | |||
| 245 | addr = ETHER1_RAM; | ||
| 246 | |||
| 247 | thislen = length; | ||
| 248 | if (thislen > 4096) | ||
| 249 | thislen = 4096; | ||
| 250 | page++; | ||
| 251 | } while (thislen); | ||
| 252 | } | ||
| 253 | |||
| 254 | static int __devinit | ||
| 255 | ether1_ramtest(struct net_device *dev, unsigned char byte) | ||
| 256 | { | ||
| 257 | unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL); | ||
| 258 | int i, ret = BUFFER_SIZE; | ||
| 259 | int max_errors = 15; | ||
| 260 | int bad = -1; | ||
| 261 | int bad_start = 0; | ||
| 262 | |||
| 263 | if (!buffer) | ||
| 264 | return 1; | ||
| 265 | |||
| 266 | memset (buffer, byte, BUFFER_SIZE); | ||
| 267 | ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE); | ||
| 268 | memset (buffer, byte ^ 0xff, BUFFER_SIZE); | ||
| 269 | ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE); | ||
| 270 | |||
| 271 | for (i = 0; i < BUFFER_SIZE; i++) { | ||
| 272 | if (buffer[i] != byte) { | ||
| 273 | if (max_errors >= 0 && bad != buffer[i]) { | ||
| 274 | if (bad != -1) | ||
| 275 | printk ("\n"); | ||
| 276 | printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X", | ||
| 277 | dev->name, buffer[i], byte, i); | ||
| 278 | ret = -ENODEV; | ||
| 279 | max_errors --; | ||
| 280 | bad = buffer[i]; | ||
| 281 | bad_start = i; | ||
| 282 | } | ||
| 283 | } else { | ||
| 284 | if (bad != -1) { | ||
| 285 | if (bad_start == i - 1) | ||
| 286 | printk ("\n"); | ||
| 287 | else | ||
| 288 | printk (" - 0x%04X\n", i - 1); | ||
| 289 | bad = -1; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | if (bad != -1) | ||
| 295 | printk (" - 0x%04X\n", BUFFER_SIZE); | ||
| 296 | kfree (buffer); | ||
| 297 | |||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int | ||
| 302 | ether1_reset (struct net_device *dev) | ||
| 303 | { | ||
| 304 | writeb(CTRL_RST|CTRL_ACK, REG_CONTROL); | ||
| 305 | return BUS_16; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int __devinit | ||
| 309 | ether1_init_2(struct net_device *dev) | ||
| 310 | { | ||
| 311 | int i; | ||
| 312 | dev->mem_start = 0; | ||
| 313 | |||
| 314 | i = ether1_ramtest (dev, 0x5a); | ||
| 315 | |||
| 316 | if (i > 0) | ||
| 317 | i = ether1_ramtest (dev, 0x1e); | ||
| 318 | |||
| 319 | if (i <= 0) | ||
| 320 | return -ENODEV; | ||
| 321 | |||
| 322 | dev->mem_end = i; | ||
| 323 | return 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* | ||
| 327 | * These are the structures that are loaded into the ether RAM card to | ||
| 328 | * initialise the 82586 | ||
| 329 | */ | ||
| 330 | |||
| 331 | /* at 0x0100 */ | ||
| 332 | #define NOP_ADDR (TX_AREA_START) | ||
| 333 | #define NOP_SIZE (0x06) | ||
| 334 | static nop_t init_nop = { | ||
| 335 | 0, | ||
| 336 | CMD_NOP, | ||
| 337 | NOP_ADDR | ||
| 338 | }; | ||
| 339 | |||
| 340 | /* at 0x003a */ | ||
| 341 | #define TDR_ADDR (0x003a) | ||
| 342 | #define TDR_SIZE (0x08) | ||
| 343 | static tdr_t init_tdr = { | ||
| 344 | 0, | ||
| 345 | CMD_TDR | CMD_INTR, | ||
| 346 | NOP_ADDR, | ||
| 347 | 0 | ||
| 348 | }; | ||
| 349 | |||
| 350 | /* at 0x002e */ | ||
| 351 | #define MC_ADDR (0x002e) | ||
| 352 | #define MC_SIZE (0x0c) | ||
| 353 | static mc_t init_mc = { | ||
| 354 | 0, | ||
| 355 | CMD_SETMULTICAST, | ||
| 356 | TDR_ADDR, | ||
| 357 | 0, | ||
| 358 | { { 0, } } | ||
| 359 | }; | ||
| 360 | |||
| 361 | /* at 0x0022 */ | ||
| 362 | #define SA_ADDR (0x0022) | ||
| 363 | #define SA_SIZE (0x0c) | ||
| 364 | static sa_t init_sa = { | ||
| 365 | 0, | ||
| 366 | CMD_SETADDRESS, | ||
| 367 | MC_ADDR, | ||
| 368 | { 0, } | ||
| 369 | }; | ||
| 370 | |||
| 371 | /* at 0x0010 */ | ||
| 372 | #define CFG_ADDR (0x0010) | ||
| 373 | #define CFG_SIZE (0x12) | ||
| 374 | static cfg_t init_cfg = { | ||
| 375 | 0, | ||
| 376 | CMD_CONFIG, | ||
| 377 | SA_ADDR, | ||
| 378 | 8, | ||
| 379 | 8, | ||
| 380 | CFG8_SRDY, | ||
| 381 | CFG9_PREAMB8 | CFG9_ADDRLENBUF | CFG9_ADDRLEN(6), | ||
| 382 | 0, | ||
| 383 | 0x60, | ||
| 384 | 0, | ||
| 385 | CFG13_RETRY(15) | CFG13_SLOTH(2), | ||
| 386 | 0, | ||
| 387 | }; | ||
| 388 | |||
| 389 | /* at 0x0000 */ | ||
| 390 | #define SCB_ADDR (0x0000) | ||
| 391 | #define SCB_SIZE (0x10) | ||
| 392 | static scb_t init_scb = { | ||
| 393 | 0, | ||
| 394 | SCB_CMDACKRNR | SCB_CMDACKCNA | SCB_CMDACKFR | SCB_CMDACKCX, | ||
| 395 | CFG_ADDR, | ||
| 396 | RX_AREA_START, | ||
| 397 | 0, | ||
| 398 | 0, | ||
| 399 | 0, | ||
| 400 | 0 | ||
| 401 | }; | ||
| 402 | |||
| 403 | /* at 0xffee */ | ||
| 404 | #define ISCP_ADDR (0xffee) | ||
| 405 | #define ISCP_SIZE (0x08) | ||
| 406 | static iscp_t init_iscp = { | ||
| 407 | 1, | ||
| 408 | SCB_ADDR, | ||
| 409 | 0x0000, | ||
| 410 | 0x0000 | ||
| 411 | }; | ||
| 412 | |||
| 413 | /* at 0xfff6 */ | ||
| 414 | #define SCP_ADDR (0xfff6) | ||
| 415 | #define SCP_SIZE (0x0a) | ||
| 416 | static scp_t init_scp = { | ||
| 417 | SCP_SY_16BBUS, | ||
| 418 | { 0, 0 }, | ||
| 419 | ISCP_ADDR, | ||
| 420 | 0 | ||
| 421 | }; | ||
| 422 | |||
| 423 | #define RFD_SIZE (0x16) | ||
| 424 | static rfd_t init_rfd = { | ||
| 425 | 0, | ||
| 426 | 0, | ||
| 427 | 0, | ||
| 428 | 0, | ||
| 429 | { 0, }, | ||
| 430 | { 0, }, | ||
| 431 | 0 | ||
| 432 | }; | ||
| 433 | |||
| 434 | #define RBD_SIZE (0x0a) | ||
| 435 | static rbd_t init_rbd = { | ||
| 436 | 0, | ||
| 437 | 0, | ||
| 438 | 0, | ||
| 439 | 0, | ||
| 440 | ETH_FRAME_LEN + 8 | ||
| 441 | }; | ||
| 442 | |||
| 443 | #define TX_SIZE (0x08) | ||
| 444 | #define TBD_SIZE (0x08) | ||
| 445 | |||
| 446 | static int | ||
| 447 | ether1_init_for_open (struct net_device *dev) | ||
| 448 | { | ||
| 449 | int i, status, addr, next, next2; | ||
| 450 | int failures = 0; | ||
| 451 | unsigned long timeout; | ||
| 452 | |||
| 453 | writeb(CTRL_RST|CTRL_ACK, REG_CONTROL); | ||
| 454 | |||
| 455 | for (i = 0; i < 6; i++) | ||
| 456 | init_sa.sa_addr[i] = dev->dev_addr[i]; | ||
| 457 | |||
| 458 | /* load data structures into ether1 RAM */ | ||
| 459 | ether1_writebuffer (dev, &init_scp, SCP_ADDR, SCP_SIZE); | ||
| 460 | ether1_writebuffer (dev, &init_iscp, ISCP_ADDR, ISCP_SIZE); | ||
| 461 | ether1_writebuffer (dev, &init_scb, SCB_ADDR, SCB_SIZE); | ||
| 462 | ether1_writebuffer (dev, &init_cfg, CFG_ADDR, CFG_SIZE); | ||
| 463 | ether1_writebuffer (dev, &init_sa, SA_ADDR, SA_SIZE); | ||
| 464 | ether1_writebuffer (dev, &init_mc, MC_ADDR, MC_SIZE); | ||
| 465 | ether1_writebuffer (dev, &init_tdr, TDR_ADDR, TDR_SIZE); | ||
| 466 | ether1_writebuffer (dev, &init_nop, NOP_ADDR, NOP_SIZE); | ||
| 467 | |||
| 468 | if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) { | ||
| 469 | printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n", | ||
| 470 | dev->name); | ||
| 471 | return 1; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* | ||
| 475 | * setup circularly linked list of { rfd, rbd, buffer }, with | ||
| 476 | * all rfds circularly linked, rbds circularly linked. | ||
| 477 | * First rfd is linked to scp, first rbd is linked to first | ||
| 478 | * rfd. Last rbd has a suspend command. | ||
| 479 | */ | ||
| 480 | addr = RX_AREA_START; | ||
| 481 | do { | ||
| 482 | next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10; | ||
| 483 | next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10; | ||
| 484 | |||
| 485 | if (next2 >= RX_AREA_END) { | ||
| 486 | next = RX_AREA_START; | ||
| 487 | init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND; | ||
| 488 | priv(dev)->rx_tail = addr; | ||
| 489 | } else | ||
| 490 | init_rfd.rfd_command = 0; | ||
| 491 | if (addr == RX_AREA_START) | ||
| 492 | init_rfd.rfd_rbdoffset = addr + RFD_SIZE; | ||
| 493 | else | ||
| 494 | init_rfd.rfd_rbdoffset = 0; | ||
| 495 | init_rfd.rfd_link = next; | ||
| 496 | init_rbd.rbd_link = next + RFD_SIZE; | ||
| 497 | init_rbd.rbd_bufl = addr + RFD_SIZE + RBD_SIZE; | ||
| 498 | |||
| 499 | ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE); | ||
| 500 | ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE); | ||
| 501 | addr = next; | ||
| 502 | } while (next2 < RX_AREA_END); | ||
| 503 | |||
| 504 | priv(dev)->tx_link = NOP_ADDR; | ||
| 505 | priv(dev)->tx_head = NOP_ADDR + NOP_SIZE; | ||
| 506 | priv(dev)->tx_tail = TDR_ADDR; | ||
| 507 | priv(dev)->rx_head = RX_AREA_START; | ||
| 508 | |||
| 509 | /* release reset & give 586 a prod */ | ||
| 510 | priv(dev)->resetting = 1; | ||
| 511 | priv(dev)->initialising = 1; | ||
| 512 | writeb(CTRL_RST, REG_CONTROL); | ||
| 513 | writeb(0, REG_CONTROL); | ||
| 514 | writeb(CTRL_CA, REG_CONTROL); | ||
| 515 | |||
| 516 | /* 586 should now unset iscp.busy */ | ||
| 517 | timeout = jiffies + HZ/2; | ||
| 518 | while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) { | ||
| 519 | if (time_after(jiffies, timeout)) { | ||
| 520 | printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name); | ||
| 521 | return 1; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | /* check status of commands that we issued */ | ||
| 526 | timeout += HZ/10; | ||
| 527 | while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS)) | ||
| 528 | & STAT_COMPLETE) == 0) { | ||
| 529 | if (time_after(jiffies, timeout)) | ||
| 530 | break; | ||
| 531 | } | ||
| 532 | |||
| 533 | if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { | ||
| 534 | printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status); | ||
| 535 | printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, | ||
| 536 | ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), | ||
| 537 | ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), | ||
| 538 | ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), | ||
| 539 | ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); | ||
| 540 | failures += 1; | ||
| 541 | } | ||
| 542 | |||
| 543 | timeout += HZ/10; | ||
| 544 | while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) | ||
| 545 | & STAT_COMPLETE) == 0) { | ||
| 546 | if (time_after(jiffies, timeout)) | ||
| 547 | break; | ||
| 548 | } | ||
| 549 | |||
| 550 | if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { | ||
| 551 | printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status); | ||
| 552 | printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, | ||
| 553 | ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), | ||
| 554 | ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), | ||
| 555 | ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), | ||
| 556 | ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); | ||
| 557 | failures += 1; | ||
| 558 | } | ||
| 559 | |||
| 560 | timeout += HZ/10; | ||
| 561 | while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) | ||
| 562 | & STAT_COMPLETE) == 0) { | ||
| 563 | if (time_after(jiffies, timeout)) | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | |||
| 567 | if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { | ||
| 568 | printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status); | ||
| 569 | printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, | ||
| 570 | ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), | ||
| 571 | ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), | ||
| 572 | ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), | ||
| 573 | ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); | ||
| 574 | failures += 1; | ||
| 575 | } | ||
| 576 | |||
| 577 | timeout += HZ; | ||
| 578 | while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS)) | ||
| 579 | & STAT_COMPLETE) == 0) { | ||
| 580 | if (time_after(jiffies, timeout)) | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | |||
| 584 | if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { | ||
| 585 | printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name); | ||
| 586 | printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, | ||
| 587 | ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), | ||
| 588 | ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), | ||
| 589 | ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), | ||
| 590 | ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); | ||
| 591 | } else { | ||
| 592 | status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS); | ||
| 593 | if (status & TDR_XCVRPROB) | ||
| 594 | printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name); | ||
| 595 | else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) { | ||
| 596 | #ifdef FANCY | ||
| 597 | printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name, | ||
| 598 | status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10, | ||
| 599 | (status & TDR_TIME) % 10); | ||
| 600 | #else | ||
| 601 | printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name, | ||
| 602 | status & TDR_SHORT ? "short" : "open", (status & TDR_TIME)); | ||
| 603 | #endif | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | if (failures) | ||
| 608 | ether1_reset (dev); | ||
| 609 | return failures ? 1 : 0; | ||
| 610 | } | ||
| 611 | |||
| 612 | /* ------------------------------------------------------------------------- */ | ||
| 613 | |||
| 614 | static int | ||
| 615 | ether1_txalloc (struct net_device *dev, int size) | ||
| 616 | { | ||
| 617 | int start, tail; | ||
| 618 | |||
| 619 | size = (size + 1) & ~1; | ||
| 620 | tail = priv(dev)->tx_tail; | ||
| 621 | |||
| 622 | if (priv(dev)->tx_head + size > TX_AREA_END) { | ||
| 623 | if (tail > priv(dev)->tx_head) | ||
| 624 | return -1; | ||
| 625 | start = TX_AREA_START; | ||
| 626 | if (start + size > tail) | ||
| 627 | return -1; | ||
| 628 | priv(dev)->tx_head = start + size; | ||
| 629 | } else { | ||
| 630 | if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail) | ||
| 631 | return -1; | ||
| 632 | start = priv(dev)->tx_head; | ||
| 633 | priv(dev)->tx_head += size; | ||
| 634 | } | ||
| 635 | |||
| 636 | return start; | ||
| 637 | } | ||
| 638 | |||
| 639 | static int | ||
| 640 | ether1_open (struct net_device *dev) | ||
| 641 | { | ||
| 642 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
| 643 | printk(KERN_WARNING "%s: invalid ethernet MAC address\n", | ||
| 644 | dev->name); | ||
| 645 | return -EINVAL; | ||
| 646 | } | ||
| 647 | |||
| 648 | if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) | ||
| 649 | return -EAGAIN; | ||
| 650 | |||
| 651 | if (ether1_init_for_open (dev)) { | ||
| 652 | free_irq (dev->irq, dev); | ||
| 653 | return -EAGAIN; | ||
| 654 | } | ||
| 655 | |||
| 656 | netif_start_queue(dev); | ||
| 657 | |||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static void | ||
| 662 | ether1_timeout(struct net_device *dev) | ||
| 663 | { | ||
| 664 | printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n", | ||
| 665 | dev->name); | ||
| 666 | printk(KERN_WARNING "%s: resetting device\n", dev->name); | ||
| 667 | |||
| 668 | ether1_reset (dev); | ||
| 669 | |||
| 670 | if (ether1_init_for_open (dev)) | ||
| 671 | printk (KERN_ERR "%s: unable to restart interface\n", dev->name); | ||
| 672 | |||
| 673 | dev->stats.tx_errors++; | ||
| 674 | netif_wake_queue(dev); | ||
| 675 | } | ||
| 676 | |||
| 677 | static int | ||
| 678 | ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) | ||
| 679 | { | ||
| 680 | int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr; | ||
| 681 | unsigned long flags; | ||
| 682 | tx_t tx; | ||
| 683 | tbd_t tbd; | ||
| 684 | nop_t nop; | ||
| 685 | |||
| 686 | if (priv(dev)->restart) { | ||
| 687 | printk(KERN_WARNING "%s: resetting device\n", dev->name); | ||
| 688 | |||
| 689 | ether1_reset(dev); | ||
| 690 | |||
| 691 | if (ether1_init_for_open(dev)) | ||
| 692 | printk(KERN_ERR "%s: unable to restart interface\n", dev->name); | ||
| 693 | else | ||
| 694 | priv(dev)->restart = 0; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (skb->len < ETH_ZLEN) { | ||
| 698 | if (skb_padto(skb, ETH_ZLEN)) | ||
| 699 | goto out; | ||
| 700 | } | ||
| 701 | |||
| 702 | /* | ||
| 703 | * insert packet followed by a nop | ||
| 704 | */ | ||
| 705 | txaddr = ether1_txalloc (dev, TX_SIZE); | ||
| 706 | tbdaddr = ether1_txalloc (dev, TBD_SIZE); | ||
| 707 | dataddr = ether1_txalloc (dev, skb->len); | ||
| 708 | nopaddr = ether1_txalloc (dev, NOP_SIZE); | ||
| 709 | |||
| 710 | tx.tx_status = 0; | ||
| 711 | tx.tx_command = CMD_TX | CMD_INTR; | ||
| 712 | tx.tx_link = nopaddr; | ||
| 713 | tx.tx_tbdoffset = tbdaddr; | ||
| 714 | tbd.tbd_opts = TBD_EOL | skb->len; | ||
| 715 | tbd.tbd_link = I82586_NULL; | ||
| 716 | tbd.tbd_bufl = dataddr; | ||
| 717 | tbd.tbd_bufh = 0; | ||
| 718 | nop.nop_status = 0; | ||
| 719 | nop.nop_command = CMD_NOP; | ||
| 720 | nop.nop_link = nopaddr; | ||
| 721 | |||
| 722 | local_irq_save(flags); | ||
| 723 | ether1_writebuffer (dev, &tx, txaddr, TX_SIZE); | ||
| 724 | ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE); | ||
| 725 | ether1_writebuffer (dev, skb->data, dataddr, skb->len); | ||
| 726 | ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE); | ||
| 727 | tmp = priv(dev)->tx_link; | ||
| 728 | priv(dev)->tx_link = nopaddr; | ||
| 729 | |||
| 730 | /* now reset the previous nop pointer */ | ||
| 731 | ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS); | ||
| 732 | |||
| 733 | local_irq_restore(flags); | ||
| 734 | |||
| 735 | /* handle transmit */ | ||
| 736 | |||
| 737 | /* check to see if we have room for a full sized ether frame */ | ||
| 738 | tmp = priv(dev)->tx_head; | ||
| 739 | tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN); | ||
| 740 | priv(dev)->tx_head = tmp; | ||
| 741 | dev_kfree_skb (skb); | ||
| 742 | |||
| 743 | if (tst == -1) | ||
| 744 | netif_stop_queue(dev); | ||
| 745 | |||
| 746 | out: | ||
| 747 | return NETDEV_TX_OK; | ||
| 748 | } | ||
| 749 | |||
| 750 | static void | ||
| 751 | ether1_xmit_done (struct net_device *dev) | ||
| 752 | { | ||
| 753 | nop_t nop; | ||
| 754 | int caddr, tst; | ||
| 755 | |||
| 756 | caddr = priv(dev)->tx_tail; | ||
| 757 | |||
| 758 | again: | ||
| 759 | ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); | ||
| 760 | |||
| 761 | switch (nop.nop_command & CMD_MASK) { | ||
| 762 | case CMD_TDR: | ||
| 763 | /* special case */ | ||
| 764 | if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) | ||
| 765 | != (unsigned short)I82586_NULL) { | ||
| 766 | ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, | ||
| 767 | scb_command, NORMALIRQS); | ||
| 768 | writeb(CTRL_CA, REG_CONTROL); | ||
| 769 | } | ||
| 770 | priv(dev)->tx_tail = NOP_ADDR; | ||
| 771 | return; | ||
| 772 | |||
| 773 | case CMD_NOP: | ||
| 774 | if (nop.nop_link == caddr) { | ||
| 775 | if (priv(dev)->initialising == 0) | ||
| 776 | printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name); | ||
| 777 | else | ||
| 778 | priv(dev)->initialising = 0; | ||
| 779 | return; | ||
| 780 | } | ||
| 781 | if (caddr == nop.nop_link) | ||
| 782 | return; | ||
| 783 | caddr = nop.nop_link; | ||
| 784 | goto again; | ||
| 785 | |||
| 786 | case CMD_TX: | ||
| 787 | if (nop.nop_status & STAT_COMPLETE) | ||
| 788 | break; | ||
| 789 | printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name); | ||
| 790 | priv(dev)->restart = 1; | ||
| 791 | return; | ||
| 792 | |||
| 793 | default: | ||
| 794 | printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name, | ||
| 795 | nop.nop_command & CMD_MASK, caddr); | ||
| 796 | priv(dev)->restart = 1; | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | while (nop.nop_status & STAT_COMPLETE) { | ||
| 801 | if (nop.nop_status & STAT_OK) { | ||
| 802 | dev->stats.tx_packets++; | ||
| 803 | dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS); | ||
| 804 | } else { | ||
| 805 | dev->stats.tx_errors++; | ||
| 806 | |||
| 807 | if (nop.nop_status & STAT_COLLAFTERTX) | ||
| 808 | dev->stats.collisions++; | ||
| 809 | if (nop.nop_status & STAT_NOCARRIER) | ||
| 810 | dev->stats.tx_carrier_errors++; | ||
| 811 | if (nop.nop_status & STAT_TXLOSTCTS) | ||
| 812 | printk (KERN_WARNING "%s: cts lost\n", dev->name); | ||
| 813 | if (nop.nop_status & STAT_TXSLOWDMA) | ||
| 814 | dev->stats.tx_fifo_errors++; | ||
| 815 | if (nop.nop_status & STAT_COLLEXCESSIVE) | ||
| 816 | dev->stats.collisions += 16; | ||
| 817 | } | ||
| 818 | |||
| 819 | if (nop.nop_link == caddr) { | ||
| 820 | printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name); | ||
| 821 | break; | ||
| 822 | } | ||
| 823 | |||
| 824 | caddr = nop.nop_link; | ||
| 825 | ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); | ||
| 826 | if ((nop.nop_command & CMD_MASK) != CMD_NOP) { | ||
| 827 | printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name); | ||
| 828 | break; | ||
| 829 | } | ||
| 830 | |||
| 831 | if (caddr == nop.nop_link) | ||
| 832 | break; | ||
| 833 | |||
| 834 | caddr = nop.nop_link; | ||
| 835 | ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); | ||
| 836 | if ((nop.nop_command & CMD_MASK) != CMD_TX) { | ||
| 837 | printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name); | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | } | ||
| 841 | priv(dev)->tx_tail = caddr; | ||
| 842 | |||
| 843 | caddr = priv(dev)->tx_head; | ||
| 844 | tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN); | ||
| 845 | priv(dev)->tx_head = caddr; | ||
| 846 | if (tst != -1) | ||
| 847 | netif_wake_queue(dev); | ||
| 848 | } | ||
| 849 | |||
| 850 | static void | ||
| 851 | ether1_recv_done (struct net_device *dev) | ||
| 852 | { | ||
| 853 | int status; | ||
| 854 | int nexttail, rbdaddr; | ||
| 855 | rbd_t rbd; | ||
| 856 | |||
| 857 | do { | ||
| 858 | status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS); | ||
| 859 | if ((status & RFD_COMPLETE) == 0) | ||
| 860 | break; | ||
| 861 | |||
| 862 | rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS); | ||
| 863 | ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE); | ||
| 864 | |||
| 865 | if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) { | ||
| 866 | int length = rbd.rbd_status & RBD_ACNT; | ||
| 867 | struct sk_buff *skb; | ||
| 868 | |||
| 869 | length = (length + 1) & ~1; | ||
| 870 | skb = dev_alloc_skb (length + 2); | ||
| 871 | |||
| 872 | if (skb) { | ||
| 873 | skb_reserve (skb, 2); | ||
| 874 | |||
| 875 | ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length); | ||
| 876 | |||
| 877 | skb->protocol = eth_type_trans (skb, dev); | ||
| 878 | netif_rx (skb); | ||
| 879 | dev->stats.rx_packets++; | ||
| 880 | } else | ||
| 881 | dev->stats.rx_dropped++; | ||
| 882 | } else { | ||
| 883 | printk(KERN_WARNING "%s: %s\n", dev->name, | ||
| 884 | (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid"); | ||
| 885 | dev->stats.rx_dropped++; | ||
| 886 | } | ||
| 887 | |||
| 888 | nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS); | ||
| 889 | /* nexttail should be rx_head */ | ||
| 890 | if (nexttail != priv(dev)->rx_head) | ||
| 891 | printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n", | ||
| 892 | dev->name, nexttail, priv(dev)->rx_head); | ||
| 893 | ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS); | ||
| 894 | ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS); | ||
| 895 | ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS); | ||
| 896 | ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS); | ||
| 897 | |||
| 898 | priv(dev)->rx_tail = nexttail; | ||
| 899 | priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS); | ||
| 900 | } while (1); | ||
| 901 | } | ||
| 902 | |||
| 903 | static irqreturn_t | ||
| 904 | ether1_interrupt (int irq, void *dev_id) | ||
| 905 | { | ||
| 906 | struct net_device *dev = (struct net_device *)dev_id; | ||
| 907 | int status; | ||
| 908 | |||
| 909 | status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS); | ||
| 910 | |||
| 911 | if (status) { | ||
| 912 | ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX), | ||
| 913 | SCB_ADDR, scb_t, scb_command, NORMALIRQS); | ||
| 914 | writeb(CTRL_CA | CTRL_ACK, REG_CONTROL); | ||
| 915 | if (status & SCB_STCX) { | ||
| 916 | ether1_xmit_done (dev); | ||
| 917 | } | ||
| 918 | if (status & SCB_STCNA) { | ||
| 919 | if (priv(dev)->resetting == 0) | ||
| 920 | printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name); | ||
| 921 | else | ||
| 922 | priv(dev)->resetting += 1; | ||
| 923 | if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) | ||
| 924 | != (unsigned short)I82586_NULL) { | ||
| 925 | ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS); | ||
| 926 | writeb(CTRL_CA, REG_CONTROL); | ||
| 927 | } | ||
| 928 | if (priv(dev)->resetting == 2) | ||
| 929 | priv(dev)->resetting = 0; | ||
| 930 | } | ||
| 931 | if (status & SCB_STFR) { | ||
| 932 | ether1_recv_done (dev); | ||
| 933 | } | ||
| 934 | if (status & SCB_STRNR) { | ||
| 935 | if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) { | ||
| 936 | printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name); | ||
| 937 | ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS); | ||
| 938 | writeb(CTRL_CA, REG_CONTROL); | ||
| 939 | dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */ | ||
| 940 | } else | ||
| 941 | printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name, | ||
| 942 | ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS)); | ||
| 943 | printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, | ||
| 944 | NORMALIRQS)); | ||
| 945 | } | ||
| 946 | } else | ||
| 947 | writeb(CTRL_ACK, REG_CONTROL); | ||
| 948 | |||
| 949 | return IRQ_HANDLED; | ||
| 950 | } | ||
| 951 | |||
| 952 | static int | ||
| 953 | ether1_close (struct net_device *dev) | ||
| 954 | { | ||
| 955 | ether1_reset (dev); | ||
| 956 | |||
| 957 | free_irq(dev->irq, dev); | ||
| 958 | |||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 962 | /* | ||
| 963 | * Set or clear the multicast filter for this adaptor. | ||
| 964 | * num_addrs == -1 Promiscuous mode, receive all packets. | ||
| 965 | * num_addrs == 0 Normal mode, clear multicast list. | ||
| 966 | * num_addrs > 0 Multicast mode, receive normal and MC packets, and do | ||
| 967 | * best-effort filtering. | ||
| 968 | */ | ||
| 969 | static void | ||
| 970 | ether1_setmulticastlist (struct net_device *dev) | ||
| 971 | { | ||
| 972 | } | ||
| 973 | |||
| 974 | /* ------------------------------------------------------------------------- */ | ||
| 975 | |||
| 976 | static void __devinit ether1_banner(void) | ||
| 977 | { | ||
| 978 | static unsigned int version_printed = 0; | ||
| 979 | |||
| 980 | if (net_debug && version_printed++ == 0) | ||
| 981 | printk(KERN_INFO "%s", version); | ||
| 982 | } | ||
| 983 | |||
| 984 | static const struct net_device_ops ether1_netdev_ops = { | ||
| 985 | .ndo_open = ether1_open, | ||
| 986 | .ndo_stop = ether1_close, | ||
| 987 | .ndo_start_xmit = ether1_sendpacket, | ||
| 988 | .ndo_set_multicast_list = ether1_setmulticastlist, | ||
| 989 | .ndo_tx_timeout = ether1_timeout, | ||
| 990 | .ndo_validate_addr = eth_validate_addr, | ||
| 991 | .ndo_change_mtu = eth_change_mtu, | ||
| 992 | .ndo_set_mac_address = eth_mac_addr, | ||
| 993 | }; | ||
| 994 | |||
| 995 | static int __devinit | ||
| 996 | ether1_probe(struct expansion_card *ec, const struct ecard_id *id) | ||
| 997 | { | ||
| 998 | struct net_device *dev; | ||
| 999 | int i, ret = 0; | ||
| 1000 | |||
| 1001 | ether1_banner(); | ||
| 1002 | |||
| 1003 | ret = ecard_request_resources(ec); | ||
| 1004 | if (ret) | ||
| 1005 | goto out; | ||
| 1006 | |||
| 1007 | dev = alloc_etherdev(sizeof(struct ether1_priv)); | ||
| 1008 | if (!dev) { | ||
| 1009 | ret = -ENOMEM; | ||
| 1010 | goto release; | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | SET_NETDEV_DEV(dev, &ec->dev); | ||
| 1014 | |||
| 1015 | dev->irq = ec->irq; | ||
| 1016 | priv(dev)->base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); | ||
| 1017 | if (!priv(dev)->base) { | ||
| 1018 | ret = -ENOMEM; | ||
| 1019 | goto free; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) { | ||
| 1023 | ret = -ENODEV; | ||
| 1024 | goto free; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | for (i = 0; i < 6; i++) | ||
| 1028 | dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2)); | ||
| 1029 | |||
| 1030 | if (ether1_init_2(dev)) { | ||
| 1031 | ret = -ENODEV; | ||
| 1032 | goto free; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | dev->netdev_ops = ðer1_netdev_ops; | ||
| 1036 | dev->watchdog_timeo = 5 * HZ / 100; | ||
| 1037 | |||
| 1038 | ret = register_netdev(dev); | ||
| 1039 | if (ret) | ||
| 1040 | goto free; | ||
| 1041 | |||
| 1042 | printk(KERN_INFO "%s: ether1 in slot %d, %pM\n", | ||
| 1043 | dev->name, ec->slot_no, dev->dev_addr); | ||
| 1044 | |||
| 1045 | ecard_set_drvdata(ec, dev); | ||
| 1046 | return 0; | ||
| 1047 | |||
| 1048 | free: | ||
| 1049 | free_netdev(dev); | ||
| 1050 | release: | ||
| 1051 | ecard_release_resources(ec); | ||
| 1052 | out: | ||
| 1053 | return ret; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | static void __devexit ether1_remove(struct expansion_card *ec) | ||
| 1057 | { | ||
| 1058 | struct net_device *dev = ecard_get_drvdata(ec); | ||
| 1059 | |||
| 1060 | ecard_set_drvdata(ec, NULL); | ||
| 1061 | |||
| 1062 | unregister_netdev(dev); | ||
| 1063 | free_netdev(dev); | ||
| 1064 | ecard_release_resources(ec); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static const struct ecard_id ether1_ids[] = { | ||
| 1068 | { MANU_ACORN, PROD_ACORN_ETHER1 }, | ||
| 1069 | { 0xffff, 0xffff } | ||
| 1070 | }; | ||
| 1071 | |||
| 1072 | static struct ecard_driver ether1_driver = { | ||
| 1073 | .probe = ether1_probe, | ||
| 1074 | .remove = __devexit_p(ether1_remove), | ||
| 1075 | .id_table = ether1_ids, | ||
| 1076 | .drv = { | ||
| 1077 | .name = "ether1", | ||
| 1078 | }, | ||
| 1079 | }; | ||
| 1080 | |||
| 1081 | static int __init ether1_init(void) | ||
| 1082 | { | ||
| 1083 | return ecard_register_driver(ðer1_driver); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static void __exit ether1_exit(void) | ||
| 1087 | { | ||
| 1088 | ecard_remove_driver(ðer1_driver); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | module_init(ether1_init); | ||
| 1092 | module_exit(ether1_exit); | ||
| 1093 | |||
| 1094 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h new file mode 100644 index 00000000000..3a5830ab3dc --- /dev/null +++ b/drivers/net/arm/ether1.h | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/acorn/net/ether1.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 1996 Russell King | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Network driver for Acorn Ether1 cards. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _LINUX_ether1_H | ||
| 14 | #define _LINUX_ether1_H | ||
| 15 | |||
| 16 | #ifdef __ETHER1_C | ||
| 17 | /* use 0 for production, 1 for verification, >2 for debug */ | ||
| 18 | #ifndef NET_DEBUG | ||
| 19 | #define NET_DEBUG 0 | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #define priv(dev) ((struct ether1_priv *)netdev_priv(dev)) | ||
| 23 | |||
| 24 | /* Page register */ | ||
| 25 | #define REG_PAGE (priv(dev)->base + 0x0000) | ||
| 26 | |||
| 27 | /* Control register */ | ||
| 28 | #define REG_CONTROL (priv(dev)->base + 0x0004) | ||
| 29 | #define CTRL_RST 0x01 | ||
| 30 | #define CTRL_LOOPBACK 0x02 | ||
| 31 | #define CTRL_CA 0x04 | ||
| 32 | #define CTRL_ACK 0x08 | ||
| 33 | |||
| 34 | #define ETHER1_RAM (priv(dev)->base + 0x2000) | ||
| 35 | |||
| 36 | /* HW address */ | ||
| 37 | #define IDPROM_ADDRESS (priv(dev)->base + 0x0024) | ||
| 38 | |||
| 39 | struct ether1_priv { | ||
| 40 | void __iomem *base; | ||
| 41 | unsigned int tx_link; | ||
| 42 | unsigned int tx_head; | ||
| 43 | volatile unsigned int tx_tail; | ||
| 44 | volatile unsigned int rx_head; | ||
| 45 | volatile unsigned int rx_tail; | ||
| 46 | unsigned char bus_type; | ||
| 47 | unsigned char resetting; | ||
| 48 | unsigned char initialising : 1; | ||
| 49 | unsigned char restart : 1; | ||
| 50 | }; | ||
| 51 | |||
| 52 | #define I82586_NULL (-1) | ||
| 53 | |||
| 54 | typedef struct { /* tdr */ | ||
| 55 | unsigned short tdr_status; | ||
| 56 | unsigned short tdr_command; | ||
| 57 | unsigned short tdr_link; | ||
| 58 | unsigned short tdr_result; | ||
| 59 | #define TDR_TIME (0x7ff) | ||
| 60 | #define TDR_SHORT (1 << 12) | ||
| 61 | #define TDR_OPEN (1 << 13) | ||
| 62 | #define TDR_XCVRPROB (1 << 14) | ||
| 63 | #define TDR_LNKOK (1 << 15) | ||
| 64 | } tdr_t; | ||
| 65 | |||
| 66 | typedef struct { /* transmit */ | ||
| 67 | unsigned short tx_status; | ||
| 68 | unsigned short tx_command; | ||
| 69 | unsigned short tx_link; | ||
| 70 | unsigned short tx_tbdoffset; | ||
| 71 | } tx_t; | ||
| 72 | |||
| 73 | typedef struct { /* tbd */ | ||
| 74 | unsigned short tbd_opts; | ||
| 75 | #define TBD_CNT (0x3fff) | ||
| 76 | #define TBD_EOL (1 << 15) | ||
| 77 | unsigned short tbd_link; | ||
| 78 | unsigned short tbd_bufl; | ||
| 79 | unsigned short tbd_bufh; | ||
| 80 | } tbd_t; | ||
| 81 | |||
| 82 | typedef struct { /* rfd */ | ||
| 83 | unsigned short rfd_status; | ||
| 84 | #define RFD_NOEOF (1 << 6) | ||
| 85 | #define RFD_FRAMESHORT (1 << 7) | ||
| 86 | #define RFD_DMAOVRN (1 << 8) | ||
| 87 | #define RFD_NORESOURCES (1 << 9) | ||
| 88 | #define RFD_ALIGNERROR (1 << 10) | ||
| 89 | #define RFD_CRCERROR (1 << 11) | ||
| 90 | #define RFD_OK (1 << 13) | ||
| 91 | #define RFD_FDCONSUMED (1 << 14) | ||
| 92 | #define RFD_COMPLETE (1 << 15) | ||
| 93 | unsigned short rfd_command; | ||
| 94 | #define RFD_CMDSUSPEND (1 << 14) | ||
| 95 | #define RFD_CMDEL (1 << 15) | ||
| 96 | unsigned short rfd_link; | ||
| 97 | unsigned short rfd_rbdoffset; | ||
| 98 | unsigned char rfd_dest[6]; | ||
| 99 | unsigned char rfd_src[6]; | ||
| 100 | unsigned short rfd_len; | ||
| 101 | } rfd_t; | ||
| 102 | |||
| 103 | typedef struct { /* rbd */ | ||
| 104 | unsigned short rbd_status; | ||
| 105 | #define RBD_ACNT (0x3fff) | ||
| 106 | #define RBD_ACNTVALID (1 << 14) | ||
| 107 | #define RBD_EOF (1 << 15) | ||
| 108 | unsigned short rbd_link; | ||
| 109 | unsigned short rbd_bufl; | ||
| 110 | unsigned short rbd_bufh; | ||
| 111 | unsigned short rbd_len; | ||
| 112 | } rbd_t; | ||
| 113 | |||
| 114 | typedef struct { /* nop */ | ||
| 115 | unsigned short nop_status; | ||
| 116 | unsigned short nop_command; | ||
| 117 | unsigned short nop_link; | ||
| 118 | } nop_t; | ||
| 119 | |||
| 120 | typedef struct { /* set multicast */ | ||
| 121 | unsigned short mc_status; | ||
| 122 | unsigned short mc_command; | ||
| 123 | unsigned short mc_link; | ||
| 124 | unsigned short mc_cnt; | ||
| 125 | unsigned char mc_addrs[1][6]; | ||
| 126 | } mc_t; | ||
| 127 | |||
| 128 | typedef struct { /* set address */ | ||
| 129 | unsigned short sa_status; | ||
| 130 | unsigned short sa_command; | ||
| 131 | unsigned short sa_link; | ||
| 132 | unsigned char sa_addr[6]; | ||
| 133 | } sa_t; | ||
| 134 | |||
| 135 | typedef struct { /* config command */ | ||
| 136 | unsigned short cfg_status; | ||
| 137 | unsigned short cfg_command; | ||
| 138 | unsigned short cfg_link; | ||
| 139 | unsigned char cfg_bytecnt; /* size foll data: 4 - 12 */ | ||
| 140 | unsigned char cfg_fifolim; /* FIFO threshold */ | ||
| 141 | unsigned char cfg_byte8; | ||
| 142 | #define CFG8_SRDY (1 << 6) | ||
| 143 | #define CFG8_SAVEBADF (1 << 7) | ||
| 144 | unsigned char cfg_byte9; | ||
| 145 | #define CFG9_ADDRLEN(x) (x) | ||
| 146 | #define CFG9_ADDRLENBUF (1 << 3) | ||
| 147 | #define CFG9_PREAMB2 (0 << 4) | ||
| 148 | #define CFG9_PREAMB4 (1 << 4) | ||
| 149 | #define CFG9_PREAMB8 (2 << 4) | ||
| 150 | #define CFG9_PREAMB16 (3 << 4) | ||
| 151 | #define CFG9_ILOOPBACK (1 << 6) | ||
| 152 | #define CFG9_ELOOPBACK (1 << 7) | ||
| 153 | unsigned char cfg_byte10; | ||
| 154 | #define CFG10_LINPRI(x) (x) | ||
| 155 | #define CFG10_ACR(x) (x << 4) | ||
| 156 | #define CFG10_BOFMET (1 << 7) | ||
| 157 | unsigned char cfg_ifs; | ||
| 158 | unsigned char cfg_slotl; | ||
| 159 | unsigned char cfg_byte13; | ||
| 160 | #define CFG13_SLOTH(x) (x) | ||
| 161 | #define CFG13_RETRY(x) (x << 4) | ||
| 162 | unsigned char cfg_byte14; | ||
| 163 | #define CFG14_PROMISC (1 << 0) | ||
| 164 | #define CFG14_DISBRD (1 << 1) | ||
| 165 | #define CFG14_MANCH (1 << 2) | ||
| 166 | #define CFG14_TNCRS (1 << 3) | ||
| 167 | #define CFG14_NOCRC (1 << 4) | ||
| 168 | #define CFG14_CRC16 (1 << 5) | ||
| 169 | #define CFG14_BTSTF (1 << 6) | ||
| 170 | #define CFG14_FLGPAD (1 << 7) | ||
| 171 | unsigned char cfg_byte15; | ||
| 172 | #define CFG15_CSTF(x) (x) | ||
| 173 | #define CFG15_ICSS (1 << 3) | ||
| 174 | #define CFG15_CDTF(x) (x << 4) | ||
| 175 | #define CFG15_ICDS (1 << 7) | ||
| 176 | unsigned short cfg_minfrmlen; | ||
| 177 | } cfg_t; | ||
| 178 | |||
| 179 | typedef struct { /* scb */ | ||
| 180 | unsigned short scb_status; /* status of 82586 */ | ||
| 181 | #define SCB_STRXMASK (7 << 4) /* Receive unit status */ | ||
| 182 | #define SCB_STRXIDLE (0 << 4) /* Idle */ | ||
| 183 | #define SCB_STRXSUSP (1 << 4) /* Suspended */ | ||
| 184 | #define SCB_STRXNRES (2 << 4) /* No resources */ | ||
| 185 | #define SCB_STRXRDY (4 << 4) /* Ready */ | ||
| 186 | #define SCB_STCUMASK (7 << 8) /* Command unit status */ | ||
| 187 | #define SCB_STCUIDLE (0 << 8) /* Idle */ | ||
| 188 | #define SCB_STCUSUSP (1 << 8) /* Suspended */ | ||
| 189 | #define SCB_STCUACTV (2 << 8) /* Active */ | ||
| 190 | #define SCB_STRNR (1 << 12) /* Receive unit not ready */ | ||
| 191 | #define SCB_STCNA (1 << 13) /* Command unit not ready */ | ||
| 192 | #define SCB_STFR (1 << 14) /* Frame received */ | ||
| 193 | #define SCB_STCX (1 << 15) /* Command completed */ | ||
| 194 | unsigned short scb_command; /* Next command */ | ||
| 195 | #define SCB_CMDRXSTART (1 << 4) /* Start (at rfa_offset) */ | ||
| 196 | #define SCB_CMDRXRESUME (2 << 4) /* Resume reception */ | ||
| 197 | #define SCB_CMDRXSUSPEND (3 << 4) /* Suspend reception */ | ||
| 198 | #define SCB_CMDRXABORT (4 << 4) /* Abort reception */ | ||
| 199 | #define SCB_CMDCUCSTART (1 << 8) /* Start (at cbl_offset) */ | ||
| 200 | #define SCB_CMDCUCRESUME (2 << 8) /* Resume execution */ | ||
| 201 | #define SCB_CMDCUCSUSPEND (3 << 8) /* Suspend execution */ | ||
| 202 | #define SCB_CMDCUCABORT (4 << 8) /* Abort execution */ | ||
| 203 | #define SCB_CMDACKRNR (1 << 12) /* Ack RU not ready */ | ||
| 204 | #define SCB_CMDACKCNA (1 << 13) /* Ack CU not ready */ | ||
| 205 | #define SCB_CMDACKFR (1 << 14) /* Ack Frame received */ | ||
| 206 | #define SCB_CMDACKCX (1 << 15) /* Ack Command complete */ | ||
| 207 | unsigned short scb_cbl_offset; /* Offset of first command unit */ | ||
| 208 | unsigned short scb_rfa_offset; /* Offset of first receive frame area */ | ||
| 209 | unsigned short scb_crc_errors; /* Properly aligned frame with CRC error*/ | ||
| 210 | unsigned short scb_aln_errors; /* Misaligned frames */ | ||
| 211 | unsigned short scb_rsc_errors; /* Frames lost due to no space */ | ||
| 212 | unsigned short scb_ovn_errors; /* Frames lost due to slow bus */ | ||
| 213 | } scb_t; | ||
| 214 | |||
| 215 | typedef struct { /* iscp */ | ||
| 216 | unsigned short iscp_busy; /* set by CPU before CA */ | ||
| 217 | unsigned short iscp_offset; /* offset of SCB */ | ||
| 218 | unsigned short iscp_basel; /* base of SCB */ | ||
| 219 | unsigned short iscp_baseh; | ||
| 220 | } iscp_t; | ||
| 221 | |||
| 222 | /* this address must be 0xfff6 */ | ||
| 223 | typedef struct { /* scp */ | ||
| 224 | unsigned short scp_sysbus; /* bus size */ | ||
| 225 | #define SCP_SY_16BBUS 0x00 | ||
| 226 | #define SCP_SY_8BBUS 0x01 | ||
| 227 | unsigned short scp_junk[2]; /* junk */ | ||
| 228 | unsigned short scp_iscpl; /* lower 16 bits of iscp */ | ||
| 229 | unsigned short scp_iscph; /* upper 16 bits of iscp */ | ||
| 230 | } scp_t; | ||
| 231 | |||
| 232 | /* commands */ | ||
| 233 | #define CMD_NOP 0 | ||
| 234 | #define CMD_SETADDRESS 1 | ||
| 235 | #define CMD_CONFIG 2 | ||
| 236 | #define CMD_SETMULTICAST 3 | ||
| 237 | #define CMD_TX 4 | ||
| 238 | #define CMD_TDR 5 | ||
| 239 | #define CMD_DUMP 6 | ||
| 240 | #define CMD_DIAGNOSE 7 | ||
| 241 | |||
| 242 | #define CMD_MASK 7 | ||
| 243 | |||
| 244 | #define CMD_INTR (1 << 13) | ||
| 245 | #define CMD_SUSP (1 << 14) | ||
| 246 | #define CMD_EOL (1 << 15) | ||
| 247 | |||
| 248 | #define STAT_COLLISIONS (15) | ||
| 249 | #define STAT_COLLEXCESSIVE (1 << 5) | ||
| 250 | #define STAT_COLLAFTERTX (1 << 6) | ||
| 251 | #define STAT_TXDEFERRED (1 << 7) | ||
| 252 | #define STAT_TXSLOWDMA (1 << 8) | ||
| 253 | #define STAT_TXLOSTCTS (1 << 9) | ||
| 254 | #define STAT_NOCARRIER (1 << 10) | ||
| 255 | #define STAT_FAIL (1 << 11) | ||
| 256 | #define STAT_ABORTED (1 << 12) | ||
| 257 | #define STAT_OK (1 << 13) | ||
| 258 | #define STAT_BUSY (1 << 14) | ||
| 259 | #define STAT_COMPLETE (1 << 15) | ||
| 260 | #endif | ||
| 261 | #endif | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Ether1 card definitions: | ||
| 265 | * | ||
| 266 | * FAST accesses: | ||
| 267 | * +0 Page register | ||
| 268 | * 16 pages | ||
| 269 | * +4 Control | ||
| 270 | * '1' = reset | ||
| 271 | * '2' = loopback | ||
| 272 | * '4' = CA | ||
| 273 | * '8' = int ack | ||
| 274 | * | ||
| 275 | * RAM at address + 0x2000 | ||
| 276 | * Pod. Prod id = 3 | ||
| 277 | * Words after ID block [base + 8 words] | ||
| 278 | * +0 pcb issue (0x0c and 0xf3 invalid) | ||
| 279 | * +1 - +6 eth hw address | ||
| 280 | */ | ||
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c new file mode 100644 index 00000000000..44a8746f401 --- /dev/null +++ b/drivers/net/arm/ether3.c | |||
| @@ -0,0 +1,918 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/acorn/net/ether3.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995-2000 Russell King | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * SEEQ nq8005 ethernet driver for Acorn/ANT Ether3 card | ||
| 11 | * for Acorn machines | ||
| 12 | * | ||
| 13 | * By Russell King, with some suggestions from borris@ant.co.uk | ||
| 14 | * | ||
| 15 | * Changelog: | ||
| 16 | * 1.04 RMK 29/02/1996 Won't pass packets that are from our ethernet | ||
| 17 | * address up to the higher levels - they're | ||
| 18 | * silently ignored. I/F can now be put into | ||
| 19 | * multicast mode. Receiver routine optimised. | ||
| 20 | * 1.05 RMK 30/02/1996 Now claims interrupt at open when part of | ||
| 21 | * the kernel rather than when a module. | ||
| 22 | * 1.06 RMK 02/03/1996 Various code cleanups | ||
| 23 | * 1.07 RMK 13/10/1996 Optimised interrupt routine and transmit | ||
| 24 | * routines. | ||
| 25 | * 1.08 RMK 14/10/1996 Fixed problem with too many packets, | ||
| 26 | * prevented the kernel message about dropped | ||
| 27 | * packets appearing too many times a second. | ||
| 28 | * Now does not disable all IRQs, only the IRQ | ||
| 29 | * used by this card. | ||
| 30 | * 1.09 RMK 10/11/1996 Only enables TX irq when buffer space is low, | ||
| 31 | * but we still service the TX queue if we get a | ||
| 32 | * RX interrupt. | ||
| 33 | * 1.10 RMK 15/07/1997 Fixed autoprobing of NQ8004. | ||
| 34 | * 1.11 RMK 16/11/1997 Fixed autoprobing of NQ8005A. | ||
| 35 | * 1.12 RMK 31/12/1997 Removed reference to dev_tint for Linux 2.1. | ||
| 36 | * RMK 27/06/1998 Changed asm/delay.h to linux/delay.h. | ||
| 37 | * 1.13 RMK 29/06/1998 Fixed problem with transmission of packets. | ||
| 38 | * Chip seems to have a bug in, whereby if the | ||
| 39 | * packet starts two bytes from the end of the | ||
| 40 | * buffer, it corrupts the receiver chain, and | ||
| 41 | * never updates the transmit status correctly. | ||
| 42 | * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing. | ||
| 43 | * 1.15 RMK 30/04/1999 More fixes to the transmit routine for buggy | ||
| 44 | * hardware. | ||
| 45 | * 1.16 RMK 10/02/2000 Updated for 2.3.43 | ||
| 46 | * 1.17 RMK 13/05/2000 Updated for 2.3.99-pre8 | ||
| 47 | */ | ||
| 48 | |||
| 49 | #include <linux/module.h> | ||
| 50 | #include <linux/kernel.h> | ||
| 51 | #include <linux/types.h> | ||
| 52 | #include <linux/fcntl.h> | ||
| 53 | #include <linux/interrupt.h> | ||
| 54 | #include <linux/ioport.h> | ||
| 55 | #include <linux/in.h> | ||
| 56 | #include <linux/slab.h> | ||
| 57 | #include <linux/string.h> | ||
| 58 | #include <linux/errno.h> | ||
| 59 | #include <linux/netdevice.h> | ||
| 60 | #include <linux/etherdevice.h> | ||
| 61 | #include <linux/skbuff.h> | ||
| 62 | #include <linux/device.h> | ||
| 63 | #include <linux/init.h> | ||
| 64 | #include <linux/delay.h> | ||
| 65 | #include <linux/bitops.h> | ||
| 66 | |||
| 67 | #include <asm/system.h> | ||
| 68 | #include <asm/ecard.h> | ||
| 69 | #include <asm/io.h> | ||
| 70 | |||
| 71 | static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; | ||
| 72 | |||
| 73 | #include "ether3.h" | ||
| 74 | |||
| 75 | static unsigned int net_debug = NET_DEBUG; | ||
| 76 | |||
| 77 | static void ether3_setmulticastlist(struct net_device *dev); | ||
| 78 | static int ether3_rx(struct net_device *dev, unsigned int maxcnt); | ||
| 79 | static void ether3_tx(struct net_device *dev); | ||
| 80 | static int ether3_open (struct net_device *dev); | ||
| 81 | static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); | ||
| 82 | static irqreturn_t ether3_interrupt (int irq, void *dev_id); | ||
| 83 | static int ether3_close (struct net_device *dev); | ||
| 84 | static void ether3_setmulticastlist (struct net_device *dev); | ||
| 85 | static void ether3_timeout(struct net_device *dev); | ||
| 86 | |||
| 87 | #define BUS_16 2 | ||
| 88 | #define BUS_8 1 | ||
| 89 | #define BUS_UNKNOWN 0 | ||
| 90 | |||
| 91 | /* --------------------------------------------------------------------------- */ | ||
| 92 | |||
| 93 | typedef enum { | ||
| 94 | buffer_write, | ||
| 95 | buffer_read | ||
| 96 | } buffer_rw_t; | ||
| 97 | |||
| 98 | /* | ||
| 99 | * ether3 read/write. Slow things down a bit... | ||
| 100 | * The SEEQ8005 doesn't like us writing to its registers | ||
| 101 | * too quickly. | ||
| 102 | */ | ||
| 103 | static inline void ether3_outb(int v, const void __iomem *r) | ||
| 104 | { | ||
| 105 | writeb(v, r); | ||
| 106 | udelay(1); | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline void ether3_outw(int v, const void __iomem *r) | ||
| 110 | { | ||
| 111 | writew(v, r); | ||
| 112 | udelay(1); | ||
| 113 | } | ||
| 114 | #define ether3_inb(r) ({ unsigned int __v = readb((r)); udelay(1); __v; }) | ||
| 115 | #define ether3_inw(r) ({ unsigned int __v = readw((r)); udelay(1); __v; }) | ||
| 116 | |||
| 117 | static int | ||
| 118 | ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start) | ||
| 119 | { | ||
| 120 | int timeout = 1000; | ||
| 121 | |||
| 122 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
| 123 | ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND); | ||
| 124 | |||
| 125 | while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) { | ||
| 126 | if (!timeout--) { | ||
| 127 | printk("%s: setbuffer broken\n", dev->name); | ||
| 128 | priv(dev)->broken = 1; | ||
| 129 | return 1; | ||
| 130 | } | ||
| 131 | udelay(1); | ||
| 132 | } | ||
| 133 | |||
| 134 | if (read == buffer_read) { | ||
| 135 | ether3_outw(start, REG_DMAADDR); | ||
| 136 | ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND); | ||
| 137 | } else { | ||
| 138 | ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND); | ||
| 139 | ether3_outw(start, REG_DMAADDR); | ||
| 140 | } | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | /* | ||
| 145 | * write data to the buffer memory | ||
| 146 | */ | ||
| 147 | #define ether3_writebuffer(dev,data,length) \ | ||
| 148 | writesw(REG_BUFWIN, (data), (length) >> 1) | ||
| 149 | |||
| 150 | #define ether3_writeword(dev,data) \ | ||
| 151 | writew((data), REG_BUFWIN) | ||
| 152 | |||
| 153 | #define ether3_writelong(dev,data) { \ | ||
| 154 | void __iomem *reg_bufwin = REG_BUFWIN; \ | ||
| 155 | writew((data), reg_bufwin); \ | ||
| 156 | writew((data) >> 16, reg_bufwin); \ | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * read data from the buffer memory | ||
| 161 | */ | ||
| 162 | #define ether3_readbuffer(dev,data,length) \ | ||
| 163 | readsw(REG_BUFWIN, (data), (length) >> 1) | ||
| 164 | |||
| 165 | #define ether3_readword(dev) \ | ||
| 166 | readw(REG_BUFWIN) | ||
| 167 | |||
| 168 | #define ether3_readlong(dev) \ | ||
| 169 | readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16) | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Switch LED off... | ||
| 173 | */ | ||
| 174 | static void ether3_ledoff(unsigned long data) | ||
| 175 | { | ||
| 176 | struct net_device *dev = (struct net_device *)data; | ||
| 177 | ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2); | ||
| 178 | } | ||
| 179 | |||
| 180 | /* | ||
| 181 | * switch LED on... | ||
| 182 | */ | ||
| 183 | static inline void ether3_ledon(struct net_device *dev) | ||
| 184 | { | ||
| 185 | del_timer(&priv(dev)->timer); | ||
| 186 | priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */ | ||
| 187 | priv(dev)->timer.data = (unsigned long)dev; | ||
| 188 | priv(dev)->timer.function = ether3_ledoff; | ||
| 189 | add_timer(&priv(dev)->timer); | ||
| 190 | if (priv(dev)->regs.config2 & CFG2_CTRLO) | ||
| 191 | ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2); | ||
| 192 | } | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Read the ethernet address string from the on board rom. | ||
| 196 | * This is an ascii string!!! | ||
| 197 | */ | ||
| 198 | static int __devinit | ||
| 199 | ether3_addr(char *addr, struct expansion_card *ec) | ||
| 200 | { | ||
| 201 | struct in_chunk_dir cd; | ||
| 202 | char *s; | ||
| 203 | |||
| 204 | if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { | ||
| 205 | int i; | ||
| 206 | for (i = 0; i<6; i++) { | ||
| 207 | addr[i] = simple_strtoul(s + 1, &s, 0x10); | ||
| 208 | if (*s != (i==5?')' : ':' )) | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | if (i == 6) | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | /* I wonder if we should even let the user continue in this case | ||
| 215 | * - no, it would be better to disable the device | ||
| 216 | */ | ||
| 217 | printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n"); | ||
| 218 | return -ENODEV; | ||
| 219 | } | ||
| 220 | |||
| 221 | /* --------------------------------------------------------------------------- */ | ||
| 222 | |||
| 223 | static int __devinit | ||
| 224 | ether3_ramtest(struct net_device *dev, unsigned char byte) | ||
| 225 | { | ||
| 226 | unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); | ||
| 227 | int i,ret = 0; | ||
| 228 | int max_errors = 4; | ||
| 229 | int bad = -1; | ||
| 230 | |||
| 231 | if (!buffer) | ||
| 232 | return 1; | ||
| 233 | |||
| 234 | memset(buffer, byte, RX_END); | ||
| 235 | ether3_setbuffer(dev, buffer_write, 0); | ||
| 236 | ether3_writebuffer(dev, buffer, TX_END); | ||
| 237 | ether3_setbuffer(dev, buffer_write, RX_START); | ||
| 238 | ether3_writebuffer(dev, buffer + RX_START, RX_LEN); | ||
| 239 | memset(buffer, byte ^ 0xff, RX_END); | ||
| 240 | ether3_setbuffer(dev, buffer_read, 0); | ||
| 241 | ether3_readbuffer(dev, buffer, TX_END); | ||
| 242 | ether3_setbuffer(dev, buffer_read, RX_START); | ||
| 243 | ether3_readbuffer(dev, buffer + RX_START, RX_LEN); | ||
| 244 | |||
| 245 | for (i = 0; i < RX_END; i++) { | ||
| 246 | if (buffer[i] != byte) { | ||
| 247 | if (max_errors > 0 && bad != buffer[i]) { | ||
| 248 | printk("%s: RAM failed with (%02X instead of %02X) at 0x%04X", | ||
| 249 | dev->name, buffer[i], byte, i); | ||
| 250 | ret = 2; | ||
| 251 | max_errors--; | ||
| 252 | bad = i; | ||
| 253 | } | ||
| 254 | } else { | ||
| 255 | if (bad != -1) { | ||
| 256 | if (bad != i - 1) | ||
| 257 | printk(" - 0x%04X\n", i - 1); | ||
| 258 | printk("\n"); | ||
| 259 | bad = -1; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | } | ||
| 263 | if (bad != -1) | ||
| 264 | printk(" - 0xffff\n"); | ||
| 265 | kfree(buffer); | ||
| 266 | |||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | /* ------------------------------------------------------------------------------- */ | ||
| 271 | |||
| 272 | static int __devinit ether3_init_2(struct net_device *dev) | ||
| 273 | { | ||
| 274 | int i; | ||
| 275 | |||
| 276 | priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8; | ||
| 277 | priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC; | ||
| 278 | priv(dev)->regs.command = 0; | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Set up our hardware address | ||
| 282 | */ | ||
| 283 | ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); | ||
| 284 | for (i = 0; i < 6; i++) | ||
| 285 | ether3_outb(dev->dev_addr[i], REG_BUFWIN); | ||
| 286 | |||
| 287 | if (dev->flags & IFF_PROMISC) | ||
| 288 | priv(dev)->regs.config1 |= CFG1_RECVPROMISC; | ||
| 289 | else if (dev->flags & IFF_MULTICAST) | ||
| 290 | priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; | ||
| 291 | else | ||
| 292 | priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; | ||
| 293 | |||
| 294 | /* | ||
| 295 | * There is a problem with the NQ8005 in that it occasionally loses the | ||
| 296 | * last two bytes. To get round this problem, we receive the CRC as | ||
| 297 | * well. That way, if we do lose the last two, then it doesn't matter. | ||
| 298 | */ | ||
| 299 | ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); | ||
| 300 | ether3_outw((TX_END>>8) - 1, REG_BUFWIN); | ||
| 301 | ether3_outw(priv(dev)->rx_head, REG_RECVPTR); | ||
| 302 | ether3_outw(0, REG_TRANSMITPTR); | ||
| 303 | ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND); | ||
| 304 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
| 305 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
| 306 | ether3_outw(priv(dev)->regs.command, REG_COMMAND); | ||
| 307 | |||
| 308 | i = ether3_ramtest(dev, 0x5A); | ||
| 309 | if(i) | ||
| 310 | return i; | ||
| 311 | i = ether3_ramtest(dev, 0x1E); | ||
| 312 | if(i) | ||
| 313 | return i; | ||
| 314 | |||
| 315 | ether3_setbuffer(dev, buffer_write, 0); | ||
| 316 | ether3_writelong(dev, 0); | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static void | ||
| 321 | ether3_init_for_open(struct net_device *dev) | ||
| 322 | { | ||
| 323 | int i; | ||
| 324 | |||
| 325 | /* Reset the chip */ | ||
| 326 | ether3_outw(CFG2_RESET, REG_CONFIG2); | ||
| 327 | udelay(4); | ||
| 328 | |||
| 329 | priv(dev)->regs.command = 0; | ||
| 330 | ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); | ||
| 331 | while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)) | ||
| 332 | barrier(); | ||
| 333 | |||
| 334 | ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); | ||
| 335 | for (i = 0; i < 6; i++) | ||
| 336 | ether3_outb(dev->dev_addr[i], REG_BUFWIN); | ||
| 337 | |||
| 338 | priv(dev)->tx_head = 0; | ||
| 339 | priv(dev)->tx_tail = 0; | ||
| 340 | priv(dev)->regs.config2 |= CFG2_CTRLO; | ||
| 341 | priv(dev)->rx_head = RX_START; | ||
| 342 | |||
| 343 | ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); | ||
| 344 | ether3_outw((TX_END>>8) - 1, REG_BUFWIN); | ||
| 345 | ether3_outw(priv(dev)->rx_head, REG_RECVPTR); | ||
| 346 | ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND); | ||
| 347 | ether3_outw(0, REG_TRANSMITPTR); | ||
| 348 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
| 349 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
| 350 | |||
| 351 | ether3_setbuffer(dev, buffer_write, 0); | ||
| 352 | ether3_writelong(dev, 0); | ||
| 353 | |||
| 354 | priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX; | ||
| 355 | ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND); | ||
| 356 | } | ||
| 357 | |||
| 358 | static inline int | ||
| 359 | ether3_probe_bus_8(struct net_device *dev, int val) | ||
| 360 | { | ||
| 361 | int write_low, write_high, read_low, read_high; | ||
| 362 | |||
| 363 | write_low = val & 255; | ||
| 364 | write_high = val >> 8; | ||
| 365 | |||
| 366 | printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low); | ||
| 367 | |||
| 368 | ether3_outb(write_low, REG_RECVPTR); | ||
| 369 | ether3_outb(write_high, REG_RECVPTR + 4); | ||
| 370 | |||
| 371 | read_low = ether3_inb(REG_RECVPTR); | ||
| 372 | read_high = ether3_inb(REG_RECVPTR + 4); | ||
| 373 | |||
| 374 | printk(", read8 [%02X:%02X]\n", read_high, read_low); | ||
| 375 | |||
| 376 | return read_low == write_low && read_high == write_high; | ||
| 377 | } | ||
| 378 | |||
| 379 | static inline int | ||
| 380 | ether3_probe_bus_16(struct net_device *dev, int val) | ||
| 381 | { | ||
| 382 | int read_val; | ||
| 383 | |||
| 384 | ether3_outw(val, REG_RECVPTR); | ||
| 385 | read_val = ether3_inw(REG_RECVPTR); | ||
| 386 | |||
| 387 | printk(KERN_DEBUG "ether3_probe: write16 [%04X], read16 [%04X]\n", val, read_val); | ||
| 388 | |||
| 389 | return read_val == val; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* | ||
| 393 | * Open/initialize the board. This is called (in the current kernel) | ||
| 394 | * sometime after booting when the 'ifconfig' program is run. | ||
| 395 | * | ||
| 396 | * This routine should set everything up anew at each open, even | ||
| 397 | * registers that "should" only need to be set once at boot, so that | ||
| 398 | * there is non-reboot way to recover if something goes wrong. | ||
| 399 | */ | ||
| 400 | static int | ||
| 401 | ether3_open(struct net_device *dev) | ||
| 402 | { | ||
| 403 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
| 404 | printk(KERN_WARNING "%s: invalid ethernet MAC address\n", | ||
| 405 | dev->name); | ||
| 406 | return -EINVAL; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) | ||
| 410 | return -EAGAIN; | ||
| 411 | |||
| 412 | ether3_init_for_open(dev); | ||
| 413 | |||
| 414 | netif_start_queue(dev); | ||
| 415 | |||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | /* | ||
| 420 | * The inverse routine to ether3_open(). | ||
| 421 | */ | ||
| 422 | static int | ||
| 423 | ether3_close(struct net_device *dev) | ||
| 424 | { | ||
| 425 | netif_stop_queue(dev); | ||
| 426 | |||
| 427 | disable_irq(dev->irq); | ||
| 428 | |||
| 429 | ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); | ||
| 430 | priv(dev)->regs.command = 0; | ||
| 431 | while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)) | ||
| 432 | barrier(); | ||
| 433 | ether3_outb(0x80, REG_CONFIG2 + 4); | ||
| 434 | ether3_outw(0, REG_COMMAND); | ||
| 435 | |||
| 436 | free_irq(dev->irq, dev); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | /* | ||
| 442 | * Set or clear promiscuous/multicast mode filter for this adaptor. | ||
| 443 | * | ||
| 444 | * We don't attempt any packet filtering. The card may have a SEEQ 8004 | ||
| 445 | * in which does not have the other ethernet address registers present... | ||
| 446 | */ | ||
| 447 | static void ether3_setmulticastlist(struct net_device *dev) | ||
| 448 | { | ||
| 449 | priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC; | ||
| 450 | |||
| 451 | if (dev->flags & IFF_PROMISC) { | ||
| 452 | /* promiscuous mode */ | ||
| 453 | priv(dev)->regs.config1 |= CFG1_RECVPROMISC; | ||
| 454 | } else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { | ||
| 455 | priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; | ||
| 456 | } else | ||
| 457 | priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; | ||
| 458 | |||
| 459 | ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); | ||
| 460 | } | ||
| 461 | |||
| 462 | static void ether3_timeout(struct net_device *dev) | ||
| 463 | { | ||
| 464 | unsigned long flags; | ||
| 465 | |||
| 466 | del_timer(&priv(dev)->timer); | ||
| 467 | |||
| 468 | local_irq_save(flags); | ||
| 469 | printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name); | ||
| 470 | printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name, | ||
| 471 | ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2)); | ||
| 472 | printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name, | ||
| 473 | ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR)); | ||
| 474 | printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name, | ||
| 475 | priv(dev)->tx_head, priv(dev)->tx_tail); | ||
| 476 | ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail); | ||
| 477 | printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev)); | ||
| 478 | local_irq_restore(flags); | ||
| 479 | |||
| 480 | priv(dev)->regs.config2 |= CFG2_CTRLO; | ||
| 481 | dev->stats.tx_errors += 1; | ||
| 482 | ether3_outw(priv(dev)->regs.config2, REG_CONFIG2); | ||
| 483 | priv(dev)->tx_head = priv(dev)->tx_tail = 0; | ||
| 484 | |||
| 485 | netif_wake_queue(dev); | ||
| 486 | } | ||
| 487 | |||
| 488 | /* | ||
| 489 | * Transmit a packet | ||
| 490 | */ | ||
| 491 | static int | ||
| 492 | ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) | ||
| 493 | { | ||
| 494 | unsigned long flags; | ||
| 495 | unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
| 496 | unsigned int ptr, next_ptr; | ||
| 497 | |||
| 498 | if (priv(dev)->broken) { | ||
| 499 | dev_kfree_skb(skb); | ||
| 500 | dev->stats.tx_dropped++; | ||
| 501 | netif_start_queue(dev); | ||
| 502 | return NETDEV_TX_OK; | ||
| 503 | } | ||
| 504 | |||
| 505 | length = (length + 1) & ~1; | ||
| 506 | if (length != skb->len) { | ||
| 507 | if (skb_padto(skb, length)) | ||
| 508 | goto out; | ||
| 509 | } | ||
| 510 | |||
| 511 | next_ptr = (priv(dev)->tx_head + 1) & 15; | ||
| 512 | |||
| 513 | local_irq_save(flags); | ||
| 514 | |||
| 515 | if (priv(dev)->tx_tail == next_ptr) { | ||
| 516 | local_irq_restore(flags); | ||
| 517 | return NETDEV_TX_BUSY; /* unable to queue */ | ||
| 518 | } | ||
| 519 | |||
| 520 | ptr = 0x600 * priv(dev)->tx_head; | ||
| 521 | priv(dev)->tx_head = next_ptr; | ||
| 522 | next_ptr *= 0x600; | ||
| 523 | |||
| 524 | #define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS) | ||
| 525 | |||
| 526 | ether3_setbuffer(dev, buffer_write, next_ptr); | ||
| 527 | ether3_writelong(dev, 0); | ||
| 528 | ether3_setbuffer(dev, buffer_write, ptr); | ||
| 529 | ether3_writelong(dev, 0); | ||
| 530 | ether3_writebuffer(dev, skb->data, length); | ||
| 531 | ether3_writeword(dev, htons(next_ptr)); | ||
| 532 | ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16); | ||
| 533 | ether3_setbuffer(dev, buffer_write, ptr); | ||
| 534 | ether3_writeword(dev, htons((ptr + length + 4))); | ||
| 535 | ether3_writeword(dev, TXHDR_FLAGS >> 16); | ||
| 536 | ether3_ledon(dev); | ||
| 537 | |||
| 538 | if (!(ether3_inw(REG_STATUS) & STAT_TXON)) { | ||
| 539 | ether3_outw(ptr, REG_TRANSMITPTR); | ||
| 540 | ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND); | ||
| 541 | } | ||
| 542 | |||
| 543 | next_ptr = (priv(dev)->tx_head + 1) & 15; | ||
| 544 | local_irq_restore(flags); | ||
| 545 | |||
| 546 | dev_kfree_skb(skb); | ||
| 547 | |||
| 548 | if (priv(dev)->tx_tail == next_ptr) | ||
| 549 | netif_stop_queue(dev); | ||
| 550 | |||
| 551 | out: | ||
| 552 | return NETDEV_TX_OK; | ||
| 553 | } | ||
| 554 | |||
| 555 | static irqreturn_t | ||
| 556 | ether3_interrupt(int irq, void *dev_id) | ||
| 557 | { | ||
| 558 | struct net_device *dev = (struct net_device *)dev_id; | ||
| 559 | unsigned int status, handled = IRQ_NONE; | ||
| 560 | |||
| 561 | #if NET_DEBUG > 1 | ||
| 562 | if(net_debug & DEBUG_INT) | ||
| 563 | printk("eth3irq: %d ", irq); | ||
| 564 | #endif | ||
| 565 | |||
| 566 | status = ether3_inw(REG_STATUS); | ||
| 567 | |||
| 568 | if (status & STAT_INTRX) { | ||
| 569 | ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND); | ||
| 570 | ether3_rx(dev, 12); | ||
| 571 | handled = IRQ_HANDLED; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (status & STAT_INTTX) { | ||
| 575 | ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND); | ||
| 576 | ether3_tx(dev); | ||
| 577 | handled = IRQ_HANDLED; | ||
| 578 | } | ||
| 579 | |||
| 580 | #if NET_DEBUG > 1 | ||
| 581 | if(net_debug & DEBUG_INT) | ||
| 582 | printk("done\n"); | ||
| 583 | #endif | ||
| 584 | return handled; | ||
| 585 | } | ||
| 586 | |||
| 587 | /* | ||
| 588 | * If we have a good packet(s), get it/them out of the buffers. | ||
| 589 | */ | ||
| 590 | static int ether3_rx(struct net_device *dev, unsigned int maxcnt) | ||
| 591 | { | ||
| 592 | unsigned int next_ptr = priv(dev)->rx_head, received = 0; | ||
| 593 | |||
| 594 | ether3_ledon(dev); | ||
| 595 | |||
| 596 | do { | ||
| 597 | unsigned int this_ptr, status; | ||
| 598 | unsigned char addrs[16]; | ||
| 599 | |||
| 600 | /* | ||
| 601 | * read the first 16 bytes from the buffer. | ||
| 602 | * This contains the status bytes etc and ethernet addresses, | ||
| 603 | * and we also check the source ethernet address to see if | ||
| 604 | * it originated from us. | ||
| 605 | */ | ||
| 606 | { | ||
| 607 | unsigned int temp_ptr; | ||
| 608 | ether3_setbuffer(dev, buffer_read, next_ptr); | ||
| 609 | temp_ptr = ether3_readword(dev); | ||
| 610 | status = ether3_readword(dev); | ||
| 611 | if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) != | ||
| 612 | (RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr) | ||
| 613 | break; | ||
| 614 | |||
| 615 | this_ptr = next_ptr + 4; | ||
| 616 | next_ptr = ntohs(temp_ptr); | ||
| 617 | } | ||
| 618 | ether3_setbuffer(dev, buffer_read, this_ptr); | ||
| 619 | ether3_readbuffer(dev, addrs+2, 12); | ||
| 620 | |||
| 621 | if (next_ptr < RX_START || next_ptr >= RX_END) { | ||
| 622 | int i; | ||
| 623 | printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head); | ||
| 624 | printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8); | ||
| 625 | for (i = 2; i < 14; i++) | ||
| 626 | printk("%02X ", addrs[i]); | ||
| 627 | printk("\n"); | ||
| 628 | next_ptr = priv(dev)->rx_head; | ||
| 629 | break; | ||
| 630 | } | ||
| 631 | /* | ||
| 632 | * ignore our own packets... | ||
| 633 | */ | ||
| 634 | if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) && | ||
| 635 | !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) { | ||
| 636 | maxcnt ++; /* compensate for loopedback packet */ | ||
| 637 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
| 638 | } else | ||
| 639 | if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) { | ||
| 640 | unsigned int length = next_ptr - this_ptr; | ||
| 641 | struct sk_buff *skb; | ||
| 642 | |||
| 643 | if (next_ptr <= this_ptr) | ||
| 644 | length += RX_END - RX_START; | ||
| 645 | |||
| 646 | skb = dev_alloc_skb(length + 2); | ||
| 647 | if (skb) { | ||
| 648 | unsigned char *buf; | ||
| 649 | |||
| 650 | skb_reserve(skb, 2); | ||
| 651 | buf = skb_put(skb, length); | ||
| 652 | ether3_readbuffer(dev, buf + 12, length - 12); | ||
| 653 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
| 654 | *(unsigned short *)(buf + 0) = *(unsigned short *)(addrs + 2); | ||
| 655 | *(unsigned long *)(buf + 2) = *(unsigned long *)(addrs + 4); | ||
| 656 | *(unsigned long *)(buf + 6) = *(unsigned long *)(addrs + 8); | ||
| 657 | *(unsigned short *)(buf + 10) = *(unsigned short *)(addrs + 12); | ||
| 658 | skb->protocol = eth_type_trans(skb, dev); | ||
| 659 | netif_rx(skb); | ||
| 660 | received ++; | ||
| 661 | } else | ||
| 662 | goto dropping; | ||
| 663 | } else { | ||
| 664 | struct net_device_stats *stats = &dev->stats; | ||
| 665 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
| 666 | if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++; | ||
| 667 | if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++; | ||
| 668 | if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++; | ||
| 669 | if (status & RXSTAT_SHORTPACKET) stats->rx_length_errors ++; | ||
| 670 | stats->rx_errors++; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | while (-- maxcnt); | ||
| 674 | |||
| 675 | done: | ||
| 676 | dev->stats.rx_packets += received; | ||
| 677 | priv(dev)->rx_head = next_ptr; | ||
| 678 | /* | ||
| 679 | * If rx went off line, then that means that the buffer may be full. We | ||
| 680 | * have dropped at least one packet. | ||
| 681 | */ | ||
| 682 | if (!(ether3_inw(REG_STATUS) & STAT_RXON)) { | ||
| 683 | dev->stats.rx_dropped++; | ||
| 684 | ether3_outw(next_ptr, REG_RECVPTR); | ||
| 685 | ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND); | ||
| 686 | } | ||
| 687 | |||
| 688 | return maxcnt; | ||
| 689 | |||
| 690 | dropping:{ | ||
| 691 | static unsigned long last_warned; | ||
| 692 | |||
| 693 | ether3_outw(next_ptr >> 8, REG_RECVEND); | ||
| 694 | /* | ||
| 695 | * Don't print this message too many times... | ||
| 696 | */ | ||
| 697 | if (time_after(jiffies, last_warned + 10 * HZ)) { | ||
| 698 | last_warned = jiffies; | ||
| 699 | printk("%s: memory squeeze, dropping packet.\n", dev->name); | ||
| 700 | } | ||
| 701 | dev->stats.rx_dropped++; | ||
| 702 | goto done; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Update stats for the transmitted packet(s) | ||
| 708 | */ | ||
| 709 | static void ether3_tx(struct net_device *dev) | ||
| 710 | { | ||
| 711 | unsigned int tx_tail = priv(dev)->tx_tail; | ||
| 712 | int max_work = 14; | ||
| 713 | |||
| 714 | do { | ||
| 715 | unsigned long status; | ||
| 716 | |||
| 717 | /* | ||
| 718 | * Read the packet header | ||
| 719 | */ | ||
| 720 | ether3_setbuffer(dev, buffer_read, tx_tail * 0x600); | ||
| 721 | status = ether3_readlong(dev); | ||
| 722 | |||
| 723 | /* | ||
| 724 | * Check to see if this packet has been transmitted | ||
| 725 | */ | ||
| 726 | if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) != | ||
| 727 | (TXSTAT_DONE | TXHDR_TRANSMIT)) | ||
| 728 | break; | ||
| 729 | |||
| 730 | /* | ||
| 731 | * Update errors | ||
| 732 | */ | ||
| 733 | if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS))) | ||
| 734 | dev->stats.tx_packets++; | ||
| 735 | else { | ||
| 736 | dev->stats.tx_errors++; | ||
| 737 | if (status & TXSTAT_16COLLISIONS) | ||
| 738 | dev->stats.collisions += 16; | ||
| 739 | if (status & TXSTAT_BABBLED) | ||
| 740 | dev->stats.tx_fifo_errors++; | ||
| 741 | } | ||
| 742 | |||
| 743 | tx_tail = (tx_tail + 1) & 15; | ||
| 744 | } while (--max_work); | ||
| 745 | |||
| 746 | if (priv(dev)->tx_tail != tx_tail) { | ||
| 747 | priv(dev)->tx_tail = tx_tail; | ||
| 748 | netif_wake_queue(dev); | ||
| 749 | } | ||
| 750 | } | ||
| 751 | |||
| 752 | static void __devinit ether3_banner(void) | ||
| 753 | { | ||
| 754 | static unsigned version_printed = 0; | ||
| 755 | |||
| 756 | if (net_debug && version_printed++ == 0) | ||
| 757 | printk(KERN_INFO "%s", version); | ||
| 758 | } | ||
| 759 | |||
| 760 | static const struct net_device_ops ether3_netdev_ops = { | ||
| 761 | .ndo_open = ether3_open, | ||
| 762 | .ndo_stop = ether3_close, | ||
| 763 | .ndo_start_xmit = ether3_sendpacket, | ||
| 764 | .ndo_set_multicast_list = ether3_setmulticastlist, | ||
| 765 | .ndo_tx_timeout = ether3_timeout, | ||
| 766 | .ndo_validate_addr = eth_validate_addr, | ||
| 767 | .ndo_change_mtu = eth_change_mtu, | ||
| 768 | .ndo_set_mac_address = eth_mac_addr, | ||
| 769 | }; | ||
| 770 | |||
| 771 | static int __devinit | ||
| 772 | ether3_probe(struct expansion_card *ec, const struct ecard_id *id) | ||
| 773 | { | ||
| 774 | const struct ether3_data *data = id->data; | ||
| 775 | struct net_device *dev; | ||
| 776 | int bus_type, ret; | ||
| 777 | |||
| 778 | ether3_banner(); | ||
| 779 | |||
| 780 | ret = ecard_request_resources(ec); | ||
| 781 | if (ret) | ||
| 782 | goto out; | ||
| 783 | |||
| 784 | dev = alloc_etherdev(sizeof(struct dev_priv)); | ||
| 785 | if (!dev) { | ||
| 786 | ret = -ENOMEM; | ||
| 787 | goto release; | ||
| 788 | } | ||
| 789 | |||
| 790 | SET_NETDEV_DEV(dev, &ec->dev); | ||
| 791 | |||
| 792 | priv(dev)->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); | ||
| 793 | if (!priv(dev)->base) { | ||
| 794 | ret = -ENOMEM; | ||
| 795 | goto free; | ||
| 796 | } | ||
| 797 | |||
| 798 | ec->irqaddr = priv(dev)->base + data->base_offset; | ||
| 799 | ec->irqmask = 0xf0; | ||
| 800 | |||
| 801 | priv(dev)->seeq = priv(dev)->base + data->base_offset; | ||
| 802 | dev->irq = ec->irq; | ||
| 803 | |||
| 804 | ether3_addr(dev->dev_addr, ec); | ||
| 805 | |||
| 806 | init_timer(&priv(dev)->timer); | ||
| 807 | |||
| 808 | /* Reset card... | ||
| 809 | */ | ||
| 810 | ether3_outb(0x80, REG_CONFIG2 + 4); | ||
| 811 | bus_type = BUS_UNKNOWN; | ||
| 812 | udelay(4); | ||
| 813 | |||
| 814 | /* Test using Receive Pointer (16-bit register) to find out | ||
| 815 | * how the ether3 is connected to the bus... | ||
| 816 | */ | ||
| 817 | if (ether3_probe_bus_8(dev, 0x100) && | ||
| 818 | ether3_probe_bus_8(dev, 0x201)) | ||
| 819 | bus_type = BUS_8; | ||
| 820 | |||
| 821 | if (bus_type == BUS_UNKNOWN && | ||
| 822 | ether3_probe_bus_16(dev, 0x101) && | ||
| 823 | ether3_probe_bus_16(dev, 0x201)) | ||
| 824 | bus_type = BUS_16; | ||
| 825 | |||
| 826 | switch (bus_type) { | ||
| 827 | case BUS_UNKNOWN: | ||
| 828 | printk(KERN_ERR "%s: unable to identify bus width\n", dev->name); | ||
| 829 | ret = -ENODEV; | ||
| 830 | goto free; | ||
| 831 | |||
| 832 | case BUS_8: | ||
| 833 | printk(KERN_ERR "%s: %s found, but is an unsupported " | ||
| 834 | "8-bit card\n", dev->name, data->name); | ||
| 835 | ret = -ENODEV; | ||
| 836 | goto free; | ||
| 837 | |||
| 838 | default: | ||
| 839 | break; | ||
| 840 | } | ||
| 841 | |||
| 842 | if (ether3_init_2(dev)) { | ||
| 843 | ret = -ENODEV; | ||
| 844 | goto free; | ||
| 845 | } | ||
| 846 | |||
| 847 | dev->netdev_ops = ðer3_netdev_ops; | ||
| 848 | dev->watchdog_timeo = 5 * HZ / 100; | ||
| 849 | |||
| 850 | ret = register_netdev(dev); | ||
| 851 | if (ret) | ||
| 852 | goto free; | ||
| 853 | |||
| 854 | printk("%s: %s in slot %d, %pM\n", | ||
| 855 | dev->name, data->name, ec->slot_no, dev->dev_addr); | ||
| 856 | |||
| 857 | ecard_set_drvdata(ec, dev); | ||
| 858 | return 0; | ||
| 859 | |||
| 860 | free: | ||
| 861 | free_netdev(dev); | ||
| 862 | release: | ||
| 863 | ecard_release_resources(ec); | ||
| 864 | out: | ||
| 865 | return ret; | ||
| 866 | } | ||
| 867 | |||
| 868 | static void __devexit ether3_remove(struct expansion_card *ec) | ||
| 869 | { | ||
| 870 | struct net_device *dev = ecard_get_drvdata(ec); | ||
| 871 | |||
| 872 | ecard_set_drvdata(ec, NULL); | ||
| 873 | |||
| 874 | unregister_netdev(dev); | ||
| 875 | free_netdev(dev); | ||
| 876 | ecard_release_resources(ec); | ||
| 877 | } | ||
| 878 | |||
| 879 | static struct ether3_data ether3 = { | ||
| 880 | .name = "ether3", | ||
| 881 | .base_offset = 0, | ||
| 882 | }; | ||
| 883 | |||
| 884 | static struct ether3_data etherb = { | ||
| 885 | .name = "etherb", | ||
| 886 | .base_offset = 0x800, | ||
| 887 | }; | ||
| 888 | |||
| 889 | static const struct ecard_id ether3_ids[] = { | ||
| 890 | { MANU_ANT2, PROD_ANT_ETHER3, ðer3 }, | ||
| 891 | { MANU_ANT, PROD_ANT_ETHER3, ðer3 }, | ||
| 892 | { MANU_ANT, PROD_ANT_ETHERB, ðerb }, | ||
| 893 | { 0xffff, 0xffff } | ||
| 894 | }; | ||
| 895 | |||
| 896 | static struct ecard_driver ether3_driver = { | ||
| 897 | .probe = ether3_probe, | ||
| 898 | .remove = __devexit_p(ether3_remove), | ||
| 899 | .id_table = ether3_ids, | ||
| 900 | .drv = { | ||
| 901 | .name = "ether3", | ||
| 902 | }, | ||
| 903 | }; | ||
| 904 | |||
| 905 | static int __init ether3_init(void) | ||
| 906 | { | ||
| 907 | return ecard_register_driver(ðer3_driver); | ||
| 908 | } | ||
| 909 | |||
| 910 | static void __exit ether3_exit(void) | ||
| 911 | { | ||
| 912 | ecard_remove_driver(ðer3_driver); | ||
| 913 | } | ||
| 914 | |||
| 915 | module_init(ether3_init); | ||
| 916 | module_exit(ether3_exit); | ||
| 917 | |||
| 918 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h new file mode 100644 index 00000000000..2db63b08bdf --- /dev/null +++ b/drivers/net/arm/ether3.h | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/acorn/net/ether3.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995-2000 Russell King | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * network driver for Acorn/ANT Ether3 cards | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _LINUX_ether3_H | ||
| 14 | #define _LINUX_ether3_H | ||
| 15 | |||
| 16 | /* use 0 for production, 1 for verification, >2 for debug. debug flags: */ | ||
| 17 | #define DEBUG_TX 2 | ||
| 18 | #define DEBUG_RX 4 | ||
| 19 | #define DEBUG_INT 8 | ||
| 20 | #define DEBUG_IC 16 | ||
| 21 | #ifndef NET_DEBUG | ||
| 22 | #define NET_DEBUG 0 | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #define priv(dev) ((struct dev_priv *)netdev_priv(dev)) | ||
| 26 | |||
| 27 | /* Command register definitions & bits */ | ||
| 28 | #define REG_COMMAND (priv(dev)->seeq + 0x0000) | ||
| 29 | #define CMD_ENINTDMA 0x0001 | ||
| 30 | #define CMD_ENINTRX 0x0002 | ||
| 31 | #define CMD_ENINTTX 0x0004 | ||
| 32 | #define CMD_ENINTBUFWIN 0x0008 | ||
| 33 | #define CMD_ACKINTDMA 0x0010 | ||
| 34 | #define CMD_ACKINTRX 0x0020 | ||
| 35 | #define CMD_ACKINTTX 0x0040 | ||
| 36 | #define CMD_ACKINTBUFWIN 0x0080 | ||
| 37 | #define CMD_DMAON 0x0100 | ||
| 38 | #define CMD_RXON 0x0200 | ||
| 39 | #define CMD_TXON 0x0400 | ||
| 40 | #define CMD_DMAOFF 0x0800 | ||
| 41 | #define CMD_RXOFF 0x1000 | ||
| 42 | #define CMD_TXOFF 0x2000 | ||
| 43 | #define CMD_FIFOREAD 0x4000 | ||
| 44 | #define CMD_FIFOWRITE 0x8000 | ||
| 45 | |||
| 46 | /* status register */ | ||
| 47 | #define REG_STATUS (priv(dev)->seeq + 0x0000) | ||
| 48 | #define STAT_ENINTSTAT 0x0001 | ||
| 49 | #define STAT_ENINTRX 0x0002 | ||
| 50 | #define STAT_ENINTTX 0x0004 | ||
| 51 | #define STAT_ENINTBUFWIN 0x0008 | ||
| 52 | #define STAT_INTDMA 0x0010 | ||
| 53 | #define STAT_INTRX 0x0020 | ||
| 54 | #define STAT_INTTX 0x0040 | ||
| 55 | #define STAT_INTBUFWIN 0x0080 | ||
| 56 | #define STAT_DMAON 0x0100 | ||
| 57 | #define STAT_RXON 0x0200 | ||
| 58 | #define STAT_TXON 0x0400 | ||
| 59 | #define STAT_FIFOFULL 0x2000 | ||
| 60 | #define STAT_FIFOEMPTY 0x4000 | ||
| 61 | #define STAT_FIFODIR 0x8000 | ||
| 62 | |||
| 63 | /* configuration register 1 */ | ||
| 64 | #define REG_CONFIG1 (priv(dev)->seeq + 0x0040) | ||
| 65 | #define CFG1_BUFSELSTAT0 0x0000 | ||
| 66 | #define CFG1_BUFSELSTAT1 0x0001 | ||
| 67 | #define CFG1_BUFSELSTAT2 0x0002 | ||
| 68 | #define CFG1_BUFSELSTAT3 0x0003 | ||
| 69 | #define CFG1_BUFSELSTAT4 0x0004 | ||
| 70 | #define CFG1_BUFSELSTAT5 0x0005 | ||
| 71 | #define CFG1_ADDRPROM 0x0006 | ||
| 72 | #define CFG1_TRANSEND 0x0007 | ||
| 73 | #define CFG1_LOCBUFMEM 0x0008 | ||
| 74 | #define CFG1_INTVECTOR 0x0009 | ||
| 75 | #define CFG1_RECVSPECONLY 0x0000 | ||
| 76 | #define CFG1_RECVSPECBROAD 0x4000 | ||
| 77 | #define CFG1_RECVSPECBRMULTI 0x8000 | ||
| 78 | #define CFG1_RECVPROMISC 0xC000 | ||
| 79 | |||
| 80 | /* The following aren't in 8004 */ | ||
| 81 | #define CFG1_DMABURSTCONT 0x0000 | ||
| 82 | #define CFG1_DMABURST800NS 0x0010 | ||
| 83 | #define CFG1_DMABURST1600NS 0x0020 | ||
| 84 | #define CFG1_DMABURST3200NS 0x0030 | ||
| 85 | #define CFG1_DMABURST1 0x0000 | ||
| 86 | #define CFG1_DMABURST4 0x0040 | ||
| 87 | #define CFG1_DMABURST8 0x0080 | ||
| 88 | #define CFG1_DMABURST16 0x00C0 | ||
| 89 | #define CFG1_RECVCOMPSTAT0 0x0100 | ||
| 90 | #define CFG1_RECVCOMPSTAT1 0x0200 | ||
| 91 | #define CFG1_RECVCOMPSTAT2 0x0400 | ||
| 92 | #define CFG1_RECVCOMPSTAT3 0x0800 | ||
| 93 | #define CFG1_RECVCOMPSTAT4 0x1000 | ||
| 94 | #define CFG1_RECVCOMPSTAT5 0x2000 | ||
| 95 | |||
| 96 | /* configuration register 2 */ | ||
| 97 | #define REG_CONFIG2 (priv(dev)->seeq + 0x0080) | ||
| 98 | #define CFG2_BYTESWAP 0x0001 | ||
| 99 | #define CFG2_ERRENCRC 0x0008 | ||
| 100 | #define CFG2_ERRENDRIBBLE 0x0010 | ||
| 101 | #define CFG2_ERRSHORTFRAME 0x0020 | ||
| 102 | #define CFG2_SLOTSELECT 0x0040 | ||
| 103 | #define CFG2_PREAMSELECT 0x0080 | ||
| 104 | #define CFG2_ADDRLENGTH 0x0100 | ||
| 105 | #define CFG2_RECVCRC 0x0200 | ||
| 106 | #define CFG2_XMITNOCRC 0x0400 | ||
| 107 | #define CFG2_LOOPBACK 0x0800 | ||
| 108 | #define CFG2_CTRLO 0x1000 | ||
| 109 | #define CFG2_RESET 0x8000 | ||
| 110 | |||
| 111 | #define REG_RECVEND (priv(dev)->seeq + 0x00c0) | ||
| 112 | |||
| 113 | #define REG_BUFWIN (priv(dev)->seeq + 0x0100) | ||
| 114 | |||
| 115 | #define REG_RECVPTR (priv(dev)->seeq + 0x0140) | ||
| 116 | |||
| 117 | #define REG_TRANSMITPTR (priv(dev)->seeq + 0x0180) | ||
| 118 | |||
| 119 | #define REG_DMAADDR (priv(dev)->seeq + 0x01c0) | ||
| 120 | |||
| 121 | /* | ||
| 122 | * Cards transmit/receive headers | ||
| 123 | */ | ||
| 124 | #define TX_NEXT (0xffff) | ||
| 125 | #define TXHDR_ENBABBLEINT (1 << 16) | ||
| 126 | #define TXHDR_ENCOLLISIONINT (1 << 17) | ||
| 127 | #define TXHDR_EN16COLLISION (1 << 18) | ||
| 128 | #define TXHDR_ENSUCCESS (1 << 19) | ||
| 129 | #define TXHDR_DATAFOLLOWS (1 << 21) | ||
| 130 | #define TXHDR_CHAINCONTINUE (1 << 22) | ||
| 131 | #define TXHDR_TRANSMIT (1 << 23) | ||
| 132 | #define TXSTAT_BABBLED (1 << 24) | ||
| 133 | #define TXSTAT_COLLISION (1 << 25) | ||
| 134 | #define TXSTAT_16COLLISIONS (1 << 26) | ||
| 135 | #define TXSTAT_DONE (1 << 31) | ||
| 136 | |||
| 137 | #define RX_NEXT (0xffff) | ||
| 138 | #define RXHDR_CHAINCONTINUE (1 << 6) | ||
| 139 | #define RXHDR_RECEIVE (1 << 7) | ||
| 140 | #define RXSTAT_OVERSIZE (1 << 8) | ||
| 141 | #define RXSTAT_CRCERROR (1 << 9) | ||
| 142 | #define RXSTAT_DRIBBLEERROR (1 << 10) | ||
| 143 | #define RXSTAT_SHORTPACKET (1 << 11) | ||
| 144 | #define RXSTAT_DONE (1 << 15) | ||
| 145 | |||
| 146 | |||
| 147 | #define TX_START 0x0000 | ||
| 148 | #define TX_END 0x6000 | ||
| 149 | #define RX_START 0x6000 | ||
| 150 | #define RX_LEN 0xA000 | ||
| 151 | #define RX_END 0x10000 | ||
| 152 | /* must be a power of 2 and greater than MAX_TX_BUFFERED */ | ||
| 153 | #define MAX_TXED 16 | ||
| 154 | #define MAX_TX_BUFFERED 10 | ||
| 155 | |||
| 156 | struct dev_priv { | ||
| 157 | void __iomem *base; | ||
| 158 | void __iomem *seeq; | ||
| 159 | struct { | ||
| 160 | unsigned int command; | ||
| 161 | unsigned int config1; | ||
| 162 | unsigned int config2; | ||
| 163 | } regs; | ||
| 164 | unsigned char tx_head; /* buffer nr to insert next packet */ | ||
| 165 | unsigned char tx_tail; /* buffer nr of transmitting packet */ | ||
| 166 | unsigned int rx_head; /* address to fetch next packet from */ | ||
| 167 | struct timer_list timer; | ||
| 168 | int broken; /* 0 = ok, 1 = something went wrong */ | ||
| 169 | }; | ||
| 170 | |||
| 171 | struct ether3_data { | ||
| 172 | const char name[8]; | ||
| 173 | unsigned long base_offset; | ||
| 174 | }; | ||
| 175 | |||
| 176 | #endif | ||
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c new file mode 100644 index 00000000000..03e217a868d --- /dev/null +++ b/drivers/net/arm/etherh.c | |||
| @@ -0,0 +1,866 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/acorn/net/etherh.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2002 Russell King | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * NS8390 I-cubed EtherH and ANT EtherM specific driver | ||
| 11 | * Thanks to I-Cubed for information on their cards. | ||
| 12 | * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton | ||
| 13 | * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan) | ||
| 14 | * EtherM integration re-engineered by Russell King. | ||
| 15 | * | ||
| 16 | * Changelog: | ||
| 17 | * 08-12-1996 RMK 1.00 Created | ||
| 18 | * RMK 1.03 Added support for EtherLan500 cards | ||
| 19 | * 23-11-1997 RMK 1.04 Added media autodetection | ||
| 20 | * 16-04-1998 RMK 1.05 Improved media autodetection | ||
| 21 | * 10-02-2000 RMK 1.06 Updated for 2.3.43 | ||
| 22 | * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8 | ||
| 23 | * 12-10-1999 CK/TEW EtherM driver first release | ||
| 24 | * 21-12-2000 TTC EtherH/EtherM integration | ||
| 25 | * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. | ||
| 26 | * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/kernel.h> | ||
| 31 | #include <linux/types.h> | ||
| 32 | #include <linux/fcntl.h> | ||
| 33 | #include <linux/interrupt.h> | ||
| 34 | #include <linux/ioport.h> | ||
| 35 | #include <linux/in.h> | ||
| 36 | #include <linux/string.h> | ||
| 37 | #include <linux/errno.h> | ||
| 38 | #include <linux/netdevice.h> | ||
| 39 | #include <linux/etherdevice.h> | ||
| 40 | #include <linux/ethtool.h> | ||
| 41 | #include <linux/skbuff.h> | ||
| 42 | #include <linux/delay.h> | ||
| 43 | #include <linux/device.h> | ||
| 44 | #include <linux/init.h> | ||
| 45 | #include <linux/bitops.h> | ||
| 46 | #include <linux/jiffies.h> | ||
| 47 | |||
| 48 | #include <asm/system.h> | ||
| 49 | #include <asm/ecard.h> | ||
| 50 | #include <asm/io.h> | ||
| 51 | |||
| 52 | #define EI_SHIFT(x) (ei_local->reg_offset[x]) | ||
| 53 | |||
| 54 | #define ei_inb(_p) readb((void __iomem *)_p) | ||
| 55 | #define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p) | ||
| 56 | #define ei_inb_p(_p) readb((void __iomem *)_p) | ||
| 57 | #define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p) | ||
| 58 | |||
| 59 | #define NET_DEBUG 0 | ||
| 60 | #define DEBUG_INIT 2 | ||
| 61 | |||
| 62 | #define DRV_NAME "etherh" | ||
| 63 | #define DRV_VERSION "1.11" | ||
| 64 | |||
| 65 | static char version[] __initdata = | ||
| 66 | "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; | ||
| 67 | |||
| 68 | #include "../lib8390.c" | ||
| 69 | |||
| 70 | static unsigned int net_debug = NET_DEBUG; | ||
| 71 | |||
| 72 | struct etherh_priv { | ||
| 73 | void __iomem *ioc_fast; | ||
| 74 | void __iomem *memc; | ||
| 75 | void __iomem *dma_base; | ||
| 76 | unsigned int id; | ||
| 77 | void __iomem *ctrl_port; | ||
| 78 | unsigned char ctrl; | ||
| 79 | u32 supported; | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct etherh_data { | ||
| 83 | unsigned long ns8390_offset; | ||
| 84 | unsigned long dataport_offset; | ||
| 85 | unsigned long ctrlport_offset; | ||
| 86 | int ctrl_ioc; | ||
| 87 | const char name[16]; | ||
| 88 | u32 supported; | ||
| 89 | unsigned char tx_start_page; | ||
| 90 | unsigned char stop_page; | ||
| 91 | }; | ||
| 92 | |||
| 93 | MODULE_AUTHOR("Russell King"); | ||
| 94 | MODULE_DESCRIPTION("EtherH/EtherM driver"); | ||
| 95 | MODULE_LICENSE("GPL"); | ||
| 96 | |||
| 97 | #define ETHERH500_DATAPORT 0x800 /* MEMC */ | ||
| 98 | #define ETHERH500_NS8390 0x000 /* MEMC */ | ||
| 99 | #define ETHERH500_CTRLPORT 0x800 /* IOC */ | ||
| 100 | |||
| 101 | #define ETHERH600_DATAPORT 0x040 /* MEMC */ | ||
| 102 | #define ETHERH600_NS8390 0x800 /* MEMC */ | ||
| 103 | #define ETHERH600_CTRLPORT 0x200 /* MEMC */ | ||
| 104 | |||
| 105 | #define ETHERH_CP_IE 1 | ||
| 106 | #define ETHERH_CP_IF 2 | ||
| 107 | #define ETHERH_CP_HEARTBEAT 2 | ||
| 108 | |||
| 109 | #define ETHERH_TX_START_PAGE 1 | ||
| 110 | #define ETHERH_STOP_PAGE 127 | ||
| 111 | |||
| 112 | /* | ||
| 113 | * These came from CK/TEW | ||
| 114 | */ | ||
| 115 | #define ETHERM_DATAPORT 0x200 /* MEMC */ | ||
| 116 | #define ETHERM_NS8390 0x800 /* MEMC */ | ||
| 117 | #define ETHERM_CTRLPORT 0x23c /* MEMC */ | ||
| 118 | |||
| 119 | #define ETHERM_TX_START_PAGE 64 | ||
| 120 | #define ETHERM_STOP_PAGE 127 | ||
| 121 | |||
| 122 | /* ------------------------------------------------------------------------ */ | ||
| 123 | |||
| 124 | #define etherh_priv(dev) \ | ||
| 125 | ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device))) | ||
| 126 | |||
| 127 | static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask) | ||
| 128 | { | ||
| 129 | unsigned char ctrl = eh->ctrl | mask; | ||
| 130 | eh->ctrl = ctrl; | ||
| 131 | writeb(ctrl, eh->ctrl_port); | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask) | ||
| 135 | { | ||
| 136 | unsigned char ctrl = eh->ctrl & ~mask; | ||
| 137 | eh->ctrl = ctrl; | ||
| 138 | writeb(ctrl, eh->ctrl_port); | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline unsigned int etherh_get_stat(struct etherh_priv *eh) | ||
| 142 | { | ||
| 143 | return readb(eh->ctrl_port); | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | |||
| 148 | |||
| 149 | static void etherh_irq_enable(ecard_t *ec, int irqnr) | ||
| 150 | { | ||
| 151 | struct etherh_priv *eh = ec->irq_data; | ||
| 152 | |||
| 153 | etherh_set_ctrl(eh, ETHERH_CP_IE); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void etherh_irq_disable(ecard_t *ec, int irqnr) | ||
| 157 | { | ||
| 158 | struct etherh_priv *eh = ec->irq_data; | ||
| 159 | |||
| 160 | etherh_clr_ctrl(eh, ETHERH_CP_IE); | ||
| 161 | } | ||
| 162 | |||
| 163 | static expansioncard_ops_t etherh_ops = { | ||
| 164 | .irqenable = etherh_irq_enable, | ||
| 165 | .irqdisable = etherh_irq_disable, | ||
| 166 | }; | ||
| 167 | |||
| 168 | |||
| 169 | |||
| 170 | |||
| 171 | static void | ||
| 172 | etherh_setif(struct net_device *dev) | ||
| 173 | { | ||
| 174 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 175 | unsigned long flags; | ||
| 176 | void __iomem *addr; | ||
| 177 | |||
| 178 | local_irq_save(flags); | ||
| 179 | |||
| 180 | /* set the interface type */ | ||
| 181 | switch (etherh_priv(dev)->id) { | ||
| 182 | case PROD_I3_ETHERLAN600: | ||
| 183 | case PROD_I3_ETHERLAN600A: | ||
| 184 | addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; | ||
| 185 | |||
| 186 | switch (dev->if_port) { | ||
| 187 | case IF_PORT_10BASE2: | ||
| 188 | writeb((readb(addr) & 0xf8) | 1, addr); | ||
| 189 | break; | ||
| 190 | case IF_PORT_10BASET: | ||
| 191 | writeb((readb(addr) & 0xf8), addr); | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | break; | ||
| 195 | |||
| 196 | case PROD_I3_ETHERLAN500: | ||
| 197 | switch (dev->if_port) { | ||
| 198 | case IF_PORT_10BASE2: | ||
| 199 | etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF); | ||
| 200 | break; | ||
| 201 | |||
| 202 | case IF_PORT_10BASET: | ||
| 203 | etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF); | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | break; | ||
| 207 | |||
| 208 | default: | ||
| 209 | break; | ||
| 210 | } | ||
| 211 | |||
| 212 | local_irq_restore(flags); | ||
| 213 | } | ||
| 214 | |||
| 215 | static int | ||
| 216 | etherh_getifstat(struct net_device *dev) | ||
| 217 | { | ||
| 218 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 219 | void __iomem *addr; | ||
| 220 | int stat = 0; | ||
| 221 | |||
| 222 | switch (etherh_priv(dev)->id) { | ||
| 223 | case PROD_I3_ETHERLAN600: | ||
| 224 | case PROD_I3_ETHERLAN600A: | ||
| 225 | addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; | ||
| 226 | switch (dev->if_port) { | ||
| 227 | case IF_PORT_10BASE2: | ||
| 228 | stat = 1; | ||
| 229 | break; | ||
| 230 | case IF_PORT_10BASET: | ||
| 231 | stat = readb(addr) & 4; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | break; | ||
| 235 | |||
| 236 | case PROD_I3_ETHERLAN500: | ||
| 237 | switch (dev->if_port) { | ||
| 238 | case IF_PORT_10BASE2: | ||
| 239 | stat = 1; | ||
| 240 | break; | ||
| 241 | case IF_PORT_10BASET: | ||
| 242 | stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT; | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | break; | ||
| 246 | |||
| 247 | default: | ||
| 248 | stat = 0; | ||
| 249 | break; | ||
| 250 | } | ||
| 251 | |||
| 252 | return stat != 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | * Configure the interface. Note that we ignore the other | ||
| 257 | * parts of ifmap, since its mostly meaningless for this driver. | ||
| 258 | */ | ||
| 259 | static int etherh_set_config(struct net_device *dev, struct ifmap *map) | ||
| 260 | { | ||
| 261 | switch (map->port) { | ||
| 262 | case IF_PORT_10BASE2: | ||
| 263 | case IF_PORT_10BASET: | ||
| 264 | /* | ||
| 265 | * If the user explicitly sets the interface | ||
| 266 | * media type, turn off automedia detection. | ||
| 267 | */ | ||
| 268 | dev->flags &= ~IFF_AUTOMEDIA; | ||
| 269 | dev->if_port = map->port; | ||
| 270 | break; | ||
| 271 | |||
| 272 | default: | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | |||
| 276 | etherh_setif(dev); | ||
| 277 | |||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Reset the 8390 (hard reset). Note that we can't actually do this. | ||
| 283 | */ | ||
| 284 | static void | ||
| 285 | etherh_reset(struct net_device *dev) | ||
| 286 | { | ||
| 287 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 288 | void __iomem *addr = (void __iomem *)dev->base_addr; | ||
| 289 | |||
| 290 | writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr); | ||
| 291 | |||
| 292 | /* | ||
| 293 | * See if we need to change the interface type. | ||
| 294 | * Note that we use 'interface_num' as a flag | ||
| 295 | * to indicate that we need to change the media. | ||
| 296 | */ | ||
| 297 | if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) { | ||
| 298 | ei_local->interface_num = 0; | ||
| 299 | |||
| 300 | if (dev->if_port == IF_PORT_10BASET) | ||
| 301 | dev->if_port = IF_PORT_10BASE2; | ||
| 302 | else | ||
| 303 | dev->if_port = IF_PORT_10BASET; | ||
| 304 | |||
| 305 | etherh_setif(dev); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | /* | ||
| 310 | * Write a block of data out to the 8390 | ||
| 311 | */ | ||
| 312 | static void | ||
| 313 | etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page) | ||
| 314 | { | ||
| 315 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 316 | unsigned long dma_start; | ||
| 317 | void __iomem *dma_base, *addr; | ||
| 318 | |||
| 319 | if (ei_local->dmaing) { | ||
| 320 | printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " | ||
| 321 | " DMAstat %d irqlock %d\n", dev->name, | ||
| 322 | ei_local->dmaing, ei_local->irqlock); | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* | ||
| 327 | * Make sure we have a round number of bytes if we're in word mode. | ||
| 328 | */ | ||
| 329 | if (count & 1 && ei_local->word16) | ||
| 330 | count++; | ||
| 331 | |||
| 332 | ei_local->dmaing = 1; | ||
| 333 | |||
| 334 | addr = (void __iomem *)dev->base_addr; | ||
| 335 | dma_base = etherh_priv(dev)->dma_base; | ||
| 336 | |||
| 337 | count = (count + 1) & ~1; | ||
| 338 | writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); | ||
| 339 | |||
| 340 | writeb (0x42, addr + EN0_RCNTLO); | ||
| 341 | writeb (0x00, addr + EN0_RCNTHI); | ||
| 342 | writeb (0x42, addr + EN0_RSARLO); | ||
| 343 | writeb (0x00, addr + EN0_RSARHI); | ||
| 344 | writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); | ||
| 345 | |||
| 346 | udelay (1); | ||
| 347 | |||
| 348 | writeb (ENISR_RDC, addr + EN0_ISR); | ||
| 349 | writeb (count, addr + EN0_RCNTLO); | ||
| 350 | writeb (count >> 8, addr + EN0_RCNTHI); | ||
| 351 | writeb (0, addr + EN0_RSARLO); | ||
| 352 | writeb (start_page, addr + EN0_RSARHI); | ||
| 353 | writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD); | ||
| 354 | |||
| 355 | if (ei_local->word16) | ||
| 356 | writesw (dma_base, buf, count >> 1); | ||
| 357 | else | ||
| 358 | writesb (dma_base, buf, count); | ||
| 359 | |||
| 360 | dma_start = jiffies; | ||
| 361 | |||
| 362 | while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0) | ||
| 363 | if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ | ||
| 364 | printk(KERN_ERR "%s: timeout waiting for TX RDC\n", | ||
| 365 | dev->name); | ||
| 366 | etherh_reset (dev); | ||
| 367 | __NS8390_init (dev, 1); | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | |||
| 371 | writeb (ENISR_RDC, addr + EN0_ISR); | ||
| 372 | ei_local->dmaing = 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Read a block of data from the 8390 | ||
| 377 | */ | ||
| 378 | static void | ||
| 379 | etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) | ||
| 380 | { | ||
| 381 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 382 | unsigned char *buf; | ||
| 383 | void __iomem *dma_base, *addr; | ||
| 384 | |||
| 385 | if (ei_local->dmaing) { | ||
| 386 | printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " | ||
| 387 | " DMAstat %d irqlock %d\n", dev->name, | ||
| 388 | ei_local->dmaing, ei_local->irqlock); | ||
| 389 | return; | ||
| 390 | } | ||
| 391 | |||
| 392 | ei_local->dmaing = 1; | ||
| 393 | |||
| 394 | addr = (void __iomem *)dev->base_addr; | ||
| 395 | dma_base = etherh_priv(dev)->dma_base; | ||
| 396 | |||
| 397 | buf = skb->data; | ||
| 398 | writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); | ||
| 399 | writeb (count, addr + EN0_RCNTLO); | ||
| 400 | writeb (count >> 8, addr + EN0_RCNTHI); | ||
| 401 | writeb (ring_offset, addr + EN0_RSARLO); | ||
| 402 | writeb (ring_offset >> 8, addr + EN0_RSARHI); | ||
| 403 | writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); | ||
| 404 | |||
| 405 | if (ei_local->word16) { | ||
| 406 | readsw (dma_base, buf, count >> 1); | ||
| 407 | if (count & 1) | ||
| 408 | buf[count - 1] = readb (dma_base); | ||
| 409 | } else | ||
| 410 | readsb (dma_base, buf, count); | ||
| 411 | |||
| 412 | writeb (ENISR_RDC, addr + EN0_ISR); | ||
| 413 | ei_local->dmaing = 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | /* | ||
| 417 | * Read a header from the 8390 | ||
| 418 | */ | ||
| 419 | static void | ||
| 420 | etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) | ||
| 421 | { | ||
| 422 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 423 | void __iomem *dma_base, *addr; | ||
| 424 | |||
| 425 | if (ei_local->dmaing) { | ||
| 426 | printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " | ||
| 427 | " DMAstat %d irqlock %d\n", dev->name, | ||
| 428 | ei_local->dmaing, ei_local->irqlock); | ||
| 429 | return; | ||
| 430 | } | ||
| 431 | |||
| 432 | ei_local->dmaing = 1; | ||
| 433 | |||
| 434 | addr = (void __iomem *)dev->base_addr; | ||
| 435 | dma_base = etherh_priv(dev)->dma_base; | ||
| 436 | |||
| 437 | writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); | ||
| 438 | writeb (sizeof (*hdr), addr + EN0_RCNTLO); | ||
| 439 | writeb (0, addr + EN0_RCNTHI); | ||
| 440 | writeb (0, addr + EN0_RSARLO); | ||
| 441 | writeb (ring_page, addr + EN0_RSARHI); | ||
| 442 | writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); | ||
| 443 | |||
| 444 | if (ei_local->word16) | ||
| 445 | readsw (dma_base, hdr, sizeof (*hdr) >> 1); | ||
| 446 | else | ||
| 447 | readsb (dma_base, hdr, sizeof (*hdr)); | ||
| 448 | |||
| 449 | writeb (ENISR_RDC, addr + EN0_ISR); | ||
| 450 | ei_local->dmaing = 0; | ||
| 451 | } | ||
| 452 | |||
| 453 | /* | ||
| 454 | * Open/initialize the board. This is called (in the current kernel) | ||
| 455 | * sometime after booting when the 'ifconfig' program is run. | ||
| 456 | * | ||
| 457 | * This routine should set everything up anew at each open, even | ||
| 458 | * registers that "should" only need to be set once at boot, so that | ||
| 459 | * there is non-reboot way to recover if something goes wrong. | ||
| 460 | */ | ||
| 461 | static int | ||
| 462 | etherh_open(struct net_device *dev) | ||
| 463 | { | ||
| 464 | struct ei_device *ei_local = netdev_priv(dev); | ||
| 465 | |||
| 466 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
| 467 | printk(KERN_WARNING "%s: invalid ethernet MAC address\n", | ||
| 468 | dev->name); | ||
| 469 | return -EINVAL; | ||
| 470 | } | ||
| 471 | |||
| 472 | if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev)) | ||
| 473 | return -EAGAIN; | ||
| 474 | |||
| 475 | /* | ||
| 476 | * Make sure that we aren't going to change the | ||
| 477 | * media type on the next reset - we are about to | ||
| 478 | * do automedia manually now. | ||
| 479 | */ | ||
| 480 | ei_local->interface_num = 0; | ||
| 481 | |||
| 482 | /* | ||
| 483 | * If we are doing automedia detection, do it now. | ||
| 484 | * This is more reliable than the 8390's detection. | ||
| 485 | */ | ||
| 486 | if (dev->flags & IFF_AUTOMEDIA) { | ||
| 487 | dev->if_port = IF_PORT_10BASET; | ||
| 488 | etherh_setif(dev); | ||
| 489 | mdelay(1); | ||
| 490 | if (!etherh_getifstat(dev)) { | ||
| 491 | dev->if_port = IF_PORT_10BASE2; | ||
| 492 | etherh_setif(dev); | ||
| 493 | } | ||
| 494 | } else | ||
| 495 | etherh_setif(dev); | ||
| 496 | |||
| 497 | etherh_reset(dev); | ||
| 498 | __ei_open(dev); | ||
| 499 | |||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * The inverse routine to etherh_open(). | ||
| 505 | */ | ||
| 506 | static int | ||
| 507 | etherh_close(struct net_device *dev) | ||
| 508 | { | ||
| 509 | __ei_close (dev); | ||
| 510 | free_irq (dev->irq, dev); | ||
| 511 | return 0; | ||
| 512 | } | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Initialisation | ||
| 516 | */ | ||
| 517 | |||
| 518 | static void __init etherh_banner(void) | ||
| 519 | { | ||
| 520 | static int version_printed; | ||
| 521 | |||
| 522 | if (net_debug && version_printed++ == 0) | ||
| 523 | printk(KERN_INFO "%s", version); | ||
| 524 | } | ||
| 525 | |||
| 526 | /* | ||
| 527 | * Read the ethernet address string from the on board rom. | ||
| 528 | * This is an ascii string... | ||
| 529 | */ | ||
| 530 | static int __devinit etherh_addr(char *addr, struct expansion_card *ec) | ||
| 531 | { | ||
| 532 | struct in_chunk_dir cd; | ||
| 533 | char *s; | ||
| 534 | |||
| 535 | if (!ecard_readchunk(&cd, ec, 0xf5, 0)) { | ||
| 536 | printk(KERN_ERR "%s: unable to read podule description string\n", | ||
| 537 | dev_name(&ec->dev)); | ||
| 538 | goto no_addr; | ||
| 539 | } | ||
| 540 | |||
| 541 | s = strchr(cd.d.string, '('); | ||
| 542 | if (s) { | ||
| 543 | int i; | ||
| 544 | |||
| 545 | for (i = 0; i < 6; i++) { | ||
| 546 | addr[i] = simple_strtoul(s + 1, &s, 0x10); | ||
| 547 | if (*s != (i == 5? ')' : ':')) | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | |||
| 551 | if (i == 6) | ||
| 552 | return 0; | ||
| 553 | } | ||
| 554 | |||
| 555 | printk(KERN_ERR "%s: unable to parse MAC address: %s\n", | ||
| 556 | dev_name(&ec->dev), cd.d.string); | ||
| 557 | |||
| 558 | no_addr: | ||
| 559 | return -ENODEV; | ||
| 560 | } | ||
| 561 | |||
| 562 | /* | ||
| 563 | * Create an ethernet address from the system serial number. | ||
| 564 | */ | ||
| 565 | static int __init etherm_addr(char *addr) | ||
| 566 | { | ||
| 567 | unsigned int serial; | ||
| 568 | |||
| 569 | if (system_serial_low == 0 && system_serial_high == 0) | ||
| 570 | return -ENODEV; | ||
| 571 | |||
| 572 | serial = system_serial_low | system_serial_high; | ||
| 573 | |||
| 574 | addr[0] = 0; | ||
| 575 | addr[1] = 0; | ||
| 576 | addr[2] = 0xa4; | ||
| 577 | addr[3] = 0x10 + (serial >> 24); | ||
| 578 | addr[4] = serial >> 16; | ||
| 579 | addr[5] = serial >> 8; | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | ||
| 584 | { | ||
| 585 | strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); | ||
| 586 | strlcpy(info->version, DRV_VERSION, sizeof(info->version)); | ||
| 587 | strlcpy(info->bus_info, dev_name(dev->dev.parent), | ||
| 588 | sizeof(info->bus_info)); | ||
| 589 | } | ||
| 590 | |||
| 591 | static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 592 | { | ||
| 593 | cmd->supported = etherh_priv(dev)->supported; | ||
| 594 | ethtool_cmd_speed_set(cmd, SPEED_10); | ||
| 595 | cmd->duplex = DUPLEX_HALF; | ||
| 596 | cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC; | ||
| 597 | cmd->autoneg = (dev->flags & IFF_AUTOMEDIA ? | ||
| 598 | AUTONEG_ENABLE : AUTONEG_DISABLE); | ||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 603 | { | ||
| 604 | switch (cmd->autoneg) { | ||
| 605 | case AUTONEG_ENABLE: | ||
| 606 | dev->flags |= IFF_AUTOMEDIA; | ||
| 607 | break; | ||
| 608 | |||
| 609 | case AUTONEG_DISABLE: | ||
| 610 | switch (cmd->port) { | ||
| 611 | case PORT_TP: | ||
| 612 | dev->if_port = IF_PORT_10BASET; | ||
| 613 | break; | ||
| 614 | |||
| 615 | case PORT_BNC: | ||
| 616 | dev->if_port = IF_PORT_10BASE2; | ||
| 617 | break; | ||
| 618 | |||
| 619 | default: | ||
| 620 | return -EINVAL; | ||
| 621 | } | ||
| 622 | dev->flags &= ~IFF_AUTOMEDIA; | ||
| 623 | break; | ||
| 624 | |||
| 625 | default: | ||
| 626 | return -EINVAL; | ||
| 627 | } | ||
| 628 | |||
| 629 | etherh_setif(dev); | ||
| 630 | |||
| 631 | return 0; | ||
| 632 | } | ||
| 633 | |||
| 634 | static const struct ethtool_ops etherh_ethtool_ops = { | ||
| 635 | .get_settings = etherh_get_settings, | ||
| 636 | .set_settings = etherh_set_settings, | ||
| 637 | .get_drvinfo = etherh_get_drvinfo, | ||
| 638 | }; | ||
| 639 | |||
| 640 | static const struct net_device_ops etherh_netdev_ops = { | ||
| 641 | .ndo_open = etherh_open, | ||
| 642 | .ndo_stop = etherh_close, | ||
| 643 | .ndo_set_config = etherh_set_config, | ||
| 644 | .ndo_start_xmit = __ei_start_xmit, | ||
| 645 | .ndo_tx_timeout = __ei_tx_timeout, | ||
| 646 | .ndo_get_stats = __ei_get_stats, | ||
| 647 | .ndo_set_multicast_list = __ei_set_multicast_list, | ||
| 648 | .ndo_validate_addr = eth_validate_addr, | ||
| 649 | .ndo_set_mac_address = eth_mac_addr, | ||
| 650 | .ndo_change_mtu = eth_change_mtu, | ||
| 651 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 652 | .ndo_poll_controller = __ei_poll, | ||
| 653 | #endif | ||
| 654 | }; | ||
| 655 | |||
| 656 | static u32 etherh_regoffsets[16]; | ||
| 657 | static u32 etherm_regoffsets[16]; | ||
| 658 | |||
| 659 | static int __devinit | ||
| 660 | etherh_probe(struct expansion_card *ec, const struct ecard_id *id) | ||
| 661 | { | ||
| 662 | const struct etherh_data *data = id->data; | ||
| 663 | struct ei_device *ei_local; | ||
| 664 | struct net_device *dev; | ||
| 665 | struct etherh_priv *eh; | ||
| 666 | int ret; | ||
| 667 | |||
| 668 | etherh_banner(); | ||
| 669 | |||
| 670 | ret = ecard_request_resources(ec); | ||
| 671 | if (ret) | ||
| 672 | goto out; | ||
| 673 | |||
| 674 | dev = ____alloc_ei_netdev(sizeof(struct etherh_priv)); | ||
| 675 | if (!dev) { | ||
| 676 | ret = -ENOMEM; | ||
| 677 | goto release; | ||
| 678 | } | ||
| 679 | |||
| 680 | SET_NETDEV_DEV(dev, &ec->dev); | ||
| 681 | |||
| 682 | dev->netdev_ops = ðerh_netdev_ops; | ||
| 683 | dev->irq = ec->irq; | ||
| 684 | dev->ethtool_ops = ðerh_ethtool_ops; | ||
| 685 | |||
| 686 | if (data->supported & SUPPORTED_Autoneg) | ||
| 687 | dev->flags |= IFF_AUTOMEDIA; | ||
| 688 | if (data->supported & SUPPORTED_TP) { | ||
| 689 | dev->flags |= IFF_PORTSEL; | ||
| 690 | dev->if_port = IF_PORT_10BASET; | ||
| 691 | } else if (data->supported & SUPPORTED_BNC) { | ||
| 692 | dev->flags |= IFF_PORTSEL; | ||
| 693 | dev->if_port = IF_PORT_10BASE2; | ||
| 694 | } else | ||
| 695 | dev->if_port = IF_PORT_UNKNOWN; | ||
| 696 | |||
| 697 | eh = etherh_priv(dev); | ||
| 698 | eh->supported = data->supported; | ||
| 699 | eh->ctrl = 0; | ||
| 700 | eh->id = ec->cid.product; | ||
| 701 | eh->memc = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE); | ||
| 702 | if (!eh->memc) { | ||
| 703 | ret = -ENOMEM; | ||
| 704 | goto free; | ||
| 705 | } | ||
| 706 | |||
| 707 | eh->ctrl_port = eh->memc; | ||
| 708 | if (data->ctrl_ioc) { | ||
| 709 | eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE); | ||
| 710 | if (!eh->ioc_fast) { | ||
| 711 | ret = -ENOMEM; | ||
| 712 | goto free; | ||
| 713 | } | ||
| 714 | eh->ctrl_port = eh->ioc_fast; | ||
| 715 | } | ||
| 716 | |||
| 717 | dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset; | ||
| 718 | eh->dma_base = eh->memc + data->dataport_offset; | ||
| 719 | eh->ctrl_port += data->ctrlport_offset; | ||
| 720 | |||
| 721 | /* | ||
| 722 | * IRQ and control port handling - only for non-NIC slot cards. | ||
| 723 | */ | ||
| 724 | if (ec->slot_no != 8) { | ||
| 725 | ecard_setirq(ec, ðerh_ops, eh); | ||
| 726 | } else { | ||
| 727 | /* | ||
| 728 | * If we're in the NIC slot, make sure the IRQ is enabled | ||
| 729 | */ | ||
| 730 | etherh_set_ctrl(eh, ETHERH_CP_IE); | ||
| 731 | } | ||
| 732 | |||
| 733 | ei_local = netdev_priv(dev); | ||
| 734 | spin_lock_init(&ei_local->page_lock); | ||
| 735 | |||
| 736 | if (ec->cid.product == PROD_ANT_ETHERM) { | ||
| 737 | etherm_addr(dev->dev_addr); | ||
| 738 | ei_local->reg_offset = etherm_regoffsets; | ||
| 739 | } else { | ||
| 740 | etherh_addr(dev->dev_addr, ec); | ||
| 741 | ei_local->reg_offset = etherh_regoffsets; | ||
| 742 | } | ||
| 743 | |||
| 744 | ei_local->name = dev->name; | ||
| 745 | ei_local->word16 = 1; | ||
| 746 | ei_local->tx_start_page = data->tx_start_page; | ||
| 747 | ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; | ||
| 748 | ei_local->stop_page = data->stop_page; | ||
| 749 | ei_local->reset_8390 = etherh_reset; | ||
| 750 | ei_local->block_input = etherh_block_input; | ||
| 751 | ei_local->block_output = etherh_block_output; | ||
| 752 | ei_local->get_8390_hdr = etherh_get_header; | ||
| 753 | ei_local->interface_num = 0; | ||
| 754 | |||
| 755 | etherh_reset(dev); | ||
| 756 | __NS8390_init(dev, 0); | ||
| 757 | |||
| 758 | ret = register_netdev(dev); | ||
| 759 | if (ret) | ||
| 760 | goto free; | ||
| 761 | |||
| 762 | printk(KERN_INFO "%s: %s in slot %d, %pM\n", | ||
| 763 | dev->name, data->name, ec->slot_no, dev->dev_addr); | ||
| 764 | |||
| 765 | ecard_set_drvdata(ec, dev); | ||
| 766 | |||
| 767 | return 0; | ||
| 768 | |||
| 769 | free: | ||
| 770 | free_netdev(dev); | ||
| 771 | release: | ||
| 772 | ecard_release_resources(ec); | ||
| 773 | out: | ||
| 774 | return ret; | ||
| 775 | } | ||
| 776 | |||
| 777 | static void __devexit etherh_remove(struct expansion_card *ec) | ||
| 778 | { | ||
| 779 | struct net_device *dev = ecard_get_drvdata(ec); | ||
| 780 | |||
| 781 | ecard_set_drvdata(ec, NULL); | ||
| 782 | |||
| 783 | unregister_netdev(dev); | ||
| 784 | |||
| 785 | free_netdev(dev); | ||
| 786 | |||
| 787 | ecard_release_resources(ec); | ||
| 788 | } | ||
| 789 | |||
| 790 | static struct etherh_data etherm_data = { | ||
| 791 | .ns8390_offset = ETHERM_NS8390, | ||
| 792 | .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT, | ||
| 793 | .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT, | ||
| 794 | .name = "ANT EtherM", | ||
| 795 | .supported = SUPPORTED_10baseT_Half, | ||
| 796 | .tx_start_page = ETHERM_TX_START_PAGE, | ||
| 797 | .stop_page = ETHERM_STOP_PAGE, | ||
| 798 | }; | ||
| 799 | |||
| 800 | static struct etherh_data etherlan500_data = { | ||
| 801 | .ns8390_offset = ETHERH500_NS8390, | ||
| 802 | .dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT, | ||
| 803 | .ctrlport_offset = ETHERH500_CTRLPORT, | ||
| 804 | .ctrl_ioc = 1, | ||
| 805 | .name = "i3 EtherH 500", | ||
| 806 | .supported = SUPPORTED_10baseT_Half, | ||
| 807 | .tx_start_page = ETHERH_TX_START_PAGE, | ||
| 808 | .stop_page = ETHERH_STOP_PAGE, | ||
| 809 | }; | ||
| 810 | |||
| 811 | static struct etherh_data etherlan600_data = { | ||
| 812 | .ns8390_offset = ETHERH600_NS8390, | ||
| 813 | .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, | ||
| 814 | .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, | ||
| 815 | .name = "i3 EtherH 600", | ||
| 816 | .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, | ||
| 817 | .tx_start_page = ETHERH_TX_START_PAGE, | ||
| 818 | .stop_page = ETHERH_STOP_PAGE, | ||
| 819 | }; | ||
| 820 | |||
| 821 | static struct etherh_data etherlan600a_data = { | ||
| 822 | .ns8390_offset = ETHERH600_NS8390, | ||
| 823 | .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, | ||
| 824 | .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, | ||
| 825 | .name = "i3 EtherH 600A", | ||
| 826 | .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, | ||
| 827 | .tx_start_page = ETHERH_TX_START_PAGE, | ||
| 828 | .stop_page = ETHERH_STOP_PAGE, | ||
| 829 | }; | ||
| 830 | |||
| 831 | static const struct ecard_id etherh_ids[] = { | ||
| 832 | { MANU_ANT, PROD_ANT_ETHERM, ðerm_data }, | ||
| 833 | { MANU_I3, PROD_I3_ETHERLAN500, ðerlan500_data }, | ||
| 834 | { MANU_I3, PROD_I3_ETHERLAN600, ðerlan600_data }, | ||
| 835 | { MANU_I3, PROD_I3_ETHERLAN600A, ðerlan600a_data }, | ||
| 836 | { 0xffff, 0xffff } | ||
| 837 | }; | ||
| 838 | |||
| 839 | static struct ecard_driver etherh_driver = { | ||
| 840 | .probe = etherh_probe, | ||
| 841 | .remove = __devexit_p(etherh_remove), | ||
| 842 | .id_table = etherh_ids, | ||
| 843 | .drv = { | ||
| 844 | .name = DRV_NAME, | ||
| 845 | }, | ||
| 846 | }; | ||
| 847 | |||
| 848 | static int __init etherh_init(void) | ||
| 849 | { | ||
| 850 | int i; | ||
| 851 | |||
| 852 | for (i = 0; i < 16; i++) { | ||
| 853 | etherh_regoffsets[i] = i << 2; | ||
| 854 | etherm_regoffsets[i] = i << 5; | ||
| 855 | } | ||
| 856 | |||
| 857 | return ecard_register_driver(ðerh_driver); | ||
| 858 | } | ||
| 859 | |||
| 860 | static void __exit etherh_exit(void) | ||
| 861 | { | ||
| 862 | ecard_remove_driver(ðerh_driver); | ||
| 863 | } | ||
| 864 | |||
| 865 | module_init(etherh_init); | ||
| 866 | module_exit(etherh_exit); | ||
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c new file mode 100644 index 00000000000..de51e8453c1 --- /dev/null +++ b/drivers/net/arm/ixp4xx_eth.c | |||
| @@ -0,0 +1,1489 @@ | |||
| 1 | /* | ||
| 2 | * Intel IXP4xx Ethernet driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of version 2 of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Ethernet port config (0x00 is not present on IXP42X): | ||
| 11 | * | ||
| 12 | * logical port 0x00 0x10 0x20 | ||
| 13 | * NPE 0 (NPE-A) 1 (NPE-B) 2 (NPE-C) | ||
| 14 | * physical PortId 2 0 1 | ||
| 15 | * TX queue 23 24 25 | ||
| 16 | * RX-free queue 26 27 28 | ||
| 17 | * TX-done queue is always 31, per-port RX and TX-ready queues are configurable | ||
| 18 | * | ||
| 19 | * | ||
| 20 | * Queue entries: | ||
| 21 | * bits 0 -> 1 - NPE ID (RX and TX-done) | ||
| 22 | * bits 0 -> 2 - priority (TX, per 802.1D) | ||
| 23 | * bits 3 -> 4 - port ID (user-set?) | ||
| 24 | * bits 5 -> 31 - physical descriptor address | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/dma-mapping.h> | ||
| 29 | #include <linux/dmapool.h> | ||
| 30 | #include <linux/etherdevice.h> | ||
| 31 | #include <linux/io.h> | ||
| 32 | #include <linux/kernel.h> | ||
| 33 | #include <linux/net_tstamp.h> | ||
| 34 | #include <linux/phy.h> | ||
| 35 | #include <linux/platform_device.h> | ||
| 36 | #include <linux/ptp_classify.h> | ||
| 37 | #include <linux/slab.h> | ||
| 38 | #include <mach/ixp46x_ts.h> | ||
| 39 | #include <mach/npe.h> | ||
| 40 | #include <mach/qmgr.h> | ||
| 41 | |||
| 42 | #define DEBUG_DESC 0 | ||
| 43 | #define DEBUG_RX 0 | ||
| 44 | #define DEBUG_TX 0 | ||
| 45 | #define DEBUG_PKT_BYTES 0 | ||
| 46 | #define DEBUG_MDIO 0 | ||
| 47 | #define DEBUG_CLOSE 0 | ||
| 48 | |||
| 49 | #define DRV_NAME "ixp4xx_eth" | ||
| 50 | |||
| 51 | #define MAX_NPES 3 | ||
| 52 | |||
| 53 | #define RX_DESCS 64 /* also length of all RX queues */ | ||
| 54 | #define TX_DESCS 16 /* also length of all TX queues */ | ||
| 55 | #define TXDONE_QUEUE_LEN 64 /* dwords */ | ||
| 56 | |||
| 57 | #define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) | ||
| 58 | #define REGS_SIZE 0x1000 | ||
| 59 | #define MAX_MRU 1536 /* 0x600 */ | ||
| 60 | #define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4) | ||
| 61 | |||
| 62 | #define NAPI_WEIGHT 16 | ||
| 63 | #define MDIO_INTERVAL (3 * HZ) | ||
| 64 | #define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */ | ||
| 65 | #define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */ | ||
| 66 | |||
| 67 | #define NPE_ID(port_id) ((port_id) >> 4) | ||
| 68 | #define PHYSICAL_ID(port_id) ((NPE_ID(port_id) + 2) % 3) | ||
| 69 | #define TX_QUEUE(port_id) (NPE_ID(port_id) + 23) | ||
| 70 | #define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26) | ||
| 71 | #define TXDONE_QUEUE 31 | ||
| 72 | |||
| 73 | #define PTP_SLAVE_MODE 1 | ||
| 74 | #define PTP_MASTER_MODE 2 | ||
| 75 | #define PORT2CHANNEL(p) NPE_ID(p->id) | ||
| 76 | |||
| 77 | /* TX Control Registers */ | ||
| 78 | #define TX_CNTRL0_TX_EN 0x01 | ||
| 79 | #define TX_CNTRL0_HALFDUPLEX 0x02 | ||
| 80 | #define TX_CNTRL0_RETRY 0x04 | ||
| 81 | #define TX_CNTRL0_PAD_EN 0x08 | ||
| 82 | #define TX_CNTRL0_APPEND_FCS 0x10 | ||
| 83 | #define TX_CNTRL0_2DEFER 0x20 | ||
| 84 | #define TX_CNTRL0_RMII 0x40 /* reduced MII */ | ||
| 85 | #define TX_CNTRL1_RETRIES 0x0F /* 4 bits */ | ||
| 86 | |||
| 87 | /* RX Control Registers */ | ||
| 88 | #define RX_CNTRL0_RX_EN 0x01 | ||
| 89 | #define RX_CNTRL0_PADSTRIP_EN 0x02 | ||
| 90 | #define RX_CNTRL0_SEND_FCS 0x04 | ||
| 91 | #define RX_CNTRL0_PAUSE_EN 0x08 | ||
| 92 | #define RX_CNTRL0_LOOP_EN 0x10 | ||
| 93 | #define RX_CNTRL0_ADDR_FLTR_EN 0x20 | ||
| 94 | #define RX_CNTRL0_RX_RUNT_EN 0x40 | ||
| 95 | #define RX_CNTRL0_BCAST_DIS 0x80 | ||
| 96 | #define RX_CNTRL1_DEFER_EN 0x01 | ||
| 97 | |||
| 98 | /* Core Control Register */ | ||
| 99 | #define CORE_RESET 0x01 | ||
| 100 | #define CORE_RX_FIFO_FLUSH 0x02 | ||
| 101 | #define CORE_TX_FIFO_FLUSH 0x04 | ||
| 102 | #define CORE_SEND_JAM 0x08 | ||
| 103 | #define CORE_MDC_EN 0x10 /* MDIO using NPE-B ETH-0 only */ | ||
| 104 | |||
| 105 | #define DEFAULT_TX_CNTRL0 (TX_CNTRL0_TX_EN | TX_CNTRL0_RETRY | \ | ||
| 106 | TX_CNTRL0_PAD_EN | TX_CNTRL0_APPEND_FCS | \ | ||
| 107 | TX_CNTRL0_2DEFER) | ||
| 108 | #define DEFAULT_RX_CNTRL0 RX_CNTRL0_RX_EN | ||
| 109 | #define DEFAULT_CORE_CNTRL CORE_MDC_EN | ||
| 110 | |||
| 111 | |||
| 112 | /* NPE message codes */ | ||
| 113 | #define NPE_GETSTATUS 0x00 | ||
| 114 | #define NPE_EDB_SETPORTADDRESS 0x01 | ||
| 115 | #define NPE_EDB_GETMACADDRESSDATABASE 0x02 | ||
| 116 | #define NPE_EDB_SETMACADDRESSSDATABASE 0x03 | ||
| 117 | #define NPE_GETSTATS 0x04 | ||
| 118 | #define NPE_RESETSTATS 0x05 | ||
| 119 | #define NPE_SETMAXFRAMELENGTHS 0x06 | ||
| 120 | #define NPE_VLAN_SETRXTAGMODE 0x07 | ||
| 121 | #define NPE_VLAN_SETDEFAULTRXVID 0x08 | ||
| 122 | #define NPE_VLAN_SETPORTVLANTABLEENTRY 0x09 | ||
| 123 | #define NPE_VLAN_SETPORTVLANTABLERANGE 0x0A | ||
| 124 | #define NPE_VLAN_SETRXQOSENTRY 0x0B | ||
| 125 | #define NPE_VLAN_SETPORTIDEXTRACTIONMODE 0x0C | ||
| 126 | #define NPE_STP_SETBLOCKINGSTATE 0x0D | ||
| 127 | #define NPE_FW_SETFIREWALLMODE 0x0E | ||
| 128 | #define NPE_PC_SETFRAMECONTROLDURATIONID 0x0F | ||
| 129 | #define NPE_PC_SETAPMACTABLE 0x11 | ||
| 130 | #define NPE_SETLOOPBACK_MODE 0x12 | ||
| 131 | #define NPE_PC_SETBSSIDTABLE 0x13 | ||
| 132 | #define NPE_ADDRESS_FILTER_CONFIG 0x14 | ||
| 133 | #define NPE_APPENDFCSCONFIG 0x15 | ||
| 134 | #define NPE_NOTIFY_MAC_RECOVERY_DONE 0x16 | ||
| 135 | #define NPE_MAC_RECOVERY_START 0x17 | ||
| 136 | |||
| 137 | |||
| 138 | #ifdef __ARMEB__ | ||
| 139 | typedef struct sk_buff buffer_t; | ||
| 140 | #define free_buffer dev_kfree_skb | ||
| 141 | #define free_buffer_irq dev_kfree_skb_irq | ||
| 142 | #else | ||
| 143 | typedef void buffer_t; | ||
| 144 | #define free_buffer kfree | ||
| 145 | #define free_buffer_irq kfree | ||
| 146 | #endif | ||
| 147 | |||
| 148 | struct eth_regs { | ||
| 149 | u32 tx_control[2], __res1[2]; /* 000 */ | ||
| 150 | u32 rx_control[2], __res2[2]; /* 010 */ | ||
| 151 | u32 random_seed, __res3[3]; /* 020 */ | ||
| 152 | u32 partial_empty_threshold, __res4; /* 030 */ | ||
| 153 | u32 partial_full_threshold, __res5; /* 038 */ | ||
| 154 | u32 tx_start_bytes, __res6[3]; /* 040 */ | ||
| 155 | u32 tx_deferral, rx_deferral, __res7[2];/* 050 */ | ||
| 156 | u32 tx_2part_deferral[2], __res8[2]; /* 060 */ | ||
| 157 | u32 slot_time, __res9[3]; /* 070 */ | ||
| 158 | u32 mdio_command[4]; /* 080 */ | ||
| 159 | u32 mdio_status[4]; /* 090 */ | ||
| 160 | u32 mcast_mask[6], __res10[2]; /* 0A0 */ | ||
| 161 | u32 mcast_addr[6], __res11[2]; /* 0C0 */ | ||
| 162 | u32 int_clock_threshold, __res12[3]; /* 0E0 */ | ||
| 163 | u32 hw_addr[6], __res13[61]; /* 0F0 */ | ||
| 164 | u32 core_control; /* 1FC */ | ||
| 165 | }; | ||
| 166 | |||
| 167 | struct port { | ||
| 168 | struct resource *mem_res; | ||
| 169 | struct eth_regs __iomem *regs; | ||
| 170 | struct npe *npe; | ||
| 171 | struct net_device *netdev; | ||
| 172 | struct napi_struct napi; | ||
| 173 | struct phy_device *phydev; | ||
| 174 | struct eth_plat_info *plat; | ||
| 175 | buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; | ||
| 176 | struct desc *desc_tab; /* coherent */ | ||
| 177 | u32 desc_tab_phys; | ||
| 178 | int id; /* logical port ID */ | ||
| 179 | int speed, duplex; | ||
| 180 | u8 firmware[4]; | ||
| 181 | int hwts_tx_en; | ||
| 182 | int hwts_rx_en; | ||
| 183 | }; | ||
| 184 | |||
| 185 | /* NPE message structure */ | ||
| 186 | struct msg { | ||
| 187 | #ifdef __ARMEB__ | ||
| 188 | u8 cmd, eth_id, byte2, byte3; | ||
| 189 | u8 byte4, byte5, byte6, byte7; | ||
| 190 | #else | ||
| 191 | u8 byte3, byte2, eth_id, cmd; | ||
| 192 | u8 byte7, byte6, byte5, byte4; | ||
| 193 | #endif | ||
| 194 | }; | ||
| 195 | |||
| 196 | /* Ethernet packet descriptor */ | ||
| 197 | struct desc { | ||
| 198 | u32 next; /* pointer to next buffer, unused */ | ||
| 199 | |||
| 200 | #ifdef __ARMEB__ | ||
| 201 | u16 buf_len; /* buffer length */ | ||
| 202 | u16 pkt_len; /* packet length */ | ||
| 203 | u32 data; /* pointer to data buffer in RAM */ | ||
| 204 | u8 dest_id; | ||
| 205 | u8 src_id; | ||
| 206 | u16 flags; | ||
| 207 | u8 qos; | ||
| 208 | u8 padlen; | ||
| 209 | u16 vlan_tci; | ||
| 210 | #else | ||
| 211 | u16 pkt_len; /* packet length */ | ||
| 212 | u16 buf_len; /* buffer length */ | ||
| 213 | u32 data; /* pointer to data buffer in RAM */ | ||
| 214 | u16 flags; | ||
| 215 | u8 src_id; | ||
| 216 | u8 dest_id; | ||
| 217 | u16 vlan_tci; | ||
| 218 | u8 padlen; | ||
| 219 | u8 qos; | ||
| 220 | #endif | ||
| 221 | |||
| 222 | #ifdef __ARMEB__ | ||
| 223 | u8 dst_mac_0, dst_mac_1, dst_mac_2, dst_mac_3; | ||
| 224 | u8 dst_mac_4, dst_mac_5, src_mac_0, src_mac_1; | ||
| 225 | u8 src_mac_2, src_mac_3, src_mac_4, src_mac_5; | ||
| 226 | #else | ||
| 227 | u8 dst_mac_3, dst_mac_2, dst_mac_1, dst_mac_0; | ||
| 228 | u8 src_mac_1, src_mac_0, dst_mac_5, dst_mac_4; | ||
| 229 | u8 src_mac_5, src_mac_4, src_mac_3, src_mac_2; | ||
| 230 | #endif | ||
| 231 | }; | ||
| 232 | |||
| 233 | |||
| 234 | #define rx_desc_phys(port, n) ((port)->desc_tab_phys + \ | ||
| 235 | (n) * sizeof(struct desc)) | ||
| 236 | #define rx_desc_ptr(port, n) (&(port)->desc_tab[n]) | ||
| 237 | |||
| 238 | #define tx_desc_phys(port, n) ((port)->desc_tab_phys + \ | ||
| 239 | ((n) + RX_DESCS) * sizeof(struct desc)) | ||
| 240 | #define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS]) | ||
| 241 | |||
| 242 | #ifndef __ARMEB__ | ||
| 243 | static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) | ||
| 244 | { | ||
| 245 | int i; | ||
| 246 | for (i = 0; i < cnt; i++) | ||
| 247 | dest[i] = swab32(src[i]); | ||
| 248 | } | ||
| 249 | #endif | ||
| 250 | |||
| 251 | static spinlock_t mdio_lock; | ||
| 252 | static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */ | ||
| 253 | static struct mii_bus *mdio_bus; | ||
| 254 | static int ports_open; | ||
| 255 | static struct port *npe_port_tab[MAX_NPES]; | ||
| 256 | static struct dma_pool *dma_pool; | ||
| 257 | |||
| 258 | static struct sock_filter ptp_filter[] = { | ||
| 259 | PTP_FILTER | ||
| 260 | }; | ||
| 261 | |||
| 262 | static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) | ||
| 263 | { | ||
| 264 | u8 *data = skb->data; | ||
| 265 | unsigned int offset; | ||
| 266 | u16 *hi, *id; | ||
| 267 | u32 lo; | ||
| 268 | |||
| 269 | if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4) | ||
| 270 | return 0; | ||
| 271 | |||
| 272 | offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; | ||
| 273 | |||
| 274 | if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid)) | ||
| 275 | return 0; | ||
| 276 | |||
| 277 | hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID); | ||
| 278 | id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); | ||
| 279 | |||
| 280 | memcpy(&lo, &hi[1], sizeof(lo)); | ||
| 281 | |||
| 282 | return (uid_hi == ntohs(*hi) && | ||
| 283 | uid_lo == ntohl(lo) && | ||
| 284 | seqid == ntohs(*id)); | ||
| 285 | } | ||
| 286 | |||
| 287 | static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb) | ||
| 288 | { | ||
| 289 | struct skb_shared_hwtstamps *shhwtstamps; | ||
| 290 | struct ixp46x_ts_regs *regs; | ||
| 291 | u64 ns; | ||
| 292 | u32 ch, hi, lo, val; | ||
| 293 | u16 uid, seq; | ||
| 294 | |||
| 295 | if (!port->hwts_rx_en) | ||
| 296 | return; | ||
| 297 | |||
| 298 | ch = PORT2CHANNEL(port); | ||
| 299 | |||
| 300 | regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; | ||
| 301 | |||
| 302 | val = __raw_readl(®s->channel[ch].ch_event); | ||
| 303 | |||
| 304 | if (!(val & RX_SNAPSHOT_LOCKED)) | ||
| 305 | return; | ||
| 306 | |||
| 307 | lo = __raw_readl(®s->channel[ch].src_uuid_lo); | ||
| 308 | hi = __raw_readl(®s->channel[ch].src_uuid_hi); | ||
| 309 | |||
| 310 | uid = hi & 0xffff; | ||
| 311 | seq = (hi >> 16) & 0xffff; | ||
| 312 | |||
| 313 | if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq))) | ||
| 314 | goto out; | ||
| 315 | |||
| 316 | lo = __raw_readl(®s->channel[ch].rx_snap_lo); | ||
| 317 | hi = __raw_readl(®s->channel[ch].rx_snap_hi); | ||
| 318 | ns = ((u64) hi) << 32; | ||
| 319 | ns |= lo; | ||
| 320 | ns <<= TICKS_NS_SHIFT; | ||
| 321 | |||
| 322 | shhwtstamps = skb_hwtstamps(skb); | ||
| 323 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); | ||
| 324 | shhwtstamps->hwtstamp = ns_to_ktime(ns); | ||
| 325 | out: | ||
| 326 | __raw_writel(RX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) | ||
| 330 | { | ||
| 331 | struct skb_shared_hwtstamps shhwtstamps; | ||
| 332 | struct ixp46x_ts_regs *regs; | ||
| 333 | struct skb_shared_info *shtx; | ||
| 334 | u64 ns; | ||
| 335 | u32 ch, cnt, hi, lo, val; | ||
| 336 | |||
| 337 | shtx = skb_shinfo(skb); | ||
| 338 | if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en)) | ||
| 339 | shtx->tx_flags |= SKBTX_IN_PROGRESS; | ||
| 340 | else | ||
| 341 | return; | ||
| 342 | |||
| 343 | ch = PORT2CHANNEL(port); | ||
| 344 | |||
| 345 | regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; | ||
| 346 | |||
| 347 | /* | ||
| 348 | * This really stinks, but we have to poll for the Tx time stamp. | ||
| 349 | * Usually, the time stamp is ready after 4 to 6 microseconds. | ||
| 350 | */ | ||
| 351 | for (cnt = 0; cnt < 100; cnt++) { | ||
| 352 | val = __raw_readl(®s->channel[ch].ch_event); | ||
| 353 | if (val & TX_SNAPSHOT_LOCKED) | ||
| 354 | break; | ||
| 355 | udelay(1); | ||
| 356 | } | ||
| 357 | if (!(val & TX_SNAPSHOT_LOCKED)) { | ||
| 358 | shtx->tx_flags &= ~SKBTX_IN_PROGRESS; | ||
| 359 | return; | ||
| 360 | } | ||
| 361 | |||
| 362 | lo = __raw_readl(®s->channel[ch].tx_snap_lo); | ||
| 363 | hi = __raw_readl(®s->channel[ch].tx_snap_hi); | ||
| 364 | ns = ((u64) hi) << 32; | ||
| 365 | ns |= lo; | ||
| 366 | ns <<= TICKS_NS_SHIFT; | ||
| 367 | |||
| 368 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); | ||
| 369 | shhwtstamps.hwtstamp = ns_to_ktime(ns); | ||
| 370 | skb_tstamp_tx(skb, &shhwtstamps); | ||
| 371 | |||
| 372 | __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); | ||
| 373 | } | ||
| 374 | |||
| 375 | static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||
| 376 | { | ||
| 377 | struct hwtstamp_config cfg; | ||
| 378 | struct ixp46x_ts_regs *regs; | ||
| 379 | struct port *port = netdev_priv(netdev); | ||
| 380 | int ch; | ||
| 381 | |||
| 382 | if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) | ||
| 383 | return -EFAULT; | ||
| 384 | |||
| 385 | if (cfg.flags) /* reserved for future extensions */ | ||
| 386 | return -EINVAL; | ||
| 387 | |||
| 388 | ch = PORT2CHANNEL(port); | ||
| 389 | regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; | ||
| 390 | |||
| 391 | switch (cfg.tx_type) { | ||
| 392 | case HWTSTAMP_TX_OFF: | ||
| 393 | port->hwts_tx_en = 0; | ||
| 394 | break; | ||
| 395 | case HWTSTAMP_TX_ON: | ||
| 396 | port->hwts_tx_en = 1; | ||
| 397 | break; | ||
| 398 | default: | ||
| 399 | return -ERANGE; | ||
| 400 | } | ||
| 401 | |||
| 402 | switch (cfg.rx_filter) { | ||
| 403 | case HWTSTAMP_FILTER_NONE: | ||
| 404 | port->hwts_rx_en = 0; | ||
| 405 | break; | ||
| 406 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
| 407 | port->hwts_rx_en = PTP_SLAVE_MODE; | ||
| 408 | __raw_writel(0, ®s->channel[ch].ch_control); | ||
| 409 | break; | ||
| 410 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
| 411 | port->hwts_rx_en = PTP_MASTER_MODE; | ||
| 412 | __raw_writel(MASTER_MODE, ®s->channel[ch].ch_control); | ||
| 413 | break; | ||
| 414 | default: | ||
| 415 | return -ERANGE; | ||
| 416 | } | ||
| 417 | |||
| 418 | /* Clear out any old time stamps. */ | ||
| 419 | __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, | ||
| 420 | ®s->channel[ch].ch_event); | ||
| 421 | |||
| 422 | return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, | ||
| 426 | int write, u16 cmd) | ||
| 427 | { | ||
| 428 | int cycles = 0; | ||
| 429 | |||
| 430 | if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) { | ||
| 431 | printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name); | ||
| 432 | return -1; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (write) { | ||
| 436 | __raw_writel(cmd & 0xFF, &mdio_regs->mdio_command[0]); | ||
| 437 | __raw_writel(cmd >> 8, &mdio_regs->mdio_command[1]); | ||
| 438 | } | ||
| 439 | __raw_writel(((phy_id << 5) | location) & 0xFF, | ||
| 440 | &mdio_regs->mdio_command[2]); | ||
| 441 | __raw_writel((phy_id >> 3) | (write << 2) | 0x80 /* GO */, | ||
| 442 | &mdio_regs->mdio_command[3]); | ||
| 443 | |||
| 444 | while ((cycles < MAX_MDIO_RETRIES) && | ||
| 445 | (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80)) { | ||
| 446 | udelay(1); | ||
| 447 | cycles++; | ||
| 448 | } | ||
| 449 | |||
| 450 | if (cycles == MAX_MDIO_RETRIES) { | ||
| 451 | printk(KERN_ERR "%s #%i: MII write failed\n", bus->name, | ||
| 452 | phy_id); | ||
| 453 | return -1; | ||
| 454 | } | ||
| 455 | |||
| 456 | #if DEBUG_MDIO | ||
| 457 | printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name, | ||
| 458 | phy_id, write ? "write" : "read", cycles); | ||
| 459 | #endif | ||
| 460 | |||
| 461 | if (write) | ||
| 462 | return 0; | ||
| 463 | |||
| 464 | if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) { | ||
| 465 | #if DEBUG_MDIO | ||
| 466 | printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name, | ||
| 467 | phy_id); | ||
| 468 | #endif | ||
| 469 | return 0xFFFF; /* don't return error */ | ||
| 470 | } | ||
| 471 | |||
| 472 | return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) | | ||
| 473 | ((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8); | ||
| 474 | } | ||
| 475 | |||
| 476 | static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location) | ||
| 477 | { | ||
| 478 | unsigned long flags; | ||
| 479 | int ret; | ||
| 480 | |||
| 481 | spin_lock_irqsave(&mdio_lock, flags); | ||
| 482 | ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0); | ||
| 483 | spin_unlock_irqrestore(&mdio_lock, flags); | ||
| 484 | #if DEBUG_MDIO | ||
| 485 | printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name, | ||
| 486 | phy_id, location, ret); | ||
| 487 | #endif | ||
| 488 | return ret; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location, | ||
| 492 | u16 val) | ||
| 493 | { | ||
| 494 | unsigned long flags; | ||
| 495 | int ret; | ||
| 496 | |||
| 497 | spin_lock_irqsave(&mdio_lock, flags); | ||
| 498 | ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val); | ||
| 499 | spin_unlock_irqrestore(&mdio_lock, flags); | ||
| 500 | #if DEBUG_MDIO | ||
| 501 | printk(KERN_DEBUG "%s #%i: MII write [%i] <- 0x%X, err = %i\n", | ||
| 502 | bus->name, phy_id, location, val, ret); | ||
| 503 | #endif | ||
| 504 | return ret; | ||
| 505 | } | ||
| 506 | |||
| 507 | static int ixp4xx_mdio_register(void) | ||
| 508 | { | ||
| 509 | int err; | ||
| 510 | |||
| 511 | if (!(mdio_bus = mdiobus_alloc())) | ||
| 512 | return -ENOMEM; | ||
| 513 | |||
| 514 | if (cpu_is_ixp43x()) { | ||
| 515 | /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */ | ||
| 516 | if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH)) | ||
| 517 | return -ENODEV; | ||
| 518 | mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT; | ||
| 519 | } else { | ||
| 520 | /* All MII PHY accesses use NPE-B Ethernet registers */ | ||
| 521 | if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) | ||
| 522 | return -ENODEV; | ||
| 523 | mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; | ||
| 524 | } | ||
| 525 | |||
| 526 | __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); | ||
| 527 | spin_lock_init(&mdio_lock); | ||
| 528 | mdio_bus->name = "IXP4xx MII Bus"; | ||
| 529 | mdio_bus->read = &ixp4xx_mdio_read; | ||
| 530 | mdio_bus->write = &ixp4xx_mdio_write; | ||
| 531 | strcpy(mdio_bus->id, "0"); | ||
| 532 | |||
| 533 | if ((err = mdiobus_register(mdio_bus))) | ||
| 534 | mdiobus_free(mdio_bus); | ||
| 535 | return err; | ||
| 536 | } | ||
| 537 | |||
| 538 | static void ixp4xx_mdio_remove(void) | ||
| 539 | { | ||
| 540 | mdiobus_unregister(mdio_bus); | ||
| 541 | mdiobus_free(mdio_bus); | ||
| 542 | } | ||
| 543 | |||
| 544 | |||
| 545 | static void ixp4xx_adjust_link(struct net_device *dev) | ||
| 546 | { | ||
| 547 | struct port *port = netdev_priv(dev); | ||
| 548 | struct phy_device *phydev = port->phydev; | ||
| 549 | |||
| 550 | if (!phydev->link) { | ||
| 551 | if (port->speed) { | ||
| 552 | port->speed = 0; | ||
| 553 | printk(KERN_INFO "%s: link down\n", dev->name); | ||
| 554 | } | ||
| 555 | return; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (port->speed == phydev->speed && port->duplex == phydev->duplex) | ||
| 559 | return; | ||
| 560 | |||
| 561 | port->speed = phydev->speed; | ||
| 562 | port->duplex = phydev->duplex; | ||
| 563 | |||
| 564 | if (port->duplex) | ||
| 565 | __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, | ||
| 566 | &port->regs->tx_control[0]); | ||
| 567 | else | ||
| 568 | __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, | ||
| 569 | &port->regs->tx_control[0]); | ||
| 570 | |||
| 571 | printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", | ||
| 572 | dev->name, port->speed, port->duplex ? "full" : "half"); | ||
| 573 | } | ||
| 574 | |||
| 575 | |||
| 576 | static inline void debug_pkt(struct net_device *dev, const char *func, | ||
| 577 | u8 *data, int len) | ||
| 578 | { | ||
| 579 | #if DEBUG_PKT_BYTES | ||
| 580 | int i; | ||
| 581 | |||
| 582 | printk(KERN_DEBUG "%s: %s(%i) ", dev->name, func, len); | ||
| 583 | for (i = 0; i < len; i++) { | ||
| 584 | if (i >= DEBUG_PKT_BYTES) | ||
| 585 | break; | ||
| 586 | printk("%s%02X", | ||
| 587 | ((i == 6) || (i == 12) || (i >= 14)) ? " " : "", | ||
| 588 | data[i]); | ||
| 589 | } | ||
| 590 | printk("\n"); | ||
| 591 | #endif | ||
| 592 | } | ||
| 593 | |||
| 594 | |||
| 595 | static inline void debug_desc(u32 phys, struct desc *desc) | ||
| 596 | { | ||
| 597 | #if DEBUG_DESC | ||
| 598 | printk(KERN_DEBUG "%X: %X %3X %3X %08X %2X < %2X %4X %X" | ||
| 599 | " %X %X %02X%02X%02X%02X%02X%02X < %02X%02X%02X%02X%02X%02X\n", | ||
| 600 | phys, desc->next, desc->buf_len, desc->pkt_len, | ||
| 601 | desc->data, desc->dest_id, desc->src_id, desc->flags, | ||
| 602 | desc->qos, desc->padlen, desc->vlan_tci, | ||
| 603 | desc->dst_mac_0, desc->dst_mac_1, desc->dst_mac_2, | ||
| 604 | desc->dst_mac_3, desc->dst_mac_4, desc->dst_mac_5, | ||
| 605 | desc->src_mac_0, desc->src_mac_1, desc->src_mac_2, | ||
| 606 | desc->src_mac_3, desc->src_mac_4, desc->src_mac_5); | ||
| 607 | #endif | ||
| 608 | } | ||
| 609 | |||
| 610 | static inline int queue_get_desc(unsigned int queue, struct port *port, | ||
| 611 | int is_tx) | ||
| 612 | { | ||
| 613 | u32 phys, tab_phys, n_desc; | ||
| 614 | struct desc *tab; | ||
| 615 | |||
| 616 | if (!(phys = qmgr_get_entry(queue))) | ||
| 617 | return -1; | ||
| 618 | |||
| 619 | phys &= ~0x1F; /* mask out non-address bits */ | ||
| 620 | tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0); | ||
| 621 | tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0); | ||
| 622 | n_desc = (phys - tab_phys) / sizeof(struct desc); | ||
| 623 | BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS)); | ||
| 624 | debug_desc(phys, &tab[n_desc]); | ||
| 625 | BUG_ON(tab[n_desc].next); | ||
| 626 | return n_desc; | ||
| 627 | } | ||
| 628 | |||
| 629 | static inline void queue_put_desc(unsigned int queue, u32 phys, | ||
| 630 | struct desc *desc) | ||
| 631 | { | ||
| 632 | debug_desc(phys, desc); | ||
| 633 | BUG_ON(phys & 0x1F); | ||
| 634 | qmgr_put_entry(queue, phys); | ||
| 635 | /* Don't check for queue overflow here, we've allocated sufficient | ||
| 636 | length and queues >= 32 don't support this check anyway. */ | ||
| 637 | } | ||
| 638 | |||
| 639 | |||
| 640 | static inline void dma_unmap_tx(struct port *port, struct desc *desc) | ||
| 641 | { | ||
| 642 | #ifdef __ARMEB__ | ||
| 643 | dma_unmap_single(&port->netdev->dev, desc->data, | ||
| 644 | desc->buf_len, DMA_TO_DEVICE); | ||
| 645 | #else | ||
| 646 | dma_unmap_single(&port->netdev->dev, desc->data & ~3, | ||
| 647 | ALIGN((desc->data & 3) + desc->buf_len, 4), | ||
| 648 | DMA_TO_DEVICE); | ||
| 649 | #endif | ||
| 650 | } | ||
| 651 | |||
| 652 | |||
| 653 | static void eth_rx_irq(void *pdev) | ||
| 654 | { | ||
| 655 | struct net_device *dev = pdev; | ||
| 656 | struct port *port = netdev_priv(dev); | ||
| 657 | |||
| 658 | #if DEBUG_RX | ||
| 659 | printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name); | ||
| 660 | #endif | ||
| 661 | qmgr_disable_irq(port->plat->rxq); | ||
| 662 | napi_schedule(&port->napi); | ||
| 663 | } | ||
| 664 | |||
| 665 | static int eth_poll(struct napi_struct *napi, int budget) | ||
| 666 | { | ||
| 667 | struct port *port = container_of(napi, struct port, napi); | ||
| 668 | struct net_device *dev = port->netdev; | ||
| 669 | unsigned int rxq = port->plat->rxq, rxfreeq = RXFREE_QUEUE(port->id); | ||
| 670 | int received = 0; | ||
| 671 | |||
| 672 | #if DEBUG_RX | ||
| 673 | printk(KERN_DEBUG "%s: eth_poll\n", dev->name); | ||
| 674 | #endif | ||
| 675 | |||
| 676 | while (received < budget) { | ||
| 677 | struct sk_buff *skb; | ||
| 678 | struct desc *desc; | ||
| 679 | int n; | ||
| 680 | #ifdef __ARMEB__ | ||
| 681 | struct sk_buff *temp; | ||
| 682 | u32 phys; | ||
| 683 | #endif | ||
| 684 | |||
| 685 | if ((n = queue_get_desc(rxq, port, 0)) < 0) { | ||
| 686 | #if DEBUG_RX | ||
| 687 | printk(KERN_DEBUG "%s: eth_poll napi_complete\n", | ||
| 688 | dev->name); | ||
| 689 | #endif | ||
| 690 | napi_complete(napi); | ||
| 691 | qmgr_enable_irq(rxq); | ||
| 692 | if (!qmgr_stat_below_low_watermark(rxq) && | ||
| 693 | napi_reschedule(napi)) { /* not empty again */ | ||
| 694 | #if DEBUG_RX | ||
| 695 | printk(KERN_DEBUG "%s: eth_poll" | ||
| 696 | " napi_reschedule successed\n", | ||
| 697 | dev->name); | ||
| 698 | #endif | ||
| 699 | qmgr_disable_irq(rxq); | ||
| 700 | continue; | ||
| 701 | } | ||
| 702 | #if DEBUG_RX | ||
| 703 | printk(KERN_DEBUG "%s: eth_poll all done\n", | ||
| 704 | dev->name); | ||
| 705 | #endif | ||
| 706 | return received; /* all work done */ | ||
| 707 | } | ||
| 708 | |||
| 709 | desc = rx_desc_ptr(port, n); | ||
| 710 | |||
| 711 | #ifdef __ARMEB__ | ||
| 712 | if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) { | ||
| 713 | phys = dma_map_single(&dev->dev, skb->data, | ||
| 714 | RX_BUFF_SIZE, DMA_FROM_DEVICE); | ||
| 715 | if (dma_mapping_error(&dev->dev, phys)) { | ||
| 716 | dev_kfree_skb(skb); | ||
| 717 | skb = NULL; | ||
| 718 | } | ||
| 719 | } | ||
| 720 | #else | ||
| 721 | skb = netdev_alloc_skb(dev, | ||
| 722 | ALIGN(NET_IP_ALIGN + desc->pkt_len, 4)); | ||
| 723 | #endif | ||
| 724 | |||
| 725 | if (!skb) { | ||
| 726 | dev->stats.rx_dropped++; | ||
| 727 | /* put the desc back on RX-ready queue */ | ||
| 728 | desc->buf_len = MAX_MRU; | ||
| 729 | desc->pkt_len = 0; | ||
| 730 | queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); | ||
| 731 | continue; | ||
| 732 | } | ||
| 733 | |||
| 734 | /* process received frame */ | ||
| 735 | #ifdef __ARMEB__ | ||
| 736 | temp = skb; | ||
| 737 | skb = port->rx_buff_tab[n]; | ||
| 738 | dma_unmap_single(&dev->dev, desc->data - NET_IP_ALIGN, | ||
| 739 | RX_BUFF_SIZE, DMA_FROM_DEVICE); | ||
| 740 | #else | ||
| 741 | dma_sync_single_for_cpu(&dev->dev, desc->data - NET_IP_ALIGN, | ||
| 742 | RX_BUFF_SIZE, DMA_FROM_DEVICE); | ||
| 743 | memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], | ||
| 744 | ALIGN(NET_IP_ALIGN + desc->pkt_len, 4) / 4); | ||
| 745 | #endif | ||
| 746 | skb_reserve(skb, NET_IP_ALIGN); | ||
| 747 | skb_put(skb, desc->pkt_len); | ||
| 748 | |||
| 749 | debug_pkt(dev, "eth_poll", skb->data, skb->len); | ||
| 750 | |||
| 751 | ixp_rx_timestamp(port, skb); | ||
| 752 | skb->protocol = eth_type_trans(skb, dev); | ||
| 753 | dev->stats.rx_packets++; | ||
| 754 | dev->stats.rx_bytes += skb->len; | ||
| 755 | netif_receive_skb(skb); | ||
| 756 | |||
| 757 | /* put the new buffer on RX-free queue */ | ||
| 758 | #ifdef __ARMEB__ | ||
| 759 | port->rx_buff_tab[n] = temp; | ||
| 760 | desc->data = phys + NET_IP_ALIGN; | ||
| 761 | #endif | ||
| 762 | desc->buf_len = MAX_MRU; | ||
| 763 | desc->pkt_len = 0; | ||
| 764 | queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); | ||
| 765 | received++; | ||
| 766 | } | ||
| 767 | |||
| 768 | #if DEBUG_RX | ||
| 769 | printk(KERN_DEBUG "eth_poll(): end, not all work done\n"); | ||
| 770 | #endif | ||
| 771 | return received; /* not all work done */ | ||
| 772 | } | ||
| 773 | |||
| 774 | |||
| 775 | static void eth_txdone_irq(void *unused) | ||
| 776 | { | ||
| 777 | u32 phys; | ||
| 778 | |||
| 779 | #if DEBUG_TX | ||
| 780 | printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n"); | ||
| 781 | #endif | ||
| 782 | while ((phys = qmgr_get_entry(TXDONE_QUEUE)) != 0) { | ||
| 783 | u32 npe_id, n_desc; | ||
| 784 | struct port *port; | ||
| 785 | struct desc *desc; | ||
| 786 | int start; | ||
| 787 | |||
| 788 | npe_id = phys & 3; | ||
| 789 | BUG_ON(npe_id >= MAX_NPES); | ||
| 790 | port = npe_port_tab[npe_id]; | ||
| 791 | BUG_ON(!port); | ||
| 792 | phys &= ~0x1F; /* mask out non-address bits */ | ||
| 793 | n_desc = (phys - tx_desc_phys(port, 0)) / sizeof(struct desc); | ||
| 794 | BUG_ON(n_desc >= TX_DESCS); | ||
| 795 | desc = tx_desc_ptr(port, n_desc); | ||
| 796 | debug_desc(phys, desc); | ||
| 797 | |||
| 798 | if (port->tx_buff_tab[n_desc]) { /* not the draining packet */ | ||
| 799 | port->netdev->stats.tx_packets++; | ||
| 800 | port->netdev->stats.tx_bytes += desc->pkt_len; | ||
| 801 | |||
| 802 | dma_unmap_tx(port, desc); | ||
| 803 | #if DEBUG_TX | ||
| 804 | printk(KERN_DEBUG "%s: eth_txdone_irq free %p\n", | ||
| 805 | port->netdev->name, port->tx_buff_tab[n_desc]); | ||
| 806 | #endif | ||
| 807 | free_buffer_irq(port->tx_buff_tab[n_desc]); | ||
| 808 | port->tx_buff_tab[n_desc] = NULL; | ||
| 809 | } | ||
| 810 | |||
| 811 | start = qmgr_stat_below_low_watermark(port->plat->txreadyq); | ||
| 812 | queue_put_desc(port->plat->txreadyq, phys, desc); | ||
| 813 | if (start) { /* TX-ready queue was empty */ | ||
| 814 | #if DEBUG_TX | ||
| 815 | printk(KERN_DEBUG "%s: eth_txdone_irq xmit ready\n", | ||
| 816 | port->netdev->name); | ||
| 817 | #endif | ||
| 818 | netif_wake_queue(port->netdev); | ||
| 819 | } | ||
| 820 | } | ||
| 821 | } | ||
| 822 | |||
| 823 | static int eth_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 824 | { | ||
| 825 | struct port *port = netdev_priv(dev); | ||
| 826 | unsigned int txreadyq = port->plat->txreadyq; | ||
| 827 | int len, offset, bytes, n; | ||
| 828 | void *mem; | ||
| 829 | u32 phys; | ||
| 830 | struct desc *desc; | ||
| 831 | |||
| 832 | #if DEBUG_TX | ||
| 833 | printk(KERN_DEBUG "%s: eth_xmit\n", dev->name); | ||
| 834 | #endif | ||
| 835 | |||
| 836 | if (unlikely(skb->len > MAX_MRU)) { | ||
| 837 | dev_kfree_skb(skb); | ||
| 838 | dev->stats.tx_errors++; | ||
| 839 | return NETDEV_TX_OK; | ||
| 840 | } | ||
| 841 | |||
| 842 | debug_pkt(dev, "eth_xmit", skb->data, skb->len); | ||
| 843 | |||
| 844 | len = skb->len; | ||
| 845 | #ifdef __ARMEB__ | ||
| 846 | offset = 0; /* no need to keep alignment */ | ||
| 847 | bytes = len; | ||
| 848 | mem = skb->data; | ||
| 849 | #else | ||
| 850 | offset = (int)skb->data & 3; /* keep 32-bit alignment */ | ||
| 851 | bytes = ALIGN(offset + len, 4); | ||
| 852 | if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { | ||
| 853 | dev_kfree_skb(skb); | ||
| 854 | dev->stats.tx_dropped++; | ||
| 855 | return NETDEV_TX_OK; | ||
| 856 | } | ||
| 857 | memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); | ||
| 858 | #endif | ||
| 859 | |||
| 860 | phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); | ||
| 861 | if (dma_mapping_error(&dev->dev, phys)) { | ||
| 862 | dev_kfree_skb(skb); | ||
| 863 | #ifndef __ARMEB__ | ||
| 864 | kfree(mem); | ||
| 865 | #endif | ||
| 866 | dev->stats.tx_dropped++; | ||
| 867 | return NETDEV_TX_OK; | ||
| 868 | } | ||
| 869 | |||
| 870 | n = queue_get_desc(txreadyq, port, 1); | ||
| 871 | BUG_ON(n < 0); | ||
| 872 | desc = tx_desc_ptr(port, n); | ||
| 873 | |||
| 874 | #ifdef __ARMEB__ | ||
| 875 | port->tx_buff_tab[n] = skb; | ||
| 876 | #else | ||
| 877 | port->tx_buff_tab[n] = mem; | ||
| 878 | #endif | ||
| 879 | desc->data = phys + offset; | ||
| 880 | desc->buf_len = desc->pkt_len = len; | ||
| 881 | |||
| 882 | /* NPE firmware pads short frames with zeros internally */ | ||
| 883 | wmb(); | ||
| 884 | queue_put_desc(TX_QUEUE(port->id), tx_desc_phys(port, n), desc); | ||
| 885 | |||
| 886 | if (qmgr_stat_below_low_watermark(txreadyq)) { /* empty */ | ||
| 887 | #if DEBUG_TX | ||
| 888 | printk(KERN_DEBUG "%s: eth_xmit queue full\n", dev->name); | ||
| 889 | #endif | ||
| 890 | netif_stop_queue(dev); | ||
| 891 | /* we could miss TX ready interrupt */ | ||
| 892 | /* really empty in fact */ | ||
| 893 | if (!qmgr_stat_below_low_watermark(txreadyq)) { | ||
| 894 | #if DEBUG_TX | ||
| 895 | printk(KERN_DEBUG "%s: eth_xmit ready again\n", | ||
| 896 | dev->name); | ||
| 897 | #endif | ||
| 898 | netif_wake_queue(dev); | ||
| 899 | } | ||
| 900 | } | ||
| 901 | |||
| 902 | #if DEBUG_TX | ||
| 903 | printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name); | ||
| 904 | #endif | ||
| 905 | |||
| 906 | ixp_tx_timestamp(port, skb); | ||
| 907 | skb_tx_timestamp(skb); | ||
| 908 | |||
| 909 | #ifndef __ARMEB__ | ||
| 910 | dev_kfree_skb(skb); | ||
| 911 | #endif | ||
| 912 | return NETDEV_TX_OK; | ||
| 913 | } | ||
| 914 | |||
| 915 | |||
| 916 | static void eth_set_mcast_list(struct net_device *dev) | ||
| 917 | { | ||
| 918 | struct port *port = netdev_priv(dev); | ||
| 919 | struct netdev_hw_addr *ha; | ||
| 920 | u8 diffs[ETH_ALEN], *addr; | ||
| 921 | int i; | ||
| 922 | static const u8 allmulti[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
| 923 | |||
| 924 | if (dev->flags & IFF_ALLMULTI) { | ||
| 925 | for (i = 0; i < ETH_ALEN; i++) { | ||
| 926 | __raw_writel(allmulti[i], &port->regs->mcast_addr[i]); | ||
| 927 | __raw_writel(allmulti[i], &port->regs->mcast_mask[i]); | ||
| 928 | } | ||
| 929 | __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN, | ||
| 930 | &port->regs->rx_control[0]); | ||
| 931 | return; | ||
| 932 | } | ||
| 933 | |||
| 934 | if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) { | ||
| 935 | __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN, | ||
| 936 | &port->regs->rx_control[0]); | ||
| 937 | return; | ||
| 938 | } | ||
| 939 | |||
| 940 | memset(diffs, 0, ETH_ALEN); | ||
| 941 | |||
| 942 | addr = NULL; | ||
| 943 | netdev_for_each_mc_addr(ha, dev) { | ||
| 944 | if (!addr) | ||
| 945 | addr = ha->addr; /* first MAC address */ | ||
| 946 | for (i = 0; i < ETH_ALEN; i++) | ||
| 947 | diffs[i] |= addr[i] ^ ha->addr[i]; | ||
| 948 | } | ||
| 949 | |||
| 950 | for (i = 0; i < ETH_ALEN; i++) { | ||
| 951 | __raw_writel(addr[i], &port->regs->mcast_addr[i]); | ||
| 952 | __raw_writel(~diffs[i], &port->regs->mcast_mask[i]); | ||
| 953 | } | ||
| 954 | |||
| 955 | __raw_writel(DEFAULT_RX_CNTRL0 | RX_CNTRL0_ADDR_FLTR_EN, | ||
| 956 | &port->regs->rx_control[0]); | ||
| 957 | } | ||
| 958 | |||
| 959 | |||
| 960 | static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | ||
| 961 | { | ||
| 962 | struct port *port = netdev_priv(dev); | ||
| 963 | |||
| 964 | if (!netif_running(dev)) | ||
| 965 | return -EINVAL; | ||
| 966 | |||
| 967 | if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) | ||
| 968 | return hwtstamp_ioctl(dev, req, cmd); | ||
| 969 | |||
| 970 | return phy_mii_ioctl(port->phydev, req, cmd); | ||
| 971 | } | ||
| 972 | |||
| 973 | /* ethtool support */ | ||
| 974 | |||
| 975 | static void ixp4xx_get_drvinfo(struct net_device *dev, | ||
| 976 | struct ethtool_drvinfo *info) | ||
| 977 | { | ||
| 978 | struct port *port = netdev_priv(dev); | ||
| 979 | strcpy(info->driver, DRV_NAME); | ||
| 980 | snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u", | ||
| 981 | port->firmware[0], port->firmware[1], | ||
| 982 | port->firmware[2], port->firmware[3]); | ||
| 983 | strcpy(info->bus_info, "internal"); | ||
| 984 | } | ||
| 985 | |||
| 986 | static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 987 | { | ||
| 988 | struct port *port = netdev_priv(dev); | ||
| 989 | return phy_ethtool_gset(port->phydev, cmd); | ||
| 990 | } | ||
| 991 | |||
| 992 | static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 993 | { | ||
| 994 | struct port *port = netdev_priv(dev); | ||
| 995 | return phy_ethtool_sset(port->phydev, cmd); | ||
| 996 | } | ||
| 997 | |||
| 998 | static int ixp4xx_nway_reset(struct net_device *dev) | ||
| 999 | { | ||
| 1000 | struct port *port = netdev_priv(dev); | ||
| 1001 | return phy_start_aneg(port->phydev); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static const struct ethtool_ops ixp4xx_ethtool_ops = { | ||
| 1005 | .get_drvinfo = ixp4xx_get_drvinfo, | ||
| 1006 | .get_settings = ixp4xx_get_settings, | ||
| 1007 | .set_settings = ixp4xx_set_settings, | ||
| 1008 | .nway_reset = ixp4xx_nway_reset, | ||
| 1009 | .get_link = ethtool_op_get_link, | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | |||
| 1013 | static int request_queues(struct port *port) | ||
| 1014 | { | ||
| 1015 | int err; | ||
| 1016 | |||
| 1017 | err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0, | ||
| 1018 | "%s:RX-free", port->netdev->name); | ||
| 1019 | if (err) | ||
| 1020 | return err; | ||
| 1021 | |||
| 1022 | err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0, | ||
| 1023 | "%s:RX", port->netdev->name); | ||
| 1024 | if (err) | ||
| 1025 | goto rel_rxfree; | ||
| 1026 | |||
| 1027 | err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0, | ||
| 1028 | "%s:TX", port->netdev->name); | ||
| 1029 | if (err) | ||
| 1030 | goto rel_rx; | ||
| 1031 | |||
| 1032 | err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0, | ||
| 1033 | "%s:TX-ready", port->netdev->name); | ||
| 1034 | if (err) | ||
| 1035 | goto rel_tx; | ||
| 1036 | |||
| 1037 | /* TX-done queue handles skbs sent out by the NPEs */ | ||
| 1038 | if (!ports_open) { | ||
| 1039 | err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0, | ||
| 1040 | "%s:TX-done", DRV_NAME); | ||
| 1041 | if (err) | ||
| 1042 | goto rel_txready; | ||
| 1043 | } | ||
| 1044 | return 0; | ||
| 1045 | |||
| 1046 | rel_txready: | ||
| 1047 | qmgr_release_queue(port->plat->txreadyq); | ||
| 1048 | rel_tx: | ||
| 1049 | qmgr_release_queue(TX_QUEUE(port->id)); | ||
| 1050 | rel_rx: | ||
| 1051 | qmgr_release_queue(port->plat->rxq); | ||
| 1052 | rel_rxfree: | ||
| 1053 | qmgr_release_queue(RXFREE_QUEUE(port->id)); | ||
| 1054 | printk(KERN_DEBUG "%s: unable to request hardware queues\n", | ||
| 1055 | port->netdev->name); | ||
| 1056 | return err; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | static void release_queues(struct port *port) | ||
| 1060 | { | ||
| 1061 | qmgr_release_queue(RXFREE_QUEUE(port->id)); | ||
| 1062 | qmgr_release_queue(port->plat->rxq); | ||
| 1063 | qmgr_release_queue(TX_QUEUE(port->id)); | ||
| 1064 | qmgr_release_queue(port->plat->txreadyq); | ||
| 1065 | |||
| 1066 | if (!ports_open) | ||
| 1067 | qmgr_release_queue(TXDONE_QUEUE); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static int init_queues(struct port *port) | ||
| 1071 | { | ||
| 1072 | int i; | ||
| 1073 | |||
| 1074 | if (!ports_open) | ||
| 1075 | if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, | ||
| 1076 | POOL_ALLOC_SIZE, 32, 0))) | ||
| 1077 | return -ENOMEM; | ||
| 1078 | |||
| 1079 | if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, | ||
| 1080 | &port->desc_tab_phys))) | ||
| 1081 | return -ENOMEM; | ||
| 1082 | memset(port->desc_tab, 0, POOL_ALLOC_SIZE); | ||
| 1083 | memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */ | ||
| 1084 | memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab)); | ||
| 1085 | |||
| 1086 | /* Setup RX buffers */ | ||
| 1087 | for (i = 0; i < RX_DESCS; i++) { | ||
| 1088 | struct desc *desc = rx_desc_ptr(port, i); | ||
| 1089 | buffer_t *buff; /* skb or kmalloc()ated memory */ | ||
| 1090 | void *data; | ||
| 1091 | #ifdef __ARMEB__ | ||
| 1092 | if (!(buff = netdev_alloc_skb(port->netdev, RX_BUFF_SIZE))) | ||
| 1093 | return -ENOMEM; | ||
| 1094 | data = buff->data; | ||
| 1095 | #else | ||
| 1096 | if (!(buff = kmalloc(RX_BUFF_SIZE, GFP_KERNEL))) | ||
| 1097 | return -ENOMEM; | ||
| 1098 | data = buff; | ||
| 1099 | #endif | ||
| 1100 | desc->buf_len = MAX_MRU; | ||
| 1101 | desc->data = dma_map_single(&port->netdev->dev, data, | ||
| 1102 | RX_BUFF_SIZE, DMA_FROM_DEVICE); | ||
| 1103 | if (dma_mapping_error(&port->netdev->dev, desc->data)) { | ||
| 1104 | free_buffer(buff); | ||
| 1105 | return -EIO; | ||
| 1106 | } | ||
| 1107 | desc->data += NET_IP_ALIGN; | ||
| 1108 | port->rx_buff_tab[i] = buff; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | return 0; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static void destroy_queues(struct port *port) | ||
| 1115 | { | ||
| 1116 | int i; | ||
| 1117 | |||
| 1118 | if (port->desc_tab) { | ||
| 1119 | for (i = 0; i < RX_DESCS; i++) { | ||
| 1120 | struct desc *desc = rx_desc_ptr(port, i); | ||
| 1121 | buffer_t *buff = port->rx_buff_tab[i]; | ||
| 1122 | if (buff) { | ||
| 1123 | dma_unmap_single(&port->netdev->dev, | ||
| 1124 | desc->data - NET_IP_ALIGN, | ||
| 1125 | RX_BUFF_SIZE, DMA_FROM_DEVICE); | ||
| 1126 | free_buffer(buff); | ||
| 1127 | } | ||
| 1128 | } | ||
| 1129 | for (i = 0; i < TX_DESCS; i++) { | ||
| 1130 | struct desc *desc = tx_desc_ptr(port, i); | ||
| 1131 | buffer_t *buff = port->tx_buff_tab[i]; | ||
| 1132 | if (buff) { | ||
| 1133 | dma_unmap_tx(port, desc); | ||
| 1134 | free_buffer(buff); | ||
| 1135 | } | ||
| 1136 | } | ||
| 1137 | dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys); | ||
| 1138 | port->desc_tab = NULL; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | if (!ports_open && dma_pool) { | ||
| 1142 | dma_pool_destroy(dma_pool); | ||
| 1143 | dma_pool = NULL; | ||
| 1144 | } | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | static int eth_open(struct net_device *dev) | ||
| 1148 | { | ||
| 1149 | struct port *port = netdev_priv(dev); | ||
| 1150 | struct npe *npe = port->npe; | ||
| 1151 | struct msg msg; | ||
| 1152 | int i, err; | ||
| 1153 | |||
| 1154 | if (!npe_running(npe)) { | ||
| 1155 | err = npe_load_firmware(npe, npe_name(npe), &dev->dev); | ||
| 1156 | if (err) | ||
| 1157 | return err; | ||
| 1158 | |||
| 1159 | if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) { | ||
| 1160 | printk(KERN_ERR "%s: %s not responding\n", dev->name, | ||
| 1161 | npe_name(npe)); | ||
| 1162 | return -EIO; | ||
| 1163 | } | ||
| 1164 | port->firmware[0] = msg.byte4; | ||
| 1165 | port->firmware[1] = msg.byte5; | ||
| 1166 | port->firmware[2] = msg.byte6; | ||
| 1167 | port->firmware[3] = msg.byte7; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | memset(&msg, 0, sizeof(msg)); | ||
| 1171 | msg.cmd = NPE_VLAN_SETRXQOSENTRY; | ||
| 1172 | msg.eth_id = port->id; | ||
| 1173 | msg.byte5 = port->plat->rxq | 0x80; | ||
| 1174 | msg.byte7 = port->plat->rxq << 4; | ||
| 1175 | for (i = 0; i < 8; i++) { | ||
| 1176 | msg.byte3 = i; | ||
| 1177 | if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ")) | ||
| 1178 | return -EIO; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | msg.cmd = NPE_EDB_SETPORTADDRESS; | ||
| 1182 | msg.eth_id = PHYSICAL_ID(port->id); | ||
| 1183 | msg.byte2 = dev->dev_addr[0]; | ||
| 1184 | msg.byte3 = dev->dev_addr[1]; | ||
| 1185 | msg.byte4 = dev->dev_addr[2]; | ||
| 1186 | msg.byte5 = dev->dev_addr[3]; | ||
| 1187 | msg.byte6 = dev->dev_addr[4]; | ||
| 1188 | msg.byte7 = dev->dev_addr[5]; | ||
| 1189 | if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC")) | ||
| 1190 | return -EIO; | ||
| 1191 | |||
| 1192 | memset(&msg, 0, sizeof(msg)); | ||
| 1193 | msg.cmd = NPE_FW_SETFIREWALLMODE; | ||
| 1194 | msg.eth_id = port->id; | ||
| 1195 | if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE")) | ||
| 1196 | return -EIO; | ||
| 1197 | |||
| 1198 | if ((err = request_queues(port)) != 0) | ||
| 1199 | return err; | ||
| 1200 | |||
| 1201 | if ((err = init_queues(port)) != 0) { | ||
| 1202 | destroy_queues(port); | ||
| 1203 | release_queues(port); | ||
| 1204 | return err; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | port->speed = 0; /* force "link up" message */ | ||
| 1208 | phy_start(port->phydev); | ||
| 1209 | |||
| 1210 | for (i = 0; i < ETH_ALEN; i++) | ||
| 1211 | __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); | ||
| 1212 | __raw_writel(0x08, &port->regs->random_seed); | ||
| 1213 | __raw_writel(0x12, &port->regs->partial_empty_threshold); | ||
| 1214 | __raw_writel(0x30, &port->regs->partial_full_threshold); | ||
| 1215 | __raw_writel(0x08, &port->regs->tx_start_bytes); | ||
| 1216 | __raw_writel(0x15, &port->regs->tx_deferral); | ||
| 1217 | __raw_writel(0x08, &port->regs->tx_2part_deferral[0]); | ||
| 1218 | __raw_writel(0x07, &port->regs->tx_2part_deferral[1]); | ||
| 1219 | __raw_writel(0x80, &port->regs->slot_time); | ||
| 1220 | __raw_writel(0x01, &port->regs->int_clock_threshold); | ||
| 1221 | |||
| 1222 | /* Populate queues with buffers, no failure after this point */ | ||
| 1223 | for (i = 0; i < TX_DESCS; i++) | ||
| 1224 | queue_put_desc(port->plat->txreadyq, | ||
| 1225 | tx_desc_phys(port, i), tx_desc_ptr(port, i)); | ||
| 1226 | |||
| 1227 | for (i = 0; i < RX_DESCS; i++) | ||
| 1228 | queue_put_desc(RXFREE_QUEUE(port->id), | ||
| 1229 | rx_desc_phys(port, i), rx_desc_ptr(port, i)); | ||
| 1230 | |||
| 1231 | __raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]); | ||
| 1232 | __raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]); | ||
| 1233 | __raw_writel(0, &port->regs->rx_control[1]); | ||
| 1234 | __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]); | ||
| 1235 | |||
| 1236 | napi_enable(&port->napi); | ||
| 1237 | eth_set_mcast_list(dev); | ||
| 1238 | netif_start_queue(dev); | ||
| 1239 | |||
| 1240 | qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY, | ||
| 1241 | eth_rx_irq, dev); | ||
| 1242 | if (!ports_open) { | ||
| 1243 | qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY, | ||
| 1244 | eth_txdone_irq, NULL); | ||
| 1245 | qmgr_enable_irq(TXDONE_QUEUE); | ||
| 1246 | } | ||
| 1247 | ports_open++; | ||
| 1248 | /* we may already have RX data, enables IRQ */ | ||
| 1249 | napi_schedule(&port->napi); | ||
| 1250 | return 0; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | static int eth_close(struct net_device *dev) | ||
| 1254 | { | ||
| 1255 | struct port *port = netdev_priv(dev); | ||
| 1256 | struct msg msg; | ||
| 1257 | int buffs = RX_DESCS; /* allocated RX buffers */ | ||
| 1258 | int i; | ||
| 1259 | |||
| 1260 | ports_open--; | ||
| 1261 | qmgr_disable_irq(port->plat->rxq); | ||
| 1262 | napi_disable(&port->napi); | ||
| 1263 | netif_stop_queue(dev); | ||
| 1264 | |||
| 1265 | while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0) | ||
| 1266 | buffs--; | ||
| 1267 | |||
| 1268 | memset(&msg, 0, sizeof(msg)); | ||
| 1269 | msg.cmd = NPE_SETLOOPBACK_MODE; | ||
| 1270 | msg.eth_id = port->id; | ||
| 1271 | msg.byte3 = 1; | ||
| 1272 | if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK")) | ||
| 1273 | printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name); | ||
| 1274 | |||
| 1275 | i = 0; | ||
| 1276 | do { /* drain RX buffers */ | ||
| 1277 | while (queue_get_desc(port->plat->rxq, port, 0) >= 0) | ||
| 1278 | buffs--; | ||
| 1279 | if (!buffs) | ||
| 1280 | break; | ||
| 1281 | if (qmgr_stat_empty(TX_QUEUE(port->id))) { | ||
| 1282 | /* we have to inject some packet */ | ||
| 1283 | struct desc *desc; | ||
| 1284 | u32 phys; | ||
| 1285 | int n = queue_get_desc(port->plat->txreadyq, port, 1); | ||
| 1286 | BUG_ON(n < 0); | ||
| 1287 | desc = tx_desc_ptr(port, n); | ||
| 1288 | phys = tx_desc_phys(port, n); | ||
| 1289 | desc->buf_len = desc->pkt_len = 1; | ||
| 1290 | wmb(); | ||
| 1291 | queue_put_desc(TX_QUEUE(port->id), phys, desc); | ||
| 1292 | } | ||
| 1293 | udelay(1); | ||
| 1294 | } while (++i < MAX_CLOSE_WAIT); | ||
| 1295 | |||
| 1296 | if (buffs) | ||
| 1297 | printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)" | ||
| 1298 | " left in NPE\n", dev->name, buffs); | ||
| 1299 | #if DEBUG_CLOSE | ||
| 1300 | if (!buffs) | ||
| 1301 | printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i); | ||
| 1302 | #endif | ||
| 1303 | |||
| 1304 | buffs = TX_DESCS; | ||
| 1305 | while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0) | ||
| 1306 | buffs--; /* cancel TX */ | ||
| 1307 | |||
| 1308 | i = 0; | ||
| 1309 | do { | ||
| 1310 | while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) | ||
| 1311 | buffs--; | ||
| 1312 | if (!buffs) | ||
| 1313 | break; | ||
| 1314 | } while (++i < MAX_CLOSE_WAIT); | ||
| 1315 | |||
| 1316 | if (buffs) | ||
| 1317 | printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) " | ||
| 1318 | "left in NPE\n", dev->name, buffs); | ||
| 1319 | #if DEBUG_CLOSE | ||
| 1320 | if (!buffs) | ||
| 1321 | printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); | ||
| 1322 | #endif | ||
| 1323 | |||
| 1324 | msg.byte3 = 0; | ||
| 1325 | if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK")) | ||
| 1326 | printk(KERN_CRIT "%s: unable to disable loopback\n", | ||
| 1327 | dev->name); | ||
| 1328 | |||
| 1329 | phy_stop(port->phydev); | ||
| 1330 | |||
| 1331 | if (!ports_open) | ||
| 1332 | qmgr_disable_irq(TXDONE_QUEUE); | ||
| 1333 | destroy_queues(port); | ||
| 1334 | release_queues(port); | ||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | static const struct net_device_ops ixp4xx_netdev_ops = { | ||
| 1339 | .ndo_open = eth_open, | ||
| 1340 | .ndo_stop = eth_close, | ||
| 1341 | .ndo_start_xmit = eth_xmit, | ||
| 1342 | .ndo_set_multicast_list = eth_set_mcast_list, | ||
| 1343 | .ndo_do_ioctl = eth_ioctl, | ||
| 1344 | .ndo_change_mtu = eth_change_mtu, | ||
| 1345 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1346 | .ndo_validate_addr = eth_validate_addr, | ||
| 1347 | }; | ||
| 1348 | |||
| 1349 | static int __devinit eth_init_one(struct platform_device *pdev) | ||
| 1350 | { | ||
| 1351 | struct port *port; | ||
| 1352 | struct net_device *dev; | ||
| 1353 | struct eth_plat_info *plat = pdev->dev.platform_data; | ||
| 1354 | u32 regs_phys; | ||
| 1355 | char phy_id[MII_BUS_ID_SIZE + 3]; | ||
| 1356 | int err; | ||
| 1357 | |||
| 1358 | if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { | ||
| 1359 | pr_err("ixp4xx_eth: bad ptp filter\n"); | ||
| 1360 | return -EINVAL; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | if (!(dev = alloc_etherdev(sizeof(struct port)))) | ||
| 1364 | return -ENOMEM; | ||
| 1365 | |||
| 1366 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
| 1367 | port = netdev_priv(dev); | ||
| 1368 | port->netdev = dev; | ||
| 1369 | port->id = pdev->id; | ||
| 1370 | |||
| 1371 | switch (port->id) { | ||
| 1372 | case IXP4XX_ETH_NPEA: | ||
| 1373 | port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT; | ||
| 1374 | regs_phys = IXP4XX_EthA_BASE_PHYS; | ||
| 1375 | break; | ||
| 1376 | case IXP4XX_ETH_NPEB: | ||
| 1377 | port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; | ||
| 1378 | regs_phys = IXP4XX_EthB_BASE_PHYS; | ||
| 1379 | break; | ||
| 1380 | case IXP4XX_ETH_NPEC: | ||
| 1381 | port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT; | ||
| 1382 | regs_phys = IXP4XX_EthC_BASE_PHYS; | ||
| 1383 | break; | ||
| 1384 | default: | ||
| 1385 | err = -ENODEV; | ||
| 1386 | goto err_free; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | dev->netdev_ops = &ixp4xx_netdev_ops; | ||
| 1390 | dev->ethtool_ops = &ixp4xx_ethtool_ops; | ||
| 1391 | dev->tx_queue_len = 100; | ||
| 1392 | |||
| 1393 | netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT); | ||
| 1394 | |||
| 1395 | if (!(port->npe = npe_request(NPE_ID(port->id)))) { | ||
| 1396 | err = -EIO; | ||
| 1397 | goto err_free; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name); | ||
| 1401 | if (!port->mem_res) { | ||
| 1402 | err = -EBUSY; | ||
| 1403 | goto err_npe_rel; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | port->plat = plat; | ||
| 1407 | npe_port_tab[NPE_ID(port->id)] = port; | ||
| 1408 | memcpy(dev->dev_addr, plat->hwaddr, ETH_ALEN); | ||
| 1409 | |||
| 1410 | platform_set_drvdata(pdev, dev); | ||
| 1411 | |||
| 1412 | __raw_writel(DEFAULT_CORE_CNTRL | CORE_RESET, | ||
| 1413 | &port->regs->core_control); | ||
| 1414 | udelay(50); | ||
| 1415 | __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); | ||
| 1416 | udelay(50); | ||
| 1417 | |||
| 1418 | snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy); | ||
| 1419 | port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, | ||
| 1420 | PHY_INTERFACE_MODE_MII); | ||
| 1421 | if (IS_ERR(port->phydev)) { | ||
| 1422 | err = PTR_ERR(port->phydev); | ||
| 1423 | goto err_free_mem; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | port->phydev->irq = PHY_POLL; | ||
| 1427 | |||
| 1428 | if ((err = register_netdev(dev))) | ||
| 1429 | goto err_phy_dis; | ||
| 1430 | |||
| 1431 | printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, | ||
| 1432 | npe_name(port->npe)); | ||
| 1433 | |||
| 1434 | return 0; | ||
| 1435 | |||
| 1436 | err_phy_dis: | ||
| 1437 | phy_disconnect(port->phydev); | ||
| 1438 | err_free_mem: | ||
| 1439 | npe_port_tab[NPE_ID(port->id)] = NULL; | ||
| 1440 | platform_set_drvdata(pdev, NULL); | ||
| 1441 | release_resource(port->mem_res); | ||
| 1442 | err_npe_rel: | ||
| 1443 | npe_release(port->npe); | ||
| 1444 | err_free: | ||
| 1445 | free_netdev(dev); | ||
| 1446 | return err; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | static int __devexit eth_remove_one(struct platform_device *pdev) | ||
| 1450 | { | ||
| 1451 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1452 | struct port *port = netdev_priv(dev); | ||
| 1453 | |||
| 1454 | unregister_netdev(dev); | ||
| 1455 | phy_disconnect(port->phydev); | ||
| 1456 | npe_port_tab[NPE_ID(port->id)] = NULL; | ||
| 1457 | platform_set_drvdata(pdev, NULL); | ||
| 1458 | npe_release(port->npe); | ||
| 1459 | release_resource(port->mem_res); | ||
| 1460 | free_netdev(dev); | ||
| 1461 | return 0; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | static struct platform_driver ixp4xx_eth_driver = { | ||
| 1465 | .driver.name = DRV_NAME, | ||
| 1466 | .probe = eth_init_one, | ||
| 1467 | .remove = eth_remove_one, | ||
| 1468 | }; | ||
| 1469 | |||
| 1470 | static int __init eth_init_module(void) | ||
| 1471 | { | ||
| 1472 | int err; | ||
| 1473 | if ((err = ixp4xx_mdio_register())) | ||
| 1474 | return err; | ||
| 1475 | return platform_driver_register(&ixp4xx_eth_driver); | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | static void __exit eth_cleanup_module(void) | ||
| 1479 | { | ||
| 1480 | platform_driver_unregister(&ixp4xx_eth_driver); | ||
| 1481 | ixp4xx_mdio_remove(); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | MODULE_AUTHOR("Krzysztof Halasa"); | ||
| 1485 | MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver"); | ||
| 1486 | MODULE_LICENSE("GPL v2"); | ||
| 1487 | MODULE_ALIAS("platform:ixp4xx_eth"); | ||
| 1488 | module_init(eth_init_module); | ||
| 1489 | module_exit(eth_cleanup_module); | ||
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c new file mode 100644 index 00000000000..c827a6097d0 --- /dev/null +++ b/drivers/net/arm/ks8695net.c | |||
| @@ -0,0 +1,1656 @@ | |||
| 1 | /* | ||
| 2 | * Micrel KS8695 (Centaur) Ethernet. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation; either version 2 of the | ||
| 7 | * License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * Copyright 2008 Simtec Electronics | ||
| 15 | * Daniel Silverstone <dsilvers@simtec.co.uk> | ||
| 16 | * Vincent Sanders <vince@simtec.co.uk> | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/dma-mapping.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/ioport.h> | ||
| 22 | #include <linux/netdevice.h> | ||
| 23 | #include <linux/etherdevice.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/skbuff.h> | ||
| 27 | #include <linux/spinlock.h> | ||
| 28 | #include <linux/crc32.h> | ||
| 29 | #include <linux/mii.h> | ||
| 30 | #include <linux/ethtool.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/irq.h> | ||
| 34 | #include <linux/io.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | |||
| 37 | #include <asm/irq.h> | ||
| 38 | |||
| 39 | #include <mach/regs-switch.h> | ||
| 40 | #include <mach/regs-misc.h> | ||
| 41 | #include <asm/mach/irq.h> | ||
| 42 | #include <mach/regs-irq.h> | ||
| 43 | |||
| 44 | #include "ks8695net.h" | ||
| 45 | |||
| 46 | #define MODULENAME "ks8695_ether" | ||
| 47 | #define MODULEVERSION "1.02" | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Transmit and device reset timeout, default 5 seconds. | ||
| 51 | */ | ||
| 52 | static int watchdog = 5000; | ||
| 53 | |||
| 54 | /* Hardware structures */ | ||
| 55 | |||
| 56 | /** | ||
| 57 | * struct rx_ring_desc - Receive descriptor ring element | ||
| 58 | * @status: The status of the descriptor element (E.g. who owns it) | ||
| 59 | * @length: The number of bytes in the block pointed to by data_ptr | ||
| 60 | * @data_ptr: The physical address of the data block to receive into | ||
| 61 | * @next_desc: The physical address of the next descriptor element. | ||
| 62 | */ | ||
| 63 | struct rx_ring_desc { | ||
| 64 | __le32 status; | ||
| 65 | __le32 length; | ||
| 66 | __le32 data_ptr; | ||
| 67 | __le32 next_desc; | ||
| 68 | }; | ||
| 69 | |||
| 70 | /** | ||
| 71 | * struct tx_ring_desc - Transmit descriptor ring element | ||
| 72 | * @owner: Who owns the descriptor | ||
| 73 | * @status: The number of bytes in the block pointed to by data_ptr | ||
| 74 | * @data_ptr: The physical address of the data block to receive into | ||
| 75 | * @next_desc: The physical address of the next descriptor element. | ||
| 76 | */ | ||
| 77 | struct tx_ring_desc { | ||
| 78 | __le32 owner; | ||
| 79 | __le32 status; | ||
| 80 | __le32 data_ptr; | ||
| 81 | __le32 next_desc; | ||
| 82 | }; | ||
| 83 | |||
| 84 | /** | ||
| 85 | * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings. | ||
| 86 | * @skb: The buffer in the ring | ||
| 87 | * @dma_ptr: The mapped DMA pointer of the buffer | ||
| 88 | * @length: The number of bytes mapped to dma_ptr | ||
| 89 | */ | ||
| 90 | struct ks8695_skbuff { | ||
| 91 | struct sk_buff *skb; | ||
| 92 | dma_addr_t dma_ptr; | ||
| 93 | u32 length; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* Private device structure */ | ||
| 97 | |||
| 98 | #define MAX_TX_DESC 8 | ||
| 99 | #define MAX_TX_DESC_MASK 0x7 | ||
| 100 | #define MAX_RX_DESC 16 | ||
| 101 | #define MAX_RX_DESC_MASK 0xf | ||
| 102 | |||
| 103 | /*napi_weight have better more than rx DMA buffers*/ | ||
| 104 | #define NAPI_WEIGHT 64 | ||
| 105 | |||
| 106 | #define MAX_RXBUF_SIZE 0x700 | ||
| 107 | |||
| 108 | #define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC) | ||
| 109 | #define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC) | ||
| 110 | #define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE) | ||
| 111 | |||
| 112 | /** | ||
| 113 | * enum ks8695_dtype - Device type | ||
| 114 | * @KS8695_DTYPE_WAN: This device is a WAN interface | ||
| 115 | * @KS8695_DTYPE_LAN: This device is a LAN interface | ||
| 116 | * @KS8695_DTYPE_HPNA: This device is an HPNA interface | ||
| 117 | */ | ||
| 118 | enum ks8695_dtype { | ||
| 119 | KS8695_DTYPE_WAN, | ||
| 120 | KS8695_DTYPE_LAN, | ||
| 121 | KS8695_DTYPE_HPNA, | ||
| 122 | }; | ||
| 123 | |||
| 124 | /** | ||
| 125 | * struct ks8695_priv - Private data for the KS8695 Ethernet | ||
| 126 | * @in_suspend: Flag to indicate if we're suspending/resuming | ||
| 127 | * @ndev: The net_device for this interface | ||
| 128 | * @dev: The platform device object for this interface | ||
| 129 | * @dtype: The type of this device | ||
| 130 | * @io_regs: The ioremapped registers for this interface | ||
| 131 | * @napi : Add support NAPI for Rx | ||
| 132 | * @rx_irq_name: The textual name of the RX IRQ from the platform data | ||
| 133 | * @tx_irq_name: The textual name of the TX IRQ from the platform data | ||
| 134 | * @link_irq_name: The textual name of the link IRQ from the | ||
| 135 | * platform data if available | ||
| 136 | * @rx_irq: The IRQ number for the RX IRQ | ||
| 137 | * @tx_irq: The IRQ number for the TX IRQ | ||
| 138 | * @link_irq: The IRQ number for the link IRQ if available | ||
| 139 | * @regs_req: The resource request for the registers region | ||
| 140 | * @phyiface_req: The resource request for the phy/switch region | ||
| 141 | * if available | ||
| 142 | * @phyiface_regs: The ioremapped registers for the phy/switch if available | ||
| 143 | * @ring_base: The base pointer of the dma coherent memory for the rings | ||
| 144 | * @ring_base_dma: The DMA mapped equivalent of ring_base | ||
| 145 | * @tx_ring: The pointer in ring_base of the TX ring | ||
| 146 | * @tx_ring_used: The number of slots in the TX ring which are occupied | ||
| 147 | * @tx_ring_next_slot: The next slot to fill in the TX ring | ||
| 148 | * @tx_ring_dma: The DMA mapped equivalent of tx_ring | ||
| 149 | * @tx_buffers: The sk_buff mappings for the TX ring | ||
| 150 | * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables | ||
| 151 | * @rx_ring: The pointer in ring_base of the RX ring | ||
| 152 | * @rx_ring_dma: The DMA mapped equivalent of rx_ring | ||
| 153 | * @rx_buffers: The sk_buff mappings for the RX ring | ||
| 154 | * @next_rx_desc_read: The next RX descriptor to read from on IRQ | ||
| 155 | * @rx_lock: A lock to protect Rx irq function | ||
| 156 | * @msg_enable: The flags for which messages to emit | ||
| 157 | */ | ||
| 158 | struct ks8695_priv { | ||
| 159 | int in_suspend; | ||
| 160 | struct net_device *ndev; | ||
| 161 | struct device *dev; | ||
| 162 | enum ks8695_dtype dtype; | ||
| 163 | void __iomem *io_regs; | ||
| 164 | |||
| 165 | struct napi_struct napi; | ||
| 166 | |||
| 167 | const char *rx_irq_name, *tx_irq_name, *link_irq_name; | ||
| 168 | int rx_irq, tx_irq, link_irq; | ||
| 169 | |||
| 170 | struct resource *regs_req, *phyiface_req; | ||
| 171 | void __iomem *phyiface_regs; | ||
| 172 | |||
| 173 | void *ring_base; | ||
| 174 | dma_addr_t ring_base_dma; | ||
| 175 | |||
| 176 | struct tx_ring_desc *tx_ring; | ||
| 177 | int tx_ring_used; | ||
| 178 | int tx_ring_next_slot; | ||
| 179 | dma_addr_t tx_ring_dma; | ||
| 180 | struct ks8695_skbuff tx_buffers[MAX_TX_DESC]; | ||
| 181 | spinlock_t txq_lock; | ||
| 182 | |||
| 183 | struct rx_ring_desc *rx_ring; | ||
| 184 | dma_addr_t rx_ring_dma; | ||
| 185 | struct ks8695_skbuff rx_buffers[MAX_RX_DESC]; | ||
| 186 | int next_rx_desc_read; | ||
| 187 | spinlock_t rx_lock; | ||
| 188 | |||
| 189 | int msg_enable; | ||
| 190 | }; | ||
| 191 | |||
| 192 | /* Register access */ | ||
| 193 | |||
| 194 | /** | ||
| 195 | * ks8695_readreg - Read from a KS8695 ethernet register | ||
| 196 | * @ksp: The device to read from | ||
| 197 | * @reg: The register to read | ||
| 198 | */ | ||
| 199 | static inline u32 | ||
| 200 | ks8695_readreg(struct ks8695_priv *ksp, int reg) | ||
| 201 | { | ||
| 202 | return readl(ksp->io_regs + reg); | ||
| 203 | } | ||
| 204 | |||
| 205 | /** | ||
| 206 | * ks8695_writereg - Write to a KS8695 ethernet register | ||
| 207 | * @ksp: The device to write to | ||
| 208 | * @reg: The register to write | ||
| 209 | * @value: The value to write to the register | ||
| 210 | */ | ||
| 211 | static inline void | ||
| 212 | ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value) | ||
| 213 | { | ||
| 214 | writel(value, ksp->io_regs + reg); | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Utility functions */ | ||
| 218 | |||
| 219 | /** | ||
| 220 | * ks8695_port_type - Retrieve port-type as user-friendly string | ||
| 221 | * @ksp: The device to return the type for | ||
| 222 | * | ||
| 223 | * Returns a string indicating which of the WAN, LAN or HPNA | ||
| 224 | * ports this device is likely to represent. | ||
| 225 | */ | ||
| 226 | static const char * | ||
| 227 | ks8695_port_type(struct ks8695_priv *ksp) | ||
| 228 | { | ||
| 229 | switch (ksp->dtype) { | ||
| 230 | case KS8695_DTYPE_LAN: | ||
| 231 | return "LAN"; | ||
| 232 | case KS8695_DTYPE_WAN: | ||
| 233 | return "WAN"; | ||
| 234 | case KS8695_DTYPE_HPNA: | ||
| 235 | return "HPNA"; | ||
| 236 | } | ||
| 237 | |||
| 238 | return "UNKNOWN"; | ||
| 239 | } | ||
| 240 | |||
| 241 | /** | ||
| 242 | * ks8695_update_mac - Update the MAC registers in the device | ||
| 243 | * @ksp: The device to update | ||
| 244 | * | ||
| 245 | * Updates the MAC registers in the KS8695 device from the address in the | ||
| 246 | * net_device structure associated with this interface. | ||
| 247 | */ | ||
| 248 | static void | ||
| 249 | ks8695_update_mac(struct ks8695_priv *ksp) | ||
| 250 | { | ||
| 251 | /* Update the HW with the MAC from the net_device */ | ||
| 252 | struct net_device *ndev = ksp->ndev; | ||
| 253 | u32 machigh, maclow; | ||
| 254 | |||
| 255 | maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) | | ||
| 256 | (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0)); | ||
| 257 | machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0)); | ||
| 258 | |||
| 259 | ks8695_writereg(ksp, KS8695_MAL, maclow); | ||
| 260 | ks8695_writereg(ksp, KS8695_MAH, machigh); | ||
| 261 | |||
| 262 | } | ||
| 263 | |||
| 264 | /** | ||
| 265 | * ks8695_refill_rxbuffers - Re-fill the RX buffer ring | ||
| 266 | * @ksp: The device to refill | ||
| 267 | * | ||
| 268 | * Iterates the RX ring of the device looking for empty slots. | ||
| 269 | * For each empty slot, we allocate and map a new SKB and give it | ||
| 270 | * to the hardware. | ||
| 271 | * This can be called from interrupt context safely. | ||
| 272 | */ | ||
| 273 | static void | ||
| 274 | ks8695_refill_rxbuffers(struct ks8695_priv *ksp) | ||
| 275 | { | ||
| 276 | /* Run around the RX ring, filling in any missing sk_buff's */ | ||
| 277 | int buff_n; | ||
| 278 | |||
| 279 | for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { | ||
| 280 | if (!ksp->rx_buffers[buff_n].skb) { | ||
| 281 | struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE); | ||
| 282 | dma_addr_t mapping; | ||
| 283 | |||
| 284 | ksp->rx_buffers[buff_n].skb = skb; | ||
| 285 | if (skb == NULL) { | ||
| 286 | /* Failed to allocate one, perhaps | ||
| 287 | * we'll try again later. | ||
| 288 | */ | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | |||
| 292 | mapping = dma_map_single(ksp->dev, skb->data, | ||
| 293 | MAX_RXBUF_SIZE, | ||
| 294 | DMA_FROM_DEVICE); | ||
| 295 | if (unlikely(dma_mapping_error(ksp->dev, mapping))) { | ||
| 296 | /* Failed to DMA map this SKB, try later */ | ||
| 297 | dev_kfree_skb_irq(skb); | ||
| 298 | ksp->rx_buffers[buff_n].skb = NULL; | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | ksp->rx_buffers[buff_n].dma_ptr = mapping; | ||
| 302 | skb->dev = ksp->ndev; | ||
| 303 | ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE; | ||
| 304 | |||
| 305 | /* Record this into the DMA ring */ | ||
| 306 | ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping); | ||
| 307 | ksp->rx_ring[buff_n].length = | ||
| 308 | cpu_to_le32(MAX_RXBUF_SIZE); | ||
| 309 | |||
| 310 | wmb(); | ||
| 311 | |||
| 312 | /* And give ownership over to the hardware */ | ||
| 313 | ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | /* Maximum number of multicast addresses which the KS8695 HW supports */ | ||
| 319 | #define KS8695_NR_ADDRESSES 16 | ||
| 320 | |||
| 321 | /** | ||
| 322 | * ks8695_init_partial_multicast - Init the mcast addr registers | ||
| 323 | * @ksp: The device to initialise | ||
| 324 | * @addr: The multicast address list to use | ||
| 325 | * @nr_addr: The number of addresses in the list | ||
| 326 | * | ||
| 327 | * This routine is a helper for ks8695_set_multicast - it writes | ||
| 328 | * the additional-address registers in the KS8695 ethernet device | ||
| 329 | * and cleans up any others left behind. | ||
| 330 | */ | ||
| 331 | static void | ||
| 332 | ks8695_init_partial_multicast(struct ks8695_priv *ksp, | ||
| 333 | struct net_device *ndev) | ||
| 334 | { | ||
| 335 | u32 low, high; | ||
| 336 | int i; | ||
| 337 | struct netdev_hw_addr *ha; | ||
| 338 | |||
| 339 | i = 0; | ||
| 340 | netdev_for_each_mc_addr(ha, ndev) { | ||
| 341 | /* Ran out of space in chip? */ | ||
| 342 | BUG_ON(i == KS8695_NR_ADDRESSES); | ||
| 343 | |||
| 344 | low = (ha->addr[2] << 24) | (ha->addr[3] << 16) | | ||
| 345 | (ha->addr[4] << 8) | (ha->addr[5]); | ||
| 346 | high = (ha->addr[0] << 8) | (ha->addr[1]); | ||
| 347 | |||
| 348 | ks8695_writereg(ksp, KS8695_AAL_(i), low); | ||
| 349 | ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high); | ||
| 350 | i++; | ||
| 351 | } | ||
| 352 | |||
| 353 | /* Clear the remaining Additional Station Addresses */ | ||
| 354 | for (; i < KS8695_NR_ADDRESSES; i++) { | ||
| 355 | ks8695_writereg(ksp, KS8695_AAL_(i), 0); | ||
| 356 | ks8695_writereg(ksp, KS8695_AAH_(i), 0); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | /* Interrupt handling */ | ||
| 361 | |||
| 362 | /** | ||
| 363 | * ks8695_tx_irq - Transmit IRQ handler | ||
| 364 | * @irq: The IRQ which went off (ignored) | ||
| 365 | * @dev_id: The net_device for the interrupt | ||
| 366 | * | ||
| 367 | * Process the TX ring, clearing out any transmitted slots. | ||
| 368 | * Allows the net_device to pass us new packets once slots are | ||
| 369 | * freed. | ||
| 370 | */ | ||
| 371 | static irqreturn_t | ||
| 372 | ks8695_tx_irq(int irq, void *dev_id) | ||
| 373 | { | ||
| 374 | struct net_device *ndev = (struct net_device *)dev_id; | ||
| 375 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 376 | int buff_n; | ||
| 377 | |||
| 378 | for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { | ||
| 379 | if (ksp->tx_buffers[buff_n].skb && | ||
| 380 | !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) { | ||
| 381 | rmb(); | ||
| 382 | /* An SKB which is not owned by HW is present */ | ||
| 383 | /* Update the stats for the net_device */ | ||
| 384 | ndev->stats.tx_packets++; | ||
| 385 | ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length; | ||
| 386 | |||
| 387 | /* Free the packet from the ring */ | ||
| 388 | ksp->tx_ring[buff_n].data_ptr = 0; | ||
| 389 | |||
| 390 | /* Free the sk_buff */ | ||
| 391 | dma_unmap_single(ksp->dev, | ||
| 392 | ksp->tx_buffers[buff_n].dma_ptr, | ||
| 393 | ksp->tx_buffers[buff_n].length, | ||
| 394 | DMA_TO_DEVICE); | ||
| 395 | dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb); | ||
| 396 | ksp->tx_buffers[buff_n].skb = NULL; | ||
| 397 | ksp->tx_ring_used--; | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | netif_wake_queue(ndev); | ||
| 402 | |||
| 403 | return IRQ_HANDLED; | ||
| 404 | } | ||
| 405 | |||
| 406 | /** | ||
| 407 | * ks8695_get_rx_enable_bit - Get rx interrupt enable/status bit | ||
| 408 | * @ksp: Private data for the KS8695 Ethernet | ||
| 409 | * | ||
| 410 | * For KS8695 document: | ||
| 411 | * Interrupt Enable Register (offset 0xE204) | ||
| 412 | * Bit29 : WAN MAC Receive Interrupt Enable | ||
| 413 | * Bit16 : LAN MAC Receive Interrupt Enable | ||
| 414 | * Interrupt Status Register (Offset 0xF208) | ||
| 415 | * Bit29: WAN MAC Receive Status | ||
| 416 | * Bit16: LAN MAC Receive Status | ||
| 417 | * So, this Rx interrrupt enable/status bit number is equal | ||
| 418 | * as Rx IRQ number. | ||
| 419 | */ | ||
| 420 | static inline u32 ks8695_get_rx_enable_bit(struct ks8695_priv *ksp) | ||
| 421 | { | ||
| 422 | return ksp->rx_irq; | ||
| 423 | } | ||
| 424 | |||
| 425 | /** | ||
| 426 | * ks8695_rx_irq - Receive IRQ handler | ||
| 427 | * @irq: The IRQ which went off (ignored) | ||
| 428 | * @dev_id: The net_device for the interrupt | ||
| 429 | * | ||
| 430 | * Inform NAPI that packet reception needs to be scheduled | ||
| 431 | */ | ||
| 432 | |||
| 433 | static irqreturn_t | ||
| 434 | ks8695_rx_irq(int irq, void *dev_id) | ||
| 435 | { | ||
| 436 | struct net_device *ndev = (struct net_device *)dev_id; | ||
| 437 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 438 | |||
| 439 | spin_lock(&ksp->rx_lock); | ||
| 440 | |||
| 441 | if (napi_schedule_prep(&ksp->napi)) { | ||
| 442 | unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN); | ||
| 443 | unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp); | ||
| 444 | /*disable rx interrupt*/ | ||
| 445 | status &= ~mask_bit; | ||
| 446 | writel(status , KS8695_IRQ_VA + KS8695_INTEN); | ||
| 447 | __napi_schedule(&ksp->napi); | ||
| 448 | } | ||
| 449 | |||
| 450 | spin_unlock(&ksp->rx_lock); | ||
| 451 | return IRQ_HANDLED; | ||
| 452 | } | ||
| 453 | |||
| 454 | /** | ||
| 455 | * ks8695_rx - Receive packets called by NAPI poll method | ||
| 456 | * @ksp: Private data for the KS8695 Ethernet | ||
| 457 | * @budget: Number of packets allowed to process | ||
| 458 | */ | ||
| 459 | static int ks8695_rx(struct ks8695_priv *ksp, int budget) | ||
| 460 | { | ||
| 461 | struct net_device *ndev = ksp->ndev; | ||
| 462 | struct sk_buff *skb; | ||
| 463 | int buff_n; | ||
| 464 | u32 flags; | ||
| 465 | int pktlen; | ||
| 466 | int received = 0; | ||
| 467 | |||
| 468 | buff_n = ksp->next_rx_desc_read; | ||
| 469 | while (received < budget | ||
| 470 | && ksp->rx_buffers[buff_n].skb | ||
| 471 | && (!(ksp->rx_ring[buff_n].status & | ||
| 472 | cpu_to_le32(RDES_OWN)))) { | ||
| 473 | rmb(); | ||
| 474 | flags = le32_to_cpu(ksp->rx_ring[buff_n].status); | ||
| 475 | |||
| 476 | /* Found an SKB which we own, this means we | ||
| 477 | * received a packet | ||
| 478 | */ | ||
| 479 | if ((flags & (RDES_FS | RDES_LS)) != | ||
| 480 | (RDES_FS | RDES_LS)) { | ||
| 481 | /* This packet is not the first and | ||
| 482 | * the last segment. Therefore it is | ||
| 483 | * a "spanning" packet and we can't | ||
| 484 | * handle it | ||
| 485 | */ | ||
| 486 | goto rx_failure; | ||
| 487 | } | ||
| 488 | |||
| 489 | if (flags & (RDES_ES | RDES_RE)) { | ||
| 490 | /* It's an error packet */ | ||
| 491 | ndev->stats.rx_errors++; | ||
| 492 | if (flags & RDES_TL) | ||
| 493 | ndev->stats.rx_length_errors++; | ||
| 494 | if (flags & RDES_RF) | ||
| 495 | ndev->stats.rx_length_errors++; | ||
| 496 | if (flags & RDES_CE) | ||
| 497 | ndev->stats.rx_crc_errors++; | ||
| 498 | if (flags & RDES_RE) | ||
| 499 | ndev->stats.rx_missed_errors++; | ||
| 500 | |||
| 501 | goto rx_failure; | ||
| 502 | } | ||
| 503 | |||
| 504 | pktlen = flags & RDES_FLEN; | ||
| 505 | pktlen -= 4; /* Drop the CRC */ | ||
| 506 | |||
| 507 | /* Retrieve the sk_buff */ | ||
| 508 | skb = ksp->rx_buffers[buff_n].skb; | ||
| 509 | |||
| 510 | /* Clear it from the ring */ | ||
| 511 | ksp->rx_buffers[buff_n].skb = NULL; | ||
| 512 | ksp->rx_ring[buff_n].data_ptr = 0; | ||
| 513 | |||
| 514 | /* Unmap the SKB */ | ||
| 515 | dma_unmap_single(ksp->dev, | ||
| 516 | ksp->rx_buffers[buff_n].dma_ptr, | ||
| 517 | ksp->rx_buffers[buff_n].length, | ||
| 518 | DMA_FROM_DEVICE); | ||
| 519 | |||
| 520 | /* Relinquish the SKB to the network layer */ | ||
| 521 | skb_put(skb, pktlen); | ||
| 522 | skb->protocol = eth_type_trans(skb, ndev); | ||
| 523 | netif_receive_skb(skb); | ||
| 524 | |||
| 525 | /* Record stats */ | ||
| 526 | ndev->stats.rx_packets++; | ||
| 527 | ndev->stats.rx_bytes += pktlen; | ||
| 528 | goto rx_finished; | ||
| 529 | |||
| 530 | rx_failure: | ||
| 531 | /* This ring entry is an error, but we can | ||
| 532 | * re-use the skb | ||
| 533 | */ | ||
| 534 | /* Give the ring entry back to the hardware */ | ||
| 535 | ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN); | ||
| 536 | rx_finished: | ||
| 537 | received++; | ||
| 538 | buff_n = (buff_n + 1) & MAX_RX_DESC_MASK; | ||
| 539 | } | ||
| 540 | |||
| 541 | /* And note which RX descriptor we last did */ | ||
| 542 | ksp->next_rx_desc_read = buff_n; | ||
| 543 | |||
| 544 | /* And refill the buffers */ | ||
| 545 | ks8695_refill_rxbuffers(ksp); | ||
| 546 | |||
| 547 | /* Kick the RX DMA engine, in case it became suspended */ | ||
| 548 | ks8695_writereg(ksp, KS8695_DRSC, 0); | ||
| 549 | |||
| 550 | return received; | ||
| 551 | } | ||
| 552 | |||
| 553 | |||
| 554 | /** | ||
| 555 | * ks8695_poll - Receive packet by NAPI poll method | ||
| 556 | * @ksp: Private data for the KS8695 Ethernet | ||
| 557 | * @budget: The remaining number packets for network subsystem | ||
| 558 | * | ||
| 559 | * Invoked by the network core when it requests for new | ||
| 560 | * packets from the driver | ||
| 561 | */ | ||
| 562 | static int ks8695_poll(struct napi_struct *napi, int budget) | ||
| 563 | { | ||
| 564 | struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi); | ||
| 565 | unsigned long work_done; | ||
| 566 | |||
| 567 | unsigned long isr = readl(KS8695_IRQ_VA + KS8695_INTEN); | ||
| 568 | unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp); | ||
| 569 | |||
| 570 | work_done = ks8695_rx(ksp, budget); | ||
| 571 | |||
| 572 | if (work_done < budget) { | ||
| 573 | unsigned long flags; | ||
| 574 | spin_lock_irqsave(&ksp->rx_lock, flags); | ||
| 575 | __napi_complete(napi); | ||
| 576 | /*enable rx interrupt*/ | ||
| 577 | writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN); | ||
| 578 | spin_unlock_irqrestore(&ksp->rx_lock, flags); | ||
| 579 | } | ||
| 580 | return work_done; | ||
| 581 | } | ||
| 582 | |||
| 583 | /** | ||
| 584 | * ks8695_link_irq - Link change IRQ handler | ||
| 585 | * @irq: The IRQ which went off (ignored) | ||
| 586 | * @dev_id: The net_device for the interrupt | ||
| 587 | * | ||
| 588 | * The WAN interface can generate an IRQ when the link changes, | ||
| 589 | * report this to the net layer and the user. | ||
| 590 | */ | ||
| 591 | static irqreturn_t | ||
| 592 | ks8695_link_irq(int irq, void *dev_id) | ||
| 593 | { | ||
| 594 | struct net_device *ndev = (struct net_device *)dev_id; | ||
| 595 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 596 | u32 ctrl; | ||
| 597 | |||
| 598 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 599 | if (ctrl & WMC_WLS) { | ||
| 600 | netif_carrier_on(ndev); | ||
| 601 | if (netif_msg_link(ksp)) | ||
| 602 | dev_info(ksp->dev, | ||
| 603 | "%s: Link is now up (10%sMbps/%s-duplex)\n", | ||
| 604 | ndev->name, | ||
| 605 | (ctrl & WMC_WSS) ? "0" : "", | ||
| 606 | (ctrl & WMC_WDS) ? "Full" : "Half"); | ||
| 607 | } else { | ||
| 608 | netif_carrier_off(ndev); | ||
| 609 | if (netif_msg_link(ksp)) | ||
| 610 | dev_info(ksp->dev, "%s: Link is now down.\n", | ||
| 611 | ndev->name); | ||
| 612 | } | ||
| 613 | |||
| 614 | return IRQ_HANDLED; | ||
| 615 | } | ||
| 616 | |||
| 617 | |||
| 618 | /* KS8695 Device functions */ | ||
| 619 | |||
| 620 | /** | ||
| 621 | * ks8695_reset - Reset a KS8695 ethernet interface | ||
| 622 | * @ksp: The interface to reset | ||
| 623 | * | ||
| 624 | * Perform an engine reset of the interface and re-program it | ||
| 625 | * with sensible defaults. | ||
| 626 | */ | ||
| 627 | static void | ||
| 628 | ks8695_reset(struct ks8695_priv *ksp) | ||
| 629 | { | ||
| 630 | int reset_timeout = watchdog; | ||
| 631 | /* Issue the reset via the TX DMA control register */ | ||
| 632 | ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST); | ||
| 633 | while (reset_timeout--) { | ||
| 634 | if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST)) | ||
| 635 | break; | ||
| 636 | msleep(1); | ||
| 637 | } | ||
| 638 | |||
| 639 | if (reset_timeout < 0) { | ||
| 640 | dev_crit(ksp->dev, | ||
| 641 | "Timeout waiting for DMA engines to reset\n"); | ||
| 642 | /* And blithely carry on */ | ||
| 643 | } | ||
| 644 | |||
| 645 | /* Definitely wait long enough before attempting to program | ||
| 646 | * the engines | ||
| 647 | */ | ||
| 648 | msleep(10); | ||
| 649 | |||
| 650 | /* RX: unicast and broadcast */ | ||
| 651 | ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB); | ||
| 652 | /* TX: pad and add CRC */ | ||
| 653 | ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC); | ||
| 654 | } | ||
| 655 | |||
| 656 | /** | ||
| 657 | * ks8695_shutdown - Shut down a KS8695 ethernet interface | ||
| 658 | * @ksp: The interface to shut down | ||
| 659 | * | ||
| 660 | * This disables packet RX/TX, cleans up IRQs, drains the rings, | ||
| 661 | * and basically places the interface into a clean shutdown | ||
| 662 | * state. | ||
| 663 | */ | ||
| 664 | static void | ||
| 665 | ks8695_shutdown(struct ks8695_priv *ksp) | ||
| 666 | { | ||
| 667 | u32 ctrl; | ||
| 668 | int buff_n; | ||
| 669 | |||
| 670 | /* Disable packet transmission */ | ||
| 671 | ctrl = ks8695_readreg(ksp, KS8695_DTXC); | ||
| 672 | ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE); | ||
| 673 | |||
| 674 | /* Disable packet reception */ | ||
| 675 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); | ||
| 676 | ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE); | ||
| 677 | |||
| 678 | /* Release the IRQs */ | ||
| 679 | free_irq(ksp->rx_irq, ksp->ndev); | ||
| 680 | free_irq(ksp->tx_irq, ksp->ndev); | ||
| 681 | if (ksp->link_irq != -1) | ||
| 682 | free_irq(ksp->link_irq, ksp->ndev); | ||
| 683 | |||
| 684 | /* Throw away any pending TX packets */ | ||
| 685 | for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { | ||
| 686 | if (ksp->tx_buffers[buff_n].skb) { | ||
| 687 | /* Remove this SKB from the TX ring */ | ||
| 688 | ksp->tx_ring[buff_n].owner = 0; | ||
| 689 | ksp->tx_ring[buff_n].status = 0; | ||
| 690 | ksp->tx_ring[buff_n].data_ptr = 0; | ||
| 691 | |||
| 692 | /* Unmap and bin this SKB */ | ||
| 693 | dma_unmap_single(ksp->dev, | ||
| 694 | ksp->tx_buffers[buff_n].dma_ptr, | ||
| 695 | ksp->tx_buffers[buff_n].length, | ||
| 696 | DMA_TO_DEVICE); | ||
| 697 | dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb); | ||
| 698 | ksp->tx_buffers[buff_n].skb = NULL; | ||
| 699 | } | ||
| 700 | } | ||
| 701 | |||
| 702 | /* Purge the RX buffers */ | ||
| 703 | for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { | ||
| 704 | if (ksp->rx_buffers[buff_n].skb) { | ||
| 705 | /* Remove the SKB from the RX ring */ | ||
| 706 | ksp->rx_ring[buff_n].status = 0; | ||
| 707 | ksp->rx_ring[buff_n].data_ptr = 0; | ||
| 708 | |||
| 709 | /* Unmap and bin the SKB */ | ||
| 710 | dma_unmap_single(ksp->dev, | ||
| 711 | ksp->rx_buffers[buff_n].dma_ptr, | ||
| 712 | ksp->rx_buffers[buff_n].length, | ||
| 713 | DMA_FROM_DEVICE); | ||
| 714 | dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb); | ||
| 715 | ksp->rx_buffers[buff_n].skb = NULL; | ||
| 716 | } | ||
| 717 | } | ||
| 718 | } | ||
| 719 | |||
| 720 | |||
| 721 | /** | ||
| 722 | * ks8695_setup_irq - IRQ setup helper function | ||
| 723 | * @irq: The IRQ number to claim | ||
| 724 | * @irq_name: The name to give the IRQ claimant | ||
| 725 | * @handler: The function to call to handle the IRQ | ||
| 726 | * @ndev: The net_device to pass in as the dev_id argument to the handler | ||
| 727 | * | ||
| 728 | * Return 0 on success. | ||
| 729 | */ | ||
| 730 | static int | ||
| 731 | ks8695_setup_irq(int irq, const char *irq_name, | ||
| 732 | irq_handler_t handler, struct net_device *ndev) | ||
| 733 | { | ||
| 734 | int ret; | ||
| 735 | |||
| 736 | ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev); | ||
| 737 | |||
| 738 | if (ret) { | ||
| 739 | dev_err(&ndev->dev, "failure to request IRQ %d\n", irq); | ||
| 740 | return ret; | ||
| 741 | } | ||
| 742 | |||
| 743 | return 0; | ||
| 744 | } | ||
| 745 | |||
| 746 | /** | ||
| 747 | * ks8695_init_net - Initialise a KS8695 ethernet interface | ||
| 748 | * @ksp: The interface to initialise | ||
| 749 | * | ||
| 750 | * This routine fills the RX ring, initialises the DMA engines, | ||
| 751 | * allocates the IRQs and then starts the packet TX and RX | ||
| 752 | * engines. | ||
| 753 | */ | ||
| 754 | static int | ||
| 755 | ks8695_init_net(struct ks8695_priv *ksp) | ||
| 756 | { | ||
| 757 | int ret; | ||
| 758 | u32 ctrl; | ||
| 759 | |||
| 760 | ks8695_refill_rxbuffers(ksp); | ||
| 761 | |||
| 762 | /* Initialise the DMA engines */ | ||
| 763 | ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma); | ||
| 764 | ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma); | ||
| 765 | |||
| 766 | /* Request the IRQs */ | ||
| 767 | ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name, | ||
| 768 | ks8695_rx_irq, ksp->ndev); | ||
| 769 | if (ret) | ||
| 770 | return ret; | ||
| 771 | ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name, | ||
| 772 | ks8695_tx_irq, ksp->ndev); | ||
| 773 | if (ret) | ||
| 774 | return ret; | ||
| 775 | if (ksp->link_irq != -1) { | ||
| 776 | ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name, | ||
| 777 | ks8695_link_irq, ksp->ndev); | ||
| 778 | if (ret) | ||
| 779 | return ret; | ||
| 780 | } | ||
| 781 | |||
| 782 | /* Set up the ring indices */ | ||
| 783 | ksp->next_rx_desc_read = 0; | ||
| 784 | ksp->tx_ring_next_slot = 0; | ||
| 785 | ksp->tx_ring_used = 0; | ||
| 786 | |||
| 787 | /* Bring up transmission */ | ||
| 788 | ctrl = ks8695_readreg(ksp, KS8695_DTXC); | ||
| 789 | /* Enable packet transmission */ | ||
| 790 | ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE); | ||
| 791 | |||
| 792 | /* Bring up the reception */ | ||
| 793 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); | ||
| 794 | /* Enable packet reception */ | ||
| 795 | ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE); | ||
| 796 | /* And start the DMA engine */ | ||
| 797 | ks8695_writereg(ksp, KS8695_DRSC, 0); | ||
| 798 | |||
| 799 | /* All done */ | ||
| 800 | return 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | /** | ||
| 804 | * ks8695_release_device - HW resource release for KS8695 e-net | ||
| 805 | * @ksp: The device to be freed | ||
| 806 | * | ||
| 807 | * This unallocates io memory regions, dma-coherent regions etc | ||
| 808 | * which were allocated in ks8695_probe. | ||
| 809 | */ | ||
| 810 | static void | ||
| 811 | ks8695_release_device(struct ks8695_priv *ksp) | ||
| 812 | { | ||
| 813 | /* Unmap the registers */ | ||
| 814 | iounmap(ksp->io_regs); | ||
| 815 | if (ksp->phyiface_regs) | ||
| 816 | iounmap(ksp->phyiface_regs); | ||
| 817 | |||
| 818 | /* And release the request */ | ||
| 819 | release_resource(ksp->regs_req); | ||
| 820 | kfree(ksp->regs_req); | ||
| 821 | if (ksp->phyiface_req) { | ||
| 822 | release_resource(ksp->phyiface_req); | ||
| 823 | kfree(ksp->phyiface_req); | ||
| 824 | } | ||
| 825 | |||
| 826 | /* Free the ring buffers */ | ||
| 827 | dma_free_coherent(ksp->dev, RING_DMA_SIZE, | ||
| 828 | ksp->ring_base, ksp->ring_base_dma); | ||
| 829 | } | ||
| 830 | |||
| 831 | /* Ethtool support */ | ||
| 832 | |||
| 833 | /** | ||
| 834 | * ks8695_get_msglevel - Get the messages enabled for emission | ||
| 835 | * @ndev: The network device to read from | ||
| 836 | */ | ||
| 837 | static u32 | ||
| 838 | ks8695_get_msglevel(struct net_device *ndev) | ||
| 839 | { | ||
| 840 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 841 | |||
| 842 | return ksp->msg_enable; | ||
| 843 | } | ||
| 844 | |||
| 845 | /** | ||
| 846 | * ks8695_set_msglevel - Set the messages enabled for emission | ||
| 847 | * @ndev: The network device to configure | ||
| 848 | * @value: The messages to set for emission | ||
| 849 | */ | ||
| 850 | static void | ||
| 851 | ks8695_set_msglevel(struct net_device *ndev, u32 value) | ||
| 852 | { | ||
| 853 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 854 | |||
| 855 | ksp->msg_enable = value; | ||
| 856 | } | ||
| 857 | |||
| 858 | /** | ||
| 859 | * ks8695_wan_get_settings - Get device-specific settings. | ||
| 860 | * @ndev: The network device to read settings from | ||
| 861 | * @cmd: The ethtool structure to read into | ||
| 862 | */ | ||
| 863 | static int | ||
| 864 | ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | ||
| 865 | { | ||
| 866 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 867 | u32 ctrl; | ||
| 868 | |||
| 869 | /* All ports on the KS8695 support these... */ | ||
| 870 | cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | | ||
| 871 | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | | ||
| 872 | SUPPORTED_TP | SUPPORTED_MII); | ||
| 873 | cmd->transceiver = XCVR_INTERNAL; | ||
| 874 | |||
| 875 | cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; | ||
| 876 | cmd->port = PORT_MII; | ||
| 877 | cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); | ||
| 878 | cmd->phy_address = 0; | ||
| 879 | |||
| 880 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 881 | if ((ctrl & WMC_WAND) == 0) { | ||
| 882 | /* auto-negotiation is enabled */ | ||
| 883 | cmd->advertising |= ADVERTISED_Autoneg; | ||
| 884 | if (ctrl & WMC_WANA100F) | ||
| 885 | cmd->advertising |= ADVERTISED_100baseT_Full; | ||
| 886 | if (ctrl & WMC_WANA100H) | ||
| 887 | cmd->advertising |= ADVERTISED_100baseT_Half; | ||
| 888 | if (ctrl & WMC_WANA10F) | ||
| 889 | cmd->advertising |= ADVERTISED_10baseT_Full; | ||
| 890 | if (ctrl & WMC_WANA10H) | ||
| 891 | cmd->advertising |= ADVERTISED_10baseT_Half; | ||
| 892 | if (ctrl & WMC_WANAP) | ||
| 893 | cmd->advertising |= ADVERTISED_Pause; | ||
| 894 | cmd->autoneg = AUTONEG_ENABLE; | ||
| 895 | |||
| 896 | ethtool_cmd_speed_set(cmd, | ||
| 897 | (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10); | ||
| 898 | cmd->duplex = (ctrl & WMC_WDS) ? | ||
| 899 | DUPLEX_FULL : DUPLEX_HALF; | ||
| 900 | } else { | ||
| 901 | /* auto-negotiation is disabled */ | ||
| 902 | cmd->autoneg = AUTONEG_DISABLE; | ||
| 903 | |||
| 904 | ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ? | ||
| 905 | SPEED_100 : SPEED_10)); | ||
| 906 | cmd->duplex = (ctrl & WMC_WANFF) ? | ||
| 907 | DUPLEX_FULL : DUPLEX_HALF; | ||
| 908 | } | ||
| 909 | |||
| 910 | return 0; | ||
| 911 | } | ||
| 912 | |||
| 913 | /** | ||
| 914 | * ks8695_wan_set_settings - Set device-specific settings. | ||
| 915 | * @ndev: The network device to configure | ||
| 916 | * @cmd: The settings to configure | ||
| 917 | */ | ||
| 918 | static int | ||
| 919 | ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | ||
| 920 | { | ||
| 921 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 922 | u32 ctrl; | ||
| 923 | |||
| 924 | if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100)) | ||
| 925 | return -EINVAL; | ||
| 926 | if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL)) | ||
| 927 | return -EINVAL; | ||
| 928 | if (cmd->port != PORT_MII) | ||
| 929 | return -EINVAL; | ||
| 930 | if (cmd->transceiver != XCVR_INTERNAL) | ||
| 931 | return -EINVAL; | ||
| 932 | if ((cmd->autoneg != AUTONEG_DISABLE) && | ||
| 933 | (cmd->autoneg != AUTONEG_ENABLE)) | ||
| 934 | return -EINVAL; | ||
| 935 | |||
| 936 | if (cmd->autoneg == AUTONEG_ENABLE) { | ||
| 937 | if ((cmd->advertising & (ADVERTISED_10baseT_Half | | ||
| 938 | ADVERTISED_10baseT_Full | | ||
| 939 | ADVERTISED_100baseT_Half | | ||
| 940 | ADVERTISED_100baseT_Full)) == 0) | ||
| 941 | return -EINVAL; | ||
| 942 | |||
| 943 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 944 | |||
| 945 | ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | | ||
| 946 | WMC_WANA10F | WMC_WANA10H); | ||
| 947 | if (cmd->advertising & ADVERTISED_100baseT_Full) | ||
| 948 | ctrl |= WMC_WANA100F; | ||
| 949 | if (cmd->advertising & ADVERTISED_100baseT_Half) | ||
| 950 | ctrl |= WMC_WANA100H; | ||
| 951 | if (cmd->advertising & ADVERTISED_10baseT_Full) | ||
| 952 | ctrl |= WMC_WANA10F; | ||
| 953 | if (cmd->advertising & ADVERTISED_10baseT_Half) | ||
| 954 | ctrl |= WMC_WANA10H; | ||
| 955 | |||
| 956 | /* force a re-negotiation */ | ||
| 957 | ctrl |= WMC_WANR; | ||
| 958 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
| 959 | } else { | ||
| 960 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 961 | |||
| 962 | /* disable auto-negotiation */ | ||
| 963 | ctrl |= WMC_WAND; | ||
| 964 | ctrl &= ~(WMC_WANF100 | WMC_WANFF); | ||
| 965 | |||
| 966 | if (cmd->speed == SPEED_100) | ||
| 967 | ctrl |= WMC_WANF100; | ||
| 968 | if (cmd->duplex == DUPLEX_FULL) | ||
| 969 | ctrl |= WMC_WANFF; | ||
| 970 | |||
| 971 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
| 972 | } | ||
| 973 | |||
| 974 | return 0; | ||
| 975 | } | ||
| 976 | |||
| 977 | /** | ||
| 978 | * ks8695_wan_nwayreset - Restart the autonegotiation on the port. | ||
| 979 | * @ndev: The network device to restart autoneotiation on | ||
| 980 | */ | ||
| 981 | static int | ||
| 982 | ks8695_wan_nwayreset(struct net_device *ndev) | ||
| 983 | { | ||
| 984 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 985 | u32 ctrl; | ||
| 986 | |||
| 987 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 988 | |||
| 989 | if ((ctrl & WMC_WAND) == 0) | ||
| 990 | writel(ctrl | WMC_WANR, | ||
| 991 | ksp->phyiface_regs + KS8695_WMC); | ||
| 992 | else | ||
| 993 | /* auto-negotiation not enabled */ | ||
| 994 | return -EINVAL; | ||
| 995 | |||
| 996 | return 0; | ||
| 997 | } | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising | ||
| 1001 | * @ndev: The device to retrieve settings from | ||
| 1002 | * @param: The structure to fill out with the information | ||
| 1003 | */ | ||
| 1004 | static void | ||
| 1005 | ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) | ||
| 1006 | { | ||
| 1007 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1008 | u32 ctrl; | ||
| 1009 | |||
| 1010 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
| 1011 | |||
| 1012 | /* advertise Pause */ | ||
| 1013 | param->autoneg = (ctrl & WMC_WANAP); | ||
| 1014 | |||
| 1015 | /* current Rx Flow-control */ | ||
| 1016 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); | ||
| 1017 | param->rx_pause = (ctrl & DRXC_RFCE); | ||
| 1018 | |||
| 1019 | /* current Tx Flow-control */ | ||
| 1020 | ctrl = ks8695_readreg(ksp, KS8695_DTXC); | ||
| 1021 | param->tx_pause = (ctrl & DTXC_TFCE); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /** | ||
| 1025 | * ks8695_get_drvinfo - Retrieve driver information | ||
| 1026 | * @ndev: The network device to retrieve info about | ||
| 1027 | * @info: The info structure to fill out. | ||
| 1028 | */ | ||
| 1029 | static void | ||
| 1030 | ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) | ||
| 1031 | { | ||
| 1032 | strlcpy(info->driver, MODULENAME, sizeof(info->driver)); | ||
| 1033 | strlcpy(info->version, MODULEVERSION, sizeof(info->version)); | ||
| 1034 | strlcpy(info->bus_info, dev_name(ndev->dev.parent), | ||
| 1035 | sizeof(info->bus_info)); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static const struct ethtool_ops ks8695_ethtool_ops = { | ||
| 1039 | .get_msglevel = ks8695_get_msglevel, | ||
| 1040 | .set_msglevel = ks8695_set_msglevel, | ||
| 1041 | .get_drvinfo = ks8695_get_drvinfo, | ||
| 1042 | }; | ||
| 1043 | |||
| 1044 | static const struct ethtool_ops ks8695_wan_ethtool_ops = { | ||
| 1045 | .get_msglevel = ks8695_get_msglevel, | ||
| 1046 | .set_msglevel = ks8695_set_msglevel, | ||
| 1047 | .get_settings = ks8695_wan_get_settings, | ||
| 1048 | .set_settings = ks8695_wan_set_settings, | ||
| 1049 | .nway_reset = ks8695_wan_nwayreset, | ||
| 1050 | .get_link = ethtool_op_get_link, | ||
| 1051 | .get_pauseparam = ks8695_wan_get_pause, | ||
| 1052 | .get_drvinfo = ks8695_get_drvinfo, | ||
| 1053 | }; | ||
| 1054 | |||
| 1055 | /* Network device interface functions */ | ||
| 1056 | |||
| 1057 | /** | ||
| 1058 | * ks8695_set_mac - Update MAC in net dev and HW | ||
| 1059 | * @ndev: The network device to update | ||
| 1060 | * @addr: The new MAC address to set | ||
| 1061 | */ | ||
| 1062 | static int | ||
| 1063 | ks8695_set_mac(struct net_device *ndev, void *addr) | ||
| 1064 | { | ||
| 1065 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1066 | struct sockaddr *address = addr; | ||
| 1067 | |||
| 1068 | if (!is_valid_ether_addr(address->sa_data)) | ||
| 1069 | return -EADDRNOTAVAIL; | ||
| 1070 | |||
| 1071 | memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len); | ||
| 1072 | |||
| 1073 | ks8695_update_mac(ksp); | ||
| 1074 | |||
| 1075 | dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n", | ||
| 1076 | ndev->name, ndev->dev_addr); | ||
| 1077 | |||
| 1078 | return 0; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /** | ||
| 1082 | * ks8695_set_multicast - Set up the multicast behaviour of the interface | ||
| 1083 | * @ndev: The net_device to configure | ||
| 1084 | * | ||
| 1085 | * This routine, called by the net layer, configures promiscuity | ||
| 1086 | * and multicast reception behaviour for the interface. | ||
| 1087 | */ | ||
| 1088 | static void | ||
| 1089 | ks8695_set_multicast(struct net_device *ndev) | ||
| 1090 | { | ||
| 1091 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1092 | u32 ctrl; | ||
| 1093 | |||
| 1094 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); | ||
| 1095 | |||
| 1096 | if (ndev->flags & IFF_PROMISC) { | ||
| 1097 | /* enable promiscuous mode */ | ||
| 1098 | ctrl |= DRXC_RA; | ||
| 1099 | } else if (ndev->flags & ~IFF_PROMISC) { | ||
| 1100 | /* disable promiscuous mode */ | ||
| 1101 | ctrl &= ~DRXC_RA; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | if (ndev->flags & IFF_ALLMULTI) { | ||
| 1105 | /* enable all multicast mode */ | ||
| 1106 | ctrl |= DRXC_RM; | ||
| 1107 | } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) { | ||
| 1108 | /* more specific multicast addresses than can be | ||
| 1109 | * handled in hardware | ||
| 1110 | */ | ||
| 1111 | ctrl |= DRXC_RM; | ||
| 1112 | } else { | ||
| 1113 | /* enable specific multicasts */ | ||
| 1114 | ctrl &= ~DRXC_RM; | ||
| 1115 | ks8695_init_partial_multicast(ksp, ndev); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | ks8695_writereg(ksp, KS8695_DRXC, ctrl); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | /** | ||
| 1122 | * ks8695_timeout - Handle a network tx/rx timeout. | ||
| 1123 | * @ndev: The net_device which timed out. | ||
| 1124 | * | ||
| 1125 | * A network transaction timed out, reset the device. | ||
| 1126 | */ | ||
| 1127 | static void | ||
| 1128 | ks8695_timeout(struct net_device *ndev) | ||
| 1129 | { | ||
| 1130 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1131 | |||
| 1132 | netif_stop_queue(ndev); | ||
| 1133 | ks8695_shutdown(ksp); | ||
| 1134 | |||
| 1135 | ks8695_reset(ksp); | ||
| 1136 | |||
| 1137 | ks8695_update_mac(ksp); | ||
| 1138 | |||
| 1139 | /* We ignore the return from this since it managed to init | ||
| 1140 | * before it probably will be okay to init again. | ||
| 1141 | */ | ||
| 1142 | ks8695_init_net(ksp); | ||
| 1143 | |||
| 1144 | /* Reconfigure promiscuity etc */ | ||
| 1145 | ks8695_set_multicast(ndev); | ||
| 1146 | |||
| 1147 | /* And start the TX queue once more */ | ||
| 1148 | netif_start_queue(ndev); | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | /** | ||
| 1152 | * ks8695_start_xmit - Start a packet transmission | ||
| 1153 | * @skb: The packet to transmit | ||
| 1154 | * @ndev: The network device to send the packet on | ||
| 1155 | * | ||
| 1156 | * This routine, called by the net layer, takes ownership of the | ||
| 1157 | * sk_buff and adds it to the TX ring. It then kicks the TX DMA | ||
| 1158 | * engine to ensure transmission begins. | ||
| 1159 | */ | ||
| 1160 | static int | ||
| 1161 | ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
| 1162 | { | ||
| 1163 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1164 | int buff_n; | ||
| 1165 | dma_addr_t dmap; | ||
| 1166 | |||
| 1167 | spin_lock_irq(&ksp->txq_lock); | ||
| 1168 | |||
| 1169 | if (ksp->tx_ring_used == MAX_TX_DESC) { | ||
| 1170 | /* Somehow we got entered when we have no room */ | ||
| 1171 | spin_unlock_irq(&ksp->txq_lock); | ||
| 1172 | return NETDEV_TX_BUSY; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | buff_n = ksp->tx_ring_next_slot; | ||
| 1176 | |||
| 1177 | BUG_ON(ksp->tx_buffers[buff_n].skb); | ||
| 1178 | |||
| 1179 | dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE); | ||
| 1180 | if (unlikely(dma_mapping_error(ksp->dev, dmap))) { | ||
| 1181 | /* Failed to DMA map this SKB, give it back for now */ | ||
| 1182 | spin_unlock_irq(&ksp->txq_lock); | ||
| 1183 | dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\ | ||
| 1184 | "transmission, trying later\n", ndev->name); | ||
| 1185 | return NETDEV_TX_BUSY; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | ksp->tx_buffers[buff_n].dma_ptr = dmap; | ||
| 1189 | /* Mapped okay, store the buffer pointer and length for later */ | ||
| 1190 | ksp->tx_buffers[buff_n].skb = skb; | ||
| 1191 | ksp->tx_buffers[buff_n].length = skb->len; | ||
| 1192 | |||
| 1193 | /* Fill out the TX descriptor */ | ||
| 1194 | ksp->tx_ring[buff_n].data_ptr = | ||
| 1195 | cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr); | ||
| 1196 | ksp->tx_ring[buff_n].status = | ||
| 1197 | cpu_to_le32(TDES_IC | TDES_FS | TDES_LS | | ||
| 1198 | (skb->len & TDES_TBS)); | ||
| 1199 | |||
| 1200 | wmb(); | ||
| 1201 | |||
| 1202 | /* Hand it over to the hardware */ | ||
| 1203 | ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN); | ||
| 1204 | |||
| 1205 | if (++ksp->tx_ring_used == MAX_TX_DESC) | ||
| 1206 | netif_stop_queue(ndev); | ||
| 1207 | |||
| 1208 | /* Kick the TX DMA in case it decided to go IDLE */ | ||
| 1209 | ks8695_writereg(ksp, KS8695_DTSC, 0); | ||
| 1210 | |||
| 1211 | /* And update the next ring slot */ | ||
| 1212 | ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK; | ||
| 1213 | |||
| 1214 | spin_unlock_irq(&ksp->txq_lock); | ||
| 1215 | return NETDEV_TX_OK; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | /** | ||
| 1219 | * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface | ||
| 1220 | * @ndev: The net_device to stop | ||
| 1221 | * | ||
| 1222 | * This disables the TX queue and cleans up a KS8695 ethernet | ||
| 1223 | * device. | ||
| 1224 | */ | ||
| 1225 | static int | ||
| 1226 | ks8695_stop(struct net_device *ndev) | ||
| 1227 | { | ||
| 1228 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1229 | |||
| 1230 | netif_stop_queue(ndev); | ||
| 1231 | napi_disable(&ksp->napi); | ||
| 1232 | |||
| 1233 | ks8695_shutdown(ksp); | ||
| 1234 | |||
| 1235 | return 0; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | /** | ||
| 1239 | * ks8695_open - Open (bring up) a KS8695 ethernet interface | ||
| 1240 | * @ndev: The net_device to open | ||
| 1241 | * | ||
| 1242 | * This resets, configures the MAC, initialises the RX ring and | ||
| 1243 | * DMA engines and starts the TX queue for a KS8695 ethernet | ||
| 1244 | * device. | ||
| 1245 | */ | ||
| 1246 | static int | ||
| 1247 | ks8695_open(struct net_device *ndev) | ||
| 1248 | { | ||
| 1249 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1250 | int ret; | ||
| 1251 | |||
| 1252 | if (!is_valid_ether_addr(ndev->dev_addr)) | ||
| 1253 | return -EADDRNOTAVAIL; | ||
| 1254 | |||
| 1255 | ks8695_reset(ksp); | ||
| 1256 | |||
| 1257 | ks8695_update_mac(ksp); | ||
| 1258 | |||
| 1259 | ret = ks8695_init_net(ksp); | ||
| 1260 | if (ret) { | ||
| 1261 | ks8695_shutdown(ksp); | ||
| 1262 | return ret; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | napi_enable(&ksp->napi); | ||
| 1266 | netif_start_queue(ndev); | ||
| 1267 | |||
| 1268 | return 0; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | /* Platform device driver */ | ||
| 1272 | |||
| 1273 | /** | ||
| 1274 | * ks8695_init_switch - Init LAN switch to known good defaults. | ||
| 1275 | * @ksp: The device to initialise | ||
| 1276 | * | ||
| 1277 | * This initialises the LAN switch in the KS8695 to a known-good | ||
| 1278 | * set of defaults. | ||
| 1279 | */ | ||
| 1280 | static void __devinit | ||
| 1281 | ks8695_init_switch(struct ks8695_priv *ksp) | ||
| 1282 | { | ||
| 1283 | u32 ctrl; | ||
| 1284 | |||
| 1285 | /* Default value for SEC0 according to datasheet */ | ||
| 1286 | ctrl = 0x40819e00; | ||
| 1287 | |||
| 1288 | /* LED0 = Speed LED1 = Link/Activity */ | ||
| 1289 | ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S); | ||
| 1290 | ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY); | ||
| 1291 | |||
| 1292 | /* Enable Switch */ | ||
| 1293 | ctrl |= SEC0_ENABLE; | ||
| 1294 | |||
| 1295 | writel(ctrl, ksp->phyiface_regs + KS8695_SEC0); | ||
| 1296 | |||
| 1297 | /* Defaults for SEC1 */ | ||
| 1298 | writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1); | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | /** | ||
| 1302 | * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults | ||
| 1303 | * @ksp: The device to initialise | ||
| 1304 | * | ||
| 1305 | * This initialises a KS8695's WAN phy to sensible values for | ||
| 1306 | * autonegotiation etc. | ||
| 1307 | */ | ||
| 1308 | static void __devinit | ||
| 1309 | ks8695_init_wan_phy(struct ks8695_priv *ksp) | ||
| 1310 | { | ||
| 1311 | u32 ctrl; | ||
| 1312 | |||
| 1313 | /* Support auto-negotiation */ | ||
| 1314 | ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H | | ||
| 1315 | WMC_WANA10F | WMC_WANA10H); | ||
| 1316 | |||
| 1317 | /* LED0 = Activity , LED1 = Link */ | ||
| 1318 | ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK); | ||
| 1319 | |||
| 1320 | /* Restart Auto-negotiation */ | ||
| 1321 | ctrl |= WMC_WANR; | ||
| 1322 | |||
| 1323 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
| 1324 | |||
| 1325 | writel(0, ksp->phyiface_regs + KS8695_WPPM); | ||
| 1326 | writel(0, ksp->phyiface_regs + KS8695_PPS); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | static const struct net_device_ops ks8695_netdev_ops = { | ||
| 1330 | .ndo_open = ks8695_open, | ||
| 1331 | .ndo_stop = ks8695_stop, | ||
| 1332 | .ndo_start_xmit = ks8695_start_xmit, | ||
| 1333 | .ndo_tx_timeout = ks8695_timeout, | ||
| 1334 | .ndo_set_mac_address = ks8695_set_mac, | ||
| 1335 | .ndo_validate_addr = eth_validate_addr, | ||
| 1336 | .ndo_set_multicast_list = ks8695_set_multicast, | ||
| 1337 | }; | ||
| 1338 | |||
| 1339 | /** | ||
| 1340 | * ks8695_probe - Probe and initialise a KS8695 ethernet interface | ||
| 1341 | * @pdev: The platform device to probe | ||
| 1342 | * | ||
| 1343 | * Initialise a KS8695 ethernet device from platform data. | ||
| 1344 | * | ||
| 1345 | * This driver requires at least one IORESOURCE_MEM for the | ||
| 1346 | * registers and two IORESOURCE_IRQ for the RX and TX IRQs | ||
| 1347 | * respectively. It can optionally take an additional | ||
| 1348 | * IORESOURCE_MEM for the switch or phy in the case of the lan or | ||
| 1349 | * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan | ||
| 1350 | * port. | ||
| 1351 | */ | ||
| 1352 | static int __devinit | ||
| 1353 | ks8695_probe(struct platform_device *pdev) | ||
| 1354 | { | ||
| 1355 | struct ks8695_priv *ksp; | ||
| 1356 | struct net_device *ndev; | ||
| 1357 | struct resource *regs_res, *phyiface_res; | ||
| 1358 | struct resource *rxirq_res, *txirq_res, *linkirq_res; | ||
| 1359 | int ret = 0; | ||
| 1360 | int buff_n; | ||
| 1361 | u32 machigh, maclow; | ||
| 1362 | |||
| 1363 | /* Initialise a net_device */ | ||
| 1364 | ndev = alloc_etherdev(sizeof(struct ks8695_priv)); | ||
| 1365 | if (!ndev) { | ||
| 1366 | dev_err(&pdev->dev, "could not allocate device.\n"); | ||
| 1367 | return -ENOMEM; | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | SET_NETDEV_DEV(ndev, &pdev->dev); | ||
| 1371 | |||
| 1372 | dev_dbg(&pdev->dev, "ks8695_probe() called\n"); | ||
| 1373 | |||
| 1374 | /* Configure our private structure a little */ | ||
| 1375 | ksp = netdev_priv(ndev); | ||
| 1376 | |||
| 1377 | ksp->dev = &pdev->dev; | ||
| 1378 | ksp->ndev = ndev; | ||
| 1379 | ksp->msg_enable = NETIF_MSG_LINK; | ||
| 1380 | |||
| 1381 | /* Retrieve resources */ | ||
| 1382 | regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1383 | phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 1384 | |||
| 1385 | rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 1386 | txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
| 1387 | linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); | ||
| 1388 | |||
| 1389 | if (!(regs_res && rxirq_res && txirq_res)) { | ||
| 1390 | dev_err(ksp->dev, "insufficient resources\n"); | ||
| 1391 | ret = -ENOENT; | ||
| 1392 | goto failure; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | ksp->regs_req = request_mem_region(regs_res->start, | ||
| 1396 | resource_size(regs_res), | ||
| 1397 | pdev->name); | ||
| 1398 | |||
| 1399 | if (!ksp->regs_req) { | ||
| 1400 | dev_err(ksp->dev, "cannot claim register space\n"); | ||
| 1401 | ret = -EIO; | ||
| 1402 | goto failure; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res)); | ||
| 1406 | |||
| 1407 | if (!ksp->io_regs) { | ||
| 1408 | dev_err(ksp->dev, "failed to ioremap registers\n"); | ||
| 1409 | ret = -EINVAL; | ||
| 1410 | goto failure; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | if (phyiface_res) { | ||
| 1414 | ksp->phyiface_req = | ||
| 1415 | request_mem_region(phyiface_res->start, | ||
| 1416 | resource_size(phyiface_res), | ||
| 1417 | phyiface_res->name); | ||
| 1418 | |||
| 1419 | if (!ksp->phyiface_req) { | ||
| 1420 | dev_err(ksp->dev, | ||
| 1421 | "cannot claim switch register space\n"); | ||
| 1422 | ret = -EIO; | ||
| 1423 | goto failure; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | ksp->phyiface_regs = ioremap(phyiface_res->start, | ||
| 1427 | resource_size(phyiface_res)); | ||
| 1428 | |||
| 1429 | if (!ksp->phyiface_regs) { | ||
| 1430 | dev_err(ksp->dev, | ||
| 1431 | "failed to ioremap switch registers\n"); | ||
| 1432 | ret = -EINVAL; | ||
| 1433 | goto failure; | ||
| 1434 | } | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | ksp->rx_irq = rxirq_res->start; | ||
| 1438 | ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX"; | ||
| 1439 | ksp->tx_irq = txirq_res->start; | ||
| 1440 | ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX"; | ||
| 1441 | ksp->link_irq = (linkirq_res ? linkirq_res->start : -1); | ||
| 1442 | ksp->link_irq_name = (linkirq_res && linkirq_res->name) ? | ||
| 1443 | linkirq_res->name : "Ethernet Link"; | ||
| 1444 | |||
| 1445 | /* driver system setup */ | ||
| 1446 | ndev->netdev_ops = &ks8695_netdev_ops; | ||
| 1447 | ndev->watchdog_timeo = msecs_to_jiffies(watchdog); | ||
| 1448 | |||
| 1449 | netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); | ||
| 1450 | |||
| 1451 | /* Retrieve the default MAC addr from the chip. */ | ||
| 1452 | /* The bootloader should have left it in there for us. */ | ||
| 1453 | |||
| 1454 | machigh = ks8695_readreg(ksp, KS8695_MAH); | ||
| 1455 | maclow = ks8695_readreg(ksp, KS8695_MAL); | ||
| 1456 | |||
| 1457 | ndev->dev_addr[0] = (machigh >> 8) & 0xFF; | ||
| 1458 | ndev->dev_addr[1] = machigh & 0xFF; | ||
| 1459 | ndev->dev_addr[2] = (maclow >> 24) & 0xFF; | ||
| 1460 | ndev->dev_addr[3] = (maclow >> 16) & 0xFF; | ||
| 1461 | ndev->dev_addr[4] = (maclow >> 8) & 0xFF; | ||
| 1462 | ndev->dev_addr[5] = maclow & 0xFF; | ||
| 1463 | |||
| 1464 | if (!is_valid_ether_addr(ndev->dev_addr)) | ||
| 1465 | dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please " | ||
| 1466 | "set using ifconfig\n", ndev->name); | ||
| 1467 | |||
| 1468 | /* In order to be efficient memory-wise, we allocate both | ||
| 1469 | * rings in one go. | ||
| 1470 | */ | ||
| 1471 | ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE, | ||
| 1472 | &ksp->ring_base_dma, GFP_KERNEL); | ||
| 1473 | if (!ksp->ring_base) { | ||
| 1474 | ret = -ENOMEM; | ||
| 1475 | goto failure; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | /* Specify the TX DMA ring buffer */ | ||
| 1479 | ksp->tx_ring = ksp->ring_base; | ||
| 1480 | ksp->tx_ring_dma = ksp->ring_base_dma; | ||
| 1481 | |||
| 1482 | /* And initialise the queue's lock */ | ||
| 1483 | spin_lock_init(&ksp->txq_lock); | ||
| 1484 | spin_lock_init(&ksp->rx_lock); | ||
| 1485 | |||
| 1486 | /* Specify the RX DMA ring buffer */ | ||
| 1487 | ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE; | ||
| 1488 | ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE; | ||
| 1489 | |||
| 1490 | /* Zero the descriptor rings */ | ||
| 1491 | memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE); | ||
| 1492 | memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE); | ||
| 1493 | |||
| 1494 | /* Build the rings */ | ||
| 1495 | for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) { | ||
| 1496 | ksp->tx_ring[buff_n].next_desc = | ||
| 1497 | cpu_to_le32(ksp->tx_ring_dma + | ||
| 1498 | (sizeof(struct tx_ring_desc) * | ||
| 1499 | ((buff_n + 1) & MAX_TX_DESC_MASK))); | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) { | ||
| 1503 | ksp->rx_ring[buff_n].next_desc = | ||
| 1504 | cpu_to_le32(ksp->rx_ring_dma + | ||
| 1505 | (sizeof(struct rx_ring_desc) * | ||
| 1506 | ((buff_n + 1) & MAX_RX_DESC_MASK))); | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | /* Initialise the port (physically) */ | ||
| 1510 | if (ksp->phyiface_regs && ksp->link_irq == -1) { | ||
| 1511 | ks8695_init_switch(ksp); | ||
| 1512 | ksp->dtype = KS8695_DTYPE_LAN; | ||
| 1513 | SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); | ||
| 1514 | } else if (ksp->phyiface_regs && ksp->link_irq != -1) { | ||
| 1515 | ks8695_init_wan_phy(ksp); | ||
| 1516 | ksp->dtype = KS8695_DTYPE_WAN; | ||
| 1517 | SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); | ||
| 1518 | } else { | ||
| 1519 | /* No initialisation since HPNA does not have a PHY */ | ||
| 1520 | ksp->dtype = KS8695_DTYPE_HPNA; | ||
| 1521 | SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | /* And bring up the net_device with the net core */ | ||
| 1525 | platform_set_drvdata(pdev, ndev); | ||
| 1526 | ret = register_netdev(ndev); | ||
| 1527 | |||
| 1528 | if (ret == 0) { | ||
| 1529 | dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n", | ||
| 1530 | ks8695_port_type(ksp), ndev->dev_addr); | ||
| 1531 | } else { | ||
| 1532 | /* Report the failure to register the net_device */ | ||
| 1533 | dev_err(ksp->dev, "ks8695net: failed to register netdev.\n"); | ||
| 1534 | goto failure; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | /* All is well */ | ||
| 1538 | return 0; | ||
| 1539 | |||
| 1540 | /* Error exit path */ | ||
| 1541 | failure: | ||
| 1542 | ks8695_release_device(ksp); | ||
| 1543 | free_netdev(ndev); | ||
| 1544 | |||
| 1545 | return ret; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | /** | ||
| 1549 | * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device. | ||
| 1550 | * @pdev: The device to suspend | ||
| 1551 | * @state: The suspend state | ||
| 1552 | * | ||
| 1553 | * This routine detaches and shuts down a KS8695 ethernet device. | ||
| 1554 | */ | ||
| 1555 | static int | ||
| 1556 | ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 1557 | { | ||
| 1558 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 1559 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1560 | |||
| 1561 | ksp->in_suspend = 1; | ||
| 1562 | |||
| 1563 | if (netif_running(ndev)) { | ||
| 1564 | netif_device_detach(ndev); | ||
| 1565 | ks8695_shutdown(ksp); | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | return 0; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | /** | ||
| 1572 | * ks8695_drv_resume - Resume a KS8695 ethernet platform device. | ||
| 1573 | * @pdev: The device to resume | ||
| 1574 | * | ||
| 1575 | * This routine re-initialises and re-attaches a KS8695 ethernet | ||
| 1576 | * device. | ||
| 1577 | */ | ||
| 1578 | static int | ||
| 1579 | ks8695_drv_resume(struct platform_device *pdev) | ||
| 1580 | { | ||
| 1581 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 1582 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1583 | |||
| 1584 | if (netif_running(ndev)) { | ||
| 1585 | ks8695_reset(ksp); | ||
| 1586 | ks8695_init_net(ksp); | ||
| 1587 | ks8695_set_multicast(ndev); | ||
| 1588 | netif_device_attach(ndev); | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | ksp->in_suspend = 0; | ||
| 1592 | |||
| 1593 | return 0; | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | /** | ||
| 1597 | * ks8695_drv_remove - Remove a KS8695 net device on driver unload. | ||
| 1598 | * @pdev: The platform device to remove | ||
| 1599 | * | ||
| 1600 | * This unregisters and releases a KS8695 ethernet device. | ||
| 1601 | */ | ||
| 1602 | static int __devexit | ||
| 1603 | ks8695_drv_remove(struct platform_device *pdev) | ||
| 1604 | { | ||
| 1605 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 1606 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
| 1607 | |||
| 1608 | platform_set_drvdata(pdev, NULL); | ||
| 1609 | netif_napi_del(&ksp->napi); | ||
| 1610 | |||
| 1611 | unregister_netdev(ndev); | ||
| 1612 | ks8695_release_device(ksp); | ||
| 1613 | free_netdev(ndev); | ||
| 1614 | |||
| 1615 | dev_dbg(&pdev->dev, "released and freed device\n"); | ||
| 1616 | return 0; | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | static struct platform_driver ks8695_driver = { | ||
| 1620 | .driver = { | ||
| 1621 | .name = MODULENAME, | ||
| 1622 | .owner = THIS_MODULE, | ||
| 1623 | }, | ||
| 1624 | .probe = ks8695_probe, | ||
| 1625 | .remove = __devexit_p(ks8695_drv_remove), | ||
| 1626 | .suspend = ks8695_drv_suspend, | ||
| 1627 | .resume = ks8695_drv_resume, | ||
| 1628 | }; | ||
| 1629 | |||
| 1630 | /* Module interface */ | ||
| 1631 | |||
| 1632 | static int __init | ||
| 1633 | ks8695_init(void) | ||
| 1634 | { | ||
| 1635 | printk(KERN_INFO "%s Ethernet driver, V%s\n", | ||
| 1636 | MODULENAME, MODULEVERSION); | ||
| 1637 | |||
| 1638 | return platform_driver_register(&ks8695_driver); | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | static void __exit | ||
| 1642 | ks8695_cleanup(void) | ||
| 1643 | { | ||
| 1644 | platform_driver_unregister(&ks8695_driver); | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | module_init(ks8695_init); | ||
| 1648 | module_exit(ks8695_cleanup); | ||
| 1649 | |||
| 1650 | MODULE_AUTHOR("Simtec Electronics"); | ||
| 1651 | MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver"); | ||
| 1652 | MODULE_LICENSE("GPL"); | ||
| 1653 | MODULE_ALIAS("platform:" MODULENAME); | ||
| 1654 | |||
| 1655 | module_param(watchdog, int, 0400); | ||
| 1656 | MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); | ||
diff --git a/drivers/net/arm/ks8695net.h b/drivers/net/arm/ks8695net.h new file mode 100644 index 00000000000..80eff6ea516 --- /dev/null +++ b/drivers/net/arm/ks8695net.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * Micrel KS8695 (Centaur) Ethernet. | ||
| 3 | * | ||
| 4 | * Copyright 2008 Simtec Electronics | ||
| 5 | * Daniel Silverstone <dsilvers@simtec.co.uk> | ||
| 6 | * Vincent Sanders <vince@simtec.co.uk> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef KS8695NET_H | ||
| 10 | #define KS8695NET_H | ||
| 11 | |||
| 12 | /* Receive descriptor flags */ | ||
| 13 | #define RDES_OWN (1 << 31) /* Ownership */ | ||
| 14 | #define RDES_FS (1 << 30) /* First Descriptor */ | ||
| 15 | #define RDES_LS (1 << 29) /* Last Descriptor */ | ||
| 16 | #define RDES_IPE (1 << 28) /* IP Checksum error */ | ||
| 17 | #define RDES_TCPE (1 << 27) /* TCP Checksum error */ | ||
| 18 | #define RDES_UDPE (1 << 26) /* UDP Checksum error */ | ||
| 19 | #define RDES_ES (1 << 25) /* Error summary */ | ||
| 20 | #define RDES_MF (1 << 24) /* Multicast Frame */ | ||
| 21 | #define RDES_RE (1 << 19) /* MII Error reported */ | ||
| 22 | #define RDES_TL (1 << 18) /* Frame too Long */ | ||
| 23 | #define RDES_RF (1 << 17) /* Runt Frame */ | ||
| 24 | #define RDES_CE (1 << 16) /* CRC error */ | ||
| 25 | #define RDES_FT (1 << 15) /* Frame Type */ | ||
| 26 | #define RDES_FLEN (0x7ff) /* Frame Length */ | ||
| 27 | |||
| 28 | #define RDES_RER (1 << 25) /* Receive End of Ring */ | ||
| 29 | #define RDES_RBS (0x7ff) /* Receive Buffer Size */ | ||
| 30 | |||
| 31 | /* Transmit descriptor flags */ | ||
| 32 | |||
| 33 | #define TDES_OWN (1 << 31) /* Ownership */ | ||
| 34 | |||
| 35 | #define TDES_IC (1 << 31) /* Interrupt on Completion */ | ||
| 36 | #define TDES_FS (1 << 30) /* First Segment */ | ||
| 37 | #define TDES_LS (1 << 29) /* Last Segment */ | ||
| 38 | #define TDES_IPCKG (1 << 28) /* IP Checksum generate */ | ||
| 39 | #define TDES_TCPCKG (1 << 27) /* TCP Checksum generate */ | ||
| 40 | #define TDES_UDPCKG (1 << 26) /* UDP Checksum generate */ | ||
| 41 | #define TDES_TER (1 << 25) /* Transmit End of Ring */ | ||
| 42 | #define TDES_TBS (0x7ff) /* Transmit Buffer Size */ | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Network controller register offsets | ||
| 46 | */ | ||
| 47 | #define KS8695_DTXC (0x00) /* DMA Transmit Control */ | ||
| 48 | #define KS8695_DRXC (0x04) /* DMA Receive Control */ | ||
| 49 | #define KS8695_DTSC (0x08) /* DMA Transmit Start Command */ | ||
| 50 | #define KS8695_DRSC (0x0c) /* DMA Receive Start Command */ | ||
| 51 | #define KS8695_TDLB (0x10) /* Transmit Descriptor List | ||
| 52 | * Base Address | ||
| 53 | */ | ||
| 54 | #define KS8695_RDLB (0x14) /* Receive Descriptor List | ||
| 55 | * Base Address | ||
| 56 | */ | ||
| 57 | #define KS8695_MAL (0x18) /* MAC Station Address Low */ | ||
| 58 | #define KS8695_MAH (0x1c) /* MAC Station Address High */ | ||
| 59 | #define KS8695_AAL_(n) (0x80 + ((n)*8)) /* MAC Additional | ||
| 60 | * Station Address | ||
| 61 | * (0..15) Low | ||
| 62 | */ | ||
| 63 | #define KS8695_AAH_(n) (0x84 + ((n)*8)) /* MAC Additional | ||
| 64 | * Station Address | ||
| 65 | * (0..15) High | ||
| 66 | */ | ||
| 67 | |||
| 68 | |||
| 69 | /* DMA Transmit Control Register */ | ||
| 70 | #define DTXC_TRST (1 << 31) /* Soft Reset */ | ||
| 71 | #define DTXC_TBS (0x3f << 24) /* Transmit Burst Size */ | ||
| 72 | #define DTXC_TUCG (1 << 18) /* Transmit UDP | ||
| 73 | * Checksum Generate | ||
| 74 | */ | ||
| 75 | #define DTXC_TTCG (1 << 17) /* Transmit TCP | ||
| 76 | * Checksum Generate | ||
| 77 | */ | ||
| 78 | #define DTXC_TICG (1 << 16) /* Transmit IP | ||
| 79 | * Checksum Generate | ||
| 80 | */ | ||
| 81 | #define DTXC_TFCE (1 << 9) /* Transmit Flow | ||
| 82 | * Control Enable | ||
| 83 | */ | ||
| 84 | #define DTXC_TLB (1 << 8) /* Loopback mode */ | ||
| 85 | #define DTXC_TEP (1 << 2) /* Transmit Enable Padding */ | ||
| 86 | #define DTXC_TAC (1 << 1) /* Transmit Add CRC */ | ||
| 87 | #define DTXC_TE (1 << 0) /* TX Enable */ | ||
| 88 | |||
| 89 | /* DMA Receive Control Register */ | ||
| 90 | #define DRXC_RBS (0x3f << 24) /* Receive Burst Size */ | ||
| 91 | #define DRXC_RUCC (1 << 18) /* Receive UDP Checksum check */ | ||
| 92 | #define DRXC_RTCG (1 << 17) /* Receive TCP Checksum check */ | ||
| 93 | #define DRXC_RICG (1 << 16) /* Receive IP Checksum check */ | ||
| 94 | #define DRXC_RFCE (1 << 9) /* Receive Flow Control | ||
| 95 | * Enable | ||
| 96 | */ | ||
| 97 | #define DRXC_RB (1 << 6) /* Receive Broadcast */ | ||
| 98 | #define DRXC_RM (1 << 5) /* Receive Multicast */ | ||
| 99 | #define DRXC_RU (1 << 4) /* Receive Unicast */ | ||
| 100 | #define DRXC_RERR (1 << 3) /* Receive Error Frame */ | ||
| 101 | #define DRXC_RA (1 << 2) /* Receive All */ | ||
| 102 | #define DRXC_RE (1 << 0) /* RX Enable */ | ||
| 103 | |||
| 104 | /* Additional Station Address High */ | ||
| 105 | #define AAH_E (1 << 31) /* Address Enabled */ | ||
| 106 | |||
| 107 | #endif /* KS8695NET_H */ | ||
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c new file mode 100644 index 00000000000..bfea499a351 --- /dev/null +++ b/drivers/net/arm/w90p910_ether.c | |||
| @@ -0,0 +1,1123 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
| 3 | * | ||
| 4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation;version 2 of the License. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/mii.h> | ||
| 15 | #include <linux/netdevice.h> | ||
| 16 | #include <linux/etherdevice.h> | ||
| 17 | #include <linux/skbuff.h> | ||
| 18 | #include <linux/ethtool.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/gfp.h> | ||
| 22 | |||
| 23 | #define DRV_MODULE_NAME "w90p910-emc" | ||
| 24 | #define DRV_MODULE_VERSION "0.1" | ||
| 25 | |||
| 26 | /* Ethernet MAC Registers */ | ||
| 27 | #define REG_CAMCMR 0x00 | ||
| 28 | #define REG_CAMEN 0x04 | ||
| 29 | #define REG_CAMM_BASE 0x08 | ||
| 30 | #define REG_CAML_BASE 0x0c | ||
| 31 | #define REG_TXDLSA 0x88 | ||
| 32 | #define REG_RXDLSA 0x8C | ||
| 33 | #define REG_MCMDR 0x90 | ||
| 34 | #define REG_MIID 0x94 | ||
| 35 | #define REG_MIIDA 0x98 | ||
| 36 | #define REG_FFTCR 0x9C | ||
| 37 | #define REG_TSDR 0xa0 | ||
| 38 | #define REG_RSDR 0xa4 | ||
| 39 | #define REG_DMARFC 0xa8 | ||
| 40 | #define REG_MIEN 0xac | ||
| 41 | #define REG_MISTA 0xb0 | ||
| 42 | #define REG_CTXDSA 0xcc | ||
| 43 | #define REG_CTXBSA 0xd0 | ||
| 44 | #define REG_CRXDSA 0xd4 | ||
| 45 | #define REG_CRXBSA 0xd8 | ||
| 46 | |||
| 47 | /* mac controller bit */ | ||
| 48 | #define MCMDR_RXON 0x01 | ||
| 49 | #define MCMDR_ACP (0x01 << 3) | ||
| 50 | #define MCMDR_SPCRC (0x01 << 5) | ||
| 51 | #define MCMDR_TXON (0x01 << 8) | ||
| 52 | #define MCMDR_FDUP (0x01 << 18) | ||
| 53 | #define MCMDR_ENMDC (0x01 << 19) | ||
| 54 | #define MCMDR_OPMOD (0x01 << 20) | ||
| 55 | #define SWR (0x01 << 24) | ||
| 56 | |||
| 57 | /* cam command regiser */ | ||
| 58 | #define CAMCMR_AUP 0x01 | ||
| 59 | #define CAMCMR_AMP (0x01 << 1) | ||
| 60 | #define CAMCMR_ABP (0x01 << 2) | ||
| 61 | #define CAMCMR_CCAM (0x01 << 3) | ||
| 62 | #define CAMCMR_ECMP (0x01 << 4) | ||
| 63 | #define CAM0EN 0x01 | ||
| 64 | |||
| 65 | /* mac mii controller bit */ | ||
| 66 | #define MDCCR (0x0a << 20) | ||
| 67 | #define PHYAD (0x01 << 8) | ||
| 68 | #define PHYWR (0x01 << 16) | ||
| 69 | #define PHYBUSY (0x01 << 17) | ||
| 70 | #define PHYPRESP (0x01 << 18) | ||
| 71 | #define CAM_ENTRY_SIZE 0x08 | ||
| 72 | |||
| 73 | /* rx and tx status */ | ||
| 74 | #define TXDS_TXCP (0x01 << 19) | ||
| 75 | #define RXDS_CRCE (0x01 << 17) | ||
| 76 | #define RXDS_PTLE (0x01 << 19) | ||
| 77 | #define RXDS_RXGD (0x01 << 20) | ||
| 78 | #define RXDS_ALIE (0x01 << 21) | ||
| 79 | #define RXDS_RP (0x01 << 22) | ||
| 80 | |||
| 81 | /* mac interrupt status*/ | ||
| 82 | #define MISTA_EXDEF (0x01 << 19) | ||
| 83 | #define MISTA_TXBERR (0x01 << 24) | ||
| 84 | #define MISTA_TDU (0x01 << 23) | ||
| 85 | #define MISTA_RDU (0x01 << 10) | ||
| 86 | #define MISTA_RXBERR (0x01 << 11) | ||
| 87 | |||
| 88 | #define ENSTART 0x01 | ||
| 89 | #define ENRXINTR 0x01 | ||
| 90 | #define ENRXGD (0x01 << 4) | ||
| 91 | #define ENRXBERR (0x01 << 11) | ||
| 92 | #define ENTXINTR (0x01 << 16) | ||
| 93 | #define ENTXCP (0x01 << 18) | ||
| 94 | #define ENTXABT (0x01 << 21) | ||
| 95 | #define ENTXBERR (0x01 << 24) | ||
| 96 | #define ENMDC (0x01 << 19) | ||
| 97 | #define PHYBUSY (0x01 << 17) | ||
| 98 | #define MDCCR_VAL 0xa00000 | ||
| 99 | |||
| 100 | /* rx and tx owner bit */ | ||
| 101 | #define RX_OWEN_DMA (0x01 << 31) | ||
| 102 | #define RX_OWEN_CPU (~(0x03 << 30)) | ||
| 103 | #define TX_OWEN_DMA (0x01 << 31) | ||
| 104 | #define TX_OWEN_CPU (~(0x01 << 31)) | ||
| 105 | |||
| 106 | /* tx frame desc controller bit */ | ||
| 107 | #define MACTXINTEN 0x04 | ||
| 108 | #define CRCMODE 0x02 | ||
| 109 | #define PADDINGMODE 0x01 | ||
| 110 | |||
| 111 | /* fftcr controller bit */ | ||
| 112 | #define TXTHD (0x03 << 8) | ||
| 113 | #define BLENGTH (0x01 << 20) | ||
| 114 | |||
| 115 | /* global setting for driver */ | ||
| 116 | #define RX_DESC_SIZE 50 | ||
| 117 | #define TX_DESC_SIZE 10 | ||
| 118 | #define MAX_RBUFF_SZ 0x600 | ||
| 119 | #define MAX_TBUFF_SZ 0x600 | ||
| 120 | #define TX_TIMEOUT (HZ/2) | ||
| 121 | #define DELAY 1000 | ||
| 122 | #define CAM0 0x0 | ||
| 123 | |||
| 124 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg); | ||
| 125 | |||
| 126 | struct w90p910_rxbd { | ||
| 127 | unsigned int sl; | ||
| 128 | unsigned int buffer; | ||
| 129 | unsigned int reserved; | ||
| 130 | unsigned int next; | ||
| 131 | }; | ||
| 132 | |||
| 133 | struct w90p910_txbd { | ||
| 134 | unsigned int mode; | ||
| 135 | unsigned int buffer; | ||
| 136 | unsigned int sl; | ||
| 137 | unsigned int next; | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct recv_pdesc { | ||
| 141 | struct w90p910_rxbd desclist[RX_DESC_SIZE]; | ||
| 142 | char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ]; | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct tran_pdesc { | ||
| 146 | struct w90p910_txbd desclist[TX_DESC_SIZE]; | ||
| 147 | char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ]; | ||
| 148 | }; | ||
| 149 | |||
| 150 | struct w90p910_ether { | ||
| 151 | struct recv_pdesc *rdesc; | ||
| 152 | struct tran_pdesc *tdesc; | ||
| 153 | dma_addr_t rdesc_phys; | ||
| 154 | dma_addr_t tdesc_phys; | ||
| 155 | struct net_device_stats stats; | ||
| 156 | struct platform_device *pdev; | ||
| 157 | struct resource *res; | ||
| 158 | struct sk_buff *skb; | ||
| 159 | struct clk *clk; | ||
| 160 | struct clk *rmiiclk; | ||
| 161 | struct mii_if_info mii; | ||
| 162 | struct timer_list check_timer; | ||
| 163 | void __iomem *reg; | ||
| 164 | int rxirq; | ||
| 165 | int txirq; | ||
| 166 | unsigned int cur_tx; | ||
| 167 | unsigned int cur_rx; | ||
| 168 | unsigned int finish_tx; | ||
| 169 | unsigned int rx_packets; | ||
| 170 | unsigned int rx_bytes; | ||
| 171 | unsigned int start_tx_ptr; | ||
| 172 | unsigned int start_rx_ptr; | ||
| 173 | unsigned int linkflag; | ||
| 174 | }; | ||
| 175 | |||
| 176 | static void update_linkspeed_register(struct net_device *dev, | ||
| 177 | unsigned int speed, unsigned int duplex) | ||
| 178 | { | ||
| 179 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 180 | unsigned int val; | ||
| 181 | |||
| 182 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
| 183 | |||
| 184 | if (speed == SPEED_100) { | ||
| 185 | /* 100 full/half duplex */ | ||
| 186 | if (duplex == DUPLEX_FULL) { | ||
| 187 | val |= (MCMDR_OPMOD | MCMDR_FDUP); | ||
| 188 | } else { | ||
| 189 | val |= MCMDR_OPMOD; | ||
| 190 | val &= ~MCMDR_FDUP; | ||
| 191 | } | ||
| 192 | } else { | ||
| 193 | /* 10 full/half duplex */ | ||
| 194 | if (duplex == DUPLEX_FULL) { | ||
| 195 | val |= MCMDR_FDUP; | ||
| 196 | val &= ~MCMDR_OPMOD; | ||
| 197 | } else { | ||
| 198 | val &= ~(MCMDR_FDUP | MCMDR_OPMOD); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
| 203 | } | ||
| 204 | |||
| 205 | static void update_linkspeed(struct net_device *dev) | ||
| 206 | { | ||
| 207 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 208 | struct platform_device *pdev; | ||
| 209 | unsigned int bmsr, bmcr, lpa, speed, duplex; | ||
| 210 | |||
| 211 | pdev = ether->pdev; | ||
| 212 | |||
| 213 | if (!mii_link_ok(ðer->mii)) { | ||
| 214 | ether->linkflag = 0x0; | ||
| 215 | netif_carrier_off(dev); | ||
| 216 | dev_warn(&pdev->dev, "%s: Link down.\n", dev->name); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | |||
| 220 | if (ether->linkflag == 1) | ||
| 221 | return; | ||
| 222 | |||
| 223 | bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR); | ||
| 224 | bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR); | ||
| 225 | |||
| 226 | if (bmcr & BMCR_ANENABLE) { | ||
| 227 | if (!(bmsr & BMSR_ANEGCOMPLETE)) | ||
| 228 | return; | ||
| 229 | |||
| 230 | lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_LPA); | ||
| 231 | |||
| 232 | if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) | ||
| 233 | speed = SPEED_100; | ||
| 234 | else | ||
| 235 | speed = SPEED_10; | ||
| 236 | |||
| 237 | if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) | ||
| 238 | duplex = DUPLEX_FULL; | ||
| 239 | else | ||
| 240 | duplex = DUPLEX_HALF; | ||
| 241 | |||
| 242 | } else { | ||
| 243 | speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; | ||
| 244 | duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; | ||
| 245 | } | ||
| 246 | |||
| 247 | update_linkspeed_register(dev, speed, duplex); | ||
| 248 | |||
| 249 | dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed, | ||
| 250 | (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex"); | ||
| 251 | ether->linkflag = 0x01; | ||
| 252 | |||
| 253 | netif_carrier_on(dev); | ||
| 254 | } | ||
| 255 | |||
| 256 | static void w90p910_check_link(unsigned long dev_id) | ||
| 257 | { | ||
| 258 | struct net_device *dev = (struct net_device *) dev_id; | ||
| 259 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 260 | |||
| 261 | update_linkspeed(dev); | ||
| 262 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
| 263 | } | ||
| 264 | |||
| 265 | static void w90p910_write_cam(struct net_device *dev, | ||
| 266 | unsigned int x, unsigned char *pval) | ||
| 267 | { | ||
| 268 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 269 | unsigned int msw, lsw; | ||
| 270 | |||
| 271 | msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3]; | ||
| 272 | |||
| 273 | lsw = (pval[4] << 24) | (pval[5] << 16); | ||
| 274 | |||
| 275 | __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE); | ||
| 276 | __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE); | ||
| 277 | } | ||
| 278 | |||
| 279 | static int w90p910_init_desc(struct net_device *dev) | ||
| 280 | { | ||
| 281 | struct w90p910_ether *ether; | ||
| 282 | struct w90p910_txbd *tdesc; | ||
| 283 | struct w90p910_rxbd *rdesc; | ||
| 284 | struct platform_device *pdev; | ||
| 285 | unsigned int i; | ||
| 286 | |||
| 287 | ether = netdev_priv(dev); | ||
| 288 | pdev = ether->pdev; | ||
| 289 | |||
| 290 | ether->tdesc = (struct tran_pdesc *) | ||
| 291 | dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc), | ||
| 292 | ðer->tdesc_phys, GFP_KERNEL); | ||
| 293 | |||
| 294 | if (!ether->tdesc) { | ||
| 295 | dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n"); | ||
| 296 | return -ENOMEM; | ||
| 297 | } | ||
| 298 | |||
| 299 | ether->rdesc = (struct recv_pdesc *) | ||
| 300 | dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc), | ||
| 301 | ðer->rdesc_phys, GFP_KERNEL); | ||
| 302 | |||
| 303 | if (!ether->rdesc) { | ||
| 304 | dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n"); | ||
| 305 | dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc), | ||
| 306 | ether->tdesc, ether->tdesc_phys); | ||
| 307 | return -ENOMEM; | ||
| 308 | } | ||
| 309 | |||
| 310 | for (i = 0; i < TX_DESC_SIZE; i++) { | ||
| 311 | unsigned int offset; | ||
| 312 | |||
| 313 | tdesc = &(ether->tdesc->desclist[i]); | ||
| 314 | |||
| 315 | if (i == TX_DESC_SIZE - 1) | ||
| 316 | offset = offsetof(struct tran_pdesc, desclist[0]); | ||
| 317 | else | ||
| 318 | offset = offsetof(struct tran_pdesc, desclist[i + 1]); | ||
| 319 | |||
| 320 | tdesc->next = ether->tdesc_phys + offset; | ||
| 321 | tdesc->buffer = ether->tdesc_phys + | ||
| 322 | offsetof(struct tran_pdesc, tran_buf[i]); | ||
| 323 | tdesc->sl = 0; | ||
| 324 | tdesc->mode = 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | ether->start_tx_ptr = ether->tdesc_phys; | ||
| 328 | |||
| 329 | for (i = 0; i < RX_DESC_SIZE; i++) { | ||
| 330 | unsigned int offset; | ||
| 331 | |||
| 332 | rdesc = &(ether->rdesc->desclist[i]); | ||
| 333 | |||
| 334 | if (i == RX_DESC_SIZE - 1) | ||
| 335 | offset = offsetof(struct recv_pdesc, desclist[0]); | ||
| 336 | else | ||
| 337 | offset = offsetof(struct recv_pdesc, desclist[i + 1]); | ||
| 338 | |||
| 339 | rdesc->next = ether->rdesc_phys + offset; | ||
| 340 | rdesc->sl = RX_OWEN_DMA; | ||
| 341 | rdesc->buffer = ether->rdesc_phys + | ||
| 342 | offsetof(struct recv_pdesc, recv_buf[i]); | ||
| 343 | } | ||
| 344 | |||
| 345 | ether->start_rx_ptr = ether->rdesc_phys; | ||
| 346 | |||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | static void w90p910_set_fifo_threshold(struct net_device *dev) | ||
| 351 | { | ||
| 352 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 353 | unsigned int val; | ||
| 354 | |||
| 355 | val = TXTHD | BLENGTH; | ||
| 356 | __raw_writel(val, ether->reg + REG_FFTCR); | ||
| 357 | } | ||
| 358 | |||
| 359 | static void w90p910_return_default_idle(struct net_device *dev) | ||
| 360 | { | ||
| 361 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 362 | unsigned int val; | ||
| 363 | |||
| 364 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
| 365 | val |= SWR; | ||
| 366 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
| 367 | } | ||
| 368 | |||
| 369 | static void w90p910_trigger_rx(struct net_device *dev) | ||
| 370 | { | ||
| 371 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 372 | |||
| 373 | __raw_writel(ENSTART, ether->reg + REG_RSDR); | ||
| 374 | } | ||
| 375 | |||
| 376 | static void w90p910_trigger_tx(struct net_device *dev) | ||
| 377 | { | ||
| 378 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 379 | |||
| 380 | __raw_writel(ENSTART, ether->reg + REG_TSDR); | ||
| 381 | } | ||
| 382 | |||
| 383 | static void w90p910_enable_mac_interrupt(struct net_device *dev) | ||
| 384 | { | ||
| 385 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 386 | unsigned int val; | ||
| 387 | |||
| 388 | val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP; | ||
| 389 | val |= ENTXBERR | ENRXBERR | ENTXABT; | ||
| 390 | |||
| 391 | __raw_writel(val, ether->reg + REG_MIEN); | ||
| 392 | } | ||
| 393 | |||
| 394 | static void w90p910_get_and_clear_int(struct net_device *dev, | ||
| 395 | unsigned int *val) | ||
| 396 | { | ||
| 397 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 398 | |||
| 399 | *val = __raw_readl(ether->reg + REG_MISTA); | ||
| 400 | __raw_writel(*val, ether->reg + REG_MISTA); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void w90p910_set_global_maccmd(struct net_device *dev) | ||
| 404 | { | ||
| 405 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 406 | unsigned int val; | ||
| 407 | |||
| 408 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
| 409 | val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC; | ||
| 410 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
| 411 | } | ||
| 412 | |||
| 413 | static void w90p910_enable_cam(struct net_device *dev) | ||
| 414 | { | ||
| 415 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 416 | unsigned int val; | ||
| 417 | |||
| 418 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
| 419 | |||
| 420 | val = __raw_readl(ether->reg + REG_CAMEN); | ||
| 421 | val |= CAM0EN; | ||
| 422 | __raw_writel(val, ether->reg + REG_CAMEN); | ||
| 423 | } | ||
| 424 | |||
| 425 | static void w90p910_enable_cam_command(struct net_device *dev) | ||
| 426 | { | ||
| 427 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 428 | unsigned int val; | ||
| 429 | |||
| 430 | val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP; | ||
| 431 | __raw_writel(val, ether->reg + REG_CAMCMR); | ||
| 432 | } | ||
| 433 | |||
| 434 | static void w90p910_enable_tx(struct net_device *dev, unsigned int enable) | ||
| 435 | { | ||
| 436 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 437 | unsigned int val; | ||
| 438 | |||
| 439 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
| 440 | |||
| 441 | if (enable) | ||
| 442 | val |= MCMDR_TXON; | ||
| 443 | else | ||
| 444 | val &= ~MCMDR_TXON; | ||
| 445 | |||
| 446 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
| 447 | } | ||
| 448 | |||
| 449 | static void w90p910_enable_rx(struct net_device *dev, unsigned int enable) | ||
| 450 | { | ||
| 451 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 452 | unsigned int val; | ||
| 453 | |||
| 454 | val = __raw_readl(ether->reg + REG_MCMDR); | ||
| 455 | |||
| 456 | if (enable) | ||
| 457 | val |= MCMDR_RXON; | ||
| 458 | else | ||
| 459 | val &= ~MCMDR_RXON; | ||
| 460 | |||
| 461 | __raw_writel(val, ether->reg + REG_MCMDR); | ||
| 462 | } | ||
| 463 | |||
| 464 | static void w90p910_set_curdest(struct net_device *dev) | ||
| 465 | { | ||
| 466 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 467 | |||
| 468 | __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA); | ||
| 469 | __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA); | ||
| 470 | } | ||
| 471 | |||
| 472 | static void w90p910_reset_mac(struct net_device *dev) | ||
| 473 | { | ||
| 474 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 475 | |||
| 476 | w90p910_enable_tx(dev, 0); | ||
| 477 | w90p910_enable_rx(dev, 0); | ||
| 478 | w90p910_set_fifo_threshold(dev); | ||
| 479 | w90p910_return_default_idle(dev); | ||
| 480 | |||
| 481 | if (!netif_queue_stopped(dev)) | ||
| 482 | netif_stop_queue(dev); | ||
| 483 | |||
| 484 | w90p910_init_desc(dev); | ||
| 485 | |||
| 486 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
| 487 | ether->cur_tx = 0x0; | ||
| 488 | ether->finish_tx = 0x0; | ||
| 489 | ether->cur_rx = 0x0; | ||
| 490 | |||
| 491 | w90p910_set_curdest(dev); | ||
| 492 | w90p910_enable_cam(dev); | ||
| 493 | w90p910_enable_cam_command(dev); | ||
| 494 | w90p910_enable_mac_interrupt(dev); | ||
| 495 | w90p910_enable_tx(dev, 1); | ||
| 496 | w90p910_enable_rx(dev, 1); | ||
| 497 | w90p910_trigger_tx(dev); | ||
| 498 | w90p910_trigger_rx(dev); | ||
| 499 | |||
| 500 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
| 501 | |||
| 502 | if (netif_queue_stopped(dev)) | ||
| 503 | netif_wake_queue(dev); | ||
| 504 | } | ||
| 505 | |||
| 506 | static void w90p910_mdio_write(struct net_device *dev, | ||
| 507 | int phy_id, int reg, int data) | ||
| 508 | { | ||
| 509 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 510 | struct platform_device *pdev; | ||
| 511 | unsigned int val, i; | ||
| 512 | |||
| 513 | pdev = ether->pdev; | ||
| 514 | |||
| 515 | __raw_writel(data, ether->reg + REG_MIID); | ||
| 516 | |||
| 517 | val = (phy_id << 0x08) | reg; | ||
| 518 | val |= PHYBUSY | PHYWR | MDCCR_VAL; | ||
| 519 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
| 520 | |||
| 521 | for (i = 0; i < DELAY; i++) { | ||
| 522 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
| 523 | break; | ||
| 524 | } | ||
| 525 | |||
| 526 | if (i == DELAY) | ||
| 527 | dev_warn(&pdev->dev, "mdio write timed out\n"); | ||
| 528 | } | ||
| 529 | |||
| 530 | static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg) | ||
| 531 | { | ||
| 532 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 533 | struct platform_device *pdev; | ||
| 534 | unsigned int val, i, data; | ||
| 535 | |||
| 536 | pdev = ether->pdev; | ||
| 537 | |||
| 538 | val = (phy_id << 0x08) | reg; | ||
| 539 | val |= PHYBUSY | MDCCR_VAL; | ||
| 540 | __raw_writel(val, ether->reg + REG_MIIDA); | ||
| 541 | |||
| 542 | for (i = 0; i < DELAY; i++) { | ||
| 543 | if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0) | ||
| 544 | break; | ||
| 545 | } | ||
| 546 | |||
| 547 | if (i == DELAY) { | ||
| 548 | dev_warn(&pdev->dev, "mdio read timed out\n"); | ||
| 549 | data = 0xffff; | ||
| 550 | } else { | ||
| 551 | data = __raw_readl(ether->reg + REG_MIID); | ||
| 552 | } | ||
| 553 | |||
| 554 | return data; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int w90p910_set_mac_address(struct net_device *dev, void *addr) | ||
| 558 | { | ||
| 559 | struct sockaddr *address = addr; | ||
| 560 | |||
| 561 | if (!is_valid_ether_addr(address->sa_data)) | ||
| 562 | return -EADDRNOTAVAIL; | ||
| 563 | |||
| 564 | memcpy(dev->dev_addr, address->sa_data, dev->addr_len); | ||
| 565 | w90p910_write_cam(dev, CAM0, dev->dev_addr); | ||
| 566 | |||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | static int w90p910_ether_close(struct net_device *dev) | ||
| 571 | { | ||
| 572 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 573 | struct platform_device *pdev; | ||
| 574 | |||
| 575 | pdev = ether->pdev; | ||
| 576 | |||
| 577 | dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc), | ||
| 578 | ether->rdesc, ether->rdesc_phys); | ||
| 579 | dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc), | ||
| 580 | ether->tdesc, ether->tdesc_phys); | ||
| 581 | |||
| 582 | netif_stop_queue(dev); | ||
| 583 | |||
| 584 | del_timer_sync(ðer->check_timer); | ||
| 585 | clk_disable(ether->rmiiclk); | ||
| 586 | clk_disable(ether->clk); | ||
| 587 | |||
| 588 | free_irq(ether->txirq, dev); | ||
| 589 | free_irq(ether->rxirq, dev); | ||
| 590 | |||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | static struct net_device_stats *w90p910_ether_stats(struct net_device *dev) | ||
| 595 | { | ||
| 596 | struct w90p910_ether *ether; | ||
| 597 | |||
| 598 | ether = netdev_priv(dev); | ||
| 599 | |||
| 600 | return ðer->stats; | ||
| 601 | } | ||
| 602 | |||
| 603 | static int w90p910_send_frame(struct net_device *dev, | ||
| 604 | unsigned char *data, int length) | ||
| 605 | { | ||
| 606 | struct w90p910_ether *ether; | ||
| 607 | struct w90p910_txbd *txbd; | ||
| 608 | struct platform_device *pdev; | ||
| 609 | unsigned char *buffer; | ||
| 610 | |||
| 611 | ether = netdev_priv(dev); | ||
| 612 | pdev = ether->pdev; | ||
| 613 | |||
| 614 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
| 615 | buffer = ether->tdesc->tran_buf[ether->cur_tx]; | ||
| 616 | |||
| 617 | if (length > 1514) { | ||
| 618 | dev_err(&pdev->dev, "send data %d bytes, check it\n", length); | ||
| 619 | length = 1514; | ||
| 620 | } | ||
| 621 | |||
| 622 | txbd->sl = length & 0xFFFF; | ||
| 623 | |||
| 624 | memcpy(buffer, data, length); | ||
| 625 | |||
| 626 | txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN; | ||
| 627 | |||
| 628 | w90p910_enable_tx(dev, 1); | ||
| 629 | |||
| 630 | w90p910_trigger_tx(dev); | ||
| 631 | |||
| 632 | if (++ether->cur_tx >= TX_DESC_SIZE) | ||
| 633 | ether->cur_tx = 0; | ||
| 634 | |||
| 635 | txbd = ðer->tdesc->desclist[ether->cur_tx]; | ||
| 636 | |||
| 637 | if (txbd->mode & TX_OWEN_DMA) | ||
| 638 | netif_stop_queue(dev); | ||
| 639 | |||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 644 | { | ||
| 645 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 646 | |||
| 647 | if (!(w90p910_send_frame(dev, skb->data, skb->len))) { | ||
| 648 | ether->skb = skb; | ||
| 649 | dev_kfree_skb_irq(skb); | ||
| 650 | return 0; | ||
| 651 | } | ||
| 652 | return -EAGAIN; | ||
| 653 | } | ||
| 654 | |||
| 655 | static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id) | ||
| 656 | { | ||
| 657 | struct w90p910_ether *ether; | ||
| 658 | struct w90p910_txbd *txbd; | ||
| 659 | struct platform_device *pdev; | ||
| 660 | struct net_device *dev; | ||
| 661 | unsigned int cur_entry, entry, status; | ||
| 662 | |||
| 663 | dev = dev_id; | ||
| 664 | ether = netdev_priv(dev); | ||
| 665 | pdev = ether->pdev; | ||
| 666 | |||
| 667 | w90p910_get_and_clear_int(dev, &status); | ||
| 668 | |||
| 669 | cur_entry = __raw_readl(ether->reg + REG_CTXDSA); | ||
| 670 | |||
| 671 | entry = ether->tdesc_phys + | ||
| 672 | offsetof(struct tran_pdesc, desclist[ether->finish_tx]); | ||
| 673 | |||
| 674 | while (entry != cur_entry) { | ||
| 675 | txbd = ðer->tdesc->desclist[ether->finish_tx]; | ||
| 676 | |||
| 677 | if (++ether->finish_tx >= TX_DESC_SIZE) | ||
| 678 | ether->finish_tx = 0; | ||
| 679 | |||
| 680 | if (txbd->sl & TXDS_TXCP) { | ||
| 681 | ether->stats.tx_packets++; | ||
| 682 | ether->stats.tx_bytes += txbd->sl & 0xFFFF; | ||
| 683 | } else { | ||
| 684 | ether->stats.tx_errors++; | ||
| 685 | } | ||
| 686 | |||
| 687 | txbd->sl = 0x0; | ||
| 688 | txbd->mode = 0x0; | ||
| 689 | |||
| 690 | if (netif_queue_stopped(dev)) | ||
| 691 | netif_wake_queue(dev); | ||
| 692 | |||
| 693 | entry = ether->tdesc_phys + | ||
| 694 | offsetof(struct tran_pdesc, desclist[ether->finish_tx]); | ||
| 695 | } | ||
| 696 | |||
| 697 | if (status & MISTA_EXDEF) { | ||
| 698 | dev_err(&pdev->dev, "emc defer exceed interrupt\n"); | ||
| 699 | } else if (status & MISTA_TXBERR) { | ||
| 700 | dev_err(&pdev->dev, "emc bus error interrupt\n"); | ||
| 701 | w90p910_reset_mac(dev); | ||
| 702 | } else if (status & MISTA_TDU) { | ||
| 703 | if (netif_queue_stopped(dev)) | ||
| 704 | netif_wake_queue(dev); | ||
| 705 | } | ||
| 706 | |||
| 707 | return IRQ_HANDLED; | ||
| 708 | } | ||
| 709 | |||
| 710 | static void netdev_rx(struct net_device *dev) | ||
| 711 | { | ||
| 712 | struct w90p910_ether *ether; | ||
| 713 | struct w90p910_rxbd *rxbd; | ||
| 714 | struct platform_device *pdev; | ||
| 715 | struct sk_buff *skb; | ||
| 716 | unsigned char *data; | ||
| 717 | unsigned int length, status, val, entry; | ||
| 718 | |||
| 719 | ether = netdev_priv(dev); | ||
| 720 | pdev = ether->pdev; | ||
| 721 | |||
| 722 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
| 723 | |||
| 724 | do { | ||
| 725 | val = __raw_readl(ether->reg + REG_CRXDSA); | ||
| 726 | |||
| 727 | entry = ether->rdesc_phys + | ||
| 728 | offsetof(struct recv_pdesc, desclist[ether->cur_rx]); | ||
| 729 | |||
| 730 | if (val == entry) | ||
| 731 | break; | ||
| 732 | |||
| 733 | status = rxbd->sl; | ||
| 734 | length = status & 0xFFFF; | ||
| 735 | |||
| 736 | if (status & RXDS_RXGD) { | ||
| 737 | data = ether->rdesc->recv_buf[ether->cur_rx]; | ||
| 738 | skb = dev_alloc_skb(length+2); | ||
| 739 | if (!skb) { | ||
| 740 | dev_err(&pdev->dev, "get skb buffer error\n"); | ||
| 741 | ether->stats.rx_dropped++; | ||
| 742 | return; | ||
| 743 | } | ||
| 744 | |||
| 745 | skb_reserve(skb, 2); | ||
| 746 | skb_put(skb, length); | ||
| 747 | skb_copy_to_linear_data(skb, data, length); | ||
| 748 | skb->protocol = eth_type_trans(skb, dev); | ||
| 749 | ether->stats.rx_packets++; | ||
| 750 | ether->stats.rx_bytes += length; | ||
| 751 | netif_rx(skb); | ||
| 752 | } else { | ||
| 753 | ether->stats.rx_errors++; | ||
| 754 | |||
| 755 | if (status & RXDS_RP) { | ||
| 756 | dev_err(&pdev->dev, "rx runt err\n"); | ||
| 757 | ether->stats.rx_length_errors++; | ||
| 758 | } else if (status & RXDS_CRCE) { | ||
| 759 | dev_err(&pdev->dev, "rx crc err\n"); | ||
| 760 | ether->stats.rx_crc_errors++; | ||
| 761 | } else if (status & RXDS_ALIE) { | ||
| 762 | dev_err(&pdev->dev, "rx aligment err\n"); | ||
| 763 | ether->stats.rx_frame_errors++; | ||
| 764 | } else if (status & RXDS_PTLE) { | ||
| 765 | dev_err(&pdev->dev, "rx longer err\n"); | ||
| 766 | ether->stats.rx_over_errors++; | ||
| 767 | } | ||
| 768 | } | ||
| 769 | |||
| 770 | rxbd->sl = RX_OWEN_DMA; | ||
| 771 | rxbd->reserved = 0x0; | ||
| 772 | |||
| 773 | if (++ether->cur_rx >= RX_DESC_SIZE) | ||
| 774 | ether->cur_rx = 0; | ||
| 775 | |||
| 776 | rxbd = ðer->rdesc->desclist[ether->cur_rx]; | ||
| 777 | |||
| 778 | } while (1); | ||
| 779 | } | ||
| 780 | |||
| 781 | static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id) | ||
| 782 | { | ||
| 783 | struct net_device *dev; | ||
| 784 | struct w90p910_ether *ether; | ||
| 785 | struct platform_device *pdev; | ||
| 786 | unsigned int status; | ||
| 787 | |||
| 788 | dev = dev_id; | ||
| 789 | ether = netdev_priv(dev); | ||
| 790 | pdev = ether->pdev; | ||
| 791 | |||
| 792 | w90p910_get_and_clear_int(dev, &status); | ||
| 793 | |||
| 794 | if (status & MISTA_RDU) { | ||
| 795 | netdev_rx(dev); | ||
| 796 | w90p910_trigger_rx(dev); | ||
| 797 | |||
| 798 | return IRQ_HANDLED; | ||
| 799 | } else if (status & MISTA_RXBERR) { | ||
| 800 | dev_err(&pdev->dev, "emc rx bus error\n"); | ||
| 801 | w90p910_reset_mac(dev); | ||
| 802 | } | ||
| 803 | |||
| 804 | netdev_rx(dev); | ||
| 805 | return IRQ_HANDLED; | ||
| 806 | } | ||
| 807 | |||
| 808 | static int w90p910_ether_open(struct net_device *dev) | ||
| 809 | { | ||
| 810 | struct w90p910_ether *ether; | ||
| 811 | struct platform_device *pdev; | ||
| 812 | |||
| 813 | ether = netdev_priv(dev); | ||
| 814 | pdev = ether->pdev; | ||
| 815 | |||
| 816 | w90p910_reset_mac(dev); | ||
| 817 | w90p910_set_fifo_threshold(dev); | ||
| 818 | w90p910_set_curdest(dev); | ||
| 819 | w90p910_enable_cam(dev); | ||
| 820 | w90p910_enable_cam_command(dev); | ||
| 821 | w90p910_enable_mac_interrupt(dev); | ||
| 822 | w90p910_set_global_maccmd(dev); | ||
| 823 | w90p910_enable_rx(dev, 1); | ||
| 824 | |||
| 825 | clk_enable(ether->rmiiclk); | ||
| 826 | clk_enable(ether->clk); | ||
| 827 | |||
| 828 | ether->rx_packets = 0x0; | ||
| 829 | ether->rx_bytes = 0x0; | ||
| 830 | |||
| 831 | if (request_irq(ether->txirq, w90p910_tx_interrupt, | ||
| 832 | 0x0, pdev->name, dev)) { | ||
| 833 | dev_err(&pdev->dev, "register irq tx failed\n"); | ||
| 834 | return -EAGAIN; | ||
| 835 | } | ||
| 836 | |||
| 837 | if (request_irq(ether->rxirq, w90p910_rx_interrupt, | ||
| 838 | 0x0, pdev->name, dev)) { | ||
| 839 | dev_err(&pdev->dev, "register irq rx failed\n"); | ||
| 840 | free_irq(ether->txirq, dev); | ||
| 841 | return -EAGAIN; | ||
| 842 | } | ||
| 843 | |||
| 844 | mod_timer(ðer->check_timer, jiffies + msecs_to_jiffies(1000)); | ||
| 845 | netif_start_queue(dev); | ||
| 846 | w90p910_trigger_rx(dev); | ||
| 847 | |||
| 848 | dev_info(&pdev->dev, "%s is OPENED\n", dev->name); | ||
| 849 | |||
| 850 | return 0; | ||
| 851 | } | ||
| 852 | |||
| 853 | static void w90p910_ether_set_multicast_list(struct net_device *dev) | ||
| 854 | { | ||
| 855 | struct w90p910_ether *ether; | ||
| 856 | unsigned int rx_mode; | ||
| 857 | |||
| 858 | ether = netdev_priv(dev); | ||
| 859 | |||
| 860 | if (dev->flags & IFF_PROMISC) | ||
| 861 | rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
| 862 | else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) | ||
| 863 | rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; | ||
| 864 | else | ||
| 865 | rx_mode = CAMCMR_ECMP | CAMCMR_ABP; | ||
| 866 | __raw_writel(rx_mode, ether->reg + REG_CAMCMR); | ||
| 867 | } | ||
| 868 | |||
| 869 | static int w90p910_ether_ioctl(struct net_device *dev, | ||
| 870 | struct ifreq *ifr, int cmd) | ||
| 871 | { | ||
| 872 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 873 | struct mii_ioctl_data *data = if_mii(ifr); | ||
| 874 | |||
| 875 | return generic_mii_ioctl(ðer->mii, data, cmd, NULL); | ||
| 876 | } | ||
| 877 | |||
| 878 | static void w90p910_get_drvinfo(struct net_device *dev, | ||
| 879 | struct ethtool_drvinfo *info) | ||
| 880 | { | ||
| 881 | strcpy(info->driver, DRV_MODULE_NAME); | ||
| 882 | strcpy(info->version, DRV_MODULE_VERSION); | ||
| 883 | } | ||
| 884 | |||
| 885 | static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 886 | { | ||
| 887 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 888 | return mii_ethtool_gset(ðer->mii, cmd); | ||
| 889 | } | ||
| 890 | |||
| 891 | static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 892 | { | ||
| 893 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 894 | return mii_ethtool_sset(ðer->mii, cmd); | ||
| 895 | } | ||
| 896 | |||
| 897 | static int w90p910_nway_reset(struct net_device *dev) | ||
| 898 | { | ||
| 899 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 900 | return mii_nway_restart(ðer->mii); | ||
| 901 | } | ||
| 902 | |||
| 903 | static u32 w90p910_get_link(struct net_device *dev) | ||
| 904 | { | ||
| 905 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 906 | return mii_link_ok(ðer->mii); | ||
| 907 | } | ||
| 908 | |||
| 909 | static const struct ethtool_ops w90p910_ether_ethtool_ops = { | ||
| 910 | .get_settings = w90p910_get_settings, | ||
| 911 | .set_settings = w90p910_set_settings, | ||
| 912 | .get_drvinfo = w90p910_get_drvinfo, | ||
| 913 | .nway_reset = w90p910_nway_reset, | ||
| 914 | .get_link = w90p910_get_link, | ||
| 915 | }; | ||
| 916 | |||
| 917 | static const struct net_device_ops w90p910_ether_netdev_ops = { | ||
| 918 | .ndo_open = w90p910_ether_open, | ||
| 919 | .ndo_stop = w90p910_ether_close, | ||
| 920 | .ndo_start_xmit = w90p910_ether_start_xmit, | ||
| 921 | .ndo_get_stats = w90p910_ether_stats, | ||
| 922 | .ndo_set_multicast_list = w90p910_ether_set_multicast_list, | ||
| 923 | .ndo_set_mac_address = w90p910_set_mac_address, | ||
| 924 | .ndo_do_ioctl = w90p910_ether_ioctl, | ||
| 925 | .ndo_validate_addr = eth_validate_addr, | ||
| 926 | .ndo_change_mtu = eth_change_mtu, | ||
| 927 | }; | ||
| 928 | |||
| 929 | static void __init get_mac_address(struct net_device *dev) | ||
| 930 | { | ||
| 931 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 932 | struct platform_device *pdev; | ||
| 933 | char addr[6]; | ||
| 934 | |||
| 935 | pdev = ether->pdev; | ||
| 936 | |||
| 937 | addr[0] = 0x00; | ||
| 938 | addr[1] = 0x02; | ||
| 939 | addr[2] = 0xac; | ||
| 940 | addr[3] = 0x55; | ||
| 941 | addr[4] = 0x88; | ||
| 942 | addr[5] = 0xa8; | ||
| 943 | |||
| 944 | if (is_valid_ether_addr(addr)) | ||
| 945 | memcpy(dev->dev_addr, &addr, 0x06); | ||
| 946 | else | ||
| 947 | dev_err(&pdev->dev, "invalid mac address\n"); | ||
| 948 | } | ||
| 949 | |||
| 950 | static int w90p910_ether_setup(struct net_device *dev) | ||
| 951 | { | ||
| 952 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 953 | |||
| 954 | ether_setup(dev); | ||
| 955 | dev->netdev_ops = &w90p910_ether_netdev_ops; | ||
| 956 | dev->ethtool_ops = &w90p910_ether_ethtool_ops; | ||
| 957 | |||
| 958 | dev->tx_queue_len = 16; | ||
| 959 | dev->dma = 0x0; | ||
| 960 | dev->watchdog_timeo = TX_TIMEOUT; | ||
| 961 | |||
| 962 | get_mac_address(dev); | ||
| 963 | |||
| 964 | ether->cur_tx = 0x0; | ||
| 965 | ether->cur_rx = 0x0; | ||
| 966 | ether->finish_tx = 0x0; | ||
| 967 | ether->linkflag = 0x0; | ||
| 968 | ether->mii.phy_id = 0x01; | ||
| 969 | ether->mii.phy_id_mask = 0x1f; | ||
| 970 | ether->mii.reg_num_mask = 0x1f; | ||
| 971 | ether->mii.dev = dev; | ||
| 972 | ether->mii.mdio_read = w90p910_mdio_read; | ||
| 973 | ether->mii.mdio_write = w90p910_mdio_write; | ||
| 974 | |||
| 975 | setup_timer(ðer->check_timer, w90p910_check_link, | ||
| 976 | (unsigned long)dev); | ||
| 977 | |||
| 978 | return 0; | ||
| 979 | } | ||
| 980 | |||
| 981 | static int __devinit w90p910_ether_probe(struct platform_device *pdev) | ||
| 982 | { | ||
| 983 | struct w90p910_ether *ether; | ||
| 984 | struct net_device *dev; | ||
| 985 | int error; | ||
| 986 | |||
| 987 | dev = alloc_etherdev(sizeof(struct w90p910_ether)); | ||
| 988 | if (!dev) | ||
| 989 | return -ENOMEM; | ||
| 990 | |||
| 991 | ether = netdev_priv(dev); | ||
| 992 | |||
| 993 | ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 994 | if (ether->res == NULL) { | ||
| 995 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
| 996 | error = -ENXIO; | ||
| 997 | goto failed_free; | ||
| 998 | } | ||
| 999 | |||
| 1000 | if (!request_mem_region(ether->res->start, | ||
| 1001 | resource_size(ether->res), pdev->name)) { | ||
| 1002 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
| 1003 | error = -EBUSY; | ||
| 1004 | goto failed_free; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | ether->reg = ioremap(ether->res->start, resource_size(ether->res)); | ||
| 1008 | if (ether->reg == NULL) { | ||
| 1009 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
| 1010 | error = -ENXIO; | ||
| 1011 | goto failed_free_mem; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | ether->txirq = platform_get_irq(pdev, 0); | ||
| 1015 | if (ether->txirq < 0) { | ||
| 1016 | dev_err(&pdev->dev, "failed to get ether tx irq\n"); | ||
| 1017 | error = -ENXIO; | ||
| 1018 | goto failed_free_io; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | ether->rxirq = platform_get_irq(pdev, 1); | ||
| 1022 | if (ether->rxirq < 0) { | ||
| 1023 | dev_err(&pdev->dev, "failed to get ether rx irq\n"); | ||
| 1024 | error = -ENXIO; | ||
| 1025 | goto failed_free_txirq; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | platform_set_drvdata(pdev, dev); | ||
| 1029 | |||
| 1030 | ether->clk = clk_get(&pdev->dev, NULL); | ||
| 1031 | if (IS_ERR(ether->clk)) { | ||
| 1032 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
| 1033 | error = PTR_ERR(ether->clk); | ||
| 1034 | goto failed_free_rxirq; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | ether->rmiiclk = clk_get(&pdev->dev, "RMII"); | ||
| 1038 | if (IS_ERR(ether->rmiiclk)) { | ||
| 1039 | dev_err(&pdev->dev, "failed to get ether clock\n"); | ||
| 1040 | error = PTR_ERR(ether->rmiiclk); | ||
| 1041 | goto failed_put_clk; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | ether->pdev = pdev; | ||
| 1045 | |||
| 1046 | w90p910_ether_setup(dev); | ||
| 1047 | |||
| 1048 | error = register_netdev(dev); | ||
| 1049 | if (error != 0) { | ||
| 1050 | dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n"); | ||
| 1051 | error = -ENODEV; | ||
| 1052 | goto failed_put_rmiiclk; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | return 0; | ||
| 1056 | failed_put_rmiiclk: | ||
| 1057 | clk_put(ether->rmiiclk); | ||
| 1058 | failed_put_clk: | ||
| 1059 | clk_put(ether->clk); | ||
| 1060 | failed_free_rxirq: | ||
| 1061 | free_irq(ether->rxirq, pdev); | ||
| 1062 | platform_set_drvdata(pdev, NULL); | ||
| 1063 | failed_free_txirq: | ||
| 1064 | free_irq(ether->txirq, pdev); | ||
| 1065 | failed_free_io: | ||
| 1066 | iounmap(ether->reg); | ||
| 1067 | failed_free_mem: | ||
| 1068 | release_mem_region(ether->res->start, resource_size(ether->res)); | ||
| 1069 | failed_free: | ||
| 1070 | free_netdev(dev); | ||
| 1071 | return error; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static int __devexit w90p910_ether_remove(struct platform_device *pdev) | ||
| 1075 | { | ||
| 1076 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1077 | struct w90p910_ether *ether = netdev_priv(dev); | ||
| 1078 | |||
| 1079 | unregister_netdev(dev); | ||
| 1080 | |||
| 1081 | clk_put(ether->rmiiclk); | ||
| 1082 | clk_put(ether->clk); | ||
| 1083 | |||
| 1084 | iounmap(ether->reg); | ||
| 1085 | release_mem_region(ether->res->start, resource_size(ether->res)); | ||
| 1086 | |||
| 1087 | free_irq(ether->txirq, dev); | ||
| 1088 | free_irq(ether->rxirq, dev); | ||
| 1089 | |||
| 1090 | del_timer_sync(ðer->check_timer); | ||
| 1091 | platform_set_drvdata(pdev, NULL); | ||
| 1092 | |||
| 1093 | free_netdev(dev); | ||
| 1094 | return 0; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | static struct platform_driver w90p910_ether_driver = { | ||
| 1098 | .probe = w90p910_ether_probe, | ||
| 1099 | .remove = __devexit_p(w90p910_ether_remove), | ||
| 1100 | .driver = { | ||
| 1101 | .name = "nuc900-emc", | ||
| 1102 | .owner = THIS_MODULE, | ||
| 1103 | }, | ||
| 1104 | }; | ||
| 1105 | |||
| 1106 | static int __init w90p910_ether_init(void) | ||
| 1107 | { | ||
| 1108 | return platform_driver_register(&w90p910_ether_driver); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void __exit w90p910_ether_exit(void) | ||
| 1112 | { | ||
| 1113 | platform_driver_unregister(&w90p910_ether_driver); | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | module_init(w90p910_ether_init); | ||
| 1117 | module_exit(w90p910_ether_exit); | ||
| 1118 | |||
| 1119 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
| 1120 | MODULE_DESCRIPTION("w90p910 MAC driver!"); | ||
| 1121 | MODULE_LICENSE("GPL"); | ||
| 1122 | MODULE_ALIAS("platform:nuc900-emc"); | ||
| 1123 | |||
