2 * Copyright (c) 1997, 2001 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 * $FreeBSD: src/sys/i4b/layer4/i4b_i4bdrv.c,v 1.11.2.5 2001/12/16 15:12:59 hm Exp $
31 * $DragonFly: src/sys/net/i4b/layer4/i4b_i4bdrv.c,v 1.20 2008/01/06 16:55:52 swildner Exp $
33 * last edit-date: [Sat Aug 11 18:08:10 2001]
35 *---------------------------------------------------------------------------*/
38 #include "use_i4bipr.h"
39 #include "use_i4btel.h"
42 #error "only 1 (one) i4b device possible!"
47 #include <sys/param.h>
49 #include <sys/ioccom.h>
50 #include <sys/malloc.h>
52 #include <sys/kernel.h>
53 #include <sys/systm.h>
55 #include <sys/device.h>
57 #include <sys/socket.h>
58 #include <sys/thread2.h>
59 #include <sys/selinfo.h>
63 #include "use_i4bing.h"
64 #include "use_i4bisppp.h"
66 #include <net/i4b/include/machine/i4b_debug.h>
67 #include <net/i4b/include/machine/i4b_ioctl.h>
68 #include <net/i4b/include/machine/i4b_cause.h>
70 #include "../include/i4b_l3l4.h"
71 #include "../include/i4b_mbuf.h"
72 #include "../include/i4b_global.h"
78 struct selinfo select_rd_info
;
80 static struct ifqueue i4b_rdqueue
;
81 static int openflag
= 0;
82 static int selflag
= 0;
83 static int readflag
= 0;
85 #define PDEVSTATIC static
87 PDEVSTATIC d_open_t i4bopen
;
88 PDEVSTATIC d_close_t i4bclose
;
89 PDEVSTATIC d_read_t i4bread
;
90 PDEVSTATIC d_ioctl_t i4bioctl
;
92 PDEVSTATIC d_poll_t i4bpoll
;
93 #define POLLFIELD i4bpoll
97 static struct dev_ops i4b_ops
= {
98 { "i4b", CDEV_MAJOR
, 0 },
106 PDEVSTATIC
void i4battach(void *);
107 PSEUDO_SET(i4battach
, i4b_i4bdrv
);
110 i4b_drvinit(void *unused
)
112 dev_ops_add(&i4b_ops
, 0, 0);
115 SYSINIT(i4bdev
,SI_SUB_DRIVERS
,SI_ORDER_MIDDLE
+CDEV_MAJOR
,i4b_drvinit
,NULL
)
117 /*---------------------------------------------------------------------------*
118 * interface attach routine
119 *---------------------------------------------------------------------------*/
121 i4battach(void *dummy
)
123 kprintf("i4b: ISDN call control device attached\n");
125 i4b_rdqueue
.ifq_maxlen
= IFQ_MAXLEN
;
127 make_dev(&i4b_ops
, 0, UID_ROOT
, GID_WHEEL
, 0600, "i4b");
130 /*---------------------------------------------------------------------------*
131 * i4bopen - device driver open routine
132 *---------------------------------------------------------------------------*/
134 i4bopen(struct dev_open_args
*ap
)
136 cdev_t dev
= ap
->a_head
.a_dev
;
144 i4b_l4_daemon_attached();
150 /*---------------------------------------------------------------------------*
151 * i4bclose - device driver close routine
152 *---------------------------------------------------------------------------*/
154 i4bclose(struct dev_close_args
*ap
)
158 i4b_l4_daemon_detached();
159 i4b_Dcleanifq(&i4b_rdqueue
);
164 /*---------------------------------------------------------------------------*
165 * i4bread - device driver read routine
166 *---------------------------------------------------------------------------*/
168 i4bread(struct dev_read_args
*ap
)
170 cdev_t dev
= ap
->a_head
.a_dev
;
178 while(IF_QEMPTY(&i4b_rdqueue
))
181 error
= tsleep((caddr_t
) &i4b_rdqueue
, PCATCH
, "bird", 0);
188 IF_DEQUEUE(&i4b_rdqueue
, m
);
193 error
= uiomove(m
->m_data
, m
->m_len
, ap
->a_uio
);
203 /*---------------------------------------------------------------------------*
204 * i4bioctl - device driver ioctl routine
205 *---------------------------------------------------------------------------*/
207 i4bioctl(struct dev_ioctl_args
*ap
)
209 cdev_t dev
= ap
->a_head
.a_dev
;
210 caddr_t data
= ap
->a_data
;
219 /* cdid request, reserve cd and return cdid */
224 mir
= (msg_cdid_req_t
*)data
;
226 mir
->cdid
= cd
->cdid
;
230 /* connect request, dial out to remote */
232 case I4B_CONNECT_REQ
:
234 msg_connect_req_t
*mcr
;
235 mcr
= (msg_connect_req_t
*)data
; /* setup ptr */
237 if((cd
= cd_by_cdid(mcr
->cdid
)) == NULL
)/* get cd */
239 NDBGL4(L4_ERR
, "I4B_CONNECT_REQ ioctl, cdid not found!");
244 /* prevent dialling on leased lines */
245 if(ctrl_desc
[mcr
->controller
].protocol
== PROTOCOL_D64S
)
247 SET_CAUSE_TYPE(cd
->cause_in
, CAUSET_I4B
);
248 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_LLDIAL
);
249 i4b_l4_disconnect_ind(cd
);
254 cd
->controller
= mcr
->controller
; /* fill cd */
255 cd
->bprot
= mcr
->bprot
;
256 cd
->driver
= mcr
->driver
;
257 cd
->driver_unit
= mcr
->driver_unit
;
258 cd
->cr
= get_rand_cr(ctrl_desc
[cd
->controller
].unit
);
260 cd
->shorthold_data
.shorthold_algorithm
= mcr
->shorthold_data
.shorthold_algorithm
;
261 cd
->shorthold_data
.unitlen_time
= mcr
->shorthold_data
.unitlen_time
;
262 cd
->shorthold_data
.idle_time
= mcr
->shorthold_data
.idle_time
;
263 cd
->shorthold_data
.earlyhup_time
= mcr
->shorthold_data
.earlyhup_time
;
265 cd
->last_aocd_time
= 0;
266 if(mcr
->unitlen_method
== ULEN_METHOD_DYNAMIC
)
273 cd
->max_idle_time
= 0; /* this is outgoing */
275 cd
->dir
= DIR_OUTGOING
;
277 NDBGL4(L4_TIMO
, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
278 (long)cd
->shorthold_data
.shorthold_algorithm
, (long)cd
->shorthold_data
.unitlen_time
,
279 (long)cd
->shorthold_data
.idle_time
, (long)cd
->shorthold_data
.earlyhup_time
);
281 strcpy(cd
->dst_telno
, mcr
->dst_telno
);
282 strcpy(cd
->src_telno
, mcr
->src_telno
);
284 if(mcr
->keypad
[0] != '\0')
285 strcpy(cd
->keypad
, mcr
->keypad
);
287 cd
->keypad
[0] = '\0';
289 cd
->display
[0] = '\0';
291 SET_CAUSE_TYPE(cd
->cause_in
, CAUSET_I4B
);
292 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NORMAL
);
298 if(ctrl_desc
[mcr
->controller
].bch_state
[mcr
->channel
] != BCH_ST_FREE
)
299 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NOCHAN
);
306 i
< ctrl_desc
[mcr
->controller
].nbch
&&
307 ctrl_desc
[mcr
->controller
].bch_state
[i
] != BCH_ST_FREE
;
309 if (i
== ctrl_desc
[mcr
->controller
].nbch
)
310 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NOCHAN
);
311 /* else mcr->channel = i; XXX */
316 SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NOCHAN
);
320 cd
->channelid
= mcr
->channel
;
322 cd
->isdntxdelay
= mcr
->txdelay
;
324 /* check whether we have a pointer. Seems like */
325 /* this should be adequate. GJ 19.09.97 */
326 if(ctrl_desc
[cd
->controller
].N_CONNECT_REQUEST
== NULL
)
327 /*XXX*/ SET_CAUSE_VAL(cd
->cause_in
, CAUSE_I4B_NOCHAN
);
329 if((GET_CAUSE_VAL(cd
->cause_in
)) != CAUSE_I4B_NORMAL
)
331 i4b_l4_disconnect_ind(cd
);
336 (*ctrl_desc
[cd
->controller
].N_CONNECT_REQUEST
)(mcr
->cdid
);
341 /* connect response, accept/reject/ignore incoming call */
343 case I4B_CONNECT_RESP
:
345 msg_connect_resp_t
*mcrsp
;
347 mcrsp
= (msg_connect_resp_t
*)data
;
349 if((cd
= cd_by_cdid(mcrsp
->cdid
)) == NULL
)/* get cd */
351 NDBGL4(L4_ERR
, "I4B_CONNECT_RESP ioctl, cdid not found!");
358 cd
->driver
= mcrsp
->driver
;
359 cd
->driver_unit
= mcrsp
->driver_unit
;
360 cd
->max_idle_time
= mcrsp
->max_idle_time
;
362 cd
->shorthold_data
.shorthold_algorithm
= SHA_FIXU
;
363 cd
->shorthold_data
.unitlen_time
= 0; /* this is incoming */
364 cd
->shorthold_data
.idle_time
= 0;
365 cd
->shorthold_data
.earlyhup_time
= 0;
367 cd
->isdntxdelay
= mcrsp
->txdelay
;
369 NDBGL4(L4_TIMO
, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd
->max_idle_time
);
371 (*ctrl_desc
[cd
->controller
].N_CONNECT_RESPONSE
)(mcrsp
->cdid
, mcrsp
->response
, mcrsp
->cause
);
375 /* disconnect request, actively terminate connection */
377 case I4B_DISCONNECT_REQ
:
379 msg_discon_req_t
*mdr
;
381 mdr
= (msg_discon_req_t
*)data
;
383 if((cd
= cd_by_cdid(mdr
->cdid
)) == NULL
)/* get cd */
385 NDBGL4(L4_ERR
, "I4B_DISCONNECT_REQ ioctl, cdid not found!");
390 /* preset causes with our cause */
391 cd
->cause_in
= cd
->cause_out
= mdr
->cause
;
393 (*ctrl_desc
[cd
->controller
].N_DISCONNECT_REQUEST
)(mdr
->cdid
, mdr
->cause
);
397 /* controller info request */
399 case I4B_CTRL_INFO_REQ
:
401 msg_ctrl_info_req_t
*mcir
;
403 mcir
= (msg_ctrl_info_req_t
*)data
;
404 mcir
->ncontroller
= nctrl
;
406 if(mcir
->controller
> nctrl
)
408 mcir
->ctrl_type
= -1;
409 mcir
->card_type
= -1;
414 ctrl_desc
[mcir
->controller
].ctrl_type
;
416 ctrl_desc
[mcir
->controller
].card_type
;
418 ctrl_desc
[mcir
->controller
].nbch
;
420 if(ctrl_desc
[mcir
->controller
].ctrl_type
== CTRL_PASSIVE
)
421 mcir
->tei
= ctrl_desc
[mcir
->controller
].tei
;
430 case I4B_DIALOUT_RESP
:
432 drvr_link_t
*dlt
= NULL
;
433 msg_dialout_resp_t
*mdrsp
;
435 mdrsp
= (msg_dialout_resp_t
*)data
;
437 switch(mdrsp
->driver
)
441 dlt
= ipr_ret_linktab(mdrsp
->driver_unit
);
447 dlt
= i4bisppp_ret_linktab(mdrsp
->driver_unit
);
453 dlt
= tel_ret_linktab(mdrsp
->driver_unit
);
459 dlt
= ibc_ret_linktab(mdrsp
->driver_unit
);
465 dlt
= ing_ret_linktab(mdrsp
->driver_unit
);
471 (*dlt
->dial_response
)(mdrsp
->driver_unit
, mdrsp
->stat
, mdrsp
->cause
);
475 /* update timeout value */
477 case I4B_TIMEOUT_UPD
:
479 msg_timeout_upd_t
*mtu
;
481 mtu
= (msg_timeout_upd_t
*)data
;
483 NDBGL4(L4_TIMO
, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
484 mtu
->shorthold_data
.shorthold_algorithm
, mtu
->shorthold_data
.unitlen_time
,
485 mtu
->shorthold_data
.idle_time
, mtu
->shorthold_data
.earlyhup_time
);
487 if((cd
= cd_by_cdid(mtu
->cdid
)) == NULL
)/* get cd */
489 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
494 switch( mtu
->shorthold_data
.shorthold_algorithm
)
498 * For this algorithm unitlen_time,
499 * idle_time and earlyhup_time are used.
502 if(!(mtu
->shorthold_data
.unitlen_time
>= 0 &&
503 mtu
->shorthold_data
.idle_time
>= 0 &&
504 mtu
->shorthold_data
.earlyhup_time
>= 0))
506 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
513 * For this algorithm unitlen_time and
514 * idle_time are used. both must be
515 * positive integers. earlyhup_time is
516 * not used and must be 0.
519 if(!(mtu
->shorthold_data
.unitlen_time
> 0 &&
520 mtu
->shorthold_data
.idle_time
>= 0 &&
521 mtu
->shorthold_data
.earlyhup_time
== 0))
523 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
529 NDBGL4(L4_ERR
, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
535 * any error set above requires us to break
536 * out of the outer switch
542 cd
->shorthold_data
.shorthold_algorithm
= mtu
->shorthold_data
.shorthold_algorithm
;
543 cd
->shorthold_data
.unitlen_time
= mtu
->shorthold_data
.unitlen_time
;
544 cd
->shorthold_data
.idle_time
= mtu
->shorthold_data
.idle_time
;
545 cd
->shorthold_data
.earlyhup_time
= mtu
->shorthold_data
.earlyhup_time
;
550 /* soft enable/disable interface */
554 msg_updown_ind_t
*mui
;
556 mui
= (msg_updown_ind_t
*)data
;
559 if(mui
->driver
== BDRV_IPR
)
562 dlt
= ipr_ret_linktab(mui
->driver_unit
);
563 (*dlt
->updown_ind
)(mui
->driver_unit
, mui
->updown
);
569 /* send ALERT request */
573 msg_alert_req_t
*mar
;
575 mar
= (msg_alert_req_t
*)data
;
577 if((cd
= cd_by_cdid(mar
->cdid
)) == NULL
)
579 NDBGL4(L4_ERR
, "I4B_ALERT_REQ ioctl, cdid not found!");
586 (*ctrl_desc
[cd
->controller
].N_ALERT_REQUEST
)(mar
->cdid
);
591 /* version/release number request */
597 mvr
= (msg_vr_req_t
*)data
;
599 mvr
->version
= VERSION
;
605 /* set D-channel protocol for a controller */
611 mpi
= (msg_prot_ind_t
*)data
;
613 ctrl_desc
[mpi
->controller
].protocol
= mpi
->protocol
;
618 /* Download request */
620 case I4B_CTRL_DOWNLOAD
:
622 struct isdn_dr_prot
*prots
= NULL
, *prots2
= NULL
;
623 struct isdn_download_request
*r
=
624 (struct isdn_download_request
*)data
;
627 if (r
->controller
< 0 || r
->controller
>= nctrl
)
633 if(!ctrl_desc
[r
->controller
].N_DOWNLOAD
)
639 prots
= kmalloc(r
->numprotos
* sizeof(struct isdn_dr_prot
),
642 prots2
= kmalloc(r
->numprotos
* sizeof(struct isdn_dr_prot
),
645 copyin(r
->protocols
, prots
, r
->numprotos
* sizeof(struct isdn_dr_prot
));
647 for(i
= 0; i
< r
->numprotos
; i
++)
649 prots2
[i
].microcode
= kmalloc(prots
[i
].bytecount
, M_DEVBUF
, M_WAITOK
);
650 copyin(prots
[i
].microcode
, prots2
[i
].microcode
, prots
[i
].bytecount
);
651 prots2
[i
].bytecount
= prots
[i
].bytecount
;
654 error
= ctrl_desc
[r
->controller
].N_DOWNLOAD(
655 ctrl_desc
[r
->controller
].unit
,
656 r
->numprotos
, prots2
);
661 for(i
= 0; i
< r
->numprotos
; i
++)
663 if(prots2
[i
].microcode
)
665 kfree(prots2
[i
].microcode
, M_DEVBUF
);
668 kfree(prots2
, M_DEVBUF
);
673 kfree(prots
, M_DEVBUF
);
678 /* Diagnostic request */
680 case I4B_ACTIVE_DIAGNOSTIC
:
682 struct isdn_diagnostic_request req
, *r
=
683 (struct isdn_diagnostic_request
*)data
;
685 req
.in_param
= req
.out_param
= NULL
;
686 if (r
->controller
< 0 || r
->controller
>= nctrl
)
692 if(!ctrl_desc
[r
->controller
].N_DIAGNOSTICS
)
698 memcpy(&req
, r
, sizeof(req
));
702 /* XXX arbitrary limit */
703 if (req
.in_param_len
>
704 I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN
) {
709 req
.in_param
= kmalloc(r
->in_param_len
, M_DEVBUF
, M_WAITOK
);
711 error
= copyin(r
->in_param
, req
.in_param
, req
.in_param_len
);
716 if(req
.out_param_len
)
717 req
.out_param
= kmalloc(r
->out_param_len
, M_DEVBUF
, M_WAITOK
);
719 error
= ctrl_desc
[r
->controller
].N_DIAGNOSTICS(r
->controller
, &req
);
721 if(!error
&& req
.out_param_len
)
722 error
= copyout(req
.out_param
, r
->out_param
, req
.out_param_len
);
726 kfree(req
.in_param
, M_DEVBUF
);
729 kfree(req
.out_param
, M_DEVBUF
);
744 /*---------------------------------------------------------------------------*
745 * i4bpoll - device driver poll routine
746 *---------------------------------------------------------------------------*/
748 i4bpoll(struct dev_poll_args
*ap
)
750 cdev_t dev
= ap
->a_head
.a_dev
;
758 if (ap
->a_events
& (POLLIN
|POLLRDNORM
)) {
760 if (!IF_QEMPTY(&i4b_rdqueue
)) {
761 revents
|= POLLIN
| POLLRDNORM
;
763 selrecord(curthread
, &select_rd_info
);
769 if (ap
->a_events
& (POLLOUT
|POLLWRNORM
)) {
770 revents
|= ap
->a_events
& (POLLOUT
| POLLWRNORM
);
772 ap
->a_events
= revents
;
776 /*---------------------------------------------------------------------------*
777 * i4bputqueue - put message into queue to userland
778 *---------------------------------------------------------------------------*/
780 i4bputqueue(struct mbuf
*m
)
790 if(IF_QFULL(&i4b_rdqueue
))
793 IF_DEQUEUE(&i4b_rdqueue
, m1
);
795 NDBGL4(L4_ERR
, "ERROR, queue full, removing entry!");
798 IF_ENQUEUE(&i4b_rdqueue
, m
);
805 wakeup((caddr_t
) &i4b_rdqueue
);
811 selwakeup(&select_rd_info
);
815 /*---------------------------------------------------------------------------*
816 * i4bputqueue_hipri - put message into front of queue to userland
817 *---------------------------------------------------------------------------*/
819 i4bputqueue_hipri(struct mbuf
*m
)
829 if(IF_QFULL(&i4b_rdqueue
))
832 IF_DEQUEUE(&i4b_rdqueue
, m1
);
834 NDBGL4(L4_ERR
, "ERROR, queue full, removing entry!");
837 IF_PREPEND(&i4b_rdqueue
, m
);
844 wakeup((caddr_t
) &i4b_rdqueue
);
850 selwakeup(&select_rd_info
);
854 #endif /* NI4B > 0 */