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

1.1     ! root        1: /* 3c507.c: An EtherLink16 device driver for Linux. */
        !             2: /*
        !             3:        Written 1993,1994 by Donald Becker.
        !             4: 
        !             5:        Copyright 1993 United States Government as represented by the
        !             6:        Director, National Security Agency.
        !             7: 
        !             8:        This software may be used and distributed according to the terms
        !             9:        of the GNU Public License, incorporated herein by reference.
        !            10: 
        !            11:        The author may be reached as [email protected], or C/O
        !            12:        Center of Excellence in Space Data and Information Sciences
        !            13:           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
        !            14: 
        !            15:        Thanks go to [email protected] ( Patrick Jennings)
        !            16:        and [email protected] (Rick Sladkey) for testing and bugfixes.
        !            17:        Mark Salazar <[email protected]> made the changes for cards with
        !            18:        only 16K packet buffers.
        !            19: 
        !            20:        Things remaining to do:
        !            21:        Verify that the tx and rx buffers don't have fencepost errors.
        !            22:        Move the theory of operation and memory map documentation.
        !            23:        The statistics need to be updated correctly.
        !            24: */
        !            25: 
        !            26: static const char *version =
        !            27:        "3c507.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
        !            28: 
        !            29: 
        !            30: #include <linux/module.h>
        !            31: 
        !            32: /*
        !            33:   Sources:
        !            34:        This driver wouldn't have been written with the availability of the
        !            35:        Crynwr driver source code.      It provided a known-working implementation
        !            36:        that filled in the gaping holes of the Intel documentation.  Three cheers
        !            37:        for Russ Nelson.
        !            38: 
        !            39:        Intel Microcommunications Databook, Vol. 1, 1990.  It provides just enough
        !            40:        info that the casual reader might think that it documents the i82586 :-<.
        !            41: */
        !            42: 
        !            43: #include <linux/kernel.h>
        !            44: #include <linux/sched.h>
        !            45: #include <linux/types.h>
        !            46: #include <linux/fcntl.h>
        !            47: #include <linux/interrupt.h>
        !            48: #include <linux/ptrace.h>
        !            49: #include <linux/ioport.h>
        !            50: #include <linux/in.h>
        !            51: #include <linux/string.h>
        !            52: #include <asm/system.h>
        !            53: #include <asm/bitops.h>
        !            54: #include <asm/io.h>
        !            55: #include <asm/dma.h>
        !            56: #include <linux/errno.h>
        !            57: 
        !            58: #include <linux/netdevice.h>
        !            59: #include <linux/etherdevice.h>
        !            60: #include <linux/skbuff.h>
        !            61: #include <linux/malloc.h>
        !            62: 
        !            63: 
        !            64: /* use 0 for production, 1 for verification, 2..7 for debug */
        !            65: #ifndef NET_DEBUG
        !            66: #define NET_DEBUG 1
        !            67: #endif
        !            68: static unsigned int net_debug = NET_DEBUG;
        !            69: 
        !            70: /* A zero-terminated list of common I/O addresses to be probed. */
        !            71: static unsigned int netcard_portlist[] =
        !            72:        { 0x300, 0x320, 0x340, 0x280, 0};
        !            73: 
        !            74: /*
        !            75:                        Details of the i82586.
        !            76: 
        !            77:    You'll really need the databook to understand the details of this part,
        !            78:    but the outline is that the i82586 has two separate processing units.
        !            79:    Both are started from a list of three configuration tables, of which only
        !            80:    the last, the System Control Block (SCB), is used after reset-time.  The SCB
        !            81:    has the following fields:
        !            82:                Status word
        !            83:                Command word
        !            84:                Tx/Command block addr.
        !            85:                Rx block addr.
        !            86:    The command word accepts the following controls for the Tx and Rx units:
        !            87:   */
        !            88: 
        !            89: #define         CUC_START       0x0100
        !            90: #define         CUC_RESUME      0x0200
        !            91: #define         CUC_SUSPEND 0x0300
        !            92: #define         RX_START        0x0010
        !            93: #define         RX_RESUME       0x0020
        !            94: #define         RX_SUSPEND      0x0030
        !            95: 
        !            96: /* The Rx unit uses a list of frame descriptors and a list of data buffer
        !            97:    descriptors.  We use full-sized (1518 byte) data buffers, so there is
        !            98:    a one-to-one pairing of frame descriptors to buffer descriptors.
        !            99: 
        !           100:    The Tx ("command") unit executes a list of commands that look like:
        !           101:                Status word             Written by the 82586 when the command is done.
        !           102:                Command word    Command in lower 3 bits, post-command action in upper 3
        !           103:                Link word               The address of the next command.
        !           104:                Parameters              (as needed).
        !           105: 
        !           106:        Some definitions related to the Command Word are:
        !           107:  */
        !           108: #define CMD_EOL                0x8000                  /* The last command of the list, stop. */
        !           109: #define CMD_SUSP       0x4000                  /* Suspend after doing cmd. */
        !           110: #define CMD_INTR       0x2000                  /* Interrupt after doing cmd. */
        !           111: 
        !           112: enum commands {
        !           113:        CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
        !           114:        CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
        !           115: 
        !           116: /* Information that need to be kept for each board. */
        !           117: struct net_local {
        !           118:        struct enet_statistics stats;
        !           119:        int last_restart;
        !           120:        ushort rx_head;
        !           121:        ushort rx_tail;
        !           122:        ushort tx_head;
        !           123:        ushort tx_cmd_link;
        !           124:        ushort tx_reap;
        !           125: };
        !           126: 
        !           127: /*
        !           128:                Details of the EtherLink16 Implementation
        !           129:   The 3c507 is a generic shared-memory i82586 implementation.
        !           130:   The host can map 16K, 32K, 48K, or 64K of the 64K memory into
        !           131:   0x0[CD][08]0000, or all 64K into 0xF[02468]0000.
        !           132:   */
        !           133: 
        !           134: /* Offsets from the base I/O address. */
        !           135: #define        SA_DATA         0       /* Station address data, or 3Com signature. */
        !           136: #define MISC_CTRL      6       /* Switch the SA_DATA banks, and bus config bits. */
        !           137: #define RESET_IRQ      10      /* Reset the latched IRQ line. */
        !           138: #define SIGNAL_CA      11      /* Frob the 82586 Channel Attention line. */
        !           139: #define ROM_CONFIG     13
        !           140: #define MEM_CONFIG     14
        !           141: #define IRQ_CONFIG     15
        !           142: #define EL16_IO_EXTENT 16
        !           143: 
        !           144: /* The ID port is used at boot-time to locate the ethercard. */
        !           145: #define ID_PORT                0x100
        !           146: 
        !           147: /* Offsets to registers in the mailbox (SCB). */
        !           148: #define iSCB_STATUS    0x8
        !           149: #define iSCB_CMD               0xA
        !           150: #define iSCB_CBL               0xC     /* Command BLock offset. */
        !           151: #define iSCB_RFA               0xE     /* Rx Frame Area offset. */
        !           152: 
        !           153: /*  Since the 3c507 maps the shared memory window so that the last byte is
        !           154:        at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
        !           155:        48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively. 
        !           156:        We can account for this be setting the 'SBC Base' entry in the ISCP table
        !           157:        below for all the 16 bit offset addresses, and also adding the 'SCB Base'
        !           158:        value to all 24 bit physical addresses (in the SCP table and the TX and RX
        !           159:        Buffer Descriptors).
        !           160:                                        -Mark   
        !           161:        */
        !           162: #define SCB_BASE               ((unsigned)64*1024 - (dev->mem_end - dev->mem_start))
        !           163:  
        !           164: /*
        !           165:   What follows in 'init_words[]' is the "program" that is downloaded to the
        !           166:   82586 memory.         It's mostly tables and command blocks, and starts at the
        !           167:   reset address 0xfffff6.  This is designed to be similar to the EtherExpress,
        !           168:   thus the unusual location of the SCB at 0x0008.
        !           169: 
        !           170:   Even with the additional "don't care" values, doing it this way takes less
        !           171:   program space than initializing the individual tables, and I feel it's much
        !           172:   cleaner.
        !           173: 
        !           174:   The databook is particularly useless for the first two structures, I had
        !           175:   to use the Crynwr driver as an example.
        !           176: 
        !           177:    The memory setup is as follows:
        !           178:    */
        !           179: 
        !           180: #define CONFIG_CMD     0x0018
        !           181: #define SET_SA_CMD     0x0024
        !           182: #define SA_OFFSET      0x002A
        !           183: #define IDLELOOP       0x30
        !           184: #define TDR_CMD                0x38
        !           185: #define TDR_TIME       0x3C
        !           186: #define DUMP_CMD       0x40
        !           187: #define DIAG_CMD       0x48
        !           188: #define SET_MC_CMD     0x4E
        !           189: #define DUMP_DATA      0x56    /* A 170 byte buffer for dump and Set-MC into. */
        !           190: 
        !           191: #define TX_BUF_START   0x0100
        !           192: #define NUM_TX_BUFS    4
        !           193: #define TX_BUF_SIZE    (1518+14+20+16) /* packet+header+TBD */
        !           194: 
        !           195: #define RX_BUF_START   0x2000
        !           196: #define RX_BUF_SIZE    (1518+14+18)    /* packet+header+RBD */
        !           197: #define RX_BUF_END             (dev->mem_end - dev->mem_start)
        !           198: 
        !           199: /*
        !           200:   That's it: only 86 bytes to set up the beast, including every extra
        !           201:   command available.  The 170 byte buffer at DUMP_DATA is shared between the
        !           202:   Dump command (called only by the diagnostic program) and the SetMulticastList
        !           203:   command. 
        !           204: 
        !           205:   To complete the memory setup you only have to write the station address at
        !           206:   SA_OFFSET and create the Tx & Rx buffer lists.
        !           207: 
        !           208:   The Tx command chain and buffer list is setup as follows:
        !           209:   A Tx command table, with the data buffer pointing to...
        !           210:   A Tx data buffer descriptor.  The packet is in a single buffer, rather than
        !           211:        chaining together several smaller buffers.
        !           212:   A NoOp command, which initially points to itself,
        !           213:   And the packet data.
        !           214: 
        !           215:   A transmit is done by filling in the Tx command table and data buffer,
        !           216:   re-writing the NoOp command, and finally changing the offset of the last
        !           217:   command to point to the current Tx command.  When the Tx command is finished,
        !           218:   it jumps to the NoOp, when it loops until the next Tx command changes the
        !           219:   "link offset" in the NoOp.  This way the 82586 never has to go through the
        !           220:   slow restart sequence.
        !           221: 
        !           222:   The Rx buffer list is set up in the obvious ring structure.  We have enough
        !           223:   memory (and low enough interrupt latency) that we can avoid the complicated
        !           224:   Rx buffer linked lists by alway associating a full-size Rx data buffer with
        !           225:   each Rx data frame.
        !           226: 
        !           227:   I current use four transmit buffers starting at TX_BUF_START (0x0100), and
        !           228:   use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers.
        !           229: 
        !           230:   */
        !           231: 
        !           232: unsigned short init_words[] = {
        !           233:        /*      System Configuration Pointer (SCP). */
        !           234:        0x0000,                                 /* Set bus size to 16 bits. */
        !           235:        0,0,                                    /* pad words. */
        !           236:        0x0000,0x0000,                  /* ISCP phys addr, set in init_82586_mem(). */
        !           237: 
        !           238:        /*      Intermediate System Configuration Pointer (ISCP). */
        !           239:        0x0001,                                 /* Status word that's cleared when init is done. */
        !           240:        0x0008,0,0,                             /* SCB offset, (skip, skip) */
        !           241: 
        !           242:        /* System Control Block (SCB). */
        !           243:        0,0xf000|RX_START|CUC_START,    /* SCB status and cmd. */
        !           244:        CONFIG_CMD,                             /* Command list pointer, points to Configure. */
        !           245:        RX_BUF_START,                           /* Rx block list. */
        !           246:        0,0,0,0,                                /* Error count: CRC, align, buffer, overrun. */
        !           247: 
        !           248:        /* 0x0018: Configure command.  Change to put MAC data with packet. */
        !           249:        0, CmdConfigure,                /* Status, command.             */
        !           250:        SET_SA_CMD,                             /* Next command is Set Station Addr. */
        !           251:        0x0804,                                 /* "4" bytes of config data, 8 byte FIFO. */
        !           252:        0x2e40,                                 /* Magic values, including MAC data location. */
        !           253:        0,                                              /* Unused pad word. */
        !           254: 
        !           255:        /* 0x0024: Setup station address command. */
        !           256:        0, CmdSASetup,
        !           257:        SET_MC_CMD,                             /* Next command. */
        !           258:        0xaa00,0xb000,0x0bad,   /* Station address (to be filled in) */
        !           259: 
        !           260:        /* 0x0030: NOP, looping back to itself.  Point to first Tx buffer to Tx. */
        !           261:        0, CmdNOp, IDLELOOP, 0 /* pad */,
        !           262: 
        !           263:        /* 0x0038: A unused Time-Domain Reflectometer command. */
        !           264:        0, CmdTDR, IDLELOOP, 0,
        !           265: 
        !           266:        /* 0x0040: An unused Dump State command. */
        !           267:        0, CmdDump, IDLELOOP, DUMP_DATA,
        !           268: 
        !           269:        /* 0x0048: An unused Diagnose command. */
        !           270:        0, CmdDiagnose, IDLELOOP,
        !           271: 
        !           272:        /* 0x004E: An empty set-multicast-list command. */
        !           273:        0, CmdMulticastList, IDLELOOP, 0,
        !           274: };
        !           275: 
        !           276: /* Index to functions, as function prototypes. */
        !           277: 
        !           278: extern int el16_probe(struct device *dev);     /* Called from Space.c */
        !           279: 
        !           280: static int     el16_probe1(struct device *dev, int ioaddr);
        !           281: static int     el16_open(struct device *dev);
        !           282: static int     el16_send_packet(struct sk_buff *skb, struct device *dev);
        !           283: static void    el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           284: static void el16_rx(struct device *dev);
        !           285: static int     el16_close(struct device *dev);
        !           286: static struct enet_statistics *el16_get_stats(struct device *dev);
        !           287: 
        !           288: static void hardware_send_packet(struct device *dev, void *buf, short length);
        !           289: void init_82586_mem(struct device *dev);
        !           290: 
        !           291: 
        !           292: #ifdef HAVE_DEVLIST
        !           293: struct netdev_entry netcard_drv =
        !           294: {"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist};
        !           295: #endif
        !           296: 
        !           297: /* Check for a network adaptor of this type, and return '0' iff one exists.
        !           298:        If dev->base_addr == 0, probe all likely locations.
        !           299:        If dev->base_addr == 1, always return failure.
        !           300:        If dev->base_addr == 2, (detachable devices only) allocate space for the
        !           301:        device and return success.
        !           302:        */
        !           303: int
        !           304: el16_probe(struct device *dev)
        !           305: {
        !           306:        int base_addr = dev ? dev->base_addr : 0;
        !           307:        int i;
        !           308: 
        !           309:        if (base_addr > 0x1ff)  /* Check a single specified location. */
        !           310:                return el16_probe1(dev, base_addr);
        !           311:        else if (base_addr != 0)
        !           312:                return ENXIO;           /* Don't probe at all. */
        !           313: 
        !           314:        for (i = 0; netcard_portlist[i]; i++) {
        !           315:                int ioaddr = netcard_portlist[i];
        !           316:                if (check_region(ioaddr, EL16_IO_EXTENT))
        !           317:                        continue;
        !           318:                if (el16_probe1(dev, ioaddr) == 0)
        !           319:                        return 0;
        !           320:        }
        !           321: 
        !           322:        return ENODEV;
        !           323: }
        !           324: 
        !           325: int el16_probe1(struct device *dev, int ioaddr)
        !           326: {
        !           327:        static unsigned char init_ID_done = 0, version_printed = 0;
        !           328:        int i, irq, irqval;
        !           329: 
        !           330:        if (init_ID_done == 0) {
        !           331:                ushort lrs_state = 0xff;
        !           332:                /* Send the ID sequence to the ID_PORT to enable the board(s). */
        !           333:                outb(0x00, ID_PORT);
        !           334:                for(i = 0; i < 255; i++) {
        !           335:                        outb(lrs_state, ID_PORT);
        !           336:                        lrs_state <<= 1;
        !           337:                        if (lrs_state & 0x100)
        !           338:                                lrs_state ^= 0xe7;
        !           339:                }
        !           340:                outb(0x00, ID_PORT);
        !           341:                init_ID_done = 1;
        !           342:        }
        !           343: 
        !           344:        if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3'
        !           345:                && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O')
        !           346:                ;
        !           347:        else
        !           348:                return ENODEV;
        !           349: 
        !           350:        /* Allocate a new 'dev' if needed. */
        !           351:        if (dev == NULL)
        !           352:                dev = init_etherdev(0, sizeof(struct net_local));
        !           353: 
        !           354:        if (net_debug  &&  version_printed++ == 0)
        !           355:                printk(version);
        !           356: 
        !           357:        printk("%s: 3c507 at %#x,", dev->name, ioaddr);
        !           358: 
        !           359:        /* We should make a few more checks here, like the first three octets of
        !           360:           the S.A. for the manufacturer's code. */ 
        !           361: 
        !           362:        irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
        !           363: 
        !           364:        irqval = request_irq(irq, &el16_interrupt, 0, "3c507", NULL);
        !           365:        if (irqval) {
        !           366:                printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
        !           367:                return EAGAIN;
        !           368:        }
        !           369:        
        !           370:        /* We've committed to using the board, and can start filling in *dev. */
        !           371:        request_region(ioaddr, EL16_IO_EXTENT, "3c507");
        !           372:        dev->base_addr = ioaddr;
        !           373: 
        !           374:        outb(0x01, ioaddr + MISC_CTRL);
        !           375:        for (i = 0; i < 6; i++) {
        !           376:                dev->dev_addr[i] = inb(ioaddr + i);
        !           377:                printk(" %02x", dev->dev_addr[i]);
        !           378:        }
        !           379: 
        !           380:        if ((dev->mem_start & 0xf) > 0)
        !           381:                net_debug = dev->mem_start & 7;
        !           382: 
        !           383: #ifdef MEM_BASE
        !           384:        dev->mem_start = MEM_BASE;
        !           385:        dev->mem_end = dev->mem_start + 0x10000;
        !           386: #else
        !           387:        {
        !           388:                int base;
        !           389:                int size;
        !           390:                char mem_config = inb(ioaddr + MEM_CONFIG);
        !           391:                if (mem_config & 0x20) {
        !           392:                        size = 64*1024;
        !           393:                        base = 0xf00000 + (mem_config & 0x08 ? 0x080000
        !           394:                                                           : ((mem_config & 3) << 17));
        !           395:                } else {
        !           396:                        size = ((mem_config & 3) + 1) << 14;
        !           397:                        base = 0x0c0000 + ( (mem_config & 0x18) << 12);
        !           398:                }
        !           399:                dev->mem_start = base;
        !           400:                dev->mem_end = base + size;
        !           401:        }
        !           402: #endif
        !           403: 
        !           404:        dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0;
        !           405:        dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
        !           406: 
        !           407:        printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq,
        !           408:                   dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1);
        !           409: 
        !           410:        if (net_debug)
        !           411:                printk(version);
        !           412: 
        !           413:        /* Initialize the device structure. */
        !           414:        dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        !           415:        if (dev->priv == NULL)
        !           416:                return -ENOMEM;
        !           417:        memset(dev->priv, 0, sizeof(struct net_local));
        !           418: 
        !           419:        dev->open               = el16_open;
        !           420:        dev->stop               = el16_close;
        !           421:        dev->hard_start_xmit = el16_send_packet;
        !           422:        dev->get_stats  = el16_get_stats;
        !           423: 
        !           424:        ether_setup(dev);       /* Generic ethernet behaviour */
        !           425:        
        !           426:        dev->flags&=~IFF_MULTICAST;     /* Multicast doesn't work */
        !           427: 
        !           428:        return 0;
        !           429: }
        !           430: 
        !           431: 
        !           432: 
        !           433: static int
        !           434: el16_open(struct device *dev)
        !           435: {
        !           436:        irq2dev_map[dev->irq] = dev;
        !           437: 
        !           438:        /* Initialize the 82586 memory and start it. */
        !           439:        init_82586_mem(dev);
        !           440: 
        !           441:        dev->tbusy = 0;
        !           442:        dev->interrupt = 0;
        !           443:        dev->start = 1;
        !           444: 
        !           445:        MOD_INC_USE_COUNT;
        !           446: 
        !           447:        return 0;
        !           448: }
        !           449: 
        !           450: static int
        !           451: el16_send_packet(struct sk_buff *skb, struct device *dev)
        !           452: {
        !           453:        struct net_local *lp = (struct net_local *)dev->priv;
        !           454:        int ioaddr = dev->base_addr;
        !           455:        short *shmem = (short*)dev->mem_start;
        !           456: 
        !           457:        if (dev->tbusy) {
        !           458:                /* If we get here, some higher level has decided we are broken.
        !           459:                   There should really be a "kick me" function call instead. */
        !           460:                int tickssofar = jiffies - dev->trans_start;
        !           461:                if (tickssofar < 5)
        !           462:                        return 1;
        !           463:                if (net_debug > 1)
        !           464:                        printk("%s: transmit timed out, %s?  ", dev->name,
        !           465:                                   shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" :
        !           466:                                   "network cable problem");
        !           467:                /* Try to restart the adaptor. */
        !           468:                if (lp->last_restart == lp->stats.tx_packets) {
        !           469:                        if (net_debug > 1) printk("Resetting board.\n");
        !           470:                        /* Completely reset the adaptor. */
        !           471:                        init_82586_mem(dev);
        !           472:                } else {
        !           473:                        /* Issue the channel attention signal and hope it "gets better". */
        !           474:                        if (net_debug > 1) printk("Kicking board.\n");
        !           475:                        shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START;
        !           476:                        outb(0, ioaddr + SIGNAL_CA);                    /* Issue channel-attn. */
        !           477:                        lp->last_restart = lp->stats.tx_packets;
        !           478:                }
        !           479:                dev->tbusy=0;
        !           480:                dev->trans_start = jiffies;
        !           481:        }
        !           482: 
        !           483:        /* If some higher layer thinks we've missed an tx-done interrupt
        !           484:           we are passed NULL. Caution: dev_tint() handles the cli()/sti()
        !           485:           itself. */
        !           486:        if (skb == NULL) {
        !           487:                dev_tint(dev);
        !           488:                return 0;
        !           489:        }
        !           490: 
        !           491:        /* Block a timer-based transmit from overlapping. */
        !           492:        if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           493:                printk("%s: Transmitter access conflict.\n", dev->name);
        !           494:        else {
        !           495:                short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        !           496:                unsigned char *buf = skb->data;
        !           497: 
        !           498:                /* Disable the 82586's input to the interrupt line. */
        !           499:                outb(0x80, ioaddr + MISC_CTRL);
        !           500:                hardware_send_packet(dev, buf, length);
        !           501:                dev->trans_start = jiffies;
        !           502:                /* Enable the 82586 interrupt input. */
        !           503:                outb(0x84, ioaddr + MISC_CTRL);
        !           504:        }
        !           505: 
        !           506:        dev_kfree_skb (skb, FREE_WRITE);
        !           507: 
        !           508:        /* You might need to clean up and record Tx statistics here. */
        !           509: 
        !           510:        return 0;
        !           511: }
        !           512: 
        !           513: /*     The typical workload of the driver:
        !           514:        Handle the network interface interrupts. */
        !           515: static void
        !           516: el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        !           517: {
        !           518:        struct device *dev = (struct device *)(irq2dev_map[irq]);
        !           519:        struct net_local *lp;
        !           520:        int ioaddr, status, boguscount = 0;
        !           521:        ushort ack_cmd = 0;
        !           522:        ushort *shmem;
        !           523:        
        !           524:        if (dev == NULL) {
        !           525:                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
        !           526:                return;
        !           527:        }
        !           528:        dev->interrupt = 1;
        !           529:        
        !           530:        ioaddr = dev->base_addr;
        !           531:        lp = (struct net_local *)dev->priv;
        !           532:        shmem = ((ushort*)dev->mem_start);
        !           533:        
        !           534:        status = shmem[iSCB_STATUS>>1];
        !           535:        
        !           536:        if (net_debug > 4) {
        !           537:                printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status);
        !           538:        }
        !           539: 
        !           540:        /* Disable the 82586's input to the interrupt line. */
        !           541:        outb(0x80, ioaddr + MISC_CTRL);
        !           542: 
        !           543:        /* Reap the Tx packet buffers. */
        !           544:        while (lp->tx_reap != lp->tx_head) {
        !           545:          unsigned short tx_status = shmem[lp->tx_reap>>1];
        !           546: 
        !           547:          if (tx_status == 0) {
        !           548:                if (net_debug > 5)  printk("Couldn't reap %#x.\n", lp->tx_reap);
        !           549:                break;
        !           550:          }
        !           551:          if (tx_status & 0x2000) {
        !           552:                lp->stats.tx_packets++;
        !           553:                lp->stats.collisions += tx_status & 0xf;
        !           554:                dev->tbusy = 0;
        !           555:                mark_bh(NET_BH);                /* Inform upper layers. */
        !           556:          } else {
        !           557:                lp->stats.tx_errors++;
        !           558:                if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
        !           559:                if (tx_status & 0x0100)  lp->stats.tx_fifo_errors++;
        !           560:                if (!(tx_status & 0x0040))  lp->stats.tx_heartbeat_errors++;
        !           561:                if (tx_status & 0x0020)  lp->stats.tx_aborted_errors++;
        !           562:          }
        !           563:          if (net_debug > 5)
        !           564:                  printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status);
        !           565:          lp->tx_reap += TX_BUF_SIZE;
        !           566:          if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE)
        !           567:                lp->tx_reap = TX_BUF_START;
        !           568:          if (++boguscount > 4)
        !           569:                break;
        !           570:        }
        !           571: 
        !           572:        if (status & 0x4000) { /* Packet received. */
        !           573:                if (net_debug > 5)
        !           574:                        printk("Received packet, rx_head %04x.\n", lp->rx_head);
        !           575:                el16_rx(dev);
        !           576:        }
        !           577: 
        !           578:        /* Acknowledge the interrupt sources. */
        !           579:        ack_cmd = status & 0xf000;
        !           580: 
        !           581:        if ((status & 0x0700) != 0x0200 && dev->start) {
        !           582:                if (net_debug)
        !           583:                        printk("%s: Command unit stopped, status %04x, restarting.\n",
        !           584:                                   dev->name, status);
        !           585:                /* If this ever occurs we should really re-write the idle loop, reset
        !           586:                   the Tx list, and do a complete restart of the command unit.
        !           587:                   For now we rely on the Tx timeout if the resume doesn't work. */
        !           588:                ack_cmd |= CUC_RESUME;
        !           589:        }
        !           590: 
        !           591:        if ((status & 0x0070) != 0x0040  &&  dev->start) {
        !           592:          static void init_rx_bufs(struct device *);
        !           593:                /* The Rx unit is not ready, it must be hung.  Restart the receiver by
        !           594:                   initializing the rx buffers, and issuing an Rx start command. */
        !           595:                if (net_debug)
        !           596:                        printk("%s: Rx unit stopped, status %04x, restarting.\n",
        !           597:                                   dev->name, status);
        !           598:                init_rx_bufs(dev);
        !           599:                shmem[iSCB_RFA >> 1] = RX_BUF_START;
        !           600:                ack_cmd |= RX_START;
        !           601:        }
        !           602: 
        !           603:        shmem[iSCB_CMD>>1] = ack_cmd;
        !           604:        outb(0, ioaddr + SIGNAL_CA);                    /* Issue channel-attn. */
        !           605: 
        !           606:        /* Clear the latched interrupt. */
        !           607:        outb(0, ioaddr + RESET_IRQ);
        !           608: 
        !           609:        /* Enable the 82586's interrupt input. */
        !           610:        outb(0x84, ioaddr + MISC_CTRL);
        !           611: 
        !           612:        return;
        !           613: }
        !           614: 
        !           615: static int
        !           616: el16_close(struct device *dev)
        !           617: {
        !           618:        int ioaddr = dev->base_addr;
        !           619:        ushort *shmem = (short*)dev->mem_start;
        !           620: 
        !           621:        dev->tbusy = 1;
        !           622:        dev->start = 0;
        !           623: 
        !           624:        /* Flush the Tx and disable Rx. */
        !           625:        shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND;
        !           626:        outb(0, ioaddr + SIGNAL_CA);
        !           627: 
        !           628:        /* Disable the 82586's input to the interrupt line. */
        !           629:        outb(0x80, ioaddr + MISC_CTRL);
        !           630: 
        !           631:        /* We always physically use the IRQ line, so we don't do free_irq().
        !           632:           We do remove ourselves from the map. */
        !           633: 
        !           634:        irq2dev_map[dev->irq] = 0;
        !           635: 
        !           636:        /* Update the statistics here. */
        !           637: 
        !           638:        MOD_DEC_USE_COUNT;
        !           639: 
        !           640:        return 0;
        !           641: }
        !           642: 
        !           643: /* Get the current statistics. This may be called with the card open or
        !           644:    closed. */
        !           645: static struct enet_statistics *
        !           646: el16_get_stats(struct device *dev)
        !           647: {
        !           648:        struct net_local *lp = (struct net_local *)dev->priv;
        !           649: 
        !           650:        /* ToDo: decide if there are any useful statistics from the SCB. */
        !           651: 
        !           652:        return &lp->stats;
        !           653: }
        !           654: 
        !           655: /* Initialize the Rx-block list. */
        !           656: static void
        !           657: init_rx_bufs(struct device *dev)
        !           658: {
        !           659:        struct net_local *lp = (struct net_local *)dev->priv;
        !           660:        unsigned short *write_ptr;
        !           661:        unsigned short SCB_base = SCB_BASE;
        !           662: 
        !           663:        int cur_rxbuf = lp->rx_head = RX_BUF_START;
        !           664:        
        !           665:        /* Initialize each Rx frame + data buffer. */
        !           666:        do {    /* While there is room for one more. */
        !           667: 
        !           668:          write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf);
        !           669: 
        !           670:                *write_ptr++ = 0x0000;                          /* Status */
        !           671:                *write_ptr++ = 0x0000;                          /* Command */
        !           672:                *write_ptr++ = cur_rxbuf + RX_BUF_SIZE; /* Link */
        !           673:                *write_ptr++ = cur_rxbuf + 22;          /* Buffer offset */
        !           674:                *write_ptr++ = 0x0000;                          /* Pad for dest addr. */
        !           675:                *write_ptr++ = 0x0000;
        !           676:                *write_ptr++ = 0x0000;
        !           677:                *write_ptr++ = 0x0000;                          /* Pad for source addr. */
        !           678:                *write_ptr++ = 0x0000;
        !           679:                *write_ptr++ = 0x0000;
        !           680:                *write_ptr++ = 0x0000;                          /* Pad for protocol. */
        !           681:                
        !           682:                *write_ptr++ = 0x0000;                          /* Buffer: Actual count */
        !           683:                *write_ptr++ = -1;                                      /* Buffer: Next (none). */
        !           684:                *write_ptr++ = cur_rxbuf + 0x20 + SCB_base;     /* Buffer: Address low */
        !           685:                *write_ptr++ = 0x0000;
        !           686:                /* Finally, the number of bytes in the buffer. */
        !           687:                *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20;
        !           688:                
        !           689:                lp->rx_tail = cur_rxbuf;
        !           690:                cur_rxbuf += RX_BUF_SIZE;
        !           691:        } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE);
        !           692:        
        !           693:        /* Terminate the list by setting the EOL bit, and wrap the pointer to make
        !           694:           the list a ring. */
        !           695:        write_ptr = (unsigned short *)
        !           696:          (dev->mem_start + lp->rx_tail + 2);
        !           697:        *write_ptr++ = 0xC000;                                  /* Command, mark as last. */
        !           698:        *write_ptr++ = lp->rx_head;                             /* Link */
        !           699: 
        !           700: }
        !           701: 
        !           702: void
        !           703: init_82586_mem(struct device *dev)
        !           704: {
        !           705:        struct net_local *lp = (struct net_local *)dev->priv;
        !           706:        short ioaddr = dev->base_addr;
        !           707:        ushort *shmem = (short*)dev->mem_start;
        !           708: 
        !           709:        /* Enable loopback to protect the wire while starting up,
        !           710:           and hold the 586 in reset during the memory initialization. */
        !           711:        outb(0x20, ioaddr + MISC_CTRL);
        !           712: 
        !           713:        /* Fix the ISCP address and base. */
        !           714:        init_words[3] = SCB_BASE;
        !           715:        init_words[7] = SCB_BASE;
        !           716: 
        !           717:        /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */
        !           718:        memcpy((void*)dev->mem_end-10, init_words, 10);
        !           719: 
        !           720:        /* Write the words at 0x0000. */
        !           721:        memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10);
        !           722: 
        !           723:        /* Fill in the station address. */
        !           724:        memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr,
        !           725:                   sizeof(dev->dev_addr));
        !           726: 
        !           727:        /* The Tx-block list is written as needed.  We just set up the values. */
        !           728:        lp->tx_cmd_link = IDLELOOP + 4;
        !           729:        lp->tx_head = lp->tx_reap = TX_BUF_START;
        !           730: 
        !           731:        init_rx_bufs(dev);
        !           732: 
        !           733:        /* Start the 586 by releasing the reset line, but leave loopback. */
        !           734:        outb(0xA0, ioaddr + MISC_CTRL);
        !           735: 
        !           736:        /* This was time consuming to track down: you need to give two channel
        !           737:           attention signals to reliably start up the i82586. */
        !           738:        outb(0, ioaddr + SIGNAL_CA);
        !           739: 
        !           740:        {
        !           741:                int boguscnt = 50;
        !           742:                while (shmem[iSCB_STATUS>>1] == 0)
        !           743:                        if (--boguscnt == 0) {
        !           744:                                printk("%s: i82586 initialization timed out with status %04x,"
        !           745:                                           "cmd %04x.\n", dev->name,
        !           746:                                           shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
        !           747:                                break;
        !           748:                        }
        !           749:                /* Issue channel-attn -- the 82586 won't start. */
        !           750:                outb(0, ioaddr + SIGNAL_CA);
        !           751:        }
        !           752: 
        !           753:        /* Disable loopback and enable interrupts. */
        !           754:        outb(0x84, ioaddr + MISC_CTRL);
        !           755:        if (net_debug > 4)
        !           756:                printk("%s: Initialized 82586, status %04x.\n", dev->name,
        !           757:                           shmem[iSCB_STATUS>>1]);
        !           758:        return;
        !           759: }
        !           760: 
        !           761: static void
        !           762: hardware_send_packet(struct device *dev, void *buf, short length)
        !           763: {
        !           764:        struct net_local *lp = (struct net_local *)dev->priv;
        !           765:        short ioaddr = dev->base_addr;
        !           766:        ushort tx_block = lp->tx_head;
        !           767:        ushort *write_ptr =       (ushort *)(dev->mem_start + tx_block);
        !           768: 
        !           769:        /* Set the write pointer to the Tx block, and put out the header. */
        !           770:        *write_ptr++ = 0x0000;                          /* Tx status */
        !           771:        *write_ptr++ = CMD_INTR|CmdTx;          /* Tx command */
        !           772:        *write_ptr++ = tx_block+16;                     /* Next command is a NoOp. */
        !           773:        *write_ptr++ = tx_block+8;                      /* Data Buffer offset. */
        !           774: 
        !           775:        /* Output the data buffer descriptor. */
        !           776:        *write_ptr++ = length | 0x8000;         /* Byte count parameter. */
        !           777:        *write_ptr++ = -1;                                      /* No next data buffer. */
        !           778:        *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */
        !           779:        *write_ptr++ = 0x0000;                          /* Buffer address high bits (always zero). */
        !           780: 
        !           781:        /* Output the Loop-back NoOp command. */
        !           782:        *write_ptr++ = 0x0000;                          /* Tx status */
        !           783:        *write_ptr++ = CmdNOp;                          /* Tx command */
        !           784:        *write_ptr++ = tx_block+16;                     /* Next is myself. */
        !           785: 
        !           786:        /* Output the packet at the write pointer. */
        !           787:        memcpy(write_ptr, buf, length);
        !           788: 
        !           789:        /* Set the old command link pointing to this send packet. */
        !           790:        *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block;
        !           791:        lp->tx_cmd_link = tx_block + 20;
        !           792: 
        !           793:        /* Set the next free tx region. */
        !           794:        lp->tx_head = tx_block + TX_BUF_SIZE;
        !           795:        if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE)
        !           796:                lp->tx_head = TX_BUF_START;
        !           797: 
        !           798:        if (net_debug > 4) {
        !           799:                printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n",
        !           800:                           dev->name, ioaddr, length, tx_block, lp->tx_head);
        !           801:        }
        !           802: 
        !           803:        if (lp->tx_head != lp->tx_reap)
        !           804:                dev->tbusy = 0;
        !           805: }
        !           806: 
        !           807: static void
        !           808: el16_rx(struct device *dev)
        !           809: {
        !           810:        struct net_local *lp = (struct net_local *)dev->priv;
        !           811:        short *shmem = (short*)dev->mem_start;
        !           812:        ushort rx_head = lp->rx_head;
        !           813:        ushort rx_tail = lp->rx_tail;
        !           814:        ushort boguscount = 10;
        !           815:        short frame_status;
        !           816: 
        !           817:        while ((frame_status = shmem[rx_head>>1]) < 0) {   /* Command complete */
        !           818:                ushort *read_frame =  (short *)(dev->mem_start + rx_head);
        !           819:                ushort rfd_cmd = read_frame[1];
        !           820:                ushort next_rx_frame = read_frame[2];
        !           821:                ushort data_buffer_addr = read_frame[3];
        !           822:                ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr);
        !           823:                ushort pkt_len = data_frame[0];
        !           824: 
        !           825:                if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
        !           826:                        || (pkt_len & 0xC000) != 0xC000) {
        !           827:                        printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x"
        !           828:                                   "next %04x data-buf @%04x %04x.\n", dev->name, rx_head,
        !           829:                                   frame_status, rfd_cmd, next_rx_frame, data_buffer_addr,
        !           830:                                   pkt_len);
        !           831:                } else if ((frame_status & 0x2000) == 0) {
        !           832:                        /* Frame Rxed, but with error. */
        !           833:                        lp->stats.rx_errors++;
        !           834:                        if (frame_status & 0x0800) lp->stats.rx_crc_errors++;
        !           835:                        if (frame_status & 0x0400) lp->stats.rx_frame_errors++;
        !           836:                        if (frame_status & 0x0200) lp->stats.rx_fifo_errors++;
        !           837:                        if (frame_status & 0x0100) lp->stats.rx_over_errors++;
        !           838:                        if (frame_status & 0x0080) lp->stats.rx_length_errors++;
        !           839:                } else {
        !           840:                        /* Malloc up new buffer. */
        !           841:                        struct sk_buff *skb;
        !           842: 
        !           843:                        pkt_len &= 0x3fff;
        !           844:                        skb = dev_alloc_skb(pkt_len+2);
        !           845:                        if (skb == NULL) {
        !           846:                                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
        !           847:                                lp->stats.rx_dropped++;
        !           848:                                break;
        !           849:                        }
        !           850:                        
        !           851:                        skb_reserve(skb,2);
        !           852:                        skb->dev = dev;
        !           853: 
        !           854:                        /* 'skb->data' points to the start of sk_buff data area. */
        !           855:                        memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len);
        !           856:                
        !           857:                        skb->protocol=eth_type_trans(skb,dev);
        !           858:                        netif_rx(skb);
        !           859:                        lp->stats.rx_packets++;
        !           860:                }
        !           861: 
        !           862:                /* Clear the status word and set End-of-List on the rx frame. */
        !           863:                read_frame[0] = 0;
        !           864:                read_frame[1] = 0xC000;
        !           865:                /* Clear the end-of-list on the prev. RFD. */
        !           866:                *(short*)(dev->mem_start + rx_tail + 2) = 0x0000;
        !           867: 
        !           868:                rx_tail = rx_head;
        !           869:                rx_head = next_rx_frame;
        !           870:                if (--boguscount == 0)
        !           871:                        break;
        !           872:        }
        !           873: 
        !           874:        lp->rx_head = rx_head;
        !           875:        lp->rx_tail = rx_tail;
        !           876: }
        !           877: #ifdef MODULE
        !           878: static char devicename[9] = { 0, };
        !           879: static struct device dev_3c507 = {
        !           880:        devicename, /* device name is inserted by linux/drivers/net/net_init.c */
        !           881:        0, 0, 0, 0,
        !           882:        0, 0,
        !           883:        0, 0, 0, NULL, el16_probe
        !           884: };
        !           885: 
        !           886: static int io = 0x300;
        !           887: static int irq = 0;
        !           888: 
        !           889: int init_module(void)
        !           890: {
        !           891:        if (io == 0)
        !           892:                printk("3c507: You should not use auto-probing with insmod!\n");
        !           893:        dev_3c507.base_addr = io;
        !           894:        dev_3c507.irq       = irq;
        !           895:        if (register_netdev(&dev_3c507) != 0) {
        !           896:                printk("3c507: register_netdev() returned non-zero.\n");
        !           897:                return -EIO;
        !           898:        }
        !           899:        return 0;
        !           900: }
        !           901: 
        !           902: void
        !           903: cleanup_module(void)
        !           904: {
        !           905:        unregister_netdev(&dev_3c507);
        !           906:        kfree(dev_3c507.priv);
        !           907:        dev_3c507.priv = NULL;
        !           908: 
        !           909:        /* If we don't do this, we can't re-insmod it later. */
        !           910:        free_irq(dev_3c507.irq, NULL);
        !           911:        release_region(dev_3c507.base_addr, EL16_IO_EXTENT);
        !           912: }
        !           913: #endif /* MODULE */
        !           914: 
        !           915: /*
        !           916:  * Local variables:
        !           917:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c"
        !           918:  *  version-control: t
        !           919:  *  kept-new-versions: 5
        !           920:  *  tab-width: 4
        !           921:  *  c-indent-level: 4
        !           922:  * End:
        !           923:  */

unix.superglobalmegacorp.com

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