Import 2.1.81
[davej-history.git] / drivers / isdn / hisax / ix1_micro.c
blobbd595d0c8449f0567be0d005058e9f4752e24236
1 /* $Id: ix1_micro.c,v 1.3 1997/04/13 19:54:02 keil Exp $
3 * ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards
4 * derived from the original file teles3.c from Karsten Keil
6 * Copyright (C) 1997 Klaus-Peter Nischke (ITK AG) (for the modifications to
7 * the original file teles.c)
9 * Thanks to Jan den Ouden
10 * Fritz Elfert
11 * Beat Doebeli
13 * $Log: ix1_micro.c,v $
14 * Revision 1.3 1997/04/13 19:54:02 keil
15 * Change in IRQ check delay for SMP
17 * Revision 1.2 1997/04/06 22:54:21 keil
18 * Using SKB's
20 * Revision 1.1 1997/01/27 15:43:10 keil
21 * first version
27 For the modification done by the author the following terms and conditions
28 apply (GNU PUBLIC LICENSE)
31 This program is free software; you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation; either version 2 of the License, or
34 (at your option) any later version.
36 This program is distributed in the hope that it will be useful,
37 but WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 GNU General Public License for more details.
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
46 You may contact Klaus-Peter Nischke by email: klaus@nischke.do.eunet.de
47 or by conventional mail:
49 Klaus-Peter Nischke
50 Deusener Str. 287
51 44369 Dortmund
52 Germany
56 #define __NO_VERSION__
57 #include "siemens.h"
58 #include "hisax.h"
59 #include "teles3.h"
60 #include "isdnl1.h"
61 #include <linux/kernel_stat.h>
63 extern const char *CardType[];
64 const char *ix1_revision = "$Revision: 1.3 $";
66 #define byteout(addr,val) outb_p(val,addr)
67 #define bytein(addr) inb_p(addr)
69 #define SPECIAL_PORT_OFFSET 3
71 #define ISAC_COMMAND_OFFSET 2
72 #define ISAC_DATA_OFFSET 0
73 #define HSCX_COMMAND_OFFSET 2
74 #define HSCX_DATA_OFFSET 1
76 #define ISAC_FIFOSIZE 16
77 #define HSCX_FIFOSIZE 16
79 #define TIMEOUT 50
81 static inline u_char
82 IsacReadReg(unsigned int adr, u_char off)
84 byteout(adr + ISAC_COMMAND_OFFSET, off + 0x20);
85 return bytein(adr + ISAC_DATA_OFFSET);
88 static inline void
89 IsacWriteReg(unsigned int adr, u_char off, u_char data)
91 byteout(adr + ISAC_COMMAND_OFFSET, off + 0x20);
92 byteout(adr + ISAC_DATA_OFFSET, data);
95 #define HSCX_OFFSET(WhichHscx,offset) \
96 ( (WhichHscx) ? (offset+0x60) : (offset+0x20) )
98 static inline u_char
99 HscxReadReg(unsigned int adr, int WhichHscx, u_char off)
101 byteout(adr + HSCX_COMMAND_OFFSET, HSCX_OFFSET(WhichHscx, off));
102 return bytein(adr + HSCX_DATA_OFFSET);
105 static inline void
106 HscxWriteReg(unsigned int adr, int WhichHscx, u_char off, u_char data)
108 byteout(adr + HSCX_COMMAND_OFFSET, HSCX_OFFSET(WhichHscx, off));
109 byteout(adr + HSCX_DATA_OFFSET, data);
113 static inline void
114 IsacReadFifo(unsigned int adr, u_char * data, int size)
116 byteout(adr + ISAC_COMMAND_OFFSET, 0);
117 while (size--)
118 *data++ = bytein(adr + ISAC_DATA_OFFSET);
121 static void
122 IsacWriteFifo(unsigned int adr, u_char * data, int size)
124 byteout(adr + ISAC_COMMAND_OFFSET, 0);
125 while (size--) {
126 byteout(adr + ISAC_DATA_OFFSET, *data);
127 data++;
131 static inline void
132 HscxReadFifo(unsigned int adr, int WhichHscx, u_char * data, int size)
134 byteout(adr + HSCX_COMMAND_OFFSET, (WhichHscx) ? 0x40 : 0x00);
135 while (size--)
136 *data++ = bytein(adr + HSCX_DATA_OFFSET);
139 static void
140 HscxWriteFifo(unsigned int adr, int WhichHscx, u_char * data, int size)
142 byteout(adr + HSCX_COMMAND_OFFSET, (WhichHscx) ? 0x40 : 0x00);
143 while (size--) {
144 byteout(adr + HSCX_DATA_OFFSET, *data);
145 data++;
149 static inline void
150 waitforCEC(int adr, int WhichHscx)
152 int to = TIMEOUT;
154 while ((HscxReadReg(adr, WhichHscx, HSCX_STAR) & 0x04) && to) {
155 udelay(1);
156 to--;
158 if (!to)
159 printk(KERN_WARNING "ix1-Micro: waitforCEC timeout\n");
163 static inline void
164 waitforXFW(int adr, int WhichHscx)
166 int to = TIMEOUT;
168 while ((!(HscxReadReg(adr, WhichHscx, HSCX_STAR) & 0x44) == 0x40) && to) {
169 udelay(1);
170 to--;
172 if (!to)
173 printk(KERN_WARNING "ix1-Micro: waitforXFW timeout\n");
176 static inline void
177 writehscxCMDR(int adr, int WhichHscx, u_char data)
179 long flags;
181 save_flags(flags);
182 cli();
183 waitforCEC(adr, WhichHscx);
184 HscxWriteReg(adr, WhichHscx, HSCX_CMDR, data);
185 restore_flags(flags);
189 * fast interrupt here
192 static void
193 hscxreport(struct IsdnCardState *sp, int hscx)
195 printk(KERN_DEBUG "HSCX %d\n", hscx);
196 printk(KERN_DEBUG "ISTA %x\n", HscxReadReg(sp->hscx[hscx], hscx, HSCX_ISTA));
197 printk(KERN_DEBUG "STAR %x\n", HscxReadReg(sp->hscx[hscx], hscx, HSCX_STAR));
198 printk(KERN_DEBUG "EXIR %x\n", HscxReadReg(sp->hscx[hscx], hscx, HSCX_EXIR));
201 void
202 ix1micro_report(struct IsdnCardState *sp)
204 printk(KERN_DEBUG "ISAC\n");
205 printk(KERN_DEBUG "ISTA %x\n", IsacReadReg(sp->isac, ISAC_ISTA));
206 printk(KERN_DEBUG "STAR %x\n", IsacReadReg(sp->isac, ISAC_STAR));
207 printk(KERN_DEBUG "EXIR %x\n", IsacReadReg(sp->isac, ISAC_EXIR));
208 hscxreport(sp, 0);
209 hscxreport(sp, 1);
213 * HSCX stuff goes here
216 static void
217 hscx_empty_fifo(struct HscxState *hsp, int count)
219 u_char *ptr;
220 struct IsdnCardState *sp = hsp->sp;
221 long flags;
223 if ((sp->debug & L1_DEB_HSCX) && !(sp->debug & L1_DEB_HSCX_FIFO))
224 debugl1(sp, "hscx_empty_fifo");
226 if (hsp->rcvidx + count > HSCX_BUFMAX) {
227 if (sp->debug & L1_DEB_WARN)
228 debugl1(sp, "hscx_empty_fifo: incoming packet too large");
229 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x80);
230 hsp->rcvidx = 0;
231 return;
233 ptr = hsp->rcvbuf + hsp->rcvidx;
234 hsp->rcvidx += count;
235 save_flags(flags);
236 cli();
237 HscxReadFifo(sp->hscx[hsp->hscx], hsp->hscx, ptr, count);
238 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x80);
239 restore_flags(flags);
240 if (sp->debug & L1_DEB_HSCX_FIFO) {
241 char tmp[128];
242 char *t = tmp;
244 t += sprintf(t, "hscx_empty_fifo %c cnt %d",
245 hsp->hscx ? 'B' : 'A', count);
246 QuickHex(t, ptr, count);
247 debugl1(sp, tmp);
251 static void
252 hscx_fill_fifo(struct HscxState *hsp)
254 struct IsdnCardState *sp = hsp->sp;
255 int more, count;
256 u_char *ptr;
257 long flags;
259 if ((sp->debug & L1_DEB_HSCX) && !(sp->debug & L1_DEB_HSCX_FIFO))
260 debugl1(sp, "hscx_fill_fifo");
262 if (!hsp->tx_skb)
263 return;
264 if (hsp->tx_skb->len <= 0)
265 return;
267 more = (hsp->mode == 1) ? 1 : 0;
268 if (hsp->tx_skb->len > 32) {
269 more = !0;
270 count = 32;
271 } else
272 count = hsp->tx_skb->len;
274 waitforXFW(sp->hscx[hsp->hscx], hsp->hscx);
275 save_flags(flags);
276 cli();
277 ptr = hsp->tx_skb->data;
278 skb_pull(hsp->tx_skb, count);
279 hsp->tx_cnt -= count;
280 hsp->count += count;
281 HscxWriteFifo(sp->hscx[hsp->hscx], hsp->hscx, ptr, count);
282 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, more ? 0x8 : 0xa);
283 restore_flags(flags);
284 if (sp->debug & L1_DEB_HSCX_FIFO) {
285 char tmp[128];
286 char *t = tmp;
288 t += sprintf(t, "hscx_fill_fifo %c cnt %d",
289 hsp->hscx ? 'B' : 'A', count);
290 QuickHex(t, ptr, count);
291 debugl1(sp, tmp);
295 static inline void
296 hscx_interrupt(struct IsdnCardState *sp, u_char val, u_char hscx)
298 u_char r;
299 struct HscxState *hsp = sp->hs + hscx;
300 struct sk_buff *skb;
301 int count;
302 char tmp[32];
304 if (!hsp->init)
305 return;
307 if (val & 0x80) { /* RME */
309 r = HscxReadReg(sp->hscx[hsp->hscx], hscx, HSCX_RSTA);
310 if ((r & 0xf0) != 0xa0) {
311 if (!r & 0x80)
312 if (sp->debug & L1_DEB_WARN)
313 debugl1(sp, "HSCX invalid frame");
314 if ((r & 0x40) && hsp->mode)
315 if (sp->debug & L1_DEB_WARN) {
316 sprintf(tmp, "HSCX RDO mode=%d",
317 hsp->mode);
318 debugl1(sp, tmp);
320 if (!r & 0x20)
321 if (sp->debug & L1_DEB_WARN)
322 debugl1(sp, "HSCX CRC error");
323 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x80);
324 } else {
325 count = HscxReadReg(sp->hscx[hsp->hscx], hscx, HSCX_RBCL) & 0x1f;
326 if (count == 0)
327 count = 32;
328 hscx_empty_fifo(hsp, count);
329 if ((count = hsp->rcvidx - 1) > 0) {
330 if (sp->debug & L1_DEB_HSCX_FIFO) {
331 sprintf(tmp, "HX Frame %d", count);
332 debugl1(sp, tmp);
334 if (!(skb = dev_alloc_skb(count)))
335 printk(KERN_WARNING "IX1: receive out of memory\n");
336 else {
337 memcpy(skb_put(skb, count), hsp->rcvbuf, count);
338 skb_queue_tail(&hsp->rqueue, skb);
342 hsp->rcvidx = 0;
343 hscx_sched_event(hsp, HSCX_RCVBUFREADY);
345 if (val & 0x40) { /* RPF */
346 hscx_empty_fifo(hsp, 32);
347 if (hsp->mode == 1) {
348 /* receive audio data */
349 if (!(skb = dev_alloc_skb(32)))
350 printk(KERN_WARNING "IX1: receive out of memory\n");
351 else {
352 memcpy(skb_put(skb, 32), hsp->rcvbuf, 32);
353 skb_queue_tail(&hsp->rqueue, skb);
355 hsp->rcvidx = 0;
356 hscx_sched_event(hsp, HSCX_RCVBUFREADY);
359 if (val & 0x10) { /* XPR */
360 if (hsp->tx_skb)
361 if (hsp->tx_skb->len) {
362 hscx_fill_fifo(hsp);
363 return;
364 } else {
365 SET_SKB_FREE(hsp->tx_skb);
366 dev_kfree_skb(hsp->tx_skb, FREE_WRITE);
367 hsp->count = 0;
368 if (hsp->st->l4.l1writewakeup)
369 hsp->st->l4.l1writewakeup(hsp->st);
370 hsp->tx_skb = NULL;
372 if ((hsp->tx_skb = skb_dequeue(&hsp->squeue))) {
373 hsp->count = 0;
374 hscx_fill_fifo(hsp);
375 } else
376 hscx_sched_event(hsp, HSCX_XMTBUFREADY);
381 * ISAC stuff goes here
384 static void
385 isac_empty_fifo(struct IsdnCardState *sp, int count)
387 u_char *ptr;
388 long flags;
390 if ((sp->debug & L1_DEB_ISAC) && !(sp->debug & L1_DEB_ISAC_FIFO))
391 if (sp->debug & L1_DEB_ISAC)
392 debugl1(sp, "isac_empty_fifo");
394 if ((sp->rcvidx + count) >= MAX_DFRAME_LEN) {
395 if (sp->debug & L1_DEB_WARN) {
396 char tmp[40];
397 sprintf(tmp, "isac_empty_fifo overrun %d",
398 sp->rcvidx + count);
399 debugl1(sp, tmp);
401 IsacWriteReg(sp->isac, ISAC_CMDR, 0x80);
402 sp->rcvidx = 0;
403 return;
405 ptr = sp->rcvbuf + sp->rcvidx;
406 sp->rcvidx += count;
407 save_flags(flags);
408 cli();
409 IsacReadFifo(sp->isac, ptr, count);
410 IsacWriteReg(sp->isac, ISAC_CMDR, 0x80);
411 restore_flags(flags);
412 if (sp->debug & L1_DEB_ISAC_FIFO) {
413 char tmp[128];
414 char *t = tmp;
416 t += sprintf(t, "isac_empty_fifo cnt %d", count);
417 QuickHex(t, ptr, count);
418 debugl1(sp, tmp);
422 static void
423 isac_fill_fifo(struct IsdnCardState *sp)
425 int count, more;
426 u_char *ptr;
427 long flags;
429 if ((sp->debug & L1_DEB_ISAC) && !(sp->debug & L1_DEB_ISAC_FIFO))
430 debugl1(sp, "isac_fill_fifo");
432 if (!sp->tx_skb)
433 return;
435 count = sp->tx_skb->len;
436 if (count <= 0)
437 return;
439 more = 0;
440 if (count > 32) {
441 more = !0;
442 count = 32;
444 save_flags(flags);
445 cli();
446 ptr = sp->tx_skb->data;
447 skb_pull(sp->tx_skb, count);
448 sp->tx_cnt += count;
449 IsacWriteFifo(sp->isac, ptr, count);
450 IsacWriteReg(sp->isac, ISAC_CMDR, more ? 0x8 : 0xa);
451 restore_flags(flags);
452 if (sp->debug & L1_DEB_ISAC_FIFO) {
453 char tmp[128];
454 char *t = tmp;
456 t += sprintf(t, "isac_fill_fifo cnt %d", count);
457 QuickHex(t, ptr, count);
458 debugl1(sp, tmp);
462 static void
463 ph_command(struct IsdnCardState *sp, unsigned int command)
465 if (sp->debug & L1_DEB_ISAC) {
466 char tmp[32];
467 sprintf(tmp, "ph_command %d", command);
468 debugl1(sp, tmp);
470 IsacWriteReg(sp->isac, ISAC_CIX0, (command << 2) | 3);
474 static inline void
475 isac_interrupt(struct IsdnCardState *sp, u_char val)
477 u_char exval;
478 struct sk_buff *skb;
479 unsigned int count;
480 char tmp[32];
482 if (sp->debug & L1_DEB_ISAC) {
483 sprintf(tmp, "ISAC interrupt %x", val);
484 debugl1(sp, tmp);
486 if (val & 0x80) { /* RME */
487 exval = IsacReadReg(sp->isac, ISAC_RSTA);
488 if ((exval & 0x70) != 0x20) {
489 if (exval & 0x40)
490 if (sp->debug & L1_DEB_WARN)
491 debugl1(sp, "ISAC RDO");
492 if (!exval & 0x20)
493 if (sp->debug & L1_DEB_WARN)
494 debugl1(sp, "ISAC CRC error");
495 IsacWriteReg(sp->isac, ISAC_CMDR, 0x80);
496 } else {
497 count = IsacReadReg(sp->isac, ISAC_RBCL) & 0x1f;
498 if (count == 0)
499 count = 32;
500 isac_empty_fifo(sp, count);
501 if ((count = sp->rcvidx) > 0) {
502 sp->rcvidx = 0;
503 if (!(skb = alloc_skb(count, GFP_ATOMIC)))
504 printk(KERN_WARNING "IX1: D receive out of memory\n");
505 else {
506 memcpy(skb_put(skb, count), sp->rcvbuf, count);
507 skb_queue_tail(&sp->rq, skb);
511 sp->rcvidx = 0;
512 isac_sched_event(sp, ISAC_RCVBUFREADY);
514 if (val & 0x40) { /* RPF */
515 isac_empty_fifo(sp, 32);
517 if (val & 0x20) { /* RSC */
518 /* never */
519 if (sp->debug & L1_DEB_WARN)
520 debugl1(sp, "ISAC RSC interrupt");
522 if (val & 0x10) { /* XPR */
523 if (sp->tx_skb)
524 if (sp->tx_skb->len) {
525 isac_fill_fifo(sp);
526 goto afterXPR;
527 } else {
528 SET_SKB_FREE(sp->tx_skb);
529 dev_kfree_skb(sp->tx_skb, FREE_WRITE);
530 sp->tx_cnt = 0;
531 sp->tx_skb = NULL;
533 if ((sp->tx_skb = skb_dequeue(&sp->sq))) {
534 sp->tx_cnt = 0;
535 isac_fill_fifo(sp);
536 } else
537 isac_sched_event(sp, ISAC_XMTBUFREADY);
539 afterXPR:
540 if (val & 0x04) { /* CISQ */
541 sp->ph_state = (IsacReadReg(sp->isac, ISAC_CIX0) >> 2)
542 & 0xf;
543 if (sp->debug & L1_DEB_ISAC) {
544 sprintf(tmp, "l1state %d", sp->ph_state);
545 debugl1(sp, tmp);
547 isac_new_ph(sp);
549 if (val & 0x02) { /* SIN */
550 /* never */
551 if (sp->debug & L1_DEB_WARN)
552 debugl1(sp, "ISAC SIN interrupt");
554 if (val & 0x01) { /* EXI */
555 exval = IsacReadReg(sp->isac, ISAC_EXIR);
556 if (sp->debug & L1_DEB_WARN) {
557 sprintf(tmp, "ISAC EXIR %02x", exval);
558 debugl1(sp, tmp);
563 static inline void
564 hscx_int_main(struct IsdnCardState *sp, u_char val)
567 u_char exval;
568 struct HscxState *hsp;
569 char tmp[32];
572 if (val & 0x01) {
573 hsp = sp->hs + 1;
574 exval = HscxReadReg(sp->hscx[1], 1, HSCX_EXIR);
575 if (exval == 0x40) {
576 if (hsp->mode == 1)
577 hscx_fill_fifo(hsp);
578 else {
579 /* Here we lost an TX interrupt, so
580 * restart transmitting the whole frame.
582 if (hsp->tx_skb) {
583 skb_push(hsp->tx_skb, hsp->count);
584 hsp->tx_cnt += hsp->count;
585 hsp->count = 0;
587 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x01);
588 if (sp->debug & L1_DEB_WARN) {
589 sprintf(tmp, "HSCX B EXIR %x Lost TX", exval);
590 debugl1(sp, tmp);
593 } else if (sp->debug & L1_DEB_HSCX) {
594 sprintf(tmp, "HSCX B EXIR %x", exval);
595 debugl1(sp, tmp);
598 if (val & 0xf8) {
599 if (sp->debug & L1_DEB_HSCX) {
600 sprintf(tmp, "HSCX B interrupt %x", val);
601 debugl1(sp, tmp);
603 hscx_interrupt(sp, val, 1);
605 if (val & 0x02) {
606 hsp = sp->hs;
607 exval = HscxReadReg(sp->hscx[0], 0, HSCX_EXIR);
608 if (exval == 0x40) {
609 if (hsp->mode == 1)
610 hscx_fill_fifo(hsp);
611 else {
612 /* Here we lost an TX interrupt, so
613 * restart transmitting the whole frame.
615 if (hsp->tx_skb) {
616 skb_push(hsp->tx_skb, hsp->count);
617 hsp->tx_cnt += hsp->count;
618 hsp->count = 0;
620 writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x01);
621 if (sp->debug & L1_DEB_WARN) {
622 sprintf(tmp, "HSCX A EXIR %x Lost TX", exval);
623 debugl1(sp, tmp);
626 } else if (sp->debug & L1_DEB_HSCX) {
627 sprintf(tmp, "HSCX A EXIR %x", exval);
628 debugl1(sp, tmp);
631 if (val & 0x04) {
632 exval = HscxReadReg(sp->hscx[0], 0, HSCX_ISTA);
633 if (sp->debug & L1_DEB_HSCX) {
634 sprintf(tmp, "HSCX A interrupt %x", exval);
635 debugl1(sp, tmp);
637 hscx_interrupt(sp, exval, 0);
641 static void
642 ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
644 struct IsdnCardState *sp;
645 u_char val, stat = 0;
647 sp = (struct IsdnCardState *) dev_id;
649 if (!sp) {
650 printk(KERN_WARNING "Teles: Spurious interrupt!\n");
651 return;
653 val = HscxReadReg(sp->hscx[1], 1, HSCX_ISTA);
654 Start_HSCX:
655 if (val) {
656 hscx_int_main(sp, val);
657 stat |= 1;
659 val = IsacReadReg(sp->isac, ISAC_ISTA);
660 Start_ISAC:
661 if (val) {
662 isac_interrupt(sp, val);
663 stat |= 2;
665 val = HscxReadReg(sp->hscx[1], 1, HSCX_ISTA);
666 if (val) {
667 if (sp->debug & L1_DEB_HSCX)
668 debugl1(sp, "HSCX IntStat after IntRoutine");
669 goto Start_HSCX;
671 val = IsacReadReg(sp->isac, ISAC_ISTA);
672 if (val) {
673 if (sp->debug & L1_DEB_ISAC)
674 debugl1(sp, "ISAC IntStat after IntRoutine");
675 goto Start_ISAC;
677 if (stat & 1) {
678 HscxWriteReg(sp->hscx[0], 0, HSCX_MASK, 0xFF);
679 HscxWriteReg(sp->hscx[1], 1, HSCX_MASK, 0xFF);
680 HscxWriteReg(sp->hscx[0], 0, HSCX_MASK, 0x0);
681 HscxWriteReg(sp->hscx[1], 1, HSCX_MASK, 0x0);
683 if (stat & 2) {
684 IsacWriteReg(sp->isac, ISAC_MASK, 0xFF);
685 IsacWriteReg(sp->isac, ISAC_MASK, 0x0);
690 static void
691 initisac(struct IsdnCardState *sp)
693 unsigned int adr = sp->isac;
695 /* 16.3 IOM 2 Mode */
696 IsacWriteReg(adr, ISAC_MASK, 0xff);
697 IsacWriteReg(adr, ISAC_ADF2, 0x80);
698 IsacWriteReg(adr, ISAC_SQXR, 0x2f);
699 IsacWriteReg(adr, ISAC_SPCR, 0x0);
700 IsacWriteReg(adr, ISAC_ADF1, 0x2);
701 IsacWriteReg(adr, ISAC_STCR, 0x70);
702 IsacWriteReg(adr, ISAC_MODE, 0xc9);
703 IsacWriteReg(adr, ISAC_TIMR, 0x0);
704 IsacWriteReg(adr, ISAC_ADF1, 0x0);
705 IsacWriteReg(adr, ISAC_CMDR, 0x41);
706 IsacWriteReg(adr, ISAC_CIX0, (1 << 2) | 3);
707 IsacWriteReg(adr, ISAC_MASK, 0xff);
708 IsacWriteReg(adr, ISAC_MASK, 0x0);
711 static void
712 modehscx(struct HscxState *hs, int mode, int ichan)
714 struct IsdnCardState *sp = hs->sp;
715 int hscx = hs->hscx;
717 if (sp->debug & L1_DEB_HSCX) {
718 char tmp[40];
719 sprintf(tmp, "hscx %c mode %d ichan %d",
720 'A' + hscx, mode, ichan);
721 debugl1(sp, tmp);
723 hs->mode = mode;
724 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR1, 0x85);
725 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XAD1, 0xFF);
726 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XAD2, 0xFF);
727 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RAH2, 0xFF);
728 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XBCH, 0x0);
729 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RLCR, 0x0);
731 switch (mode) {
732 case 0:
733 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR2, 0x30);
734 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAX, 0xff);
735 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAR, 0xff);
736 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XCCR, 7);
737 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RCCR, 7);
738 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_MODE, 0x84);
739 break;
740 case 1:
741 if (ichan == 0) {
742 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR2, 0x30);
743 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAX, 0x2f);
744 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAR, 0x2f);
745 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XCCR, 7);
746 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RCCR, 7);
747 } else {
748 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR2, 0x30);
749 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAX, 0x3);
750 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAR, 0x3);
751 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XCCR, 7);
752 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RCCR, 7);
754 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_MODE, 0xe4);
755 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CMDR, 0x41);
756 break;
757 case 2:
758 if (ichan == 0) {
759 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR2, 0x30);
760 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAX, 0x2f);
761 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAR, 0x2f);
762 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XCCR, 7);
763 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RCCR, 7);
764 } else {
765 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CCR2, 0x30);
766 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAX, 0x3);
767 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_TSAR, 0x3);
768 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_XCCR, 7);
769 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_RCCR, 7);
771 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_MODE, 0x8c);
772 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_CMDR, 0x41);
773 break;
775 HscxWriteReg(sp->hscx[hscx], hscx, HSCX_ISTA, 0x00);
778 void
779 release_io_ix1micro(struct IsdnCard *card)
781 if (card->sp->cfg_reg)
782 release_region(card->sp->cfg_reg, 4);
785 static void
786 clear_pending_ints(struct IsdnCardState *sp)
788 int val;
789 char tmp[64];
791 val = HscxReadReg(sp->hscx[1], 1, HSCX_ISTA);
792 sprintf(tmp, "HSCX B ISTA %x", val);
793 debugl1(sp, tmp);
794 if (val & 0x01) {
795 val = HscxReadReg(sp->hscx[1], 1, HSCX_EXIR);
796 sprintf(tmp, "HSCX B EXIR %x", val);
797 debugl1(sp, tmp);
798 } else if (val & 0x02) {
799 val = HscxReadReg(sp->hscx[0], 0, HSCX_EXIR);
800 sprintf(tmp, "HSCX A EXIR %x", val);
801 debugl1(sp, tmp);
803 val = HscxReadReg(sp->hscx[0], 0, HSCX_ISTA);
804 sprintf(tmp, "HSCX A ISTA %x", val);
805 debugl1(sp, tmp);
806 val = HscxReadReg(sp->hscx[1], 1, HSCX_STAR);
807 sprintf(tmp, "HSCX B STAR %x", val);
808 debugl1(sp, tmp);
809 val = HscxReadReg(sp->hscx[0], 0, HSCX_STAR);
810 sprintf(tmp, "HSCX A STAR %x", val);
811 debugl1(sp, tmp);
812 val = IsacReadReg(sp->isac, ISAC_STAR);
813 sprintf(tmp, "ISAC STAR %x", val);
814 debugl1(sp, tmp);
815 val = IsacReadReg(sp->isac, ISAC_MODE);
816 sprintf(tmp, "ISAC MODE %x", val);
817 debugl1(sp, tmp);
818 val = IsacReadReg(sp->isac, ISAC_ADF2);
819 sprintf(tmp, "ISAC ADF2 %x", val);
820 debugl1(sp, tmp);
821 val = IsacReadReg(sp->isac, ISAC_ISTA);
822 sprintf(tmp, "ISAC ISTA %x", val);
823 debugl1(sp, tmp);
824 if (val & 0x01) {
825 val = IsacReadReg(sp->isac, ISAC_EXIR);
826 sprintf(tmp, "ISAC EXIR %x", val);
827 debugl1(sp, tmp);
828 } else if (val & 0x04) {
829 val = IsacReadReg(sp->isac, ISAC_CIR0);
830 sprintf(tmp, "ISAC CIR0 %x", val);
831 debugl1(sp, tmp);
833 IsacWriteReg(sp->isac, ISAC_MASK, 0);
834 IsacWriteReg(sp->isac, ISAC_CMDR, 0x41);
838 initix1micro(struct IsdnCardState *sp)
840 int ret;
841 int loop = 0;
842 char tmp[40];
844 sp->counter = kstat_irqs(sp->irq);
845 sprintf(tmp, "IRQ %d count %d", sp->irq, sp->counter);
846 debugl1(sp, tmp);
847 clear_pending_ints(sp);
848 ret = get_irq(sp->cardnr, &ix1micro_interrupt);
849 if (ret) {
850 initisac(sp);
851 sp->modehscx(sp->hs, 0, 0);
852 sp->modehscx(sp->hs + 1, 0, 0);
853 while (loop++ < 10) {
854 /* At least 1-3 irqs must happen
855 * (one from HSCX A, one from HSCX B, 3rd from ISAC)
857 if (kstat_irqs(sp->irq) > sp->counter)
858 break;
859 current->state = TASK_INTERRUPTIBLE;
860 current->timeout = jiffies + 1;
861 schedule();
863 sprintf(tmp, "IRQ %d count %d", sp->irq,
864 kstat_irqs(sp->irq));
865 debugl1(sp, tmp);
866 if (kstat_irqs(sp->irq) == sp->counter) {
867 printk(KERN_WARNING
868 "ix1-Micro: IRQ(%d) getting no interrupts during init\n",
869 sp->irq);
870 free_irq(sp->irq, sp);
871 return (0);
874 return (ret);
878 setup_ix1micro(struct IsdnCard *card)
880 u_char val, verA, verB;
881 struct IsdnCardState *sp = card->sp;
882 long flags;
883 char tmp[64];
885 strcpy(tmp, ix1_revision);
886 printk(KERN_NOTICE "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
887 if (sp->typ != ISDN_CTYPE_IX1MICROR2)
888 return (0);
890 /* IO-Ports */
891 sp->isac = sp->hscx[0] = sp->hscx[1] = sp->cfg_reg = card->para[1];
892 sp->irq = card->para[0];
893 if (sp->cfg_reg) {
894 if (check_region((sp->cfg_reg), 4)) {
895 printk(KERN_WARNING
896 "HiSax: %s config port %x-%x already in use\n",
897 CardType[card->typ],
898 sp->cfg_reg,
899 sp->cfg_reg + 4);
900 return (0);
901 } else
902 request_region(sp->cfg_reg, 4, "ix1micro cfg");
904 /* reset isac */
905 save_flags(flags);
906 val = 3 * (HZ / 10) + 1;
907 sti();
908 while (val--) {
909 byteout(sp->cfg_reg + SPECIAL_PORT_OFFSET, 1);
910 HZDELAY(1); /* wait >=10 ms */
912 byteout(sp->cfg_reg + SPECIAL_PORT_OFFSET, 0);
913 restore_flags(flags);
915 printk(KERN_NOTICE
916 "HiSax: %s config irq:%d io:0x%x\n",
917 CardType[sp->typ], sp->irq,
918 sp->cfg_reg);
919 verA = HscxReadReg(sp->hscx[0], 0, HSCX_VSTR) & 0xf;
920 verB = HscxReadReg(sp->hscx[1], 1, HSCX_VSTR) & 0xf;
921 printk(KERN_INFO "ix1-Micro: HSCX version A: %s B: %s\n",
922 HscxVersion(verA), HscxVersion(verB));
923 val = IsacReadReg(sp->isac, ISAC_RBCH);
924 printk(KERN_INFO "ix1-Micro: ISAC %s\n",
925 ISACVersion(val));
926 if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf)) {
927 printk(KERN_WARNING
928 "ix1-Micro: wrong HSCX versions check IO address\n");
929 release_io_ix1micro(card);
930 return (0);
932 sp->modehscx = &modehscx;
933 sp->ph_command = &ph_command;
934 sp->hscx_fill_fifo = &hscx_fill_fifo;
935 sp->isac_fill_fifo = &isac_fill_fifo;
936 return (1);