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