Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / drivers / isdn / hardware / avm / b1.c
1 /* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
2  * 
3  * Common module for AVM B1 cards.
4  * 
5  * Copyright 1999 by Carsten Paeth <calle@calle.de>
6  *
7  * This software may be used and distributed according to the terms
8  * of the GNU General Public License, incorporated herein by reference.
9  *
10  */
11
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/pci.h>
15 #include <linux/proc_fs.h>
16 #include <linux/seq_file.h>
17 #include <linux/skbuff.h>
18 #include <linux/delay.h>
19 #include <linux/mm.h>
20 #include <linux/interrupt.h>
21 #include <linux/ioport.h>
22 #include <linux/capi.h>
23 #include <linux/kernelcapi.h>
24 #include <asm/io.h>
25 #include <linux/init.h>
26 #include <asm/uaccess.h>
27 #include <linux/netdevice.h>
28 #include <linux/isdn/capilli.h>
29 #include "avmcard.h"
30 #include <linux/isdn/capicmd.h>
31 #include <linux/isdn/capiutil.h>
32
33 static char *revision = "$Revision: 1.1.2.2 $";
34
35 /* ------------------------------------------------------------- */
36
37 MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
38 MODULE_AUTHOR("Carsten Paeth");
39 MODULE_LICENSE("GPL");
40
41 /* ------------------------------------------------------------- */
42
43 int b1_irq_table[16] =
44 {0,
45  0,
46  0,
47  192,                           /* irq 3 */
48  32,                            /* irq 4 */
49  160,                           /* irq 5 */
50  96,                            /* irq 6 */
51  224,                           /* irq 7 */
52  0,
53  64,                            /* irq 9 */
54  80,                            /* irq 10 */
55  208,                           /* irq 11 */
56  48,                            /* irq 12 */
57  0,
58  0,
59  112,                           /* irq 15 */
60 };
61
62 /* ------------------------------------------------------------- */     
63
64 avmcard *b1_alloc_card(int nr_controllers)
65 {
66         avmcard *card;
67         avmctrl_info *cinfo;
68         int i;
69
70         card = kzalloc(sizeof(*card), GFP_KERNEL);
71         if (!card)
72                 return NULL;
73
74         cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
75         if (!cinfo) {
76                 kfree(card);
77                 return NULL;
78         }
79
80         card->ctrlinfo = cinfo;
81         for (i = 0; i < nr_controllers; i++) {
82                 INIT_LIST_HEAD(&cinfo[i].ncci_head);
83                 cinfo[i].card = card;
84         }
85         spin_lock_init(&card->lock);
86         card->nr_controllers = nr_controllers;
87
88         return card;
89 }
90
91 /* ------------------------------------------------------------- */
92
93 void b1_free_card(avmcard *card)
94 {
95         kfree(card->ctrlinfo);
96         kfree(card);
97 }
98
99 /* ------------------------------------------------------------- */
100
101 int b1_detect(unsigned int base, enum avmcardtype cardtype)
102 {
103         int onoff, i;
104
105         /*
106          * Statusregister 0000 00xx 
107          */
108         if ((inb(base + B1_INSTAT) & 0xfc)
109             || (inb(base + B1_OUTSTAT) & 0xfc))
110                 return 1;
111         /*
112          * Statusregister 0000 001x 
113          */
114         b1outp(base, B1_INSTAT, 0x2);   /* enable irq */
115         /* b1outp(base, B1_OUTSTAT, 0x2); */
116         if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
117             /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
118                 return 2;
119         /*
120          * Statusregister 0000 000x 
121          */
122         b1outp(base, B1_INSTAT, 0x0);   /* disable irq */
123         b1outp(base, B1_OUTSTAT, 0x0);
124         if ((inb(base + B1_INSTAT) & 0xfe)
125             || (inb(base + B1_OUTSTAT) & 0xfe))
126                 return 3;
127         
128         for (onoff = !0, i= 0; i < 10 ; i++) {
129                 b1_set_test_bit(base, cardtype, onoff);
130                 if (b1_get_test_bit(base, cardtype) != onoff)
131                    return 4;
132                 onoff = !onoff;
133         }
134
135         if (cardtype == avm_m1)
136            return 0;
137
138         if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
139            return 5;
140
141         return 0;
142 }
143
144 void b1_getrevision(avmcard *card)
145 {
146     card->class = inb(card->port + B1_ANALYSE);
147     card->revision = inb(card->port + B1_REVISION);
148 }
149
150 #define FWBUF_SIZE      256
151 int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
152 {
153         unsigned char buf[FWBUF_SIZE];
154         unsigned char *dp;
155         int i, left;
156         unsigned int base = card->port;
157
158         dp = t4file->data;
159         left = t4file->len;
160         while (left > FWBUF_SIZE) {
161                 if (t4file->user) {
162                         if (copy_from_user(buf, dp, FWBUF_SIZE))
163                                 return -EFAULT;
164                 } else {
165                         memcpy(buf, dp, FWBUF_SIZE);
166                 }
167                 for (i = 0; i < FWBUF_SIZE; i++)
168                         if (b1_save_put_byte(base, buf[i]) < 0) {
169                                 printk(KERN_ERR "%s: corrupted firmware file ?\n",
170                                                 card->name);
171                                 return -EIO;
172                         }
173                 left -= FWBUF_SIZE;
174                 dp += FWBUF_SIZE;
175         }
176         if (left) {
177                 if (t4file->user) {
178                         if (copy_from_user(buf, dp, left))
179                                 return -EFAULT;
180                 } else {
181                         memcpy(buf, dp, left);
182                 }
183                 for (i = 0; i < left; i++)
184                         if (b1_save_put_byte(base, buf[i]) < 0) {
185                                 printk(KERN_ERR "%s: corrupted firmware file ?\n",
186                                                 card->name);
187                                 return -EIO;
188                         }
189         }
190         return 0;
191 }
192
193 int b1_load_config(avmcard *card, capiloaddatapart * config)
194 {
195         unsigned char buf[FWBUF_SIZE];
196         unsigned char *dp;
197         unsigned int base = card->port;
198         int i, j, left;
199
200         dp = config->data;
201         left = config->len;
202         if (left) {
203                 b1_put_byte(base, SEND_CONFIG);
204                 b1_put_word(base, 1);
205                 b1_put_byte(base, SEND_CONFIG);
206                 b1_put_word(base, left);
207         }
208         while (left > FWBUF_SIZE) {
209                 if (config->user) {
210                         if (copy_from_user(buf, dp, FWBUF_SIZE))
211                                 return -EFAULT;
212                 } else {
213                         memcpy(buf, dp, FWBUF_SIZE);
214                 }
215                 for (i = 0; i < FWBUF_SIZE; ) {
216                         b1_put_byte(base, SEND_CONFIG);
217                         for (j=0; j < 4; j++) {
218                                 b1_put_byte(base, buf[i++]);
219                         }
220                 }
221                 left -= FWBUF_SIZE;
222                 dp += FWBUF_SIZE;
223         }
224         if (left) {
225                 if (config->user) {
226                         if (copy_from_user(buf, dp, left))
227                                 return -EFAULT;
228                 } else {
229                         memcpy(buf, dp, left);
230                 }
231                 for (i = 0; i < left; ) {
232                         b1_put_byte(base, SEND_CONFIG);
233                         for (j=0; j < 4; j++) {
234                                 if (i < left)
235                                         b1_put_byte(base, buf[i++]);
236                                 else
237                                         b1_put_byte(base, 0);
238                         }
239                 }
240         }
241         return 0;
242 }
243
244 int b1_loaded(avmcard *card)
245 {
246         unsigned int base = card->port;
247         unsigned long stop;
248         unsigned char ans;
249         unsigned long tout = 2;
250
251         for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
252                 if (b1_tx_empty(base))
253                         break;
254         }
255         if (!b1_tx_empty(base)) {
256                 printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n",
257                                 card->name);
258                 return 0;
259         }
260         b1_put_byte(base, SEND_POLL);
261         for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
262                 if (b1_rx_full(base)) {
263                         if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
264                                 return 1;
265                         }
266                         printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
267                                         card->name, ans);
268                         return 0;
269                 }
270         }
271         printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name);
272         return 0;
273 }
274
275 /* ------------------------------------------------------------- */
276
277 int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
278 {
279         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
280         avmcard *card = cinfo->card;
281         unsigned int port = card->port;
282         unsigned long flags;
283         int retval;
284
285         b1_reset(port);
286
287         if ((retval = b1_load_t4file(card, &data->firmware))) {
288                 b1_reset(port);
289                 printk(KERN_ERR "%s: failed to load t4file!!\n",
290                                         card->name);
291                 return retval;
292         }
293
294         b1_disable_irq(port);
295
296         if (data->configuration.len > 0 && data->configuration.data) {
297                 if ((retval = b1_load_config(card, &data->configuration))) {
298                         b1_reset(port);
299                         printk(KERN_ERR "%s: failed to load config!!\n",
300                                         card->name);
301                         return retval;
302                 }
303         }
304
305         if (!b1_loaded(card)) {
306                 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
307                 return -EIO;
308         }
309
310         spin_lock_irqsave(&card->lock, flags);
311         b1_setinterrupt(port, card->irq, card->cardtype);
312         b1_put_byte(port, SEND_INIT);
313         b1_put_word(port, CAPI_MAXAPPL);
314         b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
315         b1_put_word(port, ctrl->cnr - 1);
316         spin_unlock_irqrestore(&card->lock, flags);
317
318         return 0;
319 }
320
321 void b1_reset_ctr(struct capi_ctr *ctrl)
322 {
323         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
324         avmcard *card = cinfo->card;
325         unsigned int port = card->port;
326         unsigned long flags;
327
328         b1_reset(port);
329         b1_reset(port);
330
331         memset(cinfo->version, 0, sizeof(cinfo->version));
332         spin_lock_irqsave(&card->lock, flags);
333         capilib_release(&cinfo->ncci_head);
334         spin_unlock_irqrestore(&card->lock, flags);
335         capi_ctr_down(ctrl);
336 }
337
338 void b1_register_appl(struct capi_ctr *ctrl,
339                                 u16 appl,
340                                 capi_register_params *rp)
341 {
342         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
343         avmcard *card = cinfo->card;
344         unsigned int port = card->port;
345         unsigned long flags;
346         int nconn, want = rp->level3cnt;
347
348         if (want > 0) nconn = want;
349         else nconn = ctrl->profile.nbchannel * -want;
350         if (nconn == 0) nconn = ctrl->profile.nbchannel;
351
352         spin_lock_irqsave(&card->lock, flags);
353         b1_put_byte(port, SEND_REGISTER);
354         b1_put_word(port, appl);
355         b1_put_word(port, 1024 * (nconn+1));
356         b1_put_word(port, nconn);
357         b1_put_word(port, rp->datablkcnt);
358         b1_put_word(port, rp->datablklen);
359         spin_unlock_irqrestore(&card->lock, flags);
360 }
361
362 void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
363 {
364         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
365         avmcard *card = cinfo->card;
366         unsigned int port = card->port;
367         unsigned long flags;
368
369         spin_lock_irqsave(&card->lock, flags);
370         capilib_release_appl(&cinfo->ncci_head, appl);
371         b1_put_byte(port, SEND_RELEASE);
372         b1_put_word(port, appl);
373         spin_unlock_irqrestore(&card->lock, flags);
374 }
375
376 u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
377 {
378         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
379         avmcard *card = cinfo->card;
380         unsigned int port = card->port;
381         unsigned long flags;
382         u16 len = CAPIMSG_LEN(skb->data);
383         u8 cmd = CAPIMSG_COMMAND(skb->data);
384         u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
385         u16 dlen, retval;
386
387         spin_lock_irqsave(&card->lock, flags);
388         if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
389                 retval = capilib_data_b3_req(&cinfo->ncci_head,
390                                              CAPIMSG_APPID(skb->data),
391                                              CAPIMSG_NCCI(skb->data),
392                                              CAPIMSG_MSGID(skb->data));
393                 if (retval != CAPI_NOERROR) {
394                         spin_unlock_irqrestore(&card->lock, flags);
395                         return retval;
396                 }
397
398                 dlen = CAPIMSG_DATALEN(skb->data);
399
400                 b1_put_byte(port, SEND_DATA_B3_REQ);
401                 b1_put_slice(port, skb->data, len);
402                 b1_put_slice(port, skb->data + len, dlen);
403         } else {
404                 b1_put_byte(port, SEND_MESSAGE);
405                 b1_put_slice(port, skb->data, len);
406         }
407         spin_unlock_irqrestore(&card->lock, flags);
408
409         dev_kfree_skb_any(skb);
410         return CAPI_NOERROR;
411 }
412
413 /* ------------------------------------------------------------- */
414
415 void b1_parse_version(avmctrl_info *cinfo)
416 {
417         struct capi_ctr *ctrl = &cinfo->capi_ctrl;
418         avmcard *card = cinfo->card;
419         capi_profile *profp;
420         u8 *dversion;
421         u8 flag;
422         int i, j;
423
424         for (j = 0; j < AVM_MAXVERSION; j++)
425                 cinfo->version[j] = "\0\0" + 1;
426         for (i = 0, j = 0;
427              j < AVM_MAXVERSION && i < cinfo->versionlen;
428              j++, i += cinfo->versionbuf[i] + 1)
429                 cinfo->version[j] = &cinfo->versionbuf[i + 1];
430
431         strlcpy(ctrl->serial, cinfo->version[VER_SERIAL], sizeof(ctrl->serial));
432         memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile));
433         strlcpy(ctrl->manu, "AVM GmbH", sizeof(ctrl->manu));
434         dversion = cinfo->version[VER_DRIVER];
435         ctrl->version.majorversion = 2;
436         ctrl->version.minorversion = 0;
437         ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
438         ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
439         ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
440         ctrl->version.minormanuversion |=
441                         (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
442
443         profp = &ctrl->profile;
444
445         flag = ((u8 *)(profp->manu))[1];
446         switch (flag) {
447         case 0: if (cinfo->version[VER_CARDTYPE])
448                    strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]);
449                 else strcpy(cinfo->cardname, "B1");
450                 break;
451         case 3: strcpy(cinfo->cardname,"PCMCIA B"); break;
452         case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break;
453         case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break;
454         case 6: strcpy(cinfo->cardname,"B1 V3.0"); break;
455         case 7: strcpy(cinfo->cardname,"B1 PCI"); break;
456         default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break;
457         }
458         printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
459                                 card->name, ctrl->cnr, cinfo->cardname);
460
461         flag = ((u8 *)(profp->manu))[3];
462         if (flag)
463                 printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n",
464                         card->name,
465                         ctrl->cnr,
466                         (flag & 0x01) ? " DSS1" : "",
467                         (flag & 0x02) ? " CT1" : "",
468                         (flag & 0x04) ? " VN3" : "",
469                         (flag & 0x08) ? " NI1" : "",
470                         (flag & 0x10) ? " AUSTEL" : "",
471                         (flag & 0x20) ? " ESS" : "",
472                         (flag & 0x40) ? " 1TR6" : ""
473                         );
474
475         flag = ((u8 *)(profp->manu))[5];
476         if (flag)
477                 printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
478                         card->name,
479                         ctrl->cnr,
480                         (flag & 0x01) ? " point to point" : "",
481                         (flag & 0x02) ? " point to multipoint" : "",
482                         (flag & 0x08) ? " leased line without D-channel" : "",
483                         (flag & 0x04) ? " leased line with D-channel" : ""
484                         );
485 }
486
487 /* ------------------------------------------------------------- */
488
489 irqreturn_t b1_interrupt(int interrupt, void *devptr)
490 {
491         avmcard *card = devptr;
492         avmctrl_info *cinfo = &card->ctrlinfo[0];
493         struct capi_ctr *ctrl = &cinfo->capi_ctrl;
494         unsigned char b1cmd;
495         struct sk_buff *skb;
496
497         unsigned ApplId;
498         unsigned MsgLen;
499         unsigned DataB3Len;
500         unsigned NCCI;
501         unsigned WindowSize;
502         unsigned long flags;
503
504         spin_lock_irqsave(&card->lock, flags);
505
506         if (!b1_rx_full(card->port)) {
507                 spin_unlock_irqrestore(&card->lock, flags);
508                 return IRQ_NONE;
509         }
510
511         b1cmd = b1_get_byte(card->port);
512
513         switch (b1cmd) {
514
515         case RECEIVE_DATA_B3_IND:
516
517                 ApplId = (unsigned) b1_get_word(card->port);
518                 MsgLen = b1_get_slice(card->port, card->msgbuf);
519                 DataB3Len = b1_get_slice(card->port, card->databuf);
520                 spin_unlock_irqrestore(&card->lock, flags);
521
522                 if (MsgLen < 30) { /* not CAPI 64Bit */
523                         memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
524                         MsgLen = 30;
525                         CAPIMSG_SETLEN(card->msgbuf, 30);
526                 }
527                 if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
528                         printk(KERN_ERR "%s: incoming packet dropped\n",
529                                         card->name);
530                 } else {
531                         memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
532                         memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
533                         capi_ctr_handle_message(ctrl, ApplId, skb);
534                 }
535                 break;
536
537         case RECEIVE_MESSAGE:
538
539                 ApplId = (unsigned) b1_get_word(card->port);
540                 MsgLen = b1_get_slice(card->port, card->msgbuf);
541                 if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
542                         printk(KERN_ERR "%s: incoming packet dropped\n",
543                                         card->name);
544                         spin_unlock_irqrestore(&card->lock, flags);
545                 } else {
546                         memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
547                         if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
548                                 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
549                                                      CAPIMSG_NCCI(skb->data),
550                                                      CAPIMSG_MSGID(skb->data));
551                         spin_unlock_irqrestore(&card->lock, flags);
552                         capi_ctr_handle_message(ctrl, ApplId, skb);
553                 }
554                 break;
555
556         case RECEIVE_NEW_NCCI:
557
558                 ApplId = b1_get_word(card->port);
559                 NCCI = b1_get_word(card->port);
560                 WindowSize = b1_get_word(card->port);
561                 capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
562                 spin_unlock_irqrestore(&card->lock, flags);
563                 break;
564
565         case RECEIVE_FREE_NCCI:
566
567                 ApplId = b1_get_word(card->port);
568                 NCCI = b1_get_word(card->port);
569                 if (NCCI != 0xffffffff)
570                         capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
571                 spin_unlock_irqrestore(&card->lock, flags);
572                 break;
573
574         case RECEIVE_START:
575                 /* b1_put_byte(card->port, SEND_POLLACK); */
576                 spin_unlock_irqrestore(&card->lock, flags);
577                 capi_ctr_resume_output(ctrl);
578                 break;
579
580         case RECEIVE_STOP:
581                 spin_unlock_irqrestore(&card->lock, flags);
582                 capi_ctr_suspend_output(ctrl);
583                 break;
584
585         case RECEIVE_INIT:
586
587                 cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
588                 spin_unlock_irqrestore(&card->lock, flags);
589                 b1_parse_version(cinfo);
590                 printk(KERN_INFO "%s: %s-card (%s) now active\n",
591                        card->name,
592                        cinfo->version[VER_CARDTYPE],
593                        cinfo->version[VER_DRIVER]);
594                 capi_ctr_ready(ctrl);
595                 break;
596
597         case RECEIVE_TASK_READY:
598                 ApplId = (unsigned) b1_get_word(card->port);
599                 MsgLen = b1_get_slice(card->port, card->msgbuf);
600                 spin_unlock_irqrestore(&card->lock, flags);
601                 card->msgbuf[MsgLen] = 0;
602                 while (    MsgLen > 0
603                        && (   card->msgbuf[MsgLen-1] == '\n'
604                            || card->msgbuf[MsgLen-1] == '\r')) {
605                         card->msgbuf[MsgLen-1] = 0;
606                         MsgLen--;
607                 }
608                 printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
609                                 card->name, ApplId, card->msgbuf);
610                 break;
611
612         case RECEIVE_DEBUGMSG:
613                 MsgLen = b1_get_slice(card->port, card->msgbuf);
614                 spin_unlock_irqrestore(&card->lock, flags);
615                 card->msgbuf[MsgLen] = 0;
616                 while (    MsgLen > 0
617                        && (   card->msgbuf[MsgLen-1] == '\n'
618                            || card->msgbuf[MsgLen-1] == '\r')) {
619                         card->msgbuf[MsgLen-1] = 0;
620                         MsgLen--;
621                 }
622                 printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
623                 break;
624
625         case 0xff:
626                 spin_unlock_irqrestore(&card->lock, flags);
627                 printk(KERN_ERR "%s: card removed ?\n", card->name);
628                 return IRQ_NONE;
629         default:
630                 spin_unlock_irqrestore(&card->lock, flags);
631                 printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
632                                 card->name, b1cmd);
633                 return IRQ_HANDLED;
634         }
635         return IRQ_HANDLED;
636 }
637
638 /* ------------------------------------------------------------- */
639 static int b1ctl_proc_show(struct seq_file *m, void *v)
640 {
641         struct capi_ctr *ctrl = m->private;
642         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
643         avmcard *card = cinfo->card;
644         u8 flag;
645         char *s;
646
647         seq_printf(m, "%-16s %s\n", "name", card->name);
648         seq_printf(m, "%-16s 0x%x\n", "io", card->port);
649         seq_printf(m, "%-16s %d\n", "irq", card->irq);
650         switch (card->cardtype) {
651         case avm_b1isa: s = "B1 ISA"; break;
652         case avm_b1pci: s = "B1 PCI"; break;
653         case avm_b1pcmcia: s = "B1 PCMCIA"; break;
654         case avm_m1: s = "M1"; break;
655         case avm_m2: s = "M2"; break;
656         case avm_t1isa: s = "T1 ISA (HEMA)"; break;
657         case avm_t1pci: s = "T1 PCI"; break;
658         case avm_c4: s = "C4"; break;
659         case avm_c2: s = "C2"; break;
660         default: s = "???"; break;
661         }
662         seq_printf(m, "%-16s %s\n", "type", s);
663         if (card->cardtype == avm_t1isa)
664                 seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr);
665         if ((s = cinfo->version[VER_DRIVER]) != NULL)
666                 seq_printf(m, "%-16s %s\n", "ver_driver", s);
667         if ((s = cinfo->version[VER_CARDTYPE]) != NULL)
668                 seq_printf(m, "%-16s %s\n", "ver_cardtype", s);
669         if ((s = cinfo->version[VER_SERIAL]) != NULL)
670                 seq_printf(m, "%-16s %s\n", "ver_serial", s);
671
672         if (card->cardtype != avm_m1) {
673                 flag = ((u8 *)(ctrl->profile.manu))[3];
674                 if (flag)
675                         seq_printf(m, "%-16s%s%s%s%s%s%s%s\n",
676                         "protocol",
677                         (flag & 0x01) ? " DSS1" : "",
678                         (flag & 0x02) ? " CT1" : "",
679                         (flag & 0x04) ? " VN3" : "",
680                         (flag & 0x08) ? " NI1" : "",
681                         (flag & 0x10) ? " AUSTEL" : "",
682                         (flag & 0x20) ? " ESS" : "",
683                         (flag & 0x40) ? " 1TR6" : ""
684                         );
685         }
686         if (card->cardtype != avm_m1) {
687                 flag = ((u8 *)(ctrl->profile.manu))[5];
688                 if (flag)
689                         seq_printf(m, "%-16s%s%s%s%s\n",
690                         "linetype",
691                         (flag & 0x01) ? " point to point" : "",
692                         (flag & 0x02) ? " point to multipoint" : "",
693                         (flag & 0x08) ? " leased line without D-channel" : "",
694                         (flag & 0x04) ? " leased line with D-channel" : ""
695                         );
696         }
697         seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname);
698
699         return 0;
700 }
701
702 static int b1ctl_proc_open(struct inode *inode, struct file *file)
703 {
704         return single_open(file, b1ctl_proc_show, PDE(inode)->data);
705 }
706
707 const struct file_operations b1ctl_proc_fops = {
708         .owner          = THIS_MODULE,
709         .open           = b1ctl_proc_open,
710         .read           = seq_read,
711         .llseek         = seq_lseek,
712         .release        = single_release,
713 };
714 EXPORT_SYMBOL(b1ctl_proc_fops);
715
716 /* ------------------------------------------------------------- */
717
718 #ifdef CONFIG_PCI
719
720 avmcard_dmainfo *
721 avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize)
722 {
723         avmcard_dmainfo *p;
724         void *buf;
725
726         p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL);
727         if (!p) {
728                 printk(KERN_WARNING "%s: no memory.\n", name);
729                 goto err;
730         }
731
732         p->recvbuf.size = rsize;
733         buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr);
734         if (!buf) {
735                 printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name);
736                 goto err_kfree;
737         }
738         p->recvbuf.dmabuf = buf;
739
740         p->sendbuf.size = ssize;
741         buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr);
742         if (!buf) {
743                 printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name);
744                 goto err_free_consistent;
745         }
746
747         p->sendbuf.dmabuf = buf;
748         skb_queue_head_init(&p->send_queue);
749
750         return p;
751
752  err_free_consistent:
753         pci_free_consistent(p->pcidev, p->recvbuf.size,
754                             p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
755  err_kfree:
756         kfree(p);
757  err:
758         return NULL;
759 }
760
761 void avmcard_dma_free(avmcard_dmainfo *p)
762 {
763         pci_free_consistent(p->pcidev, p->recvbuf.size,
764                             p->recvbuf.dmabuf, p->recvbuf.dmaaddr);
765         pci_free_consistent(p->pcidev, p->sendbuf.size,
766                             p->sendbuf.dmabuf, p->sendbuf.dmaaddr);
767         skb_queue_purge(&p->send_queue);
768         kfree(p);
769 }
770
771 EXPORT_SYMBOL(avmcard_dma_alloc);
772 EXPORT_SYMBOL(avmcard_dma_free);
773
774 #endif
775
776 EXPORT_SYMBOL(b1_irq_table);
777
778 EXPORT_SYMBOL(b1_alloc_card);
779 EXPORT_SYMBOL(b1_free_card);
780 EXPORT_SYMBOL(b1_detect);
781 EXPORT_SYMBOL(b1_getrevision);
782 EXPORT_SYMBOL(b1_load_t4file);
783 EXPORT_SYMBOL(b1_load_config);
784 EXPORT_SYMBOL(b1_loaded);
785 EXPORT_SYMBOL(b1_load_firmware);
786 EXPORT_SYMBOL(b1_reset_ctr);
787 EXPORT_SYMBOL(b1_register_appl);
788 EXPORT_SYMBOL(b1_release_appl);
789 EXPORT_SYMBOL(b1_send_message);
790
791 EXPORT_SYMBOL(b1_parse_version);
792 EXPORT_SYMBOL(b1_interrupt);
793
794 static int __init b1_init(void)
795 {
796         char *p;
797         char rev[32];
798
799         if ((p = strchr(revision, ':')) != NULL && p[1]) {
800                 strlcpy(rev, p + 2, 32);
801                 if ((p = strchr(rev, '$')) != NULL && p > rev)
802                    *(p-1) = 0;
803         } else
804                 strcpy(rev, "1.0");
805
806         printk(KERN_INFO "b1: revision %s\n", rev);
807
808         return 0;
809 }
810
811 static void __exit b1_exit(void)
812 {
813 }
814
815 module_init(b1_init);
816 module_exit(b1_exit);