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: releng/5.4/sys/i4b/layer4/i4b_l4mgmt.c 141090 2005-01-31 23:27:04Z imp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40
41 #include <machine/i4b_debug.h>
42 #include <machine/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].ctrl_type == CTRL_PASSIVE)
305 {
306 NDBGL4(L4_MSG, "CMR_DOPEN sent to unit %d", ctrl_desc[i].unit);
307 (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DOPEN, 0);
308 }
309 }
310 splx(x);
311 }
312
313 /*---------------------------------------------------------------------------*
314 * daemon is detached
315 *---------------------------------------------------------------------------*/
316 void
317 i4b_l4_daemon_detached(void)
318 {
319 int i;
320
321 int x = SPLI4B();
322
323 for(i=0; i < nctrl; i++)
324 {
325 /*XXX*/ if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE)
326 {
327 NDBGL4(L4_MSG, "CMR_DCLOSE sent to unit %d", ctrl_desc[i].unit);
328 (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DCLOSE, 0);
329 }
330 }
331 splx(x);
332 }
333
334 #ifdef I4B_CD_DEBUG_PRINT
335
336 extern char *print_l3state(call_desc_t *cd);
337
338 void i4b_print_cdp(call_desc_t *cdp);
339 void i4b_print_cdx(int index);
340 void i4b_print_cda(void);
341 void i4b_print_cdaa(void);
342
343 /*---------------------------------------------------------------------------*
344 * print a call descriptor by cd-pointer
345 *---------------------------------------------------------------------------*/
346 void
347 i4b_print_cdp(call_desc_t *cdp)
348 {
349 if((cdp > &(call_desc[N_CALL_DESC])) || (cdp < &(call_desc[0])))
350 {
351 printf("i4b_print_cd: cdp out of range!\n");
352 return;
353 }
354
355 printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp - (&(call_desc[0])), (unsigned long)cdp);
356
357 printf(" cdid = %d\n", cdp->cdid);
358 printf(" controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n",
359 cdp->controller,
360 ctrl_desc[cdp->controller].unit,
361 ctrl_desc[cdp->controller].dl_est,
362 ctrl_desc[cdp->controller].bch_state[CHAN_B1],
363 ctrl_desc[cdp->controller].bch_state[CHAN_B2]);
364 printf(" cr = 0x%02x\n", cdp->cr);
365 printf(" crflag = %d\n", cdp->crflag);
366 printf(" channelid = %d\n", cdp->channelid);
367 printf(" bprot = %d\n", cdp->bprot);
368 printf(" bcap = %d\n", cdp->bcap);
369 printf(" driver = %d\n", cdp->driver);
370 printf(" driver_unit = %d\n", cdp->driver_unit);
371 printf(" call_state = %d\n", cdp->call_state);
372 printf(" Q931state = %s\n", print_l3state(cdp));
373 printf(" event = %d\n", cdp->event);
374 printf(" response = %d\n", cdp->response);
375 printf(" T303 = %d\n", cdp->T303);
376 printf("T303_first_to = %d\n", cdp->T303_first_to);
377 printf(" T305 = %d\n", cdp->T305);
378 printf(" T308 = %d\n", cdp->T308);
379 printf("T308_first_to = %d\n", cdp->T308_first_to);
380 printf(" T309 = %d\n", cdp->T309);
381 printf(" T310 = %d\n", cdp->T310);
382 printf(" T313 = %d\n", cdp->T313);
383 printf(" T400 = %d\n", cdp->T400);
384 printf(" dir = %s\n", cdp->dir == DIR_OUTGOING ? "out" : "in");
385 }
386
387 /*---------------------------------------------------------------------------*
388 * print a call descriptor by index
389 *---------------------------------------------------------------------------*/
390 void
391 i4b_print_cdx(int index)
392 {
393 if(index >= N_CALL_DESC)
394 {
395 printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index, N_CALL_DESC);
396 return;
397 }
398 i4b_print_cdp(&(call_desc[index]));
399 }
400
401 /*---------------------------------------------------------------------------*
402 * print all call descriptors
403 *---------------------------------------------------------------------------*/
404 void
405 i4b_print_cda(void)
406 {
407 int i;
408
409 for(i=0; i < N_CALL_DESC; i++)
410 {
411 i4b_print_cdp(&(call_desc[i]));
412 }
413 }
414
415 /*---------------------------------------------------------------------------*
416 * print all active call descriptors
417 *---------------------------------------------------------------------------*/
418 void
419 i4b_print_cdaa(void)
420 {
421 int i;
422
423 for(i=0; i < N_CALL_DESC; i++)
424 {
425 if(call_desc[i].cdid != CDID_UNUSED)
426 {
427 i4b_print_cdp(&(call_desc[i]));
428 }
429 }
430 }
431
432 #endif /* I4B_CD_DEBUG_PRINT */
Cache object: fbe0c2540ba00e2e9b22955dc463178d
|