linux-bk/drivers/net/de620.c
<<
>>
Prefs
   1/*
   2 *      de620.c $Revision: 1.40 $ BETA
   3 *
   4 *
   5 *      Linux driver for the D-Link DE-620 Ethernet pocket adapter.
   6 *
   7 *      Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <bj0rn@blox.se>
   8 *
   9 *      Based on adapter information gathered from DOS packetdriver
  10 *      sources from D-Link Inc:  (Special thanks to Henry Ngai of D-Link.)
  11 *              Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992
  12 *              Copyright, 1988, Russell Nelson, Crynwr Software
  13 *
  14 *      Adapted to the sample network driver core for linux,
  15 *      written by: Donald Becker <becker@super.org>
  16 *              (Now at <becker@scyld.com>)
  17 *
  18 *      Valuable assistance from:
  19 *              J. Joshua Kopper <kopper@rtsg.mot.com>
  20 *              Olav Kvittem <Olav.Kvittem@uninett.no>
  21 *              Germano Caronni <caronni@nessie.cs.id.ethz.ch>
  22 *              Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
  23 *
  24 *****************************************************************************/
  25/*
  26 *      This program is free software; you can redistribute it and/or modify
  27 *      it under the terms of the GNU General Public License as published by
  28 *      the Free Software Foundation; either version 2, or (at your option)
  29 *      any later version.
  30 *
  31 *      This program is distributed in the hope that it will be useful,
  32 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  33 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  34 *      GNU General Public License for more details.
  35 *
  36 *      You should have received a copy of the GNU General Public License
  37 *      along with this program; if not, write to the Free Software
  38 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  39 *
  40 *****************************************************************************/
  41static const char version[] =
  42        "de620.c: $Revision: 1.40 $,  Bjorn Ekwall <bj0rn@blox.se>\n";
  43
  44/***********************************************************************
  45 *
  46 * "Tuning" section.
  47 *
  48 * Compile-time options: (see below for descriptions)
  49 * -DDE620_IO=0x378     (lpt1)
  50 * -DDE620_IRQ=7        (lpt1)
  51 * -DDE602_DEBUG=...
  52 * -DSHUTDOWN_WHEN_LOST
  53 * -DCOUNT_LOOPS
  54 * -DLOWSPEED
  55 * -DREAD_DELAY
  56 * -DWRITE_DELAY
  57 */
  58
  59/*
  60 * This driver assumes that the printer port is a "normal",
  61 * dumb, uni-directional port!
  62 * If your port is "fancy" in any way, please try to set it to "normal"
  63 * with your BIOS setup.  I have no access to machines with bi-directional
  64 * ports, so I can't test such a driver :-(
  65 * (Yes, I _know_ it is possible to use DE620 with bidirectional ports...)
  66 *
  67 * There are some clones of DE620 out there, with different names.
  68 * If the current driver does not recognize a clone, try to change
  69 * the following #define to:
  70 *
  71 * #define DE620_CLONE 1
  72 */
  73#define DE620_CLONE 0
  74
  75/*
  76 * If the adapter has problems with high speeds, enable this #define
  77 * otherwise full printerport speed will be attempted.
  78 *
  79 * You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED
  80 *
  81#define LOWSPEED
  82 */
  83
  84#ifndef READ_DELAY
  85#define READ_DELAY 100  /* adapter internal read delay in 100ns units */
  86#endif
  87
  88#ifndef WRITE_DELAY
  89#define WRITE_DELAY 100 /* adapter internal write delay in 100ns units */
  90#endif
  91
  92/*
  93 * Enable this #define if you want the adapter to do a "ifconfig down" on
  94 * itself when we have detected that something is possibly wrong with it.
  95 * The default behaviour is to retry with "adapter_init()" until success.
  96 * This should be used for debugging purposes only.
  97 *
  98#define SHUTDOWN_WHEN_LOST
  99 */
 100
 101/*
 102 * Enable debugging by "-DDE620_DEBUG=3" when compiling,
 103 * OR by enabling the following #define
 104 *
 105 * use 0 for production, 1 for verification, >2 for debug
 106 *
 107#define DE620_DEBUG 3
 108 */
 109
 110#ifdef LOWSPEED
 111/*
 112 * Enable this #define if you want to see debugging output that show how long
 113 * we have to wait before the DE-620 is ready for the next read/write/command.
 114 *
 115#define COUNT_LOOPS
 116 */
 117#endif
 118
 119#include <linux/module.h>
 120
 121#include <linux/kernel.h>
 122#include <linux/sched.h>
 123#include <linux/types.h>
 124#include <linux/fcntl.h>
 125#include <linux/string.h>
 126#include <linux/interrupt.h>
 127#include <linux/ioport.h>
 128#include <asm/io.h>
 129#include <linux/in.h>
 130#include <asm/system.h>
 131#include <linux/errno.h>
 132#include <linux/init.h>
 133
 134#include <linux/inet.h>
 135#include <linux/netdevice.h>
 136#include <linux/etherdevice.h>
 137#include <linux/skbuff.h>
 138
 139/* Constant definitions for the DE-620 registers, commands and bits */
 140#include "de620.h"
 141
 142typedef unsigned char byte;
 143
 144/*******************************************************
 145 *                                                     *
 146 * Definition of D-Link DE-620 Ethernet Pocket adapter *
 147 * See also "de620.h"                                  *
 148 *                                                     *
 149 *******************************************************/
 150#ifndef DE620_IO /* Compile-time configurable */
 151#define DE620_IO 0x378
 152#endif
 153
 154#ifndef DE620_IRQ /* Compile-time configurable */
 155#define DE620_IRQ       7
 156#endif
 157
 158#define DATA_PORT       (dev->base_addr)
 159#define STATUS_PORT     (dev->base_addr + 1)
 160#define COMMAND_PORT    (dev->base_addr + 2)
 161
 162#define RUNT 60         /* Too small Ethernet packet */
 163#define GIANT 1514      /* largest legal size packet, no fcs */
 164
 165#ifdef DE620_DEBUG /* Compile-time configurable */
 166#define PRINTK(x) if (de620_debug >= 2) printk x
 167#else
 168#define DE620_DEBUG 0
 169#define PRINTK(x) /**/
 170#endif
 171
 172
 173/*
 174 * Force media with insmod:
 175 *      insmod de620.o bnc=1
 176 * or
 177 *      insmod de620.o utp=1
 178 *
 179 * Force io and/or irq with insmod:
 180 *      insmod de620.o io=0x378 irq=7
 181 *
 182 * Make a clone skip the Ethernet-address range check:
 183 *      insmod de620.o clone=1
 184 */
 185static int bnc;
 186static int utp;
 187static int io  = DE620_IO;
 188static int irq = DE620_IRQ;
 189static int clone = DE620_CLONE;
 190
 191static unsigned int de620_debug = DE620_DEBUG;
 192
 193MODULE_PARM(bnc, "i");
 194MODULE_PARM(utp, "i");
 195MODULE_PARM(io, "i");
 196MODULE_PARM(irq, "i");
 197MODULE_PARM(clone, "i");
 198MODULE_PARM(de620_debug, "i");
 199MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)");
 200MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)");
 201MODULE_PARM_DESC(io, "DE-620 I/O base address,required");
 202MODULE_PARM_DESC(irq, "DE-620 IRQ number,required");
 203MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)");
 204MODULE_PARM_DESC(de620_debug, "DE-620 debug level (0-2)");
 205
 206/***********************************************
 207 *                                             *
 208 * Index to functions, as function prototypes. *
 209 *                                             *
 210 ***********************************************/
 211
 212/*
 213 * Routines used internally. (See also "convenience macros.. below")
 214 */
 215
 216/* Put in the device structure. */
 217static int      de620_open(struct net_device *);
 218static int      de620_close(struct net_device *);
 219static struct   net_device_stats *get_stats(struct net_device *);
 220static void     de620_set_multicast_list(struct net_device *);
 221static int      de620_start_xmit(struct sk_buff *, struct net_device *);
 222
 223/* Dispatch from interrupts. */
 224static void     de620_interrupt(int, void *, struct pt_regs *);
 225static int      de620_rx_intr(struct net_device *);
 226
 227/* Initialization */
 228static int      adapter_init(struct net_device *);
 229int             de620_probe(struct net_device *);
 230static int      read_eeprom(struct net_device *);
 231
 232
 233/*
 234 * D-Link driver variables:
 235 */
 236#define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX
 237#define TCR_DEF RXPB                    /* not used: | TXSUCINT | T16INT */
 238#define DE620_RX_START_PAGE 12          /* 12 pages (=3k) reserved for tx */
 239#define DEF_NIC_CMD IRQEN | ICEN | DS1
 240
 241static volatile byte    NIC_Cmd;
 242static volatile byte    next_rx_page;
 243static byte             first_rx_page;
 244static byte             last_rx_page;
 245static byte             EIPRegister;
 246
 247static struct nic {
 248        byte    NodeID[6];
 249        byte    RAM_Size;
 250        byte    Model;
 251        byte    Media;
 252        byte    SCR;
 253} nic_data;
 254
 255/**********************************************************
 256 *                                                        *
 257 * Convenience macros/functions for D-Link DE-620 adapter *
 258 *                                                        *
 259 **********************************************************/
 260#define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1))
 261#define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT);
 262
 263/* Check for ready-status, and return a nibble (high 4 bits) for data input */
 264#ifdef COUNT_LOOPS
 265static int tot_cnt;
 266#endif
 267static inline byte
 268de620_ready(struct net_device *dev)
 269{
 270        byte value;
 271        register short int cnt = 0;
 272
 273        while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000))
 274                ++cnt;
 275
 276#ifdef COUNT_LOOPS
 277        tot_cnt += cnt;
 278#endif
 279        return value & 0xf0; /* nibble */
 280}
 281
 282static inline void
 283de620_send_command(struct net_device *dev, byte cmd)
 284{
 285        de620_ready(dev);
 286        if (cmd == W_DUMMY)
 287                outb(NIC_Cmd, COMMAND_PORT);
 288
 289        outb(cmd, DATA_PORT);
 290
 291        outb(NIC_Cmd ^ CS0, COMMAND_PORT);
 292        de620_ready(dev);
 293        outb(NIC_Cmd, COMMAND_PORT);
 294}
 295
 296static inline void
 297de620_put_byte(struct net_device *dev, byte value)
 298{
 299        /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
 300        de620_ready(dev);
 301        outb(value, DATA_PORT);
 302        de620_flip_ds(dev);
 303}
 304
 305static inline byte
 306de620_read_byte(struct net_device *dev)
 307{
 308        byte value;
 309
 310        /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */
 311        value = de620_ready(dev); /* High nibble */
 312        de620_flip_ds(dev);
 313        value |= de620_ready(dev) >> 4; /* Low nibble */
 314        return value;
 315}
 316
 317static inline void
 318de620_write_block(struct net_device *dev, byte *buffer, int count)
 319{
 320#ifndef LOWSPEED
 321        byte uflip = NIC_Cmd ^ (DS0 | DS1);
 322        byte dflip = NIC_Cmd;
 323#else /* LOWSPEED */
 324#ifdef COUNT_LOOPS
 325        int bytes = count;
 326#endif /* COUNT_LOOPS */
 327#endif /* LOWSPEED */
 328
 329#ifdef LOWSPEED
 330#ifdef COUNT_LOOPS
 331        tot_cnt = 0;
 332#endif /* COUNT_LOOPS */
 333        /* No further optimization useful, the limit is in the adapter. */
 334        for ( ; count > 0; --count, ++buffer) {
 335                de620_put_byte(dev,*buffer);
 336        }
 337        de620_send_command(dev,W_DUMMY);
 338#ifdef COUNT_LOOPS
 339        /* trial debug output: loops per byte in de620_ready() */
 340        printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1)));
 341#endif /* COUNT_LOOPS */
 342#else /* not LOWSPEED */
 343        for ( ; count > 0; count -=2) {
 344                outb(*buffer++, DATA_PORT);
 345                outb(uflip, COMMAND_PORT);
 346                outb(*buffer++, DATA_PORT);
 347                outb(dflip, COMMAND_PORT);
 348        }
 349        de620_send_command(dev,W_DUMMY);
 350#endif /* LOWSPEED */
 351}
 352
 353static inline void
 354de620_read_block(struct net_device *dev, byte *data, int count)
 355{
 356#ifndef LOWSPEED
 357        byte value;
 358        byte uflip = NIC_Cmd ^ (DS0 | DS1);
 359        byte dflip = NIC_Cmd;
 360#else /* LOWSPEED */
 361#ifdef COUNT_LOOPS
 362        int bytes = count;
 363
 364        tot_cnt = 0;
 365#endif /* COUNT_LOOPS */
 366#endif /* LOWSPEED */
 367
 368#ifdef LOWSPEED
 369        /* No further optimization useful, the limit is in the adapter. */
 370        while (count-- > 0) {
 371                *data++ = de620_read_byte(dev);
 372                de620_flip_ds(dev);
 373        }
 374#ifdef COUNT_LOOPS
 375        /* trial debug output: loops per byte in de620_ready() */
 376        printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1)));
 377#endif /* COUNT_LOOPS */
 378#else /* not LOWSPEED */
 379        while (count-- > 0) {
 380                value = inb(STATUS_PORT) & 0xf0; /* High nibble */
 381                outb(uflip, COMMAND_PORT);
 382                *data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */
 383                outb(dflip , COMMAND_PORT);
 384        }
 385#endif /* LOWSPEED */
 386}
 387
 388static inline void
 389de620_set_delay(struct net_device *dev)
 390{
 391        de620_ready(dev);
 392        outb(W_DFR, DATA_PORT);
 393        outb(NIC_Cmd ^ CS0, COMMAND_PORT);
 394
 395        de620_ready(dev);
 396#ifdef LOWSPEED
 397        outb(WRITE_DELAY, DATA_PORT);
 398#else
 399        outb(0, DATA_PORT);
 400#endif
 401        de620_flip_ds(dev);
 402
 403        de620_ready(dev);
 404#ifdef LOWSPEED
 405        outb(READ_DELAY, DATA_PORT);
 406#else
 407        outb(0, DATA_PORT);
 408#endif
 409        de620_flip_ds(dev);
 410}
 411
 412static inline void
 413de620_set_register(struct net_device *dev, byte reg, byte value)
 414{
 415        de620_ready(dev);
 416        outb(reg, DATA_PORT);
 417        outb(NIC_Cmd ^ CS0, COMMAND_PORT);
 418
 419        de620_put_byte(dev, value);
 420}
 421
 422static inline byte
 423de620_get_register(struct net_device *dev, byte reg)
 424{
 425        byte value;
 426
 427        de620_send_command(dev,reg);
 428        value = de620_read_byte(dev);
 429        de620_send_command(dev,W_DUMMY);
 430
 431        return value;
 432}
 433
 434/*********************************************************************
 435 *
 436 * Open/initialize the board.
 437 *
 438 * This routine should set everything up anew at each open, even
 439 * registers that "should" only need to be set once at boot, so that
 440 * there is a non-reboot way to recover if something goes wrong.
 441 *
 442 */
 443static int de620_open(struct net_device *dev)
 444{
 445        int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev);
 446        if (ret) {
 447                printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
 448                return ret;
 449        }
 450
 451        if (adapter_init(dev)) {
 452                ret = -EIO;
 453                goto out_free_irq;
 454        }
 455
 456        netif_start_queue(dev);
 457        return 0;
 458
 459out_free_irq:
 460        free_irq(dev->irq, dev);
 461        return ret;
 462}
 463
 464/************************************************
 465 *
 466 * The inverse routine to de620_open().
 467 *
 468 */
 469
 470static int de620_close(struct net_device *dev)
 471{
 472        netif_stop_queue(dev);
 473        /* disable recv */
 474        de620_set_register(dev, W_TCR, RXOFF);
 475        free_irq(dev->irq, dev);
 476        return 0;
 477}
 478
 479/*********************************************
 480 *
 481 * Return current statistics
 482 *
 483 */
 484static struct net_device_stats *get_stats(struct net_device *dev)
 485{
 486        return (struct net_device_stats *)(dev->priv);
 487}
 488
 489/*********************************************
 490 *
 491 * Set or clear the multicast filter for this adaptor.
 492 * (no real multicast implemented for the DE-620, but she can be promiscuous...)
 493 *
 494 */
 495
 496static void de620_set_multicast_list(struct net_device *dev)
 497{
 498        if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
 499        { /* Enable promiscuous mode */
 500                /*
 501                 *      We must make the kernel realise we had to move
 502                 *      into promisc mode or we start all out war on
 503                 *      the cable. - AC
 504                 */
 505                dev->flags|=IFF_PROMISC;
 506
 507                de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL);
 508        }
 509        else
 510        { /* Disable promiscuous mode, use normal mode */
 511                de620_set_register(dev, W_TCR, TCR_DEF);
 512        }
 513}
 514
 515/*******************************************************
 516 *      
 517 * Handle timeouts on transmit
 518 */
 519 
 520static void de620_timeout(struct net_device *dev)
 521{
 522        printk("%s: transmit timed out, %s?\n",
 523                dev->name,
 524                "network cable problem"
 525                );
 526        /* Restart the adapter. */
 527        if (!adapter_init(dev)) /* maybe close it */
 528                netif_wake_queue(dev);
 529}
 530
 531/*******************************************************
 532 *
 533 * Copy a buffer to the adapter transmit page memory.
 534 * Start sending.
 535 */
 536static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
 537{
 538        unsigned long flags;
 539        int len;
 540        byte *buffer = skb->data;
 541        byte using_txbuf;
 542
 543        using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */
 544        
 545        netif_stop_queue(dev);
 546        
 547
 548        if ((len = skb->len) < RUNT)
 549                len = RUNT;
 550        if (len & 1) /* send an even number of bytes */
 551                ++len;
 552
 553        /* Start real output */
 554        save_flags(flags);
 555        cli();
 556
 557        PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n",
 558                (int)skb->len, using_txbuf));
 559
 560        /* select a free tx buffer. if there is one... */
 561        switch (using_txbuf) {
 562        default: /* both are free: use TXBF0 */
 563        case TXBF1: /* use TXBF0 */
 564                de620_send_command(dev,W_CR | RW0);
 565                using_txbuf |= TXBF0;
 566                break;
 567
 568        case TXBF0: /* use TXBF1 */
 569                de620_send_command(dev,W_CR | RW1);
 570                using_txbuf |= TXBF1;
 571                break;
 572
 573        case (TXBF0 | TXBF1): /* NONE!!! */
 574                printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
 575                restore_flags(flags);
 576                return 1;
 577        }
 578        de620_write_block(dev, buffer, len);
 579
 580        dev->trans_start = jiffies;
 581        if(!(using_txbuf == (TXBF0 | TXBF1)))
 582                netif_wake_queue(dev);
 583
 584        ((struct net_device_stats *)(dev->priv))->tx_packets++;
 585        restore_flags(flags); /* interrupts maybe back on */
 586        dev_kfree_skb (skb);
 587        return 0;
 588}
 589
 590/*****************************************************
 591 *
 592 * Handle the network interface interrupts.
 593 *
 594 */
 595static void de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
 596{
 597        struct net_device *dev = dev_id;
 598        byte irq_status;
 599        int bogus_count = 0;
 600        int again = 0;
 601
 602        /* This might be deleted now, no crummy drivers present :-) Or..? */
 603        if ((dev == NULL) || (irq != irq_in)) {
 604                printk("%s: bogus interrupt %d\n", dev?dev->name:"de620", irq_in);
 605                return;
 606        }
 607
 608        /* Read the status register (_not_ the status port) */
 609        irq_status = de620_get_register(dev, R_STS);
 610
 611        PRINTK(("de620_interrupt (%2.2X)\n", irq_status));
 612
 613        if (irq_status & RXGOOD) {
 614                do {
 615                        again = de620_rx_intr(dev);
 616                        PRINTK(("again=%d\n", again));
 617                }
 618                while (again && (++bogus_count < 100));
 619        }
 620
 621        if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))
 622                netif_wake_queue(dev);
 623}
 624
 625/**************************************
 626 *
 627 * Get a packet from the adapter
 628 *
 629 * Send it "upstairs"
 630 *
 631 */
 632static int de620_rx_intr(struct net_device *dev)
 633{
 634        struct header_buf {
 635                byte            status;
 636                byte            Rx_NextPage;
 637                unsigned short  Rx_ByteCount;
 638        } header_buf;
 639        struct sk_buff *skb;
 640        int size;
 641        byte *buffer;
 642        byte pagelink;
 643        byte curr_page;
 644
 645        PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page));
 646
 647        /* Tell the adapter that we are going to read data, and from where */
 648        de620_send_command(dev, W_CR | RRN);
 649        de620_set_register(dev, W_RSA1, next_rx_page);
 650        de620_set_register(dev, W_RSA0, 0);
 651
 652        /* Deep breath, and away we goooooo */
 653        de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));
 654        PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n",
 655        header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount));
 656
 657        /* Plausible page header? */
 658        pagelink = header_buf.Rx_NextPage;
 659        if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
 660                /* Ouch... Forget it! Skip all and start afresh... */
 661                printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);
 662                /* You win some, you lose some. And sometimes plenty... */
 663                adapter_init(dev);
 664                netif_wake_queue(dev);
 665                ((struct net_device_stats *)(dev->priv))->rx_over_errors++;
 666                return 0;
 667        }
 668
 669        /* OK, this look good, so far. Let's see if it's consistent... */
 670        /* Let's compute the start of the next packet, based on where we are */
 671        pagelink = next_rx_page +
 672                ((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8);
 673
 674        /* Are we going to wrap around the page counter? */
 675        if (pagelink > last_rx_page)
 676                pagelink -= (last_rx_page - first_rx_page + 1);
 677
 678        /* Is the _computed_ next page number equal to what the adapter says? */
 679        if (pagelink != header_buf.Rx_NextPage) {
 680                /* Naah, we'll skip this packet. Probably bogus data as well */
 681                printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);
 682                next_rx_page = header_buf.Rx_NextPage; /* at least a try... */
 683                de620_send_command(dev, W_DUMMY);
 684                de620_set_register(dev, W_NPRF, next_rx_page);
 685                ((struct net_device_stats *)(dev->priv))->rx_over_errors++;
 686                return 0;
 687        }
 688        next_rx_page = pagelink;
 689
 690        size = header_buf.Rx_ByteCount - 4;
 691        if ((size < RUNT) || (GIANT < size)) {
 692                printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
 693        }
 694        else { /* Good packet? */
 695                skb = dev_alloc_skb(size+2);
 696                if (skb == NULL) { /* Yeah, but no place to put it... */
 697                        printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n",
 698                                dev->name, size);
 699                        ((struct net_device_stats *)(dev->priv))->rx_dropped++;
 700                }
 701                else { /* Yep! Go get it! */
 702                        skb_reserve(skb,2);     /* Align */
 703                        skb->dev = dev;
 704                        /* skb->data points to the start of sk_buff data area */
 705                        buffer = skb_put(skb,size);
 706                        /* copy the packet into the buffer */
 707                        de620_read_block(dev, buffer, size);
 708                        PRINTK(("Read %d bytes\n", size));
 709                        skb->protocol=eth_type_trans(skb,dev);
 710                        netif_rx(skb); /* deliver it "upstairs" */
 711                        dev->last_rx = jiffies;
 712                        /* count all receives */
 713                        ((struct net_device_stats *)(dev->priv))->rx_packets++;
 714                        ((struct net_device_stats *)(dev->priv))->rx_bytes += size;
 715                }
 716        }
 717
 718        /* Let's peek ahead to see if we have read the last current packet */
 719        /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */
 720        curr_page = de620_get_register(dev, R_CPR);
 721        de620_set_register(dev, W_NPRF, next_rx_page);
 722        PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page));
 723
 724        return (next_rx_page != curr_page); /* That was slightly tricky... */
 725}
 726
 727/*********************************************
 728 *
 729 * Reset the adapter to a known state
 730 *
 731 */
 732static int adapter_init(struct net_device *dev)
 733{
 734        int i;
 735        static int was_down;
 736
 737        if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */
 738                EIPRegister = NCTL0;
 739                if (nic_data.Media != 1)
 740                        EIPRegister |= NIS0;    /* not BNC */
 741        }
 742        else if (nic_data.Model == 2) { /* UTP */
 743                EIPRegister = NCTL0 | NIS0;
 744        }
 745
 746        if (utp)
 747                EIPRegister = NCTL0 | NIS0;
 748        if (bnc)
 749                EIPRegister = NCTL0;
 750
 751        de620_send_command(dev, W_CR | RNOP | CLEAR);
 752        de620_send_command(dev, W_CR | RNOP);
 753
 754        de620_set_register(dev, W_SCR, SCR_DEF);
 755        /* disable recv to wait init */
 756        de620_set_register(dev, W_TCR, RXOFF);
 757
 758        /* Set the node ID in the adapter */
 759        for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */
 760                de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]);
 761        }
 762
 763        de620_set_register(dev, W_EIP, EIPRegister);
 764
 765        next_rx_page = first_rx_page = DE620_RX_START_PAGE;
 766        if (nic_data.RAM_Size)
 767                last_rx_page = nic_data.RAM_Size - 1;
 768        else /* 64k RAM */
 769                last_rx_page = 255;
 770
 771        de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/
 772        de620_set_register(dev, W_EPR, last_rx_page);  /* End Page Register */
 773        de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/
 774        de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/
 775        de620_send_command(dev, W_DUMMY);
 776        de620_set_delay(dev);
 777
 778        /* Final sanity check: Anybody out there? */
 779        /* Let's hope some bits from the statusregister make a good check */
 780#define CHECK_MASK (  0 | TXSUC |  T16  |  0  | RXCRC | RXSHORT |  0  |  0  )
 781#define CHECK_OK   (  0 |   0   |  0    |  0  |   0   |   0     |  0  |  0  )
 782        /* success:   X     0      0       X      0       0        X     X  */
 783        /* ignore:   EEDI                RXGOOD                   COLS  LNKS*/
 784
 785        if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {
 786                printk(KERN_ERR "%s: Something has happened to the DE-620!  Please check it"
 787#ifdef SHUTDOWN_WHEN_LOST
 788                        " and do a new ifconfig"
 789#endif
 790                        "! (%02x)\n", dev->name, i);
 791#ifdef SHUTDOWN_WHEN_LOST
 792                /* Goodbye, cruel world... */
 793                dev->flags &= ~IFF_UP;
 794                de620_close(dev);
 795#endif
 796                was_down = 1;
 797                return 1; /* failed */
 798        }
 799        if (was_down) {
 800                printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);
 801                was_down = 0;
 802        }
 803
 804        /* All OK, go ahead... */
 805        de620_set_register(dev, W_TCR, TCR_DEF);
 806
 807        return 0; /* all ok */
 808}
 809
 810/******************************************************************************
 811 *
 812 * Only start-up code below
 813 *
 814 */
 815/****************************************
 816 *
 817 * Check if there is a DE-620 connected
 818 */
 819int __init de620_probe(struct net_device *dev)
 820{
 821        static struct net_device_stats de620_netstats;
 822        int i;
 823        byte checkbyte = 0xa5;
 824
 825        SET_MODULE_OWNER(dev);
 826
 827        /*
 828         * This is where the base_addr and irq gets set.
 829         * Tunable at compile-time and insmod-time
 830         */
 831        dev->base_addr = io;
 832        dev->irq       = irq;
 833
 834        if (de620_debug)
 835                printk(version);
 836
 837        printk(KERN_INFO "D-Link DE-620 pocket adapter");
 838
 839        /* Initially, configure basic nibble mode, so we can read the EEPROM */
 840        NIC_Cmd = DEF_NIC_CMD;
 841        de620_set_register(dev, W_EIP, EIPRegister);
 842
 843        /* Anybody out there? */
 844        de620_set_register(dev, W_CPR, checkbyte);
 845        checkbyte = de620_get_register(dev, R_CPR);
 846
 847        if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) {
 848                printk(" not identified in the printer port\n");
 849                return -ENODEV;
 850        }
 851
 852#if 0 /* Not yet */
 853        if (check_region(dev->base_addr, 3)) {
 854                printk(", port 0x%x busy\n", dev->base_addr);
 855                return -EBUSY;
 856        }
 857#endif
 858        if (!request_region(dev->base_addr, 3, "de620")) {
 859                printk(KERN_ERR "io 0x%3lX, which is busy.\n", dev->base_addr);
 860                return -EBUSY;
 861        }
 862
 863        /* else, got it! */
 864        printk(", Ethernet Address: %2.2X",
 865                dev->dev_addr[0] = nic_data.NodeID[0]);
 866        for (i = 1; i < ETH_ALEN; i++) {
 867                printk(":%2.2X", dev->dev_addr[i] = nic_data.NodeID[i]);
 868                dev->broadcast[i] = 0xff;
 869        }
 870
 871        printk(" (%dk RAM,",
 872                (nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
 873
 874        if (nic_data.Media == 1)
 875                printk(" BNC)\n");
 876        else
 877                printk(" UTP)\n");
 878
 879        /* Initialize the device structure. */
 880        dev->priv = &de620_netstats;
 881
 882        memset(dev->priv, 0, sizeof(struct net_device_stats));
 883        dev->get_stats          = get_stats;
 884        dev->open               = de620_open;
 885        dev->stop               = de620_close;
 886        dev->hard_start_xmit    = de620_start_xmit;
 887        dev->tx_timeout         = de620_timeout;
 888        dev->watchdog_timeo     = HZ*2;
 889        dev->set_multicast_list = de620_set_multicast_list;
 890        
 891        /* base_addr and irq are already set, see above! */
 892
 893        ether_setup(dev);
 894
 895        /* dump eeprom */
 896        if (de620_debug) {
 897                printk("\nEEPROM contents:\n");
 898                printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);
 899                printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n",
 900                        nic_data.NodeID[0], nic_data.NodeID[1],
 901                        nic_data.NodeID[2], nic_data.NodeID[3],
 902                        nic_data.NodeID[4], nic_data.NodeID[5]);
 903                printk("Model = %d\n", nic_data.Model);
 904                printk("Media = %d\n", nic_data.Media);
 905                printk("SCR = 0x%02x\n", nic_data.SCR);
 906        }
 907
 908        return 0;
 909}
 910
 911/**********************************
 912 *
 913 * Read info from on-board EEPROM
 914 *
 915 * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_!
 916 */
 917#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
 918
 919static unsigned short __init ReadAWord(struct net_device *dev, int from)
 920{
 921        unsigned short data;
 922        int nbits;
 923
 924        /* cs   [__~~] SET SEND STATE */
 925        /* di   [____]                */
 926        /* sck  [_~~_]                */
 927        sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4);
 928
 929        /* Send the 9-bit address from where we want to read the 16-bit word */
 930        for (nbits = 9; nbits > 0; --nbits, from <<= 1) {
 931                if (from & 0x0100) { /* bit set? */
 932                        /* cs    [~~~~] SEND 1 */
 933                        /* di    [~~~~]        */
 934                        /* sck   [_~~_]        */
 935                        sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6);
 936                }
 937                else {
 938                        /* cs    [~~~~] SEND 0 */
 939                        /* di    [____]        */
 940                        /* sck   [_~~_]        */
 941                        sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
 942                }
 943        }
 944
 945        /* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */
 946        for (data = 0, nbits = 16; nbits > 0; --nbits) {
 947                /* cs    [~~~~] SEND 0 */
 948                /* di    [____]        */
 949                /* sck   [_~~_]        */
 950                sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
 951                data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7);
 952        }
 953        /* cs    [____] RESET SEND STATE */
 954        /* di    [____]                  */
 955        /* sck   [_~~_]                  */
 956        sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0);
 957
 958        return data;
 959}
 960
 961static int __init read_eeprom(struct net_device *dev)
 962{
 963        unsigned short wrd;
 964
 965        /* D-Link Ethernet addresses are in the series  00:80:c8:7X:XX:XX:XX */
 966        wrd = ReadAWord(dev, 0x1aa);    /* bytes 0 + 1 of NodeID */
 967        if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */
 968                return -1; /* Nope, not a DE-620 */
 969        nic_data.NodeID[0] = wrd & 0xff;
 970        nic_data.NodeID[1] = wrd >> 8;
 971
 972        wrd = ReadAWord(dev, 0x1ab);    /* bytes 2 + 3 of NodeID */
 973        if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */
 974                return -1; /* Nope, not a DE-620 */
 975        nic_data.NodeID[2] = wrd & 0xff;
 976        nic_data.NodeID[3] = wrd >> 8;
 977
 978        wrd = ReadAWord(dev, 0x1ac);    /* bytes 4 + 5 of NodeID */
 979        nic_data.NodeID[4] = wrd & 0xff;
 980        nic_data.NodeID[5] = wrd >> 8;
 981
 982        wrd = ReadAWord(dev, 0x1ad);    /* RAM size in pages (256 bytes). 0 = 64k */
 983        nic_data.RAM_Size = (wrd >> 8);
 984
 985        wrd = ReadAWord(dev, 0x1ae);    /* hardware model (CT = 3) */
 986        nic_data.Model = (wrd & 0xff);
 987
 988        wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */
 989        nic_data.Media = (wrd & 0xff);
 990
 991        wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */
 992        nic_data.SCR = (wrd >> 8);
 993
 994        return 0; /* no errors */
 995}
 996
 997/******************************************************************************
 998 *
 999 * Loadable module skeleton
1000 *
1001 */
1002#ifdef MODULE
1003static struct net_device de620_dev;
1004
1005int init_module(void)
1006{
1007        de620_dev.init = de620_probe;
1008        if (register_netdev(&de620_dev) != 0)
1009                return -EIO;
1010        return 0;
1011}
1012
1013void cleanup_module(void)
1014{
1015        unregister_netdev(&de620_dev);
1016        release_region(de620_dev.base_addr, 3);
1017}
1018#endif /* MODULE */
1019MODULE_LICENSE("GPL");
1020
1021
1022/*
1023 * (add '-DMODULE' when compiling as loadable module)
1024 *
1025 * compile-command:
1026 *      gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \
1027 *       -fomit-frame-pointer -m486 \
1028 *      -I/usr/src/linux/include -I../../net/inet -c de620.c
1029*/
1030/*
1031 * Local variables:
1032 *  kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1033 *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1034 *  compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1035 * End:
1036 */
1037
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.