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