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