~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/net/pcmcia/com20020_cs.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  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 #include <linux/kernel.h>
 35 #include <linux/init.h>
 36 #include <linux/ptrace.h>
 37 #include <linux/slab.h>
 38 #include <linux/string.h>
 39 #include <linux/timer.h>
 40 #include <linux/delay.h>
 41 #include <linux/module.h>
 42 #include <linux/netdevice.h>
 43 #include <linux/arcdevice.h>
 44 #include <linux/com20020.h>
 45 
 46 #include <pcmcia/cs_types.h>
 47 #include <pcmcia/cs.h>
 48 #include <pcmcia/cistpl.h>
 49 #include <pcmcia/ds.h>
 50 
 51 #include <asm/io.h>
 52 #include <asm/system.h>
 53 
 54 #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
 55 
 56 #ifdef PCMCIA_DEBUG
 57 
 58 static int pc_debug = PCMCIA_DEBUG;
 59 module_param(pc_debug, int, 0);
 60 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 61 
 62 static void regdump(struct net_device *dev)
 63 {
 64     int ioaddr = dev->base_addr;
 65     int count;
 66     
 67     printk("com20020 register dump:\n");
 68     for (count = ioaddr; count < ioaddr + 16; count++)
 69     {
 70         if (!(count % 16))
 71             printk("\n%04X: ", count);
 72         printk("%02X ", inb(count));
 73     }
 74     printk("\n");
 75     
 76     printk("buffer0 dump:\n");
 77         /* set up the address register */
 78         count = 0;
 79         outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
 80         outb(count & 0xff, _ADDR_LO);
 81     
 82     for (count = 0; count < 256+32; count++)
 83     {
 84         if (!(count % 16))
 85             printk("\n%04X: ", count);
 86         
 87         /* copy the data */
 88         printk("%02X ", inb(_MEMDATA));
 89     }
 90     printk("\n");
 91 }
 92 
 93 #else
 94 
 95 #define DEBUG(n, args...) do { } while (0)
 96 static inline void regdump(struct net_device *dev) { }
 97 
 98 #endif
 99 
