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