]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/isdn/hardware/avm/avm_cs.c
pcmcia: do not use io_req_t when calling pcmcia_request_io()
[net-next-2.6.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>
1da177e4 15#include <linux/ptrace.h>
1da177e4
LT
16#include <linux/string.h>
17#include <linux/tty.h>
18#include <linux/serial.h>
19#include <linux/major.h>
20#include <asm/io.h>
21#include <asm/system.h>
22
1da177e4
LT
23#include <pcmcia/cs.h>
24#include <pcmcia/cistpl.h>
25#include <pcmcia/ciscode.h>
26#include <pcmcia/ds.h>
27#include <pcmcia/cisreg.h>
28
29#include <linux/skbuff.h>
30#include <linux/capi.h>
31#include <linux/b1lli.h>
32#include <linux/b1pcmcia.h>
33
34/*====================================================================*/
35
36MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
37MODULE_AUTHOR("Carsten Paeth");
38MODULE_LICENSE("GPL");
39
40/*====================================================================*/
41
42/*
43 The event() function is this driver's Card Services event handler.
44 It will be called by Card Services when an appropriate card status
45 event is received. The config() and release() entry points are
46 used to configure or release a socket, in response to card insertion
47 and ejection events. They are invoked from the skeleton event
48 handler.
49*/
50
15b99ac1 51static int avmcs_config(struct pcmcia_device *link);
fba395ee 52static void avmcs_release(struct pcmcia_device *link);
1da177e4
LT
53
54/*
55 The attach() and detach() entry points are used to create and destroy
56 "instances" of the driver, where each instance represents everything
57 needed to manage one actual PCMCIA card.
58*/
59
cc3b4866 60static void avmcs_detach(struct pcmcia_device *p_dev);
1da177e4 61
1da177e4
LT
62/*======================================================================
63
64 avmcs_attach() creates an "instance" of the driver, allocating
65 local data structures for one device. The device is registered
66 with Card Services.
67
68 The dev_link structure is initialized, but we don't actually
69 configure the card at this point -- we wait until we receive a
70 card insertion event.
71
72======================================================================*/
73
15b99ac1 74static int avmcs_probe(struct pcmcia_device *p_dev)
1da177e4 75{
f8cfa618 76
1da177e4 77 /* The io structure describes IO port mapping */
90abdc3b
DB
78 p_dev->resource[0]->end = 16;
79 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
1da177e4 80
1da177e4 81 /* General socket configuration */
fd238232
DB
82 p_dev->conf.Attributes = CONF_ENABLE_IRQ;
83 p_dev->conf.IntType = INT_MEMORY_AND_IO;
84 p_dev->conf.ConfigIndex = 1;
85 p_dev->conf.Present = PRESENT_OPTION;
1da177e4 86
15b99ac1 87 return avmcs_config(p_dev);
1da177e4
LT
88} /* avmcs_attach */
89
90/*======================================================================
91
92 This deletes a driver "instance". The device is de-registered
93 with Card Services. If it has been released, all local data
94 structures are freed. Otherwise, the structures will be freed
95 when the device is released.
96
97======================================================================*/
98
fba395ee 99static void avmcs_detach(struct pcmcia_device *link)
1da177e4 100{
cc3b4866 101 avmcs_release(link);
1da177e4
LT
102} /* avmcs_detach */
103
104/*======================================================================
105
106 avmcs_config() is scheduled to run after a CARD_INSERTION event
107 is received, to configure the PCMCIA socket, and to make the
108 ethernet device available to the system.
109
110======================================================================*/
111
5fcd4da0
DB
112static int avmcs_configcheck(struct pcmcia_device *p_dev,
113 cistpl_cftable_entry_t *cf,
8e2fc39d 114 cistpl_cftable_entry_t *dflt,
ad913c11 115 unsigned int vcc,
5fcd4da0 116 void *priv_data)
1da177e4 117{
5fcd4da0
DB
118 if (cf->io.nwin <= 0)
119 return -ENODEV;
120
90abdc3b
DB
121 p_dev->resource[0]->start = cf->io.win[0].base;
122 p_dev->resource[0]->end = cf->io.win[0].len;
123 return pcmcia_request_io(p_dev);
1da177e4
LT
124}
125
15b99ac1 126static int avmcs_config(struct pcmcia_device *link)
1da177e4 127{
eb14120f 128 int i = -1;
1da177e4
LT
129 char devname[128];
130 int cardtype;
131 int (*addcard)(unsigned int port, unsigned irq);
fba395ee 132
5fcd4da0
DB
133 devname[0] = 0;
134 if (link->prod_id[1])
135 strlcpy(devname, link->prod_id[1], sizeof(devname));
a9606fd3 136
5fcd4da0
DB
137 /*
138 * find IO port
139 */
140 if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
141 return -ENODEV;
50db3fdb 142
5fcd4da0 143 do {
eb14120f 144 if (!link->irq) {
50db3fdb 145 /* undo */
fba395ee 146 pcmcia_disable_device(link);
1da177e4
LT
147 break;
148 }
50db3fdb 149
1da177e4
LT
150 /*
151 * configure the PCMCIA socket
152 */
fba395ee 153 i = pcmcia_request_configuration(link, &link->conf);
4c89e88b 154 if (i != 0) {
fba395ee 155 pcmcia_disable_device(link);
1da177e4
LT
156 break;
157 }
158
159 } while (0);
160
1da177e4
LT
161 if (devname[0]) {
162 char *s = strrchr(devname, ' ');
163 if (!s)
164 s = devname;
165 else s++;
1da177e4
LT
166 if (strcmp("M1", s) == 0) {
167 cardtype = AVM_CARDTYPE_M1;
168 } else if (strcmp("M2", s) == 0) {
169 cardtype = AVM_CARDTYPE_M2;
170 } else {
171 cardtype = AVM_CARDTYPE_B1;
172 }
ded6a1a3 173 } else
1da177e4 174 cardtype = AVM_CARDTYPE_B1;
e2d40963 175
1da177e4
LT
176 /* If any step failed, release any partially configured state */
177 if (i != 0) {
178 avmcs_release(link);
15b99ac1 179 return -ENODEV;
1da177e4
LT
180 }
181
182
183 switch (cardtype) {
184 case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
185 case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
186 default:
187 case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
188 }
9a017a91
DB
189 if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) {
190 dev_err(&link->dev,
191 "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n",
192 (unsigned int) link->resource[0]->start, link->irq);
ded6a1a3
DB
193 avmcs_release(link);
194 return -ENODEV;
1da177e4 195 }
15b99ac1 196 return 0;
1da177e4
LT
197
198} /* avmcs_config */
199
200/*======================================================================
201
202 After a card is removed, avmcs_release() will unregister the net
203 device, and release the PCMCIA configuration. If the device is
204 still open, this will be postponed until it is closed.
205
206======================================================================*/
207
fba395ee 208static void avmcs_release(struct pcmcia_device *link)
1da177e4 209{
9a017a91 210 b1pcmcia_delcard(link->resource[0]->start, link->irq);
fba395ee 211 pcmcia_disable_device(link);
1da177e4
LT
212} /* avmcs_release */
213
1da177e4 214
a13bcf0d
DB
215static struct pcmcia_device_id avmcs_ids[] = {
216 PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
217 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430),
218 PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a),
219 PCMCIA_DEVICE_NULL
220};
221MODULE_DEVICE_TABLE(pcmcia, avmcs_ids);
222
1da177e4
LT
223static struct pcmcia_driver avmcs_driver = {
224 .owner = THIS_MODULE,
225 .drv = {
226 .name = "avm_cs",
227 },
15b99ac1 228 .probe = avmcs_probe,
cc3b4866 229 .remove = avmcs_detach,
a13bcf0d 230 .id_table = avmcs_ids,
1da177e4
LT
231};
232
233static int __init avmcs_init(void)
234{
235 return pcmcia_register_driver(&avmcs_driver);
236}
237
238static void __exit avmcs_exit(void)
239{
240 pcmcia_unregister_driver(&avmcs_driver);
1da177e4
LT
241}
242
243module_init(avmcs_init);
244module_exit(avmcs_exit);