]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer4/i4b_l4mgmt.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer4 / i4b_l4mgmt.c
1 /*-
2  * Copyright (c) 1997, 2002 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*---------------------------------------------------------------------------
27  *
28  *      i4b_l4mgmt.c - layer 4 calldescriptor management utilites
29  *      -----------------------------------------------------------
30  *      last edit-date: [Sun Aug 11 12:42:01 2002]
31  *
32  *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40
41 #include <i4b/include/i4b_debug.h>
42 #include <i4b/include/i4b_ioctl.h>
43
44 #include <i4b/include/i4b_l3l4.h>
45 #include <i4b/include/i4b_global.h>
46
47 #include <i4b/layer4/i4b_l4.h>
48
49 call_desc_t call_desc[N_CALL_DESC];     /* call descriptor array */
50
51 static unsigned int get_cdid(void);
52
53 int nctrl;                              /* number of attached controllers */
54
55 void i4b_init_callout(call_desc_t *);
56
57 /*---------------------------------------------------------------------------*
58  *      return a new unique call descriptor id
59  *      --------------------------------------
60  *      returns a new calldescriptor id which is used to uniquely identyfy
61  *      a single call in the communication between kernel and userland.
62  *      this cdid is then used to associate a calldescriptor with an id.
63  *---------------------------------------------------------------------------*/
64 static unsigned int
65 get_cdid(void)
66 {
67         static unsigned int cdid_count = 0;
68         int i;
69         int x;
70
71         x = SPLI4B();
72
73         /* get next id */
74
75         cdid_count++;
76
77 again:
78         if(cdid_count == CDID_UNUSED)           /* zero is invalid */
79                 cdid_count++;
80         else if(cdid_count > CDID_MAX)          /* wraparound ? */
81                 cdid_count = 1;
82
83         /* check if id already in use */
84
85         for(i=0; i < N_CALL_DESC; i++)
86         {
87                 if(call_desc[i].cdid == cdid_count)
88                 {
89                         cdid_count++;
90                         goto again;
91                 }
92         }
93
94         splx(x);
95
96         return(cdid_count);
97 }
98
99 /*---------------------------------------------------------------------------*
100  *      reserve a calldescriptor for later usage
101  *      ----------------------------------------
102  *      searches the calldescriptor array until an unused
103  *      descriptor is found, gets a new calldescriptor id
104  *      and reserves it by putting the id into the cdid field.
105  *      returns pointer to the calldescriptor.
106  *---------------------------------------------------------------------------*/
107 call_desc_t *
108 reserve_cd(void)
109 {
110         call_desc_t *cd;
111         int x;
112         int i;
113
114         x = SPLI4B();
115
116         cd = NULL;
117
118         for(i=0; i < N_CALL_DESC; i++)
119         {
120                 if(call_desc[i].cdid == CDID_UNUSED)
121                 {
122                         bzero(&call_desc[i], sizeof(call_desc_t)); /* clear it */
123                         call_desc[i].cdid = get_cdid(); /* fill in new cdid */
124                         cd = &(call_desc[i]);   /* get pointer to descriptor */
125                         NDBGL4(L4_MSG, "found free cd - index=%d cdid=%u",
126                                  i, call_desc[i].cdid);
127                         break;
128                 }
129         }
130
131         splx(x);
132
133         if(cd == NULL)
134                 panic("reserve_cd: no free call descriptor available!");
135
136         i4b_init_callout(cd);
137
138         return(cd);
139 }
140
141 /*---------------------------------------------------------------------------*
142  *      free a calldescriptor
143  *      ---------------------
144  *      free an unused calldescriptor by giving address of calldescriptor
145  *      and writing a 0 into the cdid field marking it as unused.
146  *---------------------------------------------------------------------------*/
147 void
148 freecd_by_cd(call_desc_t *cd)
149 {
150         int i;
151         int x = SPLI4B();
152
153         for(i=0; i < N_CALL_DESC; i++)
154         {
155                 if( (call_desc[i].cdid != CDID_UNUSED) &&
156                     (&(call_desc[i]) == cd) )
157                 {
158                         NDBGL4(L4_MSG, "releasing cd - index=%d cdid=%u cr=%d",
159                                 i, call_desc[i].cdid, cd->cr);
160                         call_desc[i].cdid = CDID_UNUSED;
161                         break;
162                 }
163         }
164
165         if(i == N_CALL_DESC)
166                 panic("freecd_by_cd: ERROR, cd not found, cr = %d\n", cd->cr);
167
168         splx(x);
169 }
170
171 /*---------------------------------------------------------------------------*
172  *      return pointer to calldescriptor by giving the calldescriptor id
173  *      ----------------------------------------------------------------
174  *      lookup a calldescriptor in the calldescriptor array by looking
175  *      at the cdid field. return pointer to calldescriptor if found,
176  *      else return NULL if not found.
177  *---------------------------------------------------------------------------*/
178 call_desc_t *
179 cd_by_cdid(unsigned int cdid)
180 {
181         int i;
182
183         for(i=0; i < N_CALL_DESC; i++)
184         {
185                 if(call_desc[i].cdid == cdid)
186                 {
187                         NDBGL4(L4_MSG, "found cdid - index=%d cdid=%u cr=%d",
188                                         i, call_desc[i].cdid, call_desc[i].cr);
189
190                         i4b_init_callout(&call_desc[i]);
191
192                         return(&(call_desc[i]));
193                 }
194         }
195         return(NULL);
196 }
197
198 /*---------------------------------------------------------------------------*
199  *      search calldescriptor
200  *      ---------------------
201  *      This routine searches for the calldescriptor for a passive controller
202  *      given by unit number, callreference and callreference flag.
203  *      It returns a pointer to the calldescriptor if found, else a NULL.
204  *---------------------------------------------------------------------------*/
205 call_desc_t *
206 cd_by_unitcr(int unit, int cr, int crf)
207 {
208         int i;
209
210         for(i=0; i < N_CALL_DESC; i++)
211         {
212           if((call_desc[i].cdid != CDID_UNUSED)                                       &&
213              (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
214              (ctrl_desc[call_desc[i].controller].unit == unit)              &&
215              (call_desc[i].cr == cr)                                        &&
216              (call_desc[i].crflag == crf) )
217           {
218             NDBGL4(L4_MSG, "found cd, index=%d cdid=%u cr=%d",
219                         i, call_desc[i].cdid, call_desc[i].cr);
220
221             i4b_init_callout(&call_desc[i]);
222
223             return(&(call_desc[i]));
224           }
225         }
226         return(NULL);
227 }
228
229 /*---------------------------------------------------------------------------*
230  *      generate 7 bit "random" number used for outgoing Call Reference
231  *---------------------------------------------------------------------------*/
232 unsigned char
233 get_rand_cr(int unit)
234 {
235         register int i, j;
236         static u_char val, retval;
237         static int called = 42;
238
239         val += ++called;
240
241         for(i=0; i < 50 ; i++, val++)
242         {
243                 int found = 1;
244
245 #ifdef RANDOMDEV
246                 read_random((char *)&val, sizeof(val));
247 #else
248                 val = (u_char)random();
249 #endif /* RANDOMDEV */
250
251                 retval = val & 0x7f;
252
253                 if(retval == 0 || retval == 0x7f)
254                         continue;
255
256                 for(j=0; j < N_CALL_DESC; j++)
257                 {
258                         if( (call_desc[j].cdid != CDID_UNUSED) &&
259                             (call_desc[j].cr == retval) )
260                         {
261                                 found = 0;
262                                 break;
263                         }
264                 }
265
266                 if(found)
267                         return(retval);
268         }
269         return(0);      /* XXX */
270 }
271
272 /*---------------------------------------------------------------------------*
273  *      initialize the callout handles for FreeBSD
274  *---------------------------------------------------------------------------*/
275 void
276 i4b_init_callout(call_desc_t *cd)
277 {
278         if(cd->callouts_inited == 0)
279         {
280                 callout_handle_init(&cd->idle_timeout_handle);
281                 callout_handle_init(&cd->T303_callout);
282                 callout_handle_init(&cd->T305_callout);
283                 callout_handle_init(&cd->T308_callout);
284                 callout_handle_init(&cd->T309_callout);
285                 callout_handle_init(&cd->T310_callout);
286                 callout_handle_init(&cd->T313_callout);
287                 callout_handle_init(&cd->T400_callout);
288                 cd->callouts_inited = 1;
289         }
290 }
291
292 /*---------------------------------------------------------------------------*
293  *      daemon is attached
294  *---------------------------------------------------------------------------*/
295 void
296 i4b_l4_daemon_attached(void)
297 {
298         int i;
299
300         int x = SPLI4B();
301
302         for(i=0; i < nctrl; i++)
303         {
304 /*XXX*/         if(*ctrl_desc[i].N_MGMT_COMMAND &&
305                    (ctrl_desc[i].ctrl_type == CTRL_PASSIVE ||
306                     ctrl_desc[i].ctrl_type == CTRL_CAPIMGR))
307                 {
308                         NDBGL4(L4_MSG, "CMR_DOPEN sent to unit %d", ctrl_desc[i].unit);
309                         (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DOPEN, 0);
310                 }
311         }
312         splx(x);
313 }
314
315 /*---------------------------------------------------------------------------*
316  *      daemon is detached
317  *---------------------------------------------------------------------------*/
318 void
319 i4b_l4_daemon_detached(void)
320 {
321         int i;
322
323         int x = SPLI4B();
324
325         for(i=0; i < nctrl; i++)
326         {
327 /*XXX*/         if(*ctrl_desc[i].N_MGMT_COMMAND &&
328                    (ctrl_desc[i].ctrl_type == CTRL_PASSIVE ||
329                     ctrl_desc[i].ctrl_type == CTRL_CAPIMGR))
330                 {
331                         NDBGL4(L4_MSG, "CMR_DCLOSE sent to unit %d", ctrl_desc[i].unit);
332                         (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DCLOSE, 0);
333                 }
334         }
335         splx(x);
336 }
337
338 #ifdef I4B_CD_DEBUG_PRINT
339
340 extern char *print_l3state(call_desc_t *cd);
341
342 void i4b_print_cdp(call_desc_t *cdp);
343 void i4b_print_cdx(int index);
344 void i4b_print_cda(void);
345 void i4b_print_cdaa(void);
346
347 /*---------------------------------------------------------------------------*
348  *      print a call descriptor by cd-pointer
349  *---------------------------------------------------------------------------*/
350 void
351 i4b_print_cdp(call_desc_t *cdp)
352 {
353         if((cdp > &(call_desc[N_CALL_DESC])) || (cdp < &(call_desc[0])))
354         {
355                 printf("i4b_print_cd: cdp out of range!\n");
356                 return;
357         }
358
359         printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp - (&(call_desc[0])), (unsigned long)cdp);
360
361         printf("         cdid = %d\n", cdp->cdid);
362         printf("   controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n",
363                         cdp->controller,
364                         ctrl_desc[cdp->controller].unit,
365                         ctrl_desc[cdp->controller].dl_est,
366                         ctrl_desc[cdp->controller].bch_state[CHAN_B1],
367                         ctrl_desc[cdp->controller].bch_state[CHAN_B2]);
368         printf("           cr = 0x%02x\n", cdp->cr);
369         printf("       crflag = %d\n", cdp->crflag);
370         printf("    channelid = %d\n", cdp->channelid);
371         printf("        bprot = %d\n", cdp->bprot);
372         printf("         bcap = %d\n", cdp->bcap);
373         printf("       driver = %d\n", cdp->driver);
374         printf("  driver_unit = %d\n", cdp->driver_unit);
375         printf("   call_state = %d\n", cdp->call_state);
376         printf("    Q931state = %s\n", print_l3state(cdp));
377         printf("        event = %d\n", cdp->event);
378         printf("     response = %d\n", cdp->response);
379         printf("         T303 = %d\n", cdp->T303);
380         printf("T303_first_to = %d\n", cdp->T303_first_to);
381         printf("         T305 = %d\n", cdp->T305);
382         printf("         T308 = %d\n", cdp->T308);
383         printf("T308_first_to = %d\n", cdp->T308_first_to);
384         printf("         T309 = %d\n", cdp->T309);
385         printf("         T310 = %d\n", cdp->T310);
386         printf("         T313 = %d\n", cdp->T313);
387         printf("         T400 = %d\n", cdp->T400);
388         printf("          dir = %s\n", cdp->dir == DIR_OUTGOING ? "out" : "in");
389 }
390
391 /*---------------------------------------------------------------------------*
392  *      print a call descriptor by index
393  *---------------------------------------------------------------------------*/
394 void
395 i4b_print_cdx(int index)
396 {
397         if(index >= N_CALL_DESC)
398         {
399                 printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index, N_CALL_DESC);
400                 return;
401         }
402         i4b_print_cdp(&(call_desc[index]));
403 }
404
405 /*---------------------------------------------------------------------------*
406  *      print all call descriptors
407  *---------------------------------------------------------------------------*/
408 void
409 i4b_print_cda(void)
410 {
411         int i;
412
413         for(i=0; i < N_CALL_DESC; i++)
414         {
415                 i4b_print_cdp(&(call_desc[i]));
416         }
417 }
418
419 /*---------------------------------------------------------------------------*
420  *      print all active call descriptors
421  *---------------------------------------------------------------------------*/
422 void
423 i4b_print_cdaa(void)
424 {
425         int i;
426
427         for(i=0; i < N_CALL_DESC; i++)
428         {
429                 if(call_desc[i].cdid != CDID_UNUSED)
430                 {
431                         i4b_print_cdp(&(call_desc[i]));
432                 }
433         }
434 }
435
436 #endif /* I4B_CD_DEBUG_PRINT */