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 #include <linux/module.h> 29 #include <linux/moduleparam.h> 30 #include <linux/kernel.h> 31 #include <linux/types.h> 32 #include <linux/ioport.h> 33 #include <linux/errno.h> 34 #include <linux/delay.h> 35 #include <linux/netdevice.h> 36 #include <linux/init.h> 37 #include <linux/bootmem.h> 38 #include <linux/arcdevice.h> 39 #include <linux/com20020.h> 40 41 #include <asm/io.h> 42 43 #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" 44 45 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 BUGLVL(D_NORMAL) printk(VERSION); 58 59 ioaddr = dev->base_addr; 60 if (!ioaddr) { 61 BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you " 62 "must specify the base address!\n"); 63 return -ENODEV; 64 } 65 if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { 66 BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n", 67 ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); 68 return -ENXIO; 69 } 70 if (ASTATUS() == 0xFF) { 71 BUGMSG(D_NORMAL, "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 BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK)); 86 outb(0, _INTMASK); 87 airqmask = probe_irq_on(); 88 outb(NORXflag, _INTMASK); 89 udelay(1); 90 outb(0, _INTMASK); 91 dev->irq = probe_irq_off(airqmask); 92 93 if ((int)dev->irq <= 0) { 94 BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n"); 95 airqmask = probe_irq_on(); 96 outb(NORXflag, _INTMASK); 97 udelay(5); 98 outb(0, _INTMASK); 99 dev->irq = probe_irq_off(airqmask); 100 if ((int)dev->irq <= 0) { 101 BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n"); 102 err = -ENODEV; 103 goto out; 104 } 105 } 106 } 107 108 lp->card_name = "ISA COM20020"; 109 if ((err = com20020_found(dev, 0)) != 0) 110 goto out; 111 112 return 0; 113 114 out: 115 release_region(ioaddr, ARCNET_TOTAL_SIZE); 116 return err; 117 } 118 119 static int node = 0; 120 static int io = 0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ 121 static int irq = 0; /* or use the insmod io= irq= shmem= options */ 122 static char device[9]; /* use eg. device="arc1" to change name */ 123 static int timeout = 3; 124 static int backplane = 0; 125 static int clockp = 0; 126 static int clockm = 0; 127 128 module_param(node, int, 0); 129 module_param(io, int, 0); 130 module_param(irq, int, 0); 131 module_param_string(device, device, sizeof(device), 0); 132 module_param(timeout, int, 0); 133 module_param(backplane, int, 0); 134 module_param(clockp, int, 0); 135 module_param(clockm, int, 0); 136 137 MODULE_LICENSE("GPL"); 138 139 static struct net_device *my_dev; 140 141 static int __init com20020_init(void) 142 { 143 struct net_device *dev; 144 struct arcnet_local *lp; 145 146 dev = alloc_arcdev(device); 147 if (!dev) 148 return -ENOMEM; 149 150 if (node && node != 0xff) 151 dev->dev_addr[0] = node; 152 153 dev->netdev_ops = &com20020_netdev_ops; 154 155 lp = netdev_priv(dev); 156 lp->backplane = backplane; 157 lp->clockp = clockp & 7; 158 lp->clockm = clockm & 3; 159 lp->timeout = timeout & 3; 160 lp->hw.owner = THIS_MODULE; 161 162 dev->base_addr = io; 163 dev->irq = irq; 164 165 if (dev->irq == 2) 166 dev->irq = 9; 167 168 if (com20020isa_probe(dev)) { 169 free_netdev(dev); 170 return -EIO; 171 } 172 173 my_dev = dev; 174 return 0; 175 } 176 177 static void __exit com20020_exit(void) 178 { 179 unregister_netdev(my_dev); 180 free_irq(my_dev->irq, my_dev); 181 release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE); 182 free_netdev(my_dev); 183 } 184 185 #ifndef MODULE 186 static int __init com20020isa_setup(char *s) 187 { 188 int ints[8]; 189 190 s = get_options(s, 8, ints); 191 if (!ints[0]) 192 return 1; 193 194 switch (ints[0]) { 195 default: /* ERROR */ 196 printk("com90xx: Too many arguments.\n"); 197 case 6: /* Timeout */ 198 timeout = ints[6]; 199 case 5: /* CKP value */ 200 clockp = ints[5]; 201 case 4: /* Backplane flag */ 202 backplane = ints[4]; 203 case 3: /* Node ID */ 204 node = ints[3]; 205 case 2: /* IRQ */ 206 irq = ints[2]; 207 case 1: /* IO address */ 208 io = ints[1]; 209 } 210 if (*s) 211 snprintf(device, sizeof(device), "%s", s); 212 return 1; 213 } 214 215 __setup("com20020=", com20020isa_setup); 216 217 #endif /* MODULE */ 218 219 module_init(com20020_init) 220 module_exit(com20020_exit) 221