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