1 /* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
2 /*======================================================================
4 A teles S0 PCMCIA client driver
6 Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
7 Written by Christof Petig, christof.petig@wtal.de
9 Also inspired by ELSA PCMCIA driver
10 by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
12 Extentions to new hisax_pcmcia by Karsten Keil
14 minor changes to be compatible with kernel 2.4.x
15 by Jan.Schubert@GMX.li
17 ======================================================================*/
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/sched.h>
23 #include <linux/ptrace.h>
24 #include <linux/slab.h>
25 #include <linux/string.h>
26 #include <linux/timer.h>
27 #include <linux/ioport.h>
29 #include <asm/system.h>
31 #include <pcmcia/cs_types.h>
32 #include <pcmcia/cs.h>
33 #include <pcmcia/cistpl.h>
34 #include <pcmcia/cisreg.h>
35 #include <pcmcia/ds.h>
36 #include "hisax_cfg.h"
38 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");
39 MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");
40 MODULE_LICENSE("GPL");
43 All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
44 you do not define PCMCIA_DEBUG at all, all the debug code will be
45 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
46 be present but disabled -- but it can then be enabled for specific
47 modules at load time with a 'pc_debug=#' option to insmod.
51 static int pc_debug = PCMCIA_DEBUG;
52 module_param(pc_debug, int, 0);
53 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
54 static char *version =
55 "teles_cs.c 2.10 2002/07/30 22:23:34 kkeil";
57 #define DEBUG(n, args...)
60 /*====================================================================*/
62 /* Parameters that can be set with 'insmod' */
64 static int protocol = 2; /* EURO-ISDN Default */
65 module_param(protocol, int, 0);
67 /*====================================================================*/
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 teles_cs event
78 static void teles_cs_config(dev_link_t *link);
79 static void teles_cs_release(dev_link_t *link);
82 The attach() and detach() entry points are used to create and destroy
83 "instances" of the driver, where each instance represents everything
84 needed to manage one actual PCMCIA card.
87 static void teles_detach(struct pcmcia_device *p_dev);
90 A linked list of "instances" of the teles_cs device. Each actual
91 PCMCIA card corresponds to one device instance, and is described
92 by one dev_link_t structure (defined in ds.h).
94 You may not want to use a linked list for this -- for example, the
95 memory card driver uses an array of dev_link_t pointers, where minor
96 device numbers are used to derive the corresponding array index.
100 A driver needs to provide a dev_node_t structure for each device
101 on a card. In some cases, there is only one device per card (for
102 example, ethernet cards, modems). In other cases, there may be
103 many actual or logical devices (SCSI adapters, memory cards with
104 multiple partitions). The dev_node_t structures need to be kept
105 in a linked list starting at the 'dev' field of a dev_link_t
106 structure. We allocate them in the card's private data structure,
107 because they generally shouldn't be allocated dynamically.
108 In this case, we also provide a flag to indicate if a device is
109 "stopped" due to a power management event, or card ejection. The
110 device IO routines can use a flag like this to throttle IO to a
111 card that is not ready to accept it.
114 typedef struct local_info_t {
121 /*======================================================================
123 teles_attach() creates an "instance" of the driver, allocatingx
124 local data structures for one device. The device is registered
127 The dev_link structure is initialized, but we don't actually
128 configure the card at this point -- we wait until we receive a
129 card insertion event.
131 ======================================================================*/
133 static int teles_attach(struct pcmcia_device *p_dev)
138 DEBUG(0, "teles_attach()\n");
140 /* Allocate space for private device-specific data */
141 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
142 if (!local) return -ENOMEM;
143 memset(local, 0, sizeof(local_info_t));
145 link = &local->link; link->priv = local;
147 /* Interrupt setup */
148 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
149 link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;
150 link->irq.Handler = NULL;
153 General socket configuration defaults can go here. In this
154 client, we assume very little, and rely on the CIS for almost
155 everything. In most clients, many details (i.e., number, sizes,
156 and attributes of IO windows) are fixed by the nature of the
157 device, and can be hard-wired here.
159 link->io.NumPorts1 = 96;
160 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
161 link->io.IOAddrLines = 5;
163 link->conf.Attributes = CONF_ENABLE_IRQ;
164 link->conf.IntType = INT_MEMORY_AND_IO;
166 link->handle = p_dev;
167 p_dev->instance = link;
169 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
170 teles_cs_config(link);
175 /*======================================================================
177 This deletes a driver "instance". The device is de-registered
178 with Card Services. If it has been released, all local data
179 structures are freed. Otherwise, the structures will be freed
180 when the device is released.
182 ======================================================================*/
184 static void teles_detach(struct pcmcia_device *p_dev)
186 dev_link_t *link = dev_to_instance(p_dev);
187 local_info_t *info = link->priv;
189 DEBUG(0, "teles_detach(0x%p)\n", link);
191 if (link->state & DEV_CONFIG) {
193 teles_cs_release(link);
200 /*======================================================================
202 teles_cs_config() is scheduled to run after a CARD_INSERTION event
203 is received, to configure the PCMCIA socket, and to make the
204 device available to the system.
206 ======================================================================*/
207 static int get_tuple(client_handle_t handle, tuple_t *tuple,
210 int i = pcmcia_get_tuple_data(handle, tuple);
211 if (i != CS_SUCCESS) return i;
212 return pcmcia_parse_tuple(handle, tuple, parse);
215 static int first_tuple(client_handle_t handle, tuple_t *tuple,
218 int i = pcmcia_get_first_tuple(handle, tuple);
219 if (i != CS_SUCCESS) return i;
220 return get_tuple(handle, tuple, parse);
223 static int next_tuple(client_handle_t handle, tuple_t *tuple,
226 int i = pcmcia_get_next_tuple(handle, tuple);
227 if (i != CS_SUCCESS) return i;
228 return get_tuple(handle, tuple, parse);
231 static void teles_cs_config(dev_link_t *link)
233 client_handle_t handle;
239 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
242 DEBUG(0, "teles_config(0x%p)\n", link);
243 handle = link->handle;
247 This reads the card's CONFIG tuple to find its configuration
250 tuple.DesiredTuple = CISTPL_CONFIG;
251 tuple.TupleData = (cisdata_t *)buf;
252 tuple.TupleDataMax = 255;
253 tuple.TupleOffset = 0;
254 tuple.Attributes = 0;
255 i = first_tuple(handle, &tuple, &parse);
256 if (i != CS_SUCCESS) {
257 last_fn = ParseTuple;
260 link->conf.ConfigBase = parse.config.base;
261 link->conf.Present = parse.config.rmask[0];
264 link->state |= DEV_CONFIG;
266 tuple.TupleData = (cisdata_t *)buf;
267 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
268 tuple.Attributes = 0;
269 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
270 i = first_tuple(handle, &tuple, &parse);
271 while (i == CS_SUCCESS) {
272 if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
273 printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
274 link->conf.ConfigIndex = cf->index;
275 link->io.BasePort1 = cf->io.win[0].base;
276 i = pcmcia_request_io(link->handle, &link->io);
277 if (i == CS_SUCCESS) break;
279 printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
280 link->conf.ConfigIndex = cf->index;
281 for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
282 link->io.BasePort1 = j;
283 i = pcmcia_request_io(link->handle, &link->io);
284 if (i == CS_SUCCESS) break;
288 i = next_tuple(handle, &tuple, &parse);
291 if (i != CS_SUCCESS) {
296 i = pcmcia_request_irq(link->handle, &link->irq);
297 if (i != CS_SUCCESS) {
298 link->irq.AssignedIRQ = 0;
299 last_fn = RequestIRQ;
303 i = pcmcia_request_configuration(link->handle, &link->conf);
304 if (i != CS_SUCCESS) {
305 last_fn = RequestConfiguration;
309 /* At this point, the dev_node_t structure(s) should be
310 initialized and arranged in a linked list at link->dev. *//* */
311 sprintf(dev->node.dev_name, "teles");
312 dev->node.major = dev->node.minor = 0x0;
314 link->dev = &dev->node;
316 /* Finally, report what we've done */
317 printk(KERN_INFO "%s: index 0x%02x:",
318 dev->node.dev_name, link->conf.ConfigIndex);
319 if (link->conf.Attributes & CONF_ENABLE_IRQ)
320 printk(", irq %d", link->irq.AssignedIRQ);
321 if (link->io.NumPorts1)
322 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
323 link->io.BasePort1+link->io.NumPorts1-1);
324 if (link->io.NumPorts2)
325 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
326 link->io.BasePort2+link->io.NumPorts2-1);
329 link->state &= ~DEV_CONFIG_PENDING;
331 icard.para[0] = link->irq.AssignedIRQ;
332 icard.para[1] = link->io.BasePort1;
333 icard.protocol = protocol;
334 icard.typ = ISDN_CTYPE_TELESPCMCIA;
336 i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
338 printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
339 i, link->io.BasePort1);
340 teles_cs_release(link);
342 ((local_info_t*)link->priv)->cardnr = i;
346 cs_error(link->handle, last_fn, i);
347 teles_cs_release(link);
348 } /* teles_cs_config */
350 /*======================================================================
352 After a card is removed, teles_cs_release() will unregister the net
353 device, and release the PCMCIA configuration. If the device is
354 still open, this will be postponed until it is closed.
356 ======================================================================*/
358 static void teles_cs_release(dev_link_t *link)
360 local_info_t *local = link->priv;
362 DEBUG(0, "teles_cs_release(0x%p)\n", link);
365 if (local->cardnr >= 0) {
366 /* no unregister function with hisax */
367 HiSax_closecard(local->cardnr);
371 pcmcia_disable_device(link->handle);
372 } /* teles_cs_release */
374 static int teles_suspend(struct pcmcia_device *p_dev)
376 dev_link_t *link = dev_to_instance(p_dev);
377 local_info_t *dev = link->priv;
384 static int teles_resume(struct pcmcia_device *p_dev)
386 dev_link_t *link = dev_to_instance(p_dev);
387 local_info_t *dev = link->priv;
395 static struct pcmcia_device_id teles_ids[] = {
396 PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
399 MODULE_DEVICE_TABLE(pcmcia, teles_ids);
401 static struct pcmcia_driver teles_cs_driver = {
402 .owner = THIS_MODULE,
406 .probe = teles_attach,
407 .remove = teles_detach,
408 .id_table = teles_ids,
409 .suspend = teles_suspend,
410 .resume = teles_resume,
413 static int __init init_teles_cs(void)
415 return pcmcia_register_driver(&teles_cs_driver);
418 static void __exit exit_teles_cs(void)
420 pcmcia_unregister_driver(&teles_cs_driver);
423 module_init(init_teles_cs);
424 module_exit(exit_teles_cs);