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