2 * $Id: b1.c,v 1.8 1999/08/22 20:26:22 calle Exp $
4 * Common module for AVM B1 cards.
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
9 * Revision 1.8 1999/08/22 20:26:22 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.7 1999/08/04 10:10:09 calle
16 * Bugfix: corrected /proc functions, added structure for new AVM cards.
18 * Revision 1.6 1999/07/23 08:51:04 calle
19 * small fix and typo in checkin before.
21 * Revision 1.5 1999/07/23 08:41:48 calle
22 * prepared for new AVM cards.
24 * Revision 1.4 1999/07/09 15:05:38 keil
25 * compat.h is now isdn_compat.h
27 * Revision 1.3 1999/07/06 07:41:59 calle
28 * - changes in /proc interface
29 * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
31 * Revision 1.2 1999/07/05 15:09:47 calle
32 * - renamed "appl_release" to "appl_released".
33 * - version und profile data now cleared on controller reset
34 * - extended /proc interface, to allow driver and controller specific
35 * informations to include by driver hackers.
37 * Revision 1.1 1999/07/01 15:26:23 calle
38 * complete new version (I love it):
39 * + new hardware independed "capi_driver" interface that will make it easy to:
40 * - support other controllers with CAPI-2.0 (i.e. USB Controller)
41 * - write a CAPI-2.0 for the passive cards
42 * - support serial link CAPI-2.0 boxes.
43 * + wrote "capi_driver" for all supported cards.
44 * + "capi_driver" (supported cards) now have to be configured with
45 * make menuconfig, in the past all supported cards where included
47 * + new and better informations in /proc/capi/
48 * + new ioctl to switch trace of capi messages per controller
49 * using "avmcapictrl trace [contr] on|off|...."
50 * + complete testcircle with all supported cards and also the
51 * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
56 #include <linux/module.h>
57 #include <linux/kernel.h>
58 #include <linux/skbuff.h>
59 #include <linux/delay.h>
61 #include <linux/interrupt.h>
62 #include <linux/ioport.h>
63 #include <linux/capi.h>
65 #include <linux/isdn_compat.h>
71 static char *revision
= "$Revision: 1.8 $";
73 /* ------------------------------------------------------------- */
75 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
77 /* ------------------------------------------------------------- */
79 int b1_irq_table
[16] =
98 /* ------------------------------------------------------------- */
100 int b1_detect(unsigned int base
, enum avmcardtype cardtype
)
105 * Statusregister 0000 00xx
107 if ((inb(base
+ B1_INSTAT
) & 0xfc)
108 || (inb(base
+ B1_OUTSTAT
) & 0xfc))
111 * Statusregister 0000 001x
113 b1outp(base
, B1_INSTAT
, 0x2); /* enable irq */
114 /* b1outp(base, B1_OUTSTAT, 0x2); */
115 if ((inb(base
+ B1_INSTAT
) & 0xfe) != 0x2
116 /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
119 * Statusregister 0000 000x
121 b1outp(base
, B1_INSTAT
, 0x0); /* disable irq */
122 b1outp(base
, B1_OUTSTAT
, 0x0);
123 if ((inb(base
+ B1_INSTAT
) & 0xfe)
124 || (inb(base
+ B1_OUTSTAT
) & 0xfe))
127 for (onoff
= !0, i
= 0; i
< 10 ; i
++) {
128 b1_set_test_bit(base
, cardtype
, onoff
);
129 if (b1_get_test_bit(base
, cardtype
) != onoff
)
134 if (cardtype
== avm_m1
)
137 if ((b1_rd_reg(base
, B1_STAT1(cardtype
)) & 0x0f) != 0x01)
143 int b1_load_t4file(unsigned int base
, capiloaddatapart
* t4file
)
145 unsigned char buf
[256];
151 while (left
> sizeof(buf
)) {
153 retval
= copy_from_user(buf
, dp
, sizeof(buf
));
157 memcpy(buf
, dp
, sizeof(buf
));
159 for (i
= 0; i
< sizeof(buf
); i
++)
160 if (b1_save_put_byte(base
, buf
[i
]) < 0) {
161 printk(KERN_ERR
"b1_load_t4file: corrupted t4 file ?\n");
169 retval
= copy_from_user(buf
, dp
, left
);
173 memcpy(buf
, dp
, left
);
175 for (i
= 0; i
< left
; i
++)
176 if (b1_save_put_byte(base
, buf
[i
]) < 0) {
177 printk(KERN_ERR
"b1_load_t4file: corrupted t4 file ?\n");
184 int b1_load_config(unsigned int base
, capiloaddatapart
* config
)
186 unsigned char buf
[256];
188 int i
, j
, left
, retval
;
193 b1_put_byte(base
, SEND_CONFIG
);
194 b1_put_word(base
, 1);
195 b1_put_byte(base
, SEND_CONFIG
);
196 b1_put_word(base
, left
);
198 while (left
> sizeof(buf
)) {
200 retval
= copy_from_user(buf
, dp
, sizeof(buf
));
204 memcpy(buf
, dp
, sizeof(buf
));
206 for (i
= 0; i
< sizeof(buf
); ) {
207 b1_put_byte(base
, SEND_CONFIG
);
208 for (j
=0; j
< 4; j
++) {
209 b1_put_byte(base
, buf
[i
++]);
217 retval
= copy_from_user(buf
, dp
, left
);
221 memcpy(buf
, dp
, left
);
223 for (i
= 0; i
< left
; ) {
224 b1_put_byte(base
, SEND_CONFIG
);
225 for (j
=0; j
< 4; j
++) {
227 b1_put_byte(base
, buf
[i
++]);
229 b1_put_byte(base
, 0);
236 int b1_loaded(unsigned int base
)
240 unsigned long tout
= 2;
242 for (stop
= jiffies
+ tout
* HZ
; time_before(jiffies
, stop
);) {
243 if (b1_tx_empty(base
))
246 if (!b1_tx_empty(base
)) {
247 printk(KERN_ERR
"b1_loaded: tx err, corrupted t4 file ?\n");
250 b1_put_byte(base
, SEND_POLL
);
251 for (stop
= jiffies
+ tout
* HZ
; time_before(jiffies
, stop
);) {
252 if (b1_rx_full(base
)) {
253 if ((ans
= b1_get_byte(base
)) == RECEIVE_POLL
) {
256 printk(KERN_ERR
"b1_loaded: got 0x%x, firmware not running\n", ans
);
260 printk(KERN_ERR
"b1_loaded: firmware not running\n");
264 /* ------------------------------------------------------------- */
266 int b1_load_firmware(struct capi_ctr
*ctrl
, capiloaddata
*data
)
268 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
269 unsigned int port
= card
->port
;
275 if ((retval
= b1_load_t4file(port
, &data
->firmware
))) {
277 printk(KERN_ERR
"%s: failed to load t4file!!\n",
282 b1_disable_irq(port
);
284 if (data
->configuration
.len
> 0 && data
->configuration
.data
) {
285 if ((retval
= b1_load_config(port
, &data
->configuration
))) {
287 printk(KERN_ERR
"%s: failed to load config!!\n",
293 if (!b1_loaded(port
)) {
294 printk(KERN_ERR
"%s: failed to load t4file.\n", card
->name
);
300 b1_setinterrupt(port
, card
->irq
, card
->cardtype
);
301 b1_put_byte(port
, SEND_INIT
);
302 b1_put_word(port
, AVM_NAPPS
);
303 b1_put_word(port
, AVM_NCCI_PER_CHANNEL
*2);
304 b1_put_word(port
, ctrl
->cnr
- 1);
305 restore_flags(flags
);
310 void b1_reset_ctr(struct capi_ctr
*ctrl
)
312 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
313 unsigned int port
= card
->port
;
318 memset(card
->version
, 0, sizeof(card
->version
));
322 void b1_register_appl(struct capi_ctr
*ctrl
,
324 capi_register_params
*rp
)
326 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
327 unsigned int port
= card
->port
;
329 int nconn
, want
= rp
->level3cnt
;
331 if (want
> 0) nconn
= want
;
332 else nconn
= ctrl
->profile
.nbchannel
* -want
;
333 if (nconn
== 0) nconn
= ctrl
->profile
.nbchannel
;
337 b1_put_byte(port
, SEND_REGISTER
);
338 b1_put_word(port
, appl
);
339 b1_put_word(port
, 1024 * (nconn
+1));
340 b1_put_word(port
, nconn
);
341 b1_put_word(port
, rp
->datablkcnt
);
342 b1_put_word(port
, rp
->datablklen
);
343 restore_flags(flags
);
345 ctrl
->appl_registered(ctrl
, appl
);
348 void b1_release_appl(struct capi_ctr
*ctrl
, __u16 appl
)
350 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
351 unsigned int port
= card
->port
;
356 b1_put_byte(port
, SEND_RELEASE
);
357 b1_put_word(port
, appl
);
358 restore_flags(flags
);
361 void b1_send_message(struct capi_ctr
*ctrl
, struct sk_buff
*skb
)
363 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
364 unsigned int port
= card
->port
;
366 __u16 len
= CAPIMSG_LEN(skb
->data
);
367 __u8 cmd
= CAPIMSG_COMMAND(skb
->data
);
368 __u8 subcmd
= CAPIMSG_SUBCOMMAND(skb
->data
);
372 if (CAPICMD(cmd
, subcmd
) == CAPI_DATA_B3_REQ
) {
373 __u16 dlen
= CAPIMSG_DATALEN(skb
->data
);
374 b1_put_byte(port
, SEND_DATA_B3_REQ
);
375 b1_put_slice(port
, skb
->data
, len
);
376 b1_put_slice(port
, skb
->data
+ len
, dlen
);
378 b1_put_byte(port
, SEND_MESSAGE
);
379 b1_put_slice(port
, skb
->data
, len
);
381 restore_flags(flags
);
385 /* ------------------------------------------------------------- */
387 void b1_parse_version(avmcard
*card
)
389 struct capi_ctr
*ctrl
= card
->ctrl
;
395 for (j
= 0; j
< AVM_MAXVERSION
; j
++)
396 card
->version
[j
] = "\0\0" + 1;
398 j
< AVM_MAXVERSION
&& i
< card
->versionlen
;
399 j
++, i
+= card
->versionbuf
[i
] + 1)
400 card
->version
[j
] = &card
->versionbuf
[i
+ 1];
402 strncpy(ctrl
->serial
, card
->version
[VER_SERIAL
], CAPI_SERIAL_LEN
);
403 memcpy(&ctrl
->profile
, card
->version
[VER_PROFILE
],sizeof(capi_profile
));
404 strncpy(ctrl
->manu
, "AVM GmbH", CAPI_MANUFACTURER_LEN
);
405 dversion
= card
->version
[VER_DRIVER
];
406 ctrl
->version
.majorversion
= 2;
407 ctrl
->version
.minorversion
= 0;
408 ctrl
->version
.majormanuversion
= (((dversion
[0] - '0') & 0xf) << 4);
409 ctrl
->version
.majormanuversion
|= ((dversion
[2] - '0') & 0xf);
410 ctrl
->version
.minormanuversion
= (dversion
[3] - '0') << 4;
411 ctrl
->version
.minormanuversion
|=
412 (dversion
[5] - '0') * 10 + ((dversion
[6] - '0') & 0xf);
414 profp
= &ctrl
->profile
;
416 flag
= ((__u8
*)(profp
->manu
))[1];
418 case 0: if (card
->version
[VER_CARDTYPE
])
419 strcpy(card
->cardname
, card
->version
[VER_CARDTYPE
]);
420 else strcpy(card
->cardname
, "B1");
422 case 3: strcpy(card
->cardname
,"PCMCIA B"); break;
423 case 4: strcpy(card
->cardname
,"PCMCIA M1"); break;
424 case 5: strcpy(card
->cardname
,"PCMCIA M2"); break;
425 case 6: strcpy(card
->cardname
,"B1 V3.0"); break;
426 case 7: strcpy(card
->cardname
,"B1 PCI"); break;
427 default: sprintf(card
->cardname
, "AVM?%u", (unsigned int)flag
); break;
429 printk(KERN_NOTICE
"%s: card %d \"%s\" ready.\n",
430 card
->name
, ctrl
->cnr
, card
->cardname
);
432 flag
= ((__u8
*)(profp
->manu
))[3];
434 printk(KERN_NOTICE
"b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
436 (flag
& 0x01) ? " DSS1" : "",
437 (flag
& 0x02) ? " CT1" : "",
438 (flag
& 0x04) ? " VN3" : "",
439 (flag
& 0x08) ? " NI1" : "",
440 (flag
& 0x10) ? " AUSTEL" : "",
441 (flag
& 0x20) ? " ESS" : "",
442 (flag
& 0x40) ? " 1TR6" : ""
445 flag
= ((__u8
*)(profp
->manu
))[5];
447 printk(KERN_NOTICE
"%s: card %d Linetype:%s%s%s%s\n",
450 (flag
& 0x01) ? " point to point" : "",
451 (flag
& 0x02) ? " point to multipoint" : "",
452 (flag
& 0x08) ? " leased line without D-channel" : "",
453 (flag
& 0x04) ? " leased line with D-channel" : ""
457 /* ------------------------------------------------------------- */
459 void b1_handle_interrupt(avmcard
* card
)
461 struct capi_ctr
*ctrl
= card
->ctrl
;
471 if (!b1_rx_full(card
->port
))
474 b1cmd
= b1_get_byte(card
->port
);
478 case RECEIVE_DATA_B3_IND
:
480 ApplId
= (unsigned) b1_get_word(card
->port
);
481 MsgLen
= b1_get_slice(card
->port
, card
->msgbuf
);
482 DataB3Len
= b1_get_slice(card
->port
, card
->databuf
);
484 if (!(skb
= alloc_skb(DataB3Len
+ MsgLen
, GFP_ATOMIC
))) {
485 printk(KERN_ERR
"%s: incoming packet dropped\n",
488 memcpy(skb_put(skb
, MsgLen
), card
->msgbuf
, MsgLen
);
489 memcpy(skb_put(skb
, DataB3Len
), card
->databuf
, DataB3Len
);
490 CAPIMSG_SETDATA(skb
->data
, skb
->data
+ MsgLen
);
491 ctrl
->handle_capimsg(ctrl
, ApplId
, skb
);
495 case RECEIVE_MESSAGE
:
497 ApplId
= (unsigned) b1_get_word(card
->port
);
498 MsgLen
= b1_get_slice(card
->port
, card
->msgbuf
);
499 if (!(skb
= alloc_skb(MsgLen
, GFP_ATOMIC
))) {
500 printk(KERN_ERR
"%s: incoming packet dropped\n",
503 memcpy(skb_put(skb
, MsgLen
), card
->msgbuf
, MsgLen
);
504 ctrl
->handle_capimsg(ctrl
, ApplId
, skb
);
508 case RECEIVE_NEW_NCCI
:
510 ApplId
= b1_get_word(card
->port
);
511 NCCI
= b1_get_word(card
->port
);
512 WindowSize
= b1_get_word(card
->port
);
514 ctrl
->new_ncci(ctrl
, ApplId
, NCCI
, WindowSize
);
518 case RECEIVE_FREE_NCCI
:
520 ApplId
= b1_get_word(card
->port
);
521 NCCI
= b1_get_word(card
->port
);
523 if (NCCI
!= 0xffffffff)
524 ctrl
->free_ncci(ctrl
, ApplId
, NCCI
);
525 else ctrl
->appl_released(ctrl
, ApplId
);
529 /* b1_put_byte(card->port, SEND_POLLACK); */
530 ctrl
->resume_output(ctrl
);
534 ctrl
->suspend_output(ctrl
);
539 card
->versionlen
= b1_get_slice(card
->port
, card
->versionbuf
);
540 b1_parse_version(card
);
541 printk(KERN_INFO
"%s: %s-card (%s) now active\n",
543 card
->version
[VER_CARDTYPE
],
544 card
->version
[VER_DRIVER
]);
548 case RECEIVE_TASK_READY
:
549 ApplId
= (unsigned) b1_get_word(card
->port
);
550 MsgLen
= b1_get_slice(card
->port
, card
->msgbuf
);
551 card
->msgbuf
[MsgLen
--] = 0;
553 && ( card
->msgbuf
[MsgLen
] == '\n'
554 || card
->msgbuf
[MsgLen
] == '\r'))
555 card
->msgbuf
[MsgLen
--] = 0;
556 printk(KERN_INFO
"%s: task %d \"%s\" ready.\n",
557 card
->name
, ApplId
, card
->msgbuf
);
560 case RECEIVE_DEBUGMSG
:
561 MsgLen
= b1_get_slice(card
->port
, card
->msgbuf
);
562 card
->msgbuf
[MsgLen
--] = 0;
564 && ( card
->msgbuf
[MsgLen
] == '\n'
565 || card
->msgbuf
[MsgLen
] == '\r'))
566 card
->msgbuf
[MsgLen
--] = 0;
567 printk(KERN_INFO
"%s: DEBUG: %s\n", card
->name
, card
->msgbuf
);
571 printk(KERN_ERR
"%s: card removed ?\n", card
->name
);
574 printk(KERN_ERR
"%s: b1_interrupt: 0x%x ???\n",
580 /* ------------------------------------------------------------- */
581 int b1ctl_read_proc(char *page
, char **start
, off_t off
,
582 int count
, int *eof
, struct capi_ctr
*ctrl
)
584 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
589 len
+= sprintf(page
+len
, "%-16s %s\n", "name", card
->name
);
590 len
+= sprintf(page
+len
, "%-16s 0x%x\n", "io", card
->port
);
591 len
+= sprintf(page
+len
, "%-16s %d\n", "irq", card
->irq
);
592 switch (card
->cardtype
) {
593 case avm_b1isa
: s
= "B1 ISA"; break;
594 case avm_b1pci
: s
= "B1 PCI"; break;
595 case avm_b1pcmcia
: s
= "B1 PCMCIA"; break;
596 case avm_m1
: s
= "M1"; break;
597 case avm_m2
: s
= "M2"; break;
598 case avm_t1isa
: s
= "T1 ISA (HEMA)"; break;
599 case avm_t1pci
: s
= "T1 PCI"; break;
600 case avm_c4
: s
= "C4"; break;
601 default: s
= "???"; break;
603 len
+= sprintf(page
+len
, "%-16s %s\n", "type", s
);
604 if (card
->cardtype
== avm_t1isa
)
605 len
+= sprintf(page
+len
, "%-16s %d\n", "cardnr", card
->cardnr
);
606 if ((s
= card
->version
[VER_DRIVER
]) != 0)
607 len
+= sprintf(page
+len
, "%-16s %s\n", "ver_driver", s
);
608 if ((s
= card
->version
[VER_CARDTYPE
]) != 0)
609 len
+= sprintf(page
+len
, "%-16s %s\n", "ver_cardtype", s
);
610 if ((s
= card
->version
[VER_SERIAL
]) != 0)
611 len
+= sprintf(page
+len
, "%-16s %s\n", "ver_serial", s
);
613 if (card
->cardtype
!= avm_m1
) {
614 flag
= ((__u8
*)(ctrl
->profile
.manu
))[3];
616 len
+= sprintf(page
+len
, "%-16s%s%s%s%s%s%s%s\n",
618 (flag
& 0x01) ? " DSS1" : "",
619 (flag
& 0x02) ? " CT1" : "",
620 (flag
& 0x04) ? " VN3" : "",
621 (flag
& 0x08) ? " NI1" : "",
622 (flag
& 0x10) ? " AUSTEL" : "",
623 (flag
& 0x20) ? " ESS" : "",
624 (flag
& 0x40) ? " 1TR6" : ""
627 if (card
->cardtype
!= avm_m1
) {
628 flag
= ((__u8
*)(ctrl
->profile
.manu
))[5];
630 len
+= sprintf(page
+len
, "%-16s%s%s%s%s\n",
632 (flag
& 0x01) ? " point to point" : "",
633 (flag
& 0x02) ? " point to multipoint" : "",
634 (flag
& 0x08) ? " leased line without D-channel" : "",
635 (flag
& 0x04) ? " leased line with D-channel" : ""
638 len
+= sprintf(page
+len
, "%-16s %s\n", "cardname", card
->cardname
);
640 if (off
+count
>= len
)
645 return ((count
< len
-off
) ? count
: len
-off
);
648 /* ------------------------------------------------------------- */
650 EXPORT_SYMBOL(b1_irq_table
);
652 EXPORT_SYMBOL(b1_detect
);
653 EXPORT_SYMBOL(b1_load_t4file
);
654 EXPORT_SYMBOL(b1_load_config
);
655 EXPORT_SYMBOL(b1_loaded
);
656 EXPORT_SYMBOL(b1_load_firmware
);
657 EXPORT_SYMBOL(b1_reset_ctr
);
658 EXPORT_SYMBOL(b1_register_appl
);
659 EXPORT_SYMBOL(b1_release_appl
);
660 EXPORT_SYMBOL(b1_send_message
);
662 EXPORT_SYMBOL(b1_parse_version
);
663 EXPORT_SYMBOL(b1_handle_interrupt
);
665 EXPORT_SYMBOL(b1ctl_read_proc
);
668 #define b1_init init_module
669 void cleanup_module(void);
677 if ((p
= strchr(revision
, ':'))) {
678 strncpy(rev
, p
+ 1, sizeof(rev
));
679 p
= strchr(rev
, '$');
684 printk(KERN_INFO
"b1: revision %s\n", rev
);
690 void cleanup_module(void)