File: /usr/src/linux/drivers/isdn/hisax/diva.c

1     /* $Id: diva.c,v 1.25.6.4 2001/02/16 16:43:25 kai Exp $
2      *
3      * diva.c     low level stuff for Eicon.Diehl Diva Family ISDN cards
4      *
5      * Author     Karsten Keil (keil@isdn4linux.de)
6      *
7      *		This file is (c) under GNU General Public License
8      *		For changes and modifications please read
9      *		../../../Documentation/isdn/HiSax.cert
10      *
11      * Thanks to Eicon Technology for documents and informations
12      *
13      */
14     
15     #define __NO_VERSION__
16     #include <linux/init.h>
17     #include <linux/config.h>
18     #include "hisax.h"
19     #include "isac.h"
20     #include "hscx.h"
21     #include "ipac.h"
22     #include "isdnl1.h"
23     #include <linux/pci.h>
24     
25     extern const char *CardType[];
26     
27     const char *Diva_revision = "$Revision: 1.25.6.4 $";
28     
29     #define byteout(addr,val) outb(val,addr)
30     #define bytein(addr) inb(addr)
31     
32     #define DIVA_HSCX_DATA		0
33     #define DIVA_HSCX_ADR		4
34     #define DIVA_ISA_ISAC_DATA	2
35     #define DIVA_ISA_ISAC_ADR	6
36     #define DIVA_ISA_CTRL		7
37     #define DIVA_IPAC_ADR		0
38     #define DIVA_IPAC_DATA		1
39     
40     #define DIVA_PCI_ISAC_DATA	8
41     #define DIVA_PCI_ISAC_ADR	0xc
42     #define DIVA_PCI_CTRL		0x10
43     
44     /* SUB Types */
45     #define DIVA_ISA	1
46     #define DIVA_PCI	2
47     #define DIVA_IPAC_ISA	3
48     #define DIVA_IPAC_PCI	4
49     
50     /* CTRL (Read) */
51     #define DIVA_IRQ_STAT	0x01
52     #define DIVA_EEPROM_SDA	0x02
53     
54     /* CTRL (Write) */
55     #define DIVA_IRQ_REQ	0x01
56     #define DIVA_RESET	0x08
57     #define DIVA_EEPROM_CLK	0x40
58     #define DIVA_PCI_LED_A	0x10
59     #define DIVA_PCI_LED_B	0x20
60     #define DIVA_ISA_LED_A	0x20
61     #define DIVA_ISA_LED_B	0x40
62     #define DIVA_IRQ_CLR	0x80
63     
64     /* Siemens PITA */
65     #define PITA_MISC_REG		0x1c
66     #ifdef __BIG_ENDIAN
67     #define PITA_PARA_SOFTRESET	0x00000001
68     #define PITA_PARA_MPX_MODE	0x00000004
69     #define PITA_INT0_ENABLE	0x00000200
70     #else
71     #define PITA_PARA_SOFTRESET	0x01000000
72     #define PITA_PARA_MPX_MODE	0x04000000
73     #define PITA_INT0_ENABLE	0x00020000
74     #endif
75     #define PITA_INT0_STATUS	0x02
76     
77     static inline u_char
78     readreg(unsigned int ale, unsigned int adr, u_char off)
79     {
80     	register u_char ret;
81     	long flags;
82     
83     	save_flags(flags);
84     	cli();
85     	byteout(ale, off);
86     	ret = bytein(adr);
87     	restore_flags(flags);
88     	return (ret);
89     }
90     
91     static inline void
92     readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
93     {
94     	/* fifo read without cli because it's allready done  */
95     
96     	byteout(ale, off);
97     	insb(adr, data, size);
98     }
99     
100     
101     static inline void
102     writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
103     {
104     	long flags;
105     
106     	save_flags(flags);
107     	cli();
108     	byteout(ale, off);
109     	byteout(adr, data);
110     	restore_flags(flags);
111     }
112     
113     static inline void
114     writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
115     {
116     	/* fifo write without cli because it's allready done  */
117     	byteout(ale, off);
118     	outsb(adr, data, size);
119     }
120     
121     static inline u_char
122     memreadreg(unsigned long adr, u_char off)
123     {
124     	return(*((unsigned char *)
125     		(((unsigned int *)adr) + off)));
126     }
127     
128     static inline void
129     memwritereg(unsigned long adr, u_char off, u_char data)
130     {
131     	register u_char *p;
132     	
133     	p = (unsigned char *)(((unsigned int *)adr) + off);
134     	*p = data;
135     }
136     
137     /* Interface functions */
138     
139     static u_char
140     ReadISAC(struct IsdnCardState *cs, u_char offset)
141     {
142     	return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset));
143     }
144     
145     static void
146     WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
147     {
148     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value);
149     }
150     
151     static void
152     ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
153     {
154     	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
155     }
156     
157     static void
158     WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
159     {
160     	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
161     }
162     
163     static u_char
164     ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
165     {
166     	return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80));
167     }
168     
169     static void
170     WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
171     {
172     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
173     }
174     
175     static void
176     ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
177     {
178     	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
179     }
180     
181     static void
182     WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
183     {
184     	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
185     }
186     
187     static u_char
188     ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
189     {
190     	return(readreg(cs->hw.diva.hscx_adr,
191     		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0)));
192     }
193     
194     static void
195     WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
196     {
197     	writereg(cs->hw.diva.hscx_adr,
198     		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value);
199     }
200     
201     static u_char
202     MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
203     {
204     	return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80));
205     }
206     
207     static void
208     MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
209     {
210     	memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
211     }
212     
213     static void
214     MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
215     {
216     	while(size--)
217     		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
218     }
219     
220     static void
221     MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
222     {
223     	while(size--)
224     		memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
225     }
226     
227     static u_char
228     MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
229     {
230     	return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)));
231     }
232     
233     static void
234     MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
235     {
236     	memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
237     }
238     
239     /*
240      * fast interrupt HSCX stuff goes here
241      */
242     
243     #define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \
244     		cs->hw.diva.hscx, reg + (nr ? 0x40 : 0))
245     #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \
246                     cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data)
247     
248     #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \
249     		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
250     
251     #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \
252     		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
253     
254     #include "hscx_irq.c"
255     
256     static void
257     diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
258     {
259     	struct IsdnCardState *cs = dev_id;
260     	u_char val, sval;
261     	int cnt=5;
262     
263     	if (!cs) {
264     		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
265     		return;
266     	}
267     	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
268     		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
269     		if (val)
270     			hscx_int_main(cs, val);
271     		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
272     		if (val)
273     			isac_interrupt(cs, val);
274     		cnt--;
275     	}
276     	if (!cnt)
277     		printk(KERN_WARNING "Diva: IRQ LOOP\n");
278     	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
279     	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
280     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
281     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
282     	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
283     	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
284     }
285     
286     static void
287     diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
288     {
289     	struct IsdnCardState *cs = dev_id;
290     	u_char ista,val;
291     	int icnt=5;
292     
293     	if (!cs) {
294     		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
295     		return;
296     	}
297     	ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
298     Start_IPACISA:
299     	if (cs->debug & L1_DEB_IPAC)
300     		debugl1(cs, "IPAC ISTA %02X", ista);
301     	if (ista & 0x0f) {
302     		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
303     		if (ista & 0x01)
304     			val |= 0x01;
305     		if (ista & 0x04)
306     			val |= 0x02;
307     		if (ista & 0x08)
308     			val |= 0x04;
309     		if (val)
310     			hscx_int_main(cs, val);
311     	}
312     	if (ista & 0x20) {
313     		val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
314     		if (val) {
315     			isac_interrupt(cs, val);
316     		}
317     	}
318     	if (ista & 0x10) {
319     		val = 0x01;
320     		isac_interrupt(cs, val);
321     	}
322     	ista  = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
323     	if ((ista & 0x3f) && icnt) {
324     		icnt--;
325     		goto Start_IPACISA;
326     	}
327     	if (!icnt)
328     		printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
329     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
330     	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
331     }
332     
333     static inline void
334     MemwaitforCEC(struct IsdnCardState *cs, int hscx)
335     {
336     	int to = 50;
337     
338     	while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
339     		udelay(1);
340     		to--;
341     	}
342     	if (!to)
343     		printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
344     }
345     
346     
347     static inline void
348     MemwaitforXFW(struct IsdnCardState *cs, int hscx)
349     {
350     	int to = 50;
351     
352     	while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
353     		udelay(1);
354     		to--;
355     	}
356     	if (!to)
357     		printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
358     }
359     
360     static inline void
361     MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
362     {
363     	long flags;
364     
365     	save_flags(flags);
366     	cli();
367     	MemwaitforCEC(cs, hscx);
368     	MemWriteHSCX(cs, hscx, HSCX_CMDR, data);
369     	restore_flags(flags);
370     }
371     
372     static void
373     Memhscx_empty_fifo(struct BCState *bcs, int count)
374     {
375     	u_char *ptr;
376     	struct IsdnCardState *cs = bcs->cs;
377     	long flags;
378     	int cnt;
379     
380     	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
381     		debugl1(cs, "hscx_empty_fifo");
382     
383     	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
384     		if (cs->debug & L1_DEB_WARN)
385     			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
386     		MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
387     		bcs->hw.hscx.rcvidx = 0;
388     		return;
389     	}
390     	save_flags(flags);
391     	cli();
392     	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
393     	cnt = count;
394     	while (cnt--)
395     		*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
396     	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
397     	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
398     	bcs->hw.hscx.rcvidx += count;
399     	restore_flags(flags);
400     	if (cs->debug & L1_DEB_HSCX_FIFO) {
401     		char *t = bcs->blog;
402     
403     		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
404     			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
405     		QuickHex(t, ptr, count);
406     		debugl1(cs, bcs->blog);
407     	}
408     }
409     
410     static void
411     Memhscx_fill_fifo(struct BCState *bcs)
412     {
413     	struct IsdnCardState *cs = bcs->cs;
414     	int more, count, cnt;
415     	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
416     	u_char *ptr,*p;
417     	long flags;
418     
419     
420     	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
421     		debugl1(cs, "hscx_fill_fifo");
422     
423     	if (!bcs->tx_skb)
424     		return;
425     	if (bcs->tx_skb->len <= 0)
426     		return;
427     
428     	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
429     	if (bcs->tx_skb->len > fifo_size) {
430     		more = !0;
431     		count = fifo_size;
432     	} else
433     		count = bcs->tx_skb->len;
434     	cnt = count;
435     	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
436     	save_flags(flags);
437     	cli();
438     	p = ptr = bcs->tx_skb->data;
439     	skb_pull(bcs->tx_skb, count);
440     	bcs->tx_cnt -= count;
441     	bcs->hw.hscx.count += count;
442     	while(cnt--)
443     		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
444     			*p++);
445     	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
446     	restore_flags(flags);
447     	if (cs->debug & L1_DEB_HSCX_FIFO) {
448     		char *t = bcs->blog;
449     
450     		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
451     			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
452     		QuickHex(t, ptr, count);
453     		debugl1(cs, bcs->blog);
454     	}
455     }
456     
457     static inline void
458     Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
459     {
460     	u_char r;
461     	struct BCState *bcs = cs->bcs + hscx;
462     	struct sk_buff *skb;
463     	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
464     	int count;
465     
466     	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
467     		return;
468     
469     	if (val & 0x80) {	/* RME */
470     		r = MemReadHSCX(cs, hscx, HSCX_RSTA);
471     		if ((r & 0xf0) != 0xa0) {
472     			if (!(r & 0x80))
473     				if (cs->debug & L1_DEB_WARN)
474     					debugl1(cs, "HSCX invalid frame");
475     			if ((r & 0x40) && bcs->mode)
476     				if (cs->debug & L1_DEB_WARN)
477     					debugl1(cs, "HSCX RDO mode=%d",
478     						bcs->mode);
479     			if (!(r & 0x20))
480     				if (cs->debug & L1_DEB_WARN)
481     					debugl1(cs, "HSCX CRC error");
482     			MemWriteHSCXCMDR(cs, hscx, 0x80);
483     		} else {
484     			count = MemReadHSCX(cs, hscx, HSCX_RBCL) & (
485     				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
486     			if (count == 0)
487     				count = fifo_size;
488     			Memhscx_empty_fifo(bcs, count);
489     			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
490     				if (cs->debug & L1_DEB_HSCX_FIFO)
491     					debugl1(cs, "HX Frame %d", count);
492     				if (!(skb = dev_alloc_skb(count)))
493     					printk(KERN_WARNING "HSCX: receive out of memory\n");
494     				else {
495     					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
496     					skb_queue_tail(&bcs->rqueue, skb);
497     				}
498     			}
499     		}
500     		bcs->hw.hscx.rcvidx = 0;
501     		hscx_sched_event(bcs, B_RCVBUFREADY);
502     	}
503     	if (val & 0x40) {	/* RPF */
504     		Memhscx_empty_fifo(bcs, fifo_size);
505     		if (bcs->mode == L1_MODE_TRANS) {
506     			/* receive audio data */
507     			if (!(skb = dev_alloc_skb(fifo_size)))
508     				printk(KERN_WARNING "HiSax: receive out of memory\n");
509     			else {
510     				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
511     				skb_queue_tail(&bcs->rqueue, skb);
512     			}
513     			bcs->hw.hscx.rcvidx = 0;
514     			hscx_sched_event(bcs, B_RCVBUFREADY);
515     		}
516     	}
517     	if (val & 0x10) {	/* XPR */
518     		if (bcs->tx_skb) {
519     			if (bcs->tx_skb->len) {
520     				Memhscx_fill_fifo(bcs);
521     				return;
522     			} else {
523     				if (bcs->st->lli.l1writewakeup &&
524     					(PACKET_NOACK != bcs->tx_skb->pkt_type))
525     					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
526     				dev_kfree_skb_irq(bcs->tx_skb);
527     				bcs->hw.hscx.count = 0; 
528     				bcs->tx_skb = NULL;
529     			}
530     		}
531     		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
532     			bcs->hw.hscx.count = 0;
533     			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
534     			Memhscx_fill_fifo(bcs);
535     		} else {
536     			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
537     			hscx_sched_event(bcs, B_XMTBUFREADY);
538     		}
539     	}
540     }
541     
542     static inline void
543     Memhscx_int_main(struct IsdnCardState *cs, u_char val)
544     {
545     
546     	u_char exval;
547     	struct BCState *bcs;
548     
549     	if (val & 0x01) {
550     		bcs = cs->bcs + 1;
551     		exval = MemReadHSCX(cs, 1, HSCX_EXIR);
552     		if (exval & 0x40) {
553     			if (bcs->mode == 1)
554     				Memhscx_fill_fifo(bcs);
555     			else {
556     				/* Here we lost an TX interrupt, so
557     				   * restart transmitting the whole frame.
558     				 */
559     				if (bcs->tx_skb) {
560     					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
561     					bcs->tx_cnt += bcs->hw.hscx.count;
562     					bcs->hw.hscx.count = 0;
563     				}
564     				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
565     				if (cs->debug & L1_DEB_WARN)
566     					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
567     			}
568     		} else if (cs->debug & L1_DEB_HSCX)
569     			debugl1(cs, "HSCX B EXIR %x", exval);
570     	}
571     	if (val & 0xf8) {
572     		if (cs->debug & L1_DEB_HSCX)
573     			debugl1(cs, "HSCX B interrupt %x", val);
574     		Memhscx_interrupt(cs, val, 1);
575     	}
576     	if (val & 0x02) {
577     		bcs = cs->bcs;
578     		exval = MemReadHSCX(cs, 0, HSCX_EXIR);
579     		if (exval & 0x40) {
580     			if (bcs->mode == L1_MODE_TRANS)
581     				Memhscx_fill_fifo(bcs);
582     			else {
583     				/* Here we lost an TX interrupt, so
584     				   * restart transmitting the whole frame.
585     				 */
586     				if (bcs->tx_skb) {
587     					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
588     					bcs->tx_cnt += bcs->hw.hscx.count;
589     					bcs->hw.hscx.count = 0;
590     				}
591     				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
592     				if (cs->debug & L1_DEB_WARN)
593     					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
594     			}
595     		} else if (cs->debug & L1_DEB_HSCX)
596     			debugl1(cs, "HSCX A EXIR %x", exval);
597     	}
598     	if (val & 0x04) {
599     		exval = MemReadHSCX(cs, 0, HSCX_ISTA);
600     		if (cs->debug & L1_DEB_HSCX)
601     			debugl1(cs, "HSCX A interrupt %x", exval);
602     		Memhscx_interrupt(cs, exval, 0);
603     	}
604     }
605     
606     static void
607     diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
608     {
609     	struct IsdnCardState *cs = dev_id;
610     	u_char ista,val;
611     	int icnt=5;
612     	u_char *cfg;
613     
614     	if (!cs) {
615     		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
616     		return;
617     	}
618     	cfg = (u_char *) cs->hw.diva.pci_cfg;
619     	val = *cfg;
620     	if (!(val & PITA_INT0_STATUS))
621     		return; /* other shared IRQ */
622     	*cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
623     	ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
624     Start_IPACPCI:
625     	if (cs->debug & L1_DEB_IPAC)
626     		debugl1(cs, "IPAC ISTA %02X", ista);
627     	if (ista & 0x0f) {
628     		val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
629     		if (ista & 0x01)
630     			val |= 0x01;
631     		if (ista & 0x04)
632     			val |= 0x02;
633     		if (ista & 0x08)
634     			val |= 0x04;
635     		if (val)
636     			Memhscx_int_main(cs, val);
637     	}
638     	if (ista & 0x20) {
639     		val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
640     		if (val) {
641     			isac_interrupt(cs, val);
642     		}
643     	}
644     	if (ista & 0x10) {
645     		val = 0x01;
646     		isac_interrupt(cs, val);
647     	}
648     	ista  = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
649     	if ((ista & 0x3f) && icnt) {
650     		icnt--;
651     		goto Start_IPACPCI;
652     	}
653     	if (!icnt)
654     		printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
655     	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
656     	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
657     }
658     
659     void
660     release_io_diva(struct IsdnCardState *cs)
661     {
662     	int bytecnt;
663     
664     	if (cs->subtyp == DIVA_IPAC_PCI) {
665     		u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
666     
667     		*cfg = 0; /* disable INT0/1 */ 
668     		*cfg = 2; /* reset pending INT0 */
669     		iounmap((void *)cs->hw.diva.cfg_reg);
670     		iounmap((void *)cs->hw.diva.pci_cfg);
671     		return;
672     	} else if (cs->subtyp != DIVA_IPAC_ISA) {
673     		del_timer(&cs->hw.diva.tl);
674     		if (cs->hw.diva.cfg_reg)
675     			byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
676     	}
677     	if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
678     		bytecnt = 8;
679     	else
680     		bytecnt = 32;
681     	if (cs->hw.diva.cfg_reg) {
682     		release_region(cs->hw.diva.cfg_reg, bytecnt);
683     	}
684     }
685     
686     static void
687     reset_diva(struct IsdnCardState *cs)
688     {
689     	long flags;
690     
691     	save_flags(flags);
692     	sti();
693     	if (cs->subtyp == DIVA_IPAC_ISA) {
694     		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
695     		set_current_state(TASK_UNINTERRUPTIBLE);
696     		schedule_timeout((10*HZ)/1000);
697     		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
698     		set_current_state(TASK_UNINTERRUPTIBLE);
699     		schedule_timeout((10*HZ)/1000);
700     		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
701     	} else if (cs->subtyp == DIVA_IPAC_PCI) {
702     		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
703     					PITA_MISC_REG);
704     		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
705     		set_current_state(TASK_UNINTERRUPTIBLE);
706     		schedule_timeout((10*HZ)/1000);
707     		*ireg = PITA_PARA_MPX_MODE;
708     		set_current_state(TASK_UNINTERRUPTIBLE);
709     		schedule_timeout((10*HZ)/1000);
710     		memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
711     	} else { /* DIVA 2.0 */
712     		cs->hw.diva.ctrl_reg = 0;        /* Reset On */
713     		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
714     		set_current_state(TASK_UNINTERRUPTIBLE);
715     		schedule_timeout((10*HZ)/1000);
716     		cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
717     		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
718     		set_current_state(TASK_UNINTERRUPTIBLE);
719     		schedule_timeout((10*HZ)/1000);
720     		if (cs->subtyp == DIVA_ISA)
721     			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
722     		else {
723     			/* Workaround PCI9060 */
724     			byteout(cs->hw.diva.pci_cfg + 0x69, 9);
725     			cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
726     		}
727     		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
728     	}
729     	restore_flags(flags);
730     }
731     
732     #define DIVA_ASSIGN 1
733     
734     static void
735     diva_led_handler(struct IsdnCardState *cs)
736     {
737     	int blink = 0;
738     
739     	if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
740     		return;
741     	del_timer(&cs->hw.diva.tl);
742     	if (cs->hw.diva.status & DIVA_ASSIGN)
743     		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
744     			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
745     	else {
746     		cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
747     			DIVA_ISA_LED_A : DIVA_PCI_LED_A;
748     		blink = 250;
749     	}
750     	if (cs->hw.diva.status & 0xf000)
751     		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
752     			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
753     	else if (cs->hw.diva.status & 0x0f00) {
754     		cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
755     			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
756     		blink = 500;
757     	} else
758     		cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ?
759     			DIVA_ISA_LED_B : DIVA_PCI_LED_B);
760     
761     	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
762     	if (blink) {
763     		init_timer(&cs->hw.diva.tl);
764     		cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000);
765     		add_timer(&cs->hw.diva.tl);
766     	}
767     }
768     
769     static int
770     Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
771     {
772     	u_int *ireg;
773     
774     	switch (mt) {
775     		case CARD_RESET:
776     			reset_diva(cs);
777     			return(0);
778     		case CARD_RELEASE:
779     			release_io_diva(cs);
780     			return(0);
781     		case CARD_INIT:
782     			if (cs->subtyp == DIVA_IPAC_PCI) {
783     				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
784     				*ireg = PITA_INT0_ENABLE;
785     			}
786     			inithscxisac(cs, 3);
787     			return(0);
788     		case CARD_TEST:
789     			return(0);
790     		case (MDL_REMOVE | REQUEST):
791     			cs->hw.diva.status = 0;
792     			break;
793     		case (MDL_ASSIGN | REQUEST):
794     			cs->hw.diva.status |= DIVA_ASSIGN;
795     			break;
796     		case MDL_INFO_SETUP:
797     			if ((long)arg)
798     				cs->hw.diva.status |=  0x0200;
799     			else
800     				cs->hw.diva.status |=  0x0100;
801     			break;
802     		case MDL_INFO_CONN:
803     			if ((long)arg)
804     				cs->hw.diva.status |=  0x2000;
805     			else
806     				cs->hw.diva.status |=  0x1000;
807     			break;
808     		case MDL_INFO_REL:
809     			if ((long)arg) {
810     				cs->hw.diva.status &=  ~0x2000;
811     				cs->hw.diva.status &=  ~0x0200;
812     			} else {
813     				cs->hw.diva.status &=  ~0x1000;
814     				cs->hw.diva.status &=  ~0x0100;
815     			}
816     			break;
817     	}
818     	if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI))
819     		diva_led_handler(cs);
820     	return(0);
821     }
822     
823     static struct pci_dev *dev_diva __initdata = NULL;
824     static struct pci_dev *dev_diva_u __initdata = NULL;
825     static struct pci_dev *dev_diva201 __initdata = NULL;
826     
827     int __init
828     setup_diva(struct IsdnCard *card)
829     {
830     	int bytecnt;
831     	u_char val;
832     	struct IsdnCardState *cs = card->cs;
833     	char tmp[64];
834     
835     	strcpy(tmp, Diva_revision);
836     	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
837     	if (cs->typ != ISDN_CTYPE_DIEHLDIVA)
838     		return(0);
839     	cs->hw.diva.status = 0;
840     	if (card->para[1]) {
841     		cs->hw.diva.ctrl_reg = 0;
842     		cs->hw.diva.cfg_reg = card->para[1];
843     		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
844     			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
845     		printk(KERN_INFO "Diva: IPAC version %x\n", val);
846     		if ((val == 1) || (val==2)) {
847     			cs->subtyp = DIVA_IPAC_ISA;
848     			cs->hw.diva.ctrl = 0;
849     			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
850     			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
851     			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
852     			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
853     			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
854     		} else {
855     			cs->subtyp = DIVA_ISA;
856     			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
857     			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
858     			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
859     			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
860     			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
861     		}
862     		cs->irq = card->para[0];
863     		bytecnt = 8;
864     	} else {
865     #if CONFIG_PCI
866     		if (!pci_present()) {
867     			printk(KERN_ERR "Diva: no PCI bus present\n");
868     			return(0);
869     		}
870     
871     		cs->subtyp = 0;
872     		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
873     			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
874     			if (pci_enable_device(dev_diva))
875     				return(0);
876     			cs->subtyp = DIVA_PCI;
877     			cs->irq = dev_diva->irq;
878     			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
879     		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
880     			PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
881     			if (pci_enable_device(dev_diva_u))
882     				return(0);
883     			cs->subtyp = DIVA_PCI;
884     			cs->irq = dev_diva_u->irq;
885     			cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
886     		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
887     			PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
888     			if (pci_enable_device(dev_diva201))
889     				return(0);
890     			cs->subtyp = DIVA_IPAC_PCI;
891     			cs->irq = dev_diva201->irq;
892     			cs->hw.diva.pci_cfg =
893     				(ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
894     			cs->hw.diva.cfg_reg =
895     				(ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
896     		} else {
897     			printk(KERN_WARNING "Diva: No PCI card found\n");
898     			return(0);
899     		}
900     
901     		if (!cs->irq) {
902     			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
903     			return(0);
904     		}
905     
906     		if (!cs->hw.diva.cfg_reg) {
907     			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
908     			return(0);
909     		}
910     		cs->irq_flags |= SA_SHIRQ;
911     #else
912     		printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
913     		printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
914     		return (0);
915     #endif /* CONFIG_PCI */
916     		if (cs->subtyp == DIVA_IPAC_PCI) {
917     			cs->hw.diva.ctrl = 0;
918     			cs->hw.diva.isac = 0;
919     			cs->hw.diva.hscx = 0;
920     			cs->hw.diva.isac_adr = 0;
921     			cs->hw.diva.hscx_adr = 0;
922     			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
923     			bytecnt = 0;
924     		} else {
925     			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
926     			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
927     			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
928     			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
929     			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
930     			bytecnt = 32;
931     		}
932     	}
933     
934     	printk(KERN_INFO
935     		"Diva: %s card configured at %#lx IRQ %d\n",
936     		(cs->subtyp == DIVA_PCI) ? "PCI" :
937     		(cs->subtyp == DIVA_ISA) ? "ISA" : 
938     		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI",
939     		cs->hw.diva.cfg_reg, cs->irq);
940     	if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI))
941     		printk(KERN_INFO "Diva: %s PCI space at %#lx\n",
942     			(cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI",
943     			cs->hw.diva.pci_cfg);
944     	if (cs->subtyp != DIVA_IPAC_PCI) {
945     		if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
946     			printk(KERN_WARNING
947     			       "HiSax: %s config port %lx-%lx already in use\n",
948     			       CardType[card->typ],
949     			       cs->hw.diva.cfg_reg,
950     			       cs->hw.diva.cfg_reg + bytecnt);
951     			return (0);
952     		} else {
953     			request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
954     		}
955     	}
956     	reset_diva(cs);
957     	cs->BC_Read_Reg  = &ReadHSCX;
958     	cs->BC_Write_Reg = &WriteHSCX;
959     	cs->BC_Send_Data = &hscx_fill_fifo;
960     	cs->cardmsg = &Diva_card_msg;
961     	if (cs->subtyp == DIVA_IPAC_ISA) {
962     		cs->readisac  = &ReadISAC_IPAC;
963     		cs->writeisac = &WriteISAC_IPAC;
964     		cs->readisacfifo  = &ReadISACfifo_IPAC;
965     		cs->writeisacfifo = &WriteISACfifo_IPAC;
966     		cs->irq_func = &diva_irq_ipac_isa;
967     		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
968     		printk(KERN_INFO "Diva: IPAC version %x\n", val);
969     	} else if (cs->subtyp == DIVA_IPAC_PCI) {
970     		cs->readisac  = &MemReadISAC_IPAC;
971     		cs->writeisac = &MemWriteISAC_IPAC;
972     		cs->readisacfifo  = &MemReadISACfifo_IPAC;
973     		cs->writeisacfifo = &MemWriteISACfifo_IPAC;
974     		cs->BC_Read_Reg  = &MemReadHSCX;
975     		cs->BC_Write_Reg = &MemWriteHSCX;
976     		cs->BC_Send_Data = &Memhscx_fill_fifo;
977     		cs->irq_func = &diva_irq_ipac_pci;
978     		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
979     		printk(KERN_INFO "Diva: IPAC version %x\n", val);
980     	} else { /* DIVA 2.0 */
981     		cs->hw.diva.tl.function = (void *) diva_led_handler;
982     		cs->hw.diva.tl.data = (long) cs;
983     		init_timer(&cs->hw.diva.tl);
984     		cs->readisac  = &ReadISAC;
985     		cs->writeisac = &WriteISAC;
986     		cs->readisacfifo  = &ReadISACfifo;
987     		cs->writeisacfifo = &WriteISACfifo;
988     		cs->irq_func = &diva_interrupt;
989     		ISACVersion(cs, "Diva:");
990     		if (HscxVersion(cs, "Diva:")) {
991     			printk(KERN_WARNING
992     		       "Diva: wrong HSCX versions check IO address\n");
993     			release_io_diva(cs);
994     			return (0);
995     		}
996     	}
997     	return (1);
998     }
999