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