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.59 2000/10/06 08:37:43 hm Exp $
34 * last edit-date: [Mon Oct 2 09:55:28 2000]
36 *---------------------------------------------------------------------------*/
44 #error "only 1 (one) i4b device possible!"
49 #include <sys/param.h>
51 #if defined(__FreeBSD__)
52 #include <sys/ioccom.h>
53 #include <sys/malloc.h>
56 #include <sys/ioctl.h>
59 #include <sys/kernel.h>
60 #include <sys/systm.h>
63 #include <sys/socket.h>
64 #include <sys/select.h>
68 #include <sys/types.h>
71 #if defined(__FreeBSD__)
81 #include <net/if_sppp.h>
87 #if defined(__FreeBSD__) && __FreeBSD__ == 3
88 #include "opt_devfs.h"
92 #include <sys/devfsext.h>
95 #endif /* __FreeBSD__*/
98 #include <machine/i4b_debug.h>
99 #include <machine/i4b_ioctl.h>
100 #include <machine/i4b_cause.h>
102 #include <i4b/i4b_debug.h>
103 #include <i4b/i4b_ioctl.h>
104 #include <i4b/i4b_cause.h>
107 #include <i4b/include/i4b_l3l4.h>
108 #include <i4b/include/i4b_mbuf.h>
109 #include <i4b/include/i4b_global.h>
111 #include <i4b/layer4/i4b_l4.h>
114 #include <sys/poll.h>
117 struct selinfo select_rd_info;
119 static struct ifqueue i4b_rdqueue;
120 static int openflag = 0;
121 static int selflag = 0;
122 static int readflag = 0;
124 #if defined(__FreeBSD__) && __FreeBSD__ == 3
126 static void *devfs_token;
132 #define PDEVSTATIC /* - not static - */
133 PDEVSTATIC void i4battach __P((void));
134 PDEVSTATIC int i4bopen __P((dev_t dev, int flag, int fmt, struct proc *p));
135 PDEVSTATIC int i4bclose __P((dev_t dev, int flag, int fmt, struct proc *p));
136 PDEVSTATIC int i4bread __P((dev_t dev, struct uio *uio, int ioflag));
139 PDEVSTATIC int i4bioctl __P((dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p));
141 PDEVSTATIC int i4bioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
145 PDEVSTATIC int i4bpoll __P((dev_t dev, int events, struct proc *p));
147 PDEVSTATIC int i4bselect __P((dev_t dev, int rw, struct proc *p));
150 #endif /* #ifndef __FreeBSD__ */
152 #if BSD > 199306 && defined(__FreeBSD__)
154 #define PDEVSTATIC static
156 PDEVSTATIC d_open_t i4bopen;
157 PDEVSTATIC d_close_t i4bclose;
158 PDEVSTATIC d_read_t i4bread;
159 PDEVSTATIC d_ioctl_t i4bioctl;
162 PDEVSTATIC d_poll_t i4bpoll;
163 #define POLLFIELD i4bpoll
165 PDEVSTATIC d_select_t i4bselect;
166 #define POLLFIELD i4bselect
169 #define CDEV_MAJOR 60
171 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
172 static struct cdevsw i4b_cdevsw = {
174 /* close */ i4bclose,
177 /* ioctl */ i4bioctl,
178 /* poll */ POLLFIELD,
180 /* strategy */ nostrategy,
182 /* maj */ CDEV_MAJOR,
189 static struct cdevsw i4b_cdevsw = {
190 i4bopen, i4bclose, i4bread, nowrite,
191 i4bioctl, nostop, nullreset, nodevtotty,
192 POLLFIELD, nommap, NULL, "i4b", NULL, -1
196 PDEVSTATIC void i4battach(void *);
197 PSEUDO_SET(i4battach, i4b_i4bdrv);
200 i4b_drvinit(void *unused)
202 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
203 cdevsw_add(&i4b_cdevsw);
205 static int i4b_devsw_installed = 0;
208 if( ! i4b_devsw_installed )
210 dev = makedev(CDEV_MAJOR,0);
211 cdevsw_add(&dev,&i4b_cdevsw,NULL);
212 i4b_devsw_installed = 1;
217 SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL)
219 #endif /* BSD > 199306 && defined(__FreeBSD__) */
222 #include <sys/device.h>
223 int i4bmatch(struct device *parent, struct cfdata *cf, void *aux);
224 void dummy_i4battach(struct device*, struct device *, void *);
226 #define CDEV_MAJOR 65
228 static struct cfdriver i4bcd =
229 { NULL, "i4b", i4bmatch, dummy_i4battach, DV_DULL,
230 sizeof(struct cfdriver) };
233 i4bopen, i4bclose, i4bread, nowrite,
234 i4bioctl, i4bselect, nommap, nostrat,
235 nodump, nopsize, 0, nostop
239 i4bmatch(struct device *parent, struct cfdata *cf, void *aux)
241 printf("i4bmatch: aux=0x%x\n", aux);
245 dummy_i4battach(struct device *parent, struct device *self, void *aux)
247 printf("dummy_i4battach: aux=0x%x\n", aux);
249 #endif /* __bsdi__ */
251 /*---------------------------------------------------------------------------*
252 * interface attach routine
253 *---------------------------------------------------------------------------*/
256 i4battach(void *dummy)
261 #ifndef HACK_NO_PSEUDO_ATTACH_MSG
262 printf("i4b: ISDN call control device attached\n");
264 i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
266 #if defined(__FreeBSD__)
270 devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR,
271 UID_ROOT, GID_WHEEL, 0600,
276 make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
281 /*---------------------------------------------------------------------------*
282 * i4bopen - device driver open routine
283 *---------------------------------------------------------------------------*/
285 i4bopen(dev_t dev, int flag, int fmt, struct proc *p)
297 i4b_l4_daemon_attached();
303 /*---------------------------------------------------------------------------*
304 * i4bclose - device driver close routine
305 *---------------------------------------------------------------------------*/
307 i4bclose(dev_t dev, int flag, int fmt, struct proc *p)
311 i4b_l4_daemon_detached();
312 i4b_Dcleanifq(&i4b_rdqueue);
317 /*---------------------------------------------------------------------------*
318 * i4bread - device driver read routine
319 *---------------------------------------------------------------------------*/
321 i4bread(dev_t dev, struct uio *uio, int ioflag)
331 while(IF_QEMPTY(&i4b_rdqueue))
334 error = tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0);
341 IF_DEQUEUE(&i4b_rdqueue, m);
346 error = uiomove(m->m_data, m->m_len, uio);
356 /*---------------------------------------------------------------------------*
357 * i4bioctl - device driver ioctl routine
358 *---------------------------------------------------------------------------*/
360 #if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
361 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
362 #elif defined(__bsdi__)
363 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
365 i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
376 /* cdid request, reserve cd and return cdid */
381 mir = (msg_cdid_req_t *)data;
383 mir->cdid = cd->cdid;
387 /* connect request, dial out to remote */
389 case I4B_CONNECT_REQ:
391 msg_connect_req_t *mcr;
392 mcr = (msg_connect_req_t *)data; /* setup ptr */
394 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
396 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
401 /* prevent dialling on leased lines */
402 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
404 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
405 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
406 i4b_l4_disconnect_ind(cd);
411 cd->controller = mcr->controller; /* fill cd */
412 cd->bprot = mcr->bprot;
413 cd->driver = mcr->driver;
414 cd->driver_unit = mcr->driver_unit;
415 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
417 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
418 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
419 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
420 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
422 cd->last_aocd_time = 0;
423 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
430 cd->max_idle_time = 0; /* this is outgoing */
432 cd->dir = DIR_OUTGOING;
434 NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
435 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
436 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
438 strcpy(cd->dst_telno, mcr->dst_telno);
439 strcpy(cd->src_telno, mcr->src_telno);
440 cd->display[0] = '\0';
442 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
443 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
449 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
450 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
454 if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) &&
455 (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE))
456 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
460 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
464 cd->channelid = mcr->channel;
466 cd->isdntxdelay = mcr->txdelay;
468 /* check whether we have a pointer. Seems like */
469 /* this should be adequate. GJ 19.09.97 */
470 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
471 /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
473 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
475 i4b_l4_disconnect_ind(cd);
480 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
485 /* connect response, accept/reject/ignore incoming call */
487 case I4B_CONNECT_RESP:
489 msg_connect_resp_t *mcrsp;
491 mcrsp = (msg_connect_resp_t *)data;
493 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
495 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
502 cd->driver = mcrsp->driver;
503 cd->driver_unit = mcrsp->driver_unit;
504 cd->max_idle_time = mcrsp->max_idle_time;
506 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
507 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
508 cd->shorthold_data.idle_time = 0;
509 cd->shorthold_data.earlyhup_time = 0;
511 cd->isdntxdelay = mcrsp->txdelay;
513 NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
515 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
519 /* disconnect request, actively terminate connection */
521 case I4B_DISCONNECT_REQ:
523 msg_discon_req_t *mdr;
525 mdr = (msg_discon_req_t *)data;
527 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
529 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!");
534 /* preset causes with our cause */
535 cd->cause_in = cd->cause_out = mdr->cause;
537 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
541 /* controller info request */
543 case I4B_CTRL_INFO_REQ:
545 msg_ctrl_info_req_t *mcir;
547 mcir = (msg_ctrl_info_req_t *)data;
548 mcir->ncontroller = nctrl;
550 if(mcir->controller > nctrl)
552 mcir->ctrl_type = -1;
553 mcir->card_type = -1;
558 ctrl_desc[mcir->controller].ctrl_type;
560 ctrl_desc[mcir->controller].card_type;
562 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
563 mcir->tei = ctrl_desc[mcir->controller].tei;
572 case I4B_DIALOUT_RESP:
574 drvr_link_t *dlt = NULL;
575 msg_dialout_resp_t *mdrsp;
577 mdrsp = (msg_dialout_resp_t *)data;
579 switch(mdrsp->driver)
583 dlt = ipr_ret_linktab(mdrsp->driver_unit);
589 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
595 dlt = tel_ret_linktab(mdrsp->driver_unit);
601 dlt = ibc_ret_linktab(mdrsp->driver_unit);
607 dlt = ing_ret_linktab(mdrsp->driver_unit);
613 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
617 /* update timeout value */
619 case I4B_TIMEOUT_UPD:
621 msg_timeout_upd_t *mtu;
624 mtu = (msg_timeout_upd_t *)data;
626 NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
627 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
628 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
630 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
632 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
637 switch( mtu->shorthold_data.shorthold_algorithm )
641 * For this algorithm unitlen_time,
642 * idle_time and earlyhup_time are used.
645 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
646 mtu->shorthold_data.idle_time >= 0 &&
647 mtu->shorthold_data.earlyhup_time >= 0))
649 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
656 * For this algorithm unitlen_time and
657 * idle_time are used. both must be
658 * positive integers. earlyhup_time is
659 * not used and must be 0.
662 if(!(mtu->shorthold_data.unitlen_time > 0 &&
663 mtu->shorthold_data.idle_time >= 0 &&
664 mtu->shorthold_data.earlyhup_time == 0))
666 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
672 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
678 * any error set above requires us to break
679 * out of the outer switch
685 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
686 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
687 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
688 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
693 /* soft enable/disable interface */
697 msg_updown_ind_t *mui;
699 mui = (msg_updown_ind_t *)data;
702 if(mui->driver == BDRV_IPR)
705 dlt = ipr_ret_linktab(mui->driver_unit);
706 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
712 /* send ALERT request */
716 msg_alert_req_t *mar;
718 mar = (msg_alert_req_t *)data;
720 if((cd = cd_by_cdid(mar->cdid)) == NULL)
722 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
729 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
734 /* version/release number request */
740 mvr = (msg_vr_req_t *)data;
742 mvr->version = VERSION;
748 /* set D-channel protocol for a controller */
754 mpi = (msg_prot_ind_t *)data;
756 ctrl_desc[mpi->controller].protocol = mpi->protocol;
761 /* Download request */
763 case I4B_CTRL_DOWNLOAD:
765 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
766 struct isdn_download_request *r =
767 (struct isdn_download_request*)data;
770 if (r->controller < 0 || r->controller >= nctrl)
776 if(!ctrl_desc[r->controller].N_DOWNLOAD)
782 prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
785 prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
788 if(!prots || !prots2)
794 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
796 for(i = 0; i < r->numprotos; i++)
798 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
799 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
800 prots2[i].bytecount = prots[i].bytecount;
803 error = ctrl_desc[r->controller].N_DOWNLOAD(
804 ctrl_desc[r->controller].unit,
805 r->numprotos, prots2);
810 for(i = 0; i < r->numprotos; i++)
812 if(prots2[i].microcode)
814 free(prots2[i].microcode, M_DEVBUF);
817 free(prots2, M_DEVBUF);
822 free(prots, M_DEVBUF);
827 /* Diagnostic request */
829 case I4B_ACTIVE_DIAGNOSTIC:
831 struct isdn_diagnostic_request req, *r =
832 (struct isdn_diagnostic_request*)data;
834 req.in_param = req.out_param = NULL;
835 if (r->controller < 0 || r->controller >= nctrl)
841 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
847 memcpy(&req, r, sizeof(req));
851 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
858 error = copyin(r->in_param, req.in_param, req.in_param_len);
863 if(req.out_param_len)
865 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
874 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
876 if(!error && req.out_param_len)
877 error = copyout(req.out_param, r->out_param, req.out_param_len);
881 free(req.in_param, M_DEVBUF);
884 free(req.out_param, M_DEVBUF);
899 #ifdef OS_USES_SELECT
901 /*---------------------------------------------------------------------------*
902 * i4bselect - device driver select routine
903 *---------------------------------------------------------------------------*/
905 i4bselect(dev_t dev, int rw, struct proc *p)
915 if(!IF_QEMPTY(&i4b_rdqueue))
918 selrecord(p, &select_rd_info);
931 #else /* OS_USES_SELECT */
933 /*---------------------------------------------------------------------------*
934 * i4bpoll - device driver poll routine
935 *---------------------------------------------------------------------------*/
937 i4bpoll(dev_t dev, int events, struct proc *p)
944 if((events & POLLIN) || (events & POLLRDNORM))
946 if(!IF_QEMPTY(&i4b_rdqueue))
950 selrecord(p, &select_rd_info);
955 else if((events & POLLOUT) || (events & POLLWRNORM))
963 #endif /* OS_USES_SELECT */
965 /*---------------------------------------------------------------------------*
966 * i4bputqueue - put message into queue to userland
967 *---------------------------------------------------------------------------*/
969 i4bputqueue(struct mbuf *m)
981 if(IF_QFULL(&i4b_rdqueue))
984 IF_DEQUEUE(&i4b_rdqueue, m1);
986 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
989 IF_ENQUEUE(&i4b_rdqueue, m);
996 wakeup((caddr_t) &i4b_rdqueue);
1002 selwakeup(&select_rd_info);
1006 /*---------------------------------------------------------------------------*
1007 * i4bputqueue_hipri - put message into front of queue to userland
1008 *---------------------------------------------------------------------------*/
1010 i4bputqueue_hipri(struct mbuf *m)
1022 if(IF_QFULL(&i4b_rdqueue))
1025 IF_DEQUEUE(&i4b_rdqueue, m1);
1027 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
1030 IF_PREPEND(&i4b_rdqueue, m);
1037 wakeup((caddr_t) &i4b_rdqueue);
1043 selwakeup(&select_rd_info);
1047 #endif /* NI4B > 0 */