summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer3
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
committerphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
commitc7ecc129d72ba32b5d83c9a6019e93fd181d719c (patch)
tree8d5099bc7ef24151b4f6deb00d1d34a7e7ac694a /sys/i4b/layer3
parent3f431df8ec46b86090ad59ee153872c45d4d429d (diff)
downloadFreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.zip
FreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.tar.gz
Initial entry of ISDN4BSD into the FreeBSD tree.
ISDN4BSD is the work of our brand-new comitter: Hellmuth Michaelis, who has done a tremendous amount of work to bring us this far. There are still some outstanding issues and files to bring into the tree, and for now it will be needed to pick up all the extra docs from the isdn4bsd release. It is probably also a very good idea to subscribe to the isdn@freebsd.org mailing list before you try this out. These files correspond to release "beta Version 0.70.00 / December 1998" from Hellmuth.
Diffstat (limited to 'sys/i4b/layer3')
-rw-r--r--sys/i4b/layer3/i4b_l2if.c642
-rw-r--r--sys/i4b/layer3/i4b_l3.h80
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.c1034
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.h105
-rw-r--r--sys/i4b/layer3/i4b_l3timer.c347
-rw-r--r--sys/i4b/layer3/i4b_l4if.c339
-rw-r--r--sys/i4b/layer3/i4b_q931.c624
-rw-r--r--sys/i4b/layer3/i4b_q931.h116
-rw-r--r--sys/i4b/layer3/i4b_q932fac.c569
-rw-r--r--sys/i4b/layer3/i4b_q932fac.h167
10 files changed, 4023 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 */
diff --git a/sys/i4b/layer3/i4b_l3.h b/sys/i4b/layer3/i4b_l3.h
new file mode 100644
index 0000000..9d05055
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3.h
@@ -0,0 +1,80 @@
+/*
+ * 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_l3.h - layer 3 header file
+ * ------------------------------
+ *
+ * $Id: i4b_l3.h,v 1.8 1998/12/05 18:05:30 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:31:41 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L3_H_
+#define _I4B_L3_H_
+
+extern int utoc_tab[];
+extern unsigned char cause_tab_q931[];
+
+extern int i4b_aoc ( unsigned char *, call_desc_t *cd );
+extern void i4b_decode_q931 ( int unit, int msg_len, u_char *msg_ptr );
+extern int i4b_decode_q931_cs0_ie ( int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr );
+extern void i4b_decode_q931_message ( int unit, call_desc_t *cd, u_char message_type );
+extern void i4b_l3_stop_all_timers ( call_desc_t *cd );
+extern void i4b_l3_tx_alert ( call_desc_t *cd );
+extern void i4b_l3_tx_connect ( call_desc_t *cd );
+extern void i4b_l3_tx_connect_ack ( call_desc_t *cd );
+extern void i4b_l3_tx_disconnect ( call_desc_t *cd );
+extern void i4b_l3_tx_release ( call_desc_t *cd, int send_cause_flag );
+extern void i4b_l3_tx_release_complete ( call_desc_t *cd, int send_cause_flag );
+extern void i4b_l3_tx_setup ( call_desc_t *cd );
+extern void i4b_l3_tx_status ( call_desc_t *cd, u_char q850cause );
+extern int i4b_dl_data_ind ( int unit, struct mbuf *m );
+extern int i4b_dl_establish_cnf ( int unit );
+extern int i4b_dl_establish_ind ( int unit );
+extern int i4b_dl_release_cnf ( int unit );
+extern int i4b_dl_release_ind ( int unit );
+extern int i4b_dl_unit_data_ind ( int unit, struct mbuf *m );
+extern int i4b_get_dl_stat( call_desc_t *cd );
+extern int i4b_mdl_status_ind ( int unit, int status, int parm);
+extern void i4b_print_frame ( int len, u_char *buf );
+extern void next_l3state ( call_desc_t *cd, int event );
+extern char *print_l3state ( call_desc_t *cd );
+extern unsigned char setup_cr ( call_desc_t *cd, unsigned char cr );
+extern void T303_start ( call_desc_t *cd );
+extern void T303_stop ( call_desc_t *cd );
+extern void T305_start ( call_desc_t *cd );
+extern void T305_stop ( call_desc_t *cd );
+extern void T308_start ( call_desc_t *cd );
+extern void T308_stop ( call_desc_t *cd );
+extern void T309_start ( call_desc_t *cd );
+extern void T309_stop ( call_desc_t *cd );
+extern void T310_start ( call_desc_t *cd );
+extern void T310_stop ( call_desc_t *cd );
+extern void T313_start ( call_desc_t *cd );
+extern void T313_stop ( call_desc_t *cd );
+
+#endif /* _I4B_L3_H_ */
diff --git a/sys/i4b/layer3/i4b_l3fsm.c b/sys/i4b/layer3/i4b_l3fsm.c
new file mode 100644
index 0000000..e45e119
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3fsm.c
@@ -0,0 +1,1034 @@
+/*
+ * 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_l3fsm.c - layer 3 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l3fsm.c,v 1.13 1998/12/05 18:05:31 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:32:17 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/include/i4b_global.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 void F_00A(call_desc_t *cd), F_00H(call_desc_t *cd), F_00I(call_desc_t *cd);
+static void F_00J(call_desc_t *cd);
+
+static void F_01B(call_desc_t *cd), F_01K(call_desc_t *cd), F_01L(call_desc_t *cd);
+static void F_01M(call_desc_t *cd), F_01N(call_desc_t *cd), F_01U(call_desc_t *cd);
+static void F_01O(call_desc_t *cd);
+
+static void F_03C(call_desc_t *cd), F_03N(call_desc_t *cd), F_03O(call_desc_t *cd);
+static void F_03P(call_desc_t *cd), F_03Y(call_desc_t *cd);
+
+static void F_04O(call_desc_t *cd);
+
+static void F_06D(call_desc_t *cd), F_06E(call_desc_t *cd), F_06F(call_desc_t *cd);
+static void F_06G(call_desc_t *cd), F_06J(call_desc_t *cd), F_06Q(call_desc_t *cd);
+
+static void F_07E(call_desc_t *cd), F_07F(call_desc_t *cd), F_07G(call_desc_t *cd);
+
+static void F_08R(call_desc_t *cd), F_08Z(call_desc_t *cd);
+
+static void F_09D(call_desc_t *cd), F_09E(call_desc_t *cd), F_09F(call_desc_t *cd);
+static void F_09G(call_desc_t *cd);
+
+static void F_11J(call_desc_t *cd), F_11Q(call_desc_t *cd), F_11V(call_desc_t *cd);
+
+static void F_12C(call_desc_t *cd), F_12J(call_desc_t *cd);
+
+static void F_19I(call_desc_t *cd), F_19J(call_desc_t *cd), F_19K(call_desc_t *cd);
+static void F_19W(call_desc_t *cd);
+
+static void F_NCNA(call_desc_t *cd), F_STENQ(call_desc_t *cd), F_STAT(call_desc_t *cd);
+static void F_INFO(call_desc_t *cd), F_RELCP(call_desc_t *cd), F_REL(call_desc_t *cd);
+static void F_DISC(call_desc_t *cd), F_DCRQ(call_desc_t *cd), F_UEM(call_desc_t *cd);
+static void F_SIGN(call_desc_t *cd), F_DLEI(call_desc_t *cd), F_ILL(call_desc_t *cd);
+static void F_309TO(call_desc_t *cd), F_DECF(call_desc_t *cd), F_FCTY(call_desc_t *cd);
+static void F_DECF1(call_desc_t *cd), F_DECF2(call_desc_t *cd), F_DECF3(call_desc_t *cd);
+static void F_DLRI(call_desc_t *cd), F_DLRIA(call_desc_t *cd), F_DECF4(call_desc_t *cd);
+
+static char *l3state_text[N_STATES] = {
+ "ST_U0 - Null",
+ "ST_U1 - Out Init",
+ "ST_U3 - Out Proc",
+ "ST_U4 - Out Delv",
+ "ST_U6 - In Pres",
+ "ST_U7 - In Rxd",
+ "ST_U8 - In ConReq",
+ "ST_U9 - In Proc",
+ "ST_U10 - Active",
+ "ST_U11 - Disc Req",
+ "ST_U12 - Disc Ind",
+ "ST_U19 - Rel Req",
+
+ "ST_IWA - In Wait EST-Accept",
+ "ST_IWR - In Wait EST-Reject",
+ "ST_OW - Out Wait EST",
+ "ST_IWL - In Wait EST-Alert",
+
+ "ST_SUSE - Subroutine sets state",
+
+ "Illegal State"
+};
+
+static char *l3event_text[N_EVENTS] = {
+ "EV_SETUPRQ - L4 SETUP REQ", /* setup request from L4 */
+ "EV_DISCRQ - L4 DISC REQ", /* disconnect request from L4 */
+ "EV_RELRQ - L4 REL REQ", /* release request from L4 */
+ "EV_ALERTRQ - L4 ALERT REQ", /* alerting request from L4 */
+ "EV_SETACRS - L4 accept RSP", /* setup response accept from l4 */
+ "EV_SETRJRS - L4 reject RSP", /* setup response reject from l4 */
+ "EV_SETDCRS - L4 ignore RSP", /* setup response dontcare from l4 */
+
+ "EV_SETUP - rxd SETUP", /* incoming SETUP message from L2 */
+ "EV_STATUS - rxd STATUS", /* incoming STATUS message from L2 */
+ "EV_RELEASE - rxd REL", /* incoming RELEASE message from L2 */
+ "EV_RELCOMP - rxd REL COMPL", /* incoming RELEASE COMPLETE from L2 */
+ "EV_SETUPAK - rxd SETUP ACK", /* incoming SETUP ACK message from L2 */
+ "EV_CALLPRC - rxd CALL PROC", /* incoming CALL PROCEEDING from L2 */
+ "EV_ALERT - rxd ALERT", /* incoming ALERT message from L2 */
+ "EV_CONNECT - rxd CONNECT", /* incoming CONNECT message from L2 */
+ "EV_PROGIND - rxd PROG IND", /* incoming Progress IND from L2 */
+ "EV_DISCONN - rxd DISC", /* incoming DISCONNECT message from L2 */
+ "EV_CONACK - rxd CONN ACK", /* incoming CONNECT ACK message from L2 */
+ "EV_STATENQ - rxd STAT ENQ", /* incoming STATUS ENQ message from L2 */
+ "EV_INFO - rxd INFO", /* incoming INFO message from L2 */
+ "EV_FACILITY - rxd FACILITY", /* incoming FACILITY message */
+
+ "EV_T303EXP - T303 timeout", /* Timer T303 expired */
+ "EV_T305EXP - T305 timeout", /* Timer T305 expired */
+ "EV_T308EXP - T308 timeout", /* Timer T308 expired */
+ "EV_T309EXP - T309 timeout", /* Timer T309 expired */
+ "EV_T310EXP - T310 timeout", /* Timer T310 expired */
+ "EV_T313EXP - T313 timeout", /* Timer T313 expired */
+
+ "EV_DLESTIN - L2 DL_Est_Ind", /* dl establish indication from l2 */
+ "EV_DLRELIN - L2 DL_Rel_Ind", /* dl release indication from l2 */
+ "EV_DLESTCF - L2 DL_Est_Cnf", /* dl establish confirm from l2 */
+ "EV_DLRELCF - L2 DL_Rel_Cnf", /* dl release confirm from l2 */
+
+ "EV_ILL - Illegal event!!" /* Illegal */
+};
+
+/*---------------------------------------------------------------------------*
+ * layer 3 state transition table
+ *---------------------------------------------------------------------------*/
+struct l3state_tab {
+ void (*func) (call_desc_t *); /* function to execute */
+ int newstate; /* next state */
+} l3state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_SETUPRQ*/ {{F_00A, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DISCRQ */ {{F_ILL, ST_ILL}, {F_01B, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_NCNA, ST_U12}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELRQ */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_12C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ALERTRQ*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06D, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_09D, ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETACRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06E, ST_SUSE}, {F_07E, ST_U8}, {F_ILL, ST_ILL}, {F_09E, ST_U8}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETRJRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06F, ST_SUSE}, {F_07F, ST_U0}, {F_ILL, ST_ILL}, {F_09F, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETDCRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06G, ST_U0}, {F_07G, ST_U0}, {F_ILL, ST_ILL}, {F_09G, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_SETUP */ {{F_00H, ST_U6}, {F_SIGN, ST_U1}, {F_SIGN, ST_U3}, {F_SIGN, ST_U4}, {F_SIGN, ST_U6}, {F_SIGN, ST_U7}, {F_SIGN, ST_U8}, {F_SIGN, ST_U9}, {F_SIGN, ST_U10}, {F_SIGN, ST_U11}, {F_SIGN, ST_U12}, {F_SIGN, ST_U19}, {F_SIGN, ST_IWA}, {F_SIGN, ST_IWR}, {F_SIGN, ST_OW}, {F_SIGN, ST_IWL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_STATUS */ {{F_00I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_19I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELEASE*/ {{F_00J, ST_U0}, {F_UEM, ST_SUSE}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_06J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_11J, ST_U0}, {F_12J, ST_U0}, {F_19J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELCOMP*/ {{F_NCNA, ST_U0}, {F_01K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_19K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETUPAK*/ {{F_UEM, ST_SUSE}, {F_01L, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CALLPRC*/ {{F_UEM, ST_SUSE}, {F_01M, ST_U3}, {F_NCNA, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ALERT */ {{F_UEM, ST_SUSE}, {F_01N, ST_U4}, {F_03N, ST_U4}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CONNECT*/ {{F_UEM, ST_SUSE}, {F_01O, ST_U10}, {F_03O, ST_U10}, {F_04O, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_PROGIND*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_03P, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DISCONN*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_06Q, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_11Q, ST_U19}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CONACK */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_08R, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_STATENQ*/ {{F_STENQ,ST_U0}, {F_STENQ,ST_U1}, {F_STENQ,ST_U3}, {F_STENQ,ST_U4}, {F_STENQ,ST_U6}, {F_STENQ,ST_U7}, {F_STENQ,ST_U8}, {F_STENQ,ST_U9}, {F_STENQ,ST_U10}, {F_STENQ,ST_U11}, {F_STENQ,ST_U12}, {F_STENQ,ST_U19}, {F_STENQ,ST_IWA}, {F_STENQ,ST_IWR}, {F_STENQ,ST_OW}, {F_STENQ,ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_INFO */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_INFO, ST_U3}, {F_INFO, ST_U4}, {F_UEM, ST_SUSE}, {F_INFO, ST_U7}, {F_INFO, ST_U8}, {F_INFO, ST_U9}, {F_INFO, ST_U10}, {F_INFO, ST_U11}, {F_INFO, ST_U12}, {F_UEM, ST_SUSE}, {F_INFO, ST_IWA}, {F_INFO, ST_IWR}, {F_INFO, ST_OW}, {F_INFO, ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_FACILITY*/ {{F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_T303EXP*/ {{F_ILL, ST_ILL}, {F_01U, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T305EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_11V, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T308EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_19W, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T309EXP*/ {{F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T310EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03Y, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T313EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_08Z, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_DLESTIN*/ {{F_ILL, ST_ILL}, {F_DLEI, ST_U1}, {F_DLEI, ST_U3}, {F_DLEI, ST_U4}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLRELIN*/ {{F_NCNA, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRIA,ST_U10}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLESTCF*/ {{F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF2,ST_U8}, {F_DECF3,ST_U0}, {F_DECF1,ST_U1}, {F_DECF4,ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLRELCF*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ILL */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void next_l3state(call_desc_t *cd, int event)
+{
+ int currstate, newstate;
+
+ if(event > N_EVENTS)
+ panic("i4b_l3fsm.c: event > N_EVENTS\n");
+
+ currstate = cd->Q931state;
+
+ if(currstate > N_STATES)
+ panic("i4b_l3fsm.c: currstate > N_STATES\n");
+
+ newstate = l3state_tab[event][currstate].newstate;
+
+ if(newstate > N_STATES)
+ panic("i4b_l3fsm.c: newstate > N_STATES\n");
+
+ DBGL3(L3_F_MSG, "next_l3state", ("L3 FSM event [%s]: [%s => %s]\n",
+ l3event_text[event],
+ l3state_text[currstate],
+ l3state_text[newstate]));
+
+ /* execute function */
+
+ (*l3state_tab[event][currstate].func)(cd);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = currstate;
+ DBGL3(L3_F_ERR, "next_l3state", ("FSM illegal state, state = %s, event = %s!\n",
+ l3state_text[newstate],
+ l3event_text[event]));
+ }
+
+ if(newstate != ST_SUSE)
+ cd->Q931state = newstate;
+}
+
+/*---------------------------------------------------------------------------*
+ * resturn pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *print_l3state(call_desc_t *cd)
+{
+ return((char *) l3state_text[cd->Q931state]);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event L4 setup req
+ *---------------------------------------------------------------------------*/
+static void F_00A(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00A", ("FSM function F_00A executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_OW;
+ }
+ else
+ {
+ i4b_l3_tx_setup(cd);
+ cd->Q931state = ST_U1;
+ }
+
+ cd->T303_first_to = 1;
+ T303_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event SETUP from L2
+ *---------------------------------------------------------------------------*/
+static void F_00H(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00H", ("FSM function F_00H executing\n"));
+ i4b_l4_connect_ind(cd); /* tell l4 we have an incoming setup */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_00I(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00I", ("FSM function F_00I executing\n"));
+
+ if(cd->call_state != 0)
+ {
+ cd->cause_out = 101;
+ i4b_l3_tx_release_complete(cd, 1); /* 1 = send cause */
+ }
+ cd->Q931state = ST_U0;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_00J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00J", ("FSM function F_00J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0); /* 0 = don't send cause */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event disconnect req from L4
+ *---------------------------------------------------------------------------*/
+static void F_01B(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01B", ("FSM function F_01B executing\n"));
+ /* cause from L4 */
+ i4b_l3_tx_disconnect(cd);
+ T303_stop(cd);
+ T305_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_01K(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01K", ("FSM function F_01K executing\n"));
+ T303_stop(cd);
+ i4b_l4_disconnect_ind(cd); /* tell l4 we were rejected */
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event SETUP ACK from L2
+ *---------------------------------------------------------------------------*/
+static void F_01L(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01L", ("FSM function F_01L executing\n"));
+ T303_stop(cd);
+
+ /*
+ * since this implementation does NOT support overlap sending,
+ * we react here as if we received a CALL PROCEEDING because
+ * several PBX's react with a SETUP ACK even if the called
+ * number is complete AND we sent a SENDING COMPLETE in the
+ * preceeding SETUP message. (-hm)
+ */
+
+ T310_start(cd);
+ i4b_l4_proceeding_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event CALL PROCEEDING from L2
+ *---------------------------------------------------------------------------*/
+static void F_01M(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01M", ("FSM function F_01M executing\n"));
+ T303_stop(cd);
+ T310_start(cd);
+ i4b_l4_proceeding_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event ALERT from L2 (XXX !)
+ *---------------------------------------------------------------------------*/
+static void F_01N(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01N", ("FSM function F_01N executing\n"));
+ T303_stop(cd);
+ i4b_l4_alert_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event CONNECT from L2 (XXX !)
+ *---------------------------------------------------------------------------*/
+static void F_01O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01O", ("FSM function F_01O executing\n"));
+ T303_stop(cd);
+ i4b_l3_tx_connect_ack(cd);
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event T303 timeout
+ *---------------------------------------------------------------------------*/
+static void F_01U(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01U", ("FSM function F_01U executing\n"));
+ if(cd->T303_first_to == 1)
+ {
+ cd->T303_first_to = 0;
+ i4b_l3_tx_setup(cd);
+ T303_start(cd);
+ cd->Q931state = ST_U1;
+ }
+ else
+ {
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event release req from L4
+ *---------------------------------------------------------------------------*/
+static void F_03C(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03C", ("FSM function F_03C executing\n"));
+ T310_stop(cd);
+ cd->cause_out = 6;
+ i4b_l3_tx_release(cd, 1); /* 0 = don't send cause */
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event ALERT from L2
+ *---------------------------------------------------------------------------*/
+static void F_03N(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03N", ("FSM function F_03N executing\n"));
+ T310_stop(cd);
+ i4b_l4_alert_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event CONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_03O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03O", ("FSM function F_03O executing\n"));
+ T310_stop(cd);
+ i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event PROGESS IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_03P(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03P", ("FSM function F_03P executing\n"));
+ T310_stop(cd);
+#ifdef NOTDEF
+ i4b_l4_progress_ind(cd);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event T310 timeout
+ *---------------------------------------------------------------------------*/
+static void F_03Y(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03Y", ("FSM function F_03Y executing\n"));
+ cd->cause_out = 102; /* recovery on timer expiry */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U4 event CONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_04O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_04O", ("FSM function F_04O executing\n"));
+ i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event alert req from L4
+ *---------------------------------------------------------------------------*/
+static void F_06D(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06D", ("FSM function F_06D executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWL;
+ }
+ else
+ {
+ i4b_l3_tx_alert(cd);
+ cd->Q931state = ST_U7;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_06E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06E", ("FSM function F_06E executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWA;
+ }
+ else
+ {
+ i4b_l3_tx_connect(cd);
+ cd->Q931state = ST_U8;
+ }
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_06F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06F", ("FSM function F_06F executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWR;
+ }
+ else
+ {
+ int s = SPLI4B();
+ i4b_l3_tx_release_complete(cd, 1);
+ cd->Q931state = ST_U0;
+ freecd_by_cd(cd);
+ splx(s);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_06G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06G", ("FSM function F_06G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_06J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06J", ("FSM function F_06J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_06Q(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06Q", ("FSM function F_06Q executing\n"));
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_07E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07E", ("FSM function F_07E executing\n"));
+ i4b_l3_tx_connect(cd);
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_07F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07F", ("FSM function F_07F executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_07G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07G", ("FSM function F_07G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U8 event CONNECT ACK from L2
+ *---------------------------------------------------------------------------*/
+static void F_08R(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_08R", ("FSM function F_08R executing\n"));
+ T313_stop(cd);
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U8 event T313 timeout
+ *---------------------------------------------------------------------------*/
+static void F_08Z(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_08Z", ("FSM function F_08Z executing\n"));
+ cd->cause_out = 102; /* recovery on timer expiry */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event alert req from L4
+ *---------------------------------------------------------------------------*/
+static void F_09D(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09D", ("FSM function F_09D executing\n"));
+ i4b_l3_tx_alert(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_09E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09E", ("FSM function F_09E executing\n"));
+ i4b_l3_tx_connect(cd);
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_09F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09F", ("FSM function F_09F executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_09G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09G", ("FSM function F_09G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_11J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11J", ("FSM function F_11J executing\n"));
+ T305_stop(cd);
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_11Q(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11Q", ("FSM function F_11Q executing\n"));
+ T305_stop(cd);
+ i4b_l3_tx_release(cd, 0);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event T305 timeout
+ *---------------------------------------------------------------------------*/
+static void F_11V(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11V", ("FSM function F_11V executing\n"));
+ cd->cause_out = 102;
+ i4b_l3_tx_release(cd, 1);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U12 event release req from L4
+ *---------------------------------------------------------------------------*/
+static void F_12C(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_12C", ("FSM function F_12C executing\n"));
+ i4b_l3_tx_release(cd, 1);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U12 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_12J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_12J", ("FSM function F_12J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_19I(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19I", ("FSM function F_19I executing\n"));
+
+ if(cd->call_state == 0)
+ {
+ i4b_l4_status_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+ else
+ {
+ cd->Q931state = ST_U19;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_19J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19J", ("FSM function F_19J executing\n"));
+ T308_stop(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_19K(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19K", ("FSM function F_19K executing\n"));
+ T308_stop(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event T308 timeout
+ *---------------------------------------------------------------------------*/
+static void F_19W(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19W", ("FSM function F_19W executing\n"));
+ if(cd->T308_first_to == 0)
+ {
+ cd->T308_first_to = 1;
+ i4b_l3_tx_release(cd, 0);
+ T308_start(cd);
+ cd->Q931state = ST_U19;
+ }
+ else
+ {
+ cd->T308_first_to = 0;
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM routine no change no action
+ *---------------------------------------------------------------------------*/
+static void F_NCNA(call_desc_t *cd)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event STATUS ENQ from L2
+ *---------------------------------------------------------------------------*/
+static void F_STENQ(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_STENQ", ("FSM function F_STENQ executing\n"));
+ i4b_l3_tx_status(cd, CAUSE_Q850_STENQRSP); /* 30, resonse to stat enq */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 & 19 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_STAT(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_STAT", ("FSM function F_STAT executing\n"));
+ if(cd->call_state == 0)
+ {
+ i4b_l4_status_ind(cd);
+ cd->Q931state = ST_U0;
+ freecd_by_cd(cd);
+ }
+ else
+ {
+ /* XXX !!!!!!!!!!!!!!!!!! */
+
+ i4b_l4_status_ind(cd);
+ cd->cause_out = 101; /* message not compatible with call state */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ cd->Q931state = ST_U11;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event INFORMATION from L2
+ *---------------------------------------------------------------------------*/
+static void F_INFO(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_INFO", ("FSM function F_INFO executing\n"));
+ i4b_l4_info_ind(cd);
+ /* remain in current state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_RELCP(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_RELCP", ("FSM function F_RELCP executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_REL(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_REL", ("FSM function F_REL executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_DISC(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DISC", ("FSM function F_DISC executing\n"));
+ i4b_l3_stop_all_timers(cd);
+
+ /*
+ * no disconnect ind to L4, no jump to state U12
+ * instead we issue a RELEASE and jump to U19
+ */
+
+ i4b_l3_tx_release(cd, 0);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+ cd->Q931state = ST_U19;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event disconnect request from L4
+ *---------------------------------------------------------------------------*/
+static void F_DCRQ(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DCRQ", ("FSM function F_DCRQ executing\n"));
+ /* cause from L4 */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ cd->Q931state = ST_U11;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 event unexpected message from L2
+ *---------------------------------------------------------------------------*/
+static void F_UEM(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_UEM", ("FSM function F_UEM executing, state = %s\n", print_l3state(cd)));
+ i4b_l3_tx_status(cd, CAUSE_Q850_MSGNCWCS); /* 101, message not compatible with call state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 event SETUP from L2
+ *---------------------------------------------------------------------------*/
+static void F_SIGN(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_SIGN", ("FSM function F_SIGN executing\n"));
+
+/* XXX */ /* freecd_by_cd(cd); ?????????? XXX */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM relevant states event DL ESTABLISH IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLEI(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLEI", ("FSM function F_DLEI executing\n"));
+
+/* XXX */
+
+ /* remain in current state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event illegal event occured
+ *---------------------------------------------------------------------------*/
+static void F_ILL(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_ILL", ("FSM function F_ILL executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event T309 timeout
+ *---------------------------------------------------------------------------*/
+static void F_309TO(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_309TO", ("FSM function F_309TO executing\n"));
+
+/* XXX */
+
+#ifdef NOTDEF
+ i4b_l4_dl_fail_ind(cd);
+#endif
+
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event FACILITY message received
+ *---------------------------------------------------------------------------*/
+static void F_FCTY(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_FCTY", ("FSM function F_FCTY executing\n"));
+ /* ST_SUSE, no change in state ! */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_OW event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF1(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF1", ("FSM function F_DECF1 executing\n"));
+ i4b_l3_tx_setup(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWA event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF2(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF2", ("FSM function F_DECF2 executing\n"));
+ i4b_l3_tx_connect(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWR event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF3(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF3", ("FSM function F_DECF3 executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWL event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF4(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF4", ("FSM function F_DECF4 executing\n"));
+ i4b_l3_tx_alert(cd);
+}
+
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF", ("FSM function F_DECF executing\n"));
+ T309_stop(cd);
+ i4b_l3_tx_status(cd, CAUSE_Q850_NORMUNSP); /* 31, normal unspecified */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except U10 event DL RELEASE IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLRI(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLRI", ("FSM function F_DLRI executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U10 event DL RELEASE IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLRIA(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLRIA", ("FSM function F_DLRIA executing\n"));
+
+ if(cd->T309 == TIMER_IDLE)
+ T309_start(cd);
+
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_l3fsm.h b/sys/i4b/layer3/i4b_l3fsm.h
new file mode 100644
index 0000000..d69b810
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3fsm.h
@@ -0,0 +1,105 @@
+/*
+ * 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_l3fsm.c - layer 3 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l3fsm.h,v 1.5 1998/12/05 18:05:33 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:32:45 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L3FSM_H_
+#define _I4B_L3FSM_H_
+
+enum Q931_states {
+ ST_U0,
+ ST_U1,
+ ST_U3,
+ ST_U4,
+ ST_U6,
+ ST_U7,
+ ST_U8,
+ ST_U9,
+ ST_U10,
+ ST_U11,
+ ST_U12,
+ ST_U19,
+
+ ST_IWA, /* incoming call, wait establish, then accept */
+ ST_IWR, /* incoming call, wait establish, then reject */
+ ST_OW, /* outgoing call, wait establish */
+ ST_IWL, /* incoming call, wait establish, then alert */
+
+ ST_SUSE, /* SUBroutine SETs new state on exit */
+ ST_ILL, /* Illegal */
+
+ N_STATES /* number of states */
+};
+
+enum Q931_events {
+
+ EV_SETUPRQ, /* setup request from L4 */
+ EV_DISCRQ, /* disconnect request from L4 */
+ EV_RELRQ, /* release request from L4 */
+ EV_ALERTRQ, /* alerting request from L4 */
+ EV_SETACRS, /* setup response accept from l4 */
+ EV_SETRJRS, /* setup response reject from l4 */
+ EV_SETDCRS, /* setup response dontcare from l4 */
+
+ EV_SETUP, /* incoming SETUP message from L2 */
+ EV_STATUS, /* incoming STATUS message from L2 */
+ EV_RELEASE, /* incoming RELEASE message from L2 */
+ EV_RELCOMP, /* incoming RELEASE COMPLETE from L2 */
+ EV_SETUPAK, /* incoming SETUP ACK message from L2 */
+ EV_CALLPRC, /* incoming CALL PROCEEDING from L2 */
+ EV_ALERT, /* incoming ALERT message from L2 */
+ EV_CONNECT, /* incoming CONNECT message from L2 */
+ EV_PROGIND, /* incoming Progress IND from L2 */
+ EV_DISCONN, /* incoming DISCONNECT message from L2 */
+ EV_CONACK, /* incoming CONNECT ACK message from L2 */
+ EV_STATENQ, /* incoming STATUS ENQ message from L2 */
+ EV_INFO, /* incoming INFO message from L2 */
+ EV_FACILITY, /* FACILITY message */
+
+ EV_T303EXP, /* Timer T303 expired */
+ EV_T305EXP, /* Timer T305 expired */
+ EV_T308EXP, /* Timer T308 expired */
+ EV_T309EXP, /* Timer T309 expired */
+ EV_T310EXP, /* Timer T310 expired */
+ EV_T313EXP, /* Timer T313 expired */
+
+ EV_DLESTIN, /* dl establish indication from l2 */
+ EV_DLRELIN, /* dl release indication from l2 */
+ EV_DLESTCF, /* dl establish confirm from l2 */
+ EV_DLRELCF, /* dl release indication from l2 */
+
+ EV_ILL, /* Illegal */
+ N_EVENTS
+};
+
+#endif /* _I4B_L3FSM_H_ */
diff --git a/sys/i4b/layer3/i4b_l3timer.c b/sys/i4b/layer3/i4b_l3timer.c
new file mode 100644
index 0000000..6c1a2d3
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3timer.c
@@ -0,0 +1,347 @@
+/*
+ * 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_l3timer.c - timer and timeout handling for layer 3
+ * ------------------------------------------------------
+ *
+ * $Id: i4b_l3timer.c,v 1.9 1998/12/05 18:05:35 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:00 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>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#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>
+
+/*---------------------------------------------------------------------------*
+ * stop all layer 3 timers
+ *---------------------------------------------------------------------------*/
+void i4b_l3_stop_all_timers(call_desc_t *cd)
+{
+ T303_stop(cd);
+ T305_stop(cd);
+ T308_stop(cd);
+ T309_stop(cd);
+ T310_stop(cd);
+ T313_stop(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T303_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T303_timeout", ("SETUP not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T303EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 start
+ *---------------------------------------------------------------------------*/
+void
+T303_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T303_start", ("cr = %d\n", cd->cr));
+ cd->T303 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T303_callout = timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 stop
+ *---------------------------------------------------------------------------*/
+void
+T303_stop(call_desc_t *cd)
+{
+ if(cd->T303 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, cd->T303_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd);
+#endif
+ cd->T303 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T303_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T305_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T305_timeout", ("DISC not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T305EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 start
+ *---------------------------------------------------------------------------*/
+void
+T305_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T305_start", ("cr = %d\n", cd->cr));
+ cd->T305 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T305_callout = timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 stop
+ *---------------------------------------------------------------------------*/
+void
+T305_stop(call_desc_t *cd)
+{
+ if(cd->T305 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, cd->T305_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd);
+#endif
+ cd->T305 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T305_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T308_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T308_timeout", ("REL not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T308EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 start
+ *---------------------------------------------------------------------------*/
+void
+T308_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T308_start", ("cr = %d\n", cd->cr));
+ cd->T308 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T308_callout = timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 stop
+ *---------------------------------------------------------------------------*/
+void
+T308_stop(call_desc_t *cd)
+{
+ if(cd->T308 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, cd->T308_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd);
+#endif
+ cd->T308 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T308_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T309_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T309_timeout", ("datalink not reconnected, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T309EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 start
+ *---------------------------------------------------------------------------*/
+void
+T309_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T309_start", ("cr = %d\n", cd->cr));
+ cd->T309 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T309_callout = timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 stop
+ *---------------------------------------------------------------------------*/
+void
+T309_stop(call_desc_t *cd)
+{
+ if(cd->T309 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, cd->T309_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd);
+#endif
+ cd->T309 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T309_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T310_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T310_timeout", ("CALL PROC timeout, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T310EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 start
+ *---------------------------------------------------------------------------*/
+void
+T310_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T310_start", ("cr = %d\n", cd->cr));
+ cd->T310 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T310_callout = timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 stop
+ *---------------------------------------------------------------------------*/
+void
+T310_stop(call_desc_t *cd)
+{
+ if(cd->T310 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, cd->T310_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd);
+#endif
+ cd->T310 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T310_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T313_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T313_timeout", ("CONN ACK not received, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T313EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 start
+ *---------------------------------------------------------------------------*/
+void
+T313_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T313_start", ("cr = %d\n", cd->cr));
+ cd->T313 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T313_callout = timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 stop
+ *---------------------------------------------------------------------------*/
+void
+T313_stop(call_desc_t *cd)
+{
+ if(cd->T313 != TIMER_IDLE)
+ {
+ cd->T313 = TIMER_IDLE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, cd->T313_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd);
+#endif
+ }
+ DBGL3(L3_T_MSG, "T313_stop", ("cr = %d\n", cd->cr));
+}
+
+#endif /* NI4BQ931 > 0 */
+
diff --git a/sys/i4b/layer3/i4b_l4if.c b/sys/i4b/layer3/i4b_l4if.c
new file mode 100644
index 0000000..55d9bb9
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l4if.c
@@ -0,0 +1,339 @@
+/*
+ * 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_l4if.c - Layer 3 interface to Layer 4
+ * -------------------------------------------
+ *
+ * $Id: i4b_l4if.c,v 1.17 1998/12/05 18:05:36 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:16 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/include/i4b_global.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>
+
+extern void isic_settrace(int unit, int val); /*XXX*/
+extern int isic_gettrace(int unit); /*XXX*/
+
+static void n_connect_request(u_int cdid);
+static void n_connect_response(u_int cdid, int response, int cause);
+static void n_disconnect_request(u_int cdid, int cause);
+static void n_alert_request(u_int cdid);
+static void n_mgmt_command(int unit, int cmd, int parm);
+
+/*---------------------------------------------------------------------------*
+ * i4b_mdl_status_ind - status indication from lower layers
+ *---------------------------------------------------------------------------*/
+int
+i4b_mdl_status_ind(int unit, int status, int parm)
+{
+ int sendup;
+ int i;
+
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("unit = %d, status = %d, parm = %d\n", unit, status, parm));
+
+ switch(status)
+ {
+ case STI_ATTACH:
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_ATTACH: attaching unit %d to controller %d\n", unit, nctrl));
+
+ /* init function pointers */
+
+ ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request;
+ ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response;
+ ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request;
+ ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request;
+ ctrl_desc[nctrl].N_SET_TRACE = isic_settrace;
+ ctrl_desc[nctrl].N_GET_TRACE = isic_gettrace;
+ ctrl_desc[nctrl].N_DOWNLOAD = NULL; /* only used by active cards */
+ ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* only used by active cards */
+ ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command;
+
+ /* init type and unit */
+
+ ctrl_desc[nctrl].unit = unit;
+ ctrl_desc[nctrl].ctrl_type = CTRL_PASSIVE;
+ ctrl_desc[nctrl].card_type = parm;
+
+ /* state fields */
+
+ ctrl_desc[nctrl].dl_est = DL_DOWN;
+ ctrl_desc[nctrl].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[nctrl].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[nctrl].tei = -1;
+
+ /* init unit to controller table */
+
+ utoc_tab[unit] = nctrl;
+
+ /* increment no. of controllers */
+
+ nctrl++;
+
+ break;
+
+ case STI_L1STAT:
+ i4b_l4_l12stat(unit, 1, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L1STAT: unit %d layer 1 = %s\n", unit, status ? "up" : "down"));
+ break;
+
+ case STI_L2STAT:
+ i4b_l4_l12stat(unit, 2, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L2STAT: unit %d layer 2 = %s\n", unit, status ? "up" : "down"));
+ break;
+
+ case STI_TEIASG:
+ ctrl_desc[unit].tei = parm;
+ i4b_l4_teiasg(unit, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_TEIASG: unit %d TEI = %d = 0x%02x\n", unit, parm, parm));
+ break;
+
+ case STI_PDEACT: /* L1 T4 timeout */
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_PDEACT: unit %d TEI = %d = 0x%02x\n", unit, parm, parm));
+
+ sendup = 0;
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ if(call_desc[i].cdid != CDID_UNUSED)
+ sendup++;
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+
+ if(sendup)
+ i4b_l4_pdeact(unit, sendup);
+ break;
+
+ case STI_NOL1ACC: /* no outgoing access to S0 */
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_NOL1ACC: unit %d no outgoing access to S0\n", unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ if(call_desc[i].cdid != CDID_UNUSED)
+ {
+ SET_CAUSE_TYPE(call_desc[i].cause_in, CAUSET_I4B);
+ SET_CAUSE_VAL(call_desc[i].cause_in, CAUSE_I4B_L1ERROR);
+ i4b_l4_disconnect_ind(&(call_desc[i]));
+ }
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+ break;
+
+ default:
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("ERROR, unit %d, unknown status value %d!\n", unit, status));
+ break;
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * send command to the lower layers
+ *---------------------------------------------------------------------------*/
+static void
+n_mgmt_command(int unit, int cmd, int parm)
+{
+ int i;
+
+ switch(cmd)
+ {
+ case CMR_DOPEN:
+ DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DOPEN for unit %d\n", unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ call_desc[i].cdid = CDID_UNUSED;
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+ break;
+
+ case CMR_DCLOSE:
+ DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DCLOSE for unit %d\n", unit));
+ break;
+
+ default:
+ break;
+
+ }
+
+ MDL_Command_Req(unit, cmd, parm);
+
+}
+
+/*---------------------------------------------------------------------------*
+ * handle connect request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_connect_request(u_int cdid)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ next_l3state(cd, EV_SETUPRQ);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle setup response message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_connect_response(u_int cdid, int response, int cause)
+{
+ call_desc_t *cd;
+ int chstate;
+
+ cd = cd_by_cdid(cdid);
+
+ T400_stop(cd);
+
+ cd->response = response;
+ cd->cause_out = cause;
+
+ switch(response)
+ {
+ case SETUP_RESP_ACCEPT:
+ next_l3state(cd, EV_SETACRS);
+ chstate = BCH_ST_USED;
+ break;
+
+ case SETUP_RESP_REJECT:
+ next_l3state(cd, EV_SETRJRS);
+ chstate = BCH_ST_FREE;
+ break;
+
+ case SETUP_RESP_DNTCRE:
+ next_l3state(cd, EV_SETDCRS);
+ chstate = BCH_ST_FREE;
+ break;
+
+ default: /* failsafe */
+ next_l3state(cd, EV_SETDCRS);
+ chstate = BCH_ST_FREE;
+ DBGL3(L3_ERR, "n_connect_response", ("unknown response, doing SETUP_RESP_DNTCRE"));
+ break;
+ }
+
+ if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
+ {
+ ctrl_desc[cd->controller].bch_state[cd->channelid] = chstate;
+ }
+ else
+ {
+ DBGL3(L3_ERR, "n_connect_response", ("ERROR, invalid channel %d\n", cd->channelid));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * handle disconnect request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_disconnect_request(u_int cdid, int cause)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ cd->cause_out = cause;
+
+ next_l3state(cd, EV_DISCRQ);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle alert request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_alert_request(u_int cdid)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ next_l3state(cd, EV_ALERTRQ);
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q931.c b/sys/i4b/layer3/i4b_q931.c
new file mode 100644
index 0000000..6c111d1
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q931.c
@@ -0,0 +1,624 @@
+/*
+ * 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_q931.c - Q931 received messages handling
+ * --------------------------------------------
+ *
+ * $Id: i4b_q931.c,v 1.18 1998/12/05 18:05:38 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:36 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/include/i4b_global.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>
+
+#ifndef __FreeBSD__
+#define memcpy(d,s,l) bcopy(s,d,l)
+#endif
+
+unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT;
+
+call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */
+ctrl_desc_t ctrl_desc[MAX_CONTROLLERS]; /* controller description array */
+int utoc_tab[MAX_CONTROLLERS]; /* unit to controller conversion */
+
+/* protocol independent causes -> Q.931 causes */
+
+unsigned char cause_tab_q931[CAUSE_I4B_MAX] = {
+ CAUSE_Q850_NCCLR, /* CAUSE_I4B_NORMAL -> normal call clearing */
+ CAUSE_Q850_USRBSY, /* CAUSE_I4B_BUSY -> user busy */
+ CAUSE_Q850_NOCAVAIL, /* CAUSE_I4B_NOCHAN -> no circuit/channel available*/
+ CAUSE_Q850_INCDEST, /* CAUSE_I4B_INCOMP -> incompatible destination */
+ CAUSE_Q850_CALLREJ, /* CAUSE_I4B_REJECT -> call rejected */
+ CAUSE_Q850_DSTOOORDR, /* CAUSE_I4B_OOO -> destination out of order */
+ CAUSE_Q850_TMPFAIL, /* CAUSE_I4B_TMPFAIL -> temporary failure */
+};
+
+/*---------------------------------------------------------------------------*
+ * setup cr ref flag according to direction
+ *---------------------------------------------------------------------------*/
+unsigned char
+setup_cr(call_desc_t *cd, unsigned char cr)
+{
+ if(cd->crflag == CRF_ORIG)
+ return(cr & 0x7f); /* clear cr ref flag */
+ else if(cd->crflag == CRF_DEST)
+ return(cr | 0x80); /* set cr ref flag */
+ else
+ panic("setup_cr: invalid crflag!\n");
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process a Q.931 message
+ *---------------------------------------------------------------------------*/
+void
+i4b_decode_q931(int unit, int msg_len, u_char *msg_ptr)
+{
+ call_desc_t *cd;
+ int codeset = CODESET_0;
+ int old_codeset = CODESET_0;
+ int shift_flag = UNSHIFTED;
+ int crlen = 0;
+ int crval = 0;
+ int crflag = 0;
+ int i;
+ int offset;
+ int s;
+
+ /* check protocol discriminator */
+
+ if(*msg_ptr != PD_Q931)
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("protocol discriminator 0x%x != Q.931\n", *msg_ptr));
+ return;
+ }
+ msg_ptr++;
+ msg_len--;
+
+ s = SPLI4B(); /* this has to be protected ! */
+
+ /* extract call reference */
+
+ crlen = *msg_ptr & CRLENGTH_MASK;
+ msg_ptr++;
+ msg_len--;
+
+ if(crlen != 0)
+ {
+ crval += *msg_ptr & 0x7f;
+ crflag = (*msg_ptr >> 7) & 0x01;
+ msg_ptr++;
+ msg_len--;
+
+ for(i=1; i < crlen; i++)
+ {
+ crval += *msg_ptr;
+ msg_ptr++;
+ msg_len--;
+ }
+ }
+ else
+ {
+ crval = 0;
+ crflag = 0;
+ }
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931", ("Call Ref, len %d, val %d, flag %d\n", crlen, crval, crflag));
+
+ /* find or allocate calldescriptor */
+
+ if((cd = cd_by_unitcr(unit, crval,
+ crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL)
+ {
+ if(*msg_ptr == SETUP)
+ {
+ /* get and init new calldescriptor */
+
+ cd = reserve_cd(); /* cdid filled in */
+ cd->controller = utoc_tab[unit];
+ cd->cr = crval;
+ cd->crflag = CRF_DEST; /* we are the dest side */
+ cd->ilt = NULL; /* reset link tab ptrs */
+ cd->dlt = NULL;
+ }
+ else
+ {
+/*XXX*/ if(crval != 0) /* ignore global call references */
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("cannot find calldescriptor for cr = 0x%x, crflag = 0x%x, msg = 0x%x, frame = ", crval, crflag, *msg_ptr));
+ i4b_print_frame(msg_len, msg_ptr);
+ }
+ splx(s);
+ return;
+ }
+ }
+
+ splx(s);
+
+ /* decode and handle message type */
+
+ i4b_decode_q931_message(unit, cd, *msg_ptr);
+ msg_ptr++;
+ msg_len--;
+
+ /* process information elements */
+
+ while(msg_len > 0)
+ {
+ /* check for shift codeset IE */
+
+ if((*msg_ptr & 0x80) && ((*msg_ptr & 0xf0) == SOIE_SHIFT))
+ {
+ if(!(*msg_ptr & SHIFT_LOCK))
+ shift_flag = SHIFTED;
+
+ old_codeset = codeset;
+ codeset = *msg_ptr & CODESET_MASK;
+
+ if((shift_flag != SHIFTED) &&
+ (codeset <= old_codeset))
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("Q.931 lockingshift proc violation, shift %d -> %d\n", old_codeset, codeset));
+ codeset = old_codeset;
+ }
+ msg_len--;
+ msg_ptr++;
+ }
+
+ /* process one IE for selected codeset */
+
+ switch(codeset)
+ {
+ case CODESET_0:
+ offset = i4b_decode_q931_cs0_ie(unit, cd, msg_len, msg_ptr);
+ msg_len -= offset;
+ msg_ptr += offset;
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("unknown codeset %d, ", codeset));
+ i4b_print_frame(msg_len, msg_ptr);
+ msg_len = 0;
+ break;
+ }
+
+ /* check for non-locking shifts */
+
+ if(shift_flag == SHIFTED)
+ {
+ shift_flag = UNSHIFTED;
+ codeset = old_codeset;
+ }
+ }
+ next_l3state(cd, cd->event);
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process one Q.931 codeset 0 information element
+ *---------------------------------------------------------------------------*/
+int
+i4b_decode_q931_cs0_ie(int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr)
+{
+ int i, j;
+ char *p;
+
+ switch(*msg_ptr)
+ {
+ /* single byte IE's */
+
+ case IEI_SENDCOMPL:
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_SENDCOMPL\n"));
+ return(1);
+ break;
+
+ /* multi byte IE's */
+
+ case IEI_BEARERCAP: /* bearer capability */
+ switch(msg_ptr[2])
+ {
+ case 0x80: /* speech */
+ case 0x89: /* restricted digital info */
+ case 0x90: /* 3.1KHz audio */
+/* XXX */ cd->bprot = BPROT_NONE;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Telephony\n"));
+ break;
+
+ case 0x88: /* unrestricted digital info */
+/* XXX */ cd->bprot = BPROT_RHDLC;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Raw HDLC\n"));
+ break;
+
+ default:
+/* XXX */ cd->bprot = BPROT_NONE;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - No Protocol\n"));
+ break;
+ }
+ break;
+
+ case IEI_CAUSE: /* cause */
+ if(msg_ptr[2] & 0x80)
+ {
+ cd->cause_in = msg_ptr[3] & 0x7f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[3] & 0x7f));
+ }
+ else
+ {
+ cd->cause_in = msg_ptr[4] & 0x7f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[4] & 0x7f));
+ }
+ break;
+
+ case IEI_CHANNELID: /* channel id */
+ if((msg_ptr[2] & 0xf4) != 0x80)
+ {
+ cd->channelid = CHAN_NO;
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IEI_CHANNELID, unsupported value 0x%x\n", msg_ptr[2]));
+ }
+ else
+ {
+ switch(msg_ptr[2] & 0x03)
+ {
+ case IE_CHAN_ID_NO:
+ cd->channelid = CHAN_NO;
+ break;
+ case IE_CHAN_ID_B1:
+ cd->channelid = CHAN_B1;
+ break;
+ case IE_CHAN_ID_B2:
+ cd->channelid = CHAN_B2;
+ break;
+ case IE_CHAN_ID_ANY:
+ cd->channelid = CHAN_ANY;
+ break;
+ }
+ cd->channelexcl = (msg_ptr[2] & 0x08) >> 3;
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CHANNELID - channel %d, exclusive = %d\n", cd->channelid, cd->channelexcl));
+
+ /* if this is a setup message, reserve channel */
+
+ if(cd->event == EV_SETUP)
+ {
+ if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
+ {
+ if(ctrl_desc[cd->controller].bch_state[cd->channelid] == BCH_ST_FREE)
+ ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD;
+ else
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IE ChannelID, Channel NOT free!!\n"));
+ }
+ else if(cd->channelid == CHAN_NO)
+ {
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IE ChannelID, SETUP with channel = No channel (CW)\n"));
+ }
+ else /* cd->channelid == CHAN_ANY */
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("ERROR: IE ChannelID, SETUP with channel = Any channel!\n"));
+ }
+ }
+ }
+ break;
+
+ case IEI_CALLINGPN: /* calling party no */
+ if(msg_ptr[2] & 0x80) /* no presentation/screening indicator ? */
+ {
+ memcpy(cd->src_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
+ cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 1)] = '\0';
+ cd->scr_ind = SCR_NONE;
+ }
+ else
+ {
+ memcpy(cd->src_telno, &msg_ptr[4], min(TELNO_MAX, msg_ptr[1]-2));
+ cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 2)] = '\0';
+ cd->scr_ind = (msg_ptr[3] & 0x03) + SCR_USR_NOSC;
+ }
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLINGPN = %s\n", cd->src_telno));
+ break;
+
+ case IEI_CALLEDPN: /* called party number */
+ memcpy(cd->dst_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
+ cd->dst_telno[min(TELNO_MAX, msg_ptr [1] - 1)] = '\0';
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLED = %s\n", cd->dst_telno));
+ break;
+
+ case IEI_CALLSTATE: /* call state */
+ cd->call_state = msg_ptr[2] & 0x3f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLSTATE = %d\n", cd->call_state));
+ break;
+
+ case IEI_PROGRESSI: /* progress indicator */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_PROGRESSINDICATOR\n"));
+ break;
+
+ case IEI_DISPLAY: /* display */
+ /* CHANGED BY <chris@medis.de> */
+ memcpy(cd->display, &msg_ptr[2], min(DISPLAY_MAX, msg_ptr[1]));
+ cd->display[min(DISPLAY_MAX, msg_ptr[1])] = '\0';
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DISPLAY = %s\n", cd->display));
+ break;
+
+ case IEI_DATETIME: /* date/time */
+ i = 2;
+ j = msg_ptr[1];
+ p = &(cd->datetime[0]);
+ *p = '\0';
+
+ for(j = msg_ptr[1]; j > 0; j--, i++)
+ sprintf(p+strlen(p), "%02d", msg_ptr[i]);
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DATETIME = %s\n", cd->datetime));
+ break;
+
+ case IEI_FACILITY: /* facility */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_FACILITY\n"));
+ if(i4b_aoc(msg_ptr, cd) > -1)
+ i4b_l4_charging_ind(cd);
+ break;
+
+ case IEI_CONCTDNO: /* connected number */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CONCTDNO\n"));
+ break;
+
+ case IEI_NETSPCFAC: /* network specific fac */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_NETSPCFAC\n"));
+ break;
+
+ case IEI_LLCOMPAT: /* low layer compat */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_LLCOMPAT\n"));
+ break;
+
+ case IEI_HLCOMPAT: /* high layer compat */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_HLCOMPAT\n"));
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("Unknown IE %d - ", *msg_ptr));
+ i4b_print_frame(msg_ptr[1]+2, msg_ptr);
+ break;
+ }
+ return(msg_ptr[1] + 2);
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process one Q.931 codeset 0 information element
+ *---------------------------------------------------------------------------*/
+void
+i4b_decode_q931_message(int unit, call_desc_t *cd, u_char message_type)
+{
+ cd->event = EV_ILL;
+
+ switch(message_type)
+ {
+ /* call establishment */
+
+ case ALERT:
+ cd->event = EV_ALERT;
+ DBGL3(L3_PRIM, "rx ALERT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case CALL_PROCEEDING:
+ cd->event = EV_CALLPRC;
+ DBGL3(L3_PRIM, "rx CALL-PROC", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case PROGRESS:
+ cd->event = EV_PROGIND;
+ DBGL3(L3_PRIM, "rx PROGRESS", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SETUP:
+ DBGL3(L3_PRIM, "rx SETUP", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->bprot = BPROT_NONE;
+ cd->cause_in = 0;
+ cd->cause_out = 0;
+ cd->dst_telno[0] = '\0';
+ cd->src_telno[0] = '\0';
+ cd->channelid = CHAN_NO;
+ cd->channelexcl = 0;
+ cd->display[0] = '\0';
+ cd->datetime[0] = '\0';
+ cd->event = EV_SETUP;
+ break;
+
+ case CONNECT:
+ DBGL3(L3_PRIM, "rx CONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->datetime[0] = '\0';
+ cd->event = EV_CONNECT;
+ break;
+
+ case SETUP_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx SETUP-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_SETUPAK;
+ break;
+
+ case CONNECT_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_CONACK;
+ break;
+
+ /* call information */
+
+ case USER_INFORMATION:
+ DBGL3(L3_PRIM, "rx USER-INFO", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND_REJECT:
+ DBGL3(L3_PRIM, "rx SUSPEND-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME_REJECT:
+ DBGL3(L3_PRIM, "rx RESUME-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD:
+ DBGL3(L3_PRIM, "rx HOLD", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND:
+ DBGL3(L3_PRIM, "rx SUSPEND", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME:
+ DBGL3(L3_PRIM, "rx RESUME", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx HOLD-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx SUSPEND-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RESUME-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD_REJECT:
+ DBGL3(L3_PRIM, "rx HOLD-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE:
+ DBGL3(L3_PRIM, "rx RETRIEVE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RETRIEVE-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE_REJECT:
+ DBGL3(L3_PRIM, "rx RETRIEVE-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ /* call clearing */
+
+ case DISCONNECT:
+ DBGL3(L3_PRIM, "rx DISCONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_DISCONN;
+ break;
+
+ case RESTART:
+ DBGL3(L3_PRIM, "rx RESTART", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RELEASE:
+ DBGL3(L3_PRIM, "rx RELEASE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_RELEASE;
+ break;
+
+ case RESTART_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RESTART-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RELEASE_COMPLETE:
+ DBGL3(L3_PRIM, "rx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_RELCOMP;
+ break;
+
+ /* misc messages */
+
+ case SEGMENT:
+ DBGL3(L3_PRIM, "rx SEGMENT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case FACILITY:
+ DBGL3(L3_PRIM, "rx FACILITY", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_FACILITY;
+ break;
+
+ case REGISTER:
+ DBGL3(L3_PRIM, "rx REGISTER", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case NOTIFY:
+ DBGL3(L3_PRIM, "rx NOTIFY", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case STATUS_ENQUIRY:
+ DBGL3(L3_PRIM, "rx STATUS-ENQ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_STATENQ;
+ break;
+
+ case CONGESTION_CONTROL:
+ DBGL3(L3_PRIM, "rx CONGESTION-CONTROL", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case INFORMATION:
+ DBGL3(L3_PRIM, "rx INFORMATION", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_INFO;
+ break;
+
+ case STATUS:
+ DBGL3(L3_PRIM, "rx STATUS", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_STATUS;
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "rx UNKNOWN msg", ("unit %d, cr = 0x%02x, msg = 0x%02x\n", unit, cd->cr, message_type));
+ break;
+ }
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q931.h b/sys/i4b/layer3/i4b_q931.h
new file mode 100644
index 0000000..cb916b0
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q931.h
@@ -0,0 +1,116 @@
+/*
+ * 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_q931.h - Q931 handling header file
+ * --------------------------------------
+ *
+ * $Id: i4b_q931.h,v 1.5 1998/12/05 18:05:39 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:53 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_Q931_H_
+#define _I4B_Q931_H_
+
+/* extension bit */
+
+#define EXT_LAST 0x80 /* last octett */
+
+/* reserve space in mbuf */
+
+#define I_FRAME_HDRLEN 4 /* to be added by layer 2 */
+
+/* SHIFT */
+
+#define CODESET_MASK 0x07
+#define UNSHIFTED 0
+#define SHIFTED 1
+#define CRLENGTH_MASK 0x0f
+
+/* CONNECT */
+
+#define MSG_CONNECT_LEN 4 /* length of a connect message */
+
+/* DISCONNECT */
+
+#define MSG_DISCONNECT_LEN 8 /* length of a disconnect message */
+
+/* RELEASE COMPLETE */
+
+#define MSG_RELEASE_COMPLETE_LEN 8 /* length of release complete msg */
+
+/* for outgoing causes */
+
+#define CAUSE_LEN 2
+#define CAUSE_STD_LOC_OUT 0x80 /* std = CCITT, loc = user */
+
+/* SETUP */
+
+#define MSG_SETUP_LEN 18 /* without number strings ! */
+
+#define IEI_BEARERCAP_LEN 2 /* 2 octetts lenght */
+
+#define IT_CAP_SPEECH 0x80 /* BC: information xfer capability */
+#define IT_CAP_UNR_DIG_INFO 0x88 /* BC: information xfer capability */
+
+#define IT_RATE_64K 0x90 /* BC: information xfer rate */
+#define IT_UL1_G711A 0xa3 /* layer1 proto G.711 A-law */
+
+#define IEI_CHANNELID_LEN 0x01 /* length of channel id */
+#define CHANNELID_B1 0x81 /* channel = B1 (outgoing) */
+#define CHANNELID_B2 0x82 /* channel = B2 (outgoing) */
+#define CHANNELID_ANY 0x83 /* channel = any channel (outgoing) */
+
+#define IE_CHAN_ID_NO 0x00 /* no channel (incoming) */
+#define IE_CHAN_ID_B1 0x01 /* B1 channel (incoming) */
+#define IE_CHAN_ID_B2 0x02 /* B2 channel (incoming) */
+#define IE_CHAN_ID_ANY 0x03 /* ANY channel (incoming) */
+
+#define NUMBER_TYPEPLAN 0x81 /* type of number/numbering plan */
+
+#define IEI_CALLINGPN_LEN 1 /* without number string ! */
+
+#define IEI_CALLEDPN_LEN 1 /* without number string ! */
+
+/* CONNECT_ACK */
+
+#define MSG_CONNECT_ACK_LEN 4 /* length of a connect ack message */
+
+/* STATUS */
+
+#define MSG_STATUS_LEN 11
+#define CALLSTATE_LEN 1
+
+/* RELEASE */
+
+#define MSG_RELEASE_LEN 8 /* length of release msg */
+
+/* ALERT */
+
+#define MSG_ALERT_LEN 4 /* length of a alert message */
+
+#endif /* _I4B_Q931_H_ */
diff --git a/sys/i4b/layer3/i4b_q932fac.c b/sys/i4b/layer3/i4b_q932fac.c
new file mode 100644
index 0000000..487ce00
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q932fac.c
@@ -0,0 +1,569 @@
+/*
+ * 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_q932fac.c - Q932 facility handling
+ * --------------------------------------
+ *
+ * $Id: i4b_q932fac.c,v 1.5 1998/12/05 18:05:41 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:34:11 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>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.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/layer3/i4b_q932fac.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+static int do_component(int length);
+static void next_state(int class, int form, int code, int val);
+
+static int byte_len;
+static unsigned char *byte_buf;
+static int state;
+
+static int units;
+static int operation_value;
+
+/*---------------------------------------------------------------------------*
+ * decode Q.931/Q.932 facility info element
+ *---------------------------------------------------------------------------*/
+int
+i4b_aoc(unsigned char *buf, call_desc_t *cd)
+{
+ int len;
+
+ cd->units_type = CHARGE_INVALID;
+ cd->units = -1;
+
+ buf++; /* length */
+
+ len = *buf;
+
+ buf++; /* protocol profile */
+
+ switch(*buf & 0x1f)
+ {
+ case FAC_PROTO_ROP:
+ break;
+
+ case FAC_PROTO_CMIP:
+ DBGL3(L3_A_MSG, "i4b_facility", ("CMIP Protocol (Q.941), UNSUPPORTED\n"));
+ return(-1);
+ break;
+
+ case FAC_PROTO_ACSE:
+ DBGL3(L3_A_MSG, "i4b_facility", ("ACSE Protocol (X.217/X.227), UNSUPPORTED!\n"));
+ return(-1);
+ break;
+
+ default:
+ DBGL3(L3_A_ERR, "i4b_facility", ("Unknown Protocol, UNSUPPORTED!\n"));
+ return(-1);
+ break;
+ }
+
+ DBGL3(L3_A_MSG, "i4b_facility", ("Remote Operations Protocol\n"));
+
+ /* next byte */
+
+ buf++;
+ len--;
+
+ /* initialize variables for do_component */
+
+ byte_len = 0;
+ byte_buf = buf;
+ state = ST_EXP_COMP_TYP;
+
+ /* decode facility */
+
+ do_component(len);
+
+ switch(operation_value)
+ {
+ case FAC_OPVAL_AOC_D_CUR:
+ cd->units_type = CHARGE_AOCD;
+ cd->units = 0;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_D_UNIT:
+ cd->units_type = CHARGE_AOCD;
+ cd->units = units;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_E_CUR:
+ cd->units_type = CHARGE_AOCE;
+ cd->units = 0;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_E_UNIT:
+ cd->units_type = CHARGE_AOCE;
+ cd->units = units;
+ return(0);
+ break;
+
+ default:
+ cd->units_type = CHARGE_INVALID;
+ cd->units = -1;
+ return(-1);
+ break;
+ }
+ return(-1);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle a component recursively
+ *---------------------------------------------------------------------------*/
+static int
+do_component(int length)
+{
+ int comp_tag_class; /* component tag class */
+ int comp_tag_form; /* component form: constructor or primitive */
+ int comp_tag_code; /* component code depending on class */
+ int comp_length = 0; /* component length */
+
+again:
+
+ /*----------------------------------------*/
+ /* first component element: component tag */
+ /*----------------------------------------*/
+
+ /* tag class bits */
+
+ comp_tag_class = (*byte_buf & 0xc0) >> 6;
+
+ switch(comp_tag_class)
+ {
+ case FAC_TAGCLASS_UNI:
+ break;
+ case FAC_TAGCLASS_APW:
+ break;
+ case FAC_TAGCLASS_COS:
+ break;
+ case FAC_TAGCLASS_PRU:
+ break;
+ }
+
+ /* tag form bit */
+
+ comp_tag_form = (*byte_buf & 0x20) > 5;
+
+ /* tag code bits */
+
+ comp_tag_code = *byte_buf & 0x1f;
+
+ if(comp_tag_code == 0x1f)
+ {
+ comp_tag_code = 0;
+
+ byte_buf++;
+ byte_len++;
+
+ while(*byte_buf & 0x80)
+ {
+ comp_tag_code += (*byte_buf & 0x7f);
+ byte_buf++;
+ byte_len++;
+ }
+ comp_tag_code += (*byte_buf & 0x7f);
+ }
+ else
+ {
+ comp_tag_code = (*byte_buf & 0x1f);
+ }
+
+ byte_buf++;
+ byte_len++;
+
+ /*--------------------------------------------*/
+ /* second component element: component length */
+ /*--------------------------------------------*/
+
+ comp_length = 0;
+
+ if(*byte_buf & 0x80)
+ {
+ int i = *byte_buf & 0x7f;
+
+ byte_len += i;
+
+ for(;i > 0;i++)
+ {
+ byte_buf++;
+ comp_length += (*byte_buf * (i*256));
+ }
+ }
+ else
+ {
+ comp_length = *byte_buf & 0x7f;
+ }
+
+ next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1);
+
+ byte_len++;
+ byte_buf++;
+
+ /*---------------------------------------------*/
+ /* third component element: component contents */
+ /*---------------------------------------------*/
+
+ if(comp_tag_form) /* == constructor */
+ {
+ do_component(comp_length);
+ }
+ else
+ {
+ int val = 0;
+ if(comp_tag_class == FAC_TAGCLASS_UNI)
+ {
+ switch(comp_tag_code)
+ {
+ case FAC_CODEUNI_INT:
+ case FAC_CODEUNI_ENUM:
+ case FAC_CODEUNI_BOOL:
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ val += (*byte_buf + (i*255));
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ break;
+ default:
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ break;
+ }
+ }
+
+ else /* comp_tag_class != FAC_TAGCLASS_UNI */
+ {
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ val += (*byte_buf + (i*255));
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ }
+ next_state(comp_tag_class, comp_tag_form, comp_tag_code, val);
+ }
+
+ if(byte_len < length)
+ goto again;
+
+ return(byte_len);
+}
+
+/*---------------------------------------------------------------------------*
+ * invoke component
+ *---------------------------------------------------------------------------*/
+static void
+F_1_1(int val)
+{
+ if(val == -1)
+ {
+ state = ST_EXP_INV_ID;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * return result
+ *---------------------------------------------------------------------------*/
+static void
+F_1_2(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+/*---------------------------------------------------------------------------*
+ * return error
+ *---------------------------------------------------------------------------*/
+static void
+F_1_3(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+/*---------------------------------------------------------------------------*
+ * reject
+ *---------------------------------------------------------------------------*/
+static void
+F_1_4(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+
+/*---------------------------------------------------------------------------*
+ * invoke id
+ *---------------------------------------------------------------------------*/
+static void
+F_2(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Invoke ID = %d\n", val));
+ state = ST_EXP_OP_VAL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * operation value
+ *---------------------------------------------------------------------------*/
+static void
+F_3(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Operation Value = %d\n", val));
+
+ operation_value = val;
+
+ if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT))
+ {
+ units = 0;
+ state = ST_EXP_INFO;
+ }
+ else
+ {
+ state = ST_EXP_NIX;
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * specific charging units
+ *---------------------------------------------------------------------------*/
+static void
+F_4(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RUL;
+}
+
+/*---------------------------------------------------------------------------*
+ * free of charge
+ *---------------------------------------------------------------------------*/
+static void
+F_4_1(int val)
+{
+ if(val == -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Free of Charge\n"));
+ /* units = 0; XXXX */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * charge not available
+ *---------------------------------------------------------------------------*/
+static void
+F_4_2(int val)
+{
+ if(val == -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Charge not available\n"));
+ /* units = -1; XXXXXX ??? */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * recorded units list
+ *---------------------------------------------------------------------------*/
+static void
+F_5(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RU;
+}
+
+/*---------------------------------------------------------------------------*
+ * recorded units
+ *---------------------------------------------------------------------------*/
+static void
+F_6(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RNOU;
+}
+
+/*---------------------------------------------------------------------------*
+ * number of units
+ *---------------------------------------------------------------------------*/
+static void
+F_7(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Number of Units = %d\n", val));
+ units = val;
+ state = ST_EXP_TOCI;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * subtotal/total
+ *---------------------------------------------------------------------------*/
+static void
+F_8(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Subtotal/Total = %d\n", val));
+ /* type_of_charge = val; */
+ state = ST_EXP_DBID;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * billing_id
+ *---------------------------------------------------------------------------*/
+static void
+F_9(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Billing ID = %d\n", val));
+ /* billing_id = val; */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static struct statetab {
+ int currstate; /* input: current state we are in */
+ int form; /* input: current tag form */
+ int class; /* input: current tag class */
+ int code; /* input: current tag code */
+ void (*func)(int); /* output: func to exec */
+} statetab[] = {
+
+/* current state tag form tag class tag code function */
+/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 },
+ {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 },
+ {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 },
+ {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 },
+ {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 },
+ {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 },
+ {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 },
+ {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 },
+ {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 },
+ {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 },
+ {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 },
+ {-1, -1, -1, -1, NULL }
+};
+
+/*---------------------------------------------------------------------------*
+ * state decode for do_component
+ *---------------------------------------------------------------------------*/
+static void
+next_state(int class, int form, int code, int val)
+{
+ int i;
+
+ for(i=0; ; i++)
+ {
+ if((statetab[i].currstate > state) ||
+ (statetab[i].currstate == -1))
+ {
+ break;
+ }
+
+ if((statetab[i].currstate == state) &&
+ (statetab[i].form == form) &&
+ (statetab[i].class == class) &&
+ (statetab[i].code == code))
+ {
+ (*statetab[i].func)(val);
+ break;
+ }
+ }
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q932fac.h b/sys/i4b/layer3/i4b_q932fac.h
new file mode 100644
index 0000000..d7544a8
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q932fac.h
@@ -0,0 +1,167 @@
+/*
+ * 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_q932fac.h - Q932 facility handling header file
+ * --------------------------------------------------
+ *
+ * $Id: i4b_q932fac.h,v 1.5 1998/12/18 17:17:57 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 18:17:23 1998]
+ *
+ *---------------------------------------------------------------------------
+ *
+ * - Q.932 (03/93) Generic Procedures for the Control of
+ * ISDN Supplementaty Services
+ * - Q.950 (03/93) Supplementary Services Protocols, Structure and
+ * General Principles
+ * - ETS 300 179 (10/92) Advice Of Charge: charging information during
+ * the call (AOC-D) supplementary service Service description
+ * - ETS 300 180 (10/92) Advice Of Charge: charging information at the
+ * end of call (AOC-E) supplementary service Service description
+ * - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service
+ * Functional capabilities and information flows
+ * - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service
+ * Digital Subscriber Signalling System No. one (DSS1) protocol
+ * - X.208 Specification of Abstract Syntax Notation One (ASN.1)
+ * - X.209 Specification of Basic Encoding Rules for
+ * Abstract Syntax Notation One (ASN.1)
+ * - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag
+ * 1992, 3rd Edition (ISBN 3-89238-062-7) (german !)
+ *
+ *---------------------------------------------------------------------------*/
+
+/* protocols */
+#define FAC_PROTO_ROP 0x11
+#define FAC_PROTO_CMIP 0x12
+#define FAC_PROTO_ACSE 0x13
+
+/* tag classes */
+#define FAC_TAGCLASS_UNI 0x00
+#define FAC_TAGCLASS_APW 0x01
+#define FAC_TAGCLASS_COS 0x02
+#define FAC_TAGCLASS_PRU 0x03
+
+/* tag forms */
+#define FAC_TAGFORM_PRI 0x00
+#define FAC_TAGFORM_CON 0x01
+
+/* class UNIVERSAL values */
+#define FAC_CODEUNI_BOOL 1
+#define FAC_CODEUNI_INT 2
+#define FAC_CODEUNI_BITS 3
+#define FAC_CODEUNI_OCTS 4
+#define FAC_CODEUNI_NULL 5
+#define FAC_CODEUNI_OBJI 6
+#define FAC_CODEUNI_OBJD 7
+#define FAC_CODEUNI_EXT 8
+#define FAC_CODEUNI_REAL 9
+#define FAC_CODEUNI_ENUM 10
+#define FAC_CODEUNI_R11 11
+#define FAC_CODEUNI_R12 12
+#define FAC_CODEUNI_R13 13
+#define FAC_CODEUNI_R14 14
+#define FAC_CODEUNI_R15 15
+#define FAC_CODEUNI_SEQ 16
+#define FAC_CODEUNI_SET 17
+#define FAC_CODEUNI_NSTR 18
+#define FAC_CODEUNI_PSTR 19
+#define FAC_CODEUNI_TSTR 20
+#define FAC_CODEUNI_VSTR 21
+#define FAC_CODEUNI_ISTR 22
+#define FAC_CODEUNI_UTIME 23
+#define FAC_CODEUNI_GTIME 24
+#define FAC_CODEUNI_GSTR 25
+#define FAC_CODEUNI_VISTR 26
+#define FAC_CODEUNI_GNSTR 27
+
+/* operation values */
+#define FAC_OPVAL_UUS 1
+#define FAC_OPVAL_CUG 2
+#define FAC_OPVAL_MCID 3
+#define FAC_OPVAL_BTPY 4
+#define FAC_OPVAL_ETPY 5
+#define FAC_OPVAL_ECT 6
+
+#define FAC_OPVAL_DIV_ACT 7
+#define FAC_OPVAL_DIV_DEACT 8
+#define FAC_OPVAL_DIV_ACTSN 9
+#define FAC_OPVAL_DIV_DEACTSN 10
+#define FAC_OPVAL_DIV_INTER 11
+#define FAC_OPVAL_DIV_INFO 12
+#define FAC_OPVAL_DIV_CALLDEF 13
+#define FAC_OPVAL_DIV_CALLRER 14
+#define FAC_OPVAL_DIV_LINF2 15
+#define FAC_OPVAL_DIV_INVS 16
+#define FAC_OPVAL_DIV_INTER1 17
+#define FAC_OPVAL_DIV_LINF1 18
+#define FAC_OPVAL_DIV_LINF3 19
+
+#define FAC_OPVAL_ER_CRCO 20
+#define FAC_OPVAL_ER_MGMT 21
+#define FAC_OPVAL_ER_CANC 22
+
+#define FAC_OPVAL_MLPP_QUERY 24
+#define FAC_OPVAL_MLPP_CALLR 25
+#define FAC_OPVAL_MLPP_CALLP 26
+
+#define FAC_OPVAL_AOC_REQ 30
+#define FAC_OPVAL_AOC_S_CUR 31
+#define FAC_OPVAL_AOC_S_SPC 32
+#define FAC_OPVAL_AOC_D_CUR 33
+#define FAC_OPVAL_AOC_D_UNIT 34
+#define FAC_OPVAL_AOC_E_CUR 35
+#define FAC_OPVAL_AOC_E_UNIT 36
+#define FAC_OPVAL_AOC_IDOFCRG 37
+
+#define FAC_OPVAL_CONF_BEG 40
+#define FAC_OPVAL_CONF_ADD 41
+#define FAC_OPVAL_CONF_SPLIT 42
+#define FAC_OPVAL_CONF_DROP 43
+#define FAC_OPVAL_CONF_ISOLATE 44
+#define FAC_OPVAL_CONF_REATT 45
+#define FAC_OPVAL_CONF_PDISC 46
+#define FAC_OPVAL_CONF_FCONF 47
+#define FAC_OPVAL_CONF_END 48
+#define FAC_OPVAL_CONF_IDCFE 49
+
+#define FAC_OPVAL_REVC_REQ 60
+
+enum states {
+ ST_EXP_COMP_TYP,
+ ST_EXP_INV_ID,
+ ST_EXP_OP_VAL,
+ ST_EXP_INFO,
+ ST_EXP_RUL,
+ ST_EXP_RU,
+ ST_EXP_RNOU,
+ ST_EXP_TOCI,
+ ST_EXP_DBID,
+
+ ST_EXP_NIX
+};
+
+/* EOF */
+
OpenPOWER on IntegriCloud