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