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/sched.h>
37#include <linux/ptrace.h>
38#include <linux/slab.h>
39#include <linux/string.h>
40#include <linux/timer.h>
41#include <linux/delay.h>
42#include <linux/module.h>
43#include <asm/io.h>
44#include <asm/system.h>
45
46#include <linux/netdevice.h>
47#include <linux/arcdevice.h>
48#include <linux/com20020.h>
49
50#include <pcmcia/version.h>
51#include <pcmcia/cs_types.h>
52#include <pcmcia/cs.h>
53#include <pcmcia/cistpl.h>
54#include <pcmcia/ds.h>
55
56#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
57
58#ifdef PCMCIA_DEBUG
59
60static int pc_debug = PCMCIA_DEBUG;
61MODULE_PARM(pc_debug, "i");
62#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
63
64static void regdump(struct net_device *dev)
65{
66    int ioaddr = dev->base_addr;
67    int count;
68
69    printk("com20020 register dump:\n");
70    for (count = ioaddr; count < ioaddr + 16; count++)
71    {
72	if (!(count % 16))
73	    printk("\n%04X: ", count);
74	printk("%02X ", inb(count));
75    }
76    printk("\n");
77
78    printk("buffer0 dump:\n");
79	/* set up the address register */
80        count = 0;
81	outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
82	outb(count & 0xff, _ADDR_LO);
83
84    for (count = 0; count < 256+32; count++)
85    {
86	if (!(count % 16))
87	    printk("\n%04X: ", count);
88
89	/* copy the data */
90	printk("%02X ", inb(_MEMDATA));
91    }
92    printk("\n");
93}
94
95#else
96
97#define DEBUG(n, args...) do { } while (0)
98static inline void regdump(struct net_device *dev) { }
99
100#endif
101
102
103/*====================================================================*/
104
105/* Parameters that can be set with 'insmod' */
106
107static int node;
108static int timeout = 3;
109static int backplane;
110static int clockp;
111static int clockm;
112
113MODULE_PARM(node, "i");
114MODULE_PARM(timeout, "i");
115MODULE_PARM(backplane, "i");
116MODULE_PARM(clockp, "i");
117MODULE_PARM(clockm, "i");
118
119/* Bit map of interrupts to choose from */
120static u_int irq_mask = 0xdeb8;
121static int irq_list[4] = { -1 };
122
123MODULE_PARM(irq_mask, "i");
124MODULE_PARM(irq_list, "1-4i");
125MODULE_LICENSE("GPL");
126
127/*====================================================================*/
128
129static void com20020_config(dev_link_t *link);
130static void com20020_release(u_long arg);
131static int com20020_event(event_t event, int priority,
132                       event_callback_args_t *args);
133
134static dev_info_t dev_info = "com20020_cs";
135
136static dev_link_t *com20020_attach(void);
137static void com20020_detach(dev_link_t *);
138
139static dev_link_t *dev_list;
140
141/*====================================================================*/
142
143typedef struct com20020_dev_t {
144    struct net_device       *dev;
145    int dev_configured;
146    dev_node_t          node;
147} com20020_dev_t;
148
149/*======================================================================
150
151    This bit of code is used to avoid unregistering network devices
152    at inappropriate times.  2.2 and later kernels are fairly picky
153    about when this can happen.
154
155======================================================================*/
156
157static void flush_stale_links(void)
158{
159    dev_link_t *link, *next;
160    for (link = dev_list; link; link = next) {
161	next = link->next;
162	if (link->state & DEV_STALE_LINK)
163	    com20020_detach(link);
164    }
165}
166
167/*====================================================================*/
168
169static void cs_error(client_handle_t handle, int func, int ret)
170{
171    error_info_t err = { func, ret };
172    CardServices(ReportError, handle, &err);
173}
174
175/*======================================================================
176
177    com20020_attach() creates an "instance" of the driver, allocating
178    local data structures for one device.  The device is registered
179    with Card Services.
180
181======================================================================*/
182
183static void com20020cs_open_close(struct net_device *dev, bool open)
184{
185    if (open)
186	MOD_INC_USE_COUNT;
187    else
188	MOD_DEC_USE_COUNT;
189}
190
191static dev_link_t *com20020_attach(void)
192{
193    client_reg_t client_reg;
194    dev_link_t *link;
195    com20020_dev_t *info;
196    struct net_device *dev;
197    int i, ret;
198    struct arcnet_local *lp;
199
200    DEBUG(0, "com20020_attach()\n");
201    flush_stale_links();
202
203    /* Create new network device */
204    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
205    if (!link)
206	return NULL;
207
208    info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
209    if (!info)
210	goto fail_alloc_info;
211
212    lp =  kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
213    if (!lp)
214	goto fail_alloc_lp;
215
216    dev = dev_alloc("arc%d", &ret);
217    if (!dev)
218	goto fail_alloc_dev;
219
220    memset(info, 0, sizeof(struct com20020_dev_t));
221    memset(lp, 0, sizeof(struct arcnet_local));
222    memset(link, 0, sizeof(struct dev_link_t));
223    dev->priv = lp;
224
225    link->release.function = &com20020_release;
226    link->release.data = (u_long)link;
227    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
228    link->io.NumPorts1 = 16;
229    link->io.IOAddrLines = 16;
230    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
231    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
232    if (irq_list[0] == -1)
233	link->irq.IRQInfo2 = irq_mask;
234    else
235	for (i = 0; i < 4; i++)
236	    link->irq.IRQInfo2 |= 1 << irq_list[i];
237    link->conf.Attributes = CONF_ENABLE_IRQ;
238    link->conf.Vcc = 50;
239    link->conf.IntType = INT_MEMORY_AND_IO;
240    link->conf.Present = PRESENT_OPTION;
241
242    /* fill in our module parameters as defaults */
243    dev->dev_addr[0] = node;
244    lp->timeout = timeout;
245    lp->backplane = backplane;
246    lp->clockp = clockp;
247    lp->clockm = clockm & 3;
248    lp->hw.open_close_ll = com20020cs_open_close;
249
250    link->irq.Instance = info->dev = dev;
251    link->priv = info;
252
253    /* Register with Card Services */
254    link->next = dev_list;
255    dev_list = link;
256    client_reg.dev_info = &dev_info;
257    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
258    client_reg.EventMask =
259        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
260        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
261        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
262    client_reg.event_handler = &com20020_event;
263    client_reg.Version = 0x0210;
264    client_reg.event_callback_args.client_data = link;
265    ret = CardServices(RegisterClient, &link->handle, &client_reg);
266    if (ret != 0) {
267        cs_error(link->handle, RegisterClient, ret);
268        com20020_detach(link);
269        return NULL;
270    }
271
272    return link;
273
274fail_alloc_dev:
275    kfree(lp);
276fail_alloc_lp:
277    kfree(info);
278fail_alloc_info:
279    kfree(link);
280    return NULL;
281} /* com20020_attach */
282
283/*======================================================================
284
285    This deletes a driver "instance".  The device is de-registered
286    with Card Services.  If it has been released, all local data
287    structures are freed.  Otherwise, the structures will be freed
288    when the device is released.
289
290======================================================================*/
291
292static void com20020_detach(dev_link_t *link)
293{
294    struct com20020_dev_t *info = link->priv;
295    dev_link_t **linkp;
296    struct net_device *dev;
297
298    DEBUG(1,"detach...\n");
299
300    DEBUG(0, "com20020_detach(0x%p)\n", link);
301
302    /* Locate device structure */
303    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
304        if (*linkp == link) break;
305    if (*linkp == NULL)
306        return;
307
308    dev = info->dev;
309
310    if (link->state & DEV_CONFIG) {
311        com20020_release((u_long)link);
312        if (link->state & DEV_STALE_CONFIG) {
313            link->state |= DEV_STALE_LINK;
314            return;
315        }
316    }
317
318    if (link->handle)
319        CardServices(DeregisterClient, link->handle);
320
321    /* Unlink device structure, free bits */
322    DEBUG(1,"unlinking...\n");
323    *linkp = link->next;
324    if (link->priv)
325    {
326	dev = info->dev;
327	if (dev)
328	{
329	    if (info->dev_configured)
330	    {
331		DEBUG(1,"unregister...\n");
332
333		if (netif_running(dev))
334		    dev->stop(dev);
335
336		/*
337		 * this is necessary because we register our IRQ separately
338		 * from card services.
339		 */
340		if (dev->irq)
341		    free_irq(dev->irq, dev);
342
343		/* ...but I/O ports are done automatically by card services */
344
345		unregister_netdev(dev);
346		MOD_DEC_USE_COUNT;
347	    }
348
349	    DEBUG(1,"kfree...\n");
350	    kfree(dev->priv);
351	    kfree(dev);
352	}
353	DEBUG(1,"kfree2...\n");
354	kfree(info);
355    }
356    DEBUG(1,"kfree3...\n");
357    kfree(link);
358
359} /* com20020_detach */
360
361/*======================================================================
362
363    com20020_config() is scheduled to run after a CARD_INSERTION event
364    is received, to configure the PCMCIA socket, and to make the
365    device available to the system.
366
367======================================================================*/
368
369#define CS_CHECK(fn, args...) \
370while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
371
372static void com20020_config(dev_link_t *link)
373{
374    struct arcnet_local *lp;
375    client_handle_t handle;
376    tuple_t tuple;
377    cisparse_t parse;
378    com20020_dev_t *info;
379    struct net_device *dev;
380    int i, last_ret, last_fn;
381    u_char buf[64];
382    int ioaddr;
383
384    handle = link->handle;
385    info = link->priv;
386    dev = info->dev;
387
388    DEBUG(1,"config...\n");
389
390    DEBUG(0, "com20020_config(0x%p)\n", link);
391
392    tuple.Attributes = 0;
393    tuple.TupleData = buf;
394    tuple.TupleDataMax = 64;
395    tuple.TupleOffset = 0;
396    tuple.DesiredTuple = CISTPL_CONFIG;
397    CS_CHECK(GetFirstTuple, handle, &tuple);
398    CS_CHECK(GetTupleData, handle, &tuple);
399    CS_CHECK(ParseTuple, handle, &tuple, &parse);
400    link->conf.ConfigBase = parse.config.base;
401
402    /* Configure card */
403    link->state |= DEV_CONFIG;
404    strcpy(info->node.dev_name, dev->name);
405
406    DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
407    i = !CS_SUCCESS;
408    if (!link->io.BasePort1)
409    {
410	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
411	{
412	    link->io.BasePort1 = ioaddr;
413	    i = CardServices(RequestIO, link->handle, &link->io);
414	    if (i == CS_SUCCESS)
415		break;
416	}
417    }
418    else
419	i = CardServices(RequestIO, link->handle, &link->io);
420
421    if (i != CS_SUCCESS)
422    {
423	DEBUG(1,"arcnet: requestIO failed totally!\n");
424	goto failed;
425    }
426
427    ioaddr = dev->base_addr = link->io.BasePort1;
428    DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr);
429
430    DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
431	   link->irq.AssignedIRQ,
432	   link->irq.IRQInfo1, link->irq.IRQInfo2);
433    i = CardServices(RequestIRQ, link->handle, &link->irq);
434    if (i != CS_SUCCESS)
435    {
436	DEBUG(1,"arcnet: requestIRQ failed totally!\n");
437	goto failed;
438    }
439
440    dev->irq = link->irq.AssignedIRQ;
441
442    CS_CHECK(RequestConfiguration, link->handle, &link->conf);
443
444    if (com20020_check(dev))
445    {
446	regdump(dev);
447	goto failed;
448    }
449
450    MOD_INC_USE_COUNT;
451
452    lp = dev->priv;
453    lp->card_name = "PCMCIA COM20020";
454    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
455
456    i = com20020_found(dev, 0);
457
458    if (i != 0) {
459	DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
460	goto failed;
461    }
462
463    info->dev_configured = 1;
464    link->dev = &info->node;
465    link->state &= ~DEV_CONFIG_PENDING;
466
467    DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
468           dev->name, dev->base_addr, dev->irq);
469    return;
470
471cs_failed:
472    cs_error(link->handle, last_fn, last_ret);
473failed:
474    DEBUG(1,"com20020_config failed...\n");
475    com20020_release((u_long)link);
476} /* com20020_config */
477
478/*======================================================================
479
480    After a card is removed, com20020_release() will unregister the net
481    device, and release the PCMCIA configuration.  If the device is
482    still open, this will be postponed until it is closed.
483
484======================================================================*/
485
486static void com20020_release(u_long arg)
487{
488    dev_link_t *link = (dev_link_t *)arg;
489
490    DEBUG(1,"release...\n");
491
492    DEBUG(0, "com20020_release(0x%p)\n", link);
493
494    if (link->open) {
495	DEBUG(1,"postpone...\n");
496	DEBUG(1, "com20020_cs: release postponed, device stll open\n");
497        link->state |= DEV_STALE_CONFIG;
498        return;
499    }
500
501    CardServices(ReleaseConfiguration, link->handle);
502    CardServices(ReleaseIO, link->handle, &link->io);
503    CardServices(ReleaseIRQ, link->handle, &link->irq);
504
505    link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
506
507} /* com20020_release */
508
509/*======================================================================
510
511    The card status event handler.  Mostly, this schedules other
512    stuff to run after an event is received.  A CARD_REMOVAL event
513    also sets some flags to discourage the net drivers from trying
514    to talk to the card any more.
515
516======================================================================*/
517
518static int com20020_event(event_t event, int priority,
519			  event_callback_args_t *args)
520{
521    dev_link_t *link = args->client_data;
522    com20020_dev_t *info = link->priv;
523    struct net_device *dev = info->dev;
524
525    DEBUG(1, "com20020_event(0x%06x)\n", event);
526
527    switch (event) {
528    case CS_EVENT_CARD_REMOVAL:
529        link->state &= ~DEV_PRESENT;
530        if (link->state & DEV_CONFIG) {
531            netif_device_detach(dev);
532            link->release.expires = jiffies + HZ/20;
533            link->state |= DEV_RELEASE_PENDING;
534            add_timer(&link->release);
535        }
536        break;
537    case CS_EVENT_CARD_INSERTION:
538        link->state |= DEV_PRESENT;
539	com20020_config(link);
540	break;
541    case CS_EVENT_PM_SUSPEND:
542        link->state |= DEV_SUSPEND;
543        /* Fall through... */
544    case CS_EVENT_RESET_PHYSICAL:
545        if (link->state & DEV_CONFIG) {
546            if (link->open) {
547                netif_device_detach(dev);
548            }
549            CardServices(ReleaseConfiguration, link->handle);
550        }
551        break;
552    case CS_EVENT_PM_RESUME:
553        link->state &= ~DEV_SUSPEND;
554        /* Fall through... */
555    case CS_EVENT_CARD_RESET:
556        if (link->state & DEV_CONFIG) {
557            CardServices(RequestConfiguration, link->handle, &link->conf);
558            if (link->open) {
559		int ioaddr = dev->base_addr;
560		struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
561		ARCRESET;
562            }
563        }
564        break;
565    }
566    return 0;
567} /* com20020_event */
568
569
570/*====================================================================*/
571
572static int __init init_com20020_cs(void)
573{
574    servinfo_t serv;
575
576    DEBUG(0, "%s\n", VERSION);
577    CardServices(GetCardServicesInfo, &serv);
578    if (serv.Revision != CS_RELEASE_CODE) {
579	printk(KERN_NOTICE "com20020_cs: Card Services release "
580	       "does not match!\n");
581        return -1;
582    }
583    register_pccard_driver(&dev_info, &com20020_attach, &com20020_detach);
584    return 0;
585}
586
587static void __exit exit_com20020_cs(void)
588{
589    DEBUG(0, "com20020_cs: unloading\n");
590    unregister_pccard_driver(&dev_info);
591    while (dev_list != NULL)
592        com20020_detach(dev_list);
593}
594
595module_init(init_com20020_cs);
596module_exit(exit_com20020_cs);
597