2 * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $
4 * Module for AVM T1 HEMA-card.
6 * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
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
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>
52 #include <linux/interrupt.h>
53 #include <linux/ioport.h>
54 #include <linux/capi.h>
56 #include <linux/isdn_compat.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] =
93 static int t1_detectandinit(unsigned int base
, unsigned irq
, int cardnr
)
95 unsigned char cregs
[8];
96 unsigned char reverse_cardnr
;
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 */
107 cregs
[4] = 0x11; /* zero wait state */
108 cregs
[5] = hema_irq_table
[irq
& 0xf];
115 t1outp(base
, T1_RESETBOARD
, 0xf);
117 dummy
= t1inp(base
, T1_FASTLINK
+T1_OUTSTAT
); /* first read */
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
);
129 t1outp(base
, T1_FASTLINK
+T1_RESETLINK
, 0);
130 t1outp(base
, T1_SLOWLINK
+T1_RESETLINK
, 0);
132 t1outp(base
, T1_FASTLINK
+T1_RESETLINK
, 1);
133 t1outp(base
, T1_SLOWLINK
+T1_RESETLINK
, 1);
135 t1outp(base
, T1_FASTLINK
+T1_RESETLINK
, 0);
136 t1outp(base
, T1_SLOWLINK
+T1_RESETLINK
, 0);
138 t1outp(base
, T1_FASTLINK
+T1_ANALYSE
, 0);
140 t1outp(base
, T1_SLOWLINK
+T1_ANALYSE
, 0);
142 if (t1inp(base
, T1_FASTLINK
+T1_OUTSTAT
) != 0x1) /* tx empty */
144 if (t1inp(base
, T1_FASTLINK
+T1_INSTAT
) != 0x0) /* rx empty */
146 if (t1inp(base
, T1_FASTLINK
+T1_IRQENABLE
) != 0x0)
148 if ((t1inp(base
, T1_FASTLINK
+T1_FIFOSTAT
) & 0xf0) != 0x70)
150 if ((t1inp(base
, T1_FASTLINK
+T1_IRQMASTER
) & 0x0e) != 0)
152 if ((t1inp(base
, T1_FASTLINK
+T1_IDENT
) & 0x7d) != 1)
154 if (t1inp(base
, T1_SLOWLINK
+T1_OUTSTAT
) != 0x1) /* tx empty */
156 if ((t1inp(base
, T1_SLOWLINK
+T1_IRQMASTER
) & 0x0e) != 0)
158 if ((t1inp(base
, T1_SLOWLINK
+T1_IDENT
) & 0x7d) != 0)
163 static void t1_handle_interrupt(avmcard
* card
)
165 struct capi_ctr
*ctrl
= card
->ctrl
;
175 while (b1_rx_full(card
->port
)) {
177 b1cmd
= b1_get_byte(card
->port
);
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");
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
);
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");
204 memcpy(skb_put(skb
, MsgLen
), card
->msgbuf
, MsgLen
);
205 ctrl
->handle_capimsg(ctrl
, ApplId
, skb
);
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
);
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
);
230 b1_put_byte(card
->port
, SEND_POLLACK
);
231 ctrl
->resume_output(ctrl
);
235 ctrl
->suspend_output(ctrl
);
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",
244 card
->version
[VER_CARDTYPE
],
245 card
->version
[VER_DRIVER
]);
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;
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
);
261 case RECEIVE_DEBUGMSG
:
262 MsgLen
= t1_get_slice(card
->port
, card
->msgbuf
);
263 card
->msgbuf
[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
);
272 printk(KERN_ERR
"%s: card reseted ?\n", card
->name
);
275 printk(KERN_ERR
"%s: b1_interrupt: 0x%x ???\n",
282 /* ------------------------------------------------------------- */
284 static void t1isa_interrupt(int interrupt
, void *devptr
, struct pt_regs
*regs
)
288 card
= (avmcard
*) devptr
;
291 printk(KERN_WARNING
"t1_interrupt: wrong device\n");
294 if (card
->interrupt
) {
295 printk(KERN_ERR
"t1_interrupt: reentering interrupt hander (%s)\n", card
->name
);
301 t1_handle_interrupt(card
);
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
;
314 t1_disable_irq(port
);
317 if ((retval
= b1_load_t4file(port
, &data
->firmware
))) {
319 printk(KERN_ERR
"%s: failed to load t4file!!\n",
324 if (data
->configuration
.len
> 0 && data
->configuration
.data
) {
325 if ((retval
= b1_load_config(port
, &data
->configuration
))) {
327 printk(KERN_ERR
"%s: failed to load config!!\n",
333 if (!b1_loaded(port
)) {
334 printk(KERN_ERR
"%s: failed to load t4file.\n", card
->name
);
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
);
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
);
359 memset(card
->version
, 0, sizeof(card
->version
));
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
);
373 di
->detach_ctr(ctrl
);
374 free_irq(card
->irq
, card
);
375 release_region(card
->port
, AVMB1_PORTLEN
);
381 /* ------------------------------------------------------------- */
383 static int t1isa_add_card(struct capi_driver
*driver
, struct capicardparams
*p
)
385 struct capi_ctr
*ctrl
;
389 card
= (avmcard
*) kmalloc(sizeof(avmcard
), GFP_ATOMIC
);
392 printk(KERN_WARNING
"t1isa: no memory.\n");
395 memset(card
, 0, sizeof(avmcard
));
396 sprintf(card
->name
, "t1isa-%x", p
->port
);
397 card
->port
= p
->port
;
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
);
408 if (check_region(card
->port
, AVMB1_PORTLEN
)) {
410 "t1isa: ports 0x%03x-0x%03x in use.\n",
411 card
->port
, card
->port
+ AVMB1_PORTLEN
);
415 if (hema_irq_table
[card
->irq
& 0xf] == 0) {
416 printk(KERN_WARNING
"t1isa: irq %d not valid.\n", card
->irq
);
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
);
427 if ((retval
= t1_detectandinit(card
->port
, card
->irq
, card
->cardnr
)) != 0) {
428 printk(KERN_NOTICE
"t1isa: NO card at 0x%x (%d)\n",
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
);
440 printk(KERN_ERR
"t1isa: unable to get IRQ %d.\n", card
->irq
);
441 release_region(card
->port
, AVMB1_PORTLEN
);
446 card
->ctrl
= di
->attach_ctr(driver
, card
->name
, card
);
448 printk(KERN_ERR
"t1isa: attach controller failed.\n");
449 free_irq(card
->irq
, card
);
450 release_region(card
->port
, AVMB1_PORTLEN
);
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
;
464 __u16 len
= CAPIMSG_LEN(skb
->data
);
465 __u8 cmd
= CAPIMSG_COMMAND(skb
->data
);
466 __u8 subcmd
= CAPIMSG_SUBCOMMAND(skb
->data
);
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
);
476 b1_put_byte(port
, SEND_MESSAGE
);
477 t1_put_slice(port
, skb
->data
, len
);
479 restore_flags(flags
);
482 /* ------------------------------------------------------------- */
484 static char *t1isa_procinfo(struct capi_ctr
*ctrl
)
486 avmcard
*card
= (avmcard
*)(ctrl
->driverdata
);
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
= {
512 0, /* use standard driver_read_proc */
518 #define t1isa_init init_module
519 void cleanup_module(void);
524 struct capi_driver
*driver
= &t1isa_driver
;
527 if ((p
= strchr(revision
, ':'))) {
528 strncpy(driver
->revision
, p
+ 1, sizeof(driver
->revision
));
529 p
= strchr(driver
->revision
, '$');
533 printk(KERN_INFO
"%s: revision %s\n", driver
->name
, driver
->revision
);
535 di
= attach_capi_driver(driver
);
538 printk(KERN_ERR
"%s: failed to attach capi_driver\n",
546 void cleanup_module(void)
548 detach_capi_driver(&t1isa_driver
);