1 /* ISDN4BSD code */
2 /*
3 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *---------------------------------------------------------------------------
27 *
28 * i4b_isic.c - global isic stuff
29 * ==============================
30 *
31 * $Id: isic.c,v 1.3 2003/10/03 17:24:11 tg Stab $
32 *
33 * last edit-date: [Fri Jan 5 11:36:10 2001]
34 *
35 *---------------------------------------------------------------------------*/
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: isic.c,v 1.19 2003/01/06 13:05:10 wiz Exp $");
39
40 #include <sys/param.h>
41 #include <sys/ioccom.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <sys/socket.h>
46 #include <net/if.h>
47 #include <sys/timeout.h>
48 #include <sys/device.h>
49 #include <machine/bus.h>
50
51 #include <netisdn/i4b_debug.h>
52 #include <netisdn/i4b_ioctl.h>
53 #include <netisdn/i4b_trace.h>
54
55 #include <netisdn/i4b_l2.h>
56 #include <netisdn/i4b_l1l2.h>
57 #include <netisdn/i4b_mbuf.h>
58 #include <netisdn/i4b_global.h>
59
60 #include <dev/ic/isic_l1.h>
61 #include <dev/ic/ipac.h>
62 #include <dev/ic/isac.h>
63 #include <dev/ic/hscx.h>
64
65 isdn_link_t *isic_ret_linktab(void*, int channel);
66 void isic_set_link(void*, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc);
67 void n_connect_request(struct call_desc *cd);
68 void n_connect_response(struct call_desc *cd, int response, int cause);
69 void n_disconnect_request(struct call_desc *cd, int cause);
70 void n_alert_request(struct call_desc *cd);
71 void n_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm);
72
73 const struct isdn_l3_driver_functions
74 isic_l3_driver = {
75 isic_ret_linktab,
76 isic_set_link,
77 n_connect_request,
78 n_connect_response,
79 n_disconnect_request,
80 n_alert_request,
81 NULL,
82 NULL,
83 n_mgmt_command
84 };
85
86 /*---------------------------------------------------------------------------*
87 * isic - device driver interrupt routine
88 *---------------------------------------------------------------------------*/
89 int
isicintr(void * arg)90 isicintr(void *arg)
91 {
92 struct isic_softc *sc = arg;
93
94 /* could this be an interrupt for us? */
95 if (sc->sc_intr_valid == ISIC_INTR_DYING)
96 return 0; /* do not touch removed hardware */
97
98 if(sc->sc_ipac == 0) /* HSCX/ISAC interrupt routine */
99 {
100 u_char was_hscx_irq = 0;
101 u_char was_isac_irq = 0;
102
103 register u_char hscx_irq_stat;
104 register u_char isac_irq_stat;
105
106 for(;;)
107 {
108 /* get hscx irq status from hscx b ista */
109 hscx_irq_stat =
110 HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
111
112 /* get isac irq status */
113 isac_irq_stat = ISAC_READ(I_ISTA);
114
115 /* do as long as there are pending irqs in the chips */
116 if(!hscx_irq_stat && !isac_irq_stat)
117 break;
118
119 if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
120 HSCX_ISTA_RSC | HSCX_ISTA_XPR |
121 HSCX_ISTA_TIN | HSCX_ISTA_EXB))
122 {
123 isic_hscx_irq(sc, hscx_irq_stat,
124 HSCX_CH_B,
125 hscx_irq_stat & HSCX_ISTA_EXB);
126 was_hscx_irq = 1;
127 }
128
129 if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
130 {
131 isic_hscx_irq(sc,
132 HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
133 HSCX_CH_A,
134 hscx_irq_stat & HSCX_ISTA_EXA);
135 was_hscx_irq = 1;
136 }
137
138 if(isac_irq_stat)
139 {
140 /* isac handler */
141 isic_isac_irq(sc, isac_irq_stat);
142 was_isac_irq = 1;
143 }
144 }
145
146 HSCX_WRITE(0, H_MASK, 0xff);
147 ISAC_WRITE(I_MASK, 0xff);
148 HSCX_WRITE(1, H_MASK, 0xff);
149
150 if (sc->clearirq)
151 {
152 DELAY(80);
153 sc->clearirq(sc);
154 } else
155 DELAY(100);
156
157 HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
158 ISAC_WRITE(I_MASK, ISAC_IMASK);
159 HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
160
161 return(was_hscx_irq || was_isac_irq);
162 }
163 else /* IPAC interrupt routine */
164 {
165 register u_char ipac_irq_stat;
166 register u_char was_ipac_irq = 0;
167
168 for(;;)
169 {
170 /* get global irq status */
171
172 ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
173
174 /* check hscx a */
175
176 if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
177 {
178 /* HSCX A interrupt */
179 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
180 HSCX_CH_A,
181 ipac_irq_stat & IPAC_ISTA_EXA);
182 was_ipac_irq = 1;
183 }
184 if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
185 {
186 /* HSCX B interrupt */
187 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
188 HSCX_CH_B,
189 ipac_irq_stat & IPAC_ISTA_EXB);
190 was_ipac_irq = 1;
191 }
192 if(ipac_irq_stat & IPAC_ISTA_ICD)
193 {
194 /* ISAC interrupt, Obey ISAC-IPAC differences */
195 u_int8_t isac_ista = ISAC_READ(I_ISTA);
196 if (isac_ista & 0xfe)
197 isic_isac_irq(sc, isac_ista & 0xfe);
198 if (isac_ista & 0x01) /* unexpected */
199 printf("%s: unexpected ipac timer2 irq\n",
200 sc->sc_dev.dv_xname);
201 was_ipac_irq = 1;
202 }
203 if(ipac_irq_stat & IPAC_ISTA_EXD)
204 {
205 /* ISAC EXI interrupt */
206 isic_isac_irq(sc, ISAC_ISTA_EXI);
207 was_ipac_irq = 1;
208 }
209
210 /* do as long as there are pending irqs in the chip */
211 if(!ipac_irq_stat)
212 break;
213 }
214
215 #if 0
216 /*
217 * This seems not to be necessary on IPACs - no idea why
218 * it is here - but due to limit range of test cards, leave
219 * it in for now, in case we have to resurrect it.
220 */
221 IPAC_WRITE(IPAC_MASK, 0xff);
222 DELAY(50);
223 IPAC_WRITE(IPAC_MASK, 0xc0);
224 #endif
225
226 return(was_ipac_irq);
227 }
228 }
229
230 int
isic_attach_bri(struct isic_softc * sc,const char * cardname,const struct isdn_layer1_isdnif_driver * dchan_driver)231 isic_attach_bri(struct isic_softc *sc, const char *cardname, const struct isdn_layer1_isdnif_driver *dchan_driver)
232 {
233 struct isdn_l3_driver * drv;
234
235 drv = isdn_attach_isdnif(sc->sc_dev.dv_xname, cardname,
236 &sc->sc_l2, &isic_l3_driver, NBCH_BRI);
237 sc->sc_l3token = drv;
238 sc->sc_l2.driver = dchan_driver;
239 sc->sc_l2.l1_token = sc;
240 sc->sc_l2.drv = drv;
241 isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
242 isdn_isdnif_ready(drv->isdnif);
243 return 1;
244 }
245
246 int
isic_detach_bri(struct isic_softc * sc)247 isic_detach_bri(struct isic_softc *sc)
248 {
249 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_ATTACH, 0);
250 isdn_detach_isdnif(sc->sc_l3token);
251 sc->sc_l3token = NULL;
252 return 1;
253 }
254