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_rbch.c - device driver for raw B channel data
28 * ---------------------------------------------------
30 * $Id: i4b_rbch.c,v 1.25 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_rbch.c,v 1.24 2009/03/14 14:46:11 dsl Exp $");
41 #include "isdnbchan.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
50 #include <sys/kernel.h>
52 #include <sys/socket.h>
57 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
58 #include <sys/callout.h>
61 #if defined (__NetBSD__) || defined (__OpenBSD__)
62 #define termioschars(t) memcpy((t)->c_cc, &ttydefchars, sizeof((t)->c_cc))
67 #if defined(__FreeBSD__) && __FreeBSD__ == 3
68 #include "opt_devfs.h"
72 #include <sys/devfsext.h>
75 #endif /* __FreeBSD__ */
78 #include <sys/filio.h>
82 #include <machine/i4b_ioctl.h>
83 #include <machine/i4b_rbch_ioctl.h>
84 #include <machine/i4b_debug.h>
86 #include <netisdn/i4b_ioctl.h>
87 #include <netisdn/i4b_rbch_ioctl.h>
88 #include <netisdn/i4b_debug.h>
91 #include <netisdn/i4b_global.h>
92 #include <netisdn/i4b_mbuf.h>
93 #include <netisdn/i4b_l3l4.h>
95 #include <netisdn/i4b_l4.h>
98 #include <sys/device.h>
102 #include <sys/ioccom.h>
103 #include <sys/poll.h>
105 #include <sys/fcntl.h>
106 #include <sys/ioctl.h>
109 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
110 #include <sys/filio.h>
113 #define I4BRBCHACCT 1 /* enable accounting messages */
114 #define I4BRBCHACCTINTVL 2 /* accounting msg interval in secs */
116 static struct rbch_softc
{
118 int sc_unit
; /* unit number */
120 int sc_devstate
; /* state of driver */
122 #define ST_CONNECTED 0x01
123 #define ST_ISOPEN 0x02
124 #define ST_RDWAITDATA 0x04
125 #define ST_WRWAITEMPTY 0x08
126 #define ST_NOBLOCK 0x10
128 int sc_bprot
; /* B-ch protocol used */
130 call_desc_t
*sc_cd
; /* Call Descriptor */
131 isdn_link_t
*sc_ilt
; /* B-channel driver/state */
133 struct termios it_in
;
135 struct ifqueue sc_hdlcq
; /* hdlc read queue */
136 #define I4BRBCHMAXQLEN 10
138 struct selinfo selp
; /* select / poll */
140 #if defined(__FreeBSD__) && __FreeBSD__ == 3
142 void *devfs_token
; /* device filesystem */
147 #if defined(__FreeBSD__)
148 struct callout_handle sc_callout
;
150 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
151 struct callout sc_callout
;
154 int sc_iinb
; /* isdn driver # of inbytes */
155 int sc_ioutb
; /* isdn driver # of outbytes */
156 int sc_linb
; /* last # of bytes rx'd */
157 int sc_loutb
; /* last # of bytes tx'd */
158 int sc_fn
; /* flag, first null acct */
160 } rbch_softc
[NISDNBCHAN
];
162 static void rbch_rx_data_rdy(void *softc
);
163 static void rbch_tx_queue_empty(void *softc
);
164 static void rbch_connect(void *softc
, void *cdp
);
165 static void rbch_disconnect(void *softc
, void *cdp
);
166 static void rbch_clrq(void *softc
);
167 static void rbch_activity(void *softc
, int rxtx
);
168 static void rbch_dialresponse(void *softc
, int status
, cause_t cause
);
169 static void rbch_updown(void *softc
, int updown
);
170 static void rbch_set_linktab(void *softc
, isdn_link_t
*ilt
);
171 static void* rbch_get_softc(int unit
);
175 #define PDEVSTATIC /* - not static - */
176 #define IOCTL_CMD_T u_long
177 void isdnbchanattach(void);
178 int isdnbchanopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
);
179 int isdnbchanclose(dev_t dev
, int flag
, int fmt
, struct lwp
*l
);
180 int isdnbchanread(dev_t dev
, struct uio
*uio
, int ioflag
);
181 int isdnbchanwrite(dev_t dev
, struct uio
*uio
, int ioflag
);
182 int isdnbchanioctl(dev_t dev
, IOCTL_CMD_T cmd
, void *arg
, int flag
, struct lwp
* l
);
184 int isdnbchanpoll(dev_t dev
, int events
, struct lwp
*l
);
185 int isdnbchankqfilter(dev_t dev
, struct knote
*kn
);
187 PDEVSTATIC
int isdnbchanselect(dev_t dev
, int rw
, struct lwp
*l
);
192 const struct cdevsw isdnbchan_cdevsw
= {
193 isdnbchanopen
, isdnbchanclose
, isdnbchanread
, isdnbchanwrite
,
194 isdnbchanioctl
, nostop
, notty
, isdnbchanpoll
, nommap
, nokqfilter
,
197 #endif /* __NetBSD__ */
199 #if BSD > 199306 && defined(__FreeBSD__)
200 #define PDEVSTATIC static
201 #define IOCTL_CMD_T u_long
203 PDEVSTATIC d_open_t isdnbchanopen
;
204 PDEVSTATIC d_close_t isdnbchanclose
;
205 PDEVSTATIC d_read_t isdnbchanread
;
206 PDEVSTATIC d_read_t isdnbchanwrite
;
207 PDEVSTATIC d_ioctl_t isdnbchanioctl
;
210 PDEVSTATIC d_poll_t isdnbchanpoll
;
211 #define POLLFIELD isdnbchanpoll
213 PDEVSTATIC d_select_t isdnbchanselect
;
214 #define POLLFIELD isdnbchanselect
217 #define CDEV_MAJOR 57
219 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
220 static struct cdevsw isdnbchan_cdevsw
= {
221 /* open */ isdnbchanopen
,
222 /* close */ isdnbchanclose
,
223 /* read */ isdnbchanread
,
224 /* write */ isdnbchanwrite
,
225 /* ioctl */ isdnbchanioctl
,
226 /* poll */ POLLFIELD
,
228 /* strategy */ nostrategy
,
229 /* name */ "isdnbchan",
230 /* maj */ CDEV_MAJOR
,
237 static struct cdevsw isdnbchan_cdevsw
= {
238 isdnbchanopen
, isdnbchanclose
, isdnbchanread
, isdnbchanwrite
,
239 isdnbchanioctl
, nostop
, noreset
, nodevtotty
,
240 POLLFIELD
, nommap
, NULL
, "isdnbchan", NULL
, -1
244 static void isdnbchanattach(void *);
245 PSEUDO_SET(isdnbchanattach
, i4b_rbch
);
247 /*===========================================================================*
248 * DEVICE DRIVER ROUTINES
249 *===========================================================================*/
251 /*---------------------------------------------------------------------------*
252 * initialization at kernel load time
253 *---------------------------------------------------------------------------*/
255 isdnbchaninit(void *unused
)
257 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
258 cdevsw_add(&isdnbchan_cdevsw
);
260 dev_t dev
= makedev(CDEV_MAJOR
, 0);
261 cdevsw_add(&dev
, &isdnbchan_cdevsw
, NULL
);
265 SYSINIT(isdnbchandev
, SI_SUB_DRIVERS
,
266 SI_ORDER_MIDDLE
+CDEV_MAJOR
, &isdnbchaninit
, NULL
);
268 #endif /* BSD > 199306 && defined(__FreeBSD__) */
271 int isdnbchanmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
);
272 void dummy_isdnbchanattach(struct device
*, struct device
*, void *);
274 #define CDEV_MAJOR 61
276 static struct cfdriver isdnbchancd
=
277 { NULL
, "isdnbchan", isdnbchanmatch
, dummy_isdnbchanattach
, DV_DULL
,
278 sizeof(struct cfdriver
) };
279 struct devsw isdnbchansw
=
281 isdnbchanopen
, isdnbchanclose
, isdnbchanread
, isdnbchanwrite
,
282 isdnbchanioctl
, seltrue
, nommap
, nostrat
,
283 nodump
, nopsize
, 0, nostop
287 isdnbchanmatch(struct device
*parent
, struct cfdata
*cf
, void *aux
)
289 printf("isdnbchanmatch: aux=0x%x\n", aux
);
293 dummy_isdnbchanattach(struct device
*parent
, struct device
*self
, void *aux
)
295 printf("dummy_isdnbchanattach: aux=0x%x\n", aux
);
297 #endif /* __bsdi__ */
300 static const struct isdn_l4_driver_functions
301 rbch_driver_functions
= {
314 static int rbch_driver_id
= -1;
316 /*---------------------------------------------------------------------------*
317 * interface attach routine
318 *---------------------------------------------------------------------------*/
321 isdnbchanattach(void *dummy
)
323 isdnbchanattach(void)
328 rbch_driver_id
= isdn_l4_driver_attach("isdnbchan", NISDNBCHAN
, &rbch_driver_functions
);
330 for(i
=0; i
< NISDNBCHAN
; i
++)
332 #if defined(__FreeBSD__)
336 rbch_softc
[i
].devfs_token
=
337 devfs_add_devswf(&isdnbchan_cdevsw
, i
, DV_CHR
,
338 UID_ROOT
, GID_WHEEL
, 0600,
343 make_dev(&isdnbchan_cdevsw
, i
,
344 UID_ROOT
, GID_WHEEL
, 0600, "isdnbchan%d", i
);
349 #if defined(__FreeBSD__)
350 callout_handle_init(&rbch_softc
[i
].sc_callout
);
352 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
353 callout_init(&rbch_softc
[i
].sc_callout
, 0);
354 selinit(&rbch_softc
[i
].selp
);
356 rbch_softc
[i
].sc_fn
= 1;
358 rbch_softc
[i
].sc_unit
= i
;
359 rbch_softc
[i
].sc_devstate
= ST_IDLE
;
360 rbch_softc
[i
].sc_hdlcq
.ifq_maxlen
= I4BRBCHMAXQLEN
;
361 rbch_softc
[i
].it_in
.c_ispeed
= rbch_softc
[i
].it_in
.c_ospeed
= 64000;
362 termioschars(&rbch_softc
[i
].it_in
);
366 /*---------------------------------------------------------------------------*
368 *---------------------------------------------------------------------------*/
370 isdnbchanopen(dev_t dev
, int flag
, int fmt
,
373 int unit
= minor(dev
);
375 if(unit
>= NISDNBCHAN
)
378 if(rbch_softc
[unit
].sc_devstate
& ST_ISOPEN
)
385 rbch_softc
[unit
].sc_devstate
|= ST_ISOPEN
;
387 NDBGL4(L4_RBCHDBG
, "unit %d, open", unit
);
392 /*---------------------------------------------------------------------------*
394 *---------------------------------------------------------------------------*/
396 isdnbchanclose(dev_t dev
, int flag
, int fmt
,
399 int unit
= minor(dev
);
400 struct rbch_softc
*sc
= &rbch_softc
[unit
];
402 if(sc
->sc_devstate
& ST_CONNECTED
)
403 i4b_l4_drvrdisc(sc
->sc_cd
->cdid
);
405 sc
->sc_devstate
&= ~ST_ISOPEN
;
409 NDBGL4(L4_RBCHDBG
, "channel %d, closed", unit
);
414 /*---------------------------------------------------------------------------*
415 * read from rbch device
416 *---------------------------------------------------------------------------*/
418 isdnbchanread(dev_t dev
, struct uio
*uio
, int ioflag
)
422 int unit
= minor(dev
);
424 struct rbch_softc
*sc
= &rbch_softc
[unit
];
428 NDBGL4(L4_RBCHDBG
, "unit %d, enter read", unit
);
431 if(!(sc
->sc_devstate
& ST_ISOPEN
))
434 NDBGL4(L4_RBCHDBG
, "unit %d, read while not open", unit
);
438 if((sc
->sc_devstate
& ST_NOBLOCK
))
440 if(!(sc
->sc_devstate
& ST_CONNECTED
)) {
445 if(sc
->sc_bprot
== BPROT_RHDLC
)
448 iqp
= sc
->sc_ilt
->rx_queue
;
450 if(IF_QEMPTY(iqp
) && (sc
->sc_devstate
& ST_ISOPEN
)) {
457 while(!(sc
->sc_devstate
& ST_CONNECTED
))
459 NDBGL4(L4_RBCHDBG
, "unit %d, wait read init", unit
);
461 if((error
= tsleep((void *) &rbch_softc
[unit
],
466 NDBGL4(L4_RBCHDBG
, "unit %d, error %d tsleep", unit
, error
);
471 if(sc
->sc_bprot
== BPROT_RHDLC
)
474 iqp
= sc
->sc_ilt
->rx_queue
;
476 while(IF_QEMPTY(iqp
) && (sc
->sc_devstate
& ST_ISOPEN
))
478 sc
->sc_devstate
|= ST_RDWAITDATA
;
480 NDBGL4(L4_RBCHDBG
, "unit %d, wait read data", unit
);
482 if((error
= tsleep((void *) &sc
->sc_ilt
->rx_queue
,
487 NDBGL4(L4_RBCHDBG
, "unit %d, error %d tsleep read", unit
, error
);
488 sc
->sc_devstate
&= ~ST_RDWAITDATA
;
490 } else if (!(sc
->sc_devstate
& ST_CONNECTED
)) {
499 NDBGL4(L4_RBCHDBG
, "unit %d, read %d bytes", unit
, m
->m_len
);
503 error
= uiomove(m
->m_data
, m
->m_len
, uio
);
507 NDBGL4(L4_RBCHDBG
, "unit %d, error %d uiomove", unit
, error
);
519 /*---------------------------------------------------------------------------*
520 * write to rbch device
521 *---------------------------------------------------------------------------*/
523 isdnbchanwrite(dev_t dev
, struct uio
* uio
, int ioflag
)
527 int unit
= minor(dev
);
528 struct rbch_softc
*sc
= &rbch_softc
[unit
];
532 NDBGL4(L4_RBCHDBG
, "unit %d, write", unit
);
535 if(!(sc
->sc_devstate
& ST_ISOPEN
))
537 NDBGL4(L4_RBCHDBG
, "unit %d, write while not open", unit
);
542 if((sc
->sc_devstate
& ST_NOBLOCK
))
544 if(!(sc
->sc_devstate
& ST_CONNECTED
)) {
548 if(IF_QFULL(sc
->sc_ilt
->tx_queue
) && (sc
->sc_devstate
& ST_ISOPEN
)) {
555 while(!(sc
->sc_devstate
& ST_CONNECTED
))
557 NDBGL4(L4_RBCHDBG
, "unit %d, write wait init", unit
);
559 error
= tsleep((void *) &rbch_softc
[unit
],
562 if(error
== ERESTART
) {
566 else if(error
== EINTR
)
569 NDBGL4(L4_RBCHDBG
, "unit %d, EINTR during wait init", unit
);
575 NDBGL4(L4_RBCHDBG
, "unit %d, error %d tsleep init", unit
, error
);
578 tsleep((void *) &rbch_softc
[unit
], TTIPRI
| PCATCH
, "xrbch", (hz
*1));
581 while(IF_QFULL(sc
->sc_ilt
->tx_queue
) && (sc
->sc_devstate
& ST_ISOPEN
))
583 sc
->sc_devstate
|= ST_WRWAITEMPTY
;
585 NDBGL4(L4_RBCHDBG
, "unit %d, write queue full", unit
);
587 if ((error
= tsleep((void *) &sc
->sc_ilt
->tx_queue
,
590 sc
->sc_devstate
&= ~ST_WRWAITEMPTY
;
591 if(error
== ERESTART
)
596 else if(error
== EINTR
)
599 NDBGL4(L4_RBCHDBG
, "unit %d, EINTR during wait write", unit
);
605 NDBGL4(L4_RBCHDBG
, "unit %d, error %d tsleep write", unit
, error
);
608 else if (!(sc
->sc_devstate
& ST_CONNECTED
)) {
616 if(!(sc
->sc_devstate
& ST_ISOPEN
))
618 NDBGL4(L4_RBCHDBG
, "unit %d, not open anymore", unit
);
623 if((m
= i4b_Bgetmbuf(BCH_MAX_DATALEN
)) != NULL
)
625 m
->m_len
= min(BCH_MAX_DATALEN
, uio
->uio_resid
);
627 NDBGL4(L4_RBCHDBG
, "unit %d, write %d bytes", unit
, m
->m_len
);
629 error
= uiomove(m
->m_data
, m
->m_len
, uio
);
631 if(IF_QFULL(sc
->sc_ilt
->tx_queue
))
637 IF_ENQUEUE(sc
->sc_ilt
->tx_queue
, m
);
640 (*sc
->sc_ilt
->bchannel_driver
->bch_tx_start
)(sc
->sc_ilt
->l1token
, sc
->sc_ilt
->channel
);
648 /*---------------------------------------------------------------------------*
649 * rbch device ioctl handlibg
650 *---------------------------------------------------------------------------*/
652 isdnbchanioctl(dev_t dev
, IOCTL_CMD_T cmd
, void *data
, int flag
,
656 int unit
= minor(dev
);
657 struct rbch_softc
*sc
= &rbch_softc
[unit
];
661 case FIOASYNC
: /* Set async mode */
664 NDBGL4(L4_RBCHDBG
, "unit %d, setting async mode", unit
);
668 NDBGL4(L4_RBCHDBG
, "unit %d, clearing async mode", unit
);
675 NDBGL4(L4_RBCHDBG
, "unit %d, setting non-blocking mode", unit
);
676 sc
->sc_devstate
|= ST_NOBLOCK
;
680 NDBGL4(L4_RBCHDBG
, "unit %d, clearing non-blocking mode", unit
);
681 sc
->sc_devstate
&= ~ST_NOBLOCK
;
685 case TIOCCDTR
: /* Clear DTR */
686 if(sc
->sc_devstate
& ST_CONNECTED
)
688 NDBGL4(L4_RBCHDBG
, "unit %d, disconnecting for DTR down", unit
);
689 i4b_l4_drvrdisc(sc
->sc_cd
->cdid
);
693 case I4B_RBCH_DIALOUT
:
697 for (x
= 0; x
< TELNO_MAX
&& ((char *)data
)[x
]; x
++)
701 NDBGL4(L4_RBCHDBG
, "%d, attempting dialout to %s", unit
, (char *)data
);
702 i4b_l4_dialoutnumber(rbch_driver_id
, unit
, x
, (char *)data
);
705 /* fall through to SDTR */
708 case TIOCSDTR
: /* Set DTR */
709 NDBGL4(L4_RBCHDBG
, "unit %d, attempting dialout (DTR)", unit
);
710 i4b_l4_dialout(rbch_driver_id
, unit
);
713 case TIOCSETA
: /* Set termios struct */
716 case TIOCGETA
: /* Get termios struct */
717 *(struct termios
*)data
= sc
->it_in
;
721 *(int *)data
= TIOCM_LE
|TIOCM_DTR
|TIOCM_RTS
|TIOCM_CTS
|TIOCM_DSR
;
722 if (sc
->sc_devstate
& ST_CONNECTED
)
723 *(int *)data
|= TIOCM_CD
;
726 case I4B_RBCH_VR_REQ
:
730 mvr
= (msg_vr_req_t
*)data
;
732 mvr
->version
= VERSION
;
738 default: /* Unknown stuff */
739 NDBGL4(L4_RBCHDBG
, "(minor=%d) ioctl, unknown cmd %lx", unit
, (u_long
)cmd
);
748 /*---------------------------------------------------------------------------*
750 *---------------------------------------------------------------------------*/
752 isdnbchanpoll(dev_t dev
, int events
, struct lwp
*l
)
754 int revents
= 0; /* Events we found */
756 int unit
= minor(dev
);
757 struct rbch_softc
*sc
= &rbch_softc
[unit
];
759 /* We can't check for anything but IN or OUT */
763 if(!(sc
->sc_devstate
& ST_ISOPEN
))
770 * Writes are OK if we are connected and the
771 * transmit queue can take them
774 if((events
& (POLLOUT
|POLLWRNORM
)) &&
775 (sc
->sc_devstate
& ST_CONNECTED
) &&
776 !IF_QFULL(sc
->sc_ilt
->tx_queue
))
778 revents
|= (events
& (POLLOUT
|POLLWRNORM
));
781 /* ... while reads are OK if we have any data */
783 if((events
& (POLLIN
|POLLRDNORM
)) &&
784 (sc
->sc_devstate
& ST_CONNECTED
))
788 if(sc
->sc_bprot
== BPROT_RHDLC
)
791 iqp
= sc
->sc_ilt
->rx_queue
;
794 revents
|= (events
& (POLLIN
|POLLRDNORM
));
798 selrecord(l
, &sc
->selp
);
805 filt_i4brbchdetach(struct knote
*kn
)
807 struct rbch_softc
*sc
= kn
->kn_hook
;
811 SLIST_REMOVE(&sc
->selp
.sel_klist
, kn
, knote
, kn_selnext
);
816 filt_i4brbchread(struct knote
*kn
, long hint
)
818 struct rbch_softc
*sc
= kn
->kn_hook
;
821 if ((sc
->sc_devstate
& ST_CONNECTED
) == 0)
824 if (sc
->sc_bprot
== BPROT_RHDLC
)
827 iqp
= sc
->sc_ilt
->rx_queue
;
832 kn
->kn_data
= 0; /* XXXLUKEM (thorpej): what to put here? */
836 static const struct filterops i4brbchread_filtops
=
837 { 1, NULL
, filt_i4brbchdetach
, filt_i4brbchread
};
840 filt_i4brbchwrite(struct knote
*kn
, long hint
)
842 struct rbch_softc
*sc
= kn
->kn_hook
;
844 if ((sc
->sc_devstate
& ST_CONNECTED
) == 0)
847 if (IF_QFULL(sc
->sc_ilt
->tx_queue
))
850 kn
->kn_data
= 0; /* XXXLUKEM (thorpej): what to put here? */
854 static const struct filterops i4brbchwrite_filtops
=
855 { 1, NULL
, filt_i4brbchdetach
, filt_i4brbchwrite
};
858 isdnbchankqfilter(dev_t dev
, struct knote
*kn
)
860 struct rbch_softc
*sc
= &rbch_softc
[minor(dev
)];
864 switch (kn
->kn_filter
) {
866 klist
= &sc
->selp
.sel_klist
;
867 kn
->kn_fop
= &i4brbchread_filtops
;
871 klist
= &sc
->selp
.sel_klist
;
872 kn
->kn_fop
= &i4brbchwrite_filtops
;
882 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
888 #else /* OS_USES_POLL */
890 /*---------------------------------------------------------------------------*
891 * device driver select
892 *---------------------------------------------------------------------------*/
894 isdnbchanselect(dev_t dev
, int rw
, struct lwp
*l
)
896 int unit
= minor(dev
);
897 struct rbch_softc
*sc
= &rbch_softc
[unit
];
902 if(!(sc
->sc_devstate
& ST_ISOPEN
))
905 NDBGL4(L4_RBCHDBG
, "(minor=%d) not open anymore", unit
);
909 if(sc
->sc_devstate
& ST_CONNECTED
)
916 if(sc
->sc_bprot
== BPROT_RHDLC
)
919 iqp
= isdn_linktab
[unit
]->rx_queue
;
929 if(!IF_QFULL(isdn_linktab
[unit
]->rx_queue
))
941 selrecord(l
, &sc
->selp
);
946 #endif /* OS_USES_POLL */
949 /*---------------------------------------------------------------------------*
951 *---------------------------------------------------------------------------*/
953 rbch_timeout(struct rbch_softc
*sc
)
955 bchan_statistics_t bs
;
957 /* get # of bytes in and out from the HSCX driver */
959 (*sc
->sc_ilt
->bchannel_driver
->bch_stat
)
960 (sc
->sc_ilt
->l1token
, sc
->sc_ilt
->channel
, &bs
);
962 sc
->sc_ioutb
+= bs
.outbytes
;
963 sc
->sc_iinb
+= bs
.inbytes
;
965 if((sc
->sc_iinb
!= sc
->sc_linb
) || (sc
->sc_ioutb
!= sc
->sc_loutb
) || sc
->sc_fn
)
967 int ri
= (sc
->sc_iinb
- sc
->sc_linb
)/I4BRBCHACCTINTVL
;
968 int ro
= (sc
->sc_ioutb
- sc
->sc_loutb
)/I4BRBCHACCTINTVL
;
970 if((sc
->sc_iinb
== sc
->sc_linb
) && (sc
->sc_ioutb
== sc
->sc_loutb
))
975 sc
->sc_linb
= sc
->sc_iinb
;
976 sc
->sc_loutb
= sc
->sc_ioutb
;
979 i4b_l4_accounting(sc
->sc_cd
->cdid
, ACCT_DURING
,
980 sc
->sc_ioutb
, sc
->sc_iinb
, ro
, ri
, sc
->sc_ioutb
, sc
->sc_iinb
);
982 START_TIMER(sc
->sc_callout
, rbch_timeout
, sc
, I4BRBCHACCTINTVL
*hz
);
984 #endif /* I4BRBCHACCT */
986 /*===========================================================================*
987 * ISDN INTERFACE ROUTINES
988 *===========================================================================*/
990 /*---------------------------------------------------------------------------*
991 * this routine is called from L4 handler at connect time
992 *---------------------------------------------------------------------------*/
994 rbch_connect(void *softc
, void *cdp
)
996 call_desc_t
*cd
= (call_desc_t
*)cdp
;
997 struct rbch_softc
*sc
= softc
;
999 sc
->sc_bprot
= cd
->bprot
;
1002 if(sc
->sc_bprot
== BPROT_RHDLC
)
1009 START_TIMER(sc
->sc_callout
, rbch_timeout
, sc
, I4BRBCHACCTINTVL
*hz
);
1012 if(!(sc
->sc_devstate
& ST_CONNECTED
))
1014 NDBGL4(L4_RBCHDBG
, "B channel %d at ISDN %d, wakeup",
1015 cd
->channelid
, cd
->isdnif
);
1016 sc
->sc_devstate
|= ST_CONNECTED
;
1019 selnotify(&sc
->selp
, 0, 0);
1023 /*---------------------------------------------------------------------------*
1024 * this routine is called from L4 handler at disconnect time
1025 *---------------------------------------------------------------------------*/
1027 rbch_disconnect(void *softc
, void *cdp
)
1029 call_desc_t
*cd
= cdp
;
1030 struct rbch_softc
*sc
= softc
;
1036 NDBGL4(L4_RBCHDBG
, "B channel %d at ISDN %d not active",
1037 cd
->channelid
, cd
->isdnif
);
1043 NDBGL4(L4_RBCHDBG
, "B channel %d at ISDN %d disconnect",
1044 cd
->channelid
, cd
->isdnif
);
1046 sc
->sc_devstate
&= ~ST_CONNECTED
;
1050 i4b_l4_accounting(sc
->sc_cd
->cdid
, ACCT_FINAL
,
1051 sc
->sc_ioutb
, sc
->sc_iinb
, 0, 0, sc
->sc_ioutb
, sc
->sc_iinb
);
1053 STOP_TIMER(sc
->sc_callout
, rbch_timeout
, sc
);
1057 if (sc
->sc_devstate
& ST_RDWAITDATA
)
1058 wakeup(&sc
->sc_ilt
->rx_queue
);
1059 if (sc
->sc_devstate
& ST_WRWAITEMPTY
)
1060 wakeup(&sc
->sc_ilt
->tx_queue
);
1064 selnotify(&sc
->selp
, 0, 0);
1067 /*---------------------------------------------------------------------------*
1068 * feedback from daemon in case of dial problems
1069 *---------------------------------------------------------------------------*/
1071 rbch_dialresponse(void *softc
, int status
,
1076 /*---------------------------------------------------------------------------*
1078 *---------------------------------------------------------------------------*/
1080 rbch_updown(void *softc
, int updown
)
1084 /*---------------------------------------------------------------------------*
1085 * this routine is called from the HSCX interrupt handler
1086 * when a new frame (mbuf) has been received and is to be put on
1088 *---------------------------------------------------------------------------*/
1090 rbch_rx_data_rdy(void *softc
)
1092 struct rbch_softc
*sc
= softc
;
1094 if(sc
->sc_bprot
== BPROT_RHDLC
)
1096 register struct mbuf
*m
;
1098 if((m
= *sc
->sc_ilt
->rx_mbuf
) == NULL
)
1101 m
->m_pkthdr
.len
= m
->m_len
;
1103 if(IF_QFULL(&sc
->sc_hdlcq
))
1105 NDBGL4(L4_RBCHDBG
, "(minor=%d) hdlc rx queue full!", sc
->sc_unit
);
1110 IF_ENQUEUE(&sc
->sc_hdlcq
, m
);
1114 if(sc
->sc_devstate
& ST_RDWAITDATA
)
1116 NDBGL4(L4_RBCHDBG
, "(minor=%d) wakeup", sc
->sc_unit
);
1117 sc
->sc_devstate
&= ~ST_RDWAITDATA
;
1118 wakeup((void *) &sc
->sc_ilt
->rx_queue
);
1122 NDBGL4(L4_RBCHDBG
, "(minor=%d) NO wakeup", sc
->sc_unit
);
1124 selnotify(&sc
->selp
, 0, 0);
1127 /*---------------------------------------------------------------------------*
1128 * this routine is called from the HSCX interrupt handler
1129 * when the last frame has been sent out and there is no
1130 * further frame (mbuf) in the tx queue.
1131 *---------------------------------------------------------------------------*/
1133 rbch_tx_queue_empty(void *softc
)
1135 struct rbch_softc
*sc
= softc
;
1137 if(sc
->sc_devstate
& ST_WRWAITEMPTY
)
1139 NDBGL4(L4_RBCHDBG
, "(minor=%d): wakeup", sc
->sc_unit
);
1140 sc
->sc_devstate
&= ~ST_WRWAITEMPTY
;
1141 wakeup((void *) &sc
->sc_ilt
->tx_queue
);
1145 NDBGL4(L4_RBCHDBG
, "(minor=%d) NO wakeup", sc
->sc_unit
);
1147 selnotify(&sc
->selp
, 0, 0);
1150 /*---------------------------------------------------------------------------*
1151 * this routine is called from the HSCX interrupt handler
1152 * each time a packet is received or transmitted
1153 *---------------------------------------------------------------------------*/
1155 rbch_activity(void *softc
, int rxtx
)
1157 struct rbch_softc
*sc
= softc
;
1160 sc
->sc_cd
->last_active_time
= SECOND
;
1161 selnotify(&sc
->selp
, 0, 0);
1164 /*---------------------------------------------------------------------------*
1165 * clear an hdlc rx queue for a rbch unit
1166 *---------------------------------------------------------------------------*/
1168 rbch_clrq(void *softc
)
1170 struct rbch_softc
*sc
= softc
;
1177 IF_DEQUEUE(&sc
->sc_hdlcq
, m
);
1187 /*---------------------------------------------------------------------------*
1188 * setup the isdn_linktab for this driver
1189 *---------------------------------------------------------------------------*/
1191 rbch_set_linktab(void *softc
, isdn_link_t
*ilt
)
1193 struct rbch_softc
*sc
= softc
;
1197 /*---------------------------------------------------------------------------*
1198 * initialize this drivers linktab
1199 *---------------------------------------------------------------------------*/
1201 rbch_get_softc(int unit
)
1203 return &rbch_softc
[unit
];
1206 /*===========================================================================*/
1208 #endif /* NISDNBCHAN > 0 */