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