summaryrefslogtreecommitdiffstats
path: root/sys/netatm/uni/unisig_sigmgr_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/uni/unisig_sigmgr_state.c')
-rw-r--r--sys/netatm/uni/unisig_sigmgr_state.c860
1 files changed, 860 insertions, 0 deletions
diff --git a/sys/netatm/uni/unisig_sigmgr_state.c b/sys/netatm/uni/unisig_sigmgr_state.c
new file mode 100644
index 0000000..2fbbfca
--- /dev/null
+++ b/sys/netatm/uni/unisig_sigmgr_state.c
@@ -0,0 +1,860 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: unisig_sigmgr_state.c,v 1.10 1998/08/26 23:29:24 mks Exp $
+ *
+ */
+
+/*
+ * ATM Forum UNI 3.0/3.1 Signalling Manager
+ * ----------------------------------------
+ *
+ * Signalling manager finite state machine
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: unisig_sigmgr_state.c,v 1.10 1998/08/26 23:29:24 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/uni/uni.h>
+#include <netatm/uni/unisig.h>
+#include <netatm/uni/unisig_var.h>
+#include <netatm/uni/unisig_msg.h>
+#include <netatm/uni/unisig_mbuf.h>
+#include <netatm/uni/unisig_decode.h>
+
+#include <netatm/uni/sscf_uni.h>
+
+
+/*
+ * Local functions
+ */
+static int unisig_sigmgr_invalid __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act01 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act02 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act03 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act04 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act05 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act06 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act07 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act08 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act09 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act10 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act11 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act12 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act13 __P((struct unisig *, KBuffer *));
+static int unisig_sigmgr_act14 __P((struct unisig *, KBuffer *));
+
+
+/*
+ * State table.
+ */
+static int sigmgr_state_table[10][7] = {
+ /* 0 1 2 3 4 5 */
+ { 1, 0, 0, 0, 0 }, /* 0 - Time out */
+ { 0, 0, 3, 5, 0 }, /* 1 - SSCF estab ind */
+ { 0, 0, 3, 5, 0 }, /* 2 - SSCF estab cnf */
+ { 0, 0, 4, 6, 0 }, /* 3 - SSCF release ind */
+ { 0, 0, 0, 6, 0 }, /* 4 - SSCF release cnf */
+ { 0, 0, 0, 7, 0 }, /* 5 - SSCF data ind */
+ { 0, 0, 2, 2, 0 }, /* 6 - SSCF unit data ind */
+ { 0, 0, 8, 8, 8 }, /* 7 - Call cleared */
+ { 14, 14, 14, 14, 0 }, /* 8 - Detach */
+ { 13, 13, 0, 0, 0 } /* 9 - Address set */
+};
+
+/*
+ * Action vector
+ */
+#define MAX_ACTION 15
+static int (*unisig_sigmgr_act_vec[MAX_ACTION])
+ __P((struct unisig *, KBuffer *)) = {
+ unisig_sigmgr_invalid,
+ unisig_sigmgr_act01,
+ unisig_sigmgr_act02,
+ unisig_sigmgr_act03,
+ unisig_sigmgr_act04,
+ unisig_sigmgr_act05,
+ unisig_sigmgr_act06,
+ unisig_sigmgr_act07,
+ unisig_sigmgr_act08,
+ unisig_sigmgr_act09,
+ unisig_sigmgr_act10,
+ unisig_sigmgr_act11,
+ unisig_sigmgr_act12,
+ unisig_sigmgr_act13,
+ unisig_sigmgr_act14
+};
+
+
+/*
+ * ATM endpoint for UNI signalling channel
+ */
+static Atm_endpoint unisig_endpt = {
+ NULL, /* ep_next */
+ ENDPT_UNI_SIG, /* ep_id */
+ NULL, /* ep_ioctl */
+ unisig_getname, /* ep_getname */
+ unisig_connected, /* ep_connected */
+ unisig_cleared, /* ep_cleared */
+ NULL, /* ep_incoming */
+ NULL, /* ep_addparty */
+ NULL, /* ep_dropparty */
+ NULL, /* ep_cpcs_ctl */
+ NULL, /* ep_cpcs_data */
+ unisig_saal_ctl, /* ep_saal_ctl */
+ unisig_saal_data, /* ep_saal_data */
+ NULL, /* ep_sscop_ctl */
+ NULL /* ep_sscop_data */
+};
+
+
+/*
+ * ATM connection attributes for UNI signalling channel
+ */
+static Atm_attributes unisig_attr = {
+ NULL, /* nif */
+ CMAPI_SAAL, /* api */
+ UNI_VERS_3_0, /* api_init */
+ 0, /* headin */
+ 0, /* headout */
+ { /* aal */
+ T_ATM_PRESENT, /* aal.tag */
+ ATM_AAL5 /* aal.aal_type */
+ },
+ { /* traffic */
+ T_ATM_PRESENT, /* traffic.tag */
+ { /* traffic.v */
+ { /* traffic.v.forward */
+ T_ATM_ABSENT, /* PCR_high */
+ 0, /* PCR_all */
+ T_ATM_ABSENT, /* SCR_high */
+ T_ATM_ABSENT, /* SCR_all */
+ T_ATM_ABSENT, /* MBS_high */
+ T_ATM_ABSENT, /* MBS_all */
+ T_NO, /* tagging */
+ },
+ { /* traffic.v.backward */
+ T_ATM_ABSENT, /* PCR_high */
+ 0, /* PCR_all */
+ T_ATM_ABSENT, /* SCR_high */
+ T_ATM_ABSENT, /* SCR_all */
+ T_ATM_ABSENT, /* MBS_high */
+ T_ATM_ABSENT, /* MBS_all */
+ T_NO, /* tagging */
+ },
+ T_YES, /* best_effort */
+ }
+ },
+ { /* bearer */
+ T_ATM_PRESENT, /* bearer.tag */
+ { /* bearer.v */
+ T_ATM_CLASS_X, /* class */
+ T_ATM_NULL, /* traffic_type */
+ T_ATM_NO_END_TO_END, /* timing_req */
+ T_NO, /* clipping */
+ T_ATM_1_TO_1, /* conn_conf */
+ }
+ },
+ { /* bhli */
+ T_ATM_ABSENT, /* bhli.tag */
+ },
+ { /* blli */
+ T_ATM_ABSENT, /* blli.tag_l2 */
+ T_ATM_ABSENT, /* blli.tag_l3 */
+ },
+ { /* llc */
+ T_ATM_ABSENT, /* llc.tag */
+ },
+ { /* called */
+ T_ATM_PRESENT, /* called.tag */
+ },
+ { /* calling */
+ T_ATM_ABSENT, /* calling.tag */
+ },
+ { /* qos */
+ T_ATM_PRESENT, /* qos.tag */
+ { /* qos.v */
+ T_ATM_NETWORK_CODING, /* coding_standard */
+ { /* qos.v.forward */
+ T_ATM_QOS_CLASS_0, /* class */
+ },
+ { /* qos.v.backward */
+ T_ATM_QOS_CLASS_0, /* class */
+ }
+ }
+ },
+ { /* transit */
+ T_ATM_ABSENT, /* transit.tag */
+ },
+ { /* cause */
+ T_ATM_ABSENT, /* cause.tag */
+ }
+};
+
+
+/*
+ * Finite state machine for the UNISIG signalling manager
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * event indication of the event to be processed
+ * m pointer to a buffer with a message (optional)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+int
+unisig_sigmgr_state(usp, event, m)
+ struct unisig *usp;
+ int event;
+ KBuffer *m;
+{
+ int action, err = 0;
+
+ /*
+ * Cancel any signalling manager timer
+ */
+ UNISIG_CANCEL(usp);
+
+ /*
+ * Select an action based on the incoming event and
+ * the signalling manager's state
+ */
+ action = sigmgr_state_table[event][usp->us_state];
+ ATM_DEBUG4("unisig_sigmgr_state: usp=0x%x, state=%d, event=%d, action=%d\n",
+ (u_int) usp, usp->us_state, event, action);
+ if (action >= MAX_ACTION || action < 0) {
+ panic("unisig_sigmgr_state: invalid action\n");
+ }
+
+ /*
+ * Perform the requested action
+ */
+ err = unisig_sigmgr_act_vec[action](usp, m);
+
+ return(err);
+}
+
+
+/*
+ * Signalling manager state machine action 0
+ *
+ * Invalid action
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_invalid(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
+ if (m)
+ KB_FREEALL(m);
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 1
+ *
+ * The kickoff timer has expired at attach time; go to
+ * UNISIG_ADDR_WAIT state.
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act01(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ /*
+ * Set the new state
+ */
+ usp->us_state = UNISIG_ADDR_WAIT;
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 2
+ *
+ * Ignore the event
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act02(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ /*
+ * Ignore event, discard message if present
+ */
+ if (m)
+ KB_FREEALL(m);
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 3
+ *
+ * SSCF session on signalling channel has come up
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act03(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ struct unisig_vccb *uvp, *vnext;
+
+ /*
+ * Log the activation
+ */
+ log(LOG_INFO, "unisig: signalling channel active\n");
+
+ /*
+ * Go to ACTIVE state
+ */
+ usp->us_state = UNISIG_ACTIVE;
+
+ /*
+ * Notify the VC state machine that the channel is up
+ */
+ for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
+ uvp; uvp = vnext) {
+ vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
+ (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
+ (struct unisig_msg *) 0);
+ }
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 4
+ *
+ * A SSCF release indication was received. Try to establish an
+ * SSCF session on the signalling PVC.
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act04(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ int err;
+
+ /*
+ * Try to establish an SSCF session.
+ */
+ err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
+ usp->us_conn,
+ (void *)0);
+ if (err)
+ panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 5
+ *
+ * SSCF session on signalling channel has been reset
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act05(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ struct unisig_vccb *uvp, *vnext;
+
+ /*
+ * Log the reset
+ */
+ log(LOG_INFO, "unisig: signalling channel reset\n");
+
+ /*
+ * Notify the VC state machine of the reset
+ */
+ for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
+ uvp; uvp = vnext) {
+ vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
+ (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
+ (struct unisig_msg *) 0);
+ }
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 6
+ *
+ * SSCF session on signalling channel has been lost
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act06(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ struct unisig_vccb *uvp, *vnext;
+
+ /*
+ * Log the fact that the session has been lost
+ */
+ log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
+
+ /*
+ * Notify the VC state machine of the loss
+ */
+ for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
+ uvp; uvp = vnext) {
+ vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
+ (void) unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
+ (struct unisig_msg *) 0);
+ }
+
+ /*
+ * Try to restart the SSCF session
+ */
+ (void) unisig_sigmgr_act04(usp, (KBuffer *) 0);
+
+ /*
+ * Go to INIT state
+ */
+ usp->us_state = UNISIG_INIT;
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 7
+ *
+ * A Q.2931 signalling message has been received
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act07(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ int err;
+
+ /*
+ * Pass the Q.2931 signalling message on
+ * to the VC state machine
+ */
+ err = unisig_rcv_msg(usp, m);
+
+ return(err);
+}
+
+
+/*
+ * Signalling manager state machine action 8
+ *
+ * Process a CALL_CLOSED event for the signalling PVC
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act08(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+
+ /*
+ * Signalling manager is now incommunicado
+ */
+ if (usp->us_state != UNISIG_DETACH) {
+ /*
+ * Log an error and set the state to NULL if
+ * we're not detaching
+ */
+ log(LOG_ERR, "unisig: signalling channel closed\n");
+ usp->us_state = UNISIG_NULL;
+ }
+ usp->us_conn = 0;
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 9
+ *
+ * Not used
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act09(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
+ if (m)
+ KB_FREEALL(m);
+ return (0);
+}
+
+
+/*
+ * Signalling manager state machine action 10
+ *
+ * Not used
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act10(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 11
+ *
+ * Not used
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act11(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
+ if (m)
+ KB_FREEALL(m);
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 12
+ *
+ * Not used
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act12(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
+ if (m)
+ KB_FREEALL(m);
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 13
+ *
+ * NSAP prefix has been set
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act13(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ int err;
+ Atm_addr_pvc *pvcp;
+
+ /*
+ * Set UNI signalling channel connection attributes
+ */
+ if (usp->us_proto == ATM_SIG_UNI30)
+ unisig_attr.api_init = UNI_VERS_3_0;
+ else
+ unisig_attr.api_init = UNI_VERS_3_1;
+
+ unisig_attr.nif = usp->us_pif->pif_nif;
+
+ unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
+ unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
+ unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
+
+ unisig_attr.called.tag = T_ATM_PRESENT;
+ unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
+ unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
+ pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
+ ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
+ ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
+ unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
+ unisig_attr.called.subaddr.address_length = 0;
+
+ unisig_attr.traffic.v.forward.PCR_all_traffic =
+ usp->us_pif->pif_pcr;
+ unisig_attr.traffic.v.backward.PCR_all_traffic =
+ usp->us_pif->pif_pcr;
+
+ /*
+ * Create UNISIG signalling channel
+ */
+ err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
+ &usp->us_conn);
+ if (err) {
+ return(err);
+ }
+
+ /*
+ * Establish the SSCF session
+ */
+ err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ,
+ usp->us_conn,
+ (void *)0);
+ if (err)
+ panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
+
+ /*
+ * Set the new state
+ */
+ usp->us_state = UNISIG_INIT;
+
+ return(0);
+}
+
+
+/*
+ * Signalling manager state machine action 14
+ *
+ * Process a detach event
+ *
+ * Arguments:
+ * usp pointer to the UNISIG protocol control block
+ * m buffer pointer (may be NULL)
+ *
+ * Returns:
+ * 0 success
+ * errno error encountered
+ *
+ */
+static int
+unisig_sigmgr_act14(usp, m)
+ struct unisig *usp;
+ KBuffer *m;
+{
+ int err;
+ struct unisig_vccb *sig_vccb, *uvp, *vnext;
+ struct atm_pif *pip;
+ struct t_atm_cause cause;
+
+ /*
+ * Locate the signalling channel's VCCB
+ */
+ sig_vccb = (struct unisig_vccb *)0;
+ if (usp->us_conn && usp->us_conn->co_connvc)
+ sig_vccb = (struct unisig_vccb *)
+ usp->us_conn->co_connvc->cvc_vcc;
+
+ /*
+ * Terminate all of our VCCs
+ */
+ for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
+ uvp; uvp = vnext) {
+ vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
+
+ /*
+ * Don't close the signalling VCC yet
+ */
+ if (uvp == sig_vccb)
+ continue;
+
+ /*
+ * Close VCC and notify owner
+ */
+ err = unisig_clear_vcc(usp, uvp,
+ T_ATM_CAUSE_NORMAL_CALL_CLEARING);
+ }
+
+ /*
+ * Set the signalling manager state
+ */
+ usp->us_state = UNISIG_DETACH;
+
+ /*
+ * Close the signalling channel
+ */
+ if (usp->us_conn) {
+ cause.coding_standard = T_ATM_ITU_CODING;
+ cause.coding_standard = T_ATM_LOC_USER;
+ cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
+ err = atm_cm_release(usp->us_conn, &cause);
+ if (err)
+ panic("unisig_sigmgr_act14: close failed\n");
+ }
+
+ /*
+ * Get rid of protocol instance if there are no VCCs queued
+ */
+ pip = usp->us_pif;
+ if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
+ pip->pif_sigmgr) {
+ struct sigmgr *smp = pip->pif_sigmgr;
+ int s = splimp();
+
+ pip->pif_sigmgr = NULL;
+ pip->pif_siginst = NULL;
+ (void) splx(s);
+
+ UNLINK((struct siginst *)usp, struct siginst,
+ smp->sm_prinst, si_next);
+ KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
+ }
+
+ /*
+ * Otherwise, wait for protocol instance to be freed
+ * during unisig_free processing for the last queued VCC
+ */
+
+ return (0);
+}
OpenPOWER on IntegriCloud