Initial import from FreeBSD RELENG_4:
[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  *
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 <netatm/kern_include.h>
44
45 #include <netatm/sigpvc/sigpvc_var.h>
46
47 #ifndef lint
48 __RCSID("@(#) $FreeBSD: src/sys/netatm/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $");
49 #endif
50
51
52 /*
53  * Global variables
54  */
55 struct sp_info  sigpvc_vcpool = {
56         "sigpvc vcc pool",              /* si_name */
57         sizeof(struct sigpvc_vccb),     /* si_blksiz */
58         10,                             /* si_blkcnt */
59         50                              /* si_maxallow */
60 };
61
62 /*
63  * Local functions
64  */
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));
73
74 /*
75  * Local variables
76  */
77 static int      sigpvc_registered = 0;
78 static struct sigmgr    sigpvc_mgr = {
79         NULL,
80         ATM_SIG_PVC,
81         NULL,
82         sigpvc_attach,
83         sigpvc_detach,
84         sigpvc_setup,
85         NULL,
86         NULL,
87         sigpvc_release,
88         sigpvc_free,
89         sigpvc_ioctl
90 };
91
92 static struct attr_cause        sigpvc_cause = {
93         T_ATM_PRESENT,
94         {
95                 T_ATM_ITU_CODING,
96                 T_ATM_LOC_USER,
97                 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
98                 {0, 0, 0, 0}
99         }
100 };
101
102
103 /*
104  * Initialize sigpvc processing
105  * 
106  * This will be called during module loading.  We'll just register
107  * the sigpvc protocol descriptor and wait for a SigPVC ATM interface 
108  * to come online.
109  *
110  * Arguments:
111  *      none
112  *
113  * Returns:
114  *      0       startup was successful 
115  *      errno   startup failed - reason indicated
116  *
117  */
118 static int
119 sigpvc_start()
120 {
121         int     err = 0;
122
123         /*
124          * Verify software version
125          */
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));
130                 return (EINVAL);
131         }
132
133         /*
134          * Register ourselves with system
135          */
136         err = atm_sigmgr_register(&sigpvc_mgr);
137         if (err == 0)
138                 sigpvc_registered = 1;
139
140         return (err);
141 }
142
143
144 /*
145  * Halt sigpvc processing 
146  * 
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.
150  *
151  * Arguments:
152  *      none
153  *
154  * Returns:
155  *      0       shutdown was successful 
156  *      errno   shutdown failed - reason indicated
157  *
158  */
159 static int
160 sigpvc_stop()
161 {
162         int     err = 0;
163         int     s = splnet();
164
165         /*
166          * Is protocol even setup?
167          */
168         if (sigpvc_registered) {
169                 
170                 /*
171                  * Any protocol instances still registered??
172                  */
173                 if (sigpvc_mgr.sm_prinst) {
174
175                         /* Yes, can't stop now */
176                         err = EBUSY;
177                         goto done;
178                 }
179
180                 /*
181                  * De-register from system
182                  */
183                 err = atm_sigmgr_deregister(&sigpvc_mgr);
184                 sigpvc_registered = 0;
185
186                 /*
187                  * Free up our vccb storage pool
188                  */
189                 atm_release_pool(&sigpvc_vcpool);
190         } else
191                 err = ENXIO;
192
193 done:
194         (void) splx(s);
195         return (err);
196 }
197
198
199 /*
200  * Attach a SigPVC-controlled interface
201  * 
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.
207  *
208  * Function must be called at splnet.
209  *
210  * Arguments:
211  *      smp     pointer to sigpvc signalling manager control block
212  *      pip     pointer to atm physical interface control block
213  *
214  * Returns:
215  *      0       attach successful 
216  *      errno   attach failed - reason indicated
217  *
218  */
219 static int
220 sigpvc_attach(smp, pip)
221         struct sigmgr   *smp;
222         struct atm_pif  *pip;
223 {
224         int     err = 0;
225         struct sigpvc   *pvp = NULL;
226
227         /*
228          * Allocate sigpvc protocol instance control block
229          */
230         pvp = (struct sigpvc *)
231                 KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT);
232         if (pvp == NULL) {
233                 err = ENOMEM;
234                 goto done;
235         }
236         KM_ZERO(pvp, sizeof(struct sigpvc));
237
238         /*
239          * Link instance into manager's chain
240          */
241         LINK2TAIL((struct siginst *)pvp, struct siginst, 
242                 smp->sm_prinst, si_next);
243
244         /*
245          * Finally, set state and link in interface
246          */
247         pvp->pv_pif = pip;
248         pvp->pv_state = SIGPVC_ACTIVE;
249         pip->pif_sigmgr = smp;
250         pip->pif_siginst = (struct siginst *)pvp;
251
252 done:
253         /*
254          * Reset our work if attach fails
255          */
256         if (err) {
257                 pip->pif_sigmgr = NULL;
258                 pip->pif_siginst = NULL;
259                 if (pvp) {
260                         UNLINK((struct siginst *)pvp, struct siginst, 
261                                 smp->sm_prinst, si_next);
262                         KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
263                 }
264         }
265
266         return (err);
267 }
268
269
270 /*
271  * Detach a SigPVC-controlled interface
272  * 
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.
277  *
278  * Function must be called at splnet.
279  *
280  * Arguments:
281  *      pip     pointer to atm physical interface control block
282  *
283  * Returns:
284  *      0       detach successful 
285  *      errno   detach failed - reason indicated
286  *
287  */
288 static int
289 sigpvc_detach(pip)
290         struct atm_pif  *pip;
291 {
292         struct sigpvc   *pvp;
293         struct vccb     *vcp, *vnext;
294
295         /*
296          * Get SigPVC protocol instance
297          */
298         pvp = (struct sigpvc *)pip->pif_siginst;
299
300         /*
301          * Terminate all of our VCCs
302          */
303         for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
304                 u_char  oustate;
305
306                 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
307
308                 /*
309                  * Close VCC and notify owner
310                  */
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);
316                 }
317         }
318
319         /*
320          * If there are no vcc's queued, then get rid of the protocol 
321          * instance.  
322          */
323         if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
324                 struct sigmgr   *smp = pip->pif_sigmgr;
325
326                 pip->pif_sigmgr = NULL;
327                 pip->pif_siginst = NULL;
328                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
329                                 si_next);
330                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
331         } else {
332
333                 /*
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.
337                  */
338                 pvp->pv_state = SIGPVC_DETACH;
339         }
340
341         return (0);
342 }
343
344
345 /*
346  * Open a SigPVC ATM Connection
347  * 
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.
351  *
352  * Function will be called at splnet.
353  *
354  * Arguments:
355  *      cvp     pointer to CM's connection VCC
356  *      errp    location to store an error code if CALL_FAILED is returned
357  *
358  * Returns:
359  *      CALL_PROCEEDING - connection establishment is in progress
360  *      CALL_FAILED     - connection establishment failed
361  *      CALL_CONNECTED  - connection has been successfully established
362  *
363  */
364 static int
365 sigpvc_setup(cvp, errp)
366         Atm_connvc      *cvp;
367         int             *errp;
368 {
369         struct sigpvc   *pvp =
370                 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
371         int     ret;
372
373         /*
374          * See what signalling has to say
375          */
376         switch (pvp->pv_state) {
377
378         case SIGPVC_ACTIVE:
379                 break;
380
381         default:
382                 *errp = ENXIO;
383                 ret = CALL_FAILED;
384                 goto done;
385         }
386         
387         /*
388          * Open requested type of connection
389          */
390         switch (cvp->cvc_attr.called.addr.address_format) {
391
392         case T_ATM_PVC_ADDR:
393                 /*
394                  * Create a PVC
395                  */
396                 ret = sigpvc_create_pvc(pvp, cvp, errp);
397                 break;
398
399         default:
400                 *errp = EPROTONOSUPPORT;
401                 ret = CALL_FAILED;
402         }
403
404 done:
405         return (ret);
406 }
407
408
409 /*
410  * Close a SigPVC ATM Connection
411  * 
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.
415  *
416  * Function will be called at splnet.
417  * 
418  * Arguments:
419  *      vcp     pointer to connection's VC control block
420  *      errp    location to store an error code if CALL_FAILED is returned
421  *
422  * Returns:
423  *      CALL_PROCEEDING - connection termination is in progress
424  *      CALL_FAILED     - connection termination failed
425  *      CALL_CLEARED    - connection has been successfully terminated
426  *
427  */
428 static int
429 sigpvc_release(vcp, errp)
430         struct vccb     *vcp;
431         int             *errp;
432 {
433
434         /*
435          * Make sure VCC is open
436          */
437         if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
438             (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
439                 *errp = EALREADY;
440                 return (CALL_FAILED);
441         }
442
443         /*
444          * Not much else to do except close the vccb
445          */
446         sigpvc_close_vcc(vcp);
447
448         return (CALL_CLEARED);
449 }
450
451
452 /*
453  * Free SigPVC ATM Connection Resources
454  * 
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.
458  *
459  * Function will be called at splnet.
460  * 
461  * Arguments:
462  *      vcp     pointer to connection's VCC control block
463  *
464  * Returns:
465  *      0       connection free was successful 
466  *      errno   connection free failed - reason indicated
467  *
468  */
469 static int
470 sigpvc_free(vcp)
471         struct vccb     *vcp;
472 {
473         struct atm_pif  *pip = vcp->vc_pif;
474         struct sigpvc   *pvp = (struct sigpvc *)pip->pif_siginst;
475
476         /*
477          * Make sure VCC has been closed
478          */
479         if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
480                 return (EEXIST);
481
482         /*
483          * Remove vccb from protocol queue
484          */
485         DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
486
487         /*
488          * Free vccb storage
489          */
490         vcp->vc_ustate = VCCU_NULL;
491         vcp->vc_sstate = VCCS_NULL;
492         atm_free((caddr_t)vcp);
493
494         /*
495          * If we're detaching and this was the last vcc queued,
496          * get rid of the protocol instance
497          */
498         if ((pvp->pv_state == SIGPVC_DETACH) && 
499             (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
500                 struct sigmgr   *smp = pip->pif_sigmgr;
501
502                 pip->pif_sigmgr = NULL;
503                 pip->pif_siginst = NULL;
504                 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst, 
505                                 si_next);
506                 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
507         }
508
509         return (0);
510 }
511
512
513 /*
514  * Process Signalling Manager PF_ATM ioctls
515  * 
516  * Function will be called at splnet.
517  *
518  * Arguments:
519  *      code    PF_ATM sub-operation code
520  *      data    pointer to code specific parameter data area
521  *      arg1    pointer to code specific argument
522  *
523  * Returns:
524  *      0       request procesed
525  *      errno   error processing request - reason indicated
526  *
527  */
528 static int
529 sigpvc_ioctl(code, data, arg1)
530         int             code;
531         caddr_t         data;
532         caddr_t         arg1;
533 {
534         struct atmdelreq        *adp;
535         struct atminfreq        *aip;
536         struct air_vcc_rsp      avr;
537         struct sigpvc   *pvp;
538         struct vccb     *vcp;
539         Atm_connection  *cop;
540         caddr_t         cp;
541         u_int   vpi, vci;
542         int     i, space, err = 0;
543
544
545         switch (code) {
546
547         case AIOCS_DEL_PVC:
548                 /*
549                  * Delete a PVC
550                  */
551                 adp = (struct atmdelreq *)data;
552                 pvp = (struct sigpvc *)arg1;
553
554                 /*
555                  * Find requested VCC
556                  */
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))
562                                 break;
563                 }
564                 if (vcp == NULL)
565                         return (ENOENT);
566
567                 /*
568                  * Schedule VCC termination
569                  */
570                 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
571                 break;
572
573         case AIOCS_DEL_SVC:
574                 /*
575                  * Delete a SVC
576                  */
577                 err = ENOENT;
578                 break;
579
580         case AIOCS_INF_VCC:
581                 /*
582                  * Get VCC information
583                  */
584                 aip = (struct atminfreq *)data;
585                 pvp = (struct sigpvc *)arg1;
586
587                 cp = aip->air_buf_addr;
588                 space = aip->air_buf_len;
589
590                 /*
591                  * Get info for all VCCs on interface
592                  */
593                 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; 
594                                 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
595                         /*
596                          * Make sure there's room in user buffer
597                          */
598                         if (space < sizeof(avr)) {
599                                 err = ENOSPC;
600                                 break;
601                         }
602
603                         /*
604                          * Fill in info to be returned
605                          */
606                         (void) snprintf(avr.avp_intf, sizeof(avr.avp_intf),
607                                 "%s%d",
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;
615                         if  (cop)
616                                 avr.avp_encaps = cop->co_mpx;
617                         else
618                                 avr.avp_encaps = 0;
619                         KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
620                         for (i = 0; cop && i < sizeof(avr.avp_owners);
621                                         cop = cop->co_next,
622                                         i += T_ATM_APP_NAME_LEN+1) {
623                                 strncpy(&avr.avp_owners[i],
624                                         cop->co_endpt->ep_getname(cop->co_toku),
625                                         T_ATM_APP_NAME_LEN);
626                         }
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;
637
638                         /*
639                          * Copy data to user buffer and update buffer info
640                          */
641                         if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
642                                 break;
643                         cp += sizeof(avr);
644                         space -= sizeof(avr);
645                 }
646
647                 /*
648                  * Update buffer pointer/count
649                  */
650                 aip->air_buf_addr = cp;
651                 aip->air_buf_len = space;
652                 break;
653
654         case AIOCS_INF_ARP:
655         case AIOCS_INF_ASV:
656                 /*
657                  * Get ARP table/server information
658                  */
659                 /* We don't maintain any ARP information */
660                 break;
661
662         default:
663                 err = EOPNOTSUPP;
664         }
665
666         return (err);
667 }
668
669
670 #ifdef ATM_SIGPVC_MODULE
671 /*
672  *******************************************************************
673  *
674  * Loadable Module Support
675  *
676  *******************************************************************
677  */
678 static int      sigpvc_doload __P((void));
679 static int      sigpvc_dounload __P((void));
680
681 /*
682  * Generic module load processing
683  * 
684  * This function is called by an OS-specific function when this
685  * module is being loaded.
686  *
687  * Arguments:
688  *      none
689  *
690  * Returns:
691  *      0       load was successful 
692  *      errno   load failed - reason indicated
693  *
694  */
695 static int
696 sigpvc_doload()
697 {
698         int     err = 0;
699
700         /*
701          * Start us up
702          */
703         err = sigpvc_start();
704         if (err)
705                 /* Problems, clean up */
706                 (void)sigpvc_stop();
707
708         return (err);
709 }
710
711
712 /*
713  * Generic module unload processing
714  * 
715  * This function is called by an OS-specific function when this
716  * module is being unloaded.
717  *
718  * Arguments:
719  *      none
720  *
721  * Returns:
722  *      0       unload was successful 
723  *      errno   unload failed - reason indicated
724  *
725  */
726 static int
727 sigpvc_dounload()
728 {
729         int     err = 0;
730
731         /*
732          * OK, try to clean up our mess
733          */
734         err = sigpvc_stop();
735
736         return (err);
737 }
738
739
740 #ifdef sun
741 /*
742  * Loadable driver description
743  */
744 struct vdldrv sigpvc_drv = {
745         VDMAGIC_PSEUDO, /* Pseudo Driver */
746         "sigpvc_mod",   /* name */
747         NULL,           /* dev_ops */
748         NULL,           /* bdevsw */
749         NULL,           /* cdevsw */
750         0,              /* blockmajor */
751         0               /* charmajor */
752 };
753
754
755 /*
756  * Loadable module support entry point
757  * 
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
762  * module.
763  *
764  * Arguments:
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)
769  *
770  * Returns:
771  *      0       command was successful 
772  *      errno   command failed - reason indicated
773  *
774  */
775 int
776 sigpvc_mod(cmd, vdp, vdi, vds)
777         int             cmd;
778         struct vddrv    *vdp;
779         caddr_t         vdi;
780         struct vdstat   *vds;
781 {
782         int     err = 0;
783
784         switch (cmd) {
785
786         case VDLOAD:
787                 /*
788                  * Module Load
789                  *
790                  * We dont support any user configuration
791                  */
792                 err = sigpvc_doload();
793                 if (err == 0)
794                         /* Let vd driver know about us */
795                         vdp->vdd_vdtab = (struct vdlinkage *)&sigpvc_drv;
796                 break;
797
798         case VDUNLOAD:
799                 /*
800                  * Module Unload
801                  */
802                 err = sigpvc_dounload();
803                 break;
804
805         case VDSTAT:
806                 /*
807                  * Module Status
808                  */
809
810                 /* Not much to say at the moment */
811
812                 break;
813
814         default:
815                 log(LOG_ERR, "sigpvc_mod: Unknown vd command 0x%x\n", cmd);
816                 err = EINVAL;
817         }
818
819         return (err);
820 }
821 #endif  /* sun */
822
823 #ifdef __FreeBSD__
824
825 #include <sys/exec.h>
826 #include <sys/sysent.h>
827 #include <sys/lkm.h>
828
829 /*
830  * Loadable miscellaneous module description
831  */
832 MOD_MISC(sigpvc);
833
834
835 /*
836  * Loadable module support "load" entry point
837  * 
838  * This is the routine called by the lkm driver whenever the
839  * modload(1) command is issued for this module.
840  *
841  * Arguments:
842  *      lkmtp   pointer to lkm drivers's structure
843  *      cmd     lkm command code
844  *
845  * Returns:
846  *      0       command was successful 
847  *      errno   command failed - reason indicated
848  *
849  */
850 static int
851 sigpvc_load(lkmtp, cmd)
852         struct lkm_table        *lkmtp;
853         int             cmd;
854 {
855         return(sigpvc_doload());
856 }
857
858
859 /*
860  * Loadable module support "unload" entry point
861  * 
862  * This is the routine called by the lkm driver whenever the
863  * modunload(1) command is issued for this module.
864  *
865  * Arguments:
866  *      lkmtp   pointer to lkm drivers's structure
867  *      cmd     lkm command code
868  *
869  * Returns:
870  *      0       command was successful 
871  *      errno   command failed - reason indicated
872  *
873  */
874 static int
875 sigpvc_unload(lkmtp, cmd)
876         struct lkm_table        *lkmtp;
877         int             cmd;
878 {
879         return(sigpvc_dounload());
880 }
881
882
883 /*
884  * Loadable module support entry point
885  * 
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
890  * module.
891  *
892  * Arguments:
893  *      lkmtp   pointer to lkm drivers's structure
894  *      cmd     lkm command code
895  *      ver     lkm version
896  *
897  * Returns:
898  *      0       command was successful 
899  *      errno   command failed - reason indicated
900  *
901  */
902 int
903 sigpvc_mod(lkmtp, cmd, ver)
904         struct lkm_table        *lkmtp;
905         int             cmd;
906         int             ver;
907 {
908         MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
909                 sigpvc_load, sigpvc_unload, lkm_nullcmd);
910 }
911 #endif  /* __FreeBSD__ */
912
913 #else   /* !ATM_SIGPVC_MODULE */
914
915 /*
916  *******************************************************************
917  *
918  * Kernel Compiled Module Support
919  *
920  *******************************************************************
921  */
922 static void     sigpvc_doload __P((void *));
923
924 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
925
926 /*
927  * Kernel initialization
928  * 
929  * Arguments:
930  *      arg     Not used
931  *
932  * Returns:
933  *      none
934  *
935  */
936 static void
937 sigpvc_doload(void *arg)
938 {
939         int     err = 0;
940
941         /*
942          * Start us up
943          */
944         err = sigpvc_start();
945         if (err) {
946                 /* Problems, clean up */
947                 (void)sigpvc_stop();
948
949                 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
950         }
951         return;
952 }
953 #endif  /* ATM_SIGPVC_MODULE */
954