isdn: Cleanup Sections in PCMCIA driver sedlbauer
[linux-2.6.git] / 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/ptrace.h>
42 #include <linux/slab.h>
43 #include <linux/string.h>
44 #include <linux/timer.h>
45 #include <linux/ioport.h>
46 #include <asm/io.h>
47 #include <asm/system.h>
48
49 #include <pcmcia/cs_types.h>
50 #include <pcmcia/cs.h>
51 #include <pcmcia/cistpl.h>
52 #include <pcmcia/cisreg.h>
53 #include <pcmcia/ds.h>
54 #include "hisax_cfg.h"
55
56 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");
57 MODULE_AUTHOR("Marcus Niemann");
58 MODULE_LICENSE("Dual MPL/GPL");
59
60
61 /*====================================================================*/
62
63 /* Parameters that can be set with 'insmod' */
64
65 static int protocol = 2;        /* EURO-ISDN Default */
66 module_param(protocol, int, 0);
67
68 /*====================================================================*/
69
70 /*
71    The event() function is this driver's Card Services event handler.
72    It will be called by Card Services when an appropriate card status
73    event is received.  The config() and release() entry points are
74    used to configure or release a socket, in response to card
75    insertion and ejection events.  They are invoked from the sedlbauer
76    event handler. 
77 */
78
79 static int sedlbauer_config(struct pcmcia_device *link) __devinit ;
80 static void sedlbauer_release(struct pcmcia_device *link);
81
82 /*
83    The attach() and detach() entry points are used to create and destroy
84    "instances" of the driver, where each instance represents everything
85    needed to manage one actual PCMCIA card.
86 */
87
88 static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit;
89
90 /*
91    You'll also need to prototype all the functions that will actually
92    be used to talk to your device.  See 'memory_cs' for a good example
93    of a fully self-sufficient driver; the other drivers rely more or
94    less on other parts of the kernel.
95 */
96
97 /*
98    A driver needs to provide a dev_node_t structure for each device
99    on a card.  In some cases, there is only one device per card (for
100    example, ethernet cards, modems).  In other cases, there may be
101    many actual or logical devices (SCSI adapters, memory cards with
102    multiple partitions).  The dev_node_t structures need to be kept
103    in a linked list starting at the 'dev' field of a struct pcmcia_device
104    structure.  We allocate them in the card's private data structure,
105    because they generally shouldn't be allocated dynamically.
106
107    In this case, we also provide a flag to indicate if a device is
108    "stopped" due to a power management event, or card ejection.  The
109    device IO routines can use a flag like this to throttle IO to a
110    card that is not ready to accept it.
111 */
112    
113 typedef struct local_info_t {
114         struct pcmcia_device    *p_dev;
115     dev_node_t          node;
116     int                 stop;
117     int                 cardnr;
118 } local_info_t;
119
120 /*======================================================================
121
122     sedlbauer_attach() creates an "instance" of the driver, allocating
123     local data structures for one device.  The device is registered
124     with Card Services.
125
126     The dev_link structure is initialized, but we don't actually
127     configure the card at this point -- we wait until we receive a
128     card insertion event.
129     
130 ======================================================================*/
131
132 static int __devinit sedlbauer_probe(struct pcmcia_device *link)
133 {
134     local_info_t *local;
135
136     dev_dbg(&link->dev, "sedlbauer_attach()\n");
137
138     /* Allocate space for private device-specific data */
139     local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
140     if (!local) return -ENOMEM;
141     local->cardnr = -1;
142
143     local->p_dev = link;
144     link->priv = local;
145
146     /* Interrupt setup */
147     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
148     link->irq.Handler = NULL;
149
150     /*
151       General socket configuration defaults can go here.  In this
152       client, we assume very little, and rely on the CIS for almost
153       everything.  In most clients, many details (i.e., number, sizes,
154       and attributes of IO windows) are fixed by the nature of the
155       device, and can be hard-wired here.
156     */
157
158     /* from old sedl_cs 
159     */
160     /* The io structure describes IO port mapping */
161     link->io.NumPorts1 = 8;
162     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
163     link->io.IOAddrLines = 3;
164
165     link->conf.Attributes = 0;
166     link->conf.IntType = INT_MEMORY_AND_IO;
167
168     return sedlbauer_config(link);
169 } /* sedlbauer_attach */
170
171 /*======================================================================
172
173     This deletes a driver "instance".  The device is de-registered
174     with Card Services.  If it has been released, all local data
175     structures are freed.  Otherwise, the structures will be freed
176     when the device is released.
177
178 ======================================================================*/
179
180 static void __devexit sedlbauer_detach(struct pcmcia_device *link)
181 {
182         dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
183
184         ((local_info_t *)link->priv)->stop = 1;
185         sedlbauer_release(link);
186
187         /* This points to the parent local_info_t struct */
188         kfree(link->priv);
189 } /* sedlbauer_detach */
190
191 /*======================================================================
192
193     sedlbauer_config() is scheduled to run after a CARD_INSERTION event
194     is received, to configure the PCMCIA socket, and to make the
195     device available to the system.
196     
197 ======================================================================*/
198 static int sedlbauer_config_check(struct pcmcia_device *p_dev,
199                                   cistpl_cftable_entry_t *cfg,
200                                   cistpl_cftable_entry_t *dflt,
201                                   unsigned int vcc,
202                                   void *priv_data)
203 {
204         win_req_t *req = priv_data;
205
206         if (cfg->index == 0)
207                 return -ENODEV;
208
209         /* Does this card need audio output? */
210         if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
211                 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
212                 p_dev->conf.Status = CCSR_AUDIO_ENA;
213         }
214
215         /* Use power settings for Vcc and Vpp if present */
216         /*  Note that the CIS values need to be rescaled */
217         if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
218                 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
219                         return -ENODEV;
220         } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
221                 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
222                         return -ENODEV;
223         }
224
225         if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
226                 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
227         else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
228                 p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
229
230         /* Do we need to allocate an interrupt? */
231         if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
232                 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
233
234         /* IO window settings */
235         p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
236         if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
237                 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
238                 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
239                 if (!(io->flags & CISTPL_IO_8BIT))
240                         p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
241                 if (!(io->flags & CISTPL_IO_16BIT))
242                         p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
243                 p_dev->io.BasePort1 = io->win[0].base;
244                 p_dev->io.NumPorts1 = io->win[0].len;
245                 if (io->nwin > 1) {
246                         p_dev->io.Attributes2 = p_dev->io.Attributes1;
247                         p_dev->io.BasePort2 = io->win[1].base;
248                         p_dev->io.NumPorts2 = io->win[1].len;
249                 }
250                 /* This reserves IO space but doesn't actually enable it */
251                 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
252                         return -ENODEV;
253         }
254
255         /*
256           Now set up a common memory window, if needed.  There is room
257           in the struct pcmcia_device structure for one memory window handle,
258           but if the base addresses need to be saved, or if multiple
259           windows are needed, the info should go in the private data
260           structure for this device.
261
262           Note that the memory window base is a physical address, and
263           needs to be mapped to virtual space with ioremap() before it
264           is used.
265         */
266         if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
267                 cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
268                 memreq_t map;
269                 req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
270                 req->Attributes |= WIN_ENABLE;
271                 req->Base = mem->win[0].host_addr;
272                 req->Size = mem->win[0].len;
273                 req->AccessSpeed = 0;
274                 if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
275                         return -ENODEV;
276                 map.Page = 0;
277                 map.CardOffset = mem->win[0].card_addr;
278                 if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)
279                         return -ENODEV;
280         }
281         return 0;
282 }
283
284
285
286 static int __devinit sedlbauer_config(struct pcmcia_device *link)
287 {
288     local_info_t *dev = link->priv;
289     win_req_t *req;
290     int ret;
291     IsdnCard_t  icard;
292
293     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
294
295     req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
296     if (!req)
297             return -ENOMEM;
298
299     /*
300       In this loop, we scan the CIS for configuration table entries,
301       each of which describes a valid card configuration, including
302       voltage, IO window, memory window, and interrupt settings.
303
304       We make no assumptions about the card to be configured: we use
305       just the information available in the CIS.  In an ideal world,
306       this would work for any PCMCIA card, but it requires a complete
307       and accurate CIS.  In practice, a driver usually "knows" most of
308       these things without consulting the CIS, and most client drivers
309       will only use the CIS to fill in implementation-defined details.
310     */
311     ret = pcmcia_loop_config(link, sedlbauer_config_check, req);
312     if (ret)
313             goto failed;
314
315     /*
316        Allocate an interrupt line.  Note that this does not assign a
317        handler to the interrupt, unless the 'Handler' member of the
318        irq structure is initialized.
319     */
320     if (link->conf.Attributes & CONF_ENABLE_IRQ) {
321             ret = pcmcia_request_irq(link, &link->irq);
322             if (ret)
323                     goto failed;
324     }
325         
326     /*
327        This actually configures the PCMCIA socket -- setting up
328        the I/O windows and the interrupt mapping, and putting the
329        card and host interface into "Memory and IO" mode.
330     */
331     ret = pcmcia_request_configuration(link, &link->conf);
332     if (ret)
333             goto failed;
334
335     /*
336       At this point, the dev_node_t structure(s) need to be
337       initialized and arranged in a linked list at link->dev.
338     */
339     sprintf(dev->node.dev_name, "sedlbauer");
340     dev->node.major = dev->node.minor = 0;
341     link->dev_node = &dev->node;
342
343     /* Finally, report what we've done */
344     printk(KERN_INFO "%s: index 0x%02x:",
345            dev->node.dev_name, link->conf.ConfigIndex);
346     if (link->conf.Vpp)
347         printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
348     if (link->conf.Attributes & CONF_ENABLE_IRQ)
349         printk(", irq %d", link->irq.AssignedIRQ);
350     if (link->io.NumPorts1)
351         printk(", io 0x%04x-0x%04x", link->io.BasePort1,
352                link->io.BasePort1+link->io.NumPorts1-1);
353     if (link->io.NumPorts2)
354         printk(" & 0x%04x-0x%04x", link->io.BasePort2,
355                link->io.BasePort2+link->io.NumPorts2-1);
356     if (link->win)
357         printk(", mem 0x%06lx-0x%06lx", req->Base,
358                req->Base+req->Size-1);
359     printk("\n");
360
361     icard.para[0] = link->irq.AssignedIRQ;
362     icard.para[1] = link->io.BasePort1;
363     icard.protocol = protocol;
364     icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
365     
366     ret = hisax_init_pcmcia(link, 
367                             &(((local_info_t *)link->priv)->stop), &icard);
368     if (ret < 0) {
369         printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
370                 ret, link->io.BasePort1);
371         sedlbauer_release(link);
372         return -ENODEV;
373     } else
374         ((local_info_t *)link->priv)->cardnr = ret;
375
376     return 0;
377
378 failed:
379     sedlbauer_release(link);
380     return -ENODEV;
381
382 } /* sedlbauer_config */
383
384 /*======================================================================
385
386     After a card is removed, sedlbauer_release() will unregister the
387     device, and release the PCMCIA configuration.  If the device is
388     still open, this will be postponed until it is closed.
389     
390 ======================================================================*/
391
392 static void sedlbauer_release(struct pcmcia_device *link)
393 {
394     local_info_t *local = link->priv;
395     dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link);
396
397     if (local) {
398         if (local->cardnr >= 0) {
399             /* no unregister function with hisax */
400             HiSax_closecard(local->cardnr);
401         }
402     }
403
404     pcmcia_disable_device(link);
405 } /* sedlbauer_release */
406
407 static int sedlbauer_suspend(struct pcmcia_device *link)
408 {
409         local_info_t *dev = link->priv;
410
411         dev->stop = 1;
412
413         return 0;
414 }
415
416 static int sedlbauer_resume(struct pcmcia_device *link)
417 {
418         local_info_t *dev = link->priv;
419
420         dev->stop = 0;
421
422         return 0;
423 }
424
425
426 static struct pcmcia_device_id sedlbauer_ids[] = {
427         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
428         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
429         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
430         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
431         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c),
432         PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae),
433 /*      PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/
434         PCMCIA_DEVICE_NULL
435 };
436 MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
437
438 static struct pcmcia_driver sedlbauer_driver = {
439         .owner          = THIS_MODULE,
440         .drv            = {
441                 .name   = "sedlbauer_cs",
442         },
443         .probe          = sedlbauer_probe,
444         .remove         = __devexit_p(sedlbauer_detach),
445         .id_table       = sedlbauer_ids,
446         .suspend        = sedlbauer_suspend,
447         .resume         = sedlbauer_resume,
448 };
449
450 static int __init init_sedlbauer_cs(void)
451 {
452         return pcmcia_register_driver(&sedlbauer_driver);
453 }
454
455 static void __exit exit_sedlbauer_cs(void)
456 {
457         pcmcia_unregister_driver(&sedlbauer_driver);
458 }
459
460 module_init(init_sedlbauer_cs);
461 module_exit(exit_sedlbauer_cs);