Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers)
0003  *
0004  * Written 1997 by David Woodhouse.
0005  * Written 1994-1999 by Avery Pennarun.
0006  * Written 1999-2000 by Martin Mares <mj@ucw.cz>.
0007  * Derived from skeleton.c by Donald Becker.
0008  *
0009  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
0010  *  for sponsoring the further development of this driver.
0011  *
0012  * **********************
0013  *
0014  * The original copyright of skeleton.c was as follows:
0015  *
0016  * skeleton.c Written 1993 by Donald Becker.
0017  * Copyright 1993 United States Government as represented by the
0018  * Director, National Security Agency.  This software may only be used
0019  * and distributed according to the terms of the GNU General Public License as
0020  * modified by SRC, incorporated herein by reference.
0021  *
0022  * **********************
0023  *
0024  * For more details, see drivers/net/arcnet.c
0025  *
0026  * **********************
0027  */
0028 
0029 #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
0030 
0031 #include <linux/kernel.h>
0032 #include <linux/module.h>
0033 #include <linux/moduleparam.h>
0034 #include <linux/ioport.h>
0035 #include <linux/delay.h>
0036 #include <linux/netdevice.h>
0037 #include <linux/memblock.h>
0038 #include <linux/init.h>
0039 #include <linux/interrupt.h>
0040 #include <linux/io.h>
0041 
0042 #include "arcdevice.h"
0043 #include "com9026.h"
0044 
0045 /* Internal function declarations */
0046 
0047 static int com90io_found(struct net_device *dev);
0048 static void com90io_command(struct net_device *dev, int command);
0049 static int com90io_status(struct net_device *dev);
0050 static void com90io_setmask(struct net_device *dev, int mask);
0051 static int com90io_reset(struct net_device *dev, int really_reset);
0052 static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset,
0053                  void *buf, int count);
0054 static void com90io_copy_from_card(struct net_device *dev, int bufnum,
0055                    int offset, void *buf, int count);
0056 
0057 /* Handy defines for ARCnet specific stuff */
0058 
0059 /* The number of low I/O ports used by the card. */
0060 #define ARCNET_TOTAL_SIZE 16
0061 
0062 /****************************************************************************
0063  *                                                                          *
0064  * IO-mapped operation routines                                             *
0065  *                                                                          *
0066  ****************************************************************************/
0067 
0068 #undef ONE_AT_A_TIME_TX
0069 #undef ONE_AT_A_TIME_RX
0070 
0071 static u_char get_buffer_byte(struct net_device *dev, unsigned offset)
0072 {
0073     int ioaddr = dev->base_addr;
0074 
0075     arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
0076     arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
0077 
0078     return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
0079 }
0080 
0081 #ifdef ONE_AT_A_TIME_TX
0082 static void put_buffer_byte(struct net_device *dev, unsigned offset,
0083                 u_char datum)
0084 {
0085     int ioaddr = dev->base_addr;
0086 
0087     arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI);
0088     arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
0089 
0090     arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA);
0091 }
0092 
0093 #endif
0094 
0095 static void get_whole_buffer(struct net_device *dev, unsigned offset,
0096                  unsigned length, char *dest)
0097 {
0098     int ioaddr = dev->base_addr;
0099 
0100     arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
0101     arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO);
0102 
0103     while (length--)
0104 #ifdef ONE_AT_A_TIME_RX
0105         *(dest++) = get_buffer_byte(dev, offset++);
0106 #else
0107         *(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
0108 #endif
0109 }
0110 
0111 static void put_whole_buffer(struct net_device *dev, unsigned offset,
0112                  unsigned length, char *dest)
0113 {
0114     int ioaddr = dev->base_addr;
0115 
0116     arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
0117     arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO);
0118 
0119     while (length--)
0120 #ifdef ONE_AT_A_TIME_TX
0121         put_buffer_byte(dev, offset++, *(dest++));
0122 #else
0123         arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA);
0124 #endif
0125 }
0126 
0127 /* We cannot probe for an IO mapped card either, although we can check that
0128  * it's where we were told it was, and even autoirq
0129  */
0130 static int __init com90io_probe(struct net_device *dev)
0131 {
0132     int ioaddr = dev->base_addr, status;
0133     unsigned long airqmask;
0134 
0135     if (BUGLVL(D_NORMAL)) {
0136         pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)");
0137         pr_info("E-mail me if you actually test this driver, please!\n");
0138     }
0139 
0140     if (!ioaddr) {
0141         arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n");
0142         return -ENODEV;
0143     }
0144     if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
0145         arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n",
0146                ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
0147         return -ENXIO;
0148     }
0149     if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) {
0150         arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n",
0151                ioaddr);
0152         goto err_out;
0153     }
0154     arcnet_inb(ioaddr, COM9026_REG_R_RESET);
0155     mdelay(RESETtime);
0156 
0157     status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
0158 
0159     if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
0160         arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n",
0161                status);
0162         goto err_out;
0163     }
0164     arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status);
0165 
0166     arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear,
0167             ioaddr, COM9026_REG_W_COMMAND);
0168 
0169     arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n",
0170            status);
0171 
0172     status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
0173 
0174     if (status & RESETflag) {
0175         arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n",
0176                status);
0177         goto err_out;
0178     }
0179     arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag,
0180             ioaddr, COM9026_REG_RW_CONFIG);
0181 
0182     /* Read first loc'n of memory */
0183 
0184     arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI);
0185     arcnet_outb(0, ioaddr,  COM9026_REG_W_ADDR_LO);
0186 
0187     status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA);
0188     if (status != 0xd1) {
0189         arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n",
0190                status);
0191         goto err_out;
0192     }
0193     if (!dev->irq) {
0194         /* if we do this, we're sure to get an IRQ since the
0195          * card has just reset and the NORXflag is on until
0196          * we tell it to start receiving.
0197          */
0198 
0199         airqmask = probe_irq_on();
0200         arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK);
0201         udelay(1);
0202         arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK);
0203         dev->irq = probe_irq_off(airqmask);
0204 
0205         if ((int)dev->irq <= 0) {
0206             arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n");
0207             goto err_out;
0208         }
0209     }
0210     release_region(ioaddr, ARCNET_TOTAL_SIZE); /* end of probing */
0211     return com90io_found(dev);
0212 
0213 err_out:
0214     release_region(ioaddr, ARCNET_TOTAL_SIZE);
0215     return -ENODEV;
0216 }
0217 
0218 /* Set up the struct net_device associated with this card.  Called after
0219  * probing succeeds.
0220  */
0221 static int __init com90io_found(struct net_device *dev)
0222 {
0223     struct arcnet_local *lp;
0224     int ioaddr = dev->base_addr;
0225     int err;
0226 
0227     /* Reserve the irq */
0228     if (request_irq(dev->irq, arcnet_interrupt, 0,
0229             "arcnet (COM90xx-IO)", dev)) {
0230         arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
0231         return -ENODEV;
0232     }
0233     /* Reserve the I/O region */
0234     if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE,
0235                 "arcnet (COM90xx-IO)")) {
0236         free_irq(dev->irq, dev);
0237         return -EBUSY;
0238     }
0239 
0240     lp = netdev_priv(dev);
0241     lp->card_name = "COM90xx I/O";
0242     lp->hw.command = com90io_command;
0243     lp->hw.status = com90io_status;
0244     lp->hw.intmask = com90io_setmask;
0245     lp->hw.reset = com90io_reset;
0246     lp->hw.owner = THIS_MODULE;
0247     lp->hw.copy_to_card = com90io_copy_to_card;
0248     lp->hw.copy_from_card = com90io_copy_from_card;
0249 
0250     lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
0251     arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
0252 
0253     /* get and check the station ID from offset 1 in shmem */
0254 
0255     arcnet_set_addr(dev, get_buffer_byte(dev, 1));
0256 
0257     err = register_netdev(dev);
0258     if (err) {
0259         arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
0260                 ioaddr, COM9026_REG_RW_CONFIG);
0261         free_irq(dev->irq, dev);
0262         release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
0263         return err;
0264     }
0265 
0266     arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n",
0267            dev->dev_addr[0], dev->base_addr, dev->irq);
0268 
0269     return 0;
0270 }
0271 
0272 /* Do a hardware reset on the card, and set up necessary registers.
0273  *
0274  * This should be called as little as possible, because it disrupts the
0275  * token on the network (causes a RECON) and requires a significant delay.
0276  *
0277  * However, it does make sure the card is in a defined state.
0278  */
0279 static int com90io_reset(struct net_device *dev, int really_reset)
0280 {
0281     struct arcnet_local *lp = netdev_priv(dev);
0282     short ioaddr = dev->base_addr;
0283 
0284     arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n",
0285            dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS));
0286 
0287     if (really_reset) {
0288         /* reset the card */
0289         arcnet_inb(ioaddr, COM9026_REG_R_RESET);
0290         mdelay(RESETtime);
0291     }
0292     /* Set the thing to IO-mapped, 8-bit  mode */
0293     lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag;
0294     arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG);
0295 
0296     arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND);
0297                     /* clear flags & end reset */
0298     arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND);
0299 
0300     /* verify that the ARCnet signature byte is present */
0301     if (get_buffer_byte(dev, 0) != TESTvalue) {
0302         arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n");
0303         return 1;
0304     }
0305     /* enable extended (512-byte) packets */
0306     arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND);
0307     /* done!  return success. */
0308     return 0;
0309 }
0310 
0311 static void com90io_command(struct net_device *dev, int cmd)
0312 {
0313     short ioaddr = dev->base_addr;
0314 
0315     arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND);
0316 }
0317 
0318 static int com90io_status(struct net_device *dev)
0319 {
0320     short ioaddr = dev->base_addr;
0321 
0322     return arcnet_inb(ioaddr, COM9026_REG_R_STATUS);
0323 }
0324 
0325 static void com90io_setmask(struct net_device *dev, int mask)
0326 {
0327     short ioaddr = dev->base_addr;
0328 
0329     arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK);
0330 }
0331 
0332 static void com90io_copy_to_card(struct net_device *dev, int bufnum,
0333                  int offset, void *buf, int count)
0334 {
0335     TIME(dev, "put_whole_buffer", count,
0336          put_whole_buffer(dev, bufnum * 512 + offset, count, buf));
0337 }
0338 
0339 static void com90io_copy_from_card(struct net_device *dev, int bufnum,
0340                    int offset, void *buf, int count)
0341 {
0342     TIME(dev, "get_whole_buffer", count,
0343          get_whole_buffer(dev, bufnum * 512 + offset, count, buf));
0344 }
0345 
0346 static int io;          /* use the insmod io= irq= shmem= options */
0347 static int irq;
0348 static char device[9];      /* use eg. device=arc1 to change name */
0349 
0350 module_param_hw(io, int, ioport, 0);
0351 module_param_hw(irq, int, irq, 0);
0352 module_param_string(device, device, sizeof(device), 0);
0353 MODULE_LICENSE("GPL");
0354 
0355 #ifndef MODULE
0356 static int __init com90io_setup(char *s)
0357 {
0358     int ints[4];
0359 
0360     s = get_options(s, 4, ints);
0361     if (!ints[0])
0362         return 0;
0363     switch (ints[0]) {
0364     default:        /* ERROR */
0365         pr_err("Too many arguments\n");
0366         fallthrough;
0367     case 2:     /* IRQ */
0368         irq = ints[2];
0369         fallthrough;
0370     case 1:     /* IO address */
0371         io = ints[1];
0372     }
0373     if (*s)
0374         snprintf(device, sizeof(device), "%s", s);
0375     return 1;
0376 }
0377 __setup("com90io=", com90io_setup);
0378 #endif
0379 
0380 static struct net_device *my_dev;
0381 
0382 static int __init com90io_init(void)
0383 {
0384     struct net_device *dev;
0385     int err;
0386 
0387     dev = alloc_arcdev(device);
0388     if (!dev)
0389         return -ENOMEM;
0390 
0391     dev->base_addr = io;
0392     dev->irq = irq;
0393     if (dev->irq == 2)
0394         dev->irq = 9;
0395 
0396     err = com90io_probe(dev);
0397 
0398     if (err) {
0399         free_arcdev(dev);
0400         return err;
0401     }
0402 
0403     my_dev = dev;
0404     return 0;
0405 }
0406 
0407 static void __exit com90io_exit(void)
0408 {
0409     struct net_device *dev = my_dev;
0410     int ioaddr = dev->base_addr;
0411 
0412     unregister_netdev(dev);
0413 
0414     /* In case the old driver is loaded later,
0415      * set the thing back to MMAP mode
0416      */
0417     arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag,
0418             ioaddr, COM9026_REG_RW_CONFIG);
0419 
0420     free_irq(dev->irq, dev);
0421     release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
0422     free_arcdev(dev);
0423 }
0424 
0425 module_init(com90io_init)
0426 module_exit(com90io_exit)