summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer3/i4b_l2if.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i4b/layer3/i4b_l2if.c')
-rw-r--r--sys/i4b/layer3/i4b_l2if.c642
1 files changed, 642 insertions, 0 deletions
diff --git a/sys/i4b/layer3/i4b_l2if.c b/sys/i4b/layer3/i4b_l2if.c
new file mode 100644
index 0000000..33b1340
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l2if.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l2if.c - Layer 3 interface to Layer 2
+ * -------------------------------------------
+ *
+ * $Id: i4b_l2if.c,v 1.14 1998/12/05 18:05:28 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:31:26 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_cause.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_cause.h>
+#endif
+
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+static unsigned char make_q931_cause(cause_t cause);
+
+/*---------------------------------------------------------------------------*
+ * this converts our internal state (number) to the number specified
+ * in Q.931 and is used for reporting our state in STATUS messages.
+ *---------------------------------------------------------------------------*/
+int i4b_status_tab[] = {
+ 0, /* ST_U0, */
+ 1, /* ST_U1, */
+ 3, /* ST_U3, */
+ 4, /* ST_U4, */
+ 6, /* ST_U6, */
+ 7, /* ST_U7, */
+ 8, /* ST_U8, */
+ 9, /* ST_U9, */
+ 10, /* ST_U10, */
+ 11, /* ST_U11, */
+ 12, /* ST_U12, */
+ 19, /* ST_U19, */
+ 6, /* ST_IWA, */
+ 6, /* ST_IWR, */
+ 1, /* ST_OW, */
+ 6, /* ST_IWL, */
+};
+
+/*---------------------------------------------------------------------------*
+ * return a valid q.931/q.850 cause from any of the internal causes
+ *---------------------------------------------------------------------------*/
+static unsigned char
+make_q931_cause(cause_t cause)
+{
+ register unsigned char ret;
+
+ switch(GET_CAUSE_TYPE(cause))
+ {
+ case CAUSET_Q850:
+ ret = GET_CAUSE_VAL(cause);
+ break;
+ case CAUSET_I4B:
+ ret = cause_tab_q931[GET_CAUSE_VAL(cause)];
+ break;
+ default:
+ panic("make_q931_cause: unknown cause type!");
+ break;
+ }
+ ret |= EXT_LAST;
+ return(ret);
+}
+
+/*---------------------------------------------------------------------------*
+ * return status of data link
+ *---------------------------------------------------------------------------*/
+int
+i4b_get_dl_stat(call_desc_t *cd)
+{
+ return(ctrl_desc[cd->controller].dl_est);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL ESTABLISH INDICATION from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_establish_ind(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-ESTABLISH-IND", ("unit %d\n",unit));
+
+ /* first set DL up in controller descriptor */
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d DL established!\n",unit));
+ ctrl_desc[i].dl_est = DL_UP;
+ found = 1;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+ }
+
+ found = 0;
+
+ /* second, inform all (!) active call of the event */
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+ next_l3state(&call_desc[i], EV_DLESTIN);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, no cdid for unit %d found!\n", unit));
+ return(-1);
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * DL ESTABLISH CONFIRM from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_establish_cnf(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-ESTABLISH-CONF", ("unit %d\n",unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ ctrl_desc[call_desc[i].controller].dl_est = DL_UP;
+
+ DBGL3(L3_MSG, "i4b_dl_establish_cnf", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+
+ next_l3state(&call_desc[i], EV_DLESTCF);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_cnf", ("ERROR, no cdid for unit %d found!\n", unit));
+ return(-1);
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * DL RELEASE INDICATION from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_release_ind(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-RELEASE-IND", ("unit %d\n",unit));
+
+ /* first set controller to down */
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d DL released!\n",unit));
+ ctrl_desc[i].dl_est = DL_DOWN;
+ found = 1;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_release_ind", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+ }
+
+ found = 0;
+
+ /* second, inform all (!) active calls of the event */
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+ next_l3state(&call_desc[i], EV_DLRELIN);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ /* this is not an error since it might be a normal call end */
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("no cdid for unit %d found\n", unit));
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL RELEASE CONFIRM from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_release_cnf(int unit)
+{
+ int i;
+
+ DBGL2(L2_PRIM, "DL-RELEASE-CONF", ("unit %d\n",unit));
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_cnf", ("unit=%d DL released!\n",unit));
+ ctrl_desc[i].dl_est = DL_DOWN;
+ return(0);
+ }
+ }
+ DBGL3(L3_ERR, "i4b_dl_release_cnf", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_dl_data_ind - process a rx'd I-frame got from layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_data_ind(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-DATA-IND", ("unit %d\n",unit));
+#endif
+ i4b_decode_q931(unit, m->m_len, m->m_data);
+ i4b_Dfreembuf(m);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * dl_unit_data_ind - process a rx'd U-frame got from layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_unit_data_ind(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-UNIT-DATA-IND", ("unit %d\n",unit));
+#endif
+ i4b_decode_q931(unit, m->m_len, m->m_data);
+ i4b_Dfreembuf(m);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * send CONNECT message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_connect(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx CONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_LEN)) == NULL)
+ panic("i4b_l3_tx_connect: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = CONNECT; /* message type = connect */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send RELEASE COMPLETE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_release_complete(call_desc_t *cd, int send_cause_flag)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int len = I_FRAME_HDRLEN + MSG_RELEASE_COMPLETE_LEN;
+
+ DBGL3(L3_PRIM, "tx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if(send_cause_flag == 0)
+ len -= 4;
+
+ if((m = i4b_Dgetmbuf(len)) == NULL)
+ panic("i4b_l3_tx_release_complete: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = RELEASE_COMPLETE; /* message type = release complete */
+
+ if(send_cause_flag)
+ {
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+ }
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send DISCONNECT message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_disconnect(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx DISCONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL)
+ panic("i4b_l3_tx_disconnect: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call ref length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = DISCONNECT; /* message type = disconnect */
+
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send SETUP message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_setup(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int slen = strlen(cd->src_telno);
+ int dlen = strlen(cd->dst_telno);
+
+ /*
+ * there is one additional octet if cd->bprot == BPROT_NONE
+ * NOTE: the selection of a bearer capability by a B L1
+ * protocol is highly questionable and a better
+ * mechanism should be used in future. (-hm)
+ */
+
+ DBGL3(L3_PRIM, "tx SETUP", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_SETUP_LEN + slen + dlen +
+ (cd->bprot == BPROT_NONE ? 1 : 0))) == NULL)
+ {
+ panic("i4b_l3_tx_setup: can't allocate mbuf\n");
+ }
+
+ cd->crflag = CRF_ORIG; /* we are the originating side */
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call ref length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = SETUP; /* message type = setup */
+
+ *ptr++ = IEI_SENDCOMPL; /* sending complete */
+
+ *ptr++ = IEI_BEARERCAP; /* bearer capability */
+
+ /* XXX
+ * currently i have no idea if this should be switched by
+ * the choosen B channel protocol or if there should be a
+ * separate configuration item for the bearer capability.
+ * For now, it is switched by the choosen b protocol (-hm)
+ */
+
+ switch(cd->bprot)
+ {
+ case BPROT_NONE: /* telephony */
+ *ptr++ = IEI_BEARERCAP_LEN+1;
+ *ptr++ = IT_CAP_SPEECH;
+ *ptr++ = IT_RATE_64K;
+ *ptr++ = IT_UL1_G711A;
+ break;
+
+ case BPROT_RHDLC: /* raw HDLC */
+ *ptr++ = IEI_BEARERCAP_LEN;
+ *ptr++ = IT_CAP_UNR_DIG_INFO;
+ *ptr++ = IT_RATE_64K;
+ break;
+
+ default:
+ *ptr++ = IEI_BEARERCAP_LEN;
+ *ptr++ = IT_CAP_UNR_DIG_INFO;
+ *ptr++ = IT_RATE_64K;
+ break;
+ }
+
+ *ptr++ = IEI_CHANNELID; /* channel id */
+ *ptr++ = IEI_CHANNELID_LEN; /* channel id length */
+
+ switch(cd->channelid)
+ {
+ case CHAN_B1:
+ *ptr++ = CHANNELID_B1;
+ break;
+ case CHAN_B2:
+ *ptr++ = CHANNELID_B2;
+ break;
+ default:
+ *ptr++ = CHANNELID_ANY;
+ break;
+ }
+
+ *ptr++ = IEI_CALLINGPN; /* calling party no */
+ *ptr++ = IEI_CALLINGPN_LEN+slen;/* calling party no length */
+ *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
+ strncpy(ptr, cd->src_telno, slen);
+ ptr += slen;
+
+ *ptr++ = IEI_CALLEDPN; /* called party no */
+ *ptr++ = IEI_CALLEDPN_LEN+dlen; /* called party no length */
+ *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
+ strncpy(ptr, cd->dst_telno, dlen);
+ ptr += dlen;
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send CONNECT ACKNOWLEDGE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_connect_ack(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL)
+ panic("i4b_l3_tx_connect_ack: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = CONNECT_ACKNOWLEDGE; /* message type = connect ack */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send STATUS message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_status(call_desc_t *cd, u_char q850cause)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx STATUS", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL)
+ panic("i4b_l3_tx_status: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = STATUS; /* message type = connect ack */
+
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = q850cause;
+
+ *ptr++ = IEI_CALLSTATE; /* call state ie */
+ *ptr++ = CALLSTATE_LEN;
+ *ptr++ = i4b_status_tab[cd->Q931state];
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send RELEASE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN;
+
+ DBGL3(L3_PRIM, "tx RELEASE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if(send_cause_flag == 0)
+ len -= 4;
+
+ if((m = i4b_Dgetmbuf(len)) == NULL)
+ panic("i4b_l3_tx_release: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = RELEASE; /* message type = release complete */
+
+ if(send_cause_flag)
+ {
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+ }
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send ALERTING message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_alert(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL)
+ panic("i4b_l3_tx_alert: can't allocate mbuf\n");
+
+ DBGL3(L3_PRIM, "tx ALERT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = ALERT; /* message type = alert */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+#endif /* NI4BQ931 > 0 */
OpenPOWER on IntegriCloud