linux/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#define DRV_NAME        "ac3200"
  43
  44/* Offsets from the base address. */
  45#define AC_NIC_BASE     0x00
  46#define AC_SA_PROM      0x16                    /* The station address PROM. */
  47#define AC_ADDR0        0x00                    /* Prefix station address values. */
  48#define AC_ADDR1        0x40
  49#define AC_ADDR2        0x90
  50#define AC_ID_PORT      0xC80
  51#define AC_EISA_ID      0x0110d305
  52#define AC_RESET_PORT   0xC84
  53#define AC_RESET        0x00
  54#define AC_ENABLE       0x01
  55#define AC_CONFIG       0xC90   /* The configuration port. */
  56
  57#define AC_IO_EXTENT 0x20
  58                                /* Actually accessed is:
  59                                                                 * AC_NIC_BASE (0-15)
  60                                                                 * AC_SA_PROM (0-5)
  61                                                                 * AC_ID_PORT (0-3)
  62                                                                 * AC_RESET_PORT
  63                                                                 * AC_CONFIG
  64                                                                 */
  65
  66/* Decoding of the configuration register. */
  67static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
  68static int addrmap[8] =
  69{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
  70static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
  71
  72#define config2irq(configval)   config2irqmap[((configval) >> 3) & 7]
  73#define config2mem(configval)   addrmap[(configval) & 7]
  74#define config2name(configval)  port_name[((configval) >> 6) & 3]
  75
  76/* First and last 8390 pages. */
  77#define AC_START_PG             0x00    /* First page of 8390 TX buffer */
  78#define AC_STOP_PG              0x80    /* Last page +1 of the 8390 RX ring */
  79
  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
 100static int __init do_ac3200_probe(struct net_device *dev)
 101{
 102        unsigned short ioaddr = dev->base_addr;
 103        int irq = dev->irq;
 104        int mem_start = dev->mem_start;
 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                dev->irq = irq;
 118                dev->mem_start = mem_start;
 119        }
 120
 121        return -ENODEV;
 122}
 123
 124#ifndef MODULE
 125struct net_device * __init ac3200_probe(int unit)
 126{
 127        struct net_device *dev = alloc_ei_netdev();
 128        int err;
 129
 130        if (!dev)
 131                return ERR_PTR(-ENOMEM);
 132
 133        sprintf(dev->name, "eth%d", unit);
 134        netdev_boot_setup_check(dev);
 135
 136        err = do_ac3200_probe(dev);
 137        if (err)
 138                goto out;
 139        return dev;
 140out:
 141        free_netdev(dev);
 142        return ERR_PTR(err);
 143}
 144#endif
 145
 146static const struct net_device_ops ac_netdev_ops = {
 147        .ndo_open               = ac_open,
 148        .ndo_stop               = ac_close_card,
 149
 150        .ndo_start_xmit         = ei_start_xmit,
 151        .ndo_tx_timeout         = ei_tx_timeout,
 152        .ndo_get_stats          = ei_get_stats,
 153        .ndo_set_multicast_list = ei_set_multicast_list,
 154        .ndo_validate_addr      = eth_validate_addr,
 155        .ndo_set_mac_address    = eth_mac_addr,
 156        .ndo_change_mtu         = eth_change_mtu,
 157#ifdef CONFIG_NET_POLL_CONTROLLER
 158        .ndo_poll_controller    = ei_poll,
 159#endif
 160};
 161
 162static int __init ac_probe1(int ioaddr, struct net_device *dev)
 163{
 164        int i, retval;
 165
 166        if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
 167                return -EBUSY;
 168
 169        if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
 170                retval = -ENODEV;
 171                goto out;
 172        }
 173
 174        if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
 175                retval = -ENODEV;
 176                goto out;
 177        }
 178
 179#ifndef final_version
 180        printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
 181                   " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
 182                   inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
 183                   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
 184#endif
 185
 186        for (i = 0; i < 6; i++)
 187                dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
 188
 189        printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
 190               ioaddr/0x1000, dev->dev_addr);
 191#if 0
 192        /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
 193        if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
 194                || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
 195                || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
 196                printk(", not found (invalid prefix).\n");
 197                retval = -ENODEV;
 198                goto out;
 199        }
 200#endif
 201
 202        /* Assign and allocate the interrupt now. */
 203        if (dev->irq == 0) {
 204                dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
 205                printk(", using");
 206        } else {
 207                dev->irq = irq_canonicalize(dev->irq);
 208                printk(", assigning");
 209        }
 210
 211        retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 212        if (retval) {
 213                printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
 214                goto out;
 215        }
 216
 217        printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
 218
 219        dev->base_addr = ioaddr;
 220
 221#ifdef notyet
 222        if (dev->mem_start)     {               /* Override the value from the board. */
 223                for (i = 0; i < 7; i++)
 224                        if (addrmap[i] == dev->mem_start)
 225                                break;
 226                if (i >= 7)
 227                        i = 0;
 228                outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
 229        }
 230#endif
 231
 232        dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
 233        dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
 234
 235        printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
 236                        dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
 237
 238        /*
 239         *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
 240         *  the card mem within the region covered by `normal' RAM  !!!
 241         *
 242         *  ioremap() will fail in that case.
 243         */
 244        ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
 245        if (!ei_status.mem) {
 246                printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
 247                printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
 248                printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
 249                retval = -EINVAL;
 250                goto out1;
 251        }
 252        printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
 253                        AC_STOP_PG/4, ei_status.mem);
 254
 255        dev->mem_start = (unsigned long)ei_status.mem;
 256        dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
 257
 258        ei_status.name = "AC3200";
 259        ei_status.tx_start_page = AC_START_PG;
 260        ei_status.rx_start_page = AC_START_PG + TX_PAGES;
 261        ei_status.stop_page = AC_STOP_PG;
 262        ei_status.word16 = 1;
 263
 264        if (ei_debug > 0)
 265                printk(version);
 266
 267        ei_status.reset_8390 = &ac_reset_8390;
 268        ei_status.block_input = &ac_block_input;
 269        ei_status.block_output = &ac_block_output;
 270        ei_status.get_8390_hdr = &ac_get_8390_hdr;
 271
 272        dev->netdev_ops = &ac_netdev_ops;
 273        NS8390_init(dev, 0);
 274
 275        retval = register_netdev(dev);
 276        if (retval)
 277                goto out2;
 278        return 0;
 279out2:
 280        if (ei_status.reg0)
 281                iounmap(ei_status.mem);
 282out1:
 283        free_irq(dev->irq, dev);
 284out:
 285        release_region(ioaddr, AC_IO_EXTENT);
 286        return retval;
 287}
 288
 289static int ac_open(struct net_device *dev)
 290{
 291#ifdef notyet
 292        /* Someday we may enable the IRQ and shared memory here. */
 293        int ioaddr = dev->base_addr;
 294#endif
 295
 296        ei_open(dev);
 297        return 0;
 298}
 299
 300static void ac_reset_8390(struct net_device *dev)
 301{
 302        ushort ioaddr = dev->base_addr;
 303
 304        outb(AC_RESET, ioaddr + AC_RESET_PORT);
 305        if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
 306
 307        ei_status.txing = 0;
 308        outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
 309        if (ei_debug > 1) printk("reset done\n");
 310}
 311
 312/* Grab the 8390 specific header. Similar to the block_input routine, but
 313   we don't need to be concerned with ring wrap as the header will be at
 314   the start of a page, so we optimize accordingly. */
 315
 316static void
 317ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 318{
 319        void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
 320        memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 321}
 322
 323/*  Block input and output are easy on shared memory ethercards, the only
 324        complication is when the ring buffer wraps. */
 325
 326static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 327                                                  int ring_offset)
 328{
 329        void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
 330
 331        if (ring_offset + count > AC_STOP_PG*256) {
 332                /* We must wrap the input move. */
 333                int semi_count = AC_STOP_PG*256 - ring_offset;
 334                memcpy_fromio(skb->data, start, semi_count);
 335                count -= semi_count;
 336                memcpy_fromio(skb->data + semi_count,
 337                                ei_status.mem + TX_PAGES*256, count);
 338        } else {
 339                memcpy_fromio(skb->data, start, count);
 340        }
 341}
 342
 343static void ac_block_output(struct net_device *dev, int count,
 344                                                        const unsigned char *buf, int start_page)
 345{
 346        void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
 347
 348        memcpy_toio(shmem, buf, count);
 349}
 350
 351static int ac_close_card(struct net_device *dev)
 352{
 353        if (ei_debug > 1)
 354                printk("%s: Shutting down ethercard.\n", dev->name);
 355
 356#ifdef notyet
 357        /* We should someday disable shared memory and interrupts. */
 358        outb(0x00, ioaddr + 6); /* Disable interrupts. */
 359        free_irq(dev->irq, dev);
 360#endif
 361
 362        ei_close(dev);
 363        return 0;
 364}
 365
 366#ifdef MODULE
 367#define MAX_AC32_CARDS  4       /* Max number of AC32 cards per module */
 368static struct net_device *dev_ac32[MAX_AC32_CARDS];
 369static int io[MAX_AC32_CARDS];
 370static int irq[MAX_AC32_CARDS];
 371static int mem[MAX_AC32_CARDS];
 372module_param_array(io, int, NULL, 0);
 373module_param_array(irq, int, NULL, 0);
 374module_param_array(mem, int, NULL, 0);
 375MODULE_PARM_DESC(io, "I/O base address(es)");
 376MODULE_PARM_DESC(irq, "IRQ number(s)");
 377MODULE_PARM_DESC(mem, "Memory base address(es)");
 378MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
 379MODULE_LICENSE("GPL");
 380
 381static int __init ac3200_module_init(void)
 382{
 383        struct net_device *dev;
 384        int this_dev, found = 0;
 385
 386        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
 387                if (io[this_dev] == 0 && this_dev != 0)
 388                        break;
 389                dev = alloc_ei_netdev();
 390                if (!dev)
 391                        break;
 392                dev->irq = irq[this_dev];
 393                dev->base_addr = io[this_dev];
 394                dev->mem_start = mem[this_dev];         /* Currently ignored by driver */
 395                if (do_ac3200_probe(dev) == 0) {
 396                        dev_ac32[found++] = dev;
 397                        continue;
 398                }
 399                free_netdev(dev);
 400                printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
 401                break;
 402        }
 403        if (found)
 404                return 0;
 405        return -ENXIO;
 406}
 407
 408static void cleanup_card(struct net_device *dev)
 409{
 410        /* Someday free_irq may be in ac_close_card() */
 411        free_irq(dev->irq, dev);
 412        release_region(dev->base_addr, AC_IO_EXTENT);
 413        iounmap(ei_status.mem);
 414}
 415
 416static void __exit ac3200_module_exit(void)
 417{
 418        int this_dev;
 419
 420        for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
 421                struct net_device *dev = dev_ac32[this_dev];
 422                if (dev) {
 423                        unregister_netdev(dev);
 424                        cleanup_card(dev);
 425                        free_netdev(dev);
 426                }
 427        }
 428}
 429module_init(ac3200_module_init);
 430module_exit(ac3200_module_exit);
 431#endif /* MODULE */
 432