File: /usr/src/linux/drivers/isdn/avmb1/avm_cs.c

1     /*======================================================================
2     
3         A PCMCIA client driver for AVM B1/M1/M2
4     
5         Written by Carsten Paeth, calle@calle.in-berlin.de
6         
7     ======================================================================*/
8     
9     #include <linux/module.h>
10     #include <linux/kernel.h>
11     #include <linux/init.h>
12     #include <linux/sched.h>
13     #include <linux/ptrace.h>
14     #include <linux/slab.h>
15     #include <linux/string.h>
16     #include <linux/timer.h>
17     #include <linux/tty.h>
18     #include <linux/serial.h>
19     #include <linux/major.h>
20     #include <asm/io.h>
21     #include <asm/system.h>
22     
23     #include <pcmcia/version.h>
24     #include <pcmcia/cs_types.h>
25     #include <pcmcia/cs.h>
26     #include <pcmcia/cistpl.h>
27     #include <pcmcia/ciscode.h>
28     #include <pcmcia/ds.h>
29     #include <pcmcia/cisreg.h>
30     
31     #include <linux/skbuff.h>
32     #include <linux/capi.h>
33     #include <linux/b1lli.h>
34     #include <linux/b1pcmcia.h>
35     
36     /*====================================================================*/
37     
38     /* Parameters that can be set with 'insmod' */
39     
40     /* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */
41     static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 };
42     static int irq_list[10] = { -1 };
43     
44     MODULE_PARM(irq_list, "1-10i");
45     
46     /*====================================================================*/
47     
48     /*
49        The event() function is this driver's Card Services event handler.
50        It will be called by Card Services when an appropriate card status
51        event is received.  The config() and release() entry points are
52        used to configure or release a socket, in response to card insertion
53        and ejection events.  They are invoked from the skeleton event
54        handler.
55     */
56     
57     static void avmcs_config(dev_link_t *link);
58     static void avmcs_release(u_long arg);
59     static int avmcs_event(event_t event, int priority,
60     			  event_callback_args_t *args);
61     
62     /*
63        The attach() and detach() entry points are used to create and destroy
64        "instances" of the driver, where each instance represents everything
65        needed to manage one actual PCMCIA card.
66     */
67     
68     static dev_link_t *avmcs_attach(void);
69     static void avmcs_detach(dev_link_t *);
70     
71     /*
72        The dev_info variable is the "key" that is used to match up this
73        device driver with appropriate cards, through the card configuration
74        database.
75     */
76     
77     static dev_info_t dev_info = "avm_cs";
78     
79     /*
80        A linked list of "instances" of the skeleton device.  Each actual
81        PCMCIA card corresponds to one device instance, and is described
82        by one dev_link_t structure (defined in ds.h).
83     
84        You may not want to use a linked list for this -- for example, the
85        memory card driver uses an array of dev_link_t pointers, where minor
86        device numbers are used to derive the corresponding array index.
87     */
88     
89     static dev_link_t *dev_list = NULL;
90     
91     /*
92        A dev_link_t structure has fields for most things that are needed
93        to keep track of a socket, but there will usually be some device
94        specific information that also needs to be kept track of.  The
95        'priv' pointer in a dev_link_t structure can be used to point to
96        a device-specific private data structure, like this.
97     
98        A driver needs to provide a dev_node_t structure for each device
99        on a card.  In some cases, there is only one device per card (for
100        example, ethernet cards, modems).  In other cases, there may be
101        many actual or logical devices (SCSI adapters, memory cards with
102        multiple partitions).  The dev_node_t structures need to be kept
103        in a linked list starting at the 'dev' field of a dev_link_t
104        structure.  We allocate them in the card's private data structure,
105        because they generally can't be allocated dynamically.
106     */
107        
108     typedef struct local_info_t {
109         dev_node_t	node;
110     } local_info_t;
111     
112     /*====================================================================*/
113     
114     static void cs_error(client_handle_t handle, int func, int ret)
115     {
116         error_info_t err = { func, ret };
117         CardServices(ReportError, handle, &err);
118     }
119     
120     /*======================================================================
121     
122         avmcs_attach() creates an "instance" of the driver, allocating
123         local data structures for one device.  The device is registered
124         with Card Services.
125     
126         The dev_link structure is initialized, but we don't actually
127         configure the card at this point -- we wait until we receive a
128         card insertion event.
129         
130     ======================================================================*/
131     
132     static dev_link_t *avmcs_attach(void)
133     {
134         client_reg_t client_reg;
135         dev_link_t *link;
136         local_info_t *local;
137         int ret, i;
138         
139         /* Initialize the dev_link_t structure */
140         link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
141         if (!link)
142     	return NULL;
143         memset(link, 0, sizeof(struct dev_link_t));
144         link->release.function = &avmcs_release;
145         link->release.data = (u_long)link;
146     
147         /* The io structure describes IO port mapping */
148         link->io.NumPorts1 = 16;
149         link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
150         link->io.NumPorts2 = 0;
151     
152         /* Interrupt setup */
153         link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
154         link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
155     
156         link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
157         if (irq_list[0] != -1) {
158     	    for (i = 0; i < 10 && irq_list[i] > 0; i++)
159     	       link->irq.IRQInfo2 |= 1 << irq_list[i];
160         } else {
161     	    for (i = 0; i < 10 && default_irq_list[i] > 0; i++)
162     	       link->irq.IRQInfo2 |= 1 << default_irq_list[i];
163         }
164         
165         /* General socket configuration */
166         link->conf.Attributes = CONF_ENABLE_IRQ;
167         link->conf.Vcc = 50;
168         link->conf.IntType = INT_MEMORY_AND_IO;
169         link->conf.ConfigIndex = 1;
170         link->conf.Present = PRESENT_OPTION;
171     
172         /* Allocate space for private device-specific data */
173         local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
174         if (!local)
175     	return NULL;
176         memset(local, 0, sizeof(local_info_t));
177         link->priv = local;
178         
179         /* Register with Card Services */
180         link->next = dev_list;
181         dev_list = link;
182         client_reg.dev_info = &dev_info;
183         client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
184         client_reg.EventMask =
185     	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
186     	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
187     	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
188         client_reg.event_handler = &avmcs_event;
189         client_reg.Version = 0x0210;
190         client_reg.event_callback_args.client_data = link;
191         ret = CardServices(RegisterClient, &link->handle, &client_reg);
192         if (ret != 0) {
193     	cs_error(link->handle, RegisterClient, ret);
194     	avmcs_detach(link);
195     	return NULL;
196         }
197     
198         return link;
199     } /* avmcs_attach */
200     
201     /*======================================================================
202     
203         This deletes a driver "instance".  The device is de-registered
204         with Card Services.  If it has been released, all local data
205         structures are freed.  Otherwise, the structures will be freed
206         when the device is released.
207     
208     ======================================================================*/
209     
210     static void avmcs_detach(dev_link_t *link)
211     {
212         dev_link_t **linkp;
213     
214         /* Locate device structure */
215         for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
216     	if (*linkp == link) break;
217         if (*linkp == NULL)
218     	return;
219     
220         /*
221            If the device is currently configured and active, we won't
222            actually delete it yet.  Instead, it is marked so that when
223            the release() function is called, that will trigger a proper
224            detach().
225         */
226         if (link->state & DEV_CONFIG) {
227     	link->state |= DEV_STALE_LINK;
228     	return;
229         }
230     
231         /* Break the link with Card Services */
232         if (link->handle)
233     	CardServices(DeregisterClient, link->handle);
234         
235         /* Unlink device structure, free pieces */
236         *linkp = link->next;
237         if (link->priv) {
238     	kfree(link->priv);
239         }
240         kfree(link);
241         
242     } /* avmcs_detach */
243     
244     /*======================================================================
245     
246         avmcs_config() is scheduled to run after a CARD_INSERTION event
247         is received, to configure the PCMCIA socket, and to make the
248         ethernet device available to the system.
249         
250     ======================================================================*/
251     
252     static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
253     		     cisparse_t *parse)
254     {
255         int i;
256         i = CardServices(fn, handle, tuple);
257         if (i != CS_SUCCESS) return i;
258         i = CardServices(GetTupleData, handle, tuple);
259         if (i != CS_SUCCESS) return i;
260         return CardServices(ParseTuple, handle, tuple, parse);
261     }
262     
263     #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
264     #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
265     
266     static void avmcs_config(dev_link_t *link)
267     {
268         client_handle_t handle;
269         tuple_t tuple;
270         cisparse_t parse;
271         cistpl_cftable_entry_t *cf = &parse.cftable_entry;
272         local_info_t *dev;
273         int i;
274         u_char buf[64];
275         char devname[128];
276         int cardtype;
277         int (*addcard)(unsigned int port, unsigned irq);
278         
279         handle = link->handle;
280         dev = link->priv;
281     
282         /*
283            This reads the card's CONFIG tuple to find its configuration
284            registers.
285         */
286         do {
287     	tuple.DesiredTuple = CISTPL_CONFIG;
288     	i = CardServices(GetFirstTuple, handle, &tuple);
289     	if (i != CS_SUCCESS) break;
290     	tuple.TupleData = buf;
291     	tuple.TupleDataMax = 64;
292     	tuple.TupleOffset = 0;
293     	i = CardServices(GetTupleData, handle, &tuple);
294     	if (i != CS_SUCCESS) break;
295     	i = CardServices(ParseTuple, handle, &tuple, &parse);
296     	if (i != CS_SUCCESS) break;
297     	link->conf.ConfigBase = parse.config.base;
298         } while (0);
299         if (i != CS_SUCCESS) {
300     	cs_error(link->handle, ParseTuple, i);
301     	link->state &= ~DEV_CONFIG_PENDING;
302     	return;
303         }
304         
305         /* Configure card */
306         link->state |= DEV_CONFIG;
307     
308         do {
309     
310     	tuple.Attributes = 0;
311     	tuple.TupleData = buf;
312     	tuple.TupleDataMax = 254;
313     	tuple.TupleOffset = 0;
314     	tuple.DesiredTuple = CISTPL_VERS_1;
315     
316     	devname[0] = 0;
317     	if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
318     	    strncpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
319     			sizeof(devname));
320     	}
321     	/*
322              * find IO port
323              */
324     	tuple.TupleData = (cisdata_t *)buf;
325     	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
326     	tuple.Attributes = 0;
327     	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
328     	i = first_tuple(handle, &tuple, &parse);
329     	while (i == CS_SUCCESS) {
330     	    if (cf->io.nwin > 0) {
331     		link->conf.ConfigIndex = cf->index;
332     		link->io.BasePort1 = cf->io.win[0].base;
333     		link->io.NumPorts1 = cf->io.win[0].len;
334     		link->io.NumPorts2 = 0;
335                     printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
336     			link->io.BasePort1,
337     		        link->io.BasePort1+link->io.NumPorts1-1);
338     		i = CardServices(RequestIO, link->handle, &link->io);
339     		if (i == CS_SUCCESS) goto found_port;
340     	    }
341     	    i = next_tuple(handle, &tuple, &parse);
342     	}
343     
344     found_port:
345     	if (i != CS_SUCCESS) {
346     	    cs_error(link->handle, RequestIO, i);
347     	    break;
348     	}
349     	
350     	/*
351     	 * allocate an interrupt line
352     	 */
353     	i = CardServices(RequestIRQ, link->handle, &link->irq);
354     	if (i != CS_SUCCESS) {
355     	    cs_error(link->handle, RequestIRQ, i);
356     	    CardServices(ReleaseIO, link->handle, &link->io);
357     	    break;
358     	}
359     	
360     	/*
361              * configure the PCMCIA socket
362     	  */
363     	i = CardServices(RequestConfiguration, link->handle, &link->conf);
364     	if (i != CS_SUCCESS) {
365     	    cs_error(link->handle, RequestConfiguration, i);
366     	    CardServices(ReleaseIO, link->handle, &link->io);
367     	    CardServices(ReleaseIRQ, link->handle, &link->irq);
368     	    break;
369     	}
370     
371         } while (0);
372     
373         /* At this point, the dev_node_t structure(s) should be
374            initialized and arranged in a linked list at link->dev. */
375     
376         if (devname[0]) {
377     	char *s = strrchr(devname, ' ');
378     	if (!s)
379     	   s = devname;
380     	else s++;
381     	strcpy(dev->node.dev_name, s);
382             if (strcmp("M1", s) == 0) {
383                cardtype = AVM_CARDTYPE_M1;
384             } else if (strcmp("M2", s) == 0) {
385                cardtype = AVM_CARDTYPE_M2;
386     	} else {
387                cardtype = AVM_CARDTYPE_B1;
388     	}
389         } else {
390             strcpy(dev->node.dev_name, "b1");
391             cardtype = AVM_CARDTYPE_B1;
392         }
393     
394         dev->node.major = 64;
395         dev->node.minor = 0;
396         link->dev = &dev->node;
397         
398         link->state &= ~DEV_CONFIG_PENDING;
399         /* If any step failed, release any partially configured state */
400         if (i != 0) {
401     	avmcs_release((u_long)link);
402     	return;
403         }
404     
405     
406         switch (cardtype) {
407             case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
408             case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
409     	default:
410             case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
411         }
412         if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
413             printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
414     		dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
415     	avmcs_release((u_long)link);
416     	return;
417         }
418         dev->node.minor = i;
419     
420     } /* avmcs_config */
421     
422     /*======================================================================
423     
424         After a card is removed, avmcs_release() will unregister the net
425         device, and release the PCMCIA configuration.  If the device is
426         still open, this will be postponed until it is closed.
427         
428     ======================================================================*/
429     
430     static void avmcs_release(u_long arg)
431     {
432         dev_link_t *link = (dev_link_t *)arg;
433     
434         /*
435            If the device is currently in use, we won't release until it
436            is actually closed.
437         */
438         if (link->open) {
439     	link->state |= DEV_STALE_CONFIG;
440     	return;
441         }
442     
443         b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
444     
445         /* Unlink the device chain */
446         link->dev = NULL;
447         
448         /* Don't bother checking to see if these succeed or not */
449         CardServices(ReleaseConfiguration, link->handle);
450         CardServices(ReleaseIO, link->handle, &link->io);
451         CardServices(ReleaseIRQ, link->handle, &link->irq);
452         link->state &= ~DEV_CONFIG;
453         
454         if (link->state & DEV_STALE_LINK)
455     	avmcs_detach(link);
456         
457     } /* avmcs_release */
458     
459     /*======================================================================
460     
461         The card status event handler.  Mostly, this schedules other
462         stuff to run after an event is received.  A CARD_REMOVAL event
463         also sets some flags to discourage the net drivers from trying
464         to talk to the card any more.
465     
466         When a CARD_REMOVAL event is received, we immediately set a flag
467         to block future accesses to this device.  All the functions that
468         actually access the device should check this flag to make sure
469         the card is still present.
470         
471     ======================================================================*/
472     
473     static int avmcs_event(event_t event, int priority,
474     			  event_callback_args_t *args)
475     {
476         dev_link_t *link = args->client_data;
477     
478         switch (event) {
479         case CS_EVENT_CARD_REMOVAL:
480     	link->state &= ~DEV_PRESENT;
481     	if (link->state & DEV_CONFIG) {
482     	    link->release.expires = jiffies + (HZ/20);
483     	    add_timer(&link->release);
484     	}
485     	break;
486         case CS_EVENT_CARD_INSERTION:
487     	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
488     	avmcs_config(link);
489     	break;
490         case CS_EVENT_PM_SUSPEND:
491     	link->state |= DEV_SUSPEND;
492     	/* Fall through... */
493         case CS_EVENT_RESET_PHYSICAL:
494     	if (link->state & DEV_CONFIG)
495     	    CardServices(ReleaseConfiguration, link->handle);
496     	break;
497         case CS_EVENT_PM_RESUME:
498     	link->state &= ~DEV_SUSPEND;
499     	/* Fall through... */
500         case CS_EVENT_CARD_RESET:
501     	if (link->state & DEV_CONFIG)
502     	    CardServices(RequestConfiguration, link->handle, &link->conf);
503     	break;
504         }
505         return 0;
506     } /* avmcs_event */
507     
508     /*====================================================================*/
509     
510     static int __init avmcs_init(void)
511     {
512         servinfo_t serv;
513         CardServices(GetCardServicesInfo, &serv);
514         if (serv.Revision != CS_RELEASE_CODE) {
515     	printk(KERN_NOTICE "avm_cs: Card Services release "
516     	       "does not match!\n");
517     	return -1;
518         }
519         register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach);
520         return 0;
521     }
522     
523     static void __exit avmcs_exit(void)
524     {
525         unregister_pccard_driver(&dev_info);
526         while (dev_list != NULL) {
527     	if (dev_list->state & DEV_CONFIG)
528     	    avmcs_release((u_long)dev_list);
529     	avmcs_detach(dev_list);
530         }
531     }
532     
533     module_init(avmcs_init);
534     module_exit(avmcs_exit);
535