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;
265 mtx_init(&i4b_rdqueue.ifq_mtx, "i4b_rdqueue", MTX_DEF);
267 #if defined(__FreeBSD__)
271 devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR,
272 UID_ROOT, GID_WHEEL, 0600,
277 make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
282 /*---------------------------------------------------------------------------*
283 * i4bopen - device driver open routine
284 *---------------------------------------------------------------------------*/
286 i4bopen(dev_t dev, int flag, int fmt, struct proc *p)
298 i4b_l4_daemon_attached();
304 /*---------------------------------------------------------------------------*
305 * i4bclose - device driver close routine
306 *---------------------------------------------------------------------------*/
308 i4bclose(dev_t dev, int flag, int fmt, struct proc *p)
312 i4b_l4_daemon_detached();
313 i4b_Dcleanifq(&i4b_rdqueue);
318 /*---------------------------------------------------------------------------*
319 * i4bread - device driver read routine
320 *---------------------------------------------------------------------------*/
322 i4bread(dev_t dev, struct uio *uio, int ioflag)
332 IF_LOCK(&i4b_rdqueue);
333 while(IF_QEMPTY(&i4b_rdqueue))
336 error = msleep((caddr_t) &i4b_rdqueue, &i4b_rdqueue.ifq_mtx,
337 (PZERO + 1) | PCATCH, "bird", 0);
339 IF_UNLOCK(&i4b_rdqueue);
345 _IF_DEQUEUE(&i4b_rdqueue, m);
346 IF_UNLOCK(&i4b_rdqueue);
351 error = uiomove(m->m_data, m->m_len, uio);
361 /*---------------------------------------------------------------------------*
362 * i4bioctl - device driver ioctl routine
363 *---------------------------------------------------------------------------*/
365 #if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
366 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
367 #elif defined(__bsdi__)
368 i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
370 i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
381 /* cdid request, reserve cd and return cdid */
386 mir = (msg_cdid_req_t *)data;
388 mir->cdid = cd->cdid;
392 /* connect request, dial out to remote */
394 case I4B_CONNECT_REQ:
396 msg_connect_req_t *mcr;
397 mcr = (msg_connect_req_t *)data; /* setup ptr */
399 if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
401 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
406 /* prevent dialling on leased lines */
407 if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
409 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
410 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
411 i4b_l4_disconnect_ind(cd);
416 cd->controller = mcr->controller; /* fill cd */
417 cd->bprot = mcr->bprot;
418 cd->driver = mcr->driver;
419 cd->driver_unit = mcr->driver_unit;
420 cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
422 cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
423 cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time;
424 cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time;
425 cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
427 cd->last_aocd_time = 0;
428 if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
435 cd->max_idle_time = 0; /* this is outgoing */
437 cd->dir = DIR_OUTGOING;
439 NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
440 (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
441 (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
443 strcpy(cd->dst_telno, mcr->dst_telno);
444 strcpy(cd->src_telno, mcr->src_telno);
445 cd->display[0] = '\0';
447 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
448 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
454 if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
455 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
459 if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) &&
460 (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE))
461 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
465 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
469 cd->channelid = mcr->channel;
471 cd->isdntxdelay = mcr->txdelay;
473 /* check whether we have a pointer. Seems like */
474 /* this should be adequate. GJ 19.09.97 */
475 if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
476 /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
478 if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
480 i4b_l4_disconnect_ind(cd);
485 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
490 /* connect response, accept/reject/ignore incoming call */
492 case I4B_CONNECT_RESP:
494 msg_connect_resp_t *mcrsp;
496 mcrsp = (msg_connect_resp_t *)data;
498 if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
500 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
507 cd->driver = mcrsp->driver;
508 cd->driver_unit = mcrsp->driver_unit;
509 cd->max_idle_time = mcrsp->max_idle_time;
511 cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
512 cd->shorthold_data.unitlen_time = 0; /* this is incoming */
513 cd->shorthold_data.idle_time = 0;
514 cd->shorthold_data.earlyhup_time = 0;
516 cd->isdntxdelay = mcrsp->txdelay;
518 NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
520 (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
524 /* disconnect request, actively terminate connection */
526 case I4B_DISCONNECT_REQ:
528 msg_discon_req_t *mdr;
530 mdr = (msg_discon_req_t *)data;
532 if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
534 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!");
539 /* preset causes with our cause */
540 cd->cause_in = cd->cause_out = mdr->cause;
542 (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
546 /* controller info request */
548 case I4B_CTRL_INFO_REQ:
550 msg_ctrl_info_req_t *mcir;
552 mcir = (msg_ctrl_info_req_t *)data;
553 mcir->ncontroller = nctrl;
555 if(mcir->controller > nctrl)
557 mcir->ctrl_type = -1;
558 mcir->card_type = -1;
563 ctrl_desc[mcir->controller].ctrl_type;
565 ctrl_desc[mcir->controller].card_type;
567 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
568 mcir->tei = ctrl_desc[mcir->controller].tei;
577 case I4B_DIALOUT_RESP:
579 drvr_link_t *dlt = NULL;
580 msg_dialout_resp_t *mdrsp;
582 mdrsp = (msg_dialout_resp_t *)data;
584 switch(mdrsp->driver)
588 dlt = ipr_ret_linktab(mdrsp->driver_unit);
594 dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
600 dlt = tel_ret_linktab(mdrsp->driver_unit);
606 dlt = ibc_ret_linktab(mdrsp->driver_unit);
612 dlt = ing_ret_linktab(mdrsp->driver_unit);
618 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
622 /* update timeout value */
624 case I4B_TIMEOUT_UPD:
626 msg_timeout_upd_t *mtu;
629 mtu = (msg_timeout_upd_t *)data;
631 NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
632 mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
633 mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
635 if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
637 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
642 switch( mtu->shorthold_data.shorthold_algorithm )
646 * For this algorithm unitlen_time,
647 * idle_time and earlyhup_time are used.
650 if(!(mtu->shorthold_data.unitlen_time >= 0 &&
651 mtu->shorthold_data.idle_time >= 0 &&
652 mtu->shorthold_data.earlyhup_time >= 0))
654 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
661 * For this algorithm unitlen_time and
662 * idle_time are used. both must be
663 * positive integers. earlyhup_time is
664 * not used and must be 0.
667 if(!(mtu->shorthold_data.unitlen_time > 0 &&
668 mtu->shorthold_data.idle_time >= 0 &&
669 mtu->shorthold_data.earlyhup_time == 0))
671 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
677 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
683 * any error set above requires us to break
684 * out of the outer switch
690 cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
691 cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
692 cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
693 cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
698 /* soft enable/disable interface */
702 msg_updown_ind_t *mui;
704 mui = (msg_updown_ind_t *)data;
707 if(mui->driver == BDRV_IPR)
710 dlt = ipr_ret_linktab(mui->driver_unit);
711 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
717 /* send ALERT request */
721 msg_alert_req_t *mar;
723 mar = (msg_alert_req_t *)data;
725 if((cd = cd_by_cdid(mar->cdid)) == NULL)
727 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
734 (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
739 /* version/release number request */
745 mvr = (msg_vr_req_t *)data;
747 mvr->version = VERSION;
753 /* set D-channel protocol for a controller */
759 mpi = (msg_prot_ind_t *)data;
761 ctrl_desc[mpi->controller].protocol = mpi->protocol;
766 /* Download request */
768 case I4B_CTRL_DOWNLOAD:
770 struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
771 struct isdn_download_request *r =
772 (struct isdn_download_request*)data;
775 if (r->controller < 0 || r->controller >= nctrl)
781 if(!ctrl_desc[r->controller].N_DOWNLOAD)
787 prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
790 prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
793 if(!prots || !prots2)
799 copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
801 for(i = 0; i < r->numprotos; i++)
803 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
804 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
805 prots2[i].bytecount = prots[i].bytecount;
808 error = ctrl_desc[r->controller].N_DOWNLOAD(
809 ctrl_desc[r->controller].unit,
810 r->numprotos, prots2);
815 for(i = 0; i < r->numprotos; i++)
817 if(prots2[i].microcode)
819 free(prots2[i].microcode, M_DEVBUF);
822 free(prots2, M_DEVBUF);
827 free(prots, M_DEVBUF);
832 /* Diagnostic request */
834 case I4B_ACTIVE_DIAGNOSTIC:
836 struct isdn_diagnostic_request req, *r =
837 (struct isdn_diagnostic_request*)data;
839 req.in_param = req.out_param = NULL;
840 if (r->controller < 0 || r->controller >= nctrl)
846 if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
852 memcpy(&req, r, sizeof(req));
856 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
863 error = copyin(r->in_param, req.in_param, req.in_param_len);
868 if(req.out_param_len)
870 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
879 error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
881 if(!error && req.out_param_len)
882 error = copyout(req.out_param, r->out_param, req.out_param_len);
886 free(req.in_param, M_DEVBUF);
889 free(req.out_param, M_DEVBUF);
904 #ifdef OS_USES_SELECT
906 /*---------------------------------------------------------------------------*
907 * i4bselect - device driver select routine
908 *---------------------------------------------------------------------------*/
910 i4bselect(dev_t dev, int rw, struct proc *p)
920 if(!IF_QEMPTY(&i4b_rdqueue))
923 selrecord(p, &select_rd_info);
936 #else /* OS_USES_SELECT */
938 /*---------------------------------------------------------------------------*
939 * i4bpoll - device driver poll routine
940 *---------------------------------------------------------------------------*/
942 i4bpoll(dev_t dev, int events, struct proc *p)
949 if((events & POLLIN) || (events & POLLRDNORM))
951 if(!IF_QEMPTY(&i4b_rdqueue))
955 selrecord(p, &select_rd_info);
960 else if((events & POLLOUT) || (events & POLLWRNORM))
968 #endif /* OS_USES_SELECT */
970 /*---------------------------------------------------------------------------*
971 * i4bputqueue - put message into queue to userland
972 *---------------------------------------------------------------------------*/
974 i4bputqueue(struct mbuf *m)
986 IF_LOCK(&i4b_rdqueue);
987 if(_IF_QFULL(&i4b_rdqueue))
990 _IF_DEQUEUE(&i4b_rdqueue, m1);
992 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
995 _IF_ENQUEUE(&i4b_rdqueue, m);
996 IF_UNLOCK(&i4b_rdqueue);
1003 wakeup((caddr_t) &i4b_rdqueue);
1009 selwakeup(&select_rd_info);
1013 /*---------------------------------------------------------------------------*
1014 * i4bputqueue_hipri - put message into front of queue to userland
1015 *---------------------------------------------------------------------------*/
1017 i4bputqueue_hipri(struct mbuf *m)
1029 IF_LOCK(&i4b_rdqueue);
1030 if(_IF_QFULL(&i4b_rdqueue))
1033 _IF_DEQUEUE(&i4b_rdqueue, m1);
1035 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
1038 _IF_PREPEND(&i4b_rdqueue, m);
1039 IF_UNLOCK(&i4b_rdqueue);
1046 wakeup((caddr_t) &i4b_rdqueue);
1052 selwakeup(&select_rd_info);
1056 #endif /* NI4B > 0 */