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 */ 50 static 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 117 out: 118 release_region(ioaddr, ARCNET_TOTAL_SIZE); 119 return err; 120 } 121 122 static int node = 0; 123 static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ 124 static int irq = 0; /* or use the insmod io= irq= shmem= options */ 125 static char device[9]; /* use eg. device="arc1" to change name */ 126 static int timeout = 3; 127 static int backplane = 0; 128 static int clockp = 0; 129 static int clockm = 0; 130 131 module_param(node, int, 0); 132 module_param_hw(io, int, ioport, 0); 133 module_param_hw(irq, int, irq, 0); 134 module_param_string(device, device, sizeof(device), 0); 135 module_param(timeout, int, 0); 136 module_param(backplane, int, 0); 137 module_param(clockp, int, 0); 138 module_param(clockm, int, 0); 139 140 MODULE_DESCRIPTION("ARCnet COM20020 chipset ISA driver"); 141 MODULE_LICENSE("GPL"); 142 143 static struct net_device *my_dev; 144 145 static int __init com20020_init(void) 146 { 147 struct net_device *dev; 148 struct arcnet_local *lp; 149 150 dev = alloc_arcdev(device); 151 if (!dev) 152 return -ENOMEM; 153 154 if (node && node != 0xff) 155 arcnet_set_addr(dev, node); 156 157 dev->netdev_ops = &com20020_netdev_ops; 158 159 lp = netdev_priv(dev); 160 lp->backplane = backplane; 161 lp->clockp = clockp & 7; 162 lp->clockm = clockm & 3; 163 lp->timeout = timeout & 3; 164 lp->hw.owner = THIS_MODULE; 165 166 dev->base_addr = io; 167 dev->irq = irq; 168 169 if (dev->irq == 2) 170 dev->irq = 9; 171 172 if (com20020isa_probe(dev)) { 173 free_arcdev(dev); 174 return -EIO; 175 } 176 177 my_dev = dev; 178 return 0; 179 } 180 181 static void __exit com20020_exit(void) 182 { 183 unregister_netdev(my_dev); 184 free_irq(my_dev->irq, my_dev); 185 release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE); 186 free_arcdev(my_dev); 187 } 188 189 #ifndef MODULE 190 static int __init com20020isa_setup(char *s) 191 { 192 int ints[8]; 193 194 s = get_options(s, 8, ints); 195 if (!ints[0]) 196 return 1; 197 198 switch (ints[0]) { 199 default: /* ERROR */ 200 pr_info("Too many arguments\n"); 201 fallthrough; 202 case 6: /* Timeout */ 203 timeout = ints[6]; 204 fallthrough; 205 case 5: /* CKP value */ 206 clockp = ints[5]; 207 fallthrough; 208 case 4: /* Backplane flag */ 209 backplane = ints[4]; 210 fallthrough; 211 case 3: /* Node ID */ 212 node = ints[3]; 213 fallthrough; 214 case 2: /* IRQ */ 215 irq = ints[2]; 216 fallthrough; 217 case 1: /* IO address */ 218 io = ints[1]; 219 } 220 if (*s) 221 snprintf(device, sizeof(device), "%s", s); 222 return 1; 223 } 224 225 __setup("com20020=", com20020isa_setup); 226 227 #endif /* MODULE */ 228 229 module_init(com20020_init) 230 module_exit(com20020_exit) 231