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 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/kernel.h> 33 #include <linux/types.h> 34 #include <linux/ioport.h> 35 #include <linux/errno.h> 36 #include <linux/delay.h> 37 #include <linux/netdevice.h> 38 #include <linux/init.h> 39 #include <linux/interrupt.h> 40 #include <linux/io.h> 41 42 #include "arcdevice.h" 43 #include "com20020.h" 44 45 static const char * const clockrates[] = { 46 "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s", 47 "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", "156.25 Kb/s", 48 "Reserved", "Reserved", "Reserved" 49 }; 50 51 static void com20020_command(struct net_device *dev, int command); 52 static int com20020_status(struct net_device *dev); 53 static void com20020_setmask(struct net_device *dev, int mask); 54 static int com20020_reset(struct net_device *dev, int really_reset); 55 static void com20020_copy_to_card(struct net_device *dev, int bufnum, 56 int offset, void *buf, int count); 57 static void com20020_copy_from_card(struct net_device *dev, int bufnum, 58 int offset, void *buf, int count); 59 static void com20020_set_rx_mode(struct net_device *dev); 60 static void com20020_close(struct net_device *); 61 62 static void com20020_copy_from_card(struct net_device *dev, int bufnum, 63 int offset, void *buf, int count) 64 { 65 int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; 66 67 /* set up the address register */ 68 outb((ofs >> 8) | RDDATAflag | AUTOINCflag, 69 ioaddr + COM20020_REG_W_ADDR_HI); 70 outb(ofs & 0xff, ioaddr + COM20020_REG_W_ADDR_LO); 71 72 /* copy the data */ 73 TIME(dev, "insb", count, 74 insb(ioaddr + COM20020_REG_RW_MEMDATA, buf, count)); 75 } 76 77 static void com20020_copy_to_card(struct net_device *dev, int bufnum, 78 int offset, void *buf, int count) 79 { 80 int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; 81 82 /* set up the address register */ 83 outb((ofs >> 8) | AUTOINCflag, ioaddr + COM20020_REG_W_ADDR_HI); 84 outb(ofs & 0xff, ioaddr + COM20020_REG_W_ADDR_LO); 85 86 /* copy the data */ 87 TIME(dev, "outsb", count, 88 outsb(ioaddr + COM20020_REG_RW_MEMDATA, buf, count)); 89 } 90 91 /* Reset the card and check some basic stuff during the detection stage. */ 92 int com20020_check(struct net_device *dev) 93 { 94 int ioaddr = dev->base_addr, status; 95 struct arcnet_local *lp = netdev_priv(dev); 96 97 outb(XTOcfg(3) | RESETcfg, ioaddr + COM20020_REG_W_CONFIG); 98 udelay(5); 99 outb(XTOcfg(3), ioaddr + COM20020_REG_W_CONFIG); 100 mdelay(RESETtime); 101 102 lp->setup = lp->clockm ? 0 : (lp->clockp << 1); 103 lp->setup2 = (lp->clockm << 4) | 8; 104 105 /* CHECK: should we do this for SOHARD cards ? */ 106 /* Enable P1Mode for backplane mode */ 107 lp->setup = lp->setup | P1MODE; 108 109 com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); 110 outb(lp->setup, ioaddr + COM20020_REG_W_XREG); 111 112 if (lp->clockm != 0) { 113 com20020_set_subaddress(lp, ioaddr, SUB_SETUP2); 114 outb(lp->setup2, ioaddr + COM20020_REG_W_XREG); 115 116 /* must now write the magic "restart operation" command */ 117 mdelay(1); 118 outb(STARTIOcmd, ioaddr + COM20020_REG_W_COMMAND); 119 } 120 121 lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; 122 /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ 123 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 124 outb(0x42, ioaddr + COM20020_REG_W_XREG); 125 126 status = inb(ioaddr + COM20020_REG_R_STATUS); 127 128 if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) { 129 arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status); 130 return -ENODEV; 131 } 132 arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); 133 134 outb(CFLAGScmd | RESETclear | CONFIGclear, 135 ioaddr + COM20020_REG_W_COMMAND); 136 status = inb(ioaddr + COM20020_REG_R_STATUS); 137 arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n", 138 status); 139 140 /* Read first location of memory */ 141 outb(0 | RDDATAflag | AUTOINCflag, ioaddr + COM20020_REG_W_ADDR_HI); 142 outb(0, ioaddr + COM20020_REG_W_ADDR_LO); 143 144 status = inb(ioaddr + COM20020_REG_RW_MEMDATA); 145 if (status != TESTvalue) { 146 arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n", 147 status); 148 return -ENODEV; 149 } 150 return 0; 151 } 152 153 static int com20020_set_hwaddr(struct net_device *dev, void *addr) 154 { 155 int ioaddr = dev->base_addr; 156 struct arcnet_local *lp = netdev_priv(dev); 157 struct sockaddr *hwaddr = addr; 158 159 dev_addr_set(dev, hwaddr->sa_data); 160 com20020_set_subaddress(lp, ioaddr, SUB_NODE); 161 outb(dev->dev_addr[0], ioaddr + COM20020_REG_W_XREG); 162 163 return 0; 164 } 165 166 static int com20020_netdev_open(struct net_device *dev) 167 { 168 int ioaddr = dev->base_addr; 169 struct arcnet_local *lp = netdev_priv(dev); 170 171 lp->config |= TXENcfg; 172 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 173 174 return arcnet_open(dev); 175 } 176 177 static int com20020_netdev_close(struct net_device *dev) 178 { 179 int ioaddr = dev->base_addr; 180 struct arcnet_local *lp = netdev_priv(dev); 181 182 arcnet_close(dev); 183 184 /* disable transmitter */ 185 lp->config &= ~TXENcfg; 186 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 187 return 0; 188 } 189 190 const struct net_device_ops com20020_netdev_ops = { 191 .ndo_open = com20020_netdev_open, 192 .ndo_stop = com20020_netdev_close, 193 .ndo_start_xmit = arcnet_send_packet, 194 .ndo_tx_timeout = arcnet_timeout, 195 .ndo_set_mac_address = com20020_set_hwaddr, 196 .ndo_set_rx_mode = com20020_set_rx_mode, 197 }; 198 199 /* Set up the struct net_device associated with this card. Called after 200 * probing succeeds. 201 */ 202 int com20020_found(struct net_device *dev, int shared) 203 { 204 struct arcnet_local *lp; 205 int ioaddr = dev->base_addr; 206 207 /* Initialize the rest of the device structure. */ 208 209 lp = netdev_priv(dev); 210 211 lp->hw.owner = THIS_MODULE; 212 lp->hw.command = com20020_command; 213 lp->hw.status = com20020_status; 214 lp->hw.intmask = com20020_setmask; 215 lp->hw.reset = com20020_reset; 216 lp->hw.copy_to_card = com20020_copy_to_card; 217 lp->hw.copy_from_card = com20020_copy_from_card; 218 lp->hw.close = com20020_close; 219 220 /* FIXME: do this some other way! */ 221 if (!dev->dev_addr[0]) 222 arcnet_set_addr(dev, inb(ioaddr + 8)); 223 224 com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); 225 outb(lp->setup, ioaddr + COM20020_REG_W_XREG); 226 227 if (lp->card_flags & ARC_CAN_10MBIT) { 228 com20020_set_subaddress(lp, ioaddr, SUB_SETUP2); 229 outb(lp->setup2, ioaddr + COM20020_REG_W_XREG); 230 231 /* must now write the magic "restart operation" command */ 232 mdelay(1); 233 outb(STARTIOcmd, ioaddr + COM20020_REG_W_COMMAND); 234 } 235 236 lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; 237 /* Default 0x38 + register: Node ID */ 238 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 239 outb(dev->dev_addr[0], ioaddr + COM20020_REG_W_XREG); 240 241 /* reserve the irq */ 242 if (request_irq(dev->irq, arcnet_interrupt, shared, 243 "arcnet (COM20020)", dev)) { 244 arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); 245 return -ENODEV; 246 } 247 248 arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n", 249 lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); 250 251 if (lp->backplane) 252 arc_printk(D_NORMAL, dev, "Using backplane mode.\n"); 253 254 if (lp->timeout != 3) 255 arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n", 256 lp->timeout); 257 258 arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n", 259 lp->setup >> 1, 260 clockrates[3 - 261 ((lp->setup2 & 0xF0) >> 4) + 262 ((lp->setup & 0x0F) >> 1)]); 263 /* The clockrates array index looks very fragile. 264 * It seems like it could have negative indexing. 265 */ 266 267 if (register_netdev(dev)) { 268 free_irq(dev->irq, dev); 269 return -EIO; 270 } 271 return 0; 272 } 273 274 /* Do a hardware reset on the card, and set up necessary registers. 275 * 276 * This should be called as little as possible, because it disrupts the 277 * token on the network (causes a RECON) and requires a significant delay. 278 * 279 * However, it does make sure the card is in a defined state. 280 */ 281 static int com20020_reset(struct net_device *dev, int really_reset) 282 { 283 struct arcnet_local *lp = netdev_priv(dev); 284 u_int ioaddr = dev->base_addr; 285 u_char inbyte; 286 287 arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", 288 __FILE__, __LINE__, __func__, dev, lp, dev->name); 289 arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", 290 dev->name, inb(ioaddr + COM20020_REG_R_STATUS)); 291 292 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 293 lp->config |= (lp->timeout << 3) | (lp->backplane << 2); 294 /* power-up defaults */ 295 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 296 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 297 298 if (really_reset) { 299 /* reset the card */ 300 outb(lp->config | RESETcfg, ioaddr + COM20020_REG_W_CONFIG); 301 udelay(5); 302 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 303 mdelay(RESETtime * 2); 304 /* COM20020 seems to be slower sometimes */ 305 } 306 /* clear flags & end reset */ 307 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 308 outb(CFLAGScmd | RESETclear | CONFIGclear, 309 ioaddr + COM20020_REG_W_COMMAND); 310 311 /* verify that the ARCnet signature byte is present */ 312 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 313 314 com20020_copy_from_card(dev, 0, 0, &inbyte, 1); 315 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 316 if (inbyte != TESTvalue) { 317 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", 318 __FILE__, __LINE__, __func__); 319 arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); 320 return 1; 321 } 322 /* enable extended (512-byte) packets */ 323 outb(CONFIGcmd | EXTconf, ioaddr + COM20020_REG_W_COMMAND); 324 325 arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); 326 327 /* done! return success. */ 328 return 0; 329 } 330 331 static void com20020_setmask(struct net_device *dev, int mask) 332 { 333 u_int ioaddr = dev->base_addr; 334 335 arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr); 336 outb(mask, ioaddr + COM20020_REG_W_INTMASK); 337 } 338 339 static void com20020_command(struct net_device *dev, int cmd) 340 { 341 u_int ioaddr = dev->base_addr; 342 343 outb(cmd, ioaddr + COM20020_REG_W_COMMAND); 344 } 345 346 static int com20020_status(struct net_device *dev) 347 { 348 u_int ioaddr = dev->base_addr; 349 350 return inb(ioaddr + COM20020_REG_R_STATUS) + 351 (inb(ioaddr + COM20020_REG_R_DIAGSTAT) << 8); 352 } 353 354 static void com20020_close(struct net_device *dev) 355 { 356 struct arcnet_local *lp = netdev_priv(dev); 357 int ioaddr = dev->base_addr; 358 359 /* disable transmitter */ 360 lp->config &= ~TXENcfg; 361 outb(lp->config, ioaddr + COM20020_REG_W_CONFIG); 362 } 363 364 /* ARCnet does not support multicast, only unicast and broadcast */ 365 static void com20020_set_rx_mode(struct net_device *dev) 366 { 367 struct arcnet_local *lp = netdev_priv(dev); 368 int ioaddr = dev->base_addr; 369 370 if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { 371 /* Enable promiscuous mode */ 372 if (!(lp->setup & PROMISCset)) 373 arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); 374 com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); 375 lp->setup |= PROMISCset; 376 outb(lp->setup, ioaddr + COM20020_REG_W_XREG); 377 } else { 378 /* Disable promiscuous mode, use normal mode */ 379 if ((lp->setup & PROMISCset)) 380 arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); 381 com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); 382 lp->setup &= ~PROMISCset; 383 outb(lp->setup, ioaddr + COM20020_REG_W_XREG); 384 } 385 } 386 387 #ifdef CONFIG_ARCNET_COM20020_PCI_MODULE 388 EXPORT_SYMBOL(com20020_check); 389 EXPORT_SYMBOL(com20020_found); 390 EXPORT_SYMBOL(com20020_netdev_ops); 391 #endif 392 393 MODULE_DESCRIPTION("ARCnet COM20020 chipset core driver"); 394 MODULE_LICENSE("GPL"); 395