import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / isdn / avmb1 / t1isa.c
1 /* $Id: t1isa.c,v 1.1.1.1 2005/04/11 02:50:23 jack Exp $
2  * 
3  * Module for AVM T1 HEMA-card.
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/skbuff.h>
15 #include <linux/delay.h>
16 #include <linux/mm.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/capi.h>
20 #include <linux/kernelcapi.h>
21 #include <linux/init.h>
22 #include <asm/io.h>
23 #include "capicmd.h"
24 #include "capiutil.h"
25 #include "capilli.h"
26 #include "avmcard.h"
27
28 static char *revision = "$Revision: 1.1.1.1 $";
29
30 /* ------------------------------------------------------------- */
31
32 MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
33 MODULE_AUTHOR("Carsten Paeth");
34 MODULE_LICENSE("GPL");
35
36 /* ------------------------------------------------------------- */
37
38 static struct capi_driver_interface *di;
39
40 /* ------------------------------------------------------------- */
41
42 static int hema_irq_table[16] =
43 {0,
44  0,
45  0,
46  0x80,                          /* irq 3 */
47  0,
48  0x90,                          /* irq 5 */
49  0,
50  0xA0,                          /* irq 7 */
51  0,
52  0xB0,                          /* irq 9 */
53  0xC0,                          /* irq 10 */
54  0xD0,                          /* irq 11 */
55  0xE0,                          /* irq 12 */
56  0,
57  0,
58  0xF0,                          /* irq 15 */
59 };
60
61 static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
62 {
63         unsigned char cregs[8];
64         unsigned char reverse_cardnr;
65         unsigned long flags;
66         unsigned char dummy;
67         int i;
68
69         reverse_cardnr =   ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
70                          | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
71         cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
72         cregs[1] = 0x00; /* fast & slow link connected to CON1 */
73         cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
74         cregs[3] = 0;
75         cregs[4] = 0x11; /* zero wait state */
76         cregs[5] = hema_irq_table[irq & 0xf];
77         cregs[6] = 0;
78         cregs[7] = 0;
79
80         save_flags(flags);
81         cli();
82         /* board reset */
83         t1outp(base, T1_RESETBOARD, 0xf);
84         mdelay(100);
85         dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
86
87         /* write config */
88         dummy = (base >> 4) & 0xff;
89         for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
90         t1outp(base, HEMA_PAL_ID & 0xf, dummy);
91         t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
92         for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
93         t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
94         restore_flags(flags);
95
96         mdelay(100);
97         t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
98         t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
99         mdelay(10);
100         t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
101         t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
102         mdelay(100);
103         t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
104         t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
105         mdelay(10);
106         t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
107         mdelay(5);
108         t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
109
110         if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
111                 return 1;
112         if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
113                 return 2;
114         if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
115                 return 3;
116         if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
117                 return 4;
118         if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
119                 return 5;
120         if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
121                 return 6;
122         if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
123                 return 7;
124         if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
125                 return 8;
126         if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
127                 return 9;
128         return 0;
129 }
130
131 static void t1_handle_interrupt(avmcard * card)
132 {
133         avmctrl_info *cinfo = &card->ctrlinfo[0];
134         struct capi_ctr *ctrl = cinfo->capi_ctrl;
135         unsigned char b1cmd;
136         struct sk_buff *skb;
137
138         unsigned ApplId;
139         unsigned MsgLen;
140         unsigned DataB3Len;
141         unsigned NCCI;
142         unsigned WindowSize;
143
144         while (b1_rx_full(card->port)) {
145
146                 b1cmd = b1_get_byte(card->port);
147
148                 switch (b1cmd) {
149
150                 case RECEIVE_DATA_B3_IND:
151
152                         ApplId = (unsigned) b1_get_word(card->port);
153                         MsgLen = t1_get_slice(card->port, card->msgbuf);
154                         DataB3Len = t1_get_slice(card->port, card->databuf);
155
156                         if (MsgLen < 30) { /* not CAPI 64Bit */
157                                 memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
158                                 MsgLen = 30;
159                                 CAPIMSG_SETLEN(card->msgbuf, 30);
160                         }
161                         if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
162                                 printk(KERN_ERR "%s: incoming packet dropped\n",
163                                         card->name);
164                         } else {
165                                 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
166                                 memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
167                                 ctrl->handle_capimsg(ctrl, ApplId, skb);
168                         }
169                         break;
170
171                 case RECEIVE_MESSAGE:
172
173                         ApplId = (unsigned) b1_get_word(card->port);
174                         MsgLen = t1_get_slice(card->port, card->msgbuf);
175                         if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
176                                 printk(KERN_ERR "%s: incoming packet dropped\n",
177                                                 card->name);
178                         } else {
179                                 memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
180                                 ctrl->handle_capimsg(ctrl, ApplId, skb);
181                         }
182                         break;
183
184                 case RECEIVE_NEW_NCCI:
185
186                         ApplId = b1_get_word(card->port);
187                         NCCI = b1_get_word(card->port);
188                         WindowSize = b1_get_word(card->port);
189
190                         ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
191
192                         break;
193
194                 case RECEIVE_FREE_NCCI:
195
196                         ApplId = b1_get_word(card->port);
197                         NCCI = b1_get_word(card->port);
198
199                         if (NCCI != 0xffffffff)
200                                 ctrl->free_ncci(ctrl, ApplId, NCCI);
201                         else ctrl->appl_released(ctrl, ApplId);
202                         break;
203
204                 case RECEIVE_START:
205                         b1_put_byte(card->port, SEND_POLLACK);
206                         ctrl->resume_output(ctrl);
207                         break;
208
209                 case RECEIVE_STOP:
210                         ctrl->suspend_output(ctrl);
211                         break;
212
213                 case RECEIVE_INIT:
214
215                         cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
216                         b1_parse_version(cinfo);
217                         printk(KERN_INFO "%s: %s-card (%s) now active\n",
218                                card->name,
219                                cinfo->version[VER_CARDTYPE],
220                                cinfo->version[VER_DRIVER]);
221                         ctrl->ready(ctrl);
222                         break;
223
224                 case RECEIVE_TASK_READY:
225                         ApplId = (unsigned) b1_get_word(card->port);
226                         MsgLen = t1_get_slice(card->port, card->msgbuf);
227                         card->msgbuf[MsgLen] = 0;
228                         while (    MsgLen > 0
229                                && (   card->msgbuf[MsgLen-1] == '\n'
230                                    || card->msgbuf[MsgLen-1] == '\r')) {
231                                 card->msgbuf[MsgLen-1] = 0;
232                                 MsgLen--;
233                         }
234                         printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
235                                         card->name, ApplId, card->msgbuf);
236                         break;
237
238                 case RECEIVE_DEBUGMSG:
239                         MsgLen = t1_get_slice(card->port, card->msgbuf);
240                         card->msgbuf[MsgLen] = 0;
241                         while (    MsgLen > 0
242                                && (   card->msgbuf[MsgLen-1] == '\n'
243                                    || card->msgbuf[MsgLen-1] == '\r')) {
244                                 card->msgbuf[MsgLen-1] = 0;
245                                 MsgLen--;
246                         }
247                         printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
248                         break;
249
250
251                 case 0xff:
252                         printk(KERN_ERR "%s: card reseted ?\n", card->name);
253                         return;
254                 default:
255                         printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
256                                         card->name, b1cmd);
257                         return;
258                 }
259         }
260 }
261
262 /* ------------------------------------------------------------- */
263
264 static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
265 {
266         avmcard *card;
267
268         card = (avmcard *) devptr;
269
270         if (!card) {
271                 printk(KERN_WARNING "t1isa: interrupt: wrong device\n");
272                 return;
273         }
274         if (card->interrupt) {
275                 printk(KERN_ERR "%s: reentering interrupt hander.\n",
276                                  card->name);
277                 return;
278         }
279
280         card->interrupt = 1;
281
282         t1_handle_interrupt(card);
283
284         card->interrupt = 0;
285 }
286 /* ------------------------------------------------------------- */
287
288 static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
289 {
290         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
291         avmcard *card = cinfo->card;
292         unsigned int port = card->port;
293         unsigned long flags;
294         int retval;
295
296         t1_disable_irq(port);
297         b1_reset(port);
298
299         if ((retval = b1_load_t4file(card, &data->firmware))) {
300                 b1_reset(port);
301                 printk(KERN_ERR "%s: failed to load t4file!!\n",
302                                         card->name);
303                 return retval;
304         }
305
306         if (data->configuration.len > 0 && data->configuration.data) {
307                 if ((retval = b1_load_config(card, &data->configuration))) {
308                         b1_reset(port);
309                         printk(KERN_ERR "%s: failed to load config!!\n",
310                                         card->name);
311                         return retval;
312                 }
313         }
314
315         if (!b1_loaded(card)) {
316                 printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
317                 return -EIO;
318         }
319
320         save_flags(flags);
321         cli();
322         b1_setinterrupt(port, card->irq, card->cardtype);
323         b1_put_byte(port, SEND_INIT);
324         b1_put_word(port, CAPI_MAXAPPL);
325         b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
326         b1_put_word(port, ctrl->cnr - 1);
327         restore_flags(flags);
328
329         return 0;
330 }
331
332 void t1isa_reset_ctr(struct capi_ctr *ctrl)
333 {
334         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
335         avmcard *card = cinfo->card;
336         unsigned int port = card->port;
337
338         t1_disable_irq(port);
339         b1_reset(port);
340         b1_reset(port);
341
342         memset(cinfo->version, 0, sizeof(cinfo->version));
343         ctrl->reseted(ctrl);
344 }
345
346 static void t1isa_remove_ctr(struct capi_ctr *ctrl)
347 {
348         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
349         avmcard *card = cinfo->card;
350         unsigned int port = card->port;
351
352         t1_disable_irq(port);
353         b1_reset(port);
354         b1_reset(port);
355         t1_reset(port);
356
357         di->detach_ctr(ctrl);
358         free_irq(card->irq, card);
359         release_region(card->port, AVMB1_PORTLEN);
360         kfree(card->ctrlinfo);
361         kfree(card);
362
363         MOD_DEC_USE_COUNT;
364 }
365
366 /* ------------------------------------------------------------- */
367
368 static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
369 {
370         struct capi_ctr *ctrl;
371         avmctrl_info *cinfo;
372         avmcard *card;
373         int retval;
374
375         MOD_INC_USE_COUNT;
376
377         card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
378
379         if (!card) {
380                 printk(KERN_WARNING "%s: no memory.\n", driver->name);
381                 MOD_DEC_USE_COUNT;
382                 return -ENOMEM;
383         }
384         memset(card, 0, sizeof(avmcard));
385         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
386         if (!cinfo) {
387                 printk(KERN_WARNING "%s: no memory.\n", driver->name);
388                 kfree(card);
389                 MOD_DEC_USE_COUNT;
390                 return -ENOMEM;
391         }
392         memset(cinfo, 0, sizeof(avmctrl_info));
393         card->ctrlinfo = cinfo;
394         cinfo->card = card;
395         sprintf(card->name, "t1isa-%x", p->port);
396         card->port = p->port;
397         card->irq = p->irq;
398         card->cardtype = avm_t1isa;
399         card->cardnr = p->cardnr;
400
401         if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
402                 printk(KERN_WARNING "%s: illegal port 0x%x.\n",
403                                 driver->name, card->port);
404                 kfree(card->ctrlinfo);
405                 kfree(card);
406                 MOD_DEC_USE_COUNT;
407                 return -EINVAL;
408         }
409
410         if (check_region(card->port, AVMB1_PORTLEN)) {
411                 printk(KERN_WARNING
412                        "%s: ports 0x%03x-0x%03x in use.\n",
413                        driver->name, card->port, card->port + AVMB1_PORTLEN);
414                 kfree(card->ctrlinfo);
415                 kfree(card);
416                 MOD_DEC_USE_COUNT;
417                 return -EBUSY;
418         }
419         if (hema_irq_table[card->irq & 0xf] == 0) {
420                 printk(KERN_WARNING "%s: irq %d not valid.\n",
421                                 driver->name, card->irq);
422                 kfree(card->ctrlinfo);
423                 kfree(card);
424                 MOD_DEC_USE_COUNT;
425                 return -EINVAL;
426         }
427         for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
428                 avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card;
429                 if (cardp->cardnr == card->cardnr) {
430                         printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n",
431                                         driver->name, card->cardnr, cardp->port);
432                         kfree(card->ctrlinfo);
433                         kfree(card);
434                         MOD_DEC_USE_COUNT;
435                         return -EBUSY;
436                 }
437         }
438         if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
439                 printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
440                                         driver->name, card->port, retval);
441                 kfree(card->ctrlinfo);
442                 kfree(card);
443                 MOD_DEC_USE_COUNT;
444                 return -EIO;
445         }
446         t1_disable_irq(card->port);
447         b1_reset(card->port);
448
449         request_region(p->port, AVMB1_PORTLEN, card->name);
450
451         retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
452         if (retval) {
453                 printk(KERN_ERR "%s: unable to get IRQ %d.\n",
454                                 driver->name, card->irq);
455                 release_region(card->port, AVMB1_PORTLEN);
456                 kfree(card->ctrlinfo);
457                 kfree(card);
458                 MOD_DEC_USE_COUNT;
459                 return -EBUSY;
460         }
461
462         cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
463         if (!cinfo->capi_ctrl) {
464                 printk(KERN_ERR "%s: attach controller failed.\n",
465                                 driver->name);
466                 free_irq(card->irq, card);
467                 release_region(card->port, AVMB1_PORTLEN);
468                 kfree(card->ctrlinfo);
469                 kfree(card);
470                 MOD_DEC_USE_COUNT;
471                 return -EBUSY;
472         }
473
474         printk(KERN_INFO
475                 "%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
476                 driver->name, card->port, card->irq, card->cardnr);
477
478         return 0;
479 }
480
481 static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
482 {
483         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
484         avmcard *card = cinfo->card;
485         unsigned int port = card->port;
486         unsigned long flags;
487         __u16 len = CAPIMSG_LEN(skb->data);
488         __u8 cmd = CAPIMSG_COMMAND(skb->data);
489         __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
490
491         save_flags(flags);
492         cli();
493         if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
494                 __u16 dlen = CAPIMSG_DATALEN(skb->data);
495                 b1_put_byte(port, SEND_DATA_B3_REQ);
496                 t1_put_slice(port, skb->data, len);
497                 t1_put_slice(port, skb->data + len, dlen);
498         } else {
499                 b1_put_byte(port, SEND_MESSAGE);
500                 t1_put_slice(port, skb->data, len);
501         }
502         restore_flags(flags);
503         dev_kfree_skb(skb);
504 }
505 /* ------------------------------------------------------------- */
506
507 static char *t1isa_procinfo(struct capi_ctr *ctrl)
508 {
509         avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
510
511         if (!cinfo)
512                 return "";
513         sprintf(cinfo->infobuf, "%s %s 0x%x %d %d",
514                 cinfo->cardname[0] ? cinfo->cardname : "-",
515                 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
516                 cinfo->card ? cinfo->card->port : 0x0,
517                 cinfo->card ? cinfo->card->irq : 0,
518                 cinfo->card ? cinfo->card->cardnr : 0
519                 );
520         return cinfo->infobuf;
521 }
522
523
524 /* ------------------------------------------------------------- */
525
526 static struct capi_driver t1isa_driver = {
527     name: "t1isa",
528     revision: "0.0",
529     load_firmware: t1isa_load_firmware,
530     reset_ctr: t1isa_reset_ctr,
531     remove_ctr: t1isa_remove_ctr,
532     register_appl: b1_register_appl,
533     release_appl: b1_release_appl,
534     send_message: t1isa_send_message,
535
536     procinfo: t1isa_procinfo,
537     ctr_read_proc: b1ctl_read_proc,
538     driver_read_proc: 0,        /* use standard driver_read_proc */
539
540     add_card: t1isa_add_card,
541 };
542
543 static int __init t1isa_init(void)
544 {
545         struct capi_driver *driver = &t1isa_driver;
546         char *p;
547         int retval = 0;
548
549         MOD_INC_USE_COUNT;
550
551         if ((p = strchr(revision, ':')) != 0 && p[1]) {
552                 strncpy(driver->revision, p + 2, sizeof(driver->revision));
553                 driver->revision[sizeof(driver->revision)-1] = 0;
554                 if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
555                         *(p-1) = 0;
556         }
557
558         printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
559
560         di = attach_capi_driver(driver);
561
562         if (!di) {
563                 printk(KERN_ERR "%s: failed to attach capi_driver\n",
564                                 driver->name);
565                 retval = -EIO;
566         }
567
568         MOD_DEC_USE_COUNT;
569         return retval;
570 }
571
572 static void __exit t1isa_exit(void)
573 {
574     detach_capi_driver(&t1isa_driver);
575 }
576
577 module_init(t1isa_init);
578 module_exit(t1isa_exit);