FreeBSD/Linux Kernel Cross Reference
sys/netisdn/i4b_l2.c
1 /* $NetBSD: i4b_l2.c,v 1.16 2003/10/03 16:38:44 pooka Exp $ */
2
3 /*
4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *---------------------------------------------------------------------------
28 *
29 * i4b_l2.c - ISDN layer 2 (Q.921)
30 * -------------------------------
31 *
32 * $Id: i4b_l2.c,v 1.16 2003/10/03 16:38:44 pooka Exp $
33 *
34 * $FreeBSD$
35 *
36 * last edit-date: [Fri Jan 5 11:33:47 2001]
37 *
38 *---------------------------------------------------------------------------*/
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: i4b_l2.c,v 1.16 2003/10/03 16:38:44 pooka Exp $");
42
43 #ifdef __FreeBSD__
44 #include "i4bq921.h"
45 #else
46 #define NI4BQ921 1
47 #endif
48 #if NI4BQ921 > 0
49
50 #include <sys/param.h>
51 #include <sys/kernel.h>
52 #include <sys/systm.h>
53 #include <sys/mbuf.h>
54 #include <sys/socket.h>
55 #include <net/if.h>
56
57 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
58 #include <sys/callout.h>
59 #endif
60
61 #ifdef __FreeBSD__
62 #include <machine/i4b_debug.h>
63 #include <machine/i4b_ioctl.h>
64 #else
65 #include <netisdn/i4b_debug.h>
66 #include <netisdn/i4b_ioctl.h>
67 #endif
68
69 #include <netisdn/i4b_l3l4.h>
70 #include <netisdn/i4b_l2.h>
71 #include <netisdn/i4b_l1l2.h>
72 #include <netisdn/i4b_isdnq931.h>
73 #include <netisdn/i4b_mbuf.h>
74 #include <netisdn/i4b_global.h>
75
76 #include <netisdn/i4b_l2.h>
77 #include <netisdn/i4b_l2fsm.h>
78
79 /* this layers debug level */
80
81 unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT;
82
83 /*---------------------------------------------------------------------------*
84 * DL_ESTABLISH_REQ from layer 3
85 *---------------------------------------------------------------------------*/
86 int i4b_dl_establish_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv)
87 {
88 NDBGL2(L2_PRIM, "isdnif %d", l2sc->drv->isdnif);
89 i4b_l1_activate(l2sc);
90 i4b_next_l2state(l2sc, drv, EV_DLESTRQ);
91 return(0);
92 }
93
94 /*---------------------------------------------------------------------------*
95 * DL_RELEASE_REQ from layer 3
96 *---------------------------------------------------------------------------*/
97 int i4b_dl_release_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv)
98 {
99 NDBGL2(L2_PRIM, "isdnif %d", l2sc->drv->isdnif);
100 i4b_next_l2state(l2sc, drv, EV_DLRELRQ);
101 return(0);
102 }
103
104 /*---------------------------------------------------------------------------*
105 * DL UNIT DATA REQUEST from Layer 3
106 *---------------------------------------------------------------------------*/
107 int i4b_dl_unit_data_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
108 {
109 #ifdef NOTDEF
110 NDBGL2(L2_PRIM, "isdnif %d", l2sc->isdnif);
111 #endif
112 return(0);
113 }
114
115 /*---------------------------------------------------------------------------*
116 * DL DATA REQUEST from Layer 3
117 *---------------------------------------------------------------------------*/
118 int i4b_dl_data_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
119 {
120 switch(l2sc->Q921_state)
121 {
122 case ST_AW_EST:
123 case ST_MULTIFR:
124 case ST_TIMREC:
125
126 if(IF_QFULL(&l2sc->i_queue))
127 {
128 NDBGL2(L2_ERROR, "i_queue full!!");
129 i4b_Dfreembuf(m);
130 }
131 else
132 {
133 int s;
134
135 s = splnet();
136 IF_ENQUEUE(&l2sc->i_queue, m);
137 splx(s);
138
139 i4b_i_frame_queued_up(l2sc);
140 }
141 break;
142
143 default:
144 NDBGL2(L2_ERROR, "isdnif %d ERROR in state [%s], freeing mbuf", l2sc->drv->isdnif, i4b_print_l2state(l2sc));
145 i4b_Dfreembuf(m);
146 break;
147 }
148 return(0);
149 }
150
151 /*---------------------------------------------------------------------------*
152 * isdn_layer2_activate_ind - link activation/deactivation indication from layer 1
153 *---------------------------------------------------------------------------*/
154 int
155 isdn_layer2_activate_ind(struct l2_softc *l2sc, struct isdn_l3_driver *drv, int event_activate)
156 {
157 if (event_activate) {
158 l2sc->ph_active = PH_ACTIVE;
159 } else {
160 l2sc->ph_active = PH_INACTIVE;
161 }
162 return(0);
163 }
164
165 /*---------------------------------------------------------------------------*
166 * i4b_l2_unit_init - place layer 2 unit into known state
167 *---------------------------------------------------------------------------*/
168 static void
169 i4b_l2_unit_init(l2_softc_t *l2sc)
170 {
171 int s;
172
173 s = splnet();
174 l2sc->Q921_state = ST_TEI_UNAS;
175 l2sc->tei_valid = TEI_INVALID;
176 l2sc->vr = 0;
177 l2sc->vs = 0;
178 l2sc->va = 0;
179 l2sc->ack_pend = 0;
180 l2sc->rej_excpt = 0;
181 l2sc->peer_busy = 0;
182 l2sc->own_busy = 0;
183 l2sc->l3initiated = 0;
184
185 l2sc->rxd_CR = 0;
186 l2sc->rxd_PF = 0;
187 l2sc->rxd_NR = 0;
188 l2sc->RC = 0;
189 l2sc->iframe_sent = 0;
190
191 l2sc->postfsmfunc = NULL;
192
193 if(l2sc->ua_num != UA_EMPTY)
194 {
195 i4b_Dfreembuf(l2sc->ua_frame);
196 l2sc->ua_num = UA_EMPTY;
197 l2sc->ua_frame = NULL;
198 }
199
200 i4b_T200_stop(l2sc);
201 i4b_T202_stop(l2sc);
202 i4b_T203_stop(l2sc);
203
204 splx(s);
205 }
206
207 /*---------------------------------------------------------------------------*
208 * isdn_layer2_status_ind - status indication upward
209 *---------------------------------------------------------------------------*/
210 int
211 isdn_layer2_status_ind(l2_softc_t *l2sc, struct isdn_l3_driver *drv, int status, int parm)
212 {
213 int s;
214 int sendup = 1;
215
216 s = splnet();
217
218 NDBGL2(L2_PRIM, "isdnif %d, status=%d, parm=%d", l2sc->drv->isdnif, status, parm);
219
220 switch(status)
221 {
222 case STI_ATTACH:
223 if (parm == 0) {
224 /* detach */
225 callout_stop(&l2sc->T200_callout);
226 callout_stop(&l2sc->T202_callout);
227 callout_stop(&l2sc->T203_callout);
228 callout_stop(&l2sc->IFQU_callout);
229 break;
230 }
231
232 l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
233 l2sc->ua_frame = NULL;
234 memset(&l2sc->stat, 0, sizeof(lapdstat_t));
235 i4b_l2_unit_init(l2sc);
236
237 /* initialize the callout handles for timeout routines */
238 callout_init(&l2sc->T200_callout);
239 callout_init(&l2sc->T202_callout);
240 callout_init(&l2sc->T203_callout);
241 callout_init(&l2sc->IFQU_callout);
242
243 break;
244
245 case STI_L1STAT: /* state of layer 1 */
246 break;
247
248 case STI_PDEACT: /* Timer 4 expired */
249 /*XXX*/ if((l2sc->Q921_state >= ST_AW_EST) &&
250 (l2sc->Q921_state <= ST_TIMREC))
251 {
252 NDBGL2(L2_ERROR, "isdnif %d, persistent deactivation!", l2sc->drv->isdnif);
253 i4b_l2_unit_init(l2sc);
254 parm = -1; /* this is passed as the new
255 * TEI to upper layers */
256 }
257 else
258 {
259 sendup = 0;
260 }
261 break;
262
263 case STI_NOL1ACC:
264 i4b_l2_unit_init(l2sc);
265 NDBGL2(L2_ERROR, "isdnif %d, cannot access S0 bus!", l2sc->drv->isdnif);
266 break;
267
268 default:
269 NDBGL2(L2_ERROR, "ERROR, isdnif %d, unknown status message!", l2sc->drv->isdnif);
270 break;
271 }
272
273 if(sendup)
274 i4b_mdl_status_ind(l2sc->drv, status, parm); /* send up to layer 3 */
275
276 splx(s);
277
278 return(0);
279 }
280
281 /*---------------------------------------------------------------------------*
282 * MDL_COMMAND_REQ from layer 3
283 *---------------------------------------------------------------------------*/
284 int i4b_mdl_command_req(struct isdn_l3_driver *drv, int command, void * parm)
285 {
286 struct l2_softc *sc = (l2_softc_t*)drv->l1_token;
287
288 NDBGL2(L2_PRIM, "isdnif %d, command=%d, parm=%p", drv->isdnif, command, parm);
289
290 switch(command)
291 {
292 case CMR_DOPEN:
293 i4b_l2_unit_init(sc);
294 /* XXX - enable interrupts */
295 break;
296 case CMR_DCLOSE:
297 /* XXX - disable interrupts */
298 break;
299 }
300
301 /* pass down to layer 1 driver */
302 if (sc->driver)
303 sc->driver->mph_command_req(sc->l1_token, command, parm);
304
305 return(0);
306 }
307
308 /*---------------------------------------------------------------------------*
309 * isdn_layer2_data_ind - process a rx'd frame got from layer 1
310 *---------------------------------------------------------------------------*/
311 int
312 isdn_layer2_data_ind(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
313 {
314 u_char *ptr = m->m_data;
315
316 if ( (*(ptr + OFF_CNTL) & 0x01) == 0 )
317 {
318 if(m->m_len < 4) /* 6 oct - 2 chksum oct */
319 {
320 l2sc->stat.err_rx_len++;
321 NDBGL2(L2_ERROR, "ERROR, I-frame < 6 octetts!");
322 i4b_Dfreembuf(m);
323 return(0);
324 }
325 i4b_rxd_i_frame(l2sc, drv, m);
326 }
327 else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 )
328 {
329 if(m->m_len < 4) /* 6 oct - 2 chksum oct */
330 {
331 l2sc->stat.err_rx_len++;
332 NDBGL2(L2_ERROR, "ERROR, S-frame < 6 octetts!");
333 i4b_Dfreembuf(m);
334 return(0);
335 }
336 i4b_rxd_s_frame(l2sc, drv, m);
337 }
338 else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 )
339 {
340 if(m->m_len < 3) /* 5 oct - 2 chksum oct */
341 {
342 l2sc->stat.err_rx_len++;
343 NDBGL2(L2_ERROR, "ERROR, U-frame < 5 octetts!");
344 i4b_Dfreembuf(m);
345 return(0);
346 }
347 i4b_rxd_u_frame(l2sc, drv, m);
348 }
349 else
350 {
351 l2sc->stat.err_rx_badf++;
352 NDBGL2(L2_ERROR, "ERROR, bad frame rx'd - ");
353 i4b_print_frame(m->m_len, m->m_data);
354 i4b_Dfreembuf(m);
355 }
356 return(0);
357 }
358
359 int i4b_l2_channel_get_state(struct isdn_l3_driver *drv, int b_chanid)
360 {
361 l2_softc_t *sc = drv->l1_token;
362 return sc->bchan_state[b_chanid];
363 }
364
365 void i4b_l2_channel_set_state(struct isdn_l3_driver *drv, int b_chanid, int state)
366 {
367 l2_softc_t *sc = drv->l1_token;
368 sc->bchan_state[b_chanid] = state;
369 }
370
371 /*---------------------------------------------------------------------------*
372 * telephony silence detection
373 *---------------------------------------------------------------------------*/
374
375 #define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
376
377 int
378 isdn_bchan_silence(unsigned char *data, int len)
379 {
380 register int i = 0;
381 register int j = 0;
382
383 /* count idle bytes */
384
385 for(;i < len; i++)
386 {
387 if((*data >= 0xaa) && (*data <= 0xac))
388 j++;
389 data++;
390 }
391
392 #ifdef NOTDEF
393 printf("isic_hscx_silence: got %d silence bytes in frame\n", j);
394 #endif
395
396 if(j < (TEL_IDLE_MIN))
397 return(0);
398 else
399 return(1);
400
401 }
402
403
404 #endif /* NI4BQ921 > 0 */
Cache object: e669b9953b8804790a24e56d9f9c7d1b
|