Pre-2.0 release: Sync with HAMMER 65 - simplify PFS operations.
[dragonfly.git] / sys / netproto / atm / atm_signal.c
blob1bf139d71ae1f80d375846584384a1cae9798b67
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
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 $
31 * Core ATM Services
32 * -----------------
34 * General ATM signalling management
38 #include "kern_include.h"
41 * Local variables
43 static struct sigmgr *atm_sigmgr_head = NULL;
44 static struct stack_defn *atm_stack_head = NULL;
48 * Register a new Signalling Manager
50 * Each Signalling Manager must register itself here upon completing
51 * its internal initialization. This applies to both linked and loaded
52 * managers.
54 * Arguments:
55 * smp pointer to Signalling Manager description
57 * Returns:
58 * 0 registration was successful
59 * errno registration failed - reason indicated
62 int
63 atm_sigmgr_register(struct sigmgr *smp)
65 struct sigmgr *smp2;
67 crit_enter();
70 * See if we need to be initialized
72 if (!atm_init)
73 atm_initialize();
76 * Make sure there's only one instance of each protocol
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);
86 * Looks okay, link it in
88 LINK2TAIL(smp, struct sigmgr, atm_sigmgr_head, sm_next);
90 crit_exit();
91 return (0);
96 * De-register a Signalling Manager
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.
104 * Arguments:
105 * smp pointer to Signalling Manager description
107 * Returns:
108 * 0 deregistration was successful
109 * errno deregistration failed - reason indicated
113 atm_sigmgr_deregister(struct sigmgr *smp)
115 int found;
118 * Unlink descriptor
120 crit_enter();
121 UNLINKF(smp, struct sigmgr, atm_sigmgr_head, sm_next, found);
122 crit_exit();
124 if (!found)
125 return (ENOENT);
127 return (0);
132 * Attach a Signalling Manager to an ATM physical interface
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.
140 * Called from a critical section.
142 * Arguments:
143 * pip pointer to atm physical interface control block
144 * proto requested signalling protocol
146 * Returns:
147 * 0 attach successful
148 * errno attach failed - reason indicated
152 atm_sigmgr_attach(struct atm_pif *pip, u_char proto)
154 struct atm_pif *tp;
155 struct sigmgr *smp;
156 int err;
159 * Make sure interface is registered
161 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
162 if (tp == pip)
163 break;
165 if (tp == NULL) {
166 return (ENOENT);
170 * Make sure no signalling manager is already attached
172 if (pip->pif_sigmgr != NULL) {
173 return (EEXIST);
177 * Must have at least one network interface defined
179 if (pip->pif_nif == NULL)
180 return (ETOOMANYREFS);
183 * Find requested protocol
185 for (smp = atm_sigmgr_head; smp != NULL; smp = smp->sm_next) {
186 if (smp->sm_proto == proto)
187 break;
189 if (smp == NULL) {
190 return (EPROTONOSUPPORT);
194 * Tell the signal manager about it
196 err = (*smp->sm_attach)(smp, pip);
199 * Tell all registered convergence modules about this
201 if (!err) {
202 struct atm_nif *nip;
203 struct atm_ncm *ncp;
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;
211 if (err)
212 break;
215 if (err) {
217 * Someone's unhappy, so back all this out
219 atm_sigmgr_detach(pip);
223 return (err);
228 * Detach an ATM physical interface from a Signalling Manager
230 * The ATM interface must be detached from the signalling manager
231 * before the interface can be de-registered.
233 * Called from a critical section.
235 * Arguments:
236 * pip pointer to atm physical interface control block
238 * Returns:
239 * 0 detach successful
240 * errno detach failed - reason indicated
244 atm_sigmgr_detach(struct atm_pif *pip)
246 struct atm_pif *tp;
247 struct atm_nif *nip;
248 struct atm_ncm *ncp;
249 int err;
253 * Make sure interface is registered
255 for (tp = atm_interface_head; tp != NULL; tp = tp->pif_next) {
256 if (tp == pip)
257 break;
259 if (tp == NULL) {
260 return (ENOENT);
264 * Make sure a signalling manager is attached
266 if (pip->pif_sigmgr == NULL) {
267 return (ENOENT);
271 * Tell all registered convergence modules about this
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);
280 * Tell the signal manager about it
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.
287 err = (*pip->pif_sigmgr->sm_detach)(pip);
289 return (err);
294 * Register an ATM Stack Service
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).
302 * Arguments:
303 * sdp pointer to stack service definition block
305 * Returns:
306 * 0 registration successful
307 * errno registration failed - reason indicated
311 atm_stack_register(struct stack_defn *sdp)
313 struct stack_defn *tdp;
315 crit_enter();
318 * See if we need to be initialized
320 if (!atm_init)
321 atm_initialize();
324 * Ensure no duplicates
326 for (tdp = atm_stack_head; tdp != NULL; tdp = tdp->sd_next) {
327 if (tdp->sd_sap == sdp->sd_sap)
328 break;
330 if (tdp != NULL) {
331 crit_exit();
332 return (EEXIST);
336 * Add stack to list
338 LINK2TAIL(sdp, struct stack_defn, atm_stack_head, sd_next);
340 crit_exit();
341 return (0);
346 * De-register an ATM Stack Service
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.
352 * Arguments:
353 * sdp pointer to stack service definition block
355 * Returns:
356 * 0 de-registration successful
357 * errno de-registration failed - reason indicated
361 atm_stack_deregister(struct stack_defn *sdp)
363 int found;
366 * Remove service from list
368 crit_enter();
369 UNLINKF(sdp, struct stack_defn, atm_stack_head, sd_next, found);
370 crit_exit();
372 if (!found)
373 return (ENOENT);
375 return (0);
380 * Create and Instantiate a Stack
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.
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.
394 * Must be called from a critical section.
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
401 * Returns:
402 * 0 stack successfully created
403 * errno failed - reason indicated
407 atm_create_stack(Atm_connvc *cvp, struct stack_list *tlp,
408 void (*upf)(int, void *, int, int))
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;
417 * Initialize stack (element 0 is for owner's services)
419 svs.si_srvc[1] = sdp = NULL;
422 * Locate service provider for each service in the
423 * stack list. We prefer interface driver providers
424 * over kernel module providers.
426 for (i = 0; i < STACK_CNT; i++) {
427 Sap_t sap;
429 /* Stack list is 0-terminated */
430 if ((sap = tlp->sl_sap[i]) == 0)
431 break;
434 * Search interface's services
436 for (sdp = pip->pif_services; sdp; sdp = sdp->sd_next)
437 if (sdp->sd_sap == sap)
438 break;
439 if (sdp == NULL) {
442 * Search kernel services
444 for (sdp = atm_stack_head; sdp;
445 sdp = sdp->sd_next)
446 if (sdp->sd_sap == sap)
447 break;
449 if (sdp == NULL) {
452 * Requested service id not found
454 return (ENOENT);
458 * Save stack definition for this service
460 svs.si_srvc[i+1] = sdp;
463 * Quit loop if this service is terminal, ie. if
464 * it takes care of the rest of the stack.
466 if (sdp->sd_flag & SDF_TERM)
467 break;
471 * Ensure stack instance array is located and terminated
473 if ((svs.si_srvc[1] == NULL) || !(sdp->sd_flag & SDF_TERM)) {
474 return (ENOENT);
478 * Setup owner service definition
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;
486 * Instantiate the stack
488 err = (*svs.si_srvc[1]->sd_inst)(&svs.si_srvc[0], cvp);
489 if (err) {
490 return (err);
494 * Save top 'o stack info
496 cvp->cvc_lower = svs.si_srvc[1]->sd_lower;
497 cvp->cvc_tokl = svs.si_srvc[1]->sd_toku;
499 return (0);