3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $
31 * PVC-only Signalling Manager
32 * ---------------------------
34 * External interfaces to SigPVC manager. Includes support for
35 * running as a loadable kernel module.
39 #ifndef ATM_SIGPVC_MODULE
43 #include <netatm/kern_include.h>
45 #include <netatm/sigpvc/sigpvc_var.h>
48 __RCSID("@(#) $FreeBSD: src/sys/netatm/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $");
55 struct sp_info sigpvc_vcpool = {
56 "sigpvc vcc pool", /* si_name */
57 sizeof(struct sigpvc_vccb), /* si_blksiz */
65 static int sigpvc_start __P((void));
66 static int sigpvc_stop __P((void));
67 static int sigpvc_attach __P((struct sigmgr *, struct atm_pif *));
68 static int sigpvc_detach __P((struct atm_pif *));
69 static int sigpvc_setup __P((Atm_connvc *, int *));
70 static int sigpvc_release __P((struct vccb *, int *));
71 static int sigpvc_free __P((struct vccb *));
72 static int sigpvc_ioctl __P((int, caddr_t, caddr_t));
77 static int sigpvc_registered = 0;
78 static struct sigmgr sigpvc_mgr = {
92 static struct attr_cause sigpvc_cause = {
97 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
104 * Initialize sigpvc processing
106 * This will be called during module loading. We'll just register
107 * the sigpvc protocol descriptor and wait for a SigPVC ATM interface
114 * 0 startup was successful
115 * errno startup failed - reason indicated
124 * Verify software version
126 if (atm_version != ATM_VERSION) {
127 log(LOG_ERR, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
128 ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
129 ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
134 * Register ourselves with system
136 err = atm_sigmgr_register(&sigpvc_mgr);
138 sigpvc_registered = 1;
145 * Halt sigpvc processing
147 * This should be called just prior to unloading the module from
148 * memory. All sigpvc interfaces must be deregistered before the
149 * protocol can be shutdown.
155 * 0 shutdown was successful
156 * errno shutdown failed - reason indicated
166 * Is protocol even setup?
168 if (sigpvc_registered) {
171 * Any protocol instances still registered??
173 if (sigpvc_mgr.sm_prinst) {
175 /* Yes, can't stop now */
181 * De-register from system
183 err = atm_sigmgr_deregister(&sigpvc_mgr);
184 sigpvc_registered = 0;
187 * Free up our vccb storage pool
189 atm_release_pool(&sigpvc_vcpool);
200 * Attach a SigPVC-controlled interface
202 * Each ATM physical interface must be attached with the signalling manager for
203 * the interface's signalling protocol (via the atm_sigmgr_attach function).
204 * This function will handle the attachment for SigPVC-controlled interfaces.
205 * A new sigpvc protocol instance will be created and then we'll just sit
206 * around waiting for connection requests.
208 * Function must be called at splnet.
211 * smp pointer to sigpvc signalling manager control block
212 * pip pointer to atm physical interface control block
215 * 0 attach successful
216 * errno attach failed - reason indicated
220 sigpvc_attach(smp, pip)
225 struct sigpvc *pvp = NULL;
228 * Allocate sigpvc protocol instance control block
230 pvp = (struct sigpvc *)
231 KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT);
236 KM_ZERO(pvp, sizeof(struct sigpvc));
239 * Link instance into manager's chain
241 LINK2TAIL((struct siginst *)pvp, struct siginst,
242 smp->sm_prinst, si_next);
245 * Finally, set state and link in interface
248 pvp->pv_state = SIGPVC_ACTIVE;
249 pip->pif_sigmgr = smp;
250 pip->pif_siginst = (struct siginst *)pvp;
254 * Reset our work if attach fails
257 pip->pif_sigmgr = NULL;
258 pip->pif_siginst = NULL;
260 UNLINK((struct siginst *)pvp, struct siginst,
261 smp->sm_prinst, si_next);
262 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
271 * Detach a SigPVC-controlled interface
273 * Each ATM physical interface may be detached from its signalling manager
274 * (via the atm_sigmgr_detach function). This function will handle the
275 * detachment for all SigPVC-controlled interfaces. All circuits will be
276 * immediately terminated.
278 * Function must be called at splnet.
281 * pip pointer to atm physical interface control block
284 * 0 detach successful
285 * errno detach failed - reason indicated
293 struct vccb *vcp, *vnext;
296 * Get SigPVC protocol instance
298 pvp = (struct sigpvc *)pip->pif_siginst;
301 * Terminate all of our VCCs
303 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
306 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
309 * Close VCC and notify owner
311 oustate = vcp->vc_ustate;
312 sigpvc_close_vcc(vcp);
313 if (oustate == VCCU_OPEN) {
314 vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
315 atm_cm_cleared(vcp->vc_connvc);
320 * If there are no vcc's queued, then get rid of the protocol
323 if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
324 struct sigmgr *smp = pip->pif_sigmgr;
326 pip->pif_sigmgr = NULL;
327 pip->pif_siginst = NULL;
328 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
330 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
334 * Otherwise, set new state indicating detach in progress.
335 * The protocol instance will be freed during sigpvc_free
336 * processing for the last queued vcc.
338 pvp->pv_state = SIGPVC_DETACH;
346 * Open a SigPVC ATM Connection
348 * All service user requests to open a VC connection (via atm_open_connection)
349 * over an ATM interface attached to the SigPVC signalling manager are handled
350 * here. Only PVC requests are allowed.
352 * Function will be called at splnet.
355 * cvp pointer to CM's connection VCC
356 * errp location to store an error code if CALL_FAILED is returned
359 * CALL_PROCEEDING - connection establishment is in progress
360 * CALL_FAILED - connection establishment failed
361 * CALL_CONNECTED - connection has been successfully established
365 sigpvc_setup(cvp, errp)
370 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
374 * See what signalling has to say
376 switch (pvp->pv_state) {
388 * Open requested type of connection
390 switch (cvp->cvc_attr.called.addr.address_format) {
396 ret = sigpvc_create_pvc(pvp, cvp, errp);
400 *errp = EPROTONOSUPPORT;
410 * Close a SigPVC ATM Connection
412 * All service user requests to terminate a previously open VC connection
413 * (via the atm_close_connection function), which is running over an interface
414 * attached to the SigPVC signalling manager, are handled here.
416 * Function will be called at splnet.
419 * vcp pointer to connection's VC control block
420 * errp location to store an error code if CALL_FAILED is returned
423 * CALL_PROCEEDING - connection termination is in progress
424 * CALL_FAILED - connection termination failed
425 * CALL_CLEARED - connection has been successfully terminated
429 sigpvc_release(vcp, errp)
435 * Make sure VCC is open
437 if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
438 (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
440 return (CALL_FAILED);
444 * Not much else to do except close the vccb
446 sigpvc_close_vcc(vcp);
448 return (CALL_CLEARED);
453 * Free SigPVC ATM Connection Resources
455 * All service user requests to free the resources of a closed VCC connection
456 * (via the atm_free_connection function), which is running over an interface
457 * attached to the SigPVC signalling manager, are handled here.
459 * Function will be called at splnet.
462 * vcp pointer to connection's VCC control block
465 * 0 connection free was successful
466 * errno connection free failed - reason indicated
473 struct atm_pif *pip = vcp->vc_pif;
474 struct sigpvc *pvp = (struct sigpvc *)pip->pif_siginst;
477 * Make sure VCC has been closed
479 if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
483 * Remove vccb from protocol queue
485 DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
490 vcp->vc_ustate = VCCU_NULL;
491 vcp->vc_sstate = VCCS_NULL;
492 atm_free((caddr_t)vcp);
495 * If we're detaching and this was the last vcc queued,
496 * get rid of the protocol instance
498 if ((pvp->pv_state == SIGPVC_DETACH) &&
499 (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
500 struct sigmgr *smp = pip->pif_sigmgr;
502 pip->pif_sigmgr = NULL;
503 pip->pif_siginst = NULL;
504 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
506 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
514 * Process Signalling Manager PF_ATM ioctls
516 * Function will be called at splnet.
519 * code PF_ATM sub-operation code
520 * data pointer to code specific parameter data area
521 * arg1 pointer to code specific argument
525 * errno error processing request - reason indicated
529 sigpvc_ioctl(code, data, arg1)
534 struct atmdelreq *adp;
535 struct atminfreq *aip;
536 struct air_vcc_rsp avr;
542 int i, space, err = 0;
551 adp = (struct atmdelreq *)data;
552 pvp = (struct sigpvc *)arg1;
557 vpi = adp->adr_pvc_vpi;
558 vci = adp->adr_pvc_vci;
559 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
560 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
561 if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
568 * Schedule VCC termination
570 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
582 * Get VCC information
584 aip = (struct atminfreq *)data;
585 pvp = (struct sigpvc *)arg1;
587 cp = aip->air_buf_addr;
588 space = aip->air_buf_len;
591 * Get info for all VCCs on interface
593 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
594 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
596 * Make sure there's room in user buffer
598 if (space < sizeof(avr)) {
604 * Fill in info to be returned
606 (void) snprintf(avr.avp_intf, sizeof(avr.avp_intf),
608 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
609 avr.avp_vpi = vcp->vc_vpi;
610 avr.avp_vci = vcp->vc_vci;
611 avr.avp_type = vcp->vc_type;
612 avr.avp_sig_proto = ATM_SIG_PVC;
613 avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
614 cop = vcp->vc_connvc->cvc_conn;
616 avr.avp_encaps = cop->co_mpx;
619 KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
620 for (i = 0; cop && i < sizeof(avr.avp_owners);
622 i += T_ATM_APP_NAME_LEN+1) {
623 strncpy(&avr.avp_owners[i],
624 cop->co_endpt->ep_getname(cop->co_toku),
627 avr.avp_state = vcp->vc_sstate;
628 avr.avp_daddr.address_format = T_ATM_ABSENT;
629 avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
630 avr.avp_ipdus = vcp->vc_ipdus;
631 avr.avp_opdus = vcp->vc_opdus;
632 avr.avp_ibytes = vcp->vc_ibytes;
633 avr.avp_obytes = vcp->vc_obytes;
634 avr.avp_ierrors = vcp->vc_ierrors;
635 avr.avp_oerrors = vcp->vc_oerrors;
636 avr.avp_tstamp = vcp->vc_tstamp;
639 * Copy data to user buffer and update buffer info
641 if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
644 space -= sizeof(avr);
648 * Update buffer pointer/count
650 aip->air_buf_addr = cp;
651 aip->air_buf_len = space;
657 * Get ARP table/server information
659 /* We don't maintain any ARP information */
670 #ifdef ATM_SIGPVC_MODULE
672 *******************************************************************
674 * Loadable Module Support
676 *******************************************************************
678 static int sigpvc_doload __P((void));
679 static int sigpvc_dounload __P((void));
682 * Generic module load processing
684 * This function is called by an OS-specific function when this
685 * module is being loaded.
691 * 0 load was successful
692 * errno load failed - reason indicated
703 err = sigpvc_start();
705 /* Problems, clean up */
713 * Generic module unload processing
715 * This function is called by an OS-specific function when this
716 * module is being unloaded.
722 * 0 unload was successful
723 * errno unload failed - reason indicated
732 * OK, try to clean up our mess
742 * Loadable driver description
744 struct vdldrv sigpvc_drv = {
745 VDMAGIC_PSEUDO, /* Pseudo Driver */
746 "sigpvc_mod", /* name */
756 * Loadable module support entry point
758 * This is the routine called by the vd driver for all loadable module
759 * functions for this pseudo driver. This routine name must be specified
760 * on the modload(1) command. This routine will be called whenever the
761 * modload(1), modunload(1) or modstat(1) commands are issued for this
765 * cmd vd command code
766 * vdp pointer to vd driver's structure
767 * vdi pointer to command-specific vdioctl_* structure
768 * vds pointer to status structure (VDSTAT only)
771 * 0 command was successful
772 * errno command failed - reason indicated
776 sigpvc_mod(cmd, vdp, vdi, vds)
790 * We dont support any user configuration
792 err = sigpvc_doload();
794 /* Let vd driver know about us */
795 vdp->vdd_vdtab = (struct vdlinkage *)&sigpvc_drv;
802 err = sigpvc_dounload();
810 /* Not much to say at the moment */
815 log(LOG_ERR, "sigpvc_mod: Unknown vd command 0x%x\n", cmd);
825 #include <sys/exec.h>
826 #include <sys/sysent.h>
830 * Loadable miscellaneous module description
836 * Loadable module support "load" entry point
838 * This is the routine called by the lkm driver whenever the
839 * modload(1) command is issued for this module.
842 * lkmtp pointer to lkm drivers's structure
843 * cmd lkm command code
846 * 0 command was successful
847 * errno command failed - reason indicated
851 sigpvc_load(lkmtp, cmd)
852 struct lkm_table *lkmtp;
855 return(sigpvc_doload());
860 * Loadable module support "unload" entry point
862 * This is the routine called by the lkm driver whenever the
863 * modunload(1) command is issued for this module.
866 * lkmtp pointer to lkm drivers's structure
867 * cmd lkm command code
870 * 0 command was successful
871 * errno command failed - reason indicated
875 sigpvc_unload(lkmtp, cmd)
876 struct lkm_table *lkmtp;
879 return(sigpvc_dounload());
884 * Loadable module support entry point
886 * This is the routine called by the lkm driver for all loadable module
887 * functions for this driver. This routine name must be specified
888 * on the modload(1) command. This routine will be called whenever the
889 * modload(1), modunload(1) or modstat(1) commands are issued for this
893 * lkmtp pointer to lkm drivers's structure
894 * cmd lkm command code
898 * 0 command was successful
899 * errno command failed - reason indicated
903 sigpvc_mod(lkmtp, cmd, ver)
904 struct lkm_table *lkmtp;
908 MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
909 sigpvc_load, sigpvc_unload, lkm_nullcmd);
911 #endif /* __FreeBSD__ */
913 #else /* !ATM_SIGPVC_MODULE */
916 *******************************************************************
918 * Kernel Compiled Module Support
920 *******************************************************************
922 static void sigpvc_doload __P((void *));
924 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
927 * Kernel initialization
937 sigpvc_doload(void *arg)
944 err = sigpvc_start();
946 /* Problems, clean up */
949 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
953 #endif /* ATM_SIGPVC_MODULE */