linux/drivers/net/ethernet/amd/am79c961a.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  linux/drivers/net/ethernet/amd/am79c961a.c
   4 *
   5 *  by Russell King <rmk@arm.linux.org.uk> 1995-2001.
   6 *
   7 * Derived from various things including skeleton.c
   8 *
   9 * This is a special driver for the am79c961A Lance chip used in the
  10 * Intel (formally Digital Equipment Corp) EBSA110 platform.  Please
  11 * note that this can not be built as a module (it doesn't make sense).
  12 */
  13#include <linux/kernel.h>
  14#include <linux/types.h>
  15#include <linux/interrupt.h>
  16#include <linux/ioport.h>
  17#include <linux/slab.h>
  18#include <linux/string.h>
  19#include <linux/errno.h>
  20#include <linux/netdevice.h>
  21#include <linux/etherdevice.h>
  22#include <linux/delay.h>
  23#include <linux/init.h>
  24#include <linux/crc32.h>
  25#include <linux/bitops.h>
  26#include <linux/platform_device.h>
  27#include <linux/io.h>
  28
  29#include <mach/hardware.h>
  30
  31#define TX_BUFFERS 15
  32#define RX_BUFFERS 25
  33
  34#include "am79c961a.h"
  35
  36static irqreturn_t
  37am79c961_interrupt (int irq, void *dev_id);
  38
  39static unsigned int net_debug = NET_DEBUG;
  40
  41static const char version[] =
  42        "am79c961 ethernet driver (C) 1995-2001 Russell King v0.04\n";
  43
  44/* --------------------------------------------------------------------------- */
  45
  46#ifdef __arm__
  47static void write_rreg(u_long base, u_int reg, u_int val)
  48{
  49        asm volatile(
  50        "strh   %1, [%2]        @ NET_RAP\n\t"
  51        "strh   %0, [%2, #-4]   @ NET_RDP"
  52        :
  53        : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  54}
  55
  56static inline unsigned short read_rreg(u_long base_addr, u_int reg)
  57{
  58        unsigned short v;
  59        asm volatile(
  60        "strh   %1, [%2]        @ NET_RAP\n\t"
  61        "ldrh   %0, [%2, #-4]   @ NET_RDP"
  62        : "=r" (v)
  63        : "r" (reg), "r" (ISAIO_BASE + 0x0464));
  64        return v;
  65}
  66
  67static inline void write_ireg(u_long base, u_int reg, u_int val)
  68{
  69        asm volatile(
  70        "strh   %1, [%2]        @ NET_RAP\n\t"
  71        "strh   %0, [%2, #8]    @ NET_IDP"
  72        :
  73        : "r" (val), "r" (reg), "r" (ISAIO_BASE + 0x0464));
  74}
  75
  76static inline unsigned short read_ireg(u_long base_addr, u_int reg)
  77{
  78        u_short v;
  79        asm volatile(
  80        "strh   %1, [%2]        @ NAT_RAP\n\t"
  81        "ldrh   %0, [%2, #8]    @ NET_IDP\n\t"
  82        : "=r" (v)
  83        : "r" (reg), "r" (ISAIO_BASE + 0x0464));
  84        return v;
  85}
  86
  87#define am_writeword(dev,off,val) __raw_writew(val, ISAMEM_BASE + ((off) << 1))
  88#define am_readword(dev,off)      __raw_readw(ISAMEM_BASE + ((off) << 1))
  89
  90static void
  91am_writebuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
  92{
  93        offset = ISAMEM_BASE + (offset << 1);
  94        length = (length + 1) & ~1;
  95        if ((int)buf & 2) {
  96                asm volatile("strh      %2, [%0], #4"
  97                 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
  98                buf += 2;
  99                length -= 2;
 100        }
 101        while (length > 8) {
 102                register unsigned int tmp asm("r2"), tmp2 asm("r3");
 103                asm volatile(
 104                        "ldmia  %0!, {%1, %2}"
 105                        : "+r" (buf), "=&r" (tmp), "=&r" (tmp2));
 106                length -= 8;
 107                asm volatile(
 108                        "strh   %1, [%0], #4\n\t"
 109                        "mov    %1, %1, lsr #16\n\t"
 110                        "strh   %1, [%0], #4\n\t"
 111                        "strh   %2, [%0], #4\n\t"
 112                        "mov    %2, %2, lsr #16\n\t"
 113                        "strh   %2, [%0], #4"
 114                : "+r" (offset), "=&r" (tmp), "=&r" (tmp2));
 115        }
 116        while (length > 0) {
 117                asm volatile("strh      %2, [%0], #4"
 118                 : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
 119                buf += 2;
 120                length -= 2;
 121        }
 122}
 123
 124static void
 125am_readbuffer(struct net_device *dev, u_int offset, unsigned char *buf, unsigned int length)
 126{
 127        offset = ISAMEM_BASE + (offset << 1);
 128        length = (length + 1) & ~1;
 129        if ((int)buf & 2) {
 130                unsigned int tmp;
 131                asm volatile(
 132                        "ldrh   %2, [%0], #4\n\t"
 133                        "strb   %2, [%1], #1\n\t"
 134                        "mov    %2, %2, lsr #8\n\t"
 135                        "strb   %2, [%1], #1"
 136                : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
 137                length -= 2;
 138        }
 139        while (length > 8) {
 140                register unsigned int tmp asm("r2"), tmp2 asm("r3"), tmp3;
 141                asm volatile(
 142                        "ldrh   %2, [%0], #4\n\t"
 143                        "ldrh   %4, [%0], #4\n\t"
 144                        "ldrh   %3, [%0], #4\n\t"
 145                        "orr    %2, %2, %4, lsl #16\n\t"
 146                        "ldrh   %4, [%0], #4\n\t"
 147                        "orr    %3, %3, %4, lsl #16\n\t"
 148                        "stmia  %1!, {%2, %3}"
 149                : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
 150                : "0" (offset), "1" (buf));
 151                length -= 8;
 152        }
 153        while (length > 0) {
 154                unsigned int tmp;
 155                asm volatile(
 156                        "ldrh   %2, [%0], #4\n\t"
 157                        "strb   %2, [%1], #1\n\t"
 158                        "mov    %2, %2, lsr #8\n\t"
 159                        "strb   %2, [%1], #1"
 160                : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
 161                length -= 2;
 162        }
 163}
 164#else
 165#error Not compatible
 166#endif
 167
 168static int
 169am79c961_ramtest(struct net_device *dev, unsigned int val)
 170{
 171        unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
 172        int i, error = 0, errorcount = 0;
 173
 174        if (!buffer)
 175                return 0;
 176        memset (buffer, val, 65536);
 177        am_writebuffer(dev, 0, buffer, 65536);
 178        memset (buffer, val ^ 255, 65536);
 179        am_readbuffer(dev, 0, buffer, 65536);
 180        for (i = 0; i < 65536; i++) {
 181                if (buffer[i] != val && !error) {
 182                        printk ("%s: buffer error (%02X %02X) %05X - ", dev->name, val, buffer[i], i);
 183                        error = 1;
 184                        errorcount ++;
 185                } else if (error && buffer[i] == val) {
 186                        printk ("%05X\n", i);
 187                        error = 0;
 188                }
 189        }
 190        if (error)
 191                printk ("10000\n");
 192        kfree (buffer);
 193        return errorcount;
 194}
 195
 196static void am79c961_mc_hash(char *addr, u16 *hash)
 197{
 198        int idx, bit;
 199        u32 crc;
 200
 201        crc = ether_crc_le(ETH_ALEN, addr);
 202
 203        idx = crc >> 30;
 204        bit = (crc >> 26) & 15;
 205
 206        hash[idx] |= 1 << bit;
 207}
 208
 209static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash)
 210{
 211        unsigned int mode = MODE_PORT_10BT;
 212
 213        if (dev->flags & IFF_PROMISC) {
 214                mode |= MODE_PROMISC;
 215                memset(hash, 0xff, 4 * sizeof(*hash));
 216        } else if (dev->flags & IFF_ALLMULTI) {
 217                memset(hash, 0xff, 4 * sizeof(*hash));
 218        } else {
 219                struct netdev_hw_addr *ha;
 220
 221                memset(hash, 0, 4 * sizeof(*hash));
 222
 223                netdev_for_each_mc_addr(ha, dev)
 224                        am79c961_mc_hash(ha->addr, hash);
 225        }
 226
 227        return mode;
 228}
 229
 230static void
 231am79c961_init_for_open(struct net_device *dev)
 232{
 233        struct dev_priv *priv = netdev_priv(dev);
 234        unsigned long flags;
 235        unsigned char *p;
 236        u_int hdr_addr, first_free_addr;
 237        u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
 238        int i;
 239
 240        /*
 241         * Stop the chip.
 242         */
 243        spin_lock_irqsave(&priv->chip_lock, flags);
 244        write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
 245        spin_unlock_irqrestore(&priv->chip_lock, flags);
 246
 247        write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */
 248        write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */
 249        write_ireg (dev->base_addr, 7, 0x0090); /* XMIT LED */
 250        write_ireg (dev->base_addr, 2, 0x0000); /* MODE register selects media */
 251
 252        for (i = LADRL; i <= LADRH; i++)
 253                write_rreg (dev->base_addr, i, multi_hash[i - LADRL]);
 254
 255        for (i = PADRL, p = dev->dev_addr; i <= PADRH; i++, p += 2)
 256                write_rreg (dev->base_addr, i, p[0] | (p[1] << 8));
 257
 258        write_rreg (dev->base_addr, MODE, mode);
 259        write_rreg (dev->base_addr, POLLINT, 0);
 260        write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
 261        write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
 262
 263        first_free_addr = RX_BUFFERS * 8 + TX_BUFFERS * 8 + 16;
 264        hdr_addr = 0;
 265
 266        priv->rxhead = 0;
 267        priv->rxtail = 0;
 268        priv->rxhdr = hdr_addr;
 269
 270        for (i = 0; i < RX_BUFFERS; i++) {
 271                priv->rxbuffer[i] = first_free_addr;
 272                am_writeword (dev, hdr_addr, first_free_addr);
 273                am_writeword (dev, hdr_addr + 2, RMD_OWN);
 274                am_writeword (dev, hdr_addr + 4, (-1600));
 275                am_writeword (dev, hdr_addr + 6, 0);
 276                first_free_addr += 1600;
 277                hdr_addr += 8;
 278        }
 279        priv->txhead = 0;
 280        priv->txtail = 0;
 281        priv->txhdr = hdr_addr;
 282        for (i = 0; i < TX_BUFFERS; i++) {
 283                priv->txbuffer[i] = first_free_addr;
 284                am_writeword (dev, hdr_addr, first_free_addr);
 285                am_writeword (dev, hdr_addr + 2, TMD_STP|TMD_ENP);
 286                am_writeword (dev, hdr_addr + 4, 0xf000);
 287                am_writeword (dev, hdr_addr + 6, 0);
 288                first_free_addr += 1600;
 289                hdr_addr += 8;
 290        }
 291
 292        write_rreg (dev->base_addr, BASERXL, priv->rxhdr);
 293        write_rreg (dev->base_addr, BASERXH, 0);
 294        write_rreg (dev->base_addr, BASETXL, priv->txhdr);
 295        write_rreg (dev->base_addr, BASERXH, 0);
 296        write_rreg (dev->base_addr, CSR0, CSR0_STOP);
 297        write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
 298        write_rreg (dev->base_addr, CSR4, CSR4_APAD_XMIT|CSR4_MFCOM|CSR4_RCVCCOM|CSR4_TXSTRTM|CSR4_JABM);
 299        write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
 300}
 301
 302static void am79c961_timer(struct timer_list *t)
 303{
 304        struct dev_priv *priv = from_timer(priv, t, timer);
 305        struct net_device *dev = priv->dev;
 306        unsigned int lnkstat, carrier;
 307        unsigned long flags;
 308
 309        spin_lock_irqsave(&priv->chip_lock, flags);
 310        lnkstat = read_ireg(dev->base_addr, ISALED0) & ISALED0_LNKST;
 311        spin_unlock_irqrestore(&priv->chip_lock, flags);
 312        carrier = netif_carrier_ok(dev);
 313
 314        if (lnkstat && !carrier) {
 315                netif_carrier_on(dev);
 316                printk("%s: link up\n", dev->name);
 317        } else if (!lnkstat && carrier) {
 318                netif_carrier_off(dev);
 319                printk("%s: link down\n", dev->name);
 320        }
 321
 322        mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
 323}
 324
 325/*
 326 * Open/initialize the board.
 327 */
 328static int
 329am79c961_open(struct net_device *dev)
 330{
 331        struct dev_priv *priv = netdev_priv(dev);
 332        int ret;
 333
 334        ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev);
 335        if (ret)
 336                return ret;
 337
 338        am79c961_init_for_open(dev);
 339
 340        netif_carrier_off(dev);
 341
 342        priv->timer.expires = jiffies;
 343        add_timer(&priv->timer);
 344
 345        netif_start_queue(dev);
 346
 347        return 0;
 348}
 349
 350/*
 351 * The inverse routine to am79c961_open().
 352 */
 353static int
 354am79c961_close(struct net_device *dev)
 355{
 356        struct dev_priv *priv = netdev_priv(dev);
 357        unsigned long flags;
 358
 359        del_timer_sync(&priv->timer);
 360
 361        netif_stop_queue(dev);
 362        netif_carrier_off(dev);
 363
 364        spin_lock_irqsave(&priv->chip_lock, flags);
 365        write_rreg (dev->base_addr, CSR0, CSR0_STOP);
 366        write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
 367        spin_unlock_irqrestore(&priv->chip_lock, flags);
 368
 369        free_irq (dev->irq, dev);
 370
 371        return 0;
 372}
 373
 374/*
 375 * Set or clear promiscuous/multicast mode filter for this adapter.
 376 */
 377static void am79c961_setmulticastlist (struct net_device *dev)
 378{
 379        struct dev_priv *priv = netdev_priv(dev);
 380        unsigned long flags;
 381        u16 multi_hash[4], mode = am79c961_get_rx_mode(dev, multi_hash);
 382        int i, stopped;
 383
 384        spin_lock_irqsave(&priv->chip_lock, flags);
 385
 386        stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
 387
 388        if (!stopped) {
 389                /*
 390                 * Put the chip into suspend mode
 391                 */
 392                write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
 393
 394                /*
 395                 * Spin waiting for chip to report suspend mode
 396                 */
 397                while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
 398                        spin_unlock_irqrestore(&priv->chip_lock, flags);
 399                        nop();
 400                        spin_lock_irqsave(&priv->chip_lock, flags);
 401                }
 402        }
 403
 404        /*
 405         * Update the multicast hash table
 406         */
 407        for (i = 0; i < ARRAY_SIZE(multi_hash); i++)
 408                write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
 409
 410        /*
 411         * Write the mode register
 412         */
 413        write_rreg(dev->base_addr, MODE, mode);
 414
 415        if (!stopped) {
 416                /*
 417                 * Put the chip back into running mode
 418                 */
 419                write_rreg(dev->base_addr, CTRL1, 0);
 420        }
 421
 422        spin_unlock_irqrestore(&priv->chip_lock, flags);
 423}
 424
 425static void am79c961_timeout(struct net_device *dev, unsigned int txqueue)
 426{
 427        printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
 428                dev->name);
 429
 430        /*
 431         * ought to do some setup of the tx side here
 432         */
 433
 434        netif_wake_queue(dev);
 435}
 436
 437/*
 438 * Transmit a packet
 439 */
 440static netdev_tx_t
 441am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
 442{
 443        struct dev_priv *priv = netdev_priv(dev);
 444        unsigned int hdraddr, bufaddr;
 445        unsigned int head;
 446        unsigned long flags;
 447
 448        head = priv->txhead;
 449        hdraddr = priv->txhdr + (head << 3);
 450        bufaddr = priv->txbuffer[head];
 451        head += 1;
 452        if (head >= TX_BUFFERS)
 453                head = 0;
 454
 455        am_writebuffer (dev, bufaddr, skb->data, skb->len);
 456        am_writeword (dev, hdraddr + 4, -skb->len);
 457        am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
 458        priv->txhead = head;
 459
 460        spin_lock_irqsave(&priv->chip_lock, flags);
 461        write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
 462        spin_unlock_irqrestore(&priv->chip_lock, flags);
 463
 464        /*
 465         * If the next packet is owned by the ethernet device,
 466         * then the tx ring is full and we can't add another
 467         * packet.
 468         */
 469        if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)
 470                netif_stop_queue(dev);
 471
 472        dev_consume_skb_any(skb);
 473
 474        return NETDEV_TX_OK;
 475}
 476
 477/*
 478 * If we have a good packet(s), get it/them out of the buffers.
 479 */
 480static void
 481am79c961_rx(struct net_device *dev, struct dev_priv *priv)
 482{
 483        do {
 484                struct sk_buff *skb;
 485                u_int hdraddr;
 486                u_int pktaddr;
 487                u_int status;
 488                int len;
 489
 490                hdraddr = priv->rxhdr + (priv->rxtail << 3);
 491                pktaddr = priv->rxbuffer[priv->rxtail];
 492
 493                status = am_readword (dev, hdraddr + 2);
 494                if (status & RMD_OWN) /* do we own it? */
 495                        break;
 496
 497                priv->rxtail ++;
 498                if (priv->rxtail >= RX_BUFFERS)
 499                        priv->rxtail = 0;
 500
 501                if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
 502                        am_writeword (dev, hdraddr + 2, RMD_OWN);
 503                        dev->stats.rx_errors++;
 504                        if (status & RMD_ERR) {
 505                                if (status & RMD_FRAM)
 506                                        dev->stats.rx_frame_errors++;
 507                                if (status & RMD_CRC)
 508                                        dev->stats.rx_crc_errors++;
 509                        } else if (status & RMD_STP)
 510                                dev->stats.rx_length_errors++;
 511                        continue;
 512                }
 513
 514                len = am_readword(dev, hdraddr + 6);
 515                skb = netdev_alloc_skb(dev, len + 2);
 516
 517                if (skb) {
 518                        skb_reserve(skb, 2);
 519
 520                        am_readbuffer(dev, pktaddr, skb_put(skb, len), len);
 521                        am_writeword(dev, hdraddr + 2, RMD_OWN);
 522                        skb->protocol = eth_type_trans(skb, dev);
 523                        netif_rx(skb);
 524                        dev->stats.rx_bytes += len;
 525                        dev->stats.rx_packets++;
 526                } else {
 527                        am_writeword (dev, hdraddr + 2, RMD_OWN);
 528                        dev->stats.rx_dropped++;
 529                        break;
 530                }
 531        } while (1);
 532}
 533
 534/*
 535 * Update stats for the transmitted packet
 536 */
 537static void
 538am79c961_tx(struct net_device *dev, struct dev_priv *priv)
 539{
 540        do {
 541                short len;
 542                u_int hdraddr;
 543                u_int status;
 544
 545                hdraddr = priv->txhdr + (priv->txtail << 3);
 546                status = am_readword (dev, hdraddr + 2);
 547                if (status & TMD_OWN)
 548                        break;
 549
 550                priv->txtail ++;
 551                if (priv->txtail >= TX_BUFFERS)
 552                        priv->txtail = 0;
 553
 554                if (status & TMD_ERR) {
 555                        u_int status2;
 556
 557                        dev->stats.tx_errors++;
 558
 559                        status2 = am_readword (dev, hdraddr + 6);
 560
 561                        /*
 562                         * Clear the error byte
 563                         */
 564                        am_writeword (dev, hdraddr + 6, 0);
 565
 566                        if (status2 & TST_RTRY)
 567                                dev->stats.collisions += 16;
 568                        if (status2 & TST_LCOL)
 569                                dev->stats.tx_window_errors++;
 570                        if (status2 & TST_LCAR)
 571                                dev->stats.tx_carrier_errors++;
 572                        if (status2 & TST_UFLO)
 573                                dev->stats.tx_fifo_errors++;
 574                        continue;
 575                }
 576                dev->stats.tx_packets++;
 577                len = am_readword (dev, hdraddr + 4);
 578                dev->stats.tx_bytes += -len;
 579        } while (priv->txtail != priv->txhead);
 580
 581        netif_wake_queue(dev);
 582}
 583
 584static irqreturn_t
 585am79c961_interrupt(int irq, void *dev_id)
 586{
 587        struct net_device *dev = (struct net_device *)dev_id;
 588        struct dev_priv *priv = netdev_priv(dev);
 589        u_int status, n = 100;
 590        int handled = 0;
 591
 592        do {
 593                status = read_rreg(dev->base_addr, CSR0);
 594                write_rreg(dev->base_addr, CSR0, status &
 595                           (CSR0_IENA|CSR0_TINT|CSR0_RINT|
 596                            CSR0_MERR|CSR0_MISS|CSR0_CERR|CSR0_BABL));
 597
 598                if (status & CSR0_RINT) {
 599                        handled = 1;
 600                        am79c961_rx(dev, priv);
 601                }
 602                if (status & CSR0_TINT) {
 603                        handled = 1;
 604                        am79c961_tx(dev, priv);
 605                }
 606                if (status & CSR0_MISS) {
 607                        handled = 1;
 608                        dev->stats.rx_dropped++;
 609                }
 610                if (status & CSR0_CERR) {
 611                        handled = 1;
 612                        mod_timer(&priv->timer, jiffies);
 613                }
 614        } while (--n && status & (CSR0_RINT | CSR0_TINT));
 615
 616        return IRQ_RETVAL(handled);
 617}
 618
 619#ifdef CONFIG_NET_POLL_CONTROLLER
 620static void am79c961_poll_controller(struct net_device *dev)
 621{
 622        unsigned long flags;
 623        local_irq_save(flags);
 624        am79c961_interrupt(dev->irq, dev);
 625        local_irq_restore(flags);
 626}
 627#endif
 628
 629/*
 630 * Initialise the chip.  Note that we always expect
 631 * to be entered with interrupts enabled.
 632 */
 633static int
 634am79c961_hw_init(struct net_device *dev)
 635{
 636        struct dev_priv *priv = netdev_priv(dev);
 637
 638        spin_lock_irq(&priv->chip_lock);
 639        write_rreg (dev->base_addr, CSR0, CSR0_STOP);
 640        write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
 641        spin_unlock_irq(&priv->chip_lock);
 642
 643        am79c961_ramtest(dev, 0x66);
 644        am79c961_ramtest(dev, 0x99);
 645
 646        return 0;
 647}
 648
 649static void __init am79c961_banner(void)
 650{
 651        static unsigned version_printed;
 652
 653        if (net_debug && version_printed++ == 0)
 654                printk(KERN_INFO "%s", version);
 655}
 656static const struct net_device_ops am79c961_netdev_ops = {
 657        .ndo_open               = am79c961_open,
 658        .ndo_stop               = am79c961_close,
 659        .ndo_start_xmit         = am79c961_sendpacket,
 660        .ndo_set_rx_mode        = am79c961_setmulticastlist,
 661        .ndo_tx_timeout         = am79c961_timeout,
 662        .ndo_validate_addr      = eth_validate_addr,
 663        .ndo_set_mac_address    = eth_mac_addr,
 664#ifdef CONFIG_NET_POLL_CONTROLLER
 665        .ndo_poll_controller    = am79c961_poll_controller,
 666#endif
 667};
 668
 669static int am79c961_probe(struct platform_device *pdev)
 670{
 671        struct resource *res;
 672        struct net_device *dev;
 673        struct dev_priv *priv;
 674        int i, ret;
 675
 676        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 677        if (!res)
 678                return -ENODEV;
 679
 680        dev = alloc_etherdev(sizeof(struct dev_priv));
 681        ret = -ENOMEM;
 682        if (!dev)
 683                goto out;
 684
 685        SET_NETDEV_DEV(dev, &pdev->dev);
 686
 687        priv = netdev_priv(dev);
 688
 689        /*
 690         * Fixed address and IRQ lines here.
 691         * The PNP initialisation should have been
 692         * done by the ether bootp loader.
 693         */
 694        dev->base_addr = res->start;
 695        ret = platform_get_irq(pdev, 0);
 696
 697        if (ret < 0) {
 698                ret = -ENODEV;
 699                goto nodev;
 700        }
 701        dev->irq = ret;
 702
 703        ret = -ENODEV;
 704        if (!request_region(dev->base_addr, 0x18, dev->name))
 705                goto nodev;
 706
 707        /*
 708         * Reset the device.
 709         */
 710        inb(dev->base_addr + NET_RESET);
 711        udelay(5);
 712
 713        /*
 714         * Check the manufacturer part of the
 715         * ether address.
 716         */
 717        if (inb(dev->base_addr) != 0x08 ||
 718            inb(dev->base_addr + 2) != 0x00 ||
 719            inb(dev->base_addr + 4) != 0x2b)
 720                goto release;
 721
 722        for (i = 0; i < 6; i++)
 723                dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
 724
 725        am79c961_banner();
 726
 727        spin_lock_init(&priv->chip_lock);
 728        priv->dev = dev;
 729        timer_setup(&priv->timer, am79c961_timer, 0);
 730
 731        if (am79c961_hw_init(dev))
 732                goto release;
 733
 734        dev->netdev_ops = &am79c961_netdev_ops;
 735
 736        ret = register_netdev(dev);
 737        if (ret == 0) {
 738                printk(KERN_INFO "%s: ether address %pM\n",
 739                       dev->name, dev->dev_addr);
 740                return 0;
 741        }
 742
 743release:
 744        release_region(dev->base_addr, 0x18);
 745nodev:
 746        free_netdev(dev);
 747out:
 748        return ret;
 749}
 750
 751static struct platform_driver am79c961_driver = {
 752        .probe          = am79c961_probe,
 753        .driver         = {
 754                .name   = "am79c961",
 755        },
 756};
 757
 758static int __init am79c961_init(void)
 759{
 760        return platform_driver_register(&am79c961_driver);
 761}
 762
 763__initcall(am79c961_init);
 764