linux-bk/drivers/net/ac3200.c
<<
>>
Prefs
   1/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
   2/*
   3        Written 1993, 1994 by Donald Becker.
   4        Copyright 1993 United States Government as represented by the Director,
   5        National Security Agency.  This software may only be used and distributed
   6        according to the terms of the GNU General Public License as modified by SRC,
   7        incorporated herein by reference.
   8
   9        The author may be reached as becker@scyld.com, or C/O
  10        Scyld Computing Corporation
  11        410 Severn Ave., Suite 210
  12        Annapolis MD 21403
  13
  14        This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
  15        Adapter.  The programming information is from the users manual, as related
  16        by glee@ardnassak.math.clemson.edu.
  17
  18        Changelog:
  19
  20        Paul Gortmaker 05/98    : add support for shared mem above 1MB.
  21
  22  */
  23
  24static const char version[] =
  25        "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
  26
  27#include <linux/module.h>
  28
  29#include <linux/kernel.h>
  30#include <linux/sched.h>
  31#include <linux/errno.h>
  32#include <linux/string.h>
  33#include <linux/netdevice.h>
  34#include <linux/etherdevice.h>
  35#include <linux/init.h>
  36
  37#include <asm/system.h>
  38#include <asm/io.h>
  39#include <asm/irq.h>
  40
  41#include "8390.h"
  42
  43/* Offsets from the base address. */
  44#define AC_NIC_BASE     0x00
  45#define AC_SA_PROM      0x16                    /* The station address PROM. */
  46#define AC_ADDR0        0x00                    /* Prefix station address values. */
  47#define AC_ADDR1        0x40                    
  48#define AC_ADDR2        0x90
  49#define AC_ID_PORT      0xC80
  50#define AC_EISA_ID      0x0110d305
  51#define AC_RESET_PORT   0xC84
  52#define AC_RESET        0x00
  53#define AC_ENABLE       0x01
  54#define AC_CONFIG       0xC90   /* The configuration port. */
  55
  56#define AC_IO_EXTENT 0x20
  57                                /* Actually accessed is:
  58                                                                 * AC_NIC_BASE (0-15)
  59                                                                 * AC_SA_PROM (0-5)
  60                                                                 * AC_ID_PORT (0-3)
  61                                                                 * AC_RESET_PORT
  62                                                                 * AC_CONFIG
  63                                                                 */
  64
  65/* Decoding of the configuration register. */
  66static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
  67static int addrmap[8] =
  68{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
  69static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
  70
  71#define config2irq(configval)   config2irqmap[((configval) >> 3) & 7]
  72#define config2mem(configval)   addrmap[(configval) & 7]
  73#define config2name(configval)  port_name[((configval) >> 6) & 3]
  74
  75/* First and last 8390 pages. */
  76#define AC_START_PG             0x00    /* First page of 8390 TX buffer */
  77#define AC_STOP_PG              0x80    /* Last page +1 of the 8390 RX ring */
  78
  79int ac3200_probe(struct net_device *dev);
  80static int ac_probe1(int ioaddr, struct net_device *dev);
  81
  82static int ac_open(struct net_device *dev);
  83static void ac_reset_8390(struct net_device *dev);
  84static void ac_block_input(struct net_device *dev, int count,
  85                                        struct sk_buff *skb, int ring_offset);
  86static void ac_block_output(struct net_device *dev, const int count,
  87                                                        const unsigned char *buf, const int start_page);
  88static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
  89                                        int ring_page);
  90
  91static int ac_close_card(struct net_device *dev);
  92
  93
  94/*      Probe for the AC3200.
  95
  96        The AC3200 can be identified by either the EISA configuration registers,
  97        or the unique value in the station address PROM.
  98        */
  99
 100int __init ac3200_probe(struct net_device *dev)
 101{
 102        unsigned short ioaddr = dev->base_addr;
 103
 104        SET_MODULE_OWNER(dev);
 105
 106        if (ioaddr > 0x1ff)             /* Check a single specified location. */
 107                return ac_probe1(ioaddr, dev);
 108        else if (ioaddr > 0)            /* Don't probe at all. */
 109                return -ENXIO;
 110
 111        if ( ! EISA_bus)
 112                return -ENXIO;
 113
 114        for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000)
 115                if (ac_probe1(ioaddr, dev) == 0)
 116                        return 0;
 117
 118        return -ENODEV;
 119}
 120
 121static int __init ac_probe1(int ioaddr, struct net_device *dev)
 122{
 123        int i, retval;
 124
 125        if (!request_region(ioaddr, AC_IO_EXTENT, dev->name))
 126                return -EBUSY;
 127
 128        if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
 129                retval = -ENODEV;
 130                goto out;
 131        }
 132
 133        if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
 134                retval = -ENODEV;
 135                goto out;
 136        }
 137
 138#ifndef final_version
 139        printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
 140                   " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
 141                   inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
 142                   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
 143#endif
 144
 145        printk("AC3200 in EISA slot %d, node", ioaddr/0x1000);
 146        for(i = 0; i < 6; i++)
 147                printk(" %02x", dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i));
 148
 149#if 0
 150        /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
 151        if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
 152                || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
 153                || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
 154                printk(", not found (invalid prefix).\n");
 155                retval = -ENODEV;
 156                goto out;
 157        }
 158#endif
 159
 160        /* Allocate dev->priv and fill in 8390 specific dev fields. */
 161        if (ethdev_init(dev)) {
 162                printk (", unable to allocate memory for dev->priv.\n");
 163                retval = -ENOMEM;
 164                goto out;
 165        }
 166
 167        /* Assign and allocate the interrupt now. */
 168        if (dev->irq == 0) {
 169                dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
 170                printk(", using");
 171        } else {
 172                dev->irq = irq_cannonicalize(dev->irq);
 173                printk(", assigning");
 174        }
 175
 176        retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
 177        if (retval) {
 178                printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
 179                goto out1;
 180        }
 181
 182        printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
 183
 184        dev->base_addr = ioaddr;
 185
 186#ifdef notyet
 187        if (dev->mem_start)     {               /* Override the value from the board. */
 188                for (i = 0; i < 7; i++)
 189                        if (addrmap[i] == dev->mem_start)
 190                                break;
 191                if (i >= 7)
 192                        i = 0;
 193                outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
 194        }
 195#endif
 196
 197        dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
 198        dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
 199
 200        printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n", 
 201                        dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
 202
 203        /*
 204         *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
 205         *  the card mem within the region covered by `normal' RAM  !!!
 206         */
 207        if (dev->mem_start > 1024*1024) {       /* phys addr > 1MB */
 208                if (dev->mem_start < virt_to_phys(high_memory)) {
 209                        printk(KERN_CRIT "ac3200.c: Card RAM overlaps with normal memory!!!\n");
 210                        printk(KERN_CRIT "ac3200.c: Use EISA SCU to set card memory below 1MB,\n");
 211                        printk(KERN_CRIT "ac3200.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
 212                        printk(KERN_CRIT "ac3200.c: Driver NOT installed.\n");
 213                        retval = -EINVAL;
 214                        goto out2;
 215                }
 216                dev->mem_start = (unsigned long)ioremap(dev->mem_start, AC_STOP_PG*0x100);
 217                if (dev->mem_start == 0) {
 218                        printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
 219                        printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
 220                        printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
 221                        retval = -EINVAL;
 222                        goto out2;
 223                }
 224                ei_status.reg0 = 1;     /* Use as remap flag */
 225                printk("ac3200.c: remapped %dkB card memory to virtual address %#lx\n",
 226                                AC_STOP_PG/4, dev->mem_start);
 227        }
 228
 229        ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 230        dev->mem_end = ei_status.rmem_end = dev->mem_start
 231                + (AC_STOP_PG - AC_START_PG)*256;
 232
 233        ei_status.name = "AC3200";
 234        ei_status.tx_start_page = AC_START_PG;
 235        ei_status.rx_start_page = AC_START_PG + TX_PAGES;
 236        ei_status.stop_page = AC_STOP_PG;
 237        ei_status.word16 = 1;
 238
 239        if (ei_debug > 0)
 240                printk(version);
 241
 242        ei_status.reset_8390 = &ac_reset_8390;
 243        ei_status.block_input = &ac_block_input;
 244        ei_status.block_output = &ac_block_output;
 245        ei_status.get_8390_hdr = &ac_get_8390_hdr;
 246
 247        dev->open = &ac_open;
 248        dev->stop = &ac_close_card;
 249        NS8390_init(dev, 0);
 250        return 0;
 251out2:
 252        free_irq(dev->irq, dev);
 253out1:
 254        kfree(dev->priv);
 255        dev->priv = NULL;
 256out:
 257        release_region(ioaddr, AC_IO_EXTENT);
 258        return retval;
 259}
 260
 261static int ac_open(struct net_device *dev)
 262{
 263#ifdef notyet
 264        /* Someday we may enable the IRQ and shared memory here. */
 265        int ioaddr = dev->base_addr;
 266#endif
 267
 268        ei_open(dev);
 269        return 0;
 270}
 271
 272static void ac_reset_8390(struct net_device *dev)
 273{
 274        ushort ioaddr = dev->base_addr;
 275
 276        outb(AC_RESET, ioaddr + AC_RESET_PORT);
 277        if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
 278
 279        ei_status.txing = 0;
 280        outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
 281        if (ei_debug > 1) printk("reset done\n");
 282
 283        return;
 284}
 285
 286/* Grab the 8390 specific header. Similar to the block_input routine, but
 287   we don't need to be concerned with ring wrap as the header will be at
 288   the start of a page, so we optimize accordingly. */
 289
 290static void
 291ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 292{
 293        unsigned long hdr_start = dev->mem_start + ((ring_page - AC_START_PG)<<8);
 294        isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 295}
 296
 297/*  Block input and output are easy on shared memory ethercards, the only
 298        complication is when the ring buffer wraps. */
 299
 300static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 301                                                  int ring_offset)
 302{
 303        unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
 304
 305        if (xfer_start + count > ei_status.rmem_end) {
 306                /* We must wrap the input move. */
 307                int semi_count = ei_status.rmem_end - xfer_start;
 308                isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 309                count -= semi_count;
 310                isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 311        } else {
 312                /* Packet is in one chunk -- we can copy + cksum. */
 313                isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 314        }
 315}
 316
 317static void ac_block_output(struct net_device *dev, int count,
 318                                                        const unsigned char *buf, int start_page)
 319{
 320        unsigned long shmem = dev->mem_start + ((start_page - AC_START_PG)<<8);
 321
 322        isa_memcpy_toio(shmem, buf, count);
 323}
 324
 325static int ac_close_card(struct net_device *dev)
 326{
 327        if (ei_debug > 1)
 328                printk("%s: Shutting down ethercard.\n", dev->name);
 329
 330#ifdef notyet
 331        /* We should someday disable shared memory and interrupts. */
 332        outb(0x00, ioaddr + 6); /* Disable interrupts. */
 333        free_irq(dev->irq, dev);
 334#endif
 335
 336        ei_close(dev);
 337        return 0;
 338}
 339
 340#ifdef MODULE
 341#define MAX_AC32_CARDS  4       /* Max number of AC32 cards per module */
 342static struct net_device dev_ac32[MAX_AC32_CARDS];
 343static int io[MAX_AC32_CARDS];
 344static int irq[MAX_AC32_CARDS];
 345static int mem[MAX_AC32_CARDS];
 346MODULE_PARM(io, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
 347MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
 348MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_AC32_CARDS) "i");
 349MODULE_PARM_DESC(io, "I/O base adress(es)");
 350MODULE_PARM_DESC(irq, "IRQ number(s)");
 351MODULE_PARM_DESC(mem, "Memory base address(es)");
 352MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
 353MODULE_LICENSE("GPL");
 354
 355int
 356init_module(void)
 357{
 358        int this_dev, found = 0;
 359
 360        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
 361                struct net_device *dev = &dev_ac32[this_dev];
 362                dev->irq = irq[this_dev];
 363                dev->base_addr = io[this_dev];
 364                dev->mem_start = mem[this_dev];         /* Currently ignored by driver */
 365                dev->init = ac3200_probe;
 366                /* Default is to only install one card. */
 367                if (io[this_dev] == 0 && this_dev != 0) break;
 368                if (register_netdev(dev) != 0) {
 369                        printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
 370                        if (found != 0) {       /* Got at least one. */
 371                                return 0;
 372                        }
 373                        return -ENXIO;
 374                }
 375                found++;
 376        }
 377        return 0;
 378}
 379
 380void
 381cleanup_module(void)
 382{
 383        int this_dev;
 384
 385        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
 386                struct net_device *dev = &dev_ac32[this_dev];
 387                if (dev->priv != NULL) {
 388                        /* Someday free_irq may be in ac_close_card() */
 389                        free_irq(dev->irq, dev);
 390                        release_region(dev->base_addr, AC_IO_EXTENT);
 391                        if (ei_status.reg0)
 392                                iounmap((void *)dev->mem_start);
 393                        unregister_netdev(dev);
 394                        kfree(dev->priv);
 395                        dev->priv = NULL;
 396                }
 397        }
 398}
 399#endif /* MODULE */
 400
 401
 402/*
 403 * Local variables:
 404 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ac3200.c"
 405 *  version-control: t
 406 *  kept-new-versions: 5
 407 *  tab-width: 4
 408 * End:
 409 */
 410
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.