Pull motherboard into release branch
[linux-2.6] / drivers / isdn / hisax / sedlbauer_cs.c
1 /*======================================================================
2
3     A Sedlbauer PCMCIA client driver
4
5     This driver is for the Sedlbauer Speed Star and Speed Star II, 
6     which are ISDN PCMCIA Cards.
7     
8     The contents of this file are subject to the Mozilla Public
9     License Version 1.1 (the "License"); you may not use this file
10     except in compliance with the License. You may obtain a copy of
11     the License at http://www.mozilla.org/MPL/
12
13     Software distributed under the License is distributed on an "AS
14     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15     implied. See the License for the specific language governing
16     rights and limitations under the License.
17
18     The initial developer of the original code is David A. Hinds
19     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
20     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
21
22     Modifications from dummy_cs.c are Copyright (C) 1999-2001 Marcus Niemann
23     <maniemann@users.sourceforge.net>. All Rights Reserved.
24
25     Alternatively, the contents of this file may be used under the
26     terms of the GNU General Public License version 2 (the "GPL"), in
27     which case the provisions of the GPL are applicable instead of the
28     above.  If you wish to allow the use of your version of this file
29     only under the terms of the GPL and not to allow others to use
30     your version of this file under the MPL, indicate your decision
31     by deleting the provisions above and replace them with the notice
32     and other provisions required by the GPL.  If you do not delete
33     the provisions above, a recipient may use your version of this
34     file under either the MPL or the GPL.
35     
36 ======================================================================*/
37
38 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41 #include <linux/sched.h>
42 #include <linux/ptrace.h>
43 #include <linux/slab.h>
44 #include <linux/string.h>
45 #include <linux/timer.h>
46 #include <linux/ioport.h>
47 #include <asm/io.h>
48 #include <asm/system.h>
49
50 #include <pcmcia/cs_types.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/cistpl.h>
53 #include <pcmcia/cisreg.h>
54 #include <pcmcia/ds.h>
55 #include "hisax_cfg.h"
56
57 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");
58 MODULE_AUTHOR("Marcus Niemann");
59 MODULE_LICENSE("Dual MPL/GPL");
60
61 /*
62    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
63    you do not define PCMCIA_DEBUG at all, all the debug code will be
64    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
65    be present but disabled -- but it can then be enabled for specific
66    modules at load time with a 'pc_debug=#' option to insmod.
67 */
68
69 #ifdef PCMCIA_DEBUG
70 static int pc_debug = PCMCIA_DEBUG;
71 module_param(pc_debug, int, 0);
72 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); 
73 static char *version =
74 "sedlbauer_cs.c 1.1a 2001/01/28 15:04:04 (M.Niemann)";
75 #else
76 #define DEBUG(n, args...)
77 #endif
78
79
80 /*====================================================================*/
81
82 /* Parameters that can be set with 'insmod' */
83
84 static int protocol = 2;        /* EURO-ISDN Default */
85 module_param(protocol, int, 0);
86
87 /*====================================================================*/
88
89 /*
90    The event() function is this driver's Card Services event handler.
91    It will be called by Card Services when an appropriate card status
92    event is received.  The config() and release() entry points are
93    used to configure or release a socket, in response to card
94    insertion and ejection events.  They are invoked from the sedlbauer
95    event handler. 
96 */
97
98 static int sedlbauer_config(struct pcmcia_device *link);
99 static void sedlbauer_release(struct pcmcia_device *link);
100
101 /*
102    The attach() and detach() entry points are used to create and destroy
103    "instances" of the driver, where each instance represents everything
104    needed to manage one actual PCMCIA card.
105 */
106
107 static void sedlbauer_detach(struct pcmcia_device *p_dev);
108
109 /*
110    You'll also need to prototype all the functions that will actually
111    be used to talk to your device.  See 'memory_cs' for a good example
112    of a fully self-sufficient driver; the other drivers rely more or
113    less on other parts of the kernel.
114 */
115
116 /*
117    A driver needs to provide a dev_node_t structure for each device
118    on a card.  In some cases, there is only one device per card (for
119    example, ethernet cards, modems).  In other cases, there may be
120    many actual or logical devices (SCSI adapters, memory cards with
121    multiple partitions).  The dev_node_t structures need to be kept
122    in a linked list starting at the 'dev' field of a struct pcmcia_device
123    structure.  We allocate them in the card's private data structure,
124    because they generally shouldn't be allocated dynamically.
125
126    In this case, we also provide a flag to indicate if a device is
127    "stopped" due to a power management event, or card ejection.  The
128    device IO routines can use a flag like this to throttle IO to a
129    card that is not ready to accept it.
130 */
131    
132 typedef struct local_info_t {
133         struct pcmcia_device    *p_dev;
134     dev_node_t          node;
135     int                 stop;
136     int                 cardnr;
137 } local_info_t;
138
139 /*======================================================================
140
141     sedlbauer_attach() creates an "instance" of the driver, allocating
142     local data structures for one device.  The device is registered
143     with Card Services.
144
145     The dev_link structure is initialized, but we don't actually
146     configure the card at this point -- we wait until we receive a
147     card insertion event.
148     
149 ======================================================================*/
150
151 static int sedlbauer_probe(struct pcmcia_device *link)
152 {
153     local_info_t *local;
154
155     DEBUG(0, "sedlbauer_attach()\n");
156
157     /* Allocate space for private device-specific data */
158     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
159     if (!local) return -ENOMEM;
160     memset(local, 0, sizeof(local_info_t));
161     local->cardnr = -1;
162
163     local->p_dev = link;
164     link->priv = local;
165
166     /* Interrupt setup */
167     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
168     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
169     link->irq.Handler = NULL;
170
171     /*
172       General socket configuration defaults can go here.  In this
173       client, we assume very little, and rely on the CIS for almost
174       everything.  In most clients, many details (i.e., number, sizes,
175       and attributes of IO windows) are fixed by the nature of the
176       device, and can be hard-wired here.
177     */
178
179     /* from old sedl_cs 
180     */
181     /* The io structure describes IO port mapping */
182     link->io.NumPorts1 = 8;
183     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
184     link->io.IOAddrLines = 3;
185
186     link->conf.Attributes = 0;
187     link->conf.IntType = INT_MEMORY_AND_IO;
188
189     return sedlbauer_config(link);
190 } /* sedlbauer_attach */
191
192 /*======================================================================
193
194     This deletes a driver "instance".  The device is de-registered
195     with Card Services.  If it has been released, all local data
196     structures are freed.  Otherwise, the structures will be freed
197     when the device is released.
198
199 ======================================================================*/
200
201 static void sedlbauer_detach(struct pcmcia_device *link)
202 {
203         DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
204
205         ((local_info_t *)link->priv)->stop = 1;
206         sedlbauer_release(link);
207
208         /* This points to the parent local_info_t struct */
209         kfree(link->priv);
210 } /* sedlbauer_detach */
211
212 /*======================================================================
213
214     sedlbauer_config() is scheduled to run after a CARD_INSERTION event
215     is received, to configure the PCMCIA socket, and to make the
216     device available to the system.
217     
218 ======================================================================*/
219 #define CS_CHECK(fn, ret) \
220 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
221
222 static int sedlbauer_config(struct pcmcia_device *link)
223 {
224     local_info_t *dev = link->priv;
225     tuple_t tuple;
226     cisparse_t parse;
227     int last_fn, last_ret;
228     u8 buf[64];
229     config_info_t conf;
230     win_req_t req;
231     memreq_t map;
232     IsdnCard_t  icard;
233
234     DEBUG(0, "sedlbauer_config(0x%p)\n", link);
235
236     /*
237        This reads the card's CONFIG tuple to find its configuration
238        registers.
239     */
240     tuple.DesiredTuple = CISTPL_CONFIG;
241     tuple.Attributes = 0;
242     tuple.TupleData = buf;
243     tuple.TupleDataMax = sizeof(buf);
244     tuple.TupleOffset = 0;
245     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
246     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
247     CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
248     link->conf.ConfigBase = parse.config.base;
249     link->conf.Present = parse.config.rmask[0];
250
251     CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
252
253     /*
254       In this loop, we scan the CIS for configuration table entries,
255       each of which describes a valid card configuration, including
256       voltage, IO window, memory window, and interrupt settings.
257
258       We make no assumptions about the card to be configured: we use
259       just the information available in the CIS.  In an ideal world,
260       this would work for any PCMCIA card, but it requires a complete
261       and accurate CIS.  In practice, a driver usually "knows" most of
262       these things without consulting the CIS, and most client drivers
263       will only use the CIS to fill in implementation-defined details.
264     */
265     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
266     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
267     while (1) {
268         cistpl_cftable_entry_t dflt = { 0 };
269         cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
270         if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
271                 pcmcia_parse_tuple(link, &tuple, &parse) != 0)
272             goto next_entry;
273
274         if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
275         if (cfg->index == 0) goto next_entry;
276         link->conf.ConfigIndex = cfg->index;
277         
278         /* Does this card need audio output? */
279         if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
280             link->conf.Attributes |= CONF_ENABLE_SPKR;
281             link->conf.Status = CCSR_AUDIO_ENA;
282         }
283         
284         /* Use power settings for Vcc and Vpp if present */
285         /*  Note that the CIS values need to be rescaled */
286         if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
287             if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
288                 goto next_entry;
289         } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
290             if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
291                 goto next_entry;
292         }
293             
294         if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
295             link->conf.Vpp =
296                 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
297         else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
298             link->conf.Vpp =
299                 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
300         
301         /* Do we need to allocate an interrupt? */
302         if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
303             link->conf.Attributes |= CONF_ENABLE_IRQ;
304         
305         /* IO window settings */
306         link->io.NumPorts1 = link->io.NumPorts2 = 0;
307         if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
308             cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
309             link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
310             if (!(io->flags & CISTPL_IO_8BIT))
311                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
312             if (!(io->flags & CISTPL_IO_16BIT))
313                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
314 /* new in dummy.cs 2001/01/28 MN 
315             link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
316 */
317             link->io.BasePort1 = io->win[0].base;
318             link->io.NumPorts1 = io->win[0].len;
319             if (io->nwin > 1) {
320                 link->io.Attributes2 = link->io.Attributes1;
321                 link->io.BasePort2 = io->win[1].base;
322                 link->io.NumPorts2 = io->win[1].len;
323             }
324             /* This reserves IO space but doesn't actually enable it */
325             if (pcmcia_request_io(link, &link->io) != 0)
326                 goto next_entry;
327         }
328
329         /*
330           Now set up a common memory window, if needed.  There is room
331           in the struct pcmcia_device structure for one memory window handle,
332           but if the base addresses need to be saved, or if multiple
333           windows are needed, the info should go in the private data
334           structure for this device.
335
336           Note that the memory window base is a physical address, and
337           needs to be mapped to virtual space with ioremap() before it
338           is used.
339         */
340         if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
341             cistpl_mem_t *mem =
342                 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
343             req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
344             req.Attributes |= WIN_ENABLE;
345             req.Base = mem->win[0].host_addr;
346             req.Size = mem->win[0].len;
347 /* new in dummy.cs 2001/01/28 MN 
348             if (req.Size < 0x1000)
349                 req.Size = 0x1000;
350 */
351             req.AccessSpeed = 0;
352             if (pcmcia_request_window(&link, &req, &link->win) != 0)
353                 goto next_entry;
354             map.Page = 0; map.CardOffset = mem->win[0].card_addr;
355             if (pcmcia_map_mem_page(link->win, &map) != 0)
356                 goto next_entry;
357         }
358         /* If we got this far, we're cool! */
359         break;
360
361     next_entry:
362         CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
363     }
364
365     /*
366        Allocate an interrupt line.  Note that this does not assign a
367        handler to the interrupt, unless the 'Handler' member of the
368        irq structure is initialized.
369     */
370     if (link->conf.Attributes & CONF_ENABLE_IRQ)
371         CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
372         
373     /*
374        This actually configures the PCMCIA socket -- setting up
375        the I/O windows and the interrupt mapping, and putting the
376        card and host interface into "Memory and IO" mode.
377     */
378     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
379
380     /*
381       At this point, the dev_node_t structure(s) need to be
382       initialized and arranged in a linked list at link->dev.
383     */
384     sprintf(dev->node.dev_name, "sedlbauer");
385     dev->node.major = dev->node.minor = 0;
386     link->dev_node = &dev->node;
387
388     /* Finally, report what we've done */
389     printk(KERN_INFO "%s: index 0x%02x:",
390            dev->node.dev_name, link->conf.ConfigIndex);
391     if (link->conf.Vpp)
392         printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
393     if (link->conf.Attributes & CONF_ENABLE_IRQ)
394         printk(", irq %d", link->irq.AssignedIRQ);
395     if (link->io.NumPorts1)
396         printk(", io 0x%04x-0x%04x", link->io.BasePort1,
397                link->io.BasePort1+link->io.NumPorts1-1);
398     if (link->io.NumPorts2)
399         printk(" & 0x%04x-0x%04x", link->io.BasePort2,
400                link->io.BasePort2+link->io.NumPorts2-1);
401     if (link->win)
402         printk(", mem 0x%06lx-0x%06lx", req.Base,
403                req.Base+req.Size-1);
404     printk("\n");
405
406     icard.para[0] = link->irq.AssignedIRQ;
407     icard.para[1] = link->io.BasePort1;
408     icard.protocol = protocol;
409     icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
410     
411     last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard);
412     if (last_ret < 0) {
413         printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
414                 last_ret, link->io.BasePort1);
415         sedlbauer_release(link);
416         return -ENODEV;
417     } else
418         ((local_info_t*)link->priv)->cardnr = last_ret;
419
420     return 0;
421
422 cs_failed:
423     cs_error(link, last_fn, last_ret);
424     sedlbauer_release(link);
425     return -ENODEV;
426
427 } /* sedlbauer_config */
428
429 /*======================================================================
430
431     After a card is removed, sedlbauer_release() will unregister the
432     device, and release the PCMCIA configuration.  If the device is
433     still open, this will be postponed until it is closed.
434     
435 ======================================================================*/
436
437 static void sedlbauer_release(struct pcmcia_device *link)
438 {
439     local_info_t *local = link->priv;
440     DEBUG(0, "sedlbauer_release(0x%p)\n", link);
441
442     if (local) {
443         if (local->cardnr >= 0) {
444             /* no unregister function with hisax */
445             HiSax_closecard(local->cardnr);
446         }
447     }
448
449     pcmcia_disable_device(link);
450 } /* sedlbauer_release */
451
452 static int sedlbauer_suspend(struct pcmcia_device *link)
453 {
454         local_info_t *dev = link->priv;
455
456         dev->stop = 1;
457
458         return 0;
459 }
460
461 static int sedlbauer_resume(struct pcmcia_device *link)
462 {
463         local_info_t *dev = link->priv;
464
465         dev->stop = 0;
466
467         return 0;
468 }
469
470
471 static struct pcmcia_device_id sedlbauer_ids[] = {
472         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
473         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
474         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
475         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
476         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c),
477         PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae),
478 /*      PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/
479         PCMCIA_DEVICE_NULL
480 };
481 MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
482
483 static struct pcmcia_driver sedlbauer_driver = {
484         .owner          = THIS_MODULE,
485         .drv            = {
486                 .name   = "sedlbauer_cs",
487         },
488         .probe          = sedlbauer_probe,
489         .remove         = sedlbauer_detach,
490         .id_table       = sedlbauer_ids,
491         .suspend        = sedlbauer_suspend,
492         .resume         = sedlbauer_resume,
493 };
494
495 static int __init init_sedlbauer_cs(void)
496 {
497         return pcmcia_register_driver(&sedlbauer_driver);
498 }
499
500 static void __exit exit_sedlbauer_cs(void)
501 {
502         pcmcia_unregister_driver(&sedlbauer_driver);
503 }
504
505 module_init(init_sedlbauer_cs);
506 module_exit(exit_sedlbauer_cs);