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