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
eicon_isa_release_shmem(eicon_isa_card * card)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
eicon_isa_release_irq(eicon_isa_card * card)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
eicon_isa_release(eicon_isa_card * card)57 eicon_isa_release(eicon_isa_card *card) {
58 eicon_isa_release_irq(card);
59 eicon_isa_release_shmem(card);
60 }
61
62 void
eicon_isa_printpar(eicon_isa_card * card)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
eicon_isa_find_card(int Mem,int Irq,char * Id)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
eicon_isa_bootload(eicon_isa_card * card,eicon_isa_codebuf * cb)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
eicon_isa_load(eicon_isa_card * card,eicon_isa_codebuf * cb)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 */
455