[PATCH] pcmcia: remove unneeded Vcc pseudo setting
[pandora-kernel.git] / drivers / isdn / hisax / teles_cs.c
1 /* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
2 /*======================================================================
3
4     A teles S0 PCMCIA client driver
5
6     Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
7     Written by Christof Petig, christof.petig@wtal.de
8     
9     Also inspired by ELSA PCMCIA driver 
10     by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
11     
12     Extentions to new hisax_pcmcia by Karsten Keil
13
14     minor changes to be compatible with kernel 2.4.x
15     by Jan.Schubert@GMX.li
16
17 ======================================================================*/
18
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>
28 #include <asm/io.h>
29 #include <asm/system.h>
30
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"
37
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");
41
42 /*
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.
48 */
49
50 #ifdef PCMCIA_DEBUG
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";
56 #else
57 #define DEBUG(n, args...)
58 #endif
59
60 /*====================================================================*/
61
62 /* Parameters that can be set with 'insmod' */
63
64 static int protocol = 2;        /* EURO-ISDN Default */
65 module_param(protocol, int, 0);
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 teles_cs event
75    handler.
76 */
77
78 static void teles_cs_config(dev_link_t *link);
79 static void teles_cs_release(dev_link_t *link);
80
81 /*
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.
85 */
86
87 static void teles_detach(struct pcmcia_device *p_dev);
88
89 /*
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).
93
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.
97 */
98
99 /*
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.
112 */
113
114 typedef struct local_info_t {
115     dev_link_t          link;
116     dev_node_t          node;
117     int                 busy;
118     int                 cardnr;
119 } local_info_t;
120
121 /*======================================================================
122
123     teles_attach() creates an "instance" of the driver, allocatingx
124     local data structures for one device.  The device is registered
125     with Card Services.
126
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.
130
131 ======================================================================*/
132
133 static int teles_attach(struct pcmcia_device *p_dev)
134 {
135     dev_link_t *link;
136     local_info_t *local;
137
138     DEBUG(0, "teles_attach()\n");
139
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));
144     local->cardnr = -1;
145     link = &local->link; link->priv = local;
146
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;
151
152     /*
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.
158     */
159     link->io.NumPorts1 = 96;
160     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
161     link->io.IOAddrLines = 5;
162
163     link->conf.Attributes = CONF_ENABLE_IRQ;
164     link->conf.IntType = INT_MEMORY_AND_IO;
165
166     link->handle = p_dev;
167     p_dev->instance = link;
168
169     link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
170     teles_cs_config(link);
171
172     return 0;
173 } /* teles_attach */
174
175 /*======================================================================
176
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.
181
182 ======================================================================*/
183
184 static void teles_detach(struct pcmcia_device *p_dev)
185 {
186     dev_link_t *link = dev_to_instance(p_dev);
187     local_info_t *info = link->priv;
188
189     DEBUG(0, "teles_detach(0x%p)\n", link);
190
191     if (link->state & DEV_CONFIG) {
192             info->busy = 1;
193             teles_cs_release(link);
194     }
195
196     kfree(info);
197
198 } /* teles_detach */
199
200 /*======================================================================
201
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.
205
206 ======================================================================*/
207 static int get_tuple(client_handle_t handle, tuple_t *tuple,
208                      cisparse_t *parse)
209 {
210     int i = pcmcia_get_tuple_data(handle, tuple);
211     if (i != CS_SUCCESS) return i;
212     return pcmcia_parse_tuple(handle, tuple, parse);
213 }
214
215 static int first_tuple(client_handle_t handle, tuple_t *tuple,
216                      cisparse_t *parse)
217 {
218     int i = pcmcia_get_first_tuple(handle, tuple);
219     if (i != CS_SUCCESS) return i;
220     return get_tuple(handle, tuple, parse);
221 }
222
223 static int next_tuple(client_handle_t handle, tuple_t *tuple,
224                      cisparse_t *parse)
225 {
226     int i = pcmcia_get_next_tuple(handle, tuple);
227     if (i != CS_SUCCESS) return i;
228     return get_tuple(handle, tuple, parse);
229 }
230
231 static void teles_cs_config(dev_link_t *link)
232 {
233     client_handle_t handle;
234     tuple_t tuple;
235     cisparse_t parse;
236     local_info_t *dev;
237     int i, j, last_fn;
238     u_short buf[128];
239     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
240     IsdnCard_t icard;
241
242     DEBUG(0, "teles_config(0x%p)\n", link);
243     handle = link->handle;
244     dev = link->priv;
245
246     /*
247        This reads the card's CONFIG tuple to find its configuration
248        registers.
249     */
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;
258         goto cs_failed;
259     }
260     link->conf.ConfigBase = parse.config.base;
261     link->conf.Present = parse.config.rmask[0];
262
263     /* Configure card */
264     link->state |= DEV_CONFIG;
265
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;
278         } else {
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;
285           }
286           break;
287         }
288         i = next_tuple(handle, &tuple, &parse);
289     }
290
291     if (i != CS_SUCCESS) {
292         last_fn = RequestIO;
293         goto cs_failed;
294     }
295
296     i = pcmcia_request_irq(link->handle, &link->irq);
297     if (i != CS_SUCCESS) {
298         link->irq.AssignedIRQ = 0;
299         last_fn = RequestIRQ;
300         goto cs_failed;
301     }
302
303     i = pcmcia_request_configuration(link->handle, &link->conf);
304     if (i != CS_SUCCESS) {
305       last_fn = RequestConfiguration;
306       goto cs_failed;
307     }
308
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;
313
314     link->dev = &dev->node;
315
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);
327     printk("\n");
328
329     link->state &= ~DEV_CONFIG_PENDING;
330
331     icard.para[0] = link->irq.AssignedIRQ;
332     icard.para[1] = link->io.BasePort1;
333     icard.protocol = protocol;
334     icard.typ = ISDN_CTYPE_TELESPCMCIA;
335     
336     i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
337     if (i < 0) {
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);
341     } else
342         ((local_info_t*)link->priv)->cardnr = i;
343
344     return;
345 cs_failed:
346     cs_error(link->handle, last_fn, i);
347     teles_cs_release(link);
348 } /* teles_cs_config */
349
350 /*======================================================================
351
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.
355
356 ======================================================================*/
357
358 static void teles_cs_release(dev_link_t *link)
359 {
360     local_info_t *local = link->priv;
361
362     DEBUG(0, "teles_cs_release(0x%p)\n", link);
363
364     if (local) {
365         if (local->cardnr >= 0) {
366             /* no unregister function with hisax */
367             HiSax_closecard(local->cardnr);
368         }
369     }
370
371     pcmcia_disable_device(link->handle);
372 } /* teles_cs_release */
373
374 static int teles_suspend(struct pcmcia_device *p_dev)
375 {
376         dev_link_t *link = dev_to_instance(p_dev);
377         local_info_t *dev = link->priv;
378
379         dev->busy = 1;
380
381         return 0;
382 }
383
384 static int teles_resume(struct pcmcia_device *p_dev)
385 {
386         dev_link_t *link = dev_to_instance(p_dev);
387         local_info_t *dev = link->priv;
388
389         dev->busy = 0;
390
391         return 0;
392 }
393
394
395 static struct pcmcia_device_id teles_ids[] = {
396         PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
397         PCMCIA_DEVICE_NULL,
398 };
399 MODULE_DEVICE_TABLE(pcmcia, teles_ids);
400
401 static struct pcmcia_driver teles_cs_driver = {
402         .owner          = THIS_MODULE,
403         .drv            = {
404                 .name   = "teles_cs",
405         },
406         .probe          = teles_attach,
407         .remove         = teles_detach,
408         .id_table       = teles_ids,
409         .suspend        = teles_suspend,
410         .resume         = teles_resume,
411 };
412
413 static int __init init_teles_cs(void)
414 {
415         return pcmcia_register_driver(&teles_cs_driver);
416 }
417
418 static void __exit exit_teles_cs(void)
419 {
420         pcmcia_unregister_driver(&teles_cs_driver);
421 }
422
423 module_init(init_teles_cs);
424 module_exit(exit_teles_cs);