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