aboutsummaryrefslogtreecommitdiff
path: root/sys/netatm/sigpvc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netatm/sigpvc')
-rw-r--r--sys/netatm/sigpvc/sigpvc.h47
-rw-r--r--sys/netatm/sigpvc/sigpvc_if.c953
-rw-r--r--sys/netatm/sigpvc/sigpvc_subr.c181
-rw-r--r--sys/netatm/sigpvc/sigpvc_var.h95
4 files changed, 1276 insertions, 0 deletions
diff --git a/sys/netatm/sigpvc/sigpvc.h b/sys/netatm/sigpvc/sigpvc.h
new file mode 100644
index 000000000000..893a68255b77
--- /dev/null
+++ b/sys/netatm/sigpvc/sigpvc.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * ===================================
+ * 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: sigpvc.h,v 1.2 1997/05/06 22:15:43 mks Exp $
+ *
+ */
+
+/*
+ * PVC-only Signalling Manager
+ * ---------------------------
+ *
+ * Protocol definitions
+ *
+ */
+
+#ifndef _SIGPVC_SIGPVC_H
+#define _SIGPVC_SIGPVC_H
+
+/*
+ * Protocol Variables
+ */
+#define SIGPVC_DOWN_DELAY (15 * ATM_HZ) /* Delay til i/f marked down */
+#define SIGPVC_UP_DELAY (5 * ATM_HZ) /* Delay til i/f marked up */
+
+#endif /* _SIGPVC_SIGPVC_H */
diff --git a/sys/netatm/sigpvc/sigpvc_if.c b/sys/netatm/sigpvc/sigpvc_if.c
new file mode 100644
index 000000000000..4208f29f4cb3
--- /dev/null
+++ b/sys/netatm/sigpvc/sigpvc_if.c
@@ -0,0 +1,953 @@
+/*
+ *
+ * ===================================
+ * 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: sigpvc_if.c,v 1.13 1998/07/30 22:32:42 mks Exp $
+ *
+ */
+
+/*
+ * PVC-only Signalling Manager
+ * ---------------------------
+ *
+ * External interfaces to SigPVC manager. Includes support for
+ * running as a loadable kernel module.
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: sigpvc_if.c,v 1.13 1998/07/30 22:32:42 mks Exp $";
+#endif
+
+#ifndef ATM_SIGPVC_MODULE
+#include "opt_atm.h"
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/sigpvc/sigpvc.h>
+#include <netatm/sigpvc/sigpvc_var.h>
+
+
+/*
+ * Global variables
+ */
+struct sp_info sigpvc_vcpool = {
+ "sigpvc vcc pool", /* si_name */
+ sizeof(struct sigpvc_vccb), /* si_blksiz */
+ 10, /* si_blkcnt */
+ 50 /* si_maxallow */
+};
+
+/*
+ * Local functions
+ */
+static int sigpvc_start __P((void));
+static int sigpvc_stop __P((void));
+static int sigpvc_attach __P((struct sigmgr *, struct atm_pif *));
+static int sigpvc_detach __P((struct atm_pif *));
+static int sigpvc_setup __P((Atm_connvc *, int *));
+static int sigpvc_release __P((struct vccb *, int *));
+static int sigpvc_free __P((struct vccb *));
+static int sigpvc_ioctl __P((int, caddr_t, caddr_t));
+
+/*
+ * Local variables
+ */
+static int sigpvc_registered = 0;
+static struct sigmgr sigpvc_mgr = {
+ NULL,
+ ATM_SIG_PVC,
+ NULL,
+ sigpvc_attach,
+ sigpvc_detach,
+ sigpvc_setup,
+ NULL,
+ NULL,
+ sigpvc_release,
+ sigpvc_free,
+ sigpvc_ioctl
+};
+
+static struct attr_cause sigpvc_cause = {
+ T_ATM_PRESENT,
+ {
+ T_ATM_ITU_CODING,
+ T_ATM_LOC_USER,
+ T_ATM_CAUSE_UNSPECIFIED_NORMAL,
+ {0, 0, 0, 0}
+ }
+};
+
+
+/*
+ * Initialize sigpvc processing
+ *
+ * This will be called during module loading. We'll just register
+ * the sigpvc protocol descriptor and wait for a SigPVC ATM interface
+ * to come online.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 startup was successful
+ * errno startup failed - reason indicated
+ *
+ */
+static int
+sigpvc_start()
+{
+ int err = 0;
+
+ /*
+ * Verify software version
+ */
+ if (atm_version != ATM_VERSION) {
+ log(LOG_ERR, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
+ ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
+ ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
+ return (EINVAL);
+ }
+
+ /*
+ * Register ourselves with system
+ */
+ err = atm_sigmgr_register(&sigpvc_mgr);
+ if (err == 0)
+ sigpvc_registered = 1;
+
+ return (err);
+}
+
+
+/*
+ * Halt sigpvc processing
+ *
+ * This should be called just prior to unloading the module from
+ * memory. All sigpvc interfaces must be deregistered before the
+ * protocol can be shutdown.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 shutdown was successful
+ * errno shutdown failed - reason indicated
+ *
+ */
+static int
+sigpvc_stop()
+{
+ int err = 0;
+ int s = splnet();
+
+ /*
+ * Is protocol even setup?
+ */
+ if (sigpvc_registered) {
+
+ /*
+ * Any protocol instances still registered??
+ */
+ if (sigpvc_mgr.sm_prinst) {
+
+ /* Yes, can't stop now */
+ err = EBUSY;
+ goto done;
+ }
+
+ /*
+ * De-register from system
+ */
+ err = atm_sigmgr_deregister(&sigpvc_mgr);
+ sigpvc_registered = 0;
+
+ /*
+ * Free up our vccb storage pool
+ */
+ atm_release_pool(&sigpvc_vcpool);
+ } else
+ err = ENXIO;
+
+done:
+ (void) splx(s);
+ return (err);
+}
+
+
+/*
+ * Attach a SigPVC-controlled interface
+ *
+ * Each ATM physical interface must be attached with the signalling manager for
+ * the interface's signalling protocol (via the atm_sigmgr_attach function).
+ * This function will handle the attachment for SigPVC-controlled interfaces.
+ * A new sigpvc protocol instance will be created and then we'll just sit
+ * around waiting for connection requests.
+ *
+ * Function must be called at splnet.
+ *
+ * Arguments:
+ * smp pointer to sigpvc signalling manager control block
+ * pip pointer to atm physical interface control block
+ *
+ * Returns:
+ * 0 attach successful
+ * errno attach failed - reason indicated
+ *
+ */
+static int
+sigpvc_attach(smp, pip)
+ struct sigmgr *smp;
+ struct atm_pif *pip;
+{
+ int err = 0;
+ struct sigpvc *pvp = NULL;
+
+ /*
+ * Allocate sigpvc protocol instance control block
+ */
+ pvp = (struct sigpvc *)
+ KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT);
+ if (pvp == NULL) {
+ err = ENOMEM;
+ goto done;
+ }
+ KM_ZERO(pvp, sizeof(struct sigpvc));
+
+ /*
+ * Link instance into manager's chain
+ */
+ LINK2TAIL((struct siginst *)pvp, struct siginst,
+ smp->sm_prinst, si_next);
+
+ /*
+ * Finally, set state and link in interface
+ */
+ pvp->pv_pif = pip;
+ pvp->pv_state = SIGPVC_ACTIVE;
+ pip->pif_sigmgr = smp;
+ pip->pif_siginst = (struct siginst *)pvp;
+
+done:
+ /*
+ * Reset our work if attach fails
+ */
+ if (err) {
+ pip->pif_sigmgr = NULL;
+ pip->pif_siginst = NULL;
+ if (pvp) {
+ UNLINK((struct siginst *)pvp, struct siginst,
+ smp->sm_prinst, si_next);
+ KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
+ }
+ }
+
+ return (err);
+}
+
+
+/*
+ * Detach a SigPVC-controlled interface
+ *
+ * Each ATM physical interface may be detached from its signalling manager
+ * (via the atm_sigmgr_detach function). This function will handle the
+ * detachment for all SigPVC-controlled interfaces. All circuits will be
+ * immediately terminated.
+ *
+ * Function must be called at splnet.
+ *
+ * Arguments:
+ * pip pointer to atm physical interface control block
+ *
+ * Returns:
+ * 0 detach successful
+ * errno detach failed - reason indicated
+ *
+ */
+static int
+sigpvc_detach(pip)
+ struct atm_pif *pip;
+{
+ struct sigpvc *pvp;
+ struct vccb *vcp, *vnext;
+
+ /*
+ * Get SigPVC protocol instance
+ */
+ pvp = (struct sigpvc *)pip->pif_siginst;
+
+ /*
+ * Terminate all of our VCCs
+ */
+ for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
+ u_char oustate;
+
+ vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
+
+ /*
+ * Close VCC and notify owner
+ */
+ oustate = vcp->vc_ustate;
+ sigpvc_close_vcc(vcp);
+ if (oustate == VCCU_OPEN) {
+ vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
+ atm_cm_cleared(vcp->vc_connvc);
+ }
+ }
+
+ /*
+ * If there are no vcc's queued, then get rid of the protocol
+ * instance.
+ */
+ if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
+ struct sigmgr *smp = pip->pif_sigmgr;
+
+ pip->pif_sigmgr = NULL;
+ pip->pif_siginst = NULL;
+ UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
+ si_next);
+ KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
+ } else {
+
+ /*
+ * Otherwise, set new state indicating detach in progress.
+ * The protocol instance will be freed during sigpvc_free
+ * processing for the last queued vcc.
+ */
+ pvp->pv_state = SIGPVC_DETACH;
+ }
+
+ return (0);
+}
+
+
+/*
+ * Open a SigPVC ATM Connection
+ *
+ * All service user requests to open a VC connection (via atm_open_connection)
+ * over an ATM interface attached to the SigPVC signalling manager are handled
+ * here. Only PVC requests are allowed.
+ *
+ * Function will be called at splnet.
+ *
+ * Arguments:
+ * cvp pointer to CM's connection VCC
+ * errp location to store an error code if CALL_FAILED is returned
+ *
+ * Returns:
+ * CALL_PROCEEDING - connection establishment is in progress
+ * CALL_FAILED - connection establishment failed
+ * CALL_CONNECTED - connection has been successfully established
+ *
+ */
+static int
+sigpvc_setup(cvp, errp)
+ Atm_connvc *cvp;
+ int *errp;
+{
+ struct sigpvc *pvp =
+ (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
+ int ret;
+
+ /*
+ * See what signalling has to say
+ */
+ switch (pvp->pv_state) {
+
+ case SIGPVC_ACTIVE:
+ break;
+
+ default:
+ *errp = ENXIO;
+ ret = CALL_FAILED;
+ goto done;
+ }
+
+ /*
+ * Open requested type of connection
+ */
+ switch (cvp->cvc_attr.called.addr.address_format) {
+
+ case T_ATM_PVC_ADDR:
+ /*
+ * Create a PVC
+ */
+ ret = sigpvc_create_pvc(pvp, cvp, errp);
+ break;
+
+ default:
+ *errp = EPROTONOSUPPORT;
+ ret = CALL_FAILED;
+ }
+
+done:
+ return (ret);
+}
+
+
+/*
+ * Close a SigPVC ATM Connection
+ *
+ * All service user requests to terminate a previously open VC connection
+ * (via the atm_close_connection function), which is running over an interface
+ * attached to the SigPVC signalling manager, are handled here.
+ *
+ * Function will be called at splnet.
+ *
+ * Arguments:
+ * vcp pointer to connection's VC control block
+ * errp location to store an error code if CALL_FAILED is returned
+ *
+ * Returns:
+ * CALL_PROCEEDING - connection termination is in progress
+ * CALL_FAILED - connection termination failed
+ * CALL_CLEARED - connection has been successfully terminated
+ *
+ */
+static int
+sigpvc_release(vcp, errp)
+ struct vccb *vcp;
+ int *errp;
+{
+
+ /*
+ * Make sure VCC is open
+ */
+ if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
+ (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
+ *errp = EALREADY;
+ return (CALL_FAILED);
+ }
+
+ /*
+ * Not much else to do except close the vccb
+ */
+ sigpvc_close_vcc(vcp);
+
+ return (CALL_CLEARED);
+}
+
+
+/*
+ * Free SigPVC ATM Connection Resources
+ *
+ * All service user requests to free the resources of a closed VCC connection
+ * (via the atm_free_connection function), which is running over an interface
+ * attached to the SigPVC signalling manager, are handled here.
+ *
+ * Function will be called at splnet.
+ *
+ * Arguments:
+ * vcp pointer to connection's VCC control block
+ *
+ * Returns:
+ * 0 connection free was successful
+ * errno connection free failed - reason indicated
+ *
+ */
+static int
+sigpvc_free(vcp)
+ struct vccb *vcp;
+{
+ struct atm_pif *pip = vcp->vc_pif;
+ struct sigpvc *pvp = (struct sigpvc *)pip->pif_siginst;
+
+ /*
+ * Make sure VCC has been closed
+ */
+ if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
+ return (EEXIST);
+
+ /*
+ * Remove vccb from protocol queue
+ */
+ DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
+
+ /*
+ * Free vccb storage
+ */
+ vcp->vc_ustate = VCCU_NULL;
+ vcp->vc_sstate = VCCS_NULL;
+ atm_free((caddr_t)vcp);
+
+ /*
+ * If we're detaching and this was the last vcc queued,
+ * get rid of the protocol instance
+ */
+ if ((pvp->pv_state == SIGPVC_DETACH) &&
+ (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
+ struct sigmgr *smp = pip->pif_sigmgr;
+
+ pip->pif_sigmgr = NULL;
+ pip->pif_siginst = NULL;
+ UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
+ si_next);
+ KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
+ }
+
+ return (0);
+}
+
+
+/*
+ * Process Signalling Manager PF_ATM ioctls
+ *
+ * Function will be called at splnet.
+ *
+ * Arguments:
+ * code PF_ATM sub-operation code
+ * data pointer to code specific parameter data area
+ * arg1 pointer to code specific argument
+ *
+ * Returns:
+ * 0 request procesed
+ * errno error processing request - reason indicated
+ *
+ */
+static int
+sigpvc_ioctl(code, data, arg1)
+ int code;
+ caddr_t data;
+ caddr_t arg1;
+{
+ struct atmdelreq *adp;
+ struct atminfreq *aip;
+ struct air_vcc_rsp avr;
+ struct sigpvc *pvp;
+ struct vccb *vcp;
+ Atm_connection *cop;
+ caddr_t cp;
+ u_int vpi, vci;
+ int i, space, err = 0;
+
+
+ switch (code) {
+
+ case AIOCS_DEL_PVC:
+ /*
+ * Delete a PVC
+ */
+ adp = (struct atmdelreq *)data;
+ pvp = (struct sigpvc *)arg1;
+
+ /*
+ * Find requested VCC
+ */
+ vpi = adp->adr_pvc_vpi;
+ vci = adp->adr_pvc_vci;
+ for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
+ vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
+ if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
+ break;
+ }
+ if (vcp == NULL)
+ return (ENOENT);
+
+ /*
+ * Schedule VCC termination
+ */
+ err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
+ break;
+
+ case AIOCS_DEL_SVC:
+ /*
+ * Delete a SVC
+ */
+ err = ENOENT;
+ break;
+
+ case AIOCS_INF_VCC:
+ /*
+ * Get VCC information
+ */
+ aip = (struct atminfreq *)data;
+ pvp = (struct sigpvc *)arg1;
+
+ cp = aip->air_buf_addr;
+ space = aip->air_buf_len;
+
+ /*
+ * Get info for all VCCs on interface
+ */
+ for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
+ vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
+ /*
+ * Make sure there's room in user buffer
+ */
+ if (space < sizeof(avr)) {
+ err = ENOSPC;
+ break;
+ }
+
+ /*
+ * Fill in info to be returned
+ */
+ (void) sprintf(avr.avp_intf, "%s%d",
+ pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
+ avr.avp_vpi = vcp->vc_vpi;
+ avr.avp_vci = vcp->vc_vci;
+ avr.avp_type = vcp->vc_type;
+ avr.avp_sig_proto = ATM_SIG_PVC;
+ avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
+ cop = vcp->vc_connvc->cvc_conn;
+ if (cop)
+ avr.avp_encaps = cop->co_mpx;
+ else
+ avr.avp_encaps = 0;
+ KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
+ for (i = 0; cop && i < sizeof(avr.avp_owners);
+ cop = cop->co_next,
+ i += T_ATM_APP_NAME_LEN+1) {
+ strncpy(&avr.avp_owners[i],
+ cop->co_endpt->ep_getname(cop->co_toku),
+ T_ATM_APP_NAME_LEN);
+ }
+ avr.avp_state = vcp->vc_sstate;
+ avr.avp_daddr.address_format = T_ATM_ABSENT;
+ avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
+ avr.avp_ipdus = vcp->vc_ipdus;
+ avr.avp_opdus = vcp->vc_opdus;
+ avr.avp_ibytes = vcp->vc_ibytes;
+ avr.avp_obytes = vcp->vc_obytes;
+ avr.avp_ierrors = vcp->vc_ierrors;
+ avr.avp_oerrors = vcp->vc_oerrors;
+ avr.avp_tstamp = vcp->vc_tstamp;
+
+ /*
+ * Copy data to user buffer and update buffer info
+ */
+ if (err = copyout((caddr_t)&avr, cp, sizeof(avr)))
+ break;
+ cp += sizeof(avr);
+ space -= sizeof(avr);
+ }
+
+ /*
+ * Update buffer pointer/count
+ */
+ aip->air_buf_addr = cp;
+ aip->air_buf_len = space;
+ break;
+
+ case AIOCS_INF_ARP:
+ /*
+ * Get ARP table information
+ */
+ /* We don't maintain any ARP information */
+ break;
+
+ default:
+ err = EOPNOTSUPP;
+ }
+
+ return (err);
+}
+
+
+#ifdef ATM_SIGPVC_MODULE
+/*
+ *******************************************************************
+ *
+ * Loadable Module Support
+ *
+ *******************************************************************
+ */
+static int sigpvc_doload __P((void));
+static int sigpvc_dounload __P((void));
+
+/*
+ * Generic module load processing
+ *
+ * This function is called by an OS-specific function when this
+ * module is being loaded.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 load was successful
+ * errno load failed - reason indicated
+ *
+ */
+static int
+sigpvc_doload()
+{
+ int err = 0;
+
+ /*
+ * Start us up
+ */
+ err = sigpvc_start();
+ if (err)
+ /* Problems, clean up */
+ (void)sigpvc_stop();
+
+ return (err);
+}
+
+
+/*
+ * Generic module unload processing
+ *
+ * This function is called by an OS-specific function when this
+ * module is being unloaded.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * 0 unload was successful
+ * errno unload failed - reason indicated
+ *
+ */
+static int
+sigpvc_dounload()
+{
+ int err = 0;
+
+ /*
+ * OK, try to clean up our mess
+ */
+ err = sigpvc_stop();
+
+ return (err);
+}
+
+
+#ifdef sun
+/*
+ * Loadable driver description
+ */
+struct vdldrv sigpvc_drv = {
+ VDMAGIC_PSEUDO, /* Pseudo Driver */
+ "sigpvc_mod", /* name */
+ NULL, /* dev_ops */
+ NULL, /* bdevsw */
+ NULL, /* cdevsw */
+ 0, /* blockmajor */
+ 0 /* charmajor */
+};
+
+
+/*
+ * Loadable module support entry point
+ *
+ * This is the routine called by the vd driver for all loadable module
+ * functions for this pseudo driver. This routine name must be specified
+ * on the modload(1) command. This routine will be called whenever the
+ * modload(1), modunload(1) or modstat(1) commands are issued for this
+ * module.
+ *
+ * Arguments:
+ * cmd vd command code
+ * vdp pointer to vd driver's structure
+ * vdi pointer to command-specific vdioctl_* structure
+ * vds pointer to status structure (VDSTAT only)
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+int
+sigpvc_mod(cmd, vdp, vdi, vds)
+ int cmd;
+ struct vddrv *vdp;
+ caddr_t vdi;
+ struct vdstat *vds;
+{
+ int err = 0;
+
+ switch (cmd) {
+
+ case VDLOAD:
+ /*
+ * Module Load
+ *
+ * We dont support any user configuration
+ */
+ err = sigpvc_doload();
+ if (err == 0)
+ /* Let vd driver know about us */
+ vdp->vdd_vdtab = (struct vdlinkage *)&sigpvc_drv;
+ break;
+
+ case VDUNLOAD:
+ /*
+ * Module Unload
+ */
+ err = sigpvc_dounload();
+ break;
+
+ case VDSTAT:
+ /*
+ * Module Status
+ */
+
+ /* Not much to say at the moment */
+
+ break;
+
+ default:
+ log(LOG_ERR, "sigpvc_mod: Unknown vd command 0x%x\n", cmd);
+ err = EINVAL;
+ }
+
+ return (err);
+}
+#endif /* sun */
+
+#ifdef __FreeBSD__
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+/*
+ * Loadable miscellaneous module description
+ */
+MOD_MISC(sigpvc);
+
+
+/*
+ * Loadable module support "load" entry point
+ *
+ * This is the routine called by the lkm driver whenever the
+ * modload(1) command is issued for this module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+sigpvc_load(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ return(sigpvc_doload());
+}
+
+
+/*
+ * Loadable module support "unload" entry point
+ *
+ * This is the routine called by the lkm driver whenever the
+ * modunload(1) command is issued for this module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+static int
+sigpvc_unload(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+ return(sigpvc_dounload());
+}
+
+
+/*
+ * Loadable module support entry point
+ *
+ * This is the routine called by the lkm driver for all loadable module
+ * functions for this driver. This routine name must be specified
+ * on the modload(1) command. This routine will be called whenever the
+ * modload(1), modunload(1) or modstat(1) commands are issued for this
+ * module.
+ *
+ * Arguments:
+ * lkmtp pointer to lkm drivers's structure
+ * cmd lkm command code
+ * ver lkm version
+ *
+ * Returns:
+ * 0 command was successful
+ * errno command failed - reason indicated
+ *
+ */
+int
+sigpvc_mod(lkmtp, cmd, ver)
+ struct lkm_table *lkmtp;
+ int cmd;
+ int ver;
+{
+ MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
+ sigpvc_load, sigpvc_unload, lkm_nullcmd);
+}
+#endif /* __FreeBSD__ */
+
+#else /* !ATM_SIGPVC_MODULE */
+
+/*
+ *******************************************************************
+ *
+ * Kernel Compiled Module Support
+ *
+ *******************************************************************
+ */
+static void sigpvc_doload __P((void *));
+
+SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
+
+/*
+ * Kernel initialization
+ *
+ * Arguments:
+ * arg Not used
+ *
+ * Returns:
+ * none
+ *
+ */
+static void
+sigpvc_doload(void *arg)
+{
+ int err = 0;
+
+ /*
+ * Start us up
+ */
+ err = sigpvc_start();
+ if (err) {
+ /* Problems, clean up */
+ (void)sigpvc_stop();
+
+ log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
+ }
+ return;
+}
+#endif /* ATM_SIGPVC_MODULE */
+
diff --git a/sys/netatm/sigpvc/sigpvc_subr.c b/sys/netatm/sigpvc/sigpvc_subr.c
new file mode 100644
index 000000000000..00f92ec125e5
--- /dev/null
+++ b/sys/netatm/sigpvc/sigpvc_subr.c
@@ -0,0 +1,181 @@
+/*
+ *
+ * ===================================
+ * 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: sigpvc_subr.c,v 1.7 1998/06/29 21:52:25 mks Exp $
+ *
+ */
+
+/*
+ * PVC-only Signalling Manager
+ * ---------------------------
+ *
+ * Subroutines
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: sigpvc_subr.c,v 1.7 1998/06/29 21:52:25 mks Exp $";
+#endif
+
+#include <netatm/kern_include.h>
+
+#include <netatm/sigpvc/sigpvc.h>
+#include <netatm/sigpvc/sigpvc_var.h>
+
+extern struct sp_info sigpvc_vcpool;
+
+/*
+ * Create a SigPVC Permanent Virtual Channel
+ *
+ * This function will construct a vccb for a "sigpvc-controlled" PVC
+ * and create the service stack requested by the user.
+ *
+ * Must be called at splnet.
+ *
+ * Arguments:
+ * pvp pointer to sigpvc protocol instance
+ * cvp pointer to CM's connection VCC
+ * errp location to store an error code if CALL_FAILED is returned
+ *
+ * Returns:
+ * CALL_FAILED - pvc creation failed
+ * CALL_CONNECTED - pvc has been successfully created
+ *
+ */
+int
+sigpvc_create_pvc(pvp, cvp, errp)
+ struct sigpvc *pvp;
+ Atm_connvc *cvp;
+ int *errp;
+{
+ Atm_addr_pvc *pp;
+ struct vccb *vcp;
+ u_int vpi, vci;
+
+ pp = (Atm_addr_pvc *)cvp->cvc_attr.called.addr.address;
+ vpi = ATM_PVC_GET_VPI(pp);
+ vci = ATM_PVC_GET_VCI(pp);
+
+ /*
+ * Verify requested VPI,VCI
+ */
+ if ((vpi > pvp->pv_pif->pif_maxvpi) ||
+ (vci == 0) || (vci > pvp->pv_pif->pif_maxvci)) {
+ *errp = ERANGE;
+ return (CALL_FAILED);
+ }
+
+ for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
+ vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
+
+ if ((vcp->vc_vpi == vpi) &&
+ (vcp->vc_vci == vci)) {
+ *errp = EADDRINUSE;
+ return (CALL_FAILED);
+ }
+ }
+
+ /*
+ * Verify network interface
+ */
+ if (cvp->cvc_attr.nif) {
+ if (cvp->cvc_attr.nif->nif_pif != pvp->pv_pif) {
+ *errp = EINVAL;
+ return (CALL_FAILED);
+ }
+ }
+
+ /*
+ * Allocate control block for PVC
+ */
+ vcp = (struct vccb *)atm_allocate(&sigpvc_vcpool);
+ if (vcp == NULL) {
+ *errp = ENOMEM;
+ return (CALL_FAILED);
+ }
+
+ /*
+ * Fill in VCCB
+ */
+ vcp->vc_type = VCC_PVC | VCC_IN | VCC_OUT;
+ vcp->vc_proto = ATM_SIG_PVC;
+ vcp->vc_sstate = VCCS_ACTIVE;
+ vcp->vc_ustate = VCCU_OPEN;
+ vcp->vc_pif = pvp->pv_pif;
+ vcp->vc_nif = cvp->cvc_attr.nif;
+ vcp->vc_vpi = vpi;
+ vcp->vc_vci = vci;
+ vcp->vc_connvc = cvp;
+
+ /*
+ * Put VCCB on sigpvc queue
+ */
+ ENQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
+
+ /*
+ * Pass back VCCB to connection manager
+ */
+ cvp->cvc_vcc = vcp;
+
+ /*
+ * PVC is ready to go!
+ */
+ return (CALL_CONNECTED);
+}
+
+/*
+ * Close a SigPVC VCC
+ *
+ * Clean up vccb, note that it's closing and wait for its freeing.
+ *
+ * Arguments:
+ * vcp pointer to connection's VCC control block
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+sigpvc_close_vcc(vcp)
+ struct vccb *vcp;
+{
+
+ /*
+ * Sanity check (actually design-flaw check)
+ */
+ if (vcp->vc_connvc->cvc_upcnt || vcp->vc_connvc->cvc_downcnt)
+ panic("sigpvc_close_vcc: stack call");
+
+ /*
+ * Set state variables
+ */
+ vcp->vc_ustate = VCCU_CLOSED;
+ vcp->vc_sstate = VCCS_FREE;
+
+ /*
+ * Wait for user to free resources
+ */
+}
+
diff --git a/sys/netatm/sigpvc/sigpvc_var.h b/sys/netatm/sigpvc/sigpvc_var.h
new file mode 100644
index 000000000000..24f92c0f2943
--- /dev/null
+++ b/sys/netatm/sigpvc/sigpvc_var.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * ===================================
+ * 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: sigpvc_var.h,v 1.5 1998/02/19 20:16:28 mks Exp $
+ *
+ */
+
+/*
+ * PVC-only Signalling Manager
+ * ---------------------------
+ *
+ * Protocol control blocks
+ *
+ */
+
+#ifndef _SIGPVC_SIGPVC_VAR_H
+#define _SIGPVC_SIGPVC_VAR_H
+
+#ifdef ATM_KERNEL
+/*
+ * Structure containing state information for each SigPVC protocol instance.
+ * There will be one instance for each ATM device interface using the SigPVC
+ * signalling manager.
+ */
+struct sigpvc {
+ struct siginst pv_inst; /* Common header */
+};
+#define pv_next pv_inst.si_next
+#define pv_pif pv_inst.si_pif
+#define pv_addr pv_inst.si_addr
+#define pv_vccq pv_inst.si_vccq
+#define pv_state pv_inst.si_state
+#endif /* ATM_KERNEL */
+
+/*
+ * SigPVC Protocol States
+ */
+#define SIGPVC_ACTIVE 1 /* Active */
+#define SIGPVC_DETACH 2 /* Detach in progress */
+
+
+#ifdef ATM_KERNEL
+/*
+ * SigPVC Virtual Channel Connection control block. All information regarding
+ * the state of a SigPVC controlled VCC will be recorded here. There will be
+ * one SigPVC VCC control block for each SigPVC-controlled VCC.
+ */
+struct sigpvc_vccb {
+ struct vccb vcp_hdr; /* Generic vccb */
+};
+#endif /* ATM_KERNEL */
+
+/*
+ * SigPVC VCC Signalling Protocol States
+ */
+#define VCCS_NULL 0 /* No state */
+#define VCCS_ACTIVE 1 /* Active */
+#define VCCS_FREE 2 /* Waiting for user to free resources */
+
+
+#ifdef ATM_KERNEL
+/*
+ * Global function declarations
+ */
+ /* sigpvc_if.c */
+
+ /* sigpvc_subr.c */
+int sigpvc_create_pvc __P((struct sigpvc *, Atm_connvc *, int *));
+void sigpvc_close_vcc __P((struct vccb *));
+
+#endif /* ATM_KERNEL */
+
+#endif /* _SIGPVC_SIGPVC_VAR_H */