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.1 2003/04/06 04:37:48 tg 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.15 2002/05/21 10:31:10 martin 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 #include <sys/timeout.h>
58 
59 #ifdef __FreeBSD__
60 #include <machine/i4b_debug.h>
61 #include <machine/i4b_ioctl.h>
62 #else
63 #include <netisdn/i4b_debug.h>
64 #include <netisdn/i4b_ioctl.h>
65 #endif
66 
67 #include <netisdn/i4b_l3l4.h>
68 #include <netisdn/i4b_l2.h>
69 #include <netisdn/i4b_l1l2.h>
70 #include <netisdn/i4b_isdnq931.h>
71 #include <netisdn/i4b_mbuf.h>
72 #include <netisdn/i4b_global.h>
73 
74 #include <netisdn/i4b_l2.h>
75 #include <netisdn/i4b_l2fsm.h>
76 
77 /* this layers debug level */
78 
79 unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT;
80 
81 /*---------------------------------------------------------------------------*
82  *	DL_ESTABLISH_REQ from layer 3
83  *---------------------------------------------------------------------------*/
i4b_dl_establish_req(l2_softc_t * l2sc,struct isdn_l3_driver * drv)84 int i4b_dl_establish_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv)
85 {
86 	NDBGL2(L2_PRIM, "isdnif %d", l2sc->drv->isdnif);
87 	i4b_l1_activate(l2sc);
88 	i4b_next_l2state(l2sc, drv, EV_DLESTRQ);
89 	return(0);
90 }
91 
92 /*---------------------------------------------------------------------------*
93  *	DL_RELEASE_REQ from layer 3
94  *---------------------------------------------------------------------------*/
i4b_dl_release_req(l2_softc_t * l2sc,struct isdn_l3_driver * drv)95 int i4b_dl_release_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv)
96 {
97 	NDBGL2(L2_PRIM, "isdnif %d", l2sc->drv->isdnif);
98 	i4b_next_l2state(l2sc, drv, EV_DLRELRQ);
99 	return(0);
100 }
101 
102 /*---------------------------------------------------------------------------*
103  *	DL UNIT DATA REQUEST from Layer 3
104  *---------------------------------------------------------------------------*/
i4b_dl_unit_data_req(l2_softc_t * l2sc,struct isdn_l3_driver * drv,struct mbuf * m)105 int i4b_dl_unit_data_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
106 {
107 #ifdef NOTDEF
108 	NDBGL2(L2_PRIM, "isdnif %d", l2sc->isdnif);
109 #endif
110 	return(0);
111 }
112 
113 /*---------------------------------------------------------------------------*
114  *	DL DATA REQUEST from Layer 3
115  *---------------------------------------------------------------------------*/
i4b_dl_data_req(l2_softc_t * l2sc,struct isdn_l3_driver * drv,struct mbuf * m)116 int i4b_dl_data_req(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
117 {
118 	switch(l2sc->Q921_state)
119 	{
120 		case ST_AW_EST:
121 		case ST_MULTIFR:
122 		case ST_TIMREC:
123 
124 		        if(IF_QFULL(&l2sc->i_queue))
125 		        {
126 		        	NDBGL2(L2_ERROR, "i_queue full!!");
127 		        	i4b_Dfreembuf(m);
128 		        }
129 		        else
130 		        {
131 		        	int s;
132 
133 		        	s = splnet();
134 				IF_ENQUEUE(&l2sc->i_queue, m);
135 				splx(s);
136 
137 				i4b_i_frame_queued_up(l2sc);
138 			}
139 			break;
140 
141 		default:
142 			NDBGL2(L2_ERROR, "isdnif %d ERROR in state [%s], freeing mbuf", l2sc->drv->isdnif, i4b_print_l2state(l2sc));
143 			i4b_Dfreembuf(m);
144 			break;
145 	}
146 	return(0);
147 }
148 
149 /*---------------------------------------------------------------------------*
150  *	isdn_layer2_activate_ind - link activation/deactivation indication from layer 1
151  *---------------------------------------------------------------------------*/
152 int
isdn_layer2_activate_ind(struct l2_softc * l2sc,struct isdn_l3_driver * drv,int event_activate)153 isdn_layer2_activate_ind(struct l2_softc *l2sc, struct isdn_l3_driver *drv, int event_activate)
154 {
155 	if (event_activate) {
156 		l2sc->ph_active = PH_ACTIVE;
157 	} else {
158 		l2sc->ph_active = PH_INACTIVE;
159 	}
160 	return(0);
161 }
162 
163 /*---------------------------------------------------------------------------*
164  *	i4b_l2_unit_init - place layer 2 unit into known state
165  *---------------------------------------------------------------------------*/
166 static void
i4b_l2_unit_init(l2_softc_t * l2sc)167 i4b_l2_unit_init(l2_softc_t *l2sc)
168 {
169 	int s;
170 
171 	s = splnet();
172 	l2sc->Q921_state = ST_TEI_UNAS;
173 	l2sc->tei_valid = TEI_INVALID;
174 	l2sc->vr = 0;
175 	l2sc->vs = 0;
176 	l2sc->va = 0;
177 	l2sc->ack_pend = 0;
178 	l2sc->rej_excpt = 0;
179 	l2sc->peer_busy = 0;
180 	l2sc->own_busy = 0;
181 	l2sc->l3initiated = 0;
182 
183 	l2sc->rxd_CR = 0;
184 	l2sc->rxd_PF = 0;
185 	l2sc->rxd_NR = 0;
186 	l2sc->RC = 0;
187 	l2sc->iframe_sent = 0;
188 
189 	l2sc->postfsmfunc = NULL;
190 
191 	if(l2sc->ua_num != UA_EMPTY)
192 	{
193 		i4b_Dfreembuf(l2sc->ua_frame);
194 		l2sc->ua_num = UA_EMPTY;
195 		l2sc->ua_frame = NULL;
196 	}
197 
198 	i4b_T200_stop(l2sc);
199 	i4b_T202_stop(l2sc);
200 	i4b_T203_stop(l2sc);
201 
202 	splx(s);
203 }
204 
205 /*---------------------------------------------------------------------------*
206  *	isdn_layer2_status_ind - status indication upward
207  *---------------------------------------------------------------------------*/
208 int
isdn_layer2_status_ind(l2_softc_t * l2sc,struct isdn_l3_driver * drv,int status,int parm)209 isdn_layer2_status_ind(l2_softc_t *l2sc, struct isdn_l3_driver *drv, int status, int parm)
210 {
211 	int s;
212 	int sendup = 1;
213 
214 	s = splnet();
215 
216 	NDBGL2(L2_PRIM, "isdnif %d, status=%d, parm=%d", l2sc->drv->isdnif, status, parm);
217 
218 	switch(status)
219 	{
220 		case STI_ATTACH:
221 			if (parm == 0) {
222 				/* detach */
223 				timeout_del(&l2sc->T200_callout);
224 				timeout_del(&l2sc->T202_callout);
225 				timeout_del(&l2sc->T203_callout);
226 				timeout_del(&l2sc->IFQU_callout);
227 				break;
228 			}
229 
230 			l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
231 			l2sc->ua_frame = NULL;
232 			memset(&l2sc->stat, 0, sizeof(lapdstat_t));
233 			i4b_l2_unit_init(l2sc);
234 
235 			break;
236 
237 		case STI_L1STAT:	/* state of layer 1 */
238 			break;
239 
240 		case STI_PDEACT:	/* Timer 4 expired */
241 /*XXX*/			if((l2sc->Q921_state >= ST_AW_EST) &&
242 			   (l2sc->Q921_state <= ST_TIMREC))
243 			{
244 				NDBGL2(L2_ERROR, "isdnif %d, persistent deactivation!", l2sc->drv->isdnif);
245 				i4b_l2_unit_init(l2sc);
246 				parm = -1;	/* this is passed as the new
247 						 * TEI to upper layers */
248 			}
249 			else
250 			{
251 				sendup = 0;
252 			}
253 			break;
254 
255 		case STI_NOL1ACC:
256 			i4b_l2_unit_init(l2sc);
257 			NDBGL2(L2_ERROR, "isdnif %d, cannot access S0 bus!", l2sc->drv->isdnif);
258 			break;
259 
260 		default:
261 			NDBGL2(L2_ERROR, "ERROR, isdnif %d, unknown status message!", l2sc->drv->isdnif);
262 			break;
263 	}
264 
265 	if(sendup)
266 		i4b_mdl_status_ind(l2sc->drv, status, parm);  /* send up to layer 3 */
267 
268 	splx(s);
269 
270 	return(0);
271 }
272 
273 /*---------------------------------------------------------------------------*
274  *	MDL_COMMAND_REQ from layer 3
275  *---------------------------------------------------------------------------*/
i4b_mdl_command_req(struct isdn_l3_driver * drv,int command,void * parm)276 int i4b_mdl_command_req(struct isdn_l3_driver *drv, int command, void * parm)
277 {
278 	struct l2_softc *sc = (l2_softc_t*)drv->l1_token;
279 
280 	NDBGL2(L2_PRIM, "isdnif %d, command=%d, parm=%p", drv->isdnif, command, parm);
281 
282 	switch(command)
283 	{
284 		case CMR_DOPEN:
285 			i4b_l2_unit_init(sc);
286 			/* XXX - enable interrupts */
287 			break;
288 		case CMR_DCLOSE:
289 			/* XXX - disable interrupts */
290 			break;
291 	}
292 
293 	/* pass down to layer 1 driver */
294 	if (sc->driver)
295 		sc->driver->mph_command_req(sc->l1_token, command, parm);
296 
297 	return(0);
298 }
299 
300 /*---------------------------------------------------------------------------*
301  * isdn_layer2_data_ind - process a rx'd frame got from layer 1
302  *---------------------------------------------------------------------------*/
303 int
isdn_layer2_data_ind(l2_softc_t * l2sc,struct isdn_l3_driver * drv,struct mbuf * m)304 isdn_layer2_data_ind(l2_softc_t *l2sc, struct isdn_l3_driver *drv, struct mbuf *m)
305 {
306 	u_char *ptr = m->m_data;
307 
308 	if ( (*(ptr + OFF_CNTL) & 0x01) == 0 )
309 	{
310 		if(m->m_len < 4)	/* 6 oct - 2 chksum oct */
311 		{
312 			l2sc->stat.err_rx_len++;
313 			NDBGL2(L2_ERROR, "ERROR, I-frame < 6 octetts!");
314 			i4b_Dfreembuf(m);
315 			return(0);
316 		}
317 		i4b_rxd_i_frame(l2sc, drv, m);
318 	}
319 	else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 )
320 	{
321 		if(m->m_len < 4)	/* 6 oct - 2 chksum oct */
322 		{
323 			l2sc->stat.err_rx_len++;
324 			NDBGL2(L2_ERROR, "ERROR, S-frame < 6 octetts!");
325 			i4b_Dfreembuf(m);
326 			return(0);
327 		}
328 		i4b_rxd_s_frame(l2sc, drv, m);
329 	}
330 	else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 )
331 	{
332 		if(m->m_len < 3)	/* 5 oct - 2 chksum oct */
333 		{
334 			l2sc->stat.err_rx_len++;
335 			NDBGL2(L2_ERROR, "ERROR, U-frame < 5 octetts!");
336 			i4b_Dfreembuf(m);
337 			return(0);
338 		}
339 		i4b_rxd_u_frame(l2sc, drv, m);
340 	}
341 	else
342 	{
343 		l2sc->stat.err_rx_badf++;
344 		NDBGL2(L2_ERROR, "ERROR, bad frame rx'd - ");
345 		i4b_print_frame(m->m_len, m->m_data);
346 		i4b_Dfreembuf(m);
347 	}
348 	return(0);
349 }
350 
i4b_l2_channel_get_state(struct isdn_l3_driver * drv,int b_chanid)351 int i4b_l2_channel_get_state(struct isdn_l3_driver *drv, int b_chanid)
352 {
353 	l2_softc_t *sc = drv->l1_token;
354 	return sc->bchan_state[b_chanid];
355 }
356 
i4b_l2_channel_set_state(struct isdn_l3_driver * drv,int b_chanid,int state)357 void i4b_l2_channel_set_state(struct isdn_l3_driver *drv, int b_chanid, int state)
358 {
359 	l2_softc_t *sc = drv->l1_token;
360 	sc->bchan_state[b_chanid] = state;
361 }
362 
363 /*---------------------------------------------------------------------------*
364  *	telephony silence detection
365  *---------------------------------------------------------------------------*/
366 
367 #define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
368 
369 int
isdn_bchan_silence(unsigned char * data,int len)370 isdn_bchan_silence(unsigned char *data, int len)
371 {
372 	register int i = 0;
373 	register int j = 0;
374 
375 	/* count idle bytes */
376 
377 	for(;i < len; i++)
378 	{
379 		if((*data >= 0xaa) && (*data <= 0xac))
380 			j++;
381 		data++;
382 	}
383 
384 #ifdef NOTDEF
385 	printf("isic_hscx_silence: got %d silence bytes in frame\n", j);
386 #endif
387 
388 	if(j < (TEL_IDLE_MIN))
389 		return(0);
390 	else
391 		return(1);
392 
393 }
394 
395 
396 #endif /* NI4BQ921 > 0 */
397