pcmcia: do not use io_req_t when calling pcmcia_request_io()
[deliverable/linux.git] / drivers / isdn / hisax / teles_cs.c
CommitLineData
1da177e4
LT
1/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */
2/*======================================================================
3
4 A teles S0 PCMCIA client driver
5
6 Based on skeleton by David Hinds, dhinds@allegro.stanford.edu
7 Written by Christof Petig, christof.petig@wtal.de
8
9 Also inspired by ELSA PCMCIA driver
10 by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
11
12 Extentions to new hisax_pcmcia by Karsten Keil
13
14 minor changes to be compatible with kernel 2.4.x
15 by Jan.Schubert@GMX.li
16
17======================================================================*/
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/init.h>
1da177e4
LT
22#include <linux/ptrace.h>
23#include <linux/slab.h>
24#include <linux/string.h>
25#include <linux/timer.h>
26#include <linux/ioport.h>
27#include <asm/io.h>
28#include <asm/system.h>
29
1da177e4
LT
30#include <pcmcia/cs.h>
31#include <pcmcia/cistpl.h>
32#include <pcmcia/cisreg.h>
33#include <pcmcia/ds.h>
34#include "hisax_cfg.h"
35
36MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");
37MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");
38MODULE_LICENSE("GPL");
39
1da177e4
LT
40
41/*====================================================================*/
42
43/* Parameters that can be set with 'insmod' */
44
45static int protocol = 2; /* EURO-ISDN Default */
46module_param(protocol, int, 0);
47
48/*====================================================================*/
49
50/*
51 The event() function is this driver's Card Services event handler.
52 It will be called by Card Services when an appropriate card status
53 event is received. The config() and release() entry points are
54 used to configure or release a socket, in response to card insertion
55 and ejection events. They are invoked from the teles_cs event
56 handler.
57*/
58
158e33d1 59static int teles_cs_config(struct pcmcia_device *link) __devinit ;
fba395ee 60static void teles_cs_release(struct pcmcia_device *link);
1da177e4
LT
61
62/*
63 The attach() and detach() entry points are used to create and destroy
64 "instances" of the driver, where each instance represents everything
65 needed to manage one actual PCMCIA card.
66*/
67
158e33d1 68static void teles_detach(struct pcmcia_device *p_dev) __devexit ;
1da177e4 69
1da177e4 70typedef struct local_info_t {
fd238232 71 struct pcmcia_device *p_dev;
1da177e4
LT
72 int busy;
73 int cardnr;
74} local_info_t;
75
76/*======================================================================
77
78 teles_attach() creates an "instance" of the driver, allocatingx
79 local data structures for one device. The device is registered
80 with Card Services.
81
82 The dev_link structure is initialized, but we don't actually
83 configure the card at this point -- we wait until we receive a
84 card insertion event.
85
86======================================================================*/
87
158e33d1 88static int __devinit teles_probe(struct pcmcia_device *link)
1da177e4 89{
1da177e4 90 local_info_t *local;
1da177e4 91
e773cfe1 92 dev_dbg(&link->dev, "teles_attach()\n");
1da177e4
LT
93
94 /* Allocate space for private device-specific data */
41f96935 95 local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
f8cfa618 96 if (!local) return -ENOMEM;
1da177e4 97 local->cardnr = -1;
fd238232 98
fba395ee 99 local->p_dev = link;
fd238232 100 link->priv = local;
1da177e4 101
1da177e4
LT
102 /*
103 General socket configuration defaults can go here. In this
104 client, we assume very little, and rely on the CIS for almost
105 everything. In most clients, many details (i.e., number, sizes,
106 and attributes of IO windows) are fixed by the nature of the
107 device, and can be hard-wired here.
108 */
90abdc3b
DB
109 link->resource[0]->end = 96;
110 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
1da177e4
LT
111
112 link->conf.Attributes = CONF_ENABLE_IRQ;
1da177e4
LT
113 link->conf.IntType = INT_MEMORY_AND_IO;
114
15b99ac1 115 return teles_cs_config(link);
1da177e4
LT
116} /* teles_attach */
117
118/*======================================================================
119
120 This deletes a driver "instance". The device is de-registered
121 with Card Services. If it has been released, all local data
122 structures are freed. Otherwise, the structures will be freed
123 when the device is released.
124
125======================================================================*/
126
158e33d1 127static void __devexit teles_detach(struct pcmcia_device *link)
1da177e4 128{
e2d40963 129 local_info_t *info = link->priv;
1da177e4 130
e773cfe1 131 dev_dbg(&link->dev, "teles_detach(0x%p)\n", link);
1da177e4 132
e2d40963
DB
133 info->busy = 1;
134 teles_cs_release(link);
1da177e4 135
e2d40963 136 kfree(info);
1da177e4
LT
137} /* teles_detach */
138
139/*======================================================================
140
141 teles_cs_config() is scheduled to run after a CARD_INSERTION event
142 is received, to configure the PCMCIA socket, and to make the
143 device available to the system.
144
145======================================================================*/
1da177e4 146
5fcd4da0
DB
147static int teles_cs_configcheck(struct pcmcia_device *p_dev,
148 cistpl_cftable_entry_t *cf,
8e2fc39d 149 cistpl_cftable_entry_t *dflt,
ad913c11 150 unsigned int vcc,
5fcd4da0 151 void *priv_data)
1da177e4 152{
5fcd4da0
DB
153 int j;
154
90abdc3b
DB
155 p_dev->io_lines = 5;
156
5fcd4da0
DB
157 if ((cf->io.nwin > 0) && cf->io.win[0].base) {
158 printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
90abdc3b
DB
159 p_dev->resource[0]->start = cf->io.win[0].base;
160 if (!pcmcia_request_io(p_dev))
5fcd4da0
DB
161 return 0;
162 } else {
163 printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
5fcd4da0 164 for (j = 0x2f0; j > 0x100; j -= 0x10) {
90abdc3b
DB
165 p_dev->resource[0]->start = j;
166 if (!pcmcia_request_io(p_dev))
5fcd4da0
DB
167 return 0;
168 }
169 }
170 return -ENODEV;
1da177e4
LT
171}
172
158e33d1 173static int __devinit teles_cs_config(struct pcmcia_device *link)
1da177e4 174{
1da177e4 175 local_info_t *dev;
e773cfe1 176 int i;
1da177e4
LT
177 IsdnCard_t icard;
178
e773cfe1 179 dev_dbg(&link->dev, "teles_config(0x%p)\n", link);
1da177e4
LT
180 dev = link->priv;
181
5fcd4da0 182 i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
e773cfe1 183 if (i != 0)
1da177e4 184 goto cs_failed;
1da177e4 185
eb14120f 186 if (!link->irq)
1da177e4 187 goto cs_failed;
1da177e4 188
fba395ee 189 i = pcmcia_request_configuration(link, &link->conf);
e773cfe1 190 if (i != 0)
1da177e4 191 goto cs_failed;
1da177e4 192
1da177e4 193 /* Finally, report what we've done */
ded6a1a3
DB
194 dev_info(&link->dev, "index 0x%02x:",
195 link->conf.ConfigIndex);
1da177e4 196 if (link->conf.Attributes & CONF_ENABLE_IRQ)
eb14120f 197 printk(", irq %d", link->irq);
9a017a91
DB
198 if (link->resource[0])
199 printk(" & %pR", link->resource[0]);
200 if (link->resource[1])
201 printk(" & %pR", link->resource[1]);
1da177e4
LT
202 printk("\n");
203
eb14120f 204 icard.para[0] = link->irq;
9a017a91 205 icard.para[1] = link->resource[0]->start;
1da177e4
LT
206 icard.protocol = protocol;
207 icard.typ = ISDN_CTYPE_TELESPCMCIA;
208
209 i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
210 if (i < 0) {
211 printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
9a017a91 212 i, (unsigned int) link->resource[0]->start);
1da177e4 213 teles_cs_release(link);
15b99ac1
DB
214 return -ENODEV;
215 }
216
217 ((local_info_t*)link->priv)->cardnr = i;
218 return 0;
1da177e4 219
1da177e4 220cs_failed:
1da177e4 221 teles_cs_release(link);
15b99ac1 222 return -ENODEV;
1da177e4
LT
223} /* teles_cs_config */
224
225/*======================================================================
226
227 After a card is removed, teles_cs_release() will unregister the net
228 device, and release the PCMCIA configuration. If the device is
229 still open, this will be postponed until it is closed.
230
231======================================================================*/
232
fba395ee 233static void teles_cs_release(struct pcmcia_device *link)
1da177e4
LT
234{
235 local_info_t *local = link->priv;
236
e773cfe1 237 dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link);
1da177e4
LT
238
239 if (local) {
240 if (local->cardnr >= 0) {
241 /* no unregister function with hisax */
242 HiSax_closecard(local->cardnr);
243 }
244 }
5f2a71fc 245
fba395ee 246 pcmcia_disable_device(link);
1da177e4
LT
247} /* teles_cs_release */
248
fba395ee 249static int teles_suspend(struct pcmcia_device *link)
98e4c28b 250{
98e4c28b
DB
251 local_info_t *dev = link->priv;
252
98e4c28b 253 dev->busy = 1;
98e4c28b
DB
254
255 return 0;
256}
257
fba395ee 258static int teles_resume(struct pcmcia_device *link)
98e4c28b 259{
98e4c28b
DB
260 local_info_t *dev = link->priv;
261
98e4c28b
DB
262 dev->busy = 0;
263
264 return 0;
265}
266
1da177e4 267
0a10d73d
DB
268static struct pcmcia_device_id teles_ids[] = {
269 PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
270 PCMCIA_DEVICE_NULL,
271};
272MODULE_DEVICE_TABLE(pcmcia, teles_ids);
273
1da177e4
LT
274static struct pcmcia_driver teles_cs_driver = {
275 .owner = THIS_MODULE,
276 .drv = {
277 .name = "teles_cs",
278 },
15b99ac1 279 .probe = teles_probe,
158e33d1 280 .remove = __devexit_p(teles_detach),
0a10d73d 281 .id_table = teles_ids,
98e4c28b
DB
282 .suspend = teles_suspend,
283 .resume = teles_resume,
1da177e4
LT
284};
285
286static int __init init_teles_cs(void)
287{
288 return pcmcia_register_driver(&teles_cs_driver);
289}
290
291static void __exit exit_teles_cs(void)
292{
293 pcmcia_unregister_driver(&teles_cs_driver);
1da177e4
LT
294}
295
296module_init(init_teles_cs);
297module_exit(exit_teles_cs);
This page took 0.579704 seconds and 5 git commands to generate.