Merge from vendor branch GCC:
[dragonfly.git] / sys / net / i4b / layer4 / i4b_i4bdrv.c
1 /*
2  * Copyright (c) 1997, 2001 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_i4bdrv.c - i4b userland interface driver
28  *      --------------------------------------------
29  *
30  * $FreeBSD: src/sys/i4b/layer4/i4b_i4bdrv.c,v 1.11.2.5 2001/12/16 15:12:59 hm Exp $
31  * $DragonFly: src/sys/net/i4b/layer4/i4b_i4bdrv.c,v 1.12 2005/06/03 16:50:13 dillon Exp $
32  *
33  *      last edit-date: [Sat Aug 11 18:08:10 2001]
34  *
35  *---------------------------------------------------------------------------*/
36
37 #include "use_i4b.h"
38 #include "use_i4bipr.h"
39 #include "use_i4btel.h"
40
41 #if NI4B > 1
42 #error "only 1 (one) i4b device possible!"
43 #endif
44
45 #if NI4B > 0
46
47 #include <sys/param.h>
48
49 #if defined(__DragonFly__) || defined(__FreeBSD__)
50 #include <sys/ioccom.h>
51 #include <sys/malloc.h>
52 #include <sys/uio.h>
53 #else
54 #include <sys/ioctl.h>
55 #endif
56
57 #include <sys/kernel.h>
58 #include <sys/systm.h>
59 #include <sys/conf.h>
60 #include <sys/mbuf.h>
61 #include <sys/socket.h>
62 #include <sys/thread2.h>
63 #if defined(__FreeBSD__) && __FreeBSD_version >= 500014
64 #include <sys/selinfo.h>
65 #else
66 #include <sys/select.h>
67 #endif
68 #include <net/if.h>
69
70 #ifdef __NetBSD__
71 #include <sys/types.h>
72 #endif
73
74 #if defined(__DragonFly__) || defined(__FreeBSD__)
75 #include "use_i4bing.h"
76 #endif
77
78 #ifdef __bsdi__
79 #include "ibc.h"
80 #else
81 #if defined(__DragonFly__) || defined(__FreeBSD__)
82 #include "use_i4bisppp.h"
83 #else
84 #include <net/if_sppp.h>
85 #endif
86 #endif
87
88 #if defined(__DragonFly__) || defined(__FreeBSD__)
89
90 #if defined(__FreeBSD__) && __FreeBSD__ == 3
91 #include "opt_devfs.h"
92 #endif
93
94 #ifdef DEVFS
95 #include <sys/devfsext.h>
96 #endif
97
98 #endif /* __FreeBSD__*/
99
100 #if defined(__DragonFly__) || defined(__FreeBSD__)
101 #include <net/i4b/include/machine/i4b_debug.h>
102 #include <net/i4b/include/machine/i4b_ioctl.h>
103 #include <net/i4b/include/machine/i4b_cause.h>
104 #else
105 #include <i4b/i4b_debug.h>
106 #include <i4b/i4b_ioctl.h>
107 #include <i4b/i4b_cause.h>
108 #endif
109
110 #include "../include/i4b_l3l4.h"
111 #include "../include/i4b_mbuf.h"
112 #include "../include/i4b_global.h"
113
114 #include "i4b_l4.h"
115
116 #ifdef OS_USES_POLL
117 #include <sys/poll.h>
118 #endif
119
120 struct selinfo select_rd_info;
121
122 static struct ifqueue i4b_rdqueue;
123 static int openflag = 0;
124 static int selflag = 0;
125 static int readflag = 0;
126
127 #if defined(__FreeBSD__) && __FreeBSD__ == 3
128 #ifdef DEVFS
129 static void *devfs_token;
130 #endif
131 #endif
132
133 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
134
135 #define PDEVSTATIC      /* - not static - */
136 PDEVSTATIC void i4battach (void);
137 PDEVSTATIC int i4bopen (dev_t dev, int flag, int fmt, struct proc *p);
138 PDEVSTATIC int i4bclose (dev_t dev, int flag, int fmt, struct proc *p);
139 PDEVSTATIC int i4bread (dev_t dev, struct uio *uio, int ioflag);
140
141 #ifdef __bsdi__
142 PDEVSTATIC int i4bioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
143 #else
144 PDEVSTATIC int i4bioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
145 #endif
146
147 #ifdef OS_USES_POLL
148 PDEVSTATIC int i4bpoll (dev_t dev, int events, struct proc *p);
149 #else
150 PDEVSTATIC int i4bselect (dev_t dev, int rw, struct proc *p);
151 #endif
152
153 #endif /* #ifndef __FreeBSD__ */
154
155 #if defined(__DragonFly__) || (BSD > 199306 && defined(__FreeBSD__))
156
157 #define PDEVSTATIC      static
158
159 PDEVSTATIC      d_open_t        i4bopen;
160 PDEVSTATIC      d_close_t       i4bclose;
161 PDEVSTATIC      d_read_t        i4bread;
162 PDEVSTATIC      d_ioctl_t       i4bioctl;
163
164 #ifdef OS_USES_POLL
165 PDEVSTATIC      d_poll_t        i4bpoll;
166 #define POLLFIELD               i4bpoll
167 #else
168 PDEVSTATIC      d_select_t      i4bselect;
169 #define POLLFIELD               i4bselect
170 #endif
171
172 #define CDEV_MAJOR 60
173
174 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
175 static struct cdevsw i4b_cdevsw = {
176         /* name */      "i4b",
177         /* maj */       CDEV_MAJOR,
178         /* flags */     0,
179         /* port */      NULL,
180         /* clone */     NULL,
181
182         /* open */      i4bopen,
183         /* close */     i4bclose,
184         /* read */      i4bread,
185         /* write */     nowrite,
186         /* ioctl */     i4bioctl,
187         /* poll */      POLLFIELD,
188         /* mmap */      nommap,
189         /* strategy */  nostrategy,
190         /* dump */      nodump,
191         /* psize */     nopsize
192 };
193 #else
194 static struct cdevsw i4b_cdevsw = {
195         i4bopen,        i4bclose,       i4bread,        nowrite,
196         i4bioctl,       nostop,         nullreset,      nodevtotty,
197         POLLFIELD,      nommap,         NULL,           "i4b", NULL,    -1
198 };
199 #endif
200
201 PDEVSTATIC void i4battach(void *);
202 PSEUDO_SET(i4battach, i4b_i4bdrv);
203
204 static void
205 i4b_drvinit(void *unused)
206 {
207 #if defined(__DragonFly__) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
208         cdevsw_add(&i4b_cdevsw, 0, 0);
209 #else
210         static int i4b_devsw_installed = 0;
211         dev_t dev;
212
213         if( ! i4b_devsw_installed )
214         {
215                 dev = makedev(CDEV_MAJOR,0);
216                 cdevsw_add(&dev,&i4b_cdevsw,NULL);
217                 i4b_devsw_installed = 1;
218         }
219 #endif
220 }
221
222 SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL)
223
224 #endif /* BSD > 199306 && defined(__FreeBSD__) */
225
226 #ifdef __bsdi__
227 #include <sys/device.h>
228 int i4bmatch(struct device *parent, struct cfdata *cf, void *aux);
229 void dummy_i4battach(struct device*, struct device *, void *);
230
231 #define CDEV_MAJOR 65
232
233 static struct cfdriver i4bcd =
234         { NULL, "i4b", i4bmatch, dummy_i4battach, DV_DULL,
235           sizeof(struct cfdriver) };
236 struct devsw i4bsw = 
237         { &i4bcd,
238           i4bopen,      i4bclose,       i4bread,        nowrite,
239           i4bioctl,     i4bselect,      nommap,         nostrat,
240           nodump,       nopsize,        0,              nostop
241 };
242
243 int
244 i4bmatch(struct device *parent, struct cfdata *cf, void *aux)
245 {
246         printf("i4bmatch: aux=0x%x\n", aux);
247         return 1;
248 }
249 void
250 dummy_i4battach(struct device *parent, struct device *self, void *aux)
251 {
252         printf("dummy_i4battach: aux=0x%x\n", aux);
253 }
254 #endif /* __bsdi__ */
255
256 /*---------------------------------------------------------------------------*
257  *      interface attach routine
258  *---------------------------------------------------------------------------*/
259 PDEVSTATIC void
260 #if defined(__DragonFly__) || defined(__FreeBSD__)
261 i4battach(void *dummy)
262 #else
263 i4battach()
264 #endif
265 {
266         printf("i4b: ISDN call control device attached\n");
267
268         i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
269
270 #if defined(__FreeBSD__) && __FreeBSD__ > 4
271         mtx_init(&i4b_rdqueue.ifq_mtx, "i4b_rdqueue", MTX_DEF);
272 #endif
273
274 #if defined(__DragonFly__) || defined(__FreeBSD__)
275         make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
276 #endif
277 }
278
279 /*---------------------------------------------------------------------------*
280  *      i4bopen - device driver open routine
281  *---------------------------------------------------------------------------*/
282 PDEVSTATIC int
283 i4bopen(dev_t dev, int flag, int fmt, struct thread *td)
284 {
285         if(minor(dev))
286                 return(ENXIO);
287
288         if(openflag)
289                 return(EBUSY);
290         
291         crit_enter();
292         openflag = 1;
293         i4b_l4_daemon_attached();
294         crit_exit();
295         
296         return(0);
297 }
298
299 /*---------------------------------------------------------------------------*
300  *      i4bclose - device driver close routine
301  *---------------------------------------------------------------------------*/
302 PDEVSTATIC int
303 i4bclose(dev_t dev, int flag, int fmt, struct thread *td)
304 {
305         crit_enter();
306         openflag = 0;
307         i4b_l4_daemon_detached();
308         i4b_Dcleanifq(&i4b_rdqueue);
309         crit_exit();
310         return(0);
311 }
312
313 /*---------------------------------------------------------------------------*
314  *      i4bread - device driver read routine
315  *---------------------------------------------------------------------------*/
316 PDEVSTATIC int
317 i4bread(dev_t dev, struct uio *uio, int ioflag)
318 {
319         struct mbuf *m;
320         int error = 0;
321
322         if(minor(dev))
323                 return(ENODEV);
324
325         crit_enter();
326         while(IF_QEMPTY(&i4b_rdqueue))
327         {
328                 readflag = 1;
329 #if defined (__FreeBSD__) && __FreeBSD__ > 4            
330                 error = msleep((caddr_t) &i4b_rdqueue, &i4b_rdqueue.ifq_mtx,
331                         PCATCH, "bird", 0);
332 #else
333                 error = tsleep((caddr_t) &i4b_rdqueue, PCATCH, "bird", 0);
334 #endif
335                 if (error != 0) {
336                         crit_exit();
337                         return error;
338                 }
339         }
340
341         IF_DEQUEUE(&i4b_rdqueue, m);
342
343         crit_exit();
344                 
345         if(m && m->m_len)
346                 error = uiomove(m->m_data, m->m_len, uio);
347         else
348                 error = EIO;
349                 
350         if(m)
351                 i4b_Dfreembuf(m);
352
353         return(error);
354 }
355
356 /*---------------------------------------------------------------------------*
357  *      i4bioctl - device driver ioctl routine
358  *---------------------------------------------------------------------------*/
359 PDEVSTATIC int
360 #if defined(__DragonFly__) || (defined (__FreeBSD_version) && __FreeBSD_version >= 300003)
361 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
362 #elif defined(__bsdi__)
363 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
364 #else
365 i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
366 #endif
367 {
368         call_desc_t *cd;
369         int error = 0;
370         
371         if(minor(dev))
372                 return(ENODEV);
373
374         switch(cmd)
375         {
376                 /* cdid request, reserve cd and return cdid */
377
378                 case I4B_CDID_REQ:
379                 {
380                         msg_cdid_req_t *mir;
381                         mir = (msg_cdid_req_t *)data;
382                         cd = reserve_cd();
383                         mir->cdid = cd->cdid;
384                         break;
385                 }
386                 
387                 /* connect request, dial out to remote */
388                 
389                 case I4B_CONNECT_REQ:
390                 {
391                         msg_connect_req_t *mcr;
392                         mcr = (msg_connect_req_t *)data;        /* setup ptr */
393
394                         if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
395                         {
396                                 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!"); 
397                                 error = EINVAL;
398                                 break;
399                         }
400
401                         /* prevent dialling on leased lines */
402                         if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
403                         {
404                                 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
405                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
406                                 i4b_l4_disconnect_ind(cd);
407                                 freecd_by_cd(cd);
408                                 break;
409                         }
410
411                         cd->controller = mcr->controller;       /* fill cd */
412                         cd->bprot = mcr->bprot;
413                         cd->driver = mcr->driver;
414                         cd->driver_unit = mcr->driver_unit;
415                         cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
416
417                         cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
418                         cd->shorthold_data.unitlen_time  = mcr->shorthold_data.unitlen_time;
419                         cd->shorthold_data.idle_time     = mcr->shorthold_data.idle_time;
420                         cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
421
422                         cd->last_aocd_time = 0;
423                         if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
424                                 cd->aocd_flag = 1;
425                         else
426                                 cd->aocd_flag = 0;
427                                 
428                         cd->cunits = 0;
429
430                         cd->max_idle_time = 0;  /* this is outgoing */
431
432                         cd->dir = DIR_OUTGOING;
433                         
434                         NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
435                                         (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
436                                         (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
437
438                         strcpy(cd->dst_telno, mcr->dst_telno);
439                         strcpy(cd->src_telno, mcr->src_telno);
440
441                         if(mcr->keypad[0] != '\0')
442                                 strcpy(cd->keypad, mcr->keypad);
443                         else
444                                 cd->keypad[0] = '\0';
445                                 
446                         cd->display[0] = '\0';
447
448                         SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
449                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
450                         
451                         switch(mcr->channel)
452                         {
453                                 case CHAN_B1:
454                                 case CHAN_B2:
455                                         if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
456                                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
457                                         break;
458
459                                 case CHAN_ANY:
460                                 {
461                                     int i;
462                                     for (i = 0;
463                                          i < ctrl_desc[mcr->controller].nbch &&
464                                          ctrl_desc[mcr->controller].bch_state[i] != BCH_ST_FREE;
465                                          i++);
466                                     if (i == ctrl_desc[mcr->controller].nbch)
467                                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
468                                     /* else mcr->channel = i; XXX */
469                                 }
470                                         break;
471
472                                 default:
473                                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
474                                         break;
475                         }
476
477                         cd->channelid = mcr->channel;
478
479                         cd->isdntxdelay = mcr->txdelay;
480                         
481                         /* check whether we have a pointer. Seems like */
482                         /* this should be adequate. GJ 19.09.97 */
483                         if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
484 /*XXX*/                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
485
486                         if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
487                         {
488                                 i4b_l4_disconnect_ind(cd);
489                                 freecd_by_cd(cd);
490                         }
491                         else
492                         {
493                                 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
494                         }
495                         break;
496                 }
497                 
498                 /* connect response, accept/reject/ignore incoming call */
499                 
500                 case I4B_CONNECT_RESP:
501                 {
502                         msg_connect_resp_t *mcrsp;
503                         
504                         mcrsp = (msg_connect_resp_t *)data;
505
506                         if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
507                         {
508                                 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!"); 
509                                 error = EINVAL;
510                                 break;
511                         }
512
513                         T400_stop(cd);
514
515                         cd->driver = mcrsp->driver;
516                         cd->driver_unit = mcrsp->driver_unit;
517                         cd->max_idle_time = mcrsp->max_idle_time;
518
519                         cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
520                         cd->shorthold_data.unitlen_time = 0;    /* this is incoming */
521                         cd->shorthold_data.idle_time = 0;
522                         cd->shorthold_data.earlyhup_time = 0;
523
524                         cd->isdntxdelay = mcrsp->txdelay;                       
525                         
526                         NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
527
528                         (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
529                         break;
530                 }
531                 
532                 /* disconnect request, actively terminate connection */
533                 
534                 case I4B_DISCONNECT_REQ:
535                 {
536                         msg_discon_req_t *mdr;
537                         
538                         mdr = (msg_discon_req_t *)data;
539
540                         if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
541                         {
542                                 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!"); 
543                                 error = EINVAL;
544                                 break;
545                         }
546
547                         /* preset causes with our cause */
548                         cd->cause_in = cd->cause_out = mdr->cause;
549                         
550                         (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
551                         break;
552                 }
553                 
554                 /* controller info request */
555
556                 case I4B_CTRL_INFO_REQ:
557                 {
558                         msg_ctrl_info_req_t *mcir;
559                         
560                         mcir = (msg_ctrl_info_req_t *)data;
561                         mcir->ncontroller = nctrl;
562
563                         if(mcir->controller > nctrl)
564                         {
565                                 mcir->ctrl_type = -1;
566                                 mcir->card_type = -1;
567                         }
568                         else
569                         {
570                                 mcir->ctrl_type = 
571                                         ctrl_desc[mcir->controller].ctrl_type;
572                                 mcir->card_type = 
573                                         ctrl_desc[mcir->controller].card_type;
574                                 mcir->nbch =
575                                         ctrl_desc[mcir->controller].nbch;
576
577                                 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
578                                         mcir->tei = ctrl_desc[mcir->controller].tei;
579                                 else
580                                         mcir->tei = -1;
581                         }
582                         break;
583                 }
584                 
585                 /* dial response */
586                 
587                 case I4B_DIALOUT_RESP:
588                 {
589                         drvr_link_t *dlt = NULL;
590                         msg_dialout_resp_t *mdrsp;
591                         
592                         mdrsp = (msg_dialout_resp_t *)data;
593
594                         switch(mdrsp->driver)
595                         {
596 #if NI4BIPR > 0
597                                 case BDRV_IPR:
598                                         dlt = ipr_ret_linktab(mdrsp->driver_unit);
599                                         break;
600 #endif                                  
601
602 #if NI4BISPPP > 0
603                                 case BDRV_ISPPP:
604                                         dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
605                                         break;
606 #endif
607
608 #if NI4BTEL > 0
609                                 case BDRV_TEL:
610                                         dlt = tel_ret_linktab(mdrsp->driver_unit);
611                                         break;
612 #endif
613
614 #if NIBC > 0
615                                 case BDRV_IBC:
616                                         dlt = ibc_ret_linktab(mdrsp->driver_unit);
617                                         break;
618 #endif
619
620 #if NI4BING > 0
621                                 case BDRV_ING:
622                                         dlt = ing_ret_linktab(mdrsp->driver_unit);
623                                         break;
624 #endif                                  
625                         }
626
627                         if(dlt != NULL)         
628                                 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
629                         break;
630                 }
631                 
632                 /* update timeout value */
633                 
634                 case I4B_TIMEOUT_UPD:
635                 {
636                         msg_timeout_upd_t *mtu;
637                         
638                         mtu = (msg_timeout_upd_t *)data;
639
640                         NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
641                                         mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
642                                         mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time); 
643
644                         if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
645                         {
646                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!"); 
647                                 error = EINVAL;
648                                 break;
649                         }
650
651                         switch( mtu->shorthold_data.shorthold_algorithm )
652                         {
653                                 case SHA_FIXU:
654                                         /*
655                                          * For this algorithm unitlen_time,
656                                          * idle_time and earlyhup_time are used.
657                                          */
658
659                                         if(!(mtu->shorthold_data.unitlen_time >= 0 &&
660                                              mtu->shorthold_data.idle_time >= 0    &&
661                                              mtu->shorthold_data.earlyhup_time >= 0))
662                                         {
663                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!"); 
664                                                 error = EINVAL;
665                                         }
666                                         break;
667         
668                                 case SHA_VARU:
669                                         /*
670                                          * For this algorithm unitlen_time and
671                                          * idle_time are used. both must be
672                                          * positive integers. earlyhup_time is
673                                          * not used and must be 0.
674                                          */
675
676                                         if(!(mtu->shorthold_data.unitlen_time > 0 &&
677                                              mtu->shorthold_data.idle_time >= 0   &&
678                                              mtu->shorthold_data.earlyhup_time == 0))
679                                         {
680                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!"); 
681                                                 error = EINVAL;
682                                         }
683                                         break;
684         
685                                 default:
686                                         NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!"); 
687                                         error = EINVAL;
688                                         break;
689                         }
690
691                         /*
692                          * any error set above requires us to break
693                          * out of the outer switch
694                          */
695                         if(error != 0)
696                                 break;
697
698                         crit_enter();
699                         cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
700                         cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
701                         cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
702                         cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
703                         crit_exit();
704                         break;
705                 }
706                         
707                 /* soft enable/disable interface */
708                 
709                 case I4B_UPDOWN_IND:
710                 {
711                         msg_updown_ind_t *mui;
712                         
713                         mui = (msg_updown_ind_t *)data;
714
715 #if NI4BIPR > 0
716                         if(mui->driver == BDRV_IPR)
717                         {
718                                 drvr_link_t *dlt;
719                                 dlt = ipr_ret_linktab(mui->driver_unit);
720                                 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
721                         }
722 #endif
723                         break;
724                 }
725                 
726                 /* send ALERT request */
727                 
728                 case I4B_ALERT_REQ:
729                 {
730                         msg_alert_req_t *mar;
731                         
732                         mar = (msg_alert_req_t *)data;
733
734                         if((cd = cd_by_cdid(mar->cdid)) == NULL)
735                         {
736                                 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!"); 
737                                 error = EINVAL;
738                                 break;
739                         }
740
741                         T400_stop(cd);
742                         
743                         (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
744
745                         break;
746                 }
747
748                 /* version/release number request */
749                 
750                 case I4B_VR_REQ:
751                 {
752                         msg_vr_req_t *mvr;
753
754                         mvr = (msg_vr_req_t *)data;
755
756                         mvr->version = VERSION;
757                         mvr->release = REL;
758                         mvr->step = STEP;                       
759                         break;
760                 }
761
762                 /* set D-channel protocol for a controller */
763                 
764                 case I4B_PROT_IND:
765                 {
766                         msg_prot_ind_t *mpi;
767                         
768                         mpi = (msg_prot_ind_t *)data;
769
770                         ctrl_desc[mpi->controller].protocol = mpi->protocol;
771                         
772                         break;
773                 }
774                 
775                 /* Download request */
776
777                 case I4B_CTRL_DOWNLOAD:
778                 {
779                         struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
780                         struct isdn_download_request *r =
781                                 (struct isdn_download_request*)data;
782                         int i;
783
784                         if (r->controller < 0 || r->controller >= nctrl)
785                         {
786                                 error = ENODEV;
787                                 goto download_done;
788                         }
789
790                         if(!ctrl_desc[r->controller].N_DOWNLOAD)
791                         {
792                                 error = ENODEV;
793                                 goto download_done;
794                         }
795
796                         prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
797                                         M_DEVBUF, M_WAITOK);
798
799                         prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
800                                         M_DEVBUF, M_WAITOK);
801
802                         if(!prots || !prots2)
803                         {
804                                 error = ENOMEM;
805                                 goto download_done;
806                         }
807
808                         copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
809
810                         for(i = 0; i < r->numprotos; i++)
811                         {
812                                 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
813                                 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
814                                 prots2[i].bytecount = prots[i].bytecount; 
815                         }
816
817                         error = ctrl_desc[r->controller].N_DOWNLOAD(
818                                                 ctrl_desc[r->controller].unit,
819                                                 r->numprotos, prots2);
820
821 download_done:
822                         if(prots2)
823                         {
824                                 for(i = 0; i < r->numprotos; i++)
825                                 {
826                                         if(prots2[i].microcode)
827                                         {
828                                                 free(prots2[i].microcode, M_DEVBUF);
829                                         }
830                                 }
831                                 free(prots2, M_DEVBUF);
832                         }
833
834                         if(prots)
835                         {
836                                 free(prots, M_DEVBUF);
837                         }
838                         break;
839                 }
840
841                 /* Diagnostic request */
842
843                 case I4B_ACTIVE_DIAGNOSTIC:
844                 {
845                         struct isdn_diagnostic_request req, *r =
846                                 (struct isdn_diagnostic_request*)data;
847
848                         req.in_param = req.out_param = NULL;
849                         if (r->controller < 0 || r->controller >= nctrl)
850                         {
851                                 error = ENODEV;
852                                 goto diag_done;
853                         }
854
855                         if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
856                         {
857                                 error = ENODEV;
858                                 goto diag_done;
859                         }
860
861                         memcpy(&req, r, sizeof(req));
862
863                         if(req.in_param_len)
864                         {
865                                 /* XXX arbitrary limit */
866                                 if (req.in_param_len >
867                                     I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
868                                         error = EINVAL;
869                                         goto diag_done;
870                                 }       
871
872                                 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
873
874                                 if(!req.in_param)
875                                 {
876                                         error = ENOMEM;
877                                         goto diag_done;
878                                 }
879                                 error = copyin(r->in_param, req.in_param, req.in_param_len);
880                                 if (error)
881                                         goto diag_done;
882                         }
883
884                         if(req.out_param_len)
885                         {
886                                 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
887
888                                 if(!req.out_param)
889                                 {
890                                         error = ENOMEM;
891                                         goto diag_done;
892                                 }
893                         }
894                         
895                         error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
896
897                         if(!error && req.out_param_len)
898                                 error = copyout(req.out_param, r->out_param, req.out_param_len);
899
900 diag_done:
901                         if(req.in_param)
902                                 free(req.in_param, M_DEVBUF);
903                                 
904                         if(req.out_param)
905                                 free(req.out_param, M_DEVBUF);
906
907                         break;
908                 }
909
910                 /* default */
911                 
912                 default:
913                         error = ENOTTY;
914                         break;
915         }
916         
917         return(error);
918 }
919
920 #ifdef OS_USES_SELECT
921
922 /*---------------------------------------------------------------------------*
923  *      i4bselect - device driver select routine
924  *---------------------------------------------------------------------------*/
925 PDEVSTATIC int
926 i4bselect(dev_t dev, int rw, struct thread *td)
927 {
928         if(minor(dev))
929                 return(ENODEV);
930
931         switch(rw)
932         {
933                 case FREAD:
934                         if(!IF_QEMPTY(&i4b_rdqueue))
935                                 return(1);
936                         crit_enter();
937                         selrecord(td, &select_rd_info);
938                         selflag = 1;
939                         crit_exit();
940                         return(0);
941                         break;
942
943                 case FWRITE:
944                         return(1);
945                         break;
946         }
947         return(0);
948 }
949
950 #else /* OS_USES_SELECT */
951
952 /*---------------------------------------------------------------------------*
953  *      i4bpoll - device driver poll routine
954  *---------------------------------------------------------------------------*/
955 PDEVSTATIC int
956 i4bpoll(dev_t dev, int events, struct thread *td)
957 {
958         if(minor(dev))
959                 return(ENODEV);
960
961         if((events & POLLIN) || (events & POLLRDNORM))
962         {
963                 if(!IF_QEMPTY(&i4b_rdqueue))
964                         return(1);
965
966                 crit_enter();
967                 selrecord(td, &select_rd_info);
968                 selflag = 1;
969                 crit_exit();
970                 return(0);
971         }
972         else if((events & POLLOUT) || (events & POLLWRNORM))
973         {
974                 return(1);
975         }
976
977         return(0);
978 }
979
980 #endif /* OS_USES_SELECT */
981
982 /*---------------------------------------------------------------------------*
983  *      i4bputqueue - put message into queue to userland
984  *---------------------------------------------------------------------------*/
985 void
986 i4bputqueue(struct mbuf *m)
987 {
988         if(!openflag)
989         {
990                 i4b_Dfreembuf(m);
991                 return;
992         }
993
994         crit_enter();
995         
996         if(IF_QFULL(&i4b_rdqueue))
997         {
998                 struct mbuf *m1;
999                 IF_DEQUEUE(&i4b_rdqueue, m1);
1000                 i4b_Dfreembuf(m1);
1001                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
1002         }
1003
1004         IF_ENQUEUE(&i4b_rdqueue, m);
1005
1006         crit_exit();
1007
1008         if(readflag)
1009         {
1010                 readflag = 0;
1011                 wakeup((caddr_t) &i4b_rdqueue);
1012         }
1013
1014         if(selflag)
1015         {
1016                 selflag = 0;
1017                 selwakeup(&select_rd_info);
1018         }
1019 }
1020
1021 /*---------------------------------------------------------------------------*
1022  *      i4bputqueue_hipri - put message into front of queue to userland
1023  *---------------------------------------------------------------------------*/
1024 void
1025 i4bputqueue_hipri(struct mbuf *m)
1026 {
1027         if(!openflag)
1028         {
1029                 i4b_Dfreembuf(m);
1030                 return;
1031         }
1032
1033         crit_enter();
1034         
1035         if(IF_QFULL(&i4b_rdqueue))
1036         {
1037                 struct mbuf *m1;
1038                 IF_DEQUEUE(&i4b_rdqueue, m1);
1039                 i4b_Dfreembuf(m1);
1040                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
1041         }
1042
1043         IF_PREPEND(&i4b_rdqueue, m);
1044
1045         crit_exit();
1046
1047         if(readflag)
1048         {
1049                 readflag = 0;
1050                 wakeup((caddr_t) &i4b_rdqueue);
1051         }
1052
1053         if(selflag)
1054         {
1055                 selflag = 0;
1056                 selwakeup(&select_rd_info);
1057         }
1058 }
1059
1060 #endif /* NI4B > 0 */