]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netatm/atm_signal.c
This commit was generated by cvs2svn to compensate for changes in r95908,
[FreeBSD/FreeBSD.git] / sys / netatm / atm_signal.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$
27  *
28  */
29
30 /*
31  * Core ATM Services
32  * -----------------
33  *
34  * General ATM signalling management
35  *
36  */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <net/if.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_sys.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_cm.h>
49 #include <netatm/atm_if.h>
50 #include <netatm/atm_sigmgr.h>
51 #include <netatm/atm_stack.h>
52 #include <netatm/atm_pcb.h>
53 #include <netatm/atm_var.h>
54
55 #ifndef lint
56 __RCSID("@(#) $FreeBSD$");
57 #endif
58
59
60 /*
61  * Local variables
62  */
63 static struct sigmgr    *atm_sigmgr_head = NULL;
64 static struct stack_defn        *atm_stack_head = NULL;
65
66
67 /*
68  * Register a new Signalling Manager
69  * 
70  * Each Signalling Manager must register itself here upon completing
71  * its internal initialization.  This applies to both linked and loaded
72  * managers.
73  *
74  * Arguments:
75  *      smp     pointer to Signalling Manager description
76  *
77  * Returns:
78  *      0       registration was successful 
79  *      errno   registration failed - reason indicated
80  *
81  */
82 int
83 atm_sigmgr_register(smp)
84         struct sigmgr   *smp;
85 {
86         struct sigmgr   *smp2;
87         int             s = splnet();
88
89         /*
90          * See if we need to be initialized
91          */
92         if (!atm_init)
93                 atm_initialize();
94
95         /*
96          * Make sure there's only one instance of each protocol
97          */
98         for (smp2 = atm_sigmgr_head; smp2 != NULL; smp2 = smp2->sm_next) {
99                 if (smp->sm_proto == smp2->sm_proto) {
100                         (void) splx(s);
101                         return (EEXIST);
102                 }
103         }
104
105         /*
106          * Looks okay, link it in
107          */
108         LINK2TAIL(smp, struct sigmgr, atm_sigmgr_head, sm_next);
109
110         (void) splx(s);
111         return (0);
112 }
113
114
115 /*
116  * De-register a Signalling Manager
117  * 
118  * Each Signalling Manager must de-register (is this really a word?)
119  * itself before removing itself from the system.  This really only
120  * applies to managers about to be modunload'ed.  It is the signal
121  * manager's responsibility to ensure that all its protocol instances
122  * have been successfully terminated before de-registering itself.
123  *
124  * Arguments:
125  *      smp     pointer to Signalling Manager description
126  *
127  * Returns:
128  *      0       deregistration was successful 
129  *      errno   deregistration failed - reason indicated
130  *
131  */
132 int
133 atm_sigmgr_deregister(smp)
134         struct sigmgr   *smp;
135 {
136         int             found, s = splnet();
137
138         /*
139          * Unlink descriptor
140          */
141         UNLINKF(smp, struct sigmgr, atm_sigmgr_head, sm_next, found);
142
143         (void) splx(s);
144
145         if (!found)
146                 return (ENOENT);
147
148         return (0);
149 }
150
151
152 /*
153  * Attach a Signalling Manager to an ATM physical interface
154  * 
155  * Each ATM physical interface must have a signalling manager attached to 
156  * itself for the signalling protocol to be run across this interface.  The 
157  * interface must be registered and completely initialized before the attach, 
158  * since the signalling manager may initiate virtual circuit activity as part 
159  * its response to this call.
160  *
161  * Called at splnet.
162  *
163  * Arguments:
164  *      pip     pointer to atm physical interface control block
165  *      proto   requested signalling protocol
166  *
167  * Returns:
168  *      0       attach successful
169  *      errno   attach failed - reason indicated
170  *
171  */
172 int
173 atm_sigmgr_attach(pip, proto)
174         struct atm_pif  *pip;
175         u_char          proto;
176 {
177         struct atm_pif  *tp;
178         struct sigmgr   *smp;
179         int     err;
180
181         /*
182          * Make sure interface is registered
183          */
184         for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
185                 if (tp == pip)
186                         break;
187         }
188         if (tp == NULL) {
189                 return (ENOENT);
190         }
191
192         /*
193          * Make sure no signalling manager is already attached
194          */
195         if (pip->pif_sigmgr != NULL) {
196                 return (EEXIST);
197         }
198
199         /*
200          * Must have at least one network interface defined
201          */
202         if (pip->pif_nif == NULL)
203                 return (ETOOMANYREFS);
204
205         /*
206          * Find requested protocol
207          */
208         for (smp = atm_sigmgr_head; smp != NULL; smp = smp->sm_next) {
209                 if (smp->sm_proto == proto)
210                         break;
211         }
212         if (smp == NULL) {
213                 return (EPROTONOSUPPORT);
214         }
215
216         /*
217          * Tell the signal manager about it
218          */
219         err = (*smp->sm_attach)(smp, pip);
220
221         /*
222          * Tell all registered convergence modules about this
223          */
224         if (!err) {
225                 struct atm_nif  *nip;
226                 struct atm_ncm  *ncp;
227
228                 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
229                         for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
230                                 if ((err = (*ncp->ncm_stat)
231                                                 (NCM_SIGATTACH, nip, 0)) != 0)
232                                         break;
233                         }
234                         if (err)
235                                 break;
236                 }
237
238                 if (err) {
239                         /*
240                          * Someone's unhappy, so back all this out
241                          */
242                         (void) atm_sigmgr_detach(pip);
243                 }
244         }
245
246         return (err);
247 }
248
249
250 /*
251  * Detach an ATM physical interface from a Signalling Manager
252  * 
253  * The ATM interface must be detached from the signalling manager
254  * before the interface can be de-registered.  
255  *
256  * Called at splnet.
257  *
258  * Arguments:
259  *      pip     pointer to atm physical interface control block
260  *
261  * Returns:
262  *      0       detach successful
263  *      errno   detach failed - reason indicated
264  *
265  */
266 int
267 atm_sigmgr_detach(pip)
268         struct atm_pif  *pip;
269 {
270         struct atm_pif  *tp;
271         struct atm_nif  *nip;
272         struct atm_ncm  *ncp;
273         int     err;
274
275
276         /*
277          * Make sure interface is registered
278          */
279         for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
280                 if (tp == pip)
281                         break;
282         }
283         if (tp == NULL) {
284                 return (ENOENT);
285         }
286
287         /*
288          * Make sure a signalling manager is attached
289          */
290         if (pip->pif_sigmgr == NULL) {
291                 return (ENOENT);
292         }
293
294         /*
295          * Tell all registered convergence modules about this
296          */
297         for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
298                 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
299                         (void) (*ncp->ncm_stat)(NCM_SIGDETACH, nip, 0);
300                 }
301         }
302
303         /*
304          * Tell the signal manager about it
305          *
306          * NOTE:
307          * The only reason this should ever fail is if things are really
308          * hosed up somewhere, in which case doing a bunch of NCM_SIGATTACH's
309          * here just doesn't seem to help much.
310          */
311         err = (*pip->pif_sigmgr->sm_detach)(pip);
312
313         return (err);
314 }
315
316
317 /*
318  * Register an ATM Stack Service
319  * 
320  * Each ATM stack service provider must register its provided service(s) here.
321  * Each service must be registered separately.  Service providers include 
322  * both loaded and linked kernel modules.  Device driver services are NOT 
323  * registered here - their service registry is performed implicitly through 
324  * the device interface structure stack services list (pif_services).
325  *
326  * Arguments:
327  *      sdp     pointer to stack service definition block
328  *
329  * Returns:
330  *      0       registration successful
331  *      errno   registration failed - reason indicated
332  *
333  */
334 int
335 atm_stack_register(sdp)
336         struct stack_defn       *sdp;
337 {
338         struct stack_defn       *tdp;
339         int     s = splnet();
340
341         /*
342          * See if we need to be initialized
343          */
344         if (!atm_init)
345                 atm_initialize();
346
347         /*
348          * Ensure no duplicates
349          */
350         for (tdp = atm_stack_head; tdp != NULL; tdp = tdp->sd_next) {
351                 if (tdp->sd_sap == sdp->sd_sap)
352                         break;
353         }
354         if (tdp != NULL) {
355                 (void) splx(s);
356                 return (EEXIST);
357         }
358
359         /*
360          * Add stack to list
361          */
362         LINK2TAIL(sdp, struct stack_defn, atm_stack_head, sd_next);
363
364         (void) splx(s);
365         return (0);
366 }
367
368
369 /*
370  * De-register an ATM Stack Service
371  * 
372  * Each ATM stack service provider must de-register its registered service(s)
373  * before terminating the service.  Specifically, loaded kernel modules
374  * must de-register their services before unloading themselves.
375  *
376  * Arguments:
377  *      sdp     pointer to stack service definition block
378  *
379  * Returns:
380  *      0       de-registration successful 
381  *      errno   de-registration failed - reason indicated
382  *
383  */
384 int
385 atm_stack_deregister(sdp)
386         struct stack_defn       *sdp;
387 {
388         int     found, s = splnet();
389
390         /*
391          * Remove service from list
392          */
393         UNLINKF(sdp, struct stack_defn, atm_stack_head, sd_next, found);
394         (void) splx(s);
395
396         if (!found)
397                 return (ENOENT);
398
399         return (0);
400 }
401
402
403 /*
404  * Create and Instantiate a Stack
405  * 
406  * For the requested stack list, locate the stack service definitions 
407  * necessary to build the stack to implement the listed services.
408  * The stack service definitions provided by the interface device-driver
409  * are always preferred, since they are (hopefully) done with 
410  * hardware assistance from the interface card.
411  *
412  * After the stack has been built, the selected services are called to 
413  * notify them of the new stack instantiation.  Each service should then 
414  * allocate all the resources it requires for this new stack instance.  
415  * The service should then wait for subsequent protocol notification
416  * via its stack command handlers.
417  *
418  * Must be called at splnet.
419  *
420  * Arguments:
421  *      cvp     pointer to connection vcc block for the created stack
422  *      tlp     pointer to stack list
423  *      upf     top-of-stack CM upper command handler
424  *
425  * Returns:
426  *      0       stack successfully created
427  *      errno   failed - reason indicated
428  *
429  */
430 int
431 atm_create_stack(cvp, tlp, upf)
432         Atm_connvc              *cvp;
433         struct stack_list       *tlp;
434         void                    (*upf)(int, void *, int, int);
435 {
436         struct stack_defn       *sdp, usd;
437         struct stack_inst       svs;
438         struct atm_pif          *pip = cvp->cvc_attr.nif->nif_pif;
439         int             i, err;
440
441
442         /*
443          * Initialize stack (element 0 is for owner's services)
444          */
445         svs.si_srvc[1] = sdp = NULL;
446
447         /*
448          * Locate service provider for each service in the
449          * stack list.  We prefer interface driver providers
450          * over kernel module providers.
451          */
452         for (i = 0; i < STACK_CNT; i++) {
453                 Sap_t           sap;
454
455                 /* Stack list is 0-terminated */
456                 if ((sap = tlp->sl_sap[i]) == 0)
457                         break;
458
459                 /*
460                  * Search interface's services
461                  */
462                 for (sdp = pip->pif_services; sdp; sdp = sdp->sd_next)
463                         if (sdp->sd_sap == sap)
464                                 break;
465                 if (sdp == NULL) {
466
467                         /*
468                          * Search kernel services
469                          */
470                         for (sdp = atm_stack_head; sdp; 
471                                                  sdp = sdp->sd_next)
472                                 if (sdp->sd_sap == sap)
473                                         break;
474                 }
475                 if (sdp == NULL) {
476
477                         /*
478                          * Requested service id not found
479                          */
480                         return (ENOENT);
481                 }
482
483                 /*
484                  * Save stack definition for this service
485                  */
486                 svs.si_srvc[i+1] = sdp;
487
488                 /*
489                  * Quit loop if this service is terminal, ie. if
490                  * it takes care of the rest of the stack.
491                  */
492                 if (sdp->sd_flag & SDF_TERM)
493                         break;
494         }
495
496         /*
497          * Ensure stack instance array is located and terminated
498          */
499         if ((svs.si_srvc[1] == NULL) || !(sdp->sd_flag & SDF_TERM)) {
500                 return (ENOENT);
501         }
502
503         /*
504          * Setup owner service definition
505          */
506         bzero((caddr_t)&usd, sizeof(struct stack_defn));
507         usd.sd_upper = upf;
508         usd.sd_toku = cvp;
509         svs.si_srvc[0] = &usd;
510
511         /*
512          * Instantiate the stack
513          */
514         err = (*svs.si_srvc[1]->sd_inst)(&svs.si_srvc[0], cvp);
515         if (err) {
516                 return (err);
517         }
518
519         /*
520          * Save top 'o stack info
521          */
522         cvp->cvc_lower = svs.si_srvc[1]->sd_lower;
523         cvp->cvc_tokl = svs.si_srvc[1]->sd_toku;
524
525         return (0);
526 }
527