summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer4/i4b_i4bdrv.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i4b/layer4/i4b_i4bdrv.c')
-rw-r--r--sys/i4b/layer4/i4b_i4bdrv.c832
1 files changed, 832 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 */
OpenPOWER on IntegriCloud