2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_isac.c - i4b siemens isdn chipset driver ISAC handler
28 * ---------------------------------------------------------
30 * $Id: isac.c,v 1.22 2008/04/08 12:07:26 cegger Exp $
32 * last edit-date: [Fri Jan 5 11:36:10 2001]
34 *---------------------------------------------------------------------------*/
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isac.c,v 1.21 2007/10/19 11:59:54 ad Exp $");
42 #include <sys/param.h>
43 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
44 #include <sys/ioccom.h>
46 #include <sys/ioctl.h>
48 #include <sys/kernel.h>
49 #include <sys/systm.h>
51 #include <machine/stdarg.h>
54 #include <machine/clock.h>
55 #include <i386/isa/isa_device.h>
60 #include <sys/device.h>
63 #include <sys/socket.h>
66 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
67 #include <sys/callout.h>
71 #include <machine/i4b_debug.h>
72 #include <machine/i4b_ioctl.h>
73 #include <machine/i4b_trace.h>
75 #include <netisdn/i4b_debug.h>
76 #include <netisdn/i4b_ioctl.h>
77 #include <netisdn/i4b_trace.h>
80 #include <netisdn/i4b_global.h>
81 #include <netisdn/i4b_l2.h>
82 #include <netisdn/i4b_l1l2.h>
83 #include <netisdn/i4b_mbuf.h>
85 #include <dev/ic/isic_l1.h>
86 #include <dev/ic/isac.h>
87 #include <dev/ic/ipac.h>
88 #include <dev/ic/hscx.h>
90 static u_char
isic_isac_exir_hdlr(register struct isic_softc
*sc
, u_char exir
);
91 static void isic_isac_ind_hdlr(register struct isic_softc
*sc
, int ind
);
93 /*---------------------------------------------------------------------------*
94 * ISAC interrupt service routine
95 *---------------------------------------------------------------------------*/
97 isic_isac_irq(struct isic_softc
*sc
, int ista
)
99 register u_char c
= 0;
100 NDBGL1(L1_F_MSG
, "%s: ista = 0x%02x", device_xname(&sc
->sc_dev
), ista
);
102 if(ista
& ISAC_ISTA_EXI
) /* extended interrupt */
104 u_int8_t exirstat
= ISAC_READ(I_EXIR
);
105 if (sc
->sc_intr_valid
== ISIC_INTR_VALID
)
106 c
|= isic_isac_exir_hdlr(sc
, exirstat
);
109 if(ista
& ISAC_ISTA_RME
) /* receive message end */
114 /* get rx status register */
116 rsta
= ISAC_READ(I_RSTA
);
118 if((rsta
& ISAC_RSTA_MASK
) != 0x20)
122 if(!(rsta
& ISAC_RSTA_CRC
)) /* CRC error */
125 NDBGL1(L1_I_ERR
, "%s: CRC error", device_xname(&sc
->sc_dev
));
128 if(rsta
& ISAC_RSTA_RDO
) /* ReceiveDataOverflow */
131 NDBGL1(L1_I_ERR
, "%s: Data Overrun error", device_xname(&sc
->sc_dev
));
134 if(rsta
& ISAC_RSTA_RAB
) /* ReceiveABorted */
137 NDBGL1(L1_I_ERR
, "%s: Receive Aborted error", device_xname(&sc
->sc_dev
));
142 NDBGL1(L1_I_ERR
, "%s: RME unknown error, RSTA = 0x%02x!", device_xname(&sc
->sc_dev
), rsta
);
145 i4b_Dfreembuf(sc
->sc_ibuf
);
147 c
|= ISAC_CMDR_RMC
|ISAC_CMDR_RRES
;
153 ISAC_WRITE(I_CMDR
, ISAC_CMDR_RMC
|ISAC_CMDR_RRES
);
159 rest
= (ISAC_READ(I_RBCL
) & (ISAC_FIFO_LEN
-1));
162 rest
= ISAC_FIFO_LEN
;
164 if(sc
->sc_ibuf
== NULL
)
166 if((sc
->sc_ibuf
= i4b_Dgetmbuf(rest
)) != NULL
)
167 sc
->sc_ib
= sc
->sc_ibuf
->m_data
;
169 panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!");
173 if(sc
->sc_ilen
<= (MAX_DFRAME_LEN
- rest
))
175 ISAC_RDFIFO(sc
->sc_ib
, rest
);
178 sc
->sc_ibuf
->m_pkthdr
.len
=
179 sc
->sc_ibuf
->m_len
= sc
->sc_ilen
;
181 if(sc
->sc_trace
& TRACE_D_RX
)
184 memset(&hdr
, 0, sizeof hdr
);
187 hdr
.count
= ++sc
->sc_trace_dcount
;
188 isdn_layer2_trace_ind(&sc
->sc_l2
, sc
->sc_l3token
, &hdr
, sc
->sc_ibuf
->m_len
, sc
->sc_ibuf
->m_data
);
193 if(sc
->sc_intr_valid
== ISIC_INTR_VALID
&&
194 (((struct isdn_l3_driver
*)sc
->sc_l3token
)->protocol
!= PROTOCOL_D64S
))
196 isdn_layer2_data_ind(&sc
->sc_l2
, sc
->sc_l3token
, sc
->sc_ibuf
);
200 i4b_Dfreembuf(sc
->sc_ibuf
);
205 NDBGL1(L1_I_ERR
, "RME, input buffer overflow!");
206 i4b_Dfreembuf(sc
->sc_ibuf
);
207 c
|= ISAC_CMDR_RMC
|ISAC_CMDR_RRES
;
215 if(ista
& ISAC_ISTA_RPF
) /* receive fifo full */
217 if(sc
->sc_ibuf
== NULL
)
219 if((sc
->sc_ibuf
= i4b_Dgetmbuf(MAX_DFRAME_LEN
)) != NULL
)
220 sc
->sc_ib
= sc
->sc_ibuf
->m_data
;
222 panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!");
226 if(sc
->sc_ilen
<= (MAX_DFRAME_LEN
- ISAC_FIFO_LEN
))
228 ISAC_RDFIFO(sc
->sc_ib
, ISAC_FIFO_LEN
);
229 sc
->sc_ilen
+= ISAC_FIFO_LEN
;
230 sc
->sc_ib
+= ISAC_FIFO_LEN
;
235 NDBGL1(L1_I_ERR
, "RPF, input buffer overflow!");
236 i4b_Dfreembuf(sc
->sc_ibuf
);
240 c
|= ISAC_CMDR_RMC
|ISAC_CMDR_RRES
;
244 if(ista
& ISAC_ISTA_XPR
) /* transmit fifo empty (XPR bit set) */
246 if((sc
->sc_obuf2
!= NULL
) && (sc
->sc_obuf
== NULL
))
248 sc
->sc_freeflag
= sc
->sc_freeflag2
;
249 sc
->sc_obuf
= sc
->sc_obuf2
;
250 sc
->sc_op
= sc
->sc_obuf
->m_data
;
251 sc
->sc_ol
= sc
->sc_obuf
->m_len
;
254 printf("ob2=%x, op=%x, ol=%d, f=%d #",
264 printf("ob=%x, op=%x, ol=%d, f=%d #",
274 ISAC_WRFIFO(sc
->sc_op
, min(sc
->sc_ol
, ISAC_FIFO_LEN
));
276 if(sc
->sc_ol
> ISAC_FIFO_LEN
) /* length > 32 ? */
278 sc
->sc_op
+= ISAC_FIFO_LEN
; /* bufferptr+32 */
279 sc
->sc_ol
-= ISAC_FIFO_LEN
; /* length - 32 */
280 c
|= ISAC_CMDR_XTF
; /* set XTF bit */
286 i4b_Dfreembuf(sc
->sc_obuf
);
293 c
|= ISAC_CMDR_XTF
| ISAC_CMDR_XME
;
298 sc
->sc_state
&= ~ISAC_TX_ACTIVE
;
302 if(ista
& ISAC_ISTA_CISQ
) /* channel status change CISQ */
306 /* get command/indication rx register*/
308 ci
= ISAC_READ(I_CIRR
);
310 /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
312 if(ci
& ISAC_CIRR_SQC
)
313 (void) ISAC_READ(I_SQRR
);
315 /* C/I code change IRQ (flag already cleared by CIRR read) */
317 if(ci
& ISAC_CIRR_CIC0
)
318 isic_isac_ind_hdlr(sc
, (ci
>> 2) & 0xf);
323 ISAC_WRITE(I_CMDR
, c
);
328 /*---------------------------------------------------------------------------*
329 * ISAC L1 Extended IRQ handler
330 *---------------------------------------------------------------------------*/
332 isic_isac_exir_hdlr(register struct isic_softc
*sc
, u_char exir
)
336 if(exir
& ISAC_EXIR_XMR
)
338 NDBGL1(L1_I_ERR
, "EXIRQ Tx Message Repeat");
343 if(exir
& ISAC_EXIR_XDU
)
345 NDBGL1(L1_I_ERR
, "EXIRQ Tx Data Underrun");
350 if(exir
& ISAC_EXIR_PCE
)
352 NDBGL1(L1_I_ERR
, "EXIRQ Protocol Error");
355 if(exir
& ISAC_EXIR_RFO
)
357 NDBGL1(L1_I_ERR
, "EXIRQ Rx Frame Overflow");
359 c
|= ISAC_CMDR_RMC
|ISAC_CMDR_RRES
;
362 if(exir
& ISAC_EXIR_SOV
)
364 NDBGL1(L1_I_ERR
, "EXIRQ Sync Xfer Overflow");
367 if(exir
& ISAC_EXIR_MOS
)
369 NDBGL1(L1_I_ERR
, "EXIRQ Monitor Status");
372 if(exir
& ISAC_EXIR_SAW
)
374 /* cannot happen, STCR:TSF is set to 0 */
376 NDBGL1(L1_I_ERR
, "EXIRQ Subscriber Awake");
379 if(exir
& ISAC_EXIR_WOV
)
381 /* cannot happen, STCR:TSF is set to 0 */
383 NDBGL1(L1_I_ERR
, "EXIRQ Watchdog Timer Overflow");
389 /*---------------------------------------------------------------------------*
390 * ISAC L1 Indication handler
391 *---------------------------------------------------------------------------*/
393 isic_isac_ind_hdlr(register struct isic_softc
*sc
, int ind
)
400 NDBGL1(L1_I_CICO
, "rx AI8 in state %s", isic_printstate(sc
));
401 if(sc
->sc_bustyp
== BUS_TYPE_IOM2
)
402 isic_isac_l1_cmd(sc
, CMD_AR8
);
404 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_L1STAT
, LAYER_ACTIVE
);
407 case ISAC_CIRR_IAI10
:
408 NDBGL1(L1_I_CICO
, "rx AI10 in state %s", isic_printstate(sc
));
409 if(sc
->sc_bustyp
== BUS_TYPE_IOM2
)
410 isic_isac_l1_cmd(sc
, CMD_AR10
);
412 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_L1STAT
, LAYER_ACTIVE
);
416 NDBGL1(L1_I_CICO
, "rx RSY in state %s", isic_printstate(sc
));
421 NDBGL1(L1_I_CICO
, "rx PU in state %s", isic_printstate(sc
));
426 NDBGL1(L1_I_CICO
, "rx DR in state %s", isic_printstate(sc
));
427 isic_isac_l1_cmd(sc
, CMD_DIU
);
432 NDBGL1(L1_I_CICO
, "rx DID in state %s", isic_printstate(sc
));
434 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_L1STAT
, LAYER_IDLE
);
438 NDBGL1(L1_I_CICO
, "rx DIS in state %s", isic_printstate(sc
));
443 NDBGL1(L1_I_CICO
, "rx EI in state %s", isic_printstate(sc
));
444 isic_isac_l1_cmd(sc
, CMD_DIU
);
449 NDBGL1(L1_I_CICO
, "rx ARD in state %s", isic_printstate(sc
));
454 NDBGL1(L1_I_CICO
, "rx TI in state %s", isic_printstate(sc
));
459 NDBGL1(L1_I_CICO
, "rx ATI in state %s", isic_printstate(sc
));
464 NDBGL1(L1_I_CICO
, "rx SD in state %s", isic_printstate(sc
));
469 NDBGL1(L1_I_ERR
, "UNKNOWN Indication 0x%x in state %s", ind
, isic_printstate(sc
));
473 isic_next_state(sc
, event
);
476 /*---------------------------------------------------------------------------*
477 * execute a layer 1 command
478 *---------------------------------------------------------------------------*/
480 isic_isac_l1_cmd(struct isic_softc
*sc
, int command
)
484 #ifdef I4B_SMP_WORKAROUND
486 /* XXXXXXXXXXXXXXXXXXX */
489 * patch from Wolfgang Helbig:
491 * Here is a patch that makes i4b work on an SMP:
492 * The card (TELES 16.3) didn't interrupt on an SMP machine.
493 * This is a gross workaround, but anyway it works *and* provides
494 * some information as how to finally fix this problem.
497 HSCX_WRITE(0, H_MASK
, 0xff);
498 HSCX_WRITE(1, H_MASK
, 0xff);
499 ISAC_WRITE(I_MASK
, 0xff);
501 HSCX_WRITE(0, H_MASK
, HSCX_A_IMASK
);
502 HSCX_WRITE(1, H_MASK
, HSCX_B_IMASK
);
503 ISAC_WRITE(I_MASK
, ISAC_IMASK
);
505 /* XXXXXXXXXXXXXXXXXXX */
507 #endif /* I4B_SMP_WORKAROUND */
509 if(command
< 0 || command
> CMD_ILL
)
511 NDBGL1(L1_I_ERR
, "illegal cmd 0x%x in state %s", command
, isic_printstate(sc
));
515 if(sc
->sc_bustyp
== BUS_TYPE_IOM2
)
523 NDBGL1(L1_I_CICO
, "tx TIM in state %s", isic_printstate(sc
));
524 cmd
|= (ISAC_CIXR_CTIM
<< 2);
528 NDBGL1(L1_I_CICO
, "tx RS in state %s", isic_printstate(sc
));
529 cmd
|= (ISAC_CIXR_CRS
<< 2);
533 NDBGL1(L1_I_CICO
, "tx AR8 in state %s", isic_printstate(sc
));
534 cmd
|= (ISAC_CIXR_CAR8
<< 2);
538 NDBGL1(L1_I_CICO
, "tx AR10 in state %s", isic_printstate(sc
));
539 cmd
|= (ISAC_CIXR_CAR10
<< 2);
543 NDBGL1(L1_I_CICO
, "tx DIU in state %s", isic_printstate(sc
));
544 cmd
|= (ISAC_CIXR_CDIU
<< 2);
547 ISAC_WRITE(I_CIXR
, cmd
);
550 /*---------------------------------------------------------------------------*
551 * L1 ISAC initialization
552 *---------------------------------------------------------------------------*/
554 isic_isac_init(struct isic_softc
*sc
)
556 ISAC_IMASK
= 0xff; /* disable all irqs */
558 ISAC_WRITE(I_MASK
, ISAC_IMASK
);
560 if(sc
->sc_bustyp
!= BUS_TYPE_IOM2
)
562 NDBGL1(L1_I_SETUP
, "configuring for IOM-1 mode");
564 /* ADF2: Select mode IOM-1 */
565 ISAC_WRITE(I_ADF2
, 0x00);
567 /* SPCR: serial port control register:
568 * SPU - software power up = 0
569 * SAC - SIP port high Z
570 * SPM - timing mode 0
571 * TLP - test loop = 0
572 * C1C, C2C - B1 and B2 switched to/from SPa
574 ISAC_WRITE(I_SPCR
, ISAC_SPCR_C1C1
|ISAC_SPCR_C2C1
);
576 /* SQXR: S/Q channel xmit register:
577 * SQIE - S/Q IRQ enable = 0
578 * SQX1-4 - Fa bits = 1
580 ISAC_WRITE(I_SQXR
, ISAC_SQXR_SQX1
|ISAC_SQXR_SQX2
|ISAC_SQXR_SQX3
|ISAC_SQXR_SQX4
);
582 /* ADF1: additional feature reg 1:
584 * TEM - test mode = 0
585 * PFS - pre-filter = 0
586 * CFS - IOM clock/frame always active
587 * FSC1/2 - polarity of 8kHz strobe
588 * ITF - interframe fill = idle
590 ISAC_WRITE(I_ADF1
, ISAC_ADF1_FC2
); /* ADF1 */
592 /* STCR: sync transfer control reg:
593 * TSF - terminal secific functions = 0
594 * TBA - TIC bus address = 7
597 ISAC_WRITE(I_STCR
, ISAC_STCR_TBA2
|ISAC_STCR_TBA1
|ISAC_STCR_TBA0
);
601 NDBGL1(L1_I_SETUP
, "configuring for IOM-2 mode");
603 /* ADF2: Select mode IOM-2 */
604 ISAC_WRITE(I_ADF2
, ISAC_ADF2_IMS
);
606 /* SPCR: serial port control register:
607 * SPU - software power up = 0
608 * SPM - timing mode 0
609 * TLP - test loop = 0
610 * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
612 ISAC_WRITE(I_SPCR
, 0x00);
614 /* SQXR: S/Q channel xmit register:
615 * IDC - IOM direction = 0 (master)
616 * CFS - Config Select = 0 (clock always active)
617 * CI1E - C/I channel 1 IRQ enable = 0
618 * SQIE - S/Q IRQ enable = 0
619 * SQX1-4 - Fa bits = 1
621 ISAC_WRITE(I_SQXR
, ISAC_SQXR_SQX1
|ISAC_SQXR_SQX2
|ISAC_SQXR_SQX3
|ISAC_SQXR_SQX4
);
623 /* ADF1: additional feature reg 1:
625 * TEM - test mode = 0
626 * PFS - pre-filter = 0
627 * IOF - IOM i/f off = 0
628 * ITF - interframe fill = idle
630 ISAC_WRITE(I_ADF1
, 0x00);
632 /* STCR: sync transfer control reg:
633 * TSF - terminal secific functions = 0
634 * TBA - TIC bus address = 7
637 ISAC_WRITE(I_STCR
, ISAC_STCR_TBA2
|ISAC_STCR_TBA1
|ISAC_STCR_TBA0
);
641 /* MODE: Mode Register:
642 * MDSx - transparent mode 2
643 * TMD - timer mode = external
644 * RAC - Receiver enabled
645 * DIMx - digital i/f mode
647 ISAC_WRITE(I_MODE
, ISAC_MODE_MDS2
|ISAC_MODE_MDS1
|ISAC_MODE_RAC
|ISAC_MODE_DIM0
);
649 /* enabled interrupts:
650 * ===================
651 * RME - receive message end
652 * RPF - receive pool full
653 * XPR - transmit pool ready
654 * CISQ - CI or S/Q channel change
655 * EXI - extended interrupt
658 ISAC_IMASK
= ISAC_MASK_RSC
| /* auto mode only */
659 ISAC_MASK_TIN
| /* timer irq */
660 ISAC_MASK_SIN
; /* sync xfer irq */
662 ISAC_WRITE(I_MASK
, ISAC_IMASK
);
664 ISAC_WRITE(I_CMDR
, ISAC_CMDR_RRES
|ISAC_CMDR_XRES
);
670 /*---------------------------------------------------------------------------*
671 * isic_recovery - try to recover from irq lockup
672 *---------------------------------------------------------------------------*/
674 isic_recover(struct isic_softc
*sc
)
678 /* get hscx irq status from hscx b ista */
680 byte
= HSCX_READ(HSCX_CH_B
, H_ISTA
);
682 NDBGL1(L1_ERROR
, "HSCX B: ISTA = 0x%x", byte
);
684 if(byte
& HSCX_ISTA_ICA
)
685 NDBGL1(L1_ERROR
, "HSCX A: ISTA = 0x%x", (u_char
)HSCX_READ(HSCX_CH_A
, H_ISTA
));
687 if(byte
& HSCX_ISTA_EXB
)
688 NDBGL1(L1_ERROR
, "HSCX B: EXIR = 0x%x", (u_char
)HSCX_READ(HSCX_CH_B
, H_EXIR
));
690 if(byte
& HSCX_ISTA_EXA
)
691 NDBGL1(L1_ERROR
, "HSCX A: EXIR = 0x%x", (u_char
)HSCX_READ(HSCX_CH_A
, H_EXIR
));
693 /* get isac irq status */
695 byte
= ISAC_READ(I_ISTA
);
697 NDBGL1(L1_ERROR
, " ISAC: ISTA = 0x%x", byte
);
699 if(byte
& ISAC_ISTA_EXI
)
700 NDBGL1(L1_ERROR
, " ISAC: EXIR = 0x%x", (u_char
)ISAC_READ(I_EXIR
));
702 if(byte
& ISAC_ISTA_CISQ
)
704 byte
= ISAC_READ(I_CIRR
);
706 NDBGL1(L1_ERROR
, " ISAC: CISQ = 0x%x", byte
);
708 if(byte
& ISAC_CIRR_SQC
)
709 NDBGL1(L1_ERROR
, " ISAC: SQRR = 0x%x", (u_char
)ISAC_READ(I_SQRR
));
712 NDBGL1(L1_ERROR
, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK
);
713 NDBGL1(L1_ERROR
, "HSCX A: IMASK = 0x%x", HSCX_A_IMASK
);
715 HSCX_WRITE(0, H_MASK
, 0xff);
716 HSCX_WRITE(1, H_MASK
, 0xff);
718 HSCX_WRITE(0, H_MASK
, HSCX_A_IMASK
);
719 HSCX_WRITE(1, H_MASK
, HSCX_B_IMASK
);
722 NDBGL1(L1_ERROR
, " ISAC: IMASK = 0x%x", ISAC_IMASK
);
724 ISAC_WRITE(I_MASK
, 0xff);
726 ISAC_WRITE(I_MASK
, ISAC_IMASK
);