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