Rename sprintf -> ksprintf
[dragonfly.git] / sys / netproto / atm / sigpvc / sigpvc_if.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/sigpvc/sigpvc_if.c,v 1.11 2006/12/20 18:14:43 dillon Exp $
28  */
29
30 /*
31  * PVC-only Signalling Manager
32  * ---------------------------
33  *
34  * External interfaces to SigPVC manager.  Includes support for 
35  * running as a loadable kernel module.
36  *
37  */
38
39 #ifndef ATM_SIGPVC_MODULE
40 #include "opt_atm.h"
41 #endif
42
43 #include <netproto/atm/kern_include.h>
44
45 #include "sigpvc_var.h"
46
47 /*
48  * Global variables
49  */
50 struct sp_info  sigpvc_vcpool = {
51         "sigpvc vcc pool",              /* si_name */
52         sizeof(struct sigpvc_vccb),     /* si_blksiz */
53         10,                             /* si_blkcnt */
54         50                              /* si_maxallow */
55 };
56
57 /*
58  * Local functions
59  */
60 static int      sigpvc_start (void);
61 static int      sigpvc_stop (void);
62 static int      sigpvc_attach (struct sigmgr *, struct atm_pif *);
63 static int      sigpvc_detach (struct atm_pif *);
64 static int      sigpvc_setup (Atm_connvc *, int *);
65 static int      sigpvc_release (struct vccb *, int *);
66 static int      sigpvc_free (struct vccb *);
67 static int      sigpvc_ioctl (int, caddr_t, caddr_t);
68
69 /*
70  * Local variables
71  */
72 static int      sigpvc_registered = 0;
73 static struct sigmgr    sigpvc_mgr = {
74         NULL,
75         ATM_SIG_PVC,
76         NULL,
77         sigpvc_attach,
78         sigpvc_detach,
79         sigpvc_setup,
80         NULL,
81         NULL,
82         sigpvc_release,
83         sigpvc_free,
84         sigpvc_ioctl
85 };
86
87 static struct attr_cause        sigpvc_cause = {
88         T_ATM_PRESENT,
89         {
90                 T_ATM_ITU_CODING,
91                 T_ATM_LOC_USER,
92                 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
93                 {0, 0, 0, 0}
94         }
95 };
96
97
98 /*
99  * Initialize sigpvc processing
100  * 
101  * This will be called during module loading.  We'll just register
102  * the sigpvc protocol descriptor and wait for a SigPVC ATM interface 
103  * to come online.
104  *
105  * Arguments:
106  *      none
107  *
108  * Returns:
109  *      0       startup was successful 
110  *      errno   startup failed - reason indicated
111  *
112  */
113 static int
114 sigpvc_start(void)
115 {
116         int     err = 0;
117
118         /*
119          * Verify software version
120          */
121         if (atm_version != ATM_VERSION) {
122                 log(LOG_ERR, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
123                         ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
124                         ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
125                 return (EINVAL);
126         }
127
128         /*
129          * Register ourselves with system
130          */
131         err = atm_sigmgr_register(&sigpvc_mgr);
132         if (err == 0)
133                 sigpvc_registered = 1;
134
135         return (err);
136 }
137
138
139 /*
140  * Halt sigpvc processing 
141  * 
142  * This should be called just prior to unloading the module from
143  * memory.  All sigpvc interfaces must be deregistered before the
144  * protocol can be shutdown.
145  *
146  * Arguments:
147  *      none
148  *
149  * Returns:
150  *      0       shutdown was successful 
151  *      errno   shutdown failed - reason indicated
152  *
153  */
154 static int
155 sigpvc_stop(void)
156 {
157         int     err = 0;
158
159         crit_enter();
160
161         /*
162          * Is protocol even setup?
163          */
164         if (sigpvc_registered) {
165                 
166                 /*
167                  * Any protocol instances still registered??
168                  */
169                 if (sigpvc_mgr.sm_prinst) {
170
171                         /* Yes, can't stop now */
172                         err = EBUSY;
173                         goto done;
174                 }
175
176                 /*
177                  * De-register from system
178                  */
179                 err = atm_sigmgr_deregister(&sigpvc_mgr);
180                 sigpvc_registered = 0;
181
182                 /*
183                  * Free up our vccb storage pool
184                  */
185                 atm_release_pool(&sigpvc_vcpool);
186         } else
187                 err = ENXIO;
188
189 done:
190         crit_exit();
191         return (err);
192 }
193
194
195 /*
196  * Attach a SigPVC-controlled interface
197  * 
198  * Each ATM physical interface must be attached with the signalling manager for
199  * the interface's signalling protocol (via the atm_sigmgr_attach function).  
200  * This function will handle the attachment for SigPVC-controlled interfaces.
201  * A new sigpvc protocol instance will be created and then we'll just sit
202  * around waiting for connection requests.
203  *
204  * Function must be called from a critical section.
205  *
206  * Arguments:
207  *      smp     pointer to sigpvc signalling manager control block
208  *      pip     pointer to atm physical interface control block
209  *
210  * Returns:
211  *      0       attach successful 
212  *      errno   attach failed - reason indicated
213  *
214  */
215 static int
216 sigpvc_attach(struct sigmgr *smp, struct atm_pif *pip)
217 {
218         int     err = 0;
219         struct sigpvc   *pvp = NULL;
220
221         /*
222          * Allocate sigpvc protocol instance control block
223          */
224         pvp = KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_INTWAIT | M_NULLOK);
225         if (pvp == NULL) {
226                 err = ENOMEM;
227                 goto done;
228         }
229         KM_ZERO(pvp, sizeof(struct sigpvc));
230
231         /*
232          * Link instance into manager's chain
233          */
234         LINK2TAIL((struct siginst *)pvp, struct siginst, 
235                 smp->sm_prinst, si_next);
236
237         /*
238          * Finally, set state and link in interface
239          */
240         pvp->pv_pif = pip;
241         pvp->pv_state = SIGPVC_ACTIVE;
242         pip->pif_sigmgr = smp;
243         pip->pif_siginst = (struct siginst *)pvp;
244
245 done:
246         /*
247          * Reset our work if attach fails
248          */
249         if (err) {
250                 pip->pif_sigmgr = NULL;
251                 pip->pif_siginst = NULL;
252                 if (pvp) {
253                         UNLINK((struct siginst *)pvp, struct siginst, 
254                                 smp->sm_prinst, si_next);
255                         KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
256                 }
257         }
258
259         return (err);
260 }
261
262
263 /*
264  * Detach a SigPVC-controlled interface
265  * 
266  * Each ATM physical interface may be detached from its signalling manager 
267  * (via the atm_sigmgr_detach function).  This function will handle the 
268  * detachment for all SigPVC-controlled interfaces.  All circuits will be 
269  * immediately terminated.
270  *
271  * Function must be called from a critical section.
272  *
273  * Arguments:
274  *      pip     pointer to atm physical interface control block
275  *
276  * Returns:
277  *      0       detach successful 
278  *      errno   detach failed - reason indicated
279  *
280  */
281 static int
282 sigpvc_detach(struct atm_pif *pip)
283 {
284         struct sigpvc   *pvp;
285         struct vccb     *vcp, *vnext;
286
287         /*
288          * Get SigPVC protocol instance
289          */
290         pvp = (struct sigpvc *)pip->pif_siginst;
291
292         /*
293          * Terminate all of our VCCs
294          */
295         for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
296                 u_char  oustate;
297
298                 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
299
300                 /*
301                  * Close VCC and notify owner
302                  */
303                 oustate = vcp->vc_ustate;
304                 sigpvc_close_vcc(vcp);
305                 if (oustate == VCCU_OPEN) {
306                         vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
307                         atm_cm_cleared(vcp->vc_connvc);
308                 }
309         }
310
311         /*
312          * If there are no vcc's queued, then get rid of the protocol 
313          * instance.  
314          */
315         if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
316                 struct sigmgr   *smp = pip->pif_sigmgr;
317
318                 pip->pif_sigmgr = NULL;
319                 pip->pif_siginst = NULL;
320                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
321                                 si_next);
322                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
323         } else {
324
325                 /*
326                  * Otherwise, set new state indicating detach in progress.
327                  * The protocol instance will be freed during sigpvc_free 
328                  * processing for the last queued vcc.
329                  */
330                 pvp->pv_state = SIGPVC_DETACH;
331         }
332
333         return (0);
334 }
335
336
337 /*
338  * Open a SigPVC ATM Connection
339  * 
340  * All service user requests to open a VC connection (via atm_open_connection)
341  * over an ATM interface attached to the SigPVC signalling manager are handled 
342  * here.  Only PVC requests are allowed.
343  *
344  * Function will be called from a critical section.
345  *
346  * Arguments:
347  *      cvp     pointer to CM's connection VCC
348  *      errp    location to store an error code if CALL_FAILED is returned
349  *
350  * Returns:
351  *      CALL_PROCEEDING - connection establishment is in progress
352  *      CALL_FAILED     - connection establishment failed
353  *      CALL_CONNECTED  - connection has been successfully established
354  *
355  */
356 static int
357 sigpvc_setup(Atm_connvc *cvp, int *errp)
358 {
359         struct sigpvc   *pvp =
360                 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
361         int     ret;
362
363         /*
364          * See what signalling has to say
365          */
366         switch (pvp->pv_state) {
367
368         case SIGPVC_ACTIVE:
369                 break;
370
371         default:
372                 *errp = ENXIO;
373                 ret = CALL_FAILED;
374                 goto done;
375         }
376         
377         /*
378          * Open requested type of connection
379          */
380         switch (cvp->cvc_attr.called.addr.address_format) {
381
382         case T_ATM_PVC_ADDR:
383                 /*
384                  * Create a PVC
385                  */
386                 ret = sigpvc_create_pvc(pvp, cvp, errp);
387                 break;
388
389         default:
390                 *errp = EPROTONOSUPPORT;
391                 ret = CALL_FAILED;
392         }
393
394 done:
395         return (ret);
396 }
397
398
399 /*
400  * Close a SigPVC ATM Connection
401  * 
402  * All service user requests to terminate a previously open VC connection 
403  * (via the atm_close_connection function), which is running over an interface 
404  * attached to the SigPVC signalling manager, are handled here.
405  *
406  * Function will be called from a critical section.
407  * 
408  * Arguments:
409  *      vcp     pointer to connection's VC control block
410  *      errp    location to store an error code if CALL_FAILED is returned
411  *
412  * Returns:
413  *      CALL_PROCEEDING - connection termination is in progress
414  *      CALL_FAILED     - connection termination failed
415  *      CALL_CLEARED    - connection has been successfully terminated
416  *
417  */
418 static int
419 sigpvc_release(struct vccb *vcp, int *errp)
420 {
421
422         /*
423          * Make sure VCC is open
424          */
425         if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
426             (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
427                 *errp = EALREADY;
428                 return (CALL_FAILED);
429         }
430
431         /*
432          * Not much else to do except close the vccb
433          */
434         sigpvc_close_vcc(vcp);
435
436         return (CALL_CLEARED);
437 }
438
439
440 /*
441  * Free SigPVC ATM Connection Resources
442  * 
443  * All service user requests to free the resources of a closed VCC connection
444  * (via the atm_free_connection function), which is running over an interface 
445  * attached to the SigPVC signalling manager, are handled here.
446  *
447  * Function will be called from a critical section.
448  * 
449  * Arguments:
450  *      vcp     pointer to connection's VCC control block
451  *
452  * Returns:
453  *      0       connection free was successful 
454  *      errno   connection free failed - reason indicated
455  *
456  */
457 static int
458 sigpvc_free(struct vccb *vcp)
459 {
460         struct atm_pif  *pip = vcp->vc_pif;
461         struct sigpvc   *pvp = (struct sigpvc *)pip->pif_siginst;
462
463         /*
464          * Make sure VCC has been closed
465          */
466         if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
467                 return (EEXIST);
468
469         /*
470          * Remove vccb from protocol queue
471          */
472         DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
473
474         /*
475          * Free vccb storage
476          */
477         vcp->vc_ustate = VCCU_NULL;
478         vcp->vc_sstate = VCCS_NULL;
479         atm_free((caddr_t)vcp);
480
481         /*
482          * If we're detaching and this was the last vcc queued,
483          * get rid of the protocol instance
484          */
485         if ((pvp->pv_state == SIGPVC_DETACH) && 
486             (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
487                 struct sigmgr   *smp = pip->pif_sigmgr;
488
489                 pip->pif_sigmgr = NULL;
490                 pip->pif_siginst = NULL;
491                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
492                                 si_next);
493                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
494         }
495
496         return (0);
497 }
498
499
500 /*
501  * Process Signalling Manager PF_ATM ioctls
502  * 
503  * Function will be called from a critical section.
504  *
505  * Arguments:
506  *      code    PF_ATM sub-operation code
507  *      data    pointer to code specific parameter data area
508  *      arg1    pointer to code specific argument
509  *
510  * Returns:
511  *      0       request procesed
512  *      errno   error processing request - reason indicated
513  *
514  */
515 static int
516 sigpvc_ioctl(int code, caddr_t data, caddr_t arg1)
517 {
518         struct atmdelreq        *adp;
519         struct atminfreq        *aip;
520         struct air_vcc_rsp      avr;
521         struct sigpvc   *pvp;
522         struct vccb     *vcp;
523         Atm_connection  *cop;
524         caddr_t         cp;
525         u_int   vpi, vci;
526         int     i, space, err = 0;
527
528
529         switch (code) {
530
531         case AIOCS_DEL_PVC:
532                 /*
533                  * Delete a PVC
534                  */
535                 adp = (struct atmdelreq *)data;
536                 pvp = (struct sigpvc *)arg1;
537
538                 /*
539                  * Find requested VCC
540                  */
541                 vpi = adp->adr_pvc_vpi;
542                 vci = adp->adr_pvc_vci;
543                 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; 
544                                 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
545                         if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
546                                 break;
547                 }
548                 if (vcp == NULL)
549                         return (ENOENT);
550
551                 /*
552                  * Schedule VCC termination
553                  */
554                 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
555                 break;
556
557         case AIOCS_DEL_SVC:
558                 /*
559                  * Delete a SVC
560                  */
561                 err = ENOENT;
562                 break;
563
564         case AIOCS_INF_VCC:
565                 /*
566                  * Get VCC information
567                  */
568                 aip = (struct atminfreq *)data;
569                 pvp = (struct sigpvc *)arg1;
570
571                 cp = aip->air_buf_addr;
572                 space = aip->air_buf_len;
573
574                 /*
575                  * Get info for all VCCs on interface
576                  */
577                 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; 
578                                 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
579                         /*
580                          * Make sure there's room in user buffer
581                          */
582                         if (space < sizeof(avr)) {
583                                 err = ENOSPC;
584                                 break;
585                         }
586
587                         /*
588                          * Fill in info to be returned
589                          */
590                         ksnprintf(avr.avp_intf, sizeof(avr.avp_intf),
591                                 "%s%d",
592                                 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
593                         avr.avp_vpi = vcp->vc_vpi;
594                         avr.avp_vci = vcp->vc_vci;
595                         avr.avp_type = vcp->vc_type;
596                         avr.avp_sig_proto = ATM_SIG_PVC;
597                         avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
598                         cop = vcp->vc_connvc->cvc_conn;
599                         if  (cop)
600                                 avr.avp_encaps = cop->co_mpx;
601                         else
602                                 avr.avp_encaps = 0;
603                         KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
604                         for (i = 0; cop && i < sizeof(avr.avp_owners);
605                                         cop = cop->co_next,
606                                         i += T_ATM_APP_NAME_LEN+1) {
607                                 strncpy(&avr.avp_owners[i],
608                                         cop->co_endpt->ep_getname(cop->co_toku),
609                                         T_ATM_APP_NAME_LEN);
610                         }
611                         avr.avp_state = vcp->vc_sstate;
612                         avr.avp_daddr.address_format = T_ATM_ABSENT;
613                         avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
614                         avr.avp_ipdus = vcp->vc_ipdus;
615                         avr.avp_opdus = vcp->vc_opdus;
616                         avr.avp_ibytes = vcp->vc_ibytes;
617                         avr.avp_obytes = vcp->vc_obytes;
618                         avr.avp_ierrors = vcp->vc_ierrors;
619                         avr.avp_oerrors = vcp->vc_oerrors;
620                         avr.avp_tstamp = vcp->vc_tstamp;
621
622                         /*
623                          * Copy data to user buffer and update buffer info
624                          */
625                         if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
626                                 break;
627                         cp += sizeof(avr);
628                         space -= sizeof(avr);
629                 }
630
631                 /*
632                  * Update buffer pointer/count
633                  */
634                 aip->air_buf_addr = cp;
635                 aip->air_buf_len = space;
636                 break;
637
638         case AIOCS_INF_ARP:
639         case AIOCS_INF_ASV:
640                 /*
641                  * Get ARP table/server information
642                  */
643                 /* We don't maintain any ARP information */
644                 break;
645
646         default:
647                 err = EOPNOTSUPP;
648         }
649
650         return (err);
651 }
652
653
654 #ifdef ATM_SIGPVC_MODULE
655 /*
656  *******************************************************************
657  *
658  * Loadable Module Support
659  *
660  *******************************************************************
661  */
662 static int      sigpvc_doload (void);
663 static int      sigpvc_dounload (void);
664
665 /*
666  * Generic module load processing
667  * 
668  * This function is called by an OS-specific function when this
669  * module is being loaded.
670  *
671  * Arguments:
672  *      none
673  *
674  * Returns:
675  *      0       load was successful 
676  *      errno   load failed - reason indicated
677  *
678  */
679 static int
680 sigpvc_doload(void)
681 {
682         int     err = 0;
683
684         /*
685          * Start us up
686          */
687         err = sigpvc_start();
688         if (err)
689                 /* Problems, clean up */
690                 sigpvc_stop();
691
692         return (err);
693 }
694
695
696 /*
697  * Generic module unload processing
698  * 
699  * This function is called by an OS-specific function when this
700  * module is being unloaded.
701  *
702  * Arguments:
703  *      none
704  *
705  * Returns:
706  *      0       unload was successful 
707  *      errno   unload failed - reason indicated
708  *
709  */
710 static int
711 sigpvc_dounload(void)
712 {
713         int     err = 0;
714
715         /*
716          * OK, try to clean up our mess
717          */
718         err = sigpvc_stop();
719
720         return (err);
721 }
722
723 #include <sys/exec.h>
724 #include <sys/sysent.h>
725 #include <sys/lkm.h>
726
727 /*
728  * Loadable miscellaneous module description
729  */
730 MOD_MISC(sigpvc);
731
732
733 /*
734  * Loadable module support "load" entry point
735  * 
736  * This is the routine called by the lkm driver whenever the
737  * modload(1) command is issued for this module.
738  *
739  * Arguments:
740  *      lkmtp   pointer to lkm drivers's structure
741  *      cmd     lkm command code
742  *
743  * Returns:
744  *      0       command was successful 
745  *      errno   command failed - reason indicated
746  *
747  */
748 static int
749 sigpvc_load(struct lkm_table *lkmtp, int cmd)
750 {
751         return(sigpvc_doload());
752 }
753
754
755 /*
756  * Loadable module support "unload" entry point
757  * 
758  * This is the routine called by the lkm driver whenever the
759  * modunload(1) command is issued for this module.
760  *
761  * Arguments:
762  *      lkmtp   pointer to lkm drivers's structure
763  *      cmd     lkm command code
764  *
765  * Returns:
766  *      0       command was successful 
767  *      errno   command failed - reason indicated
768  *
769  */
770 static int
771 sigpvc_unload(struct lkm_table *lkmtp, int cmd)
772 {
773         return(sigpvc_dounload());
774 }
775
776
777 /*
778  * Loadable module support entry point
779  * 
780  * This is the routine called by the lkm driver for all loadable module
781  * functions for this driver.  This routine name must be specified
782  * on the modload(1) command.  This routine will be called whenever the
783  * modload(1), modunload(1) or modstat(1) commands are issued for this
784  * module.
785  *
786  * Arguments:
787  *      lkmtp   pointer to lkm drivers's structure
788  *      cmd     lkm command code
789  *      ver     lkm version
790  *
791  * Returns:
792  *      0       command was successful 
793  *      errno   command failed - reason indicated
794  *
795  */
796 int
797 sigpvc_mod(struct lkm_table *lkmtp, int cmd, int ver)
798 {
799         MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
800                 sigpvc_load, sigpvc_unload, lkm_nullcmd);
801 }
802
803 #else   /* !ATM_SIGPVC_MODULE */
804
805 /*
806  *******************************************************************
807  *
808  * Kernel Compiled Module Support
809  *
810  *******************************************************************
811  */
812 static void     sigpvc_doload (void *);
813
814 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
815
816 /*
817  * Kernel initialization
818  * 
819  * Arguments:
820  *      arg     Not used
821  *
822  * Returns:
823  *      none
824  *
825  */
826 static void
827 sigpvc_doload(void *arg)
828 {
829         int     err = 0;
830
831         /*
832          * Start us up
833          */
834         err = sigpvc_start();
835         if (err) {
836                 /* Problems, clean up */
837                 sigpvc_stop();
838
839                 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
840         }
841         return;
842 }
843 #endif  /* ATM_SIGPVC_MODULE */
844