]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer4/i4b_l4.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer4 / i4b_l4.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_l4.c - kernel interface to userland
29  *      -----------------------------------------
30  *      last edit-date: [Sun Aug 11 12:43:14 2002]
31  *
32  *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "opt_i4b.h"
38
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43
44 #include <i4b/include/i4b_debug.h>
45 #include <i4b/include/i4b_ioctl.h>
46 #include <i4b/include/i4b_cause.h>
47
48 #include <i4b/include/i4b_global.h>
49 #include <i4b/include/i4b_l3l4.h>
50 #include <i4b/include/i4b_mbuf.h>
51 #include <i4b/layer4/i4b_l4.h>
52
53 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
54
55 struct ctrl_type_desc ctrl_types[CTRL_NUMTYPES] = { { NULL, NULL} };
56
57 static int i4b_link_bchandrvr(call_desc_t *cd);
58 static void i4b_unlink_bchandrvr(call_desc_t *cd);
59 static void i4b_l4_setup_timeout(call_desc_t *cd);
60 static void i4b_idle_check_fix_unit(call_desc_t *cd);
61 static void i4b_idle_check_var_unit(call_desc_t *cd);
62 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
63 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
64 static time_t i4b_get_idletime(call_desc_t *cd);
65
66 #if defined(NI4BISPPP) && (NI4BISPPP > 0)
67 extern time_t i4bisppp_idletime(int);
68 #endif
69
70 /*---------------------------------------------------------------------------*
71  *      send MSG_PDEACT_IND message to userland
72  *---------------------------------------------------------------------------*/
73 void
74 i4b_l4_pdeact(int controller, int numactive)
75 {
76         struct mbuf *m;
77         int i;
78         call_desc_t *cd;
79         
80         for(i=0; i < N_CALL_DESC; i++)
81         {
82                 if((call_desc[i].cdid != CDID_UNUSED)                             &&
83                    (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
84                    (ctrl_desc[call_desc[i].controller].unit == controller))
85                 {
86                         cd = &call_desc[i];
87                         
88                         if(cd->timeout_active)
89                         {
90                                 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
91                         }
92                         
93                         if(cd->dlt != NULL)
94                         {
95                                 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
96                                 i4b_unlink_bchandrvr(cd);
97                         }
98                 
99                         if((cd->channelid >= 0) & (cd->channelid < ctrl_desc[cd->controller].nbch))
100                         {
101                                 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
102                         }
103
104                         cd->cdid = CDID_UNUSED;
105                 }
106         }
107         
108         if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
109         {
110                 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
111
112                 md->header.type = MSG_PDEACT_IND;
113                 md->header.cdid = -1;
114
115                 md->controller = controller;
116                 md->numactive = numactive;
117
118                 i4bputqueue_hipri(m);           /* URGENT !!! */
119         }
120 }
121
122 /*---------------------------------------------------------------------------*
123  *      send MSG_L12STAT_IND message to userland
124  *---------------------------------------------------------------------------*/
125 void
126 i4b_l4_l12stat(int controller, int layer, int state)
127 {
128         struct mbuf *m;
129
130         if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
131         {
132                 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
133
134                 md->header.type = MSG_L12STAT_IND;
135                 md->header.cdid = -1;
136
137                 md->controller = controller;
138                 md->layer = layer;
139                 md->state = state;
140
141                 i4bputqueue(m);
142         }
143 }
144
145 /*---------------------------------------------------------------------------*
146  *      send MSG_TEIASG_IND message to userland
147  *---------------------------------------------------------------------------*/
148 void
149 i4b_l4_teiasg(int controller, int tei)
150 {
151         struct mbuf *m;
152
153         if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
154         {
155                 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
156
157                 md->header.type = MSG_TEIASG_IND;
158                 md->header.cdid = -1;
159
160                 md->controller = controller;
161                 md->tei = ctrl_desc[controller].tei;
162
163                 i4bputqueue(m);
164         }
165 }
166
167 /*---------------------------------------------------------------------------*
168  *      send MSG_DIALOUT_IND message to userland
169  *---------------------------------------------------------------------------*/
170 void
171 i4b_l4_dialout(int driver, int driver_unit)
172 {
173         struct mbuf *m;
174
175         if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
176         {
177                 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
178
179                 md->header.type = MSG_DIALOUT_IND;
180                 md->header.cdid = -1;
181
182                 md->driver = driver;
183                 md->driver_unit = driver_unit;  
184
185                 i4bputqueue(m);
186         }
187 }
188
189 /*---------------------------------------------------------------------------*
190  *      send MSG_DIALOUTNUMBER_IND message to userland
191  *---------------------------------------------------------------------------*/
192 void
193 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
194 {
195         struct mbuf *m;
196
197         if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
198         {
199                 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
200                 int i;
201
202                 md->header.type = MSG_DIALOUTNUMBER_IND;
203                 md->header.cdid = -1;
204
205                 md->driver = driver;
206                 md->driver_unit = driver_unit;
207
208                 for (i = 0; i < cmdlen; i++)
209                         if (cmd[i] == '*')
210                                 break;
211
212                 /* XXX: TELNO_MAX is _with_ tailing '\0', so max is actually TELNO_MAX - 1 */
213                 md->cmdlen = (i < TELNO_MAX  - 1 ? i : TELNO_MAX - 1);
214                 /* skip the (first) '*' */
215                 md->subaddrlen = (cmdlen - i - 1 < SUBADDR_MAX - 1 ? cmdlen - i - 1 : SUBADDR_MAX - 1);
216
217                 bcopy(cmd, md->cmd, md->cmdlen);
218                 if (md->subaddrlen != -1)
219                         bcopy(cmd+i+1, md->subaddr, md->subaddrlen); 
220
221                 NDBGL4(L4_TIMO, "cmd[%d]=%s, subaddr[%d]=%s", md->cmdlen, md->cmd, md->subaddrlen, md->subaddr);
222                 i4bputqueue(m);
223         }
224 }
225
226 /*---------------------------------------------------------------------------*
227  *      send MSG_KEYPAD_IND message to userland
228  *---------------------------------------------------------------------------*/
229 void
230 i4b_l4_keypad(int driver, int driver_unit, int cmdlen, char *cmd)
231 {
232         struct mbuf *m;
233
234         if((m = i4b_Dgetmbuf(sizeof(msg_keypad_ind_t))) != NULL)
235         {
236                 msg_keypad_ind_t *md = (msg_keypad_ind_t *)m->m_data;
237
238                 md->header.type = MSG_KEYPAD_IND;
239                 md->header.cdid = -1;
240
241                 md->driver = driver;
242                 md->driver_unit = driver_unit;
243
244                 if(cmdlen > KEYPAD_MAX)
245                         cmdlen = KEYPAD_MAX;
246
247                 md->cmdlen = cmdlen;
248                 bcopy(cmd, md->cmd, cmdlen);
249                 i4bputqueue(m);
250         }
251 }
252
253 /*---------------------------------------------------------------------------*
254  *      send MSG_NEGOTIATION_COMPL message to userland
255  *---------------------------------------------------------------------------*/
256 void
257 i4b_l4_negcomplete(call_desc_t *cd)
258 {
259         struct mbuf *m;
260
261         if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
262         {
263                 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
264
265                 md->header.type = MSG_NEGCOMP_IND;
266                 md->header.cdid = cd->cdid;
267
268                 i4bputqueue(m);
269         }
270 }
271
272 /*---------------------------------------------------------------------------*
273  *      send MSG_IFSTATE_CHANGED_IND message to userland
274  *---------------------------------------------------------------------------*/
275 void
276 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
277 {
278         struct mbuf *m;
279
280         if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
281         {
282                 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
283
284                 md->header.type = MSG_IFSTATE_CHANGED_IND;
285                 md->header.cdid = cd->cdid;
286                 md->state = new_state;
287
288                 i4bputqueue(m);
289         }
290 }
291
292 /*---------------------------------------------------------------------------*
293  *      send MSG_DRVRDISC_REQ message to userland
294  *---------------------------------------------------------------------------*/
295 void
296 i4b_l4_drvrdisc(int driver, int driver_unit)
297 {
298         struct mbuf *m;
299
300         if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
301         {
302                 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
303
304                 md->header.type = MSG_DRVRDISC_REQ;
305                 md->header.cdid = -1;
306
307                 md->driver = driver;
308                 md->driver_unit = driver_unit;  
309
310                 i4bputqueue(m);
311         }
312 }
313
314 /*---------------------------------------------------------------------------*
315  *      send MSG_ACCT_IND message to userland
316  *---------------------------------------------------------------------------*/
317 void
318 i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes,
319                 int iinbytes, int ro, int ri, int outbytes, int inbytes)
320 {
321         struct mbuf *m;
322
323         if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
324         {
325                 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
326
327                 md->header.type = MSG_ACCT_IND;
328                 md->header.cdid = -1;
329
330                 md->driver = driver;
331                 md->driver_unit = driver_unit;  
332
333                 md->accttype = accttype;
334                 md->ioutbytes = ioutbytes;
335                 md->iinbytes = iinbytes;
336                 md->outbps = ro;
337                 md->inbps = ri;
338                 md->outbytes = outbytes;
339                 md->inbytes = inbytes;
340                 
341                 i4bputqueue(m);
342         }
343 }
344
345 /*---------------------------------------------------------------------------*
346  *      send MSG_CONNECT_IND message to userland
347  *---------------------------------------------------------------------------*/
348 void
349 i4b_l4_connect_ind(call_desc_t *cd)
350 {
351         struct mbuf *m;
352
353         if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
354         {
355                 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
356
357                 mp->header.type = MSG_CONNECT_IND;
358                 mp->header.cdid = cd->cdid;
359
360                 mp->controller = cd->controller;
361                 mp->channel = cd->channelid;
362                 mp->bprot = cd->bprot;
363                 mp->bcap = cd->bcap;            
364
365                 cd->dir = DIR_INCOMING;
366
367                 if(strlen(cd->dst_telno) > 0)
368                         strcpy(mp->dst_telno, cd->dst_telno);
369                 else
370                         strcpy(mp->dst_telno, TELNO_EMPTY);
371
372                 if(strlen(cd->dst_subaddr) > 0)
373                         strcpy(mp->dst_subaddr, cd->dst_subaddr);
374                 else
375                         strcpy(mp->dst_subaddr, TELNO_EMPTY);
376
377                 if(strlen(cd->src_telno) > 0)
378                         strcpy(mp->src_telno, cd->src_telno);
379                 else
380                         strcpy(mp->src_telno, TELNO_EMPTY);
381                         
382                 if(strlen(cd->src_subaddr) > 0)
383                         strcpy(mp->src_subaddr, cd->src_subaddr);
384                 else
385                         strcpy(mp->src_subaddr, TELNO_EMPTY);
386
387                 mp->src_ton = cd->src_ton;
388                 mp->dst_ton = cd->dst_ton;
389
390                 strcpy(mp->display, cd->display);
391
392                 mp->scr_ind = cd->scr_ind;
393                 mp->prs_ind = cd->prs_ind;              
394                 
395                 T400_start(cd);
396                 
397                 i4bputqueue(m);
398         }
399 }
400
401 /*---------------------------------------------------------------------------*
402  *      send MSG_CONNECT_ACTIVE_IND message to userland
403  *---------------------------------------------------------------------------*/
404 void
405 i4b_l4_connect_active_ind(call_desc_t *cd)
406 {
407         int s;
408         struct mbuf *m;
409
410         s = SPLI4B();
411
412         cd->last_active_time = cd->connect_time = SECOND;
413
414         NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
415         
416         i4b_link_bchandrvr(cd);
417
418         (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd);
419
420         i4b_l4_setup_timeout(cd);
421         
422         splx(s);        
423         
424         if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
425         {
426                 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
427
428                 mp->header.type = MSG_CONNECT_ACTIVE_IND;
429                 mp->header.cdid = cd->cdid;
430                 mp->controller = cd->controller;
431                 mp->channel = cd->channelid;
432                 if(cd->datetime[0] != '\0')
433                         strcpy(mp->datetime, cd->datetime);
434                 else
435                         mp->datetime[0] = '\0';
436                 i4bputqueue(m);
437         }
438 }
439
440 /*---------------------------------------------------------------------------*
441  *      send MSG_DISCONNECT_IND message to userland
442  *---------------------------------------------------------------------------*/
443 void
444 i4b_l4_disconnect_ind(call_desc_t *cd)
445 {
446         struct mbuf *m;
447
448         if(cd->timeout_active)
449                 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
450
451         if(cd->dlt != NULL)
452         {
453                 (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd);
454                 i4b_unlink_bchandrvr(cd);
455         }
456
457         if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch))
458         {
459                 ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
460         }
461         else
462         {
463                 /* no error, might be hunting call for callback */
464                 NDBGL4(L4_MSG, "channel free not valid but %d!", cd->channelid);
465         }
466         
467         if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
468         {
469                 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
470
471                 mp->header.type = MSG_DISCONNECT_IND;
472                 mp->header.cdid = cd->cdid;
473                 mp->cause = cd->cause_in;
474
475                 i4bputqueue(m);
476         }
477 }
478
479 /*---------------------------------------------------------------------------*
480  *      send MSG_IDLE_TIMEOUT_IND message to userland
481  *---------------------------------------------------------------------------*/
482 void
483 i4b_l4_idle_timeout_ind(call_desc_t *cd)
484 {
485         struct mbuf *m;
486
487         if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
488         {
489                 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
490
491                 mp->header.type = MSG_IDLE_TIMEOUT_IND;
492                 mp->header.cdid = cd->cdid;
493
494                 i4bputqueue(m);
495         }
496 }
497
498 /*---------------------------------------------------------------------------*
499  *      send MSG_CHARGING_IND message to userland
500  *---------------------------------------------------------------------------*/
501 void
502 i4b_l4_charging_ind(call_desc_t *cd)
503 {
504         struct mbuf *m;
505
506         if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
507         {
508                 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
509
510                 mp->header.type = MSG_CHARGING_IND;
511                 mp->header.cdid = cd->cdid;
512                 mp->units_type = cd->units_type;
513
514 /*XXX*/         if(mp->units_type == CHARGE_CALC)
515                         mp->units = cd->cunits;
516                 else
517                         mp->units = cd->units;
518
519                 i4bputqueue(m);
520         }
521 }
522
523 /*---------------------------------------------------------------------------*
524  *      send MSG_STATUS_IND message to userland
525  *---------------------------------------------------------------------------*/
526 void
527 i4b_l4_status_ind(call_desc_t *cd)
528 {
529 }
530
531 /*---------------------------------------------------------------------------*
532  *      send MSG_ALERT_IND message to userland
533  *---------------------------------------------------------------------------*/
534 void
535 i4b_l4_alert_ind(call_desc_t *cd)
536 {
537         struct mbuf *m;
538
539         if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
540         {
541                 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
542
543                 mp->header.type = MSG_ALERT_IND;
544                 mp->header.cdid = cd->cdid;
545
546                 i4bputqueue(m);
547         }
548 }
549
550 /*---------------------------------------------------------------------------*
551  *      send MSG_INFO_IND message to userland
552  *---------------------------------------------------------------------------*/
553 void
554 i4b_l4_info_ind(call_desc_t *cd)
555 {
556 }
557
558 /*---------------------------------------------------------------------------*
559  *      send MSG_INFO_IND message to userland
560  *---------------------------------------------------------------------------*/
561 void
562 i4b_l4_proceeding_ind(call_desc_t *cd)
563 {
564         struct mbuf *m;
565
566         if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
567         {
568                 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
569
570                 mp->header.type = MSG_PROCEEDING_IND;
571                 mp->header.cdid = cd->cdid;
572                 mp->controller = cd->controller;
573                 mp->channel = cd->channelid;
574                 i4bputqueue(m);
575         }
576 }
577
578 /*---------------------------------------------------------------------------*
579  *    send MSG_PACKET_IND message to userland
580  *---------------------------------------------------------------------------*/
581 void
582 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
583 {
584         struct mbuf *m;
585         int len = pkt->m_pkthdr.len;
586         unsigned char *ip = pkt->m_data;
587
588         if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
589         {
590                 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
591
592                 mp->header.type = MSG_PACKET_IND;
593                 mp->header.cdid = -1;
594                 mp->driver = driver;
595                 mp->driver_unit = driver_unit;
596                 mp->direction = dir;
597                 memcpy(mp->pktdata, ip,
598                         len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
599                 i4bputqueue(m);
600         }
601 }
602
603 /*---------------------------------------------------------------------------*
604  *      link a driver(unit) to a B-channel(controller,unit,channel)
605  *---------------------------------------------------------------------------*/
606 static int
607 i4b_link_bchandrvr(call_desc_t *cd)
608 {
609         int t = ctrl_desc[cd->controller].ctrl_type;
610         
611         if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
612         {
613                         cd->ilt = NULL;
614         }
615         else
616         {
617                 cd->ilt = ctrl_types[t].get_linktab(
618                         ctrl_desc[cd->controller].unit,
619                         cd->channelid);
620         }
621
622         switch(cd->driver)
623         {
624 #if defined(NI4BRBCH) && (NI4BRBCH > 0)
625                 case BDRV_RBCH:
626                         cd->dlt = rbch_ret_linktab(cd->driver_unit);
627                         break;
628 #endif
629                 
630 #if defined(NI4BTEL) && (NI4BTEL > 0)
631                 case BDRV_TEL:
632                         cd->dlt = tel_ret_linktab(cd->driver_unit);
633                         break;
634 #endif
635
636 #if defined(NI4BIPR) && (NI4BIPR > 0)
637                 case BDRV_IPR:
638                         cd->dlt = ipr_ret_linktab(cd->driver_unit);
639                         break;
640 #endif
641
642 #if defined(NI4BISPPP) && (NI4BISPPP > 0)
643                 case BDRV_ISPPP:
644                         cd->dlt = i4bisppp_ret_linktab(cd->driver_unit);
645                         break;
646 #endif
647
648 #if defined(NIBC) && NIBC > 0
649                 case BDRV_IBC:
650                         cd->dlt = ibc_ret_linktab(cd->driver_unit);
651                         break;
652 #endif
653
654 #if defined(NI4BING) && (NI4BING > 0)
655                 case BDRV_ING:
656                         cd->dlt = ing_ret_linktab(cd->driver_unit);
657                         break;
658 #endif
659
660                 default:
661                         cd->dlt = NULL;
662                         break;
663         }
664
665         if(cd->dlt == NULL || cd->ilt == NULL)
666                 return(-1);
667
668         if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL)
669         {
670                 ctrl_types[t].set_linktab(
671                                 ctrl_desc[cd->controller].unit,
672                                 cd->channelid,
673                                 cd->dlt);
674         }
675
676         switch(cd->driver)
677         {
678 #if defined(NI4BRBCH) && (NI4BRBCH > 0)
679                 case BDRV_RBCH:
680                         rbch_set_linktab(cd->driver_unit, cd->ilt);
681                         break;
682 #endif
683
684 #if defined(NI4BTEL) && (NI4BTEL > 0)
685                 case BDRV_TEL:
686                         tel_set_linktab(cd->driver_unit, cd->ilt);
687                         break;
688 #endif
689
690 #if defined(NI4BIPR) && (NI4BIPR > 0)
691                 case BDRV_IPR:
692                         ipr_set_linktab(cd->driver_unit, cd->ilt);
693                         break;
694 #endif
695
696 #if defined(NI4BISPPP) && (NI4BISPPP > 0)
697                 case BDRV_ISPPP:
698                         i4bisppp_set_linktab(cd->driver_unit, cd->ilt);
699                         break;
700 #endif
701
702 #if defined(NIBC) && NIBC > 0
703                 case BDRV_IBC:
704                         ibc_set_linktab(cd->driver_unit, cd->ilt);
705                         break;
706 #endif
707
708 #if defined(NI4BING) && (NI4BING > 0)
709                 case BDRV_ING:
710                         ing_set_linktab(cd->driver_unit, cd->ilt);
711                         break;
712 #endif
713
714                 default:
715                         return(0);
716                         break;
717         }
718
719         /* activate B channel */
720                 
721         (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 1);
722
723         return(0);
724 }
725
726 /*---------------------------------------------------------------------------*
727  *      unlink a driver(unit) from a B-channel(controller,unit,channel)
728  *---------------------------------------------------------------------------*/
729 static void
730 i4b_unlink_bchandrvr(call_desc_t *cd)
731 {
732         int t = ctrl_desc[cd->controller].ctrl_type;
733
734         if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL)
735         {
736                 cd->ilt = NULL;
737                 return;
738         }
739         else
740         {
741                 cd->ilt = ctrl_types[t].get_linktab(
742                                 ctrl_desc[cd->controller].unit,
743                                 cd->channelid);
744         }
745         
746         /* deactivate B channel */
747                 
748         (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 0);
749
750
751 /*---------------------------------------------------------------------------
752
753         How shorthold mode works for OUTGOING connections
754         =================================================
755
756         |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
757
758 idletime_state:      IST_NONCHK             IST_CHECK       IST_SAFE    
759         
760         |                               |               |               |
761   time>>+-------------------------------+---------------+---------------+-...
762         |                               |               |               |
763         |                               |<--idle_time-->|<--earlyhup--->|
764         |<-----------------------unitlen------------------------------->|
765
766         
767           unitlen - specifies the time a charging unit lasts
768         idle_time - specifies the thime the line must be idle at the
769                     end of the unit to be elected for hangup
770          earlyhup - is the beginning of a timing safety zone before the
771                     next charging unit starts
772
773         The algorithm works as follows: lets assume the unitlen is 100
774         secons, idle_time is 40 seconds and earlyhup is 10 seconds.
775         The line then must be idle 50 seconds after the begin of the
776         current unit and it must then be quiet for 40 seconds. if it
777         has been quiet for this 40 seconds, the line is closed 10
778         seconds before the next charging unit starts. In case there was
779         any traffic within the idle_time, the line is not closed.
780         It does not matter whether there was any traffic between second
781         0 and second 50 or not.
782
783
784         How shorthold mode works for INCOMING connections
785         =================================================
786
787         it is just possible to specify a maximum idle time for incoming
788         connections, after this time of no activity on the line the line
789         is closed.
790         
791 ---------------------------------------------------------------------------*/   
792
793 static time_t
794 i4b_get_idletime(call_desc_t *cd)
795 {
796         switch (cd->driver) {
797 #if defined(NI4BISPPP) && (NI4BISPPP > 0)
798                 case BDRV_ISPPP:
799                         return i4bisppp_idletime(cd->driver_unit);
800                 break;
801 #endif
802                 default:
803                         return cd->last_active_time;
804                 break;
805         }
806 }
807 /*---------------------------------------------------------------------------*
808  *      B channel idle check timeout setup
809  *---------------------------------------------------------------------------*/ 
810 static void
811 i4b_l4_setup_timeout(call_desc_t *cd)
812 {
813         NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
814                 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
815         
816         cd->timeout_active = 0;
817         cd->idletime_state = IST_IDLE;
818         
819         if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
820         {
821                 /* incoming call: simple max idletime check */
822         
823                 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
824                 cd->timeout_active = 1;
825                 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
826         }
827         else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
828         {
829                 switch( cd->shorthold_data.shorthold_algorithm )
830                 {
831                         default:        /* fall into the old fix algorithm */
832                         case SHA_FIXU:
833                                 i4b_l4_setup_timeout_fix_unit( cd );
834                                 break;
835                                 
836                         case SHA_VARU:
837                                 i4b_l4_setup_timeout_var_unit( cd );
838                                 break;
839                 }
840         }
841         else
842         {
843                 NDBGL4(L4_TIMO, "no idle_timeout configured");
844         }
845 }
846
847 /*---------------------------------------------------------------------------*
848  *      fixed unit algorithm B channel idle check timeout setup
849  *---------------------------------------------------------------------------*/
850 static void
851 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
852 {
853         /* outgoing call */
854         
855         if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
856         {
857                 /* outgoing call: simple max idletime check */
858                 
859                 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
860                 cd->timeout_active = 1;
861                 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
862                         (long)SECOND, (long)cd->shorthold_data.idle_time);
863         }
864         else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
865         {
866                 /* outgoing call: full shorthold mode check */
867                 
868                 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
869                 cd->timeout_active = 1;
870                 cd->idletime_state = IST_NONCHK;
871                 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window", 
872                         (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
873
874                 if(cd->aocd_flag == 0)
875                 {
876                         cd->units_type = CHARGE_CALC;
877                         cd->cunits++;
878                         i4b_l4_charging_ind(cd);
879                 }
880         }
881         else
882         {
883                 /* parms somehow got wrong .. */
884                 
885                 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
886                         (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
887         }
888 }
889
890 /*---------------------------------------------------------------------------*
891  *      variable unit algorithm B channel idle check timeout setup
892  *---------------------------------------------------------------------------*/
893 static void
894 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
895 {
896         /* outgoing call: variable unit idletime check */
897                 
898         /*
899          * start checking for an idle connect one second before the end of the unit.
900          * The one second takes into account of rounding due to the driver only
901          * using the seconds and not the uSeconds of the current time
902          */
903         cd->idletime_state = IST_CHECK; /* move directly to the checking state */
904
905         START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
906         cd->timeout_active = 1;
907         NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
908                 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
909 }
910
911
912 /*---------------------------------------------------------------------------*
913  *      B channel idle check timeout function
914  *---------------------------------------------------------------------------*/ 
915 void
916 i4b_idle_check(call_desc_t *cd)
917 {
918         int s;
919
920         if(cd->cdid == CDID_UNUSED)
921                 return;
922         
923         s = SPLI4B();
924
925         /* failsafe */
926
927         if(cd->timeout_active == 0)
928         {
929                 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
930         }
931         else
932         {       
933                 cd->timeout_active = 0;
934         }
935         
936         /* incoming connections, simple idletime check */
937
938         if(cd->dir == DIR_INCOMING)
939         {
940                 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
941                 {
942                         NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
943                         (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid,
944                                         (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
945                         i4b_l4_idle_timeout_ind(cd);
946                 }
947                 else
948                 {
949                         NDBGL4(L4_TIMO, "%ld: incoming-call, activity, last_active=%ld, max_idle=%ld", (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->max_idle_time);
950
951                         START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
952                         cd->timeout_active = 1;
953                 }
954         }
955
956         /* outgoing connections */
957
958         else if(cd->dir == DIR_OUTGOING)
959         {
960                 switch( cd->shorthold_data.shorthold_algorithm )
961                 {
962                         case SHA_FIXU:
963                                 i4b_idle_check_fix_unit( cd );
964                                 break;
965                         case SHA_VARU:
966                                 i4b_idle_check_var_unit( cd );
967                                 break;
968                         default:
969                                 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
970                                         (long)SECOND, cd->shorthold_data.shorthold_algorithm);
971                                 i4b_idle_check_fix_unit( cd );
972                                 break;
973                 }
974         }
975         splx(s);
976 }
977
978 /*---------------------------------------------------------------------------*
979  *      fixed unit algorithm B channel idle check timeout function
980  *---------------------------------------------------------------------------*/
981 static void
982 i4b_idle_check_fix_unit(call_desc_t *cd)
983 {
984
985         /* simple idletime calculation */
986
987         if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
988         {
989                 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
990                 {
991                         NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
992                         (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
993                         i4b_l4_idle_timeout_ind(cd);
994                 }
995                 else
996                 {
997                         NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
998                                         (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
999                         START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1000                         cd->timeout_active = 1;
1001                 }
1002         }
1003
1004         /* full shorthold mode calculation */
1005
1006         else if((cd->shorthold_data.unitlen_time > 0)
1007                  && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1008         {
1009                 switch(cd->idletime_state)
1010                 {
1011
1012                 case IST_NONCHK:        /* end of non-check time */
1013
1014                         START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1015                         cd->idletimechk_start = SECOND;
1016                         cd->idletime_state = IST_CHECK;
1017                         cd->timeout_active = 1;
1018                         NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1019                         break;
1020
1021                 case IST_CHECK:         /* end of idletime chk */
1022                         if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1023                            (i4b_get_idletime(cd) <= SECOND))
1024                         {       /* activity detected */
1025                                 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1026                                 cd->timeout_active = 1;
1027                                 cd->idletime_state = IST_SAFE;
1028                                 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1029                         }
1030                         else
1031                         {       /* no activity, hangup */
1032                                 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1033                                 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1034                                 i4b_l4_idle_timeout_ind(cd);
1035                                 cd->idletime_state = IST_IDLE;
1036                         }
1037                         break;
1038
1039                 case IST_SAFE:  /* end of earlyhup time */
1040
1041                         START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time+cd->shorthold_data.earlyhup_time)));
1042                         cd->timeout_active = 1;
1043                         cd->idletime_state = IST_NONCHK;
1044
1045                         if(cd->aocd_flag == 0)
1046                         {
1047                                 cd->units_type = CHARGE_CALC;
1048                                 cd->cunits++;
1049                                 i4b_l4_charging_ind(cd);
1050                         }
1051                         
1052                         NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1053                         break;
1054
1055                 default:
1056                         NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1057                         cd->idletime_state = IST_IDLE;
1058                         break;
1059                 }
1060         }
1061 }
1062
1063 /*---------------------------------------------------------------------------*
1064  *      variable unit algorithm B channel idle check timeout function
1065  *---------------------------------------------------------------------------*/
1066 static void
1067 i4b_idle_check_var_unit(call_desc_t *cd)
1068 {
1069         switch(cd->idletime_state)
1070         {
1071
1072         /* see if there has been any activity within the last idle_time seconds */
1073         case IST_CHECK:
1074                 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1075                 {       /* activity detected */
1076                         /* check again in one second */         
1077                         cd->idle_timeout_handle =
1078                                 START_TIMER (cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1079                         cd->timeout_active = 1;
1080                         cd->idletime_state = IST_CHECK;
1081                         NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1082                 }
1083                 else
1084                 {       /* no activity, hangup */
1085                         NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1086                         (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1087                         i4b_l4_idle_timeout_ind(cd);
1088                         cd->idletime_state = IST_IDLE;
1089                 }
1090                 break;
1091
1092         default:
1093                 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1094                 cd->idletime_state = IST_IDLE;
1095                 break;
1096         }
1097 }