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#include <linux/kernel.h>
 121#include <linux/types.h>
 122#include <linux/fcntl.h>
 123#include <linux/string.h>
 124#include <linux/interrupt.h>
 125#include <linux/ioport.h>
 126#include <linux/in.h>
 127#include <linux/errno.h>
 128#include <linux/init.h>
 129#include <linux/inet.h>
 130#include <linux/netdevice.h>
 131#include <linux/etherdevice.h>
 132#include <linux/skbuff.h>
 133
 134#include <asm/io.h>
 135#include <asm/system.h>
 136
 137/* Constant definitions for the DE-620 registers, commands and bits */
 138#include "de620.h"
 139
 140typedef unsigned char byte;
 141
 142/*******************************************************
 143 *                                                     *
 144 * Definition of D-Link DE-620 Ethernet Pocket adapter *
 145 * See also "de620.h"                                  *
 146 *                                                     *
 147 *******************************************************/
 148#ifndef DE620_IO /* Compile-time configurable */
 149#define DE620_IO 0x378
 150#endif
 151
 152#ifndef DE620_IRQ /* Compile-time configurable */
 153#define DE620_IRQ       7
 154#endif
 155
 156#define DATA_PORT       (dev->base_addr)
 157#define STATUS_PORT     (dev->base_addr + 1)
 158#define COMMAND_PORT    (dev->base_addr + 2)
 159
 160#define RUNT 60         /* Too small Ethernet packet */
 161#define GIANT 1514      /* largest legal size packet, no fcs */
 162
 163#ifdef DE620_DEBUG /* Compile-time configurable */
 164#define PRINTK(x) if (de620_debug >= 2) printk x
 165#else
 166#define DE620_DEBUG 0
 167#define PRINTK(x) /**/
 168#endif
 169
 170
 171/*
 172 * Force media with insmod:
 173 *      insmod de620.o bnc=1
 174 * or
 175 *      insmod de620.o utp=1
 176 *
 177 * Force io and/or irq with insmod:
 178 *      insmod de620.o io=0x378 irq=7
 179 *
 180 * Make a clone skip the Ethernet-address range check:
 181 *      insmod de620.o clone=1
 182 */
 183static int bnc;
 184static int utp;
 185static int io  = DE620_IO;
 186static int irq = DE620_IRQ;
 187static int clone = DE620_CLONE;
 188
 189static unsigned int de620_debug = DE620_DEBUG;
 190
 191static spinlock_t de620_lock;
 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 irqreturn_t 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, int pad)
 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        for ( count = pad ; count > 0; --count, ++buffer) {
 338                de620_put_byte(dev, 0);
 339        }
 340        de620_send_command(dev,W_DUMMY);
 341#ifdef COUNT_LOOPS
 342        /* trial debug output: loops per byte in de620_ready() */
 343        printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1)));
 344#endif /* COUNT_LOOPS */
 345#else /* not LOWSPEED */
 346        for ( ; count > 0; count -=2) {
 347                outb(*buffer++, DATA_PORT);
 348                outb(uflip, COMMAND_PORT);
 349                outb(*buffer++, DATA_PORT);
 350                outb(dflip, COMMAND_PORT);
 351        }
 352        de620_send_command(dev,W_DUMMY);
 353#endif /* LOWSPEED */
 354}
 355
 356static inline void
 357de620_read_block(struct net_device *dev, byte *data, int count)
 358{
 359#ifndef LOWSPEED
 360        byte value;
 361        byte uflip = NIC_Cmd ^ (DS0 | DS1);
 362        byte dflip = NIC_Cmd;
 363#else /* LOWSPEED */
 364#ifdef COUNT_LOOPS
 365        int bytes = count;
 366
 367        tot_cnt = 0;
 368#endif /* COUNT_LOOPS */
 369#endif /* LOWSPEED */
 370
 371#ifdef LOWSPEED
 372        /* No further optimization useful, the limit is in the adapter. */
 373        while (count-- > 0) {
 374                *data++ = de620_read_byte(dev);
 375                de620_flip_ds(dev);
 376        }
 377#ifdef COUNT_LOOPS
 378        /* trial debug output: loops per byte in de620_ready() */
 379        printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1)));
 380#endif /* COUNT_LOOPS */
 381#else /* not LOWSPEED */
 382        while (count-- > 0) {
 383                value = inb(STATUS_PORT) & 0xf0; /* High nibble */
 384                outb(uflip, COMMAND_PORT);
 385                *data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */
 386                outb(dflip , COMMAND_PORT);
 387        }
 388#endif /* LOWSPEED */
 389}
 390
 391static inline void
 392de620_set_delay(struct net_device *dev)
 393{
 394        de620_ready(dev);
 395        outb(W_DFR, DATA_PORT);
 396        outb(NIC_Cmd ^ CS0, COMMAND_PORT);
 397
 398        de620_ready(dev);
 399#ifdef LOWSPEED
 400        outb(WRITE_DELAY, DATA_PORT);
 401#else
 402        outb(0, DATA_PORT);
 403#endif
 404        de620_flip_ds(dev);
 405
 406        de620_ready(dev);
 407#ifdef LOWSPEED
 408        outb(READ_DELAY, DATA_PORT);
 409#else
 410        outb(0, DATA_PORT);
 411#endif
 412        de620_flip_ds(dev);
 413}
 414
 415static inline void
 416de620_set_register(struct net_device *dev, byte reg, byte value)
 417{
 418        de620_ready(dev);
 419        outb(reg, DATA_PORT);
 420        outb(NIC_Cmd ^ CS0, COMMAND_PORT);
 421
 422        de620_put_byte(dev, value);
 423}
 424
 425static inline byte
 426de620_get_register(struct net_device *dev, byte reg)
 427{
 428        byte value;
 429
 430        de620_send_command(dev,reg);
 431        value = de620_read_byte(dev);
 432        de620_send_command(dev,W_DUMMY);
 433
 434        return value;
 435}
 436
 437/*********************************************************************
 438 *
 439 * Open/initialize the board.
 440 *
 441 * This routine should set everything up anew at each open, even
 442 * registers that "should" only need to be set once at boot, so that
 443 * there is a non-reboot way to recover if something goes wrong.
 444 *
 445 */
 446static int de620_open(struct net_device *dev)
 447{
 448        int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev);
 449        if (ret) {
 450                printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
 451                return ret;
 452        }
 453
 454        if (adapter_init(dev)) {
 455                ret = -EIO;
 456                goto out_free_irq;
 457        }
 458
 459        netif_start_queue(dev);
 460        return 0;
 461
 462out_free_irq:
 463        free_irq(dev->irq, dev);
 464        return ret;
 465}
 466
 467/************************************************
 468 *
 469 * The inverse routine to de620_open().
 470 *
 471 */
 472
 473static int de620_close(struct net_device *dev)
 474{
 475        netif_stop_queue(dev);
 476        /* disable recv */
 477        de620_set_register(dev, W_TCR, RXOFF);
 478        free_irq(dev->irq, dev);
 479        return 0;
 480}
 481
 482/*********************************************
 483 *
 484 * Return current statistics
 485 *
 486 */
 487static struct net_device_stats *get_stats(struct net_device *dev)
 488{
 489        return (struct net_device_stats *)(dev->priv);
 490}
 491
 492/*********************************************
 493 *
 494 * Set or clear the multicast filter for this adaptor.
 495 * (no real multicast implemented for the DE-620, but she can be promiscuous...)
 496 *
 497 */
 498
 499static void de620_set_multicast_list(struct net_device *dev)
 500{
 501        if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
 502        { /* Enable promiscuous mode */
 503                /*
 504                 *      We must make the kernel realise we had to move
 505                 *      into promisc mode or we start all out war on
 506                 *      the cable. - AC
 507                 */
 508                dev->flags|=IFF_PROMISC;
 509
 510                de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL);
 511        }
 512        else
 513        { /* Disable promiscuous mode, use normal mode */
 514                de620_set_register(dev, W_TCR, TCR_DEF);
 515        }
 516}
 517
 518/*******************************************************
 519 *      
 520 * Handle timeouts on transmit
 521 */
 522 
 523static void de620_timeout(struct net_device *dev)
 524{
 525        printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, "network cable problem");
 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
 555        spin_lock_irqsave(&de620_lock, flags)
 556        PRINTK(("de620_start_xmit: len=%d, bufs 0x%02x\n",
 557                (int)skb->len, using_txbuf));
 558
 559        /* select a free tx buffer. if there is one... */
 560        switch (using_txbuf) {
 561        default: /* both are free: use TXBF0 */
 562        case TXBF1: /* use TXBF0 */
 563                de620_send_command(dev,W_CR | RW0);
 564                using_txbuf |= TXBF0;
 565                break;
 566
 567        case TXBF0: /* use TXBF1 */
 568                de620_send_command(dev,W_CR | RW1);
 569                using_txbuf |= TXBF1;
 570                break;
 571
 572        case (TXBF0 | TXBF1): /* NONE!!! */
 573                printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
 574                spin_unlock_irqrestore(&de620_lock, flags);
 575                return 1;
 576        }
 577        de620_write_block(dev, buffer, skb->len, len-skb->len);
 578
 579        dev->trans_start = jiffies;
 580        if(!(using_txbuf == (TXBF0 | TXBF1)))
 581                netif_wake_queue(dev);
 582
 583        ((struct net_device_stats *)(dev->priv))->tx_packets++;
 584        spin_unlock_irqrestore(&de620_lock, flags);
 585        dev_kfree_skb (skb);
 586        return 0;
 587}
 588
 589/*****************************************************
 590 *
 591 * Handle the network interface interrupts.
 592 *
 593 */
 594static irqreturn_t
 595de620_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        spin_lock(&de620_lock);
 603        
 604        /* Read the status register (_not_ the status port) */
 605        irq_status = de620_get_register(dev, R_STS);
 606
 607        PRINTK(("de620_interrupt (%2.2X)\n", irq_status));
 608
 609        if (irq_status & RXGOOD) {
 610                do {
 611                        again = de620_rx_intr(dev);
 612                        PRINTK(("again=%d\n", again));
 613                }
 614                while (again && (++bogus_count < 100));
 615        }
 616
 617        if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))
 618                netif_wake_queue(dev);
 619                
 620        spin_unlock(&de620_lock);
 621        return IRQ_HANDLED;
 622}
 623
 624/**************************************
 625 *
 626 * Get a packet from the adapter
 627 *
 628 * Send it "upstairs"
 629 *
 630 */
 631static int de620_rx_intr(struct net_device *dev)
 632{
 633        struct header_buf {
 634                byte            status;
 635                byte            Rx_NextPage;
 636                unsigned short  Rx_ByteCount;
 637        } header_buf;
 638        struct sk_buff *skb;
 639        int size;
 640        byte *buffer;
 641        byte pagelink;
 642        byte curr_page;
 643
 644        PRINTK(("de620_rx_intr: next_rx_page = %d\n", next_rx_page));
 645
 646        /* Tell the adapter that we are going to read data, and from where */
 647        de620_send_command(dev, W_CR | RRN);
 648        de620_set_register(dev, W_RSA1, next_rx_page);
 649        de620_set_register(dev, W_RSA0, 0);
 650
 651        /* Deep breath, and away we goooooo */
 652        de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf));
 653        PRINTK(("page status=0x%02x, nextpage=%d, packetsize=%d\n",
 654        header_buf.status, header_buf.Rx_NextPage, header_buf.Rx_ByteCount));
 655
 656        /* Plausible page header? */
 657        pagelink = header_buf.Rx_NextPage;
 658        if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
 659                /* Ouch... Forget it! Skip all and start afresh... */
 660                printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);
 661                /* You win some, you lose some. And sometimes plenty... */
 662                adapter_init(dev);
 663                netif_wake_queue(dev);
 664                ((struct net_device_stats *)(dev->priv))->rx_over_errors++;
 665                return 0;
 666        }
 667
 668        /* OK, this look good, so far. Let's see if it's consistent... */
 669        /* Let's compute the start of the next packet, based on where we are */
 670        pagelink = next_rx_page +
 671                ((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8);
 672
 673        /* Are we going to wrap around the page counter? */
 674        if (pagelink > last_rx_page)
 675                pagelink -= (last_rx_page - first_rx_page + 1);
 676
 677        /* Is the _computed_ next page number equal to what the adapter says? */
 678        if (pagelink != header_buf.Rx_NextPage) {
 679                /* Naah, we'll skip this packet. Probably bogus data as well */
 680                printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);
 681                next_rx_page = header_buf.Rx_NextPage; /* at least a try... */
 682                de620_send_command(dev, W_DUMMY);
 683                de620_set_register(dev, W_NPRF, next_rx_page);
 684                ((struct net_device_stats *)(dev->priv))->rx_over_errors++;
 685                return 0;
 686        }
 687        next_rx_page = pagelink;
 688
 689        size = header_buf.Rx_ByteCount - 4;
 690        if ((size < RUNT) || (GIANT < size)) {
 691                printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
 692        }
 693        else { /* Good packet? */
 694                skb = dev_alloc_skb(size+2);
 695                if (skb == NULL) { /* Yeah, but no place to put it... */
 696                        printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
 697                        ((struct net_device_stats *)(dev->priv))->rx_dropped++;
 698                }
 699                else { /* Yep! Go get it! */
 700                        skb_reserve(skb,2);     /* Align */
 701                        skb->dev = dev;
 702                        /* skb->data points to the start of sk_buff data area */
 703                        buffer = skb_put(skb,size);
 704                        /* copy the packet into the buffer */
 705                        de620_read_block(dev, buffer, size);
 706                        PRINTK(("Read %d bytes\n", size));
 707                        skb->protocol=eth_type_trans(skb,dev);
 708                        netif_rx(skb); /* deliver it "upstairs" */
 709                        dev->last_rx = jiffies;
 710                        /* count all receives */
 711                        ((struct net_device_stats *)(dev->priv))->rx_packets++;
 712                        ((struct net_device_stats *)(dev->priv))->rx_bytes += size;
 713                }
 714        }
 715
 716        /* Let's peek ahead to see if we have read the last current packet */
 717        /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */
 718        curr_page = de620_get_register(dev, R_CPR);
 719        de620_set_register(dev, W_NPRF, next_rx_page);
 720        PRINTK(("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page));
 721
 722        return (next_rx_page != curr_page); /* That was slightly tricky... */
 723}
 724
 725/*********************************************
 726 *
 727 * Reset the adapter to a known state
 728 *
 729 */
 730static int adapter_init(struct net_device *dev)
 731{
 732        int i;
 733        static int was_down;
 734
 735        if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */
 736                EIPRegister = NCTL0;
 737                if (nic_data.Media != 1)
 738                        EIPRegister |= NIS0;    /* not BNC */
 739        }
 740        else if (nic_data.Model == 2) { /* UTP */
 741                EIPRegister = NCTL0 | NIS0;
 742        }
 743
 744        if (utp)
 745                EIPRegister = NCTL0 | NIS0;
 746        if (bnc)
 747                EIPRegister = NCTL0;
 748
 749        de620_send_command(dev, W_CR | RNOP | CLEAR);
 750        de620_send_command(dev, W_CR | RNOP);
 751
 752        de620_set_register(dev, W_SCR, SCR_DEF);
 753        /* disable recv to wait init */
 754        de620_set_register(dev, W_TCR, RXOFF);
 755
 756        /* Set the node ID in the adapter */
 757        for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */
 758                de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]);
 759        }
 760
 761        de620_set_register(dev, W_EIP, EIPRegister);
 762
 763        next_rx_page = first_rx_page = DE620_RX_START_PAGE;
 764        if (nic_data.RAM_Size)
 765                last_rx_page = nic_data.RAM_Size - 1;
 766        else /* 64k RAM */
 767                last_rx_page = 255;
 768
 769        de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/
 770        de620_set_register(dev, W_EPR, last_rx_page);  /* End Page Register */
 771        de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/
 772        de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/
 773        de620_send_command(dev, W_DUMMY);
 774        de620_set_delay(dev);
 775
 776        /* Final sanity check: Anybody out there? */
 777        /* Let's hope some bits from the statusregister make a good check */
 778#define CHECK_MASK (  0 | TXSUC |  T16  |  0  | RXCRC | RXSHORT |  0  |  0  )
 779#define CHECK_OK   (  0 |   0   |  0    |  0  |   0   |   0     |  0  |  0  )
 780        /* success:   X     0      0       X      0       0        X     X  */
 781        /* ignore:   EEDI                RXGOOD                   COLS  LNKS*/
 782
 783        if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {
 784                printk(KERN_ERR "%s: Something has happened to the DE-620!  Please check it"
 785#ifdef SHUTDOWN_WHEN_LOST
 786                        " and do a new ifconfig"
 787#endif
 788                        "! (%02x)\n", dev->name, i);
 789#ifdef SHUTDOWN_WHEN_LOST
 790                /* Goodbye, cruel world... */
 791                dev->flags &= ~IFF_UP;
 792                de620_close(dev);
 793#endif
 794                was_down = 1;
 795                return 1; /* failed */
 796        }
 797        if (was_down) {
 798                printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);
 799                was_down = 0;
 800        }
 801
 802        /* All OK, go ahead... */
 803        de620_set_register(dev, W_TCR, TCR_DEF);
 804
 805        return 0; /* all ok */
 806}
 807
 808/******************************************************************************
 809 *
 810 * Only start-up code below
 811 *
 812 */
 813/****************************************
 814 *
 815 * Check if there is a DE-620 connected
 816 */
 817int __init de620_probe(struct net_device *dev)
 818{
 819        static struct net_device_stats de620_netstats;
 820        int i;
 821        byte checkbyte = 0xa5;
 822
 823        SET_MODULE_OWNER(dev);
 824
 825        spin_lock_init(&de620_lock);
 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 (!request_region(dev->base_addr, 3, "de620")) {
 853                printk(KERN_ERR "io 0x%3lX, which is busy.\n", dev->base_addr);
 854                return -EBUSY;
 855        }
 856
 857        /* else, got it! */
 858        printk(", Ethernet Address: %2.2X",
 859                dev->dev_addr[0] = nic_data.NodeID[0]);
 860        for (i = 1; i < ETH_ALEN; i++) {
 861                printk(":%2.2X", dev->dev_addr[i] = nic_data.NodeID[i]);
 862                dev->broadcast[i] = 0xff;
 863        }
 864
 865        printk(" (%dk RAM,",
 866                (nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
 867
 868        if (nic_data.Media == 1)
 869                printk(" BNC)\n");
 870        else
 871                printk(" UTP)\n");
 872
 873        /* Initialize the device structure. */
 874        dev->priv = &de620_netstats;
 875
 876        memset(dev->priv, 0, sizeof(struct net_device_stats));
 877        dev->get_stats          = get_stats;
 878        dev->open               = de620_open;
 879        dev->stop               = de620_close;
 880        dev->hard_start_xmit    = de620_start_xmit;
 881        dev->tx_timeout         = de620_timeout;
 882        dev->watchdog_timeo     = HZ*2;
 883        dev->set_multicast_list = de620_set_multicast_list;
 884        
 885        /* base_addr and irq are already set, see above! */
 886
 887        ether_setup(dev);
 888
 889        /* dump eeprom */
 890        if (de620_debug) {
 891                printk("\nEEPROM contents:\n");
 892                printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);
 893                printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n",
 894                        nic_data.NodeID[0], nic_data.NodeID[1],
 895                        nic_data.NodeID[2], nic_data.NodeID[3],
 896                        nic_data.NodeID[4], nic_data.NodeID[5]);
 897                printk("Model = %d\n", nic_data.Model);
 898                printk("Media = %d\n", nic_data.Media);
 899                printk("SCR = 0x%02x\n", nic_data.SCR);
 900        }
 901
 902        return 0;
 903}
 904
 905/**********************************
 906 *
 907 * Read info from on-board EEPROM
 908 *
 909 * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_!
 910 */
 911#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
 912
 913static unsigned short __init ReadAWord(struct net_device *dev, int from)
 914{
 915        unsigned short data;
 916        int nbits;
 917
 918        /* cs   [__~~] SET SEND STATE */
 919        /* di   [____]                */
 920        /* sck  [_~~_]                */
 921        sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4);
 922
 923        /* Send the 9-bit address from where we want to read the 16-bit word */
 924        for (nbits = 9; nbits > 0; --nbits, from <<= 1) {
 925                if (from & 0x0100) { /* bit set? */
 926                        /* cs    [~~~~] SEND 1 */
 927                        /* di    [~~~~]        */
 928                        /* sck   [_~~_]        */
 929                        sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6);
 930                }
 931                else {
 932                        /* cs    [~~~~] SEND 0 */
 933                        /* di    [____]        */
 934                        /* sck   [_~~_]        */
 935                        sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
 936                }
 937        }
 938
 939        /* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */
 940        for (data = 0, nbits = 16; nbits > 0; --nbits) {
 941                /* cs    [~~~~] SEND 0 */
 942                /* di    [____]        */
 943                /* sck   [_~~_]        */
 944                sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4);
 945                data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7);
 946        }
 947        /* cs    [____] RESET SEND STATE */
 948        /* di    [____]                  */
 949        /* sck   [_~~_]                  */
 950        sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0);
 951
 952        return data;
 953}
 954
 955static int __init read_eeprom(struct net_device *dev)
 956{
 957        unsigned short wrd;
 958
 959        /* D-Link Ethernet addresses are in the series  00:80:c8:7X:XX:XX:XX */
 960        wrd = ReadAWord(dev, 0x1aa);    /* bytes 0 + 1 of NodeID */
 961        if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */
 962                return -1; /* Nope, not a DE-620 */
 963        nic_data.NodeID[0] = wrd & 0xff;
 964        nic_data.NodeID[1] = wrd >> 8;
 965
 966        wrd = ReadAWord(dev, 0x1ab);    /* bytes 2 + 3 of NodeID */
 967        if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */
 968                return -1; /* Nope, not a DE-620 */
 969        nic_data.NodeID[2] = wrd & 0xff;
 970        nic_data.NodeID[3] = wrd >> 8;
 971
 972        wrd = ReadAWord(dev, 0x1ac);    /* bytes 4 + 5 of NodeID */
 973        nic_data.NodeID[4] = wrd & 0xff;
 974        nic_data.NodeID[5] = wrd >> 8;
 975
 976        wrd = ReadAWord(dev, 0x1ad);    /* RAM size in pages (256 bytes). 0 = 64k */
 977        nic_data.RAM_Size = (wrd >> 8);
 978
 979        wrd = ReadAWord(dev, 0x1ae);    /* hardware model (CT = 3) */
 980        nic_data.Model = (wrd & 0xff);
 981
 982        wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */
 983        nic_data.Media = (wrd & 0xff);
 984
 985        wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */
 986        nic_data.SCR = (wrd >> 8);
 987
 988        return 0; /* no errors */
 989}
 990
 991/******************************************************************************
 992 *
 993 * Loadable module skeleton
 994 *
 995 */
 996#ifdef MODULE
 997static struct net_device de620_dev;
 998
 999int init_module(void)
1000{
1001        de620_dev.init = de620_probe;
1002        if (register_netdev(&de620_dev) != 0)
1003                return -EIO;
1004        return 0;
1005}
1006
1007void cleanup_module(void)
1008{
1009        unregister_netdev(&de620_dev);
1010        release_region(de620_dev.base_addr, 3);
1011}
1012#endif /* MODULE */
1013MODULE_LICENSE("GPL");
1014
1015
1016/*
1017 * (add '-DMODULE' when compiling as loadable module)
1018 *
1019 * compile-command:
1020 *      gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \
1021 *       -fomit-frame-pointer -m486 \
1022 *      -I/usr/src/linux/include -I../../net/inet -c de620.c
1023*/
1024/*
1025 * Local variables:
1026 *  kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1027 *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1028 *  compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
1029 * End:
1030 */
1031
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.