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/malloc.h>
51 #include <sys/kernel.h>
52 #include <sys/systm.h>
54 #include <sys/device.h>
56 #include <sys/socket.h>
57 #include <sys/thread2.h>
58 #include <sys/selinfo.h>
62 #include "use_i4bing.h"
63 #include "use_i4bisppp.h"
65 #include <net/i4b/include/machine/i4b_debug.h>
66 #include <net/i4b/include/machine/i4b_ioctl.h>
67 #include <net/i4b/include/machine/i4b_cause.h>
69 #include "../include/i4b_l3l4.h"
70 #include "../include/i4b_mbuf.h"
71 #include "../include/i4b_global.h"
76 #include <sys/event.h>
78 struct selinfo select_rd_info;
80 static struct ifqueue i4b_rdqueue;
81 static int openflag = 0;
82 static int readflag = 0;
84 #define PDEVSTATIC static
86 PDEVSTATIC d_open_t i4bopen;
87 PDEVSTATIC d_close_t i4bclose;
88 PDEVSTATIC d_read_t i4bread;
89 PDEVSTATIC d_ioctl_t i4bioctl;
90 PDEVSTATIC d_kqfilter_t i4bkqfilter;
92 PDEVSTATIC void i4bkqfilt_detach(struct knote *);
93 PDEVSTATIC int i4bkqfilt_read(struct knote *, long);
94 PDEVSTATIC int i4bkqfilt_write(struct knote *, long);
96 PDEVSTATIC d_poll_t i4bpoll;
97 #define POLLFIELD i4bpoll
101 static struct dev_ops i4b_ops = {
102 { "i4b", CDEV_MAJOR, D_KQFILTER },
108 .d_kqfilter = i4bkqfilter
111 PDEVSTATIC void i4battach(void *);
112 PSEUDO_SET(i4battach, i4b_i4bdrv);
114 /*---------------------------------------------------------------------------*
115 * interface attach routine
116 *---------------------------------------------------------------------------*/
118 i4battach(void *dummy)
120 kprintf("i4b: ISDN call control device attached\n");
122 i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
124 make_dev(&i4b_ops, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
127 /*---------------------------------------------------------------------------*
128 * i4bopen - device driver open routine
129 *---------------------------------------------------------------------------*/
131 i4bopen(struct dev_open_args *ap)
133 cdev_t dev = ap->a_head.a_dev;
141 i4b_l4_daemon_attached();
147 /*---------------------------------------------------------------------------*
148 * i4bclose - device driver close routine
149 *---------------------------------------------------------------------------*/
151 i4bclose(struct dev_close_args *ap)
155 i4b_l4_daemon_detached();
156 i4b_Dcleanifq(&i4b_rdqueue);
161 /*---------------------------------------------------------------------------*
162 * i4bread - device driver read routine
163 *---------------------------------------------------------------------------*/
165 i4bread(struct dev_read_args *ap)
167 cdev_t dev = ap->a_head.a_dev;
175 while(IF_QEMPTY(&i4b_rdqueue))
178 error = tsleep((caddr_t) &i4b_rdqueue, PCATCH, "bird", 0);
185 IF_DEQUEUE(&i4b_rdqueue, m);
190 error = uiomove(m->m_data, m->m_len, ap->a_uio);
200 /*---------------------------------------------------------------------------*
201 * i4bioctl - device driver ioctl routine
202 *---------------------------------------------------------------------------*/
204 i4bioctl(struct dev_ioctl_args *ap)
206 cdev_t dev = ap->a_head.a_dev;
207 caddr_t data = ap->a_data;
216 /* cdid request, reserve cd and return cdid */
221 mir = (msg_cdid_req_t *)data;
223 mir->cdid = cd->cdid;
227 /* connect request, dial out to remote */
229 case I4B_CONNECT_REQ:
231 msg_connect_req_t *mcr;
232 mcr = (msg_connect_req_t *)data; /* setup ptr */
234 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
236 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
241 /* prevent dialling on leased lines */
242 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
244 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
245 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
246 i4b_l4_disconnect_ind(cd);
251 cd->controller = mcr->controller; /* fill cd */
252 cd->bprot = mcr->bprot;
253 cd->driver = mcr->driver;
254 cd->driver_unit = mcr->driver_unit;
255 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
257 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
258 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
259 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
260 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
262 cd->last_aocd_time = 0;
263 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
270 cd->max_idle_time = 0; /* this is outgoing */
272 cd->dir = DIR_OUTGOING;
274 NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
275 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
276 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
278 strcpy(cd->dst_telno, mcr->dst_telno);
279 strcpy(cd->src_telno, mcr->src_telno);
281 if(mcr->keypad[0] != '\0')
282 strcpy(cd->keypad, mcr->keypad);
284 cd->keypad[0] = '\0';
286 cd->display[0] = '\0';
288 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
289 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
295 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
296 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
303 i < ctrl_desc[mcr->controller].nbch &&
304 ctrl_desc[mcr->controller].bch_state[i] != BCH_ST_FREE;
306 if (i == ctrl_desc[mcr->controller].nbch)
307 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
308 /* else mcr->channel = i; XXX */
313 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
317 cd->channelid = mcr->channel;
319 cd->isdntxdelay = mcr->txdelay;
321 /* check whether we have a pointer. Seems like */
322 /* this should be adequate. GJ 19.09.97 */
323 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
324 /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
326 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
328 i4b_l4_disconnect_ind(cd);
333 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
338 /* connect response, accept/reject/ignore incoming call */
340 case I4B_CONNECT_RESP:
342 msg_connect_resp_t *mcrsp;
344 mcrsp = (msg_connect_resp_t *)data;
346 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
348 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
355 cd->driver = mcrsp->driver;
356 cd->driver_unit = mcrsp->driver_unit;
357 cd->max_idle_time = mcrsp->max_idle_time;
359 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
360 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
361 cd->shorthold_data.idle_time = 0;
362 cd->shorthold_data.earlyhup_time = 0;
364 cd->isdntxdelay = mcrsp->txdelay;
366 NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
368 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
372 /* disconnect request, actively terminate connection */
374 case I4B_DISCONNECT_REQ:
376 msg_discon_req_t *mdr;
378 mdr = (msg_discon_req_t *)data;
380 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
382 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!");
387 /* preset causes with our cause */
388 cd->cause_in = cd->cause_out = mdr->cause;
390 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
394 /* controller info request */
396 case I4B_CTRL_INFO_REQ:
398 msg_ctrl_info_req_t *mcir;
400 mcir = (msg_ctrl_info_req_t *)data;
401 mcir->ncontroller = nctrl;
403 if(mcir->controller > nctrl)
405 mcir->ctrl_type = -1;
406 mcir->card_type = -1;
411 ctrl_desc[mcir->controller].ctrl_type;
413 ctrl_desc[mcir->controller].card_type;
415 ctrl_desc[mcir->controller].nbch;
417 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
418 mcir->tei = ctrl_desc[mcir->controller].tei;
427 case I4B_DIALOUT_RESP:
429 drvr_link_t *dlt = NULL;
430 msg_dialout_resp_t *mdrsp;
432 mdrsp = (msg_dialout_resp_t *)data;
434 switch(mdrsp->driver)
438 dlt = ipr_ret_linktab(mdrsp->driver_unit);
444 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
450 dlt = tel_ret_linktab(mdrsp->driver_unit);
456 dlt = ing_ret_linktab(mdrsp->driver_unit);
462 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
466 /* update timeout value */
468 case I4B_TIMEOUT_UPD:
470 msg_timeout_upd_t *mtu;
472 mtu = (msg_timeout_upd_t *)data;
474 NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
475 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
476 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
478 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
480 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
485 switch( mtu->shorthold_data.shorthold_algorithm )
489 * For this algorithm unitlen_time,
490 * idle_time and earlyhup_time are used.
493 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
494 mtu->shorthold_data.idle_time >= 0 &&
495 mtu->shorthold_data.earlyhup_time >= 0))
497 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
504 * For this algorithm unitlen_time and
505 * idle_time are used. both must be
506 * positive integers. earlyhup_time is
507 * not used and must be 0.
510 if(!(mtu->shorthold_data.unitlen_time > 0 &&
511 mtu->shorthold_data.idle_time >= 0 &&
512 mtu->shorthold_data.earlyhup_time == 0))
514 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
520 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
526 * any error set above requires us to break
527 * out of the outer switch
533 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
534 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
535 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
536 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
541 /* soft enable/disable interface */
545 msg_updown_ind_t *mui;
547 mui = (msg_updown_ind_t *)data;
550 if(mui->driver == BDRV_IPR)
553 dlt = ipr_ret_linktab(mui->driver_unit);
554 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
560 /* send ALERT request */
564 msg_alert_req_t *mar;
566 mar = (msg_alert_req_t *)data;
568 if((cd = cd_by_cdid(mar->cdid)) == NULL)
570 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
577 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
582 /* version/release number request */
588 mvr = (msg_vr_req_t *)data;
590 mvr->version = VERSION;
596 /* set D-channel protocol for a controller */
602 mpi = (msg_prot_ind_t *)data;
604 ctrl_desc[mpi->controller].protocol = mpi->protocol;
609 /* Download request */
611 case I4B_CTRL_DOWNLOAD:
613 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
614 struct isdn_download_request *r =
615 (struct isdn_download_request*)data;
618 if (r->controller < 0 || r->controller >= nctrl)
624 if(!ctrl_desc[r->controller].N_DOWNLOAD)
630 prots = kmalloc(r->numprotos * sizeof(struct isdn_dr_prot),
633 prots2 = kmalloc(r->numprotos * sizeof(struct isdn_dr_prot),
636 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
638 for(i = 0; i < r->numprotos; i++)
640 prots2[i].microcode = kmalloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
641 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
642 prots2[i].bytecount = prots[i].bytecount;
645 error = ctrl_desc[r->controller].N_DOWNLOAD(
646 ctrl_desc[r->controller].unit,
647 r->numprotos, prots2);
652 for(i = 0; i < r->numprotos; i++)
654 if(prots2[i].microcode)
656 kfree(prots2[i].microcode, M_DEVBUF);
659 kfree(prots2, M_DEVBUF);
664 kfree(prots, M_DEVBUF);
669 /* Diagnostic request */
671 case I4B_ACTIVE_DIAGNOSTIC:
673 struct isdn_diagnostic_request req, *r =
674 (struct isdn_diagnostic_request*)data;
676 req.in_param = req.out_param = NULL;
677 if (r->controller < 0 || r->controller >= nctrl)
683 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
689 memcpy(&req, r, sizeof(req));
693 /* XXX arbitrary limit */
694 if (req.in_param_len >
695 I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
700 req.in_param = kmalloc(r->in_param_len, M_DEVBUF, M_WAITOK);
702 error = copyin(r->in_param, req.in_param, req.in_param_len);
707 if(req.out_param_len)
708 req.out_param = kmalloc(r->out_param_len, M_DEVBUF, M_WAITOK);
710 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
712 if(!error && req.out_param_len)
713 error = copyout(req.out_param, r->out_param, req.out_param_len);
717 kfree(req.in_param, M_DEVBUF);
720 kfree(req.out_param, M_DEVBUF);
735 /*---------------------------------------------------------------------------*
736 * i4bpoll - device driver poll routine
737 *---------------------------------------------------------------------------*/
739 i4bpoll(struct dev_poll_args *ap)
741 cdev_t dev = ap->a_head.a_dev;
749 if (ap->a_events & (POLLIN|POLLRDNORM)) {
751 if (!IF_QEMPTY(&i4b_rdqueue)) {
752 revents |= POLLIN | POLLRDNORM;
754 selrecord(curthread, &select_rd_info);
759 if (ap->a_events & (POLLOUT|POLLWRNORM)) {
760 revents |= ap->a_events & (POLLOUT | POLLWRNORM);
762 ap->a_events = revents;
766 static struct filterops i4bkqfiltops_read =
767 { 1, NULL, i4bkqfilt_detach, i4bkqfilt_read };
768 static struct filterops i4bkqfiltops_write =
769 { 1, NULL, i4bkqfilt_detach, i4bkqfilt_write };
772 i4bkqfilter(struct dev_kqfilter_args *ap)
774 cdev_t dev = ap->a_head.a_dev;
775 struct knote *kn = ap->a_kn;
783 switch (kn->kn_filter) {
785 kn->kn_fop = &i4bkqfiltops_read;
788 kn->kn_fop = &i4bkqfiltops_write;
791 ap->a_result = EOPNOTSUPP;
796 klist = &select_rd_info.si_note;
797 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
804 i4bkqfilt_detach(struct knote *kn)
809 klist = &select_rd_info.si_note;
810 SLIST_REMOVE(klist, kn, knote, kn_selnext);
815 i4bkqfilt_read(struct knote *kn, long hint)
820 if (!IF_QEMPTY(&i4b_rdqueue))
828 i4bkqfilt_write(struct knote *kn, long hint)
833 /*---------------------------------------------------------------------------*
834 * i4bputqueue - put message into queue to userland
835 *---------------------------------------------------------------------------*/
837 i4bputqueue(struct mbuf *m)
847 if(IF_QFULL(&i4b_rdqueue))
850 IF_DEQUEUE(&i4b_rdqueue, m1);
852 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
855 IF_ENQUEUE(&i4b_rdqueue, m);
862 wakeup((caddr_t) &i4b_rdqueue);
865 selwakeup(&select_rd_info);
868 /*---------------------------------------------------------------------------*
869 * i4bputqueue_hipri - put message into front of queue to userland
870 *---------------------------------------------------------------------------*/
872 i4bputqueue_hipri(struct mbuf *m)
882 if(IF_QFULL(&i4b_rdqueue))
885 IF_DEQUEUE(&i4b_rdqueue, m1);
887 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
890 IF_PREPEND(&i4b_rdqueue, m);
897 wakeup((caddr_t) &i4b_rdqueue);
900 selwakeup(&select_rd_info);
903 #endif /* NI4B > 0 */