Nuke compatiblity parts.
[dragonfly.git] / sys / net / i4b / layer4 / i4b_l4mgmt.c
1 /*
2  * Copyright (c) 1997, 2000 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  *      i4b_l4mgmt.c - layer 4 calldescriptor management utilites
28  *      -----------------------------------------------------------
29  *
30  *      $Id: i4b_l4mgmt.c,v 1.34 2000/09/01 14:11:51 hm Exp $ 
31  *
32  * $FreeBSD: src/sys/i4b/layer4/i4b_l4mgmt.c,v 1.6.2.2 2001/08/10 14:08:43 obrien Exp $
33  * $DragonFly: src/sys/net/i4b/layer4/i4b_l4mgmt.c,v 1.8 2005/06/14 21:19:19 joerg Exp $
34  *
35  *      last edit-date: [Fri Oct 13 15:58:34 2000]
36  *
37  *---------------------------------------------------------------------------*/
38
39 #include "use_i4b.h"
40
41 #if NI4B > 0
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/thread2.h>
47
48 #include <net/i4b/include/machine/i4b_debug.h>
49 #include <net/i4b/include/machine/i4b_ioctl.h>
50
51 #include "../include/i4b_l3l4.h"
52 #include "../include/i4b_global.h"
53
54 #include "i4b_l4.h"
55
56 call_desc_t call_desc[N_CALL_DESC];     /* call descriptor array */
57
58 static unsigned int get_cdid(void);
59
60 int nctrl;                              /* number of attached controllers */
61
62 static void i4b_init_callout(call_desc_t *);
63
64 /*---------------------------------------------------------------------------*
65  *      return a new unique call descriptor id
66  *      --------------------------------------
67  *      returns a new calldescriptor id which is used to uniquely identyfy
68  *      a single call in the communication between kernel and userland.
69  *      this cdid is then used to associate a calldescriptor with an id.
70  *---------------------------------------------------------------------------*/
71 static unsigned int
72 get_cdid(void)
73 {
74         static unsigned int cdid_count = 0;
75         int i;
76
77         crit_enter();
78
79         /* get next id */
80         
81         cdid_count++;
82         
83 again:
84         if(cdid_count == CDID_UNUSED)           /* zero is invalid */
85                 cdid_count++;
86         else if(cdid_count > CDID_MAX)          /* wraparound ? */
87                 cdid_count = 1;
88
89         /* check if id already in use */
90         
91         for(i=0; i < N_CALL_DESC; i++)
92         {
93                 if(call_desc[i].cdid == cdid_count)
94                 {
95                         cdid_count++;
96                         goto again;
97                 }
98         }
99
100         crit_exit();
101         
102         return(cdid_count);
103 }
104
105 /*---------------------------------------------------------------------------*
106  *      reserve a calldescriptor for later usage
107  *      ----------------------------------------
108  *      searches the calldescriptor array until an unused
109  *      descriptor is found, gets a new calldescriptor id
110  *      and reserves it by putting the id into the cdid field.
111  *      returns pointer to the calldescriptor.
112  *---------------------------------------------------------------------------*/
113 call_desc_t *
114 reserve_cd(void)
115 {
116         call_desc_t *cd;
117         int i;
118
119         crit_enter();
120
121         cd = NULL;
122         
123         for(i=0; i < N_CALL_DESC; i++)
124         {
125                 if(call_desc[i].cdid == CDID_UNUSED)
126                 {
127                         bzero(&call_desc[i], sizeof(call_desc_t)); /* clear it */
128                         call_desc[i].cdid = get_cdid(); /* fill in new cdid */
129                         cd = &(call_desc[i]);   /* get pointer to descriptor */
130                         NDBGL4(L4_MSG, "found free cd - index=%d cdid=%u",
131                                  i, call_desc[i].cdid);
132                         break;
133                 }
134         }
135
136         crit_exit();
137
138         if(cd == NULL)
139                 panic("reserve_cd: no free call descriptor available!");
140
141         i4b_init_callout(cd);
142
143         return(cd);
144 }
145
146 /*---------------------------------------------------------------------------*
147  *      free a calldescriptor
148  *      ---------------------
149  *      free a unused calldescriptor by giving address of calldescriptor
150  *      and writing a 0 into the cdid field marking it as unused.
151  *---------------------------------------------------------------------------*/
152 void
153 freecd_by_cd(call_desc_t *cd)
154 {
155         int i;
156
157         crit_enter();
158         
159         for(i=0; i < N_CALL_DESC; i++)
160         {
161                 if( (call_desc[i].cdid != CDID_UNUSED) &&
162                     (&(call_desc[i]) == cd) )
163                 {
164                         NDBGL4(L4_MSG, "releasing cd - index=%d cdid=%u cr=%d",
165                                 i, call_desc[i].cdid, cd->cr);
166                         call_desc[i].cdid = CDID_UNUSED;
167                         break;
168                 }
169         }
170
171         if(i == N_CALL_DESC)
172                 panic("freecd_by_cd: ERROR, cd not found, cr = %d\n", cd->cr);
173
174         crit_exit();
175 }
176
177 /*---------------------------------------------------------------------------*
178  *      return pointer to calldescriptor by giving the calldescriptor id
179  *      ----------------------------------------------------------------
180  *      lookup a calldescriptor in the calldescriptor array by looking
181  *      at the cdid field. return pointer to calldescriptor if found,
182  *      else return NULL if not found.
183  *---------------------------------------------------------------------------*/
184 call_desc_t *
185 cd_by_cdid(unsigned int cdid)
186 {
187         int i;
188
189         for(i=0; i < N_CALL_DESC; i++)
190         {
191                 if(call_desc[i].cdid == cdid)
192                 {
193                         NDBGL4(L4_MSG, "found cdid - index=%d cdid=%u cr=%d",
194                                         i, call_desc[i].cdid, call_desc[i].cr);
195                         i4b_init_callout(&call_desc[i]);
196                         return(&(call_desc[i]));
197                 }
198         }
199         return(NULL);
200 }
201
202 /*---------------------------------------------------------------------------*
203  *      search calldescriptor
204  *      ---------------------
205  *      This routine searches for the calldescriptor for a passive controller
206  *      given by unit number, callreference and callreference flag.
207  *      It returns a pointer to the calldescriptor if found, else a NULL.
208  *---------------------------------------------------------------------------*/
209 call_desc_t *
210 cd_by_unitcr(int unit, int cr, int crf)
211 {
212         int i;
213
214         for(i=0; i < N_CALL_DESC; i++)
215         {
216           if((call_desc[i].cdid != CDID_UNUSED)                                       &&
217              (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
218              (ctrl_desc[call_desc[i].controller].unit == unit)              &&
219              (call_desc[i].cr == cr)                                        &&
220              (call_desc[i].crflag == crf) )
221           {
222             NDBGL4(L4_MSG, "found cd, index=%d cdid=%u cr=%d",
223                         i, call_desc[i].cdid, call_desc[i].cr);
224             i4b_init_callout(&call_desc[i]);
225             return(&(call_desc[i]));
226           }
227         }
228         return(NULL);
229 }
230
231 /*---------------------------------------------------------------------------*
232  *      generate 7 bit "random" number used for outgoing Call Reference
233  *---------------------------------------------------------------------------*/
234 unsigned char
235 get_rand_cr(int unit)
236 {
237         int i, j;
238         static u_char val, retval;
239         static int called = 42;
240         
241         val += ++called;
242         
243         for(i=0; i < 50 ; i++, val++)
244         {
245                 int found = 1;
246                 
247 #ifdef RANDOMDEV
248                 read_random((char *)&val, sizeof(val));
249 #else
250                 val = (u_char)random();
251 #endif /* RANDOMDEV */
252
253                 retval = val & 0x7f;
254                 
255                 if(retval == 0 || retval == 0x7f)
256                         continue;
257
258                 for(j=0; j < N_CALL_DESC; j++)
259                 {
260                         if( (call_desc[j].cdid != CDID_UNUSED) &&
261                             (call_desc[j].cr == retval) )
262                         {
263                                 found = 0;
264                                 break;
265                         }
266                 }
267
268                 if(found)
269                         return(retval);
270         }
271         return(0);      /* XXX */
272 }
273
274 /*---------------------------------------------------------------------------*
275  *      initialize the callout handles for FreeBSD
276  *---------------------------------------------------------------------------*/
277 static void
278 i4b_init_callout(call_desc_t *cd)
279 {
280         if(cd->callouts_inited == 0)
281         {
282                 callout_init(&cd->idle_timeout);
283                 callout_init(&cd->T303_timeout);
284                 callout_init(&cd->T305_timeout);
285                 callout_init(&cd->T308_timeout);
286                 callout_init(&cd->T309_timeout);
287                 callout_init(&cd->T310_timeout);
288                 callout_init(&cd->T313_timeout);
289                 callout_init(&cd->T400_timeout);
290                 cd->callouts_inited = 1;
291         }
292 }
293
294 /*---------------------------------------------------------------------------*
295  *      daemon is attached
296  *---------------------------------------------------------------------------*/
297 void 
298 i4b_l4_daemon_attached(void)
299 {
300         int i;
301
302         crit_enter();
303         
304         for(i=0; i < nctrl; i++)
305         {
306 /*XXX*/         if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE)
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         crit_exit();
313 }
314
315 /*---------------------------------------------------------------------------*
316  *      daemon is detached
317  *---------------------------------------------------------------------------*/
318 void 
319 i4b_l4_daemon_detached(void)
320 {
321         int i;
322
323         crit_enter();
324
325         for(i=0; i < nctrl; i++)
326         {
327 /*XXX*/         if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE)
328                 {
329                         NDBGL4(L4_MSG, "CMR_DCLOSE sent to unit %d", ctrl_desc[i].unit);
330                         (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DCLOSE, 0);
331                 }
332         }
333         crit_exit();
334 }
335
336 #ifdef I4B_CD_DEBUG_PRINT
337
338 extern char *print_l3state(call_desc_t *cd);
339
340 void i4b_print_cdp(call_desc_t *cdp);
341 void i4b_print_cdx(int index);
342 void i4b_print_cda(void);
343 void i4b_print_cdaa(void);
344         
345 /*---------------------------------------------------------------------------*
346  *      print a call descriptor by cd-pointer
347  *---------------------------------------------------------------------------*/
348 void 
349 i4b_print_cdp(call_desc_t *cdp)
350 {
351         if((cdp > &(call_desc[N_CALL_DESC])) || (cdp < &(call_desc[0])))
352         {
353                 printf("i4b_print_cd: cdp out of range!\n");
354                 return;
355         }
356
357         printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp - (&(call_desc[0])), (unsigned long)cdp);
358
359         printf("         cdid = %d\n", cdp->cdid);
360         printf("   controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n",
361                         cdp->controller,
362                         ctrl_desc[cdp->controller].unit,
363                         ctrl_desc[cdp->controller].dl_est,
364                         ctrl_desc[cdp->controller].bch_state[CHAN_B1],
365                         ctrl_desc[cdp->controller].bch_state[CHAN_B2]); 
366         printf("           cr = 0x%02x\n", cdp->cr);
367         printf("       crflag = %d\n", cdp->crflag);
368         printf("    channelid = %d\n", cdp->channelid);
369         printf("        bprot = %d\n", cdp->bprot);
370         printf("       driver = %d\n", cdp->driver);
371         printf("  driver_unit = %d\n", cdp->driver_unit);
372         printf("   call_state = %d\n", cdp->call_state);
373         printf("    Q931state = %s\n", print_l3state(cdp));
374         printf("        event = %d\n", cdp->event);
375         printf("     response = %d\n", cdp->response);
376         printf("         T303 = %d\n", cdp->T303);
377         printf("T303_first_to = %d\n", cdp->T303_first_to);
378         printf("         T305 = %d\n", cdp->T305);
379         printf("         T308 = %d\n", cdp->T308);
380         printf("T308_first_to = %d\n", cdp->T308_first_to);
381         printf("         T309 = %d\n", cdp->T309);
382         printf("         T310 = %d\n", cdp->T310);
383         printf("         T313 = %d\n", cdp->T313);
384         printf("         T400 = %d\n", cdp->T400);
385         printf("          dir = %s\n", cdp->dir == DIR_OUTGOING ? "out" : "in");
386 }
387
388 /*---------------------------------------------------------------------------*
389  *      print a call descriptor by index
390  *---------------------------------------------------------------------------*/
391 void 
392 i4b_print_cdx(int index)
393 {
394         if(index >= N_CALL_DESC)
395         {
396                 printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index, N_CALL_DESC);
397                 return;
398         }
399         i4b_print_cdp(&(call_desc[index]));
400 }
401
402 /*---------------------------------------------------------------------------*
403  *      print all call descriptors
404  *---------------------------------------------------------------------------*/
405 void 
406 i4b_print_cda(void)
407 {
408         int i;
409
410         for(i=0; i < N_CALL_DESC; i++)
411         {
412                 i4b_print_cdp(&(call_desc[i]));
413         }
414 }
415
416 /*---------------------------------------------------------------------------*
417  *      print all active call descriptors
418  *---------------------------------------------------------------------------*/
419 void 
420 i4b_print_cdaa(void)
421 {
422         int i;
423
424         for(i=0; i < N_CALL_DESC; i++)
425         {
426                 if(call_desc[i].cdid != CDID_UNUSED)
427                 {
428                         i4b_print_cdp(&(call_desc[i]));
429                 }
430         }
431 }
432
433 #endif /* I4B_CD_DEBUG_PRINT */
434
435 #endif /* NI4BQ931 > 0 */