File: /usr/src/linux/drivers/isdn/avmb1/b1pcmcia.c
1 /*
2 * $Id: b1pcmcia.c,v 1.12.6.4 2001/05/17 20:41:51 kai Exp $
3 *
4 * Module for AVM B1/M1/M2 PCMCIA-card.
5 *
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
7 *
8 */
9
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/skbuff.h>
13 #include <linux/delay.h>
14 #include <linux/mm.h>
15 #include <linux/interrupt.h>
16 #include <linux/ioport.h>
17 #include <linux/init.h>
18 #include <asm/io.h>
19 #include <linux/capi.h>
20 #include <linux/b1pcmcia.h>
21 #include "capicmd.h"
22 #include "capiutil.h"
23 #include "capilli.h"
24 #include "avmcard.h"
25
26 static char *revision = "$Revision: 1.12.6.4 $";
27
28 /* ------------------------------------------------------------- */
29
30 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
31
32 /* ------------------------------------------------------------- */
33
34 static struct capi_driver_interface *di;
35
36 /* ------------------------------------------------------------- */
37
38 static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
39 {
40 avmcard *card;
41
42 card = (avmcard *) devptr;
43
44 if (!card) {
45 printk(KERN_WARNING "b1pcmcia: interrupt: wrong device\n");
46 return;
47 }
48 if (card->interrupt) {
49 printk(KERN_ERR "%s: reentering interrupt hander.\n",
50 card->name);
51 return;
52 }
53
54 card->interrupt = 1;
55
56 b1_handle_interrupt(card);
57
58 card->interrupt = 0;
59 }
60 /* ------------------------------------------------------------- */
61
62 static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
63 {
64 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
65 avmcard *card = cinfo->card;
66 unsigned int port = card->port;
67
68 b1_reset(port);
69 b1_reset(port);
70
71 di->detach_ctr(ctrl);
72 free_irq(card->irq, card);
73 /* io addrsses managent by CardServices
74 * release_region(card->port, AVMB1_PORTLEN);
75 */
76 kfree(card);
77
78 MOD_DEC_USE_COUNT;
79 }
80
81 /* ------------------------------------------------------------- */
82
83 static int b1pcmcia_add_card(struct capi_driver *driver,
84 unsigned int port,
85 unsigned irq,
86 enum avmcardtype cardtype)
87 {
88 avmctrl_info *cinfo;
89 avmcard *card;
90 char *cardname;
91 int retval;
92
93 MOD_INC_USE_COUNT;
94
95 card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
96
97 if (!card) {
98 printk(KERN_WARNING "%s: no memory.\n", driver->name);
99 MOD_DEC_USE_COUNT;
100 return -ENOMEM;
101 }
102 memset(card, 0, sizeof(avmcard));
103 cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
104 if (!cinfo) {
105 printk(KERN_WARNING "%s: no memory.\n", driver->name);
106 kfree(card);
107 MOD_DEC_USE_COUNT;
108 return -ENOMEM;
109 }
110 memset(cinfo, 0, sizeof(avmctrl_info));
111 card->ctrlinfo = cinfo;
112 cinfo->card = card;
113 switch (cardtype) {
114 case avm_m1: sprintf(card->name, "m1-%x", port); break;
115 case avm_m2: sprintf(card->name, "m2-%x", port); break;
116 default: sprintf(card->name, "b1pcmcia-%x", port); break;
117 }
118 card->port = port;
119 card->irq = irq;
120 card->cardtype = cardtype;
121
122 b1_reset(card->port);
123 if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
124 printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
125 driver->name, card->port, retval);
126 kfree(card->ctrlinfo);
127 kfree(card);
128 MOD_DEC_USE_COUNT;
129 return -EIO;
130 }
131 b1_reset(card->port);
132 b1_getrevision(card);
133
134 retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card);
135 if (retval) {
136 printk(KERN_ERR "%s: unable to get IRQ %d.\n",
137 driver->name, card->irq);
138 kfree(card->ctrlinfo);
139 kfree(card);
140 MOD_DEC_USE_COUNT;
141 return -EBUSY;
142 }
143
144 cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
145 if (!cinfo->capi_ctrl) {
146 printk(KERN_ERR "%s: attach controller failed.\n",
147 driver->name);
148 free_irq(card->irq, card);
149 kfree(card->ctrlinfo);
150 kfree(card);
151 MOD_DEC_USE_COUNT;
152 return -EBUSY;
153 }
154 switch (cardtype) {
155 case avm_m1: cardname = "M1"; break;
156 case avm_m2: cardname = "M2"; break;
157 default : cardname = "B1 PCMCIA"; break;
158 }
159
160 printk(KERN_INFO
161 "%s: AVM %s at i/o %#x, irq %d, revision %d\n",
162 driver->name, cardname, card->port, card->irq, card->revision);
163
164 return cinfo->capi_ctrl->cnr;
165 }
166
167 /* ------------------------------------------------------------- */
168
169 static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
170 {
171 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
172
173 if (!cinfo)
174 return "";
175 sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
176 cinfo->cardname[0] ? cinfo->cardname : "-",
177 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
178 cinfo->card ? cinfo->card->port : 0x0,
179 cinfo->card ? cinfo->card->irq : 0,
180 cinfo->card ? cinfo->card->revision : 0
181 );
182 return cinfo->infobuf;
183 }
184
185 /* ------------------------------------------------------------- */
186
187 static struct capi_driver b1pcmcia_driver = {
188 name: "b1pcmcia",
189 revision: "0.0",
190 load_firmware: b1_load_firmware,
191 reset_ctr: b1_reset_ctr,
192 remove_ctr: b1pcmcia_remove_ctr,
193 register_appl: b1_register_appl,
194 release_appl: b1_release_appl,
195 send_message: b1_send_message,
196
197 procinfo: b1pcmcia_procinfo,
198 ctr_read_proc: b1ctl_read_proc,
199 driver_read_proc: 0, /* use standard driver_read_proc */
200
201 add_card: 0,
202 };
203
204 /* ------------------------------------------------------------- */
205
206 int b1pcmcia_addcard_b1(unsigned int port, unsigned irq)
207 {
208 return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_b1pcmcia);
209 }
210
211 int b1pcmcia_addcard_m1(unsigned int port, unsigned irq)
212 {
213 return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m1);
214 }
215
216 int b1pcmcia_addcard_m2(unsigned int port, unsigned irq)
217 {
218 return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m2);
219 }
220
221 int b1pcmcia_delcard(unsigned int port, unsigned irq)
222 {
223 struct capi_ctr *ctrl;
224 avmcard *card;
225
226 for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) {
227 card = ((avmctrl_info *)(ctrl->driverdata))->card;
228 if (card->port == port && card->irq == irq) {
229 b1pcmcia_remove_ctr(ctrl);
230 return 0;
231 }
232 }
233 return -ESRCH;
234 }
235
236 EXPORT_SYMBOL(b1pcmcia_addcard_b1);
237 EXPORT_SYMBOL(b1pcmcia_addcard_m1);
238 EXPORT_SYMBOL(b1pcmcia_addcard_m2);
239 EXPORT_SYMBOL(b1pcmcia_delcard);
240
241 /* ------------------------------------------------------------- */
242
243 static int __init b1pcmcia_init(void)
244 {
245 struct capi_driver *driver = &b1pcmcia_driver;
246 char *p;
247 int retval = 0;
248
249 MOD_INC_USE_COUNT;
250
251 if ((p = strchr(revision, ':')) != 0 && p[1]) {
252 strncpy(driver->revision, p + 2, sizeof(driver->revision));
253 driver->revision[sizeof(driver->revision)-1] = 0;
254 if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
255 *(p-1) = 0;
256 }
257
258 printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
259
260 di = attach_capi_driver(driver);
261
262 if (!di) {
263 printk(KERN_ERR "%s: failed to attach capi_driver\n",
264 driver->name);
265 retval = -EIO;
266 }
267 MOD_DEC_USE_COUNT;
268 return retval;
269 }
270
271 static void __exit b1pcmcia_exit(void)
272 {
273 detach_capi_driver(&b1pcmcia_driver);
274 }
275
276 module_init(b1pcmcia_init);
277 module_exit(b1pcmcia_exit);
278