linux/drivers/net/de600.c
<<
>>
Prefs
   1static const char version[] = "de600.c: $Revision: 1.41-2.5 $,  Bjorn Ekwall (bj0rn@blox.se)\n";
   2/*
   3 *      de600.c
   4 *
   5 *      Linux driver for the D-Link DE-600 Ethernet pocket adapter.
   6 *
   7 *      Portions (C) Copyright 1993, 1994 by Bjorn Ekwall
   8 *      The Author may be reached as bj0rn@blox.se
   9 *
  10 *      Based on adapter information gathered from DE600.ASM by D-Link Inc.,
  11 *      as included on disk C in the v.2.11 of PC/TCP from FTP Software.
  12 *      For DE600.asm:
  13 *              Portions (C) Copyright 1990 D-Link, Inc.
  14 *              Copyright, 1988-1992, Russell Nelson, Crynwr Software
  15 *
  16 *      Adapted to the sample network driver core for linux,
  17 *      written by: Donald Becker <becker@super.org>
  18 *              (Now at <becker@scyld.com>)
  19 *
  20 **************************************************************/
  21/*
  22 *      This program is free software; you can redistribute it and/or modify
  23 *      it under the terms of the GNU General Public License as published by
  24 *      the Free Software Foundation; either version 2, or (at your option)
  25 *      any later version.
  26 *
  27 *      This program is distributed in the hope that it will be useful,
  28 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  29 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30 *      GNU General Public License for more details.
  31 *
  32 *      You should have received a copy of the GNU General Public License
  33 *      along with this program; if not, write to the Free Software
  34 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  35 *
  36 **************************************************************/
  37
  38/* Add more time here if your adapter won't work OK: */
  39#define DE600_SLOW_DOWN udelay(delay_time)
  40
  41#include <linux/module.h>
  42#include <linux/kernel.h>
  43#include <linux/types.h>
  44#include <linux/fcntl.h>
  45#include <linux/string.h>
  46#include <linux/interrupt.h>
  47#include <linux/ioport.h>
  48#include <linux/in.h>
  49#include <asm/system.h>
  50#include <linux/errno.h>
  51#include <linux/init.h>
  52#include <linux/delay.h>
  53#include <linux/inet.h>
  54#include <linux/netdevice.h>
  55#include <linux/etherdevice.h>
  56#include <linux/skbuff.h>
  57
  58#include <asm/io.h>
  59
  60#include "de600.h"
  61
  62static unsigned int check_lost = 1;
  63module_param(check_lost, bool, 0);
  64MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600");
  65
  66static unsigned int delay_time = 10;
  67module_param(delay_time, int, 0);
  68MODULE_PARM_DESC(delay_time, "DE-600 deley on I/O in microseconds");
  69
  70
  71/*
  72 * D-Link driver variables:
  73 */
  74
  75static volatile int             rx_page;
  76
  77#define TX_PAGES 2
  78static volatile int             tx_fifo[TX_PAGES];
  79static volatile int             tx_fifo_in;
  80static volatile int             tx_fifo_out;
  81static volatile int             free_tx_pages = TX_PAGES;
  82static int                      was_down;
  83static DEFINE_SPINLOCK(de600_lock);
  84
  85static inline u8 de600_read_status(struct net_device *dev)
  86{
  87        u8 status;
  88
  89        outb_p(STATUS, DATA_PORT);
  90        status = inb(STATUS_PORT);
  91        outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT);
  92
  93        return status;
  94}
  95
  96static inline u8 de600_read_byte(unsigned char type, struct net_device *dev)
  97{
  98        /* dev used by macros */
  99        u8 lo;
 100        outb_p((type), DATA_PORT);
 101        lo = ((unsigned char)inb(STATUS_PORT)) >> 4;
 102        outb_p((type) | HI_NIBBLE, DATA_PORT);
 103        return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo;
 104}
 105
 106/*
 107 * Open/initialize the board.  This is called (in the current kernel)
 108 * after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1).
 109 *
 110 * This routine should set everything up anew at each open, even
 111 * registers that "should" only need to be set once at boot, so that
 112 * there is a non-reboot way to recover if something goes wrong.
 113 */
 114
 115static int de600_open(struct net_device *dev)
 116{
 117        unsigned long flags;
 118        int ret = request_irq(DE600_IRQ, de600_interrupt, 0, dev->name, dev);
 119        if (ret) {
 120                printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, DE600_IRQ);
 121                return ret;
 122        }
 123        spin_lock_irqsave(&de600_lock, flags);
 124        ret = adapter_init(dev);
 125        spin_unlock_irqrestore(&de600_lock, flags);
 126        return ret;
 127}
 128
 129/*
 130 * The inverse routine to de600_open().
 131 */
 132
 133static int de600_close(struct net_device *dev)
 134{
 135        select_nic();
 136        rx_page = 0;
 137        de600_put_command(RESET);
 138        de600_put_command(STOP_RESET);
 139        de600_put_command(0);
 140        select_prn();
 141        free_irq(DE600_IRQ, dev);
 142        return 0;
 143}
 144
 145static inline void trigger_interrupt(struct net_device *dev)
 146{
 147        de600_put_command(FLIP_IRQ);
 148        select_prn();
 149        DE600_SLOW_DOWN;
 150        select_nic();
 151        de600_put_command(0);
 152}
 153
 154/*
 155 * Copy a buffer to the adapter transmit page memory.
 156 * Start sending.
 157 */
 158
 159static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
 160{
 161        unsigned long flags;
 162        int     transmit_from;
 163        int     len;
 164        int     tickssofar;
 165        u8      *buffer = skb->data;
 166        int     i;
 167
 168        if (free_tx_pages <= 0) {       /* Do timeouts, to avoid hangs. */
 169                tickssofar = jiffies - dev->trans_start;
 170                if (tickssofar < 5)
 171                        return NETDEV_TX_BUSY;
 172                /* else */
 173                printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem");
 174                /* Restart the adapter. */
 175                spin_lock_irqsave(&de600_lock, flags);
 176                if (adapter_init(dev)) {
 177                        spin_unlock_irqrestore(&de600_lock, flags);
 178                        return NETDEV_TX_BUSY;
 179                }
 180                spin_unlock_irqrestore(&de600_lock, flags);
 181        }
 182
 183        /* Start real output */
 184        pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages);
 185
 186        if ((len = skb->len) < RUNT)
 187                len = RUNT;
 188
 189        spin_lock_irqsave(&de600_lock, flags);
 190        select_nic();
 191        tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
 192        tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */
 193
 194        if(check_lost)
 195        {
 196                /* This costs about 40 instructions per packet... */
 197                de600_setup_address(NODE_ADDRESS, RW_ADDR);
 198                de600_read_byte(READ_DATA, dev);
 199                if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
 200                        if (adapter_init(dev)) {
 201                                spin_unlock_irqrestore(&de600_lock, flags);
 202                                return NETDEV_TX_BUSY;
 203                        }
 204                }
 205        }
 206
 207        de600_setup_address(transmit_from, RW_ADDR);
 208        for (i = 0;  i < skb->len ; ++i, ++buffer)
 209                de600_put_byte(*buffer);
 210        for (; i < len; ++i)
 211                de600_put_byte(0);
 212
 213        if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
 214                dev->trans_start = jiffies;
 215                netif_start_queue(dev); /* allow more packets into adapter */
 216                /* Send page and generate a faked interrupt */
 217                de600_setup_address(transmit_from, TX_ADDR);
 218                de600_put_command(TX_ENABLE);
 219        }
 220        else {
 221                if (free_tx_pages)
 222                        netif_start_queue(dev);
 223                else
 224                        netif_stop_queue(dev);
 225                select_prn();
 226        }
 227        spin_unlock_irqrestore(&de600_lock, flags);
 228        dev_kfree_skb(skb);
 229        return NETDEV_TX_OK;
 230}
 231
 232/*
 233 * The typical workload of the driver:
 234 * Handle the network interface interrupts.
 235 */
 236
 237static irqreturn_t de600_interrupt(int irq, void *dev_id)
 238{
 239        struct net_device       *dev = dev_id;
 240        u8              irq_status;
 241        int             retrig = 0;
 242        int             boguscount = 0;
 243
 244        spin_lock(&de600_lock);
 245
 246        select_nic();
 247        irq_status = de600_read_status(dev);
 248
 249        do {
 250                pr_debug("de600_interrupt (%02X)\n", irq_status);
 251
 252                if (irq_status & RX_GOOD)
 253                        de600_rx_intr(dev);
 254                else if (!(irq_status & RX_BUSY))
 255                        de600_put_command(RX_ENABLE);
 256
 257                /* Any transmission in progress? */
 258                if (free_tx_pages < TX_PAGES)
 259                        retrig = de600_tx_intr(dev, irq_status);
 260                else
 261                        retrig = 0;
 262
 263                irq_status = de600_read_status(dev);
 264        } while ( (irq_status & RX_GOOD) || ((++boguscount < 100) && retrig) );
 265        /*
 266         * Yeah, it _looks_ like busy waiting, smells like busy waiting
 267         * and I know it's not PC, but please, it will only occur once
 268         * in a while and then only for a loop or so (< 1ms for sure!)
 269         */
 270
 271        /* Enable adapter interrupts */
 272        select_prn();
 273        if (retrig)
 274                trigger_interrupt(dev);
 275        spin_unlock(&de600_lock);
 276        return IRQ_HANDLED;
 277}
 278
 279static int de600_tx_intr(struct net_device *dev, int irq_status)
 280{
 281        /*
 282         * Returns 1 if tx still not done
 283         */
 284
 285        /* Check if current transmission is done yet */
 286        if (irq_status & TX_BUSY)
 287                return 1; /* tx not done, try again */
 288
 289        /* else */
 290        /* If last transmission OK then bump fifo index */
 291        if (!(irq_status & TX_FAILED16)) {
 292                tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES;
 293                ++free_tx_pages;
 294                dev->stats.tx_packets++;
 295                netif_wake_queue(dev);
 296        }
 297
 298        /* More to send, or resend last packet? */
 299        if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) {
 300                dev->trans_start = jiffies;
 301                de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR);
 302                de600_put_command(TX_ENABLE);
 303                return 1;
 304        }
 305        /* else */
 306
 307        return 0;
 308}
 309
 310/*
 311 * We have a good packet, get it out of the adapter.
 312 */
 313static void de600_rx_intr(struct net_device *dev)
 314{
 315        struct sk_buff  *skb;
 316        int             i;
 317        int             read_from;
 318        int             size;
 319        unsigned char   *buffer;
 320
 321        /* Get size of received packet */
 322        size = de600_read_byte(RX_LEN, dev);    /* low byte */
 323        size += (de600_read_byte(RX_LEN, dev) << 8);    /* high byte */
 324        size -= 4;      /* Ignore trailing 4 CRC-bytes */
 325
 326        /* Tell adapter where to store next incoming packet, enable receiver */
 327        read_from = rx_page_adr();
 328        next_rx_page();
 329        de600_put_command(RX_ENABLE);
 330
 331        if ((size < 32)  ||  (size > 1535)) {
 332                printk(KERN_WARNING "%s: Bogus packet size %d.\n", dev->name, size);
 333                if (size > 10000)
 334                        adapter_init(dev);
 335                return;
 336        }
 337
 338        skb = dev_alloc_skb(size+2);
 339        if (skb == NULL) {
 340                printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size);
 341                return;
 342        }
 343        /* else */
 344
 345        skb_reserve(skb,2);     /* Align */
 346
 347        /* 'skb->data' points to the start of sk_buff data area. */
 348        buffer = skb_put(skb,size);
 349
 350        /* copy the packet into the buffer */
 351        de600_setup_address(read_from, RW_ADDR);
 352        for (i = size; i > 0; --i, ++buffer)
 353                *buffer = de600_read_byte(READ_DATA, dev);
 354
 355        skb->protocol=eth_type_trans(skb,dev);
 356
 357        netif_rx(skb);
 358
 359        /* update stats */
 360        dev->stats.rx_packets++; /* count all receives */
 361        dev->stats.rx_bytes += size; /* count all received bytes */
 362
 363        /*
 364         * If any worth-while packets have been received, netif_rx()
 365         * will work on them when we get to the tasklets.
 366         */
 367}
 368
 369static const struct net_device_ops de600_netdev_ops = {
 370        .ndo_open               = de600_open,
 371        .ndo_stop               = de600_close,
 372        .ndo_start_xmit         = de600_start_xmit,
 373        .ndo_change_mtu         = eth_change_mtu,
 374        .ndo_set_mac_address    = eth_mac_addr,
 375        .ndo_validate_addr      = eth_validate_addr,
 376};
 377
 378
 379static struct net_device * __init de600_probe(void)
 380{
 381        int     i;
 382        struct net_device *dev;
 383        int err;
 384
 385        dev = alloc_etherdev(0);
 386        if (!dev)
 387                return ERR_PTR(-ENOMEM);
 388
 389
 390        if (!request_region(DE600_IO, 3, "de600")) {
 391                printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO);
 392                err = -EBUSY;
 393                goto out;
 394        }
 395
 396        printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name);
 397        /* Alpha testers must have the version number to report bugs. */
 398        pr_debug("%s", version);
 399
 400        /* probe for adapter */
 401        err = -ENODEV;
 402        rx_page = 0;
 403        select_nic();
 404        (void)de600_read_status(dev);
 405        de600_put_command(RESET);
 406        de600_put_command(STOP_RESET);
 407        if (de600_read_status(dev) & 0xf0) {
 408                printk(": not at I/O %#3x.\n", DATA_PORT);
 409                goto out1;
 410        }
 411
 412        /*
 413         * Maybe we found one,
 414         * have to check if it is a D-Link DE-600 adapter...
 415         */
 416
 417        /* Get the adapter ethernet address from the ROM */
 418        de600_setup_address(NODE_ADDRESS, RW_ADDR);
 419        for (i = 0; i < ETH_ALEN; i++) {
 420                dev->dev_addr[i] = de600_read_byte(READ_DATA, dev);
 421                dev->broadcast[i] = 0xff;
 422        }
 423
 424        /* Check magic code */
 425        if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) {
 426                /* OK, install real address */
 427                dev->dev_addr[0] = 0x00;
 428                dev->dev_addr[1] = 0x80;
 429                dev->dev_addr[2] = 0xc8;
 430                dev->dev_addr[3] &= 0x0f;
 431                dev->dev_addr[3] |= 0x70;
 432        } else {
 433                printk(" not identified in the printer port\n");
 434                goto out1;
 435        }
 436
 437        printk(", Ethernet Address: %pM\n", dev->dev_addr);
 438
 439        dev->netdev_ops = &de600_netdev_ops;
 440
 441        dev->flags&=~IFF_MULTICAST;
 442
 443        select_prn();
 444
 445        err = register_netdev(dev);
 446        if (err)
 447                goto out1;
 448
 449        return dev;
 450
 451out1:
 452        release_region(DE600_IO, 3);
 453out:
 454        free_netdev(dev);
 455        return ERR_PTR(err);
 456}
 457
 458static int adapter_init(struct net_device *dev)
 459{
 460        int     i;
 461
 462        select_nic();
 463        rx_page = 0; /* used by RESET */
 464        de600_put_command(RESET);
 465        de600_put_command(STOP_RESET);
 466
 467        /* Check if it is still there... */
 468        /* Get the some bytes of the adapter ethernet address from the ROM */
 469        de600_setup_address(NODE_ADDRESS, RW_ADDR);
 470        de600_read_byte(READ_DATA, dev);
 471        if ((de600_read_byte(READ_DATA, dev) != 0xde) ||
 472            (de600_read_byte(READ_DATA, dev) != 0x15)) {
 473        /* was: if (de600_read_status(dev) & 0xf0) { */
 474                printk("Something has happened to the DE-600!  Please check it and do a new ifconfig!\n");
 475                /* Goodbye, cruel world... */
 476                dev->flags &= ~IFF_UP;
 477                de600_close(dev);
 478                was_down = 1;
 479                netif_stop_queue(dev); /* Transmit busy...  */
 480                return 1; /* failed */
 481        }
 482
 483        if (was_down) {
 484                printk(KERN_INFO "%s: Thanks, I feel much better now!\n", dev->name);
 485                was_down = 0;
 486        }
 487
 488        tx_fifo_in = 0;
 489        tx_fifo_out = 0;
 490        free_tx_pages = TX_PAGES;
 491
 492
 493        /* set the ether address. */
 494        de600_setup_address(NODE_ADDRESS, RW_ADDR);
 495        for (i = 0; i < ETH_ALEN; i++)
 496                de600_put_byte(dev->dev_addr[i]);
 497
 498        /* where to start saving incoming packets */
 499        rx_page = RX_BP | RX_BASE_PAGE;
 500        de600_setup_address(MEM_4K, RW_ADDR);
 501        /* Enable receiver */
 502        de600_put_command(RX_ENABLE);
 503        select_prn();
 504
 505        netif_start_queue(dev);
 506
 507        return 0; /* OK */
 508}
 509
 510static struct net_device *de600_dev;
 511
 512static int __init de600_init(void)
 513{
 514        de600_dev = de600_probe();
 515        if (IS_ERR(de600_dev))
 516                return PTR_ERR(de600_dev);
 517        return 0;
 518}
 519
 520static void __exit de600_exit(void)
 521{
 522        unregister_netdev(de600_dev);
 523        release_region(DE600_IO, 3);
 524        free_netdev(de600_dev);
 525}
 526
 527module_init(de600_init);
 528module_exit(de600_exit);
 529
 530MODULE_LICENSE("GPL");
 531