2 * Copyright (c) 1997, 1999 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.52 1999/12/13 21:25:28 hm Exp $
34 * last edit-date: [Mon Dec 13 22:06:11 1999]
36 *---------------------------------------------------------------------------*/
49 #error "only 1 (one) i4b device possible!"
54 #include <sys/param.h>
56 #if defined(__FreeBSD__)
57 #include <sys/ioccom.h>
58 #include <sys/malloc.h>
61 #include <sys/ioctl.h>
64 #include <sys/kernel.h>
65 #include <sys/systm.h>
69 #include <sys/fcntl.h>
70 #include <sys/socket.h>
71 #include <sys/select.h>
76 #if defined(__FreeBSD__) && __FreeBSD__ == 3
77 #include "opt_devfs.h"
81 #include <sys/devfsext.h>
84 #endif /* __FreeBSD__*/
87 #include <machine/i4b_debug.h>
88 #include <machine/i4b_ioctl.h>
89 #include <machine/i4b_cause.h>
91 #include <i4b/i4b_debug.h>
92 #include <i4b/i4b_ioctl.h>
93 #include <i4b/i4b_cause.h>
96 #include <i4b/include/i4b_l3l4.h>
97 #include <i4b/include/i4b_mbuf.h>
98 #include <i4b/include/i4b_global.h>
100 #include <i4b/layer4/i4b_l4.h>
103 #include <sys/poll.h>
106 struct selinfo select_rd_info;
108 static struct ifqueue i4b_rdqueue;
109 static int openflag = 0;
110 static int selflag = 0;
111 static int readflag = 0;
113 #if defined(__FreeBSD__) && __FreeBSD__ == 3
115 static void *devfs_token;
121 #define PDEVSTATIC /* - not static - */
122 PDEVSTATIC void i4battach __P((void));
123 PDEVSTATIC int i4bopen __P((dev_t dev, int flag, int fmt, struct proc *p));
124 PDEVSTATIC int i4bclose __P((dev_t dev, int flag, int fmt, struct proc *p));
125 PDEVSTATIC int i4bread __P((dev_t dev, struct uio *uio, int ioflag));
128 PDEVSTATIC int i4bioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
130 PDEVSTATIC int i4bioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
134 PDEVSTATIC int i4bpoll __P((dev_t dev, int events, struct proc *p));
136 PDEVSTATIC int i4bselect __P((dev_t dev, int rw, struct proc *p));
139 #endif /* #ifndef __FreeBSD__ */
141 #if BSD > 199306 && defined(__FreeBSD__)
143 #define PDEVSTATIC static
145 PDEVSTATIC d_open_t i4bopen;
146 PDEVSTATIC d_close_t i4bclose;
147 PDEVSTATIC d_read_t i4bread;
148 PDEVSTATIC d_ioctl_t i4bioctl;
151 PDEVSTATIC d_poll_t i4bpoll;
152 #define POLLFIELD i4bpoll
154 PDEVSTATIC d_select_t i4bselect;
155 #define POLLFIELD i4bselect
158 #define CDEV_MAJOR 60
160 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
161 static struct cdevsw i4b_cdevsw = {
163 /* close */ i4bclose,
166 /* ioctl */ i4bioctl,
167 /* poll */ POLLFIELD,
169 /* strategy */ nostrategy,
171 /* maj */ CDEV_MAJOR,
178 static struct cdevsw i4b_cdevsw = {
179 i4bopen, i4bclose, i4bread, nowrite,
180 i4bioctl, nostop, nullreset, nodevtotty,
181 POLLFIELD, nommap, NULL, "i4b", NULL, -1
185 PDEVSTATIC void i4battach(void *);
186 PSEUDO_SET(i4battach, i4b_i4bdrv);
189 i4b_drvinit(void *unused)
191 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
192 cdevsw_add(&i4b_cdevsw);
194 static int i4b_devsw_installed = 0;
197 if( ! i4b_devsw_installed )
199 dev = makedev(CDEV_MAJOR,0);
200 cdevsw_add(&dev,&i4b_cdevsw,NULL);
201 i4b_devsw_installed = 1;
206 SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL)
208 #endif /* BSD > 199306 && defined(__FreeBSD__) */
211 #include <sys/device.h>
212 int i4bmatch(struct device *parent, struct cfdata *cf, void *aux);
213 void dummy_i4battach(struct device*, struct device *, void *);
215 #define CDEV_MAJOR 65
217 static struct cfdriver i4bcd =
218 { NULL, "i4b", i4bmatch, dummy_i4battach, DV_DULL,
219 sizeof(struct cfdriver) };
222 i4bopen, i4bclose, i4bread, nowrite,
223 i4bioctl, i4bselect, nommap, nostrat,
224 nodump, nopsize, 0, nostop
228 i4bmatch(struct device *parent, struct cfdata *cf, void *aux)
230 printf("i4bmatch: aux=0x%x\n", aux);
234 dummy_i4battach(struct device *parent, struct device *self, void *aux)
236 printf("dummy_i4battach: aux=0x%x\n", aux);
238 #endif /* __bsdi__ */
240 /*---------------------------------------------------------------------------*
241 * interface attach routine
242 *---------------------------------------------------------------------------*/
245 i4battach(void *dummy)
250 #ifndef HACK_NO_PSEUDO_ATTACH_MSG
251 printf("i4b: ISDN call control device attached\n");
253 i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
255 #if defined(__FreeBSD__)
259 devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR,
260 UID_ROOT, GID_WHEEL, 0600,
265 make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
270 /*---------------------------------------------------------------------------*
271 * i4bopen - device driver open routine
272 *---------------------------------------------------------------------------*/
274 i4bopen(dev_t dev, int flag, int fmt, struct proc *p)
286 i4b_l4_daemon_attached();
292 /*---------------------------------------------------------------------------*
293 * i4bclose - device driver close routine
294 *---------------------------------------------------------------------------*/
296 i4bclose(dev_t dev, int flag, int fmt, struct proc *p)
300 i4b_l4_daemon_detached();
301 i4b_Dcleanifq(&i4b_rdqueue);
306 /*---------------------------------------------------------------------------*
307 * i4bread - device driver read routine
308 *---------------------------------------------------------------------------*/
310 i4bread(dev_t dev, struct uio *uio, int ioflag)
319 while(IF_QEMPTY(&i4b_rdqueue))
324 tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0);
329 IF_DEQUEUE(&i4b_rdqueue, m);
334 error = uiomove(m->m_data, m->m_len, uio);
344 /*---------------------------------------------------------------------------*
345 * i4bioctl - device driver ioctl routine
346 *---------------------------------------------------------------------------*/
348 #if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
349 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
350 #elif defined(__bsdi__)
351 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
353 i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
364 /* cdid request, reserve cd and return cdid */
369 mir = (msg_cdid_req_t *)data;
371 mir->cdid = cd->cdid;
375 /* connect request, dial out to remote */
377 case I4B_CONNECT_REQ:
379 msg_connect_req_t *mcr;
380 mcr = (msg_connect_req_t *)data; /* setup ptr */
382 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
384 DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_REQ ioctl, cdid not found!\n"));
389 /* prevent dialling on leased lines */
390 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
392 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
393 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
394 i4b_l4_disconnect_ind(cd);
399 cd->controller = mcr->controller; /* fill cd */
400 cd->bprot = mcr->bprot;
401 cd->driver = mcr->driver;
402 cd->driver_unit = mcr->driver_unit;
403 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
405 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
406 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
407 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
408 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
410 cd->last_aocd_time = 0;
411 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
418 cd->max_idle_time = 0; /* this is outgoing */
420 cd->dir = DIR_OUTGOING;
422 DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld\n",
423 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
424 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time));
426 strcpy(cd->dst_telno, mcr->dst_telno);
427 strcpy(cd->src_telno, mcr->src_telno);
428 cd->display[0] = '\0';
430 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
431 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
437 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
438 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
442 if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) &&
443 (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE))
444 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
448 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
452 cd->channelid = mcr->channel;
454 cd->isdntxdelay = mcr->txdelay;
456 /* check whether we have a pointer. Seems like */
457 /* this should be adequate. GJ 19.09.97 */
458 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
459 /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
461 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
463 i4b_l4_disconnect_ind(cd);
468 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
473 /* connect response, accept/reject/ignore incoming call */
475 case I4B_CONNECT_RESP:
477 msg_connect_resp_t *mcrsp;
479 mcrsp = (msg_connect_resp_t *)data;
481 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
483 DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_RESP ioctl, cdid not found!\n"));
490 cd->driver = mcrsp->driver;
491 cd->driver_unit = mcrsp->driver_unit;
492 cd->max_idle_time = mcrsp->max_idle_time;
494 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
495 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
496 cd->shorthold_data.idle_time = 0;
497 cd->shorthold_data.earlyhup_time = 0;
499 cd->isdntxdelay = mcrsp->txdelay;
501 DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_RESP max_idle_time set to %ld seconds\n", (long)cd->max_idle_time));
503 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
507 /* disconnect request, actively terminate connection */
509 case I4B_DISCONNECT_REQ:
511 msg_discon_req_t *mdr;
513 mdr = (msg_discon_req_t *)data;
515 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
517 DBGL4(L4_ERR, "i4bioctl", ("I4B_DISCONNECT_REQ ioctl, cdid not found!\n"));
522 /* preset causes with our cause */
523 cd->cause_in = cd->cause_out = mdr->cause;
525 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
529 /* controller info request */
531 case I4B_CTRL_INFO_REQ:
533 msg_ctrl_info_req_t *mcir;
535 mcir = (msg_ctrl_info_req_t *)data;
536 mcir->ncontroller = nctrl;
538 if(mcir->controller > nctrl)
540 mcir->ctrl_type = -1;
541 mcir->card_type = -1;
546 ctrl_desc[mcir->controller].ctrl_type;
548 ctrl_desc[mcir->controller].card_type;
550 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
551 mcir->tei = ctrl_desc[mcir->controller].tei;
560 case I4B_DIALOUT_RESP:
562 drvr_link_t *dlt = NULL;
563 msg_dialout_resp_t *mdrsp;
565 mdrsp = (msg_dialout_resp_t *)data;
567 switch(mdrsp->driver)
571 dlt = ipr_ret_linktab(mdrsp->driver_unit);
577 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
583 dlt = tel_ret_linktab(mdrsp->driver_unit);
589 dlt = ibc_ret_linktab(mdrsp->driver_unit);
595 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
599 /* update timeout value */
601 case I4B_TIMEOUT_UPD:
603 msg_timeout_upd_t *mtu;
606 mtu = (msg_timeout_upd_t *)data;
608 DBGL4(L4_TIMO, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!\n",
609 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
610 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time ));
612 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
614 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, cdid not found!\n"));
619 switch( mtu->shorthold_data.shorthold_algorithm )
623 * For this algorithm unitlen_time,
624 * idle_time and earlyhup_time are used.
627 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
628 mtu->shorthold_data.idle_time >= 0 &&
629 mtu->shorthold_data.earlyhup_time >= 0))
631 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!\n"));
638 * For this algorithm unitlen_time and
639 * idle_time are used. both must be
640 * positive integers. earlyhup_time is
641 * not used and must be 0.
644 if(!(mtu->shorthold_data.unitlen_time > 0 &&
645 mtu->shorthold_data.idle_time >= 0 &&
646 mtu->shorthold_data.earlyhup_time == 0))
648 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!\n"));
654 DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid algorithm!\n"));
660 * any error set above requires us to break
661 * out of the outer switch
667 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
668 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
669 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
670 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
675 /* soft enable/disable interface */
679 msg_updown_ind_t *mui;
681 mui = (msg_updown_ind_t *)data;
684 if(mui->driver == BDRV_IPR)
687 dlt = ipr_ret_linktab(mui->driver_unit);
688 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
694 /* send ALERT request */
698 msg_alert_req_t *mar;
700 mar = (msg_alert_req_t *)data;
702 if((cd = cd_by_cdid(mar->cdid)) == NULL)
704 DBGL4(L4_ERR, "i4bioctl", ("I4B_ALERT_REQ ioctl, cdid not found!\n"));
711 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
716 /* version/release number request */
722 mvr = (msg_vr_req_t *)data;
724 mvr->version = VERSION;
730 /* set D-channel protocol for a controller */
736 mpi = (msg_prot_ind_t *)data;
738 ctrl_desc[mpi->controller].protocol = mpi->protocol;
743 /* Download request */
745 case I4B_CTRL_DOWNLOAD:
747 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
748 struct isdn_download_request *r =
749 (struct isdn_download_request*)data;
752 if (r->controller < 0 || r->controller >= nctrl)
758 if(!ctrl_desc[r->controller].N_DOWNLOAD)
764 prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
767 prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
770 if(!prots || !prots2)
776 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
778 for(i = 0; i < r->numprotos; i++)
780 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
781 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
782 prots2[i].bytecount = prots[i].bytecount;
785 error = ctrl_desc[r->controller].N_DOWNLOAD(
786 ctrl_desc[r->controller].unit,
787 r->numprotos, prots2);
792 for(i = 0; i < r->numprotos; i++)
794 if(prots2[i].microcode)
796 free(prots2[i].microcode, M_DEVBUF);
799 free(prots2, M_DEVBUF);
804 free(prots, M_DEVBUF);
809 /* Diagnostic request */
811 case I4B_ACTIVE_DIAGNOSTIC:
813 struct isdn_diagnostic_request req, *r =
814 (struct isdn_diagnostic_request*)data;
816 req.in_param = req.out_param = NULL;
817 if (r->controller < 0 || r->controller >= nctrl)
823 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
829 memcpy(&req, r, sizeof(req));
833 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
840 error = copyin(r->in_param, req.in_param, req.in_param_len);
845 if(req.out_param_len)
847 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
856 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
858 if(!error && req.out_param_len)
859 error = copyout(req.out_param, r->out_param, req.out_param_len);
863 free(req.in_param, M_DEVBUF);
866 free(req.out_param, M_DEVBUF);
881 #ifdef OS_USES_SELECT
883 /*---------------------------------------------------------------------------*
884 * i4bselect - device driver select routine
885 *---------------------------------------------------------------------------*/
887 i4bselect(dev_t dev, int rw, struct proc *p)
897 if(!IF_QEMPTY(&i4b_rdqueue))
900 selrecord(p, &select_rd_info);
913 #else /* OS_USES_SELECT */
915 /*---------------------------------------------------------------------------*
916 * i4bpoll - device driver poll routine
917 *---------------------------------------------------------------------------*/
919 i4bpoll(dev_t dev, int events, struct proc *p)
926 if((events & POLLIN) || (events & POLLRDNORM))
928 if(!IF_QEMPTY(&i4b_rdqueue))
932 selrecord(p, &select_rd_info);
937 else if((events & POLLOUT) || (events & POLLWRNORM))
945 #endif /* OS_USES_SELECT */
947 /*---------------------------------------------------------------------------*
948 * i4bputqueue - put message into queue to userland
949 *---------------------------------------------------------------------------*/
951 i4bputqueue(struct mbuf *m)
963 if(IF_QFULL(&i4b_rdqueue))
966 IF_DEQUEUE(&i4b_rdqueue, m1);
968 DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n"));
971 IF_ENQUEUE(&i4b_rdqueue, m);
978 wakeup((caddr_t) &i4b_rdqueue);
984 selwakeup(&select_rd_info);
988 /*---------------------------------------------------------------------------*
989 * i4bputqueue_hipri - put message into front of queue to userland
990 *---------------------------------------------------------------------------*/
992 i4bputqueue_hipri(struct mbuf *m)
1004 if(IF_QFULL(&i4b_rdqueue))
1007 IF_DEQUEUE(&i4b_rdqueue, m1);
1009 DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n"));
1012 IF_PREPEND(&i4b_rdqueue, m);
1019 wakeup((caddr_t) &i4b_rdqueue);
1025 selwakeup(&select_rd_info);
1029 #endif /* NI4B > 0 */