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