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_l2if.c - Layer 3 interface to Layer 2
28  *	-------------------------------------------
29  *
30  *	$Id: i4b_l2if.c,v 1.3 2003/10/03 17:24:15 tg Stab $
31  *
32  * $FreeBSD$
33  *
34  *      last edit-date: [Fri Jan  5 11:33:47 2001]
35  *
36  *---------------------------------------------------------------------------*/
37 
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_l2if.c,v 1.7 2002/09/27 15:37:56 provos Exp $");
40 
41 #ifdef __FreeBSD__
42 #include "i4bq931.h"
43 #else
44 #define	NI4BQ931	1
45 #endif
46 #if NI4BQ931 > 0
47 
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
51 #include <sys/mbuf.h>
52 #include <sys/socket.h>
53 #include <net/if.h>
54 
55 #include <sys/timeout.h>
56 
57 #ifdef __FreeBSD__
58 #include <machine/i4b_debug.h>
59 #include <machine/i4b_ioctl.h>
60 #include <machine/i4b_cause.h>
61 #else
62 #include <netisdn/i4b_debug.h>
63 #include <netisdn/i4b_ioctl.h>
64 #include <netisdn/i4b_cause.h>
65 #endif
66 
67 #include <netisdn/i4b_isdnq931.h>
68 #include <netisdn/i4b_l3l4.h>
69 #include <netisdn/i4b_mbuf.h>
70 
71 #include <netisdn/i4b_l2.h>
72 #include <netisdn/i4b_l1l2.h>
73 #include <netisdn/i4b_l3.h>
74 #include <netisdn/i4b_l3fsm.h>
75 #include <netisdn/i4b_q931.h>
76 
77 #include <netisdn/i4b_l4.h>
78 
79 static unsigned char make_q931_cause(cause_t cause);
80 
81 /*---------------------------------------------------------------------------*
82  * this converts our internal state (number) to the number specified
83  * in Q.931 and is used for reporting our state in STATUS messages.
84  *---------------------------------------------------------------------------*/
85 int i4b_status_tab[] = {
86 	0,	/*	ST_U0,	*/
87 	1,	/*	ST_U1,	*/
88 	3,	/*	ST_U3,	*/
89 	4,	/*	ST_U4,	*/
90 	6,	/*	ST_U6,	*/
91 	7,	/*	ST_U7,	*/
92 	8,	/*	ST_U8,	*/
93 	9,	/*	ST_U9,	*/
94 	10,	/*	ST_U10,	*/
95 	11,	/*	ST_U11,	*/
96 	12,	/*	ST_U12,	*/
97 	19,	/*	ST_U19,	*/
98 	6,	/*	ST_IWA,	*/
99 	6,	/*	ST_IWR,	*/
100 	1,	/*	ST_OW,	*/
101 	6,	/*	ST_IWL,	*/
102 };
103 
104 /*---------------------------------------------------------------------------*
105  *	return a valid q.931/q.850 cause from any of the internal causes
106  *---------------------------------------------------------------------------*/
107 static unsigned char
make_q931_cause(cause_t cause)108 make_q931_cause(cause_t cause)
109 {
110 	register unsigned char ret;
111 
112 	switch(GET_CAUSE_TYPE(cause))
113 	{
114 		case CAUSET_Q850:
115 			ret = GET_CAUSE_VAL(cause);
116 			break;
117 		case CAUSET_I4B:
118 			ret = cause_tab_q931[GET_CAUSE_VAL(cause)];
119 			break;
120 		default:
121 			panic("make_q931_cause: unknown cause type!");
122 			break;
123 	}
124 	ret |= EXT_LAST;
125 	return(ret);
126 }
127 
128 /*---------------------------------------------------------------------------*
129  *	return status of data link
130  *---------------------------------------------------------------------------*/
131 int
i4b_get_dl_stat(call_desc_t * cd)132 i4b_get_dl_stat(call_desc_t *cd)
133 {
134 	const struct isdn_l3_driver * drv = cd->l3drv;
135 	return drv->dl_est;
136 }
137 
138 /*---------------------------------------------------------------------------*
139  *	DL ESTABLISH INDICATION from Layer 2
140  *---------------------------------------------------------------------------*/
141 int
i4b_dl_establish_ind(struct isdn_l3_driver * drv)142 i4b_dl_establish_ind(struct isdn_l3_driver * drv)
143 {
144 	int i, found;
145 	NDBGL2(L2_PRIM, "DL-ESTABLISH-IND isdnif %d", drv->isdnif);
146 
147 	/* first set DL up in controller descriptor */
148 	NDBGL3(L3_MSG, "isdnif %d DL established!", drv->isdnif);
149 	drv->dl_est = DL_UP;
150 
151 	found = 0;
152 
153 	/* second, inform all (!) active call of the event */
154 
155 	for(i=0; i < num_call_desc; i++)
156 	{
157 		if( (call_desc[i].cdid != 0)
158 		    && call_desc[i].isdnif == drv->isdnif) {
159 			next_l3state(&call_desc[i], EV_DLESTIN);
160 			found++;
161 		}
162 	}
163 
164 	if(found == 0)
165 	{
166 		NDBGL3(L3_ERR, "ERROR, no cdid for isdnif %d found!",
167 		    drv->isdnif);
168 		return(-1);
169 	}
170 	else
171 	{
172 		return(0);
173 	}
174 }
175 
176 /*---------------------------------------------------------------------------*
177  *	DL ESTABLISH CONFIRM from Layer 2
178  *---------------------------------------------------------------------------*/
179 int
i4b_dl_establish_cnf(struct isdn_l3_driver * drv)180 i4b_dl_establish_cnf(struct isdn_l3_driver * drv)
181 {
182 	int i;
183 	int found = 0;
184 
185 	NDBGL2(L2_PRIM, "DL-ESTABLISH-CONF isdnif %d", drv->isdnif);
186 
187 	for(i=0; i < num_call_desc; i++)
188 	{
189 		if(call_desc[i].cdid != 0
190 		    && call_desc[i].isdnif == drv->isdnif) {
191 			drv->dl_est = DL_UP;
192 			next_l3state(&call_desc[i], EV_DLESTCF);
193 			found++;
194 		}
195 	}
196 
197 	if(found == 0)
198 	{
199 		NDBGL3(L3_ERR, "ERROR, no cdid for isdnif %d found!",
200 		    drv->isdnif);
201 		return(-1);
202 	}
203 	else
204 	{
205 		return(0);
206 	}
207 }
208 
209 /*---------------------------------------------------------------------------*
210  *	DL RELEASE INDICATION from Layer 2
211  *---------------------------------------------------------------------------*/
212 int
i4b_dl_release_ind(struct isdn_l3_driver * drv)213 i4b_dl_release_ind(struct isdn_l3_driver * drv)
214 {
215 	int i;
216 	int found = 0;
217 
218 	NDBGL2(L2_PRIM, "DL-RELEASE-IND isdnif %d", drv->isdnif);
219 
220 	/* first set controller to down */
221 
222 	drv->dl_est = DL_DOWN;
223 
224 	found = 0;
225 
226 	/* second, inform all (!) active calls of the event */
227 
228 	for(i=0; i < num_call_desc; i++)
229 	{
230 		if(call_desc[i].cdid != 0
231 		    && call_desc[i].isdnif == drv->isdnif) {
232 			next_l3state(&call_desc[i], EV_DLRELIN);
233 			found++;
234 		}
235 	}
236 
237 	if(found == 0)
238 	{
239 		/* this is not an error since it might be a normal call end */
240 		NDBGL3(L3_MSG, "no cdid for isdnif %d found", drv->isdnif);
241 	}
242 	return(0);
243 }
244 
245 /*---------------------------------------------------------------------------*
246  *	DL RELEASE CONFIRM from Layer 2
247  *---------------------------------------------------------------------------*/
248 int
i4b_dl_release_cnf(struct isdn_l3_driver * drv)249 i4b_dl_release_cnf(struct isdn_l3_driver * drv)
250 {
251 	NDBGL2(L2_PRIM, "DL-RELEASE-CONF isdnif %d", drv->isdnif);
252 
253 	drv->dl_est = DL_DOWN;
254 	return(0);
255 }
256 
257 /*---------------------------------------------------------------------------*
258  *	i4b_dl_data_ind - process a rx'd I-frame got from layer 2
259  *---------------------------------------------------------------------------*/
260 int
i4b_dl_data_ind(struct isdn_l3_driver * drv,struct mbuf * m)261 i4b_dl_data_ind(struct isdn_l3_driver *drv, struct mbuf *m)
262 {
263 	i4b_decode_q931(drv->isdnif, m->m_len, m->m_data);
264 	i4b_Dfreembuf(m);
265 	return(0);
266 }
267 
268 /*---------------------------------------------------------------------------*
269  *	dl_unit_data_ind - process a rx'd U-frame got from layer 2
270  *---------------------------------------------------------------------------*/
271 int
i4b_dl_unit_data_ind(struct isdn_l3_driver * drv,struct mbuf * m)272 i4b_dl_unit_data_ind(struct isdn_l3_driver *drv, struct mbuf *m)
273 {
274 	i4b_decode_q931(drv->isdnif, m->m_len, m->m_data);
275 	i4b_Dfreembuf(m);
276 	return(0);
277 }
278 
279 /*---------------------------------------------------------------------------*
280  *	send CONNECT message
281  *---------------------------------------------------------------------------*/
282 void
i4b_l3_tx_connect(call_desc_t * cd)283 i4b_l3_tx_connect(call_desc_t *cd)
284 {
285 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
286 	struct mbuf *m;
287 	u_char *ptr;
288 
289 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
290 
291 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_LEN)) == NULL)
292 		panic("i4b_l3_tx_connect: can't allocate mbuf");
293 
294 	ptr = m->m_data + I_FRAME_HDRLEN;
295 
296 	*ptr++ = PD_Q931;		/* protocol discriminator */
297 	*ptr++ = 0x01;			/* call reference length */
298 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
299 	*ptr++ = CONNECT;		/* message type = connect */
300 
301 	i4b_dl_data_req(l2sc, l2sc->drv, m);
302 }
303 
304 /*---------------------------------------------------------------------------*
305  *	send RELEASE COMPLETE message
306  *---------------------------------------------------------------------------*/
307 void
i4b_l3_tx_release_complete(call_desc_t * cd,int send_cause_flag)308 i4b_l3_tx_release_complete(call_desc_t *cd, int send_cause_flag)
309 {
310 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
311 	struct mbuf *m;
312 	u_char *ptr;
313 	int len = I_FRAME_HDRLEN + MSG_RELEASE_COMPLETE_LEN;
314 
315 	if(send_cause_flag == 0)
316 	{
317 		len -= 4;
318 		NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x",
319 			cd->isdnif, cd->cr);
320 	}
321 	else
322 	{
323 		NDBGL3(L3_PRIM, "isdnif=%d, cr=0x%02x, cause=0x%x",
324 			cd->isdnif, cd->cr, cd->cause_out);
325 	}
326 
327 	if((m = i4b_Dgetmbuf(len)) == NULL)
328 		panic("i4b_l3_tx_release_complete: can't allocate mbuf");
329 
330 	ptr = m->m_data + I_FRAME_HDRLEN;
331 
332 	*ptr++ = PD_Q931;		/* protocol discriminator */
333 	*ptr++ = 0x01;			/* call reference length */
334 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
335 	*ptr++ = RELEASE_COMPLETE;	/* message type = release complete */
336 
337 	if(send_cause_flag)
338 	{
339 		*ptr++ = IEI_CAUSE;		/* cause ie */
340 		*ptr++ = CAUSE_LEN;
341 		*ptr++ = CAUSE_STD_LOC_OUT;
342 		*ptr++ = make_q931_cause(cd->cause_out);
343 	}
344 
345 	i4b_dl_data_req(l2sc, l2sc->drv, m);
346 }
347 
348 /*---------------------------------------------------------------------------*
349  *	send DISCONNECT message
350  *---------------------------------------------------------------------------*/
351 void
i4b_l3_tx_disconnect(call_desc_t * cd)352 i4b_l3_tx_disconnect(call_desc_t *cd)
353 {
354 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
355 	struct mbuf *m;
356 	u_char *ptr;
357 
358 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
359 
360 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL)
361 		panic("i4b_l3_tx_disconnect: can't allocate mbuf");
362 
363 	ptr = m->m_data + I_FRAME_HDRLEN;
364 
365 	*ptr++ = PD_Q931;		/* protocol discriminator */
366 	*ptr++ = 0x01;			/* call ref length */
367 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
368 	*ptr++ = DISCONNECT;		/* message type = disconnect */
369 
370 	*ptr++ = IEI_CAUSE;		/* cause ie */
371 	*ptr++ = CAUSE_LEN;
372 	*ptr++ = CAUSE_STD_LOC_OUT;
373 	*ptr++ = make_q931_cause(cd->cause_out);
374 
375 	i4b_dl_data_req(l2sc, l2sc->drv, m);
376 }
377 
378 /*---------------------------------------------------------------------------*
379  *	send SETUP message
380  *---------------------------------------------------------------------------*/
381 void
i4b_l3_tx_setup(call_desc_t * cd)382 i4b_l3_tx_setup(call_desc_t *cd)
383 {
384 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
385 	struct mbuf *m;
386 	u_char *ptr;
387 	int slen = strlen(cd->src_telno);
388 	int dlen = strlen(cd->dst_telno);
389 
390 	/*
391 	 * there is one additional octet if cd->bprot == BPROT_NONE
392 	 * NOTE: the selection of a bearer capability by a B L1
393 	 *       protocol is highly questionable and a better
394 	 *       mechanism should be used in future. (-hm)
395 	 */
396 
397 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
398 
399 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_SETUP_LEN + slen + dlen +
400 			    (cd->bprot == BPROT_NONE ? 1 : 0))) == NULL)
401 	{
402 		panic("i4b_l3_tx_setup: can't allocate mbuf");
403 	}
404 
405 	cd->crflag = CRF_ORIG;		/* we are the originating side */
406 
407 	ptr = m->m_data + I_FRAME_HDRLEN;
408 
409 	*ptr++ = PD_Q931;		/* protocol discriminator */
410 	*ptr++ = 0x01;			/* call ref length */
411 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
412 	*ptr++ = SETUP;			/* message type = setup */
413 
414 	*ptr++ = IEI_SENDCOMPL;		/* sending complete */
415 
416 	*ptr++ = IEI_BEARERCAP;		/* bearer capability */
417 
418 	/* XXX
419 	 * currently i have no idea if this should be switched by
420 	 * the choosen B channel protocol or if there should be a
421 	 * separate configuration item for the bearer capability.
422 	 * For now, it is switched by the choosen b protocol (-hm)
423 	 */
424 
425 	switch(cd->bprot)
426 	{
427 		case BPROT_NONE:	/* telephony */
428 			*ptr++ = IEI_BEARERCAP_LEN+1;
429 			*ptr++ = IT_CAP_SPEECH;
430 			*ptr++ = IT_RATE_64K;
431 			*ptr++ = IT_UL1_G711A;
432 			break;
433 
434 		case BPROT_RHDLC:	/* raw HDLC */
435 			*ptr++ = IEI_BEARERCAP_LEN;
436 			*ptr++ = IT_CAP_UNR_DIG_INFO;
437 			*ptr++ = IT_RATE_64K;
438 			break;
439 
440 		default:
441 			*ptr++ = IEI_BEARERCAP_LEN;
442 			*ptr++ = IT_CAP_UNR_DIG_INFO;
443 			*ptr++ = IT_RATE_64K;
444 			break;
445 	}
446 
447 	*ptr++ = IEI_CHANNELID;		/* channel id */
448 	*ptr++ = IEI_CHANNELID_LEN;	/* channel id length */
449 
450 	switch(cd->channelid)
451 	{
452 		case CHAN_B1:
453 			*ptr++ = CHANNELID_B1;
454 			break;
455 		case CHAN_B2:
456 			*ptr++ = CHANNELID_B2;
457 			break;
458 		default:
459 			*ptr++ = CHANNELID_ANY;
460 			break;
461 	}
462 
463 	*ptr++ = IEI_CALLINGPN;		/* calling party no */
464 	*ptr++ = IEI_CALLINGPN_LEN+slen;/* calling party no length */
465 	*ptr++ = NUMBER_TYPEPLAN;	/* type of number, number plan id */
466 	strncpy(ptr, cd->src_telno, slen);
467 	ptr += slen;
468 
469 	*ptr++ = IEI_CALLEDPN;		/* called party no */
470 	*ptr++ = IEI_CALLEDPN_LEN+dlen;	/* called party no length */
471 	*ptr++ = NUMBER_TYPEPLAN;	/* type of number, number plan id */
472 	strncpy(ptr, cd->dst_telno, dlen);
473 	ptr += dlen;
474 
475 	i4b_dl_data_req(l2sc, l2sc->drv, m);
476 }
477 
478 /*---------------------------------------------------------------------------*
479  *	send CONNECT ACKNOWLEDGE message
480  *---------------------------------------------------------------------------*/
481 void
i4b_l3_tx_connect_ack(call_desc_t * cd)482 i4b_l3_tx_connect_ack(call_desc_t *cd)
483 {
484 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
485 	struct mbuf *m;
486 	u_char *ptr;
487 
488 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
489 
490 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL)
491 		panic("i4b_l3_tx_connect_ack: can't allocate mbuf");
492 
493 	ptr = m->m_data + I_FRAME_HDRLEN;
494 
495 	*ptr++ = PD_Q931;		/* protocol discriminator */
496 	*ptr++ = 0x01;			/* call reference length */
497 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
498 	*ptr++ = CONNECT_ACKNOWLEDGE;	/* message type = connect ack */
499 
500 	i4b_dl_data_req(l2sc, l2sc->drv, m);
501 }
502 
503 /*---------------------------------------------------------------------------*
504  *	send STATUS message
505  *---------------------------------------------------------------------------*/
506 void
i4b_l3_tx_status(call_desc_t * cd,u_char q850cause)507 i4b_l3_tx_status(call_desc_t *cd, u_char q850cause)
508 {
509 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
510 	struct mbuf *m;
511 	u_char *ptr;
512 
513 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
514 
515 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL)
516 		panic("i4b_l3_tx_status: can't allocate mbuf");
517 
518 	ptr = m->m_data + I_FRAME_HDRLEN;
519 
520 	*ptr++ = PD_Q931;		/* protocol discriminator */
521 	*ptr++ = 0x01;			/* call reference length */
522 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
523 	*ptr++ = STATUS;	/* message type = connect ack */
524 
525 	*ptr++ = IEI_CAUSE;		/* cause ie */
526 	*ptr++ = CAUSE_LEN;
527 	*ptr++ = CAUSE_STD_LOC_OUT;
528 	*ptr++ = q850cause | EXT_LAST;
529 
530 	*ptr++ = IEI_CALLSTATE;		/* call state ie */
531 	*ptr++ = CALLSTATE_LEN;
532 	*ptr++ = i4b_status_tab[cd->Q931state];
533 
534 	i4b_dl_data_req(l2sc, l2sc->drv, m);
535 }
536 
537 /*---------------------------------------------------------------------------*
538  *	send RELEASE message
539  *---------------------------------------------------------------------------*/
540 void
i4b_l3_tx_release(call_desc_t * cd,int send_cause_flag)541 i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag)
542 {
543 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
544 	struct mbuf *m;
545 	u_char *ptr;
546 	int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN;
547 
548 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
549 
550 	if(send_cause_flag == 0)
551 		len -= 4;
552 
553 	if((m = i4b_Dgetmbuf(len)) == NULL)
554 		panic("i4b_l3_tx_release: can't allocate mbuf");
555 
556 	ptr = m->m_data + I_FRAME_HDRLEN;
557 
558 	*ptr++ = PD_Q931;		/* protocol discriminator */
559 	*ptr++ = 0x01;			/* call reference length */
560 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
561 	*ptr++ = RELEASE;		/* message type = release complete */
562 
563 	if(send_cause_flag)
564 	{
565 		*ptr++ = IEI_CAUSE;		/* cause ie */
566 		*ptr++ = CAUSE_LEN;
567 		*ptr++ = CAUSE_STD_LOC_OUT;
568 		*ptr++ = make_q931_cause(cd->cause_out);
569 	}
570 
571 	i4b_dl_data_req(l2sc, l2sc->drv, m);
572 }
573 
574 /*---------------------------------------------------------------------------*
575  *	send ALERTING message
576  *---------------------------------------------------------------------------*/
577 void
i4b_l3_tx_alert(call_desc_t * cd)578 i4b_l3_tx_alert(call_desc_t *cd)
579 {
580 	struct l2_softc *l2sc = (l2_softc_t*)cd->l3drv->l1_token;
581 	struct mbuf *m;
582 	u_char *ptr;
583 
584 	if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL)
585 		panic("i4b_l3_tx_alert: can't allocate mbuf");
586 
587 	NDBGL3(L3_PRIM, "isdnif %d, cr = 0x%02x", cd->isdnif, cd->cr);
588 
589 	ptr = m->m_data + I_FRAME_HDRLEN;
590 
591 	*ptr++ = PD_Q931;		/* protocol discriminator */
592 	*ptr++ = 0x01;			/* call reference length */
593 	*ptr++ = setup_cr(cd, cd->cr);	/* call reference value */
594 	*ptr++ = ALERT;			/* message type = alert */
595 
596 	i4b_dl_data_req(l2sc, l2sc->drv, m);
597 }
598 
599 #endif /* NI4BQ931 > 0 */
600