1/* $Id: eicon_isa.c,v 1.1.1.1 2008/10/15 03:26:33 james26_jang 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
23char *eicon_isa_revision = "$Revision: 1.1.1.1 $";
24
25#undef EICON_MCA_DEBUG
26
27#ifdef CONFIG_ISDN_DRV_EICON_ISA
28
29/* Mask for detecting invalid IRQ parameter */
30static 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
38static void
39eicon_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
47static void
48eicon_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
56void
57eicon_isa_release(eicon_isa_card *card) {
58	eicon_isa_release_irq(card);
59	eicon_isa_release_shmem(card);
60}
61
62void
63eicon_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
77int
78eicon_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
123int
124eicon_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
299int
300eicon_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