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_LICENSE("GPL"); 141 142 static struct net_device *my_dev; 143 144 static 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 180 static 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 189 static 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 228 module_init(com20020_init) 229 module_exit(com20020_exit) 230