FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/isic.c
1 /*
2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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
23 * SUCH DAMAGE.
24 *
25 *---------------------------------------------------------------------------
26 *
27 * i4b_isic.c - global isic stuff
28 * ==============================
29 *
30 * $Id: isic.c,v 1.21 2005/02/27 00:27:01 perry Exp $
31 *
32 * last edit-date: [Fri Jan 5 11:36:10 2001]
33 *
34 *---------------------------------------------------------------------------*/
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isic.c,v 1.21 2005/02/27 00:27:01 perry Exp $");
38
39 #include <sys/param.h>
40 #include <sys/ioccom.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/socket.h>
45 #include <net/if.h>
46 #include <sys/callout.h>
47 #include <sys/device.h>
48 #include <machine/bus.h>
49
50 #include <netisdn/i4b_debug.h>
51 #include <netisdn/i4b_ioctl.h>
52 #include <netisdn/i4b_trace.h>
53
54 #include <netisdn/i4b_l2.h>
55 #include <netisdn/i4b_l1l2.h>
56 #include <netisdn/i4b_mbuf.h>
57 #include <netisdn/i4b_global.h>
58
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>
63
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);
71
72 const struct isdn_l3_driver_functions
73 isic_l3_driver = {
74 isic_ret_linktab,
75 isic_set_link,
76 n_connect_request,
77 n_connect_response,
78 n_disconnect_request,
79 n_alert_request,
80 NULL,
81 NULL,
82 n_mgmt_command
83 };
84
85 /*---------------------------------------------------------------------------*
86 * isic - device driver interrupt routine
87 *---------------------------------------------------------------------------*/
88 int
89 isicintr(void *arg)
90 {
91 struct isic_softc *sc = arg;
92
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 */
96
97 if(sc->sc_ipac == 0) /* HSCX/ISAC interrupt routine */
98 {
99 u_char was_hscx_irq = 0;
100 u_char was_isac_irq = 0;
101
102 register u_char hscx_irq_stat;
103 register u_char isac_irq_stat;
104
105 for(;;)
106 {
107 /* get hscx irq status from hscx b ista */
108 hscx_irq_stat =
109 HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
110
111 /* get isac irq status */
112 isac_irq_stat = ISAC_READ(I_ISTA);
113
114 /* do as long as there are pending irqs in the chips */
115 if(!hscx_irq_stat && !isac_irq_stat)
116 break;
117
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))
121 {
122 isic_hscx_irq(sc, hscx_irq_stat,
123 HSCX_CH_B,
124 hscx_irq_stat & HSCX_ISTA_EXB);
125 was_hscx_irq = 1;
126 }
127
128 if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
129 {
130 isic_hscx_irq(sc,
131 HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
132 HSCX_CH_A,
133 hscx_irq_stat & HSCX_ISTA_EXA);
134 was_hscx_irq = 1;
135 }
136
137 if(isac_irq_stat)
138 {
139 /* isac handler */
140 isic_isac_irq(sc, isac_irq_stat);
141 was_isac_irq = 1;
142 }
143 }
144
145 HSCX_WRITE(0, H_MASK, 0xff);
146 ISAC_WRITE(I_MASK, 0xff);
147 HSCX_WRITE(1, H_MASK, 0xff);
148
149 if (sc->clearirq)
150 {
151 DELAY(80);
152 sc->clearirq(sc);
153 } else
154 DELAY(100);
155
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);
159
160 return(was_hscx_irq || was_isac_irq);
161 }
162 else /* IPAC interrupt routine */
163 {
164 register u_char ipac_irq_stat;
165 register u_char was_ipac_irq = 0;
166
167 for(;;)
168 {
169 /* get global irq status */
170
171 ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
172
173 /* check hscx a */
174
175 if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
176 {
177 /* HSCX A interrupt */
178 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
179 HSCX_CH_A,
180 ipac_irq_stat & IPAC_ISTA_EXA);
181 was_ipac_irq = 1;
182 }
183 if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
184 {
185 /* HSCX B interrupt */
186 isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
187 HSCX_CH_B,
188 ipac_irq_stat & IPAC_ISTA_EXB);
189 was_ipac_irq = 1;
190 }
191 if(ipac_irq_stat & IPAC_ISTA_ICD)
192 {
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 printf("%s: unexpected ipac timer2 irq\n",
199 sc->sc_dev.dv_xname);
200 was_ipac_irq = 1;
201 }
202 if(ipac_irq_stat & IPAC_ISTA_EXD)
203 {
204 /* ISAC EXI interrupt */
205 isic_isac_irq(sc, ISAC_ISTA_EXI);
206 was_ipac_irq = 1;
207 }
208
209 /* do as long as there are pending irqs in the chip */
210 if(!ipac_irq_stat)
211 break;
212 }
213
214 #if 0
215 /*
216 * This seems not to be necessary on IPACs - no idea why
217 * it is here - but due to limit range of test cards, leave
218 * it in for now, in case we have to resurrect it.
219 */
220 IPAC_WRITE(IPAC_MASK, 0xff);
221 DELAY(50);
222 IPAC_WRITE(IPAC_MASK, 0xc0);
223 #endif
224
225 return(was_ipac_irq);
226 }
227 }
228
229 int
230 isic_attach_bri(struct isic_softc *sc, const char *cardname, const struct isdn_layer1_isdnif_driver *dchan_driver)
231 {
232 struct isdn_l3_driver * drv;
233
234 drv = isdn_attach_isdnif(sc->sc_dev.dv_xname, cardname,
235 &sc->sc_l2, &isic_l3_driver, NBCH_BRI);
236 sc->sc_l3token = drv;
237 sc->sc_l2.driver = dchan_driver;
238 sc->sc_l2.l1_token = sc;
239 sc->sc_l2.drv = drv;
240 isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
241 isdn_isdnif_ready(drv->isdnif);
242 return 1;
243 }
244
245 int
246 isic_detach_bri(struct isic_softc *sc)
247 {
248 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_ATTACH, 0);
249 isdn_detach_isdnif(sc->sc_l3token);
250 sc->sc_l3token = NULL;
251 return 1;
252 }
Cache object: b6962cbf2522483aa7a959b154f63c6b
|