import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / isdn / eicon / eicon_isa.c
1 /* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
2  *
3  * ISDN low-level module for Eicon active ISDN-Cards.
4  * Hardware-specific code for old ISA cards.
5  *
6  * Copyright 1998      by Fritz Elfert (fritz@isdn4linux.de)
7  * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
8  * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
9  *
10  * This software may be used and distributed according to the terms
11  * of the GNU General Public License, incorporated herein by reference.
12  *
13  */
14
15 #include <linux/config.h>
16 #include "eicon.h"
17 #include "eicon_isa.h"
18
19 #define check_shmem   check_region
20 #define release_shmem release_region
21 #define request_shmem request_region
22
23 char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
24
25 #undef EICON_MCA_DEBUG
26
27 #ifdef CONFIG_ISDN_DRV_EICON_ISA
28
29 /* Mask for detecting invalid IRQ parameter */
30 static int eicon_isa_valid_irq[] = {
31         0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/
32         0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */
33         0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */
34         0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */
35         0x1cbc  /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */
36 };
37
38 static void
39 eicon_isa_release_shmem(eicon_isa_card *card) {
40         if (card->mvalid) {
41                 iounmap(card->shmem);
42                 release_mem_region(card->physmem, card->ramsize);
43         }
44         card->mvalid = 0;
45 }
46
47 static void
48 eicon_isa_release_irq(eicon_isa_card *card) {
49         if (!card->master)
50                 return;
51         if (card->ivalid)
52                 free_irq(card->irq, card);
53         card->ivalid = 0;
54 }
55
56 void
57 eicon_isa_release(eicon_isa_card *card) {
58         eicon_isa_release_irq(card);
59         eicon_isa_release_shmem(card);
60 }
61
62 void
63 eicon_isa_printpar(eicon_isa_card *card) {
64         switch (card->type) {
65                 case EICON_CTYPE_S:
66                 case EICON_CTYPE_SX:
67                 case EICON_CTYPE_SCOM:
68                 case EICON_CTYPE_QUADRO:
69                 case EICON_CTYPE_S2M:
70                         printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n",
71                                eicon_ctype_name[card->type],
72                                card->physmem,
73                                card->irq);
74         }
75 }
76
77 int
78 eicon_isa_find_card(int Mem, int Irq, char * Id)
79 {
80         int primary = 1;
81         unsigned long amem;
82
83         if (!strlen(Id))
84                 return -1;
85
86         if (Mem == -1)
87                 return -1;
88
89         /* Check for valid membase address */
90         if ((Mem < 0x0c0000) ||
91             (Mem > 0x0fc000) ||
92             (Mem & 0xfff)) { 
93                 printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %s\n",
94                          Mem, Id);
95                 return -1;
96         }
97         if (check_mem_region(Mem, RAMSIZE)) {
98                 printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem);
99                 return -1;
100         }
101
102         amem = (unsigned long) ioremap(Mem, RAMSIZE);
103         writew(0x55aa, amem + 0x402);
104         if (readw(amem + 0x402) != 0x55aa) primary = 0;
105         writew(0, amem + 0x402);
106         if (readw(amem + 0x402) != 0) primary = 0;
107
108         printk(KERN_INFO "Eicon: Driver-ID: %s\n", Id);
109         if (primary) {
110                 printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem);
111                 writeb(0, amem + 0x3ffe);
112                 iounmap((unsigned char *)amem);
113                 return EICON_CTYPE_ISAPRI;
114         } else {
115                 printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem);
116                 writeb(0, amem + 0x400);
117                 iounmap((unsigned char *)amem);
118                 return EICON_CTYPE_ISABRI;
119         }
120         return -1;
121 }
122
123 int
124 eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
125         int     tmp;
126         int               timeout;
127         eicon_isa_codebuf cbuf;
128         unsigned char     *code;
129         eicon_isa_boot    *boot;
130
131         if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
132                 return -EFAULT;
133
134         /* Allocate code-buffer and copy code from userspace */
135         if (cbuf.bootstrap_len > 1024) {
136                 printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ld\n",
137                        cbuf.bootstrap_len);
138                 return -EINVAL;
139         }
140         if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) {
141                 printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n");
142                 return -ENOMEM;
143         }
144         if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) {
145                 kfree(code);
146                 return -EFAULT;
147         }
148
149         if (card->type == EICON_CTYPE_ISAPRI)
150                 card->ramsize  = RAMSIZE_P;
151         else
152                 card->ramsize  = RAMSIZE;
153
154         if (check_mem_region(card->physmem, card->ramsize)) {
155                 printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
156                         card->physmem);
157                 kfree(code);
158                 return -EBUSY;
159         }
160         request_mem_region(card->physmem, card->ramsize, "Eicon ISA ISDN");
161         card->shmem = (eicon_isa_shmem *) ioremap(card->physmem, card->ramsize);
162 #ifdef EICON_MCA_DEBUG
163         printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize);
164 #endif
165         card->mvalid = 1;
166
167         switch(card->type) {
168                 case EICON_CTYPE_S:
169                 case EICON_CTYPE_SX:
170                 case EICON_CTYPE_SCOM:
171                 case EICON_CTYPE_QUADRO:
172                 case EICON_CTYPE_ISABRI:
173                         card->intack   = (__u8 *)card->shmem + INTACK;
174                         card->startcpu = (__u8 *)card->shmem + STARTCPU;
175                         card->stopcpu  = (__u8 *)card->shmem + STOPCPU;
176                         break;
177                 case EICON_CTYPE_S2M:
178                 case EICON_CTYPE_ISAPRI:
179                         card->intack   = (__u8 *)card->shmem + INTACK_P;
180                         card->startcpu = (__u8 *)card->shmem + STARTCPU_P;
181                         card->stopcpu  = (__u8 *)card->shmem + STOPCPU_P;
182                         break;
183                 default:
184                         printk(KERN_WARNING "eicon_isa_boot: Invalid card type %d\n", card->type);
185                         eicon_isa_release_shmem(card);
186                         kfree(code);
187                         return -EINVAL;
188         }
189
190         /* clear any pending irq's */
191         readb(card->intack);
192 #ifdef CONFIG_MCA
193         if (MCA_bus) {
194                 if (card->type == EICON_CTYPE_SCOM) {
195                         outb_p(0,card->io+1);
196                 }
197                 else {
198                         printk(KERN_WARNING "eicon_isa_boot: Card type not supported yet.\n");
199                         eicon_isa_release_shmem(card);
200                         return -EINVAL;
201                 };
202
203 #ifdef EICON_MCA_DEBUG
204         printk(KERN_INFO "eicon_isa_boot: card->io      = %x.\n", card->io);
205         printk(KERN_INFO "eicon_isa_boot: card->irq     = %d.\n", (int)card->irq);
206 #endif
207         }
208 #else
209         /* set reset-line active */
210         writeb(0, card->stopcpu); 
211 #endif  /* CONFIG_MCA */
212         /* clear irq-requests */
213         writeb(0, card->intack);
214         readb(card->intack);
215
216         /* Copy code into card */
217         memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len);
218
219         /* Check for properly loaded code */
220         if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) {
221                 printk(KERN_WARNING "eicon_isa_boot: Could not load startup-code\n");
222                 eicon_isa_release_shmem(card);
223                 kfree(code);
224                 return -EIO;
225         }
226         /* if 16k-ramsize, duplicate the reset-jump-code */
227         if (card->ramsize == RAMSIZE_P)
228                 memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12);
229
230         kfree(code);
231         boot = &card->shmem->boot;
232
233         /* Delay 0.2 sec. */
234         SLEEP(HZ / 5);
235
236         /* Start CPU */
237         writeb(cbuf.boot_opt, &boot->ctrl);
238 #ifdef CONFIG_MCA
239         if (MCA_bus) {
240                 outb_p(0, card->io);
241         }
242 #else 
243         writeb(0, card->startcpu); 
244 #endif /* CONFIG_MCA */
245
246         /* Delay 0.2 sec. */
247         SLEEP(HZ / 5);
248
249         timeout = jiffies + (HZ * 22);
250         while (time_before(jiffies, timeout)) {
251                 if (readb(&boot->ctrl) == 0)
252                         break;
253                 SLEEP(10);
254         }
255         if (readb(&boot->ctrl) != 0) {
256                 printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n");
257 #ifdef EICON_MCA_DEBUG
258                 printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n",
259                         readb(&boot->ctrl));
260 #endif
261                 eicon_isa_release_shmem(card);
262                 return -EIO;
263         }
264
265         /* Check for memory-test errors */
266         if (readw(&boot->ebit)) {
267                 printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)\n",
268                        readw(&boot->ebit), readl(&boot->eloc));
269                 eicon_isa_release_shmem(card);
270                 return -EIO;
271         }
272
273         /* Check card type and memory size */
274         tmp = readb(&boot->card);
275         if ((tmp < 0) || (tmp > 4)) {
276                 printk(KERN_WARNING "eicon_isa_boot: Type detect failed\n");
277                 eicon_isa_release_shmem(card);
278                 return -EIO;
279         }
280         card->type = tmp;
281         ((eicon_card *)card->card)->type = tmp;
282
283         tmp = readb(&boot->msize);
284         if (tmp != 8 && tmp != 16 && tmp != 24 &&
285             tmp != 32 && tmp != 48 && tmp != 60) {
286                 printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n");
287                 eicon_isa_release_shmem(card);
288                 return -EIO;
289         }
290         printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); 
291         if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) {
292                 tmp = eicon_addcard(card->type, card->physmem, card->irq, 
293                                 ((eicon_card *)card->card)->regname, 0);
294                 printk(KERN_INFO "Eicon: %d adapters added\n", tmp);
295         }
296         return 0;
297 }
298
299 int
300 eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
301         eicon_isa_boot    *boot;
302         int               tmp;
303         int               timeout;
304         int               j;
305         eicon_isa_codebuf cbuf;
306         unsigned char     *code;
307         unsigned char     *p;
308
309         if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
310                 return -EFAULT;
311
312         if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) {
313                 printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n");
314                 return -ENOMEM;
315         }
316
317         if (copy_from_user(code, &cb->code, cbuf.firmware_len)) {
318                 kfree(code);
319                 return -EFAULT;
320         }
321
322         boot = &card->shmem->boot;
323
324         if ((!card->ivalid) && card->master) {
325                 card->irqprobe = 1;
326                 /* Check for valid IRQ */
327                 if ((card->irq < 0) || (card->irq > 15) || 
328                     (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) {
329                         printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq);
330                         eicon_isa_release_shmem(card);
331                         kfree(code);
332                         return -EINVAL;
333                 }
334                 /* Register irq */
335                 if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card))
336                         card->ivalid = 1;
337                 else {
338                         printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n",
339                                card->irq);
340                         eicon_isa_release_shmem(card);
341                         kfree(code);
342                         return -EBUSY;
343                 }
344         }
345
346         tmp = readb(&boot->msize);
347         if (tmp != 8 && tmp != 16 && tmp != 24 &&
348             tmp != 32 && tmp != 48 && tmp != 60) {
349                 printk(KERN_WARNING "eicon_isa_load: invalid memsize\n");
350                 eicon_isa_release_shmem(card);
351                 return -EIO;
352         }
353
354         eicon_isa_printpar(card);
355
356         /* Download firmware */
357         printk(KERN_INFO "%s %dkB, loading firmware ...\n", 
358                eicon_ctype_name[card->type],
359                tmp * 16);
360         tmp = cbuf.firmware_len >> 8;
361         p = code;
362         while (tmp--) {
363                 memcpy_toio(&boot->b, p, 256);
364                 writeb(1, &boot->ctrl);
365                 timeout = jiffies + HZ / 10;
366                 while (time_before(jiffies, timeout)) {
367                         if (readb(&boot->ctrl) == 0)
368                                 break;
369                         SLEEP(2);
370                 }
371                 if (readb(&boot->ctrl)) {
372                         printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code);
373                         eicon_isa_release(card);
374                         kfree(code);
375                         return -EIO;
376                 }
377                 p += 256;
378         }
379         kfree(code);
380
381         /* Initialize firmware parameters */
382         memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14);
383         memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96);
384         memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96);
385         
386         /* Start firmware, wait for signature */
387         writeb(2, &boot->ctrl);
388         timeout = jiffies + (5*HZ);
389         while (time_before(jiffies, timeout)) {
390                 if (readw(&boot->signature) == 0x4447)
391                         break;
392                 SLEEP(2);
393         }
394         if (readw(&boot->signature) != 0x4447) {
395                 printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n",
396                        readw(&boot->signature));
397                 eicon_isa_release(card);
398                 return -EIO;
399         }
400
401         card->channels = readb(&card->shmem->c[0x3f6]);
402
403         /* clear irq-requests, reset irq-count */
404         readb(card->intack);
405         writeb(0, card->intack);
406
407         if (card->master) {
408                 card->irqprobe = 1;
409                 /* Trigger an interrupt and check if it is delivered */
410                 tmp = readb(&card->shmem->com.ReadyInt);
411                 tmp ++;
412                 writeb(tmp, &card->shmem->com.ReadyInt);
413                 timeout = jiffies + HZ / 5;
414                 while (time_before(jiffies, timeout)) {
415                         if (card->irqprobe > 1)
416                                 break;
417                         SLEEP(2);
418                 }
419                 if (card->irqprobe == 1) {
420                         printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq);
421                         eicon_isa_release(card);
422                         return -EIO;
423                 }
424         }
425 #ifdef EICON_MCA_DEBUG
426         printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq);
427 #endif
428
429         writeb(card->irq, &card->shmem->com.Int);
430
431         /* initializing some variables */
432         ((eicon_card *)card->card)->ReadyInt = 0;
433         ((eicon_card *)card->card)->ref_in  = 1;
434         ((eicon_card *)card->card)->ref_out = 1;
435         for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
436         for(j=0; j< (card->channels + 1); j++) {
437                 ((eicon_card *)card->card)->bch[j].e.busy = 0;
438                 ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
439                 ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
440                 ((eicon_card *)card->card)->bch[j].e.ref = 0;
441                 ((eicon_card *)card->card)->bch[j].e.Req = 0;
442                 ((eicon_card *)card->card)->bch[j].e.complete = 1;
443                 ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
444         }
445
446         printk(KERN_INFO "Eicon: Supported channels: %d\n", card->channels); 
447         printk(KERN_INFO "%s successfully started\n", eicon_ctype_name[card->type]);
448
449         /* Enable normal IRQ processing */
450         card->irqprobe = 0;
451         return 0;
452 }
453
454 #endif /* CONFIG_ISDN_DRV_EICON_ISA */