diff options
Diffstat (limited to 'sys/i4b/layer4')
-rw-r--r-- | sys/i4b/layer4/i4b_i4bdrv.c | 832 | ||||
-rw-r--r-- | sys/i4b/layer4/i4b_l4.c | 897 | ||||
-rw-r--r-- | sys/i4b/layer4/i4b_l4.h | 69 | ||||
-rw-r--r-- | sys/i4b/layer4/i4b_l4mgmt.c | 467 | ||||
-rw-r--r-- | sys/i4b/layer4/i4b_l4timer.c | 110 |
5 files changed, 2375 insertions, 0 deletions
diff --git a/sys/i4b/layer4/i4b_i4bdrv.c b/sys/i4b/layer4/i4b_i4bdrv.c new file mode 100644 index 0000000..0c21e8e --- /dev/null +++ b/sys/i4b/layer4/i4b_i4bdrv.c @@ -0,0 +1,832 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_i4bdrv.c - i4b userland interface driver + * -------------------------------------------- + * + * $Id: i4b_i4bdrv.c,v 1.33 1998/12/12 19:44:36 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:02 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" +#include "i4bipr.h" + +#if NI4B > 1 +#error "only 1 (one) i4b device possible!" +#endif + +#if NI4B > 0 + +#include <sys/param.h> + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#include <sys/malloc.h> +#include <sys/uio.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer4/i4b_l4.h> + +#if defined(__FreeBSD__) && (!defined(__FreeBSD_version) || __FreeBSD_version < 300001) +/* do nothing */ +#else +#include <sys/poll.h> +#endif + +struct selinfo select_rd_info; + +static struct ifqueue i4b_rdqueue; +static int openflag = 0; +static int selflag = 0; +static int readflag = 0; +#ifdef DEVFS +static void *devfs_token; +#endif + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* - not static - */ +PDEVSTATIC void i4battach __P((void)); +PDEVSTATIC int i4bopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +PDEVSTATIC int i4bclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +PDEVSTATIC int i4bread __P((dev_t dev, struct uio *uio, int ioflag)); +PDEVSTATIC int i4bioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +PDEVSTATIC int i4bpoll __P((dev_t dev, int events, struct proc *p)); + +#if defined (__OpenBSD__) +PDEVSTATIC int i4bselect(dev_t dev, int rw, struct proc *p); +#endif + +#endif + +#if BSD > 199306 && defined(__FreeBSD__) +#define PDEVSTATIC static + +PDEVSTATIC d_open_t i4bopen; +PDEVSTATIC d_close_t i4bclose; +PDEVSTATIC d_read_t i4bread; +PDEVSTATIC d_ioctl_t i4bioctl; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +PDEVSTATIC d_poll_t i4bpoll; +#else +PDEVSTATIC d_select_t i4bselect; +#endif + +#define CDEV_MAJOR 60 +static struct cdevsw i4b_cdevsw = + { i4bopen, i4bclose, i4bread, nowrite, + i4bioctl, nostop, nullreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4bpoll, nommap, NULL, "i4b", NULL, -1 }; +#else + i4bselect, nommap, NULL, "i4b", NULL, -1 }; +#endif + +PDEVSTATIC void i4battach(void *); +PSEUDO_SET(i4battach, i4b_i4bdrv); + +#endif /* __FreeBSD__ */ + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4battach(void *dummy) +#else +i4battach() +#endif +{ +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4b: ISDN call control device attached\n"); +#endif + i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN; +#ifdef DEVFS + devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4b", 0); +#endif +} + +/*---------------------------------------------------------------------------* + * i4bopen - device driver open routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENXIO); + + if(openflag) + return(EBUSY); + + x = splimp(); + openflag = 1; + i4b_l4_daemon_attached(); + splx(x); + + return(0); +} + +/*---------------------------------------------------------------------------* + * i4bclose - device driver close routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + int x = splimp(); + openflag = 0; + i4b_l4_daemon_detached(); + i4b_Dcleanifq(&i4b_rdqueue); + splx(x); + return(0); +} + +/*---------------------------------------------------------------------------* + * i4bread - device driver read routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bread(dev_t dev, struct uio *uio, int ioflag) +{ + struct mbuf *m; + int x; + int error = 0; + + if(minor(dev)) + return(ENODEV); + + while(IF_QEMPTY(&i4b_rdqueue)) + { + x = splimp(); + readflag = 1; + splx(x); + tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0); + } + + x = splimp(); + + IF_DEQUEUE(&i4b_rdqueue, m); + + splx(x); + + if(m && m->m_len) + error = uiomove(m->m_data, m->m_len, uio); + else + error = EIO; + + if(m) + i4b_Dfreembuf(m); + + return(error); +} + +/*---------------------------------------------------------------------------* + * i4bioctl - device driver ioctl routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003 +i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +#else +i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) +#endif +{ + call_desc_t *cd; + int error = 0; + + if(minor(dev)) + return(ENODEV); + + switch(cmd) + { + /* cdid request, reserve cd and return cdid */ + + case I4B_CDID_REQ: + { + msg_cdid_req_t *mir; + mir = (msg_cdid_req_t *)data; + cd = reserve_cd(); + mir->cdid = cd->cdid; + break; + } + + /* connect request, dial out to remote */ + + case I4B_CONNECT_REQ: + { + msg_connect_req_t *mcr; + mcr = (msg_connect_req_t *)data; /* setup ptr */ + + if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + cd->controller = mcr->controller; /* fill cd */ + cd->bprot = mcr->bprot; + cd->driver = mcr->driver; + cd->driver_unit = mcr->driver_unit; + cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit); + + cd->unitlen_time = mcr->unitlen_time; + cd->idle_time = mcr->idle_time; + cd->earlyhup_time = mcr->earlyhup_time; + + cd->last_aocd_time = 0; + if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC) + cd->aocd_flag = 1; + else + cd->aocd_flag = 0; + + cd->cunits = 0; + + cd->max_idle_time = 0; /* this is outgoing */ + + cd->dir = DIR_OUTGOING; + + DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_REQ times, unitlen=%ld idle=%ld earlyhup=%ld\n", + (long)cd->unitlen_time, (long)cd->idle_time, (long)cd->earlyhup_time)); + + strcpy(cd->dst_telno, mcr->dst_telno); + strcpy(cd->src_telno, mcr->src_telno); + cd->display[0] = '\0'; + + SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B); + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL); + + switch(mcr->channel) + { + case CHAN_B1: + case CHAN_B2: + if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE) + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + + case CHAN_ANY: + if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) && + (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE)) + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + + default: + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + } + + cd->channelid = mcr->channel; + + cd->isdntxdelay = mcr->txdelay; + + /* check whether we have a pointer. Seems like */ + /* this should be adequate. GJ 19.09.97 */ + if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL) +/*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + + if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL) + { + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); + } + else + { + (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid); + } + break; + } + + /* connect response, accept/reject/ignore incoming call */ + + case I4B_CONNECT_RESP: + { + msg_connect_resp_t *mcrsp; + + mcrsp = (msg_connect_resp_t *)data; + + if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_RESP ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + T400_stop(cd); + + cd->driver = mcrsp->driver; + cd->driver_unit = mcrsp->driver_unit; + cd->max_idle_time = mcrsp->max_idle_time; + + cd->unitlen_time = 0; /* this is incoming */ + cd->idle_time = 0; + cd->earlyhup_time = 0; + + cd->isdntxdelay = mcrsp->txdelay; + + DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_RESP max_idle_time set to %ld seconds\n", (long)cd->max_idle_time)); + + (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause); + break; + } + + /* disconnect request, actively terminate connection */ + + case I4B_DISCONNECT_REQ: + { + msg_discon_req_t *mdr; + + mdr = (msg_discon_req_t *)data; + + if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_DISCONNECT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + /* preset causes with our cause */ + cd->cause_in = cd->cause_out = mdr->cause; + + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause); + break; + } + + /* controller info request */ + + case I4B_CTRL_INFO_REQ: + { + msg_ctrl_info_req_t *mcir; + + mcir = (msg_ctrl_info_req_t *)data; + mcir->ncontroller = nctrl; + + if(mcir->controller > nctrl) + { + mcir->ctrl_type = -1; + mcir->card_type = -1; + } + else + { + mcir->ctrl_type = + ctrl_desc[mcir->controller].ctrl_type; + mcir->card_type = + ctrl_desc[mcir->controller].card_type; + + if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE) + mcir->tei = ctrl_desc[mcir->controller].tei; + else + mcir->tei = -1; + } + break; + } + + /* dial response */ + + case I4B_DIALOUT_RESP: + { + msg_dialout_resp_t *mdrsp; + + mdrsp = (msg_dialout_resp_t *)data; + +#if NI4BIPR > 0 + if(mdrsp->driver == BDRV_IPR) + { + drvr_link_t *dlt; + dlt = ipr_ret_linktab(mdrsp->driver_unit); + (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat); + } +#endif + break; + } + + /* update timeout value */ + + case I4B_TIMEOUT_UPD: + { + msg_timeout_upd_t *mtu; + int x; + + mtu = (msg_timeout_upd_t *)data; + + if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + x = SPLI4B(); + cd->unitlen_time = mtu->unitlen_time; + cd->idle_time = mtu->idle_time; + cd->earlyhup_time = mtu->earlyhup_time; + splx(x); + break; + } + + /* soft enable/disable interface */ + + case I4B_UPDOWN_IND: + { + msg_updown_ind_t *mui; + + mui = (msg_updown_ind_t *)data; + +#if NI4BIPR > 0 + if(mui->driver == BDRV_IPR) + { + drvr_link_t *dlt; + dlt = ipr_ret_linktab(mui->driver_unit); + (*dlt->updown_ind)(mui->driver_unit, mui->updown); + } +#endif + break; + } + + /* send ALERT request */ + + case I4B_ALERT_REQ: + { + msg_alert_req_t *mar; + + mar = (msg_alert_req_t *)data; + + if((cd = cd_by_cdid(mar->cdid)) == NULL) + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_ALERT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + T400_stop(cd); + + (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid); + + break; + } + + /* version/release number request */ + + case I4B_VR_REQ: + { + msg_vr_req_t *mvr; + + mvr = (msg_vr_req_t *)data; + + mvr->version = VERSION; + mvr->release = REL; + mvr->step = STEP; + break; + } + + /* Download request */ + + case I4B_CTRL_DOWNLOAD: + { + struct isdn_dr_prot *prots = NULL, *prots2 = NULL; + struct isdn_download_request *r = + (struct isdn_download_request*)data; + int i; + + if(!ctrl_desc[r->controller].N_DOWNLOAD) + { + error = ENODEV; + goto download_done; + } + + prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot), + M_DEVBUF, M_WAITOK); + + prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot), + M_DEVBUF, M_WAITOK); + + if(!prots || !prots2) + { + error = ENOMEM; + goto download_done; + } + + copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot)); + + for(i = 0; i < r->numprotos; i++) + { + prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK); + copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount); + prots2[i].bytecount = prots[i].bytecount; + } + + error = ctrl_desc[r->controller].N_DOWNLOAD( + ctrl_desc[r->controller].unit, + r->numprotos, prots2); + +download_done: + if(prots2) + { + for(i = 0; i < r->numprotos; i++) + { + if(prots2[i].microcode) + { + free(prots2[i].microcode, M_DEVBUF); + } + } + free(prots2, M_DEVBUF); + } + + if(prots) + { + free(prots, M_DEVBUF); + } + break; + } + + /* Diagnostic request */ + + case I4B_ACTIVE_DIAGNOSTIC: + { + struct isdn_diagnostic_request req, *r = + (struct isdn_diagnostic_request*)data; + + req.in_param = req.out_param = NULL; + + if(!ctrl_desc[r->controller].N_DIAGNOSTICS) + { + error = ENODEV; + goto diag_done; + } + + memcpy(&req, r, sizeof(req)); + + if(req.in_param_len) + { + req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK); + + if(!req.in_param) + { + error = ENOMEM; + goto diag_done; + } + copyin(r->in_param, req.in_param, req.in_param_len); + } + + if(req.out_param_len) + { + req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK); + + if(!req.out_param) + { + error = ENOMEM; + goto diag_done; + } + } + + error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req); + + if(!error && req.out_param_len) + copyout(req.out_param, r->out_param, req.out_param_len); + +diag_done: + if(req.in_param) + free(req.in_param, M_DEVBUF); + + if(req.out_param) + free(req.out_param, M_DEVBUF); + + break; + } + + /* default */ + + default: + error = ENOTTY; + break; + } + + return(error); +} + +#if (defined(__FreeBSD__) && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 300001))) \ + || defined (__OpenBSD__) + +/*---------------------------------------------------------------------------* + * i4bselect - device driver select routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bselect(dev_t dev, int rw, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENODEV); + + switch(rw) + { + case FREAD: + if(!IF_QEMPTY(&i4b_rdqueue)) + return(1); + x = splimp(); + selrecord(p, &select_rd_info); + selflag = 1; + splx(x); + return(0); + break; + + case FWRITE: + return(1); + break; + } + return(0); +} + +#else /* NetBSD and FreeBSD -current */ + +/*---------------------------------------------------------------------------* + * i4bpoll - device driver poll routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bpoll(dev_t dev, int events, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENODEV); + + if((events & POLLIN) || (events & POLLRDNORM)) + { + if(!IF_QEMPTY(&i4b_rdqueue)) + return(1); + + x = splimp(); + selrecord(p, &select_rd_info); + selflag = 1; + splx(x); + return(0); + } + else if((events & POLLOUT) || (events & POLLWRNORM)) + { + return(1); + } + + return(0); +} + +#endif /* defined(__FreeBSD__) && __FreeBSD__ < 3 */ + +/*---------------------------------------------------------------------------* + * i4bputqueue - put message into queue to userland + *---------------------------------------------------------------------------*/ +void +i4bputqueue(struct mbuf *m) +{ + int x; + + if(!openflag) + { + i4b_Dfreembuf(m); + return; + } + + x = splimp(); + + if(IF_QFULL(&i4b_rdqueue)) + { + struct mbuf *m1; + IF_DEQUEUE(&i4b_rdqueue, m1); + i4b_Dfreembuf(m1); + DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n")); + } + + IF_ENQUEUE(&i4b_rdqueue, m); + + splx(x); + + if(readflag) + { + readflag = 0; + wakeup((caddr_t) &i4b_rdqueue); + } + + if(selflag) + { + selflag = 0; + selwakeup(&select_rd_info); + } +} + +/*---------------------------------------------------------------------------* + * i4bputqueue_hipri - put message into front of queue to userland + *---------------------------------------------------------------------------*/ +void +i4bputqueue_hipri(struct mbuf *m) +{ + int x; + + if(!openflag) + { + i4b_Dfreembuf(m); + return; + } + + x = splimp(); + + if(IF_QFULL(&i4b_rdqueue)) + { + struct mbuf *m1; + IF_DEQUEUE(&i4b_rdqueue, m1); + i4b_Dfreembuf(m1); + DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n")); + } + + IF_PREPEND(&i4b_rdqueue, m); + + splx(x); + + if(readflag) + { + readflag = 0; + wakeup((caddr_t) &i4b_rdqueue); + } + + if(selflag) + { + selflag = 0; + selwakeup(&select_rd_info); + } +} + +#if BSD > 199306 && defined(__FreeBSD__) +static i4b_devsw_installed = 0; + +static void +i4b_drvinit(void *unused) +{ + dev_t dev; + + if( ! i4b_devsw_installed ) { + dev = makedev(CDEV_MAJOR,0); + cdevsw_add(&dev,&i4b_cdevsw,NULL); + i4b_devsw_installed = 1; + } +} + +SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL) +#endif /* __FreeBSD__ */ +#endif /* NI4B > 0 */ diff --git a/sys/i4b/layer4/i4b_l4.c b/sys/i4b/layer4/i4b_l4.c new file mode 100644 index 0000000..cecd5f4 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4.c @@ -0,0 +1,897 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4.c - kernel interface to userland + * ----------------------------------------- + * + * $Id: i4b_l4.c,v 1.33 1998/12/05 18:05:49 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:16 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" +#include "i4bipr.h" +#include "i4bisppp.h" +#include "i4brbch.h" +#include "i4btel.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer4/i4b_l4.h> + +unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT; + +struct ctrl_type_desc ctrl_types[CTRL_NUMTYPES] = { { NULL, NULL} }; + +static int i4b_link_bchandrvr(call_desc_t *cd); +static void i4b_unlink_bchandrvr(call_desc_t *cd); +static void i4b_l4_setup_timeout(call_desc_t *cd); + +/*---------------------------------------------------------------------------* + * send MSG_PDEACT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_pdeact(int controller, int numactive) +{ + struct mbuf *m; + int i; + call_desc_t *cd; + + for(i=0; i < N_CALL_DESC; i++) + { + if((call_desc[i].cdid != CDID_UNUSED) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == controller)) + { + cd = &call_desc[i]; + + if(cd->timeout_active) + { +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, cd->idle_timeout_handle); +#else + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd); +#endif + } + + if(cd->dlt != NULL) + { + (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); + i4b_unlink_bchandrvr(cd); + } + + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; + } + + cd->cdid = CDID_UNUSED; + } + } + + if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL) + { + msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data; + + md->header.type = MSG_PDEACT_IND; + md->header.cdid = -1; + + md->controller = controller; + md->numactive = numactive; + + i4bputqueue_hipri(m); /* URGENT !!! */ + } +} + +/*---------------------------------------------------------------------------* + * send MSG_L12STAT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_l12stat(int controller, int layer, int state) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL) + { + msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data; + + md->header.type = MSG_L12STAT_IND; + md->header.cdid = -1; + + md->controller = controller; + md->layer = layer; + md->state = state; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_TEIASG_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_teiasg(int controller, int tei) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL) + { + msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data; + + md->header.type = MSG_TEIASG_IND; + md->header.cdid = -1; + + md->controller = controller; + md->tei = ctrl_desc[controller].tei; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DIALOUT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_dialout(int driver, int driver_unit) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL) + { + msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data; + + md->header.type = MSG_DIALOUT_IND; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_NEGOTIATION_COMPL message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_negcomplete(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL) + { + msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data; + + md->header.type = MSG_NEGCOMP_IND; + md->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_IFSTATE_CHANGED_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_ifstate_changed(call_desc_t *cd, int new_state) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL) + { + msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data; + + md->header.type = MSG_IFSTATE_CHANGED_IND; + md->header.cdid = cd->cdid; + md->state = new_state; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DRVRDISC_REQ message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_drvrdisc(int driver, int driver_unit) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL) + { + msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data; + + md->header.type = MSG_DRVRDISC_REQ; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_ACCT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes, + int iinbytes, int ro, int ri, int outbytes, int inbytes) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL) + { + msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data; + + md->header.type = MSG_ACCT_IND; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + md->accttype = accttype; + md->ioutbytes = ioutbytes; + md->iinbytes = iinbytes; + md->outbps = ro; + md->inbps = ri; + md->outbytes = outbytes; + md->inbytes = inbytes; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CONNECT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_connect_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL) + { + msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data; + + mp->header.type = MSG_CONNECT_IND; + mp->header.cdid = cd->cdid; + + mp->controller = cd->controller; + mp->channel = cd->channelid; + mp->bprot = cd->bprot; + + cd->dir = DIR_INCOMING; + + if(strlen(cd->dst_telno) > 0) + strcpy(mp->dst_telno, cd->dst_telno); + else + strcpy(mp->dst_telno, TELNO_EMPTY); + + if(strlen(cd->src_telno) > 0) + strcpy(mp->src_telno, cd->src_telno); + else + strcpy(mp->src_telno, TELNO_EMPTY); + + strcpy(mp->display, cd->display); + + mp->scr_ind = cd->scr_ind; + + T400_start(cd); + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CONNECT_ACTIVE_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_connect_active_ind(call_desc_t *cd) +{ + int s; + struct mbuf *m; + + s = SPLI4B(); + + cd->last_active_time = cd->connect_time = SECOND; + + DBGL4(L4_TIMO, "i4b_l4_connect_active_ind", ("last_active/connect_time=%ld\n", (long)cd->connect_time)); + + i4b_link_bchandrvr(cd); + + (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd); + + i4b_l4_setup_timeout(cd); + + splx(s); + + if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL) + { + msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data; + + mp->header.type = MSG_CONNECT_ACTIVE_IND; + mp->header.cdid = cd->cdid; + mp->controller = cd->controller; + mp->channel = cd->channelid; + if(cd->datetime[0] != '\0') + strcpy(mp->datetime, cd->datetime); + else + mp->datetime[0] = '\0'; + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DISCONNECT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_disconnect_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if(cd->timeout_active) +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, cd->idle_timeout_handle); +#else + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd); +#endif + + if(cd->dlt != NULL) + { + (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); + i4b_unlink_bchandrvr(cd); + } + + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; + } + else + { + /* no error, might be hunting call for callback */ + DBGL4(L4_MSG, "i4b_l4_disconnect_ind", ("channel free not B1/B2 but %d!\n", cd->channelid)); + } + + if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL) + { + msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data; + + mp->header.type = MSG_DISCONNECT_IND; + mp->header.cdid = cd->cdid; + mp->cause = cd->cause_in; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_IDLE_TIMEOUT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_idle_timeout_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL) + { + msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data; + + mp->header.type = MSG_IDLE_TIMEOUT_IND; + mp->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CHARGING_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_charging_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL) + { + msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data; + + mp->header.type = MSG_CHARGING_IND; + mp->header.cdid = cd->cdid; + mp->units_type = cd->units_type; + +/*XXX*/ if(mp->units_type == CHARGE_CALC) + mp->units = cd->cunits; + else + mp->units = cd->units; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_STATUS_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_status_ind(call_desc_t *cd) +{ +} + +/*---------------------------------------------------------------------------* + * send MSG_ALERT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_alert_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL) + { + msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data; + + mp->header.type = MSG_ALERT_IND; + mp->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_INFO_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_info_ind(call_desc_t *cd) +{ +} + +/*---------------------------------------------------------------------------* + * send MSG_INFO_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_proceeding_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL) + { + msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data; + + mp->header.type = MSG_PROCEEDING_IND; + mp->header.cdid = cd->cdid; + mp->controller = cd->controller; + mp->channel = cd->channelid; + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * link a driver(unit) to a B-channel(controller,unit,channel) + *---------------------------------------------------------------------------*/ +static int +i4b_link_bchandrvr(call_desc_t *cd) +{ + int t = ctrl_desc[cd->controller].ctrl_type; + + if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL) + { + cd->ilt = NULL; + } + else + { + cd->ilt = ctrl_types[t].get_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid); + } + + switch(cd->driver) + { +#if NI4BRBCH > 0 + case BDRV_RBCH: + cd->dlt = rbch_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BTEL > 0 + case BDRV_TEL: + cd->dlt = tel_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BIPR > 0 + case BDRV_IPR: + cd->dlt = ipr_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BISPPP > 0 + case BDRV_ISPPP: + cd->dlt = i4bisppp_ret_linktab(cd->driver_unit); + break; +#endif + + default: + cd->dlt = NULL; + break; + } + + if(cd->dlt == NULL || cd->ilt == NULL) + return(-1); + + if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL) + { + ctrl_types[t].set_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid, + cd->dlt); + } + + switch(cd->driver) + { +#if NI4BRBCH > 0 + case BDRV_RBCH: + rbch_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BTEL > 0 + case BDRV_TEL: + tel_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BIPR > 0 + case BDRV_IPR: + ipr_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BISPPP > 0 + case BDRV_ISPPP: + i4bisppp_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + default: + return(0); + break; + } + + /* activate B channel */ + + (*cd->ilt->bch_config)(ctrl_desc[cd->controller].unit, + cd->channelid, cd->bprot, 1); + + return(0); +} + +/*---------------------------------------------------------------------------* + * unlink a driver(unit) from a B-channel(controller,unit,channel) + *---------------------------------------------------------------------------*/ +static void +i4b_unlink_bchandrvr(call_desc_t *cd) +{ + int t = ctrl_desc[cd->controller].ctrl_type; + + if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL) + { + cd->ilt = NULL; + return; + } + else + { + cd->ilt = ctrl_types[t].get_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid); + } + + /* deactivate B channel */ + + (*cd->ilt->bch_config)(ctrl_desc[cd->controller].unit, + cd->channelid, cd->bprot, 0); +} + +/*--------------------------------------------------------------------------- + + How shorthold mode works for OUTGOING connections + ================================================= + + |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>| + +idletime_state: IST_NONCHK IST_CHECK IST_SAFE + + | | | | + time>>+-------------------------------+---------------+---------------+-... + | | | | + | |<--idle_time-->|<--earlyhup--->| + |<-----------------------unitlen------------------------------->| + + + unitlen - specifies the time a charging unit lasts + idle_time - specifies the thime the line must be idle at the + end of the unit to be elected for hangup + earlyhup - is the beginning of a timing safety zone before the + next charging unit starts + + The algorithm works as follows: lets assume the unitlen is 100 + secons, idle_time is 40 seconds and earlyhup is 10 seconds. + The line then must be idle 50 seconds after the begin of the + current unit and it must then be quiet for 40 seconds. if it + has been quiet for this 40 seconds, the line is closed 10 + seconds before the next charging unit starts. In case there was + any traffic within the idle_time, the line is not closed. + It does not matter whether there was any traffic between second + 0 and second 50 or not. + + + How shorthold mode works for INCOMING connections + ================================================= + + it is just possible to specify a maximum idle time for incoming + connections, after this time of no activity on the line the line + is closed. + +---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------* + * B channel idle check timeout setup + *---------------------------------------------------------------------------*/ +static void +i4b_l4_setup_timeout(call_desc_t *cd) +{ + cd->timeout_active = 0; + cd->idletime_state = IST_IDLE; + + if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0)) + { + /* incoming call: simple max idletime check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: incoming-call, setup max_idle_time to %ld\n", (long)SECOND, (long)cd->max_idle_time)); + } + else if((cd->dir == DIR_OUTGOING) && (cd->idle_time > 0)) + { + /* outgoing call */ + + if((cd->idle_time > 0) && (cd->unitlen_time == 0)) + { + /* outgoing call: simple max idletime check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: outgoing-call, setup idle_time to %ld\n", (long)SECOND, (long)cd->idle_time)); + } + else if((cd->unitlen_time > 0) && (cd->unitlen_time > (cd->idle_time + cd->earlyhup_time))) + { + /* outgoing call: full shorthold mode check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->unitlen_time - (cd->idle_time + cd->earlyhup_time))); + cd->timeout_active = 1; + cd->idletime_state = IST_NONCHK; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: outgoing-call, start %ld sec nocheck window\n", + (long)SECOND, (long)(cd->unitlen_time - (cd->idle_time + cd->earlyhup_time)))); + + if(cd->aocd_flag == 0) + { + cd->units_type = CHARGE_CALC; + cd->cunits++; + i4b_l4_charging_ind(cd); + } + } + else + { + /* parms somehow got wrong .. */ + + DBGL4(L4_ERR, "i4b_l4_setup_timeout", ("%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!\n", + (long)SECOND, (long)cd->idle_time, (long)cd->earlyhup_time, (long)cd->unitlen_time)); + } + } + else + { + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("no idle_timeout configured\n")); + } +} + +/*---------------------------------------------------------------------------* + * B channel idle check timeout function + *---------------------------------------------------------------------------*/ +void +i4b_idle_check(call_desc_t *cd) +{ + int s; + + if(cd->cdid == CDID_UNUSED) + return; + + s = SPLI4B(); + + /* failsafe */ + + if(cd->timeout_active == 0) + { + DBGL4(L4_ERR, "i4b_idle_check", ("ERROR: timeout_active == 0 !!!\n")); + } + else + { + cd->timeout_active = 0; + } + + /* incoming connections, simple idletime check */ + + if(cd->dir == DIR_INCOMING) + { + if((cd->last_active_time + cd->max_idle_time) <= SECOND) + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: incoming-call, line idle timeout, disconnecting!\n", (long)SECOND)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + } + else + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: incoming-call, activity, last_active=%ld, max_idle=%ld\n", (long)SECOND, (long)cd->last_active_time, (long)cd->max_idle_time)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + } + } + + /* outgoing connections */ + + else if(cd->dir == DIR_OUTGOING) + { + + /* simple idletime calculation */ + + if((cd->idle_time > 0) && (cd->unitlen_time == 0)) + { + if((cd->last_active_time + cd->idle_time) <= SECOND) + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call-st, idle timeout, disconnecting!\n", (long)SECOND)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + } + else + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld\n", + (long)SECOND, (long)cd->last_active_time, (long)cd->idle_time)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + } + } + + /* full shorthold mode calculation */ + + else if((cd->unitlen_time > 0) && (cd->unitlen_time > (cd->idle_time + cd->earlyhup_time))) + { + switch(cd->idletime_state) + { + case IST_NONCHK: /* end of non-check time */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->idle_time)); + cd->idletimechk_start = SECOND; + cd->idletime_state = IST_CHECK; + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, idletime check window reached!\n", (long)SECOND)); + break; + + case IST_CHECK: /* end of idletime chk */ + if((cd->last_active_time > cd->idletimechk_start) && + (cd->last_active_time <= SECOND)) + { /* activity detected */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->earlyhup_time)); + cd->timeout_active = 1; + cd->idletime_state = IST_SAFE; + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, activity at %ld, wait earlyhup-end\n", (long)SECOND, (long)cd->last_active_time)); + } + else + { /* no activity, hangup */ + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, idle timeout, last activity at %ld\n", (long)SECOND, (long)cd->last_active_time)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + cd->idletime_state = IST_IDLE; + } + break; + + case IST_SAFE: /* end of earlyhup time */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->unitlen_time - (cd->idle_time+cd->earlyhup_time))); + cd->timeout_active = 1; + cd->idletime_state = IST_NONCHK; + + if(cd->aocd_flag == 0) + { + cd->units_type = CHARGE_CALC; + cd->cunits++; + i4b_l4_charging_ind(cd); + } + + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, earlyhup end, wait for idletime start\n", (long)SECOND)); + break; + + default: + DBGL4(L4_ERR, "i4b_idle_check", ("outgoing-call: invalid idletime_state value!\n")); + cd->idletime_state = IST_IDLE; + break; + } + } + } + splx(s); +} + +#endif /* NI4B > 0 */ diff --git a/sys/i4b/layer4/i4b_l4.h b/sys/i4b/layer4/i4b_l4.h new file mode 100644 index 0000000..e4ed863f --- /dev/null +++ b/sys/i4b/layer4/i4b_l4.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4.h - kernel interface to userland header file + * --------------------------------------------------- + * + * $Id: i4b_l4.h,v 1.13 1998/12/05 18:05:50 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:34 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L4_H_ +#define _I4B_L4_H_ + +extern void i4bputqueue ( struct mbuf *m ); +extern void i4bputqueue_hipri(struct mbuf *m); +extern void i4b_l4_accounting(int, int, int, int, int, int, int, int, int); +extern void i4b_l4_alert_ind ( call_desc_t *cd ); +extern void i4b_l4_charging_ind( call_desc_t *cd ); +extern void i4b_l4_connect_active_ind ( call_desc_t *cd ); +extern void i4b_l4_connect_ind ( call_desc_t *cd ); +extern void i4b_l4_daemon_attached(void); +extern void i4b_l4_daemon_detached(void); +extern void i4b_l4_dialout( int driver, int driver_unit ); +extern void i4b_l4_disconnect_ind ( call_desc_t *cd ); +extern void i4b_l4_drvrdisc (int driver, int driver_unit ); +extern void i4b_l4_negcomplete( call_desc_t *cd ); +extern void i4b_l4_ifstate_changed( call_desc_t *cd, int new_state ); +extern void i4b_l4_idle_timeout_ind( call_desc_t *cd ); +extern void i4b_l4_info_ind ( call_desc_t *cd ); +extern void i4b_l4_l12stat(int controller, int layer, int state); +extern void i4b_l4_pdeact(int controller, int numactive); +extern void i4b_l4_teiasg(int controller, int tei); +extern void i4b_l4_status_ind ( call_desc_t *cd ); +extern void i4b_l4_proceeding_ind ( call_desc_t *cd ); +extern void i4b_idle_check(call_desc_t *cdp); +extern call_desc_t * cd_by_cdid ( unsigned int cdid ); +extern call_desc_t * cd_by_unitcr ( int unit, int cr, int crf ); +extern void freecd_by_cd ( call_desc_t *cd ); +extern unsigned char get_rand_cr ( int unit ); +extern call_desc_t * reserve_cd ( void ); +extern void T400_start ( call_desc_t *cd ); +extern void T400_stop ( call_desc_t *cd ); + +#endif /* _I4B_L4_H_ */ diff --git a/sys/i4b/layer4/i4b_l4mgmt.c b/sys/i4b/layer4/i4b_l4mgmt.c new file mode 100644 index 0000000..e8e1a96 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4mgmt.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4mgmt.c - layer 4 calldescriptor management utilites + * ----------------------------------------------------------- + * + * $Id: i4b_l4mgmt.c,v 1.23 1998/12/05 18:05:52 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:50 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <machine/random.h> +#endif +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer4/i4b_l4.h> + +call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */ + +static unsigned int get_cdid(void); + +int nctrl; /* number of attached controllers */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +void init_callout(call_desc_t *); +#endif + +/*---------------------------------------------------------------------------* + * return a new unique call descriptor id + * -------------------------------------- + * returns a new calldescriptor id which is used to uniquely identyfy + * a single call in the communication between kernel and userland. + * this cdid is then used to associate a calldescriptor with an id. + *---------------------------------------------------------------------------*/ +static unsigned int +get_cdid(void) +{ + static unsigned int cdid_count = 0; + int i; + int x; + + x = SPLI4B(); + + /* get next id */ + + cdid_count++; + +again: + if(cdid_count == CDID_UNUSED) /* zero is invalid */ + cdid_count++; + else if(cdid_count > CDID_MAX) /* wraparound ? */ + cdid_count = 1; + + /* check if id already in use */ + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == cdid_count) + { + cdid_count++; + goto again; + } + } + + splx(x); + + return(cdid_count); +} + +/*---------------------------------------------------------------------------* + * reserve a calldescriptor for later usage + * ---------------------------------------- + * searches the calldescriptor array until an unused + * descriptor is found, gets a new calldescriptor id + * and reserves it by putting the id into the cdid field. + * returns pointer to the calldescriptor. + *---------------------------------------------------------------------------*/ +call_desc_t * +reserve_cd(void) +{ + call_desc_t *cd; + int x; + int i; + + x = SPLI4B(); + + cd = NULL; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == CDID_UNUSED) + { + bzero(&call_desc[i], sizeof(call_desc_t)); /* clear it */ + call_desc[i].cdid = get_cdid(); /* fill in new cdid */ + cd = &(call_desc[i]); /* get pointer to descriptor */ + DBGL4(L4_MSG, "reserve_cd", ("found free cd - index=%d cdid=%u\n", + i, call_desc[i].cdid)); + break; + } + } + + splx(x); + + if(cd == NULL) + panic("reserve_cd: no free call descriptor available!"); + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(cd); +#endif + + return(cd); +} + +/*---------------------------------------------------------------------------* + * free a calldescriptor + * --------------------- + * free a unused calldescriptor by giving address of calldescriptor + * and writing a 0 into the cdid field marking it as unused. + *---------------------------------------------------------------------------*/ +void +freecd_by_cd(call_desc_t *cd) +{ + int i; + int x = SPLI4B(); + + for(i=0; i < N_CALL_DESC; i++) + { + if( (call_desc[i].cdid != CDID_UNUSED) && + (&(call_desc[i]) == cd) ) + { + DBGL4(L4_MSG, "freecd_by_cd", ("releasing cd - index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, cd->cr)); + call_desc[i].cdid = CDID_UNUSED; + break; + } + } + + if(i == N_CALL_DESC) + panic("freecd_by_cd: ERROR, cd not found, cr = %d\n", cd->cr); + + splx(x); +} + +/*---------------------------------------------------------------------------* + * return pointer to calldescriptor by giving the calldescriptor id + * ---------------------------------------------------------------- + * lookup a calldescriptor in the calldescriptor array by looking + * at the cdid field. return pointer to calldescriptor if found, + * else return NULL if not found. + *---------------------------------------------------------------------------*/ +call_desc_t * +cd_by_cdid(unsigned int cdid) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == cdid) + { + DBGL4(L4_MSG, "cd_by_cdid", ("found cdid - index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, call_desc[i].cr)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(&call_desc[i]); +#endif + return(&(call_desc[i])); + } + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * search calldescriptor + * --------------------- + * This routine searches for the calldescriptor for a passive controller + * given by unit number, callreference and callreference flag. + * It returns a pointer to the calldescriptor if found, else a NULL. + *---------------------------------------------------------------------------*/ +call_desc_t * +cd_by_unitcr(int unit, int cr, int crf) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if((call_desc[i].cdid != CDID_UNUSED) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit) && + (call_desc[i].cr == cr) && + (call_desc[i].crflag == crf) ) + { + DBGL4(L4_MSG, "cd_by_unitcr", ("found cd, index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, call_desc[i].cr)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(&call_desc[i]); +#endif + return(&(call_desc[i])); + } + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * generate 7 bit "random" number used for outgoing Call Reference + *---------------------------------------------------------------------------*/ +unsigned char +get_rand_cr(int unit) +{ + register int i, j; + static u_char val, retval; + static int called = 42; + + val += ++called; + + for(i=0; i < 50 ; i++, val++) + { + int found = 1; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + read_random((char *)&val, sizeof(val)); +#else + val |= unit+i; + val <<= i; + val ^= (time.tv_sec >> 8) ^ time.tv_usec; + val <<= i; + val ^= time.tv_sec ^ (time.tv_usec >> 8); +#endif + + retval = val & 0x7f; + + if(retval == 0 || retval == 0x7f) + continue; + + for(j=0; j < N_CALL_DESC; j++) + { + if( (call_desc[j].cdid != CDID_UNUSED) && + (call_desc[j].cr == retval) ) + { + found = 0; + break; + } + } + + if(found) + return(retval); + } + return(0); /* XXX */ +} + +/*---------------------------------------------------------------------------* + * initialize the callout handles for FreeBSD-current 3.0 + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +void +init_callout(call_desc_t *cd) +{ + if(cd->callouts_inited == 0) + { + callout_handle_init(&cd->idle_timeout_handle); + callout_handle_init(&cd->T303_callout); + callout_handle_init(&cd->T305_callout); + callout_handle_init(&cd->T308_callout); + callout_handle_init(&cd->T309_callout); + callout_handle_init(&cd->T310_callout); + callout_handle_init(&cd->T313_callout); + callout_handle_init(&cd->T400_callout); + cd->callouts_inited = 1; + } +} +#endif + +/*---------------------------------------------------------------------------* + * daemon is attached + *---------------------------------------------------------------------------*/ +void +i4b_l4_daemon_attached(void) +{ + int i; + + int x = SPLI4B(); + + for(i=0; i < nctrl; i++) + { +/*XXX*/ if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE) + { + DBGL4(L4_MSG, "i4b_l4_daemon_attached", ("CMR_DOPEN sent to unit %d\n", ctrl_desc[i].unit)); + + (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DOPEN, 0); + } + } + splx(x); +} + +/*---------------------------------------------------------------------------* + * daemon is detached + *---------------------------------------------------------------------------*/ +void +i4b_l4_daemon_detached(void) +{ + int i; + + int x = SPLI4B(); + + for(i=0; i < nctrl; i++) + { +/*XXX*/ if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE) + { + DBGL4(L4_MSG, "i4b_l4_daemon_detached", ("CMR_DCLOSE sent to unit %d\n", ctrl_desc[i].unit)); + + (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DCLOSE, 0); + } + } + splx(x); +} + +#ifdef I4B_CD_DEBUG_PRINT + +extern char *print_l3state(call_desc_t *cd); + +void i4b_print_cdp(call_desc_t *cdp); +void i4b_print_cdx(int index); +void i4b_print_cda(void); +void i4b_print_cdaa(void); + +/*---------------------------------------------------------------------------* + * print a call descriptor by cd-pointer + *---------------------------------------------------------------------------*/ +void +i4b_print_cdp(call_desc_t *cdp) +{ + if((cdp > &(call_desc[N_CALL_DESC])) || (cdp < &(call_desc[0]))) + { + printf("i4b_print_cd: cdp out of range!\n"); + return; + } + + printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp - (&(call_desc[0])), (unsigned long)cdp); + + printf(" cdid = %d\n", cdp->cdid); + printf(" controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n", + cdp->controller, + ctrl_desc[cdp->controller].unit, + ctrl_desc[cdp->controller].dl_est, + ctrl_desc[cdp->controller].bch_state[CHAN_B1], + ctrl_desc[cdp->controller].bch_state[CHAN_B2]); + printf(" cr = 0x%02x\n", cdp->cr); + printf(" crflag = %d\n", cdp->crflag); + printf(" channelid = %d\n", cdp->channelid); + printf(" bprot = %d\n", cdp->bprot); + printf(" driver = %d\n", cdp->driver); + printf(" driver_unit = %d\n", cdp->driver_unit); + printf(" call_state = %d\n", cdp->call_state); + printf(" Q931state = %s\n", print_l3state(cdp)); + printf(" event = %d\n", cdp->event); + printf(" response = %d\n", cdp->response); + printf(" T303 = %d\n", cdp->T303); + printf("T303_first_to = %d\n", cdp->T303_first_to); + printf(" T305 = %d\n", cdp->T305); + printf(" T308 = %d\n", cdp->T308); + printf("T308_first_to = %d\n", cdp->T308_first_to); + printf(" T309 = %d\n", cdp->T309); + printf(" T310 = %d\n", cdp->T310); + printf(" T313 = %d\n", cdp->T313); + printf(" T400 = %d\n", cdp->T400); + printf(" dir = %s\n", cdp->dir == DIR_OUTGOING ? "out" : "in"); +} + +/*---------------------------------------------------------------------------* + * print a call descriptor by index + *---------------------------------------------------------------------------*/ +void +i4b_print_cdx(int index) +{ + if(index >= N_CALL_DESC) + { + printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index, N_CALL_DESC); + return; + } + i4b_print_cdp(&(call_desc[index])); +} + +/*---------------------------------------------------------------------------* + * print all call descriptors + *---------------------------------------------------------------------------*/ +void +i4b_print_cda(void) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + i4b_print_cdp(&(call_desc[i])); + } +} + +/*---------------------------------------------------------------------------* + * print all active call descriptors + *---------------------------------------------------------------------------*/ +void +i4b_print_cdaa(void) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid != CDID_UNUSED) + { + i4b_print_cdp(&(call_desc[i])); + } + } +} + +#endif /* I4B_CD_DEBUG_PRINT */ + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer4/i4b_l4timer.c b/sys/i4b/layer4/i4b_l4timer.c new file mode 100644 index 0000000..7a38e13 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4timer.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4timer.c - timer and timeout handling for layer 4 + * -------------------------------------------------------- + * + * $Id: i4b_l4timer.c,v 1.10 1998/12/05 18:05:53 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:07 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer4/i4b_l4.h> + +/*---------------------------------------------------------------------------* + * timer T400 timeout function + *---------------------------------------------------------------------------*/ +static void +T400_timeout(call_desc_t *cd) +{ + DBGL4(L4_ERR, "T400_timeout", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T400 start + *---------------------------------------------------------------------------*/ +void +T400_start(call_desc_t *cd) +{ + DBGL4(L4_MSG, "T400_start", ("cr = %d\n", cd->cr)); + + cd->T400 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T400_callout = timeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, T400DEF); +#else + timeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, T400DEF); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T400 stop + *---------------------------------------------------------------------------*/ +void +T400_stop(call_desc_t *cd) +{ + DBGL4(L4_MSG, "T400_stop", ("cr = %d\n", cd->cr)); + + if(cd->T400 == TIMER_ACTIVE) + { + cd->T400 = TIMER_IDLE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, cd->T400_callout); +#else + untimeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd); +#endif + } +} + +#endif /* NI4B > 0 */ |