- Linus: more PageDirty / swapcache handling
[davej-history.git] / drivers / isdn / avmb1 / b1.c
blob3feb65ce9fc03ab9cfbc1d0a5c863d4cf313b052
1 /*
2 * $Id: b1.c,v 1.20 2000/11/23 20:45:14 kai Exp $
3 *
4 * Common module for AVM B1 cards.
5 *
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
7 *
8 * $Log: b1.c,v $
9 * Revision 1.20 2000/11/23 20:45:14 kai
10 * fixed module_init/exit stuff
11 * Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
13 * Revision 1.19 2000/11/19 17:02:47 kai
14 * compatibility cleanup - part 3
16 * Revision 1.18 2000/11/19 17:01:53 kai
17 * compatibility cleanup - part 2
19 * Revision 1.17 2000/11/01 14:05:02 calle
20 * - use module_init/module_exit from linux/init.h.
21 * - all static struct variables are initialized with "membername:" now.
22 * - avm_cs.c, let it work with newer pcmcia-cs.
24 * Revision 1.16 2000/08/04 15:36:31 calle
25 * copied wrong from file to file :-(
27 * Revision 1.15 2000/08/04 12:20:08 calle
28 * - Fix unsigned/signed warning in the right way ...
30 * Revision 1.14 2000/06/19 16:51:53 keil
31 * don't free skb in irq context
33 * Revision 1.13 2000/01/25 14:33:38 calle
34 * - Added Support AVM B1 PCI V4.0 (tested with prototype)
35 * - splitted up t1pci.c into b1dma.c for common function with b1pciv4
36 * - support for revision register
38 * Revision 1.12 1999/11/05 16:38:01 calle
39 * Cleanups before kernel 2.4:
40 * - Changed all messages to use card->name or driver->name instead of
41 * constant string.
42 * - Moved some data from struct avmcard into new struct avmctrl_info.
43 * Changed all lowlevel capi driver to match the new structur.
45 * Revision 1.11 1999/10/11 22:04:12 keil
46 * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
48 * Revision 1.10 1999/09/15 08:16:03 calle
49 * Implementation of 64Bit extention complete.
51 * Revision 1.9 1999/09/07 09:02:53 calle
52 * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
53 * DATA_B3_IND is always directly after the CAPI message. The "Data" member
54 * ist never used inside the kernel.
56 * Revision 1.8 1999/08/22 20:26:22 calle
57 * backported changes from kernel 2.3.14:
58 * - several #include "config.h" gone, others come.
59 * - "struct device" changed to "struct net_device" in 2.3.14, added a
60 * define in isdn_compat.h for older kernel versions.
62 * Revision 1.7 1999/08/04 10:10:09 calle
63 * Bugfix: corrected /proc functions, added structure for new AVM cards.
65 * Revision 1.6 1999/07/23 08:51:04 calle
66 * small fix and typo in checkin before.
68 * Revision 1.5 1999/07/23 08:41:48 calle
69 * prepared for new AVM cards.
71 * Revision 1.4 1999/07/09 15:05:38 keil
72 * compat.h is now isdn_compat.h
74 * Revision 1.3 1999/07/06 07:41:59 calle
75 * - changes in /proc interface
76 * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
78 * Revision 1.2 1999/07/05 15:09:47 calle
79 * - renamed "appl_release" to "appl_released".
80 * - version und profile data now cleared on controller reset
81 * - extended /proc interface, to allow driver and controller specific
82 * informations to include by driver hackers.
84 * Revision 1.1 1999/07/01 15:26:23 calle
85 * complete new version (I love it):
86 * + new hardware independed "capi_driver" interface that will make it easy to:
87 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
88 * - write a CAPI-2.0 for the passive cards
89 * - support serial link CAPI-2.0 boxes.
90 * + wrote "capi_driver" for all supported cards.
91 * + "capi_driver" (supported cards) now have to be configured with
92 * make menuconfig, in the past all supported cards where included
93 * at once.
94 * + new and better informations in /proc/capi/
95 * + new ioctl to switch trace of capi messages per controller
96 * using "avmcapictrl trace [contr] on|off|...."
97 * + complete testcircle with all supported cards and also the
98 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
103 #include <linux/module.h>
104 #include <linux/kernel.h>
105 #include <linux/skbuff.h>
106 #include <linux/delay.h>
107 #include <linux/mm.h>
108 #include <linux/interrupt.h>
109 #include <linux/ioport.h>
110 #include <linux/capi.h>
111 #include <asm/io.h>
112 #include <linux/init.h>
113 #include <asm/uaccess.h>
114 #include <linux/netdevice.h>
115 #include "capilli.h"
116 #include "avmcard.h"
117 #include "capicmd.h"
118 #include "capiutil.h"
120 static char *revision = "$Revision: 1.20 $";
122 /* ------------------------------------------------------------- */
124 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
126 /* ------------------------------------------------------------- */
128 int b1_irq_table[16] =
132 192, /* irq 3 */
133 32, /* irq 4 */
134 160, /* irq 5 */
135 96, /* irq 6 */
136 224, /* irq 7 */
138 64, /* irq 9 */
139 80, /* irq 10 */
140 208, /* irq 11 */
141 48, /* irq 12 */
144 112, /* irq 15 */
147 /* ------------------------------------------------------------- */
149 int b1_detect(unsigned int base, enum avmcardtype cardtype)
151 int onoff, i;
154 * Statusregister 0000 00xx
156 if ((inb(base + B1_INSTAT) & 0xfc)
157 || (inb(base + B1_OUTSTAT) & 0xfc))
158 return 1;
160 * Statusregister 0000 001x
162 b1outp(base, B1_INSTAT, 0x2); /* enable irq */
163 /* b1outp(base, B1_OUTSTAT, 0x2); */
164 if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
165 /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
166 return 2;
168 * Statusregister 0000 000x
170 b1outp(base, B1_INSTAT, 0x0); /* disable irq */
171 b1outp(base, B1_OUTSTAT, 0x0);
172 if ((inb(base + B1_INSTAT) & 0xfe)
173 || (inb(base + B1_OUTSTAT) & 0xfe))
174 return 3;
176 for (onoff = !0, i= 0; i < 10 ; i++) {
177 b1_set_test_bit(base, cardtype, onoff);
178 if (b1_get_test_bit(base, cardtype) != onoff)
179 return 4;
180 onoff = !onoff;
183 if (cardtype == avm_m1)
184 return 0;
186 if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
187 return 5;
189 return 0;
192 void b1_getrevision(avmcard *card)
194 card->class = inb(card->port + B1_ANALYSE);
195 card->revision = inb(card->port + B1_REVISION);
198 int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
200 unsigned char buf[256];
201 unsigned char *dp;
202 int i, left, retval;
203 unsigned int base = card->port;
205 dp = t4file->data;
206 left = t4file->len;
207 while (left > sizeof(buf)) {
208 if (t4file->user) {
209 retval = copy_from_user(buf, dp, sizeof(buf));
210 if (retval)
211 return -EFAULT;
212 } else {
213 memcpy(buf, dp, sizeof(buf));
215 for (i = 0; i < sizeof(buf); i++)
216 if (b1_save_put_byte(base, buf[i]) < 0) {
217 printk(KERN_ERR "%s: corrupted firmware file ?\n",
218 card->name);
219 return -EIO;
221 left -= sizeof(buf);
222 dp += sizeof(buf);
224 if (left) {
225 if (t4file->user) {
226 retval = copy_from_user(buf, dp, left);
227 if (retval)
228 return -EFAULT;
229 } else {
230 memcpy(buf, dp, left);
232 for (i = 0; i < left; i++)
233 if (b1_save_put_byte(base, buf[i]) < 0) {
234 printk(KERN_ERR "%s: corrupted firmware file ?\n",
235 card->name);
236 return -EIO;
239 return 0;
242 int b1_load_config(avmcard *card, capiloaddatapart * config)
244 unsigned char buf[256];
245 unsigned char *dp;
246 unsigned int base = card->port;
247 int i, j, left, retval;
249 dp = config->data;
250 left = config->len;
251 if (left) {
252 b1_put_byte(base, SEND_CONFIG);
253 b1_put_word(base, 1);
254 b1_put_byte(base, SEND_CONFIG);
255 b1_put_word(base, left);
257 while (left > sizeof(buf)) {
258 if (config->user) {
259 retval = copy_from_user(buf, dp, sizeof(buf));
260 if (retval)
261 return -EFAULT;
262 } else {
263 memcpy(buf, dp, sizeof(buf));
265 for (i = 0; i < sizeof(buf); ) {
266 b1_put_byte(base, SEND_CONFIG);
267 for (j=0; j < 4; j++) {
268 b1_put_byte(base, buf[i++]);
271 left -= sizeof(buf);
272 dp += sizeof(buf);
274 if (left) {
275 if (config->user) {
276 retval = copy_from_user(buf, dp, left);
277 if (retval)
278 return -EFAULT;
279 } else {
280 memcpy(buf, dp, left);
282 for (i = 0; i < left; ) {
283 b1_put_byte(base, SEND_CONFIG);
284 for (j=0; j < 4; j++) {
285 if (i < left)
286 b1_put_byte(base, buf[i++]);
287 else
288 b1_put_byte(base, 0);
292 return 0;
295 int b1_loaded(avmcard *card)
297 unsigned int base = card->port;
298 unsigned long stop;
299 unsigned char ans;
300 unsigned long tout = 2;
302 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
303 if (b1_tx_empty(base))
304 break;
306 if (!b1_tx_empty(base)) {
307 printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n",
308 card->name);
309 return 0;
311 b1_put_byte(base, SEND_POLL);
312 for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
313 if (b1_rx_full(base)) {
314 if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
315 return 1;
317 printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
318 card->name, ans);
319 return 0;
322 printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name);
323 return 0;
326 /* ------------------------------------------------------------- */
328 int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
330 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
331 avmcard *card = cinfo->card;
332 unsigned int port = card->port;
333 unsigned long flags;
334 int retval;
336 b1_reset(port);
338 if ((retval = b1_load_t4file(card, &data->firmware))) {
339 b1_reset(port);
340 printk(KERN_ERR "%s: failed to load t4file!!\n",
341 card->name);
342 return retval;
345 b1_disable_irq(port);
347 if (data->configuration.len > 0 && data->configuration.data) {
348 if ((retval = b1_load_config(card, &data->configuration))) {
349 b1_reset(port);
350 printk(KERN_ERR "%s: failed to load config!!\n",
351 card->name);
352 return retval;
356 if (!b1_loaded(card)) {
357 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
358 return -EIO;
361 save_flags(flags);
362 cli();
363 b1_setinterrupt(port, card->irq, card->cardtype);
364 b1_put_byte(port, SEND_INIT);
365 b1_put_word(port, AVM_NAPPS);
366 b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
367 b1_put_word(port, ctrl->cnr - 1);
368 restore_flags(flags);
370 return 0;
373 void b1_reset_ctr(struct capi_ctr *ctrl)
375 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
376 avmcard *card = cinfo->card;
377 unsigned int port = card->port;
379 b1_reset(port);
380 b1_reset(port);
382 memset(cinfo->version, 0, sizeof(cinfo->version));
383 ctrl->reseted(ctrl);
386 void b1_register_appl(struct capi_ctr *ctrl,
387 __u16 appl,
388 capi_register_params *rp)
390 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
391 avmcard *card = cinfo->card;
392 unsigned int port = card->port;
393 unsigned long flags;
394 int nconn, want = rp->level3cnt;
396 if (want > 0) nconn = want;
397 else nconn = ctrl->profile.nbchannel * -want;
398 if (nconn == 0) nconn = ctrl->profile.nbchannel;
400 save_flags(flags);
401 cli();
402 b1_put_byte(port, SEND_REGISTER);
403 b1_put_word(port, appl);
404 b1_put_word(port, 1024 * (nconn+1));
405 b1_put_word(port, nconn);
406 b1_put_word(port, rp->datablkcnt);
407 b1_put_word(port, rp->datablklen);
408 restore_flags(flags);
410 ctrl->appl_registered(ctrl, appl);
413 void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
415 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
416 avmcard *card = cinfo->card;
417 unsigned int port = card->port;
418 unsigned long flags;
420 save_flags(flags);
421 cli();
422 b1_put_byte(port, SEND_RELEASE);
423 b1_put_word(port, appl);
424 restore_flags(flags);
427 void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
429 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
430 avmcard *card = cinfo->card;
431 unsigned int port = card->port;
432 unsigned long flags;
433 __u16 len = CAPIMSG_LEN(skb->data);
434 __u8 cmd = CAPIMSG_COMMAND(skb->data);
435 __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
437 save_flags(flags);
438 cli();
439 if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
440 __u16 dlen = CAPIMSG_DATALEN(skb->data);
441 b1_put_byte(port, SEND_DATA_B3_REQ);
442 b1_put_slice(port, skb->data, len);
443 b1_put_slice(port, skb->data + len, dlen);
444 } else {
445 b1_put_byte(port, SEND_MESSAGE);
446 b1_put_slice(port, skb->data, len);
448 restore_flags(flags);
449 dev_kfree_skb_any(skb);
452 /* ------------------------------------------------------------- */
454 void b1_parse_version(avmctrl_info *cinfo)
456 struct capi_ctr *ctrl = cinfo->capi_ctrl;
457 avmcard *card = cinfo->card;
458 capi_profile *profp;
459 __u8 *dversion;
460 __u8 flag;
461 int i, j;
463 for (j = 0; j < AVM_MAXVERSION; j++)
464 cinfo->version[j] = "\0\0" + 1;
465 for (i = 0, j = 0;
466 j < AVM_MAXVERSION && i < cinfo->versionlen;
467 j++, i += cinfo->versionbuf[i] + 1)
468 cinfo->version[j] = &cinfo->versionbuf[i + 1];
470 strncpy(ctrl->serial, cinfo->version[VER_SERIAL], CAPI_SERIAL_LEN);
471 memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile));
472 strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN);
473 dversion = cinfo->version[VER_DRIVER];
474 ctrl->version.majorversion = 2;
475 ctrl->version.minorversion = 0;
476 ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
477 ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
478 ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
479 ctrl->version.minormanuversion |=
480 (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
482 profp = &ctrl->profile;
484 flag = ((__u8 *)(profp->manu))[1];
485 switch (flag) {
486 case 0: if (cinfo->version[VER_CARDTYPE])
487 strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]);
488 else strcpy(cinfo->cardname, "B1");
489 break;
490 case 3: strcpy(cinfo->cardname,"PCMCIA B"); break;
491 case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break;
492 case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break;
493 case 6: strcpy(cinfo->cardname,"B1 V3.0"); break;
494 case 7: strcpy(cinfo->cardname,"B1 PCI"); break;
495 default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break;
497 printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
498 card->name, ctrl->cnr, cinfo->cardname);
500 flag = ((__u8 *)(profp->manu))[3];
501 if (flag)
502 printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n",
503 card->name,
504 ctrl->cnr,
505 (flag & 0x01) ? " DSS1" : "",
506 (flag & 0x02) ? " CT1" : "",
507 (flag & 0x04) ? " VN3" : "",
508 (flag & 0x08) ? " NI1" : "",
509 (flag & 0x10) ? " AUSTEL" : "",
510 (flag & 0x20) ? " ESS" : "",
511 (flag & 0x40) ? " 1TR6" : ""
514 flag = ((__u8 *)(profp->manu))[5];
515 if (flag)
516 printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
517 card->name,
518 ctrl->cnr,
519 (flag & 0x01) ? " point to point" : "",
520 (flag & 0x02) ? " point to multipoint" : "",
521 (flag & 0x08) ? " leased line without D-channel" : "",
522 (flag & 0x04) ? " leased line with D-channel" : ""
526 /* ------------------------------------------------------------- */
528 void b1_handle_interrupt(avmcard * card)
530 avmctrl_info *cinfo = &card->ctrlinfo[0];
531 struct capi_ctr *ctrl = cinfo->capi_ctrl;
532 unsigned char b1cmd;
533 struct sk_buff *skb;
535 unsigned ApplId;
536 unsigned MsgLen;
537 unsigned DataB3Len;
538 unsigned NCCI;
539 unsigned WindowSize;
541 if (!b1_rx_full(card->port))
542 return;
544 b1cmd = b1_get_byte(card->port);
546 switch (b1cmd) {
548 case RECEIVE_DATA_B3_IND:
550 ApplId = (unsigned) b1_get_word(card->port);
551 MsgLen = b1_get_slice(card->port, card->msgbuf);
552 DataB3Len = b1_get_slice(card->port, card->databuf);
554 if (MsgLen < 30) { /* not CAPI 64Bit */
555 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
556 MsgLen = 30;
557 CAPIMSG_SETLEN(card->msgbuf, 30);
559 if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
560 printk(KERN_ERR "%s: incoming packet dropped\n",
561 card->name);
562 } else {
563 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
564 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
565 ctrl->handle_capimsg(ctrl, ApplId, skb);
567 break;
569 case RECEIVE_MESSAGE:
571 ApplId = (unsigned) b1_get_word(card->port);
572 MsgLen = b1_get_slice(card->port, card->msgbuf);
573 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
574 printk(KERN_ERR "%s: incoming packet dropped\n",
575 card->name);
576 } else {
577 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
578 ctrl->handle_capimsg(ctrl, ApplId, skb);
580 break;
582 case RECEIVE_NEW_NCCI:
584 ApplId = b1_get_word(card->port);
585 NCCI = b1_get_word(card->port);
586 WindowSize = b1_get_word(card->port);
588 ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
590 break;
592 case RECEIVE_FREE_NCCI:
594 ApplId = b1_get_word(card->port);
595 NCCI = b1_get_word(card->port);
597 if (NCCI != 0xffffffff)
598 ctrl->free_ncci(ctrl, ApplId, NCCI);
599 else ctrl->appl_released(ctrl, ApplId);
600 break;
602 case RECEIVE_START:
603 /* b1_put_byte(card->port, SEND_POLLACK); */
604 ctrl->resume_output(ctrl);
605 break;
607 case RECEIVE_STOP:
608 ctrl->suspend_output(ctrl);
609 break;
611 case RECEIVE_INIT:
613 cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
614 b1_parse_version(cinfo);
615 printk(KERN_INFO "%s: %s-card (%s) now active\n",
616 card->name,
617 cinfo->version[VER_CARDTYPE],
618 cinfo->version[VER_DRIVER]);
619 ctrl->ready(ctrl);
620 break;
622 case RECEIVE_TASK_READY:
623 ApplId = (unsigned) b1_get_word(card->port);
624 MsgLen = b1_get_slice(card->port, card->msgbuf);
625 card->msgbuf[MsgLen] = 0;
626 while ( MsgLen > 0
627 && ( card->msgbuf[MsgLen-1] == '\n'
628 || card->msgbuf[MsgLen-1] == '\r')) {
629 card->msgbuf[MsgLen-1] = 0;
630 MsgLen--;
632 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
633 card->name, ApplId, card->msgbuf);
634 break;
636 case RECEIVE_DEBUGMSG:
637 MsgLen = b1_get_slice(card->port, card->msgbuf);
638 card->msgbuf[MsgLen] = 0;
639 while ( MsgLen > 0
640 && ( card->msgbuf[MsgLen-1] == '\n'
641 || card->msgbuf[MsgLen-1] == '\r')) {
642 card->msgbuf[MsgLen-1] = 0;
643 MsgLen--;
645 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
646 break;
648 case 0xff:
649 printk(KERN_ERR "%s: card removed ?\n", card->name);
650 return;
651 default:
652 printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
653 card->name, b1cmd);
654 return;
658 /* ------------------------------------------------------------- */
659 int b1ctl_read_proc(char *page, char **start, off_t off,
660 int count, int *eof, struct capi_ctr *ctrl)
662 avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
663 avmcard *card = cinfo->card;
664 __u8 flag;
665 int len = 0;
666 char *s;
668 len += sprintf(page+len, "%-16s %s\n", "name", card->name);
669 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
670 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
671 switch (card->cardtype) {
672 case avm_b1isa: s = "B1 ISA"; break;
673 case avm_b1pci: s = "B1 PCI"; break;
674 case avm_b1pcmcia: s = "B1 PCMCIA"; break;
675 case avm_m1: s = "M1"; break;
676 case avm_m2: s = "M2"; break;
677 case avm_t1isa: s = "T1 ISA (HEMA)"; break;
678 case avm_t1pci: s = "T1 PCI"; break;
679 case avm_c4: s = "C4"; break;
680 default: s = "???"; break;
682 len += sprintf(page+len, "%-16s %s\n", "type", s);
683 if (card->cardtype == avm_t1isa)
684 len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
685 if ((s = cinfo->version[VER_DRIVER]) != 0)
686 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
687 if ((s = cinfo->version[VER_CARDTYPE]) != 0)
688 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
689 if ((s = cinfo->version[VER_SERIAL]) != 0)
690 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
692 if (card->cardtype != avm_m1) {
693 flag = ((__u8 *)(ctrl->profile.manu))[3];
694 if (flag)
695 len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
696 "protocol",
697 (flag & 0x01) ? " DSS1" : "",
698 (flag & 0x02) ? " CT1" : "",
699 (flag & 0x04) ? " VN3" : "",
700 (flag & 0x08) ? " NI1" : "",
701 (flag & 0x10) ? " AUSTEL" : "",
702 (flag & 0x20) ? " ESS" : "",
703 (flag & 0x40) ? " 1TR6" : ""
706 if (card->cardtype != avm_m1) {
707 flag = ((__u8 *)(ctrl->profile.manu))[5];
708 if (flag)
709 len += sprintf(page+len, "%-16s%s%s%s%s\n",
710 "linetype",
711 (flag & 0x01) ? " point to point" : "",
712 (flag & 0x02) ? " point to multipoint" : "",
713 (flag & 0x08) ? " leased line without D-channel" : "",
714 (flag & 0x04) ? " leased line with D-channel" : ""
717 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
719 if (off+count >= len)
720 *eof = 1;
721 if (len < off)
722 return 0;
723 *start = page + off;
724 return ((count < len-off) ? count : len-off);
727 /* ------------------------------------------------------------- */
729 EXPORT_SYMBOL(b1_irq_table);
731 EXPORT_SYMBOL(b1_detect);
732 EXPORT_SYMBOL(b1_getrevision);
733 EXPORT_SYMBOL(b1_load_t4file);
734 EXPORT_SYMBOL(b1_load_config);
735 EXPORT_SYMBOL(b1_loaded);
736 EXPORT_SYMBOL(b1_load_firmware);
737 EXPORT_SYMBOL(b1_reset_ctr);
738 EXPORT_SYMBOL(b1_register_appl);
739 EXPORT_SYMBOL(b1_release_appl);
740 EXPORT_SYMBOL(b1_send_message);
742 EXPORT_SYMBOL(b1_parse_version);
743 EXPORT_SYMBOL(b1_handle_interrupt);
745 EXPORT_SYMBOL(b1ctl_read_proc);
747 static int __init b1_init(void)
749 char *p;
750 char rev[10];
752 if ((p = strchr(revision, ':'))) {
753 strncpy(rev, p + 1, sizeof(rev));
754 p = strchr(rev, '$');
755 *p = 0;
756 } else
757 strcpy(rev, "1.0");
759 printk(KERN_INFO "b1: revision %s\n", rev);
761 return 0;
764 static void __exit b1_exit(void)
768 module_init(b1_init);
769 module_exit(b1_exit);