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