* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / isdn / avmb1 / t1isa.c
blob3546e10610f3744b81e1644b7035140a3dd95a5b
1 /*
2 * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $
3 *
4 * Module for AVM T1 HEMA-card.
5 *
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
7 *
8 * $Log: t1isa.c,v $
9 * Revision 1.5 1999/08/22 20:26:28 calle
10 * backported changes from kernel 2.3.14:
11 * - several #include "config.h" gone, others come.
12 * - "struct device" changed to "struct net_device" in 2.3.14, added a
13 * define in isdn_compat.h for older kernel versions.
15 * Revision 1.4 1999/07/09 15:05:50 keil
16 * compat.h is now isdn_compat.h
18 * Revision 1.3 1999/07/06 07:42:04 calle
19 * - changes in /proc interface
20 * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
22 * Revision 1.2 1999/07/05 15:09:54 calle
23 * - renamed "appl_release" to "appl_released".
24 * - version und profile data now cleared on controller reset
25 * - extended /proc interface, to allow driver and controller specific
26 * informations to include by driver hackers.
28 * Revision 1.1 1999/07/01 15:26:44 calle
29 * complete new version (I love it):
30 * + new hardware independed "capi_driver" interface that will make it easy to:
31 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
32 * - write a CAPI-2.0 for the passive cards
33 * - support serial link CAPI-2.0 boxes.
34 * + wrote "capi_driver" for all supported cards.
35 * + "capi_driver" (supported cards) now have to be configured with
36 * make menuconfig, in the past all supported cards where included
37 * at once.
38 * + new and better informations in /proc/capi/
39 * + new ioctl to switch trace of capi messages per controller
40 * using "avmcapictrl trace [contr] on|off|...."
41 * + complete testcircle with all supported cards and also the
42 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
47 #include <linux/module.h>
48 #include <linux/kernel.h>
49 #include <linux/skbuff.h>
50 #include <linux/delay.h>
51 #include <linux/mm.h>
52 #include <linux/interrupt.h>
53 #include <linux/ioport.h>
54 #include <linux/capi.h>
55 #include <asm/io.h>
56 #include <linux/isdn_compat.h>
57 #include "capicmd.h"
58 #include "capiutil.h"
59 #include "capilli.h"
60 #include "avmcard.h"
62 static char *revision = "$Revision: 1.5 $";
64 /* ------------------------------------------------------------- */
66 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
68 /* ------------------------------------------------------------- */
70 static struct capi_driver_interface *di;
72 /* ------------------------------------------------------------- */
74 static int hema_irq_table[16] =
75 {0,
78 0x80, /* irq 3 */
80 0x90, /* irq 5 */
82 0xA0, /* irq 7 */
84 0xB0, /* irq 9 */
85 0xC0, /* irq 10 */
86 0xD0, /* irq 11 */
87 0xE0, /* irq 12 */
90 0xF0, /* irq 15 */
93 static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
95 unsigned char cregs[8];
96 unsigned char reverse_cardnr;
97 unsigned long flags;
98 unsigned char dummy;
99 int i;
101 reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
102 | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
103 cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
104 cregs[1] = 0x00; /* fast & slow link connected to CON1 */
105 cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
106 cregs[3] = 0;
107 cregs[4] = 0x11; /* zero wait state */
108 cregs[5] = hema_irq_table[irq & 0xf];
109 cregs[6] = 0;
110 cregs[7] = 0;
112 save_flags(flags);
113 cli();
114 /* board reset */
115 t1outp(base, T1_RESETBOARD, 0xf);
116 udelay(100 * 1000);
117 dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
119 /* write config */
120 dummy = (base >> 4) & 0xff;
121 for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
122 t1outp(base, HEMA_PAL_ID & 0xf, dummy);
123 t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
124 for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
125 t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
126 restore_flags(flags);
128 udelay(100 * 1000);
129 t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
130 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
131 udelay(10 * 1000);
132 t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
133 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
134 udelay(100 * 1000);
135 t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
136 t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
137 udelay(10 * 1000);
138 t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
139 udelay(5 * 1000);
140 t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
142 if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
143 return 1;
144 if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
145 return 2;
146 if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
147 return 3;
148 if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
149 return 4;
150 if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
151 return 5;
152 if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
153 return 6;
154 if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
155 return 7;
156 if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
157 return 8;
158 if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
159 return 9;
160 return 0;
163 static void t1_handle_interrupt(avmcard * card)
165 struct capi_ctr *ctrl = card->ctrl;
166 unsigned char b1cmd;
167 struct sk_buff *skb;
169 unsigned ApplId;
170 unsigned MsgLen;
171 unsigned DataB3Len;
172 unsigned NCCI;
173 unsigned WindowSize;
175 while (b1_rx_full(card->port)) {
177 b1cmd = b1_get_byte(card->port);
179 switch (b1cmd) {
181 case RECEIVE_DATA_B3_IND:
183 ApplId = (unsigned) b1_get_word(card->port);
184 MsgLen = t1_get_slice(card->port, card->msgbuf);
185 DataB3Len = t1_get_slice(card->port, card->databuf);
187 if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
188 printk(KERN_ERR "t1isa: incoming packet dropped\n");
189 } else {
190 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
191 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
192 CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
193 ctrl->handle_capimsg(ctrl, ApplId, skb);
195 break;
197 case RECEIVE_MESSAGE:
199 ApplId = (unsigned) b1_get_word(card->port);
200 MsgLen = t1_get_slice(card->port, card->msgbuf);
201 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
202 printk(KERN_ERR "t1isa: incoming packet dropped\n");
203 } else {
204 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
205 ctrl->handle_capimsg(ctrl, ApplId, skb);
207 break;
209 case RECEIVE_NEW_NCCI:
211 ApplId = b1_get_word(card->port);
212 NCCI = b1_get_word(card->port);
213 WindowSize = b1_get_word(card->port);
215 ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
217 break;
219 case RECEIVE_FREE_NCCI:
221 ApplId = b1_get_word(card->port);
222 NCCI = b1_get_word(card->port);
224 if (NCCI != 0xffffffff)
225 ctrl->free_ncci(ctrl, ApplId, NCCI);
226 else ctrl->appl_released(ctrl, ApplId);
227 break;
229 case RECEIVE_START:
230 b1_put_byte(card->port, SEND_POLLACK);
231 ctrl->resume_output(ctrl);
232 break;
234 case RECEIVE_STOP:
235 ctrl->suspend_output(ctrl);
236 break;
238 case RECEIVE_INIT:
240 card->versionlen = t1_get_slice(card->port, card->versionbuf);
241 b1_parse_version(card);
242 printk(KERN_INFO "%s: %s-card (%s) now active\n",
243 card->name,
244 card->version[VER_CARDTYPE],
245 card->version[VER_DRIVER]);
246 ctrl->ready(ctrl);
247 break;
249 case RECEIVE_TASK_READY:
250 ApplId = (unsigned) b1_get_word(card->port);
251 MsgLen = t1_get_slice(card->port, card->msgbuf);
252 card->msgbuf[MsgLen--] = 0;
253 while ( MsgLen >= 0
254 && ( card->msgbuf[MsgLen] == '\n'
255 || card->msgbuf[MsgLen] == '\r'))
256 card->msgbuf[MsgLen--] = 0;
257 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
258 card->name, ApplId, card->msgbuf);
259 break;
261 case RECEIVE_DEBUGMSG:
262 MsgLen = t1_get_slice(card->port, card->msgbuf);
263 card->msgbuf[MsgLen--] = 0;
264 while ( MsgLen >= 0
265 && ( card->msgbuf[MsgLen] == '\n'
266 || card->msgbuf[MsgLen] == '\r'))
267 card->msgbuf[MsgLen--] = 0;
268 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
269 break;
271 case 0xff:
272 printk(KERN_ERR "%s: card reseted ?\n", card->name);
273 return;
274 default:
275 printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
276 card->name, b1cmd);
277 return;
282 /* ------------------------------------------------------------- */
284 static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
286 avmcard *card;
288 card = (avmcard *) devptr;
290 if (!card) {
291 printk(KERN_WARNING "t1_interrupt: wrong device\n");
292 return;
294 if (card->interrupt) {
295 printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name);
296 return;
299 card->interrupt = 1;
301 t1_handle_interrupt(card);
303 card->interrupt = 0;
305 /* ------------------------------------------------------------- */
307 static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
309 avmcard *card = (avmcard *)(ctrl->driverdata);
310 unsigned int port = card->port;
311 unsigned long flags;
312 int retval;
314 t1_disable_irq(port);
315 b1_reset(port);
317 if ((retval = b1_load_t4file(port, &data->firmware))) {
318 b1_reset(port);
319 printk(KERN_ERR "%s: failed to load t4file!!\n",
320 card->name);
321 return retval;
324 if (data->configuration.len > 0 && data->configuration.data) {
325 if ((retval = b1_load_config(port, &data->configuration))) {
326 b1_reset(port);
327 printk(KERN_ERR "%s: failed to load config!!\n",
328 card->name);
329 return retval;
333 if (!b1_loaded(port)) {
334 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
335 return -EIO;
338 save_flags(flags);
339 cli();
340 b1_setinterrupt(port, card->irq, card->cardtype);
341 b1_put_byte(port, SEND_INIT);
342 b1_put_word(port, AVM_NAPPS);
343 b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
344 b1_put_word(port, ctrl->cnr - 1);
345 restore_flags(flags);
347 return 0;
350 void t1isa_reset_ctr(struct capi_ctr *ctrl)
352 avmcard *card = (avmcard *)(ctrl->driverdata);
353 unsigned int port = card->port;
355 t1_disable_irq(port);
356 b1_reset(port);
357 b1_reset(port);
359 memset(card->version, 0, sizeof(card->version));
360 ctrl->reseted(ctrl);
363 static void t1isa_remove_ctr(struct capi_ctr *ctrl)
365 avmcard *card = (avmcard *)(ctrl->driverdata);
366 unsigned int port = card->port;
368 t1_disable_irq(port);
369 b1_reset(port);
370 b1_reset(port);
371 t1_reset(port);
373 di->detach_ctr(ctrl);
374 free_irq(card->irq, card);
375 release_region(card->port, AVMB1_PORTLEN);
376 kfree(card);
378 MOD_DEC_USE_COUNT;
381 /* ------------------------------------------------------------- */
383 static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
385 struct capi_ctr *ctrl;
386 avmcard *card;
387 int retval;
389 card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
391 if (!card) {
392 printk(KERN_WARNING "t1isa: no memory.\n");
393 return -ENOMEM;
395 memset(card, 0, sizeof(avmcard));
396 sprintf(card->name, "t1isa-%x", p->port);
397 card->port = p->port;
398 card->irq = p->irq;
399 card->cardtype = avm_t1isa;
400 card->cardnr = p->cardnr;
402 if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
403 printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port);
404 kfree(card);
405 return -EINVAL;
408 if (check_region(card->port, AVMB1_PORTLEN)) {
409 printk(KERN_WARNING
410 "t1isa: ports 0x%03x-0x%03x in use.\n",
411 card->port, card->port + AVMB1_PORTLEN);
412 kfree(card);
413 return -EBUSY;
415 if (hema_irq_table[card->irq & 0xf] == 0) {
416 printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq);
417 kfree(card);
418 return -EINVAL;
420 for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
421 if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) {
422 printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr);
423 kfree(card);
424 return -EBUSY;
427 if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
428 printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n",
429 card->port, retval);
430 kfree(card);
431 return -EIO;
433 t1_disable_irq(card->port);
434 b1_reset(card->port);
436 request_region(p->port, AVMB1_PORTLEN, card->name);
438 retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
439 if (retval) {
440 printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq);
441 release_region(card->port, AVMB1_PORTLEN);
442 kfree(card);
443 return -EBUSY;
446 card->ctrl = di->attach_ctr(driver, card->name, card);
447 if (!card->ctrl) {
448 printk(KERN_ERR "t1isa: attach controller failed.\n");
449 free_irq(card->irq, card);
450 release_region(card->port, AVMB1_PORTLEN);
451 kfree(card);
452 return -EBUSY;
455 MOD_INC_USE_COUNT;
456 return 0;
459 static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
461 avmcard *card = (avmcard *)(ctrl->driverdata);
462 unsigned int port = card->port;
463 unsigned long flags;
464 __u16 len = CAPIMSG_LEN(skb->data);
465 __u8 cmd = CAPIMSG_COMMAND(skb->data);
466 __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
468 save_flags(flags);
469 cli();
470 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
471 __u16 dlen = CAPIMSG_DATALEN(skb->data);
472 b1_put_byte(port, SEND_DATA_B3_REQ);
473 t1_put_slice(port, skb->data, len);
474 t1_put_slice(port, skb->data + len, dlen);
475 } else {
476 b1_put_byte(port, SEND_MESSAGE);
477 t1_put_slice(port, skb->data, len);
479 restore_flags(flags);
480 dev_kfree_skb(skb);
482 /* ------------------------------------------------------------- */
484 static char *t1isa_procinfo(struct capi_ctr *ctrl)
486 avmcard *card = (avmcard *)(ctrl->driverdata);
487 if (!card)
488 return "";
489 sprintf(card->infobuf, "%s %s 0x%x %d %d",
490 card->cardname[0] ? card->cardname : "-",
491 card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
492 card->port, card->irq, card->cardnr
494 return card->infobuf;
498 /* ------------------------------------------------------------- */
500 static struct capi_driver t1isa_driver = {
501 "t1isa",
502 "0.0",
503 t1isa_load_firmware,
504 t1isa_reset_ctr,
505 t1isa_remove_ctr,
506 b1_register_appl,
507 b1_release_appl,
508 t1isa_send_message,
510 t1isa_procinfo,
511 b1ctl_read_proc,
512 0, /* use standard driver_read_proc */
514 t1isa_add_card,
517 #ifdef MODULE
518 #define t1isa_init init_module
519 void cleanup_module(void);
520 #endif
522 int t1isa_init(void)
524 struct capi_driver *driver = &t1isa_driver;
525 char *p;
527 if ((p = strchr(revision, ':'))) {
528 strncpy(driver->revision, p + 1, sizeof(driver->revision));
529 p = strchr(driver->revision, '$');
530 *p = 0;
533 printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
535 di = attach_capi_driver(driver);
537 if (!di) {
538 printk(KERN_ERR "%s: failed to attach capi_driver\n",
539 driver->name);
540 return -EIO;
542 return 0;
545 #ifdef MODULE
546 void cleanup_module(void)
548 detach_capi_driver(&t1isa_driver);
550 #endif