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_isic.c - global isic stuff
28 * ==============================
30 * $Id: isic.c,v 1.24 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: isic.c,v 1.23 2007/10/19 11:59:54 ad Exp $");
39 #include <sys/param.h>
40 #include <sys/ioccom.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
44 #include <sys/socket.h>
46 #include <sys/callout.h>
47 #include <sys/device.h>
50 #include <netisdn/i4b_debug.h>
51 #include <netisdn/i4b_ioctl.h>
52 #include <netisdn/i4b_trace.h>
54 #include <netisdn/i4b_l2.h>
55 #include <netisdn/i4b_l1l2.h>
56 #include <netisdn/i4b_mbuf.h>
57 #include <netisdn/i4b_global.h>
59 #include <dev/ic/isic_l1.h>
60 #include <dev/ic/ipac.h>
61 #include <dev/ic/isac.h>
62 #include <dev/ic/hscx.h>
64 isdn_link_t
*isic_ret_linktab(void*, int channel
);
65 void isic_set_link(void*, int channel
, const struct isdn_l4_driver_functions
*l4_driver
, void *l4_driver_softc
);
66 void n_connect_request(struct call_desc
*cd
);
67 void n_connect_response(struct call_desc
*cd
, int response
, int cause
);
68 void n_disconnect_request(struct call_desc
*cd
, int cause
);
69 void n_alert_request(struct call_desc
*cd
);
70 void n_mgmt_command(struct isdn_l3_driver
*drv
, int cmd
, void *parm
);
72 const struct isdn_l3_driver_functions
85 /*---------------------------------------------------------------------------*
86 * isic - device driver interrupt routine
87 *---------------------------------------------------------------------------*/
91 struct isic_softc
*sc
= arg
;
93 /* could this be an interrupt for us? */
94 if (sc
->sc_intr_valid
== ISIC_INTR_DYING
)
95 return 0; /* do not touch removed hardware */
97 if(sc
->sc_ipac
== 0) /* HSCX/ISAC interrupt routine */
99 u_char was_hscx_irq
= 0;
100 u_char was_isac_irq
= 0;
102 register u_char hscx_irq_stat
;
103 register u_char isac_irq_stat
;
107 /* get hscx irq status from hscx b ista */
109 HSCX_READ(HSCX_CH_B
, H_ISTA
) & ~HSCX_B_IMASK
;
111 /* get isac irq status */
112 isac_irq_stat
= ISAC_READ(I_ISTA
);
114 /* do as long as there are pending irqs in the chips */
115 if(!hscx_irq_stat
&& !isac_irq_stat
)
118 if(hscx_irq_stat
& (HSCX_ISTA_RME
| HSCX_ISTA_RPF
|
119 HSCX_ISTA_RSC
| HSCX_ISTA_XPR
|
120 HSCX_ISTA_TIN
| HSCX_ISTA_EXB
))
122 isic_hscx_irq(sc
, hscx_irq_stat
,
124 hscx_irq_stat
& HSCX_ISTA_EXB
);
128 if(hscx_irq_stat
& (HSCX_ISTA_ICA
| HSCX_ISTA_EXA
))
131 HSCX_READ(HSCX_CH_A
, H_ISTA
) & ~HSCX_A_IMASK
,
133 hscx_irq_stat
& HSCX_ISTA_EXA
);
140 isic_isac_irq(sc
, isac_irq_stat
);
145 HSCX_WRITE(0, H_MASK
, 0xff);
146 ISAC_WRITE(I_MASK
, 0xff);
147 HSCX_WRITE(1, H_MASK
, 0xff);
156 HSCX_WRITE(0, H_MASK
, HSCX_A_IMASK
);
157 ISAC_WRITE(I_MASK
, ISAC_IMASK
);
158 HSCX_WRITE(1, H_MASK
, HSCX_B_IMASK
);
160 return(was_hscx_irq
|| was_isac_irq
);
162 else /* IPAC interrupt routine */
164 register u_char ipac_irq_stat
;
165 register u_char was_ipac_irq
= 0;
169 /* get global irq status */
171 ipac_irq_stat
= (IPAC_READ(IPAC_ISTA
)) & 0x3f;
175 if(ipac_irq_stat
& (IPAC_ISTA_ICA
| IPAC_ISTA_EXA
))
177 /* HSCX A interrupt */
178 isic_hscx_irq(sc
, HSCX_READ(HSCX_CH_A
, H_ISTA
),
180 ipac_irq_stat
& IPAC_ISTA_EXA
);
183 if(ipac_irq_stat
& (IPAC_ISTA_ICB
| IPAC_ISTA_EXB
))
185 /* HSCX B interrupt */
186 isic_hscx_irq(sc
, HSCX_READ(HSCX_CH_B
, H_ISTA
),
188 ipac_irq_stat
& IPAC_ISTA_EXB
);
191 if(ipac_irq_stat
& IPAC_ISTA_ICD
)
193 /* ISAC interrupt, Obey ISAC-IPAC differences */
194 u_int8_t isac_ista
= ISAC_READ(I_ISTA
);
195 if (isac_ista
& 0xfe)
196 isic_isac_irq(sc
, isac_ista
& 0xfe);
197 if (isac_ista
& 0x01) /* unexpected */
198 aprint_error_dev(&sc
->sc_dev
, "unexpected ipac timer2 irq\n");
201 if(ipac_irq_stat
& IPAC_ISTA_EXD
)
203 /* ISAC EXI interrupt */
204 isic_isac_irq(sc
, ISAC_ISTA_EXI
);
208 /* do as long as there are pending irqs in the chip */
215 * This seems not to be necessary on IPACs - no idea why
216 * it is here - but due to limit range of test cards, leave
217 * it in for now, in case we have to resurrect it.
219 IPAC_WRITE(IPAC_MASK
, 0xff);
221 IPAC_WRITE(IPAC_MASK
, 0xc0);
224 return(was_ipac_irq
);
229 isic_attach_bri(struct isic_softc
*sc
, const char *cardname
, const struct isdn_layer1_isdnif_driver
*dchan_driver
)
231 struct isdn_l3_driver
* drv
;
233 drv
= isdn_attach_isdnif(device_xname(&sc
->sc_dev
), cardname
,
234 &sc
->sc_l2
, &isic_l3_driver
, NBCH_BRI
);
235 sc
->sc_l3token
= drv
;
236 sc
->sc_l2
.driver
= dchan_driver
;
237 sc
->sc_l2
.l1_token
= sc
;
239 isdn_layer2_status_ind(&sc
->sc_l2
, drv
, STI_ATTACH
, 1);
240 isdn_isdnif_ready(drv
->isdnif
);
245 isic_detach_bri(struct isic_softc
*sc
)
247 isdn_layer2_status_ind(&sc
->sc_l2
, sc
->sc_l3token
, STI_ATTACH
, 0);
248 isdn_detach_isdnif(sc
->sc_l3token
);
249 sc
->sc_l3token
= NULL
;