OSDN Git Service

pcmcia: re-work pcmcia_request_irq()
[uclinux-h8/linux.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     /*
147       General socket configuration defaults can go here.  In this
148       client, we assume very little, and rely on the CIS for almost
149       everything.  In most clients, many details (i.e., number, sizes,
150       and attributes of IO windows) are fixed by the nature of the
151       device, and can be hard-wired here.
152     */
153
154     /* from old sedl_cs 
155     */
156     /* The io structure describes IO port mapping */
157     link->io.NumPorts1 = 8;
158     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
159     link->io.IOAddrLines = 3;
160
161     link->conf.Attributes = 0;
162     link->conf.IntType = INT_MEMORY_AND_IO;
163
164     return sedlbauer_config(link);
165 } /* sedlbauer_attach */
166
167 /*======================================================================
168
169     This deletes a driver "instance".  The device is de-registered
170     with Card Services.  If it has been released, all local data
171     structures are freed.  Otherwise, the structures will be freed
172     when the device is released.
173
174 ======================================================================*/
175
176 static void __devexit sedlbauer_detach(struct pcmcia_device *link)
177 {
178         dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
179
180         ((local_info_t *)link->priv)->stop = 1;
181         sedlbauer_release(link);
182
183         /* This points to the parent local_info_t struct */
184         kfree(link->priv);
185 } /* sedlbauer_detach */
186
187 /*======================================================================
188
189     sedlbauer_config() is scheduled to run after a CARD_INSERTION event
190     is received, to configure the PCMCIA socket, and to make the
191     device available to the system.
192     
193 ======================================================================*/
194 static int sedlbauer_config_check(struct pcmcia_device *p_dev,
195                                   cistpl_cftable_entry_t *cfg,
196                                   cistpl_cftable_entry_t *dflt,
197                                   unsigned int vcc,
198                                   void *priv_data)
199 {
200         win_req_t *req = priv_data;
201
202         if (cfg->index == 0)
203                 return -ENODEV;
204
205         /* Does this card need audio output? */
206         if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
207                 p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
208                 p_dev->conf.Status = CCSR_AUDIO_ENA;
209         }
210
211         /* Use power settings for Vcc and Vpp if present */
212         /*  Note that the CIS values need to be rescaled */
213         if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
214                 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
215                         return -ENODEV;
216         } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
217                 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
218                         return -ENODEV;
219         }
220
221         if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
222                 p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
223         else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
224                 p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
225
226         p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
227
228         /* IO window settings */
229         p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
230         if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
231                 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
232                 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
233                 if (!(io->flags & CISTPL_IO_8BIT))
234                         p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
235                 if (!(io->flags & CISTPL_IO_16BIT))
236                         p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
237                 p_dev->io.BasePort1 = io->win[0].base;
238                 p_dev->io.NumPorts1 = io->win[0].len;
239                 if (io->nwin > 1) {
240                         p_dev->io.Attributes2 = p_dev->io.Attributes1;
241                         p_dev->io.BasePort2 = io->win[1].base;
242                         p_dev->io.NumPorts2 = io->win[1].len;
243                 }
244                 /* This reserves IO space but doesn't actually enable it */
245                 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
246                         return -ENODEV;
247         }
248
249         /*
250           Now set up a common memory window, if needed.  There is room
251           in the struct pcmcia_device structure for one memory window handle,
252           but if the base addresses need to be saved, or if multiple
253           windows are needed, the info should go in the private data
254           structure for this device.
255
256           Note that the memory window base is a physical address, and
257           needs to be mapped to virtual space with ioremap() before it
258           is used.
259         */
260         if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
261                 cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
262                 memreq_t map;
263                 req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
264                 req->Attributes |= WIN_ENABLE;
265                 req->Base = mem->win[0].host_addr;
266                 req->Size = mem->win[0].len;
267                 req->AccessSpeed = 0;
268                 if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
269                         return -ENODEV;
270                 map.Page = 0;
271                 map.CardOffset = mem->win[0].card_addr;
272                 if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)
273                         return -ENODEV;
274         }
275         return 0;
276 }
277
278
279
280 static int __devinit sedlbauer_config(struct pcmcia_device *link)
281 {
282     local_info_t *dev = link->priv;
283     win_req_t *req;
284     int ret;
285     IsdnCard_t  icard;
286
287     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
288
289     req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
290     if (!req)
291             return -ENOMEM;
292
293     /*
294       In this loop, we scan the CIS for configuration table entries,
295       each of which describes a valid card configuration, including
296       voltage, IO window, memory window, and interrupt settings.
297
298       We make no assumptions about the card to be configured: we use
299       just the information available in the CIS.  In an ideal world,
300       this would work for any PCMCIA card, but it requires a complete
301       and accurate CIS.  In practice, a driver usually "knows" most of
302       these things without consulting the CIS, and most client drivers
303       will only use the CIS to fill in implementation-defined details.
304     */
305     ret = pcmcia_loop_config(link, sedlbauer_config_check, req);
306     if (ret)
307             goto failed;
308
309     /*
310        This actually configures the PCMCIA socket -- setting up
311        the I/O windows and the interrupt mapping, and putting the
312        card and host interface into "Memory and IO" mode.
313     */
314     ret = pcmcia_request_configuration(link, &link->conf);
315     if (ret)
316             goto failed;
317
318     /*
319       At this point, the dev_node_t structure(s) need to be
320       initialized and arranged in a linked list at link->dev.
321     */
322     sprintf(dev->node.dev_name, "sedlbauer");
323     dev->node.major = dev->node.minor = 0;
324     link->dev_node = &dev->node;
325
326     /* Finally, report what we've done */
327     printk(KERN_INFO "%s: index 0x%02x:",
328            dev->node.dev_name, link->conf.ConfigIndex);
329     if (link->conf.Vpp)
330         printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
331     if (link->conf.Attributes & CONF_ENABLE_IRQ)
332         printk(", irq %d", link->irq);
333     if (link->io.NumPorts1)
334         printk(", io 0x%04x-0x%04x", link->io.BasePort1,
335                link->io.BasePort1+link->io.NumPorts1-1);
336     if (link->io.NumPorts2)
337         printk(" & 0x%04x-0x%04x", link->io.BasePort2,
338                link->io.BasePort2+link->io.NumPorts2-1);
339     if (link->win)
340         printk(", mem 0x%06lx-0x%06lx", req->Base,
341                req->Base+req->Size-1);
342     printk("\n");
343
344     icard.para[0] = link->irq;
345     icard.para[1] = link->io.BasePort1;
346     icard.protocol = protocol;
347     icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
348     
349     ret = hisax_init_pcmcia(link, 
350                             &(((local_info_t *)link->priv)->stop), &icard);
351     if (ret < 0) {
352         printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
353                 ret, link->io.BasePort1);
354         sedlbauer_release(link);
355         return -ENODEV;
356     } else
357         ((local_info_t *)link->priv)->cardnr = ret;
358
359     return 0;
360
361 failed:
362     sedlbauer_release(link);
363     return -ENODEV;
364
365 } /* sedlbauer_config */
366
367 /*======================================================================
368
369     After a card is removed, sedlbauer_release() will unregister the
370     device, and release the PCMCIA configuration.  If the device is
371     still open, this will be postponed until it is closed.
372     
373 ======================================================================*/
374
375 static void sedlbauer_release(struct pcmcia_device *link)
376 {
377     local_info_t *local = link->priv;
378     dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link);
379
380     if (local) {
381         if (local->cardnr >= 0) {
382             /* no unregister function with hisax */
383             HiSax_closecard(local->cardnr);
384         }
385     }
386
387     pcmcia_disable_device(link);
388 } /* sedlbauer_release */
389
390 static int sedlbauer_suspend(struct pcmcia_device *link)
391 {
392         local_info_t *dev = link->priv;
393
394         dev->stop = 1;
395
396         return 0;
397 }
398
399 static int sedlbauer_resume(struct pcmcia_device *link)
400 {
401         local_info_t *dev = link->priv;
402
403         dev->stop = 0;
404
405         return 0;
406 }
407
408
409 static struct pcmcia_device_id sedlbauer_ids[] = {
410         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
411         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
412         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
413         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
414         PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c),
415         PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae),
416 /*      PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/
417         PCMCIA_DEVICE_NULL
418 };
419 MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
420
421 static struct pcmcia_driver sedlbauer_driver = {
422         .owner          = THIS_MODULE,
423         .drv            = {
424                 .name   = "sedlbauer_cs",
425         },
426         .probe          = sedlbauer_probe,
427         .remove         = __devexit_p(sedlbauer_detach),
428         .id_table       = sedlbauer_ids,
429         .suspend        = sedlbauer_suspend,
430         .resume         = sedlbauer_resume,
431 };
432
433 static int __init init_sedlbauer_cs(void)
434 {
435         return pcmcia_register_driver(&sedlbauer_driver);
436 }
437
438 static void __exit exit_sedlbauer_cs(void)
439 {
440         pcmcia_unregister_driver(&sedlbauer_driver);
441 }
442
443 module_init(init_sedlbauer_cs);
444 module_exit(exit_sedlbauer_cs);