root/drivers/net/arcnet/com20020_cs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. regdump
  2. com20020_probe
  3. com20020_detach
  4. com20020_config
  5. com20020_release
  6. com20020_suspend
  7. com20020_resume

   1 /*
   2  * Linux ARCnet driver - COM20020 PCMCIA support
   3  *
   4  * Written 1994-1999 by Avery Pennarun,
   5  *    based on an ISA version by David Woodhouse.
   6  * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
   7  *    which was derived from pcnet_cs.c by David Hinds.
   8  * Some additional portions derived from skeleton.c by Donald Becker.
   9  *
  10  * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
  11  *  for sponsoring the further development of this driver.
  12  *
  13  * **********************
  14  *
  15  * The original copyright of skeleton.c was as follows:
  16  *
  17  * skeleton.c Written 1993 by Donald Becker.
  18  * Copyright 1993 United States Government as represented by the
  19  * Director, National Security Agency.  This software may only be used
  20  * and distributed according to the terms of the GNU General Public License as
  21  * modified by SRC, incorporated herein by reference.
  22  *
  23  * **********************
  24  * Changes:
  25  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
  26  * - reorganize kmallocs in com20020_attach, checking all for failure
  27  *   and releasing the previous allocations if one fails
  28  * **********************
  29  *
  30  * For more details, see drivers/net/arcnet.c
  31  *
  32  * **********************
  33  */
  34 
  35 #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
  36 
  37 #include <linux/kernel.h>
  38 #include <linux/ptrace.h>
  39 #include <linux/slab.h>
  40 #include <linux/string.h>
  41 #include <linux/timer.h>
  42 #include <linux/delay.h>
  43 #include <linux/module.h>
  44 #include <linux/netdevice.h>
  45 #include <linux/io.h>
  46 #include <pcmcia/cistpl.h>
  47 #include <pcmcia/ds.h>
  48 
  49 #include "arcdevice.h"
  50 #include "com20020.h"
  51 
  52 static void regdump(struct net_device *dev)
  53 {
  54 #ifdef DEBUG
  55         int ioaddr = dev->base_addr;
  56         int count;
  57 
  58         netdev_dbg(dev, "register dump:\n");
  59         for (count = 0; count < 16; count++) {
  60                 if (!(count % 16))
  61                         pr_cont("%04X:", ioaddr + count);
  62                 pr_cont(" %02X", arcnet_inb(ioaddr, count));
  63         }
  64         pr_cont("\n");
  65 
  66         netdev_dbg(dev, "buffer0 dump:\n");
  67         /* set up the address register */
  68         count = 0;
  69         arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag,
  70                     ioaddr, com20020_REG_W_ADDR_HI);
  71         arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
  72 
  73         for (count = 0; count < 256 + 32; count++) {
  74                 if (!(count % 16))
  75                         pr_cont("%04X:", count);
  76 
  77                 /* copy the data */
  78                 pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA));
  79         }
  80         pr_cont("\n");
  81 #endif
  82 }
  83 
  84 /*====================================================================*/
  85 
  86 /* Parameters that can be set with 'insmod' */
  87 
  88 static int node;
  89 static int timeout = 3;
  90 static int backplane;
  91 static int clockp;
  92 static int clockm;
  93 
  94 module_param(node, int, 0);
  95 module_param(timeout, int, 0);
  96 module_param(backplane, int, 0);
  97 module_param(clockp, int, 0);
  98 module_param(clockm, int, 0);
  99 
 100 MODULE_LICENSE("GPL");
 101 
 102 /*====================================================================*/
 103 
 104 static int com20020_config(struct pcmcia_device *link);
 105 static void com20020_release(struct pcmcia_device *link);
 106 
 107 static void com20020_detach(struct pcmcia_device *p_dev);
 108 
 109 /*====================================================================*/
 110 
 111 static int com20020_probe(struct pcmcia_device *p_dev)
 112 {
 113         struct com20020_dev *info;
 114         struct net_device *dev;
 115         struct arcnet_local *lp;
 116 
 117         dev_dbg(&p_dev->dev, "com20020_attach()\n");
 118 
 119         /* Create new network device */
 120         info = kzalloc(sizeof(*info), GFP_KERNEL);
 121         if (!info)
 122                 goto fail_alloc_info;
 123 
 124         dev = alloc_arcdev("");
 125         if (!dev)
 126                 goto fail_alloc_dev;
 127 
 128         lp = netdev_priv(dev);
 129         lp->timeout = timeout;
 130         lp->backplane = backplane;
 131         lp->clockp = clockp;
 132         lp->clockm = clockm & 3;
 133         lp->hw.owner = THIS_MODULE;
 134 
 135         /* fill in our module parameters as defaults */
 136         dev->dev_addr[0] = node;
 137 
 138         p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 139         p_dev->resource[0]->end = 16;
 140         p_dev->config_flags |= CONF_ENABLE_IRQ;
 141 
 142         info->dev = dev;
 143         p_dev->priv = info;
 144 
 145         return com20020_config(p_dev);
 146 
 147 fail_alloc_dev:
 148         kfree(info);
 149 fail_alloc_info:
 150         return -ENOMEM;
 151 } /* com20020_attach */
 152 
 153 static void com20020_detach(struct pcmcia_device *link)
 154 {
 155         struct com20020_dev *info = link->priv;
 156         struct net_device *dev = info->dev;
 157 
 158         dev_dbg(&link->dev, "detach...\n");
 159 
 160         dev_dbg(&link->dev, "com20020_detach\n");
 161 
 162         dev_dbg(&link->dev, "unregister...\n");
 163 
 164         unregister_netdev(dev);
 165 
 166         /* this is necessary because we register our IRQ separately
 167          * from card services.
 168          */
 169         if (dev->irq)
 170                 free_irq(dev->irq, dev);
 171 
 172         com20020_release(link);
 173 
 174         /* Unlink device structure, free bits */
 175         dev_dbg(&link->dev, "unlinking...\n");
 176         if (link->priv) {
 177                 dev = info->dev;
 178                 if (dev) {
 179                         dev_dbg(&link->dev, "kfree...\n");
 180                         free_netdev(dev);
 181                 }
 182                 dev_dbg(&link->dev, "kfree2...\n");
 183                 kfree(info);
 184         }
 185 
 186 } /* com20020_detach */
 187 
 188 static int com20020_config(struct pcmcia_device *link)
 189 {
 190         struct arcnet_local *lp;
 191         struct com20020_dev *info;
 192         struct net_device *dev;
 193         int i, ret;
 194         int ioaddr;
 195 
 196         info = link->priv;
 197         dev = info->dev;
 198 
 199         dev_dbg(&link->dev, "config...\n");
 200 
 201         dev_dbg(&link->dev, "com20020_config\n");
 202 
 203         dev_dbg(&link->dev, "baseport1 is %Xh\n",
 204                 (unsigned int)link->resource[0]->start);
 205 
 206         i = -ENODEV;
 207         link->io_lines = 16;
 208 
 209         if (!link->resource[0]->start) {
 210                 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) {
 211                         link->resource[0]->start = ioaddr;
 212                         i = pcmcia_request_io(link);
 213                         if (i == 0)
 214                                 break;
 215                 }
 216         } else {
 217                 i = pcmcia_request_io(link);
 218         }
 219 
 220         if (i != 0) {
 221                 dev_dbg(&link->dev, "requestIO failed totally!\n");
 222                 goto failed;
 223         }
 224 
 225         ioaddr = dev->base_addr = link->resource[0]->start;
 226         dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
 227 
 228         dev_dbg(&link->dev, "request IRQ %d\n",
 229                 link->irq);
 230         if (!link->irq) {
 231                 dev_dbg(&link->dev, "requestIRQ failed totally!\n");
 232                 goto failed;
 233         }
 234 
 235         dev->irq = link->irq;
 236 
 237         ret = pcmcia_enable_device(link);
 238         if (ret)
 239                 goto failed;
 240 
 241         if (com20020_check(dev)) {
 242                 regdump(dev);
 243                 goto failed;
 244         }
 245 
 246         lp = netdev_priv(dev);
 247         lp->card_name = "PCMCIA COM20020";
 248         lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
 249 
 250         SET_NETDEV_DEV(dev, &link->dev);
 251 
 252         i = com20020_found(dev, 0);     /* calls register_netdev */
 253 
 254         if (i != 0) {
 255                 dev_notice(&link->dev,
 256                            "com20020_found() failed\n");
 257                 goto failed;
 258         }
 259 
 260         netdev_dbg(dev, "port %#3lx, irq %d\n",
 261                    dev->base_addr, dev->irq);
 262         return 0;
 263 
 264 failed:
 265         dev_dbg(&link->dev, "com20020_config failed...\n");
 266         com20020_release(link);
 267         return -ENODEV;
 268 } /* com20020_config */
 269 
 270 static void com20020_release(struct pcmcia_device *link)
 271 {
 272         dev_dbg(&link->dev, "com20020_release\n");
 273         pcmcia_disable_device(link);
 274 }
 275 
 276 static int com20020_suspend(struct pcmcia_device *link)
 277 {
 278         struct com20020_dev *info = link->priv;
 279         struct net_device *dev = info->dev;
 280 
 281         if (link->open)
 282                 netif_device_detach(dev);
 283 
 284         return 0;
 285 }
 286 
 287 static int com20020_resume(struct pcmcia_device *link)
 288 {
 289         struct com20020_dev *info = link->priv;
 290         struct net_device *dev = info->dev;
 291 
 292         if (link->open) {
 293                 int ioaddr = dev->base_addr;
 294                 struct arcnet_local *lp = netdev_priv(dev);
 295 
 296                 arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
 297                 udelay(5);
 298                 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
 299         }
 300 
 301         return 0;
 302 }
 303 
 304 static const struct pcmcia_device_id com20020_ids[] = {
 305         PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
 306                                 "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
 307         PCMCIA_DEVICE_PROD_ID12("SoHard AG",
 308                                 "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
 309         PCMCIA_DEVICE_NULL
 310 };
 311 MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
 312 
 313 static struct pcmcia_driver com20020_cs_driver = {
 314         .owner          = THIS_MODULE,
 315         .name           = "com20020_cs",
 316         .probe          = com20020_probe,
 317         .remove         = com20020_detach,
 318         .id_table       = com20020_ids,
 319         .suspend        = com20020_suspend,
 320         .resume         = com20020_resume,
 321 };
 322 module_pcmcia_driver(com20020_cs_driver);

/* [<][>][^][v][top][bottom][index][help] */