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