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