1 /* $NetBSD: i4b_l4mgmt.c,v 1.16 2006/06/07 22:34:04 kardel Exp $ */
4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 *---------------------------------------------------------------------------
29 * i4b_l4mgmt.c - layer 4 calldescriptor management utilites
30 * -----------------------------------------------------------
32 * $Id: i4b_l4mgmt.c,v 1.17 2007/07/09 21:11:14 ad Exp $
36 * last edit-date: [Fri Jan 5 11:33:47 2001]
38 *---------------------------------------------------------------------------*/
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: i4b_l4mgmt.c,v 1.16 2006/06/07 22:34:04 kardel Exp $");
47 #include <sys/param.h>
48 #include <sys/kernel.h>
49 #include <sys/systm.h>
51 #include <sys/socket.h>
54 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
55 #include <sys/callout.h>
58 #if defined(__FreeBSD__)
59 #if defined (__FreeBSD_version) && __FreeBSD_version <= 400000
60 #include <machine/random.h>
62 #include <sys/random.h>
67 #include <machine/i4b_debug.h>
68 #include <machine/i4b_ioctl.h>
70 #include <netisdn/i4b_debug.h>
71 #include <netisdn/i4b_ioctl.h>
74 #include <netisdn/i4b_l3l4.h>
75 #include <netisdn/i4b_mbuf.h>
76 #include <netisdn/i4b_isdnq931.h>
77 #include <netisdn/i4b_global.h>
79 #include <netisdn/i4b_l2.h>
80 #include <netisdn/i4b_l1l2.h>
81 #include <netisdn/i4b_l4.h>
83 static unsigned int get_cdid(void);
85 static void i4b_init_callout(call_desc_t
*);
86 static void i4b_stop_callout(call_desc_t
*cd
);
88 call_desc_t call_desc
[N_CALL_DESC
]; /* call descriptor array */
89 int num_call_desc
= 0;
91 /*---------------------------------------------------------------------------*
92 * return a new unique call descriptor id
93 * --------------------------------------
94 * returns a new calldescriptor id which is used to uniquely identyfy
95 * a single call in the communication between kernel and userland.
96 * this cdid is then used to associate a calldescriptor with an id.
97 *---------------------------------------------------------------------------*/
101 static unsigned int cdid_count
= 0;
112 if(cdid_count
== CDID_UNUSED
) /* zero is invalid */
114 else if(cdid_count
> CDID_MAX
) /* wraparound ? */
117 /* check if id already in use */
119 for(i
=0; i
< num_call_desc
; i
++)
121 if(call_desc
[i
].cdid
== cdid_count
)
133 /*---------------------------------------------------------------------------*
134 * reserve a calldescriptor for later usage
135 * ----------------------------------------
136 * searches the calldescriptor array until an unused
137 * descriptor is found, gets a new calldescriptor id
138 * and reserves it by putting the id into the cdid field.
139 * returns pointer to the calldescriptor.
140 *---------------------------------------------------------------------------*/
152 for(i
=0; i
< num_call_desc
; i
++)
154 if(call_desc
[i
].cdid
== CDID_UNUSED
)
156 cd
= &(call_desc
[i
]); /* get pointer to descriptor */
157 NDBGL4(L4_MSG
, "found free cd - index=%d cdid=%u",
158 i
, call_desc
[i
].cdid
);
162 if (cd
== NULL
&& num_call_desc
< N_CALL_DESC
) {
164 cd
= &(call_desc
[i
]); /* get pointer to descriptor */
165 NDBGL4(L4_MSG
, "found free cd - index=%d cdid=%u",
166 i
, call_desc
[i
].cdid
);
169 memset(cd
, 0, sizeof(call_desc_t
)); /* clear it */
170 cd
->cdid
= get_cdid(); /* fill in new cdid */
176 panic("reserve_cd: no free call descriptor available!");
178 i4b_init_callout(cd
);
183 /*---------------------------------------------------------------------------*
184 * free a calldescriptor
185 * ---------------------
186 * free a unused calldescriptor by giving address of calldescriptor
187 * and writing a 0 into the cdid field marking it as unused.
188 *---------------------------------------------------------------------------*/
190 freecd_by_cd(call_desc_t
*cd
)
195 for(i
=0; i
< num_call_desc
; i
++)
197 if( (call_desc
[i
].cdid
!= CDID_UNUSED
) &&
198 (&(call_desc
[i
]) == cd
) )
200 NDBGL4(L4_MSG
, "releasing cd - index=%d cdid=%u cr=%d",
201 i
, call_desc
[i
].cdid
, cd
->cr
);
202 call_desc
[i
].cdid
= CDID_UNUSED
;
208 panic("freecd_by_cd: ERROR, cd not found, cr = %d", cd
->cr
);
214 * ISDN is gone, get rid of all CDs for it
216 void free_all_cd_of_isdnif(int isdnif
)
221 for(i
=0; i
< num_call_desc
; i
++)
223 if( (call_desc
[i
].cdid
!= CDID_UNUSED
) &&
224 call_desc
[i
].isdnif
== isdnif
) {
225 NDBGL4(L4_MSG
, "releasing cd - index=%d cdid=%u cr=%d",
226 i
, call_desc
[i
].cdid
, call_desc
[i
].cr
);
227 if (call_desc
[i
].callouts_inited
)
228 i4b_stop_callout(&call_desc
[i
]);
229 call_desc
[i
].cdid
= CDID_UNUSED
;
230 call_desc
[i
].isdnif
= -1;
231 call_desc
[i
].l3drv
= NULL
;
238 /*---------------------------------------------------------------------------*
239 * return pointer to calldescriptor by giving the calldescriptor id
240 * ----------------------------------------------------------------
241 * lookup a calldescriptor in the calldescriptor array by looking
242 * at the cdid field. return pointer to calldescriptor if found,
243 * else return NULL if not found.
244 *---------------------------------------------------------------------------*/
246 cd_by_cdid(unsigned int cdid
)
250 for(i
=0; i
< num_call_desc
; i
++)
252 if(call_desc
[i
].cdid
== cdid
)
254 NDBGL4(L4_MSG
, "found cdid - index=%d cdid=%u cr=%d",
255 i
, call_desc
[i
].cdid
, call_desc
[i
].cr
);
256 i4b_init_callout(&call_desc
[i
]);
257 return(&(call_desc
[i
]));
263 /*---------------------------------------------------------------------------*
264 * search calldescriptor
265 * ---------------------
266 * This routine searches for the calldescriptor for a passive controller
267 * given by unit number, callreference and callreference flag.
268 * It returns a pointer to the calldescriptor if found, else a NULL.
269 *---------------------------------------------------------------------------*/
271 cd_by_isdnifcr(int isdnif
, int cr
, int crf
)
275 for(i
=0; i
< num_call_desc
; i
++) {
276 if (call_desc
[i
].cdid
!= CDID_UNUSED
277 && call_desc
[i
].isdnif
== isdnif
278 && call_desc
[i
].cr
== cr
279 && call_desc
[i
].crflag
== crf
) {
280 NDBGL4(L4_MSG
, "found cd, index=%d cdid=%u cr=%d",
281 i
, call_desc
[i
].cdid
, call_desc
[i
].cr
);
282 i4b_init_callout(&call_desc
[i
]);
283 return(&(call_desc
[i
]));
289 /*---------------------------------------------------------------------------*
290 * generate 7 bit "random" number used for outgoing Call Reference
291 *---------------------------------------------------------------------------*/
293 get_rand_cr(int unit
)
296 static u_char val
, retval
;
297 static int called
= 42;
302 for(i
=0; i
< 50 ; i
++, val
++)
306 #if defined(__FreeBSD__)
309 read_random((char *)&val
, sizeof(val
));
311 val
= (u_char
)random();
312 #endif /* RANDOMDEV */
318 val
^= (t
.tv_sec
>> 8) ^ t
.tv_usec
;
320 val
^= t
.tv_sec
^ (t
.tv_usec
>> 8);
325 if(retval
== 0 || retval
== 0x7f)
328 for(j
=0; j
< num_call_desc
; j
++)
330 if( (call_desc
[j
].cdid
!= CDID_UNUSED
) &&
331 (call_desc
[j
].cr
== retval
) )
345 i4b_stop_callout(call_desc_t
*cd
)
347 if (!cd
->callouts_inited
)
350 callout_stop(&cd
->idle_timeout_handle
);
351 callout_stop(&cd
->T303_callout
);
352 callout_stop(&cd
->T305_callout
);
353 callout_stop(&cd
->T308_callout
);
354 callout_stop(&cd
->T309_callout
);
355 callout_stop(&cd
->T310_callout
);
356 callout_stop(&cd
->T313_callout
);
357 callout_stop(&cd
->T400_callout
);
360 /*---------------------------------------------------------------------------*
361 * initialize the callout handles for FreeBSD
362 *---------------------------------------------------------------------------*/
364 i4b_init_callout(call_desc_t
*cd
)
366 if(cd
->callouts_inited
== 0)
368 callout_init(&cd
->idle_timeout_handle
, 0);
369 callout_init(&cd
->T303_callout
, 0);
370 callout_init(&cd
->T305_callout
, 0);
371 callout_init(&cd
->T308_callout
, 0);
372 callout_init(&cd
->T309_callout
, 0);
373 callout_init(&cd
->T310_callout
, 0);
374 callout_init(&cd
->T313_callout
, 0);
375 callout_init(&cd
->T400_callout
, 0);
376 cd
->callouts_inited
= 1;
380 #ifdef I4B_CD_DEBUG_PRINT
382 extern char *print_l3state(call_desc_t
*cd
);
384 void i4b_print_cdp(call_desc_t
*cdp
);
385 void i4b_print_cdx(int index
);
386 void i4b_print_cda(void);
387 void i4b_print_cdaa(void);
389 /*---------------------------------------------------------------------------*
390 * print a call descriptor by cd-pointer
391 *---------------------------------------------------------------------------*/
393 i4b_print_cdp(call_desc_t
*cdp
)
395 if((cdp
> &(call_desc
[num_call_desc
])) || (cdp
< &(call_desc
[0])))
397 printf("i4b_print_cd: cdp out of range!\n");
401 printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp
- (&(call_desc
[0])), (unsigned long)cdp
);
403 printf(" cdid = %d\n", cdp
->cdid
);
404 printf(" controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n",
406 ctrl_desc
[cdp
->controller
].unit
,
407 ctrl_desc
[cdp
->controller
].dl_est
,
408 ctrl_desc
[cdp
->controller
].bch_state
[CHAN_B1
],
409 ctrl_desc
[cdp
->controller
].bch_state
[CHAN_B2
]);
410 printf(" cr = 0x%02x\n", cdp
->cr
);
411 printf(" crflag = %d\n", cdp
->crflag
);
412 printf(" channelid = %d\n", cdp
->channelid
);
413 printf(" bprot = %d\n", cdp
->bprot
);
414 printf(" driver = %d\n", cdp
->driver
);
415 printf(" driver_unit = %d\n", cdp
->driver_unit
);
416 printf(" call_state = %d\n", cdp
->call_state
);
417 printf(" Q931state = %s\n", print_l3state(cdp
));
418 printf(" event = %d\n", cdp
->event
);
419 printf(" response = %d\n", cdp
->response
);
420 printf(" T303 = %d\n", cdp
->T303
);
421 printf("T303_first_to = %d\n", cdp
->T303_first_to
);
422 printf(" T305 = %d\n", cdp
->T305
);
423 printf(" T308 = %d\n", cdp
->T308
);
424 printf("T308_first_to = %d\n", cdp
->T308_first_to
);
425 printf(" T309 = %d\n", cdp
->T309
);
426 printf(" T310 = %d\n", cdp
->T310
);
427 printf(" T313 = %d\n", cdp
->T313
);
428 printf(" T400 = %d\n", cdp
->T400
);
429 printf(" dir = %s\n", cdp
->dir
== DIR_OUTGOING
? "out" : "in");
432 /*---------------------------------------------------------------------------*
433 * print a call descriptor by index
434 *---------------------------------------------------------------------------*/
436 i4b_print_cdx(int index
)
438 if(index
>= num_call_desc
)
440 printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index
, N_CALL_DESC
);
443 i4b_print_cdp(&(call_desc
[index
]));
446 /*---------------------------------------------------------------------------*
447 * print all call descriptors
448 *---------------------------------------------------------------------------*/
454 for(i
=0; i
< num_call_desc
; i
++)
456 i4b_print_cdp(&(call_desc
[i
]));
460 /*---------------------------------------------------------------------------*
461 * print all active call descriptors
462 *---------------------------------------------------------------------------*/
468 for(i
=0; i
< num_call_desc
; i
++)
470 if(call_desc
[i
].cdid
!= CDID_UNUSED
)
472 i4b_print_cdp(&(call_desc
[i
]));
477 #endif /* I4B_CD_DEBUG_PRINT */
479 #endif /* NISDN > 0 */