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