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