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