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/spans/spans_if.c,v 1.6 1999/08/28 00:48:49 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/spans/spans_if.c,v 1.5 2003/08/23 10:06:22 rob Exp $
31 * SPANS Signalling Manager
32 * ---------------------------
34 * External interfaces to SPANS manager. Includes support for
35 * running as a loadable kernel module.
39 #ifndef ATM_SPANS_MODULE
43 #include <netproto/atm/kern_include.h>
45 #include "spans_xdr.h"
46 #include "spans_var.h"
51 struct sp_info spans_vcpool = {
52 "spans vcc pool", /* si_name */
53 sizeof(struct spans_vccb), /* si_blksiz */
58 struct sp_info spans_msgpool = {
59 "spans message pool", /* si_name */
60 sizeof(spans_msg), /* si_blksiz */
68 static int spans_start (void);
69 static int spans_stop (void);
70 static int spans_attach (struct sigmgr *, struct atm_pif *);
71 static int spans_detach (struct atm_pif *);
72 static int spans_setup (Atm_connvc *, int *);
73 static int spans_release (struct vccb *, int *);
74 static int spans_accept (struct vccb *, int *);
75 static int spans_reject (struct vccb *, int *);
76 static int spans_ioctl (int, caddr_t, caddr_t);
81 static struct sigmgr *spans_mgr = NULL;
85 * Initialize SPANS processing
87 * This will be called during module loading. We'll just register
88 * the SPANS protocol descriptor and wait for a SPANS ATM interface
95 * 0 startup was successful
96 * errno startup failed - reason indicated
105 * Verify software version
107 if (atm_version != ATM_VERSION) {
108 log(LOG_ERR, "version mismatch: spans=%d.%d kernel=%d.%d\n",
109 ATM_VERS_MAJ(ATM_VERSION),
110 ATM_VERS_MIN(ATM_VERSION),
111 ATM_VERS_MAJ(atm_version),
112 ATM_VERS_MIN(atm_version));
117 * Allocate protocol definition structure
119 spans_mgr = (struct sigmgr *)KM_ALLOC(sizeof(struct sigmgr),
121 if (spans_mgr == NULL) {
125 KM_ZERO(spans_mgr, sizeof(struct sigmgr));
128 * Initialize protocol invariant values
130 spans_mgr->sm_proto = ATM_SIG_SPANS;
131 spans_mgr->sm_attach = spans_attach;
132 spans_mgr->sm_detach = spans_detach;
133 spans_mgr->sm_setup = spans_setup;
134 spans_mgr->sm_release = spans_release;
135 spans_mgr->sm_accept = spans_accept;
136 spans_mgr->sm_reject = spans_reject;
137 spans_mgr->sm_free = spans_free;
138 spans_mgr->sm_ioctl = spans_ioctl;
141 * Register ourselves with system
143 err = atm_sigmgr_register(spans_mgr);
148 * Start up Connectionless Service
150 err = spanscls_start();
160 * Halt SPANS processing
162 * This should be called just prior to unloading the module from
163 * memory. All SPANS interfaces must be deregistered before the
164 * protocol can be shutdown.
170 * 0 startup was successful
171 * errno startup failed - reason indicated
181 * Is protocol even set up?
186 * Any protocol instances still registered?
188 if (spans_mgr->sm_prinst) {
190 /* Yes, can't stop now */
196 * Stop Connectionless Service
201 * De-register from system
203 err = atm_sigmgr_deregister(spans_mgr);
206 * Free up protocol block
208 KM_FREE(spans_mgr, sizeof(struct sigmgr), M_DEVBUF);
212 * Free up our storage pools
214 atm_release_pool(&spans_vcpool);
215 atm_release_pool(&spans_msgpool);
226 * Attach a SPANS-controlled interface
228 * Each ATM physical interface must be attached with the signalling
229 * manager for the interface's signalling protocol (via the
230 * atm_sigmgr_attach function). This function will handle the
231 * attachment for SPANS-controlled interfaces. A new SPANS protocol
232 * instance will be created and then we'll just sit around waiting for
233 * status or connection requests.
235 * Function must be called at splnet.
238 * smp pointer to SPANS signalling manager control block
239 * pip pointer to ATM physical interface control block
242 * 0 attach successful
243 * errno attach failed - reason indicated
247 spans_attach(smp, pip)
251 int err = 0, n = 0, s;
252 struct spans *spp = NULL;
255 ATM_DEBUG2("spans_attach: smp=%p, pip=%p\n", smp, pip);
258 * Count network interfaces attached to the physical interface.
259 * If there are more or less than one, we have big problems.
272 * Allocate SPANS protocol instance control block
274 spp = (struct spans *)KM_ALLOC(sizeof(struct spans),
280 KM_ZERO(spp, sizeof(struct spans));
283 * Set variables in SPANS protocol instance control block
285 spp->sp_state = SPANS_INIT;
286 spp->sp_h_epoch = time_second;
288 spp->sp_addr.address_format = T_ATM_ABSENT;
289 spp->sp_addr.address_length = 0;
290 spp->sp_subaddr.address_format = T_ATM_ABSENT;
291 spp->sp_subaddr.address_length = 0;
292 spp->sp_probe_ct = 0;
293 spp->sp_alloc_vci = SPANS_MIN_VCI;
294 spp->sp_alloc_vpi = SPANS_VPI;
295 spp->sp_min_vci = SPANS_MIN_VCI;
296 spp->sp_max_vci = pip->pif_maxvci;
299 * Link instance into manager's chain
301 LINK2TAIL((struct siginst *)spp, struct siginst, smp->sm_prinst,
308 pip->pif_sigmgr = smp;
309 pip->pif_siginst = (struct siginst *) spp;
312 * Kick-start the SPANS protocol
317 * Notify Connectionless Service
319 err = spanscls_attach(spp);
322 * Log the fact that we've attached
325 log(LOG_INFO, "spans: attached to interface %s%d\n",
326 pip->pif_name, pip->pif_unit);
330 * Reset our work if attach fails
335 UNLINK((struct siginst *)spp, struct siginst,
336 smp->sm_prinst, si_next);
337 KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
340 pip->pif_sigmgr = NULL;
341 pip->pif_siginst = NULL;
350 * Detach a SPANS-controlled interface
352 * Each ATM physical interface may be detached from its signalling
353 * manager (via the atm_sigmgr_detach function). This function will
354 * handle the detachment for all SPANS-controlled interfaces. All
355 * circuits will be immediately terminated.
357 * Function must be called at splnet.
360 * pip pointer to ATM physical interface control block
363 * 0 detach successful
364 * errno detach failed - reason indicated
372 struct vccb *vcp, *vnext;
376 ATM_DEBUG1("spans_detach: pip=%p\n", pip);
379 * Get SPANS protocol instance
381 spp = (struct spans *)pip->pif_siginst;
384 * Return an error if we're already detaching
386 if (spp->sp_state == SPANS_DETACH) {
391 * Cancel any outstanding timer
396 * Notify Connectionless Service
398 spanscls_detach(spp);
401 * Terminate all of our VCCs
403 for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp; vcp = vnext) {
405 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
408 * Don't close the signalling VCC yet
410 if (vcp->vc_connvc && vcp->vc_connvc->cvc_conn ==
415 * Close VCC and notify owner
417 err = spans_clear_vcc(spp, (struct spans_vccb *)vcp);
419 log(LOG_ERR, "spans: error %d clearing VCCB %p\n",
425 * Now close the SPANS signalling VCC
427 if ((cop = spp->sp_conn) != NULL) {
428 err = atm_cm_release(cop, &spans_cause);
431 "spans_detach: close failed for SPANS signalling channel; cop=%p, err=%d\n",
437 * Get rid of protocol instance if there are no VCCs queued
439 if (Q_HEAD(spp->sp_vccq, struct vccb) == NULL) {
440 struct sigmgr *smp = pip->pif_sigmgr;
442 pip->pif_sigmgr = NULL;
443 pip->pif_siginst = NULL;
444 UNLINK((struct siginst *)spp, struct siginst,
445 smp->sm_prinst, si_next);
446 KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
449 * Otherwise, wait for protocol instance to be freed
450 * during spans_free processing for the last queued VCC.
452 spp->sp_state = SPANS_DETACH;
456 * Log the fact that we've detached
458 log(LOG_INFO, "spans: detached from interface %s%d\n",
459 pip->pif_name, pip->pif_unit);
466 * Open a SPANS ATM Connection
468 * All service user requests to open a VC connection (via
469 * atm_open_connection) over an ATM interface attached to the SPANS
470 * signalling manager are handled here.
472 * Function will be called at splnet.
475 * cvp pointer to user's requested connection parameters
476 * errp pointer to an int for extended error information
479 * CALL_PROCEEDING connection establishment is in progress
480 * CALL_FAILED connection establishment failed
481 * CALL_CONNECTED connection has been successfully established
485 spans_setup(cvp, errp)
489 struct atm_pif *pip = cvp->cvc_attr.nif->nif_pif;
490 struct spans *spp = (struct spans *)pip->pif_siginst;
493 ATM_DEBUG1("spans_setup: cvp=%p\n", cvp);
496 * Intialize the returned error code
501 * Open the connection
503 switch (cvp->cvc_attr.called.addr.address_format) {
508 *errp = spans_open_vcc(spp, cvp);
509 rc = (*errp ? CALL_FAILED : CALL_CONNECTED);
512 case T_ATM_SPANS_ADDR:
517 *errp = spans_open_vcc(spp, cvp);
518 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
522 *errp = EPROTONOSUPPORT;
531 * Close a SPANS ATM Connection
533 * All service user requests to terminate a previously open VC
534 * connection (via the atm_close_connection function), which is running
535 * over an interface attached to the SPANS signalling manager, are
538 * Function will be called at splnet.
541 * vcp pointer to connection's VC control block
542 * errp pointer to an int for extended error information
545 * CALL_PROCEEDING connection termination is in progress
546 * CALL_FAILED connection termination failed
547 * CALL_CLEARED connection has been successfully terminated
551 spans_release(vcp, errp)
556 struct atm_pif *pip = vcp->vc_pif;
557 struct spans *spp = (struct spans *)pip->pif_siginst;
559 ATM_DEBUG1("spans_release: vcp=%p\n", vcp);
562 * Initialize returned error code
567 * Make sure VCC is open
569 if ((vcp->vc_sstate == SPANS_VC_NULL) ||
570 (vcp->vc_sstate == SPANS_VC_CLOSE) ||
571 (vcp->vc_sstate == SPANS_VC_FREE) ||
572 (vcp->vc_ustate == VCCU_NULL) ||
573 (vcp->vc_ustate == VCCU_CLOSED)) {
579 * Validate the connection type (PVC or SVC)
581 if (!(vcp->vc_type & (VCC_PVC | VCC_SVC))) {
582 *errp = EPROTONOSUPPORT;
589 *errp = spans_close_vcc(spp, (struct spans_vccb *)vcp, FALSE);
592 * Set the return code
594 if (vcp->vc_type & VCC_PVC) {
595 rc = (*errp ? CALL_FAILED : CALL_CLEARED);
597 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
605 * Accept a SPANS Open from a remote host
607 * A user calls this routine (via the atm_accept_call function)
608 * after it is notified that an open request was received for it.
610 * Function will be called at splnet.
613 * vcp pointer to user's VCCB
614 * errp pointer to an int for extended error information
617 * CALL_PROCEEDING connection establishment is in progress
618 * CALL_FAILED connection establishment failed
619 * CALL_CONNECTED connection has been successfully established
623 spans_accept(vcp, errp)
627 struct atm_pif *pip = vcp->vc_pif;
628 struct spans *spp = (struct spans *)pip->pif_siginst;
629 struct spans_vccb *svp = (struct spans_vccb *)vcp;
631 ATM_DEBUG1("spans_accept: vcp=%p\n", vcp);
634 * Initialize the returned error code
639 * Return an error if we're detaching
641 if (spp->sp_state == SPANS_DETACH) {
643 ATM_DEBUG0("spans_accept: detaching\n");
648 * Respond to the open request
650 *errp = spans_send_open_rsp(spp, svp, SPANS_OK);
652 ATM_DEBUG0("spans_accept: spans_send_open_rsp failed\n");
657 * Update the VCC states
659 svp->sv_sstate = SPANS_VC_OPEN;
660 svp->sv_ustate = VCCU_OPEN;
662 return(CALL_CONNECTED);
666 * On error, free the VCCB and return CALL_FAILED
668 svp->sv_sstate = SPANS_VC_FREE;
669 svp->sv_ustate = VCCU_CLOSED;
670 DEQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
671 spans_free((struct vccb *)svp);
678 * Reject a SPANS Open from a remote host
680 * A user calls this routine (via the atm_reject_call function)
681 * after it is notified that an open request was received for it.
683 * Function will be called at splnet.
686 * vcp pointer to user's VCCB
687 * errp pointer to an int for extended error information
690 * CALL_CLEARED call request rejected
691 * CALL_FAILED call rejection failed
695 spans_reject(vcp, errp)
699 struct atm_pif *pip = vcp->vc_pif;
700 struct spans *spp = (struct spans *)pip->pif_siginst;
701 struct spans_vccb *svp = (struct spans_vccb *)vcp;
703 ATM_DEBUG1("spans_reject: vcp=%p\n", vcp);
706 * Initialize the returned error code
711 * Return an error if we're detaching
713 if (spp->sp_state == SPANS_DETACH) {
715 ATM_DEBUG0("spans_reject: detaching\n");
719 ATM_DEBUG1("spans_reject: cause code is %d\n",
720 vcp->vc_connvc->cvc_attr.cause.v.cause_value);
723 * Clean up the VCCB--the connection manager will free it
724 * spans_close_vcc will send a SPANS open response
726 if ((*errp = spans_close_vcc(spp, svp, TRUE)) != 0) {
727 ATM_DEBUG0("spans_reject: spans_close_vcc failed\n");
731 return(CALL_CLEARED);
736 * Abort a SPANS ATM Connection
738 * All (non-user) requests to abort a previously open VC connection (via
739 * the atm_abort_connection function), which is running over an
740 * interface attached to the SPANS signalling manager, are handled here.
741 * The VCC owner will be notified of the request, in order to initiate
742 * termination of the connection.
744 * Function will be called at splnet.
747 * vcp pointer to connection's VC control block
750 * 0 connection release was succesful
751 * errno connection release failed - reason indicated
760 * Make sure VCC is available
762 if ((vcp->vc_sstate == SPANS_VC_NULL) ||
763 (vcp->vc_sstate == SPANS_VC_CLOSE) ||
764 (vcp->vc_sstate == SPANS_VC_FREE) ||
765 (vcp->vc_ustate == VCCU_NULL) ||
766 (vcp->vc_ustate == VCCU_CLOSED)) {
773 if (vcp->vc_sstate == SPANS_VC_ABORT) {
778 * Cancel any timer that might be running
780 SPANS_VC_CANCEL(vcp);
783 * Set immediate timer to schedule connection termination
785 vcp->vc_sstate = SPANS_VC_ABORT;
786 SPANS_VC_TIMER(vcp, 0);
793 * Free SPANS ATM connection resources
795 * All service user requests to free the resources of a closed
796 * VCC connection (via the atm_free_connection function), which
797 * is running over an interface attached to the SigPVC signalling
798 * manager, are handled here.
800 * Function will be called at splnet.
803 * vcp pointer to connection's VC control block
806 * 0 connection free was successful
807 * errno connection free failed - reason indicated
814 struct atm_pif *pip = vcp->vc_pif;
815 struct spans *spp = (struct spans *)pip->pif_siginst;
817 ATM_DEBUG1("spans_free: vcp = %p\n", vcp);
820 * Make sure VCC has been closed
822 if ((vcp->vc_ustate != VCCU_CLOSED) ||
823 (vcp->vc_sstate != SPANS_VC_FREE)) {
824 ATM_DEBUG2("spans_free: bad state, sstate=%d, ustate=%d\n",
825 vcp->vc_sstate, vcp->vc_ustate);
830 * Remove VCCB from protocol queue
832 DEQUEUE(vcp, struct vccb, vc_sigelem, spp->sp_vccq);
837 vcp->vc_ustate = VCCU_NULL;
838 vcp->vc_sstate = SPANS_VC_NULL;
839 atm_free((caddr_t)vcp);
842 * If we're detaching and this was the last VCC queued,
843 * get rid of the protocol instance
845 if ((spp->sp_state == SPANS_DETACH) &&
846 (Q_HEAD(spp->sp_vccq, struct vccb) == NULL)) {
847 struct sigmgr *smp = pip->pif_sigmgr;
849 pip->pif_sigmgr = NULL;
850 pip->pif_siginst = NULL;
851 UNLINK((struct siginst *)spp, struct siginst, smp->sm_prinst,
853 KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
861 * SPANS IOCTL support
863 * Function will be called at splnet.
866 * code PF_ATM sub-operation code
867 * data pointer to code specific parameter data area
868 * arg1 pointer to code specific argument
872 * errno error processing request - reason indicated
876 spans_ioctl(code, data, arg1)
881 struct atmdelreq *adp;
882 struct atminfreq *aip;
884 struct spans_vccb *svp;
885 struct air_vcc_rsp rsp;
887 int buf_len, err = 0, i, vpi, vci;
898 adp = (struct atmdelreq *)data;
899 spp = (struct spans *)arg1;
902 * Don't let a user close the SPANS signalling VC or
905 vpi = adp->adr_pvc_vpi;
906 vci = adp->adr_pvc_vci;
907 if ((vpi == SPANS_SIG_VPI && vci == SPANS_SIG_VCI) ||
908 (vpi == SPANS_CLS_VPI &&
909 vci == SPANS_CLS_VCI))
915 for (svp = Q_HEAD(spp->sp_vccq, struct spans_vccb); svp;
916 svp = Q_NEXT(svp, struct spans_vccb, sv_sigelem)) {
917 if ((svp->sv_vpi == vpi) && (svp->sv_vci == vci))
928 if (!(svp->sv_type & VCC_PVC)) {
933 if (!(svp->sv_type & VCC_SVC)) {
940 * Schedule VCC termination
942 err = spans_abort((struct vccb *)svp);
947 * Return VCC information
949 aip = (struct atminfreq *)data;
950 spp = (struct spans *)arg1;
952 buf_addr = aip->air_buf_addr;
953 buf_len = aip->air_buf_len;
956 * Loop through the VCC queue
958 for (svp = Q_HEAD(spp->sp_vccq, struct spans_vccb); svp;
959 svp = Q_NEXT(svp, struct spans_vccb, sv_sigelem)) {
961 * Make sure there's room in the user's buffer
963 if (buf_len < sizeof(rsp)) {
969 * Fill out the response struct for the VCC
971 (void) snprintf(rsp.avp_intf,
972 sizeof(rsp.avp_intf), "%s%d",
973 spp->sp_pif->pif_name,
974 spp->sp_pif->pif_unit);
975 rsp.avp_vpi = svp->sv_vpi;
976 rsp.avp_vci = svp->sv_vci;
977 rsp.avp_type = svp->sv_type;
978 rsp.avp_aal = svp->sv_connvc->cvc_attr.aal.type;
979 rsp.avp_sig_proto = svp->sv_proto;
980 cop = svp->sv_connvc->cvc_conn;
982 rsp.avp_encaps = cop->co_mpx;
985 rsp.avp_state = svp->sv_sstate;
986 KM_ZERO(rsp.avp_owners, sizeof(rsp.avp_owners));
987 for (i = 0; cop && i < sizeof(rsp.avp_owners);
989 i += T_ATM_APP_NAME_LEN+1) {
990 strncpy(&rsp.avp_owners[i],
991 cop->co_endpt->ep_getname(cop->co_toku),
994 rsp.avp_daddr.address_format = T_ATM_SPANS_ADDR;
995 rsp.avp_daddr.address_length =
996 sizeof(Atm_addr_spans);
997 if (svp->sv_type & VCC_OUT) {
998 spans_addr_copy(&svp->sv_conn.con_dst,
999 rsp.avp_daddr.address);
1001 spans_addr_copy(&svp->sv_conn.con_src,
1002 rsp.avp_daddr.address);
1004 rsp.avp_dsubaddr.address_format = T_ATM_ABSENT;
1005 rsp.avp_dsubaddr.address_length = 0;
1006 rsp.avp_ipdus = svp->sv_ipdus;
1007 rsp.avp_opdus = svp->sv_opdus;
1008 rsp.avp_ibytes = svp->sv_ibytes;
1009 rsp.avp_obytes = svp->sv_obytes;
1010 rsp.avp_ierrors = svp->sv_ierrors;
1011 rsp.avp_oerrors = svp->sv_oerrors;
1012 rsp.avp_tstamp = svp->sv_tstamp;
1015 * Copy the response into the user's buffer
1017 if ((err = copyout((caddr_t)&rsp, buf_addr,
1020 buf_addr += sizeof(rsp);
1021 buf_len -= sizeof(rsp);
1025 * Update the buffer pointer and length
1027 aip->air_buf_addr = buf_addr;
1028 aip->air_buf_len = buf_len;
1036 * ARP specific ioctl's
1038 err = spansarp_ioctl(code, data, arg1);
1049 #ifdef ATM_SPANS_MODULE
1051 *******************************************************************
1053 * Loadable Module Support
1055 *******************************************************************
1057 static int spans_doload (void);
1058 static int spans_dounload (void);
1061 * Generic module load processing
1063 * This function is called by an OS-specific function when this
1064 * module is being loaded.
1070 * 0 load was successful
1071 * errno load failed - reason indicated
1082 err = spans_start();
1084 /* Problems, clean up */
1092 * Generic module unload processing
1094 * This function is called by an OS-specific function when this
1095 * module is being unloaded.
1101 * 0 unload was successful
1102 * errno unload failed - reason indicated
1111 * OK, try to clean up our mess
1121 * Loadable driver description
1123 struct vdldrv spans_drv = {
1124 VDMAGIC_PSEUDO, /* Pseudo Driver */
1125 "spans_mod", /* name */
1135 * Loadable module support entry point
1137 * This is the routine called by the vd driver for all loadable module
1138 * functions for this pseudo driver. This routine name must be specified
1139 * on the modload(1) command. This routine will be called whenever the
1140 * modload(1), modunload(1) or modstat(1) commands are issued for this
1144 * cmd vd command code
1145 * vdp pointer to vd driver's structure
1146 * vdi pointer to command-specific vdioctl_* structure
1147 * vds pointer to status structure (VDSTAT only)
1150 * 0 command was successful
1151 * errno command failed - reason indicated
1155 spans_mod(cmd, vdp, vdi, vds)
1169 * We dont support any user configuration
1171 err = spans_doload();
1173 /* Let vd driver know about us */
1174 vdp->vdd_vdtab = (struct vdlinkage *)&spans_drv;
1181 err = spans_dounload();
1189 /* Not much to say at the moment */
1194 log(LOG_ERR, "spans_mod: Unknown vd command 0x%x\n", cmd);
1204 #include <sys/exec.h>
1205 #include <sys/sysent.h>
1206 #include <sys/lkm.h>
1209 * Loadable miscellaneous module description
1215 * Loadable module support "load" entry point
1217 * This is the routine called by the lkm driver whenever the
1218 * modload(1) command is issued for this module.
1221 * lkmtp pointer to lkm drivers's structure
1222 * cmd lkm command code
1225 * 0 command was successful
1226 * errno command failed - reason indicated
1230 spans_load(lkmtp, cmd)
1231 struct lkm_table *lkmtp;
1234 return(spans_doload());
1239 * Loadable module support "unload" entry point
1241 * This is the routine called by the lkm driver whenever the
1242 * modunload(1) command is issued for this module.
1245 * lkmtp pointer to lkm drivers's structure
1246 * cmd lkm command code
1249 * 0 command was successful
1250 * errno command failed - reason indicated
1254 spans_unload(lkmtp, cmd)
1255 struct lkm_table *lkmtp;
1258 return(spans_dounload());
1263 * Loadable module support entry point
1265 * This is the routine called by the lkm driver for all loadable module
1266 * functions for this driver. This routine name must be specified
1267 * on the modload(1) command. This routine will be called whenever the
1268 * modload(1), modunload(1) or modstat(1) commands are issued for this
1272 * lkmtp pointer to lkm drivers's structure
1273 * cmd lkm command code
1277 * 0 command was successful
1278 * errno command failed - reason indicated
1282 spans_mod(lkmtp, cmd, ver)
1283 struct lkm_table *lkmtp;
1287 MOD_DISPATCH(spans, lkmtp, cmd, ver,
1288 spans_load, spans_unload, lkm_nullcmd);
1290 #endif /* __FreeBSD__ */
1292 #else /* !ATM_SPANS_MODULE */
1295 *******************************************************************
1297 * Kernel Compiled Module Support
1299 *******************************************************************
1301 static void spans_doload (void *);
1303 SYSINIT(atmspans, SI_SUB_PROTO_END, SI_ORDER_ANY, spans_doload, NULL)
1306 * Kernel initialization
1316 spans_doload(void *arg)
1323 err = spans_start();
1325 /* Problems, clean up */
1328 log(LOG_ERR, "ATM SPANS unable to initialize (%d)!!\n", err);
1332 #endif /* ATM_SPANS_MODULE */