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