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