[PATCH] pcmcia: use bitfield instead of p_state and state
[deliverable/linux.git] / drivers / isdn / hardware / avm / avm_cs.c
CommitLineData
1da177e4
LT
1/* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $
2 *
3 * A PCMCIA client driver for AVM B1/M1/M2
4 *
5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/sched.h>
16#include <linux/ptrace.h>
17#include <linux/slab.h>
18#include <linux/string.h>
19#include <linux/tty.h>
20#include <linux/serial.h>
21#include <linux/major.h>
22#include <asm/io.h>
23#include <asm/system.h>
24
1da177e4
LT
25#include <pcmcia/cs_types.h>
26#include <pcmcia/cs.h>
27#include <pcmcia/cistpl.h>
28#include <pcmcia/ciscode.h>
29#include <pcmcia/ds.h>
30#include <pcmcia/cisreg.h>
31
32#include <linux/skbuff.h>
33#include <linux/capi.h>
34#include <linux/b1lli.h>
35#include <linux/b1pcmcia.h>
36
37/*====================================================================*/
38
39MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
40MODULE_AUTHOR("Carsten Paeth");
41MODULE_LICENSE("GPL");
42
43/*====================================================================*/
44
45/*
46 The event() function is this driver's Card Services event handler.
47 It will be called by Card Services when an appropriate card status
48 event is received. The config() and release() entry points are
49 used to configure or release a socket, in response to card insertion
50 and ejection events. They are invoked from the skeleton event
51 handler.
52*/
53
15b99ac1 54static int avmcs_config(struct pcmcia_device *link);
fba395ee 55static void avmcs_release(struct pcmcia_device *link);
1da177e4
LT
56
57/*
58 The attach() and detach() entry points are used to create and destroy
59 "instances" of the driver, where each instance represents everything
60 needed to manage one actual PCMCIA card.
61*/
62
cc3b4866 63static void avmcs_detach(struct pcmcia_device *p_dev);
1da177e4 64
1da177e4
LT
65/*
66 A linked list of "instances" of the skeleton device. Each actual
67 PCMCIA card corresponds to one device instance, and is described
fba395ee 68 by one struct pcmcia_device structure (defined in ds.h).
1da177e4
LT
69
70 You may not want to use a linked list for this -- for example, the
fba395ee 71 memory card driver uses an array of struct pcmcia_device pointers, where minor
1da177e4
LT
72 device numbers are used to derive the corresponding array index.
73*/
74
1da177e4 75/*
1da177e4
LT
76 A driver needs to provide a dev_node_t structure for each device
77 on a card. In some cases, there is only one device per card (for
78 example, ethernet cards, modems). In other cases, there may be
79 many actual or logical devices (SCSI adapters, memory cards with
80 multiple partitions). The dev_node_t structures need to be kept
fba395ee 81 in a linked list starting at the 'dev' field of a struct pcmcia_device
1da177e4
LT
82 structure. We allocate them in the card's private data structure,
83 because they generally can't be allocated dynamically.
84*/
85
86typedef struct local_info_t {
87 dev_node_t node;
88} local_info_t;
89
90/*======================================================================
91
92 avmcs_attach() creates an "instance" of the driver, allocating
93 local data structures for one device. The device is registered
94 with Card Services.
95
96 The dev_link structure is initialized, but we don't actually
97 configure the card at this point -- we wait until we receive a
98 card insertion event.
99
100======================================================================*/
101
15b99ac1 102static int avmcs_probe(struct pcmcia_device *p_dev)
1da177e4 103{
1da177e4 104 local_info_t *local;
f8cfa618 105
1da177e4 106 /* The io structure describes IO port mapping */
fd238232
DB
107 p_dev->io.NumPorts1 = 16;
108 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
109 p_dev->io.NumPorts2 = 0;
1da177e4
LT
110
111 /* Interrupt setup */
fd238232
DB
112 p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
113 p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
114
115 p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
1da177e4 116
1da177e4 117 /* General socket configuration */
fd238232
DB
118 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
119 p_dev->conf.IntType = INT_MEMORY_AND_IO;
120 p_dev->conf.ConfigIndex = 1;
121 p_dev->conf.Present = PRESENT_OPTION;
1da177e4
LT
122
123 /* Allocate space for private device-specific data */
124 local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
125 if (!local)
fd238232 126 goto err;
1da177e4 127 memset(local, 0, sizeof(local_info_t));
fd238232 128 p_dev->priv = local;
f8cfa618 129
15b99ac1 130 return avmcs_config(p_dev);
1da177e4 131
1da177e4 132 err:
15b99ac1 133 return -ENOMEM;
1da177e4
LT
134} /* avmcs_attach */
135
136/*======================================================================
137
138 This deletes a driver "instance". The device is de-registered
139 with Card Services. If it has been released, all local data
140 structures are freed. Otherwise, the structures will be freed
141 when the device is released.
142
143======================================================================*/
144
fba395ee 145static void avmcs_detach(struct pcmcia_device *link)
1da177e4 146{
cc3b4866 147 avmcs_release(link);
e2d40963 148 kfree(link->priv);
1da177e4
LT
149} /* avmcs_detach */
150
151/*======================================================================
152
153 avmcs_config() is scheduled to run after a CARD_INSERTION event
154 is received, to configure the PCMCIA socket, and to make the
155 ethernet device available to the system.
156
157======================================================================*/
158
fba395ee 159static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
1da177e4
LT
160 cisparse_t *parse)
161{
162 int i = pcmcia_get_tuple_data(handle, tuple);
163 if (i != CS_SUCCESS) return i;
164 return pcmcia_parse_tuple(handle, tuple, parse);
165}
166
fba395ee 167static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
1da177e4
LT
168 cisparse_t *parse)
169{
170 int i = pcmcia_get_first_tuple(handle, tuple);
171 if (i != CS_SUCCESS) return i;
172 return get_tuple(handle, tuple, parse);
173}
174
fba395ee 175static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
1da177e4
LT
176 cisparse_t *parse)
177{
178 int i = pcmcia_get_next_tuple(handle, tuple);
179 if (i != CS_SUCCESS) return i;
180 return get_tuple(handle, tuple, parse);
181}
182
15b99ac1 183static int avmcs_config(struct pcmcia_device *link)
1da177e4 184{
1da177e4
LT
185 tuple_t tuple;
186 cisparse_t parse;
187 cistpl_cftable_entry_t *cf = &parse.cftable_entry;
188 local_info_t *dev;
189 int i;
190 u_char buf[64];
191 char devname[128];
192 int cardtype;
193 int (*addcard)(unsigned int port, unsigned irq);
fba395ee 194
1da177e4
LT
195 dev = link->priv;
196
197 /*
198 This reads the card's CONFIG tuple to find its configuration
199 registers.
200 */
201 do {
202 tuple.DesiredTuple = CISTPL_CONFIG;
fba395ee 203 i = pcmcia_get_first_tuple(link, &tuple);
1da177e4
LT
204 if (i != CS_SUCCESS) break;
205 tuple.TupleData = buf;
206 tuple.TupleDataMax = 64;
207 tuple.TupleOffset = 0;
fba395ee 208 i = pcmcia_get_tuple_data(link, &tuple);
1da177e4 209 if (i != CS_SUCCESS) break;
fba395ee 210 i = pcmcia_parse_tuple(link, &tuple, &parse);
1da177e4
LT
211 if (i != CS_SUCCESS) break;
212 link->conf.ConfigBase = parse.config.base;
213 } while (0);
214 if (i != CS_SUCCESS) {
fba395ee 215 cs_error(link, ParseTuple, i);
15b99ac1 216 return -ENODEV;
1da177e4 217 }
1da177e4
LT
218
219 do {
220
221 tuple.Attributes = 0;
222 tuple.TupleData = buf;
223 tuple.TupleDataMax = 254;
224 tuple.TupleOffset = 0;
225 tuple.DesiredTuple = CISTPL_VERS_1;
226
227 devname[0] = 0;
fba395ee 228 if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
1da177e4
LT
229 strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
230 sizeof(devname));
231 }
232 /*
233 * find IO port
234 */
235 tuple.TupleData = (cisdata_t *)buf;
236 tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
237 tuple.Attributes = 0;
238 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
fba395ee 239 i = first_tuple(link, &tuple, &parse);
1da177e4
LT
240 while (i == CS_SUCCESS) {
241 if (cf->io.nwin > 0) {
242 link->conf.ConfigIndex = cf->index;
243 link->io.BasePort1 = cf->io.win[0].base;
244 link->io.NumPorts1 = cf->io.win[0].len;
245 link->io.NumPorts2 = 0;
246 printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
247 link->io.BasePort1,
248 link->io.BasePort1+link->io.NumPorts1-1);
fba395ee 249 i = pcmcia_request_io(link, &link->io);
1da177e4
LT
250 if (i == CS_SUCCESS) goto found_port;
251 }
fba395ee 252 i = next_tuple(link, &tuple, &parse);
1da177e4
LT
253 }
254
255found_port:
256 if (i != CS_SUCCESS) {
fba395ee 257 cs_error(link, RequestIO, i);
1da177e4
LT
258 break;
259 }
50db3fdb 260
1da177e4
LT
261 /*
262 * allocate an interrupt line
263 */
fba395ee 264 i = pcmcia_request_irq(link, &link->irq);
1da177e4 265 if (i != CS_SUCCESS) {
fba395ee 266 cs_error(link, RequestIRQ, i);
50db3fdb 267 /* undo */
fba395ee 268 pcmcia_disable_device(link);
1da177e4
LT
269 break;
270 }
50db3fdb 271
1da177e4
LT
272 /*
273 * configure the PCMCIA socket
274 */
fba395ee 275 i = pcmcia_request_configuration(link, &link->conf);
1da177e4 276 if (i != CS_SUCCESS) {
fba395ee
DB
277 cs_error(link, RequestConfiguration, i);
278 pcmcia_disable_device(link);
1da177e4
LT
279 break;
280 }
281
282 } while (0);
283
284 /* At this point, the dev_node_t structure(s) should be
285 initialized and arranged in a linked list at link->dev. */
286
287 if (devname[0]) {
288 char *s = strrchr(devname, ' ');
289 if (!s)
290 s = devname;
291 else s++;
292 strcpy(dev->node.dev_name, s);
293 if (strcmp("M1", s) == 0) {
294 cardtype = AVM_CARDTYPE_M1;
295 } else if (strcmp("M2", s) == 0) {
296 cardtype = AVM_CARDTYPE_M2;
297 } else {
298 cardtype = AVM_CARDTYPE_B1;
299 }
300 } else {
301 strcpy(dev->node.dev_name, "b1");
302 cardtype = AVM_CARDTYPE_B1;
303 }
304
305 dev->node.major = 64;
306 dev->node.minor = 0;
fd238232 307 link->dev_node = &dev->node;
e2d40963 308
1da177e4
LT
309 /* If any step failed, release any partially configured state */
310 if (i != 0) {
311 avmcs_release(link);
15b99ac1 312 return -ENODEV;
1da177e4
LT
313 }
314
315
316 switch (cardtype) {
317 case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
318 case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
319 default:
320 case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
321 }
322 if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
323 printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
324 dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
325 avmcs_release(link);
15b99ac1 326 return -ENODEV;
1da177e4
LT
327 }
328 dev->node.minor = i;
15b99ac1 329 return 0;
1da177e4
LT
330
331} /* avmcs_config */
332
333/*======================================================================
334
335 After a card is removed, avmcs_release() will unregister the net
336 device, and release the PCMCIA configuration. If the device is
337 still open, this will be postponed until it is closed.
338
339======================================================================*/
340
fba395ee 341static void avmcs_release(struct pcmcia_device *link)
1da177e4 342{
5f2a71fc 343 b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
fba395ee 344 pcmcia_disable_device(link);
1da177e4
LT
345} /* avmcs_release */
346
1da177e4 347
a13bcf0d
DB
348static struct pcmcia_device_id avmcs_ids[] = {
349 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
350 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430),
351 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a),
352 PCMCIA_DEVICE_NULL
353};
354MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
355
1da177e4
LT
356static struct pcmcia_driver avmcs_driver = {
357 .owner = THIS_MODULE,
358 .drv = {
359 .name = "avm_cs",
360 },
15b99ac1 361 .probe = avmcs_probe,
cc3b4866 362 .remove = avmcs_detach,
a13bcf0d 363 .id_table = avmcs_ids,
1da177e4
LT
364};
365
366static int __init avmcs_init(void)
367{
368 return pcmcia_register_driver(&avmcs_driver);
369}
370
371static void __exit avmcs_exit(void)
372{
373 pcmcia_unregister_driver(&avmcs_driver);
1da177e4
LT
374}
375
376module_init(avmcs_init);
377module_exit(avmcs_exit);
This page took 0.146196 seconds and 5 git commands to generate.