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