Annotation of Gnu-Mach/linux/src/drivers/net/e2100.c, revision 1.1.1.2

1.1       root        1: /* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
                      2: /*
                      3:        Written 1993-1994 by Donald Becker.
                      4: 
                      5:        Copyright 1994 by Donald Becker.
                      6:        Copyright 1993 United States Government as represented by the
                      7:        Director, National Security Agency.  This software may be used and
                      8:        distributed according to the terms of the GNU Public License,
                      9:        incorporated herein by reference.
                     10: 
                     11:        This is a driver for the Cabletron E2100 series ethercards.
                     12: 
                     13:        The Author may be reached as [email protected], or
                     14:        C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
                     15: 
                     16:        The E2100 series ethercard is a fairly generic shared memory 8390
                     17:        implementation.  The only unusual aspect is the way the shared memory
                     18:        registers are set: first you do an inb() in what is normally the
                     19:        station address region, and the low three bits of next outb() *address*
                     20:        is used as the write value for that register.  Either someone wasn't
                     21:        too used to dem bit en bites, or they were trying to obfuscate the
                     22:        programming interface.
                     23: 
                     24:        There is an additional complication when setting the window on the packet
                     25:        buffer.  You must first do a read into the packet buffer region with the
                     26:        low 8 address bits the address setting the page for the start of the packet
                     27:        buffer window, and then do the above operation.  See mem_on() for details.
                     28: 
                     29:        One bug on the chip is that even a hard reset won't disable the memory
                     30:        window, usually resulting in a hung machine if mem_off() isn't called.
                     31:        If this happens, you must power down the machine for about 30 seconds.
                     32: */
                     33: 
                     34: static const char *version =
                     35:        "e2100.c:v1.01 7/21/94 Donald Becker ([email protected])\n";
                     36: 
                     37: #include <linux/module.h>
                     38: 
                     39: #include <linux/kernel.h>
                     40: #include <linux/sched.h>
                     41: #include <linux/errno.h>
                     42: #include <linux/string.h>
                     43: #include <linux/ioport.h>
                     44: #include <linux/netdevice.h>
                     45: #include <linux/etherdevice.h>
                     46: 
                     47: #include <asm/io.h>
                     48: #include <asm/system.h>
                     49: 
                     50: #include "8390.h"
                     51: 
                     52: static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
                     53: 
                     54: /* Offsets from the base_addr.
                     55:    Read from the ASIC register, and the low three bits of the next outb()
                     56:    address is used to set the corresponding register. */
                     57: #define E21_NIC_OFFSET  0              /* Offset to the 8390 NIC. */
                     58: #define E21_ASIC               0x10
                     59: #define E21_MEM_ENABLE 0x10
                     60: #define  E21_MEM_ON            0x05    /* Enable memory in 16 bit mode. */
                     61: #define  E21_MEM_ON_8  0x07    /* Enable memory in  8 bit mode. */
                     62: #define E21_MEM_BASE   0x11    
                     63: #define E21_IRQ_LOW            0x12    /* The low three bits of the IRQ number. */
                     64: #define E21_IRQ_HIGH   0x14    /* The high IRQ bit and media select ...  */
                     65: #define E21_MEDIA              0x14    /* (alias). */
                     66: #define  E21_ALT_IFPORT 0x02   /* Set to use the other (BNC,AUI) port. */
                     67: #define  E21_BIG_MEM   0x04    /* Use a bigger (64K) buffer (we don't) */
                     68: #define E21_SAPROM             0x10    /* Offset to station address data. */
                     69: #define E21_IO_EXTENT   0x20
                     70: 
                     71: extern inline void mem_on(short port, volatile char *mem_base,
                     72:                                                  unsigned char start_page )
                     73: {
                     74:        /* This is a little weird: set the shared memory window by doing a
                     75:           read.  The low address bits specify the starting page. */
                     76:        mem_base[start_page];
                     77:        inb(port + E21_MEM_ENABLE);
                     78:        outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
                     79: }
                     80: 
                     81: extern inline void mem_off(short port)
                     82: {
                     83:        inb(port + E21_MEM_ENABLE);
                     84:        outb(0x00, port + E21_MEM_ENABLE);
                     85: }
                     86: 
                     87: /* In other drivers I put the TX pages first, but the E2100 window circuitry
                     88:    is designed to have a 4K Tx region last. The windowing circuitry wraps the
                     89:    window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
                     90:    appear contiguously in the window. */
                     91: #define E21_RX_START_PG                0x00    /* First page of RX buffer */
                     92: #define E21_RX_STOP_PG         0x30    /* Last page +1 of RX ring */
                     93: #define E21_BIG_RX_STOP_PG     0xF0    /* Last page +1 of RX ring */
                     94: #define E21_TX_START_PG                E21_RX_STOP_PG  /* First page of TX buffer */
                     95: 
                     96: int e2100_probe(struct device *dev);
                     97: int e21_probe1(struct device *dev, int ioaddr);
                     98: 
                     99: static int e21_open(struct device *dev);
                    100: static void e21_reset_8390(struct device *dev);
                    101: static void e21_block_input(struct device *dev, int count,
                    102:                                                   struct sk_buff *skb, int ring_offset);
                    103: static void e21_block_output(struct device *dev, int count,
                    104:                                                         const unsigned char *buf, const int start_page);
                    105: static void e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
                    106:                                                        int ring_page);
                    107: 
                    108: static int e21_close(struct device *dev);
                    109: 
                    110: 
                    111: /*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
                    112:        base address and the station address at both offset 0x10 and 0x18.  I read
                    113:        the station address from offset 0x18 to avoid the dataport of NE2000
                    114:        ethercards, and look for Ctron's unique ID (first three octets of the
                    115:        station address).
                    116:  */
                    117: 
                    118: int e2100_probe(struct device *dev)
                    119: {
                    120:        int *port;
                    121:        int base_addr = dev->base_addr;
                    122: 
                    123:        if (base_addr > 0x1ff)          /* Check a single specified location. */
                    124:                return e21_probe1(dev, base_addr);
                    125:        else if (base_addr != 0)        /* Don't probe at all. */
                    126:                return ENXIO;
                    127: 
                    128:        for (port = e21_probe_list; *port; port++) {
                    129:                if (check_region(*port, E21_IO_EXTENT))
                    130:                        continue;
                    131:                if (e21_probe1(dev, *port) == 0)
                    132:                        return 0;
                    133:        }
                    134: 
                    135:        return ENODEV;
                    136: }
                    137: 
                    138: int e21_probe1(struct device *dev, int ioaddr)
                    139: {
                    140:        int i, status;
                    141:        unsigned char *station_addr = dev->dev_addr;
                    142:        static unsigned version_printed = 0;
                    143: 
                    144:        /* First check the station address for the Ctron prefix. */
                    145:        if (inb(ioaddr + E21_SAPROM + 0) != 0x00
                    146:                || inb(ioaddr + E21_SAPROM + 1) != 0x00
                    147:                || inb(ioaddr + E21_SAPROM + 2) != 0x1d)
                    148:                return ENODEV;
                    149: 
                    150:        /* Verify by making certain that there is a 8390 at there. */
                    151:        outb(E8390_NODMA + E8390_STOP, ioaddr);
                    152:        SLOW_DOWN_IO;
                    153:        status = inb(ioaddr);
                    154:        if (status != 0x21 && status != 0x23)
                    155:                return ENODEV;
                    156: 
                    157:        /* Read the station address PROM.  */
                    158:        for (i = 0; i < 6; i++)
                    159:                station_addr[i] = inb(ioaddr + E21_SAPROM + i);
                    160: 
                    161:        inb(ioaddr + E21_MEDIA);                /* Point to media selection. */
                    162:        outb(0, ioaddr + E21_ASIC);     /* and disable the secondary interface. */
                    163: 
                    164:        if (ei_debug  &&  version_printed++ == 0)
1.1.1.2 ! root      165:                printk("%s", version);
1.1       root      166: 
                    167:        /* We should have a "dev" from Space.c or the static module table. */
                    168:        if (dev == NULL) {
                    169:                printk("e2100.c: Passed a NULL device.\n");
                    170:                dev = init_etherdev(0, 0);
                    171:        }
                    172: 
                    173:        printk("%s: E21** at %#3x,", dev->name, ioaddr);
                    174:        for (i = 0; i < 6; i++)
                    175:                printk(" %02X", station_addr[i]);
                    176: 
                    177:        if (dev->irq < 2) {
                    178:                int irqlist[] = {15,11,10,12,5,9,3,4}, i;
                    179:                for (i = 0; i < 8; i++)
                    180:                        if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
                    181:                                dev->irq = irqlist[i];
                    182:                                break;
                    183:                        }
                    184:                if (i >= 8) {
                    185:                        printk(" unable to get IRQ %d.\n", dev->irq);
                    186:                        return EAGAIN;
                    187:                }
                    188:        } else if (dev->irq == 2)       /* Fixup luser bogosity: IRQ2 is really IRQ9 */
                    189:                dev->irq = 9;
                    190: 
                    191:        /* Allocate dev->priv and fill in 8390 specific dev fields. */
                    192:        if (ethdev_init(dev)) {
                    193:                printk (" unable to get memory for dev->priv.\n");
                    194:                return -ENOMEM;
                    195:        }
                    196: 
                    197:        /* Grab the region so we can find a different board if IRQ select fails. */
                    198:        request_region(ioaddr, E21_IO_EXTENT, "e2100");
                    199: 
                    200:        /* The 8390 is at the base address. */
                    201:        dev->base_addr = ioaddr;
                    202: 
                    203:        ei_status.name = "E2100";
                    204:        ei_status.word16 = 1;
                    205:        ei_status.tx_start_page = E21_TX_START_PG;
                    206:        ei_status.rx_start_page = E21_RX_START_PG;
                    207:        ei_status.stop_page = E21_RX_STOP_PG;
                    208:        ei_status.saved_irq = dev->irq;
                    209: 
                    210:        /* Check the media port used.  The port can be passed in on the
                    211:           low mem_end bits. */
                    212:        if (dev->mem_end & 15)
                    213:                dev->if_port = dev->mem_end & 7;
                    214:        else {
                    215:                dev->if_port = 0;
                    216:                inb(ioaddr + E21_MEDIA);        /* Turn automatic media detection on. */
                    217:                for(i = 0; i < 6; i++)
                    218:                        if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
                    219:                                dev->if_port = 1;
                    220:                                break;
                    221:                        }
                    222:        }
                    223: 
                    224:        /* Never map in the E21 shared memory unless you are actively using it.
                    225:           Also, the shared memory has effective only one setting -- spread all
                    226:           over the 128K region! */
                    227:        if (dev->mem_start == 0)
                    228:                dev->mem_start = 0xd0000;
                    229:        
                    230: #ifdef notdef
                    231:        /* These values are unused.  The E2100 has a 2K window into the packet
                    232:           buffer.  The window can be set to start on any page boundary. */
                    233:        dev->rmem_start = dev->mem_start + TX_PAGES*256;
                    234:        dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024;
                    235: #endif
                    236: 
                    237:        printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
                    238:                   dev->if_port ? "secondary" : "primary", dev->mem_start);
                    239: 
                    240:        ei_status.reset_8390 = &e21_reset_8390;
                    241:        ei_status.block_input = &e21_block_input;
                    242:        ei_status.block_output = &e21_block_output;
                    243:        ei_status.get_8390_hdr = &e21_get_8390_hdr;
                    244:        dev->open = &e21_open;
                    245:        dev->stop = &e21_close;
                    246:        NS8390_init(dev, 0);
                    247: 
                    248:        return 0;
                    249: }
                    250: 
                    251: static int
                    252: e21_open(struct device *dev)
                    253: {
                    254:        short ioaddr = dev->base_addr;
                    255: 
                    256:        if (request_irq(dev->irq, ei_interrupt, 0, "e2100", NULL)) {
                    257:                return EBUSY;
                    258:        }
                    259:        irq2dev_map[dev->irq] = dev;
                    260: 
                    261:        /* Set the interrupt line and memory base on the hardware. */
                    262:        inb(ioaddr + E21_IRQ_LOW);
                    263:        outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
                    264:        inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
                    265:        outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
                    266:                   + (dev->if_port ? E21_ALT_IFPORT : 0));
                    267:        inb(ioaddr + E21_MEM_BASE);
                    268:        outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
                    269: 
                    270:        ei_open(dev);
                    271:        MOD_INC_USE_COUNT;
                    272:        return 0;
                    273: }
                    274: 
                    275: static void
                    276: e21_reset_8390(struct device *dev)
                    277: {
                    278:        short ioaddr = dev->base_addr;
                    279: 
                    280:        outb(0x01, ioaddr);
                    281:        if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
                    282:        ei_status.txing = 0;
                    283: 
                    284:        /* Set up the ASIC registers, just in case something changed them. */
                    285: 
                    286:        if (ei_debug > 1) printk("reset done\n");
                    287:        return;
                    288: }
                    289: 
                    290: /* Grab the 8390 specific header. We put the 2k window so the header page
                    291:    appears at the start of the shared memory. */
                    292: 
                    293: static void
                    294: e21_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
                    295: {
                    296: 
                    297:        short ioaddr = dev->base_addr;
                    298:        char *shared_mem = (char *)dev->mem_start;
                    299: 
                    300:        mem_on(ioaddr, shared_mem, ring_page);
                    301: 
                    302: #ifdef notdef
                    303:        /* Officially this is what we are doing, but the readl() is faster */
                    304:        memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
                    305: #else
                    306:        ((unsigned int*)hdr)[0] = readl(shared_mem);
                    307: #endif
                    308: 
                    309:        /* Turn off memory access: we would need to reprogram the window anyway. */
                    310:        mem_off(ioaddr);
                    311: 
                    312: }
                    313: 
                    314: /*  Block input and output are easy on shared memory ethercards.
                    315:        The E21xx makes block_input() especially easy by wrapping the top
                    316:        ring buffer to the bottom automatically. */
                    317: static void
                    318: e21_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
                    319: {
                    320:        short ioaddr = dev->base_addr;
                    321:        char *shared_mem = (char *)dev->mem_start;
                    322: 
                    323:        mem_on(ioaddr, shared_mem, (ring_offset>>8));
                    324: 
                    325:        /* Packet is always in one chunk -- we can copy + cksum. */
                    326:        eth_io_copy_and_sum(skb, dev->mem_start + (ring_offset & 0xff), count, 0);
                    327: 
                    328:        mem_off(ioaddr);
                    329: }
                    330: 
                    331: static void
                    332: e21_block_output(struct device *dev, int count, const unsigned char *buf,
                    333:                                 const int start_page)
                    334: {
                    335:        short ioaddr = dev->base_addr;
                    336:        volatile char *shared_mem = (char *)dev->mem_start;
                    337: 
                    338:        /* Set the shared memory window start by doing a read, with the low address
                    339:           bits specifying the starting page. */
                    340:        readb(shared_mem + start_page);
                    341:        mem_on(ioaddr, shared_mem, start_page);
                    342: 
                    343:        memcpy_toio(shared_mem, buf, count);
                    344:        mem_off(ioaddr);
                    345: }
                    346: 
                    347: static int
                    348: e21_close(struct device *dev)
                    349: {
                    350:        short ioaddr = dev->base_addr;
                    351: 
                    352:        if (ei_debug > 1)
                    353:                printk("%s: Shutting down ethercard.\n", dev->name);
                    354: 
                    355:        free_irq(dev->irq, NULL);
                    356:        dev->irq = ei_status.saved_irq;
                    357: 
                    358:        /* Shut off the interrupt line and secondary interface. */
                    359:        inb(ioaddr + E21_IRQ_LOW);
                    360:        outb(0, ioaddr + E21_ASIC);
                    361:        inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
                    362:        outb(0, ioaddr + E21_ASIC);
                    363: 
                    364:        irq2dev_map[dev->irq] = NULL;
                    365: 
                    366:        ei_close(dev);
                    367: 
                    368:        /* Double-check that the memory has been turned off, because really
                    369:           really bad things happen if it isn't. */
                    370:        mem_off(ioaddr);
                    371: 
                    372:        MOD_DEC_USE_COUNT;
                    373: 
                    374:        return 0;
                    375: }
                    376: 
                    377: #ifdef HAVE_DEVLIST
                    378: struct netdev_entry e21_drv =
                    379: {"e21", e21_probe1, E21_IO_EXTENT, e21_probe_list};
                    380: #endif
                    381: 
                    382: 
                    383: #ifdef MODULE
                    384: #define MAX_E21_CARDS  4       /* Max number of E21 cards per module */
                    385: #define NAMELEN                8       /* # of chars for storing dev->name */
                    386: static char namelist[NAMELEN * MAX_E21_CARDS] = { 0, };
                    387: static struct device dev_e21[MAX_E21_CARDS] = {
                    388:        {
                    389:                NULL,           /* assign a chunk of namelist[] below */
                    390:                0, 0, 0, 0,
                    391:                0, 0,
                    392:                0, 0, 0, NULL, NULL
                    393:        },
                    394: };
                    395: 
                    396: static int io[MAX_E21_CARDS] = { 0, };
                    397: static int irq[MAX_E21_CARDS]  = { 0, };
                    398: static int mem[MAX_E21_CARDS] = { 0, };
                    399: static int xcvr[MAX_E21_CARDS] = { 0, };               /* choose int. or ext. xcvr */
                    400: 
                    401: /* This is set up so that only a single autoprobe takes place per call.
                    402: ISA device autoprobes on a running machine are not recommended. */
                    403: int
                    404: init_module(void)
                    405: {
                    406:        int this_dev, found = 0;
                    407: 
                    408:        for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
                    409:                struct device *dev = &dev_e21[this_dev];
                    410:                dev->name = namelist+(NAMELEN*this_dev);
                    411:                dev->irq = irq[this_dev];
                    412:                dev->base_addr = io[this_dev];
                    413:                dev->mem_start = mem[this_dev];
                    414:                dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
                    415:                dev->init = e2100_probe;
                    416:                if (io[this_dev] == 0)  {
                    417:                        if (this_dev != 0) break; /* only autoprobe 1st one */
                    418:                        printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
                    419:                }
                    420:                if (register_netdev(dev) != 0) {
                    421:                        printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
                    422:                        if (found != 0) return 0;       /* Got at least one. */
                    423:                        return -ENXIO;
                    424:                }
                    425:                found++;
                    426:        }
                    427: 
                    428:        return 0;
                    429: }
                    430: 
                    431: void
                    432: cleanup_module(void)
                    433: {
                    434:        int this_dev;
                    435: 
                    436:        for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
                    437:                struct device *dev = &dev_e21[this_dev];
                    438:                if (dev->priv != NULL) {
                    439:                        /* NB: e21_close() handles free_irq + irq2dev map */
                    440:                        kfree(dev->priv);
                    441:                        dev->priv = NULL;
                    442:                        release_region(dev->base_addr, E21_IO_EXTENT);
                    443:                        unregister_netdev(dev);
                    444:                }
                    445:        }
                    446: }
                    447: #endif /* MODULE */
                    448: 
                    449: /*
                    450:  * Local variables:
                    451:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c e2100.c"
                    452:  *  version-control: t
                    453:  *  tab-width: 4
                    454:  *  kept-new-versions: 5
                    455:  * End:
                    456:  */

unix.superglobalmegacorp.com

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