2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4b_i4bdrv.c - i4b userland interface driver
28 * --------------------------------------------
30 * $Id: i4b_i4bdrv.c,v 1.36 2009/03/18 10:22:43 cegger Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_i4bdrv.c,v 1.35 2009/03/14 14:46:10 dsl Exp $");
45 #include <sys/param.h>
47 #if defined(__FreeBSD__)
48 #include <sys/ioccom.h>
49 #include <sys/malloc.h>
52 #include <sys/ioctl.h>
55 #include <sys/kernel.h>
56 #include <sys/systm.h>
60 #include <sys/fcntl.h>
61 #include <sys/socket.h>
62 #include <sys/select.h>
67 #if defined(__FreeBSD__) && __FreeBSD__ == 3
68 #include "opt_devfs.h"
72 #include <sys/devfsext.h>
75 #endif /* __FreeBSD__*/
78 #include <machine/i4b_debug.h>
79 #include <machine/i4b_ioctl.h>
80 #include <machine/i4b_cause.h>
82 #include <netisdn/i4b_debug.h>
83 #include <netisdn/i4b_ioctl.h>
84 #include <netisdn/i4b_cause.h>
87 #include <netisdn/i4b_l3l4.h>
88 #include <netisdn/i4b_mbuf.h>
89 #include <netisdn/i4b_global.h>
91 #include <netisdn/i4b_l4.h>
97 struct selinfo select_rd_info
;
99 static struct ifqueue i4b_rdqueue
;
100 static int openflag
= 0;
101 static int selflag
= 0;
102 static int readflag
= 0;
104 #if defined(__FreeBSD__) && __FreeBSD__ == 3
106 static void *devfs_token
;
112 #define PDEVSTATIC /* - not static - */
113 PDEVSTATIC
void isdnattach(void);
114 PDEVSTATIC
int isdnopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
);
115 PDEVSTATIC
int isdnclose(dev_t dev
, int flag
, int fmt
, struct lwp
*l
);
116 PDEVSTATIC
int isdnread(dev_t dev
, struct uio
*uio
, int ioflag
);
117 PDEVSTATIC
int isdnioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
);
120 PDEVSTATIC
int isdnpoll(dev_t dev
, int events
, struct lwp
*l
);
121 PDEVSTATIC
int isdnkqfilter(dev_t dev
, struct knote
*kn
);
123 PDEVSTATIC
int isdnselect(dev_t dev
, int rw
, struct lwp
*l
);
126 #endif /* #ifndef __FreeBSD__ */
128 #if BSD > 199306 && defined(__FreeBSD__)
130 #define PDEVSTATIC static
132 PDEVSTATIC d_open_t i4bopen
;
133 PDEVSTATIC d_close_t i4bclose
;
134 PDEVSTATIC d_read_t i4bread
;
135 PDEVSTATIC d_ioctl_t i4bioctl
;
138 PDEVSTATIC d_poll_t i4bpoll
;
139 #define POLLFIELD i4bpoll
141 PDEVSTATIC d_select_t i4bselect
;
142 #define POLLFIELD i4bselect
145 #define CDEV_MAJOR 60
147 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
148 static struct cdevsw i4b_cdevsw
= {
150 /* close */ i4bclose
,
153 /* ioctl */ i4bioctl
,
154 /* poll */ POLLFIELD
,
156 /* strategy */ nostrategy
,
158 /* maj */ CDEV_MAJOR
,
165 static struct cdevsw i4b_cdevsw
= {
166 i4bopen
, i4bclose
, i4bread
, nowrite
,
167 i4bioctl
, nostop
, nullreset
, nodevtotty
,
168 POLLFIELD
, nommap
, NULL
, "i4b", NULL
, -1
172 PDEVSTATIC
void i4battach(void *);
173 PSEUDO_SET(i4battach
, i4b_i4bdrv
);
176 i4b_drvinit(void *unused
)
178 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
179 cdevsw_add(&i4b_cdevsw
);
181 static int i4b_devsw_installed
= 0;
184 if( ! i4b_devsw_installed
)
186 dev
= makedev(CDEV_MAJOR
,0);
187 cdevsw_add(&dev
,&i4b_cdevsw
,NULL
);
188 i4b_devsw_installed
= 1;
193 SYSINIT(i4bdev
,SI_SUB_DRIVERS
,SI_ORDER_MIDDLE
+CDEV_MAJOR
,i4b_drvinit
,NULL
)
195 #endif /* BSD > 199306 && defined(__FreeBSD__) */
198 const struct cdevsw isdn_cdevsw
= {
199 isdnopen
, isdnclose
, isdnread
, nowrite
, isdnioctl
,
200 nostop
, notty
, isdnpoll
, nommap
, isdnkqfilter
, D_OTHER
202 #endif /* __NetBSD__ */
205 #include <sys/device.h>
206 int i4bmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
);
207 void dummy_i4battach(struct device
*, struct device
*, void *);
209 #define CDEV_MAJOR 65
211 static struct cfdriver i4bcd
=
212 { NULL
, "i4b", i4bmatch
, dummy_i4battach
, DV_DULL
,
213 sizeof(struct cfdriver
) };
216 i4bopen
, i4bclose
, i4bread
, nowrite
,
217 i4bioctl
, i4bselect
, nommap
, nostrat
,
218 nodump
, nopsize
, 0, nostop
222 i4bmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
224 printf("i4bmatch: aux=0x%x\n", aux
);
228 dummy_i4battach(struct device
*parent
, struct device
*self
, void *aux
)
230 printf("dummy_i4battach: aux=0x%x\n", aux
);
232 #endif /* __bsdi__ */
234 /*---------------------------------------------------------------------------*
235 * interface attach routine
236 *---------------------------------------------------------------------------*/
239 isdnattach(void *dummy
)
244 i4b_rdqueue
.ifq_maxlen
= IFQ_MAXLEN
;
245 selinit(&select_rd_info
);
247 #if defined(__FreeBSD__)
251 devfs_token
= devfs_add_devswf(&i4b_cdevsw
, 0, DV_CHR
,
252 UID_ROOT
, GID_WHEEL
, 0600,
257 make_dev(&i4b_cdevsw
, 0, UID_ROOT
, GID_WHEEL
, 0600, "i4b");
262 /*---------------------------------------------------------------------------*
263 * i4bopen - device driver open routine
264 *---------------------------------------------------------------------------*/
266 isdnopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
278 i4b_l4_daemon_attached();
284 /*---------------------------------------------------------------------------*
285 * i4bclose - device driver close routine
286 *---------------------------------------------------------------------------*/
288 isdnclose(dev_t dev
, int flag
, int fmt
,
293 i4b_l4_daemon_detached();
294 i4b_Dcleanifq(&i4b_rdqueue
);
299 /*---------------------------------------------------------------------------*
300 * i4bread - device driver read routine
301 *---------------------------------------------------------------------------*/
303 isdnread(dev_t dev
, struct uio
*uio
, int ioflag
)
313 while(IF_QEMPTY(&i4b_rdqueue
))
316 error
= tsleep((void *) &i4b_rdqueue
, (PZERO
+ 1) | PCATCH
, "bird", 0);
323 IF_DEQUEUE(&i4b_rdqueue
, m
);
328 error
= uiomove(m
->m_data
, m
->m_len
, uio
);
338 /*---------------------------------------------------------------------------*
339 * i4bioctl - device driver ioctl routine
340 *---------------------------------------------------------------------------*/
342 isdnioctl(dev_t dev
, u_long cmd
, void *data
, int flag
,
345 struct isdn_l3_driver
*d
;
354 /* cdid request, reserve cd and return cdid */
359 mir
= (msg_cdid_req_t
*)data
;
361 mir
->cdid
= cd
->cdid
;
365 /* connect request, dial out to remote */
367 case I4B_CONNECT_REQ
:
369 msg_connect_req_t
*mcr
;
370 mcr
= (msg_connect_req_t
*)data
; /* setup ptr */
372 if((cd
= cd_by_cdid(mcr
->cdid
)) == NULL
)/* get cd */
374 NDBGL4(L4_ERR
, "I4B_CONNECT_REQ ioctl, cdid not found!");
381 d
= isdn_find_l3_by_isdnif(mcr
->controller
);
387 /* prevent dialling on leased lines */
388 if(d
->protocol
== PROTOCOL_D64S
)
390 SET_CAUSE_TYPE(cd
->cause_in
, CAUSET_I4B
);
391 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_LLDIAL
);
392 i4b_l4_disconnect_ind(cd
);
397 cd
->isdnif
= mcr
->controller
; /* fill cd */
399 cd
->bprot
= mcr
->bprot
;
400 cd
->bchan_driver_index
= mcr
->driver
;
401 cd
->bchan_driver_unit
= mcr
->driver_unit
;
402 cd
->cr
= get_rand_cr(cd
->isdnif
);
404 cd
->shorthold_data
.shorthold_algorithm
= mcr
->shorthold_data
.shorthold_algorithm
;
405 cd
->shorthold_data
.unitlen_time
= mcr
->shorthold_data
.unitlen_time
;
406 cd
->shorthold_data
.idle_time
= mcr
->shorthold_data
.idle_time
;
407 cd
->shorthold_data
.earlyhup_time
= mcr
->shorthold_data
.earlyhup_time
;
409 cd
->last_aocd_time
= 0;
410 if(mcr
->unitlen_method
== ULEN_METHOD_DYNAMIC
)
417 cd
->max_idle_time
= 0; /* this is outgoing */
419 cd
->dir
= DIR_OUTGOING
;
421 NDBGL4(L4_TIMO
, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
422 (long)cd
->shorthold_data
.shorthold_algorithm
, (long)cd
->shorthold_data
.unitlen_time
,
423 (long)cd
->shorthold_data
.idle_time
, (long)cd
->shorthold_data
.earlyhup_time
);
425 strlcpy(cd
->dst_telno
, mcr
->dst_telno
,
426 sizeof(cd
->dst_telno
));
427 strlcpy(cd
->src_telno
, mcr
->src_telno
,
428 sizeof(cd
->src_telno
));
429 cd
->display
[0] = '\0';
431 SET_CAUSE_TYPE(cd
->cause_in
, CAUSET_I4B
);
432 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NORMAL
);
435 * If we want a specific channel, check if that
438 if ((mcr
->channel
>= 0) && (mcr
->channel
< d
->nbch
)) {
439 if(d
->bch_state
[mcr
->channel
] != BCH_ST_FREE
)
440 SET_CAUSE_VAL(cd
->cause_in
,
444 * If any channel will do, see if any are free.
446 } else if (mcr
->channel
== CHAN_ANY
) {
449 for (i
= 0; i
< d
->nbch
; i
++)
450 if (d
->bch_state
[i
] == BCH_ST_FREE
)
454 SET_CAUSE_VAL(cd
->cause_in
,
458 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NOCHAN
);
461 cd
->channelid
= mcr
->channel
;
463 cd
->isdntxdelay
= mcr
->txdelay
;
465 if((GET_CAUSE_VAL(cd
->cause_in
)) != CAUSE_I4B_NORMAL
)
467 i4b_l4_disconnect_ind(cd
);
472 d
->l3driver
->N_CONNECT_REQUEST(cd
);
477 /* connect response, accept/reject/ignore incoming call */
479 case I4B_CONNECT_RESP
:
481 msg_connect_resp_t
*mcrsp
;
483 mcrsp
= (msg_connect_resp_t
*)data
;
485 if((cd
= cd_by_cdid(mcrsp
->cdid
)) == NULL
)/* get cd */
487 NDBGL4(L4_ERR
, "I4B_CONNECT_RESP ioctl, cdid not found!");
494 cd
->bchan_driver_index
= mcrsp
->driver
;
495 cd
->bchan_driver_unit
= mcrsp
->driver_unit
;
496 cd
->max_idle_time
= mcrsp
->max_idle_time
;
498 cd
->shorthold_data
.shorthold_algorithm
= SHA_FIXU
;
499 cd
->shorthold_data
.unitlen_time
= 0; /* this is incoming */
500 cd
->shorthold_data
.idle_time
= 0;
501 cd
->shorthold_data
.earlyhup_time
= 0;
503 cd
->isdntxdelay
= mcrsp
->txdelay
;
505 NDBGL4(L4_TIMO
, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd
->max_idle_time
);
507 d
= isdn_find_l3_by_isdnif(cd
->isdnif
);
512 d
->l3driver
->N_CONNECT_RESPONSE(cd
, mcrsp
->response
, mcrsp
->cause
);
516 /* disconnect request, actively terminate connection */
518 case I4B_DISCONNECT_REQ
:
520 msg_discon_req_t
*mdr
;
522 mdr
= (msg_discon_req_t
*)data
;
524 if((cd
= cd_by_cdid(mdr
->cdid
)) == NULL
)/* get cd */
526 NDBGL4(L4_ERR
, "I4B_DISCONNECT_REQ ioctl, cdid %d not found!", mdr
->cdid
);
531 /* preset causes with our cause */
532 cd
->cause_in
= cd
->cause_out
= mdr
->cause
;
534 d
= isdn_find_l3_by_isdnif(cd
->isdnif
);
540 d
->l3driver
->N_DISCONNECT_REQUEST(cd
, mdr
->cause
);
544 /* controller info request */
546 case I4B_CTRL_INFO_REQ
:
548 msg_ctrl_info_req_t
*mcir
;
551 mcir
= (msg_ctrl_info_req_t
*)data
;
552 isdnif
= mcir
->controller
;
553 memset(mcir
, 0, sizeof(msg_ctrl_info_req_t
));
554 mcir
->controller
= isdnif
;
556 = isdn_count_isdnif(&mcir
->max_isdnif
);
557 d
= isdn_find_l3_by_isdnif(isdnif
);
560 mcir
->nbch
= d
->nbch
;
561 strncpy(mcir
->devname
, d
->devname
, sizeof(mcir
->devname
)-1);
562 strncpy(mcir
->cardname
, d
->card_name
, sizeof(mcir
->cardname
)-1);
571 case I4B_DIALOUT_RESP
:
573 const struct isdn_l4_driver_functions
*drv
;
574 msg_dialout_resp_t
*mdrsp
;
577 mdrsp
= (msg_dialout_resp_t
*)data
;
578 drv
= isdn_l4_get_driver(mdrsp
->driver
, mdrsp
->driver_unit
);
581 l4_softc
= (*drv
->get_softc
)(mdrsp
->driver_unit
);
582 (*drv
->dial_response
)(l4_softc
, mdrsp
->stat
, mdrsp
->cause
);
587 /* update timeout value */
589 case I4B_TIMEOUT_UPD
:
591 msg_timeout_upd_t
*mtu
;
594 mtu
= (msg_timeout_upd_t
*)data
;
596 NDBGL4(L4_TIMO
, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
597 mtu
->shorthold_data
.shorthold_algorithm
, mtu
->shorthold_data
.unitlen_time
,
598 mtu
->shorthold_data
.idle_time
, mtu
->shorthold_data
.earlyhup_time
);
600 if((cd
= cd_by_cdid(mtu
->cdid
)) == NULL
)/* get cd */
602 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
607 switch( mtu
->shorthold_data
.shorthold_algorithm
)
611 * For this algorithm unitlen_time,
612 * idle_time and earlyhup_time are used.
615 if(!(mtu
->shorthold_data
.unitlen_time
>= 0 &&
616 mtu
->shorthold_data
.idle_time
>= 0 &&
617 mtu
->shorthold_data
.earlyhup_time
>= 0))
619 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
626 * For this algorithm unitlen_time and
627 * idle_time are used. both must be
628 * positive integers. earlyhup_time is
629 * not used and must be 0.
632 if(!(mtu
->shorthold_data
.unitlen_time
> 0 &&
633 mtu
->shorthold_data
.idle_time
>= 0 &&
634 mtu
->shorthold_data
.earlyhup_time
== 0))
636 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
642 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
648 * any error set above requires us to break
649 * out of the outer switch
655 cd
->shorthold_data
.shorthold_algorithm
= mtu
->shorthold_data
.shorthold_algorithm
;
656 cd
->shorthold_data
.unitlen_time
= mtu
->shorthold_data
.unitlen_time
;
657 cd
->shorthold_data
.idle_time
= mtu
->shorthold_data
.idle_time
;
658 cd
->shorthold_data
.earlyhup_time
= mtu
->shorthold_data
.earlyhup_time
;
663 /* soft enable/disable interface */
667 msg_updown_ind_t
*mui
;
668 const struct isdn_l4_driver_functions
*drv
;
671 mui
= (msg_updown_ind_t
*)data
;
672 drv
= isdn_l4_get_driver(mui
->driver
, mui
->driver_unit
);
676 l4_softc
= drv
->get_softc(mui
->driver_unit
);
677 (*drv
->updown_ind
)(l4_softc
, mui
->updown
);
682 /* send ALERT request */
686 msg_alert_req_t
*mar
;
688 mar
= (msg_alert_req_t
*)data
;
690 if((cd
= cd_by_cdid(mar
->cdid
)) == NULL
)
692 NDBGL4(L4_ERR
, "I4B_ALERT_REQ ioctl, cdid not found!");
704 d
->l3driver
->N_ALERT_REQUEST(cd
);
709 /* version/release number request */
715 mvr
= (msg_vr_req_t
*)data
;
717 mvr
->version
= VERSION
;
723 /* set D-channel protocol for a controller */
729 mpi
= (msg_prot_ind_t
*)data
;
731 d
= isdn_find_l3_by_isdnif(mpi
->controller
);
736 d
->protocol
= mpi
->protocol
;
741 case I4B_L4DRIVER_LOOKUP
:
743 msg_l4driver_lookup_t
*lookup
= (msg_l4driver_lookup_t
*)data
;
744 lookup
->name
[L4DRIVER_NAME_SIZ
-1] = 0;
745 lookup
->driver_id
= isdn_l4_find_driverid(lookup
->name
);
746 if (lookup
->driver_id
< 0)
751 /* Download request */
752 case I4B_CTRL_DOWNLOAD
:
754 struct isdn_dr_prot
*prots
= NULL
, *prots2
= NULL
;
755 struct isdn_download_request
*r
=
756 (struct isdn_download_request
*)data
;
759 d
= isdn_find_l3_by_isdnif(r
->controller
);
766 if(d
->l3driver
->N_DOWNLOAD
== NULL
)
772 prots
= malloc(r
->numprotos
* sizeof(struct isdn_dr_prot
),
775 prots2
= malloc(r
->numprotos
* sizeof(struct isdn_dr_prot
),
778 if(!prots
|| !prots2
)
784 copyin(r
->protocols
, prots
, r
->numprotos
* sizeof(struct isdn_dr_prot
));
786 for(i
= 0; i
< r
->numprotos
; i
++)
788 prots2
[i
].microcode
= malloc(prots
[i
].bytecount
, M_DEVBUF
, M_WAITOK
);
789 copyin(prots
[i
].microcode
, prots2
[i
].microcode
, prots
[i
].bytecount
);
790 prots2
[i
].bytecount
= prots
[i
].bytecount
;
793 error
= d
->l3driver
->N_DOWNLOAD(
795 r
->numprotos
, prots2
);
800 for(i
= 0; i
< r
->numprotos
; i
++)
802 if(prots2
[i
].microcode
)
804 free(prots2
[i
].microcode
, M_DEVBUF
);
807 free(prots2
, M_DEVBUF
);
812 free(prots
, M_DEVBUF
);
817 /* Diagnostic request */
819 case I4B_ACTIVE_DIAGNOSTIC
:
821 struct isdn_diagnostic_request req
, *r
=
822 (struct isdn_diagnostic_request
*)data
;
824 req
.in_param
= req
.out_param
= NULL
;
825 d
= isdn_find_l3_by_isdnif(r
->controller
);
832 if (d
->l3driver
->N_DIAGNOSTICS
== NULL
)
838 memcpy(&req
, r
, sizeof(req
));
842 /* XXX arbitrary limit */
843 if (req
.in_param_len
> I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN
) {
848 req
.in_param
= malloc(r
->in_param_len
, M_DEVBUF
, M_WAITOK
);
855 error
= copyin(r
->in_param
, req
.in_param
, req
.in_param_len
);
860 if(req
.out_param_len
)
862 req
.out_param
= malloc(r
->out_param_len
, M_DEVBUF
, M_WAITOK
);
871 error
= d
->l3driver
->N_DIAGNOSTICS(d
->l1_token
, &req
);
873 if(!error
&& req
.out_param_len
)
874 error
= copyout(req
.out_param
, r
->out_param
, req
.out_param_len
);
878 free(req
.in_param
, M_DEVBUF
);
881 free(req
.out_param
, M_DEVBUF
);
896 #ifdef OS_USES_SELECT
898 /*---------------------------------------------------------------------------*
899 * i4bselect - device driver select routine
900 *---------------------------------------------------------------------------*/
902 i4bselect(dev_t dev
, int rw
, struct lwp
*l
)
912 if(!IF_QEMPTY(&i4b_rdqueue
))
915 selrecord(l
, &select_rd_info
);
928 #else /* OS_USES_SELECT */
930 /*---------------------------------------------------------------------------*
931 * i4bpoll - device driver poll routine
932 *---------------------------------------------------------------------------*/
934 isdnpoll(dev_t dev
, int events
, struct lwp
*l
)
941 if((events
& POLLIN
) || (events
& POLLRDNORM
))
943 if(!IF_QEMPTY(&i4b_rdqueue
))
947 selrecord(l
, &select_rd_info
);
952 else if((events
& POLLOUT
) || (events
& POLLWRNORM
))
961 filt_i4brdetach(struct knote
*kn
)
966 SLIST_REMOVE(&select_rd_info
.sel_klist
, kn
, knote
, kn_selnext
);
971 filt_i4bread(struct knote
*kn
, long hint
)
975 if (IF_QEMPTY(&i4b_rdqueue
))
978 IF_POLL(&i4b_rdqueue
, m
);
980 kn
->kn_data
= m
->m_len
;
984 static const struct filterops i4bread_filtops
=
985 { 1, NULL
, filt_i4brdetach
, filt_i4bread
};
987 static const struct filterops i4b_seltrue_filtops
=
988 { 1, NULL
, filt_i4brdetach
, filt_seltrue
};
991 isdnkqfilter(dev_t dev
, struct knote
*kn
)
996 switch (kn
->kn_filter
) {
998 klist
= &select_rd_info
.sel_klist
;
999 kn
->kn_fop
= &i4bread_filtops
;
1003 klist
= &select_rd_info
.sel_klist
;
1004 kn
->kn_fop
= &i4b_seltrue_filtops
;
1014 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
1020 #endif /* OS_USES_SELECT */
1022 /*---------------------------------------------------------------------------*
1023 * i4bputqueue - put message into queue to userland
1024 *---------------------------------------------------------------------------*/
1026 i4bputqueue(struct mbuf
*m
)
1038 if(IF_QFULL(&i4b_rdqueue
))
1041 IF_DEQUEUE(&i4b_rdqueue
, m1
);
1043 NDBGL4(L4_ERR
, "ERROR, queue full, removing entry!");
1046 IF_ENQUEUE(&i4b_rdqueue
, m
);
1053 wakeup((void *) &i4b_rdqueue
);
1059 selnotify(&select_rd_info
, 0, 0);
1063 /*---------------------------------------------------------------------------*
1064 * i4bputqueue_hipri - put message into front of queue to userland
1065 *---------------------------------------------------------------------------*/
1067 i4bputqueue_hipri(struct mbuf
*m
)
1079 if(IF_QFULL(&i4b_rdqueue
))
1082 IF_DEQUEUE(&i4b_rdqueue
, m1
);
1084 NDBGL4(L4_ERR
, "ERROR, queue full, removing entry!");
1087 IF_PREPEND(&i4b_rdqueue
, m
);
1094 wakeup((void *) &i4b_rdqueue
);
1100 selnotify(&select_rd_info
, 0, 0);
1105 isdn_isdnif_ready(int isdnif
)
1107 struct isdn_l3_driver
*d
= isdn_find_l3_by_isdnif(isdnif
);
1112 printf("ISDN %d at %s, %d B channels\n", isdnif
, d
->devname
, d
->nbch
);
1113 if (!openflag
) return;
1115 d
->l3driver
->N_MGMT_COMMAND(d
, CMR_DOPEN
, 0);
1116 i4b_l4_contr_ev_ind(isdnif
, 1);
1119 #endif /* NISDN > 0 */