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