1 /* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $
3 * A PCMCIA client driver for AVM B1/M1/M2
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
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>
23 #include <asm/system.h>
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>
32 #include <linux/skbuff.h>
33 #include <linux/capi.h>
34 #include <linux/b1lli.h>
35 #include <linux/b1pcmcia.h>
37 /*====================================================================*/
39 MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
40 MODULE_AUTHOR("Carsten Paeth");
41 MODULE_LICENSE("GPL");
43 /*====================================================================*/
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
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);
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.
65 static dev_link_t *avmcs_attach(void);
66 static void avmcs_detach(struct pcmcia_device *p_dev);
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
74 static dev_info_t dev_info = "avm_cs";
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).
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.
87 A driver needs to provide a dev_node_t structure for each device
88 on a card. In some cases, there is only one device per card (for
89 example, ethernet cards, modems). In other cases, there may be
90 many actual or logical devices (SCSI adapters, memory cards with
91 multiple partitions). The dev_node_t structures need to be kept
92 in a linked list starting at the 'dev' field of a dev_link_t
93 structure. We allocate them in the card's private data structure,
94 because they generally can't be allocated dynamically.
97 typedef struct local_info_t {
101 /*======================================================================
103 avmcs_attach() creates an "instance" of the driver, allocating
104 local data structures for one device. The device is registered
107 The dev_link structure is initialized, but we don't actually
108 configure the card at this point -- we wait until we receive a
109 card insertion event.
111 ======================================================================*/
113 static dev_link_t *avmcs_attach(void)
115 client_reg_t client_reg;
120 /* Initialize the dev_link_t structure */
121 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
124 memset(link, 0, sizeof(struct dev_link_t));
126 /* The io structure describes IO port mapping */
127 link->io.NumPorts1 = 16;
128 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
129 link->io.NumPorts2 = 0;
131 /* Interrupt setup */
132 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
133 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
135 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
137 /* General socket configuration */
138 link->conf.Attributes = CONF_ENABLE_IRQ;
140 link->conf.IntType = INT_MEMORY_AND_IO;
141 link->conf.ConfigIndex = 1;
142 link->conf.Present = PRESENT_OPTION;
144 /* Allocate space for private device-specific data */
145 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
148 memset(local, 0, sizeof(local_info_t));
151 /* Register with Card Services */
153 client_reg.dev_info = &dev_info;
154 client_reg.Version = 0x0210;
155 client_reg.event_callback_args.client_data = link;
156 ret = pcmcia_register_client(&link->handle, &client_reg);
158 cs_error(link->handle, RegisterClient, ret);
159 avmcs_detach(link->handle);
170 /*======================================================================
172 This deletes a driver "instance". The device is de-registered
173 with Card Services. If it has been released, all local data
174 structures are freed. Otherwise, the structures will be freed
175 when the device is released.
177 ======================================================================*/
179 static void avmcs_detach(struct pcmcia_device *p_dev)
181 dev_link_t *link = dev_to_instance(p_dev);
183 if (link->state & DEV_CONFIG)
190 /*======================================================================
192 avmcs_config() is scheduled to run after a CARD_INSERTION event
193 is received, to configure the PCMCIA socket, and to make the
194 ethernet device available to the system.
196 ======================================================================*/
198 static int get_tuple(client_handle_t handle, tuple_t *tuple,
201 int i = pcmcia_get_tuple_data(handle, tuple);
202 if (i != CS_SUCCESS) return i;
203 return pcmcia_parse_tuple(handle, tuple, parse);
206 static int first_tuple(client_handle_t handle, tuple_t *tuple,
209 int i = pcmcia_get_first_tuple(handle, tuple);
210 if (i != CS_SUCCESS) return i;
211 return get_tuple(handle, tuple, parse);
214 static int next_tuple(client_handle_t handle, tuple_t *tuple,
217 int i = pcmcia_get_next_tuple(handle, tuple);
218 if (i != CS_SUCCESS) return i;
219 return get_tuple(handle, tuple, parse);
222 static void avmcs_config(dev_link_t *link)
224 client_handle_t handle;
227 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
233 int (*addcard)(unsigned int port, unsigned irq);
235 handle = link->handle;
239 This reads the card's CONFIG tuple to find its configuration
243 tuple.DesiredTuple = CISTPL_CONFIG;
244 i = pcmcia_get_first_tuple(handle, &tuple);
245 if (i != CS_SUCCESS) break;
246 tuple.TupleData = buf;
247 tuple.TupleDataMax = 64;
248 tuple.TupleOffset = 0;
249 i = pcmcia_get_tuple_data(handle, &tuple);
250 if (i != CS_SUCCESS) break;
251 i = pcmcia_parse_tuple(handle, &tuple, &parse);
252 if (i != CS_SUCCESS) break;
253 link->conf.ConfigBase = parse.config.base;
255 if (i != CS_SUCCESS) {
256 cs_error(link->handle, ParseTuple, i);
257 link->state &= ~DEV_CONFIG_PENDING;
262 link->state |= DEV_CONFIG;
266 tuple.Attributes = 0;
267 tuple.TupleData = buf;
268 tuple.TupleDataMax = 254;
269 tuple.TupleOffset = 0;
270 tuple.DesiredTuple = CISTPL_VERS_1;
273 if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
274 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
280 tuple.TupleData = (cisdata_t *)buf;
281 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
282 tuple.Attributes = 0;
283 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
284 i = first_tuple(handle, &tuple, &parse);
285 while (i == CS_SUCCESS) {
286 if (cf->io.nwin > 0) {
287 link->conf.ConfigIndex = cf->index;
288 link->io.BasePort1 = cf->io.win[0].base;
289 link->io.NumPorts1 = cf->io.win[0].len;
290 link->io.NumPorts2 = 0;
291 printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
293 link->io.BasePort1+link->io.NumPorts1-1);
294 i = pcmcia_request_io(link->handle, &link->io);
295 if (i == CS_SUCCESS) goto found_port;
297 i = next_tuple(handle, &tuple, &parse);
301 if (i != CS_SUCCESS) {
302 cs_error(link->handle, RequestIO, i);
307 * allocate an interrupt line
309 i = pcmcia_request_irq(link->handle, &link->irq);
310 if (i != CS_SUCCESS) {
311 cs_error(link->handle, RequestIRQ, i);
312 pcmcia_release_io(link->handle, &link->io);
317 * configure the PCMCIA socket
319 i = pcmcia_request_configuration(link->handle, &link->conf);
320 if (i != CS_SUCCESS) {
321 cs_error(link->handle, RequestConfiguration, i);
322 pcmcia_release_io(link->handle, &link->io);
323 pcmcia_release_irq(link->handle, &link->irq);
329 /* At this point, the dev_node_t structure(s) should be
330 initialized and arranged in a linked list at link->dev. */
333 char *s = strrchr(devname, ' ');
337 strcpy(dev->node.dev_name, s);
338 if (strcmp("M1", s) == 0) {
339 cardtype = AVM_CARDTYPE_M1;
340 } else if (strcmp("M2", s) == 0) {
341 cardtype = AVM_CARDTYPE_M2;
343 cardtype = AVM_CARDTYPE_B1;
346 strcpy(dev->node.dev_name, "b1");
347 cardtype = AVM_CARDTYPE_B1;
350 dev->node.major = 64;
352 link->dev = &dev->node;
354 link->state &= ~DEV_CONFIG_PENDING;
355 /* If any step failed, release any partially configured state */
363 case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
364 case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
366 case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
368 if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
369 printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
370 dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
378 /*======================================================================
380 After a card is removed, avmcs_release() will unregister the net
381 device, and release the PCMCIA configuration. If the device is
382 still open, this will be postponed until it is closed.
384 ======================================================================*/
386 static void avmcs_release(dev_link_t *link)
388 b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
390 /* Unlink the device chain */
393 /* Don't bother checking to see if these succeed or not */
394 pcmcia_release_configuration(link->handle);
395 pcmcia_release_io(link->handle, &link->io);
396 pcmcia_release_irq(link->handle, &link->irq);
397 link->state &= ~DEV_CONFIG;
398 } /* avmcs_release */
400 static int avmcs_suspend(struct pcmcia_device *dev)
402 dev_link_t *link = dev_to_instance(dev);
404 link->state |= DEV_SUSPEND;
405 if (link->state & DEV_CONFIG)
406 pcmcia_release_configuration(link->handle);
411 static int avmcs_resume(struct pcmcia_device *dev)
413 dev_link_t *link = dev_to_instance(dev);
415 link->state &= ~DEV_SUSPEND;
416 if (link->state & DEV_CONFIG)
417 pcmcia_request_configuration(link->handle, &link->conf);
422 /*======================================================================
424 The card status event handler. Mostly, this schedules other
425 stuff to run after an event is received. A CARD_REMOVAL event
426 also sets some flags to discourage the net drivers from trying
427 to talk to the card any more.
429 When a CARD_REMOVAL event is received, we immediately set a flag
430 to block future accesses to this device. All the functions that
431 actually access the device should check this flag to make sure
432 the card is still present.
434 ======================================================================*/
436 static int avmcs_event(event_t event, int priority,
437 event_callback_args_t *args)
439 dev_link_t *link = args->client_data;
442 case CS_EVENT_CARD_INSERTION:
443 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
450 static struct pcmcia_device_id avmcs_ids[] = {
451 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
452 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430),
453 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a),
456 MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
458 static struct pcmcia_driver avmcs_driver = {
459 .owner = THIS_MODULE,
463 .attach = avmcs_attach,
464 .event = avmcs_event,
465 .remove = avmcs_detach,
466 .id_table = avmcs_ids,
467 .suspend= avmcs_suspend,
468 .resume = avmcs_resume,
471 static int __init avmcs_init(void)
473 return pcmcia_register_driver(&avmcs_driver);
476 static void __exit avmcs_exit(void)
478 pcmcia_unregister_driver(&avmcs_driver);
481 module_init(avmcs_init);
482 module_exit(avmcs_exit);