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