]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/isdn/hisax/teles_cs.c
pcmcia: move config_{base,index,regs} to struct pcmcia_device
[mirror_ubuntu-artful-kernel.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 113
15b99ac1 114 return teles_cs_config(link);
1da177e4
LT
115} /* teles_attach */
116
117/*======================================================================
118
119 This deletes a driver "instance". The device is de-registered
120 with Card Services. If it has been released, all local data
121 structures are freed. Otherwise, the structures will be freed
122 when the device is released.
123
124======================================================================*/
125
158e33d1 126static void __devexit teles_detach(struct pcmcia_device *link)
1da177e4 127{
e2d40963 128 local_info_t *info = link->priv;
1da177e4 129
e773cfe1 130 dev_dbg(&link->dev, "teles_detach(0x%p)\n", link);
1da177e4 131
e2d40963
DB
132 info->busy = 1;
133 teles_cs_release(link);
1da177e4 134
e2d40963 135 kfree(info);
1da177e4
LT
136} /* teles_detach */
137
138/*======================================================================
139
140 teles_cs_config() is scheduled to run after a CARD_INSERTION event
141 is received, to configure the PCMCIA socket, and to make the
142 device available to the system.
143
144======================================================================*/
1da177e4 145
5fcd4da0
DB
146static int teles_cs_configcheck(struct pcmcia_device *p_dev,
147 cistpl_cftable_entry_t *cf,
8e2fc39d 148 cistpl_cftable_entry_t *dflt,
ad913c11 149 unsigned int vcc,
5fcd4da0 150 void *priv_data)
1da177e4 151{
5fcd4da0
DB
152 int j;
153
90abdc3b
DB
154 p_dev->io_lines = 5;
155
5fcd4da0
DB
156 if ((cf->io.nwin > 0) && cf->io.win[0].base) {
157 printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
90abdc3b
DB
158 p_dev->resource[0]->start = cf->io.win[0].base;
159 if (!pcmcia_request_io(p_dev))
5fcd4da0
DB
160 return 0;
161 } else {
162 printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
5fcd4da0 163 for (j = 0x2f0; j > 0x100; j -= 0x10) {
90abdc3b
DB
164 p_dev->resource[0]->start = j;
165 if (!pcmcia_request_io(p_dev))
5fcd4da0
DB
166 return 0;
167 }
168 }
169 return -ENODEV;
1da177e4
LT
170}
171
158e33d1 172static int __devinit teles_cs_config(struct pcmcia_device *link)
1da177e4 173{
1da177e4 174 local_info_t *dev;
e773cfe1 175 int i;
1da177e4
LT
176 IsdnCard_t icard;
177
e773cfe1 178 dev_dbg(&link->dev, "teles_config(0x%p)\n", link);
1da177e4
LT
179 dev = link->priv;
180
5fcd4da0 181 i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
e773cfe1 182 if (i != 0)
1da177e4 183 goto cs_failed;
1da177e4 184
eb14120f 185 if (!link->irq)
1da177e4 186 goto cs_failed;
1da177e4 187
fba395ee 188 i = pcmcia_request_configuration(link, &link->conf);
e773cfe1 189 if (i != 0)
1da177e4 190 goto cs_failed;
1da177e4 191
1da177e4 192 /* Finally, report what we've done */
ded6a1a3 193 dev_info(&link->dev, "index 0x%02x:",
7feabb64 194 link->config_index);
1da177e4 195 if (link->conf.Attributes & CONF_ENABLE_IRQ)
eb14120f 196 printk(", irq %d", link->irq);
9a017a91
DB
197 if (link->resource[0])
198 printk(" & %pR", link->resource[0]);
199 if (link->resource[1])
200 printk(" & %pR", link->resource[1]);
1da177e4
LT
201 printk("\n");
202
eb14120f 203 icard.para[0] = link->irq;
9a017a91 204 icard.para[1] = link->resource[0]->start;
1da177e4
LT
205 icard.protocol = protocol;
206 icard.typ = ISDN_CTYPE_TELESPCMCIA;
207
208 i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
209 if (i < 0) {
210 printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
9a017a91 211 i, (unsigned int) link->resource[0]->start);
1da177e4 212 teles_cs_release(link);
15b99ac1
DB
213 return -ENODEV;
214 }
215
216 ((local_info_t*)link->priv)->cardnr = i;
217 return 0;
1da177e4 218
1da177e4 219cs_failed:
1da177e4 220 teles_cs_release(link);
15b99ac1 221 return -ENODEV;
1da177e4
LT
222} /* teles_cs_config */
223
224/*======================================================================
225
226 After a card is removed, teles_cs_release() will unregister the net
227 device, and release the PCMCIA configuration. If the device is
228 still open, this will be postponed until it is closed.
229
230======================================================================*/
231
fba395ee 232static void teles_cs_release(struct pcmcia_device *link)
1da177e4
LT
233{
234 local_info_t *local = link->priv;
235
e773cfe1 236 dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link);
1da177e4
LT
237
238 if (local) {
239 if (local->cardnr >= 0) {
240 /* no unregister function with hisax */
241 HiSax_closecard(local->cardnr);
242 }
243 }
5f2a71fc 244
fba395ee 245 pcmcia_disable_device(link);
1da177e4
LT
246} /* teles_cs_release */
247
fba395ee 248static int teles_suspend(struct pcmcia_device *link)
98e4c28b 249{
98e4c28b
DB
250 local_info_t *dev = link->priv;
251
98e4c28b 252 dev->busy = 1;
98e4c28b
DB
253
254 return 0;
255}
256
fba395ee 257static int teles_resume(struct pcmcia_device *link)
98e4c28b 258{
98e4c28b
DB
259 local_info_t *dev = link->priv;
260
98e4c28b
DB
261 dev->busy = 0;
262
263 return 0;
264}
265
1da177e4 266
0a10d73d
DB
267static struct pcmcia_device_id teles_ids[] = {
268 PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
269 PCMCIA_DEVICE_NULL,
270};
271MODULE_DEVICE_TABLE(pcmcia, teles_ids);
272
1da177e4
LT
273static struct pcmcia_driver teles_cs_driver = {
274 .owner = THIS_MODULE,
275 .drv = {
276 .name = "teles_cs",
277 },
15b99ac1 278 .probe = teles_probe,
158e33d1 279 .remove = __devexit_p(teles_detach),
0a10d73d 280 .id_table = teles_ids,
98e4c28b
DB
281 .suspend = teles_suspend,
282 .resume = teles_resume,
1da177e4
LT
283};
284
285static int __init init_teles_cs(void)
286{
287 return pcmcia_register_driver(&teles_cs_driver);
288}
289
290static void __exit exit_teles_cs(void)
291{
292 pcmcia_unregister_driver(&teles_cs_driver);
1da177e4
LT
293}
294
295module_init(init_teles_cs);
296module_exit(exit_teles_cs);