com20020-isa.c (5581B)
1/* 2 * Linux ARCnet driver - COM20020 chipset support 3 * 4 * Written 1997 by David Woodhouse. 5 * Written 1994-1999 by Avery Pennarun. 6 * Written 1999-2000 by Martin Mares <mj@ucw.cz>. 7 * Derived from skeleton.c by Donald Becker. 8 * 9 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) 10 * for sponsoring the further development of this driver. 11 * 12 * ********************** 13 * 14 * The original copyright of skeleton.c was as follows: 15 * 16 * skeleton.c Written 1993 by Donald Becker. 17 * Copyright 1993 United States Government as represented by the 18 * Director, National Security Agency. This software may only be used 19 * and distributed according to the terms of the GNU General Public License as 20 * modified by SRC, incorporated herein by reference. 21 * 22 * ********************** 23 * 24 * For more details, see drivers/net/arcnet.c 25 * 26 * ********************** 27 */ 28 29#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt 30 31#include <linux/module.h> 32#include <linux/moduleparam.h> 33#include <linux/kernel.h> 34#include <linux/types.h> 35#include <linux/ioport.h> 36#include <linux/errno.h> 37#include <linux/delay.h> 38#include <linux/netdevice.h> 39#include <linux/init.h> 40#include <linux/interrupt.h> 41#include <linux/memblock.h> 42#include <linux/io.h> 43 44#include "arcdevice.h" 45#include "com20020.h" 46 47/* We cannot (yet) probe for an IO mapped card, although we can check that 48 * it's where we were told it was, and even do autoirq. 49 */ 50static int __init com20020isa_probe(struct net_device *dev) 51{ 52 int ioaddr; 53 unsigned long airqmask; 54 struct arcnet_local *lp = netdev_priv(dev); 55 int err; 56 57 if (BUGLVL(D_NORMAL)) 58 pr_info("%s\n", "COM20020 ISA support (by David Woodhouse et al.)"); 59 60 ioaddr = dev->base_addr; 61 if (!ioaddr) { 62 arc_printk(D_NORMAL, dev, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); 63 return -ENODEV; 64 } 65 if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { 66 arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n", 67 ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); 68 return -ENXIO; 69 } 70 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { 71 arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr); 72 err = -ENODEV; 73 goto out; 74 } 75 if (com20020_check(dev)) { 76 err = -ENODEV; 77 goto out; 78 } 79 80 if (!dev->irq) { 81 /* if we do this, we're sure to get an IRQ since the 82 * card has just reset and the NORXflag is on until 83 * we tell it to start receiving. 84 */ 85 arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n", 86 arcnet_inb(ioaddr, COM20020_REG_R_STATUS)); 87 arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); 88 airqmask = probe_irq_on(); 89 arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK); 90 udelay(1); 91 arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); 92 dev->irq = probe_irq_off(airqmask); 93 94 if ((int)dev->irq <= 0) { 95 arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n"); 96 airqmask = probe_irq_on(); 97 arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK); 98 udelay(5); 99 arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); 100 dev->irq = probe_irq_off(airqmask); 101 if ((int)dev->irq <= 0) { 102 arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n"); 103 err = -ENODEV; 104 goto out; 105 } 106 } 107 } 108 109 lp->card_name = "ISA COM20020"; 110 111 err = com20020_found(dev, 0); 112 if (err != 0) 113 goto out; 114 115 return 0; 116 117out: 118 release_region(ioaddr, ARCNET_TOTAL_SIZE); 119 return err; 120} 121 122static int node = 0; 123static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ 124static int irq = 0; /* or use the insmod io= irq= shmem= options */ 125static char device[9]; /* use eg. device="arc1" to change name */ 126static int timeout = 3; 127static int backplane = 0; 128static int clockp = 0; 129static int clockm = 0; 130 131module_param(node, int, 0); 132module_param_hw(io, int, ioport, 0); 133module_param_hw(irq, int, irq, 0); 134module_param_string(device, device, sizeof(device), 0); 135module_param(timeout, int, 0); 136module_param(backplane, int, 0); 137module_param(clockp, int, 0); 138module_param(clockm, int, 0); 139 140MODULE_LICENSE("GPL"); 141 142static struct net_device *my_dev; 143 144static int __init com20020_init(void) 145{ 146 struct net_device *dev; 147 struct arcnet_local *lp; 148 149 dev = alloc_arcdev(device); 150 if (!dev) 151 return -ENOMEM; 152 153 if (node && node != 0xff) 154 arcnet_set_addr(dev, node); 155 156 dev->netdev_ops = &com20020_netdev_ops; 157 158 lp = netdev_priv(dev); 159 lp->backplane = backplane; 160 lp->clockp = clockp & 7; 161 lp->clockm = clockm & 3; 162 lp->timeout = timeout & 3; 163 lp->hw.owner = THIS_MODULE; 164 165 dev->base_addr = io; 166 dev->irq = irq; 167 168 if (dev->irq == 2) 169 dev->irq = 9; 170 171 if (com20020isa_probe(dev)) { 172 free_arcdev(dev); 173 return -EIO; 174 } 175 176 my_dev = dev; 177 return 0; 178} 179 180static void __exit com20020_exit(void) 181{ 182 unregister_netdev(my_dev); 183 free_irq(my_dev->irq, my_dev); 184 release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE); 185 free_arcdev(my_dev); 186} 187 188#ifndef MODULE 189static int __init com20020isa_setup(char *s) 190{ 191 int ints[8]; 192 193 s = get_options(s, 8, ints); 194 if (!ints[0]) 195 return 1; 196 197 switch (ints[0]) { 198 default: /* ERROR */ 199 pr_info("Too many arguments\n"); 200 fallthrough; 201 case 6: /* Timeout */ 202 timeout = ints[6]; 203 fallthrough; 204 case 5: /* CKP value */ 205 clockp = ints[5]; 206 fallthrough; 207 case 4: /* Backplane flag */ 208 backplane = ints[4]; 209 fallthrough; 210 case 3: /* Node ID */ 211 node = ints[3]; 212 fallthrough; 213 case 2: /* IRQ */ 214 irq = ints[2]; 215 fallthrough; 216 case 1: /* IO address */ 217 io = ints[1]; 218 } 219 if (*s) 220 snprintf(device, sizeof(device), "%s", s); 221 return 1; 222} 223 224__setup("com20020=", com20020isa_setup); 225 226#endif /* MODULE */ 227 228module_init(com20020_init) 229module_exit(com20020_exit)