100 
101 /*====================================================================*/
102 
103 /* Parameters that can be set with 'insmod' */
104 
105 static int node;
106 static int timeout = 3;
107 static int backplane;
108 static int clockp;
109 static int clockm;
110 
111 module_param(node, int, 0);
112 module_param(timeout, int, 0);
113 module_param(backplane, int, 0);
114 module_param(clockp, int, 0);
115 module_param(clockm, int, 0);
116 
117 MODULE_LICENSE("GPL");
118 
119 /*====================================================================*/
120 
121 static int com20020_config(struct pcmcia_device *link);
122 static void com20020_release(struct pcmcia_device *link);
123 
124 static void com20020_detach(struct pcmcia_device *p_dev);
125 
126 /*====================================================================*/
127 
128 typedef struct com20020_dev_t {
129     struct net_device       *dev;
130     dev_node_t          node;
131 } com20020_dev_t;
132 
133 /*======================================================================
134 
135     com20020_attach() creates an "instance" of the driver, allocating
136     local data structures for one device.  The device is registered
137     with Card Services.
138 
139 ======================================================================*/
140 
141 static int com20020_probe(struct pcmcia_device *p_dev)
142 {
143     com20020_dev_t *info;
144     struct net_device *dev;
145     struct arcnet_local *lp;
146 
147     DEBUG(0, "com20020_attach()\n");
148 
149     /* Create new network device */
150     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
151     if (!info)
152         goto fail_alloc_info;
153 
154     dev = alloc_arcdev("");
155     if (!dev)
156         goto fail_alloc_dev;
157 
158     memset(info, 0, sizeof(struct com20020_dev_t));
159     lp = dev->priv;
160     lp->timeout = timeout;
161     lp->backplane = backplane;
162     lp->clockp = clockp;
163     lp->clockm = clockm & 3;
164     lp->hw.owner = THIS_MODULE;
165 
166     /* fill in our module parameters as defaults */
167     dev->dev_addr[0] = node;
168 
169     p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
170     p_dev->io.NumPorts1 = 16;
171     p_dev->io.IOAddrLines = 16;
172     p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
173     p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
174     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
175     p_dev->conf.IntType = INT_MEMORY_AND_IO;
176     p_dev->conf.Present = PRESENT_OPTION;
177 
178     p_dev->irq.Instance = info->dev = dev;
179     p_dev->priv = info;
180 
181     return com20020_config(p_dev);
182 
183 fail_alloc_dev:
184     kfree(info);
185 fail_alloc_info:
186     return -ENOMEM;
187 } /* com20020_attach */
188 
189 /*======================================================================
190 
191     This deletes a driver "instance".  The device is de-registered
192     with Card Services.  If it has been released, all local data
193     structures are freed.  Otherwise, the structures will be freed
194     when the device is released.
195 
196 ======================================================================*/
197 
198 static void com20020_detach(struct pcmcia_device *link)
199 {
200     struct com20020_dev_t *info = link->priv;
201     struct net_device *dev = info->dev;
202 
203     DEBUG(1,"detach...\n");
204 
205     DEBUG(0, "com20020_detach(0x%p)\n", link);
206 
207     if (link->dev_node) {
208         DEBUG(1,"unregister...\n");
209 
210         unregister_netdev(dev);
211 
212         /*
213          * this is necessary because we register our IRQ separately
214          * from card services.
215          */
216         if (dev->irq)
217             free_irq(dev->irq, dev);
218     }
219 
220     com20020_release(link);
221 
222     /* Unlink device structure, free bits */
223     DEBUG(1,"unlinking...\n");
224     if (link->priv)
225     {
226         dev = info->dev;
227         if (dev)
228         {
229             DEBUG(1,"kfree...\n");
230             free_netdev(dev);
231         }
232         DEBUG(1,"kfree2...\n");
233         kfree(info);
234     }
235 
236 } /* com20020_detach */
237 
238 /*======================================================================
239 
240     com20020_config() is scheduled to run after a CARD_INSERTION event
241     is received, to configure the PCMCIA socket, and to make the
242     device available to the system.
243 
244 ======================================================================*/
245 
246 #define CS_CHECK(fn, ret) \
247 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
248 
249 static int com20020_config(struct pcmcia_device *link)
250 {
251     struct arcnet_local *lp;
252     tuple_t tuple;
253     cisparse_t parse;
254     com20020_dev_t *info;
255     struct net_device *dev;
256     int i, last_ret, last_fn;
257     u_char buf[64];
258     int ioaddr;
259 
260     info = link->priv;
261     dev = info->dev;
262 
263     DEBUG(1,"config...\n");
264 
265     DEBUG(0, "com20020_config(0x%p)\n", link);
266 
267     tuple.Attributes = 0;
268     tuple.TupleData = buf;
269     tuple.TupleDataMax = 64;
270     tuple.TupleOffset = 0;
271     tuple.DesiredTuple = CISTPL_CONFIG;
272     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
273     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
274     CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
275     link->conf.ConfigBase = parse.config.base;
276 
277     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
278     i = !CS_SUCCESS;
279     if (!link->io.BasePort1)
280     {
281         for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
282         {
283             link->io.BasePort1 = ioaddr;
284             i = pcmcia_request_io(link, &link->io);
285             if (i == CS_SUCCESS)
286                 break;
287         }
288     }
289     else
290         i = pcmcia_request_io(link, &link->io);
291     
292     if (i != CS_SUCCESS)
293     {
294         DEBUG(1,"arcnet: requestIO failed totally!\n");
295         goto failed;
296     }
297         
298     ioaddr = dev->base_addr = link->io.BasePort1;
299     DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
300 
301     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
302            link->irq.AssignedIRQ,
303            link->irq.IRQInfo1, link->irq.IRQInfo2);
304     i = pcmcia_request_irq(link, &link->irq);
305     if (i != CS_SUCCESS)
306     {
307         DEBUG(1,"arcnet: requestIRQ failed totally!\n");
308         goto failed;
309     }
310 
311     dev->irq = link->irq.AssignedIRQ;
312 
313     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
314 
315     if (com20020_check(dev))
316     {
317         regdump(dev);
318         goto failed;
319     }
320     
321     lp = dev->priv;
322     lp->card_name = "PCMCIA COM20020";
323     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
324 
325     link->dev_node = &info->node;
326     SET_NETDEV_DEV(dev, &handle_to_dev(link));
327 
328     i = com20020_found(dev, 0); /* calls register_netdev */
329     
330     if (i != 0) {
331         DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
332         link->dev_node = NULL;
333         goto failed;
334     }
335 
336     strcpy(info->node.dev_name, dev->name);
337 
338     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
339            dev->name, dev->base_addr, dev->irq);
340     return 0;
341 
342 cs_failed:
343     cs_error(link, last_fn, last_ret);
344 failed:
345     DEBUG(1,"com20020_config failed...\n");
346     com20020_release(link);
347     return -ENODEV;
348 } /* com20020_config */
349 
350 /*======================================================================
351 
352     After a card is removed, com20020_release() will unregister the net
353     device, and release the PCMCIA configuration.  If the device is
354     still open, this will be postponed until it is closed.
355 
356 ======================================================================*/
357 
358 static void com20020_release(struct pcmcia_device *link)
359 {
360         DEBUG(0, "com20020_release(0x%p)\n", link);
361         pcmcia_disable_device(link);
362 }
363 
364 static int com20020_suspend(struct pcmcia_device *link)
365 {
366         com20020_dev_t *info = link->priv;
367         struct net_device *dev = info->dev;
368 
369         if (link->open)
370                 netif_device_detach(dev);
371 
372         return 0;
373 }
374 
375 static int com20020_resume(struct pcmcia_device *link)
376 {
377         com20020_dev_t *info = link->priv;
378         struct net_device *dev = info->dev;
379 
380         if (link->open) {
381                 int ioaddr = dev->base_addr;
382                 struct arcnet_local *lp = dev->priv;
383                 ARCRESET;
384         }
385 
386         return 0;
387 }
388 
389 static struct pcmcia_device_id com20020_ids[] = {
390         PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
391         PCMCIA_DEVICE_NULL
392 };
393 MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
394 
395 static struct pcmcia_driver com20020_cs_driver = {
396         .owner          = THIS_MODULE,
397         .drv            = {
398                 .name   = "com20020_cs",
399         },
400         .probe          = com20020_probe,
401         .remove         = com20020_detach,
402         .id_table       = com20020_ids,
403         .suspend        = com20020_suspend,
404         .resume         = com20020_resume,
405 };
406 
407 static int __init init_com20020_cs(void)
408 {
409         return pcmcia_register_driver(&com20020_cs_driver);
410 }
411 
412 static void __exit exit_com20020_cs(void)
413 {
414         pcmcia_unregister_driver(&com20020_cs_driver);
415 }
416 
417 module_init(init_com20020_cs);
418 module_exit(exit_com20020_cs);
419 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.