linux/drivers/net/ariadne.c History
<<
>>
Prefs
   1/*
   2 *  Amiga Linux/m68k Ariadne Ethernet Driver
   3 *
   4 *  © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org)
   5 *                           Peter De Schrijver (p2@mind.be)
   6 *
   7 *  ---------------------------------------------------------------------------
   8 *
   9 *  This program is based on
  10 *
  11 *      lance.c:        An AMD LANCE ethernet driver for linux.
  12 *                      Written 1993-94 by Donald Becker.
  13 *
  14 *      Am79C960:       PCnet(tm)-ISA Single-Chip Ethernet Controller
  15 *                      Advanced Micro Devices
  16 *                      Publication #16907, Rev. B, Amendment/0, May 1994
  17 *
  18 *      MC68230:        Parallel Interface/Timer (PI/T)
  19 *                      Motorola Semiconductors, December, 1983
  20 *
  21 *  ---------------------------------------------------------------------------
  22 *
  23 *  This file is subject to the terms and conditions of the GNU General Public
  24 *  License.  See the file COPYING in the main directory of the Linux
  25 *  distribution for more details.
  26 *
  27 *  ---------------------------------------------------------------------------
  28 *
  29 *  The Ariadne is a Zorro-II board made by Village Tronic. It contains:
  30 *
  31 *      - an Am79C960 PCnet-ISA Single-Chip Ethernet Controller with both
  32 *        10BASE-2 (thin coax) and 10BASE-T (UTP) connectors
  33 *
  34 *      - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
  35 */
  36
  37#include <linux/module.h>
  38#include <linux/stddef.h>
  39#include <linux/kernel.h>
  40#include <linux/string.h>
  41#include <linux/errno.h>
  42#include <linux/ioport.h>
  43#include <linux/slab.h>
  44#include <linux/netdevice.h>
  45#include <linux/etherdevice.h>
  46#include <linux/interrupt.h>
  47#include <linux/skbuff.h>
  48#include <linux/init.h>
  49#include <linux/zorro.h>
  50#include <linux/bitops.h>
  51
  52#include <asm/amigaints.h>
  53#include <asm/amigahw.h>
  54#include <asm/irq.h>
  55
  56#include "ariadne.h"
  57
  58
  59#ifdef ARIADNE_DEBUG
  60int ariadne_debug = ARIADNE_DEBUG;
  61#else
  62int ariadne_debug = 1;
  63#endif
  64
  65
  66    /*
  67     *  Macros to Fix Endianness problems
  68     */
  69
  70                                /* Swap the Bytes in a WORD */
  71#define swapw(x)        (((x>>8)&0x00ff)|((x<<8)&0xff00))
  72                                /* Get the Low BYTE in a WORD */
  73#define lowb(x)         (x&0xff)
  74                                /* Get the Swapped High WORD in a LONG */
  75#define swhighw(x)      ((((x)>>8)&0xff00)|(((x)>>24)&0x00ff))
  76                                /* Get the Swapped Low WORD in a LONG */
  77#define swloww(x)       ((((x)<<8)&0xff00)|(((x)>>8)&0x00ff))
  78
  79
  80    /*
  81     *  Transmit/Receive Ring Definitions
  82     */
  83
  84#define TX_RING_SIZE    5
  85#define RX_RING_SIZE    16
  86
  87#define PKT_BUF_SIZE    1520
  88
  89
  90    /*
  91     *  Private Device Data
  92     */
  93
  94struct ariadne_private {
  95    volatile struct TDRE *tx_ring[TX_RING_SIZE];
  96    volatile struct RDRE *rx_ring[RX_RING_SIZE];
  97    volatile u_short *tx_buff[TX_RING_SIZE];
  98    volatile u_short *rx_buff[RX_RING_SIZE];
  99    int cur_tx, cur_rx;                 /* The next free ring entry */
 100    int dirty_tx;                       /* The ring entries to be free()ed. */
 101    char tx_full;
 102};
 103
 104
 105    /*
 106     *  Structure Created in the Ariadne's RAM Buffer
 107     */
 108
 109struct lancedata {
 110    struct TDRE tx_ring[TX_RING_SIZE];
 111    struct RDRE rx_ring[RX_RING_SIZE];
 112    u_short tx_buff[TX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
 113    u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)];
 114};
 115
 116static int ariadne_open(struct net_device *dev);
 117static void ariadne_init_ring(struct net_device *dev);
 118static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
 119                                      struct net_device *dev);
 120static void ariadne_tx_timeout(struct net_device *dev);
 121static int ariadne_rx(struct net_device *dev);
 122static void ariadne_reset(struct net_device *dev);
 123static irqreturn_t ariadne_interrupt(int irq, void *data);
 124static int ariadne_close(struct net_device *dev);
 125static struct net_device_stats *ariadne_get_stats(struct net_device *dev);
 126#ifdef HAVE_MULTICAST
 127static void set_multicast_list(struct net_device *dev);
 128#endif
 129
 130
 131static void memcpyw(volatile u_short *dest, u_short *src, int len)
 132{
 133    while (len >= 2) {
 134        *(dest++) = *(src++);
 135        len -= 2;
 136    }
 137    if (len == 1)
 138        *dest = (*(u_char *)src)<<8;
 139}
 140
 141
 142static int __devinit ariadne_init_one(struct zorro_dev *z,
 143                                      const struct zorro_device_id *ent);
 144static void __devexit ariadne_remove_one(struct zorro_dev *z);
 145
 146
 147static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
 148    { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
 149    { 0 }
 150};
 151
 152static struct zorro_driver ariadne_driver = {
 153    .name       = "ariadne",
 154    .id_table   = ariadne_zorro_tbl,
 155    .probe      = ariadne_init_one,
 156    .remove     = __devexit_p(ariadne_remove_one),
 157};
 158
 159static const struct net_device_ops ariadne_netdev_ops = {
 160        .ndo_open               = ariadne_open,
 161        .ndo_stop               = ariadne_close,
 162        .ndo_start_xmit         = ariadne_start_xmit,
 163        .ndo_tx_timeout         = ariadne_tx_timeout,
 164        .ndo_get_stats          = ariadne_get_stats,
 165        .ndo_set_multicast_list = set_multicast_list,
 166        .ndo_validate_addr      = eth_validate_addr,
 167        .ndo_change_mtu         = eth_change_mtu,
 168        .ndo_set_mac_address    = eth_mac_addr,
 169};
 170
 171static int __devinit ariadne_init_one(struct zorro_dev *z,
 172                                      const struct zorro_device_id *ent)
 173{
 174    unsigned long board = z->resource.start;
 175    unsigned long base_addr = board+ARIADNE_LANCE;
 176    unsigned long mem_start = board+ARIADNE_RAM;
 177    struct resource *r1, *r2;
 178    struct net_device *dev;
 179    struct ariadne_private *priv;
 180    int err;
 181
 182    r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
 183    if (!r1)
 184        return -EBUSY;
 185    r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
 186    if (!r2) {
 187        release_resource(r1);
 188        return -EBUSY;
 189    }
 190
 191    dev = alloc_etherdev(sizeof(struct ariadne_private));
 192    if (dev == NULL) {
 193        release_resource(r1);
 194        release_resource(r2);
 195        return -ENOMEM;
 196    }
 197
 198    priv = netdev_priv(dev);
 199
 200    r1->name = dev->name;
 201    r2->name = dev->name;
 202
 203    dev->dev_addr[0] = 0x00;
 204    dev->dev_addr[1] = 0x60;
 205    dev->dev_addr[2] = 0x30;
 206    dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff;
 207    dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff;
 208    dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
 209    dev->base_addr = ZTWO_VADDR(base_addr);
 210    dev->mem_start = ZTWO_VADDR(mem_start);
 211    dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
 212
 213    dev->netdev_ops = &ariadne_netdev_ops;
 214    dev->watchdog_timeo = 5*HZ;
 215
 216    err = register_netdev(dev);
 217    if (err) {
 218        release_resource(r1);
 219        release_resource(r2);
 220        free_netdev(dev);
 221        return err;
 222    }
 223    zorro_set_drvdata(z, dev);
 224
 225    printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
 226           dev->name, board, dev->dev_addr);
 227
 228    return 0;
 229}
 230
 231
 232static int ariadne_open(struct net_device *dev)
 233{
 234    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 235    u_short in;
 236    u_long version;
 237    int i;
 238
 239    /* Reset the LANCE */
 240    in = lance->Reset;
 241
 242    /* Stop the LANCE */
 243    lance->RAP = CSR0;          /* PCnet-ISA Controller Status */
 244    lance->RDP = STOP;
 245
 246    /* Check the LANCE version */
 247    lance->RAP = CSR88;         /* Chip ID */
 248    version = swapw(lance->RDP);
 249    lance->RAP = CSR89;         /* Chip ID */
 250    version |= swapw(lance->RDP)<<16;
 251    if ((version & 0x00000fff) != 0x00000003) {
 252        printk(KERN_WARNING "ariadne_open: Couldn't find AMD Ethernet Chip\n");
 253        return -EAGAIN;
 254    }
 255    if ((version & 0x0ffff000) != 0x00003000) {
 256        printk(KERN_WARNING "ariadne_open: Couldn't find Am79C960 (Wrong part "
 257               "number = %ld)\n", (version & 0x0ffff000)>>12);
 258        return -EAGAIN;
 259    }
 260#if 0
 261    printk(KERN_DEBUG "ariadne_open: Am79C960 (PCnet-ISA) Revision %ld\n",
 262           (version & 0xf0000000)>>28);
 263#endif
 264
 265    ariadne_init_ring(dev);
 266
 267    /* Miscellaneous Stuff */
 268    lance->RAP = CSR3;          /* Interrupt Masks and Deferral Control */
 269    lance->RDP = 0x0000;
 270    lance->RAP = CSR4;          /* Test and Features Control */
 271    lance->RDP = DPOLL|APAD_XMT|MFCOM|RCVCCOM|TXSTRTM|JABM;
 272
 273    /* Set the Multicast Table */
 274    lance->RAP = CSR8;          /* Logical Address Filter, LADRF[15:0] */
 275    lance->RDP = 0x0000;
 276    lance->RAP = CSR9;          /* Logical Address Filter, LADRF[31:16] */
 277    lance->RDP = 0x0000;
 278    lance->RAP = CSR10;         /* Logical Address Filter, LADRF[47:32] */
 279    lance->RDP = 0x0000;
 280    lance->RAP = CSR11;         /* Logical Address Filter, LADRF[63:48] */
 281    lance->RDP = 0x0000;
 282
 283    /* Set the Ethernet Hardware Address */
 284    lance->RAP = CSR12;         /* Physical Address Register, PADR[15:0] */
 285    lance->RDP = ((u_short *)&dev->dev_addr[0])[0];
 286    lance->RAP = CSR13;         /* Physical Address Register, PADR[31:16] */
 287    lance->RDP = ((u_short *)&dev->dev_addr[0])[1];
 288    lance->RAP = CSR14;         /* Physical Address Register, PADR[47:32] */
 289    lance->RDP = ((u_short *)&dev->dev_addr[0])[2];
 290
 291    /* Set the Init Block Mode */
 292    lance->RAP = CSR15;         /* Mode Register */
 293    lance->RDP = 0x0000;
 294
 295    /* Set the Transmit Descriptor Ring Pointer */
 296    lance->RAP = CSR30;         /* Base Address of Transmit Ring */
 297    lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
 298    lance->RAP = CSR31;         /* Base Address of transmit Ring */
 299    lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_ring));
 300
 301    /* Set the Receive Descriptor Ring Pointer */
 302    lance->RAP = CSR24;         /* Base Address of Receive Ring */
 303    lance->RDP = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
 304    lance->RAP = CSR25;         /* Base Address of Receive Ring */
 305    lance->RDP = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_ring));
 306
 307    /* Set the Number of RX and TX Ring Entries */
 308    lance->RAP = CSR76;         /* Receive Ring Length */
 309    lance->RDP = swapw(((u_short)-RX_RING_SIZE));
 310    lance->RAP = CSR78;         /* Transmit Ring Length */
 311    lance->RDP = swapw(((u_short)-TX_RING_SIZE));
 312
 313    /* Enable Media Interface Port Auto Select (10BASE-2/10BASE-T) */
 314    lance->RAP = ISACSR2;       /* Miscellaneous Configuration */
 315    lance->IDP = ASEL;
 316
 317    /* LED Control */
 318    lance->RAP = ISACSR5;       /* LED1 Status */
 319    lance->IDP = PSE|XMTE;
 320    lance->RAP = ISACSR6;       /* LED2 Status */
 321    lance->IDP = PSE|COLE;
 322    lance->RAP = ISACSR7;       /* LED3 Status */
 323    lance->IDP = PSE|RCVE;
 324
 325    netif_start_queue(dev);
 326
 327    i = request_irq(IRQ_AMIGA_PORTS, ariadne_interrupt, IRQF_SHARED,
 328                    dev->name, dev);
 329    if (i) return i;
 330
 331    lance->RAP = CSR0;          /* PCnet-ISA Controller Status */
 332    lance->RDP = INEA|STRT;
 333
 334    return 0;
 335}
 336
 337
 338static void ariadne_init_ring(struct net_device *dev)
 339{
 340    struct ariadne_private *priv = netdev_priv(dev);
 341    volatile struct lancedata *lancedata = (struct lancedata *)dev->mem_start;
 342    int i;
 343
 344    netif_stop_queue(dev);
 345
 346    priv->tx_full = 0;
 347    priv->cur_rx = priv->cur_tx = 0;
 348    priv->dirty_tx = 0;
 349
 350    /* Set up TX Ring */
 351    for (i = 0; i < TX_RING_SIZE; i++) {
 352        volatile struct TDRE *t = &lancedata->tx_ring[i];
 353        t->TMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i]));
 354        t->TMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, tx_buff[i])) |
 355                  TF_STP | TF_ENP;
 356        t->TMD2 = swapw((u_short)-PKT_BUF_SIZE);
 357        t->TMD3 = 0;
 358        priv->tx_ring[i] = &lancedata->tx_ring[i];
 359        priv->tx_buff[i] = lancedata->tx_buff[i];
 360#if 0
 361        printk(KERN_DEBUG "TX Entry %2d at %p, Buf at %p\n", i,
 362               &lancedata->tx_ring[i], lancedata->tx_buff[i]);
 363#endif
 364    }
 365
 366    /* Set up RX Ring */
 367    for (i = 0; i < RX_RING_SIZE; i++) {
 368        volatile struct RDRE *r = &lancedata->rx_ring[i];
 369        r->RMD0 = swloww(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i]));
 370        r->RMD1 = swhighw(ARIADNE_RAM+offsetof(struct lancedata, rx_buff[i])) |
 371                  RF_OWN;
 372        r->RMD2 = swapw((u_short)-PKT_BUF_SIZE);
 373        r->RMD3 = 0x0000;
 374        priv->rx_ring[i] = &lancedata->rx_ring[i];
 375        priv->rx_buff[i] = lancedata->rx_buff[i];
 376#if 0
 377        printk(KERN_DEBUG "RX Entry %2d at %p, Buf at %p\n", i,
 378               &lancedata->rx_ring[i], lancedata->rx_buff[i]);
 379#endif
 380    }
 381}
 382
 383
 384static int ariadne_close(struct net_device *dev)
 385{
 386    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 387
 388    netif_stop_queue(dev);
 389
 390    lance->RAP = CSR112;        /* Missed Frame Count */
 391    dev->stats.rx_missed_errors = swapw(lance->RDP);
 392    lance->RAP = CSR0;          /* PCnet-ISA Controller Status */
 393
 394    if (ariadne_debug > 1) {
 395        printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 396               dev->name, lance->RDP);
 397        printk(KERN_DEBUG "%s: %lu packets missed\n", dev->name,
 398               dev->stats.rx_missed_errors);
 399    }
 400
 401    /* We stop the LANCE here -- it occasionally polls memory if we don't. */
 402    lance->RDP = STOP;
 403
 404    free_irq(IRQ_AMIGA_PORTS, dev);
 405
 406    return 0;
 407}
 408
 409
 410static inline void ariadne_reset(struct net_device *dev)
 411{
 412    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 413
 414    lance->RAP = CSR0;  /* PCnet-ISA Controller Status */
 415    lance->RDP = STOP;
 416    ariadne_init_ring(dev);
 417    lance->RDP = INEA|STRT;
 418    netif_start_queue(dev);
 419}
 420
 421
 422static irqreturn_t ariadne_interrupt(int irq, void *data)
 423{
 424    struct net_device *dev = (struct net_device *)data;
 425    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 426    struct ariadne_private *priv;
 427    int csr0, boguscnt;
 428    int handled = 0;
 429
 430    if (dev == NULL) {
 431        printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n");
 432        return IRQ_NONE;
 433    }
 434
 435    lance->RAP = CSR0;                  /* PCnet-ISA Controller Status */
 436
 437    if (!(lance->RDP & INTR))           /* Check if any interrupt has been */
 438        return IRQ_NONE;                /* generated by the board. */
 439
 440    priv = netdev_priv(dev);
 441
 442    boguscnt = 10;
 443    while ((csr0 = lance->RDP) & (ERR|RINT|TINT) && --boguscnt >= 0) {
 444        /* Acknowledge all of the current interrupt sources ASAP. */
 445        lance->RDP = csr0 & ~(INEA|TDMD|STOP|STRT|INIT);
 446
 447#if 0
 448        if (ariadne_debug > 5) {
 449            printk(KERN_DEBUG "%s: interrupt  csr0=%#2.2x new csr=%#2.2x.",
 450                   dev->name, csr0, lance->RDP);
 451            printk("[");
 452            if (csr0 & INTR)
 453                printk(" INTR");
 454            if (csr0 & INEA)
 455                printk(" INEA");
 456            if (csr0 & RXON)
 457                printk(" RXON");
 458            if (csr0 & TXON)
 459                printk(" TXON");
 460            if (csr0 & TDMD)
 461                printk(" TDMD");
 462            if (csr0 & STOP)
 463                printk(" STOP");
 464            if (csr0 & STRT)
 465                printk(" STRT");
 466            if (csr0 & INIT)
 467                printk(" INIT");
 468            if (csr0 & ERR)
 469                printk(" ERR");
 470            if (csr0 & BABL)
 471                printk(" BABL");
 472            if (csr0 & CERR)
 473                printk(" CERR");
 474            if (csr0 & MISS)
 475                printk(" MISS");
 476            if (csr0 & MERR)
 477                printk(" MERR");
 478            if (csr0 & RINT)
 479                printk(" RINT");
 480            if (csr0 & TINT)
 481                printk(" TINT");
 482            if (csr0 & IDON)
 483                printk(" IDON");
 484            printk(" ]\n");
 485        }
 486#endif
 487
 488        if (csr0 & RINT) {      /* Rx interrupt */
 489            handled = 1;
 490            ariadne_rx(dev);
 491        }
 492
 493        if (csr0 & TINT) {      /* Tx-done interrupt */
 494            int dirty_tx = priv->dirty_tx;
 495
 496            handled = 1;
 497            while (dirty_tx < priv->cur_tx) {
 498                int entry = dirty_tx % TX_RING_SIZE;
 499                int status = lowb(priv->tx_ring[entry]->TMD1);
 500
 501                if (status & TF_OWN)
 502                    break;      /* It still hasn't been Txed */
 503
 504                priv->tx_ring[entry]->TMD1 &= 0xff00;
 505
 506                if (status & TF_ERR) {
 507                    /* There was an major error, log it. */
 508                    int err_status = priv->tx_ring[entry]->TMD3;
 509                    dev->stats.tx_errors++;
 510                    if (err_status & EF_RTRY)
 511                        dev->stats.tx_aborted_errors++;
 512                    if (err_status & EF_LCAR)
 513                        dev->stats.tx_carrier_errors++;
 514                    if (err_status & EF_LCOL)
 515                        dev->stats.tx_window_errors++;
 516                    if (err_status & EF_UFLO) {
 517                        /* Ackk!  On FIFO errors the Tx unit is turned off! */
 518                        dev->stats.tx_fifo_errors++;
 519                        /* Remove this verbosity later! */
 520                        printk(KERN_ERR "%s: Tx FIFO error! Status %4.4x.\n",
 521                               dev->name, csr0);
 522                        /* Restart the chip. */
 523                        lance->RDP = STRT;
 524                    }
 525                } else {
 526                    if (status & (TF_MORE|TF_ONE))
 527                        dev->stats.collisions++;
 528                    dev->stats.tx_packets++;
 529                }
 530                dirty_tx++;
 531            }
 532
 533#ifndef final_version
 534            if (priv->cur_tx - dirty_tx >= TX_RING_SIZE) {
 535                printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d, "
 536                       "full=%d.\n", dirty_tx, priv->cur_tx, priv->tx_full);
 537                dirty_tx += TX_RING_SIZE;
 538            }
 539#endif
 540
 541            if (priv->tx_full && netif_queue_stopped(dev) &&
 542                dirty_tx > priv->cur_tx - TX_RING_SIZE + 2) {
 543                /* The ring is no longer full. */
 544                priv->tx_full = 0;
 545                netif_wake_queue(dev);
 546            }
 547
 548            priv->dirty_tx = dirty_tx;
 549        }
 550
 551        /* Log misc errors. */
 552        if (csr0 & BABL) {
 553            handled = 1;
 554            dev->stats.tx_errors++;     /* Tx babble. */
 555        }
 556        if (csr0 & MISS) {
 557            handled = 1;
 558            dev->stats.rx_errors++;     /* Missed a Rx frame. */
 559        }
 560        if (csr0 & MERR) {
 561            handled = 1;
 562            printk(KERN_ERR "%s: Bus master arbitration failure, status "
 563                   "%4.4x.\n", dev->name, csr0);
 564            /* Restart the chip. */
 565            lance->RDP = STRT;
 566        }
 567    }
 568
 569    /* Clear any other interrupt, and set interrupt enable. */
 570    lance->RAP = CSR0;          /* PCnet-ISA Controller Status */
 571    lance->RDP = INEA|BABL|CERR|MISS|MERR|IDON;
 572
 573#if 0
 574    if (ariadne_debug > 4)
 575        printk(KERN_DEBUG "%s: exiting interrupt, csr%d=%#4.4x.\n", dev->name,
 576               lance->RAP, lance->RDP);
 577#endif
 578    return IRQ_RETVAL(handled);
 579}
 580
 581
 582static void ariadne_tx_timeout(struct net_device *dev)
 583{
 584    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 585
 586    printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
 587           dev->name, lance->RDP);
 588    ariadne_reset(dev);
 589    netif_wake_queue(dev);
 590}
 591
 592
 593static netdev_tx_t ariadne_start_xmit(struct sk_buff *skb,
 594                                      struct net_device *dev)
 595{
 596    struct ariadne_private *priv = netdev_priv(dev);
 597    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 598    int entry;
 599    unsigned long flags;
 600    int len = skb->len;
 601
 602#if 0
 603    if (ariadne_debug > 3) {
 604        lance->RAP = CSR0;      /* PCnet-ISA Controller Status */
 605        printk(KERN_DEBUG "%s: ariadne_start_xmit() called, csr0 %4.4x.\n",
 606               dev->name, lance->RDP);
 607        lance->RDP = 0x0000;
 608    }
 609#endif
 610
 611    /* FIXME: is the 79C960 new enough to do its own padding right ? */
 612    if (skb->len < ETH_ZLEN)
 613    {
 614        if (skb_padto(skb, ETH_ZLEN))
 615            return NETDEV_TX_OK;
 616        len = ETH_ZLEN;
 617    }
 618
 619    /* Fill in a Tx ring entry */
 620
 621#if 0
 622{
 623    printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
 624           " data 0x%08x len %d\n",
 625           ((u_short *)skb->data)[6],
 626           skb->data + 6, skb->data,
 627           (int)skb->data, (int)skb->len);
 628}
 629#endif
 630
 631    local_irq_save(flags);
 632
 633    entry = priv->cur_tx % TX_RING_SIZE;
 634
 635    /* Caution: the write order is important here, set the base address with
 636                the "ownership" bits last. */
 637
 638    priv->tx_ring[entry]->TMD2 = swapw((u_short)-skb->len);
 639    priv->tx_ring[entry]->TMD3 = 0x0000;
 640    memcpyw(priv->tx_buff[entry], (u_short *)skb->data, len);
 641
 642#if 0
 643    {
 644        int i, len;
 645
 646        len = skb->len > 64 ? 64 : skb->len;
 647        len >>= 1;
 648        for (i = 0; i < len; i += 8) {
 649            int j;
 650            printk(KERN_DEBUG "%04x:", i);
 651            for (j = 0; (j < 8) && ((i+j) < len); j++) {
 652                if (!(j & 1))
 653                    printk(" ");
 654                printk("%04x", priv->tx_buff[entry][i+j]);
 655            }
 656            printk("\n");
 657        }
 658    }
 659#endif
 660
 661    priv->tx_ring[entry]->TMD1 = (priv->tx_ring[entry]->TMD1&0xff00)|TF_OWN|TF_STP|TF_ENP;
 662
 663    dev_kfree_skb(skb);
 664
 665    priv->cur_tx++;
 666    if ((priv->cur_tx >= TX_RING_SIZE) && (priv->dirty_tx >= TX_RING_SIZE)) {
 667
 668#if 0
 669        printk(KERN_DEBUG "*** Subtracting TX_RING_SIZE from cur_tx (%d) and "
 670               "dirty_tx (%d)\n", priv->cur_tx, priv->dirty_tx);
 671#endif
 672
 673        priv->cur_tx -= TX_RING_SIZE;
 674        priv->dirty_tx -= TX_RING_SIZE;
 675    }
 676    dev->stats.tx_bytes += len;
 677
 678    /* Trigger an immediate send poll. */
 679    lance->RAP = CSR0;          /* PCnet-ISA Controller Status */
 680    lance->RDP = INEA|TDMD;
 681
 682    dev->trans_start = jiffies;
 683
 684    if (lowb(priv->tx_ring[(entry+1) % TX_RING_SIZE]->TMD1) != 0) {
 685        netif_stop_queue(dev);
 686        priv->tx_full = 1;
 687    }
 688    local_irq_restore(flags);
 689
 690    return NETDEV_TX_OK;
 691}
 692
 693
 694static int ariadne_rx(struct net_device *dev)
 695{
 696    struct ariadne_private *priv = netdev_priv(dev);
 697    int entry = priv->cur_rx % RX_RING_SIZE;
 698    int i;
 699
 700    /* If we own the next entry, it's a new packet. Send it up. */
 701    while (!(lowb(priv->rx_ring[entry]->RMD1) & RF_OWN)) {
 702        int status = lowb(priv->rx_ring[entry]->RMD1);
 703
 704        if (status != (RF_STP|RF_ENP)) {        /* There was an error. */
 705            /* There is a tricky error noted by John Murphy,
 706                <murf@perftech.com> to Russ Nelson: Even with full-sized
 707                buffers it's possible for a jabber packet to use two
 708                buffers, with only the last correctly noting the error. */
 709            if (status & RF_ENP)
 710                /* Only count a general error at the end of a packet.*/
 711                dev->stats.rx_errors++;
 712            if (status & RF_FRAM)
 713                dev->stats.rx_frame_errors++;
 714            if (status & RF_OFLO)
 715                dev->stats.rx_over_errors++;
 716            if (status & RF_CRC)
 717                dev->stats.rx_crc_errors++;
 718            if (status & RF_BUFF)
 719                dev->stats.rx_fifo_errors++;
 720            priv->rx_ring[entry]->RMD1 &= 0xff00|RF_STP|RF_ENP;
 721        } else {
 722            /* Malloc up new buffer, compatible with net-3. */
 723            short pkt_len = swapw(priv->rx_ring[entry]->RMD3);
 724            struct sk_buff *skb;
 725
 726            skb = dev_alloc_skb(pkt_len+2);
 727            if (skb == NULL) {
 728                printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n",
 729                       dev->name);
 730                for (i = 0; i < RX_RING_SIZE; i++)
 731                    if (lowb(priv->rx_ring[(entry+i) % RX_RING_SIZE]->RMD1) & RF_OWN)
 732                        break;
 733
 734                if (i > RX_RING_SIZE-2) {
 735                    dev->stats.rx_dropped++;
 736                    priv->rx_ring[entry]->RMD1 |= RF_OWN;
 737                    priv->cur_rx++;
 738                }
 739                break;
 740            }
 741
 742
 743            skb_reserve(skb,2);         /* 16 byte align */
 744            skb_put(skb,pkt_len);       /* Make room */
 745            skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
 746            skb->protocol=eth_type_trans(skb,dev);
 747#if 0
 748{
 749            printk(KERN_DEBUG "RX pkt type 0x%04x from ",
 750                   ((u_short *)skb->data)[6]);
 751            {
 752                u_char *ptr = &((u_char *)skb->data)[6];
 753                printk("%pM", ptr);
 754            }
 755            printk(" to ");
 756            {
 757                u_char *ptr = (u_char *)skb->data;
 758                printk("%pM", ptr);
 759            }
 760            printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
 761}
 762#endif
 763
 764            netif_rx(skb);
 765            dev->stats.rx_packets++;
 766            dev->stats.rx_bytes += pkt_len;
 767        }
 768
 769        priv->rx_ring[entry]->RMD1 |= RF_OWN;
 770        entry = (++priv->cur_rx) % RX_RING_SIZE;
 771    }
 772
 773    priv->cur_rx = priv->cur_rx % RX_RING_SIZE;
 774
 775    /* We should check that at least two ring entries are free.  If not,
 776       we should free one and mark stats->rx_dropped++. */
 777
 778    return 0;
 779}
 780
 781
 782static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
 783{
 784    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 785    short saved_addr;
 786    unsigned long flags;
 787
 788    local_irq_save(flags);
 789    saved_addr = lance->RAP;
 790    lance->RAP = CSR112;                /* Missed Frame Count */
 791    dev->stats.rx_missed_errors = swapw(lance->RDP);
 792    lance->RAP = saved_addr;
 793    local_irq_restore(flags);
 794
 795    return &dev->stats;
 796}
 797
 798
 799/* Set or clear the multicast filter for this adaptor.
 800    num_addrs == -1     Promiscuous mode, receive all packets
 801    num_addrs == 0      Normal mode, clear multicast list
 802    num_addrs > 0       Multicast mode, receive normal and MC packets, and do
 803                        best-effort filtering.
 804 */
 805static void set_multicast_list(struct net_device *dev)
 806{
 807    volatile struct Am79C960 *lance = (struct Am79C960*)dev->base_addr;
 808
 809    if (!netif_running(dev))
 810        return;
 811
 812    netif_stop_queue(dev);
 813
 814    /* We take the simple way out and always enable promiscuous mode. */
 815    lance->RAP = CSR0;                  /* PCnet-ISA Controller Status */
 816    lance->RDP = STOP;                  /* Temporarily stop the lance. */
 817    ariadne_init_ring(dev);
 818
 819    if (dev->flags & IFF_PROMISC) {
 820        lance->RAP = CSR15;             /* Mode Register */
 821        lance->RDP = PROM;              /* Set promiscuous mode */
 822    } else {
 823        short multicast_table[4];
 824        int num_addrs = dev->mc_count;
 825        int i;
 826        /* We don't use the multicast table, but rely on upper-layer filtering. */
 827        memset(multicast_table, (num_addrs == 0) ? 0 : -1,
 828               sizeof(multicast_table));
 829        for (i = 0; i < 4; i++) {
 830            lance->RAP = CSR8+(i<<8);   /* Logical Address Filter */
 831            lance->RDP = swapw(multicast_table[i]);
 832        }
 833        lance->RAP = CSR15;             /* Mode Register */
 834        lance->RDP = 0x0000;            /* Unset promiscuous mode */
 835    }
 836
 837    lance->RAP = CSR0;                  /* PCnet-ISA Controller Status */
 838    lance->RDP = INEA|STRT|IDON;        /* Resume normal operation. */
 839
 840    netif_wake_queue(dev);
 841}
 842
 843
 844static void __devexit ariadne_remove_one(struct zorro_dev *z)
 845{
 846    struct net_device *dev = zorro_get_drvdata(z);
 847
 848    unregister_netdev(dev);
 849    release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960));
 850    release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE);
 851    free_netdev(dev);
 852}
 853
 854static int __init ariadne_init_module(void)
 855{
 856    return zorro_register_driver(&ariadne_driver);
 857}
 858
 859static void __exit ariadne_cleanup_module(void)
 860{
 861    zorro_unregister_driver(&ariadne_driver);
 862}
 863
 864module_init(ariadne_init_module);
 865module_exit(ariadne_cleanup_module);
 866
 867MODULE_LICENSE("GPL");
 868
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.