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