/* * * =================================== * 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. * * @(#) $FreeBSD$ * */ /* * PVC-only Signalling Manager * --------------------------- * * Subroutines * */ #include #include #ifndef lint __RCSID("@(#) $FreeBSD$"); #endif 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 */ }