Annotation of Gnu-Mach/linux/src/drivers/net/de620.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.