Do you think /sys/netproto needs to use __P() prototypes?
[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.5 2003/08/23 10:06:22 rob 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()
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()
156 {
157         int     err = 0;
158         int     s = splnet();
159
160         /*
161          * Is protocol even setup?
162          */
163         if (sigpvc_registered) {
164                 
165                 /*
166                  * Any protocol instances still registered??
167                  */
168                 if (sigpvc_mgr.sm_prinst) {
169
170                         /* Yes, can't stop now */
171                         err = EBUSY;
172                         goto done;
173                 }
174
175                 /*
176                  * De-register from system
177                  */
178                 err = atm_sigmgr_deregister(&sigpvc_mgr);
179                 sigpvc_registered = 0;
180
181                 /*
182                  * Free up our vccb storage pool
183                  */
184                 atm_release_pool(&sigpvc_vcpool);
185         } else
186                 err = ENXIO;
187
188 done:
189         (void) splx(s);
190         return (err);
191 }
192
193
194 /*
195  * Attach a SigPVC-controlled interface
196  * 
197  * Each ATM physical interface must be attached with the signalling manager for
198  * the interface's signalling protocol (via the atm_sigmgr_attach function).  
199  * This function will handle the attachment for SigPVC-controlled interfaces.
200  * A new sigpvc protocol instance will be created and then we'll just sit
201  * around waiting for connection requests.
202  *
203  * Function must be called at splnet.
204  *
205  * Arguments:
206  *      smp     pointer to sigpvc signalling manager control block
207  *      pip     pointer to atm physical interface control block
208  *
209  * Returns:
210  *      0       attach successful 
211  *      errno   attach failed - reason indicated
212  *
213  */
214 static int
215 sigpvc_attach(smp, pip)
216         struct sigmgr   *smp;
217         struct atm_pif  *pip;
218 {
219         int     err = 0;
220         struct sigpvc   *pvp = NULL;
221
222         /*
223          * Allocate sigpvc protocol instance control block
224          */
225         pvp = (struct sigpvc *)
226                 KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT);
227         if (pvp == NULL) {
228                 err = ENOMEM;
229                 goto done;
230         }
231         KM_ZERO(pvp, sizeof(struct sigpvc));
232
233         /*
234          * Link instance into manager's chain
235          */
236         LINK2TAIL((struct siginst *)pvp, struct siginst, 
237                 smp->sm_prinst, si_next);
238
239         /*
240          * Finally, set state and link in interface
241          */
242         pvp->pv_pif = pip;
243         pvp->pv_state = SIGPVC_ACTIVE;
244         pip->pif_sigmgr = smp;
245         pip->pif_siginst = (struct siginst *)pvp;
246
247 done:
248         /*
249          * Reset our work if attach fails
250          */
251         if (err) {
252                 pip->pif_sigmgr = NULL;
253                 pip->pif_siginst = NULL;
254                 if (pvp) {
255                         UNLINK((struct siginst *)pvp, struct siginst, 
256                                 smp->sm_prinst, si_next);
257                         KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
258                 }
259         }
260
261         return (err);
262 }
263
264
265 /*
266  * Detach a SigPVC-controlled interface
267  * 
268  * Each ATM physical interface may be detached from its signalling manager 
269  * (via the atm_sigmgr_detach function).  This function will handle the 
270  * detachment for all SigPVC-controlled interfaces.  All circuits will be 
271  * immediately terminated.
272  *
273  * Function must be called at splnet.
274  *
275  * Arguments:
276  *      pip     pointer to atm physical interface control block
277  *
278  * Returns:
279  *      0       detach successful 
280  *      errno   detach failed - reason indicated
281  *
282  */
283 static int
284 sigpvc_detach(pip)
285         struct atm_pif  *pip;
286 {
287         struct sigpvc   *pvp;
288         struct vccb     *vcp, *vnext;
289
290         /*
291          * Get SigPVC protocol instance
292          */
293         pvp = (struct sigpvc *)pip->pif_siginst;
294
295         /*
296          * Terminate all of our VCCs
297          */
298         for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
299                 u_char  oustate;
300
301                 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
302
303                 /*
304                  * Close VCC and notify owner
305                  */
306                 oustate = vcp->vc_ustate;
307                 sigpvc_close_vcc(vcp);
308                 if (oustate == VCCU_OPEN) {
309                         vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
310                         atm_cm_cleared(vcp->vc_connvc);
311                 }
312         }
313
314         /*
315          * If there are no vcc's queued, then get rid of the protocol 
316          * instance.  
317          */
318         if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
319                 struct sigmgr   *smp = pip->pif_sigmgr;
320
321                 pip->pif_sigmgr = NULL;
322                 pip->pif_siginst = NULL;
323                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
324                                 si_next);
325                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
326         } else {
327
328                 /*
329                  * Otherwise, set new state indicating detach in progress.
330                  * The protocol instance will be freed during sigpvc_free 
331                  * processing for the last queued vcc.
332                  */
333                 pvp->pv_state = SIGPVC_DETACH;
334         }
335
336         return (0);
337 }
338
339
340 /*
341  * Open a SigPVC ATM Connection
342  * 
343  * All service user requests to open a VC connection (via atm_open_connection)
344  * over an ATM interface attached to the SigPVC signalling manager are handled 
345  * here.  Only PVC requests are allowed.
346  *
347  * Function will be called at splnet.
348  *
349  * Arguments:
350  *      cvp     pointer to CM's connection VCC
351  *      errp    location to store an error code if CALL_FAILED is returned
352  *
353  * Returns:
354  *      CALL_PROCEEDING - connection establishment is in progress
355  *      CALL_FAILED     - connection establishment failed
356  *      CALL_CONNECTED  - connection has been successfully established
357  *
358  */
359 static int
360 sigpvc_setup(cvp, errp)
361         Atm_connvc      *cvp;
362         int             *errp;
363 {
364         struct sigpvc   *pvp =
365                 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
366         int     ret;
367
368         /*
369          * See what signalling has to say
370          */
371         switch (pvp->pv_state) {
372
373         case SIGPVC_ACTIVE:
374                 break;
375
376         default:
377                 *errp = ENXIO;
378                 ret = CALL_FAILED;
379                 goto done;
380         }
381         
382         /*
383          * Open requested type of connection
384          */
385         switch (cvp->cvc_attr.called.addr.address_format) {
386
387         case T_ATM_PVC_ADDR:
388                 /*
389                  * Create a PVC
390                  */
391                 ret = sigpvc_create_pvc(pvp, cvp, errp);
392                 break;
393
394         default:
395                 *errp = EPROTONOSUPPORT;
396                 ret = CALL_FAILED;
397         }
398
399 done:
400         return (ret);
401 }
402
403
404 /*
405  * Close a SigPVC ATM Connection
406  * 
407  * All service user requests to terminate a previously open VC connection 
408  * (via the atm_close_connection function), which is running over an interface 
409  * attached to the SigPVC signalling manager, are handled here.
410  *
411  * Function will be called at splnet.
412  * 
413  * Arguments:
414  *      vcp     pointer to connection's VC control block
415  *      errp    location to store an error code if CALL_FAILED is returned
416  *
417  * Returns:
418  *      CALL_PROCEEDING - connection termination is in progress
419  *      CALL_FAILED     - connection termination failed
420  *      CALL_CLEARED    - connection has been successfully terminated
421  *
422  */
423 static int
424 sigpvc_release(vcp, errp)
425         struct vccb     *vcp;
426         int             *errp;
427 {
428
429         /*
430          * Make sure VCC is open
431          */
432         if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
433             (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
434                 *errp = EALREADY;
435                 return (CALL_FAILED);
436         }
437
438         /*
439          * Not much else to do except close the vccb
440          */
441         sigpvc_close_vcc(vcp);
442
443         return (CALL_CLEARED);
444 }
445
446
447 /*
448  * Free SigPVC ATM Connection Resources
449  * 
450  * All service user requests to free the resources of a closed VCC connection
451  * (via the atm_free_connection function), which is running over an interface 
452  * attached to the SigPVC signalling manager, are handled here.
453  *
454  * Function will be called at splnet.
455  * 
456  * Arguments:
457  *      vcp     pointer to connection's VCC control block
458  *
459  * Returns:
460  *      0       connection free was successful 
461  *      errno   connection free failed - reason indicated
462  *
463  */
464 static int
465 sigpvc_free(vcp)
466         struct vccb     *vcp;
467 {
468         struct atm_pif  *pip = vcp->vc_pif;
469         struct sigpvc   *pvp = (struct sigpvc *)pip->pif_siginst;
470
471         /*
472          * Make sure VCC has been closed
473          */
474         if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
475                 return (EEXIST);
476
477         /*
478          * Remove vccb from protocol queue
479          */
480         DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
481
482         /*
483          * Free vccb storage
484          */
485         vcp->vc_ustate = VCCU_NULL;
486         vcp->vc_sstate = VCCS_NULL;
487         atm_free((caddr_t)vcp);
488
489         /*
490          * If we're detaching and this was the last vcc queued,
491          * get rid of the protocol instance
492          */
493         if ((pvp->pv_state == SIGPVC_DETACH) && 
494             (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
495                 struct sigmgr   *smp = pip->pif_sigmgr;
496
497                 pip->pif_sigmgr = NULL;
498                 pip->pif_siginst = NULL;
499                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
500                                 si_next);
501                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
502         }
503
504         return (0);
505 }
506
507
508 /*
509  * Process Signalling Manager PF_ATM ioctls
510  * 
511  * Function will be called at splnet.
512  *
513  * Arguments:
514  *      code    PF_ATM sub-operation code
515  *      data    pointer to code specific parameter data area
516  *      arg1    pointer to code specific argument
517  *
518  * Returns:
519  *      0       request procesed
520  *      errno   error processing request - reason indicated
521  *
522  */
523 static int
524 sigpvc_ioctl(code, data, arg1)
525         int             code;
526         caddr_t         data;
527         caddr_t         arg1;
528 {
529         struct atmdelreq        *adp;
530         struct atminfreq        *aip;
531         struct air_vcc_rsp      avr;
532         struct sigpvc   *pvp;
533         struct vccb     *vcp;
534         Atm_connection  *cop;
535         caddr_t         cp;
536         u_int   vpi, vci;
537         int     i, space, err = 0;
538
539
540         switch (code) {
541
542         case AIOCS_DEL_PVC:
543                 /*
544                  * Delete a PVC
545                  */
546                 adp = (struct atmdelreq *)data;
547                 pvp = (struct sigpvc *)arg1;
548
549                 /*
550                  * Find requested VCC
551                  */
552                 vpi = adp->adr_pvc_vpi;
553                 vci = adp->adr_pvc_vci;
554                 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; 
555                                 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
556                         if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
557                                 break;
558                 }
559                 if (vcp == NULL)
560                         return (ENOENT);
561
562                 /*
563                  * Schedule VCC termination
564                  */
565                 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
566                 break;
567
568         case AIOCS_DEL_SVC:
569                 /*
570                  * Delete a SVC
571                  */
572                 err = ENOENT;
573                 break;
574
575         case AIOCS_INF_VCC:
576                 /*
577                  * Get VCC information
578                  */
579                 aip = (struct atminfreq *)data;
580                 pvp = (struct sigpvc *)arg1;
581
582                 cp = aip->air_buf_addr;
583                 space = aip->air_buf_len;
584
585                 /*
586                  * Get info for all VCCs on interface
587                  */
588                 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; 
589                                 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
590                         /*
591                          * Make sure there's room in user buffer
592                          */
593                         if (space < sizeof(avr)) {
594                                 err = ENOSPC;
595                                 break;
596                         }
597
598                         /*
599                          * Fill in info to be returned
600                          */
601                         (void) snprintf(avr.avp_intf, sizeof(avr.avp_intf),
602                                 "%s%d",
603                                 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
604                         avr.avp_vpi = vcp->vc_vpi;
605                         avr.avp_vci = vcp->vc_vci;
606                         avr.avp_type = vcp->vc_type;
607                         avr.avp_sig_proto = ATM_SIG_PVC;
608                         avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
609                         cop = vcp->vc_connvc->cvc_conn;
610                         if  (cop)
611                                 avr.avp_encaps = cop->co_mpx;
612                         else
613                                 avr.avp_encaps = 0;
614                         KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
615                         for (i = 0; cop && i < sizeof(avr.avp_owners);
616                                         cop = cop->co_next,
617                                         i += T_ATM_APP_NAME_LEN+1) {
618                                 strncpy(&avr.avp_owners[i],
619                                         cop->co_endpt->ep_getname(cop->co_toku),
620                                         T_ATM_APP_NAME_LEN);
621                         }
622                         avr.avp_state = vcp->vc_sstate;
623                         avr.avp_daddr.address_format = T_ATM_ABSENT;
624                         avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
625                         avr.avp_ipdus = vcp->vc_ipdus;
626                         avr.avp_opdus = vcp->vc_opdus;
627                         avr.avp_ibytes = vcp->vc_ibytes;
628                         avr.avp_obytes = vcp->vc_obytes;
629                         avr.avp_ierrors = vcp->vc_ierrors;
630                         avr.avp_oerrors = vcp->vc_oerrors;
631                         avr.avp_tstamp = vcp->vc_tstamp;
632
633                         /*
634                          * Copy data to user buffer and update buffer info
635                          */
636                         if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
637                                 break;
638                         cp += sizeof(avr);
639                         space -= sizeof(avr);
640                 }
641
642                 /*
643                  * Update buffer pointer/count
644                  */
645                 aip->air_buf_addr = cp;
646                 aip->air_buf_len = space;
647                 break;
648
649         case AIOCS_INF_ARP:
650         case AIOCS_INF_ASV:
651                 /*
652                  * Get ARP table/server information
653                  */
654                 /* We don't maintain any ARP information */
655                 break;
656
657         default:
658                 err = EOPNOTSUPP;
659         }
660
661         return (err);
662 }
663
664
665 #ifdef ATM_SIGPVC_MODULE
666 /*
667  *******************************************************************
668  *
669  * Loadable Module Support
670  *
671  *******************************************************************
672  */
673 static int      sigpvc_doload (void);
674 static int      sigpvc_dounload (void);
675
676 /*
677  * Generic module load processing
678  * 
679  * This function is called by an OS-specific function when this
680  * module is being loaded.
681  *
682  * Arguments:
683  *      none
684  *
685  * Returns:
686  *      0       load was successful 
687  *      errno   load failed - reason indicated
688  *
689  */
690 static int
691 sigpvc_doload()
692 {
693         int     err = 0;
694
695         /*
696          * Start us up
697          */
698         err = sigpvc_start();
699         if (err)
700                 /* Problems, clean up */
701                 (void)sigpvc_stop();
702
703         return (err);
704 }
705
706
707 /*
708  * Generic module unload processing
709  * 
710  * This function is called by an OS-specific function when this
711  * module is being unloaded.
712  *
713  * Arguments:
714  *      none
715  *
716  * Returns:
717  *      0       unload was successful 
718  *      errno   unload failed - reason indicated
719  *
720  */
721 static int
722 sigpvc_dounload()
723 {
724         int     err = 0;
725
726         /*
727          * OK, try to clean up our mess
728          */
729         err = sigpvc_stop();
730
731         return (err);
732 }
733
734
735 #ifdef sun
736 /*
737  * Loadable driver description
738  */
739 struct vdldrv sigpvc_drv = {
740         VDMAGIC_PSEUDO, /* Pseudo Driver */
741         "sigpvc_mod",   /* name */
742         NULL,           /* dev_ops */
743         NULL,           /* bdevsw */
744         NULL,           /* cdevsw */
745         0,              /* blockmajor */
746         0               /* charmajor */
747 };
748
749
750 /*
751  * Loadable module support entry point
752  * 
753  * This is the routine called by the vd driver for all loadable module
754  * functions for this pseudo driver.  This routine name must be specified
755  * on the modload(1) command.  This routine will be called whenever the
756  * modload(1), modunload(1) or modstat(1) commands are issued for this
757  * module.
758  *
759  * Arguments:
760  *      cmd     vd command code
761  *      vdp     pointer to vd driver's structure
762  *      vdi     pointer to command-specific vdioctl_* structure
763  *      vds     pointer to status structure (VDSTAT only)
764  *
765  * Returns:
766  *      0       command was successful 
767  *      errno   command failed - reason indicated
768  *
769  */
770 int
771 sigpvc_mod(cmd, vdp, vdi, vds)
772         int             cmd;
773         struct vddrv    *vdp;
774         caddr_t         vdi;
775         struct vdstat   *vds;
776 {
777         int     err = 0;
778
779         switch (cmd) {
780
781         case VDLOAD:
782                 /*
783                  * Module Load
784                  *
785                  * We dont support any user configuration
786                  */
787                 err = sigpvc_doload();
788                 if (err == 0)
789                         /* Let vd driver know about us */
790                         vdp->vdd_vdtab = (struct vdlinkage *)&sigpvc_drv;
791                 break;
792
793         case VDUNLOAD:
794                 /*
795                  * Module Unload
796                  */
797                 err = sigpvc_dounload();
798                 break;
799
800         case VDSTAT:
801                 /*
802                  * Module Status
803                  */
804
805                 /* Not much to say at the moment */
806
807                 break;
808
809         default:
810                 log(LOG_ERR, "sigpvc_mod: Unknown vd command 0x%x\n", cmd);
811                 err = EINVAL;
812         }
813
814         return (err);
815 }
816 #endif  /* sun */
817
818 #ifdef __FreeBSD__
819
820 #include <sys/exec.h>
821 #include <sys/sysent.h>
822 #include <sys/lkm.h>
823
824 /*
825  * Loadable miscellaneous module description
826  */
827 MOD_MISC(sigpvc);
828
829
830 /*
831  * Loadable module support "load" entry point
832  * 
833  * This is the routine called by the lkm driver whenever the
834  * modload(1) command is issued for this module.
835  *
836  * Arguments:
837  *      lkmtp   pointer to lkm drivers's structure
838  *      cmd     lkm command code
839  *
840  * Returns:
841  *      0       command was successful 
842  *      errno   command failed - reason indicated
843  *
844  */
845 static int
846 sigpvc_load(lkmtp, cmd)
847         struct lkm_table        *lkmtp;
848         int             cmd;
849 {
850         return(sigpvc_doload());
851 }
852
853
854 /*
855  * Loadable module support "unload" entry point
856  * 
857  * This is the routine called by the lkm driver whenever the
858  * modunload(1) command is issued for this module.
859  *
860  * Arguments:
861  *      lkmtp   pointer to lkm drivers's structure
862  *      cmd     lkm command code
863  *
864  * Returns:
865  *      0       command was successful 
866  *      errno   command failed - reason indicated
867  *
868  */
869 static int
870 sigpvc_unload(lkmtp, cmd)
871         struct lkm_table        *lkmtp;
872         int             cmd;
873 {
874         return(sigpvc_dounload());
875 }
876
877
878 /*
879  * Loadable module support entry point
880  * 
881  * This is the routine called by the lkm driver for all loadable module
882  * functions for this driver.  This routine name must be specified
883  * on the modload(1) command.  This routine will be called whenever the
884  * modload(1), modunload(1) or modstat(1) commands are issued for this
885  * module.
886  *
887  * Arguments:
888  *      lkmtp   pointer to lkm drivers's structure
889  *      cmd     lkm command code
890  *      ver     lkm version
891  *
892  * Returns:
893  *      0       command was successful 
894  *      errno   command failed - reason indicated
895  *
896  */
897 int
898 sigpvc_mod(lkmtp, cmd, ver)
899         struct lkm_table        *lkmtp;
900         int             cmd;
901         int             ver;
902 {
903         MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
904                 sigpvc_load, sigpvc_unload, lkm_nullcmd);
905 }
906 #endif  /* __FreeBSD__ */
907
908 #else   /* !ATM_SIGPVC_MODULE */
909
910 /*
911  *******************************************************************
912  *
913  * Kernel Compiled Module Support
914  *
915  *******************************************************************
916  */
917 static void     sigpvc_doload (void *);
918
919 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
920
921 /*
922  * Kernel initialization
923  * 
924  * Arguments:
925  *      arg     Not used
926  *
927  * Returns:
928  *      none
929  *
930  */
931 static void
932 sigpvc_doload(void *arg)
933 {
934         int     err = 0;
935
936         /*
937          * Start us up
938          */
939         err = sigpvc_start();
940         if (err) {
941                 /* Problems, clean up */
942                 (void)sigpvc_stop();
943
944                 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
945         }
946         return;
947 }
948 #endif  /* ATM_SIGPVC_MODULE */
949