aboutsummaryrefslogtreecommitdiff
path: root/sys/i4b
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
commit19c749625fd37f8c5e890077c1d4bb1f82fbf726 (patch)
tree4b7a53adb1b0254fa926016dad9d614a0399e80a /sys/i4b
parent587c729bb366182252ca16e660b5b13fe69e304d (diff)
Notes
Diffstat (limited to 'sys/i4b')
-rw-r--r--sys/i4b/driver/i4b_ctl.c303
-rw-r--r--sys/i4b/driver/i4b_ipr.c1115
-rw-r--r--sys/i4b/driver/i4b_isppp.c710
-rw-r--r--sys/i4b/driver/i4b_rbch.c820
-rw-r--r--sys/i4b/driver/i4b_tel.c713
-rw-r--r--sys/i4b/driver/i4b_trace.c508
-rw-r--r--sys/i4b/include/i4b_cause.h144
-rw-r--r--sys/i4b/include/i4b_debug.h219
-rw-r--r--sys/i4b/include/i4b_global.h95
-rw-r--r--sys/i4b/include/i4b_ioctl.h606
-rw-r--r--sys/i4b/include/i4b_isdnq931.h166
-rw-r--r--sys/i4b/include/i4b_l1l2.h99
-rw-r--r--sys/i4b/include/i4b_l2l3.h116
-rw-r--r--sys/i4b/include/i4b_l3l4.h260
-rw-r--r--sys/i4b/include/i4b_mbuf.h51
-rw-r--r--sys/i4b/include/i4b_tel_ioctl.h52
-rw-r--r--sys/i4b/include/i4b_trace.h91
-rw-r--r--sys/i4b/layer1/i4b_avm_a1.c508
-rw-r--r--sys/i4b/layer1/i4b_avm_fritz_pcmcia.c504
-rw-r--r--sys/i4b/layer1/i4b_bchan.c484
-rw-r--r--sys/i4b/layer1/i4b_ctx_s0P.c366
-rw-r--r--sys/i4b/layer1/i4b_drn_ngo.c542
-rw-r--r--sys/i4b/layer1/i4b_dynalink.c438
-rw-r--r--sys/i4b/layer1/i4b_elsa_isdnmc.c305
-rw-r--r--sys/i4b/layer1/i4b_elsa_mcall.c251
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1i.c511
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1p.c458
-rw-r--r--sys/i4b/layer1/i4b_hscx.c672
-rw-r--r--sys/i4b/layer1/i4b_hscx.h301
-rw-r--r--sys/i4b/layer1/i4b_ipac.h199
-rw-r--r--sys/i4b/layer1/i4b_isac.c679
-rw-r--r--sys/i4b/layer1/i4b_isac.h391
-rw-r--r--sys/i4b/layer1/i4b_isic.c345
-rw-r--r--sys/i4b/layer1/i4b_isic_isa.c591
-rw-r--r--sys/i4b/layer1/i4b_isic_pci.c424
-rw-r--r--sys/i4b/layer1/i4b_isic_pcmcia.c164
-rw-r--r--sys/i4b/layer1/i4b_isic_pnp.c296
-rw-r--r--sys/i4b/layer1/i4b_itk_ix1.c430
-rw-r--r--sys/i4b/layer1/i4b_l1.c315
-rw-r--r--sys/i4b/layer1/i4b_l1.h438
-rw-r--r--sys/i4b/layer1/i4b_l1fsm.c546
-rw-r--r--sys/i4b/layer1/i4b_sws.c392
-rw-r--r--sys/i4b/layer1/i4b_tel_s016.c455
-rw-r--r--sys/i4b/layer1/i4b_tel_s0163.c432
-rw-r--r--sys/i4b/layer1/i4b_tel_s08.c389
-rw-r--r--sys/i4b/layer1/i4b_tel_s0P.c378
-rw-r--r--sys/i4b/layer1/i4b_usr_sti.c440
-rw-r--r--sys/i4b/layer1/isa_isic.c828
-rw-r--r--sys/i4b/layer1/isapnp_isic.c386
-rw-r--r--sys/i4b/layer1/isic_supio.c374
-rw-r--r--sys/i4b/layer1/pci_isic.c327
-rw-r--r--sys/i4b/layer1/pcmcia_isic.c358
-rw-r--r--sys/i4b/layer1/pcmcia_isic.h60
-rw-r--r--sys/i4b/layer2/i4b_iframe.c275
-rw-r--r--sys/i4b/layer2/i4b_l2.c390
-rw-r--r--sys/i4b/layer2/i4b_l2.h339
-rw-r--r--sys/i4b/layer2/i4b_l2fsm.c1593
-rw-r--r--sys/i4b/layer2/i4b_l2fsm.h82
-rw-r--r--sys/i4b/layer2/i4b_l2timer.c263
-rw-r--r--sys/i4b/layer2/i4b_lme.c160
-rw-r--r--sys/i4b/layer2/i4b_mbuf.c245
-rw-r--r--sys/i4b/layer2/i4b_sframe.c215
-rw-r--r--sys/i4b/layer2/i4b_tei.c322
-rw-r--r--sys/i4b/layer2/i4b_uframe.c308
-rw-r--r--sys/i4b/layer2/i4b_util.c312
-rw-r--r--sys/i4b/layer3/i4b_l2if.c642
-rw-r--r--sys/i4b/layer3/i4b_l3.h80
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.c1034
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.h105
-rw-r--r--sys/i4b/layer3/i4b_l3timer.c347
-rw-r--r--sys/i4b/layer3/i4b_l4if.c339
-rw-r--r--sys/i4b/layer3/i4b_q931.c624
-rw-r--r--sys/i4b/layer3/i4b_q931.h116
-rw-r--r--sys/i4b/layer3/i4b_q932fac.c569
-rw-r--r--sys/i4b/layer3/i4b_q932fac.h167
-rw-r--r--sys/i4b/layer4/i4b_i4bdrv.c832
-rw-r--r--sys/i4b/layer4/i4b_l4.c897
-rw-r--r--sys/i4b/layer4/i4b_l4.h69
-rw-r--r--sys/i4b/layer4/i4b_l4mgmt.c467
-rw-r--r--sys/i4b/layer4/i4b_l4timer.c110
-rw-r--r--sys/i4b/tina-dd/README20
-rw-r--r--sys/i4b/tina-dd/i4b_tina_dd.c330
-rw-r--r--sys/i4b/tina-dd/i4b_tina_ioctl.h138
83 files changed, 32435 insertions, 0 deletions
diff --git a/sys/i4b/driver/i4b_ctl.c b/sys/i4b/driver/i4b_ctl.c
new file mode 100644
index 000000000000..56bcb02c2651
--- /dev/null
+++ b/sys/i4b/driver/i4b_ctl.c
@@ -0,0 +1,303 @@
+/*
+ * 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_ctl.c - i4b system control port driver
+ * ------------------------------------------
+ *
+ * $Id: i4b_ctl.c,v 1.17 1998/12/05 18:02:39 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 17:59:15 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4bctl.h"
+
+#if NI4BCTL > 1
+#error "only 1 (one) i4bctl device allowed!"
+#endif
+
+#if NI4BCTL > 0
+
+#include <sys/param.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#include <i386/isa/isa_device.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 "opt_devfs.h"
+#endif
+
+#ifdef DEVFS
+#include <sys/devfsext.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/layer1/i4b_l1.h>
+
+static int openflag = 0;
+
+#if BSD > 199306 && defined(__FreeBSD__)
+static d_open_t i4bctlopen;
+static d_close_t i4bctlclose;
+static d_ioctl_t i4bctlioctl;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+static d_poll_t i4bctlpoll;
+#endif
+
+#define CDEV_MAJOR 55
+static struct cdevsw i4bctl_cdevsw =
+ { i4bctlopen, i4bctlclose, noread, nowrite,
+ i4bctlioctl, nostop, nullreset, nodevtotty,
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ i4bctlpoll, nommap, NULL, "i4bctl", NULL, -1 };
+#else
+ noselect, nommap, NULL, "i4bctl", NULL, -1 };
+#endif
+
+static void i4bctlattach(void *);
+PSEUDO_SET(i4bctlattach, i4b_i4bctldrv);
+
+#define PDEVSTATIC static
+#endif /* __FreeBSD__ */
+
+#ifdef DEVFS
+static void *devfs_token;
+#endif
+
+#ifndef __FreeBSD__
+#define PDEVSTATIC /* */
+void i4bctlattach __P((void));
+int i4bctlopen __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4bctlclose __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4bctlioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
+#endif /* !FreeBSD */
+
+#if BSD > 199306 && defined(__FreeBSD__)
+/*---------------------------------------------------------------------------*
+ * initialization at kernel load time
+ *---------------------------------------------------------------------------*/
+static void
+i4bctlinit(void *unused)
+{
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+
+ cdevsw_add(&dev, &i4bctl_cdevsw, NULL);
+}
+
+SYSINIT(i4bctldev, SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, &i4bctlinit, NULL);
+
+#endif /* BSD > 199306 && defined(__FreeBSD__) */
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4bctlattach(void *dummy)
+#else
+i4bctlattach()
+#endif
+{
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+ printf("i4bctl: ISDN system control port attached\n");
+#endif
+#ifdef DEVFS
+ devfs_token = devfs_add_devswf(&i4bctl_cdevsw, 0, DV_CHR,
+ UID_ROOT, GID_WHEEL, 0600,
+ "i4bctl", 0);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * i4bctlopen - device driver open routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4bctlopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ if(minor(dev))
+ return (ENXIO);
+
+ if(openflag)
+ return (EBUSY);
+
+ openflag = 1;
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4bctlclose - device driver close routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4bctlclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ openflag = 0;
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4bctlioctl - device driver ioctl routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
+i4bctlioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+#else
+i4bctlioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+#endif
+{
+ ctl_debug_t *cdbg;
+ int error = 0;
+
+#ifndef DO_I4B_DEBUG
+ return(ENODEV);
+#else
+ if(minor(dev))
+ return(ENODEV);
+
+ switch(cmd)
+ {
+ case I4B_CTL_GET_DEBUG:
+ cdbg = (ctl_debug_t *)data;
+ cdbg->l1 = i4b_l1_debug;
+ cdbg->l2 = i4b_l2_debug;
+ cdbg->l3 = i4b_l3_debug;
+ cdbg->l4 = i4b_l4_debug;
+ break;
+
+ case I4B_CTL_SET_DEBUG:
+ cdbg = (ctl_debug_t *)data;
+ i4b_l1_debug = cdbg->l1;
+ i4b_l2_debug = cdbg->l2;
+ i4b_l3_debug = cdbg->l3;
+ i4b_l4_debug = cdbg->l4;
+ break;
+
+ case I4B_CTL_GET_HSCXSTAT:
+ {
+ hscxstat_t *hst;
+ struct isic_softc *sc;
+ hst = (hscxstat_t *)data;
+
+ if( hst->unit < 0 ||
+ hst->unit > ISIC_MAXUNIT ||
+ hst->chan < 0 ||
+ hst->chan > 1 )
+ {
+ error = EINVAL;
+ break;
+ }
+
+#ifndef __FreeBSD__
+ sc = isic_find_sc(hst->unit);
+#else
+ sc = &isic_sc[hst->unit];
+#endif
+ hst->vfr = sc->sc_chan[hst->chan].stat_VFR;
+ hst->rdo = sc->sc_chan[hst->chan].stat_RDO;
+ hst->crc = sc->sc_chan[hst->chan].stat_CRC;
+ hst->rab = sc->sc_chan[hst->chan].stat_RAB;
+ hst->xdu = sc->sc_chan[hst->chan].stat_XDU;
+ hst->rfo = sc->sc_chan[hst->chan].stat_RFO;
+ break;
+ }
+
+ case I4B_CTL_CLR_HSCXSTAT:
+ {
+ hscxstat_t *hst;
+ struct isic_softc *sc;
+ hst = (hscxstat_t *)data;
+
+ if( hst->unit < 0 ||
+ hst->unit > ISIC_MAXUNIT ||
+ hst->chan < 0 ||
+ hst->chan > 1 )
+ {
+ error = EINVAL;
+ break;
+ }
+
+#ifndef __FreeBSD__
+ sc = isic_find_sc(hst->unit);
+#else
+ sc = &isic_sc[hst->unit];
+#endif
+
+ sc->sc_chan[hst->chan].stat_VFR = 0;
+ sc->sc_chan[hst->chan].stat_RDO = 0;
+ sc->sc_chan[hst->chan].stat_CRC = 0;
+ sc->sc_chan[hst->chan].stat_RAB = 0;
+ sc->sc_chan[hst->chan].stat_XDU = 0;
+ sc->sc_chan[hst->chan].stat_RFO = 0;
+
+ break;
+ }
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return(error);
+#endif DO_I4B_DEBUG
+}
+
+/*---------------------------------------------------------------------------*
+ * i4bctlpoll - device driver poll routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+static int
+i4bctlpoll (dev_t dev, int events, struct proc *p)
+{
+ return (ENODEV);
+}
+#endif
+
+#endif /* NI4BCTL > 0 */
diff --git a/sys/i4b/driver/i4b_ipr.c b/sys/i4b/driver/i4b_ipr.c
new file mode 100644
index 000000000000..df3977cb72af
--- /dev/null
+++ b/sys/i4b/driver/i4b_ipr.c
@@ -0,0 +1,1115 @@
+/*
+ * 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_ipr.c - isdn4bsd IP over raw HDLC ISDN network driver
+ * ---------------------------------------------------------
+ *
+ * $Id: i4b_ipr.c,v 1.42 1998/12/18 14:20:44 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 11:50:47 1998]
+ *
+ *---------------------------------------------------------------------------*
+ *
+ * statistics counter usage (interface lifetime):
+ * ----------------------------------------------
+ * sc->sc_if.if_ipackets # of received packets
+ * sc->sc_if.if_ierrors # of error packets not going to upper layers
+ * sc->sc_if.if_opackets # of transmitted packets
+ * sc->sc_if.if_oerrors # of error packets not being transmitted
+ * sc->sc_if.if_collisions # of invalid ip packets after VJ decompression
+ * sc->sc_if.if_ibytes # of bytes coming in from the line (before VJ)
+ * sc->sc_if.if_obytes # of bytes going out to the line (after VJ)
+ * sc->sc_if.if_imcasts (currently unused)
+ * sc->sc_if.if_omcasts # of frames sent out of the fastqueue
+ * sc->sc_if.if_iqdrops # of frames dropped on input because queue full
+ * sc->sc_if.if_noproto # of frames dropped on output because !AF_INET
+ *
+ * statistics counter usage (connection lifetime):
+ * -----------------------------------------------
+ * sc->sc_iinb # of ISDN incoming bytes from HSCX
+ * sc->sc_ioutb # of ISDN outgoing bytes from HSCX
+ * sc->sc_inb # of incoming bytes after decompression
+ * sc->sc_outb # of outgoing bytes before compression
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4bipr.h"
+
+#if NI4BIPR > 0
+
+#ifdef __FreeBSD__
+#include "opt_i4b.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#include <sys/sockio.h>
+#ifdef IPR_VJ
+#include <sys/malloc.h>
+#endif
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+
+#ifdef IPR_VJ
+#include <net/slcompress.h>
+#define IPR_COMPRESS IFF_LINK0 /* compress TCP traffic */
+#define IPR_AUTOCOMP IFF_LINK1 /* auto-enable TCP compression */
+
+/*---------------------------------------------------------------------------
+ * NOTICE: using NO separate buffer relies on the assumption, that the HSCX
+ * IRQ handler _always_ allocates a single, continuous mbuf cluster large
+ * enough to hold the maximum MTU size if the ipr interface !
+ *
+ * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems
+ * with 2 i4b's back to back running cvs over ssh, cvs simply
+ * aborts because it gets bad data. Everything else (telnet/ftp?etc)
+ * functions fine.
+ *---------------------------------------------------------------------------*/
+#define IPR_VJ_USEBUFFER /* define to use an allocated separate buffer*/
+ /* undef to uncompress in the mbuf itself */
+#endif /* IPR_VJ */
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <sys/time.h>
+#include <net/bpf.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_debug.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_l3l4.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#ifndef __FreeBSD__
+#include <machine/cpu.h> /* For softnet */
+#endif
+
+#ifdef __FreeBSD__
+#define IPR_FMT "ipr%d: "
+#define IPR_ARG(sc) ((sc)->sc_if.if_unit)
+#define PDEVSTATIC static
+#else
+#define IPR_FMT "%s: "
+#define IPR_ARG(sc) ((sc)->sc_if.if_xname)
+#define PDEVSTATIC /* not static */
+#endif
+
+#define I4BIPRMTU 1500 /* regular MTU */
+#define I4BIPRMAXMTU 2000 /* max MTU */
+#define I4BIPRMINMTU 500 /* min MTU */
+
+#define I4BIPRMAXQLEN 50 /* max queue length */
+
+#define I4BIPRACCT 1 /* enable accounting messages */
+#define I4BIPRACCTINTVL 2 /* accounting msg interval in secs */
+#define I4BIPRADJFRXP 1 /* adjust 1st rxd packet */
+
+/* initialized by L4 */
+
+static drvr_link_t ipr_drvr_linktab[NI4BIPR];
+static isdn_link_t *isdn_linktab[NI4BIPR];
+
+struct ipr_softc {
+ struct ifnet sc_if; /* network-visible interface */
+ int sc_state; /* state of the interface */
+
+#ifndef __FreeBSD__
+ int sc_unit; /* unit number for Net/OpenBSD */
+#endif
+
+ call_desc_t *sc_cdp; /* ptr to call descriptor */
+ int sc_updown; /* soft state of interface */
+ struct ifqueue sc_fastq; /* interactive traffic */
+ int sc_dialresp; /* dialresponse */
+ int sc_lastdialresp;/* last dialresponse */
+
+#if I4BIPRACCT
+ int sc_iinb; /* isdn driver # of inbytes */
+ int sc_ioutb; /* isdn driver # of outbytes */
+ int sc_inb; /* # of bytes rx'd */
+ int sc_outb; /* # of bytes tx'd */
+ int sc_linb; /* last # of bytes rx'd */
+ int sc_loutb; /* last # of bytes tx'd */
+ int sc_fn; /* flag, first null acct */
+#endif
+
+#ifdef I4BIPRADJFRXP
+ int sc_first_pkt; /* flag, first rxd packet */
+#endif
+
+#ifdef IPR_VJ
+ struct slcompress sc_compr; /* tcp compression data */
+#ifdef IPR_VJ_USEBUFFER
+ u_char *sc_cbuf; /* tcp decompression buffer */
+#endif
+#endif
+
+} ipr_softc[NI4BIPR];
+
+enum ipr_states {
+ ST_IDLE, /* initialized, ready, idle */
+ ST_DIALING, /* dialling out to remote */
+ ST_CONNECTED_W, /* connected to remote */
+ ST_CONNECTED_A, /* connected to remote */
+};
+
+#ifdef __FreeBSD__
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+# define IOCTL_CMD_T u_long
+#else
+# define IOCTL_CMD_T int
+#endif
+PDEVSTATIC void i4biprattach(void *);
+PSEUDO_SET(i4biprattach, i4b_ipr);
+static int i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
+#else
+PDEVSTATIC void i4biprattach __P((void));
+static int i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+#endif
+
+static void iprwatchdog(struct ifnet *ifp);
+static void ipr_init_linktab(int unit);
+static void ipr_tx_queue_empty(int unit);
+static int i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp);
+static void iprclearqueues(struct ipr_softc *sc);
+
+/*===========================================================================*
+ * DEVICE DRIVER ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine at kernel boot time
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4biprattach(void *dummy)
+#else
+i4biprattach()
+#endif
+{
+ struct ipr_softc *sc = ipr_softc;
+ int i;
+
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+#ifdef IPR_VJ
+ printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached (VJ header compression)\n", NI4BIPR);
+#else
+ printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached\n", NI4BIPR);
+#endif
+#endif
+
+ for(i=0; i < NI4BIPR; sc++, i++)
+ {
+ ipr_init_linktab(i);
+
+ DBGL4(L4_DIALST, "i4biprattach", ("setting dial state to ST_IDLE\n"));
+
+ sc->sc_state = ST_IDLE;
+
+#ifdef __FreeBSD__
+ sc->sc_if.if_name = "ipr";
+#if __FreeBSD__ < 3
+ sc->sc_if.if_next = NULL;
+#endif
+ sc->sc_if.if_unit = i;
+#else
+ sprintf(sc->sc_if.if_xname, "ipr%d", i);
+ sc->sc_if.if_softc = sc;
+ sc->sc_unit = i;
+#endif
+
+#ifdef IPR_VJ
+ sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX | IPR_AUTOCOMP;
+#else
+ sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX;
+#endif
+
+ sc->sc_if.if_mtu = I4BIPRMTU;
+ sc->sc_if.if_type = IFT_ISDNBASIC;
+ sc->sc_if.if_ioctl = i4biprioctl;
+ sc->sc_if.if_output = i4biproutput;
+
+ sc->sc_if.if_snd.ifq_maxlen = I4BIPRMAXQLEN;
+ sc->sc_fastq.ifq_maxlen = I4BIPRMAXQLEN;
+
+ sc->sc_if.if_ipackets = 0;
+ sc->sc_if.if_ierrors = 0;
+ sc->sc_if.if_opackets = 0;
+ sc->sc_if.if_oerrors = 0;
+ sc->sc_if.if_collisions = 0;
+ sc->sc_if.if_ibytes = 0;
+ sc->sc_if.if_obytes = 0;
+ sc->sc_if.if_imcasts = 0;
+ sc->sc_if.if_omcasts = 0;
+ sc->sc_if.if_iqdrops = 0;
+ sc->sc_if.if_noproto = 0;
+
+#if I4BIPRACCT
+ sc->sc_if.if_timer = 0;
+ sc->sc_if.if_watchdog = iprwatchdog;
+ sc->sc_iinb = 0;
+ sc->sc_ioutb = 0;
+ sc->sc_inb = 0;
+ sc->sc_outb = 0;
+ sc->sc_linb = 0;
+ sc->sc_loutb = 0;
+ sc->sc_fn = 1;
+#endif
+
+#ifdef IPR_VJ
+#ifdef __FreeBSD__
+ sl_compress_init(&sc->sc_compr, -1);
+#else
+ sl_compress_init(&sc->sc_compr);
+#endif
+
+#ifdef IPR_VJ_USEBUFFER
+ if(!((sc->sc_cbuf =
+ (u_char *)malloc(I4BIPRMAXMTU+128, M_DEVBUF, M_WAITOK))))
+ {
+ panic("if_ipr.c, ipr_attach: VJ malloc failed");
+ }
+#endif
+#endif
+
+ sc->sc_updown = SOFT_ENA; /* soft enabled */
+
+ sc->sc_dialresp = DSTAT_NONE; /* no response */
+ sc->sc_lastdialresp = DSTAT_NONE;
+
+ if_attach(&sc->sc_if);
+
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
+#else
+ bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL, sizeof(u_int));
+#endif
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * output a packet to the ISDN B-channel
+ *---------------------------------------------------------------------------*/
+static int
+i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+ struct rtentry *rtp)
+{
+ struct ipr_softc *sc;
+ int unit;
+ int s;
+ struct ifqueue *ifq;
+ struct ip *ip;
+
+ s = SPLI4B();
+
+#ifdef __FreeBSD__
+ unit = ifp->if_unit;
+ sc = &ipr_softc[unit];
+#else
+ sc = ifp->if_softc;
+ unit = sc->sc_unit;
+#endif
+
+ /* check for IP */
+
+ if(dst->sa_family != AF_INET)
+ {
+ printf(IPR_FMT "af%d not supported\n", IPR_ARG(sc), dst->sa_family);
+ m_freem(m);
+ splx(s);
+ sc->sc_if.if_noproto++;
+ sc->sc_if.if_oerrors++;
+ return(EAFNOSUPPORT);
+ }
+
+ /* check interface state = UP */
+
+ if(!(ifp->if_flags & IFF_UP))
+ {
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: interface is DOWN!\n", unit));
+ m_freem(m);
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ return(ENETDOWN);
+ }
+
+ /* dial if necessary */
+
+ if(sc->sc_state == ST_IDLE || sc->sc_state == ST_DIALING)
+ {
+
+#ifdef NOTDEF
+ switch(sc->sc_dialresp)
+ {
+ case DSTAT_TFAIL: /* transient failure */
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: transient dial failure!\n", unit));
+ m_freem(m);
+ iprclearqueues(sc);
+ sc->sc_dialresp = DSTAT_NONE;
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ return(ENETUNREACH);
+ break;
+
+ case DSTAT_PFAIL: /* permanent failure */
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: permanent dial failure!\n", unit));
+ m_freem(m);
+ iprclearqueues(sc);
+ sc->sc_dialresp = DSTAT_NONE;
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ return(EHOSTUNREACH);
+ break;
+
+ case DSTAT_INONLY: /* no dialout allowed*/
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: dialout not allowed failure!\n", unit));
+ m_freem(m);
+ iprclearqueues(sc);
+ sc->sc_dialresp = DSTAT_NONE;
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ return(EHOSTUNREACH);
+ break;
+ }
+#endif
+
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: send dial request message!\n", unit));
+ DBGL4(L4_DIALST, "i4biproutput", ("ipr%d: setting dial state to ST_DIALING\n", unit));
+ i4b_l4_dialout(BDRV_IPR, unit);
+ sc->sc_state = ST_DIALING;
+ }
+
+ /* update access time */
+
+ microtime(&sc->sc_if.if_lastchange);
+
+ /*
+ * check, if type of service indicates interactive, i.e. telnet,
+ * traffic. in case it is interactive, put it into the fast queue,
+ * else (i.e. ftp traffic) put it into the "normal" queue
+ */
+
+ ip = mtod(m, struct ip *); /* get ptr to ip header */
+
+ if(ip->ip_tos & IPTOS_LOWDELAY)
+ ifq = &sc->sc_fastq;
+ else
+ ifq = &sc->sc_if.if_snd;
+
+ /* check for space in choosen send queue */
+
+ if(IF_QFULL(ifq))
+ {
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: send queue full!\n", unit));
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ return(ENOBUFS);
+ }
+
+ DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: add packet to send queue!\n", unit));
+
+ IF_ENQUEUE(ifq, m);
+
+ ipr_tx_queue_empty(unit);
+
+ splx(s);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * process ioctl
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int
+i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
+#else
+static int
+i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+#endif
+{
+#ifdef __FreeBSD__
+ struct ipr_softc *sc = &ipr_softc[ifp->if_unit];
+#else
+ struct ipr_softc *sc = ifp->if_softc;
+#endif
+
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ int s;
+ int error = 0;
+
+ s = SPLI4B();
+
+ switch (cmd)
+ {
+ case SIOCAIFADDR: /* add interface address */
+ case SIOCSIFADDR: /* set interface address */
+ case SIOCSIFDSTADDR: /* set interface destination address */
+ if(ifa->ifa_addr->sa_family != AF_INET)
+ error = EAFNOSUPPORT;
+ else
+ sc->sc_if.if_flags |= IFF_UP;
+ microtime(&sc->sc_if.if_lastchange);
+ break;
+
+ case SIOCSIFFLAGS: /* set interface flags */
+ if(!(ifr->ifr_flags & IFF_UP))
+ {
+ if(sc->sc_if.if_flags & IFF_RUNNING)
+ {
+ /* disconnect ISDN line */
+#ifdef __FreeBSD__
+ i4b_l4_drvrdisc(BDRV_IPR, ifp->if_unit);
+#else
+ i4b_l4_drvrdisc(BDRV_IPR, sc->sc_unit);
+#endif
+ sc->sc_if.if_flags &= ~IFF_RUNNING;
+ }
+
+ sc->sc_state = ST_IDLE;
+
+ /* empty queues */
+
+ iprclearqueues(sc);
+ }
+
+ if(ifr->ifr_flags & IFF_DEBUG)
+ {
+ /* enable debug messages */
+ }
+
+ microtime(&sc->sc_if.if_lastchange);
+ break;
+
+#if !defined(__OpenBSD__)
+ case SIOCSIFMTU: /* set interface MTU */
+ if(ifr->ifr_mtu > I4BIPRMAXMTU)
+ error = EINVAL;
+ else if(ifr->ifr_mtu < I4BIPRMINMTU)
+ error = EINVAL;
+ else
+ {
+ ifp->if_mtu = ifr->ifr_mtu;
+ microtime(&sc->sc_if.if_lastchange);
+ }
+ break;
+#endif /* __OPENBSD__ */
+
+#if 0
+ /* not needed for FreeBSD, done in sl_compress_init() (-hm) */
+
+ /* need to add an ioctl: set VJ max slot ID
+ * #define IPRIOCSMAXCID _IOW('I', XXX, int)
+ */
+#ifdef IPR_VJ
+ case IPRIOCSMAXCID:
+ {
+ struct proc *p = curproc; /* XXX */
+ if((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+ sl_compress_setup(sc->sc_compr, *(int *)data);
+ }
+ break;
+#endif
+#endif
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ splx(s);
+
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * clear the interface's send queues
+ *---------------------------------------------------------------------------*/
+static void
+iprclearqueues(struct ipr_softc *sc)
+{
+ int x;
+ struct mbuf *m;
+
+ for(;;)
+ {
+ x = splimp();
+ IF_DEQUEUE(&sc->sc_fastq, m);
+ splx(x);
+
+ if(m)
+ m_freem(m);
+ else
+ break;
+ }
+
+ for(;;)
+ {
+ x = splimp();
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ splx(x);
+
+ if(m)
+ m_freem(m);
+ else
+ break;
+ }
+}
+
+#if I4BIPRACCT
+/*---------------------------------------------------------------------------*
+ * watchdog routine
+ *---------------------------------------------------------------------------*/
+static void
+iprwatchdog(struct ifnet *ifp)
+{
+#ifdef __FreeBSD__
+ int unit = ifp->if_unit;
+ struct ipr_softc *sc = &ipr_softc[unit];
+#else
+ struct ipr_softc *sc = ifp->if_softc;
+ int unit = sc->sc_unit;
+#endif
+ bchan_statistics_t bs;
+
+ /* get # of bytes in and out from the HSCX driver */
+
+ (*isdn_linktab[unit]->bch_stat)
+ (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs);
+
+ sc->sc_ioutb += bs.outbytes;
+ sc->sc_iinb += bs.inbytes;
+
+ if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
+ {
+ int ri = (sc->sc_iinb - sc->sc_linb)/I4BIPRACCTINTVL;
+ int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BIPRACCTINTVL;
+
+ if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
+ sc->sc_fn = 0;
+ else
+ sc->sc_fn = 1;
+
+ sc->sc_linb = sc->sc_iinb;
+ sc->sc_loutb = sc->sc_ioutb;
+
+ i4b_l4_accounting(BDRV_IPR, unit, ACCT_DURING,
+ sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
+ }
+ sc->sc_if.if_timer = I4BIPRACCTINTVL;
+}
+#endif /* I4BIPRACCT */
+
+/*===========================================================================*
+ * ISDN INTERFACE ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * start transmitting after connect
+ *---------------------------------------------------------------------------*/
+static void
+i4bipr_connect_startio(int unit)
+{
+ struct ipr_softc *sc = &ipr_softc[unit];
+ int s = SPLI4B();
+
+ if(sc->sc_state == ST_CONNECTED_W)
+ {
+ sc->sc_state = ST_CONNECTED_A;
+ ipr_tx_queue_empty(unit);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at connect time
+ *---------------------------------------------------------------------------*/
+static void
+ipr_connect(int unit, void *cdp)
+{
+ struct ipr_softc *sc = &ipr_softc[unit];
+ int s;
+
+ sc->sc_cdp = (call_desc_t *)cdp;
+
+ s = SPLI4B();
+
+ DBGL4(L4_DIALST, "ipr_connect", ("ipr%d: setting dial state to ST_CONNECTED\n", unit));
+
+ sc->sc_if.if_flags |= IFF_RUNNING;
+ sc->sc_state = ST_CONNECTED_W;
+
+ sc->sc_dialresp = DSTAT_NONE;
+ sc->sc_lastdialresp = DSTAT_NONE;
+
+#if I4BIPRACCT
+ sc->sc_iinb = 0;
+ sc->sc_ioutb = 0;
+ sc->sc_inb = 0;
+ sc->sc_outb = 0;
+ sc->sc_linb = 0;
+ sc->sc_loutb = 0;
+ sc->sc_if.if_timer = I4BIPRACCTINTVL;
+#endif
+
+#ifdef I4BIPRADJFRXP
+ sc->sc_first_pkt = 1;
+#endif
+
+ /*
+ * Sometimes ISDN B-channels are switched thru asymmetic. This
+ * means that under such circumstances B-channel data (the first
+ * three packets of a TCP connection in my case) may get lost,
+ * causing a large delay until the connection is started.
+ * When the sending of the very first packet of a TCP connection
+ * is delayed for a to be empirically determined delay (close
+ * to a second in my case) those packets go thru and the TCP
+ * connection comes up "almost" immediately (-hm).
+ */
+
+ if(sc->sc_cdp->isdntxdelay > 0)
+ {
+ timeout((TIMEOUT_FUNC_T)i4bipr_connect_startio, (void *)unit, sc->sc_cdp->isdntxdelay /* hz*1 */);
+ }
+ else
+ {
+ sc->sc_state = ST_CONNECTED_A;
+ ipr_tx_queue_empty(unit);
+ }
+
+ splx(s);
+
+ /* we don't need any negotiation - pass event back right now */
+ i4b_l4_negcomplete(sc->sc_cdp);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at disconnect time
+ *---------------------------------------------------------------------------*/
+static void
+ipr_disconnect(int unit, void *cdp)
+{
+ call_desc_t *cd = (call_desc_t *)cdp;
+ struct ipr_softc *sc = &ipr_softc[unit];
+
+ /* new stuff to check that the active channel is being closed */
+
+ if (cd != sc->sc_cdp)
+ {
+ DBGL4(L4_IPRDBG, "ipr_disconnect", ("ipr%d: channel %d not active\n",
+ cd->driver_unit, cd->channelid));
+ return;
+ }
+
+#if I4BIPRACCT
+ sc->sc_if.if_timer = 0;
+#endif
+
+ i4b_l4_accounting(BDRV_IPR, cd->driver_unit, ACCT_FINAL,
+ sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
+
+ sc->sc_cdp = (call_desc_t *)0;
+
+ DBGL4(L4_DIALST, "ipr_disconnect", ("setting dial state to ST_IDLE\n"));
+
+ sc->sc_dialresp = DSTAT_NONE;
+ sc->sc_lastdialresp = DSTAT_NONE;
+
+ sc->sc_if.if_flags &= ~IFF_RUNNING;
+ sc->sc_state = ST_IDLE;
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is used to give a feedback from userland daemon
+ * in case of dial problems
+ *---------------------------------------------------------------------------*/
+static void
+ipr_dialresponse(int unit, int status)
+{
+ struct ipr_softc *sc = &ipr_softc[unit];
+ sc->sc_dialresp = status;
+
+ DBGL4(L4_IPRDBG, "ipr_dialresponse", ("ipr%d: last=%d, this=%d\n",
+ unit, sc->sc_lastdialresp, sc->sc_dialresp));
+}
+
+/*---------------------------------------------------------------------------*
+ * interface soft up/down
+ *---------------------------------------------------------------------------*/
+static void
+ipr_updown(int unit, int updown)
+{
+ struct ipr_softc *sc = &ipr_softc[unit];
+ sc->sc_updown = updown;
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when a new frame (mbuf) has been received and was put on
+ * the rx queue. It is assumed that this routines runs at
+ * pri level splimp() ! Keep it short !
+ *---------------------------------------------------------------------------*/
+static void
+ipr_rx_data_rdy(int unit)
+{
+ register struct ipr_softc *sc = &ipr_softc[unit];
+ register struct mbuf *m;
+#ifdef IPR_VJ
+#ifdef IPR_VJ_USEBUFFER
+ u_char *cp = sc->sc_cbuf;
+#endif
+ int len, c;
+#endif
+
+ if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
+ return;
+
+ m->m_pkthdr.rcvif = &sc->sc_if;
+
+ m->m_pkthdr.len = m->m_len;
+
+ microtime(&sc->sc_if.if_lastchange);
+
+#ifdef I4BIPRADJFRXP
+
+ /*
+ * The very first packet after the B channel is switched thru
+ * has very often several bytes of random data prepended. This
+ * routine looks where the IP header starts and removes the
+ * the bad data.
+ */
+
+ if(sc->sc_first_pkt)
+ {
+ unsigned char *mp = m->m_data;
+ int i;
+
+ sc->sc_first_pkt = 0;
+
+ for(i = 0; i < m->m_len; i++, mp++)
+ {
+ if( ((*mp & 0xf0) == 0x40) &&
+ ((*mp & 0x0f) >= 0x05) )
+ {
+ m->m_data = mp;
+ m->m_pkthdr.len -= i;
+ break;
+ }
+ }
+ }
+#endif
+
+ sc->sc_if.if_ipackets++;
+ sc->sc_if.if_ibytes += m->m_pkthdr.len;
+
+#ifdef IPR_VJ
+ if((c = (*(mtod(m, u_char *)) & 0xf0)) != (IPVERSION << 4))
+ {
+ /* copy data to buffer */
+
+ len = m->m_len;
+
+#ifdef IPR_VJ_USEBUFFER
+/* XXX */ m_copydata(m, 0, len, cp);
+#endif
+
+ if(c & 0x80)
+ {
+ c = TYPE_COMPRESSED_TCP;
+ }
+ else if(c == TYPE_UNCOMPRESSED_TCP)
+ {
+#ifdef IPR_VJ_USEBUFFER
+ *cp &= 0x4f; /* XXX */
+#else
+ *(mtod(m, u_char *)) &= 0x4f;
+#endif
+ }
+
+ /*
+ * We've got something that's not an IP packet.
+ * If compression is enabled, try to decompress it.
+ * Otherwise, if `auto-enable' compression is on and
+ * it's a reasonable packet, decompress it and then
+ * enable compression. Otherwise, drop it.
+ */
+ if(sc->sc_if.if_flags & IPR_COMPRESS)
+ {
+#ifdef IPR_VJ_USEBUFFER
+ len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
+#else
+ len = sl_uncompress_tcp((u_char **)&m->m_data, len,
+ (u_int)c, &sc->sc_compr);
+#endif
+
+ if(len <= 0)
+ {
+#ifdef DEBUG_IPR_VJ
+ printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n");
+#endif
+ goto error;
+ }
+ }
+ else if((sc->sc_if.if_flags & IPR_AUTOCOMP) &&
+ (c == TYPE_UNCOMPRESSED_TCP) && (len >= 40))
+ {
+#ifdef IPR_VJ_USEBUFFER
+ len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
+#else
+ len = sl_uncompress_tcp((u_char **)&m->m_data, len,
+ (u_int)c, &sc->sc_compr);
+#endif
+
+ if(len <= 0)
+ {
+#ifdef DEBUG_IPR_VJ
+ printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n");
+#endif
+ goto error;
+ }
+
+ sc->sc_if.if_flags |= IPR_COMPRESS;
+ }
+ else
+ {
+#ifdef DEBUG_IPR_VJ
+ printf("i4b_ipr, ipr_input: invalid ip packet!\n");
+#endif
+
+error:
+ sc->sc_if.if_ierrors++;
+ sc->sc_if.if_collisions++;
+ m_freem(m);
+ return;
+ }
+#ifdef IPR_VJ_USEBUFFER
+/* XXX */ m_copyback(m, 0, len, cp);
+#else
+ m->m_len = m->m_pkthdr.len = len;
+#endif
+ }
+#endif
+
+#if I4BIPRACCT
+ /* NB. do the accounting after decompression! */
+ sc->sc_inb += m->m_pkthdr.len;
+#endif
+
+#if NBPFILTER > 0
+ if(sc->sc_if.if_bpf)
+ {
+ /* prepend the address family as a four byte field */
+ struct mbuf mm;
+ u_int af = AF_INET;
+ mm.m_next = m;
+ mm.m_len = 4;
+ mm.m_data = (char *)&af;
+
+#ifdef __FreeBSD__
+ bpf_mtap(&sc->sc_if, &mm);
+#else
+ bpf_mtap(sc->sc_if.if_bpf, &mm);
+#endif
+ }
+#endif /* NBPFILTER > 0 */
+
+ if(IF_QFULL(&ipintrq))
+ {
+ DBGL4(L4_IPRDBG, "ipr_rx_data_rdy", ("ipr%d: ipintrq full!\n", unit));
+
+ IF_DROP(&ipintrq);
+ sc->sc_if.if_ierrors++;
+ sc->sc_if.if_iqdrops++;
+ m_freem(m);
+ }
+ else
+ {
+ IF_ENQUEUE(&ipintrq, m);
+ schednetisr(NETISR_IP);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when the last frame has been sent out and there is no
+ * further frame (mbuf) in the tx queue.
+ *---------------------------------------------------------------------------*/
+static void
+ipr_tx_queue_empty(int unit)
+{
+ register struct ipr_softc *sc = &ipr_softc[unit];
+ register struct mbuf *m;
+#ifdef IPR_VJ
+ struct ip *ip;
+#endif
+ int x = 0;
+
+ if(sc->sc_state != ST_CONNECTED_A)
+ return;
+
+ for(;;)
+ {
+ IF_DEQUEUE(&sc->sc_fastq, m);
+ if(m)
+ {
+ sc->sc_if.if_omcasts++;
+ }
+ else
+ {
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if(m == NULL)
+ break;
+ }
+
+ microtime(&sc->sc_if.if_lastchange);
+
+#if NBPFILTER > 0
+ if(sc->sc_if.if_bpf)
+ {
+ /* prepend the address family as a four byte field */
+
+ struct mbuf mm;
+ u_int af = AF_INET;
+ mm.m_next = m;
+ mm.m_len = 4;
+ mm.m_data = (char *)&af;
+
+#ifdef __FreeBSD__
+ bpf_mtap(&sc->sc_if, &mm);
+#else
+ bpf_mtap(sc->sc_if.if_bpf, &mm);
+#endif
+ }
+#endif /* NBPFILTER */
+
+#if I4BIPRACCT
+ sc->sc_outb += m->m_pkthdr.len; /* size before compression */
+#endif
+
+#ifdef IPR_VJ
+ if((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP)
+ {
+ if(sc->sc_if.if_flags & IPR_COMPRESS)
+ {
+ *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
+ &sc->sc_compr, 1);
+ }
+ }
+#endif
+ x = 1;
+
+ IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m);
+
+ sc->sc_if.if_obytes += m->m_pkthdr.len;
+
+ sc->sc_if.if_opackets++;
+ }
+
+ if(x)
+ (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * each time a packet is received or transmitted. It should
+ * be used to implement an activity timeout mechanism.
+ *---------------------------------------------------------------------------*/
+static void
+ipr_activity(int unit, int rxtx)
+{
+ ipr_softc[unit].sc_cdp->last_active_time = SECOND;
+}
+
+/*---------------------------------------------------------------------------*
+ * return this drivers linktab address
+ *---------------------------------------------------------------------------*/
+drvr_link_t *
+ipr_ret_linktab(int unit)
+{
+ return(&ipr_drvr_linktab[unit]);
+}
+
+/*---------------------------------------------------------------------------*
+ * setup the isdn_linktab for this driver
+ *---------------------------------------------------------------------------*/
+void
+ipr_set_linktab(int unit, isdn_link_t *ilt)
+{
+ isdn_linktab[unit] = ilt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize this drivers linktab
+ *---------------------------------------------------------------------------*/
+static void
+ipr_init_linktab(int unit)
+{
+ ipr_drvr_linktab[unit].unit = unit;
+ ipr_drvr_linktab[unit].bch_rx_data_ready = ipr_rx_data_rdy;
+ ipr_drvr_linktab[unit].bch_tx_queue_empty = ipr_tx_queue_empty;
+ ipr_drvr_linktab[unit].bch_activity = ipr_activity;
+ ipr_drvr_linktab[unit].line_connected = ipr_connect;
+ ipr_drvr_linktab[unit].line_disconnected = ipr_disconnect;
+ ipr_drvr_linktab[unit].dial_response = ipr_dialresponse;
+ ipr_drvr_linktab[unit].updown_ind = ipr_updown;
+}
+
+/*===========================================================================*/
+
+#endif /* NI4BIPR > 0 */
diff --git a/sys/i4b/driver/i4b_isppp.c b/sys/i4b/driver/i4b_isppp.c
new file mode 100644
index 000000000000..b1cb2cf9df5b
--- /dev/null
+++ b/sys/i4b/driver/i4b_isppp.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 1997 Joerg Wunsch. All rights reserved.
+ *
+ * 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_isppp.c - isdn4bsd kernel SyncPPP driver
+ * --------------------------------------------
+ *
+ * Uses Serge Vakulenko's sppp backend (originally contributed with
+ * the "cx" driver for Cronyx's HDLC-in-hardware device). This driver
+ * is only the glue between sppp and i4b.
+ *
+ * $Id: i4b_isppp.c,v 1.20 1998/12/18 14:20:44 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 11:47:58 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4bisppp.h"
+#ifdef __FreeBSD__
+#include "sppp.h"
+#endif
+
+#if NI4BISPPP == 0
+# error "You need to define `pseudo-device sppp <N>' with options ISPPP"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/ioccom.h>
+#include <sys/sockio.h>
+#include <sys/kernel.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#ifdef __FreeBSD__
+#include <net/if_sppp.h>
+#else
+#include <i4b/sppp/if_sppp.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <sys/time.h>
+#include <net/bpf.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_cause.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_cause.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_l3l4.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#ifdef __FreeBSD__
+#define ISPPP_FMT "isp%d: "
+#define ISPPP_ARG(sc) ((sc)->sc_if.if_unit)
+#define PDEVSTATIC static
+#define IFP2UNIT(ifp) (ifp)->if_unit
+
+# if __FreeBSD_version >= 300001
+# define CALLOUT_INIT(chan) callout_handle_init(chan)
+# define TIMEOUT(fun, arg, chan, tick) chan = timeout(fun, arg, tick)
+# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg, chan)
+# define IOCTL_CMD_T u_long
+# else
+# define CALLOUT_INIT(chan) do {} while(0)
+# define TIMEOUT(fun, arg, chan, tick) timeout(fun, arg, tick)
+# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg)
+# define IOCTL_CMD_T int
+# endif
+
+#elif defined __NetBSD__ || defined __OpenBSD__
+#define ISPPP_FMT "%s: "
+#define ISPPP_ARG(sc) ((sc)->sc_if.if_xname)
+#define PDEVSTATIC /* not static */
+#define IOCTL_CMD_T u_long
+#define IFP2UNIT(ifp) ((struct i4bisppp_softc *)ifp->if_softc)->sc_unit
+#else
+# error "What system are you using?"
+#endif
+
+#ifdef __FreeBSD__
+PDEVSTATIC void i4bispppattach(void *);
+PSEUDO_SET(i4bispppattach, i4b_isppp);
+#else
+PDEVSTATIC void i4bispppattach __P((void));
+#endif
+
+#define I4BISPPPACCT 1 /* enable accounting messages */
+#define I4BISPPPACCTINTVL 2 /* accounting msg interval in secs */
+#define I4BISPPPDISCDEBUG 1
+
+#define PPP_HDRLEN 4 /* 4 octetts PPP header length */
+
+struct i4bisppp_softc {
+ /*
+ * struct sppp starts with a struct ifnet, but we gotta allocate
+ * more space for it. NB: do not relocate this union, it must
+ * be first in isppp_softc. The tls and tlf hooks below want to
+ * convert a ``struct sppp *'' into a ``struct isppp_softc *''.
+ */
+ union {
+ struct ifnet scu_if;
+ struct sppp scu_sp;
+ } sc_if_un;
+#define sc_if sc_if_un.scu_if
+
+ int sc_state; /* state of the interface */
+
+#ifndef __FreeBSD__
+ int sc_unit; /* unit number for Net/OpenBSD */
+#endif
+
+ call_desc_t *sc_cdp; /* ptr to call descriptor */
+
+#ifdef I4BISPPPACCT
+ int sc_iinb; /* isdn driver # of inbytes */
+ int sc_ioutb; /* isdn driver # of outbytes */
+ int sc_inb; /* # of bytes rx'd */
+ int sc_outb; /* # of bytes tx'd */
+ int sc_linb; /* last # of bytes rx'd */
+ int sc_loutb; /* last # of bytes tx'd */
+ int sc_fn; /* flag, first null acct */
+#endif
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ struct callout_handle sc_ch;
+#endif
+
+} i4bisppp_softc[NI4BISPPP];
+
+static void i4bisppp_init_linktab(int unit);
+static int i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
+
+#if 0
+static void i4bisppp_send(struct ifnet *ifp);
+#endif
+
+static void i4bisppp_start(struct ifnet *ifp);
+
+#if 0 /* never used ??? */
+static void i4bisppp_timeout(void *cookie);
+#endif
+
+static void i4bisppp_tls(struct sppp *sp);
+static void i4bisppp_tlf(struct sppp *sp);
+static void i4bisppp_state_changed(struct sppp *sp, int new_state);
+static void i4bisppp_negotiation_complete(struct sppp *sp);
+static void i4bisppp_watchdog(struct ifnet *ifp);
+
+/* initialized by L4 */
+
+static drvr_link_t i4bisppp_drvr_linktab[NI4BISPPP];
+static isdn_link_t *isdn_linktab[NI4BISPPP];
+
+enum i4bisppp_states {
+ ST_IDLE, /* initialized, ready, idle */
+ ST_DIALING, /* dialling out to remote */
+ ST_CONNECTED, /* connected to remote */
+};
+
+/*===========================================================================*
+ * DEVICE DRIVER ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine at kernel boot time
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4bispppattach(void *dummy)
+#else
+i4bispppattach(void)
+#endif
+{
+ struct i4bisppp_softc *sc = i4bisppp_softc;
+ int i;
+
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+ printf("i4bisppp: %d ISDN SyncPPP device(s) attached\n",
+ NI4BISPPP);
+#endif
+
+ for(i = 0; i < NI4BISPPP; sc++, i++) {
+ i4bisppp_init_linktab(i);
+
+ sc->sc_if.if_softc = sc;
+
+#ifdef __FreeBSD__
+ sc->sc_if.if_name = "isp";
+#if defined(__FreeBSD_version) && __FreeBSD_version < 300001
+ sc->sc_if.if_next = NULL;
+#endif
+ sc->sc_if.if_unit = i;
+#else
+ sprintf(sc->sc_if.if_xname, "isp%d", i);
+ sc->sc_unit = i;
+#endif
+
+ sc->sc_if.if_mtu = PP_MTU;
+ sc->sc_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT;
+ sc->sc_if.if_type = IFT_ISDNBASIC;
+ sc->sc_state = ST_IDLE;
+
+ sc->sc_if.if_ioctl = i4bisppp_ioctl;
+
+ /* actually initialized by sppp_attach() */
+ /* sc->sc_if.if_output = sppp_output; */
+
+ sc->sc_if.if_start = i4bisppp_start;
+
+ sc->sc_if.if_hdrlen = 0;
+ sc->sc_if.if_addrlen = 0;
+ sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+
+ sc->sc_if.if_ipackets = 0;
+ sc->sc_if.if_ierrors = 0;
+ sc->sc_if.if_opackets = 0;
+ sc->sc_if.if_oerrors = 0;
+ sc->sc_if.if_collisions = 0;
+ sc->sc_if.if_ibytes = 0;
+ sc->sc_if.if_obytes = 0;
+ sc->sc_if.if_imcasts = 0;
+ sc->sc_if.if_omcasts = 0;
+ sc->sc_if.if_iqdrops = 0;
+ sc->sc_if.if_noproto = 0;
+
+#if I4BISPPPACCT
+ sc->sc_if.if_timer = 0;
+ sc->sc_if.if_watchdog = i4bisppp_watchdog;
+ sc->sc_iinb = 0;
+ sc->sc_ioutb = 0;
+ sc->sc_inb = 0;
+ sc->sc_outb = 0;
+ sc->sc_linb = 0;
+ sc->sc_loutb = 0;
+ sc->sc_fn = 1;
+#endif
+
+ sc->sc_if_un.scu_sp.pp_tls = i4bisppp_tls;
+ sc->sc_if_un.scu_sp.pp_tlf = i4bisppp_tlf;
+ sc->sc_if_un.scu_sp.pp_con = i4bisppp_negotiation_complete;
+ sc->sc_if_un.scu_sp.pp_chg = i4bisppp_state_changed;
+
+ sppp_attach(&sc->sc_if);
+ if_attach(&sc->sc_if);
+
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN);
+ CALLOUT_INIT(&sc->sc_ch);
+#endif /* __FreeBSD__ */
+#ifdef __NetBSD__
+ bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_PPP, sizeof(u_int));
+#endif
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * process ioctl
+ *---------------------------------------------------------------------------*/
+static int
+i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
+{
+ struct i4bisppp_softc *sc = ifp->if_softc;
+#if 0
+ struct sppp *sp = (struct sppp *)sc;
+ struct ifaddr *ifa = (struct ifaddr *) data;
+ struct ifreq *ifr = (struct ifreq *) data;
+#endif
+
+ int error;
+
+ error = sppp_ioctl(&sc->sc_if, cmd, data);
+ if (error)
+ return error;
+
+ switch(cmd) {
+ case SIOCSIFFLAGS:
+#if 0 /* never used ??? */
+ x = splimp();
+ if ((ifp->if_flags & IFF_UP) == 0)
+ UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
+ splx(x);
+#endif
+ break;
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * start output to ISDN B-channel
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_start(struct ifnet *ifp)
+{
+ struct i4bisppp_softc *sc = ifp->if_softc;
+ struct mbuf *m;
+ int s;
+ int unit = IFP2UNIT(ifp);
+
+ if (sppp_isempty(ifp))
+ return;
+
+ if(sc->sc_state != ST_CONNECTED)
+ return;
+
+ s = splimp();
+ /*ifp->if_flags |= IFF_OACTIVE; - need to clear this somewhere */
+ splx(s);
+
+ while ((m = sppp_dequeue(&sc->sc_if)) != NULL)
+ {
+
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ if (ifp->if_bpf)
+ bpf_mtap(ifp, m);
+#endif /* __FreeBSD__ */
+
+#ifdef __NetBSD__
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+#endif /* NBPFILTER > 0 */
+
+ microtime(&ifp->if_lastchange);
+
+ IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m);
+
+ sc->sc_if.if_obytes += m->m_pkthdr.len;
+ sc->sc_outb += m->m_pkthdr.len;
+ sc->sc_if.if_opackets++;
+ }
+ isdn_linktab[unit]->bch_tx_start(isdn_linktab[unit]->unit,
+ isdn_linktab[unit]->channel);
+}
+
+#ifdef I4BISPPPACCT
+/*---------------------------------------------------------------------------*
+ * watchdog routine
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_watchdog(struct ifnet *ifp)
+{
+ struct i4bisppp_softc *sc = ifp->if_softc;
+ int unit = IFP2UNIT(ifp);
+ bchan_statistics_t bs;
+
+ (*isdn_linktab[unit]->bch_stat)
+ (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs);
+
+ sc->sc_ioutb += bs.outbytes;
+ sc->sc_iinb += bs.inbytes;
+
+ if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
+ {
+ int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL;
+ int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL;
+
+ if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
+ sc->sc_fn = 0;
+ else
+ sc->sc_fn = 1;
+
+ sc->sc_linb = sc->sc_iinb;
+ sc->sc_loutb = sc->sc_ioutb;
+
+ i4b_l4_accounting(BDRV_ISPPP, unit, ACCT_DURING,
+ sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
+ }
+ sc->sc_if.if_timer = I4BISPPPACCTINTVL;
+
+#if 0 /* old stuff, keep it around */
+ printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc));
+ i4bisppp_start(ifp);
+#endif
+}
+#endif /* I4BISPPPACCT */
+
+/*
+ *===========================================================================*
+ * SyncPPP layer interface routines
+ *===========================================================================*
+ */
+
+#if 0 /* never used ??? */
+/*---------------------------------------------------------------------------*
+ * just an alias for i4bisppp_tls, but of type timeout_t
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_timeout(void *cookie)
+{
+ i4bisppp_tls((struct sppp *)cookie);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * PPP this-layer-started action
+ *---------------------------------------------------------------------------*
+ */
+static void
+i4bisppp_tls(struct sppp *sp)
+{
+ struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp;
+ struct ifnet *ifp = (struct ifnet *)sp;
+
+ if(sc->sc_state == ST_CONNECTED)
+ return;
+
+ i4b_l4_dialout(BDRV_ISPPP, IFP2UNIT(ifp));
+}
+
+/*---------------------------------------------------------------------------*
+ * PPP this-layer-finished action
+ *---------------------------------------------------------------------------*
+ */
+static void
+i4bisppp_tlf(struct sppp *sp)
+{
+ struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp;
+/* call_desc_t *cd = sc->sc_cdp; */
+ struct ifnet *ifp = (struct ifnet *)sp;
+
+ if(sc->sc_state != ST_CONNECTED)
+ return;
+
+#if 0 /* never used ??? */
+ UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
+#endif
+
+ i4b_l4_drvrdisc(BDRV_ISPPP, IFP2UNIT(ifp));
+}
+/*---------------------------------------------------------------------------*
+ * PPP interface phase change
+ *---------------------------------------------------------------------------*
+ */
+static void
+i4bisppp_state_changed(struct sppp *sp, int new_state)
+{
+ struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp;
+
+ i4b_l4_ifstate_changed(sc->sc_cdp, new_state);
+}
+
+/*---------------------------------------------------------------------------*
+ * PPP control protocol negotiation complete (run ip-up script now)
+ *---------------------------------------------------------------------------*
+ */
+static void
+i4bisppp_negotiation_complete(struct sppp *sp)
+{
+ struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp;
+
+ i4b_l4_negcomplete(sc->sc_cdp);
+}
+
+/*===========================================================================*
+ * ISDN INTERFACE ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at connect time
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_connect(int unit, void *cdp)
+{
+ struct i4bisppp_softc *sc = &i4bisppp_softc[unit];
+ struct sppp *sp = &sc->sc_if_un.scu_sp;
+ int s = splimp();
+
+ sc->sc_cdp = (call_desc_t *)cdp;
+ sc->sc_state = ST_CONNECTED;
+
+#if I4BISPPPACCT
+ sc->sc_iinb = 0;
+ sc->sc_ioutb = 0;
+ sc->sc_inb = 0;
+ sc->sc_outb = 0;
+ sc->sc_linb = 0;
+ sc->sc_loutb = 0;
+ sc->sc_if.if_timer = I4BISPPPACCTINTVL;
+#endif
+
+#if 0 /* never used ??? */
+ UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
+#endif
+
+ sp->pp_up(sp); /* tell PPP we are ready */
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at disconnect time
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_disconnect(int unit, void *cdp)
+{
+ call_desc_t *cd = (call_desc_t *)cdp;
+ struct i4bisppp_softc *sc = &i4bisppp_softc[unit];
+ struct sppp *sp = &sc->sc_if_un.scu_sp;
+
+ int s = splimp();
+
+ /* new stuff to check that the active channel is being closed */
+ if (cd != sc->sc_cdp)
+ {
+#ifdef I4BISPPPDISCDEBUG
+ printf("i4bisppp_disconnect: isppp%d channel%d not active\n",
+ cd->driver_unit, cd->channelid);
+#endif
+ splx(s);
+ return;
+ }
+
+#if I4BISPPPACCT
+ sc->sc_if.if_timer = 0;
+#endif
+
+ i4b_l4_accounting(BDRV_ISPPP, unit, ACCT_FINAL,
+ sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
+
+ if (sc->sc_state == ST_CONNECTED)
+ {
+#if 0 /* never used ??? */
+ UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch);
+#endif
+ sc->sc_cdp = (call_desc_t *)0;
+ /* do thhis here because pp_down calls i4bisppp_tlf */
+ sc->sc_state = ST_IDLE;
+ sp->pp_down(sp); /* tell PPP we have hung up */
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is used to give a feedback from userland demon
+ * in case of dial problems
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_dialresponse(int unit, int status)
+{
+/* struct i4bisppp_softc *sc = &i4bisppp_softc[unit]; */
+}
+
+/*---------------------------------------------------------------------------*
+ * interface up/down
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_updown(int unit, int updown)
+{
+ /* could probably do something useful here */
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when a new frame (mbuf) has been received and was put on
+ * the rx queue.
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_rx_data_rdy(int unit)
+{
+ struct i4bisppp_softc *sc = &i4bisppp_softc[unit];
+ struct mbuf *m;
+ int s;
+
+ if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
+ return;
+
+ m->m_pkthdr.rcvif = &sc->sc_if;
+ m->m_pkthdr.len = m->m_len;
+
+ microtime(&sc->sc_if.if_lastchange);
+
+ sc->sc_if.if_ipackets++;
+ sc->sc_if.if_ibytes += m->m_pkthdr.len;
+
+#if I4BISPPPACCT
+ sc->sc_inb += m->m_pkthdr.len;
+#endif
+
+#ifdef I4BISPPPDEBUG
+ printf("i4bisppp_rx_data_ready: received packet!\n");
+#endif
+
+#if NBPFILTER > 0
+
+#ifdef __FreeBSD__
+ if(sc->sc_if.if_bpf)
+ bpf_mtap(&sc->sc_if, m);
+#endif /* __FreeBSD__ */
+
+#ifdef __NetBSD__
+ if(sc->sc_if.if_bpf)
+ bpf_mtap(sc->sc_if.if_bpf, m);
+#endif
+
+#endif /* NBPFILTER > 0 */
+
+ s = splimp();
+
+ sppp_input(&sc->sc_if, m);
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when the last frame has been sent out and there is no
+ * further frame (mbuf) in the tx queue.
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_tx_queue_empty(int unit)
+{
+ i4bisppp_start(&i4bisppp_softc[unit].sc_if);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * each time a packet is received or transmitted. It should
+ * be used to implement an activity timeout mechanism.
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_activity(int unit, int rxtx)
+{
+ i4bisppp_softc[unit].sc_cdp->last_active_time = SECOND;
+}
+
+/*---------------------------------------------------------------------------*
+ * return this drivers linktab address
+ *---------------------------------------------------------------------------*/
+drvr_link_t *
+i4bisppp_ret_linktab(int unit)
+{
+ return(&i4bisppp_drvr_linktab[unit]);
+}
+
+/*---------------------------------------------------------------------------*
+ * setup the isdn_linktab for this driver
+ *---------------------------------------------------------------------------*/
+void
+i4bisppp_set_linktab(int unit, isdn_link_t *ilt)
+{
+ isdn_linktab[unit] = ilt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize this drivers linktab
+ *---------------------------------------------------------------------------*/
+static void
+i4bisppp_init_linktab(int unit)
+{
+ i4bisppp_drvr_linktab[unit].unit = unit;
+ i4bisppp_drvr_linktab[unit].bch_rx_data_ready = i4bisppp_rx_data_rdy;
+ i4bisppp_drvr_linktab[unit].bch_tx_queue_empty = i4bisppp_tx_queue_empty;
+ i4bisppp_drvr_linktab[unit].bch_activity = i4bisppp_activity;
+ i4bisppp_drvr_linktab[unit].line_connected = i4bisppp_connect;
+ i4bisppp_drvr_linktab[unit].line_disconnected = i4bisppp_disconnect;
+ i4bisppp_drvr_linktab[unit].dial_response = i4bisppp_dialresponse;
+ i4bisppp_drvr_linktab[unit].updown_ind = i4bisppp_updown;
+}
+
+/*===========================================================================*/
diff --git a/sys/i4b/driver/i4b_rbch.c b/sys/i4b/driver/i4b_rbch.c
new file mode 100644
index 000000000000..9cf432c98f29
--- /dev/null
+++ b/sys/i4b/driver/i4b_rbch.c
@@ -0,0 +1,820 @@
+/*
+ * 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_rbch.c - device driver for raw B channel data
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_rbch.c,v 1.23 1998/12/14 09:39:10 hm Exp $
+ *
+ * last edit-date: [Sun Dec 13 10:19:08 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4brbch.h"
+
+#if NI4BRBCH > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#include <sys/poll.h>
+#else
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#endif
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001)
+#include <sys/filio.h>
+#endif
+
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+
+#ifdef __NetBSD__
+extern cc_t ttydefchars;
+#define termioschars(t) memcpy((t)->c_cc, &ttydefchars, sizeof((t)->c_cc))
+#endif
+
+#ifdef __FreeBSD__
+#include "opt_devfs.h"
+#endif
+
+#ifdef DEVFS
+#include <sys/devfsext.h>
+#endif
+
+#ifdef __NetBSD__
+#include <sys/filio.h>
+#define bootverbose 0
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_debug.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_debug.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_l3l4.h>
+
+#include <i4b/layer4/i4b_l4.h>
+/* initialized by L4 */
+
+static drvr_link_t rbch_drvr_linktab[NI4BRBCH];
+static isdn_link_t *isdn_linktab[NI4BRBCH];
+
+static struct rbch_softc {
+ int sc_devstate; /* state of driver */
+#define ST_IDLE 0x00
+#define ST_CONNECTED 0x01
+#define ST_ISOPEN 0x02
+#define ST_RDWAITDATA 0x04
+#define ST_WRWAITEMPTY 0x08
+#define ST_NOBLOCK 0x10
+
+ int sc_bprot; /* B-ch protocol used */
+
+ call_desc_t *cd; /* Call Descriptor */
+ struct termios it_in;
+
+ struct ifqueue sc_hdlcq; /* hdlc read queue */
+#define I4BRBCHMAXQLEN 10
+
+ struct selinfo selp; /* select / poll */
+
+#ifdef DEVFS
+ void *devfs_token; /* device filesystem */
+#endif
+} rbch_softc[NI4BRBCH];
+
+static void rbch_rx_data_rdy(int unit);
+static void rbch_tx_queue_empty(int unit);
+static void rbch_connect(int unit, void *cdp);
+static void rbch_disconnect(int unit, void *cdp);
+static void rbch_init_linktab(int unit);
+static void rbch_clrq(int unit);
+
+#ifndef __FreeBSD__
+#define PDEVSTATIC /* - not static - */
+#define IOCTL_CMD_T u_long
+void i4brbchattach __P((void));
+int i4brbchopen __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4brbchclose __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4brbchread __P((dev_t dev, struct uio *uio, int ioflag));
+int i4brbchwrite __P((dev_t dev, struct uio *uio, int ioflag));
+int i4brbchioctl __P((dev_t dev, IOCTL_CMD_T cmd, caddr_t arg, int flag, struct proc* pr));
+int i4brbchpoll __P((dev_t dev, int events, struct proc *p));
+#endif
+
+#if BSD > 199306 && defined(__FreeBSD__)
+#define PDEVSTATIC static
+#if !defined(__FreeBSD_version) || __FreeBSD_version < 300003
+#define IOCTL_CMD_T int
+#else
+#define IOCTL_CMD_T u_long
+#endif
+
+PDEVSTATIC d_open_t i4brbchopen;
+PDEVSTATIC d_close_t i4brbchclose;
+PDEVSTATIC d_read_t i4brbchread;
+PDEVSTATIC d_read_t i4brbchwrite;
+PDEVSTATIC d_ioctl_t i4brbchioctl;
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__)
+PDEVSTATIC d_poll_t i4brbchpoll;
+#else
+PDEVSTATIC d_select_t i4brbchselect;
+#endif
+
+#define CDEV_MAJOR 57
+static struct cdevsw i4brbch_cdevsw = {
+ i4brbchopen, i4brbchclose, i4brbchread, i4brbchwrite,
+ i4brbchioctl, nostop, noreset, nodevtotty,
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ i4brbchpoll, nommap, NULL, "i4brbch", NULL, -1
+#else
+ i4brbchselect, nommap, NULL, "i4brbch", NULL, -1
+#endif
+};
+
+static void i4brbchattach(void *);
+PSEUDO_SET(i4brbchattach, i4b_rbch);
+
+/*===========================================================================*
+ * DEVICE DRIVER ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * initialization at kernel load time
+ *---------------------------------------------------------------------------*/
+static void
+i4brbchinit(void *unused)
+{
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+
+ cdevsw_add(&dev, &i4brbch_cdevsw, NULL);
+}
+
+SYSINIT(i4brbchdev, SI_SUB_DRIVERS,
+ SI_ORDER_MIDDLE+CDEV_MAJOR, &i4brbchinit, NULL);
+
+#endif /* BSD > 199306 && defined(__FreeBSD__) */
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4brbchattach(void *dummy)
+#else
+i4brbchattach()
+#endif
+{
+ int i;
+
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+ printf("i4brbch: %d raw B channel access device(s) attached\n", NI4BRBCH);
+#endif
+
+ for(i=0; i < NI4BRBCH; i++)
+ {
+#ifdef DEVFS
+ rbch_softc[i].devfs_token =
+ devfs_add_devswf(&i4brbch_cdevsw, i, DV_CHR,
+ UID_ROOT, GID_WHEEL, 0600,
+ "i4brbch%d", i);
+#endif
+ rbch_softc[i].sc_devstate = ST_IDLE;
+ rbch_softc[i].sc_hdlcq.ifq_maxlen = I4BRBCHMAXQLEN;
+ rbch_softc[i].it_in.c_ispeed = rbch_softc[i].it_in.c_ospeed = 64000;
+ termioschars(&rbch_softc[i].it_in);
+ rbch_init_linktab(i);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * open rbch device
+ *---------------------------------------------------------------------------*/
+int
+i4brbchopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int unit = minor(dev);
+
+ if(unit > NI4BRBCH)
+ return(ENXIO);
+
+ if(rbch_softc[unit].sc_devstate & ST_ISOPEN)
+ return(EBUSY);
+
+ rbch_clrq(unit);
+
+ rbch_softc[unit].sc_devstate |= ST_ISOPEN;
+
+ DBGL4(L4_RBCHDBG, "i4brbchopen", ("unit %d, open\n", unit));
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * close rbch device
+ *---------------------------------------------------------------------------*/
+int
+i4brbchclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int unit = minor(dev);
+
+ if (rbch_softc[unit].cd) {
+ i4b_l4_disconnect_ind(rbch_softc[unit].cd);
+ rbch_softc[unit].cd = NULL;
+ }
+ rbch_softc[unit].sc_devstate &= ~ST_ISOPEN;
+
+ rbch_clrq(unit);
+
+ DBGL4(L4_RBCHDBG, "i4brbclose", ("unit %d, close\n", unit));
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * read from rbch device
+ *---------------------------------------------------------------------------*/
+int
+i4brbchread(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct mbuf *m;
+ int s;
+ int error = 0;
+ int unit = minor(dev);
+ struct ifqueue *iqp;
+
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, enter read\n", unit));
+
+ if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, read while not open\n", unit));
+ return(EIO);
+ }
+
+ if((rbch_softc[unit].sc_devstate & ST_NOBLOCK)) {
+ if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ return(EWOULDBLOCK);
+
+ if(rbch_softc[unit].sc_bprot == BPROT_RHDLC)
+ iqp = &rbch_softc[unit].sc_hdlcq;
+ else
+ iqp = isdn_linktab[unit]->rx_queue;
+
+ if(IF_QEMPTY(iqp) && (rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ return(EWOULDBLOCK);
+ } else {
+ while(!(rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, wait read init\n", unit));
+
+ if((error = tsleep((caddr_t) &rbch_softc[unit],
+ TTIPRI | PCATCH,
+ "rrrbch", 0 )) != 0)
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d tsleep\n", unit, error));
+ return(error);
+ }
+ }
+
+ if(rbch_softc[unit].sc_bprot == BPROT_RHDLC)
+ iqp = &rbch_softc[unit].sc_hdlcq;
+ else
+ iqp = isdn_linktab[unit]->rx_queue;
+
+ while(IF_QEMPTY(iqp) && (rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ s = splimp();
+ rbch_softc[unit].sc_devstate |= ST_RDWAITDATA;
+ splx(s);
+
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, wait read data\n", unit));
+
+ if((error = tsleep((caddr_t) &isdn_linktab[unit]->rx_queue,
+ TTIPRI | PCATCH,
+ "rrbch", 0 )) != 0)
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d tsleep read\n", unit, error));
+ rbch_softc[unit].sc_devstate &= ~ST_RDWAITDATA;
+ return(error);
+ }
+ }
+ }
+
+ s = splimp();
+
+ IF_DEQUEUE(iqp, m);
+
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, read %d bytes\n", unit, m->m_len));
+
+ if(m && m->m_len)
+ {
+ error = uiomove(m->m_data, m->m_len, uio);
+ }
+ else
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d uiomove\n", unit, error));
+ error = EIO;
+ }
+
+ if(m)
+ i4b_Bfreembuf(m);
+
+ splx(s);
+
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * write to rbch device
+ *---------------------------------------------------------------------------*/
+int
+i4brbchwrite(dev_t dev, struct uio * uio, int ioflag)
+{
+ struct mbuf *m;
+ int s;
+ int error = 0;
+ int unit = minor(dev);
+
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write\n", unit));
+
+ if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write while not open\n", unit));
+ return(EIO);
+ }
+
+ if((rbch_softc[unit].sc_devstate & ST_NOBLOCK)) {
+ if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ return(EWOULDBLOCK);
+ if(IF_QFULL(isdn_linktab[unit]->tx_queue) && (rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ return(EWOULDBLOCK);
+ } else {
+ while(!(rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write wait init\n", unit));
+
+ error = tsleep((caddr_t) &rbch_softc[unit],
+ TTIPRI | PCATCH,
+ "wrrbch", 0 );
+ if(error == ERESTART)
+ return (ERESTART);
+ else if(error == EINTR) {
+ printf("\n ========= i4brbchwrite, EINTR during wait init ======== \n");
+ return(EINTR);
+ } else if(error) {
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, error %d tsleep init\n", unit, error));
+ return(error);
+ }
+/*XXX*/ tsleep((caddr_t) &rbch_softc[unit], TTIPRI | PCATCH, "xrbch", (hz*1));
+ }
+
+ while(IF_QFULL(isdn_linktab[unit]->tx_queue) && (rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ s = splimp();
+ rbch_softc[unit].sc_devstate |= ST_WRWAITEMPTY;
+ splx(s);
+
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write queue full\n", unit));
+
+ if ((error = tsleep((caddr_t) &isdn_linktab[unit]->tx_queue,
+ TTIPRI | PCATCH,
+ "wrbch", 0)) != 0) {
+ rbch_softc[unit].sc_devstate &= ~ST_WRWAITEMPTY;
+ if(error == ERESTART) {
+ return(ERESTART);
+ } else if(error == EINTR) {
+ printf("\n ========= i4brbchwrite, EINTR during wait write ======== \n");
+ return(error);
+ } else if(error) {
+ DBGL4(L4_RBCHDBG, "i4brbchwrite",
+ ("unit %d, error %d tsleep write\n", unit, error));
+ return(error);
+ }
+ }
+ }
+ }
+
+ s = splimp();
+
+ if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, not open anymore\n", unit));
+ splx(s);
+ return(EIO);
+ }
+
+ if((m = i4b_Bgetmbuf(BCH_MAX_DATALEN)) != NULL)
+ {
+ m->m_len = min(BCH_MAX_DATALEN, uio->uio_resid);
+
+ DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write %d bytes\n", unit, m->m_len));
+
+ error = uiomove(m->m_data, m->m_len, uio);
+
+ IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m);
+
+ (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel);
+ }
+
+ splx(s);
+
+ return(error);
+}
+
+PDEVSTATIC int
+i4brbchioctl(dev_t dev, IOCTL_CMD_T cmd, caddr_t data, int flag, struct proc* p) {
+ int error = 0;
+ int unit = minor(dev);
+
+ switch(cmd)
+ {
+#if 0
+ case I4B_RBCH_DIALOUT:
+if(bootverbose)printf("EE-rbch%d: attempting dialout (ioctl)\n", unit);
+ i4b_l4_dialout(BDRV_RBCH, unit);
+ break;
+#endif
+
+ case FIOASYNC: /* Set async mode */
+ if (*(int *)data) {
+if(bootverbose)printf("EE-rbch%d: setting async mode\n", unit);
+ } else {
+if(bootverbose)printf("EE-rbch%d: clearing async mode\n", unit);
+ }
+ break;
+ case FIONBIO:
+ if (*(int *)data) {
+if(bootverbose)printf("EE-rbch%d: setting non-blocking mode\n", unit);
+ rbch_softc[unit].sc_devstate |= ST_NOBLOCK;
+ } else {
+if(bootverbose)printf("EE-rbch%d: clearing non-blocking mode\n", unit);
+ rbch_softc[unit].sc_devstate &= ~ST_NOBLOCK;
+ }
+ break;
+ case TIOCCDTR: /* Clear DTR */
+ if(rbch_softc[unit].sc_devstate & ST_CONNECTED) {
+if(bootverbose)printf("EE-rbch%d: disconnecting for DTR down\n", unit);
+ i4b_l4_disconnect_ind(rbch_softc[unit].cd);
+ }
+ break;
+ case TIOCSDTR: /* Set DTR */
+if(bootverbose)printf("EE-rbch%d: attempting dialout (DTR)\n", unit);
+ i4b_l4_dialout(BDRV_RBCH, unit);
+ break;
+ case TIOCSETA: /* Set termios struct */
+ break;
+ case TIOCGETA: /* Get termios struct */
+ *(struct termios *)data = rbch_softc[unit].it_in;
+ break;
+ case TIOCMGET:
+ *(int *)data = TIOCM_LE|TIOCM_DTR|TIOCM_RTS|TIOCM_CTS|TIOCM_DSR;
+ if (rbch_softc[unit].sc_devstate & ST_CONNECTED)
+ *(int *)data |= TIOCM_CD;
+ break;
+ default: /* Unknown stuff */
+ printf("\n ========= i4brbch%d - ioctl, unknown cmd %lx ==================== \n",
+ unit,
+ (u_long)cmd);
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * device driver poll
+ *---------------------------------------------------------------------------*/
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__)
+
+PDEVSTATIC int
+i4brbchpoll(dev_t dev, int events, struct proc *p)
+{
+ int revents = 0; /* Events we found */
+ int s;
+ int unit = minor(dev);
+
+ /* We can't check for anything but IN or OUT */
+
+ if((events & (POLLIN|POLLOUT)) == 0)
+ return(POLLNVAL);
+
+ s = splhigh();
+
+ if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ splx(s);
+ return(POLLNVAL);
+ }
+
+ /*
+ * Writes are OK if we are connected and the
+ * transmit queue can take them
+ */
+
+ if((events & POLLOUT) &&
+ (rbch_softc[unit].sc_devstate & ST_CONNECTED) &&
+ !IF_QFULL(isdn_linktab[unit]->tx_queue))
+ {
+ revents |= POLLOUT;
+ }
+
+ /* ... while reads are OK if we have any data */
+
+ if((events & POLLIN) &&
+ (rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ {
+ struct ifqueue *iqp;
+
+ if(rbch_softc[unit].sc_bprot == BPROT_RHDLC)
+ iqp = &rbch_softc[unit].sc_hdlcq;
+ else
+ iqp = isdn_linktab[unit]->rx_queue;
+
+ if(!IF_QEMPTY(iqp))
+ revents |= POLLIN;
+ }
+
+ if(revents == 0)
+ selrecord(p, &rbch_softc[unit].selp);
+
+ splx(s);
+ return(revents);
+}
+
+#else
+
+/*---------------------------------------------------------------------------*
+ * device driver select
+ *---------------------------------------------------------------------------*/
+static int
+i4brbchselect(dev_t dev, int rw, struct proc *p)
+{
+ int unit = minor(dev);
+ int s;
+
+ s = splhigh();
+
+ if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN))
+ {
+ splx(s);
+ DBGL4(L4_RBCHDBG, "i4brbchselect", ("unit %d, not open anymore\n", unit));
+ return(1);
+ }
+
+ if(rbch_softc[unit].sc_devstate & ST_CONNECTED)
+ {
+ struct ifqueue *iqp;
+
+ switch(rw)
+ {
+ case FREAD:
+ if(rbch_softc[unit].sc_bprot == BPROT_RHDLC)
+ iqp = &rbch_softc[unit].sc_hdlcq;
+ else
+ iqp = isdn_linktab[unit]->rx_queue;
+
+ if(!IF_QEMPTY(iqp))
+ return(1);
+ break;
+
+ case FWRITE:
+ if(!IF_QFULL(isdn_linktab[unit]->rx_queue))
+ return(1);
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ selrecord(p, &rbch_softc[unit].selp);
+ return(0);
+}
+
+#endif /* defined(__FreeBSD_version) && __FreeBSD_version >= 300001 */
+
+/*===========================================================================*
+ * ISDN INTERFACE ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at connect time
+ *---------------------------------------------------------------------------*/
+static void
+rbch_connect(int unit, void *cdp)
+{
+ call_desc_t *cd = (call_desc_t *)cdp;
+
+ rbch_softc[unit].sc_bprot = cd->bprot;
+
+ if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED))
+ {
+ DBGL4(L4_RBCHDBG, "rbch_connect", ("unit %d, wakeup\n", unit));
+ rbch_softc[unit].sc_devstate |= ST_CONNECTED;
+ rbch_softc[unit].cd = cdp;
+ wakeup((caddr_t) &rbch_softc[unit]);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at disconnect time
+ *---------------------------------------------------------------------------*/
+static void
+rbch_disconnect(int unit, void *cdp)
+{
+ /* call_desc_t *cd = (call_desc_t *)cdp; */
+
+ DBGL4(L4_RBCHDBG, "rbch_disconnect", ("unit %d, deinit\n", unit));
+ rbch_softc[unit].sc_devstate &= ~ST_CONNECTED;
+ rbch_softc[unit].cd = NULL;
+}
+
+/*---------------------------------------------------------------------------*
+ * feedback from daemon in case of dial problems
+ *---------------------------------------------------------------------------*/
+static void
+rbch_dialresponse(int unit, int status)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * interface up/down
+ *---------------------------------------------------------------------------*/
+static void
+rbch_updown(int unit, int updown)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when a new frame (mbuf) has been received and is to be put on
+ * the rx queue.
+ *---------------------------------------------------------------------------*/
+static void
+rbch_rx_data_rdy(int unit)
+{
+ if(rbch_softc[unit].sc_bprot == BPROT_RHDLC)
+ {
+ register struct mbuf *m;
+
+ if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
+ return;
+
+ m->m_pkthdr.len = m->m_len;
+
+ if(IF_QFULL(&(rbch_softc[unit].sc_hdlcq)))
+ {
+ DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d: hdlc rx queue full!\n", unit));
+ m_freem(m);
+ }
+ else
+ {
+ IF_ENQUEUE(&(rbch_softc[unit].sc_hdlcq), m);
+ }
+ }
+
+ if(rbch_softc[unit].sc_devstate & ST_RDWAITDATA)
+ {
+ DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d, wakeup\n", unit));
+ rbch_softc[unit].sc_devstate &= ~ST_RDWAITDATA;
+ wakeup((caddr_t) &isdn_linktab[unit]->rx_queue);
+ }
+ else
+ {
+ DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d, NO wakeup\n", unit));
+ }
+ selwakeup(&rbch_softc[unit].selp);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when the last frame has been sent out and there is no
+ * further frame (mbuf) in the tx queue.
+ *---------------------------------------------------------------------------*/
+static void
+rbch_tx_queue_empty(int unit)
+{
+ if(rbch_softc[unit].sc_devstate & ST_WRWAITEMPTY)
+ {
+ DBGL4(L4_RBCHDBG, "rbch_tx_queue_empty", ("unit %d, wakeup\n", unit));
+ rbch_softc[unit].sc_devstate &= ~ST_WRWAITEMPTY;
+ wakeup((caddr_t) &isdn_linktab[unit]->tx_queue);
+ }
+ else
+ {
+ DBGL4(L4_RBCHDBG, "rbch_tx_queue_empty", ("unit %d, NO wakeup\n", unit));
+ }
+ selwakeup(&rbch_softc[unit].selp);
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * each time a packet is received or transmitted
+ *---------------------------------------------------------------------------*/
+static void
+rbch_activity(int unit, int rxtx)
+{
+ if (rbch_softc[unit].cd)
+ rbch_softc[unit].cd->last_active_time = SECOND;
+ selwakeup(&rbch_softc[unit].selp);
+}
+
+/*---------------------------------------------------------------------------*
+ * clear an hdlc rx queue for a rbch unit
+ *---------------------------------------------------------------------------*/
+static void
+rbch_clrq(int unit)
+{
+ int x;
+ struct mbuf *m;
+
+ for(;;)
+ {
+ x = splimp();
+ IF_DEQUEUE(&rbch_softc[unit].sc_hdlcq, m);
+ splx(x);
+ if(m)
+ m_freem(m);
+ else
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * return this drivers linktab address
+ *---------------------------------------------------------------------------*/
+drvr_link_t *
+rbch_ret_linktab(int unit)
+{
+ rbch_init_linktab(unit);
+ return(&rbch_drvr_linktab[unit]);
+}
+
+/*---------------------------------------------------------------------------*
+ * setup the isdn_linktab for this driver
+ *---------------------------------------------------------------------------*/
+void
+rbch_set_linktab(int unit, isdn_link_t *ilt)
+{
+ isdn_linktab[unit] = ilt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize this drivers linktab
+ *---------------------------------------------------------------------------*/
+static void
+rbch_init_linktab(int unit)
+{
+ rbch_drvr_linktab[unit].unit = unit;
+ rbch_drvr_linktab[unit].bch_rx_data_ready = rbch_rx_data_rdy;
+ rbch_drvr_linktab[unit].bch_tx_queue_empty = rbch_tx_queue_empty;
+ rbch_drvr_linktab[unit].bch_activity = rbch_activity;
+ rbch_drvr_linktab[unit].line_connected = rbch_connect;
+ rbch_drvr_linktab[unit].line_disconnected = rbch_disconnect;
+ rbch_drvr_linktab[unit].dial_response = rbch_dialresponse;
+ rbch_drvr_linktab[unit].updown_ind = rbch_updown;
+}
+
+/*===========================================================================*/
+
+#endif /* NI4BRBCH > 0 */
diff --git a/sys/i4b/driver/i4b_tel.c b/sys/i4b/driver/i4b_tel.c
new file mode 100644
index 000000000000..81b38a614b06
--- /dev/null
+++ b/sys/i4b/driver/i4b_tel.c
@@ -0,0 +1,713 @@
+/*
+ * 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_tel.c - device driver for ISDN telephony
+ * --------------------------------------------
+ *
+ * $Id: i4b_tel.c,v 1.18 1998/12/14 10:31:53 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 11:32:06 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4btel.h"
+
+#if NI4BTEL > 0
+
+#undef I4BTELDEBUG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+
+#ifdef __FreeBSD__
+#include "opt_devfs.h"
+#endif
+
+#ifdef DEVFS
+#include <sys/devfsext.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_tel_ioctl.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_tel_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_l3l4.h>
+
+typedef struct {
+ drvr_link_t drvr_linktab; /* driver linktab */
+ isdn_link_t *isdn_linktab; /* isdn linktab */
+ int devstate; /* state of this unit */
+#define ST_IDLE 0x00 /* idle */
+#define ST_CONNECTED 0x01 /* isdn connected state */
+#define ST_ISOPEN 0x02 /* userland opened */
+#define ST_RDWAITDATA 0x04 /* userland read waiting */
+#define ST_WRWAITEMPTY 0x08 /* userland write waiting */
+ int audiofmt; /* audio format conversion */
+ call_desc_t *cdp; /* call descriptor pointer */
+#ifdef DEVFS
+ void *devfs_token; /* token for DEVFS */
+#endif
+} tel_sc_t;
+
+static tel_sc_t tel_sc[NI4BTEL];
+
+/* forward decl */
+
+static void tel_rx_data_rdy(int unit);
+static void tel_tx_queue_empty(int unit);
+static void tel_init_linktab(int unit);
+static void tel_connect(int unit, void *cdp);
+static void tel_disconnect(int unit, void *cdp);
+
+static unsigned char alaw_ulaw[];
+static unsigned char ulaw_alaw[];
+
+#ifndef __FreeBSD__
+#define PDEVSTATIC /* - not static - */
+PDEVSTATIC void i4btelattach __P((void));
+PDEVSTATIC int i4btelioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
+int i4btelopen __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4btelclose __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4btelread __P((dev_t dev, struct uio *uio, int ioflag));
+int i4btelwrite __P((dev_t dev, struct uio * uio, int ioflag));
+#endif
+#if BSD > 199306 && defined(__FreeBSD__)
+#define PDEVSTATIC static
+PDEVSTATIC d_open_t i4btelopen;
+PDEVSTATIC d_close_t i4btelclose;
+PDEVSTATIC d_read_t i4btelread;
+PDEVSTATIC d_read_t i4btelwrite;
+PDEVSTATIC d_ioctl_t i4btelioctl;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+PDEVSTATIC d_poll_t i4btelpoll;
+#endif
+
+#define CDEV_MAJOR 56
+static struct cdevsw i4btel_cdevsw = {
+ i4btelopen, i4btelclose, i4btelread, i4btelwrite,
+ i4btelioctl, nostop, noreset, nodevtotty,
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ i4btelpoll, nommap, NULL, "i4btel", NULL, -1
+#else
+ noselect, nommap, NULL, "i4btel", NULL, -1
+#endif
+};
+
+PDEVSTATIC void i4btelinit(void *unused);
+
+PDEVSTATIC void i4btelattach(void *);
+PSEUDO_SET(i4btelattach, i4b_tel);
+
+/*===========================================================================*
+ * DEVICE DRIVER ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * initialization at kernel load time
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+i4btelinit(void *unused)
+{
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+
+ cdevsw_add(&dev, &i4btel_cdevsw, NULL);
+}
+
+SYSINIT(i4bteldev, SI_SUB_DRIVERS,
+ SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btelinit, NULL);
+
+#endif /* BSD > 199306 && defined(__FreeBSD__) */
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4btelattach(void *dummy)
+#else
+i4btelattach()
+#endif
+{
+ int i;
+
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+ printf("i4btel: %d ISDN telephony interface device(s) attached\n", NI4BTEL);
+#endif
+
+ for(i=0; i < NI4BTEL; i++)
+ {
+ tel_sc[i].devstate = ST_IDLE;
+ tel_sc[i].audiofmt = CVT_NONE;
+ tel_init_linktab(i);
+#ifdef DEVFS
+ tel_sc[i].devfs_token
+ = devfs_add_devswf(&i4btel_cdevsw, i, DV_CHR,
+ UID_ROOT, GID_WHEEL, 0600,
+ "i4btel%d", i);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * open tel device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btelopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int unit = minor(dev);
+ tel_sc_t *sc;
+
+ if(unit > NI4BTEL)
+ return(ENXIO);
+
+ sc = &tel_sc[unit];
+
+ if(!(sc->devstate & ST_CONNECTED))
+ return(EIO);
+
+ if(sc->devstate & ST_ISOPEN)
+ return(EBUSY);
+
+ sc->devstate |= ST_ISOPEN;
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * close tel device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btelclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int unit = minor(dev);
+ tel_sc_t *sc;
+ int error = 0;
+
+ if(unit > NI4BTEL)
+ return(ENXIO);
+
+ sc = &tel_sc[unit];
+
+ if(sc->isdn_linktab != NULL && sc->isdn_linktab->tx_queue != NULL)
+ {
+ while(!(IF_QEMPTY(sc->isdn_linktab->tx_queue)))
+ {
+ sc->devstate |= ST_WRWAITEMPTY;
+
+ if((error = tsleep((caddr_t) &sc->isdn_linktab->tx_queue,
+ TTIPRI | PCATCH, "wtcl", 0)) != 0)
+ {
+ break;
+ }
+ }
+ sc->devstate &= ~ST_WRWAITEMPTY;
+ }
+ sc->devstate &= ~ST_ISOPEN;
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4btelioctl - device driver ioctl routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003
+i4btelioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+#else
+i4btelioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+#endif
+{
+ int error = 0;
+ struct mbuf *m;
+ int s;
+ tel_sc_t *sc = &tel_sc[minor(dev)];
+
+ switch(cmd)
+ {
+ case I4B_TEL_GETAUDIOFMT:
+ *(int *)data = sc->audiofmt;
+ break;
+
+ case I4B_TEL_SETAUDIOFMT:
+ sc->audiofmt = *(int *)data;
+ break;
+
+ case I4B_TEL_EMPTYINPUTQUEUE:
+ s = splimp();
+ while((sc->devstate & ST_CONNECTED) &&
+ (sc->devstate & ST_ISOPEN) &&
+ !IF_QEMPTY(sc->isdn_linktab->rx_queue))
+ {
+ IF_DEQUEUE(sc->isdn_linktab->rx_queue, m);
+ if(m)
+ i4b_Bfreembuf(m);
+ }
+ splx(s);
+ break;
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * read from tel device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btelread(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct mbuf *m;
+ int s;
+ int error = 0;
+ tel_sc_t *sc = &tel_sc[minor(dev)];
+
+ if(!(sc->devstate & ST_CONNECTED))
+ return(EIO);
+
+ if(!(sc->devstate & ST_ISOPEN))
+ return(EIO);
+
+#ifdef NOTDEF
+ while(!(sc->devstate & ST_CONNECTED))
+ {
+ if((error = tsleep((caddr_t) &sc->devstate,
+ TTIPRI | PCATCH,
+ "rrtel", 0 )) != 0)
+ {
+ return(error);
+ }
+ }
+#endif
+
+ while(IF_QEMPTY(sc->isdn_linktab->rx_queue) &&
+ (sc->devstate & ST_ISOPEN) &&
+ (sc->devstate & ST_CONNECTED))
+ {
+ sc->devstate |= ST_RDWAITDATA;
+
+ if((error = tsleep((caddr_t) &sc->isdn_linktab->rx_queue,
+ TTIPRI | PCATCH,
+ "rtel", 0 )) != 0)
+ {
+ sc->devstate &= ~ST_RDWAITDATA;
+ return(error);
+ }
+ }
+
+ if(!(sc->devstate & ST_ISOPEN))
+ {
+ return(EIO);
+ }
+
+ if(!(sc->devstate & ST_CONNECTED))
+ {
+ return(EIO);
+ }
+
+ s = splimp();
+
+ IF_DEQUEUE(sc->isdn_linktab->rx_queue, m);
+
+ if(m && m->m_len)
+ {
+ if(sc->audiofmt == CVT_ALAW2ULAW)
+ {
+ int i;
+ for(i = 0; i < m->m_len; i++)
+ m->m_data[i] = alaw_ulaw[(int)m->m_data[i]];
+ }
+ error = uiomove(m->m_data, m->m_len, uio);
+ }
+ else
+ {
+ error = EIO;
+ }
+
+ if(m)
+ i4b_Bfreembuf(m);
+
+ splx(s);
+
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * write to tel device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btelwrite(dev_t dev, struct uio * uio, int ioflag)
+{
+ struct mbuf *m;
+ int s;
+ int error = 0;
+ tel_sc_t *sc = &tel_sc[minor(dev)];
+
+ if(!(sc->devstate & ST_CONNECTED))
+ return(EIO);
+
+ if(!(sc->devstate & ST_ISOPEN))
+ {
+ return(EIO);
+ }
+
+#ifdef NOTDEF
+ while(!(sc->devstate & ST_CONNECTED))
+ {
+ if((error = tsleep((caddr_t) &sc->devstate,
+ TTIPRI | PCATCH,
+ "wrtel", 0 )) != 0)
+ {
+ return(error);
+ }
+
+ /*
+ * XXX the originations B channel gets much earlier
+ * switched thru than the destinations B channel, so
+ * if the origination starts to send at once, some
+ * 200 bytes (at my site) or so get lost, so i delay
+ * a bit before sending. (-hm)
+ */
+
+ tsleep((caddr_t) &sc->devstate, TTIPRI | PCATCH, "xtel", (hz*1));
+ }
+#endif
+
+ while((IF_QFULL(sc->isdn_linktab->tx_queue)) &&
+ (sc->devstate & ST_ISOPEN))
+ {
+ sc->devstate |= ST_WRWAITEMPTY;
+
+ if((error = tsleep((caddr_t) &sc->isdn_linktab->tx_queue,
+ TTIPRI | PCATCH, "wtel", 0)) != 0)
+ {
+ sc->devstate &= ~ST_WRWAITEMPTY;
+ return(error);
+ }
+ }
+
+ if(!(sc->devstate & ST_ISOPEN))
+ {
+ return(EIO);
+ }
+
+ if(!(sc->devstate & ST_CONNECTED))
+ {
+ return(EIO);
+ }
+
+ s = splimp();
+
+ if((m = i4b_Bgetmbuf(BCH_MAX_DATALEN)) != NULL)
+ {
+ m->m_len = min(BCH_MAX_DATALEN, uio->uio_resid);
+
+ error = uiomove(m->m_data, m->m_len, uio);
+
+ if(sc->audiofmt == CVT_ALAW2ULAW)
+ {
+ int i;
+ for(i = 0; i < m->m_len; i++)
+ m->m_data[i] = ulaw_alaw[(int)m->m_data[i]];
+ }
+
+ IF_ENQUEUE(sc->isdn_linktab->tx_queue, m);
+
+ (*sc->isdn_linktab->bch_tx_start)(sc->isdn_linktab->unit, sc->isdn_linktab->channel);
+ }
+
+ splx(s);
+
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * poll
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+PDEVSTATIC int
+i4btelpoll (dev_t dev, int events, struct proc *p)
+{
+ return (ENODEV);
+}
+#endif
+
+/*===========================================================================*
+ * ISDN INTERFACE ROUTINES
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+* this routine is called from L4 handler at connect time
+ *---------------------------------------------------------------------------*/
+static void
+tel_connect(int unit, void *cdp)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+
+ sc->cdp = (call_desc_t *)cdp;
+
+#ifdef NOTDEF
+ if(!(sc->devstate & ST_CONNECTED))
+ {
+ sc->devstate |= ST_CONNECTED;
+ wakeup((caddr_t) &sc->devstate);
+ }
+#else
+ sc->devstate |= ST_CONNECTED;
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from L4 handler at disconnect time
+ *---------------------------------------------------------------------------*/
+static void
+tel_disconnect(int unit, void *cdp)
+{
+/* call_desc_t *cd = (call_desc_t *)cdp; */
+
+ tel_sc_t *sc = &tel_sc[unit];
+
+ sc->devstate &= ~ST_CONNECTED;
+
+ if(sc->devstate & ST_RDWAITDATA)
+ {
+ sc->devstate &= ~ST_RDWAITDATA;
+ wakeup((caddr_t) &sc->isdn_linktab->rx_queue);
+ }
+
+ if(sc->devstate & ST_WRWAITEMPTY)
+ {
+ sc->devstate &= ~ST_WRWAITEMPTY;
+ wakeup((caddr_t) &sc->isdn_linktab->tx_queue);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * feedback from daemon in case of dial problems
+ *---------------------------------------------------------------------------*/
+static void
+tel_dialresponse(int unit, int status)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * interface up/down
+ *---------------------------------------------------------------------------*/
+static void
+tel_updown(int unit, int updown)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when a new frame (mbuf) has been received and was put on
+ * the rx queue.
+ *---------------------------------------------------------------------------*/
+static void
+tel_rx_data_rdy(int unit)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+
+ if(sc->devstate & ST_RDWAITDATA)
+ {
+ sc->devstate &= ~ST_RDWAITDATA;
+ wakeup((caddr_t) &sc->isdn_linktab->rx_queue);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * when the last frame has been sent out and there is no
+ * further frame (mbuf) in the tx queue.
+ *---------------------------------------------------------------------------*/
+static void
+tel_tx_queue_empty(int unit)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+
+ if(sc->devstate & ST_WRWAITEMPTY)
+ {
+ sc->devstate &= ~ST_WRWAITEMPTY;
+ wakeup((caddr_t) &sc->isdn_linktab->tx_queue);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * this routine is called from the HSCX interrupt handler
+ * each time a packet is received or transmitted.
+ *---------------------------------------------------------------------------*/
+static void
+tel_activity(int unit, int rxtx)
+{
+ tel_sc[unit].cdp->last_active_time = SECOND;
+}
+
+/*---------------------------------------------------------------------------*
+ * return this drivers linktab address
+ *---------------------------------------------------------------------------*/
+drvr_link_t *
+tel_ret_linktab(int unit)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+
+ tel_init_linktab(unit);
+ return(&sc->drvr_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * setup the isdn_linktab for this driver
+ *---------------------------------------------------------------------------*/
+void
+tel_set_linktab(int unit, isdn_link_t *ilt)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+ sc->isdn_linktab = ilt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize this drivers linktab
+ *---------------------------------------------------------------------------*/
+static void
+tel_init_linktab(int unit)
+{
+ tel_sc_t *sc = &tel_sc[unit];
+
+ sc->drvr_linktab.unit = unit;
+ sc->drvr_linktab.bch_rx_data_ready = tel_rx_data_rdy;
+ sc->drvr_linktab.bch_tx_queue_empty = tel_tx_queue_empty;
+ sc->drvr_linktab.bch_activity = tel_activity;
+ sc->drvr_linktab.line_connected = tel_connect;
+ sc->drvr_linktab.line_disconnected = tel_disconnect;
+ sc->drvr_linktab.dial_response = tel_dialresponse;
+ sc->drvr_linktab.updown_ind = tel_updown;
+}
+
+/*===========================================================================*
+ * AUDIO FORMAT CONVERSION
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * A-law to mu-law conversion
+ *---------------------------------------------------------------------------*/
+static unsigned char alaw_ulaw[] = {
+ 0x002a, 0x00a9, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0048, 0x00c8,
+ 0x0039, 0x00b9, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d7,
+ 0x0022, 0x00a1, 0x005b, 0x00dd, 0x001f, 0x009f, 0x0040, 0x00c0,
+ 0x0031, 0x00b1, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00cf,
+ 0x002e, 0x00ad, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004c, 0x00cc,
+ 0x003d, 0x00bd, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00db,
+ 0x0026, 0x00a5, 0x005d, 0x00df, 0x001f, 0x009f, 0x0044, 0x00c4,
+ 0x0035, 0x00b5, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d3,
+ 0x0028, 0x00a7, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0046, 0x00c6,
+ 0x0037, 0x00b7, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0053, 0x00d5,
+ 0x0020, 0x009f, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf,
+ 0x002f, 0x00af, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004d, 0x00ce,
+ 0x002c, 0x00ab, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004a, 0x00ca,
+ 0x003b, 0x00bb, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0057, 0x00d9,
+ 0x0024, 0x00a3, 0x005d, 0x00df, 0x001f, 0x009f, 0x0042, 0x00c2,
+ 0x0033, 0x00b3, 0x006b, 0x00ef, 0x001f, 0x009f, 0x004f, 0x00d1,
+ 0x002b, 0x00aa, 0x0063, 0x00e3, 0x001f, 0x009f, 0x0049, 0x00c9,
+ 0x003a, 0x00ba, 0x0077, 0x00f7, 0x001f, 0x009f, 0x0057, 0x00d7,
+ 0x0023, 0x00a2, 0x005d, 0x00dd, 0x001f, 0x009f, 0x0041, 0x00c1,
+ 0x0032, 0x00b2, 0x006b, 0x00eb, 0x001f, 0x009f, 0x004f, 0x00cf,
+ 0x002f, 0x00ae, 0x0067, 0x00e7, 0x001f, 0x009f, 0x004d, 0x00cd,
+ 0x003e, 0x00be, 0x00ff, 0x00ff, 0x001f, 0x009f, 0x005b, 0x00db,
+ 0x0027, 0x00a6, 0x005f, 0x00df, 0x001f, 0x009f, 0x0045, 0x00c5,
+ 0x0036, 0x00b6, 0x006f, 0x00ef, 0x001f, 0x009f, 0x0053, 0x00d3,
+ 0x0029, 0x00a8, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0047, 0x00c7,
+ 0x0038, 0x00b8, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d5,
+ 0x0021, 0x00a0, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf,
+ 0x0030, 0x00b0, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00ce,
+ 0x002d, 0x00ac, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004b, 0x00cb,
+ 0x003c, 0x00bc, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00d9,
+ 0x0025, 0x00a4, 0x005d, 0x00df, 0x001f, 0x009f, 0x0043, 0x00c3,
+ 0x0034, 0x00b4, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d1
+};
+
+/*---------------------------------------------------------------------------*
+ * mu-law to A-law conversion
+ *---------------------------------------------------------------------------*/
+static unsigned char ulaw_alaw[] = {
+ 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc,
+ 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc,
+ 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc,
+ 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00ac,
+ 0x0050, 0x00d0, 0x0010, 0x0090, 0x0070, 0x00f0, 0x0030, 0x00b0,
+ 0x0040, 0x00c0, 0x0000, 0x0080, 0x0060, 0x00e0, 0x0020, 0x00a0,
+ 0x00d8, 0x0018, 0x0098, 0x0078, 0x00f8, 0x0038, 0x00b8, 0x0048,
+ 0x00c8, 0x0008, 0x0088, 0x0068, 0x00e8, 0x0028, 0x00a8, 0x00d6,
+ 0x0096, 0x0076, 0x00f6, 0x0036, 0x00b6, 0x0046, 0x00c6, 0x0006,
+ 0x0086, 0x0066, 0x00e6, 0x0026, 0x00a6, 0x00de, 0x009e, 0x00fe,
+ 0x00fe, 0x00be, 0x00be, 0x00ce, 0x00ce, 0x008e, 0x008e, 0x00ee,
+ 0x00ee, 0x00d2, 0x00d2, 0x00f2, 0x00f2, 0x00c2, 0x00c2, 0x00e2,
+ 0x00e2, 0x00e2, 0x00da, 0x00da, 0x00da, 0x00da, 0x00fa, 0x00fa,
+ 0x00fa, 0x00fa, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ea, 0x00ea,
+ 0x00ea, 0x00ea, 0x00ea, 0x00ea, 0x00eb, 0x00eb, 0x00eb, 0x00eb,
+ 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb,
+ 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd,
+ 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd,
+ 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd,
+ 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd,
+ 0x00d1, 0x0011, 0x0091, 0x0071, 0x00f1, 0x0031, 0x00b1, 0x0041,
+ 0x00c1, 0x0001, 0x0081, 0x0061, 0x00e1, 0x0021, 0x00a1, 0x0059,
+ 0x00d9, 0x0019, 0x0099, 0x0079, 0x00f9, 0x0039, 0x00b9, 0x0049,
+ 0x00c9, 0x0009, 0x0089, 0x0069, 0x00e9, 0x0029, 0x00a9, 0x0057,
+ 0x0017, 0x0097, 0x0077, 0x00f7, 0x0037, 0x00b7, 0x0047, 0x00c7,
+ 0x0007, 0x0087, 0x0067, 0x00e7, 0x0027, 0x00a7, 0x00df, 0x009f,
+ 0x009f, 0x00ff, 0x00ff, 0x00bf, 0x00bf, 0x00cf, 0x00cf, 0x008f,
+ 0x008f, 0x00ef, 0x00ef, 0x00af, 0x00af, 0x00d3, 0x00d3, 0x00f3,
+ 0x00f3, 0x00f3, 0x00c3, 0x00c3, 0x00c3, 0x00c3, 0x00e3, 0x00e3,
+ 0x00e3, 0x00e3, 0x00db, 0x00db, 0x00db, 0x00db, 0x00fb, 0x00fb,
+ 0x00fb, 0x00fb, 0x00fb, 0x00fb, 0x00cb, 0x00cb, 0x00cb, 0x00cb,
+ 0x00cb, 0x00cb, 0x00cb, 0x00cb, 0x00eb, 0x00eb, 0x00eb, 0x00eb
+};
+
+/*===========================================================================*/
+
+#endif /* NI4BTEL > 0 */
diff --git a/sys/i4b/driver/i4b_trace.c b/sys/i4b/driver/i4b_trace.c
new file mode 100644
index 000000000000..f64e35d622fd
--- /dev/null
+++ b/sys/i4b/driver/i4b_trace.c
@@ -0,0 +1,508 @@
+/*
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4btrc - device driver for trace data read device
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_trace.c,v 1.14 1998/12/05 18:02:51 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:01:53 1998]
+ *
+ * NOTE: the code assumes that SPLI4B >= splimp !
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "i4btrc.h"
+
+#if NI4BTRC > 0
+
+#ifdef __FreeBSD__
+#include "isic.h" /* 'isic' is no pseudo-device on non FreeBSD -
+ * so we just can't count it at compile time,
+ * we're doing an attach-time check instead. */
+
+#if NI4BTRC < NISIC
+#error "number of trace devices != number of passive ISDN controllers !"
+#error "change number of i4btrc to be equal to number of isic devices !"
+#endif
+#endif /* __FreeBSD__ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/proc.h>
+#include <sys/tty.h>
+
+#ifdef __FreeBSD__
+#include "opt_devfs.h"
+#endif
+
+#ifdef DEVFS
+#include <sys/devfsext.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_trace.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_trace.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#ifndef __FreeBSD__
+#define memcpy(d,s,l) bcopy(s,d,l)
+#endif
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+
+static struct ifqueue trace_queue[NI4BTRC];
+static int device_state[NI4BTRC];
+#define ST_IDLE 0x00
+#define ST_ISOPEN 0x01
+#define ST_WAITDATA 0x02
+#ifdef DEVFS
+static void *devfs_token[NI4BTRC];
+#endif
+
+static int analyzemode = 0;
+static int rxunit = -1;
+static int txunit = -1;
+static int outunit = -1;
+
+#ifndef __FreeBSD__
+#define PDEVSTATIC /* - not static - */
+void i4btrcattach __P((void));
+int i4btrcopen __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4btrcclose __P((dev_t dev, int flag, int fmt, struct proc *p));
+int i4btrcread __P((dev_t dev, struct uio * uio, int ioflag));
+int i4btrcioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p));
+#endif
+
+#if BSD > 199306 && defined(__FreeBSD__)
+#define PDEVSTATIC static
+static d_open_t i4btrcopen;
+static d_close_t i4btrcclose;
+static d_read_t i4btrcread;
+static d_ioctl_t i4btrcioctl;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+static d_poll_t i4btrcpoll;
+#endif
+
+#define CDEV_MAJOR 59
+static struct cdevsw i4btrc_cdevsw = {
+ i4btrcopen, i4btrcclose, i4btrcread, nowrite,
+ i4btrcioctl, nostop, noreset, nodevtotty,
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ i4btrcpoll, nommap, NULL, "i4btrc", NULL, -1
+#else
+ noselect, nommap, NULL, "i4btrc", NULL, -1
+#endif
+};
+
+/*---------------------------------------------------------------------------*
+ * interface init routine
+ *---------------------------------------------------------------------------*/
+static
+void i4btrcinit(void *unused)
+{
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+
+ cdevsw_add(&dev, &i4btrc_cdevsw, NULL);
+}
+
+SYSINIT(i4btrcdev, SI_SUB_DRIVERS,
+ SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL);
+
+static void i4btrcattach(void *);
+PSEUDO_SET(i4btrcattach, i4b_trace);
+
+#endif /* BSD > 199306 && defined(__FreeBSD__) */
+
+int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf);
+
+/*---------------------------------------------------------------------------*
+ * interface attach routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC void
+#ifdef __FreeBSD__
+i4btrcattach(void *dummy)
+#else
+i4btrcattach()
+#endif
+{
+ int i;
+
+#ifndef HACK_NO_PSEUDO_ATTACH_MSG
+ printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC);
+#endif
+
+ for(i=0; i < NI4BTRC; i++)
+ {
+#ifdef DEVFS
+ devfs_token[i]
+ = devfs_add_devswf(&i4btrc_cdevsw, i, DV_CHR,
+ UID_ROOT, GID_WHEEL, 0600,
+ "i4btrc%d", i);
+#endif
+ trace_queue[i].ifq_maxlen = IFQ_MAXLEN;
+ device_state[i] = ST_IDLE;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * get_trace_data_from_l1()
+ * ------------------------
+ * is called from layer 1, adds timestamp to trace data and puts
+ * it into a queue, from which it can be read from the i4btrc
+ * device. The unit number in the trace header selects the minor
+ * device's queue the data is put into.
+ *---------------------------------------------------------------------------*/
+int
+get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf)
+{
+ struct mbuf *m;
+ int x;
+ int unit;
+ int trunc = 0;
+ int totlen = len + sizeof(i4b_trace_hdr_t);
+
+ /*
+ * for telephony (or better non-HDLC HSCX mode) we get
+ * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets
+ * to put into the queue to userland. because of this
+ * we detect this situation, strip the length to MCLBYTES
+ * max size, and infor the userland program of this fact
+ * by putting the no of truncated bytes into hdr->trunc.
+ */
+
+ if(totlen > MCLBYTES)
+ {
+ trunc = 1;
+ hdr->trunc = totlen - MCLBYTES;
+ totlen = MCLBYTES;
+ }
+ else
+ {
+ hdr->trunc = 0;
+ }
+
+ /* set length of trace record */
+
+ hdr->length = totlen;
+
+ /* check valid unit no */
+
+ if((unit = hdr->unit) > NI4BTRC)
+ {
+ printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n");
+ return(0);
+ }
+
+ /* get mbuf */
+
+ if(!(m = i4b_Bgetmbuf(totlen)))
+ {
+ printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n");
+ return(0);
+ }
+
+ /* check if we are in analyzemode */
+
+ if(analyzemode && (unit == rxunit || unit == txunit))
+ {
+ if(unit == rxunit)
+ hdr->dir = FROM_NT;
+ else
+ hdr->dir = FROM_TE;
+ unit = outunit;
+ }
+
+ if(IF_QFULL(&trace_queue[unit]))
+ {
+ struct mbuf *m1;
+
+ x = SPLI4B();
+ IF_DEQUEUE(&trace_queue[unit], m1);
+ splx(x);
+
+ i4b_Bfreembuf(m1);
+ }
+
+ /* copy trace header */
+ memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t));
+
+ /* copy trace data */
+ if(trunc)
+ memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t));
+ else
+ memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len);
+
+ x = SPLI4B();
+
+ IF_ENQUEUE(&trace_queue[unit], m);
+
+ if(device_state[unit] & ST_WAITDATA)
+ {
+ device_state[unit] &= ~ST_WAITDATA;
+ wakeup((caddr_t) &trace_queue[unit]);
+ }
+
+ splx(x);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ * open trace device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btrcopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int x;
+ int unit = minor(dev);
+
+ if(unit > NI4BTRC)
+ return(ENXIO);
+
+ if(device_state[unit] & ST_ISOPEN)
+ return(EBUSY);
+
+ if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit))
+ return(EBUSY);
+
+ x = SPLI4B();
+
+ device_state[unit] = ST_ISOPEN;
+
+ splx(x);
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * close trace device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btrcclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ int unit = minor(dev);
+ int i, x, cno = -1;
+
+ for(i = 0; i < nctrl; i++)
+ {
+ if(ctrl_desc[i].N_SET_TRACE)
+ {
+ cno = i;
+ break;
+ }
+ }
+
+ if(analyzemode && (unit == outunit))
+ {
+ analyzemode = 0;
+ outunit = -1;
+
+ if(cno >= 0)
+ {
+ ctrl_desc[cno].N_SET_TRACE(rxunit, TRACE_OFF);
+ ctrl_desc[cno].N_SET_TRACE(txunit, TRACE_OFF);
+ }
+ rxunit = -1;
+ txunit = -1;
+ }
+
+ if(cno >= 0)
+ {
+ ctrl_desc[cno].N_SET_TRACE(unit, TRACE_OFF);
+ }
+
+ x = SPLI4B();
+ device_state[unit] = ST_IDLE;
+ splx(x);
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * read from trace device
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+i4btrcread(dev_t dev, struct uio * uio, int ioflag)
+{
+ struct mbuf *m;
+ int x;
+ int error = 0;
+ int unit = minor(dev);
+
+ if(!(device_state[unit] & ST_ISOPEN))
+ return(EIO);
+
+ x = SPLI4B();
+
+ while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN))
+ {
+ device_state[unit] |= ST_WAITDATA;
+
+ if((error = tsleep((caddr_t) &trace_queue[unit],
+ TTIPRI | PCATCH,
+ "bitrc", 0 )) != 0)
+ {
+ device_state[unit] &= ~ST_WAITDATA;
+ splx(x);
+ return(error);
+ }
+ }
+
+ IF_DEQUEUE(&trace_queue[unit], m);
+
+ if(m && m->m_len)
+ error = uiomove(m->m_data, m->m_len, uio);
+ else
+ error = EIO;
+
+ if(m)
+ i4b_Bfreembuf(m);
+
+ splx(x);
+
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * poll device
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+PDEVSTATIC int
+i4btrcpoll(dev_t dev, int events, struct proc *p)
+{
+ return(ENODEV);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * device driver ioctl routine
+ *---------------------------------------------------------------------------*/
+PDEVSTATIC int
+#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003
+i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+#else
+i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
+#endif
+{
+ int error = 0;
+ int unit = minor(dev);
+ i4b_trace_setupa_t *tsa;
+ int i, cno = -1;
+
+ /* find the first passive controller to get at the set/get function
+ pointers. Would be better if we had the controller class virtual
+ function table separate from the port registry... */
+
+ for(i=0; i < nctrl; i++)
+ {
+ if(ctrl_desc[i].N_SET_TRACE)
+ {
+ cno = i; /* one suitable controller, might not */
+ break; /* be related to the trace unit at all, but */
+ } /* has the right function pointers */
+ }
+
+ switch(cmd)
+ {
+ case I4B_TRC_GET:
+ if(cno < 0)
+ return ENOTTY;
+ *(int *)data = ctrl_desc[cno].N_GET_TRACE(unit);
+ break;
+
+ case I4B_TRC_SET:
+ if(cno < 0)
+ return ENOTTY;
+ ctrl_desc[cno].N_SET_TRACE(unit, *(int *)data);
+ break;
+
+ case I4B_TRC_SETA:
+ tsa = (i4b_trace_setupa_t *)data;
+
+ if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC)
+ rxunit = tsa->rxunit;
+ else
+ error = EINVAL;
+
+ if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC)
+ txunit = tsa->txunit;
+ else
+ error = EINVAL;
+
+ if(error)
+ {
+ outunit = -1;
+ rxunit = -1;
+ txunit = -1;
+ }
+ else
+ {
+ if(cno < 0)
+ return ENOTTY;
+
+ outunit = unit;
+ analyzemode = 1;
+ ctrl_desc[cno].N_SET_TRACE(rxunit, tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX));
+ ctrl_desc[cno].N_SET_TRACE(txunit, tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX));
+ }
+ break;
+
+ case I4B_TRC_RESETA:
+ analyzemode = 0;
+ outunit = -1;
+ rxunit = -1;
+ txunit = -1;
+ break;
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return(error);
+}
+
+#endif /* NI4BTRC > 0 */
diff --git a/sys/i4b/include/i4b_cause.h b/sys/i4b/include/i4b_cause.h
new file mode 100644
index 000000000000..439db4e2bcc4
--- /dev/null
+++ b/sys/i4b/include/i4b_cause.h
@@ -0,0 +1,144 @@
+/*
+ * 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_cause.h - causes and cause handling for i4b
+ * -----------------------------------------------
+ *
+ * $Id: i4b_cause.h,v 1.8 1998/12/05 18:05:55 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:36:30 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_CAUSE_H_
+#define _I4B_CAUSE_H_
+
+/*---------------------------------------------------------------------------*
+ * ISDN4BSD internal causes specification
+ *---------------------------------------------------------------------------*/
+
+#define CAUSE_VAL 0x000000ff /* cause value */
+#define CAUSE_TYPE 0x0000ff00 /* cause type */
+#define CAUSET_Q850 0 /* value coded according to Q.850 */
+#define CAUSET_I4B 1 /* i4b protocol independent causes*/
+
+#define GET_CAUSE_VAL(cause) ((cause) & 0xff)
+#define SET_CAUSE_VAL(dest, val) ((dest) = ((dest & 0xffffff00) | \
+ (val & 0x000000ff)))
+
+#define GET_CAUSE_TYPE(cause) (((cause) >> 8) & 0xff)
+#define SET_CAUSE_TYPE(dest, type) ((dest) = ((dest & 0xffff00ff) | \
+ ((type << 8) & 0x0000ff00)))
+
+#define SET_CAUSE_TV(dest, type, val) ((dest) = ((val & 0x000000ff) | \
+ ((type << 8) & 0x0000ff00)))
+
+/* CAUSET_I4B - protocol independent cause values */
+
+#define CAUSE_I4B_NORMAL 0 /* normal call clearing */
+#define CAUSE_I4B_BUSY 1 /* user busy */
+#define CAUSE_I4B_NOCHAN 2 /* circuit/channel not available*/
+#define CAUSE_I4B_INCOMP 3 /* incompatible source/dest */
+#define CAUSE_I4B_REJECT 4 /* call rejected */
+#define CAUSE_I4B_OOO 5 /* destination out of order */
+#define CAUSE_I4B_TMPFAIL 6 /* temporary failure */
+#define CAUSE_I4B_L1ERROR 7 /* L1 error / persistent deact */
+#define CAUSE_I4B_MAX 8
+
+/* CAUSET_Q850 - causes defined in Q.850 */
+
+#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */
+#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */
+#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */
+#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */
+#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */
+#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */
+#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */
+#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */
+#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */
+#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */
+#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */
+#define CAUSE_Q850_USRBSY 0x11 /* User busy */
+#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */
+#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */
+#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */
+#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */
+#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */
+#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */
+#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */
+#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */
+#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */
+#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */
+#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */
+#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */
+#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */
+#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */
+#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */
+#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */
+#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */
+#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */
+#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */
+#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */
+#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */
+#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */
+#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */
+#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */
+#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */
+#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */
+#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */
+#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */
+#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */
+#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */
+#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */
+#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */
+#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */
+#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */
+#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */
+#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */
+#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */
+#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */
+#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */
+#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */
+#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */
+#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */
+#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */
+#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */
+#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */
+#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */
+#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */
+#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */
+#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */
+#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */
+#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */
+#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */
+#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */
+#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */
+#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */
+#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */
+
+#define CAUSE_Q850_MAX 128
+
+#endif /* _I4B_CAUSE_H_ */
diff --git a/sys/i4b/include/i4b_debug.h b/sys/i4b/include/i4b_debug.h
new file mode 100644
index 000000000000..33e6315ba285
--- /dev/null
+++ b/sys/i4b/include/i4b_debug.h
@@ -0,0 +1,219 @@
+/*
+ * 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_debug.h - i4b debug header file
+ * -----------------------------------
+ *
+ * $Id: i4b_debug.h,v 1.14 1998/12/05 18:05:57 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:36:47 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#define DO_I4B_DEBUG /* enable debugging code inclusion */
+
+#undef DO_I4B_MAXDEBUG /* enable ALL debug messages by default */
+
+#ifdef DO_I4B_DEBUG
+
+extern unsigned int i4b_l1_debug;
+extern unsigned int i4b_l2_debug;
+extern unsigned int i4b_l3_debug;
+extern unsigned int i4b_l4_debug;
+
+#define DBGL1(bits, routine, what) \
+ if(bits & i4b_l1_debug) \
+ { \
+ printf("i4b-L1-%s: ", routine); \
+ printf what ; \
+ }
+
+#define DBGL2(bits, routine, what) \
+ if(bits & i4b_l2_debug) \
+ { \
+ printf("i4b-L2-%s: ", routine); \
+ printf what ; \
+ }
+
+#define DBGL3(bits, routine, what) \
+ if(bits & i4b_l3_debug) \
+ { \
+ printf("i4b-L3-%s: ", routine); \
+ printf what ; \
+ }
+
+#define DBGL4(bits, routine, what) \
+ if(bits & i4b_l4_debug) \
+ { \
+ printf("i4b-L4-%s: ", routine); \
+ printf what ; \
+ }
+#else /* !DO_I4B_DEBUG */
+
+#define DBGL1(bits, routine, what);
+#define DBGL2(bits, routine, what);
+#define DBGL3(bits, routine, what);
+#define DBGL4(bits, routine, what);
+
+#endif /* DO_I4B_DEBUG */
+
+/* Layer 1 */
+
+#define L1_ERROR 0x0001 /* general error message*/
+#define L1_PRIM 0x0002 /* interlayer primitives*/
+#define L1_BCHAN 0x0004 /* B channel action */
+#define L1_H_ERR 0x0008 /* HSCX errors */
+#define L1_H_IRQ 0x0010 /* HSCX IRQ messages */
+#define L1_I_ERR 0x0020 /* ISAC errors */
+#define L1_I_MSG 0x0040 /* ISAC messages */
+#define L1_I_SETUP 0x0080 /* ISAC setup messages */
+#define L1_F_MSG 0x0100 /* FSM messages */
+#define L1_F_ERR 0x0200 /* FSM error messages */
+#define L1_T_MSG 0x0400 /* Timer messages */
+#define L1_T_ERR 0x0800 /* Timer error messages */
+#define L1_H_XFRERR 0x1000 /* HSCX data xfer error */
+#define L1_I_CICO 0x2000 /* ISAC command in/out */
+
+#define L1_DEBUG_MAX 0x3fef /* all messages on except IRQ! */
+#define L1_DEBUG_ERR (L1_H_ERR | L1_I_ERR | L1_F_ERR | L1_T_ERR | L1_ERROR)
+
+#ifndef L1_DEBUG_DEFAULT
+#ifdef DO_I4B_MAXDEBUG
+#define L1_DEBUG_DEFAULT L1_DEBUG_MAX
+#else
+#define L1_DEBUG_DEFAULT L1_DEBUG_ERR
+#endif
+#endif
+
+/* Layer 2 */
+
+#define L2_ERROR 0x0001 /* general error message */
+#define L2_PRIM 0x0002 /* interlayer primitives */
+#define L2_U_MSG 0x0004 /* U frame messages */
+#define L2_U_ERR 0x0008 /* U frame error messages */
+#define L2_S_MSG 0x0010 /* S frame messages */
+#define L2_S_ERR 0x0020 /* S frame error messages */
+#define L2_I_MSG 0x0040 /* I frame messages */
+#define L2_I_ERR 0x0080 /* I frame error messages */
+#define L2_F_MSG 0x0100 /* FSM messages */
+#define L2_F_ERR 0x0200 /* FSM error messages */
+#define L2_T_MSG 0x0400 /* timer messages */
+#define L2_T_ERR 0x0800 /* timer error messages */
+#define L2_TEI_MSG 0x1000 /* TEI messages */
+#define L2_TEI_ERR 0x2000 /* TEI error messages */
+
+#define L2_DEBUG_MAX 0x3fff /* all messages on */
+#define L2_DEBUG_ERR (L2_ERROR | L2_I_ERR | L2_F_ERR | L2_T_ERR | L2_S_ERR | L2_TEI_ERR | L2_U_ERR )
+
+#ifndef L2_DEBUG_DEFAULT
+#ifdef DO_I4B_MAXDEBUG
+#define L2_DEBUG_DEFAULT L2_DEBUG_MAX
+#else
+#define L2_DEBUG_DEFAULT L2_DEBUG_ERR
+#endif
+#endif
+
+/* Layer 3 */
+
+#define L3_ERR 0x0001 /* general error message */
+#define L3_MSG 0x0002 /* general message */
+#define L3_F_MSG 0x0004 /* FSM messages */
+#define L3_F_ERR 0x0008 /* FSM error messages */
+#define L3_T_MSG 0x0010 /* timer messages */
+#define L3_T_ERR 0x0020 /* timer error messages */
+#define L3_P_MSG 0x0040 /* protocol messages */
+#define L3_P_ERR 0x0080 /* protocol error messages */
+#define L3_A_MSG 0x0100 /* AOC messages */
+#define L3_A_ERR 0x0200 /* AOC error messages */
+#define L3_PRIM 0x0400 /* messages exchanged */
+
+#define L3_DEBUG_MAX 0x07ff /* all messages on */
+#define L3_DEBUG_ERR (L3_ERR | L3_F_ERR | L3_T_ERR | L3_P_ERR | L3_A_ERR)
+
+#ifndef L3_DEBUG_DEFAULT
+#ifdef DO_I4B_MAXDEBUG
+#define L3_DEBUG_DEFAULT L3_DEBUG_MAX
+#else
+#define L3_DEBUG_DEFAULT L3_DEBUG_ERR
+#endif
+#endif
+
+/* Layer 4 */
+
+#define L4_ERR 0x0001 /* general error message */
+#define L4_MSG 0x0002 /* general message */
+#define L4_TIMO 0x0004 /* b channel idle timeout msgs */
+#define L4_DIALST 0x0008 /* network driver dial states */
+#define L4_IPRDBG 0x0010 /* ipr driver debug messages */
+#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */
+
+#define L4_DEBUG_MAX 0x003f /* all messages on */
+#define L4_DEBUG_ERR (L4_ERR)
+
+#ifndef L4_DEBUG_DEFAULT
+#ifdef DO_I4B_MAXDEBUG
+#define L4_DEBUG_DEFAULT L4_DEBUG_MAX
+#else
+#define L4_DEBUG_DEFAULT L4_DEBUG_ERR
+#endif
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ioctl via /dev/i4bctl:
+ * get/set current debug bits settings
+ *---------------------------------------------------------------------------*/
+
+typedef struct {
+ unsigned int l1;
+ unsigned int l2;
+ unsigned int l3;
+ unsigned int l4;
+} ctl_debug_t;
+
+#define I4B_CTL_GET_DEBUG _IOR('C', 0, ctl_debug_t)
+
+#define I4B_CTL_SET_DEBUG _IOW('C', 1, ctl_debug_t)
+
+/*---------------------------------------------------------------------------*
+ * get hscx statistics
+ *---------------------------------------------------------------------------*/
+
+typedef struct {
+ int unit; /* controller number */
+ int chan; /* channel number */
+ int vfr;
+ int rdo;
+ int crc;
+ int rab;
+ int xdu;
+ int rfo;
+} hscxstat_t;
+
+#define I4B_CTL_GET_HSCXSTAT _IOWR('C', 2, hscxstat_t)
+
+#define I4B_CTL_CLR_HSCXSTAT _IOW('C', 3, hscxstat_t)
+
+/* EOF */
diff --git a/sys/i4b/include/i4b_global.h b/sys/i4b/include/i4b_global.h
new file mode 100644
index 000000000000..739d78d6b3ed
--- /dev/null
+++ b/sys/i4b/include/i4b_global.h
@@ -0,0 +1,95 @@
+/*
+ * 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_global.h - i4b global include file
+ * --------------------------------------
+ *
+ * $Id: i4b_global.h,v 1.17 1998/12/05 18:02:53 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:03:41 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_GLOBAL_H_
+#define _I4B_GLOBAL_H_
+
+#define SPLI4B() splimp() /* spl for i4b */
+
+#define TIMER_IDLE 1 /* a timer is running */
+#define TIMER_ACTIVE 2 /* a timer is idle */
+
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+
+#define TIMEOUT_FUNC_T timeout_t *
+#define SECOND time_second
+#define MICROTIME(x) getmicrotime(&(x))
+
+#else /* FreeBSD < 3 */
+
+#define TIMEOUT_FUNC_T timeout_func_t
+#define SECOND time.tv_sec
+#define MICROTIME(x) microtime(&(x))
+
+#endif /* >= 3 */
+#endif /* __FreeBSD__ */
+
+#if defined(__NetBSD__) || defined (__OpenBSD__)
+
+#define TIMEOUT_FUNC_T void *
+#define SECOND time.tv_sec
+#define MICROTIME(x) (x) = time
+
+#endif /* __NetBSD__ */
+
+/* definitions for the STATUS indications L1 -> L2 -> L3 */
+
+#define STI_ATTACH 0 /* attach at boot time */
+#define STI_L1STAT 1 /* layer 1 status */
+#define STI_L2STAT 2 /* layer 2 status */
+#define STI_TEIASG 3 /* TEI assignments */
+#define STI_PDEACT 4 /* Layer 1 T4 expired = persistent deactivation */
+#define STI_NOL1ACC 5 /* no outgoing L1 access possible */
+
+/* definitions for the COMMAND requests L3 -> L2 -> L1 */
+
+#define CMR_DOPEN 0 /* daemon opened /dev/i4b */
+#define CMR_DCLOSE 1 /* daemon closed /dev/i4b */
+
+/*---------------------------------------------------------------------------
+ *
+ * Number of max supported passive card units
+ *
+ * Teles/Creatix/Neuhaus cards have a hardware limitation
+ * as one is able to set 3 (sometimes 4) different configurations by
+ * jumpers so a maximum of 3 (4) cards per ISA bus is possible.
+ * (Note: there are multiple ISA buses on some architectures)
+ *
+ *---------------------------------------------------------------------------*/
+#define ISIC_MAXUNIT 3 /* max no of supported units 0..3 */
+
+#endif /* _I4B_GLOBAL_H_ */
diff --git a/sys/i4b/include/i4b_ioctl.h b/sys/i4b/include/i4b_ioctl.h
new file mode 100644
index 000000000000..17e945f173ef
--- /dev/null
+++ b/sys/i4b/include/i4b_ioctl.h
@@ -0,0 +1,606 @@
+/*
+ * 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_ioctl.h - messages kernel <--> userland
+ * -------------------------------------------
+ *
+ * $Id: i4b_ioctl.h,v 1.58 1998/12/22 19:48:24 hm Exp $
+ *
+ * last edit-date: [Tue Dec 22 20:33:46 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_IOCTL_H_
+#define _I4B_IOCTL_H_
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#ifndef _MACHINE_TYPES_H_
+#include <machine/types.h>
+#endif /* _MACHINE_TYPES_H_ */
+#endif /* __FreeBSD__ */
+
+/*---------------------------------------------------------------------------*
+ * version and release number for isdn4bsd package
+ *---------------------------------------------------------------------------*/
+#define VERSION 0 /* version number */
+#define REL 70 /* release number */
+#define STEP 00 /* release step */
+
+/*---------------------------------------------------------------------------*
+ * date/time format in i4b log messages
+ * ------------------------------------
+ * Being year 2000 clean is not easy with the current state of the
+ * ANSI C library standard and it's implementation for some locales.
+ * You might like to use the "%c" format of "strftime" sometimes,
+ * but this breaks Y2K in some locales. Also the old standard logfile
+ * format "%d.%m.%y %H:%M:%S" is non compliant.
+ * NetBSD's current toolset warns about this problems, and we compile
+ * with -Werror, so this problems need to be resolved.
+ *---------------------------------------------------------------------------*/
+#define I4B_TIME_FORMAT "%d.%m.%Y %H:%M:%S"
+
+/*---------------------------------------------------------------------------*
+ * max number of controllers in system
+ *---------------------------------------------------------------------------*/
+#define MAX_CONTROLLERS 8 /* max number of controllers */
+
+/*---------------------------------------------------------------------------*
+ * controller types
+ *---------------------------------------------------------------------------*/
+#define CTRL_INVALID (-1) /* invalid, error */
+#define CTRL_UNKNOWN 0 /* unknown controller type */
+#define CTRL_PASSIVE 1 /* passive ISDN controller cards*/
+#define CTRL_DAIC 2 /* Diehl active controller cards*/
+#define CTRL_NUMTYPES 3 /* number of controller types */
+
+/*---------------------------------------------------------------------------*
+ * card types for CTRL_PASSIVE
+ *---------------------------------------------------------------------------*/
+#define CARD_TYPEP_INVAL (-1) /* invalid, error */
+#define CARD_TYPEP_UNK 0 /* unknown */
+#define CARD_TYPEP_8 1 /* Teles, S0/8 */
+#define CARD_TYPEP_16 2 /* Teles, S0/16 */
+#define CARD_TYPEP_16_3 3 /* Teles, S0/16.3 */
+#define CARD_TYPEP_AVMA1 4 /* AVM A1 or AVM Fritz!Card */
+#define CARD_TYPEP_163P 5 /* Teles, S0/16.3 PnP */
+#define CARD_TYPEP_CS0P 6 /* Creatix, S0 PnP */
+#define CARD_TYPEP_USRTA 7 /* US Robotics ISDN TA internal */
+#define CARD_TYPEP_DRNNGO 8 /* Dr. Neuhaus Niccy GO@ */
+#define CARD_TYPEP_SWS 9 /* Sedlbauer Win Speed */
+#define CARD_TYPEP_DYNALINK 10 /* Dynalink IS64PH */
+#define CARD_TYPEP_BLMASTER 11 /* ISDN Blaster / ISDN Master */
+#define CARD_TYPEP_PCFRITZ 12 /* AVM PCMCIA Fritz!Card */
+#define CARD_TYPEP_ELSAQS1ISA 13 /* ELSA QuickStep 1000pro ISA */
+#define CARD_TYPEP_ELSAQS1PCI 14 /* ELSA QuickStep 1000pro PCI */
+#define CARD_TYPEP_SIEMENSITALK 15 /* Siemens I-Talk */
+#define CARD_TYPEP_ELSAMLIMC 16 /* ELSA MicroLink ISDN/MC */
+#define CARD_TYPEP_ELSAMLMCALL 17 /* ELSA MicroLink MCall */
+#define CARD_TYPEP_ITKIX1 18 /* ITK ix1 micro */
+
+/*
+ * in case you add support for more cards, please update:
+ *
+ * isdnd: support.c, name_of_controller()
+ * diehl/diehlctl: main.c, listall()
+ *
+ * and adjust CARD_TYPEP_MAX below.
+ */
+
+#define CARD_TYPEP_MAX 18 /* max type */
+
+/*---------------------------------------------------------------------------*
+ * card types for CTRL_DAIC
+ *---------------------------------------------------------------------------*/
+#define CARD_TYPEA_DAIC_UNK 0
+#define CARD_TYPEA_DAIC_S 1
+#define CARD_TYPEA_DAIC_SX 2
+#define CARD_TYPEA_DAIC_SCOM 3
+#define CARD_TYPEA_DAIC_QUAD 4
+
+/*---------------------------------------------------------------------------*
+ * max length of some strings
+ *---------------------------------------------------------------------------*/
+#define TELNO_MAX 41 /* max length of a telephone number (+ '\0') */
+#define DISPLAY_MAX 91 /* max length of display information (+ '\0') */
+#define DATETIME_MAX 21 /* max length of datetime information (+ '\0')*/
+
+/*---------------------------------------------------------------------------*
+ * in case the src or dst telephone number is empty
+ *---------------------------------------------------------------------------*/
+#define TELNO_EMPTY "NotAvailable"
+
+/*---------------------------------------------------------------------------*
+ * B channel parameters
+ *---------------------------------------------------------------------------*/
+#define BCH_MAX_DATALEN 2048 /* max length of a B channel frame */
+
+/*---------------------------------------------------------------------------*
+ * userland driver types
+ * ---------------------
+ * a "driver" is defined here as a piece of software interfacing an
+ * ISDN B channel with a userland service, such as IP, Telephony etc.
+ *---------------------------------------------------------------------------*/
+#define BDRV_RBCH 0 /* raw b-channel interface driver */
+#define BDRV_TEL 1 /* telephone (speech) interface driver */
+#define BDRV_IPR 2 /* IP over raw HDLC interface driver */
+#define BDRV_ISPPP 3 /* sync Kernel PPP interface driver */
+
+/*---------------------------------------------------------------------------*
+ * B channel protocol
+ *---------------------------------------------------------------------------*/
+#define BPROT_NONE 0 /* no protocol at all, raw data */
+#define BPROT_RHDLC 1 /* raw HDLC: flag, data, crc, flag */
+
+/*---------------------------------------------------------------------------*
+ * causes data type
+ *---------------------------------------------------------------------------*/
+typedef unsigned int cause_t; /* 32 bit unsigned int */
+
+/*---------------------------------------------------------------------------*
+ * call descriptor id (cdid) definitions
+ *---------------------------------------------------------------------------*/
+#define CDID_UNUSED 0 /* cdid is invalid and unused */
+#define CDID_MAX 99999 /* highest valid cdid, wraparound to 1 */
+
+
+/****************************************************************************
+
+ outgoing call:
+ --------------
+
+ userland kernel
+ -------- ------
+
+ CDID_REQ ----------------->
+
+ <------------------ cdid
+
+ CONNECT_REQ -------------->
+
+ <------------------ PROCEEDING_IND (if connect req ok)
+
+ <------------------ CONNECT_ACTIVE_IND (if connection ok)
+
+ or
+
+ <------------------ DISCONNECT_IND (if connection failed)
+
+
+
+ incoming call:
+ --------------
+
+ userland kernel
+ -------- ------
+
+ <------------------ CONNECT_IND
+
+ CONNECT_RESP ------------->
+
+ <------------------ CONNECT_ACTIVE_IND (if accepted)
+
+
+
+ active disconnect:
+ ------------------
+
+ userland kernel
+ -------- ------
+
+ DISCONNECT_REQ ------------>
+
+ <------------------ DISCONNECT_IND
+
+
+ passive disconnect:
+ -------------------
+
+ userland kernel
+ -------- ------
+
+ <------------------ DISCONNECT_IND
+
+
+****************************************************************************/
+
+
+/*===========================================================================*
+ *===========================================================================*
+ * "read" messages from kernel -> userland
+ *===========================================================================*
+ *===========================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * message header, included in every message
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ char type; /* message identifier */
+#define MSG_CONNECT_IND 'a'
+#define MSG_CONNECT_ACTIVE_IND 'b'
+#define MSG_DISCONNECT_IND 'c'
+#define MSG_DIALOUT_IND 'd'
+#define MSG_IDLE_TIMEOUT_IND 'e'
+#define MSG_ACCT_IND 'f'
+#define MSG_CHARGING_IND 'g'
+#define MSG_PROCEEDING_IND 'h'
+#define MSG_ALERT_IND 'i'
+#define MSG_DRVRDISC_REQ 'j'
+#define MSG_L12STAT_IND 'k'
+#define MSG_TEIASG_IND 'l'
+#define MSG_PDEACT_IND 'm'
+#define MSG_NEGCOMP_IND 'n'
+#define MSG_IFSTATE_CHANGED_IND 'o'
+ int cdid; /* call descriptor id */
+} msg_hdr_t;
+
+/*---------------------------------------------------------------------------*
+ * connect indication
+ * indicates incoming connection
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller number */
+ int channel; /* channel number */
+#define CHAN_B1 0 /* this _must_ be 0, HSCX B1 is also 0 */
+#define CHAN_B2 1 /* this _must_ be 1, HSCX B2 is also 1 */
+#define CHAN_ANY (-1) /* outgoing, not possible for incoming */
+#define CHAN_NO (-2) /* call waiting (CW) for incoming */
+ int bprot; /* b channel protocot, see BPROT_XXX */
+ char dst_telno[TELNO_MAX]; /* destination telno */
+ char src_telno[TELNO_MAX]; /* source telno */
+ int scr_ind;/* screening indicator */
+#define SCR_NONE 0 /* no screening indicator transmitted */
+#define SCR_USR_NOSC 1 /* screening user provided, not screened*/
+#define SCR_USR_PASS 2 /* screening user provided, verified & passed */
+#define SCR_USR_FAIL 3 /* screening user provided, verified & failed */
+#define SCR_NET 4 /* screening network provided */
+ char display[DISPLAY_MAX]; /* content of display IE*/
+} msg_connect_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * connect active indication
+ * indicates active connection
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller number actually used */
+ int channel; /* channel number actually used */
+ char datetime[DATETIME_MAX]; /* content of date/time IE */
+} msg_connect_active_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * disconnect indication
+ * indicates a disconnect
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ cause_t cause; /* cause code */
+} msg_disconnect_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * negotiation complete
+ * indicates an interface is completely up & running
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+} msg_negcomplete_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * interface changes internal state
+ * indicates an interface has somehow switched its FSM
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int state; /* new interface state */
+} msg_ifstatechg_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * initiate a call to a remote site
+ * i.e. the IP driver got a packet and wants a connection
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int driver; /* driver type */
+ int driver_unit; /* driver unit number */
+} msg_dialout_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * idle timeout disconnect sent indication
+ * kernel has sent disconnect request because of b-ch idle
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+} msg_idle_timeout_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * accounting information from userland interface driver to daemon
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int accttype; /* accounting type */
+#define ACCT_DURING 0
+#define ACCT_FINAL 1
+ int driver; /* driver type */
+ int driver_unit; /* driver unit number */
+ int ioutbytes; /* ISDN # of bytes sent */
+ int iinbytes; /* ISDN # of bytes received */
+ int outbps; /* bytes per sec out */
+ int inbps; /* bytes per sec in */
+ int outbytes; /* driver # of bytes sent */
+ int inbytes; /* driver # of bytes received */
+} msg_accounting_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * charging information from isdn driver to daemon
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int units; /* number of units */
+ int units_type; /* type of units info */
+#define CHARGE_INVALID 0 /* invalid, unknown */
+#define CHARGE_AOCD 1 /* advice of charge during call */
+#define CHARGE_AOCE 2 /* advice of charge at end of call */
+#define CHARGE_CALC 3 /* locally calculated from rates information */
+} msg_charging_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * call proceeding indication
+ * indicates outgoing SETUP has been acknowleged
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller number actually used */
+ int channel; /* channel number actually used */
+} msg_proceeding_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * alert indication
+ * indicates remote user side "rings"
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+} msg_alert_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * driver requests to disconnect line
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int driver; /* driver type */
+ int driver_unit; /* driver unit number */
+} msg_drvrdisc_req_t;
+
+/*---------------------------------------------------------------------------*
+ * state of layer 1/2
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller unit */
+ int layer; /* layer number (1/2) */
+#define LAYER_ONE 1
+#define LAYER_TWO 2
+ int state; /* state info */
+#define LAYER_IDLE 0
+#define LAYER_ACTIVE 1
+} msg_l12stat_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * TEI assignment messages
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller unit */
+ int tei; /* TEI or -1 if invalid */
+} msg_teiasg_ind_t;
+
+/*---------------------------------------------------------------------------*
+ * persistent deactivation state of stack
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ msg_hdr_t header; /* common header */
+ int controller; /* controller unit */
+ int numactive; /* number of active connections */
+} msg_pdeact_ind_t;
+
+
+/*===========================================================================*
+ *===========================================================================*
+ * "ioctl" messages from userland -> kernel
+ *===========================================================================*
+ *===========================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * request a unique cdid (to setup an outgoing call)
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+} msg_cdid_req_t;
+
+#define I4B_CDID_REQ _IOWR('4', 0, int)
+
+/*---------------------------------------------------------------------------*
+ * connect request
+ * requests an outgoing connection
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+ int controller; /* controller to use */
+ int channel; /* channel to use */
+ int txdelay; /* tx delay after connect */
+ int bprot; /* b channel protocol */
+ int driver; /* driver to route b channel data to */
+ int driver_unit; /* unit number for above driver */
+ int unitlen_time; /* length of a charging unit */
+ int idle_time; /* time without activity on b ch */
+ int earlyhup_time; /* safety area at end of unit */
+ int unitlen_method; /* how to calculate the unitlength */
+#define ULEN_METHOD_STATIC 0 /* use unitlen_time value (see above) */
+#define ULEN_METHOD_DYNAMIC 1 /* use AOCD */
+ char dst_telno[TELNO_MAX]; /* destination telephone no */
+ char src_telno[TELNO_MAX]; /* source telephone number */
+} msg_connect_req_t;
+
+#define I4B_CONNECT_REQ _IOW('4', 1, msg_connect_req_t)
+
+/*---------------------------------------------------------------------------*
+ * connect response
+ * this is the answer to an incoming connect indication
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+ int response; /* what to do with incoming call */
+#define SETUP_RESP_DNTCRE 0 /* dont care, call is not for me */
+#define SETUP_RESP_REJECT 1 /* reject call */
+#define SETUP_RESP_ACCEPT 2 /* accept call */
+ cause_t cause; /* cause for case SETUP_RESP_REJECT */
+ /* the following are only used for SETUP_RESP_ACCEPT !! */
+ int txdelay; /* tx delay after connect */
+ int bprot; /* B chan protocol */
+ int driver; /* driver to route b channel data to */
+ int driver_unit; /* unit number for above driver */
+ int max_idle_time; /* max time without activity on b ch */
+} msg_connect_resp_t;
+
+#define I4B_CONNECT_RESP _IOW('4', 2, msg_connect_resp_t)
+
+/*---------------------------------------------------------------------------*
+ * disconnect request
+ * active disconnect request
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+ cause_t cause; /* protocol independent cause */
+} msg_discon_req_t;
+
+#define I4B_DISCONNECT_REQ _IOW('4', 3, msg_discon_req_t)
+
+/*---------------------------------------------------------------------------*
+ * controller info request
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int controller; /* controller number */
+ int ncontroller; /* number of controllers in system */
+ int ctrl_type; /* controller type passive/active */
+ int card_type; /* brand / version */
+ int tei; /* tei controller probably has */
+} msg_ctrl_info_req_t;
+
+#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t)
+
+/*---------------------------------------------------------------------------*
+ * dialout response
+ * status report to driver who requested a dialout
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int driver; /* driver to route b channel data to */
+ int driver_unit; /* unit number for above driver */
+ int stat; /* state of dialout request */
+#define DSTAT_NONE 0
+#define DSTAT_TFAIL 1 /* transient failure */
+#define DSTAT_PFAIL 2 /* permanent failure */
+#define DSTAT_INONLY 3 /* no outgoing dials allowed */
+} msg_dialout_resp_t;
+
+#define I4B_DIALOUT_RESP _IOW('4', 5, msg_dialout_resp_t)
+
+/*---------------------------------------------------------------------------*
+ * timeout value update
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+ int unitlen_time; /* length of a charging unit */
+ int idle_time; /* time without activity on b ch */
+ int earlyhup_time; /* safety area at end of unit */
+} msg_timeout_upd_t;
+
+#define I4B_TIMEOUT_UPD _IOW('4', 6, msg_timeout_upd_t)
+
+/*---------------------------------------------------------------------------*
+ * soft enable/disable
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int driver; /* driver to route b channel data to */
+ int driver_unit; /* unit number for above driver */
+ int updown; /* what to do */
+#define SOFT_ENA 0 /* enable interface */
+#define SOFT_DIS 1 /* disable interface */
+} msg_updown_ind_t;
+
+#define I4B_UPDOWN_IND _IOW('4', 7, msg_updown_ind_t)
+
+/*---------------------------------------------------------------------------*
+ * send alert request
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int cdid; /* call descriptor id */
+} msg_alert_req_t;
+
+#define I4B_ALERT_REQ _IOW('4', 8, msg_alert_req_t)
+
+/*---------------------------------------------------------------------------*
+ * request version and release info from kernel part
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int version; /* version number */
+ int release; /* release number */
+ int step; /* release step number */
+} msg_vr_req_t;
+
+#define I4B_VR_REQ _IOR('4', 9, msg_vr_req_t)
+
+/*---------------------------------------------------------------------------*
+ * Protocol download to active cards
+ *---------------------------------------------------------------------------*/
+struct isdn_dr_prot {
+ size_t bytecount; /* length of code */
+ u_int8_t *microcode; /* pointer to microcode */
+};
+
+struct isdn_download_request {
+ int controller; /* controller number */
+ int numprotos; /* number of protocols in 'protocols' */
+ struct isdn_dr_prot *protocols;
+};
+
+#define I4B_CTRL_DOWNLOAD _IOW('4', 100, struct isdn_download_request)
+
+/*---------------------------------------------------------------------------*
+ * Generic diagnostic interface for active cards
+ *---------------------------------------------------------------------------*/
+struct isdn_diagnostic_request {
+ int controller; /* controller number */
+ u_int32_t cmd; /* diagnostic command to execute */
+ size_t in_param_len; /* length of additional input parameter */
+ void *in_param; /* optional input parameter */
+ size_t out_param_len; /* available output space */
+ void *out_param; /* output data goes here */
+};
+
+#define I4B_ACTIVE_DIAGNOSTIC _IOW('4', 102, struct isdn_diagnostic_request)
+
+#endif /* _I4B_IOCTL_H_ */
diff --git a/sys/i4b/include/i4b_isdnq931.h b/sys/i4b/include/i4b_isdnq931.h
new file mode 100644
index 000000000000..bdc77f08c660
--- /dev/null
+++ b/sys/i4b/include/i4b_isdnq931.h
@@ -0,0 +1,166 @@
+/*
+ * 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_isdnq931.h - DSS1 layer 3 message types
+ * -------------------------------------------
+ *
+ * $Id: i4b_isdnq931.h,v 1.4 1998/12/05 18:02:54 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:04:01 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+/* protocol discriminators */
+
+#define PD_Q931 0x08 /* Q.931/I.451 */
+
+/* Q.931 single octett information element identifiers */
+
+#define IEI_SENDCOMPL 0xa1 /* sending complete */
+
+/* Q.931 variable length information element identifiers */
+
+#define IEI_SEGMMSG 0x00 /* segmented message */
+#define IEI_BEARERCAP 0x04 /* bearer capabilities */
+#define IEI_CAUSE 0x08 /* cause */
+#define IEI_CALLID 0x10 /* call identity */
+#define IEI_CALLSTATE 0x14 /* call state */
+#define IEI_CHANNELID 0x18 /* channel identification */
+#define IEI_PROGRESSI 0x1e /* progress indicator */
+#define IEI_NETSPCFAC 0x20 /* network specific facilities */
+#define IEI_NOTIFIND 0x27 /* notification indicator */
+#define IEI_DISPLAY 0x28 /* display */
+#define IEI_DATETIME 0x29 /* date/time */
+#define IEI_KEYPAD 0x2c /* keypad facility */
+#define IEI_SIGNAL 0x34 /* signal */
+#define IEI_INFRATE 0x40 /* information rate */
+#define IEI_ETETDEL 0x42 /* end to end transit delay */
+#define IEI_TDELSELIND 0x43 /* transit delay selection and indication */
+#define IEI_PLBPARMS 0x44 /* packet layer binary parameters */
+#define IEI_PLWSIZE 0x45 /* packet layer window size */
+#define IEI_PSIZE 0x46 /* packet size */
+#define IEI_CUG 0x47 /* closed user group */
+#define IEI_REVCHRGI 0x4a /* reverse charge indication */
+#define IEI_CALLINGPN 0x6c /* calling party number */
+#define IEI_CALLINGPS 0x6d /* calling party subaddress */
+#define IEI_CALLEDPN 0x70 /* called party number */
+#define IEI_CALLEDPS 0x71 /* called party subaddress */
+#define IEI_REDIRNO 0x74 /* redirecting number */
+#define IEI_TRNSEL 0x78 /* transit network selection */
+#define IEI_RESTARTI 0x79 /* restart indicator */
+#define IEI_LLCOMPAT 0x7c /* low layer compatibility */
+#define IEI_HLCOMPAT 0x7d /* high layer compatibility */
+#define IEI_USERUSER 0x7e /* user-user */
+#define IEI_ESACPE 0x7f /* escape for extension */
+
+/* Q.932 variable length information element identifiers */
+
+#define IEI_EXTFAC 0x0d /* extended facility */
+#define IEI_FACILITY 0x1c /* facility */
+#define IEI_INFOREQ 0x32 /* information request */
+#define IEI_FEATACT 0x38 /* feature activation */
+#define IEI_FEATIND 0x39 /* feature indication */
+#define IEI_SERVPID 0x3a /* service profile identification */
+#define IEI_ENDPTID 0x3b /* endpoint identifier */
+
+/* Q.933 variable length information element identifiers */
+
+#define IEI_DATALCID 0x19 /* data link connection identifier */
+#define IEI_LLCOREP 0x48 /* link layer core parameters */
+#define IEI_LLPROTP 0x49 /* link layer protocol parameters */
+#define IEI_X213PRI 0x50 /* X.213 priority */
+#define IEI_REPORTT 0x51 /* report type */
+#define IEI_LNKITYVERF 0x53 /* link integrity verification */
+#define IEI_PVCSTAT 0x57 /* PVC status */
+
+/* Q.95x variable length information element identifiers */
+
+#define IEI_PRECLEV 0x41 /* precedence level */
+#define IEI_CONCTDNO 0x4c /* connected number */
+#define IEI_CONCTDSA 0x4d /* connected subaddress */
+#define IEI_REDICNNO 0x76 /* redirection number */
+
+/* single octett information elements */
+
+#define SOIE_SHIFT 0x90 /* shift codeset */
+#define SHIFT_LOCK 0x08 /* shift codeset, locking shift bit */
+#define SOIE_MDSC 0xa0 /* more data AND/OR sending complete */
+#define SOIE_SENDC 0xa1 /* sending complete */
+#define SOIE_CONGL 0xb0 /* congestion level */
+#define SOIE_REPTI 0xd0 /* repeat indicator */
+
+/* codesets */
+
+#define CODESET_0 0 /* codeset 0, normal DSS1 codeset */
+
+/* Q.931/Q.932 message types (see Q.931 03/93 p10 and p311) */
+
+/* call establishment messages */
+
+#define ALERT 0x01
+#define CALL_PROCEEDING 0x02
+#define PROGRESS 0x03
+#define SETUP 0x05
+#define CONNECT 0x07
+#define SETUP_ACKNOWLEDGE 0x0d
+#define CONNECT_ACKNOWLEDGE 0x0f
+
+/* call information phase messages */
+
+#define USER_INFORMATION 0x20
+#define SUSPEND_REJECT 0x21
+#define RESUME_REJECT 0x22
+#define HOLD 0x24
+#define SUSPEND 0x25
+#define RESUME 0x26
+#define HOLD_ACKNOWLEDGE 0x28
+#define SUSPEND_ACKNOWLEDGE 0x2d
+#define RESUME_ACKNOWLEDGE 0x2e
+#define HOLD_REJECT 0x30
+#define RETRIEVE 0x31
+#define RETRIEVE_ACKNOWLEDGE 0x32
+#define RETRIEVE_REJECT 0x37
+
+/* call clearing */
+
+#define DISCONNECT 0x45
+#define RESTART 0x46
+#define RELEASE 0x4d
+#define RESTART_ACKNOWLEDGE 0x4e
+#define RELEASE_COMPLETE 0x5a
+
+/* misc messages */
+
+#define SEGMENT 0x60
+#define FACILITY 0x62
+#define REGISTER 0x64
+#define NOTIFY 0x6e
+#define STATUS_ENQUIRY 0x75
+#define CONGESTION_CONTROL 0x79
+#define INFORMATION 0x7b
+#define STATUS 0x7d
+
+/* EOF */
diff --git a/sys/i4b/include/i4b_l1l2.h b/sys/i4b/include/i4b_l1l2.h
new file mode 100644
index 000000000000..782ca68a97a3
--- /dev/null
+++ b/sys/i4b/include/i4b_l1l2.h
@@ -0,0 +1,99 @@
+/*
+ * 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_l1l2.h - i4b layer 1 / layer 2 interactions
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_l1l2.h,v 1.7 1998/12/05 18:02:56 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:04:25 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L1L2_H_
+#define _I4B_L1L2_H_
+
+#ifdef __FreeBSD__
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_trace.h>
+#endif
+
+extern struct i4b_l1l2_func i4b_l1l2_func;
+
+struct i4b_l1l2_func
+{
+ /* Layer 1 --> Layer 2 */
+ /* =================== */
+
+ int (*PH_DATA_IND) (int, struct mbuf *);
+ int (*PH_ACTIVATE_IND) (int);
+ int (*PH_DEACTIVATE_IND) (int);
+
+#define PH_Data_Ind(unit, data) \
+ ((*i4b_l1l2_func.PH_DATA_IND)(unit, data))
+#define PH_Act_Ind(unit) \
+ ((*i4b_l1l2_func.PH_ACTIVATE_IND)(unit))
+#define PH_Deact_Ind(unit) \
+ ((*i4b_l1l2_func.PH_DEACTIVATE_IND)(unit))
+
+
+ /* Layer 2 --> Layer 1 */
+ /* =================== */
+
+ int (*PH_DATA_REQ) (int, struct mbuf *, int);
+
+ /* 3rd ph_data_req parameter */
+#define MBUF_DONTFREE 0
+#define MBUF_FREE 1
+
+ int (*PH_ACTIVATE_REQ) (int);
+
+#define PH_Data_Req(unit, data, freeflag) \
+ ((*i4b_l1l2_func.PH_DATA_REQ)(unit, data, freeflag))
+#define PH_Act_Req(unit) \
+ ((*i4b_l1l2_func.PH_ACTIVATE_REQ)(unit))
+
+ /* Layer 1 --> upstream, ISDN trace data */
+ /* ===================================== */
+ int (*MPH_TRACE_IND) (i4b_trace_hdr_t *, int, unsigned char *);
+
+#define MPH_Trace_Ind(header, length, pointer) \
+ ((*i4b_l1l2_func.MPH_TRACE_IND)(header, length, pointer))
+
+ /* L1/L2 management command and status information */
+ /* =============================================== */
+ int (*MPH_STATUS_IND) (int, int, int);
+ int (*MPH_COMMAND_REQ) (int, int, int);
+
+#define MPH_Status_Ind(unit, status, parm) \
+ ((*i4b_l1l2_func.MPH_STATUS_IND)(unit, status, parm))
+#define MPH_Command_Req(unit, command, parm) \
+ ((*i4b_l1l2_func.MPH_COMMAND_REQ)(unit, command, parm))
+};
+
+#endif /* _I4B_L1L2_H_ */
+
diff --git a/sys/i4b/include/i4b_l2l3.h b/sys/i4b/include/i4b_l2l3.h
new file mode 100644
index 000000000000..81ab1829ebc9
--- /dev/null
+++ b/sys/i4b/include/i4b_l2l3.h
@@ -0,0 +1,116 @@
+/*
+ * 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_l2l3.h - i4b layer 2 / layer 3 interactions
+ * -----------------------------------------------
+ *
+ * $Id: i4b_l2l3.h,v 1.5 1998/12/05 18:02:57 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:04:44 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L2L3_H_
+#define _I4B_L2L3_H_
+
+extern struct i4b_l2l3_func i4b_l2l3_func;
+
+struct i4b_l2l3_func
+{
+ /* Layer 2 --> Layer 3 */
+ /* =================== */
+
+ int (*DL_ESTABLISH_IND) (int);
+ int (*DL_ESTABLISH_CNF) (int);
+
+ int (*DL_RELEASE_IND) (int);
+ int (*DL_RELEASE_CNF) (int);
+
+ int (*DL_DATA_IND) (int, struct mbuf *);
+
+ int (*DL_UNIT_DATA_IND) (int, struct mbuf *);
+
+#define DL_Est_Ind(unit) \
+ ((*i4b_l2l3_func.DL_ESTABLISH_IND)(unit))
+#define DL_Est_Cnf(unit) \
+ ((*i4b_l2l3_func.DL_ESTABLISH_CNF)(unit))
+#define DL_Rel_Ind(unit) \
+ ((*i4b_l2l3_func.DL_RELEASE_IND)(unit))
+#define DL_Rel_Cnf(unit) \
+ ((*i4b_l2l3_func.DL_RELEASE_CNF)(unit))
+#define DL_Data_Ind(unit, data) \
+ ((*i4b_l2l3_func.DL_DATA_IND)(unit, data))
+#define DL_Unit_Data_Ind(unit, data) \
+ ((*i4b_l2l3_func.DL_UNIT_DATA_IND)(unit, data))
+
+#define DL_Est_Ind_A \
+ (i4b_l2l3_func.DL_ESTABLISH_IND)
+#define DL_Est_Cnf_A \
+ (i4b_l2l3_func.DL_ESTABLISH_CNF)
+#define DL_Rel_Ind_A \
+ (i4b_l2l3_func.DL_RELEASE_IND)
+#define DL_Rel_Cnf_A \
+ (i4b_l2l3_func.DL_RELEASE_CNF)
+
+ /* Layer 3 --> Layer 2 */
+ /* =================== */
+
+ int (*DL_ESTABLISH_REQ) (int);
+
+ int (*DL_RELEASE_REQ) (int);
+
+ int (*DL_DATA_REQ) (int, struct mbuf *);
+
+ int (*DL_UNIT_DATA_REQ) (int, struct mbuf *);
+
+#define DL_Est_Req(unit) \
+ ((*i4b_l2l3_func.DL_ESTABLISH_REQ)(unit))
+#define DL_Rel_Req(unit) \
+ ((*i4b_l2l3_func.DL_RELEASE_REQ)(unit))
+#define DL_Data_Req(unit, data) \
+ ((*i4b_l2l3_func.DL_DATA_REQ)(unit, data))
+#define DL_Unit_Data_Req(unit, data) \
+ ((*i4b_l2l3_func.DL_UNIT_DATA_REQ)(unit, data))
+
+ /* Layer 2 --> Layer 3 management */
+ /* ============================== */
+
+ int (*MDL_STATUS_IND) (int, int, int); /* L2 --> L3 status */
+
+#define MDL_Status_Ind(unit, status, parm) \
+ ((*i4b_l2l3_func.MDL_STATUS_IND)(unit, status, parm))
+
+ /* Layer 3 --> Layer 2 management */
+ /* ============================== */
+
+ int (*MDL_COMMAND_REQ) (int, int, int); /* L3 --> L2 command */
+
+#define MDL_Command_Req(unit, command, parm) \
+ ((*i4b_l2l3_func.MDL_COMMAND_REQ)(unit, command, parm))
+};
+
+#endif /* _I4B_L2L3_H_ */
+
diff --git a/sys/i4b/include/i4b_l3l4.h b/sys/i4b/include/i4b_l3l4.h
new file mode 100644
index 000000000000..642777c04d67
--- /dev/null
+++ b/sys/i4b/include/i4b_l3l4.h
@@ -0,0 +1,260 @@
+/*
+ * 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_l3l4.h - layer 3 / layer 4 interface
+ * ------------------------------------------
+ *
+ * $Id: i4b_l3l4.h,v 1.21 1998/12/05 18:02:59 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:04:58 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L3L4_H_
+#define _I4B_L3L4_H_
+
+#define T303VAL (hz*4) /* 4 seconds timeout */
+#define T305VAL (hz*30) /* 30 seconds timeout */
+#define T308VAL (hz*4) /* 4 seconds timeout */
+#define T309VAL (hz*90) /* 90 seconds timeout */
+#define T310VAL (hz*60) /* 30-120 seconds timeout */
+#define T313VAL (hz*4) /* 4 seconds timeout */
+#define T400DEF (hz*10) /* 10 seconds timeout */
+
+#define N_CALL_DESC (MAX_CONTROLLERS*2) /* no of call descriptors */
+
+extern int nctrl; /* number of controllers detected in system */
+
+typedef struct bchan_statistics {
+ int outbytes;
+ int inbytes;
+} bchan_statistics_t;
+
+/*---------------------------------------------------------------------------*
+ * table of things the driver needs to know about the b channel
+ * it is connected to for data transfer
+ *---------------------------------------------------------------------------*/
+typedef struct i4l_isdn_bchan_linktab {
+ int unit;
+ int channel;
+ void (*bch_config)(int unit, int channel, int bprot, int updown);
+ void (*bch_tx_start)(int unit, int channel);
+ void (*bch_stat)(int unit, int channel, bchan_statistics_t *bsp);
+ struct ifqueue *tx_queue;
+ struct ifqueue *rx_queue; /* data xfer for NON-HDLC traffic */
+ struct mbuf **rx_mbuf; /* data xfer for HDLC based traffic */
+} isdn_link_t;
+
+/*---------------------------------------------------------------------------*
+ * table of things the b channel handler needs to know about
+ * the driver it is connected to for data transfer
+ *---------------------------------------------------------------------------*/
+typedef struct i4l_driver_bchan_linktab {
+ int unit;
+ void (*bch_rx_data_ready)(int unit);
+ void (*bch_tx_queue_empty)(int unit);
+ void (*bch_activity)(int unit, int rxtx);
+#define ACT_RX 0
+#define ACT_TX 1
+ void (*line_connected)(int unit, void *cde);
+ void (*line_disconnected)(int unit, void *cde);
+ void (*dial_response)(int unit, int stat);
+ void (*updown_ind)(int unit, int updown);
+} drvr_link_t;
+
+/* global linktab functions for controller types (aka hardware drivers) */
+struct ctrl_type_desc {
+ isdn_link_t* (*get_linktab)(int unit, int channel);
+ void (*set_linktab)(int unit, int channel, drvr_link_t *dlt);
+};
+extern struct ctrl_type_desc ctrl_types[];
+
+/* global linktab functions for RBCH userland driver */
+
+drvr_link_t *rbch_ret_linktab(int unit);
+void rbch_set_linktab(int unit, isdn_link_t *ilt);
+
+/* global linktab functions for IPR network driver */
+
+drvr_link_t *ipr_ret_linktab(int unit);
+void ipr_set_linktab(int unit, isdn_link_t *ilt);
+
+/* global linktab functions for TEL userland driver */
+
+drvr_link_t *tel_ret_linktab(int unit);
+void tel_set_linktab(int unit, isdn_link_t *ilt);
+
+/* global linktab functions for ISPPP userland driver */
+
+drvr_link_t *i4bisppp_ret_linktab(int unit);
+void i4bisppp_set_linktab(int unit, isdn_link_t *ilt);
+
+/*---------------------------------------------------------------------------*
+ * this structure describes one call/connection on one B-channel
+ * and all its parameters
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ u_int cdid; /* call descriptor id */
+ int controller; /* isdn controller number */
+ int cr; /* call reference value */
+
+ int crflag; /* call reference flag */
+#define CRF_ORIG 0 /* originating side */
+#define CRF_DEST 1 /* destinating side */
+
+ int channelid; /* channel id value */
+ int channelexcl; /* channel exclusive */
+
+ int bprot; /* B channel protocol BPROT_XXX */
+
+ int driver; /* driver to use for B channel */
+ int driver_unit; /* unit for above driver number */
+
+ cause_t cause_in; /* cause value from NT */
+ cause_t cause_out; /* cause value to NT */
+
+ int call_state; /* from incoming SETUP */
+
+ u_char dst_telno[TELNO_MAX]; /* destination number */
+ u_char src_telno[TELNO_MAX]; /* source number */
+ int scr_ind; /* screening ind for incoming call */
+
+ int Q931state; /* Q.931 state for call */
+ int event; /* event to be processed */
+
+ int response; /* setup response type */
+
+ int T303; /* SETUP sent response timeout */
+ int T303_first_to; /* first timeout flag */
+
+ int T305; /* DISC without PROG IND */
+
+ int T308; /* RELEASE sent response timeout*/
+ int T308_first_to; /* first timeout flag */
+
+ int T309; /* data link disconnect timeout */
+
+ int T310; /* CALL PROC received */
+
+ int T313; /* CONNECT sent timeout */
+
+ int T400; /* L4 timeout */
+
+ isdn_link_t *ilt; /* isdn B channel linktab */
+ drvr_link_t *dlt; /* driver linktab */
+
+ int dir; /* outgoing or incoming call */
+#define DIR_OUTGOING 0
+#define DIR_INCOMING 1
+
+ int timeout_active; /* idle timeout() active flag */
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || \
+ (!defined(__FreeBSD_version) && defined(__FreeBSD__) && __FreeBSD__ >= 3)
+ struct callout_handle idle_timeout_handle;
+ struct callout_handle T303_callout;
+ struct callout_handle T305_callout;
+ struct callout_handle T308_callout;
+ struct callout_handle T309_callout;
+ struct callout_handle T310_callout;
+ struct callout_handle T313_callout;
+ struct callout_handle T400_callout;
+ int callouts_inited; /* must init before use */
+#endif
+
+ int idletime_state; /* wait for idle_time begin */
+#define IST_IDLE 0 /* shorthold mode disabled */
+#define IST_NONCHK 1 /* in non-checked window */
+#define IST_CHECK 2 /* in idle check window */
+#define IST_SAFE 3 /* in safety zone */
+
+ time_t idletimechk_start; /* check idletime window start */
+ time_t connect_time; /* time connect was made */
+ time_t last_active_time; /* last time with activity */
+
+ /* for incoming connections: */
+ time_t max_idle_time; /* max time without activity */
+
+ /* for outgoing connections: */
+ time_t unitlen_time; /* length of a charging unit */
+ time_t idle_time; /* idle time before end of unit */
+ time_t earlyhup_time; /* safety time zone at end of unit */
+
+ int aocd_flag; /* AOCD used for unitlength calc*/
+ time_t last_aocd_time; /* last time AOCD received */
+ int units; /* number of AOCD charging units*/
+ int units_type; /* units type: AOCD, AOCE */
+ int cunits; /* calculated units */
+
+ int isdntxdelay; /* isdn tx delay after connect */
+
+ u_char display[DISPLAY_MAX]; /* display information element */
+ char datetime[DATETIME_MAX]; /* date/time information element*/
+} call_desc_t;
+
+extern call_desc_t call_desc[N_CALL_DESC];
+
+/* forward decl. */
+struct isdn_diagnostic_request;
+struct isdn_dr_prot;
+
+/*---------------------------------------------------------------------------*
+ * this structure "describes" one controller
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ int unit; /* unit number of this contr. */
+ int ctrl_type; /* controller type (CTRL_XXX) */
+ int card_type; /* card manufacturer (CARD_XXX) */
+
+ int dl_est; /* layer 2 established */
+#define DL_DOWN 0
+#define DL_UP 1
+
+ int bch_state[2]; /* states of the b channels */
+#define BCH_ST_FREE 0 /* free to be used, idle */
+#define BCH_ST_RSVD 1 /* reserved, may become free or used */
+#define BCH_ST_USED 2 /* in use for data transfer */
+
+ int tei; /* current tei or -1 if invalid */
+
+ /* pointers to functions to be called from L4 */
+
+ void (*N_CONNECT_REQUEST) (unsigned int);
+ void (*N_CONNECT_RESPONSE) (unsigned int, int, int);
+ void (*N_DISCONNECT_REQUEST) (unsigned int, int);
+ void (*N_ALERT_REQUEST) (unsigned int);
+ void (*N_SET_TRACE) (int unit, int val);
+ int (*N_GET_TRACE) (int unit);
+ int (*N_DOWNLOAD) (int unit, int numprotos, struct isdn_dr_prot *protocols);
+ int (*N_DIAGNOSTICS) (int unit, struct isdn_diagnostic_request*);
+ void (*N_MGMT_COMMAND) (int unit, int cmd, int parm);
+} ctrl_desc_t;
+
+extern ctrl_desc_t ctrl_desc[MAX_CONTROLLERS];
+
+#endif /* _I4B_Q931_H_ */
diff --git a/sys/i4b/include/i4b_mbuf.h b/sys/i4b/include/i4b_mbuf.h
new file mode 100644
index 000000000000..49ee26d6162d
--- /dev/null
+++ b/sys/i4b/include/i4b_mbuf.h
@@ -0,0 +1,51 @@
+/*
+ * 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 - mbuf handling support routines
+ * --------------------------------------
+ *
+ * $Id: i4b_mbuf.h,v 1.6 1998/12/05 18:03:00 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:05:12 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_MBUF_H_
+#define _I4B_MBUF_H_
+
+#define IF_QEMPTY(ifq) ((ifq)->ifq_len == 0)
+
+struct mbuf *i4b_Dgetmbuf( int );
+void i4b_Dfreembuf( struct mbuf *m );
+void i4b_Dcleanifq( struct ifqueue * );
+
+struct mbuf *i4b_Bgetmbuf( int );
+void i4b_Bfreembuf( struct mbuf *m );
+void i4b_Bcleanifq( struct ifqueue * );
+
+#endif /* _I4B_MBUF_H_ */
+
+/* EOF */
diff --git a/sys/i4b/include/i4b_tel_ioctl.h b/sys/i4b/include/i4b_tel_ioctl.h
new file mode 100644
index 000000000000..b7f0f73cd92a
--- /dev/null
+++ b/sys/i4b/include/i4b_tel_ioctl.h
@@ -0,0 +1,52 @@
+/*
+ * 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_tel_ioctl.h telephony interface ioctls
+ * ------------------------------------------
+ *
+ * $Id: i4b_tel_ioctl.h,v 1.5 1998/12/14 10:31:58 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:37:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_TEL_IOCTL_H_
+#define _I4B_TEL_IOCTL_H_
+
+/* supported audio format conversions for /dev/i4btelXX devices */
+
+#define CVT_NONE 0 /* no format conversion */
+#define CVT_ALAW2ULAW 1 /* kernel A-law, userland mu-law */
+
+/*---------------------------------------------------------------------------*
+ * get / set audio format
+ *---------------------------------------------------------------------------*/
+
+#define I4B_TEL_GETAUDIOFMT _IOR('A', 0, int)
+#define I4B_TEL_SETAUDIOFMT _IOW('A', 1, int)
+#define I4B_TEL_EMPTYINPUTQUEUE _IOW('A', 2, int)
+
+#endif /* _I4B_TEL_IOCTL_H_ */
diff --git a/sys/i4b/include/i4b_trace.h b/sys/i4b/include/i4b_trace.h
new file mode 100644
index 000000000000..07e08daa075c
--- /dev/null
+++ b/sys/i4b/include/i4b_trace.h
@@ -0,0 +1,91 @@
+/*
+ * 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_trace.h - header file for trace data read device
+ * ----------------------------------------------------
+ *
+ * $Id: i4b_trace.h,v 1.5 1998/12/05 18:06:01 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:37:49 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_TRACE_H_
+#define _I4B_TRACE_H_
+
+/*---------------------------------------------------------------------------*
+ * structure of the header at the beginning of every trace mbuf
+ *---------------------------------------------------------------------------*/
+typedef struct {
+ int length; /* length of the following mbuf */
+ int unit; /* controller unit number */
+ int type; /* type of channel */
+#define TRC_CH_I 0 /* Layer 1 INFO's */
+#define TRC_CH_D 1 /* D channel */
+#define TRC_CH_B1 2 /* B1 channel */
+#define TRC_CH_B2 3 /* B2 channel */
+ int dir; /* direction */
+#define FROM_TE 0 /* user -> network */
+#define FROM_NT 1 /* network -> user */
+ int trunc; /* # of truncated bytes (frame > MCLBYTES) */
+ unsigned int count; /* frame count for this unit/type */
+ struct timeval time; /* timestamp for this frame */
+} i4b_trace_hdr_t;
+
+#define INFO0 0 /* layer 1 */
+#define INFO1_8 1
+#define INFO1_10 2
+#define INFO2 3
+#define INFO3 4
+#define INFO4_8 5
+#define INFO4_10 6
+
+/*---------------------------------------------------------------------------*
+ * ioctl via /dev/i4btrc device(s):
+ * get/set current trace flag settings
+ *---------------------------------------------------------------------------*/
+
+#define I4B_TRC_GET _IOR('T', 0, int) /* get trace settings */
+#define I4B_TRC_SET _IOW('T', 1, int) /* set trace settings */
+
+#define TRACE_OFF 0x00 /* tracing off */
+#define TRACE_I 0x01 /* trace L1 INFO's on */
+#define TRACE_D_TX 0x02 /* trace D channel on */
+#define TRACE_D_RX 0x04 /* trace D channel on */
+#define TRACE_B_TX 0x08 /* trace B channel on */
+#define TRACE_B_RX 0x10 /* trace B channel on */
+
+typedef struct {
+ int rxunit; /* unit # for rx frames */
+ int rxflags; /* d and/or b channel */
+ int txunit; /* unit # for tx frames */
+ int txflags; /* d and/or b channel */
+} i4b_trace_setupa_t;
+
+#define I4B_TRC_SETA _IOW('T', 2, i4b_trace_setupa_t) /* set analyze mode */
+#define I4B_TRC_RESETA _IOW('T', 3, int) /* reset analyze mode */
+
+#endif /* _I4B_TRACE_H_ */
diff --git a/sys/i4b/layer1/i4b_avm_a1.c b/sys/i4b/layer1/i4b_avm_a1.c
new file mode 100644
index 000000000000..bb55979e3638
--- /dev/null
+++ b/sys/i4b/layer1/i4b_avm_a1.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 1996 Andrew Gordon. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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_avm_a1.c - AVM A1/Fritz passive card driver for isdn4bsd
+ * ------------------------------------------------------------
+ *
+ * $Id: i4b_avm_a1.c,v 1.20 1998/12/16 13:57:21 hm Exp $
+ *
+ * last edit-date: [Wed Dec 16 14:59:59 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(AVM_A1)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifndef __FreeBSD__
+static u_int8_t avma1_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void avma1_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void avma1_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM A1 and AVM Fritz! Card special registers
+ *---------------------------------------------------------------------------*/
+
+#define AVM_CONF_REG 0x1800 /* base offset for config register */
+#define AVM_CONF_IRQ 0x1801 /* base offset for IRQ register */
+ /* config register write */
+#define AVM_CONF_WR_RESET 0x01 /* 1 = RESET ISAC and HSCX */
+#define AVM_CONF_WR_CCL 0x02 /* 1 = clear counter low nibble */
+#define AVM_CONF_WR_CCH 0x04 /* 1 = clear counter high nibble */
+#define AVM_CONF_WR_IRQEN 0x08 /* 1 = enable IRQ */
+#define AVM_CONF_WR_TEST 0x10 /* test bit */
+ /* config register read */
+#define AVM_CONF_RD_IIRQ 0x01 /* 0 = ISAC IRQ active */
+#define AVM_CONF_RD_HIRQ 0x02 /* 0 = HSCX IRQ active */
+#define AVM_CONF_RD_CIRQ 0x04 /* 0 = counter IRQ active */
+#define AVM_CONF_RD_ZER1 0x08 /* unused, always read 0 */
+#define AVM_CONF_RD_TEST 0x10 /* test bit read back */
+#define AVM_CONF_RD_ZER2 0x20 /* unused, always read 0 */
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_read_multi_1(t, h, 0, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+#else
+static void
+avma1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+#else
+static u_int8_t
+avma1_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1 - probe for AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char savebyte;
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for AVM A1/Fritz!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x240:
+ case 0x300:
+ case 0x340:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + 0x1400 - 0x20;
+
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + 0x400 - 0x20;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + 0xc00 - 0x20;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = inb(dev->id_iobase + AVM_CONF_REG);
+
+ /* write low to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x00)
+ {
+ printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ /* write high to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x10)
+ {
+ printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_avma1(struct isic_attach_args *ia)
+{
+ u_int8_t savebyte, v1, v2;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ v1 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXA+1].t, ia->ia_maps[ISIC_WHAT_HSCXA+1].h, H_VSTR) & 0x0f;
+ v2 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXB+1].t, ia->ia_maps[ISIC_WHAT_HSCXB+1].h, H_VSTR) & 0x0f;
+ if (v1 != v2 || (v1 != 0x05 && v1 != 0x04))
+ return 0;
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0);
+
+ /* write low to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x00)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ /* write high to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x10)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_avma1 - attach AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_avma1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_IRQ, (ffs(sc->sc_irq)) - 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else
+
+int
+isic_attach_avma1(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 1, sc->sc_irq);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+#endif
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c
new file mode 100644
index 000000000000..483eb660a828
--- /dev/null
+++ b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1998 Matthias Apitz. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Fritz!Card pcmcia specific routines for isic driver
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_avm_fritz_pcmcia.c,v 1.7 1998/12/01 21:25:53 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 22:03:51 1998]
+ *
+ * -ap added support for AVM PCMCIA Fritz!Card
+ * -mh split into separate file
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(AVM_PCMCIA)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t avma1_pcmcia_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void avma1_pcmcia_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_pcmcia_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void avma1_pcmcia_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM PCMCIA Fritz!Card special registers
+ *---------------------------------------------------------------------------*/
+
+/*
+ * register offsets from i/o base 0x140 or 0x300
+ */
+#define ADDR_REG_OFFSET 0x02
+#define DATA_REG_OFFSET 0x03
+#define STAT0_OFFSET 0x04
+#define STAT1_OFFSET 0x05
+#define MODREG_OFFSET 0x06
+#define VERREG_OFFSET 0x07
+/*
+ * AVM PCMCIA Status Latch 0 read only bits
+ */
+#define ASL_IRQ_TIMER 0x10 /* Timer interrupt, active low */
+#define ASL_IRQ_ISAC 0x20 /* ISAC interrupt, active low */
+#define ASL_IRQ_HSCX 0x40 /* HSX interrupt, active low */
+#define ASL_IRQ_BCHAN ASL_IRQ_HSCX
+#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
+/*
+ * AVM Status Latch 0 write only bits
+ */
+#define ASL_RESET_ALL 0x01 /* reset siemens IC's, active 1 */
+#define ASL_TIMERDISABLE 0x02 /* active high */
+#define ASL_TIMERRESET 0x04 /* active high */
+#define ASL_ENABLE_INT 0x08 /* active high */
+/*
+ * AVM Status Latch 1 write only bits
+ */
+#define ASL1_LED0 0x10 /* active high */
+#define ASL1_LED1 0x20 /* active high */
+
+#define ASL1_ENABLE_S0 0xc0 /* enable active S0 I/F */
+
+/*----- EEpromless controller -----*/
+/*
+ * AVM Status Latch read/write bit
+ */
+
+#define ASL_TESTBIT 0x80
+
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+avma1_pcmcia_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ insb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+/* offsets of the different 'what' arguments */
+static u_int8_t what_map[] = {
+ 0x20-0x20, /* ISIC_WHAT_ISAC */
+ 0xA0-0x20, /* ISIC_WHAT_HSCXA */
+ 0xE0-0x20 /* ISIC_WHAT_HSCXB */
+};
+static void
+avma1_pcmcia_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_read_multi_1(t, h, DATA_REG_OFFSET, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ outsb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_pcmcia_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_write_multi_1(t, h, DATA_REG_OFFSET, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_reg(u_char *base, u_int offset, u_int v)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ outb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char)v);
+}
+#else
+static void
+avma1_pcmcia_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ bus_space_write_1(t, h, DATA_REG_OFFSET, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_pcmcia_read_reg(u_char *base, u_int offset)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ return (inb(PCMCIA_IO_BASE + DATA_REG_OFFSET));
+}
+#else
+static u_int8_t
+avma1_pcmcia_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ return bus_space_read_1(t, h, DATA_REG_OFFSET);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1_pcmcia - probe for AVM PCMCIA Fritz!Card
+ * This is in the bus attachemnt part on NetBSD (pcmcia_isic.c), no
+ * card specicfic probe is needed on direct config buses like pcmcia.
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1_pcmcia(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+ int i;
+ u_int cardinfo;
+
+ /* check max unit range */
+
+ if(dev->id_unit > 1)
+ {
+ printf("isic%d: Error, unit %d > MAXUNIT for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /*
+ * we trust the IRQ we got from PCCARD service
+ */
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x140:
+ case 0x300:
+ break;
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM PCMCIA Fritz!Card.\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* ResetController */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+
+ /*
+ * CheckController
+ * The logic to check for the PCMCIA was adapted as
+ * described by AVM.
+ */
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0x21); /* ISAC STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, ISAC STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0xa1); /* HSCX STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, HSCX STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = ASL_TESTBIT;
+ for (i=0; i<256; i++) {
+ byte = byte ? 0 : ASL_TESTBIT;
+ outb(dev->id_iobase + STAT0_OFFSET, byte);
+ if ((inb(dev->id_iobase+STAT0_OFFSET)&ASL_TESTBIT)!=byte) {
+ printf("isic%d: Error during toggle of AVM PCMCIA Status Latch0\n",
+ dev->id_unit);
+ return(0);
+ }
+ }
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2; /* ap: XXX ??? */
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ /*
+ * NOTE: for PCMCIA these are no real addrs; they are
+ * offsets to be written into the base+ADDR_REG_OFFSET register
+ * to pick up the values of the bytes fro base+DATA_REG_OFFSET
+ *
+ * see also the logic in the avma1_pcmcia_* routines;
+ * therefore we also must have the base addr in some static
+ * space or struct; XXX better solution?
+ */
+
+ PCMCIA_IO_BASE = dev->id_iobase;
+ ISAC_BASE = (caddr_t)0x20;
+
+ HSCX_A_BASE = (caddr_t)0xA0;
+ HSCX_B_BASE = (caddr_t)0xE0;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /*
+ * seems we really have an AVM PCMCIA Fritz!Card controller
+ */
+ cardinfo = inb(dev->id_iobase + VERREG_OFFSET)<<8 | inb(dev->id_iobase + MODREG_OFFSET);
+ printf("isic%d: successfully detect AVM PCMCIA cardinfo = 0x%0x\n",
+ dev->id_unit, cardinfo);
+ dev->id_flags = FLAG_AVM_A1_PCMCIA;
+ return (1);
+}
+#endif /* __FreeBSD__ */
+
+
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_fritzpcmcia - attach Fritz!Card
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_fritzpcmica(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* ResetController again just to make sure... */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+ /* DELAY(SEC_DELAY / 10); */
+
+ return(1);
+}
+
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_fritzpcmcia(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space - exactly as dictated by the card */
+ if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start, cfe->iospace[0].length,
+ 0, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Reset controller again just to make sure... */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+
+ return 1;
+}
+#endif
+
+#endif /* NISIC > 0 && defined(AVM_PCMCIA) */
diff --git a/sys/i4b/layer1/i4b_bchan.c b/sys/i4b/layer1/i4b_bchan.c
new file mode 100644
index 000000000000..17ee27364777
--- /dev/null
+++ b/sys/i4b/layer1/i4b_bchan.c
@@ -0,0 +1,484 @@
+/*
+ * 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_bchan.c - B channel handling L1 procedures
+ * ----------------------------------------------
+ *
+ * $Id: i4b_bchan.c,v 1.28 1998/12/05 18:04:28 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:21:57 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 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/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __FreeBSD__
+static void isic_bchannel_start(int unit, int h_chan);
+static void isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp);
+#else
+static void isic_bchannel_start __P((int unit, int h_chan));
+static void isic_bchannel_stat __P((int unit, int h_chan, bchan_statistics_t *bsp));
+#endif
+
+static void isic_set_linktab(int unit, int channel, drvr_link_t *dlt);
+static isdn_link_t *isic_ret_linktab(int unit, int channel);
+
+/*---------------------------------------------------------------------------*
+ * initialize one B channels rx/tx data structures and init/deinit HSCX
+ *---------------------------------------------------------------------------*/
+void
+isic_bchannel_setup(int unit, int h_chan, int bprot, int activate)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+
+ int s = SPLI4B();
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ DBGL1(L1_BCHAN, "isic_bchannel_setup", ("unit=%d, channel=%d, %s\n",
+ sc->sc_unit, h_chan, activate ? "activate" : "deactivate"));
+
+ /* general part */
+
+ chan->unit = sc->sc_unit; /* unit number */
+ chan->channel = h_chan; /* B channel */
+ chan->bprot = bprot; /* B channel protocol */
+ chan->state = HSCX_IDLE; /* B channel state */
+
+ /* receiver part */
+
+ i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
+
+ chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->rxcount = 0; /* reset rx counter */
+
+ i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
+
+ chan->in_mbuf = NULL; /* reset mbuf ptr */
+ chan->in_cbptr = NULL; /* reset mbuf curr ptr */
+ chan->in_len = 0; /* reset mbuf data len */
+
+ /* transmitter part */
+
+ i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
+
+ chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->txcount = 0; /* reset tx counter */
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
+
+ chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
+ chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
+ chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
+ chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
+
+ if(activate != 0)
+ {
+ /* activation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * start transmission on a b channel
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_start(int unit, int h_chan)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ register isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ register int next_len;
+ register int len;
+
+ int s;
+ int activity = -1;
+ int cmd = 0;
+
+ s = SPLI4B(); /* enter critical section */
+ if(chan->state & HSCX_TX_ACTIVE) /* already running ? */
+ {
+ splx(s);
+ return; /* yes, leave */
+ }
+
+ /* get next mbuf from queue */
+
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL) /* queue empty ? */
+ {
+ splx(s); /* leave critical section */
+ return; /* yes, exit */
+ }
+
+ /* init current mbuf values */
+
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+
+ /* activity indicator for timeout handling */
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+
+ chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */
+
+ if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ len = 0; /* # of chars put into HSCX tx fifo this time */
+
+ /*
+ * fill the HSCX tx fifo with data from the current mbuf. if
+ * current mbuf holds less data than HSCX fifo length, try to
+ * get the next mbuf from (a possible) mbuf chain. if there is
+ * not enough data in a single mbuf or in a chain, then this
+ * is the last mbuf and we tell the HSCX that it has to send
+ * CRC and closing flag
+ */
+
+ while((len < sc->sc_bfifolen) && chan->out_mbuf_cur)
+ {
+ /*
+ * put as much data into the HSCX fifo as is
+ * available from the current mbuf
+ */
+
+ if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen)
+ next_len = sc->sc_bfifolen - len;
+ else
+ next_len = chan->out_mbuf_cur_len;
+
+#ifdef NOTDEF
+ printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ /* wait for tx fifo write enabled */
+
+ isic_hscx_waitxfw(sc, h_chan);
+
+ /* write what we have from current mbuf to HSCX fifo */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len);
+
+ len += next_len; /* update # of bytes written */
+ chan->txcount += next_len; /* statistics */
+ chan->out_mbuf_cur_ptr += next_len; /* data ptr */
+ chan->out_mbuf_cur_len -= next_len; /* data len */
+
+ /*
+ * in case the current mbuf (of a possible chain) data
+ * has been put into the fifo, check if there is a next
+ * mbuf in the chain. If there is one, get ptr to it
+ * and update the data ptr and the length
+ */
+
+ if((chan->out_mbuf_cur_len <= 0) &&
+ ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ }
+
+ /*
+ * if there is either still data in the current mbuf and/or
+ * there is a successor on the chain available issue just
+ * a XTF (transmit) command to HSCX. if ther is no more
+ * data available from the current mbuf (-chain), issue
+ * an XTF and an XME (message end) command which will then
+ * send the CRC and the closing HDLC flag sequence
+ */
+
+ if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
+ {
+ /*
+ * more data available, send current fifo out.
+ * next xfer to HSCX tx fifo is done in the
+ * HSCX interrupt routine.
+ */
+
+ cmd |= HSCX_CMDR_XTF;
+ }
+ else
+ {
+ /* end of mbuf chain */
+
+ if(chan->bprot == BPROT_NONE)
+ cmd |= HSCX_CMDR_XTF;
+ else
+ cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME;
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */
+
+ chan->out_mbuf_head = NULL;
+ chan->out_mbuf_cur = NULL;
+ chan->out_mbuf_cur_ptr = NULL;
+ chan->out_mbuf_cur_len = 0;
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+
+ if(cmd)
+ isic_hscx_cmd(sc, h_chan, cmd);
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * fill statistics struct
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ int s;
+
+ s = SPLI4B();
+
+ bsp->outbytes = chan->txcount;
+ bsp->inbytes = chan->rxcount;
+
+ chan->txcount = 0;
+ chan->rxcount = 0;
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * return the address of isic drivers linktab
+ *---------------------------------------------------------------------------*/
+static isdn_link_t *
+isic_ret_linktab(int unit, int channel)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[channel];
+
+ return(&chan->isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+static void
+isic_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[channel];
+
+ chan->drvr_linktab = dlt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+void
+isic_init_linktab(struct isic_softc *sc)
+{
+ isic_Bchan_t *chan = &sc->sc_chan[HSCX_CH_A];
+ isdn_link_t *lt = &chan->isdn_linktab;
+
+ /* make sure the hardware driver is known to layer 4 */
+ ctrl_types[CTRL_PASSIVE].set_linktab = isic_set_linktab;
+ ctrl_types[CTRL_PASSIVE].get_linktab = isic_ret_linktab;
+
+ /* local setup */
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_A;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+
+ chan = &sc->sc_chan[HSCX_CH_B];
+ lt = &chan->isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_B;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+}
+
+/*---------------------------------------------------------------------------*
+ * telephony silence detection
+ *---------------------------------------------------------------------------*/
+
+#define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
+
+int
+isic_hscx_silence(unsigned char *data, int len)
+{
+ register int i = 0;
+ register int j = 0;
+
+ /* count idle bytes */
+
+ for(;i < len; i++)
+ {
+ if((*data >= 0xaa) && (*data <= 0xac))
+ j++;
+ data++;
+ }
+
+#ifdef NOTDEF
+ printf("isic_hscx_silence: got %d silence bytes in frame\n", j);
+#endif
+
+ if(j < (TEL_IDLE_MIN))
+ return(0);
+ else
+ return(1);
+
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_ctx_s0P.c b/sys/i4b/layer1/i4b_ctx_s0P.c
new file mode 100644
index 000000000000..f9e6b7f03eed
--- /dev/null
+++ b/sys/i4b/layer1/i4b_ctx_s0P.c
@@ -0,0 +1,366 @@
+/*
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Creatix PnP cards
+ * ============================================================
+ *
+ * $Id: i4b_ctx_s0P.c,v 1.17 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:26:30 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t ctxs0P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void ctxs0P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void ctxs0P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void ctxs0P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_Cs0P(struct isic_softc *sc);
+#endif
+
+#ifdef __FreeBSD__
+#include <i386/isa/pnp.h>
+extern void isicintr ( int unit );
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+ctxs0P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+ctxs0P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+ctxs0P_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Cs0P - probe for Creatix ISDN-S0 P&P and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x120:
+ case 0x180:
+/*XXX*/ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) dev->id_iobase - 0x20;
+ HSCX_A_BASE = (caddr_t) iobase2 - 0x20;
+ HSCX_B_BASE = (caddr_t) iobase2;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the Creatix PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Creatix PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Creatix ISDN-S0 P&P
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Cs0P(struct isic_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P) */
+
diff --git a/sys/i4b/layer1/i4b_drn_ngo.c b/sys/i4b/layer1/i4b_drn_ngo.c
new file mode 100644
index 000000000000..a5f3d6941923
--- /dev/null
+++ b/sys/i4b/layer1/i4b_drn_ngo.c
@@ -0,0 +1,542 @@
+/*
+ * 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_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod
+ * --------------------------------------------------------
+ *
+ * $Id: i4b_drn_ngo.c,v 1.19 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:26:03 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+/*---------------------------------------------------------------------------*
+ * Niccy GO@ definitions
+ *
+ * the card uses 2 i/o addressranges each using 2 bytes
+ *
+ * addressrange 0:
+ * offset 0 - ISAC dataregister
+ * offset 1 - HSCX dataregister
+ * addressrange 1:
+ * offset 0 - ISAC addressregister
+ * offset 1 - HSCX addressregister
+ *
+ * to access an ISAC/HSCX register, you have to write the register
+ * number into the ISAC or HSCX addressregister and then read/write
+ * data for the ISAC/HSCX register into/from the corresponding
+ * dataregister.
+ *
+ * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving
+ * out this information!
+ *
+ *---------------------------------------------------------------------------*/
+#define NICCY_PORT_MIN 0x200
+#define NICCY_PORT_MAX 0x3e0
+
+#define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */
+#define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */
+
+#define HSCX_BOFF 0x40
+
+#define ADDR_OFF 2 /* address register range offset XXX */
+
+#define ISAC_DATA 0
+#define HSCX_DATA 1
+
+#define ISAC_ADDR 0
+#define HSCX_ADDR 1
+
+#ifdef __FreeBSD__
+
+#if 0
+#define HSCXADEBUG
+#define HSCXBDEBUG
+#define ISACDEBUG
+#else
+#undef HSCXADEBUG
+#undef HSCXBDEBUG
+#undef ISACDEBUG
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ *((u_char *)buf + offset) = inb((int)data);
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ outb((int)data, *((u_char *)buf + offset));
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write register routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int x = SPLI4B();
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXADEBUG
+printf("GO/A/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXBDEBUG
+printf("GO/B/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)v);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ outb((int)base + ISAC_DATA, (u_char)v);
+#ifdef ISACDEBUG
+printf("GO/I/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+drnngo_read_reg(u_char *base, u_int offset)
+{
+ u_char val;
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXADEBUG
+printf("GO/A/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXBDEBUG
+printf("GO/B/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)val);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ val = inb((int)base + ISAC_DATA);
+#ifdef ISACDEBUG
+printf("GO/I/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ splx(x);
+ return(val);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_drnngo - probe for Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase < NICCY_PORT_MIN || dev->id_iobase > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ if(iobase2 < NICCY_PORT_MIN || iobase2 > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid port1 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, iobase2);
+ return(0);
+ }
+
+/*XXX*/ if((dev->id_iobase + 2) != iobase2)
+ {
+ printf("isic%d: Error, port1 must be (port0+2) for Dr.Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase;
+ HSCX_A_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_ABIT);
+ HSCX_B_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_BBIT);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for Dr. Neuhaus Niccy GO@ based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dr. Neuhaus Niccy GO@\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_drnngo - attach Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ return (1);
+}
+
+#else
+
+static u_int8_t drnngo_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void drnngo_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void drnngo_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void drnngo_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_drnngo __P((struct isic_softc *sc));
+
+/*
+ * Mapping from "what" parameter to offsets into the io map
+ */
+static struct {
+ bus_size_t oa, /* address register offset */
+ od, /* data register offset */
+ or; /* additional chip register offset */
+} offset[] =
+{
+ { ISAC_ADDR, ISAC_DATA, 0 }, /* ISAC access */
+ { HSCX_ADDR, HSCX_DATA, 0 }, /* HSCX A access */
+ { HSCX_ADDR, HSCX_DATA, HSCX_BOFF } /* HSCX B access */
+};
+
+static void
+drnngo_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_read_multi_1(t, hd, offset[what].od, buf, size);
+}
+
+static void
+drnngo_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_write_multi_1(t, hd, offset[what].od, (u_int8_t*)buf, size);
+}
+
+static void
+drnngo_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ bus_space_write_1(t, hd, offset[what].od, data);
+}
+
+static u_int8_t
+drnngo_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ return bus_space_read_1(t, hd, offset[what].od);
+}
+
+void
+isic_attach_drnngo(struct isic_softc *sc)
+{
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO) */
diff --git a/sys/i4b/layer1/i4b_dynalink.c b/sys/i4b/layer1/i4b_dynalink.c
new file mode 100644
index 000000000000..846e79ae6da1
--- /dev/null
+++ b/sys/i4b/layer1/i4b_dynalink.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 1998 Martijn Plak. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA
+ * ==================================================
+ *
+ * $Id: i4b_dynalink.c,v 1.8 1998/12/17 04:55:38 hm Exp $
+ *
+ * last edit-date: [Thu Dec 17 05:50:39 1998]
+ *
+ * written by Martijn Plak <tigrfhur@xs4all.nl>
+ *
+ * -mp 11 jun 1998 first try, code borrowed from Creatix driver
+ * -mp 18 jun 1998 cleaned up code
+ * -hm FreeBSD PnP
+ * -mp 17 dec 1998 made it compile again
+ *
+ *---------------------------------------------------------------------------*/
+
+/* NOTES:
+
+ This driver was written for the Dynalink IS64PH ISDN TA, based on two
+ Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands.
+
+ model numbers found on (my) card:
+ IS64PH, TAS100H-N, P/N:89590555, TA200S100045521
+
+ chips:
+ Siemens PSB 21525N, HSCX TE V2.1
+ Siemens PSB 2186N, ISAC-S TE V1.1
+ 95MS14, PNP
+
+ plug-and-play info:
+ device id "ASU1688"
+ vendor id 0x88167506
+ serial 0x00000044
+ i/o port 4 byte alignment, 4 bytes requested,
+ 10 bit i/o decoding, 0x100-0x3f8 (?)
+ irq 3,4,5,9,10,11,12,15, high true, edge sensitive
+
+ At the moment I'm writing this Dynalink is replacing this card with
+ one based on a single Siemens chip (IPAC). It will apparently be sold
+ under the same model name.
+
+ This driver might also work for Asuscom cards.
+*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(DYNALINK)
+
+/* HEADERS
+*/
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifdef __FreeBSD__
+static void dynalink_read_fifo(void *buf, const void *base, size_t len);
+static void dynalink_write_fifo(void *base, const void *buf, size_t len);
+static void dynalink_write_reg(u_char *base, u_int offset, u_int v);
+static u_char dynalink_read_reg(u_char *base, u_int offset);
+
+extern struct isa_driver isicdriver;
+
+#else
+static void dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
+static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
+static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
+void isic_attach_Dyn(struct isic_softc *sc);
+#endif
+
+/* io address mapping */
+#define ISAC 0
+#define HSCX 1
+#define ADDR 2
+
+/* ADDR bits */
+#define ADDRMASK 0x7F
+#define RESET 0x80
+
+/* HSCX register offsets */
+#define HSCXA 0x00
+#define HSCXB 0x40
+
+#ifdef __FreeBSD__
+/* base address juggling */
+#define HSCXB_HACK 0x400
+#define IOBASE(addr) (((int)addr)&0x3FC)
+#define IOADDR(addr) (((int)addr)&0x3FF)
+#define IS_HSCXB_HACK(addr) ((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA)
+
+/* ISIC probe and attach
+*/
+
+int
+isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return (0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ if ( (dev->id_iobase < 0x100) ||
+ (dev->id_iobase > 0x3f8) ||
+ (dev->id_iobase & 3) )
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dynalink\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+int
+isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase)+ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void isic_attach_Dyn(struct isic_softc *sc)
+{
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+}
+
+#endif /* ISIC>0 && NPNP>0 && defined(DYNALINK) */
+
+/* LOW-LEVEL DEVICE ACCESS
+
+ NOTE: The isdn4bsd code expects the two HSCX channels at different
+ base addresses. I'm faking this, and remap them to the same address
+ in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK.
+
+ REM: this is only true for the FreeBSD version of I4B!
+*/
+
+#ifdef __FreeBSD__
+static void
+dynalink_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ insb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void
+dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_read_multi_1(t, h, ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+dynalink_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ outsb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+dynalink_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ outb(IOADDR(base), (u_char)v);
+}
+#else
+static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ bus_space_write_1(t, h, ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static u_char
+dynalink_read_reg(u_char *base, u_int offset)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ return (inb(IOADDR(base)));
+}
+#else
+static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ return bus_space_read_1(t, h, ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ return bus_space_read_1(t, h, HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ return bus_space_read_1(t, h, HSCX);
+ }
+ return 0;
+}
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(DYNALINK) */
diff --git a/sys/i4b/layer1/i4b_elsa_isdnmc.c b/sys/i4b/layer1/i4b_elsa_isdnmc.c
new file mode 100644
index 000000000000..c6987f55adb2
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_isdnmc.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink ISDN/MC card specific routines
+ * ---------------------------------------------
+ *
+ * $Id: i4b_elsa_isdnmc.c,v 1.2 1998/12/05 18:04:33 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 07:45:53 1998]
+ *
+ * -mh added support for elsa ISDN/mc
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(ELSA_ISDNMC)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_isdnmc_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void elsa_isdnmc_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_isdnmc_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void elsa_isdnmc_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*
+ * The ELSA MicroLink ISDN/MC uses one contigous IO region,
+ * mapped by the pcmcia code.
+ * The chip access is via three ports:
+ */
+#define ISAC_DATA 1 /* ISAC dataport at offset 1 */
+#define HSCX_DATA 2 /* HSCX dataport at offset 2 */
+#define ADDR_LATCH 4 /* address latch at offset 4 */
+
+/* This is very similar to the ELSA QuickStep 1000 (ISA) card */
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_isdnmc_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_isdnmc_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_isdnmc_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsaisdnmc(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* OK, this will work! */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLIMC;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = elsa_isdnmc_read_reg;
+ sc->writereg = elsa_isdnmc_write_reg;
+
+ sc->readfifo = elsa_isdnmc_read_fifo;
+ sc->writefifo = elsa_isdnmc_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_elsa_mcall.c b/sys/i4b/layer1/i4b_elsa_mcall.c
new file mode 100644
index 000000000000..36882e912809
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_mcall.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink MC/all card specific routines
+ * --------------------------------------------
+ *
+ * $Id: i4b_elsa_mcall.c,v 1.1 1998/12/02 06:44:27 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 07:45:53 1998]
+ *
+ * -mh started support for ELSA MC/all
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(ELSA_MCALL)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_ipac.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_mcall_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void elsa_mcall_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_mcall_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void elsa_mcall_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+elsa_mcall_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_mcall_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_mcall_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_mcall_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsamcall(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLMCALL;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = elsa_mcall_read_reg;
+ sc->writereg = elsa_mcall_write_reg;
+
+ sc->readfifo = elsa_mcall_read_fifo;
+ sc->writefifo = elsa_mcall_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_elsa_qs1i.c b/sys/i4b/layer1/i4b_elsa_qs1i.c
new file mode 100644
index 000000000000..a3c8ddc27afe
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_qs1i.c
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1i.c,v 1.12 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:27:08 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifdef __FreeBSD__
+static void i4b_eq1i_clrirq(void* base);
+#else
+static void i4b_eq1i_clrirq(struct isic_softc *sc);
+void isic_attach_Eqs1pi __P((struct isic_softc *sc));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ISAC 0x00
+#define ELSA_OFF_HSCX 0x02
+#define ELSA_OFF_OFF 0x03
+#define ELSA_OFF_CTRL 0x04
+#define ELSA_OFF_CFG 0x05
+#define ELSA_OFF_TIMR 0x06
+#define ELSA_OFF_IRQ 0x07
+
+/* control register (write access) */
+
+#define ELSA_CTRL_LED_YELLOW 0x02
+#define ELSA_CTRL_LED_GREEN 0x08
+#define ELSA_CTRL_RESET 0x20
+#define ELSA_CTRL_TIMEREN 0x80
+#define ELSA_CTRL_SECRET 0x50
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA clear IRQ routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+i4b_eq1i_clrirq(void* base)
+{
+ outb((u_int)base + ELSA_OFF_IRQ, 0);
+}
+
+#else
+static void
+i4b_eq1i_clrirq(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pi_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+/* XXX no "sc_clearirq" in sight... /phk
+ sc->sc_clearirq = i4b_eq1i_clrirq;
+*/
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the ELSA QuickStep 1000pro
+ * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Eqs1pi(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
+
+ /* setup access routines */
+
+ sc->clearirq = i4b_eq1i_clrirq;
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */
diff --git a/sys/i4b/layer1/i4b_elsa_qs1p.c b/sys/i4b/layer1/i4b_elsa_qs1p.c
new file mode 100644
index 000000000000..b2b35d03fc34
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_qs1p.c
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro PCI
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1p.c,v 1.4 1998/12/05 18:04:36 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:22:41 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+#else
+#define NISIC 1
+#endif
+
+#if (NISIC > 0) && /* (NPCI > 0) && */ defined(ELSA_QS1PCI)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_ipac.h>
+
+#ifndef __FreeBSD__
+/* we don't have the function prototypes in the global i4b_l1.h any more */
+void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+#define ELSA_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ALE 0x00
+#define ELSA_OFF_RW 0x01
+
+#define ELSA_PORT0_MAPOFF PCI_MAPREG_START+4
+#define ELSA_PORT1_MAPOFF PCI_MAPREG_START+12
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else /* IPAC */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pp_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else /* IPAC */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ {
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Eqs1pp - attach for ELSA QuickStep 1000pro/PCI
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[unit];
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/PCI!\n",
+ unit, unit);
+ return(0);
+ }
+ sc->sc_unit = unit;
+
+ /* setup iobase */
+
+ if((iobase2 <= 0) || (iobase2 > 0xffff))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/PCI!\n",
+ unit, iobase2);
+ return(0);
+ }
+ sc->sc_port = iobase2;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXB);
+ IPAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDIPAC);
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ outb(iobase1 + 0x4c, 0x41); /* enable card interrupt */
+
+ return (1);
+}
+
+#else /* !FreeBSD */
+
+void
+isic_attach_Eqs1pp(sc, pa)
+ struct isic_softc *sc;
+ struct pci_attach_args *pa;
+{
+ /* setup io mappings */
+ sc->sc_num_mappings = 2;
+ MALLOC_MAPS(sc);
+ sc->sc_maps[0].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT0_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[0].t, &sc->sc_maps[0].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ sc->sc_maps[1].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT1_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[1].t, &sc->sc_maps[1].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x41); /* enable card interrupt */
+}
+
+#endif
+
+#endif /* (NISIC > 0) && defined(ELSA_QS1PCI) */
diff --git a/sys/i4b/layer1/i4b_hscx.c b/sys/i4b/layer1/i4b_hscx.c
new file mode 100644
index 000000000000..ed80a51c5731
--- /dev/null
+++ b/sys/i4b/layer1/i4b_hscx.c
@@ -0,0 +1,672 @@
+/*
+ * 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 - Siemens HSCX chip (B-channel) handling
+ * --------------------------------------------
+ *
+ * $Id: i4b_hscx.c,v 1.37 1998/12/05 18:04:38 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* doesn't matter in non-FreeBSD, config(8) d.t.r.t. */
+#endif
+#if NISIC > 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 <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * HSCX IRQ Handler
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_irq(register struct isic_softc *sc, u_char ista, int h_chan, u_char ex_irq)
+{
+ register isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ u_char exir = 0;
+ int activity = -1;
+ u_char cmd = 0;
+
+ DBGL1(L1_H_IRQ, "isic_hscx_irq", ("%#x\n", ista));
+
+ if(ex_irq)
+ {
+ /* get channel extended irq reg */
+
+ exir = HSCX_READ(h_chan, H_EXIR);
+
+ if(exir & HSCX_EXIR_RFO)
+ {
+ chan->stat_RFO++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: receive data overflow\n"));
+ }
+
+ if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
+ {
+ chan->stat_XDU++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: xmit data underrun\n"));
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
+
+ if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
+ {
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
+ }
+ }
+
+ }
+
+ /* rx message end, end of frame */
+
+ if(ista & HSCX_ISTA_RME)
+ {
+ register int fifo_data_len;
+ u_char rsta;
+ int error = 0;
+
+ rsta = HSCX_READ(h_chan, H_RSTA);
+
+ if((rsta & 0xf0) != 0xa0)
+ {
+ if((rsta & HSCX_RSTA_VFR) == 0)
+ {
+ chan->stat_VFR++;
+ cmd |= (HSCX_CMDR_RHR);
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("received invalid Frame\n"));
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RDO)
+ {
+ chan->stat_RDO++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("receive data overflow\n"));
+ error++;
+ }
+
+ if((rsta & HSCX_RSTA_CRC) == 0)
+ {
+ chan->stat_CRC++;
+ cmd |= (HSCX_CMDR_RHR);
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("CRC check failed\n"));
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RAB)
+ {
+ chan->stat_RAB++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("Receive message aborted\n"));
+ error++;
+ }
+ }
+
+ fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
+ ((sc->sc_bfifolen)-1));
+
+ if(fifo_data_len == 0)
+ fifo_data_len = sc->sc_bfifolen;
+
+ /* all error conditions checked, now decide and take action */
+
+ if(error == 0)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
+
+ if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
+
+ cmd |= (HSCX_CMDR_RMC);
+ isic_hscx_cmd(sc, h_chan, cmd);
+ cmd = 0;
+
+ chan->in_len += fifo_data_len;
+ chan->rxcount += fifo_data_len;
+
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ activity = ACT_RX;
+
+ /* mark buffer ptr as unused */
+
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ else
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d\n", chan->in_len, fifo_data_len));
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
+ }
+ }
+ else
+ {
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ cmd |= (HSCX_CMDR_RMC);
+ }
+ }
+
+ /* rx fifo full */
+
+ if(ista & HSCX_ISTA_RPF)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ chan->rxcount += sc->sc_bfifolen;
+
+ if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len += sc->sc_bfifolen;
+ }
+ else
+ {
+ if(chan->bprot == BPROT_NONE)
+ {
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ /* move rx'd data to rx queue */
+
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ /* alloc new buffer */
+
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
+
+ /* setup new data ptr */
+
+ chan->in_cbptr = chan->in_mbuf->m_data;
+
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len = sc->sc_bfifolen;
+
+ chan->rxcount += sc->sc_bfifolen;
+ }
+ else
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RPF, in_len=%d\n", chan->in_len));
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR);
+ }
+ }
+
+ /* command to release fifo space */
+
+ cmd |= HSCX_CMDR_RMC;
+ }
+
+ /* transmit fifo empty, new data can be written to fifo */
+
+ if(ista & HSCX_ISTA_XPR)
+ {
+ /*
+ * for a description what is going on here, please have
+ * a look at isic_bchannel_start() in i4b_bchan.c !
+ */
+
+ int activity = -1;
+ int len;
+ int nextlen;
+
+ DBGL1(L1_H_IRQ, "isic_hscx_irq", ("unit %d, chan %d - XPR, Tx Fifo Empty!\n", sc->sc_unit, h_chan));
+
+ if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
+ {
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL)
+ {
+ chan->state &= ~HSCX_TX_ACTIVE;
+ (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit);
+ }
+ else
+ {
+ chan->state |= HSCX_TX_ACTIVE;
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+ }
+ }
+
+ len = 0;
+
+ while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
+ {
+ nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
+
+#ifdef NOTDEF
+ printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
+ cmd |= HSCX_CMDR_XTF;
+
+ len += nextlen;
+ chan->txcount += nextlen;
+
+ chan->out_mbuf_cur_ptr += nextlen;
+ chan->out_mbuf_cur_len -= nextlen;
+
+ if(chan->out_mbuf_cur_len == 0)
+ {
+ if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ else
+ {
+ if (chan->bprot != BPROT_NONE)
+ cmd |= HSCX_CMDR_XME;
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_head = NULL;
+ }
+
+ }
+ }
+ }
+
+ if(cmd) /* is there a command for the HSCX ? */
+ {
+ isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+}
+
+/*---------------------------------------------------------------------------*
+ * HSCX initialization
+ *
+ * for telephony: extended transparent mode 1
+ * for raw hdlc: transparent mode 0
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_init(struct isic_softc *sc, int h_chan, int activate)
+{
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+
+ HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */
+
+ if(sc->sc_ipac)
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM1); /* IPAC clock mode 5 */
+ }
+ else
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM2 | /* HSCX clock mode 5 */
+ HSCX_CCR1_CM0);
+ }
+
+ /* XAD1: Transmit Address Byte 1 */
+ HSCX_WRITE(h_chan, H_XAD1, 0xff);
+
+ /* XAD2: Transmit Address Byte 2 */
+ HSCX_WRITE(h_chan, H_XAD2, 0xff);
+
+ /* RAH2: Receive Address Byte High Reg. 2 */
+ HSCX_WRITE(h_chan, H_RAH2, 0xff);
+
+ /* XBCH: reset Transmit Byte Count High */
+ HSCX_WRITE(h_chan, H_XBCH, 0x00);
+
+ /* RLCR: reset Receive Length Check Register */
+ HSCX_WRITE(h_chan, H_RLCR, 0x00);
+
+ /* CCR2: set tx/rx clock shift bit 0 */
+ /* disable CTS irq, disable RIE irq*/
+ HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
+
+ /* XCCR: tx bit count per time slot */
+ HSCX_WRITE(h_chan, H_XCCR, 0x07);
+
+ /* RCCR: rx bit count per time slot */
+ HSCX_WRITE(h_chan, H_RCCR, 0x07);
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ {
+ switch(h_chan)
+ {
+ case HSCX_CH_A: /* Prepare HSCX channel A */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x2f);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x2f);
+ break;
+
+ case HSCX_CH_B: /* Prepare HSCX channel B */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x03);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x03);
+ break;
+ }
+ }
+ else /* IOM 1 setup */
+ {
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x07);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x07);
+ }
+
+ if(activate)
+ {
+ if(chan->bprot == BPROT_RHDLC)
+ {
+ /* HDLC Frames, transparent mode 0 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
+ }
+ else
+ {
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
+ }
+ else
+ {
+ /* TSAX: tx time slot */
+ HSCX_WRITE(h_chan, H_TSAX, 0xff);
+
+ /* TSAR: rx time slot */
+ HSCX_WRITE(h_chan, H_TSAR, 0xff);
+
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
+ /* always disable RSC and TIN */
+
+ chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
+
+ if(activate)
+ {
+ /* enable */
+ chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
+ }
+ else
+ {
+ /* disable */
+ chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
+ }
+
+ /* handle ICA, EXA, and EXB via interrupt mask of channel b */
+
+ if (h_chan == HSCX_CH_A)
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
+ HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+ else
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~HSCX_MASK_EXB;
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXB;
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+
+ /* clear spurious interrupts left over */
+
+ if(h_chan == HSCX_CH_A)
+ {
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ }
+ else /* mask ICA, because it must not be cleared by reading ISTA */
+ {
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * write command to HSCX command register
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_cmd(struct isic_softc *sc, int h_chan, unsigned char cmd)
+{
+ int timeout = 20;
+
+ while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
+ {
+ DELAY(10);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ DBGL1(L1_H_ERR, "isic_hscx_cmd", ("HSCX wait for CEC timeout!\n"));
+ }
+
+ HSCX_WRITE(h_chan, H_CMDR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * wait for HSCX transmit FIFO write enable
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_waitxfw(struct isic_softc *sc, int h_chan)
+{
+#define WAITVAL 50
+#define WAITTO 200
+
+ int timeout = WAITTO;
+
+ while((!(((HSCX_READ(h_chan, H_STAR)) &
+ (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
+ {
+ DELAY(WAITVAL);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ DBGL1(L1_H_ERR, "isic_hscx_waitxfw", ("HSCX wait for XFW timeout!\n"));
+ }
+ else if (timeout != WAITTO)
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_waitxfw", ("HSCX wait for XFW time: %d uS\n", (WAITTO-timeout)*50));
+ }
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_hscx.h b/sys/i4b/layer1/i4b_hscx.h
new file mode 100644
index 000000000000..1b1640de2282
--- /dev/null
+++ b/sys/i4b/layer1/i4b_hscx.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_hscx.h,v 1.3 1998/02/13 17:00:31 hm Exp $
+ *
+ * last edit-date: [Thu Feb 5 13:38:50 1998]
+ *
+ * -hm added AVM config register defs
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_HSCX_H_
+#define I4B_HSCX_H_
+
+enum HSCX_VERSIONS {
+ HSCX_VA1, /* 82525 A1 */
+ HSCX_UNKN1, /* unknown 1 */
+ HSCX_VA2, /* 82525 A2 */
+ HSCX_UNKN3, /* unknown 3 */
+ HSCX_VA3, /* 82525 A3 */
+ HSCX_V21, /* 82525 2.1 */
+ HSCX_UNKN /* unknown version */
+};
+
+#define HSCX_CH_A 0 /* channel A */
+#define HSCX_CH_B 1 /* channel B */
+
+#define HSCX_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the HSCX ISDN chip.
+ */
+
+typedef struct hscx_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char hscx_fifo [HSCX_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char hscx_ista;
+ unsigned char hscx_star;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_exir;
+ unsigned char hscx_rbcl;
+ unsigned char dummy_26;
+ unsigned char hscx_rsta;
+ unsigned char hscx_ral1;
+ unsigned char hscx_rhcr;
+ unsigned char dummy_2a;
+ unsigned char dummy_2b;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_rbch;
+ unsigned char hscx_vstr;
+ unsigned char hscx_ccr;
+ unsigned char dummy_30;
+ unsigned char dummy_31;
+ unsigned char dummy_32;
+ unsigned char dummy_33;
+ } hscx_r;
+ struct {
+ unsigned char hscx_mask;
+ unsigned char hscx_cmdr;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_xad1;
+ unsigned char hscx_xad2;
+ unsigned char hscx_rah1;
+ unsigned char hscx_rah2;
+ unsigned char hscx_ral1;
+ unsigned char hscx_ral2;
+ unsigned char hscx_xbcl;
+ unsigned char hscx_bgr;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_xbch;
+ unsigned char hscx_rlcr;
+ unsigned char hscx_ccr1;
+ unsigned char hscx_tsax;
+ unsigned char hscx_tsar;
+ unsigned char hscx_xccr;
+ unsigned char hscx_rccr;
+ } hscx_w;
+ } hscx_rw;
+} hscx_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* HSCX read registers */
+
+#define h_ista hscx_rw.hscx_r.hscx_ista
+#define H_ISTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ista)
+#define h_star hscx_rw.hscx_r.hscx_star
+#define H_STAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_star)
+#define h_mode hscx_rw.hscx_r.hscx_mode
+#define H_MODE REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_mode)
+#define h_timr hscx_rw.hscx_r.hscx_timr
+#define H_TIMR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_timr)
+#define h_exir hscx_rw.hscx_r.hscx_exir
+#define H_EXIR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_exir)
+#define h_rbcl hscx_rw.hscx_r.hscx_rbcl
+#define H_RBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbcl)
+#define h_rsta hscx_rw.hscx_r.hscx_rsta
+#define H_RSTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rsta)
+#define h_ral1 hscx_rw.hscx_r.hscx_ral1
+#define H_RAL1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ral1)
+#define h_rhcr hscx_rw.hscx_r.hscx_rhcr
+#define H_RHCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rhcr)
+#define h_ccr2 hscx_rw.hscx_r.hscx_ccr2
+#define H_CCR2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr2)
+#define h_rbch hscx_rw.hscx_r.hscx_rbch
+#define H_RBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbch)
+#define h_vstr hscx_rw.hscx_r.hscx_vstr
+#define H_VSTR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_vstr)
+#define h_ccr hscx_rw.hscx_r.hscx_ccr
+#define H_CCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr)
+
+/* HSCX write registers - for hscx_mode, hscx_timr, hscx_ral1, hscx_ccr2 */
+/* see read registers */
+
+#define h_mask hscx_rw.hscx_w.hscx_mask
+#define H_MASK REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_mask)
+#define h_cmdr hscx_rw.hscx_w.hscx_cmdr
+#define H_CMDR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_cmdr)
+#define h_xad1 hscx_rw.hscx_w.hscx_xad1
+#define H_XAD1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad1)
+#define h_xad2 hscx_rw.hscx_w.hscx_xad2
+#define H_XAD2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad2)
+#define h_rah1 hscx_rw.hscx_w.hscx_rah1
+#define H_RAH1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah1)
+#define h_rah2 hscx_rw.hscx_w.hscx_rah2
+#define H_RAH2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah2)
+#define h_ral2 hscx_rw.hscx_w.hscx_ral2
+#define H_RAL2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ral2)
+#define h_xbcl hscx_rw.hscx_w.hscx_xbcl
+#define H_XBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbcl)
+#define h_bgr hscx_rw.hscx_w.hscx_bgr
+#define H_BGR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_bgr)
+#define h_xbch hscx_rw.hscx_w.hscx_xbch
+#define H_XBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbch)
+#define h_rlcr hscx_rw.hscx_w.hscx_rlcr
+#define H_RLCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rlcr)
+#define h_ccr1 hscx_rw.hscx_w.hscx_ccr1
+#define H_CCR1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ccr1)
+#define h_tsax hscx_rw.hscx_w.hscx_tsax
+#define H_TSAX REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsax)
+#define h_tsar hscx_rw.hscx_w.hscx_tsar
+#define H_TSAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsar)
+#define h_xccr hscx_rw.hscx_w.hscx_xccr
+#define H_XCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xccr)
+#define h_rccr hscx_rw.hscx_w.hscx_rccr
+#define H_RCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rccr)
+
+#define HSCX_ISTA_RME 0x80
+#define HSCX_ISTA_RPF 0x40
+#define HSCX_ISTA_RSC 0x20
+#define HSCX_ISTA_XPR 0x10
+#define HSCX_ISTA_TIN 0x08
+#define HSCX_ISTA_ICA 0x04
+#define HSCX_ISTA_EXA 0x02
+#define HSCX_ISTA_EXB 0x01
+
+#define HSCX_MASK_RME 0x80
+#define HSCX_MASK_RPF 0x40
+#define HSCX_MASK_RSC 0x20
+#define HSCX_MASK_XPR 0x10
+#define HSCX_MASK_TIN 0x08
+#define HSCX_MASK_ICA 0x04
+#define HSCX_MASK_EXA 0x02
+#define HSCX_MASK_EXB 0x01
+
+#define HSCX_EXIR_XMR 0x80
+#define HSCX_EXIR_XDU 0x40
+#define HSCX_EXIR_PCE 0x20
+#define HSCX_EXIR_RFO 0x10
+#define HSCX_EXIR_CSC 0x08
+#define HSCX_EXIR_RFS 0x04
+
+/* the other bits are always 0 */
+
+#define HSCX_STAR_XDOV 0x80
+#define HSCX_STAR_XFW 0x40
+#define HSCX_STAR_XRNR 0x20
+#define HSCX_STAR_RRNR 0x10
+#define HSCX_STAR_RLI 0x08
+#define HSCX_STAR_CEC 0x04
+#define HSCX_STAR_CTS 0x02
+#define HSCX_STAR_WFA 0x01
+
+#define HSCX_CMDR_RMC 0x80
+#define HSCX_CMDR_RHR 0x40
+/* also known as XREP in transparent mode */
+#define HSCX_CMDR_RNR 0x20
+#define HSCX_CMDR_STI 0x10
+#define HSCX_CMDR_XTF 0x08
+#define HSCX_CMDR_XIF 0x04
+#define HSCX_CMDR_XME 0x02
+#define HSCX_CMDR_XRES 0x01
+
+#define HSCX_MODE_MDS1 0x80
+#define HSCX_MODE_MDS0 0x40
+#define HSCX_MODE_ADM 0x20
+#define HSCX_MODE_TMD 0x10
+#define HSCX_MODE_RAC 0x08
+#define HSCX_MODE_RTS 0x04
+#define HSCX_MODE_TRS 0x02
+#define HSCX_MODE_TLP 0x01
+
+#define HSCX_RSTA_VFR 0x80
+#define HSCX_RSTA_RDO 0x40
+#define HSCX_RSTA_CRC 0x20
+#define HSCX_RSTA_RAB 0x10
+#define HSCX_RSTA_HA1 0x08
+#define HSCX_RSTA_HA0 0x04
+#define HSCX_RSTA_CR 0x02
+#define HSCX_RSTA_LA 0x01
+
+#define HSCX_RSTA_MASK 0xf0 /* the interesting ones */
+
+/* only used in DMA mode */
+#define HSCX_XBCH_DMA 0x80
+#define HSCX_XBCH_NRM 0x40
+#define HSCX_XBCH_CAS 0x20
+#define HSCX_XBCH_XC 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_RBCH_DMA 0x80
+#define HSCX_RBCH_NRM 0x40
+#define HSCX_RBCH_CAS 0x20
+#define HSCX_RBCH_OV 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_VSTR_CD 0x80
+/* bits 6 thru 4 are 0 */
+/* bits 3 thru 0 are the version number */
+
+#define HSCX_RLCR_RC 0x80
+/* the rest of the bits are used to set the received length */
+
+#define HSCX_CCR1_PU 0x80
+/* bits 6 and 5 are SC1 SC0 */
+#define HSCX_CCR1_ODS 0x10
+#define HSCX_CCR1_ITF 0x08
+#define HSCX_CCR1_CM2 0x04
+#define HSCX_CCR1_CM1 0x02
+#define HSCX_CCR1_CM0 0x01
+
+/* for clock mode 5 */
+#define HSCX_CCR2_SOC2 0x80
+#define HSCX_CCR2_SOC1 0x40
+#define HSCX_CCR2_XCS0 0x20
+#define HSCX_CCR2_RCS0 0x10
+#define HSCX_CCR2_TIO 0x08
+#define HSCX_CCR2_CIE 0x04
+#define HSCX_CCR2_RIE 0x02
+#define HSCX_CCR2_DIV 0x01
+
+/* bits 7 thru 2 are TSNX */
+#define HSCX_TSAX_XCS2 0x02
+#define HSCX_TSAX_XCS1 0x01
+
+/* bits 7 thru 2 are TSNR */
+#define HSCX_TSAR_RCS2 0x02
+#define HSCX_TSAR_RCS1 0x01
+
+#endif /* I4B_HSCX_H_ */
diff --git a/sys/i4b/layer1/i4b_ipac.h b/sys/i4b/layer1/i4b_ipac.h
new file mode 100644
index 000000000000..79d8bc9656bd
--- /dev/null
+++ b/sys/i4b/layer1/i4b_ipac.h
@@ -0,0 +1,199 @@
+/*
+ * 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_ipac.h - definitions for the Siemens IPAC PSB2115 chip
+ * ==========================================================
+ *
+ * $Id: i4b_ipac.h,v 1.4 1998/12/05 18:04:39 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:50 1998]
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef _I4B_IPAC_H_
+#define _I4B_IPAC_H_
+
+#define IPAC_BFIFO_LEN 64 /* 64 bytes B-channel FIFO on chip */
+
+#define IPAC_HSCXA_OFF 0x00
+#define IPAC_HSCXB_OFF 0x40
+#define IPAC_ISAC_OFF 0x80
+#define IPAC_IPAC_OFF 0xc0
+
+/*
+ * definitions of registers and bits for the IPAC ISDN chip.
+ */
+
+typedef struct ipac_reg {
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_ista;
+ unsigned char ipac_id;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_arx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_r;
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_mask;
+ unsigned char ipac_dummy;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_atx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_w;
+ } ipac_rw;
+} ipac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* IPAC read registers */
+
+#define IPAC_CONF REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_conf)
+#define IPAC_ISTA REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_ista)
+#define IPAC_ID REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_id)
+#define IPAC_ACFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_acfg)
+#define IPAC_AOE REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_aoe)
+#define IPAC_ARX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_arx)
+#define IPAC_PITA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita1)
+#define IPAC_PITA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita2)
+#define IPAC_POTA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota1)
+#define IPAC_POTA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota2)
+#define IPAC_PCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pcfg)
+#define IPAC_SCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_scfg)
+#define IPAC_TIMR2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_timr2)
+
+/* IPAC write registers */
+
+#define IPAC_MASK REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_mask)
+#define IPAC_ATX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_atx)
+
+/* register bits */
+
+#define IPAC_CONF_AMP 0x80
+#define IPAC_CONF_CFS 0x40
+#define IPAC_CONF_TEM 0x20
+#define IPAC_CONF_PDS 0x10
+#define IPAC_CONF_IDH 0x08
+#define IPAC_CONF_SGO 0x04
+#define IPAC_CONF_ODS 0x02
+#define IPAC_CONF_IOF 0x01
+
+#define IPAC_ISTA_INT1 0x80
+#define IPAC_ISTA_INT0 0x40
+#define IPAC_ISTA_ICD 0x20
+#define IPAC_ISTA_EXD 0x10
+#define IPAC_ISTA_ICA 0x08
+#define IPAC_ISTA_EXA 0x04
+#define IPAC_ISTA_ICB 0x02
+#define IPAC_ISTA_EXB 0x01
+
+#define IPAC_MASK_INT1 0x80
+#define IPAC_MASK_INT0 0x40
+#define IPAC_MASK_ICD 0x20
+#define IPAC_MASK_EXD 0x10
+#define IPAC_MASK_ICA 0x08
+#define IPAC_MASK_EXA 0x04
+#define IPAC_MASK_ICB 0x02
+#define IPAC_MASK_EXB 0x01
+
+#define IPAC_ACFG_OD7 0x80
+#define IPAC_ACFG_OD6 0x40
+#define IPAC_ACFG_OD5 0x20
+#define IPAC_ACFG_OD4 0x10
+#define IPAC_ACFG_OD3 0x08
+#define IPAC_ACFG_OD2 0x04
+#define IPAC_ACFG_EL1 0x02
+#define IPAC_ACFG_EL2 0x01
+
+#define IPAC_AOE_OE7 0x80
+#define IPAC_AOE_OE6 0x40
+#define IPAC_AOE_OE5 0x20
+#define IPAC_AOE_OE4 0x10
+#define IPAC_AOE_OE3 0x08
+#define IPAC_AOE_OE2 0x04
+
+#define IPAC_ARX_AR7 0x80
+#define IPAC_ARX_AR6 0x40
+#define IPAC_ARX_AR5 0x20
+#define IPAC_ARX_AR4 0x10
+#define IPAC_ARX_AR3 0x08
+#define IPAC_ARX_AR2 0x04
+
+#define IPAC_ATX_AT7 0x80
+#define IPAC_ATX_AT6 0x40
+#define IPAC_ATX_AT5 0x20
+#define IPAC_ATX_AT4 0x10
+#define IPAC_ATX_AT3 0x08
+#define IPAC_ATX_AT2 0x04
+
+#define IPAC_PITA1_ENA 0x80
+#define IPAC_PITA1_DUDD 0x40
+
+#define IPAC_PITA2_ENA 0x80
+#define IPAC_PITA2_DUDD 0x40
+
+#define IPAC_POTA1_ENA 0x80
+#define IPAC_POTA1_DUDD 0x40
+
+#define IPAC_POTA2_ENA 0x80
+#define IPAC_POTA2_DUDD 0x40
+
+#define IPAC_PCFG_DPS 0x80
+#define IPAC_PCFG_ACL 0x40
+#define IPAC_PCFG_LED 0x20
+#define IPAC_PCFG_PLD 0x10
+#define IPAC_PCFG_FBS 0x08
+#define IPAC_PCFG_CSL2 0x04
+#define IPAC_PCFG_CSL1 0x02
+#define IPAC_PCFG_CSL0 0x01
+
+#define IPAC_SCFG_PRI 0x80
+#define IPAC_SCFG_TXD 0x40
+#define IPAC_SCFG_TLEN 0x20
+
+#define IPAC_TIMR2_TMD 0x80
+
+#endif /* _I4B_IPAC_H_ */
diff --git a/sys/i4b/layer1/i4b_isac.c b/sys/i4b/layer1/i4b_isac.c
new file mode 100644
index 000000000000..4065c9a575b9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isac.c
@@ -0,0 +1,679 @@
+/*
+ * 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_isac.c - i4b siemens isdn chipset driver ISAC handler
+ * ---------------------------------------------------------
+ *
+ * $Id: i4b_isac.c,v 1.28 1998/12/05 18:04:41 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:59 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* non-FreeBSD handles this via config(8) */
+#endif
+#if NISIC > 0
+
+#ifdef __FreeBSD__
+#include "opt_i4b.h"
+#endif
+#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/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir);
+static void isic_isac_ind_hdlr(register struct isic_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_irq(struct isic_softc *sc, int ista)
+{
+ register u_char c = 0;
+ DBGL1(L1_F_MSG, "isic_isac_irq", ("unit %d: ista = 0x%02x\n", sc->sc_unit, ista));
+
+ if(ista & ISAC_ISTA_EXI) /* extended interrupt */
+ {
+ c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
+ }
+
+ if(ista & ISAC_ISTA_RME) /* receive message end */
+ {
+ register int rest;
+ u_char rsta;
+
+ /* get rx status register */
+
+ rsta = ISAC_READ(I_RSTA);
+
+ if((rsta & ISAC_RSTA_MASK) != 0x20)
+ {
+ int error = 0;
+
+ if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: CRC error\n", sc->sc_unit));
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Data Overrun error\n", sc->sc_unit));
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Receive Aborted error\n", sc->sc_unit));
+ }
+
+ if(error == 0)
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: RME unknown error, RSTA = 0x%02x!\n", sc->sc_unit, rsta));
+
+ i4b_Dfreembuf(sc->sc_ibuf);
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
+ ISACCMDRWRDELAY();
+
+ return;
+ }
+
+ rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
+
+ if(rest == 0)
+ rest = ISAC_FIFO_LEN;
+
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
+ sc->sc_ib = sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
+ {
+ ISAC_RDFIFO(sc->sc_ib, rest);
+ sc->sc_ilen += rest;
+
+ sc->sc_ibuf->m_pkthdr.len =
+ sc->sc_ibuf->m_len = sc->sc_ilen;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled)
+ PH_Data_Ind(sc->sc_unit, sc->sc_ibuf);
+ else
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ else
+ {
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("RME, input buffer overflow!\n"));
+ i4b_Dfreembuf(sc->sc_ibuf);
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ }
+
+ if(ista & ISAC_ISTA_RPF) /* receive fifo full */
+ {
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
+ sc->sc_ib= sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
+ {
+ ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
+ sc->sc_ilen += ISAC_FIFO_LEN;
+ sc->sc_ib += ISAC_FIFO_LEN;
+ c |= ISAC_CMDR_RMC;
+ }
+ else
+ {
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("RPF, input buffer overflow!\n"));
+ i4b_Dfreembuf(sc->sc_ibuf);
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+ }
+
+ if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */
+ {
+ if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
+ {
+ sc->sc_freeflag = sc->sc_freeflag2;
+ sc->sc_obuf = sc->sc_obuf2;
+ sc->sc_op = sc->sc_obuf->m_data;
+ sc->sc_ol = sc->sc_obuf->m_len;
+ sc->sc_obuf2 = NULL;
+#ifdef NOTDEF
+ printf("ob2=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+ else
+ {
+#ifdef NOTDEF
+ printf("ob=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+
+ if(sc->sc_obuf)
+ {
+ ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
+
+ if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */
+ {
+ sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
+ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
+ c |= ISAC_CMDR_XTF; /* set XTF bit */
+ }
+ else
+ {
+ if(sc->sc_freeflag)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_freeflag = 0;
+ }
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+ }
+ else
+ {
+ sc->sc_state &= ~ISAC_TX_ACTIVE;
+ }
+ }
+
+ if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */
+ {
+ register u_char ci;
+
+ /* get command/indication rx register*/
+
+ ci = ISAC_READ(I_CIRR);
+
+ /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
+
+ if(ci & ISAC_CIRR_SQC)
+ (void) ISAC_READ(I_SQRR);
+
+ /* C/I code change IRQ (flag already cleared by CIRR read) */
+
+ if(ci & ISAC_CIRR_CIC0)
+ isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
+ }
+
+ if(c)
+ {
+ ISAC_WRITE(I_CMDR, c);
+ ISACCMDRWRDELAY();
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Extended IRQ handler
+ *---------------------------------------------------------------------------*/
+static u_char
+isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Message Repeat\n"));
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Data Underrun\n"));
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Protocol Error\n"));
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Rx Frame Overflow\n"));
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Sync Xfer Overflow\n"));
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ DBGL1(L1_I_ERR, "L1 isic_isac_exir_hdlr", ("EXIRQ Monitor Status\n"));
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Subscriber Awake\n"));
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Watchdog Timer Overflow\n"));
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+isic_isac_ind_hdlr(register struct isic_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI8 in state %s\n", isic_printstate(sc)));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI10 in state %s\n", isic_printstate(sc)));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx RSY in state %s\n", isic_printstate(sc)));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx PU in state %s\n", isic_printstate(sc)));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DR in state %s\n", isic_printstate(sc)));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DID in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_IDLE);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DIS in state %s\n", isic_printstate(sc)));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx EI in state %s\n", isic_printstate(sc)));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ARD in state %s\n", isic_printstate(sc)));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx TI in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ATI in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx SD in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ default:
+ DBGL1(L1_I_ERR, "isic_isac_ind_hdlr", ("UNKNOWN Indication 0x%x in state %s\n", ind, isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+ }
+ isic_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_l1_cmd(struct isic_softc *sc, int command)
+{
+ u_char cmd;
+
+#ifdef I4B_SMP_WORKAROUND
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+ /*
+ * patch from Wolfgang Helbig:
+ *
+ * Here is a patch that makes i4b work on an SMP:
+ * The card (TELES 16.3) didn't interrupt on an SMP machine.
+ * This is a gross workaround, but anyway it works *and* provides
+ * some information as how to finally fix this problem.
+ */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+#endif /* I4B_SMP_WORKAROUND */
+
+ if(command < 0 || command > CMD_ILL)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_l1_cmd", ("illegal cmd 0x%x in state %s\n", command, isic_printstate(sc)));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx TIM in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx RS in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR8 in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR10 in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx DIU in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+isic_isac_init(struct isic_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-1 mode\n"));
+
+ /* ADF2: Select mode IOM-1 */
+ ISAC_WRITE(I_ADF2, 0x00);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SAC - SIP port high Z
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 and B2 switched to/from SPa
+ */
+ ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);
+
+ /* SQXR: S/Q channel xmit register:
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * CFS - IOM clock/frame always active
+ * FSC1/2 - polarity of 8kHz strobe
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+ else
+ {
+ DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-2 mode\n"));
+
+ /* ADF2: Select mode IOM-2 */
+ ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
+ */
+ ISAC_WRITE(I_SPCR, 0x00);
+
+ /* SQXR: S/Q channel xmit register:
+ * IDC - IOM direction = 0 (master)
+ * CFS - Config Select = 0 (clock always active)
+ * CI1E - C/I channel 1 IRQ enable = 0
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * IOF - IOM i/f off = 0
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, 0x00);
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+
+#ifdef NOTDEF
+ /*
+ * XXX a transmitter reset causes an ISAC tx IRQ which will not
+ * be serviced at attach time under some circumstances leaving
+ * the associated IRQ line on the ISA bus active. This prevents
+ * any further interrupts to be serviced because no low -> high
+ * transition can take place anymore. (-hm)
+ */
+
+ /* command register:
+ * RRES - HDLC receiver reset
+ * XRES - transmitter reset
+ */
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
+ ISACCMDRWRDELAY();
+#endif
+
+ /* enabled interrupts:
+ * ===================
+ * RME - receive message end
+ * RPF - receive pool full
+ * XPR - transmit pool ready
+ * CISQ - CI or S/Q channel change
+ * EXI - extended interrupt
+ */
+
+ ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */
+ ISAC_MASK_TIN | /* timer irq */
+ ISAC_MASK_SIN; /* sync xfer irq */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ return(0);
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_isac.h b/sys/i4b/layer1/i4b_isac.h
new file mode 100644
index 000000000000..56a4241564fe
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isac.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_isac.h,v 1.5 1998/03/28 15:11:03 hm Exp $
+ *
+ * last edit-date: [Fri Mar 27 15:52:40 1998]
+ *
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_ISAC_H_
+#define I4B_ISAC_H_
+
+/*
+ * The ISAC databook specifies a delay of 2.5 DCL clock cycles between
+ * writes to the ISAC command register CMDR. This is the delay used to
+ * satisfy this requirement.
+ */
+
+#define I4B_ISAC_CMDRWRDELAY 30
+
+#if (I4B_ISAC_CMDRWRDELAY > 0)
+#define ISACCMDRWRDELAY() DELAY(I4B_ISAC_CMDRWRDELAY)
+#else
+#warning "I4B_ISAC_CMDRWRDELAY set to 0!"
+#define ISACCMDRWRDELAY()
+#endif
+
+enum ISAC_VERSIONS {
+ ISAC_VA, /* 2085 A1 or A2, 2086/2186 V1.1 */
+ ISAC_VB1, /* 2085 B1 */
+ ISAC_VB2, /* 2085 B2 */
+ ISAC_VB3, /* 2085 B3/V2.3 */
+ ISAC_UNKN /* unknown version */
+};
+
+#define ISAC_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the ISAC ISDN chip.
+ */
+
+typedef struct isac_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char isac_fifo [ISAC_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char isac_ista;
+ unsigned char isac_star;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_exir;
+ unsigned char isac_rbcl;
+ unsigned char isac_sapr;
+ unsigned char isac_rsta;
+ unsigned char dummy_28;
+ unsigned char isac_rhcr;
+ unsigned char isac_rbch;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cirr;
+ unsigned char isac_mor;
+ unsigned char isac_sscr;
+ unsigned char isac_sfcr;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_b1cr;
+ unsigned char isac_b2cr;
+ unsigned char isac_adf2;
+ unsigned char isac_mosr;
+ unsigned char isac_sqrr;
+ } isac_r;
+ struct {
+ unsigned char isac_mask;
+ unsigned char isac_cmdr;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_xad1;
+ unsigned char isac_xad2;
+ unsigned char isac_sap1;
+ unsigned char isac_sap2;
+ unsigned char isac_tei1;
+ unsigned char isac_tei2;
+ unsigned char dummy_2a;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cixr;
+ unsigned char isac_mox;
+ unsigned char isac_sscx;
+ unsigned char isac_sfcw;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_stcr;
+ unsigned char isac_adf1;
+ unsigned char isac_adf2;
+ unsigned char isac_mocr;
+ unsigned char isac_sqxr;
+ } isac_w;
+ } isac_rw;
+} isac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* ISAC read registers */
+
+#define i_ista isac_rw.isac_r.isac_ista
+#define I_ISTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_ista)
+#define i_star isac_rw.isac_r.isac_star
+#define I_STAR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star)
+#define i_mode isac_rw.isac_r.isac_mode
+#define I_MODE REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mode)
+#define i_timr isac_rw.isac_r.isac_timr
+#define I_TIMR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_timr)
+#define i_exir isac_rw.isac_r.isac_exir
+#define I_EXIR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_exir)
+#define i_rbcl isac_rw.isac_r.isac_rbcl
+#define I_RBCL REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbcl)
+#define i_sapr isac_rw.isac_r.isac_sapr
+#define I_SAPR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sapr)
+#define i_rsta isac_rw.isac_r.isac_rsta
+#define I_RSTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rsta)
+#define i_rhcr isac_rw.isac_r.isac_rhcr
+#define I_RHCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rhcr)
+#define i_rbch isac_rw.isac_r.isac_rbch
+#define I_RBCH REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbch)
+#define i_star2 isac_rw.isac_r.isac_star2
+#define I_STAR2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star2)
+#define i_spcr isac_rw.isac_r.isac_spcr
+#define I_SPCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_spcr)
+#define i_cirr isac_rw.isac_r.isac_cirr
+#define I_CIRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_cirr)
+#define i_mor isac_rw.isac_r.isac_mor
+#define I_MOR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mor)
+#define i_sscr isac_rw.isac_r.isac_sscr
+#define I_SSCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sscr)
+#define i_sfcr isac_rw.isac_r.isac_sfcr
+#define I_SFCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sfcr)
+#define i_c1r isac_rw.isac_r.isac_c1r
+#define I_C1R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c1r)
+#define i_c2r isac_rw.isac_r.isac_c2r
+#define I_C2R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c2r)
+#define i_b1cr isac_rw.isac_r.isac_b1cr
+#define I_B1CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b1cr)
+#define i_b2cr isac_rw.isac_r.isac_b2cr
+#define I_B2CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b2cr)
+#define i_adf2 isac_rw.isac_r.isac_adf2
+#define I_ADF2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_adf2)
+#define i_mosr isac_rw.isac_r.isac_mosr
+#define I_MOSR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mosr)
+#define i_sqrr isac_rw.isac_r.isac_sqrr
+#define I_SQRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sqrr)
+
+/* ISAC write registers - isac_mode, isac_timr, isac_star2, isac_spcr, */
+/* isac_c1r, isac_c2r, isac_adf2 see read registers */
+
+#define i_mask isac_rw.isac_w.isac_mask
+#define I_MASK REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mask)
+#define i_cmdr isac_rw.isac_w.isac_cmdr
+#define I_CMDR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cmdr)
+#define i_xad1 isac_rw.isac_w.isac_xad1
+#define I_XAD1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad1)
+#define i_xad2 isac_rw.isac_w.isac_xad2
+#define I_XAD2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad2)
+#define i_sap1 isac_rw.isac_w.isac_sap1
+#define I_SAP1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap1)
+#define i_sap2 isac_rw.isac_w.isac_sap2
+#define I_SAP2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap2)
+#define i_tei1 isac_rw.isac_w.isac_tei1
+#define i_tei2 isac_rw.isac_w.isac_tei2
+#define i_cixr isac_rw.isac_w.isac_cixr
+#define I_CIXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cixr)
+#define I_CIX0 I_CIXR
+#define i_mox isac_rw.isac_w.isac_mox
+#define I_MOX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mox)
+#define i_sscx isac_rw.isac_w.isac_sscx
+#define I_SSCX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sscx)
+#define i_sfcw isac_rw.isac_w.isac_sfcw
+#define I_SFCW REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sfcw)
+#define i_stcr isac_rw.isac_w.isac_stcr
+#define I_STCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_stcr)
+#define i_adf1 isac_rw.isac_w.isac_adf1
+#define I_ADF1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_adf1)
+#define i_mocr isac_rw.isac_w.isac_mocr
+#define I_MOCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mocr)
+#define i_sqxr isac_rw.isac_w.isac_sqxr
+#define I_SQXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sqxr)
+
+#define ISAC_ISTA_RME 0x80
+#define ISAC_ISTA_RPF 0x40
+#define ISAC_ISTA_RSC 0x20
+#define ISAC_ISTA_XPR 0x10
+#define ISAC_ISTA_TIN 0x08
+#define ISAC_ISTA_CISQ 0x04
+#define ISAC_ISTA_SIN 0x02
+#define ISAC_ISTA_EXI 0x01
+
+#define ISAC_MASK_RME 0x80
+#define ISAC_MASL_RPF 0x40
+#define ISAC_MASK_RSC 0x20
+#define ISAC_MASK_XPR 0x10
+#define ISAC_MASK_TIN 0x08
+#define ISAC_MASK_CISQ 0x04
+#define ISAC_MASK_SIN 0x02
+#define ISAC_MASK_EXI 0x01
+#define ISAC_MASK_ALL 0xff
+
+#define ISAC_STAR_XDOV 0x80
+#define ISAC_STAR_XFW 0x40
+#define ISAC_STAR_XRNR 0x20
+#define ISAC_STAR_RRNR 0x10
+#define ISAC_STAR_MBR 0x08
+#define ISAC_STAR_MAC1 0x04
+#define ISAC_STAR_BVS 0x02
+#define ISAC_STAR_MAC0 0x01
+
+#define ISAC_CMDR_RMC 0x80
+#define ISAC_CMDR_RRES 0x40
+#define ISAC_CMDR_RNR 0x20
+#define ISAC_CMDR_STI 0x10
+#define ISAC_CMDR_XTF 0x08
+#define ISAC_CMDR_XIF 0x04
+#define ISAC_CMDR_XME 0x02
+#define ISAC_CMDR_XRES 0x01
+
+#define ISAC_MODE_MDS2 0x80
+#define ISAC_MODE_MDS1 0x40
+#define ISAC_MODE_MDS0 0x20
+#define ISAC_MODE_TMD 0x10
+#define ISAC_MODE_RAC 0x08
+#define ISAC_MODE_DIM2 0x04
+#define ISAC_MODE_DIM1 0x02
+#define ISAC_MODE_DIM0 0x01
+
+#define ISAC_EXIR_XMR 0x80
+#define ISAC_EXIR_XDU 0x40
+#define ISAC_EXIR_PCE 0x20
+#define ISAC_EXIR_RFO 0x10
+#define ISAC_EXIR_SOV 0x08
+#define ISAC_EXIR_MOS 0x04
+#define ISAC_EXIR_SAW 0x02
+#define ISAC_EXIR_WOV 0x01
+
+#define ISAC_RSTA_RDA 0x80
+#define ISAC_RSTA_RDO 0x40
+#define ISAC_RSTA_CRC 0x20
+#define ISAC_RSTA_RAB 0x10
+#define ISAC_RSTA_SA1 0x08
+#define ISAC_RSTA_SA0 0x04
+#define ISAC_RSTA_CR 0x02
+#define ISAC_RSTA_TA 0x01
+
+#define ISAC_RSTA_MASK 0x70 /* the interesting bits */
+
+#define ISAC_RBCH_XAC 0x80
+#define ISAC_RBCH_VN1 0x40
+#define ISAC_RBCH_VN0 0x20
+#define ISAC_RBCH_OV 0x10
+/* the other 4 bits are the high bits of the receive byte count */
+
+#define ISAC_SPCR_SPU 0x80
+#define ISAC_SPCR_SAC 0x40
+#define ISAC_SPCR_SPM 0x20
+#define ISAC_SPCR_TLP 0x10
+#define ISAC_SPCR_C1C1 0x08
+#define ISAC_SPCR_C1C0 0x04
+#define ISAC_SPCR_C2C1 0x02
+#define ISAC_SPCR_C2C0 0x01
+
+#define ISAC_CIRR_SQC 0x80
+#define ISAC_CIRR_BAS 0x40
+/* bits 5-2 CODR */
+#define ISAC_CIRR_CIC0 0x02
+/* bit 0 is always 0 */
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the indications */
+#define ISAC_CIRR_IPU 0x07
+#define ISAC_CIRR_IDR 0x00
+#define ISAC_CIRR_ISD 0x02
+#define ISAC_CIRR_IDIS 0x03
+#define ISAC_CIRR_IEI 0x06
+#define ISAC_CIRR_IRSY 0x04
+#define ISAC_CIRR_IARD 0x08
+#define ISAC_CIRR_ITI 0x0a
+#define ISAC_CIRR_IATI 0x0b
+#define ISAC_CIRR_IAI8 0x0c
+#define ISAC_CIRR_IAI10 0x0d
+#define ISAC_CIRR_IDID 0x0f
+
+#define ISAC_CI_MASK 0x0f
+
+#define ISAC_CIXR_RSS 0x80
+#define ISAC_CIXR_BAC 0x40
+/* bits 5-2 CODX */
+#define ISAC_CIXR_TCX 0x02
+#define ISAC_CIXR_ECX 0x01
+/* in IOM-2 mode the low bits are always 1 */
+#define ISAC_CIX0_LOW 0x03
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the commands */
+#define ISAC_CIXR_CTIM 0
+#define ISAC_CIXR_CRS 0x01
+#define ISAC_CIXR_CSCZ 0x04
+#define ISAC_CIXR_CSSZ 0x02
+#define ISAC_CIXR_CAR8 0x08
+#define ISAC_CIXR_CAR10 0x09
+#define ISAC_CIXR_CARL 0x0a
+#define ISAC_CIXR_CDIU 0x0f
+
+#define ISAC_STCR_TSF 0x80
+#define ISAC_STCR_TBA2 0x40
+#define ISAC_STCR_TBA1 0x20
+#define ISAC_STCR_TBA0 0x10
+#define ISAC_STCR_ST1 0x08
+#define ISAC_STCR_ST0 0x04
+#define ISAC_STCR_SC1 0x02
+#define ISAC_STCR_SC0 0x01
+
+#define ISAC_ADF1_WTC1 0x80
+#define ISAC_ADF1_WTC2 0x40
+#define ISAC_ADF1_TEM 0x20
+#define ISAC_ADF1_PFS 0x10
+#define ISAC_ADF1_CFS 0x08
+#define ISAC_ADF1_FC2 0x04
+#define ISAC_ADF1_FC1 0x02
+#define ISAC_ADF1_ITF 0x01
+
+#define ISAC_ADF2_IMS 0x80
+/* all other bits are 0 */
+
+/* bits 7-5 are always 0 */
+#define ISAC_SQRR_SYN 0x10
+#define ISAC_SQRR_SQR1 0x08
+#define ISAC_SQRR_SQR2 0x04
+#define ISAC_SQRR_SQR3 0x02
+#define ISAC_SQRR_SQR4 0x01
+
+#define ISAC_SQXR_IDC 0x80
+#define ISAC_SQXR_CFS 0x40
+#define ISAC_SQXR_CI1E 0x20
+#define ISAC_SQXR_SQIE 0x10
+#define ISAC_SQXR_SQX1 0x08
+#define ISAC_SQXR_SQX2 0x04
+#define ISAC_SQXR_SQX3 0x02
+#define ISAC_SQXR_SQX4 0x01
+
+#endif /* I4B_ISAC_H_ */
diff --git a/sys/i4b/layer1/i4b_isic.c b/sys/i4b/layer1/i4b_isic.c
new file mode 100644
index 000000000000..922df793c07a
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic.c
@@ -0,0 +1,345 @@
+/*
+ * 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_isic.c - global isic stuff
+ * ==============================
+ *
+ * $Id: i4b_isic.c,v 1.44 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 12:14:07 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 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/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <sys/device.h>
+#if defined(__NetBSD__) && defined(amiga)
+#include <machine/bus.h>
+#else
+#include <dev/isa/isavar.h>
+#endif
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+void isic_settrace(int unit, int val);
+int isic_gettrace(int unit);
+
+#ifdef __FreeBSD__
+void isicintr_sc(struct isic_softc *sc);
+#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+void isicintr(int unit);
+#endif
+#else
+/* XXX - hack, going away soon! */
+struct isic_softc *isic_sc[ISIC_MAXUNIT];
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+void
+isicintr_sc(struct isic_softc *sc)
+{
+ isicintr(sc->sc_unit);
+}
+
+void
+isicintr(int unit)
+{
+ register struct isic_softc *sc = &isic_sc[unit];
+#else
+int
+isicintr(void *arg)
+{
+ struct isic_softc *sc = arg;
+#endif
+
+ if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */
+ {
+ u_char was_hscx_irq = 0;
+ u_char was_isac_irq = 0;
+
+ register u_char hscx_irq_stat;
+ register u_char isac_irq_stat;
+
+ for(;;)
+ {
+ /* get hscx irq status from hscx b ista */
+ hscx_irq_stat =
+ HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
+
+ /* get isac irq status */
+ isac_irq_stat = ISAC_READ(I_ISTA);
+
+ /* do as long as there are pending irqs in the chips */
+ if(!hscx_irq_stat && !isac_irq_stat)
+ break;
+
+ if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
+ HSCX_ISTA_RSC | HSCX_ISTA_XPR |
+ HSCX_ISTA_TIN | HSCX_ISTA_EXB))
+ {
+ isic_hscx_irq(sc, hscx_irq_stat,
+ HSCX_CH_B,
+ hscx_irq_stat & HSCX_ISTA_EXB);
+ was_hscx_irq = 1;
+ }
+
+ if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
+ {
+ isic_hscx_irq(sc,
+ HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
+ HSCX_CH_A,
+ hscx_irq_stat & HSCX_ISTA_EXA);
+ was_hscx_irq = 1;
+ }
+
+ if(isac_irq_stat)
+ {
+ isic_isac_irq(sc, isac_irq_stat); /* isac handler */
+ was_isac_irq = 1;
+ }
+ }
+#ifndef amiga /* XXX should be: #if INTERUPTS_ARE_SHARED */
+#ifdef ELSA_QS1ISA
+ if(sc->sc_cardtyp != CARD_TYPEP_ELSAQS1ISA)
+ {
+#endif
+ if((was_hscx_irq == 0) && (was_isac_irq == 0))
+ DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from HSCX/ISAC!\n", sc->sc_unit));
+#ifdef ELSA_QS1ISA
+ }
+#endif
+#endif /* AMIGA */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+
+#ifdef ELSA_QS1ISA
+ DELAY(80);
+
+ if(sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA)
+ if (sc->clearirq)
+ {
+ sc->clearirq(sc);
+ }
+#else
+ DELAY(100);
+#endif
+
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+#ifndef __FreeBSD__
+ return(was_hscx_irq || was_isac_irq);
+#endif
+ }
+ else /* IPAC interrupt routine */
+ {
+ register u_char ipac_irq_stat;
+ register u_char was_ipac_irq = 0;
+
+ for(;;)
+ {
+ /* get global irq status */
+
+ ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
+
+ /* check hscx a */
+
+ if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
+ {
+ /* HSCX A interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
+ HSCX_CH_A,
+ ipac_irq_stat & IPAC_ISTA_EXA);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
+ {
+ /* HSCX B interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
+ HSCX_CH_B,
+ ipac_irq_stat & IPAC_ISTA_EXB);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD))
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ was_ipac_irq = 1;
+ }
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+ }
+
+ if(was_ipac_irq == 0)
+ DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from IPAC!\n", sc->sc_unit));
+
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+
+#ifndef __FreeBSD__
+ return(was_ipac_irq);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_settrace
+ *---------------------------------------------------------------------------*/
+void
+isic_settrace(int unit, int val)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ sc->sc_trace = val;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_gettrace
+ *---------------------------------------------------------------------------*/
+int
+isic_gettrace(int unit)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ return(sc->sc_trace);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_recovery - try to recover from irq lockup
+ *---------------------------------------------------------------------------*/
+void
+isic_recover(struct isic_softc *sc)
+{
+ u_char byte;
+
+ /* get hscx irq status from hscx b ista */
+
+ byte = HSCX_READ(HSCX_CH_B, H_ISTA);
+
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: ISTA = 0x%x\n", byte));
+
+ if(byte & HSCX_ISTA_ICA)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: ISTA = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA)));
+
+ if(byte & HSCX_ISTA_EXB)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR)));
+
+ if(byte & HSCX_ISTA_EXA)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR)));
+
+ /* get isac irq status */
+
+ byte = ISAC_READ(I_ISTA);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: ISTA = 0x%x\n", byte));
+
+ if(byte & ISAC_ISTA_EXI)
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: EXIR = 0x%x\n", (u_char)ISAC_READ(I_EXIR)));
+
+ if(byte & ISAC_ISTA_CISQ)
+ {
+ byte = ISAC_READ(I_CIRR);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: CISQ = 0x%x\n", byte));
+
+ if(byte & ISAC_CIRR_SQC)
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: SQRR = 0x%x\n", (u_char)ISAC_READ(I_SQRR)));
+ }
+
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: IMASK = 0x%x\n", HSCX_B_IMASK));
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: IMASK = 0x%x\n", HSCX_A_IMASK));
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ DELAY(100);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: IMASK = 0x%x\n", ISAC_IMASK));
+
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_isic_isa.c b/sys/i4b/layer1/i4b_isic_isa.c
new file mode 100644
index 000000000000..c0e11b9a044f
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_isa.c
@@ -0,0 +1,591 @@
+/*
+ * 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_isic_isa.c - ISA bus interface
+ * ==================================
+ *
+ * $Id: i4b_isic_isa.c,v 1.14 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 12:00:26 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 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/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <sys/device.h>
+#if defined(__NetBSD__) && defined(amiga)
+#include <machine/bus.h>
+#else
+#include <dev/isa/isavar.h>
+#endif
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __FreeBSD__
+
+#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+void isicintr ( int unit );
+#endif
+
+void isicintr_sc(struct isic_softc *sc);
+
+static int isicprobe(struct isa_device *dev);
+int isicattach(struct isa_device *dev);
+
+struct isa_driver isicdriver = {
+ isicprobe,
+ isicattach,
+ "isic",
+ 0
+};
+
+int next_isic_unit = 0;
+struct isic_softc isic_sc[ISIC_MAXUNIT];
+
+#else
+
+#ifdef NetBSD1_3
+#if NetBSD1_3 < 2
+struct cfdriver isic_cd = {
+ NULL, "isic", DV_DULL
+};
+#endif
+#endif
+
+#if defined (__OpenBSD__)
+struct cfdriver isic_cd = {
+ NULL, "isic", DV_DULL
+};
+#endif
+
+#endif
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+extern void isic_settrace(int unit, int val); /*XXX*/
+extern int isic_gettrace(int unit); /*XXX*/
+
+#ifdef __FreeBSD__
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp device driver probe routine
+ *---------------------------------------------------------------------------*/
+static int
+isicprobe(struct isa_device *dev)
+{
+ int ret = 0;
+
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("isicprobe: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return(0);
+ }
+
+ switch(dev->id_flags)
+ {
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_probe_s0163(dev);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_probe_avma1(dev);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_probe_usrtai(dev);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_probe_itkix1(dev);
+ break;
+#endif
+
+ default:
+ break;
+ }
+ return(ret);
+}
+
+#else
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver probe routine, dummy for NetBSD/OpenBSD
+ *---------------------------------------------------------------------------*/
+int
+isicprobe(struct isic_attach_args *args)
+{
+ return 1;
+}
+
+#endif /* __FreeBSD__ */
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp device driver attach routine
+ *---------------------------------------------------------------------------*/
+int
+isicattach(struct isa_device *dev)
+{
+ return(isic_realattach(dev, 0));
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp and pnp device driver attach routine
+ *---------------------------------------------------------------------------*/
+int
+isic_realattach(struct isa_device *dev, unsigned int iobase2)
+
+#else /* ! __FreeBSD__ */
+
+int
+isicattach(int flags, struct isic_softc *sc)
+
+#endif /* __FreeBSD__ */
+{
+ int ret = 0;
+ char *drvid;
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#define PARM dev
+#define PARM2 dev, iobase2
+#define FLAGS dev->id_flags
+#else
+#define PARM sc
+#define PARM2 sc
+#define FLAGS flags
+#endif
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ /* done in bus specific attach code for other OS */
+
+#ifdef __FreeBSD__
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return(0);
+ }
+
+ sc->sc_unit = dev->id_unit;
+#else
+ isic_sc[sc->sc_unit] = sc;
+#endif
+
+ /* card dependent setup */
+ switch(FLAGS)
+ {
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_attach_Dyn(PARM2);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_attach_s08(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_attach_s016(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_attach_s0163(PARM);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_attach_avma1(PARM);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_attach_usrtai(PARM);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_attach_itkix1(PARM);
+ break;
+#endif
+
+/* ======================================================================
+ * Only P&P cards follow below!!!
+ */
+#ifdef __FreeBSD__ /* we've already splitted all non-ISA stuff
+ out of this ISA specific part for the other
+ OS */
+
+#ifdef AVM_PCMCIA
+ case FLAG_AVM_A1_PCMCIA:
+ ret = isic_attach_fritzpcmcia(PARM);
+ break;
+#endif
+
+#ifndef __FreeBSD__
+#ifdef TEL_S0_16_3_P
+ case FLAG_TELES_S0_163_PnP:
+ ret = isic_attach_s0163P(PARM2);
+ break;
+#endif
+#endif
+
+#ifdef CRTX_S0_P
+ case FLAG_CREATIX_S0_PnP:
+ ret = isic_attach_Cs0P(PARM2);
+ break;
+#endif
+
+#ifdef DRN_NGO
+ case FLAG_DRN_NGO:
+ ret = isic_attach_drnngo(PARM2);
+ break;
+#endif
+
+#ifdef SEDLBAUER
+ case FLAG_SWS:
+ ret = isic_attach_sws(PARM);
+ break;
+#endif
+
+#ifdef ELSA_QS1ISA
+ case FLAG_ELSA_QS1P_ISA:
+ ret = isic_attach_Eqs1pi(PARM2);
+ break;
+#endif
+
+#endif /* __FreeBSD__ / P&P specific part */
+
+/* --- XXX - don't know how to handle this - should be removed!!!! ---- */
+#ifdef amiga
+ case FLAG_BLMASTER:
+ ret = 1; /* full detection was done in caller */
+ break;
+#endif
+/* ------------------------------------------------------------------- */
+
+ default:
+ break;
+ }
+
+ if(ret == 0)
+ return(0);
+
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce manufacturer and card type */
+
+ switch(FLAGS)
+ {
+ case FLAG_TELES_S0_8:
+ drvid = "Teles S0/8 or Niccy 1008";
+ break;
+
+ case FLAG_TELES_S0_16:
+ drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
+ break;
+
+ case FLAG_TELES_S0_163:
+ drvid = "Teles S0/16.3";
+ break;
+
+ case FLAG_AVM_A1:
+ drvid = "AVM A1 or AVM Fritz!Card";
+ break;
+
+ case FLAG_AVM_A1_PCMCIA:
+ drvid = "AVM PCMCIA Fritz!Card";
+ break;
+
+ case FLAG_TELES_S0_163_PnP:
+ drvid = "Teles S0/PnP";
+ break;
+
+ case FLAG_CREATIX_S0_PnP:
+ drvid = "Creatix ISDN S0-16 P&P";
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ drvid = "USRobotics Sportster ISDN TA intern";
+ break;
+
+ case FLAG_DRN_NGO:
+ drvid = "Dr. Neuhaus NICCY Go@";
+ break;
+
+ case FLAG_DYNALINK:
+ drvid = "Dynalink IS64PH";
+ break;
+
+ case FLAG_SWS:
+ drvid = "Sedlbauer WinSpeed";
+ break;
+
+ case FLAG_BLMASTER:
+ /* board announcement was done by caller */
+ drvid = (char *)0;
+ break;
+
+ case FLAG_ELSA_QS1P_ISA:
+ drvid = "ELSA QuickStep 1000pro (ISA)";
+ break;
+
+ case FLAG_ITK_IX1:
+ drvid = "ITK ix1 micro";
+ break;
+
+ default:
+ drvid = "ERROR, unknown flag used";
+ break;
+ }
+#ifndef __FreeBSD__
+ printf("\n");
+#endif
+ if (drvid)
+ printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+#ifdef __FreeBSD__
+ printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
+#endif
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+#ifdef __FreeBSD__
+ printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);
+
+ next_isic_unit++;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003
+
+ /* set the interrupt handler - no need to change isa_device.h */
+ dev->id_intr = (inthand2_t *)isicintr;
+
+#endif
+
+#endif /* __FreeBSD__ */
+
+ return(1);
+#undef PARM
+#undef FLAGS
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_isic_pci.c b/sys/i4b/layer1/i4b_isic_pci.c
new file mode 100644
index 000000000000..3aebf08c796e
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pci.c
@@ -0,0 +1,424 @@
+/*
+ * 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_isic_pci.c - PCI bus interface
+ * ==================================
+ *
+ * $Id: i4b_isic_pci.c,v 1.9 1998/12/05 18:04:48 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:24:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if defined(__FreeBSD__)
+#include "opt_i4b.h"
+#include "pci.h"
+#endif
+
+#if (NISIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#define PCI_QS1000_ID 0x10001048
+
+#define MEM0_MAPOFF 0
+#define PORT0_MAPOFF 4
+#define PORT1_MAPOFF 12
+
+static char* i4b_pci_probe(pcici_t tag, pcidi_t type);
+static void i4b_pci_attach(pcici_t config_id, int unit);
+static int isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2);
+
+static u_long i4b_pci_count = 0;
+
+static struct pci_device i4b_pci_driver = {
+ "isic",
+ i4b_pci_probe,
+ i4b_pci_attach,
+ &i4b_pci_count,
+ NULL
+};
+
+DATA_SET (pcidevice_set, i4b_pci_driver);
+
+static void isic_pci_intr_sc(struct isic_softc *sc);
+
+
+/*---------------------------------------------------------------------------*
+ * PCI probe routine
+ *---------------------------------------------------------------------------*/
+static char *
+i4b_pci_probe(pcici_t tag, pcidi_t type)
+{
+ switch(type)
+ {
+ case PCI_QS1000_ID:
+ return("ELSA QuickStep 1000pro PCI ISDN adaptor");
+ break;
+
+ default:
+ if(bootverbose)
+ printf("i4b_pci_probe: unknown PCI type %ul!\n", (u_int)type);
+ return(NULL);
+ }
+ return(NULL);
+}
+
+/*---------------------------------------------------------------------------*
+ * PCI attach routine
+ *---------------------------------------------------------------------------*/
+static void
+i4b_pci_attach(pcici_t config_id, int unit)
+{
+ unsigned short iobase1;
+ unsigned short iobase2;
+ unsigned long type;
+ struct isic_softc *sc = &isic_sc[unit];
+
+ if(unit != next_isic_unit)
+ {
+ printf("i4b_pci_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", unit, next_isic_unit);
+ return;
+ }
+
+ if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT0_MAPOFF, &iobase1)))
+ {
+ printf("i4b_pci_attach: pci_map_port 1 failed!\n");
+ return;
+ }
+
+ if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT1_MAPOFF, &iobase2)))
+ {
+ printf("i4b_pci_attach: pci_map_port 2 failed!\n");
+ return;
+ }
+
+ if(bootverbose)
+ printf("i4b_pci_attach: unit %d, port0 0x%x, port1 0x%x\n", unit, iobase1, iobase2);
+
+ type = pci_conf_read(config_id, PCI_ID_REG);
+
+ if((isic_pciattach(unit, type, iobase1, iobase2)) == 0)
+ return;
+
+ if(!(pci_map_int(config_id, (void *)isic_pci_intr_sc, (void *)sc, &net_imask)))
+ return;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pci device driver attach routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2)
+{
+ int ret = 0;
+ struct isic_softc *sc = &isic_sc[unit];
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ switch(type)
+ {
+#ifdef ELSA_QS1PCI
+ case PCI_QS1000_ID:
+ ret = isic_attach_Eqs1pp(unit, iobase1, iobase2);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if(ret == 0)
+ return(ret);
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ sc->sc_unit = unit;
+
+ if(sc->sc_ipac)
+ {
+ ret = IPAC_READ(IPAC_ID);
+
+ switch(ret)
+ {
+ case 0x01:
+ printf("isic%d: IPAC PSB2115 Version 1.1\n", unit);
+ break;
+
+ default:
+ printf("isic%d: Error, IPAC version %d unknown!\n",
+ unit, ret);
+ return(0);
+ break;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ printf("isic%d: ISAC %s (IOM-%c)\n",
+ unit,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ break;
+
+ default:
+ printf("isic%d: Error, ISAC version %d unknown!\n",
+ unit, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ printf("isic%d: HSCX %s\n",
+ unit,
+ HSCXversion[sc->sc_hscx_version]);
+ break;
+
+ default:
+ printf("isic%d: Error, HSCX version %d unknown!\n",
+ unit, sc->sc_hscx_version);
+ return(0);
+ break;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ next_isic_unit++;
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - PCI device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+static void
+isic_pci_intr_sc(struct isic_softc *sc)
+{
+ if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */
+ {
+ register u_char hscx_irq_stat;
+ register u_char isac_irq_stat;
+
+ for(;;)
+ {
+ /* get hscx irq status from hscx b ista */
+ hscx_irq_stat =
+ HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
+
+ /* get isac irq status */
+ isac_irq_stat = ISAC_READ(I_ISTA);
+
+ /* do as long as there are pending irqs in the chips */
+ if(!hscx_irq_stat && !isac_irq_stat)
+ break;
+
+ if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
+ HSCX_ISTA_RSC | HSCX_ISTA_XPR |
+ HSCX_ISTA_TIN | HSCX_ISTA_EXB))
+ {
+ isic_hscx_irq(sc, hscx_irq_stat,
+ HSCX_CH_B,
+ hscx_irq_stat & HSCX_ISTA_EXB);
+ }
+
+ if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
+ {
+ isic_hscx_irq(sc,
+ HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
+ HSCX_CH_A,
+ hscx_irq_stat & HSCX_ISTA_EXA);
+ }
+
+ if(isac_irq_stat)
+ { /* isac handler */
+ isic_isac_irq(sc, isac_irq_stat);
+ }
+ }
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+
+ DELAY(100);
+
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ }
+ else /* IPAC interrupt routine */
+ {
+ register u_char ipac_irq_stat;
+
+ for(;;)
+ {
+ /* get global irq status */
+
+ ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+
+ /* check hscx a */
+
+ if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
+ {
+ /* HSCX A interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
+ HSCX_CH_A,
+ ipac_irq_stat & IPAC_ISTA_EXA);
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
+ {
+ /* HSCX B interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
+ HSCX_CH_B,
+ ipac_irq_stat & IPAC_ISTA_EXB);
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD))
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ }
+ }
+
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+ }
+}
+
+#endif /* (NISIC > 0) && (NPCI > 0) */
+
diff --git a/sys/i4b/layer1/i4b_isic_pcmcia.c b/sys/i4b/layer1/i4b_isic_pcmcia.c
new file mode 100644
index 000000000000..a1fb22af6206
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pcmcia.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1998 Matthias Apitz. All rights reserved.
+ *
+ * Copyright (c) 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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_isic_pcmcia.c - i4b FreeBSD PCMCIA support
+ * ----------------------------------------------
+ *
+ * $Id: i4b_isic_pcmcia.c,v 1.3 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:30:09 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "card.h"
+
+#if (NISIC > 0) && (NCARD > 0)
+
+#include "apm.h"
+#include <sys/param.h>
+#include <sys/select.h>
+#include <i386/isa/isa_device.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/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <pccard/cardinfo.h>
+#include <pccard/slot.h>
+#include <pccard/driver.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+/*
+ * PC-Card (PCMCIA) specific code.
+ */
+static int isic_pccard_init __P((struct pccard_devinfo *));
+static void isic_unload __P((struct pccard_devinfo *));
+static int isic_card_intr __P((struct pccard_devinfo *));
+
+static struct pccard_device isic_info = {
+ "isic",
+ isic_pccard_init,
+ isic_unload,
+ isic_card_intr,
+ 0, /* Attributes - presently unused */
+ &net_imask
+};
+
+DATA_SET(pccarddrv_set, isic_info);
+
+/*
+ * Initialize the device - called from Slot manager.
+ */
+
+static int opened = 0; /* our cards status */
+
+static int isic_pccard_init(devi)
+struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ struct isic_softc *sc = &isic_sc[is->id_unit];
+
+ if ((1 << is->id_unit) & opened)
+ return(EBUSY);
+
+ opened |= 1 << is->id_unit;
+ printf("isic%d: PCMCIA init, irqmask = 0x%x (%d), iobase = 0x%x\n",
+ is->id_unit, is->id_irq, devi->slt->irq, is->id_iobase);
+
+#if 0
+ /* XXX: problems resolving isic_probe_avma1_pcmcia() /phk */
+ /*
+ * look if there is really an AVM PCMCIA Fritz!Card and
+ * setup the card specific stuff
+ */
+ isic_probe_avma1_pcmcia(is);
+#endif
+
+ /* ap:
+ * XXX what's to do with the return value?
+ */
+
+ /*
+ * try to attach the PCMCIA card as a normal A1 card
+ */
+ isicattach(is);
+ return(0);
+}
+
+static void isic_unload(devi)
+struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ printf("isic%d: unloaded\n", is->id_unit);
+ opened &= ~(1 << is->id_unit);
+}
+
+/*
+ * card_intr - Shared interrupt called from
+ * front end of PC-Card handler.
+ */
+static int isic_card_intr(devi)
+struct pccard_devinfo *devi;
+{
+ isicintr(devi->isahd.id_unit);
+ return(1);
+}
+
+#endif /* (NISIC > 0) && (NCARD > 0) */
+#endif /* __FreeBSD__ */
diff --git a/sys/i4b/layer1/i4b_isic_pnp.c b/sys/i4b/layer1/i4b_isic_pnp.c
new file mode 100644
index 000000000000..ed1892d9088f
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pnp.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 1998 Eivind Eklund. All rights reserved.
+ *
+ * Copyright (c) 1998 German Tischler. All rights reserved.
+ *
+ * Copyright (c) 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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_isic_pnp.c - i4b pnp support
+ * --------------------------------
+ *
+ * $Id: i4b_isic_pnp.c,v 1.15 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 20:54:56 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "pnp.h"
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && (NPNP > 0)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+#include "ioconf.h"
+extern void isicintr(int unit); /* XXX this gives a compiler warning */
+ /* on one 2.2.7 machine but no */
+ /* warning on another one !? (-hm) */
+#endif
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+extern void isicintr(int unit);
+#endif
+
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+
+#include <i4b/include/i4b_global.h>
+#include <machine/i4b_ioctl.h>
+#include <i4b/layer1/i4b_l1.h>
+
+#define VID_TEL163PNP 0x10212750 /* Teles 16.3 PnP */
+#define VID_CREATIXPP 0x0000980e /* Creatix S0/16 P+P */
+#define VID_DYNALINK 0x88167506 /* Dynalink */
+#define VID_SEDLBAUER 0x0100274c /* Sedlbauer WinSpeed */
+#define VID_NICCYGO 0x5001814c /* Neuhaus Niccy GO@ */
+#define VID_ELSAQS1P 0x33019315 /* ELSA Quickstep1000pro*/
+
+static struct i4b_pnp_ids {
+ u_long vend_id;
+ char *id_str;
+} i4b_pnp_ids[] = {
+ { VID_TEL163PNP, "Teles 16.3 PnP" },
+ { VID_CREATIXPP, "Creatix S0/16 P+P" },
+ { VID_DYNALINK, "Dynalink IS64PH" },
+ { VID_SEDLBAUER, "Sedlbauer WinSpeed" },
+ { VID_NICCYGO, "Dr.Neuhaus Niccy Go@" },
+ { VID_ELSAQS1P, "ELSA QuickStep 1000pro"},
+ { 0 }
+};
+
+extern struct isa_driver isicdriver;
+
+static int isic_pnpprobe(struct isa_device *dev, unsigned int iobase2);
+static char *i4b_pnp_probe(u_long csn, u_long vend_id);
+static void i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev);
+
+static u_long ni4b_pnp = 0;
+
+static struct pnp_device i4b_pnp = {
+ "i4b_pnp",
+ i4b_pnp_probe,
+ i4b_pnp_attach,
+ &ni4b_pnp,
+ &net_imask
+};
+
+DATA_SET(pnpdevice_set, i4b_pnp);
+
+/*---------------------------------------------------------------------------*
+ * PnP probe routine
+ *---------------------------------------------------------------------------*/
+static char *
+i4b_pnp_probe(u_long csn, u_long vend_id)
+{
+ struct i4b_pnp_ids *ids;
+ char *string = NULL;
+
+ /* search table of knowd id's */
+
+ for(ids = i4b_pnp_ids; ids->vend_id != 0; ids++)
+ {
+ if(vend_id == ids->vend_id)
+ {
+ string = ids->id_str;
+ break;
+ }
+ }
+
+ if(string)
+ {
+ struct pnp_cinfo spci;
+
+ read_pnp_parms(&spci, 0);
+
+ if((spci.enable == 0) || (spci.flags & 0x01))
+ {
+ printf("CSN %d (%s) is disabled.\n", (int)csn, string);
+ return (NULL);
+ }
+ }
+ return(string);
+}
+
+/*---------------------------------------------------------------------------*
+ * PnP attach routine
+ *---------------------------------------------------------------------------*/
+static void
+i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
+{
+ struct pnp_cinfo spci;
+ struct isa_device *isa_devp;
+
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("i4b_pnp_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return;
+ }
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n",
+ dev->id_unit, dev->id_unit, name);
+ return;
+ }
+
+ if(read_pnp_parms(&spci, 0) == 0)
+ {
+ printf("isic%d: read_pnp_parms error for %s\n",
+ dev->id_unit, name);
+ return;
+ }
+
+ if(bootverbose)
+ {
+ printf("isic%d: vendorid = 0x%08x port0 = 0x%04x, port1 = 0x%04x, irq = %d\n",
+ dev->id_unit, spci.vendor_id, spci.port[0], spci.port[1], spci.irq[0]);
+ }
+
+ dev->id_iobase = spci.port[0];
+ dev->id_irq = (1 << spci.irq[0]);
+ dev->id_intr = (inthand2_t *) isicintr;
+ dev->id_drq = -1;
+
+/* XXX add dev->id_alive init here ! ?? */
+
+ switch(spci.vendor_id)
+ {
+ case VID_TEL163PNP:
+ dev->id_flags = FLAG_TELES_S0_163_PnP;
+ break;
+ case VID_CREATIXPP:
+ dev->id_flags = FLAG_CREATIX_S0_PnP;
+ break;
+ case VID_DYNALINK:
+ dev->id_flags = FLAG_DYNALINK;
+ break;
+ case VID_SEDLBAUER:
+ dev->id_flags = FLAG_SWS;
+ break;
+ case VID_NICCYGO:
+ dev->id_flags = FLAG_DRN_NGO;
+ break;
+ case VID_ELSAQS1P:
+ dev->id_flags = FLAG_ELSA_QS1P_ISA;
+ break;
+ }
+
+ write_pnp_parms(&spci, 0);
+ enable_pnp_card();
+
+ if(dev->id_driver == NULL)
+ {
+ dev->id_driver = &isicdriver;
+
+ isa_devp = find_isadev(isa_devtab_net, &isicdriver, 0);
+
+ if(isa_devp != NULL)
+ {
+ dev->id_id = isa_devp->id_id;
+ }
+ }
+
+ if((dev->id_alive = isic_pnpprobe(dev, spci.port[1])) != 0)
+ {
+/* XXX dev->id_alive is the size of the port area used ! */
+ isic_realattach(dev, spci.port[1]);
+ }
+ else
+ {
+ printf("isic%d: probe failed!\n", dev->id_unit);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pnp device driver probe routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pnpprobe(struct isa_device *dev, unsigned int iobase2)
+{
+ int ret = 0;
+
+ switch(dev->id_flags)
+ {
+#ifndef __FreeBSD__
+#ifdef TEL_S0_16_3_P
+ case FLAG_TELES_S0_163_PnP:
+ ret = isic_probe_s0163P(dev, iobase2);
+ break;
+#endif
+#endif
+
+#ifdef CRTX_S0_P
+ case FLAG_CREATIX_S0_PnP:
+ ret = isic_probe_Cs0P(dev, iobase2);
+ break;
+#endif
+
+#ifdef DRN_NGO
+ case FLAG_DRN_NGO:
+ ret = isic_probe_drnngo(dev, iobase2);
+ break;
+#endif
+
+#ifdef SEDLBAUER
+ case FLAG_SWS:
+ ret = 8; /* pnp only, nothing to probe */
+ break;
+#endif
+
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_probe_Dyn(dev, iobase2);
+ break;
+#endif
+
+#ifdef ELSA_QS1ISA
+ case FLAG_ELSA_QS1P_ISA:
+ ret = isic_probe_Eqs1pi(dev, iobase2);
+ break;
+#endif
+ default:
+ break;
+ }
+ return(ret);
+}
+
+#endif /* (NISIC > 0) && (NPNP > 0) */
+#endif /* __FreeBSD__ */
diff --git a/sys/i4b/layer1/i4b_itk_ix1.c b/sys/i4b/layer1/i4b_itk_ix1.c
new file mode 100644
index 000000000000..f7491cd0b62a
--- /dev/null
+++ b/sys/i4b/layer1/i4b_itk_ix1.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 1998 Martin Husemann <martin@rumolt.teuto.de>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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_itk_ix1.c - ITK ix1 micro passive card driver for isdn4bsd
+ * --------------------------------------------------------------
+ *
+ * $Id: i4b_itk_ix1.c,v 1.1 1998/12/16 13:43:20 hm Exp $
+ *
+ * last edit-date: [Wed Dec 16 14:46:36 1998]
+ *
+ *---------------------------------------------------------------------------
+ *
+ * The ITK ix1 micro ISDN card is an ISA card with one region
+ * of four io ports mapped and a fixed irq all jumpered on the card.
+ * Access to the board is straight forward and simmilar to
+ * the ELSA and DYNALINK cards. If a PCI version of this card
+ * exists all we need is probably a pci-bus attachment, all
+ * this low level routines should work imediately.
+ *
+ * To reset the card:
+ * - write 0x01 to ITK_CONFIG
+ * - wait >= 10 ms
+ * - write 0x00 to ITK_CONFIG
+ *
+ * To read or write data:
+ * - write address to ITK_ALE port
+ * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port
+ * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40).
+ *
+ * XXX - A reasonable probe routine has to be written.
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(ITKIX1)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+
+#define ITK_ISAC_DATA 0
+#define ITK_HSCX_DATA 1
+#define ITK_ALE 2
+#define ITK_CONFIG 3
+#define ITK_IO_SIZE 4
+
+#define HSCXA 0
+#define HSCXB 0x40
+
+#ifndef __FreeBSD__
+static void itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
+static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
+static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
+#else
+static u_char itkix1_read_reg(u_char *base, u_int offset);
+static void itkix1_write_reg(u_char *base, u_int offset, u_int v);
+static void itkix1_read_fifo(void *base, const void *buf, size_t len);
+static void itkix1_write_fifo(void *base, const void *buf, size_t len);
+#endif
+
+/*
+ * Probe for card
+ */
+#ifdef __FreeBSD__
+int
+isic_probe_itkix1(struct isa_device *dev)
+{
+ u_int8_t hd, cd;
+ int ret;
+
+ hd = inb(dev->id_iobase + ITK_HSCX_DATA);
+ cd = inb(dev->id_iobase + ITK_CONFIG);
+
+ ret = (hd == 0 && cd == 0xfc);
+
+#define ITK_PROBE_DEBUG
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n",
+ hd, cd, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#else
+int
+isic_probe_itkix1(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t hd, cd;
+ int ret;
+
+ hd = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ cd = bus_space_read_1(t, h, ITK_CONFIG);
+
+ ret = (hd == 0 && cd == 0xfc);
+
+#define ITK_PROBE_DEBUG
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n",
+ hd, cd, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#endif
+
+/*
+ * Attach card
+ */
+#ifdef __FreeBSD__
+int
+isic_attach_itkix1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ sc->sc_irq = dev->id_irq;
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 2;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ outb((dev->id_iobase)+ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+int isic_attach_itkix1(struct isic_softc *sc)
+{
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for ITK ix1 micro\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return 0;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return 1;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_read_fifo(void *buf, const void *base, size_t len)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ insb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void
+itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_fifo(void *base, const void *buf, size_t len)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ outsb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_write_multi_1(t, h, ITK_ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ outb(port+ITK_ISAC_DATA, (u_char)v);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ }
+}
+#else
+static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ bus_space_write_1(t, h, ITK_ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static u_char
+itkix1_read_reg(u_char *base, u_int offset)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ return (inb(port+ITK_ISAC_DATA));
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ }
+}
+#else
+static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ return bus_space_read_1(t, h, ITK_ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#endif /* ITKIX1 */
diff --git a/sys/i4b/layer1/i4b_l1.c b/sys/i4b/layer1/i4b_l1.c
new file mode 100644
index 000000000000..96497c5df6a4
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1.c
@@ -0,0 +1,315 @@
+/*
+ * 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_l1.c - isdn4bsd layer 1 handler
+ * -----------------------------------
+ *
+ * $Id: i4b_l1.c,v 1.27 1998/12/05 18:04:51 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:24:52 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* don't bother */
+#endif
+#if NISIC > 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 <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
+
+static int ph_data_req(int, struct mbuf *, int);
+static int ph_activate_req(int);
+
+/* from i4btrc driver i4b_trace.c */
+extern int get_trace_data_from_l1(int unit, int what, int len, char *buf);
+
+/* from layer 2 */
+extern int i4b_ph_data_ind(int unit, struct mbuf *m);
+extern int i4b_ph_activate_ind(int unit);
+extern int i4b_ph_deactivate_ind(int unit);
+extern int i4b_mph_attach_ind(int unit);
+extern int i4b_mph_status_ind(int, int, int);
+
+/* layer 1 lme */
+static int i4b_mph_command_req(int, int, int);
+
+/* jump table */
+struct i4b_l1l2_func i4b_l1l2_func = {
+
+ /* Layer 1 --> Layer 2 */
+
+ (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
+ (int (*)(int)) i4b_ph_activate_ind,
+ (int (*)(int)) i4b_ph_deactivate_ind,
+
+ /* Layer 2 --> Layer 1 */
+
+ (int (*)(int, struct mbuf *, int)) ph_data_req,
+ (int (*)(int)) ph_activate_req,
+
+ /* Layer 1 --> upstream, ISDN trace data */
+
+ (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
+
+ /* Driver control and status information */
+
+ (int (*)(int, int, int)) i4b_mph_status_ind,
+ (int (*)(int, int, int)) i4b_mph_command_req,
+};
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-DATA-REQUEST
+ * =========================
+ *
+ * parms:
+ * unit physical interface unit number
+ * m mbuf containing L2 frame to be sent out
+ * freeflag MBUF_FREE: free mbuf here after having sent
+ * it out
+ * MBUF_DONTFREE: mbuf is freed by Layer 2
+ * returns:
+ * ==0 fail, nothing sent out
+ * !=0 ok, frame sent out
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+#ifdef NOTDEF
+ DBGL1(L1_PRIM, "PH-DATA-REQ", ("unit %d, freeflag=%d\n", unit, freeflag));
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ DBGL1(L1_I_ERR, "ph_data_req", ("still in state F3!\n"));
+ ph_activate_req(unit);
+ }
+
+ if(sc->sc_state & ISAC_TX_ACTIVE)
+ {
+ if(sc->sc_obuf2 == NULL)
+ {
+ sc->sc_obuf2 = m; /* save mbuf ptr */
+
+ if(freeflag)
+ sc->sc_freeflag2 = 1; /* IRQ must mfree */
+ else
+ sc->sc_freeflag2 = 0; /* IRQ must not mfree */
+
+ DBGL1(L1_I_MSG, "ph_data_req", ("using 2nd ISAC TX buffer, state = %s\n", isic_printstate(sc)));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ DBGL1(L1_I_ERR, "ph_data_req", ("No Space in TX FIFO, state = %s\n", isic_printstate(sc)));
+
+ if(freeflag == MBUF_FREE)
+ i4b_Dfreembuf(m);
+
+ splx(s);
+ return (0);
+ }
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ DBGL1(L1_I_MSG, "ph_data_req", ("ISAC_TX_ACTIVE set\n"));
+
+ sc->sc_freeflag = 0; /* IRQ must NOT mfree */
+
+ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */
+
+ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */
+ {
+ sc->sc_obuf = m; /* save mbuf ptr */
+ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */
+ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */
+
+ if(freeflag)
+ sc->sc_freeflag = 1; /* IRQ must mfree */
+
+ cmd = ISAC_CMDR_XTF;
+ }
+ else
+ {
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ if(freeflag)
+ i4b_Dfreembuf(m);
+
+ cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+
+ ISAC_WRITE(I_CMDR, cmd);
+ ISACCMDRWRDELAY();
+
+ splx(s);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-ACTIVATE-REQUEST
+ * =============================
+ *
+ * parms:
+ * unit physical interface unit number
+ *
+ * returns:
+ * ==0
+ * !=0
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_activate_req(int unit)
+{
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ DBGL1(L1_PRIM, "PH-ACTIVATE-REQ", ("unit %d\n", unit));
+ isic_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+static int
+i4b_mph_command_req(int unit, int command, int parm)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DOPEN\n", unit));
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DCLOSE\n", unit));
+ sc->sc_enabled = 0;
+ break;
+
+ default:
+ DBGL1(L1_ERROR, "i4b_mph_command_req", ("ERROR, unknown command = %d, unit = %d, parm = %d\n", command, unit, parm));
+ break;
+ }
+
+ return(0);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_l1.h b/sys/i4b/layer1/i4b_l1.h
new file mode 100644
index 000000000000..2b15ccc92983
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1.h
@@ -0,0 +1,438 @@
+/*
+ * 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_l1.h - isdn4bsd layer 1 header file
+ * ---------------------------------------
+ *
+ * $Id: i4b_l1.h,v 1.54 1998/12/17 04:55:39 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:41:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef I4B_L1_H_
+#define I4B_L1_H_
+
+#include <i4b/include/i4b_l3l4.h>
+
+/*---------------------------------------------------------------------------
+ * kernel config file flags definition
+ *---------------------------------------------------------------------------*/
+ /* XXX: we do need these only for real ISA (not even ISAPNP cards), and only
+ * because we are not confident enough in the general ISA probe routine (as
+ * practiced by the NetBSD variant). *And* it is completely redundant to the
+ * various options enabling only a few card's support routines to be compiled
+ * in. Probably the current truth is: this is usefull for anybody with more
+ * than one supported real ISA card. It is not usefull in generic configs,
+ * nor in typical one-controller-only configurations.
+ * Further - it is identical to the CARD_TYPEP_xxx definitions in
+ * ../machine/i4b_ioctl.h.
+ */
+#define FLAG_TELES_S0_8 1
+#define FLAG_TELES_S0_16 2
+#define FLAG_TELES_S0_163 3
+#define FLAG_AVM_A1 4
+#define FLAG_TELES_S0_163_PnP 5 /* XXX - not needed, remove! */
+#define FLAG_CREATIX_S0_PnP 6 /* XXX - not needed, remove! */
+#define FLAG_USR_ISDN_TA_INT 7
+#define FLAG_DRN_NGO 8 /* XXX - not needed, remove! */
+#define FLAG_SWS 9 /* XXX - not needed, remove! */
+#define FLAG_AVM_A1_PCMCIA 10 /* XXX - not needed, remove! */
+#define FLAG_DYNALINK 11 /* XXX - not needed, remove! */
+#define FLAG_BLMASTER 12
+#define FLAG_ELSA_QS1P_ISA 13 /* XXX - not needed, remove! */
+#define FLAG_ELSA_QS1P_PCI 14 /* XXX - not needed, remove! */
+#define FLAG_SIEMENS_ITALK 15
+#define FLAG_ELSA_MLIMC 16 /* XXX - not needed, remove! */
+#define FLAG_ELSA_MLMCALL 17 /* XXX - not needed, remove! */
+#define FLAG_ITK_IX1 18
+
+#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/
+
+#define MAX_DFRAME_LEN 264 /* max length of a D frame */
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+#ifndef __FreeBSD__
+/* We try to map as few as possible as small as possible io and/or
+ memory regions. Each card defines its own interpretation of this
+ mapping array. At probe time we have a fixed size array, later
+ (when the card type is known) we allocate a minimal array
+ dynamically. */
+
+#define ISIC_MAX_IO_MAPS 49 /* no cardtype needs more yet */
+
+/* one entry in mapping array */
+struct isic_io_map {
+ bus_space_tag_t t; /* which bus-space is this? */
+ bus_space_handle_t h; /* handle of mapped bus space region */
+ bus_size_t offset; /* offset into region */
+ bus_size_t size; /* size of region, zero if not ours
+ (i.e.: don't ever unmap it!) */
+};
+
+/* this is passed around at probe time (no struct isic_softc yet) */
+struct isic_attach_args {
+ int ia_flags; /* flags from config file */
+ int ia_num_mappings; /* number of io mappings provided */
+ struct isic_io_map ia_maps[ISIC_MAX_IO_MAPS];
+};
+#endif
+
+#ifdef __FreeBSD__
+extern int next_isic_unit;
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_Bchan: the state of one B channel
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ int unit; /* cards unit number */
+ int channel; /* which channel is this*/
+
+#ifdef __FreeBSD__
+ caddr_t hscx; /* HSCX address */
+#endif
+
+ u_char hscx_mask; /* HSCX interrupt mask */
+
+ int bprot; /* B channel protocol */
+
+ int state; /* this channels state */
+#define HSCX_IDLE 0x00 /* channel idle */
+#define HSCX_TX_ACTIVE 0x01 /* tx running */
+
+ /* receive data from ISDN */
+
+ struct ifqueue rx_queue; /* receiver queue */
+
+ int rxcount; /* rx statistics counter*/
+
+ struct mbuf *in_mbuf; /* rx input buffer */
+ u_char *in_cbptr; /* curr buffer pointer */
+ int in_len; /* rx input buffer len */
+
+ /* transmit data to ISDN */
+
+ struct ifqueue tx_queue; /* transmitter queue */
+
+ int txcount; /* tx statistics counter*/
+
+ struct mbuf *out_mbuf_head; /* first mbuf in possible chain */
+ struct mbuf *out_mbuf_cur; /* current mbuf in possbl chain */
+ unsigned char *out_mbuf_cur_ptr; /* data pointer into mbuf */
+ int out_mbuf_cur_len; /* remaining bytes in mbuf */
+
+ /* link between b channel and driver */
+
+ isdn_link_t isdn_linktab; /* b channel addresses */
+ drvr_link_t *drvr_linktab; /* ptr to driver linktab*/
+
+ /* statistics */
+
+ /* RSTA */
+
+ int stat_VFR; /* HSCX RSTA Valid FRame */
+ int stat_RDO; /* HSCX RSTA Rx Data Overflow */
+ int stat_CRC; /* HSCX RSTA CRC */
+ int stat_RAB; /* HSCX RSTA Rx message ABorted */
+
+ /* EXIR */
+
+ int stat_XDU; /* HSCX EXIR tx data underrun */
+ int stat_RFO; /* HSCX EXIR rx frame overflow */
+
+} isic_Bchan_t;
+
+/*---------------------------------------------------------------------------*
+ * isic_softc: the state of the layer 1 of the D channel
+ *---------------------------------------------------------------------------*/
+struct isic_softc
+{
+#ifndef __FreeBSD__
+ /* We are inherited from this class. All drivers must have this
+ as their first entry in struct softc. */
+ struct device sc_dev;
+#endif
+
+ int sc_unit; /* unit number */
+ int sc_irq; /* interrupt vector */
+
+#ifdef __FreeBSD__
+ int sc_port; /* port base address */
+#else
+ u_int sc_maddr; /* "memory address" for card config register */
+ int sc_num_mappings; /* number of io mappings provided */
+ struct isic_io_map *sc_maps;
+#define MALLOC_MAPS(sc) \
+ (sc)->sc_maps = (struct isic_io_map*)malloc(sizeof((sc)->sc_maps[0])*(sc)->sc_num_mappings, M_DEVBUF, 0)
+#endif
+
+ int sc_cardtyp; /* CARD_TYPEP_xxxx */
+
+ int sc_bustyp; /* IOM1 or IOM2 */
+#define BUS_TYPE_IOM1 0x01
+#define BUS_TYPE_IOM2 0x02
+
+ int sc_trace; /* output protocol data for tracing */
+ unsigned int sc_trace_dcount;/* d channel trace frame counter */
+ unsigned int sc_trace_bcount;/* b channel trace frame counter */
+
+ int sc_state; /* ISAC state flag */
+#define ISAC_IDLE 0x00 /* state = idle */
+#define ISAC_TX_ACTIVE 0x01 /* state = transmitter active */
+
+ int sc_init_tries; /* no of out tries to access S0 */
+
+#ifdef __FreeBSD__
+ caddr_t sc_vmem_addr; /* card RAM virtual memory base */
+ caddr_t sc_isac; /* ISAC port base addr */
+#define ISAC_BASE (sc->sc_isac)
+
+ caddr_t sc_ipacbase; /* IPAC port base addr */
+#define IPAC_BASE (sc->sc_ipacbase)
+#endif
+
+ u_char sc_isac_mask; /* ISAC IRQ mask */
+#define ISAC_IMASK (sc->sc_isac_mask)
+
+ isic_Bchan_t sc_chan[2]; /* B-channel state */
+#define HSCX_A_BASE (sc->sc_chan[0].hscx)
+#define HSCX_A_IMASK (sc->sc_chan[0].hscx_mask)
+#define HSCX_B_BASE (sc->sc_chan[1].hscx)
+#define HSCX_B_IMASK (sc->sc_chan[1].hscx_mask)
+
+ struct mbuf *sc_ibuf; /* input buffer mgmt */
+ u_short sc_ilen;
+ u_char *sc_ib;
+ /* this is for the irq TX routine */
+ struct mbuf *sc_obuf; /* pointer to an mbuf with TX frame */
+ u_char *sc_op; /* ptr to next chunk of frame to tx */
+ int sc_ol; /* length of remaining frame to tx */
+ int sc_freeflag; /* m_freem mbuf if set */
+
+ struct mbuf *sc_obuf2; /* pointer to an mbuf with TX frame */
+ int sc_freeflag2; /* m_freem mbuf if set */
+
+ int sc_isac_version; /* version number of ISAC */
+ int sc_hscx_version; /* version number of HSCX */
+
+ int sc_I430state; /* I.430 state F3 .... F8 */
+
+ int sc_I430T3; /* I.430 Timer T3 running */
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ struct callout_handle sc_T3_callout;
+#endif
+
+ int sc_I430T4; /* Timer T4 running */
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ struct callout_handle sc_T4_callout;
+#endif
+
+ int sc_enabled; /* daemon is running */
+
+ int sc_ipac; /* flag, running on ipac */
+ int sc_bfifolen; /* length of b channel fifos */
+
+#ifdef __FreeBSD__
+
+ u_char (*readreg)(u_char *, u_int);
+ void (*writereg)(u_char *, u_int, u_int);
+ void (*readfifo)(void *, const void *, size_t);
+ void (*writefifo)(void *, const void *, size_t);
+ void (*clearirq)(void *);
+
+#define ISAC_READ(r) (*sc->readreg)(ISAC_BASE, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(ISAC_BASE, (r), (v));
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)((b), ISAC_BASE, (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(ISAC_BASE, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc->sc_chan[(n)].hscx, (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc->sc_chan[(n)].hscx, (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)((b), sc->sc_chan[(n)].hscx, (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc->sc_chan[(n)].hscx, (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(IPAC_BASE, (r))
+#define IPAC_WRITE(r,v) (*sc->writereg)(IPAC_BASE, (r), (v));
+
+#else /* ! __FreeBSD__ */
+
+#define ISIC_WHAT_ISAC 0
+#define ISIC_WHAT_HSCXA 1
+#define ISIC_WHAT_HSCXB 2
+#define ISIC_WHAT_IPAC 3
+
+ u_int8_t (*readreg) __P((struct isic_softc *sc, int what, bus_size_t offs));
+ void (*writereg) __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+ void (*readfifo) __P((struct isic_softc *sc, int what, void *buf, size_t size));
+ void (*writefifo) __P((struct isic_softc *sc, int what, const void *data, size_t size));
+ void (*clearirq) __P((struct isic_softc *sc));
+
+#define ISAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_ISAC, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(sc, ISIC_WHAT_ISAC, (r), (v))
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc, ISIC_WHAT_HSCXA+(n), (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc, ISIC_WHAT_HSCXA+(n), (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_IPAC, (r))
+#define IPAC_WRITE(r, v) (*sc->writereg)(sc, ISIC_WHAT_IPAC, (r), (v))
+
+#endif /* __FreeBSD__ */
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC states
+ *---------------------------------------------------------------------------*/
+enum I430states {
+ ST_F3, /* F3 Deactivated */
+ ST_F4, /* F4 Awaiting Signal */
+ ST_F5, /* F5 Identifying Input */
+ ST_F6, /* F6 Synchronized */
+ ST_F7, /* F7 Activated */
+ ST_F8, /* F8 Lost Framing */
+ ST_ILL, /* Illegal State */
+ N_STATES
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC events
+ *---------------------------------------------------------------------------*/
+enum I430events {
+ EV_PHAR, /* PH ACTIVATE REQUEST */
+ EV_T3, /* Timer 3 expired */
+ EV_INFO0, /* receiving INFO0 */
+ EV_RSY, /* receiving any signal */
+ EV_INFO2, /* receiving INFO2 */
+ EV_INFO48, /* receiving INFO4 pri 8/9 */
+ EV_INFO410, /* receiving INFO4 pri 10/11 */
+ EV_DR, /* Deactivate Request */
+ EV_PU, /* Power UP */
+ EV_DIS, /* Disconnected (only 2085) */
+ EV_EI, /* Error Indication */
+ EV_ILL, /* Illegal Event */
+ N_EVENTS
+};
+
+enum I430commands {
+ CMD_TIM, /* Timing */
+ CMD_RS, /* Reset */
+ CMD_AR8, /* Activation request pri 8 */
+ CMD_AR10, /* Activation request pri 10 */
+ CMD_DIU, /* Deactivate Indication Upstream */
+ CMD_ILL /* Illegal command */
+};
+
+#define N_COMMANDS CMD_ILL
+
+#ifdef __FreeBSD__
+
+extern struct isic_softc isic_sc[];
+
+extern void isic_recover(struct isic_softc *sc);
+extern int isic_realattach(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_avma1 ( struct isa_device *dev );
+extern int isic_attach_fritzpcmcia ( struct isa_device *dev );
+extern int isic_attach_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_s016 ( struct isa_device *dev );
+extern int isic_attach_s0163 ( struct isa_device *dev );
+extern int isic_attach_s0163P ( struct isa_device *dev );
+extern int isic_attach_s08 ( struct isa_device *dev );
+extern int isic_attach_usrtai ( struct isa_device *dev );
+extern int isic_attach_itkix1 ( struct isa_device *dev );
+extern int isic_attach_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_sws ( struct isa_device *dev );
+extern int isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2);
+extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate );
+extern void isic_hscx_init ( struct isic_softc *sc, int hscx_channel, int activate );
+extern void isic_hscx_irq ( struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq );
+extern int isic_hscx_silence ( unsigned char *data, int len );
+extern void isic_hscx_cmd( struct isic_softc *sc, int h_chan, unsigned char cmd );
+extern void isic_hscx_waitxfw( struct isic_softc *sc, int h_chan );
+extern void isic_init_linktab ( struct isic_softc *sc );
+extern int isic_isac_init ( struct isic_softc *sc );
+extern void isic_isac_irq ( struct isic_softc *sc, int r );
+extern void isic_isac_l1_cmd ( struct isic_softc *sc, int command );
+extern void isic_next_state ( struct isic_softc *sc, int event );
+extern char *isic_printstate ( struct isic_softc *sc );
+extern int isic_probe_avma1 ( struct isa_device *dev );
+extern int isic_probe_avma1_pcmcia ( struct isa_device *dev );
+extern int isic_probe_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_s016 ( struct isa_device *dev );
+extern int isic_probe_s0163 ( struct isa_device *dev );
+extern int isic_probe_s0163P ( struct isa_device *dev );
+extern int isic_probe_s08 ( struct isa_device *dev );
+extern int isic_probe_usrtai ( struct isa_device *dev );
+extern int isic_probe_itkix1 ( struct isa_device *dev );
+extern int isic_probe_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_sws ( struct isa_device *dev );
+extern int isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+
+#else /* not FreeBSD */
+
+extern void isic_recover __P((struct isic_softc *sc));
+extern int isicattach __P((int flags, struct isic_softc *sc));
+extern int isicintr __P((void *));
+extern int isicprobe __P((struct isic_attach_args *ia));
+extern int isic_attach_avma1 __P((struct isic_softc *sc));
+extern int isic_attach_s016 __P((struct isic_softc *sc));
+extern int isic_attach_s0163 __P((struct isic_softc *sc));
+extern int isic_attach_s08 __P((struct isic_softc *sc));
+extern int isic_attach_usrtai __P((struct isic_softc *sc));
+extern int isic_attach_itkix1 __P((struct isic_softc *sc));
+extern void isic_bchannel_setup __P((int unit, int hscx_channel, int bprot, int activate));
+extern void isic_hscx_init __P((struct isic_softc *sc, int hscx_channel, int activate));
+extern void isic_hscx_irq __P((struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq));
+extern int isic_hscx_silence __P(( unsigned char *data, int len ));
+extern void isic_hscx_cmd __P(( struct isic_softc *sc, int h_chan, unsigned char cmd ));
+extern void isic_hscx_waitxfw __P(( struct isic_softc *sc, int h_chan ));
+extern void isic_init_linktab __P((struct isic_softc *sc));
+extern int isic_isac_init __P((struct isic_softc *sc));
+extern void isic_isac_irq __P((struct isic_softc *sc, int r));
+extern void isic_isac_l1_cmd __P((struct isic_softc *sc, int command));
+extern void isic_next_state __P((struct isic_softc *sc, int event));
+extern char * isic_printstate __P((struct isic_softc *sc));
+extern int isic_probe_avma1 __P((struct isic_attach_args *ia));
+extern int isic_probe_s016 __P((struct isic_attach_args *ia));
+extern int isic_probe_s0163 __P((struct isic_attach_args *ia));
+extern int isic_probe_s08 __P((struct isic_attach_args *ia));
+extern int isic_probe_usrtai __P((struct isic_attach_args *ia));
+extern int isic_probe_itkix1 __P((struct isic_attach_args *ia));
+
+extern struct isic_softc *isic_sc[];
+
+#define isic_find_sc(unit) (isic_sc[(unit)])
+
+#endif /* __FreeBSD__ */
+
+#endif /* I4B_L1_H_ */
diff --git a/sys/i4b/layer1/i4b_l1fsm.c b/sys/i4b/layer1/i4b_l1fsm.c
new file mode 100644
index 000000000000..397ce11f711c
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1fsm.c
@@ -0,0 +1,546 @@
+/*
+ * 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_l1fsm.c - isdn4bsd layer 1 I.430 state machine
+ * --------------------------------------------------
+ *
+ * $Id: i4b_l1fsm.c,v 1.26 1998/12/05 18:04:55 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:25:12 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 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/mbuf.h>
+
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+
+static char *state_text[N_STATES] = {
+ "F3 Deactivated",
+ "F4 Awaiting Signal",
+ "F5 Identifying Input",
+ "F6 Synchronized",
+ "F7 Activated",
+ "F8 Lost Framing",
+ "Illegal State"
+};
+
+static char *event_text[N_EVENTS] = {
+ "EV_PHAR PH_ACT_REQ",
+ "EV_T3 Timer 3 expired",
+ "EV_INFO0 INFO0 received",
+ "EV_RSY Level Detected",
+ "EV_INFO2 INFO2 received",
+ "EV_INFO48 INFO4 received",
+ "EV_INFO410 INFO4 received",
+ "EV_DR Deactivate Req",
+ "EV_PU Power UP",
+ "EV_DIS Disconnected",
+ "EV_EI Error Ind",
+ "Illegal Event"
+};
+
+/* Function prototypes */
+
+static void timer3_expired (struct isic_softc *sc);
+static void T3_start (struct isic_softc *sc);
+static void T3_stop (struct isic_softc *sc);
+static void F_T3ex (struct isic_softc *sc);
+static void timer4_expired (struct isic_softc *sc);
+static void T4_start (struct isic_softc *sc);
+static void T4_stop (struct isic_softc *sc);
+static void F_AI8 (struct isic_softc *sc);
+static void F_AI10 (struct isic_softc *sc);
+static void F_I01 (struct isic_softc *sc);
+static void F_I02 (struct isic_softc *sc);
+static void F_I03 (struct isic_softc *sc);
+static void F_I2 (struct isic_softc *sc);
+static void F_ill (struct isic_softc *sc);
+static void F_NULL (struct isic_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct isic_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ DBGL1(L1_T_ERR, "timer3_expired", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T3 = 0;
+
+ /* XXX try some recovery here XXX */
+
+ isic_recover(sc);
+
+ sc->sc_init_tries++; /* increment retry count */
+
+/*XXX*/ if(sc->sc_init_tries > 4)
+ {
+ int s = SPLI4B();
+
+ sc->sc_init_tries = 0;
+
+ if(sc->sc_obuf2 != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf2);
+ sc->sc_obuf2 = NULL;
+ }
+ if(sc->sc_obuf != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_obuf = NULL;
+ sc->sc_freeflag = 0;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ }
+
+ splx(s);
+
+ MPH_Status_Ind(sc->sc_unit, STI_NOL1ACC, 0);
+ }
+
+ isic_next_state(sc, EV_T3);
+ }
+ else
+ {
+ DBGL1(L1_T_ERR, "timer3_expired", ("expired without starting it ....\n"));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T3_start", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T3 = 1;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz);
+#else
+ timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T3_stop", ("state = %s\n", isic_printstate(sc)));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, sc->sc_T3_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_T3ex", ("FSM function F_T3ex executing\n"));
+ PH_Deact_Ind(sc->sc_unit);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct isic_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ DBGL1(L1_T_ERR, "timer4_expired", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T4 = 0;
+ MPH_Status_Ind(sc->sc_unit, STI_PDEACT, 0);
+ }
+ else
+ {
+ DBGL1(L1_T_ERR, "timer4_expired", ("expired without starting it ....\n"));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T4_start", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T4 = 1;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz);
+#else
+ timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T4_stop", ("state = %s\n", isic_printstate(sc)));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, sc->sc_T4_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct isic_softc *sc)
+{
+ T4_stop(sc);
+
+ DBGL1(L1_F_MSG, "F_AI8", ("FSM function F_AI8 executing\n"));
+
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct isic_softc *sc)
+{
+ T4_stop(sc);
+
+ DBGL1(L1_F_MSG, "F_AI10", ("FSM function F_AI10 executing\n"));
+
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I01", ("FSM function F_I01 executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I02", ("FSM function F_I02 executing\n"));
+
+ PH_Deact_Ind(sc->sc_unit);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I03", ("FSM function F_I03 executing\n"));
+
+ PH_Deact_Ind(sc->sc_unit);
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_AR", ("FSM function F_AR executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+ isic_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I2", ("FSM function F_I2 executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct isic_softc *sc)
+{
+ DBGL1(L1_F_ERR, "F_ill", ("FSM function F_ill executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_NULL", ("FSM function F_NULL executing\n"));
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct isic_state_tab {
+ void (*func) (struct isic_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} isic_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}},
+/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}},
+/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}},
+/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}},
+/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}},
+/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}},
+/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void
+isic_next_state(struct isic_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ if(event >= N_EVENTS)
+ panic("i4b_l1fsm.c: event >= N_EVENTS\n");
+
+ currstate = sc->sc_I430state;
+
+ if(currstate >= N_STATES)
+ panic("i4b_l1fsm.c: currstate >= N_STATES\n");
+
+ newstate = isic_state_tab[event][currstate].newstate;
+
+ if(newstate >= N_STATES)
+ panic("i4b_l1fsm.c: newstate >= N_STATES\n");
+
+ DBGL1(L1_F_MSG, "isic_next_state", ("FSM event [%s]: [%s => %s]\n", event_text[event],
+ state_text[currstate],
+ state_text[newstate]));
+
+ (*isic_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ DBGL1(L1_F_ERR, "isic_next_state", ("FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!\n",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]));
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+isic_printstate(struct isic_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_sws.c b/sys/i4b/layer1/i4b_sws.c
new file mode 100644
index 000000000000..c5182b49e3d7
--- /dev/null
+++ b/sys/i4b/layer1/i4b_sws.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 1998 German Tischler. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Card format:
+ *
+ * iobase + 0 : reset on (0x03)
+ * iobase + 1 : reset off (0x0)
+ * iobase + 2 : isac read/write
+ * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 ,
+ * offset 0x40-0x7f hscx1 )
+ * iobase + 4 : offset for indirect adressing
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for SWS cards
+ * ====================================================
+ *
+ * EXPERIMENTAL !!!!
+ * =================
+ *
+ * $Id: i4b_sws.c,v 1.12 1998/12/18 09:32:45 hm Exp $
+ *
+ * last edit-date: [Sun Dec 13 10:49:25 1998]
+ *
+ * -hm adding driver to i4b
+ * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#else
+
+#define NISIC 1
+
+#endif
+
+#if defined (SEDLBAUER) && NISIC > 0
+
+#define SWS_RESON 0 /* reset on */
+#define SWS_RESOFF 1 /* reset off */
+#define SWS_ISAC 2 /* ISAC */
+#define SWS_HSCX0 3 /* HSCX0 */
+#define SWS_RW 4 /* indirect access register */
+#define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */
+ /* access is done through hscx0 */
+
+#define SWS_REGS 8 /* we use an area of 8 bytes for io */
+
+#define SWS_BASE(X) ((unsigned int)X&~(SWS_REGS-1))
+#define SWS_PART(X) ((unsigned int)X& (SWS_REGS-1))
+#define SWS_ADDR(X) ((SWS_PART(X) == SWS_ISAC) ? (SWS_BASE(X)+SWS_ISAC) : (SWS_BASE(X)+SWS_HSCX0) )
+#define SWS_REG(X,Y) ((SWS_PART(X) != SWS_HSCX1) ? Y : (Y+0x40) )
+#define SWS_IDO(X) (SWS_BASE(X)+SWS_RW)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t sws_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void sws_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void sws_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void sws_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_sws __P((struct isic_softc *sc));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(SWS_IDO(base),SWS_REG(base,0));
+ insb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb (SWS_IDO(base),SWS_REG(base,0));
+ outsb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ outb(SWS_ADDR(base),v);
+}
+
+#else
+
+static void
+sws_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+sws_read_reg(u_char *base, u_int offset)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ return inb(SWS_ADDR(base));
+}
+
+#else
+
+static u_int8_t
+sws_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/* attach callback routine */
+
+int
+isic_attach_sws(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* fill in isic_softc structure */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+ sc->clearirq = NULL;
+ sc->sc_unit = dev->id_unit;
+ sc->sc_irq = dev->id_irq;
+ sc->sc_port = dev->id_iobase;
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+ dev->id_msize = 0;
+
+ ISAC_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_ISAC);
+ HSCX_A_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX0);
+ HSCX_B_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX1);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* reset card */
+
+ outb( ((u_int) sc->sc_port) + SWS_RESON , 0x3);
+ DELAY(SEC_DELAY / 5);
+ outb( ((u_int) sc->sc_port) + SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_sws(struct isic_softc *sc)
+{
+ /* setup access routines */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for SWS PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ /* reset card */
+ {
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, SWS_RESON, 0x3);
+ DELAY(SEC_DELAY / 5);
+ bus_space_write_1(t, h, SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+ }
+}
+
+#endif /* !__FreeBSD__ */
+
+#endif /* defined(SEDLBAUER) && NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_tel_s016.c b/sys/i4b/layer1/i4b_tel_s016.c
new file mode 100644
index 000000000000..f77a3c184241
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s016.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16 and clones
+ * =================================================================
+ *
+ * $Id: i4b_tel_s016.c,v 1.12 1998/12/05 18:04:56 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:40:17 1998]
+ *
+ * -hm clean up
+ * -hm checked with a Creatix ISDN-S0 (PCB version: mp 130.1)
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#ifndef __FreeBSD__
+static u_int8_t tels016_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels016_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels016_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels016_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels016_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels016_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels016_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+
+ if(offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 fifo read/write routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels016_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels016_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s016 - probe for Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s016(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* check if valid memory addr */
+
+ switch((unsigned int)kvtop(dev->id_maddr))
+ {
+ case 0xc0000:
+ case 0xc2000:
+ case 0xc4000:
+ case 0xc6000:
+ case 0xc8000:
+ case 0xca000:
+ case 0xcc000:
+ case 0xce000:
+ case 0xd0000:
+ case 0xd2000:
+ case 0xd4000:
+ case 0xd6000:
+ case 0xd8000:
+ case 0xda000:
+ case 0xdc000:
+ case 0xde000:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid mem addr 0x%lx for Teles S0/16!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ break;
+ }
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* check card signature */
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = inb(sc->sc_port + 2);
+
+ if((byte != 0x1e) && (byte != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_memcpyb;
+ sc->writefifo = tels016_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t) ((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t) ((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t) ((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s016(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && (b2 == 0x1e || b2 == 0x1f))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s016 - attach Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s016(struct isa_device *dev)
+#else
+isic_attach_s016(struct isic_softc *sc)
+#endif
+{
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#endif
+
+ u_long irq;
+
+#ifndef __FreeBSD__
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_read_fifo;
+ sc->writefifo = tels016_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+#ifdef __FreeBSD__
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+#else
+ irq = intr_no[sc->sc_irq];
+#endif
+
+ /* configure IRQ */
+
+#ifdef __FreeBSD__
+ irq |= ((u_long) sc->sc_vmem_addr) >> 9;
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ sc->sc_vmem_addr[0x80] = 0;
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ sc->sc_vmem_addr[0x80] = 1;
+ DELAY(SEC_DELAY / 5);
+
+#else
+
+ irq |= ((sc->sc_maddr >> 9) & 0x000000f0);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 0);
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 1);
+ DELAY(SEC_DELAY / 5);
+#endif
+
+ return (1);
+}
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s0163.c b/sys/i4b/layer1/i4b_tel_s0163.c
new file mode 100644
index 000000000000..5fdd32961b73
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s0163.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3
+ * ========================================================
+ *
+ * $Id: i4b_tel_s0163.c,v 1.15 1998/12/05 18:04:58 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:40:58 1998]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm VSTR detection for older 16.3 cards
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16_3)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#ifndef __FreeBSD__
+static u_int8_t tels0163_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels0163_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels0163_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 read fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x1e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 write fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x1e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs - 0x20, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels0163_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs - 0x20);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163 - probe for Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 2)) != 0x1c)
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1c for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ ISAC_BASE = (caddr_t) 0x960;
+ HSCX_A_BASE = (caddr_t) 0x160;
+ HSCX_B_BASE = (caddr_t) 0x560;
+ break;
+
+ case 0xe80:
+ ISAC_BASE = (caddr_t) 0xa60;
+ HSCX_A_BASE = (caddr_t) 0x260;
+ HSCX_B_BASE = (caddr_t) 0x660;
+ break;
+
+ case 0xf80:
+ ISAC_BASE = (caddr_t) 0xb60;
+ HSCX_A_BASE = (caddr_t) 0x360;
+ HSCX_B_BASE = (caddr_t) 0x760;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is
+ * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s0163(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && b2 == 0x1c)
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163 - attach Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163(struct isa_device *dev)
+{
+ u_char irq;
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq | 0x01);
+
+ return (1);
+}
+
+#else
+
+int
+isic_attach_s0163(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_int8_t irq = intr_no[sc->sc_irq];
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq | 0x01);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return (1);
+}
+#endif
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s08.c b/sys/i4b/layer1/i4b_tel_s08.c
new file mode 100644
index 000000000000..6115e12ab624
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s08.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones
+ * ================================================================
+ *
+ * $Id: i4b_tel_s08.c,v 1.13 1998/12/05 18:04:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:39:12 1998]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm making it finally work (checked with board revision 1.2)
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_8)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels08_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels08_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels08_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+static void tels08_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels08_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels08_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels08_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 fifo read/write access
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels08_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels08_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s08 - probe for Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+int
+isic_probe_s08(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 2:
+ case 9: /* XXX */
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase > 0)
+ {
+ printf("isic%d: Error, iobase specified for Teles S0/8!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if inside memory range of 0xA0000 .. 0xDF000 */
+
+ if( (kvtop(dev->id_maddr) < 0xa0000) ||
+ (kvtop(dev->id_maddr) > 0xdf000) )
+ {
+ printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ }
+
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+
+ sc->readfifo = tels08_memcpyb;
+ sc->writefifo = tels08_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t)((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t)((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t)((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s08(struct isic_attach_args *ia)
+{
+ /* no real sensible probe is easy - write to fifo memory
+ and read back to verify there is memory doesn't work,
+ because you talk to tx fifo and rcv fifo. So, just check
+ HSCX version, which at least fails if no card present
+ at the given location. */
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t v1, v2;
+
+ /* HSCX A VSTR */
+ v1 = bus_space_read_1(t, h, offset[1] + H_VSTR) & 0x0f;
+ if (v1 != HSCX_VA1 && v1 != HSCX_VA2 && v1 != HSCX_VA3 && v1 != HSCX_V21)
+ return 0;
+
+ /* HSCX B VSTR */
+ v2 = bus_space_read_1(t, h, offset[2] + H_VSTR) & 0x0f;
+ if (v2 != HSCX_VA1 && v2 != HSCX_VA2 && v2 != HSCX_VA3 && v2 != HSCX_V21)
+ return 0;
+
+ /* both HSCX channels should have the same version... */
+ if (v1 != v2)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s08 - attach Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s08(struct isa_device *dev)
+#else
+isic_attach_s08(struct isic_softc *sc)
+#endif
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#else
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+#endif
+
+ /* set card off */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 0;
+#else
+ bus_space_write_1(t, h, 0x80, 0);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card on */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 1;
+#else
+ bus_space_write_1(t, h, 0x80, 1);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+#ifndef __FreeBSD__
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+ sc->readfifo = tels08_read_fifo;
+ sc->writefifo = tels08_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+ return (1);
+}
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s0P.c b/sys/i4b/layer1/i4b_tel_s0P.c
new file mode 100644
index 000000000000..9bccd77b6fc9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s0P.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 1997 Andrew Gordon. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0 PnP
+ * =======================================================
+ *
+ * EXPERIMENTAL !!!
+ * ================
+ *
+ * $Id: i4b_tel_s0P.c,v 1.12 1998/12/13 09:52:34 hm Exp $
+ *
+ * last edit-date: [Thu Dec 10 07:11:15 1998]
+ *
+ * -hm rudimentary PnP support, hint from Andrew Gordon
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16_3_P)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels0163P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels0163P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels0163P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_s0163P __P((struct isic_softc *sc));
+#endif
+
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels0163P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163P_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163P - probe for Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163P(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ case 0x500:
+ case 0x680:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ ISAC_BASE = (caddr_t) 0x580 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x180 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x180;
+ break;
+
+ case 0x500:
+ ISAC_BASE = (caddr_t) 0x500 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x100 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x100;
+ break;
+
+ case 0x680:
+ ISAC_BASE = (caddr_t) 0x680 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x280 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x280;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 PnP card is
+ * 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3 PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163P(struct isa_device *dev)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void
+isic_attach_s0163P(struct isic_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_usr_sti.c b/sys/i4b/layer1/i4b_usr_sti.c
new file mode 100644
index 000000000000..db89296160fa
--- /dev/null
+++ b/sys/i4b/layer1/i4b_usr_sti.c
@@ -0,0 +1,440 @@
+/*
+ * 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_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp)
+ * -------------------------------------------------------------
+ *
+ * $Id: i4b_usr_sti.c,v 1.16 1998/12/05 18:05:02 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:25:34 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(USR_STI)
+
+#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/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#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/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ * USR Sportster TA intern special registers
+ *---------------------------------------------------------------------------*/
+#define USR_HSCXA_OFF 0x0000
+#define USR_HSCXB_OFF 0x4000
+#define USR_INTL_OFF 0x8000
+#define USR_ISAC_OFF 0xc000
+
+#define USR_RES_BIT 0x80 /* 0 = normal, 1 = reset ISAC/HSCX */
+#define USR_INTE_BIT 0x40 /* 0 = IRQ disabled, 1 = IRQ's enabled */
+#define USR_IL_MASK 0x07 /* IRQ level config */
+
+static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 };
+
+#ifdef __FreeBSD__
+
+#define ADDR(reg) \
+ (((reg/4) * 1024) + ((reg%4) * 2))
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ *((u_char *)buf + offset) = inb((int)base + ADDR(offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ outb((int)base + ADDR(offset), *((u_char *)buf + offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + ADDR(offset), (u_char)v);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(u_char *base, u_int offset)
+{
+ return(inb((int)base + ADDR(offset)));
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= MAXUNIT for USR Sportster TA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, (ffs(dev->id_irq))-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for USR Sportster TA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ case 0x220:
+ case 0x228:
+ case 0x230:
+ case 0x238:
+ case 0x240:
+ case 0x248:
+ case 0x250:
+ case 0x258:
+ case 0x260:
+ case 0x268:
+ case 0x270:
+ case 0x278:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + USR_ISAC_OFF;
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + USR_HSCXA_OFF;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + USR_HSCXB_OFF;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for USR Sportster TA based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct isa_device *dev)
+{
+ u_char irq = 0;
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + USR_INTL_OFF, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + USR_INTL_OFF, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure and enable irq */
+
+ outb(dev->id_iobase + USR_INTL_OFF, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else /* end of FreeBSD, start NetBSD */
+
+/*
+ * Use of sc->sc_maps:
+ * 0 : config register
+ * 1 - 16 : HSCX A registers
+ * 17 - 32 : HSCX B registers
+ * 33 - 48 : ISAC registers
+ */
+
+#define USR_REG_OFFS(reg) ((reg % 4) * 2)
+#define USR_HSCXA_MAP(reg) ((reg / 4) + 1)
+#define USR_HSCXB_MAP(reg) ((reg / 4) + 17)
+#define USR_ISAC_MAP(reg) ((reg / 4) + 33)
+
+static int map_base[] = { 33, 1, 17, 0 }; /* ISAC, HSCX A, HSCX B */
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ int map, off, offset;
+ u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ *p++ = bus_space_read_1(t, h, off);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ int map, off, offset;
+ const u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+ u_char v;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ v = *p++;
+ bus_space_write_1(t, h, off, v);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ bus_space_write_1(t, h, off, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ return bus_space_read_1(t, h, off);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isic_attach_args *ia)
+{
+ /*
+ * Read HSCX A/B VSTR. Expected value for IOM2 based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if(((bus_space_read_1(ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05) ||
+ ((bus_space_read_1(ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05))
+ return 0;
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char irq = intr_no[sc->sc_irq];
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 0, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#endif /* __FreeBSD__ */
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/isa_isic.c b/sys/i4b/layer1/isa_isic.c
new file mode 100644
index 000000000000..94e4bf7e4151
--- /dev/null
+++ b/sys/i4b/layer1/isa_isic.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright (c) 1997, 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isa_isic.c - ISA bus frontend for i4b_isic driver
+ * --------------------------------------------------
+ *
+ * $Id: isa_isic.c,v 1.18 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:53:16 1998]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+
+#if defined(__OpenBSD__)
+#define __BROKEN_INDIRECT_CONFIG
+#endif
+
+/* local functions */
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isa_isic_probe __P((struct device *, void *, void *));
+#else
+static int isa_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+
+static void isa_isic_attach __P((struct device *, struct device *, void *));
+static int setup_io_map __P((int flags, bus_space_tag_t iot,
+ bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr,
+ int *num_mappings, struct isic_io_map *maps, int *iosize,
+ int *msize));
+static void args_unmap __P((int *num_mappings, struct isic_io_map *maps));
+
+struct cfattach isa_isic_ca = {
+ sizeof(struct isic_softc), isa_isic_probe, isa_isic_attach
+};
+
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isa_isic_probe(parent, match, aux)
+#else
+isa_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+#ifdef __BROKEN_INDIRECT_CONFIG
+ struct cfdata *cf = ((struct device*)match)->dv_cfdata;
+#endif
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot;
+ int flags = cf->cf_flags;
+ struct isic_attach_args args;
+ int ret = 0;
+
+ /* check irq */
+ if (ia->ia_irq == IRQUNK) {
+ printf("isic%d: config error: no IRQ specified\n", cf->cf_unit);
+ return 0;
+ }
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* if card type specified setup io map for that card */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ case FLAG_ITK_IX1:
+ if (setup_io_map(flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &ia->ia_msize)) {
+ ret = 0;
+ goto done;
+ }
+ break;
+
+ default:
+ /* no io map now, will figure card type later */
+ break;
+ }
+
+ /* probe card */
+ switch(flags)
+ {
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_probe_Dyn(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_probe_s0163(&args);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_probe_avma1(&args);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_probe_usrtai(&args);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_probe_itkix1(&args);
+ break;
+#endif
+
+ default:
+ /* No card type given, try to figure ... */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ ret = 0;
+#ifdef TEL_S0_16_3
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16_3 */
+#ifdef AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* AVM_A1 */
+#ifdef USR_STI
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ break;
+ }
+#endif /* USR_STI */
+
+#ifdef ITKIX1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_ITK_IX1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ break;
+ }
+#endif /* ITKIX1 */
+
+ } else {
+#ifdef TEL_S0_16_3
+ /* could be anything */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16_3 */
+#ifdef TEL_S0_16
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_16;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s016(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16 */
+#ifdef AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* AVM_A1 */
+#ifdef TEL_S0_8
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* TEL_S0_8 */
+ }
+ break;
+ }
+
+done:
+ /* unmap resources */
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+
+ return ret;
+}
+
+/*
+ * Attach the card
+ */
+static void
+isa_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isic_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ int flags = sc->sc_dev.dv_cfdata->cf_flags;
+ int ret = 0;
+ struct isic_attach_args args;
+
+ /* Setup parameters */
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_maddr = ia->ia_maddr;
+ sc->sc_num_mappings = 0;
+ sc->sc_maps = NULL;
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), NULL, NULL, NULL);
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ break;
+
+ default:
+ /* No card type given, try to figure ... */
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* Probe cards */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ ret = 0;
+#ifdef TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16_3 */
+#ifdef AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* AVM_A1 */
+#ifdef USR_STI
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* USR_STI */
+#ifdef ITKIX1
+ args.ia_flags = FLAG_ITK_IX1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ITKIX1 */
+ } else {
+ /* could be anything */
+ ret = 0;
+#ifdef TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16_3 */
+#ifdef TEL_S0_16
+ args.ia_flags = FLAG_TELES_S0_16;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s016(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16 */
+#ifdef AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* AVM_A1 */
+#ifdef TEL_S0_8
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_8 */
+ }
+ break;
+
+ found:
+ flags = args.ia_flags;
+ sc->sc_num_mappings = args.ia_num_mappings;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ if (ret) {
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ } else {
+ printf(": could not determine card type - not configured!\n");
+ return;
+ }
+ break;
+ }
+
+#if defined(__OpenBSD__)
+ isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc, sc->sc_dev.dv_xname);
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+#else
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+ /*
+ * Try to get a level-triggered interrupt first. If that doesn't
+ * work (like on NetBSD/Atari, try to establish an edge triggered
+ * interrupt.
+ */
+ if (isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_LEVEL,
+ IPL_NET, isicintr, sc) == NULL) {
+ if(isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc) == NULL) {
+ args_unmap(&(sc->sc_num_mappings), &(sc->sc_maps[0]));
+ free((sc)->sc_maps, M_DEVBUF);
+ }
+ else {
+ /*
+ * XXX: This is a hack that probably needs to be
+ * solved by setting an interrupt type in the sc
+ * structure. I don't feel familiar enough with the
+ * code to do this currently. Feel free to contact
+ * me about it (leo@netbsd.org).
+ */
+ isicintr(sc);
+ }
+ }
+#endif
+}
+
+/*
+ * Setup card specific io mapping. Return 0 on success,
+ * any other value on config error.
+ * Be prepared to get NULL as maps array.
+ * Make sure to keep *num_mappings in sync with the real
+ * mappings already setup when returning!
+ */
+static int
+setup_io_map(flags, iot, memt, iobase, maddr, num_mappings, maps, iosize, msize)
+ int flags, *num_mappings, *iosize, *msize;
+ bus_size_t iobase, maddr;
+ bus_space_tag_t iot, memt;
+ struct isic_io_map *maps;
+{
+ /* nothing mapped yet */
+ *num_mappings = 0;
+
+ /* which resources do we need? */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/8!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 0; /* no i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* this card uses a single memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = memt;
+ maps[0].offset = 0;
+ maps[0].size = 0x1000;
+ if (bus_space_map(maps[0].t, maddr,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_16:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* one io and one memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 2;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = memt;
+ maps[1].offset = 0;
+ maps[1].size = 0x1000;
+ if (bus_space_map(maps[1].t, maddr,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_163:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Four io mappings: config, isac, 2 * hscx */
+ if (maps == NULL) {
+ *num_mappings = 4;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = iot;
+ maps[1].offset = 0;
+ maps[1].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x980) < 0 || (iobase - 0xd80 + 0x980) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase - 0xd80 + 0x980,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[2].t = iot;
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x180) < 0 || (iobase - 0xd80 + 0x180) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase - 0xd80 + 0x180,
+ maps[2].size, 0, &maps[2].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[3].t = iot;
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x580) < 0 || (iobase - 0xd80 + 0x580) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase - 0xd80 + 0x580,
+ maps[3].size, 0, &maps[3].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_AVM_A1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for AVM A1/Fritz! card!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Seven io mappings: config, isac, 2 * hscx,
+ isac-fifo, 2 * hscx-fifo */
+ if (maps == NULL) {
+ *num_mappings = 7;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot; /* config */
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if ((iobase + 0x1800) < 0 || (iobase + 0x1800) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[0].t, iobase + 0x1800, maps[0].size, 0, &maps[0].h))
+ return 1;
+ (*num_mappings)++;
+ maps[1].t = iot; /* isac */
+ maps[1].offset = 0;
+ maps[1].size = 0x80; /* XXX - ??? */
+ if ((iobase + 0x1400 - 0x20) < 0 || (iobase + 0x1400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase + 0x1400 - 0x20, maps[1].size, 0, &maps[1].h))
+ return 1;
+ (*num_mappings)++;
+ maps[2].t = iot; /* hscx 0 */
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0x400 - 0x20) < 0 || (iobase + 0x400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase + 0x400 - 0x20, maps[2].size, 0, &maps[2].h))
+ return 1;
+ (*num_mappings)++;
+ maps[3].t = iot; /* hscx 1 */
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0xc00 - 0x20) < 0 || (iobase + 0xc00 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase + 0xc00 - 0x20, maps[3].size, 0, &maps[3].h))
+ return 1;
+ (*num_mappings)++;
+ maps[4].t = iot; /* isac-fifo */
+ maps[4].offset = 0;
+ maps[4].size = 1;
+ if ((iobase + 0x1400 - 0x20 -0x3e0) < 0 || (iobase + 0x1400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[4].t, iobase + 0x1400 - 0x20 -0x3e0, maps[4].size, 0, &maps[4].h))
+ return 1;
+ (*num_mappings)++;
+ maps[5].t = iot; /* hscx 0 fifo */
+ maps[5].offset = 0;
+ maps[5].size = 1;
+ if ((iobase + 0x400 - 0x20 -0x3e0) < 0 || (iobase + 0x400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[5].t, iobase + 0x400 - 0x20 -0x3e0, maps[5].size, 0, &maps[5].h))
+ return 1;
+ (*num_mappings)++;
+ maps[6].t = iot; /* hscx 1 fifo */
+ maps[6].offset = 0;
+ maps[6].size = 1;
+ if ((iobase + 0xc00 - 0x20 -0x3e0) < 0 || (iobase + 0xc00 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[6].t, iobase + 0xc00 - 0x20 -0x3e0, maps[6].size, 0, &maps[6].h))
+ return 1;
+ (*num_mappings)++;
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for USR Sportster TA intern!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* scattered ports, only some shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* 49 io mappings: 1 config and 48x8 registers */
+ if (maps == NULL) {
+ *num_mappings = 49;
+ return 0;
+ }
+ *num_mappings = 0;
+ {
+ int i, num;
+ bus_size_t base;
+
+ /* config at offset 0x8000 */
+ base = iobase + 0x8000;
+ maps[0].size = 1;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (base < 0 || base > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base, 1, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = num = 1;
+
+ /* HSCX A at offset 0 */
+ base = iobase;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* HSCX B at offset 0x4000 */
+ base = iobase + 0x4000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* ISAC at offset 0xc000 */
+ base = iobase + 0xc000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ }
+ break;
+
+ case FLAG_ITK_IX1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for ITK ix1 micro!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 4;
+ if (msize) *msize = 0;
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].size = 4;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (bus_space_map(iot, iobase, 4, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = 1;
+ break;
+
+ default:
+ printf("isic: config error: flags do not specify any known card!\n");
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static void
+args_unmap(num_mappings, maps)
+ int *num_mappings;
+ struct isic_io_map *maps;
+{
+ int i, n;
+ for (i = 0, n = *num_mappings; i < n; i++)
+ if (maps[i].size)
+ bus_space_unmap(maps[i].t, maps[i].h, maps[i].size);
+ *num_mappings = 0;
+}
diff --git a/sys/i4b/layer1/isapnp_isic.c b/sys/i4b/layer1/isapnp_isic.c
new file mode 100644
index 000000000000..9dfdf68c62b3
--- /dev/null
+++ b/sys/i4b/layer1/isapnp_isic.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 1997, 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isapnp_isic.c - ISA-P&P bus frontend for i4b_isic driver
+ * --------------------------------------------------------
+ *
+ * $Id: isapnp_isic.c,v 1.9 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:54:23 1998]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isapnp/isapnpreg.h>
+#include <dev/isapnp/isapnpvar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isapnp_isic_probe __P((struct device *, void *, void *));
+#else
+static int isapnp_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+static void isapnp_isic_attach __P((struct device *, struct device *, void *));
+
+struct cfattach isapnp_isic_ca = {
+ sizeof(struct isic_softc), isapnp_isic_probe, isapnp_isic_attach
+};
+
+typedef void (*allocmaps_func)(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+typedef void (*attach_func)(struct isic_softc *sc);
+
+/* map allocators */
+static void generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+static void ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+static void tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+
+/* card attach functions */
+extern void isic_attach_Cs0P __P((struct isic_softc *sc));
+extern void isic_attach_Dyn __P((struct isic_softc *sc));
+extern void isic_attach_s0163P __P((struct isic_softc *sc));
+extern void isic_attach_drnngo __P((struct isic_softc *sc));
+extern void isic_attach_sws __P((struct isic_softc *sc));
+extern void isic_attach_Eqs1pi __P((struct isic_softc *sc));
+
+struct isapnp_isic_card_desc {
+ char *devlogic; /* ISAPNP logical device ID */
+ char *name; /* Name of the card */
+ int card_type; /* isic card type identifier */
+ allocmaps_func allocmaps; /* map allocator function */
+ attach_func attach; /* card attach and init function */
+};
+static const struct isapnp_isic_card_desc
+isapnp_isic_descriptions[] =
+{
+#ifdef CRTX_S0_P
+ { "CTX0000", "Creatix ISDN S0-16 P&P", CARD_TYPEP_CS0P,
+ tls_pnp_mapalloc, isic_attach_Cs0P },
+#endif
+#ifdef TEL_S0_16_3_P
+ { "TAG2110", "Teles S0/PnP", CARD_TYPEP_163P,
+ tls_pnp_mapalloc, isic_attach_s0163P },
+#endif
+#ifdef DRN_NGO
+ { "SDA0150", "Dr. Neuhaus NICCY GO@", CARD_TYPEP_DRNNGO,
+ ngo_pnp_mapalloc, isic_attach_drnngo },
+#endif
+#ifdef ELSA_QS1ISA
+ { "ELS0133", "Elsa QuickStep 1000 (ISA)", CARD_TYPEP_ELSAQS1ISA,
+ generic_pnp_mapalloc, isic_attach_Eqs1pi },
+#endif
+#ifdef SEDLBAUER
+ { "SAG0001", "Sedlbauer WinSpeed", CARD_TYPEP_SWS,
+ generic_pnp_mapalloc, isic_attach_sws },
+#endif
+#ifdef DYNALINK
+ { "ASU1688", "Dynalink IS64PH", CARD_TYPEP_DYNALINK,
+ generic_pnp_mapalloc, isic_attach_Dyn },
+#endif
+};
+#define NUM_DESCRIPTIONS (sizeof(isapnp_isic_descriptions)/sizeof(isapnp_isic_descriptions[0]))
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isapnp_isic_probe(parent, match, aux)
+#else
+isapnp_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ return 1;
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for ISA P&P cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+static void
+isapnp_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ struct isic_softc *sc = (void *)self;
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ break;
+ if (i >= NUM_DESCRIPTIONS)
+ panic("could not identify isic PnP device");
+
+ /* setup parameters */
+ sc->sc_cardtyp = desc->card_type;
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ipa->ipa_irq[0].num;
+ desc->allocmaps(ipa, sc);
+
+ /* announce card name */
+ printf(": %s\n", desc->name);
+
+ /* establish interrupt handler */
+ isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, IST_EDGE,
+ IPL_NET, isicintr, sc);
+
+ /* init card */
+ isic_sc[sc->sc_unit] = sc;
+ desc->attach(sc);
+
+ /* announce chip versions */
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return;
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return;
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+}
+
+static void
+generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 1; /* most cards have just one mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+}
+
+static void
+ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 2; /* one data, one address mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[1].h;
+ sc->sc_maps[1].size = 0;
+}
+
+static void
+tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 4; /* config, isac, 2 * hscx */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[0].h;
+ sc->sc_maps[1].size = 0;
+ sc->sc_maps[1].offset = - 0x20;
+ sc->sc_maps[2].t = ipa->ipa_iot;
+ sc->sc_maps[2].offset = - 0x20;
+ sc->sc_maps[2].h = ipa->ipa_io[1].h;
+ sc->sc_maps[2].size = 0;
+ sc->sc_maps[3].t = ipa->ipa_iot;
+ sc->sc_maps[3].offset = 0;
+ sc->sc_maps[3].h = ipa->ipa_io[1].h;
+ sc->sc_maps[3].size = 0;
+}
diff --git a/sys/i4b/layer1/isic_supio.c b/sys/i4b/layer1/isic_supio.c
new file mode 100644
index 000000000000..6c58ad218425
--- /dev/null
+++ b/sys/i4b/layer1/isic_supio.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 1998 Ignatios Souvatzis. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic_supio.c - Amiga supio pseudo bus frontend for i4b_isic driver
+ * supports:
+ * - ISDN Blaster 5001/1
+ * - ISDN Master 2092/64
+ * But we attach to the supio, so just see "isic".
+ * -----------------------------------------------
+ *
+ * $Id: isic_supio.c,v 1.5 1998/12/19 12:07:55 hm Exp $
+ *
+ * last edit-date: [Mon Nov 16 12:29:19 1998]
+ *
+ * -is original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <amiga/dev/supio.h>
+
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_isac.h>
+
+/*static*/ int isic_supio_match __P((struct device *, struct cfdata *, void *));
+/*static*/ void isic_supio_attach __P((struct device *, struct device *, void *));
+
+/*static*/ u_int8_t aster_read_reg __P((struct isic_softc *sc, int what,
+ bus_size_t offs));
+/*static*/ void aster_write_reg __P((struct isic_softc *sc, int what,
+ bus_size_t offs, u_int8_t data));
+/*static*/ void aster_read_fifo __P((struct isic_softc *sc, int what,
+ void *buf, size_t size));
+/*static*/ void aster_write_fifo __P((struct isic_softc *sc, int what,
+ const void *data, size_t size));
+
+static int supio_isicattach __P((struct isic_softc *sc));
+
+struct isic_supio_softc {
+ struct isic_softc sc_isic;
+ struct isr sc_isr;
+ struct bus_space_tag sc_bst;
+};
+
+struct cfattach isic_supio_ca = {
+ sizeof(struct isic_supio_softc), isic_supio_match, isic_supio_attach
+};
+
+/*
+ * Probe card
+ */
+/*static*/ int
+isic_supio_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct supio_attach_args *sap = aux;
+
+ /* ARGSUSED */
+ return (!strcmp("isic", sap->supio_name));
+}
+
+int isic_supio_ipl = 2;
+/*
+ * Attach the card
+ */
+/*static*/ void
+isic_supio_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isic_supio_softc *ssc = (void *)self;
+ struct isic_softc *sc = &ssc->sc_isic;
+ struct supio_attach_args *sap = aux;
+
+ bus_space_tag_t bst;
+ bus_space_handle_t h;
+
+ /* setup parameters */
+ sc->sc_cardtyp = CARD_TYPEP_BLMASTER;
+ sc->sc_num_mappings = 3;
+ sc->sc_unit = sc->sc_dev.dv_unit; /* XXX ??? */
+
+ /* create io mappings */
+ MALLOC_MAPS(sc);
+
+ bst = sap->supio_iot;
+ bus_space_map(bst, sap->supio_iobase, 0x400, 0, &h);
+
+ /* ISAC */
+ sc->sc_maps[0].t = bst;
+ sc->sc_maps[0].h = h;
+ sc->sc_maps[0].offset = 0x300/2;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+
+ /* HSCX A */
+ sc->sc_maps[1].t = bst;
+ sc->sc_maps[1].h = h;
+ sc->sc_maps[1].offset = 0x100/2;
+ sc->sc_maps[1].size = 0; /* foreign mapping, leave it alone */
+
+ /* HSCX B */
+ sc->sc_maps[2].t = bst;
+ sc->sc_maps[2].h = h;
+ sc->sc_maps[2].offset = 0x180/2;
+ sc->sc_maps[2].size = 0; /* foreign mapping, leave it alone */
+
+ sc->clearirq = NULL;
+ sc->readreg = aster_read_reg;
+ sc->writereg = aster_write_reg;
+ sc->readfifo = aster_read_fifo;
+ sc->writefifo = aster_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_BLMASTER;
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* enable RTS on HSCX A */
+ aster_write_reg(sc, ISIC_WHAT_HSCXA, H_MODE, HSCX_MODE_RTS);
+
+ /* MI initialization of card */
+
+ printf("\n");
+ supio_isicattach(sc);
+
+ ssc->sc_isr.isr_intr = isicintr;
+ ssc->sc_isr.isr_arg = sc;
+ ssc->sc_isr.isr_ipl = isic_supio_ipl; /* XXX */
+ add_isr(&ssc->sc_isr);
+}
+
+#if 0
+int
+isic_supiointr(p)
+ void *p;
+{
+ /* XXX should test whether it is our interupt at all */
+ add_sicallback((sifunc_t)isicintr, p, NULL);
+ return 1;
+}
+#endif
+
+/*static*/ void
+aster_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_read_multi_1(t, h, o, buf, size);
+}
+
+/*static*/ void
+aster_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_write_multi_1(t, h, o, (u_int8_t*)buf, size);
+}
+
+/*static*/ u_int8_t
+aster_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ return bus_space_read_1(t, h, o + offs);
+}
+
+/*static*/ void
+aster_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_write_1(t, h, o + offs, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for pcmcia^Wsupio cards
+ * XXX this should be centralized!
+ *---------------------------------------------------------------------------*/
+
+/*
+ * parameter and format for message producing e.g. "isic0: "
+ * there is no FreeBSD/Amiga, so just:
+ */
+
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+
+int
+supio_isicattach(struct isic_softc *sc)
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc;
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pci_isic.c b/sys/i4b/layer1/pci_isic.c
new file mode 100644
index 000000000000..6f929e52cca6
--- /dev/null
+++ b/sys/i4b/layer1/pci_isic.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pci_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pci_isic.c,v 1.1 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Nov 16 20:37:32 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+
+static int pci_isic_match __P((struct device *, struct cfdata *, void *));
+static void pci_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pci_product * find_matching_card __P((struct pci_attach_args *pa));
+
+extern void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa));
+static int isic_pciattach __P((struct isic_softc *sc));
+
+struct pci_isic_softc {
+ struct isic_softc sc_isic; /* parent class */
+
+ /* PCI-specific goo */
+ void *sc_ih; /* interrupt handler */
+};
+
+struct cfattach pci_isic_ca = {
+ sizeof(struct pci_isic_softc), pci_isic_match, pci_isic_attach
+};
+
+
+static const struct isic_pci_product {
+ pci_vendor_id_t npp_vendor;
+ pci_product_id_t npp_product;
+ int cardtype;
+ int flag;
+ const char * name;
+ void (*attach)(struct isic_softc *sc, struct pci_attach_args *pa);
+} isic_pci_products[] = {
+ { PCI_VENDOR_ELSA, 0x1000,
+ CARD_TYPEP_ELSAQS1PCI, FLAG_ELSA_QS1P_PCI,
+ "ELSA QuickStep 1000pro/PCI",
+ isic_attach_Eqs1pp },
+
+ { 0, 0, 0, 0, NULL, NULL },
+};
+
+static const struct isic_pci_product * find_matching_card(pa)
+ struct pci_attach_args *pa;
+{
+ const struct isic_pci_product * pp = NULL;
+
+ for (pp = isic_pci_products; pp->npp_vendor; pp++)
+ if (PCI_VENDOR(pa->pa_id) == pp->npp_vendor &&
+ PCI_PRODUCT(pa->pa_id) == pp->npp_product)
+ return pp;
+
+ return NULL;
+}
+
+/*
+ * Match card
+ */
+static int
+pci_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pci_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_isic_softc *psc = (void*) self;
+ struct isic_softc *sc = &psc->sc_isic;
+ struct pci_attach_args *pa = aux;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pci_intr_handle_t ih;
+ const struct isic_pci_product * prod;
+ const char *intrstr;
+
+ /* Redo probe */
+ prod = find_matching_card(pa);
+ if (prod == NULL) return; /* oops - not found?!? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ printf(": %s\n", prod->name);
+
+ /* card initilization and sc setup */
+ prod->attach(sc, pa);
+
+ /* generic setup */
+ isic_pciattach(sc);
+
+ /* Map and establish the interrupt. */
+ if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &ih)) {
+ printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, ih);
+ psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, isicintr, sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ sc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pci device driver attach routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pciattach(sc)
+ struct isic_softc *sc;
+{
+ int ret = 0;
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc; /* XXX - hack! */
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ if(sc->sc_ipac)
+ {
+ ret = IPAC_READ(IPAC_ID);
+
+ switch(ret)
+ {
+ case 0x01:
+ printf("%s: IPAC PSB2115 Version 1.1\n", sc->sc_dev.dv_xname);
+ break;
+
+ default:
+ printf("%s: Error, IPAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, ret);
+ return(0);
+ break;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ printf("%s: ISAC %s (IOM-%c)\n",
+ sc->sc_dev.dv_xname,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ break;
+
+ default:
+ printf("%s: Error, ISAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ printf("%s: HSCX %s\n",
+ sc->sc_dev.dv_xname,
+ HSCXversion[sc->sc_hscx_version]);
+ break;
+
+ default:
+ printf("%s: Error, HSCX version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_hscx_version);
+ return(0);
+ break;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pcmcia_isic.c b/sys/i4b/layer1/pcmcia_isic.c
new file mode 100644
index 000000000000..9d428a1b3cef
--- /dev/null
+++ b/sys/i4b/layer1/pcmcia_isic.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.c,v 1.3 1998/12/05 18:05:04 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:38:43 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+static int pcmcia_isic_match __P((struct device *, struct cfdata *, void *));
+static void pcmcia_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa));
+static int pcmcia_isicattach __P((struct isic_softc *sc));
+
+struct cfattach pcmcia_isic_ca = {
+ sizeof(struct pcmcia_isic_softc), pcmcia_isic_match, pcmcia_isic_attach
+};
+
+struct isic_pcmcia_card_entry {
+ int32_t vendor; /* vendor ID */
+ int32_t product; /* product ID */
+ char *cis1_info[4]; /* CIS info to match */
+ char *name; /* name of controller */
+ int function; /* expected PCMCIA function type */
+ int card_type; /* card type found */
+ isic_pcmcia_attach_func attach; /* card initialization */
+};
+
+static const struct isic_pcmcia_card_entry card_list[] = {
+
+#ifdef AVM_PCMCIA
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "AVM", "ISDN A", NULL, NULL },
+ "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia },
+#endif
+
+#ifdef ELSA_ISDNMC
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+#endif
+
+#ifdef ELSA_MCALL
+ { 0x105, 0x410a,
+ { "ELSA", "MicroLink MC all", NULL, NULL },
+ "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall },
+#endif
+
+};
+#define NUM_MATCH_ENTRIES (sizeof(card_list)/sizeof(card_list[0]))
+
+static const struct isic_pcmcia_card_entry *
+find_matching_card(pa)
+ struct pcmcia_attach_args *pa;
+{
+ int i, j;
+
+ for (i = 0; i < NUM_MATCH_ENTRIES; i++) {
+ if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor)
+ continue;
+ if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product)
+ continue;
+ if (pa->pf->function != card_list[i].function)
+ continue;
+ for (j = 0; j < 4; j++) {
+ if (card_list[i].cis1_info[j] == NULL)
+ continue; /* wildcard */
+ if (pa->card->cis1_info[j] == NULL)
+ break; /* not available */
+ if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0)
+ break; /* mismatch */
+ }
+ if (j >= 4)
+ break;
+ }
+ if (i >= NUM_MATCH_ENTRIES)
+ return NULL;
+
+ return &card_list[i];
+}
+
+/*
+ * Match card
+ */
+static int
+pcmcia_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pcmcia_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pcmcia_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_isic_softc *psc = (void*) self;
+ struct isic_softc *sc = &psc->sc_isic;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ const struct isic_pcmcia_card_entry * cde;
+
+ /* Which card is it? */
+ cde = find_matching_card(pa);
+ if (cde == NULL) return; /* oops - not found?!? */
+
+ psc->sc_pf = pa->pf;
+ cfe = pa->pf->cfe_head.sqh_first;
+
+ /* Enable the card */
+ pcmcia_function_init(pa->pf, cfe);
+ pcmcia_function_enable(pa->pf);
+
+ if (!cde->attach(psc, cfe, pa))
+ return; /* Ooops ? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+
+ /* Announce card name */
+ printf(": %s\n", cde->name);
+
+ /* MI initilization */
+ pcmcia_isicattach(sc);
+
+ /* setup interrupt */
+ psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for pcmicia cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+int
+pcmcia_isicattach(struct isic_softc *sc)
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc;
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pcmcia_isic.h b/sys/i4b/layer1/pcmcia_isic.h
new file mode 100644
index 000000000000..73f52d693020
--- /dev/null
+++ b/sys/i4b/layer1/pcmcia_isic.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.h - common definitions for pcmcia isic cards
+ * --------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.h,v 1.1 1998/12/02 06:44:30 hm Exp $
+ *
+ * last edit-date: [Mon Nov 30 21:19:14 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+struct pcmcia_isic_softc {
+ struct isic_softc sc_isic; /* parent class */
+
+ /* PCMCIA-specific goo */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+ void *sc_ih; /* interrupt handler */
+};
+
+typedef int (*isic_pcmcia_attach_func)(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+extern int isic_attach_fritzpcmcia(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsaisdnmc(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsamcall(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+
diff --git a/sys/i4b/layer2/i4b_iframe.c b/sys/i4b/layer2/i4b_iframe.c
new file mode 100644
index 000000000000..c5e38d80f8ec
--- /dev/null
+++ b/sys/i4b/layer2/i4b_iframe.c
@@ -0,0 +1,275 @@
+/*
+ * 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_iframe.c - i frame handling routines
+ * ------------------------------------------
+ *
+ * $Id: i4b_iframe.c,v 1.15 1998/12/05 18:05:06 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:26:16 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * process i frame
+ * implements the routine "I COMMAND" Q.921 03/93 pp 77
+ *---------------------------------------------------------------------------*/
+void
+i4b_rxd_i_frame(int unit, struct mbuf *m)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ u_char *ptr = m->m_data;
+ int nr;
+ int ns;
+ int p;
+ int x;
+
+ if(!((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))))
+ {
+ i4b_Dfreembuf(m);
+ return;
+ }
+
+ if((l2sc->Q921_state != ST_MULTIFR) && (l2sc->Q921_state != ST_TIMREC))
+ {
+ i4b_Dfreembuf(m);
+ DBGL2(L2_I_ERR, "i4b_rxd_i_frame", ("ERROR, state != (MF || TR)!\n"));
+ return;
+ }
+
+ x = SPLI4B();
+
+ nr = GETINR(*(ptr + OFF_INR));
+ ns = GETINS(*(ptr + OFF_INS));
+ p = GETIP(*(ptr + OFF_INR));
+
+ i4b_rxd_ack(l2sc, nr); /* last packet ack */
+
+ if(l2sc->own_busy) /* own receiver busy ? */
+ {
+ i4b_Dfreembuf(m); /* yes, discard information */
+
+ if(p == 1) /* P bit == 1 ? */
+ {
+ i4b_tx_rnr_response(l2sc, p); /* yes, tx RNR */
+ l2sc->ack_pend = 0; /* clear ACK pending */
+ }
+ }
+ else /* own receiver ready */
+ {
+ if(ns == l2sc->vr) /* expected sequence number ? */
+ {
+ M128INC(l2sc->vr); /* yes, update */
+
+ l2sc->rej_excpt = 0; /* clr reject exception */
+
+ m_adj(m, I_HDR_LEN); /* strip i frame header */
+
+ l2sc->iframe_sent = 0; /* reset i acked already */
+
+ DL_Data_Ind(l2sc->unit, m); /* pass data up */
+
+ if(!l2sc->iframe_sent)
+ {
+ i4b_tx_rr_response(l2sc, p); /* yes, tx RR */
+ l2sc->ack_pend = 0; /* clr ACK pending */
+ }
+ }
+ else /* ERROR, sequence number NOT expected */
+ {
+ i4b_Dfreembuf(m); /* discard information */
+
+ if(l2sc->rej_excpt == 1) /* already exception ? */
+ {
+ if(p == 1) /* immediate response ? */
+ {
+ i4b_tx_rr_response(l2sc, p); /* yes, tx RR */
+ l2sc->ack_pend = 0; /* clr ack pend */
+ }
+ }
+ else /* not in exception cond */
+ {
+ l2sc->rej_excpt = 1; /* set exception */
+ i4b_tx_rej_response(l2sc, p); /* tx REJ */
+ l2sc->ack_pend = 0; /* clr ack pending */
+ }
+ }
+ }
+
+ /* sequence number ranges as expected ? */
+
+ if(i4b_l2_nr_ok(nr, l2sc->va, l2sc->vs))
+ {
+ if(l2sc->Q921_state == ST_TIMREC)
+ {
+ l2sc->va = nr;
+ splx(x);
+ return;
+ }
+
+ if(l2sc->peer_busy) /* yes, other side busy ? */
+ {
+ l2sc->va = nr; /* yes, update ack count */
+ }
+ else /* other side ready */
+ {
+ if(nr == l2sc->vs) /* count expected ? */
+ {
+ l2sc->va = nr; /* update ack */
+ i4b_T200_stop(l2sc);
+ i4b_T203_restart(l2sc);
+ }
+ else
+ {
+ if(nr != l2sc->va)
+ {
+ l2sc->va = nr;
+ i4b_T200_restart(l2sc);
+ }
+ }
+ }
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc); /* sequence error */
+ l2sc->Q921_state = ST_AW_EST;
+ }
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * internal I FRAME QUEUED UP routine (Q.921 03/93 p 61)
+ *---------------------------------------------------------------------------*/
+void
+i4b_i_frame_queued_up(l2_softc_t *l2sc)
+{
+ int x;
+ struct mbuf *m;
+ u_char *ptr;
+
+ x = SPLI4B();
+
+ if(l2sc->peer_busy)
+ {
+ DBGL2(L2_I_MSG, "i4b_i_frame_queued_up", ("peer busy!\n"));
+ i4b_print_l2var(l2sc);
+ splx(x);
+ return;
+ }
+
+ if(l2sc->vs == ((l2sc->va + MAX_K_VALUE) & 127))
+ {
+ DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("V(S) == ((V(A) + k) & 127)!\n"));
+ DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("state = %s\n", i4b_print_l2state(l2sc)));
+ i4b_print_l2var(l2sc);
+ splx(x);
+ return;
+ }
+
+ IF_DEQUEUE(&l2sc->i_queue, m); /* fetch next frame to tx */
+
+ if(!m)
+ {
+ DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("ERROR, mbuf NULL after IF_DEQUEUE\n"));
+ splx(x);
+ return;
+ }
+
+ ptr = m->m_data;
+
+ PUTSAPI(SAPI_CCP, CR_CMD_TO_NT, *(ptr + OFF_SAPI));
+ PUTTEI(l2sc->tei, *(ptr + OFF_TEI));
+
+ *(ptr + OFF_INS) = (l2sc->vs << 1) & 0xfe; /* bit 0 = 0 */
+ *(ptr + OFF_INR) = (l2sc->vr << 1) & 0xfe; /* P bit = 0 */
+
+ PH_Data_Req(l2sc->unit, m, MBUF_DONTFREE); /* free'd when ack'd ! */
+
+ l2sc->iframe_sent = 1; /* in case we ack an I frame with another I frame */
+
+ if(l2sc->ua_num != UA_EMPTY) /* failsafe */
+ {
+ DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("ERROR, l2sc->ua_num: %d != UA_EMPTY\n", l2sc->ua_num));
+ i4b_print_l2var(l2sc);
+ i4b_Dfreembuf(l2sc->ua_frame);
+ }
+
+ l2sc->ua_frame = m; /* save unacked frame */
+ l2sc->ua_num = l2sc->vs; /* save frame number */
+
+ M128INC(l2sc->vs);
+
+ l2sc->ack_pend = 0;
+
+ splx(x);
+
+ if(l2sc->T200 == TIMER_IDLE)
+ {
+ i4b_T203_stop(l2sc);
+ i4b_T200_start(l2sc);
+ }
+}
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_l2.c b/sys/i4b/layer2/i4b_l2.c
new file mode 100644
index 000000000000..5cdc1c7cc582
--- /dev/null
+++ b/sys/i4b/layer2/i4b_l2.c
@@ -0,0 +1,390 @@
+/*
+ * 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_l2.c - ISDN layer 2 (Q.921)
+ * -------------------------------
+ *
+ * $Id: i4b_l2.c,v 1.23 1998/12/05 18:05:08 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:27:00 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+int i4b_dl_establish_ind(int);
+int i4b_dl_establish_cnf(int);
+int i4b_dl_release_ind(int);
+int i4b_dl_release_cnf(int);
+int i4b_dl_data_ind(int, struct mbuf *);
+int i4b_dl_unit_data_ind(int, struct mbuf *);
+
+static int i4b_mdl_command_req(int, int, int);
+
+/* from layer 2 */
+
+extern int i4b_mdl_attach_ind(int, int);
+extern int i4b_mdl_status_ind(int, int, int);
+
+/* this layers debug level */
+
+unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT;
+
+struct i4b_l2l3_func i4b_l2l3_func = {
+
+ /* Layer 2 --> Layer 3 */
+
+ (int (*)(int)) i4b_dl_establish_ind,
+ (int (*)(int)) i4b_dl_establish_cnf,
+ (int (*)(int)) i4b_dl_release_ind,
+ (int (*)(int)) i4b_dl_release_cnf,
+ (int (*)(int, struct mbuf *)) i4b_dl_data_ind,
+ (int (*)(int, struct mbuf *)) i4b_dl_unit_data_ind,
+
+ /* Layer 3 --> Layer 2 */
+
+ (int (*)(int)) i4b_dl_establish_req,
+ (int (*)(int)) i4b_dl_release_req,
+ (int (*)(int, struct mbuf *)) i4b_dl_data_req,
+ (int (*)(int, struct mbuf *)) i4b_dl_unit_data_req,
+
+ /* Layer 2 --> Layer 3 management */
+
+ (int (*)(int, int, int)) i4b_mdl_status_ind,
+
+ /* Layer 3 --> Layer 2 management */
+
+ (int (*)(int, int, int)) i4b_mdl_command_req
+};
+
+/*---------------------------------------------------------------------------*
+ * DL_ESTABLISH_REQ from layer 3
+ *---------------------------------------------------------------------------*/
+int i4b_dl_establish_req(int unit)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+
+ DBGL2(L2_PRIM, "DL-ESTABLISH-REQ", ("unit %d\n",unit));
+ i4b_l1_activate(l2sc);
+ i4b_next_l2state(l2sc, EV_DLESTRQ);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL_RELEASE_REQ from layer 3
+ *---------------------------------------------------------------------------*/
+int i4b_dl_release_req(int unit)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+
+ DBGL2(L2_PRIM, "DL-RELEASE-REQ", ("unit %d\n",unit));
+ i4b_next_l2state(l2sc, EV_DLRELRQ);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL UNIT DATA REQUEST from Layer 3
+ *---------------------------------------------------------------------------*/
+int i4b_dl_unit_data_req(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-UNIT-DATA-REQ", ("unit %d\n",unit));
+#endif
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL DATA REQUEST from Layer 3
+ *---------------------------------------------------------------------------*/
+int i4b_dl_data_req(int unit, struct mbuf *m)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ int x;
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-DATA-REQ", ("unit %d\n",unit));
+#endif
+ switch(l2sc->Q921_state)
+ {
+ case ST_AW_EST:
+ case ST_MULTIFR:
+ case ST_TIMREC:
+
+ if(IF_QFULL(&l2sc->i_queue))
+ {
+ DBGL2(L2_ERROR, "i4b_dl_data_req", ("i_queue full!!\n"));
+ i4b_Dfreembuf(m);
+ }
+ else
+ {
+ x = splimp();
+ IF_ENQUEUE(&l2sc->i_queue, m);
+ splx(x);
+ i4b_i_frame_queued_up(l2sc);
+ }
+ break;
+
+ default:
+ DBGL2(L2_ERROR, "i4b_dl_data_req", ("unit %d ERROR in state [%s], freeing mbuf\n", unit, i4b_print_l2state(l2sc)));
+ i4b_Dfreembuf(m);
+ break;
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_ph_activate_ind - link activation indication from layer 1
+ *---------------------------------------------------------------------------*/
+int
+i4b_ph_activate_ind(int unit)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+
+ DBGL1(L1_PRIM, "PH-ACTIVATE-IND", ("unit %d\n",unit));
+ l2sc->ph_active = PH_ACTIVE;
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_ph_deactivate_ind - link deactivation indication from layer 1
+ *---------------------------------------------------------------------------*/
+int
+i4b_ph_deactivate_ind(int unit)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+
+ DBGL1(L1_PRIM, "PH-DEACTIVATE-IND", ("unit %d\n",unit));
+ l2sc->ph_active = PH_INACTIVE;
+ return(0);
+}
+
+
+/*---------------------------------------------------------------------------*
+ * i4b_l2_unit_init - place layer 2 unit into known state
+ *---------------------------------------------------------------------------*/
+static void
+i4b_l2_unit_init(int unit)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+
+ l2sc->Q921_state = ST_TEI_UNAS;
+ l2sc->tei_valid = TEI_INVALID;
+ l2sc->vr = 0;
+ l2sc->vs = 0;
+ l2sc->va = 0;
+ l2sc->ack_pend = 0;
+ l2sc->rej_excpt = 0;
+ l2sc->peer_busy = 0;
+ l2sc->own_busy = 0;
+ l2sc->l3initiated = 0;
+
+ l2sc->rxd_CR = 0;
+ l2sc->rxd_PF = 0;
+ l2sc->rxd_NR = 0;
+ l2sc->RC = 0;
+ l2sc->iframe_sent = 0;
+
+ l2sc->postfsmfunc = NULL;
+
+ if(l2sc->ua_num != UA_EMPTY)
+ {
+ i4b_Dfreembuf(l2sc->ua_frame);
+ l2sc->ua_num = UA_EMPTY;
+ l2sc->ua_frame = NULL;
+ }
+
+ i4b_T200_stop(l2sc);
+ i4b_T202_stop(l2sc);
+ i4b_T203_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_mph_status_ind - status indication upward
+ *---------------------------------------------------------------------------*/
+int
+i4b_mph_status_ind(int unit, int status, int parm)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ int sendup = 1;
+
+ int x = SPLI4B();
+
+ DBGL1(L1_PRIM, "MPH-STATUS-IND", ("unit %d, status=%d, parm=%d\n", unit, status, parm));
+
+ switch(status)
+ {
+ case STI_ATTACH:
+ l2sc->unit = unit;
+ l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN;
+ l2sc->ua_frame = NULL;
+ i4b_l2_unit_init(unit);
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ /* initialize the callout handles for timeout routines */
+ callout_handle_init(&l2sc->T200_callout);
+ callout_handle_init(&l2sc->T202_callout);
+ callout_handle_init(&l2sc->T203_callout);
+#endif
+ break;
+
+ case STI_L1STAT: /* state of layer 1 */
+ break;
+
+ case STI_PDEACT: /* Timer 4 expired */
+ if((l2sc->Q921_state >= ST_AW_EST) &&
+ (l2sc->Q921_state <= ST_TIMREC))
+ {
+ DBGL2(L2_ERROR, "i4b_mph_status_ind", ("unit %d, persistent deactivation!\n", unit));
+ i4b_l2_unit_init(unit);
+ }
+ else
+ {
+ sendup = 0;
+ }
+ break;
+
+ case STI_NOL1ACC:
+ i4b_l2_unit_init(unit);
+ DBGL2(L2_ERROR, "i4b_mph_status_ind", ("unit %d, cannot access S0 bus!\n", unit));
+ break;
+
+ default:
+ DBGL2(L2_ERROR, "i4b_mph_status_ind", ("ERROR, unit %d, unknown status message!\n", unit));
+ break;
+ }
+
+ if(sendup)
+ MDL_Status_Ind(unit, status, parm); /* send up to layer 3 */
+
+ splx(x);
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * MDL_COMMAND_REQ from layer 3
+ *---------------------------------------------------------------------------*/
+int i4b_mdl_command_req(int unit, int command, int parm)
+{
+ DBGL2(L2_PRIM, "MDL-COMMAND-REQ", ("unit %d, command=%d, parm=%d\n", unit, command, parm));
+
+ switch(command)
+ {
+ case CMR_DOPEN:
+ i4b_l2_unit_init(unit);
+ break;
+ }
+
+ MPH_Command_Req(unit, command, parm);
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_ph_data_ind - process a rx'd frame got from layer 1
+ *---------------------------------------------------------------------------*/
+int
+i4b_ph_data_ind(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL1(L1_PRIM, "PH-DATA-IND", ("unit %d\n", unit));
+#endif
+ u_char *ptr = m->m_data;
+
+ if ( (*(ptr + OFF_CNTL) & 0x01) == 0 )
+ {
+ if(m->m_len < 4) /* 6 oct - 2 chksum oct */
+ {
+ DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, I-frame < 6 octetts!\n"));
+ i4b_Dfreembuf(m);
+ return(0);
+ }
+ i4b_rxd_i_frame(unit, m);
+ }
+ else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 )
+ {
+ if(m->m_len < 4) /* 6 oct - 2 chksum oct */
+ {
+ DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, S-frame < 6 octetts!\n"));
+ i4b_Dfreembuf(m);
+ return(0);
+ }
+ i4b_rxd_s_frame(unit, m);
+ }
+ else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 )
+ {
+ if(m->m_len < 3) /* 5 oct - 2 chksum oct */
+ {
+ DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, U-frame < 5 octetts!\n"));
+ i4b_Dfreembuf(m);
+ return(0);
+ }
+ i4b_rxd_u_frame(unit, m);
+ }
+ else
+ {
+ DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, bad frame rx'd - "));
+ i4b_print_frame(m->m_len, m->m_data);
+ i4b_Dfreembuf(m);
+ }
+ return(0);
+}
+
+#endif /* NI4BQ921 > 0 */
+
diff --git a/sys/i4b/layer2/i4b_l2.h b/sys/i4b/layer2/i4b_l2.h
new file mode 100644
index 000000000000..ab1dfd7cd549
--- /dev/null
+++ b/sys/i4b/layer2/i4b_l2.h
@@ -0,0 +1,339 @@
+/*
+ * 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_l2.h - ISDN layer 2 (Q.921) definitions
+ * ---------------------------------------------
+ *
+ * $Id: i4b_l2.h,v 1.14 1998/12/05 18:05:09 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:27:13 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L2_H_
+#define _I4B_L2_H_
+
+typedef struct {
+ int unit; /* unit number this entry is for */
+
+ int Q921_state; /* state according to Q.921 */
+
+ u_char last_ril; /* last reference number from TEI management */
+ u_char last_rih;
+
+ int tei_valid; /* tei is valid flag */
+#define TEI_INVALID 0
+#define TEI_VALID 1
+ int tei; /* tei, if tei flag valid */
+
+ int ph_active; /* Layer 1 active flag */
+#define PH_INACTIVE 0 /* layer 1 inactive */
+#define PH_ACTIVEPEND 1 /* already tried to activate */
+#define PH_ACTIVE 2 /* layer 1 active */
+
+ int T200; /* Multiframe timeout timer */
+ int T201; /* min time between TEI ID check */
+ int T202; /* min time between TEI ID Req messages */
+ int N202; /* TEI ID Req tx counter */
+ void(*T202func)(void *);/* function to be called when T202 expires */
+ int T203; /* max line idle time */
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ struct callout_handle T200_callout;
+ struct callout_handle T202_callout;
+ struct callout_handle T203_callout;
+#endif
+
+ int vr; /* receive sequence frame counter */
+ int vs; /* transmit sequence frame counter */
+ int va; /* acknowledge sequence frame counter */
+
+ int ack_pend; /* acknowledge pending */
+ int rej_excpt; /* reject exception */
+ int peer_busy; /* peer receiver busy */
+ int own_busy; /* own receiver busy */
+ int l3initiated; /* layer 3 initiated */
+
+ struct ifqueue i_queue; /* queue of outgoing i frames */
+#define IQUEUE_MAXLEN 20
+
+ /* this implementation only supports a k-value of 1 !!! */
+ struct mbuf *ua_frame; /* last unacked frame */
+ int ua_num; /* last unacked frame number */
+#define UA_EMPTY (-1) /* ua_frame is unused */
+
+ int rxd_CR; /* received Command Response bit */
+ int rxd_PF; /* received Poll/Final bit */
+ int rxd_NR; /* received N(R) field */
+ int RC; /* Retry Counter */
+
+ int iframe_sent; /* check if i frame acked by another i frame */
+
+ int (*postfsmfunc)(int);/* function to be called at fsm exit */
+ int postfsmarg; /* argument for above function */
+} l2_softc_t;
+
+extern l2_softc_t l2_softc[];
+
+/* Q.912 system parameters (Q.921 03/93 pp 43) */
+
+#define MAX_K_VALUE 1 /* BRI - # of outstanding frames */
+
+#define N200 3 /* max no of retransmissions */
+#define N201DEF 260 /* max no of octetts in information field */
+#define N202DEF 3 /* max no of TEI ID Request message transmissions */
+
+#define T200DEF (hz*1) /* default T200 timer value = 1 second */
+#define T201DEF T200DEF /* default T201 timer value = T200DEF */
+#define T202DEF (hz*2) /* default T202 timer value = 2 seconds */
+#define T203DEF (hz*10) /* default T203 timer value = 10 seconds*/
+
+/* modulo 128 operations */
+
+#define M128INC(v) (v)++; \
+ if((v)>127) \
+ { \
+ v = 0; \
+ }
+
+#define M128DEC(v) (v)--; \
+ if((v)<0) \
+ { \
+ v = 127;\
+ }
+
+/* P-bit values */
+
+typedef enum {
+ P0,
+ P1
+} pbit_t;
+
+/* F-bit values */
+
+typedef enum {
+ F0,
+ F1
+} fbit_t;
+
+/* CR-bit values to NT */
+
+typedef enum {
+ CR_CMD_TO_NT,
+ CR_RSP_TO_NT
+} crbit_to_nt_t;
+
+/* CR-bit values from NT */
+
+typedef enum {
+ CR_RSP_FROM_NT,
+ CR_CMD_FROM_NT
+} crbit_from_nt_t;
+
+/* address field - octett 2 */
+
+#define OFF_SAPI 0 /* SAPI offset, HDLC flag is eaten by L1 */
+#define SAPI_CCP 0 /* SAPI = 0 - call control procedures */
+#define SAPI_X25 16 /* SAPI = 16 - X.25 packet procedures */
+#define SAPI_L2M 63 /* SAPI = 63 - Layer 2 management procedures */
+
+/* extract and insert macros for SAPI octett */
+
+#define GETSAPI(octett) (((octett) >> 2) & 0x3f)
+#define PUTSAPI(sapi,cr,octett) ((octett) = (((sapi << 2) & 0xfc) | ((cr & 0x01) << 1)))
+#define GETCR(octett) (((octett) >> 1) & 0x01)
+#define GETEA(octett) ((octett) & 0x01)
+
+/* address field - octett 3 */
+
+#define OFF_TEI 1 /* TEI offset */
+#define GETTEI(octett) (((octett) >> 1) & 0x7f)
+#define PUTTEI(tei, octett) ((octett) = ((((tei) << 1) & 0xfe)) | 0x01)
+#define GROUP_TEI 127 /* broadcast TEI for LME */
+
+/* control field - octett 4 */
+
+#define OFF_CNTL 2 /* 1st byte of control field */
+
+/* S frames */
+
+#define S_FRAME_LEN 4 /* lenght of a U-frame */
+#define OFF_SRCR 2 /* 1st byte of control field, */
+ /* R-commands and R-responses */
+#define OFF_SNR 3 /* 2nd byte of control field, N(R) and PF */
+#define SPFBIT 0x01 /* poll/final bit mask */
+#define SPBITSET SPFBIT
+#define SFBITSET SPFBIT
+#define GETSNR(octett) (((octett) >> 1) & 0x7f)
+#define GETSPF(octett) ((octett) & SPFBIT)
+#define RR 0x01 /* RR and bit 0 set */
+#define RNR 0x05 /* RNR and bit 0 set */
+#define REJ 0x09 /* REJ and bit 0 set */
+
+/* U frames */
+
+#define UI_HDR_LEN 3 /* length of UI header in front of L3 frame */
+#define U_FRAME_LEN 3 /* lenght of a U-frame */
+#define UPFBIT 0x10 /* poll/final bit mask */
+#define UPBITSET UPFBIT
+#define UFBITSET UPFBIT
+#define GETUPF(octett) (((octett) >> 4) & 0x01)
+
+/* commands/responses with pf bit set to 0 */
+
+#define SABME 0x6f
+#define DM 0x0f
+#define UI 0x03
+#define DISC 0x43
+#define UA 0x63
+#define FRMR 0x87
+#define XID 0xaf
+
+/* control field - octett 3 */
+
+#define OFF_MEI 3 /* 2nd byte of control field */
+
+/* control field - octett 4,5 */
+
+#define OFF_RIL 4 /* Ri low byte */
+#define OFF_RIH 5 /* Ri high byte */
+
+/* control field - octett 6 */
+
+#define OFF_MT 6 /* Message Type */
+#define OFF_AI 7 /* Action Indicator */
+#define GET_TEIFROMAI(octett) (((octett) >> 1) & 0x7f)
+
+/* I frame */
+
+#define I_HDR_LEN 4 /* length of I header in front of L3 frame */
+#define OFF_INS 2 /* transmit sequence number */
+#define OFF_INR 3 /* receive sequence number */
+#define IPFBIT 0x01 /* poll/final bit mask */
+#define IPBITSET 0x01
+#define GETINR(octett) (((octett) >> 1) & 0x7f)
+#define GETINS(octett) (((octett) >> 1) & 0x7f)
+#define GETIP(octett) ((octett) & IPFBIT)
+
+/* structure of a TEI management frame */
+
+#define TEI_MGMT_FRM_LEN 8 /* frame length */
+#define TEIM_SAPIO 0x00 /* SAPI, CR, EA */
+#define TEIM_TEIO 0x01 /* TEI, EA */
+#define TEIM_UIO 0x02 /* frame type = UI = 0x03 */
+#define TEIM_MEIO 0x03 /* management entity id = 0x0f */
+#define MEI 0x0f
+#define TEIM_RILO 0x04 /* reference number, low */
+#define TEIM_RIHO 0x05 /* reference number, high */
+#define TEIM_MTO 0x06 /* message type */
+#define MT_ID_REQEST 0x01
+#define MT_ID_ASSIGN 0x02
+#define MT_ID_DENY 0x03
+#define MT_ID_CHK_REQ 0x04
+#define MT_ID_CHK_RSP 0x05
+#define MT_ID_REMOVE 0x06
+#define MT_ID_VERIFY 0x07
+#define TEIM_AIO 0x07 /* action indicator */
+
+/* i4b_mdl_error_ind codes */
+
+enum MDL_ERROR_CODES {
+ MDL_ERR_A,
+ MDL_ERR_B,
+ MDL_ERR_C,
+ MDL_ERR_D,
+ MDL_ERR_E,
+ MDL_ERR_F,
+ MDL_ERR_G,
+ MDL_ERR_H,
+ MDL_ERR_I,
+ MDL_ERR_J,
+ MDL_ERR_K,
+ MDL_ERR_L,
+ MDL_ERR_M,
+ MDL_ERR_N,
+ MDL_ERR_O,
+ MDL_ERR_MAX
+};
+
+/* forward decl */
+
+extern void i4b_acknowledge_pending ( l2_softc_t *l2sc );
+extern struct mbuf * i4b_build_s_frame ( l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type );
+extern struct mbuf * i4b_build_u_frame ( l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type );
+extern void i4b_clear_exception_conditions ( l2_softc_t *l2sc );
+extern int i4b_dl_data_req ( int unit, struct mbuf *m );
+extern int i4b_dl_establish_req ( int unit );
+extern int i4b_dl_release_req ( int unit );
+extern int i4b_dl_unit_data_req ( int unit, struct mbuf *m );
+extern void i4b_enquiry_response ( l2_softc_t *l2sc );
+extern void i4b_establish_data_link ( l2_softc_t *l2sc );
+extern void i4b_invoke_retransmission ( l2_softc_t *l2sc, int nr );
+extern void i4b_i_frame_queued_up ( l2_softc_t *l2sc );
+extern void i4b_l1_activate ( l2_softc_t *l2sc );
+extern int i4b_l2_nr_ok ( int nr, int va, int vs );
+extern void i4b_make_rand_ri ( l2_softc_t *l2sc );
+extern void i4b_mdl_assign_ind ( l2_softc_t *l2sc );
+extern void i4b_mdl_error_ind ( l2_softc_t *l2sc, char *where, int errorcode );
+extern int i4b_mph_attach_ind ( int unit, int type );
+extern int i4b_mph_status_ind ( int unit, int status, int parm );
+extern void i4b_next_l2state ( l2_softc_t *l2sc, int event );
+extern void i4b_nr_error_recovery ( l2_softc_t *l2sc );
+extern int i4b_ph_activate_ind ( int unit );
+extern int i4b_ph_deactivate_ind ( int unit );
+extern int i4b_ph_data_ind ( int unit, struct mbuf *m );
+extern void i4b_print_frame ( int len, u_char *buf );
+extern char *i4b_print_l2state ( l2_softc_t *l2sc );
+extern void i4b_print_l2var ( l2_softc_t *l2sc );
+extern void i4b_rxd_ack(l2_softc_t *l2sc, int nr);
+extern void i4b_rxd_i_frame ( int unit, struct mbuf *m );
+extern void i4b_rxd_s_frame ( int unit, struct mbuf *m );
+extern void i4b_rxd_u_frame ( int unit, struct mbuf *m );
+extern void i4b_T200_restart ( l2_softc_t *l2sc );
+extern void i4b_T200_start ( l2_softc_t *l2sc );
+extern void i4b_T200_stop ( l2_softc_t *l2sc );
+extern void i4b_T202_start ( l2_softc_t *l2sc );
+extern void i4b_T202_stop ( l2_softc_t *l2sc );
+extern void i4b_T203_restart ( l2_softc_t *l2sc );
+extern void i4b_T203_start ( l2_softc_t *l2sc );
+extern void i4b_T203_stop ( l2_softc_t *l2sc );
+extern void i4b_tei_assign ( l2_softc_t *l2sc );
+extern void i4b_tei_chkresp ( l2_softc_t *l2sc );
+extern void i4b_tei_rxframe ( int unit, struct mbuf *m );
+extern void i4b_tei_verify ( l2_softc_t *l2sc );
+extern void i4b_transmit_enquire ( l2_softc_t *l2sc );
+extern void i4b_tx_disc ( l2_softc_t *l2sc, pbit_t pbit );
+extern void i4b_tx_dm ( l2_softc_t *l2sc, fbit_t fbit );
+extern void i4b_tx_frmr ( l2_softc_t *l2sc, fbit_t fbit );
+extern void i4b_tx_rej_response ( l2_softc_t *l2sc, fbit_t fbit );
+extern void i4b_tx_rnr_command ( l2_softc_t *l2sc, pbit_t pbit );
+extern void i4b_tx_rnr_response ( l2_softc_t *l2sc, fbit_t fbit );
+extern void i4b_tx_rr_command ( l2_softc_t *l2sc, pbit_t pbit );
+extern void i4b_tx_rr_response ( l2_softc_t *l2sc, fbit_t fbit );
+extern void i4b_tx_sabme ( l2_softc_t *l2sc, pbit_t pbit );
+extern void i4b_tx_ua ( l2_softc_t *l2sc, fbit_t fbit );
+
+#endif /* _I4B_L2_H_ */
diff --git a/sys/i4b/layer2/i4b_l2fsm.c b/sys/i4b/layer2/i4b_l2fsm.c
new file mode 100644
index 000000000000..113167c11429
--- /dev/null
+++ b/sys/i4b/layer2/i4b_l2fsm.c
@@ -0,0 +1,1593 @@
+/*
+ * 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_l2fsm.c - layer 2 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l2fsm.c,v 1.13 1998/12/05 18:05:11 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:28:15 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+l2_softc_t l2_softc[ISIC_MAXUNIT];
+
+static char *l2state_text[N_STATES] = {
+ "ST_TEI_UNAS",
+ "ST_ASG_AW_TEI",
+ "ST_EST_AW_TEI",
+ "ST_TEI_ASGD",
+
+ "ST_AW_EST",
+ "ST_AW_REL",
+ "ST_MULTIFR",
+ "ST_TIMREC",
+
+ "ST_SUBSET",
+ "Illegal State"
+};
+
+static char *l2event_text[N_EVENTS] = {
+ "EV_DLESTRQ",
+ "EV_DLUDTRQ",
+ "EV_MDASGRQ",
+ "EV_MDERRRS",
+ "EV_PSDEACT",
+ "EV_MDREMRQ",
+ "EV_RXSABME",
+ "EV_RXDISC",
+ "EV_RXUA",
+ "EV_RXDM",
+ "EV_T200EXP",
+ "EV_DLDATRQ",
+ "EV_DLRELRQ",
+ "EV_T203EXP",
+ "EV_OWNBUSY",
+ "EV_OWNRDY",
+ "EV_RXRR",
+ "EV_RXREJ",
+ "EV_RXRNR",
+ "EV_RXFRMR",
+ "Illegal Event"
+};
+
+static void F_TU01 __P((l2_softc_t *));
+static void F_TU03 __P((l2_softc_t *));
+
+static void F_TA03 __P((l2_softc_t *));
+static void F_TA04 __P((l2_softc_t *));
+static void F_TA05 __P((l2_softc_t *));
+
+static void F_TE03 __P((l2_softc_t *));
+static void F_TE04 __P((l2_softc_t *));
+static void F_TE05 __P((l2_softc_t *));
+
+static void F_T01 __P((l2_softc_t *));
+static void F_T05 __P((l2_softc_t *));
+static void F_T06 __P((l2_softc_t *));
+static void F_T07 __P((l2_softc_t *));
+static void F_T08 __P((l2_softc_t *));
+static void F_T09 __P((l2_softc_t *));
+static void F_T10 __P((l2_softc_t *));
+static void F_T13 __P((l2_softc_t *));
+
+static void F_AE01 __P((l2_softc_t *));
+static void F_AE05 __P((l2_softc_t *));
+static void F_AE06 __P((l2_softc_t *));
+static void F_AE07 __P((l2_softc_t *));
+static void F_AE08 __P((l2_softc_t *));
+static void F_AE09 __P((l2_softc_t *));
+static void F_AE10 __P((l2_softc_t *));
+static void F_AE11 __P((l2_softc_t *));
+static void F_AE12 __P((l2_softc_t *));
+
+static void F_AR05 __P((l2_softc_t *));
+static void F_AR06 __P((l2_softc_t *));
+static void F_AR07 __P((l2_softc_t *));
+static void F_AR08 __P((l2_softc_t *));
+static void F_AR09 __P((l2_softc_t *));
+static void F_AR10 __P((l2_softc_t *));
+static void F_AR11 __P((l2_softc_t *));
+
+static void F_MF01 __P((l2_softc_t *));
+static void F_MF05 __P((l2_softc_t *));
+static void F_MF06 __P((l2_softc_t *));
+static void F_MF07 __P((l2_softc_t *));
+static void F_MF08 __P((l2_softc_t *));
+static void F_MF09 __P((l2_softc_t *));
+static void F_MF10 __P((l2_softc_t *));
+static void F_MF11 __P((l2_softc_t *));
+static void F_MF12 __P((l2_softc_t *));
+static void F_MF13 __P((l2_softc_t *));
+static void F_MF14 __P((l2_softc_t *));
+static void F_MF15 __P((l2_softc_t *));
+static void F_MF16 __P((l2_softc_t *));
+static void F_MF17 __P((l2_softc_t *));
+static void F_MF18 __P((l2_softc_t *));
+static void F_MF19 __P((l2_softc_t *));
+static void F_MF20 __P((l2_softc_t *));
+
+static void F_TR01 __P((l2_softc_t *));
+static void F_TR05 __P((l2_softc_t *));
+static void F_TR06 __P((l2_softc_t *));
+static void F_TR07 __P((l2_softc_t *));
+static void F_TR08 __P((l2_softc_t *));
+static void F_TR09 __P((l2_softc_t *));
+static void F_TR10 __P((l2_softc_t *));
+static void F_TR11 __P((l2_softc_t *));
+static void F_TR12 __P((l2_softc_t *));
+static void F_TR13 __P((l2_softc_t *));
+static void F_TR15 __P((l2_softc_t *));
+static void F_TR16 __P((l2_softc_t *));
+static void F_TR17 __P((l2_softc_t *));
+static void F_TR18 __P((l2_softc_t *));
+static void F_TR19 __P((l2_softc_t *));
+static void F_TR20 __P((l2_softc_t *));
+static void F_ILL __P((l2_softc_t *));
+static void F_NCNA __P((l2_softc_t *));
+
+/*---------------------------------------------------------------------------*
+ * FSM illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ILL(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_ERR, "F_ILL", ("FSM function F_ILL executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM No change, No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NCNA(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_NCNA", ("FSM function F_NCNA executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * layer 2 state transition table
+ *---------------------------------------------------------------------------*/
+struct l2state_tab {
+ void (*func) __P((l2_softc_t *)); /* function to execute */
+ int newstate; /* next state */
+} l2state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: ST_TEI_UNAS, ST_ASG_AW_TEI, ST_EST_AW_TEI, ST_TEI_ASGD, ST_AW_EST, ST_AW_REL, ST_MULTIFR, ST_TIMREC, ST_SUBSET, ILLEGAL STATE */
+/* -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_DLESTRQ*/{ {F_TU01, ST_EST_AW_TEI}, {F_NCNA, ST_EST_AW_TEI}, {F_ILL, ST_ILL}, {F_T01, ST_AW_EST}, {F_AE01, ST_AW_EST}, {F_ILL, ST_ILL}, {F_MF01, ST_AW_EST}, {F_TR01, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_DLUDTRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_MDASGRQ*/{ {F_TU03, ST_TEI_ASGD}, {F_TA03, ST_TEI_ASGD}, {F_TE03, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_MDERRRS*/{ {F_ILL, ST_ILL}, {F_TA04, ST_TEI_UNAS}, {F_TE04, ST_TEI_UNAS}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_PSDEACT*/{ {F_ILL, ST_ILL}, {F_TA05, ST_TEI_UNAS}, {F_TE05, ST_TEI_UNAS}, {F_T05, ST_TEI_ASGD}, {F_AE05, ST_TEI_ASGD}, {F_AR05, ST_TEI_ASGD}, {F_MF05, ST_TEI_ASGD}, {F_TR05, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_MDREMRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T06, ST_TEI_UNAS}, {F_AE06, ST_TEI_UNAS}, {F_AR06, ST_TEI_UNAS}, {F_MF06, ST_TEI_UNAS}, {F_TR06, ST_TEI_UNAS}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXSABME*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T07, ST_SUBSET}, {F_AE07, ST_AW_EST}, {F_AR07, ST_AW_REL}, {F_MF07, ST_MULTIFR}, {F_TR07, ST_MULTIFR}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXDISC */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T08, ST_TEI_ASGD}, {F_AE08, ST_AW_EST}, {F_AR08, ST_AW_REL}, {F_MF08, ST_TEI_ASGD}, {F_TR08, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXUA */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T09, ST_TEI_ASGD}, {F_AE09, ST_SUBSET}, {F_AR09, ST_SUBSET}, {F_MF09, ST_MULTIFR}, {F_TR09, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXDM */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T10, ST_SUBSET}, {F_AE10, ST_SUBSET}, {F_AR10, ST_SUBSET}, {F_MF10, ST_SUBSET}, {F_TR10, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_T200EXP*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_AE11, ST_SUBSET}, {F_AR11, ST_SUBSET}, {F_MF11, ST_TIMREC}, {F_TR11, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_DLDATRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_AE12, ST_AW_EST}, {F_ILL, ST_ILL}, {F_MF12, ST_MULTIFR}, {F_TR12, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_DLRELRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T13, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF13, ST_AW_REL}, {F_TR13, ST_AW_REL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_T203EXP*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF14, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_OWNBUSY*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF15, ST_MULTIFR}, {F_TR15, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_OWNRDY */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF16, ST_MULTIFR}, {F_TR16, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXRR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF17, ST_SUBSET}, {F_TR17, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXREJ */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF18, ST_SUBSET}, {F_TR18, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXRNR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF19, ST_SUBSET}, {F_TR19, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_RXFRMR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF20, ST_AW_EST}, {F_TR20, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} },
+/*EV_ILL */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler, executes function and sets new state
+ *---------------------------------------------------------------------------*/
+void i4b_next_l2state(l2_softc_t *l2sc, int event)
+{
+ int currstate, newstate;
+
+ /* check event number */
+ if(event > N_EVENTS)
+ panic("i4b_l2fsm.c: event > N_EVENTS\n");
+
+ /* get current state and check it */
+ if((currstate = l2sc->Q921_state) > N_STATES) /* failsafe */
+ panic("i4b_l2fsm.c: currstate > N_STATES\n");
+
+ /* get new state and check it */
+ if((newstate = l2state_tab[event][currstate].newstate) > N_STATES)
+ panic("i4b_l2fsm.c: newstate > N_STATES\n");
+
+
+ if(newstate != ST_SUBSET)
+ { /* state function does NOT set new state */
+ DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM event [%s]: [%s/%d => %s/%d]\n",
+ l2event_text[event],
+ l2state_text[currstate], currstate,
+ l2state_text[newstate], newstate));
+ }
+
+ /* execute state transition function */
+ (*l2state_tab[event][currstate].func)(l2sc);
+
+ if(newstate == ST_SUBSET)
+ { /* state function DOES set new state */
+ DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM S-event [%s]: [%s => %s]\n", l2event_text[event],
+ l2state_text[currstate],
+ l2state_text[l2sc->Q921_state]));
+ }
+
+ /* check for illegal new state */
+
+ if(newstate == ST_ILL)
+ {
+ newstate = currstate;
+ DBGL2(L2_F_ERR, "i4b_next_l2state", ("FSM illegal state, state = %s, event = %s!\n",
+ l2state_text[currstate],
+ l2event_text[event]));
+ }
+
+ /* check if state machine function has to set new state */
+
+ if(newstate != ST_SUBSET)
+ l2sc->Q921_state = newstate; /* no, we set new state */
+
+ if(l2sc->postfsmfunc != NULL)
+ {
+ DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM executing postfsmfunc!\n"));
+ (*l2sc->postfsmfunc)(l2sc->postfsmarg);
+ l2sc->postfsmfunc = NULL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *i4b_print_l2state(l2_softc_t *l2sc)
+{
+ return((char *) l2state_text[l2sc->Q921_state]);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_UNAS event dl establish request
+ *---------------------------------------------------------------------------*/
+static void
+F_TU01(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TU01", ("FSM function F_TU01 executing\n"));
+ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_UNAS event mdl assign request
+ *---------------------------------------------------------------------------*/
+static void
+F_TU03(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TU03", ("FSM function F_TU03 executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_ASG_AW_TEI event mdl assign request
+ *---------------------------------------------------------------------------*/
+static void
+F_TA03(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TA03", ("FSM function F_TA03 executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_ASG_AW_TEI event mdl error response
+ *---------------------------------------------------------------------------*/
+static void
+F_TA04(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TA04", ("FSM function F_TA04 executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_ASG_AW_TEI event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_TA05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TA05", ("FSM function F_TA05 executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_EST_AW_TEI event mdl assign request
+ *---------------------------------------------------------------------------*/
+static void
+F_TE03(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TE03", ("FSM function F_TE03 executing\n"));
+ i4b_establish_data_link(l2sc);
+ l2sc->l3initiated = 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_EST_AW_TEI event mdl error response
+ *---------------------------------------------------------------------------*/
+static void
+F_TE04(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TE04", ("FSM function F_TE04 executing\n"));
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_EST_AW_TEI event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_TE05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TE05", ("FSM function F_TE05 executing\n"));
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event dl establish request
+ *---------------------------------------------------------------------------*/
+static void
+F_T01(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T01", ("FSM function F_T01 executing\n"));
+ i4b_establish_data_link(l2sc);
+ l2sc->l3initiated = 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_T05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T05", ("FSM function F_T05 executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event mdl remove request
+ *---------------------------------------------------------------------------*/
+static void
+F_T06(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T06", ("FSM function F_T06 executing\n"));
+/*XXX*/ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event rx'd SABME
+ *---------------------------------------------------------------------------*/
+static void
+F_T07(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T07", ("FSM function F_T07 executing\n"));
+
+/* XXX */
+#ifdef NOTDEF
+ if(NOT able to establish)
+ {
+ i4b_tx_dm(l2sc, l2sc->rxd_PF);
+ l2sc->Q921_state = ST_TEI_ASGD;
+ return;
+ }
+#endif
+
+ i4b_clear_exception_conditions(l2sc);
+
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE);
+
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+
+ l2sc->vs = 0;
+ l2sc->va = 0;
+ l2sc->vr = 0;
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Est_Ind_A;
+
+ i4b_T203_start(l2sc);
+
+ l2sc->Q921_state = ST_MULTIFR;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event rx'd DISC
+ *---------------------------------------------------------------------------*/
+static void
+F_T08(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T08", ("FSM function F_T08 executing\n"));
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE);
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event rx'd UA
+ *---------------------------------------------------------------------------*/
+static void
+F_T09(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T09", ("FSM function F_T09 executing\n"));
+ i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_C);
+ i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_D);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event rx'd DM
+ *---------------------------------------------------------------------------*/
+static void
+F_T10(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T10", ("FSM function F_T10 executing\n"));
+
+ if(l2sc->rxd_PF)
+ {
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+ else
+ {
+#ifdef NOTDEF
+ if(NOT able_to_etablish)
+ {
+ l2sc->Q921_state = ST_TEI_ASGD;
+ return;
+ }
+#endif
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 1;
+
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TEI_ASGD event dl release request
+ *---------------------------------------------------------------------------*/
+static void
+F_T13(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_T13", ("FSM function F_T13 executing\n"));
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event dl establish request
+ *---------------------------------------------------------------------------*/
+static void
+F_AE01(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE01", ("FSM function F_AE01 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->l3initiated = 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_AE05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE05", ("FSM function F_AE05 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event mdl remove request
+ *---------------------------------------------------------------------------*/
+static void
+F_AE06(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE06", ("FSM function F_AE06 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+
+/*XXX*/ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event rx'd SABME
+ *---------------------------------------------------------------------------*/
+static void
+F_AE07(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE07", ("FSM function F_AE07 executing\n"));
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE);
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event rx'd DISC
+ *---------------------------------------------------------------------------*/
+static void
+F_AE08(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE08", ("FSM function F_AE08 executing\n"));
+ i4b_tx_dm(l2sc, l2sc->rxd_PF);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event rx'd UA
+ *---------------------------------------------------------------------------*/
+static void
+F_AE09(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE09", ("FSM function F_AE09 executing\n"));
+
+ if(l2sc->rxd_PF == 0)
+ {
+ i4b_mdl_error_ind(l2sc, "F_AE09", MDL_ERR_D);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+ else
+ {
+ if(l2sc->l3initiated)
+ {
+ l2sc->l3initiated = 0;
+ l2sc->vr = 0;
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Est_Cnf_A;
+ }
+ else
+ {
+ if(l2sc->vs != l2sc->va)
+ {
+ i4b_Dcleanifq(&l2sc->i_queue);
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Est_Ind_A;
+ }
+ }
+
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE);
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+
+ l2sc->vs = 0;
+ l2sc->va = 0;
+
+ l2sc->Q921_state = ST_MULTIFR;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event rx'd DM
+ *---------------------------------------------------------------------------*/
+static void
+F_AE10(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE10", ("FSM function F_AE10 executing\n"));
+
+ if(l2sc->rxd_PF == 0)
+ {
+ l2sc->Q921_state = ST_AW_EST;
+ }
+ else
+ {
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event T200 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_AE11(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE11", ("FSM function F_AE11 executing\n"));
+
+ if(l2sc->RC >= N200)
+ {
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ i4b_mdl_error_ind(l2sc, "F_AE11", MDL_ERR_G);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+ else
+ {
+ l2sc->RC++;
+
+ i4b_tx_sabme(l2sc, P1);
+
+ i4b_T200_start(l2sc);
+
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_EST event dl data request
+ *---------------------------------------------------------------------------*/
+static void
+F_AE12(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AE12", ("FSM function F_AE12 executing\n"));
+
+ if(l2sc->l3initiated == 0)
+ {
+ i4b_i_frame_queued_up(l2sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_AR05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR05", ("FSM function F_AR05 executing\n"));
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+
+ i4b_T200_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event mdl remove request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR06(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR06", ("FSM function F_AR06 executing\n"));
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+
+ i4b_T200_stop(l2sc);
+
+/*XXX*/ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event rx'd SABME
+ *---------------------------------------------------------------------------*/
+static void
+F_AR07(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR07", ("FSM function F_AR07 executing\n"));
+ i4b_tx_dm(l2sc, l2sc->rxd_PF);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event rx'd DISC
+ *---------------------------------------------------------------------------*/
+static void
+F_AR08(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR08", ("FSM function F_AR08 executing\n"));
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE);
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event rx'd UA
+ *---------------------------------------------------------------------------*/
+static void
+F_AR09(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR09", ("FSM function F_AR09 executing\n"));
+
+ if(l2sc->rxd_PF)
+ {
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+
+ i4b_T200_stop(l2sc);
+
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+ else
+ {
+ i4b_mdl_error_ind(l2sc, "F_AR09", MDL_ERR_D);
+
+ l2sc->Q921_state = ST_AW_REL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event rx'd DM
+ *---------------------------------------------------------------------------*/
+static void
+F_AR10(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR10", ("FSM function F_AR10 executing\n"));
+
+ if(l2sc->rxd_PF)
+ {
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+
+ i4b_T200_stop(l2sc);
+
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+ else
+ {
+ l2sc->Q921_state = ST_AW_REL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_AW_REL event T200 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_AR11(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_AR11", ("FSM function F_AR11 executing\n"));
+
+ if(l2sc->RC >= N200)
+ {
+ i4b_mdl_error_ind(l2sc, "F_AR11", MDL_ERR_H);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Cnf_A;
+
+ l2sc->Q921_state = ST_TEI_ASGD;
+ }
+ else
+ {
+ l2sc->RC++;
+
+ i4b_tx_disc(l2sc, P1);
+
+ i4b_T200_start(l2sc);
+
+ l2sc->Q921_state = ST_AW_REL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event dl establish request
+ *---------------------------------------------------------------------------*/
+static void
+F_MF01(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF01", ("FSM function F_MF01 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_MF05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF05", ("FSM function F_MF05 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event mdl remove request
+ *---------------------------------------------------------------------------*/
+static void
+F_MF06(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF06", ("FSM function F_MF06 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_stop(l2sc);
+
+/*XXX*/ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd SABME
+ *---------------------------------------------------------------------------*/
+static void
+F_MF07(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF07", ("FSM function F_MF07 executing\n"));
+
+ i4b_clear_exception_conditions(l2sc);
+
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE);
+
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+
+ i4b_mdl_error_ind(l2sc, "F_MF07", MDL_ERR_F);
+
+ if(l2sc->vs != l2sc->va)
+ {
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Est_Ind_A;
+ }
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+
+ l2sc->vs = 0;
+ l2sc->va = 0;
+ l2sc->vr = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd DISC
+ *---------------------------------------------------------------------------*/
+static void
+F_MF08(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF08", ("FSM function F_MF08 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE);
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd UA
+ *---------------------------------------------------------------------------*/
+static void
+F_MF09(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF09", ("FSM function F_MF09 executing\n"));
+ if(l2sc->rxd_PF)
+ i4b_mdl_error_ind(l2sc, "F_MF09", MDL_ERR_C);
+ else
+ i4b_mdl_error_ind(l2sc, "F_MF09", MDL_ERR_D);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd DM
+ *---------------------------------------------------------------------------*/
+static void
+F_MF10(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF10", ("FSM function F_MF10 executing\n"));
+
+ if(l2sc->rxd_PF)
+ {
+ i4b_mdl_error_ind(l2sc, "F_MF10", MDL_ERR_B);
+
+ l2sc->Q921_state = ST_MULTIFR;
+ }
+ else
+ {
+ i4b_mdl_error_ind(l2sc, "F_MF10", MDL_ERR_E);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event T200 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_MF11(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF11", ("FSM function F_MF11 executing\n"));
+
+ l2sc->RC = 0;
+
+ i4b_transmit_enquire(l2sc);
+
+ l2sc->RC++;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event dl data request
+ *---------------------------------------------------------------------------*/
+static void
+F_MF12(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF12", ("FSM function F_MF12 executing\n"));
+
+ i4b_i_frame_queued_up(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event dl release request
+ *---------------------------------------------------------------------------*/
+static void
+F_MF13(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF13", ("FSM function F_MF13 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->RC = 0;
+
+ i4b_tx_disc(l2sc, P1);
+
+ i4b_T203_stop(l2sc);
+ i4b_T200_restart(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event T203 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_MF14(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF14", ("FSM function F_MF14 executing\n"));
+
+ i4b_transmit_enquire(l2sc);
+
+ l2sc->RC = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event set own rx busy
+ *---------------------------------------------------------------------------*/
+static void
+F_MF15(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF15", ("FSM function F_MF15 executing\n"));
+
+ if(l2sc->own_busy == 0)
+ {
+ l2sc->own_busy = 1;
+
+ i4b_tx_rnr_response(l2sc, F0); /* wrong in Q.921 03/93 p 64 */
+
+ l2sc->ack_pend = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event clear own rx busy
+ *---------------------------------------------------------------------------*/
+static void
+F_MF16(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF16", ("FSM function F_MF16 executing\n"));
+
+ if(l2sc->own_busy != 0)
+ {
+ l2sc->own_busy = 0;
+
+ i4b_tx_rr_response(l2sc, F0); /* wrong in Q.921 03/93 p 64 */
+
+ l2sc->ack_pend = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd RR
+ *---------------------------------------------------------------------------*/
+static void
+F_MF17(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF17", ("FSM function F_MF17 executing\n"));
+
+ l2sc->peer_busy = 0;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_mdl_error_ind(l2sc, "F_MF17", MDL_ERR_A);
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ if(l2sc->rxd_NR == l2sc->vs)
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_stop(l2sc);
+ i4b_T203_restart(l2sc);
+ }
+ else if(l2sc->rxd_NR != l2sc->va)
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_restart(l2sc);
+ }
+ l2sc->Q921_state = ST_MULTIFR;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd REJ
+ *---------------------------------------------------------------------------*/
+static void
+F_MF18(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF18", ("FSM function F_MF18 executing\n"));
+
+ l2sc->peer_busy = 0;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_mdl_error_ind(l2sc, "F_MF18", MDL_ERR_A);
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+ i4b_invoke_retransmission(l2sc, l2sc->rxd_NR);
+ l2sc->Q921_state = ST_MULTIFR;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd RNR
+ *---------------------------------------------------------------------------*/
+static void
+F_MF19(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF19", ("FSM function F_MF19 executing\n"));
+
+ l2sc->peer_busy = 1;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_mdl_error_ind(l2sc, "F_MF19", MDL_ERR_A);
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T203_stop(l2sc);
+ i4b_T200_restart(l2sc);
+ l2sc->Q921_state = ST_MULTIFR;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_MULTIFR event rx'd FRMR
+ *---------------------------------------------------------------------------*/
+static void
+F_MF20(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_MF20", ("FSM function F_MF20 executing\n"));
+
+ i4b_mdl_error_ind(l2sc, "F_MF20", MDL_ERR_K);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event dl establish request
+ *---------------------------------------------------------------------------*/
+static void
+F_TR01(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR01", ("FSM function F_TR01 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 1;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event persistent deactivation
+ *---------------------------------------------------------------------------*/
+static void
+F_TR05(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR05", ("FSM function F_TR05 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event mdl remove request
+ *---------------------------------------------------------------------------*/
+static void
+F_TR06(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR06", ("FSM function F_TR06 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+
+/*XXX*/ i4b_mdl_assign_ind(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd SABME
+ *---------------------------------------------------------------------------*/
+static void
+F_TR07(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR07", ("FSM function F_TR07 executing\n"));
+
+ i4b_clear_exception_conditions(l2sc);
+
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE);
+
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+
+ i4b_mdl_error_ind(l2sc, "F_TR07", MDL_ERR_F);
+
+ if(l2sc->vs != l2sc->va)
+ {
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Est_Ind_A;
+ }
+
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+
+ l2sc->vs = 0;
+ l2sc->va = 0;
+ l2sc->vr = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd DISC
+ *---------------------------------------------------------------------------*/
+static void
+F_TR08(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR08", ("FSM function F_TR08 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+ MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE);
+ i4b_tx_ua(l2sc, l2sc->rxd_PF);
+
+ l2sc->postfsmarg = l2sc->unit;
+ l2sc->postfsmfunc = DL_Rel_Ind_A;
+
+ i4b_T200_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd UA
+ *---------------------------------------------------------------------------*/
+static void
+F_TR09(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR09", ("FSM function F_TR09 executing\n"));
+ if(l2sc->rxd_PF)
+ i4b_mdl_error_ind(l2sc, "F_TR09", MDL_ERR_C);
+ else
+ i4b_mdl_error_ind(l2sc, "F_TR09", MDL_ERR_D);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd DM
+ *---------------------------------------------------------------------------*/
+static void
+F_TR10(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR10", ("FSM function F_TR10 executing\n"));
+
+ if(l2sc->rxd_PF)
+ {
+ i4b_mdl_error_ind(l2sc, "F_TR10", MDL_ERR_B);
+ }
+ else
+ {
+ i4b_mdl_error_ind(l2sc, "F_TR10", MDL_ERR_E);
+ }
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event T200 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_TR11(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR11", ("FSM function F_TR11 executing\n"));
+
+ if(l2sc->RC >= N200)
+ {
+ i4b_mdl_error_ind(l2sc, "F_TR11", MDL_ERR_I);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+
+ l2sc->Q921_state = ST_AW_EST;
+ }
+ else
+ {
+ i4b_transmit_enquire(l2sc);
+
+ l2sc->RC++;
+
+ l2sc->Q921_state = ST_TIMREC;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event dl data request
+ *---------------------------------------------------------------------------*/
+static void
+F_TR12(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR12", ("FSM function F_TR12 executing\n"));
+
+ i4b_i_frame_queued_up(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event dl release request
+ *---------------------------------------------------------------------------*/
+static void
+F_TR13(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR13", ("FSM function F_TR13 executing\n"));
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ l2sc->RC = 0;
+
+ i4b_tx_disc(l2sc, P1);
+
+ i4b_T200_restart(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event set own rx busy
+ *---------------------------------------------------------------------------*/
+static void
+F_TR15(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR15", ("FSM function F_TR15 executing\n"));
+
+ if(l2sc->own_busy == 0)
+ {
+ l2sc->own_busy = 1;
+
+ i4b_tx_rnr_response(l2sc, F0);
+
+ l2sc->ack_pend = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event clear own rx busy
+ *---------------------------------------------------------------------------*/
+static void
+F_TR16(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR16", ("FSM function F_TR16 executing\n"));
+
+ if(l2sc->own_busy != 0)
+ {
+ l2sc->own_busy = 0;
+
+ i4b_tx_rr_response(l2sc, F0); /* this is wrong */
+ /* in Q.921 03/93 p 74 ! */
+ l2sc->ack_pend = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd RR
+ *---------------------------------------------------------------------------*/
+static void
+F_TR17(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR17", ("FSM function F_TR17 executing\n"));
+
+ l2sc->peer_busy = 0;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+ i4b_invoke_retransmission(l2sc, l2sc->rxd_NR);
+ l2sc->Q921_state = ST_MULTIFR;
+ return;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ return;
+ }
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ l2sc->Q921_state = ST_TIMREC;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event
+ *---------------------------------------------------------------------------*/
+static void
+F_TR18(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR18", ("FSM function F_TR18 executing\n"));
+
+ l2sc->peer_busy = 0;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_stop(l2sc);
+ i4b_T203_start(l2sc);
+ i4b_invoke_retransmission(l2sc, l2sc->rxd_NR);
+ l2sc->Q921_state = ST_MULTIFR;
+ return;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ return;
+ }
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ l2sc->Q921_state = ST_TIMREC;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd RNR
+ *---------------------------------------------------------------------------*/
+static void
+F_TR19(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR19", ("FSM function F_TR19 executing\n"));
+
+ l2sc->peer_busy = 0;
+
+ if(l2sc->rxd_CR == CR_CMD_FROM_NT)
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ i4b_enquiry_response(l2sc);
+ }
+ }
+ else
+ {
+ if(l2sc->rxd_PF == 1)
+ {
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ i4b_T200_restart(l2sc);
+ i4b_invoke_retransmission(l2sc, l2sc->rxd_NR);
+ l2sc->Q921_state = ST_MULTIFR;
+ return;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ return;
+ }
+ }
+ }
+
+ if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs))
+ {
+ l2sc->va = l2sc->rxd_NR;
+ l2sc->Q921_state = ST_TIMREC;
+ }
+ else
+ {
+ i4b_nr_error_recovery(l2sc);
+ l2sc->Q921_state = ST_AW_EST;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM state ST_TIMREC event rx'd FRMR
+ *---------------------------------------------------------------------------*/
+static void
+F_TR20(l2_softc_t *l2sc)
+{
+ DBGL2(L2_F_MSG, "F_TR20", ("FSM function F_TR20 executing\n"));
+
+ i4b_mdl_error_ind(l2sc, "F_TR20", MDL_ERR_K);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+}
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_l2fsm.h b/sys/i4b/layer2/i4b_l2fsm.h
new file mode 100644
index 000000000000..8f510682bebf
--- /dev/null
+++ b/sys/i4b/layer2/i4b_l2fsm.h
@@ -0,0 +1,82 @@
+/*
+ * 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_l2fsm.h - layer 2 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l2fsm.h,v 1.3 1998/12/05 18:05:13 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:28:39 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L2FSM_H_
+#define _I4B_L2FSM_H_
+
+enum Q921_states {
+ ST_TEI_UNAS, /* TEI unassigned */
+ ST_ASG_AW_TEI, /* assign awaiting TEI */
+ ST_EST_AW_TEI, /* establish awaiting TEI */
+ ST_TEI_ASGD, /* TEI assigned */
+
+ ST_AW_EST, /* awaiting establishment */
+ ST_AW_REL, /* awaiting release */
+ ST_MULTIFR, /* multiple frame established */
+ ST_TIMREC, /* timer recovery */
+
+ ST_SUBSET, /* SUBroutine SETs new state */
+ ST_ILL, /* illegal state */
+ N_STATES /* number of states */
+};
+
+enum Q921_events {
+ EV_DLESTRQ, /* dl establish req */
+ EV_DLUDTRQ, /* dl unit data req */
+ EV_MDASGRQ, /* mdl assign req */
+ EV_MDERRRS, /* mdl error response */
+ EV_PSDEACT, /* persistent deactivation */
+ EV_MDREMRQ, /* mdl remove req */
+ EV_RXSABME, /* rx'd SABME */
+ EV_RXDISC, /* rx'd DISC */
+ EV_RXUA, /* rx'd UA */
+ EV_RXDM, /* rx'd DM */
+ EV_T200EXP, /* T200 expired */
+ EV_DLDATRQ, /* dl data req */
+ EV_DLRELRQ, /* dl release req */
+ EV_T203EXP, /* T203 expired */
+ EV_OWNBUSY, /* set own rx busy */
+ EV_OWNRDY, /* clear own rx busy */
+ EV_RXRR, /* rx'd RR */
+ EV_RXREJ, /* rx'd REJ */
+ EV_RXRNR, /* rx'd RNR */
+ EV_RXFRMR, /* rx'd FRMR */
+
+ EV_ILL, /* Illegal */
+ N_EVENTS
+};
+
+#endif /* _I4B_L2FSM_H_ */
+
diff --git a/sys/i4b/layer2/i4b_l2timer.c b/sys/i4b/layer2/i4b_l2timer.c
new file mode 100644
index 000000000000..3b45e807dcdb
--- /dev/null
+++ b/sys/i4b/layer2/i4b_l2timer.c
@@ -0,0 +1,263 @@
+/*
+ * 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_l2timer.c - layer 2 timer handling
+ * --------------------------------------
+ *
+ * $Id: i4b_l2timer.c,v 1.12 1998/12/05 18:05:15 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:29:13 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T200 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+i4b_T200_timeout(l2_softc_t *l2sc)
+{
+ DBGL2(L2_T_ERR, "i4b_T200_timeout", ("unit %d, RC = %d\n", l2sc->unit, l2sc->RC));
+ i4b_next_l2state(l2sc, EV_T200EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T200 start
+ *---------------------------------------------------------------------------*/
+void
+i4b_T200_start(l2_softc_t *l2sc)
+{
+ DBGL2(L2_T_MSG, "i4b_T200_start", ("unit %d\n", l2sc->unit));
+ l2sc->T200 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ l2sc->T200_callout = timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF);
+#else
+ timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T200 stop
+ *---------------------------------------------------------------------------*/
+void
+i4b_T200_stop(l2_softc_t *l2sc)
+{
+ if(l2sc->T200 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, l2sc->T200_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc);
+#endif
+ l2sc->T200 = TIMER_IDLE;
+ }
+ DBGL2(L2_T_MSG, "i4b_T200_stop", ("unit %d\n", l2sc->unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T200 restart
+ *---------------------------------------------------------------------------*/
+void
+i4b_T200_restart(l2_softc_t *l2sc)
+{
+ if(l2sc->T200 != TIMER_IDLE)
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, l2sc->T200_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc);
+#endif
+ else
+ l2sc->T200 = TIMER_ACTIVE;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ l2sc->T200_callout = timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF);
+#else
+ timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF);
+#endif
+
+ DBGL2(L2_T_MSG, "i4b_T200_restart", ("unit %d\n", l2sc->unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T202 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+i4b_T202_timeout(l2_softc_t *l2sc)
+{
+ DBGL2(L2_T_ERR, "i4b_T202_timeout", ("unit %d, N202 = %d\n", l2sc->unit, l2sc->N202));
+
+ if(--(l2sc->N202))
+ {
+ (*l2sc->T202func)(l2sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T202 start
+ *---------------------------------------------------------------------------*/
+void
+i4b_T202_start(l2_softc_t *l2sc)
+{
+ DBGL2(L2_T_MSG, "i4b_T202_start", ("unit %d\n", l2sc->unit));
+ l2sc->N202 = N202DEF;
+ l2sc->T202 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ l2sc->T202_callout = timeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, T202DEF);
+#else
+ timeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, T202DEF);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T202 stop
+ *---------------------------------------------------------------------------*/
+void
+i4b_T202_stop(l2_softc_t *l2sc)
+{
+ if(l2sc->T202 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, l2sc->T202_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc);
+#endif
+ l2sc->T202 = TIMER_IDLE;
+ }
+ DBGL2(L2_T_MSG, "i4b_T202_stop", ("unit %d\n", l2sc->unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T203 timeout function
+ *---------------------------------------------------------------------------*/
+#if I4B_T203_ACTIVE
+static void
+i4b_T203_timeout(l2_softc_t *l2sc)
+{
+ DBGL2(L2_T_ERR, "i4b_T203_timeout", ("unit %d\n", l2sc->unit));
+ i4b_next_l2state(l2sc, EV_T203EXP);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T203 start
+ *---------------------------------------------------------------------------*/
+void
+i4b_T203_start(l2_softc_t *l2sc)
+{
+#if I4B_T203_ACTIVE
+ DBGL2(L2_T_MSG, "i4b_T203_start", ("unit %d\n", l2sc->unit));
+ l2sc->T203 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ l2sc->T203_callout = timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF);
+#else
+ timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF);
+#endif
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T203 stop
+ *---------------------------------------------------------------------------*/
+void
+i4b_T203_stop(l2_softc_t *l2sc)
+{
+#if I4B_T203_ACTIVE
+ if(l2sc->T203 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, l2sc->T203_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc);
+#endif
+ l2sc->T203 = TIMER_IDLE;
+ }
+ DBGL2(L2_T_MSG, "i4b_T203_stop", ("unit %d\n", l2sc->unit));
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Q.921 timer T203 restart
+ *---------------------------------------------------------------------------*/
+void
+i4b_T203_restart(l2_softc_t *l2sc)
+{
+#if I4B_T203_ACTIVE
+ if(l2sc->T203 != TIMER_IDLE)
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, l2sc->T203_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc);
+#endif
+ else
+ l2sc->T203 = TIMER_ACTIVE;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ l2sc->T203_callout = timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF);
+#else
+ timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF);
+#endif
+
+ DBGL2(L2_T_MSG, "i4b_T203_restart", ("unit %d\n", l2sc->unit));
+#endif
+}
+
+#endif /* NI4BQ921 > 0 */
+
diff --git a/sys/i4b/layer2/i4b_lme.c b/sys/i4b/layer2/i4b_lme.c
new file mode 100644
index 000000000000..b179e94bfe43
--- /dev/null
+++ b/sys/i4b/layer2/i4b_lme.c
@@ -0,0 +1,160 @@
+/*
+ * 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_lme.c - layer management entity
+ * -------------------------------------
+ *
+ * $Id: i4b_lme.c,v 1.8 1998/12/05 18:05:19 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:29:25 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * mdl assign indication handler
+ *---------------------------------------------------------------------------*/
+void
+i4b_mdl_assign_ind(l2_softc_t *l2sc)
+{
+ DBGL2(L2_PRIM, "MDL-ASSIGN-IND", ("unit %d\n", l2sc->unit));
+
+ i4b_l1_activate(l2sc);
+
+ if(l2sc->tei_valid == TEI_VALID)
+ {
+ l2sc->T202func = (void(*)(void*))i4b_tei_verify;
+ l2sc->N202 = N202DEF;
+ i4b_tei_verify(l2sc);
+ }
+ else
+ {
+ l2sc->T202func = (void(*)(void*))i4b_tei_assign;
+ l2sc->N202 = N202DEF;
+ i4b_tei_assign(l2sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_mdl_error_ind handler (Q.921 01/94 pp 156)
+ *---------------------------------------------------------------------------*/
+void
+i4b_mdl_error_ind(l2_softc_t *l2sc, char *where, int errorcode)
+{
+ static char *error_text[] = {
+ "MDL_ERR_A: rx'd unsolicited response - supervisory (F=1)",
+ "MDL_ERR_B: rx'd unsolicited response - DM (F=1)",
+ "MDL_ERR_C: rx'd unsolicited response - UA (F=1)",
+ "MDL_ERR_D: rx'd unsolicited response - UA (F=0)",
+ "MDL_ERR_E: rx'd unsolicited response - DM (F=0)",
+ "MDL_ERR_F: peer initiated re-establishment - SABME",
+ "MDL_ERR_G: unsuccessful transmission N200times - SABME",
+ "MDL_ERR_H: unsuccessful transmission N200times - DIS",
+ "MDL_ERR_I: unsuccessful transmission N200times - Status ENQ",
+ "MDL_ERR_J: other error - N(R) error",
+ "MDL_ERR_K: other error - rx'd FRMR response",
+ "MDL_ERR_L: other error - rx'd undefined frame",
+ "MDL_ERR_M: other error - receipt of I field not permitted",
+ "MDL_ERR_N: other error - rx'd frame with wrong size",
+ "MDL_ERR_O: other error - N201 error",
+ "MDL_ERR_MAX: i4b_mdl_error_ind called with wrong parameter!!!"
+ };
+
+ if(errorcode > MDL_ERR_MAX)
+ errorcode = MDL_ERR_MAX;
+
+ DBGL2(L2_ERROR, "i4b_mdl_error_ind", ("unit = %d, location = %s\n", l2sc->unit, where));
+ DBGL2(L2_ERROR, "i4b_mdl_error_ind", ("error = %s\n", error_text[errorcode]));
+
+ switch(errorcode)
+ {
+ case MDL_ERR_A:
+ case MDL_ERR_B:
+ break;
+
+ case MDL_ERR_C:
+ case MDL_ERR_D:
+ i4b_tei_verify(l2sc);
+ break;
+
+ case MDL_ERR_E:
+ case MDL_ERR_F:
+ break;
+
+ case MDL_ERR_G:
+ case MDL_ERR_H:
+ i4b_tei_verify(l2sc);
+ break;
+
+ case MDL_ERR_I:
+ case MDL_ERR_J:
+ case MDL_ERR_K:
+ case MDL_ERR_L:
+ case MDL_ERR_M:
+ case MDL_ERR_N:
+ case MDL_ERR_O:
+ break;
+
+ default:
+ break;
+ }
+}
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_mbuf.c b/sys/i4b/layer2/i4b_mbuf.c
new file mode 100644
index 000000000000..6d085c3e08c0
--- /dev/null
+++ b/sys/i4b/layer2/i4b_mbuf.c
@@ -0,0 +1,245 @@
+/*
+ * 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 - mbuf handling support routines
+ * ------------------------------------
+ *
+ * $Id: i4b_mbuf.c,v 1.10 1998/12/05 18:05:20 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:29:44 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#define I4B_MBUF_DEBUG
+#undef I4B_MBUF_TYPE_DEBUG
+
+#ifdef I4B_MBUF_TYPE_DEBUG
+
+#ifdef __FreeBSD__
+
+#define MT_DCHAN 42
+#define MT_BCHAN 43
+
+#else /* NetBSD */
+
+#define MT_DCHAN MT_DATA
+#define MT_BCHAN MT_DATA
+
+#endif
+
+#define MT_I4B_D MT_DCHAN
+#define MT_I4B_B MT_BCHAN
+
+#else /* ! I4B_MBUF_TYPE_DEBUG */
+
+#define MT_I4B_D MT_DATA
+#define MT_I4B_B MT_DATA
+
+#endif /* I4B_MBUF_TYPE_DEBUG */
+
+/*---------------------------------------------------------------------------*
+ * allocate D-channel mbuf space
+ *---------------------------------------------------------------------------*/
+struct mbuf*
+i4b_Dgetmbuf(int len)
+{
+ struct mbuf *m;
+
+ if(len > MCLBYTES) /* if length > max extension size */
+ {
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getmbuf: error - len(%d) > MCLBYTES(%d)\n",
+ len, MCLBYTES);
+#endif
+
+ return(NULL);
+ }
+
+ MGETHDR(m, M_DONTWAIT, MT_I4B_D); /* get mbuf with pkthdr */
+
+ /* did we actually get the mbuf ? */
+
+ if(!m)
+ {
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getbuf: error - MGETHDR failed!\n");
+#endif
+
+ return(NULL);
+ }
+
+ if(len >= MHLEN)
+ {
+ MCLGET(m, M_DONTWAIT);
+
+ if(!(m->m_flags & M_EXT))
+ {
+ m_freem(m);
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getbuf: error - MCLGET failed, len(%d)\n", len);
+#endif
+
+ return (NULL);
+ }
+ }
+
+ m->m_len = len;
+
+ return(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * free a D-channel mbuf
+ *---------------------------------------------------------------------------*/
+void
+i4b_Dfreembuf(struct mbuf *m)
+{
+ if(m)
+ m_freem(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * clear a D-channel ifqueue from data
+ *---------------------------------------------------------------------------*/
+void
+i4b_Dcleanifq(struct ifqueue *ifq)
+{
+ struct mbuf *m;
+ int x = splimp();
+
+ while(!IF_QEMPTY(ifq))
+ {
+ IF_DEQUEUE(ifq, m);
+ i4b_Dfreembuf(m);
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * allocate B-channel mbuf space
+ *---------------------------------------------------------------------------*/
+struct mbuf*
+i4b_Bgetmbuf(int len)
+{
+ struct mbuf *m;
+
+ if(len > MCLBYTES) /* if length > max extension size */
+ {
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getmbuf: error - len(%d) > MCLBYTES(%d)\n",
+ len, MCLBYTES);
+#endif
+
+ return(NULL);
+ }
+
+ MGETHDR(m, M_DONTWAIT, MT_I4B_B); /* get mbuf with pkthdr */
+
+ /* did we actually get the mbuf ? */
+
+ if(!m)
+ {
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getbuf: error - MGETHDR failed!\n");
+#endif
+
+ return(NULL);
+ }
+
+ if(len >= MHLEN)
+ {
+ MCLGET(m, M_DONTWAIT);
+
+ if(!(m->m_flags & M_EXT))
+ {
+ m_freem(m);
+
+#ifdef I4B_MBUF_DEBUG
+ printf("i4b_getbuf: error - MCLGET failed, len(%d)\n", len);
+#endif
+
+ return (NULL);
+ }
+ }
+
+ m->m_len = len;
+
+ return(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * free a B-channel mbuf
+ *---------------------------------------------------------------------------*/
+void
+i4b_Bfreembuf(struct mbuf *m)
+{
+ if(m)
+ m_freem(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * clear a B-channel ifqueue from data
+ *---------------------------------------------------------------------------*/
+void
+i4b_Bcleanifq(struct ifqueue *ifq)
+{
+ struct mbuf *m;
+ int x = splimp();
+
+ while(!IF_QEMPTY(ifq))
+ {
+ IF_DEQUEUE(ifq, m);
+ i4b_Bfreembuf(m);
+ }
+
+ splx(x);
+}
+
+/* EOF */
diff --git a/sys/i4b/layer2/i4b_sframe.c b/sys/i4b/layer2/i4b_sframe.c
new file mode 100644
index 000000000000..f8d14ba1a246
--- /dev/null
+++ b/sys/i4b/layer2/i4b_sframe.c
@@ -0,0 +1,215 @@
+/*
+ * 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_sframe.c - s frame handling routines
+ * ----------------------------------------
+ *
+ * $Id: i4b_sframe.c,v 1.8 1998/12/05 18:05:21 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:30:02 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * process s frame
+ *---------------------------------------------------------------------------*/
+void
+i4b_rxd_s_frame(int unit, struct mbuf *m)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ u_char *ptr = m->m_data;
+
+ if(!((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))))
+ {
+ i4b_Dfreembuf(m);
+ return;
+ }
+
+ l2sc->rxd_CR = GETCR(*(ptr + OFF_SAPI));
+ l2sc->rxd_PF = GETSPF(*(ptr + OFF_SNR));
+ l2sc->rxd_NR = GETSNR(*(ptr + OFF_SNR));
+
+ i4b_rxd_ack(l2sc, l2sc->rxd_NR);
+
+ switch(*(ptr + OFF_SRCR))
+ {
+ case RR:
+ DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd RR, N(R) = %d\n", l2sc->rxd_NR));
+ i4b_next_l2state(l2sc, EV_RXRR);
+ break;
+
+ case RNR:
+ DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd RNR, N(R) = %d\n", l2sc->rxd_NR));
+ i4b_next_l2state(l2sc, EV_RXRNR);
+ break;
+
+ case REJ:
+ DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd REJ, N(R) = %d\n", l2sc->rxd_NR));
+ i4b_next_l2state(l2sc, EV_RXREJ);
+ break;
+
+ default:
+ DBGL2(L2_S_ERR, "i4b_rxd_s_frame", ("ERROR, unknown code, frame = \n"));
+ i4b_print_frame(m->m_len, m->m_data);
+ break;
+ }
+ i4b_Dfreembuf(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit RR command
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_rr_command(l2_softc_t *l2sc, pbit_t pbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_S_MSG, "i4b_tx_rr_command", ("tx RR, unit = %d\n", l2sc->unit));
+
+ m = i4b_build_s_frame(l2sc, CR_CMD_TO_NT, pbit, RR);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit RR response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_rr_response(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_S_MSG, "i4b_tx_rr_response", ("tx RR, unit = %d\n", l2sc->unit));
+
+ m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, RR);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit RNR command
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_rnr_command(l2_softc_t *l2sc, pbit_t pbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_S_MSG, "i4b_tx_rnr_command", ("tx RNR, unit = %d\n", l2sc->unit));
+
+ m = i4b_build_s_frame(l2sc, CR_CMD_TO_NT, pbit, RNR);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit RNR response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_rnr_response(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_S_MSG, "i4b_tx_rnr_response", ("tx RNR, unit = %d\n", l2sc->unit));
+
+ m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, RNR);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit REJ response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_rej_response(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_S_MSG, "i4b_tx_rej_response", ("tx REJ, unit = %d\n", l2sc->unit));
+
+ m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, REJ);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * build S-frame for sending
+ *---------------------------------------------------------------------------*/
+struct mbuf *
+i4b_build_s_frame(l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type)
+{
+ struct mbuf *m;
+
+ if((m = i4b_Dgetmbuf(S_FRAME_LEN)) == NULL)
+ return(NULL);
+
+ PUTSAPI(SAPI_CCP, crbit, m->m_data[OFF_SAPI]);
+
+ PUTTEI(l2sc->tei, m->m_data[OFF_TEI]);
+
+ m->m_data[OFF_SRCR] = type;
+
+ m->m_data[OFF_SNR] = (l2sc->vr << 1) | (pbit & 0x01);
+
+ return(m);
+}
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_tei.c b/sys/i4b/layer2/i4b_tei.c
new file mode 100644
index 000000000000..5c5b7b83fd87
--- /dev/null
+++ b/sys/i4b/layer2/i4b_tei.c
@@ -0,0 +1,322 @@
+/*
+ * 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_tei.c - tei handling procedures
+ * -----------------------------------
+ *
+ * $Id: i4b_tei.c,v 1.13 1998/12/05 18:05:23 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:30:20 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/syslog.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
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <machine/random.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * handle a received TEI management frame
+ *---------------------------------------------------------------------------*/
+void
+i4b_tei_rxframe(int unit, struct mbuf *m)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ u_char *ptr = m->m_data;
+
+ switch(*(ptr + OFF_MT))
+ {
+ case MT_ID_ASSIGN:
+ if( (*(ptr + OFF_RIL) == l2sc->last_ril) &&
+ (*(ptr + OFF_RIH) == l2sc->last_rih))
+ {
+ l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
+ l2sc->tei_valid = TEI_VALID;
+
+ if(l2sc->T202 == TIMER_ACTIVE)
+ i4b_T202_stop(l2sc);
+
+ MDL_Status_Ind(l2sc->unit, STI_TEIASG, l2sc->tei);
+
+ log(LOG_INFO, "i4b: unit %d, assigned TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
+
+ DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Assign - TEI = %d\n", l2sc->tei));
+
+ i4b_next_l2state(l2sc, EV_MDASGRQ);
+ }
+ break;
+
+ case MT_ID_DENY:
+ if( (*(ptr + OFF_RIL) == l2sc->last_ril) &&
+ (*(ptr + OFF_RIH) == l2sc->last_rih))
+ {
+ l2sc->tei_valid = TEI_INVALID;
+ l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
+
+ if(l2sc->tei == GROUP_TEI)
+ {
+ log(LOG_WARNING, "i4b: unit %d, denied TEI, no TEI values available from exchange!\n", l2sc->unit);
+ DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("TEI ID Denied, No TEI values available from exchange!\n"));
+ }
+ else
+ {
+ log(LOG_WARNING, "i4b: unit %d, denied TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
+ DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("TEI ID Denied - TEI = %d\n", l2sc->tei));
+ }
+ MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1);
+ i4b_next_l2state(l2sc, EV_MDERRRS);
+ }
+ break;
+
+ case MT_ID_CHK_REQ:
+ if( (l2sc->tei_valid == TEI_VALID) &&
+ ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) ||
+ (GROUP_TEI == GET_TEIFROMAI(*(ptr+OFF_AI))) ))
+ {
+ static int lasttei = -1;
+
+ if(l2sc->tei != lasttei)
+ {
+ DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Check Req - TEI = %d\n", l2sc->tei));
+ lasttei = l2sc->tei;
+ }
+
+ if(l2sc->T202 == TIMER_ACTIVE)
+ i4b_T202_stop(l2sc);
+ i4b_tei_chkresp(l2sc);
+ }
+ break;
+
+ case MT_ID_REMOVE:
+ if( (l2sc->tei_valid == TEI_VALID) &&
+ ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) ||
+ (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI)))))
+ {
+ l2sc->tei_valid = TEI_INVALID;
+ l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI));
+
+ log(LOG_INFO, "i4b: unit %d, removed TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei);
+ DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Remove - TEI = %d\n", l2sc->tei));
+ MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1);
+ i4b_next_l2state(l2sc, EV_MDREMRQ);
+ }
+ break;
+
+ default:
+ DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("UNKNOWN TEI MGMT Frame, type = 0x%x\n", *(ptr + OFF_MT)));
+ i4b_print_frame(m->m_len, m->m_data);
+ break;
+ }
+ i4b_Dfreembuf(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * allocate and fill up a TEI management frame for sending
+ *---------------------------------------------------------------------------*/
+static struct mbuf *
+build_tei_mgmt_frame(l2_softc_t *l2sc, unsigned char type)
+{
+ struct mbuf *m;
+
+ if((m = i4b_Dgetmbuf(TEI_MGMT_FRM_LEN)) == NULL)
+ return(NULL);
+
+ m->m_data[TEIM_SAPIO] = 0xfc; /* SAPI = 63, CR = 0, EA = 0 */
+ m->m_data[TEIM_TEIO] = 0xff; /* TEI = 127, EA = 1 */
+ m->m_data[TEIM_UIO] = UI; /* UI */
+ m->m_data[TEIM_MEIO] = MEI; /* MEI */
+ m->m_data[TEIM_MTO] = type; /* message type */
+
+ switch(type)
+ {
+ case MT_ID_REQEST:
+ i4b_make_rand_ri(l2sc);
+ m->m_data[TEIM_RILO] = l2sc->last_ril;
+ m->m_data[TEIM_RIHO] = l2sc->last_rih;
+ m->m_data[TEIM_AIO] = (GROUP_TEI << 1) | 0x01;
+ break;
+
+ case MT_ID_CHK_RSP:
+ i4b_make_rand_ri(l2sc);
+ m->m_data[TEIM_RILO] = l2sc->last_ril;
+ m->m_data[TEIM_RIHO] = l2sc->last_rih;
+ m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01;
+ break;
+
+ case MT_ID_VERIFY:
+ m->m_data[TEIM_RILO] = 0;
+ m->m_data[TEIM_RIHO] = 0;
+ m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01;
+ break;
+
+ default:
+ i4b_Dfreembuf(m);
+ panic("build_tei_mgmt_frame: invalid type");
+ break;
+ }
+ return(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_tei_assign - TEI assignment procedure (Q.921, 5.3.2, pp 24)
+ * T202func and N202 _MUST_ be set prior to calling this function !
+ *---------------------------------------------------------------------------*/
+void
+i4b_tei_assign(l2_softc_t *l2sc)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_TEI_MSG, "i4b_tei_assign", ("tx TEI ID_Request\n"));
+
+ m = build_tei_mgmt_frame(l2sc, MT_ID_REQEST);
+
+ if(m == NULL)
+ panic("i4b_tei_assign: no mbuf");
+
+ i4b_T202_start(l2sc);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_tei_assign - TEI verify procedure (Q.921, 5.3.5, pp 29)
+ * T202func and N202 _MUST_ be set prior to calling this function !
+ *---------------------------------------------------------------------------*/
+void
+i4b_tei_verify(l2_softc_t *l2sc)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_TEI_MSG, "i4b_tei_verify", ("tx TEI ID_Verify\n"));
+
+ m = build_tei_mgmt_frame(l2sc, MT_ID_VERIFY);
+
+ if(m == NULL)
+ panic("i4b_tei_verify: no mbuf");
+
+ i4b_T202_start(l2sc);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_tei_chkresp - TEI check response procedure (Q.921, 5.3.5, pp 29)
+ *---------------------------------------------------------------------------*/
+void
+i4b_tei_chkresp(l2_softc_t *l2sc)
+{
+ struct mbuf *m;
+ static int lasttei = 0;
+
+ if(l2sc->tei != lasttei)
+ {
+ lasttei = l2sc->tei;
+ DBGL2(L2_TEI_MSG, "i4b_tei_chkresp", ("tx TEI ID_Check_Response\n"));
+ }
+
+ m = build_tei_mgmt_frame(l2sc, MT_ID_CHK_RSP);
+
+ if(m == NULL)
+ panic("i4b_tei_chkresp: no mbuf");
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * generate some 16 bit "random" number used for TEI mgmt Ri field
+ *---------------------------------------------------------------------------*/
+void
+i4b_make_rand_ri(l2_softc_t *l2sc)
+{
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+
+ u_short val;
+ read_random((char *)&val, sizeof(val));
+
+#else
+
+ register u_short val;
+ register int i;
+ static int called = 42;
+
+ val = (l2sc->last_rih << 8) | l2sc->last_ril;
+
+ val += ++called;
+
+ for(i=0; i < 50 ; i++, val++)
+ {
+ val |= l2sc->unit+i;
+ val <<= i;
+ val ^= (time.tv_sec >> 16) ^ time.tv_usec;
+ val <<= i;
+ val ^= time.tv_sec ^ (time.tv_usec >> 16);
+
+ if(val != 0 && val != 0xffff)
+ break;
+ }
+#endif
+ l2sc->last_rih = (val >> 8) & 0x00ff;
+ l2sc->last_ril = val & 0x00ff;
+}
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_uframe.c b/sys/i4b/layer2/i4b_uframe.c
new file mode 100644
index 000000000000..90e79124d29c
--- /dev/null
+++ b/sys/i4b/layer2/i4b_uframe.c
@@ -0,0 +1,308 @@
+/*
+ * 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_uframe.c - routines for handling U-frames
+ * -----------------------------------------------
+ *
+ * $Id: i4b_uframe.c,v 1.6 1998/12/05 18:05:24 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:30:33 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * process a received U-frame
+ *---------------------------------------------------------------------------*/
+void
+i4b_rxd_u_frame(int unit, struct mbuf *m)
+{
+ l2_softc_t *l2sc = &l2_softc[unit];
+ u_char *ptr = m->m_data;
+
+ int sapi = GETSAPI(*(ptr + OFF_SAPI));
+ int tei = GETTEI(*(ptr + OFF_TEI));
+ int pfbit = GETUPF(*(ptr + OFF_CNTL));
+
+ switch(*(ptr + OFF_CNTL) & ~UPFBIT)
+ {
+ /* commands */
+
+ case SABME:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("SABME, sapi = %d, tei = %d\n", sapi, tei));
+
+ l2sc->rxd_PF = pfbit;
+
+ i4b_next_l2state(l2sc, EV_RXSABME);
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ case UI:
+ if(sapi == SAPI_L2M &&
+ tei == GROUP_TEI &&
+ *(ptr + OFF_MEI) == MEI)
+ {
+ /* layer 2 management (SAPI = 63) */
+
+ i4b_tei_rxframe(unit, m);
+ }
+ else if(sapi == SAPI_CCP && tei == GROUP_TEI)
+ {
+ /* call control (SAPI = 0) */
+
+ /* strip ui header */
+ m_adj(m, UI_HDR_LEN);
+ /* to upper layer */
+ DL_Unit_Data_Ind(unit, m);
+ }
+ else
+ {
+ DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("unknown UI frame!\n"));
+
+ i4b_Dfreembuf(m);
+ }
+ break;
+
+ case DISC:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("DISC, sapi = %d, tei = %d\n", sapi, tei));
+
+ l2sc->rxd_PF = pfbit;
+
+ i4b_next_l2state(l2sc, EV_RXDISC);
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ case XID:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("XID, sapi = %d, tei = %d\n", sapi, tei));
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ /* responses */
+
+ case DM:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("DM, sapi = %d, tei = %d\n", sapi, tei));
+
+ i4b_print_frame(m->m_len, m->m_data);
+
+ l2sc->rxd_PF = pfbit;
+
+ i4b_next_l2state(l2sc, EV_RXDM);
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ case UA:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("UA, sapi = %d, tei = %d\n", sapi, tei));
+
+ l2sc->rxd_PF = pfbit;
+
+ i4b_next_l2state(l2sc, EV_RXUA);
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ case FRMR:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("FRMR, sapi = %d, tei = %d\n", sapi, tei));
+
+ l2sc->rxd_PF = pfbit;
+
+ i4b_next_l2state(l2sc, EV_RXFRMR);
+ }
+ i4b_Dfreembuf(m);
+ break;
+
+ default:
+ if((l2sc->tei_valid == TEI_VALID) &&
+ (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))
+ {
+ DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei));
+ i4b_print_frame(m->m_len, m->m_data);
+ }
+ else
+ {
+ DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("not mine - UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei));
+ i4b_print_frame(m->m_len, m->m_data);
+ }
+ i4b_Dfreembuf(m);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * build U-frame for sending
+ *---------------------------------------------------------------------------*/
+struct mbuf *
+i4b_build_u_frame(l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type)
+{
+ struct mbuf *m;
+
+ if((m = i4b_Dgetmbuf(U_FRAME_LEN)) == NULL)
+ return(NULL);
+
+ PUTSAPI(SAPI_CCP, crbit, m->m_data[OFF_SAPI]);
+
+ PUTTEI(l2sc->tei, m->m_data[OFF_TEI]);
+
+ if(pbit)
+ m->m_data[OFF_CNTL] = type | UPBITSET;
+ else
+ m->m_data[OFF_CNTL] = type & ~UPBITSET;
+
+ return(m);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit SABME command
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_sabme(l2_softc_t *l2sc, pbit_t pbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_U_MSG, "i4b_tx_sabme", ("tx SABME, tei = %d\n", l2sc->tei));
+
+ m = i4b_build_u_frame(l2sc, CR_CMD_TO_NT, pbit, SABME);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit DM response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_dm(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_U_MSG, "i4b_tx_dm", ("tx DM, tei = %d\n", l2sc->tei));
+
+ m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, DM);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit DISC command
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_disc(l2_softc_t *l2sc, pbit_t pbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_U_MSG, "i4b_tx_disc", ("tx DISC, tei = %d\n", l2sc->tei));
+
+ m = i4b_build_u_frame(l2sc, CR_CMD_TO_NT, pbit, DISC);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit UA response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_ua(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_U_MSG, "i4b_tx_ua", ("tx UA, tei = %d\n", l2sc->tei));
+
+ m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, UA);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+/*---------------------------------------------------------------------------*
+ * transmit FRMR response
+ *---------------------------------------------------------------------------*/
+void
+i4b_tx_frmr(l2_softc_t *l2sc, fbit_t fbit)
+{
+ struct mbuf *m;
+
+ DBGL2(L2_U_MSG, "i4b_tx_frmr", ("tx FRMR, tei = %d\n", l2sc->tei));
+
+ m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, FRMR);
+
+ PH_Data_Req(l2sc->unit, m, MBUF_FREE);
+}
+
+
+#endif /* NI4BQ921 > 0 */
diff --git a/sys/i4b/layer2/i4b_util.c b/sys/i4b/layer2/i4b_util.c
new file mode 100644
index 000000000000..9f8fe196c56c
--- /dev/null
+++ b/sys/i4b/layer2/i4b_util.c
@@ -0,0 +1,312 @@
+/*
+ * 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_util.c - layer 2 utility routines
+ * -------------------------------------
+ *
+ * $Id: i4b_util.c,v 1.15 1998/12/05 18:05:26 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:31:10 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq921.h"
+#else
+#define NI4BQ921 1
+#endif
+#if NI4BQ921 > 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/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_l1l2.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_isdnq931.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer2/i4b_l2.h>
+#include <i4b/layer2/i4b_l2fsm.h>
+
+/*---------------------------------------------------------------------------*
+ * routine ESTABLISH DATA LINK (Q.921 03/93 page 83)
+ *---------------------------------------------------------------------------*/
+void
+i4b_establish_data_link(l2_softc_t *l2sc)
+{
+ i4b_l1_activate(l2sc);
+
+ i4b_clear_exception_conditions(l2sc);
+
+ l2sc->RC = 0;
+
+ i4b_tx_sabme(l2sc, P1);
+
+ i4b_T200_restart(l2sc);
+
+ i4b_T203_stop(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * routine CLEAR EXCEPTION CONDITIONS (Q.921 03/93 page 83)
+ *---------------------------------------------------------------------------*/
+void
+i4b_clear_exception_conditions(l2_softc_t *l2sc)
+{
+
+/*XXX -------------------------------------------------------------- */
+/*XXX is this really appropriate here or should it moved elsewhere ? */
+
+ i4b_Dcleanifq(&l2sc->i_queue);
+
+ if(l2sc->ua_num != UA_EMPTY)
+ {
+ i4b_Dfreembuf(l2sc->ua_frame);
+ l2sc->ua_num = UA_EMPTY;
+ }
+/*XXX -------------------------------------------------------------- */
+
+ l2sc->peer_busy = 0;
+
+ l2sc->rej_excpt = 0;
+
+ l2sc->own_busy = 0;
+
+ l2sc->ack_pend = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * routine TRANSMIT ENQUIRE (Q.921 03/93 page 83)
+ *---------------------------------------------------------------------------*/
+void
+i4b_transmit_enquire(l2_softc_t *l2sc)
+{
+ if(l2sc->own_busy)
+ i4b_tx_rnr_command(l2sc, P1);
+ else
+ i4b_tx_rr_command(l2sc, P1);
+
+ l2sc->ack_pend = 0;
+
+ i4b_T200_start(l2sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * routine NR ERROR RECOVERY (Q.921 03/93 page 83)
+ *---------------------------------------------------------------------------*/
+void
+i4b_nr_error_recovery(l2_softc_t *l2sc)
+{
+ i4b_mdl_error_ind(l2sc, "i4b_nr_error_recovery", MDL_ERR_J);
+
+ i4b_establish_data_link(l2sc);
+
+ l2sc->l3initiated = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * routine ENQUIRY RESPONSE (Q.921 03/93 page 84)
+ *---------------------------------------------------------------------------*/
+void
+i4b_enquiry_response(l2_softc_t *l2sc)
+{
+ if(l2sc->own_busy)
+ i4b_tx_rnr_response(l2sc, F1);
+ else
+ i4b_tx_rr_response(l2sc, F1);
+
+ l2sc->ack_pend = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * routine INVOKE RETRANSMISSION (Q.921 03/93 page 84)
+ *---------------------------------------------------------------------------*/
+void
+i4b_invoke_retransmission(l2_softc_t *l2sc, int nr)
+{
+ DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("nr = %d\n", nr ));
+
+ while(l2sc->vs != nr)
+ {
+ DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("nr != vs, nr = %d, vs = %d\n", nr, l2sc->vs));
+
+ M128DEC(l2sc->vs);
+
+/* XXXXXXXXXXXXXXXXX */
+
+ if((l2sc->ua_num != UA_EMPTY) && (l2sc->vs == l2sc->ua_num))
+ {
+ IF_ENQUEUE(&l2sc->i_queue, l2sc->ua_frame);
+ l2sc->ua_num = UA_EMPTY;
+ }
+ else
+ {
+ DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("ERROR, l2sc->vs = %d, l2sc->ua_num = %d \n",l2sc->vs, l2sc->ua_num));
+ }
+
+/* XXXXXXXXXXXXXXXXX */
+
+ i4b_i_frame_queued_up(l2sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * routine ACKNOWLEDGE PENDING (Q.921 03/93 p 70)
+ *---------------------------------------------------------------------------*/
+void
+i4b_acknowledge_pending(l2_softc_t *l2sc)
+{
+ if(l2sc->ack_pend)
+ {
+ l2sc->ack_pend = 0;
+ i4b_tx_rr_response(l2sc, F0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_print_frame - just print the hex contents of a frame
+ *---------------------------------------------------------------------------*/
+void
+i4b_print_frame(int len, u_char *buf)
+{
+#ifdef DO_I4B_DEBUG
+ int i;
+
+ if (!(i4b_l2_debug & L2_ERROR)) /* XXXXXXXXXXXXXXXXXXXXX */
+ return;
+
+ for(i = 0; i < len; i++)
+ printf(" 0x%x", buf[i]);
+ printf("\n");
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_print_l2var - print some l2softc vars
+ *---------------------------------------------------------------------------*/
+void
+i4b_print_l2var(l2_softc_t *l2sc)
+{
+ DBGL2(L2_ERROR, "i4b_print_l2var", ("unit%d V(R)=%d, V(S)=%d, V(A)=%d,ACKP=%d,PBSY=%d,OBSY=%d\n",
+ l2sc->unit,
+ l2sc->vr,
+ l2sc->vs,
+ l2sc->va,
+ l2sc->ack_pend,
+ l2sc->peer_busy,
+ l2sc->own_busy));
+}
+
+/*---------------------------------------------------------------------------*
+ * got s or i frame, check if valid ack for last sent frame
+ *---------------------------------------------------------------------------*/
+void
+i4b_rxd_ack(l2_softc_t *l2sc, int nr)
+{
+
+#ifdef NOTDEF
+ DBGL2(L2_ERROR, "i4b_rxd_ack", ("N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d\n",
+ nr,
+ l2sc->ua_num,
+ l2sc->vr,
+ l2sc->vs,
+ l2sc->va));
+#endif
+
+ if(l2sc->ua_num != UA_EMPTY)
+ {
+ int s;
+
+ M128DEC(nr);
+
+ if(l2sc->ua_num != nr)
+ DBGL2(L2_ERROR, "i4b_rxd_ack", ("((N(R)-1)=%d) != (UA=%d) !!!\n", nr, l2sc->ua_num));
+
+ s = SPLI4B();
+
+ i4b_Dfreembuf(l2sc->ua_frame);
+ l2sc->ua_num = UA_EMPTY;
+
+ splx(s);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * if not already active, activate layer 1
+ *---------------------------------------------------------------------------*/
+void
+i4b_l1_activate(l2_softc_t *l2sc)
+{
+ if(l2sc->ph_active == PH_INACTIVE)
+ {
+ l2sc->ph_active = PH_ACTIVEPEND;
+ PH_Act_Req(l2sc->unit);
+ }
+};
+
+/*---------------------------------------------------------------------------*
+ * check for v(a) <= n(r) <= v(s)
+ * nr = receive sequence frame counter, va = acknowledge sequence frame
+ * counter and vs = transmit sequence frame counter
+ *---------------------------------------------------------------------------*/
+int
+i4b_l2_nr_ok(int nr, int va, int vs)
+{
+ if((va > nr) && ((nr != 0) || (va != 127)))
+ {
+ DBGL2(L2_ERROR, "i4b_l2_nr_ok", ("ERROR, va = %d, nr = %d, vs = %d [1]\n", va, nr, vs));
+ return 0; /* fail */
+ }
+
+ if((nr > vs) && ((vs != 0) || (nr != 127)))
+ {
+ DBGL2(L2_ERROR, "i4b_l2_nr_ok", ("ERROR, va = %d, nr = %d, vs = %d [2]\n", va, nr, vs));
+ return 0; /* fail */
+ }
+
+ return 1; /* good */
+}
+
+#endif /* NI4BQ921 > 0 */
+
diff --git a/sys/i4b/layer3/i4b_l2if.c b/sys/i4b/layer3/i4b_l2if.c
new file mode 100644
index 000000000000..33b1340738ec
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l2if.c
@@ -0,0 +1,642 @@
+/*
+ * 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_l2if.c - Layer 3 interface to Layer 2
+ * -------------------------------------------
+ *
+ * $Id: i4b_l2if.c,v 1.14 1998/12/05 18:05:28 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:31:26 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 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/mbuf.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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+static unsigned char make_q931_cause(cause_t cause);
+
+/*---------------------------------------------------------------------------*
+ * this converts our internal state (number) to the number specified
+ * in Q.931 and is used for reporting our state in STATUS messages.
+ *---------------------------------------------------------------------------*/
+int i4b_status_tab[] = {
+ 0, /* ST_U0, */
+ 1, /* ST_U1, */
+ 3, /* ST_U3, */
+ 4, /* ST_U4, */
+ 6, /* ST_U6, */
+ 7, /* ST_U7, */
+ 8, /* ST_U8, */
+ 9, /* ST_U9, */
+ 10, /* ST_U10, */
+ 11, /* ST_U11, */
+ 12, /* ST_U12, */
+ 19, /* ST_U19, */
+ 6, /* ST_IWA, */
+ 6, /* ST_IWR, */
+ 1, /* ST_OW, */
+ 6, /* ST_IWL, */
+};
+
+/*---------------------------------------------------------------------------*
+ * return a valid q.931/q.850 cause from any of the internal causes
+ *---------------------------------------------------------------------------*/
+static unsigned char
+make_q931_cause(cause_t cause)
+{
+ register unsigned char ret;
+
+ switch(GET_CAUSE_TYPE(cause))
+ {
+ case CAUSET_Q850:
+ ret = GET_CAUSE_VAL(cause);
+ break;
+ case CAUSET_I4B:
+ ret = cause_tab_q931[GET_CAUSE_VAL(cause)];
+ break;
+ default:
+ panic("make_q931_cause: unknown cause type!");
+ break;
+ }
+ ret |= EXT_LAST;
+ return(ret);
+}
+
+/*---------------------------------------------------------------------------*
+ * return status of data link
+ *---------------------------------------------------------------------------*/
+int
+i4b_get_dl_stat(call_desc_t *cd)
+{
+ return(ctrl_desc[cd->controller].dl_est);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL ESTABLISH INDICATION from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_establish_ind(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-ESTABLISH-IND", ("unit %d\n",unit));
+
+ /* first set DL up in controller descriptor */
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d DL established!\n",unit));
+ ctrl_desc[i].dl_est = DL_UP;
+ found = 1;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+ }
+
+ found = 0;
+
+ /* second, inform all (!) active call of the event */
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+ next_l3state(&call_desc[i], EV_DLESTIN);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, no cdid for unit %d found!\n", unit));
+ return(-1);
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * DL ESTABLISH CONFIRM from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_establish_cnf(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-ESTABLISH-CONF", ("unit %d\n",unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ ctrl_desc[call_desc[i].controller].dl_est = DL_UP;
+
+ DBGL3(L3_MSG, "i4b_dl_establish_cnf", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+
+ next_l3state(&call_desc[i], EV_DLESTCF);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_establish_cnf", ("ERROR, no cdid for unit %d found!\n", unit));
+ return(-1);
+ }
+ else
+ {
+ return(0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * DL RELEASE INDICATION from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_release_ind(int unit)
+{
+ int i;
+ int found = 0;
+
+ DBGL2(L2_PRIM, "DL-RELEASE-IND", ("unit %d\n",unit));
+
+ /* first set controller to down */
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d DL released!\n",unit));
+ ctrl_desc[i].dl_est = DL_DOWN;
+ found = 1;
+ }
+ }
+
+ if(found == 0)
+ {
+ DBGL3(L3_ERR, "i4b_dl_release_ind", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+ }
+
+ found = 0;
+
+ /* second, inform all (!) active calls of the event */
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (call_desc[i].cdid != 0) &&
+ (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d, index=%d cdid=%u cr=%d\n",
+ unit, i, call_desc[i].cdid, call_desc[i].cr));
+ next_l3state(&call_desc[i], EV_DLRELIN);
+ found++;
+ }
+ }
+
+ if(found == 0)
+ {
+ /* this is not an error since it might be a normal call end */
+ DBGL3(L3_MSG, "i4b_dl_release_ind", ("no cdid for unit %d found\n", unit));
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * DL RELEASE CONFIRM from Layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_release_cnf(int unit)
+{
+ int i;
+
+ DBGL2(L2_PRIM, "DL-RELEASE-CONF", ("unit %d\n",unit));
+
+ for(i=0; i < nctrl; i++)
+ {
+ if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[i].unit == unit))
+ {
+ DBGL3(L3_MSG, "i4b_dl_release_cnf", ("unit=%d DL released!\n",unit));
+ ctrl_desc[i].dl_est = DL_DOWN;
+ return(0);
+ }
+ }
+ DBGL3(L3_ERR, "i4b_dl_release_cnf", ("ERROR, controller not found for unit=%d!\n",unit));
+ return(-1);
+}
+
+/*---------------------------------------------------------------------------*
+ * i4b_dl_data_ind - process a rx'd I-frame got from layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_data_ind(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-DATA-IND", ("unit %d\n",unit));
+#endif
+ i4b_decode_q931(unit, m->m_len, m->m_data);
+ i4b_Dfreembuf(m);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * dl_unit_data_ind - process a rx'd U-frame got from layer 2
+ *---------------------------------------------------------------------------*/
+int
+i4b_dl_unit_data_ind(int unit, struct mbuf *m)
+{
+#ifdef NOTDEF
+ DBGL2(L2_PRIM, "DL-UNIT-DATA-IND", ("unit %d\n",unit));
+#endif
+ i4b_decode_q931(unit, m->m_len, m->m_data);
+ i4b_Dfreembuf(m);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * send CONNECT message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_connect(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx CONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_LEN)) == NULL)
+ panic("i4b_l3_tx_connect: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = CONNECT; /* message type = connect */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send RELEASE COMPLETE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_release_complete(call_desc_t *cd, int send_cause_flag)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int len = I_FRAME_HDRLEN + MSG_RELEASE_COMPLETE_LEN;
+
+ DBGL3(L3_PRIM, "tx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if(send_cause_flag == 0)
+ len -= 4;
+
+ if((m = i4b_Dgetmbuf(len)) == NULL)
+ panic("i4b_l3_tx_release_complete: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = RELEASE_COMPLETE; /* message type = release complete */
+
+ if(send_cause_flag)
+ {
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+ }
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send DISCONNECT message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_disconnect(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx DISCONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL)
+ panic("i4b_l3_tx_disconnect: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call ref length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = DISCONNECT; /* message type = disconnect */
+
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send SETUP message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_setup(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int slen = strlen(cd->src_telno);
+ int dlen = strlen(cd->dst_telno);
+
+ /*
+ * there is one additional octet if cd->bprot == BPROT_NONE
+ * NOTE: the selection of a bearer capability by a B L1
+ * protocol is highly questionable and a better
+ * mechanism should be used in future. (-hm)
+ */
+
+ DBGL3(L3_PRIM, "tx SETUP", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_SETUP_LEN + slen + dlen +
+ (cd->bprot == BPROT_NONE ? 1 : 0))) == NULL)
+ {
+ panic("i4b_l3_tx_setup: can't allocate mbuf\n");
+ }
+
+ cd->crflag = CRF_ORIG; /* we are the originating side */
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call ref length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = SETUP; /* message type = setup */
+
+ *ptr++ = IEI_SENDCOMPL; /* sending complete */
+
+ *ptr++ = IEI_BEARERCAP; /* bearer capability */
+
+ /* XXX
+ * currently i have no idea if this should be switched by
+ * the choosen B channel protocol or if there should be a
+ * separate configuration item for the bearer capability.
+ * For now, it is switched by the choosen b protocol (-hm)
+ */
+
+ switch(cd->bprot)
+ {
+ case BPROT_NONE: /* telephony */
+ *ptr++ = IEI_BEARERCAP_LEN+1;
+ *ptr++ = IT_CAP_SPEECH;
+ *ptr++ = IT_RATE_64K;
+ *ptr++ = IT_UL1_G711A;
+ break;
+
+ case BPROT_RHDLC: /* raw HDLC */
+ *ptr++ = IEI_BEARERCAP_LEN;
+ *ptr++ = IT_CAP_UNR_DIG_INFO;
+ *ptr++ = IT_RATE_64K;
+ break;
+
+ default:
+ *ptr++ = IEI_BEARERCAP_LEN;
+ *ptr++ = IT_CAP_UNR_DIG_INFO;
+ *ptr++ = IT_RATE_64K;
+ break;
+ }
+
+ *ptr++ = IEI_CHANNELID; /* channel id */
+ *ptr++ = IEI_CHANNELID_LEN; /* channel id length */
+
+ switch(cd->channelid)
+ {
+ case CHAN_B1:
+ *ptr++ = CHANNELID_B1;
+ break;
+ case CHAN_B2:
+ *ptr++ = CHANNELID_B2;
+ break;
+ default:
+ *ptr++ = CHANNELID_ANY;
+ break;
+ }
+
+ *ptr++ = IEI_CALLINGPN; /* calling party no */
+ *ptr++ = IEI_CALLINGPN_LEN+slen;/* calling party no length */
+ *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
+ strncpy(ptr, cd->src_telno, slen);
+ ptr += slen;
+
+ *ptr++ = IEI_CALLEDPN; /* called party no */
+ *ptr++ = IEI_CALLEDPN_LEN+dlen; /* called party no length */
+ *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */
+ strncpy(ptr, cd->dst_telno, dlen);
+ ptr += dlen;
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send CONNECT ACKNOWLEDGE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_connect_ack(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL)
+ panic("i4b_l3_tx_connect_ack: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = CONNECT_ACKNOWLEDGE; /* message type = connect ack */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send STATUS message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_status(call_desc_t *cd, u_char q850cause)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ DBGL3(L3_PRIM, "tx STATUS", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL)
+ panic("i4b_l3_tx_status: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = STATUS; /* message type = connect ack */
+
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = q850cause;
+
+ *ptr++ = IEI_CALLSTATE; /* call state ie */
+ *ptr++ = CALLSTATE_LEN;
+ *ptr++ = i4b_status_tab[cd->Q931state];
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send RELEASE message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag)
+{
+ struct mbuf *m;
+ u_char *ptr;
+ int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN;
+
+ DBGL3(L3_PRIM, "tx RELEASE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ if(send_cause_flag == 0)
+ len -= 4;
+
+ if((m = i4b_Dgetmbuf(len)) == NULL)
+ panic("i4b_l3_tx_release: can't allocate mbuf\n");
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = RELEASE; /* message type = release complete */
+
+ if(send_cause_flag)
+ {
+ *ptr++ = IEI_CAUSE; /* cause ie */
+ *ptr++ = CAUSE_LEN;
+ *ptr++ = CAUSE_STD_LOC_OUT;
+ *ptr++ = make_q931_cause(cd->cause_out);
+ }
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+/*---------------------------------------------------------------------------*
+ * send ALERTING message
+ *---------------------------------------------------------------------------*/
+void
+i4b_l3_tx_alert(call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_char *ptr;
+
+ if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL)
+ panic("i4b_l3_tx_alert: can't allocate mbuf\n");
+
+ DBGL3(L3_PRIM, "tx ALERT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr));
+
+ ptr = m->m_data + I_FRAME_HDRLEN;
+
+ *ptr++ = PD_Q931; /* protocol discriminator */
+ *ptr++ = 0x01; /* call reference length */
+ *ptr++ = setup_cr(cd, cd->cr); /* call reference value */
+ *ptr++ = ALERT; /* message type = alert */
+
+ DL_Data_Req(ctrl_desc[cd->controller].unit, m);
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_l3.h b/sys/i4b/layer3/i4b_l3.h
new file mode 100644
index 000000000000..9d05055fc537
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3.h
@@ -0,0 +1,80 @@
+/*
+ * 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_l3.h - layer 3 header file
+ * ------------------------------
+ *
+ * $Id: i4b_l3.h,v 1.8 1998/12/05 18:05:30 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:31:41 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L3_H_
+#define _I4B_L3_H_
+
+extern int utoc_tab[];
+extern unsigned char cause_tab_q931[];
+
+extern int i4b_aoc ( unsigned char *, call_desc_t *cd );
+extern void i4b_decode_q931 ( int unit, int msg_len, u_char *msg_ptr );
+extern int i4b_decode_q931_cs0_ie ( int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr );
+extern void i4b_decode_q931_message ( int unit, call_desc_t *cd, u_char message_type );
+extern void i4b_l3_stop_all_timers ( call_desc_t *cd );
+extern void i4b_l3_tx_alert ( call_desc_t *cd );
+extern void i4b_l3_tx_connect ( call_desc_t *cd );
+extern void i4b_l3_tx_connect_ack ( call_desc_t *cd );
+extern void i4b_l3_tx_disconnect ( call_desc_t *cd );
+extern void i4b_l3_tx_release ( call_desc_t *cd, int send_cause_flag );
+extern void i4b_l3_tx_release_complete ( call_desc_t *cd, int send_cause_flag );
+extern void i4b_l3_tx_setup ( call_desc_t *cd );
+extern void i4b_l3_tx_status ( call_desc_t *cd, u_char q850cause );
+extern int i4b_dl_data_ind ( int unit, struct mbuf *m );
+extern int i4b_dl_establish_cnf ( int unit );
+extern int i4b_dl_establish_ind ( int unit );
+extern int i4b_dl_release_cnf ( int unit );
+extern int i4b_dl_release_ind ( int unit );
+extern int i4b_dl_unit_data_ind ( int unit, struct mbuf *m );
+extern int i4b_get_dl_stat( call_desc_t *cd );
+extern int i4b_mdl_status_ind ( int unit, int status, int parm);
+extern void i4b_print_frame ( int len, u_char *buf );
+extern void next_l3state ( call_desc_t *cd, int event );
+extern char *print_l3state ( call_desc_t *cd );
+extern unsigned char setup_cr ( call_desc_t *cd, unsigned char cr );
+extern void T303_start ( call_desc_t *cd );
+extern void T303_stop ( call_desc_t *cd );
+extern void T305_start ( call_desc_t *cd );
+extern void T305_stop ( call_desc_t *cd );
+extern void T308_start ( call_desc_t *cd );
+extern void T308_stop ( call_desc_t *cd );
+extern void T309_start ( call_desc_t *cd );
+extern void T309_stop ( call_desc_t *cd );
+extern void T310_start ( call_desc_t *cd );
+extern void T310_stop ( call_desc_t *cd );
+extern void T313_start ( call_desc_t *cd );
+extern void T313_stop ( call_desc_t *cd );
+
+#endif /* _I4B_L3_H_ */
diff --git a/sys/i4b/layer3/i4b_l3fsm.c b/sys/i4b/layer3/i4b_l3fsm.c
new file mode 100644
index 000000000000..e45e1195e399
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3fsm.c
@@ -0,0 +1,1034 @@
+/*
+ * 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_l3fsm.c - layer 3 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l3fsm.c,v 1.13 1998/12/05 18:05:31 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:32:17 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 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/mbuf.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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+
+static void F_00A(call_desc_t *cd), F_00H(call_desc_t *cd), F_00I(call_desc_t *cd);
+static void F_00J(call_desc_t *cd);
+
+static void F_01B(call_desc_t *cd), F_01K(call_desc_t *cd), F_01L(call_desc_t *cd);
+static void F_01M(call_desc_t *cd), F_01N(call_desc_t *cd), F_01U(call_desc_t *cd);
+static void F_01O(call_desc_t *cd);
+
+static void F_03C(call_desc_t *cd), F_03N(call_desc_t *cd), F_03O(call_desc_t *cd);
+static void F_03P(call_desc_t *cd), F_03Y(call_desc_t *cd);
+
+static void F_04O(call_desc_t *cd);
+
+static void F_06D(call_desc_t *cd), F_06E(call_desc_t *cd), F_06F(call_desc_t *cd);
+static void F_06G(call_desc_t *cd), F_06J(call_desc_t *cd), F_06Q(call_desc_t *cd);
+
+static void F_07E(call_desc_t *cd), F_07F(call_desc_t *cd), F_07G(call_desc_t *cd);
+
+static void F_08R(call_desc_t *cd), F_08Z(call_desc_t *cd);
+
+static void F_09D(call_desc_t *cd), F_09E(call_desc_t *cd), F_09F(call_desc_t *cd);
+static void F_09G(call_desc_t *cd);
+
+static void F_11J(call_desc_t *cd), F_11Q(call_desc_t *cd), F_11V(call_desc_t *cd);
+
+static void F_12C(call_desc_t *cd), F_12J(call_desc_t *cd);
+
+static void F_19I(call_desc_t *cd), F_19J(call_desc_t *cd), F_19K(call_desc_t *cd);
+static void F_19W(call_desc_t *cd);
+
+static void F_NCNA(call_desc_t *cd), F_STENQ(call_desc_t *cd), F_STAT(call_desc_t *cd);
+static void F_INFO(call_desc_t *cd), F_RELCP(call_desc_t *cd), F_REL(call_desc_t *cd);
+static void F_DISC(call_desc_t *cd), F_DCRQ(call_desc_t *cd), F_UEM(call_desc_t *cd);
+static void F_SIGN(call_desc_t *cd), F_DLEI(call_desc_t *cd), F_ILL(call_desc_t *cd);
+static void F_309TO(call_desc_t *cd), F_DECF(call_desc_t *cd), F_FCTY(call_desc_t *cd);
+static void F_DECF1(call_desc_t *cd), F_DECF2(call_desc_t *cd), F_DECF3(call_desc_t *cd);
+static void F_DLRI(call_desc_t *cd), F_DLRIA(call_desc_t *cd), F_DECF4(call_desc_t *cd);
+
+static char *l3state_text[N_STATES] = {
+ "ST_U0 - Null",
+ "ST_U1 - Out Init",
+ "ST_U3 - Out Proc",
+ "ST_U4 - Out Delv",
+ "ST_U6 - In Pres",
+ "ST_U7 - In Rxd",
+ "ST_U8 - In ConReq",
+ "ST_U9 - In Proc",
+ "ST_U10 - Active",
+ "ST_U11 - Disc Req",
+ "ST_U12 - Disc Ind",
+ "ST_U19 - Rel Req",
+
+ "ST_IWA - In Wait EST-Accept",
+ "ST_IWR - In Wait EST-Reject",
+ "ST_OW - Out Wait EST",
+ "ST_IWL - In Wait EST-Alert",
+
+ "ST_SUSE - Subroutine sets state",
+
+ "Illegal State"
+};
+
+static char *l3event_text[N_EVENTS] = {
+ "EV_SETUPRQ - L4 SETUP REQ", /* setup request from L4 */
+ "EV_DISCRQ - L4 DISC REQ", /* disconnect request from L4 */
+ "EV_RELRQ - L4 REL REQ", /* release request from L4 */
+ "EV_ALERTRQ - L4 ALERT REQ", /* alerting request from L4 */
+ "EV_SETACRS - L4 accept RSP", /* setup response accept from l4 */
+ "EV_SETRJRS - L4 reject RSP", /* setup response reject from l4 */
+ "EV_SETDCRS - L4 ignore RSP", /* setup response dontcare from l4 */
+
+ "EV_SETUP - rxd SETUP", /* incoming SETUP message from L2 */
+ "EV_STATUS - rxd STATUS", /* incoming STATUS message from L2 */
+ "EV_RELEASE - rxd REL", /* incoming RELEASE message from L2 */
+ "EV_RELCOMP - rxd REL COMPL", /* incoming RELEASE COMPLETE from L2 */
+ "EV_SETUPAK - rxd SETUP ACK", /* incoming SETUP ACK message from L2 */
+ "EV_CALLPRC - rxd CALL PROC", /* incoming CALL PROCEEDING from L2 */
+ "EV_ALERT - rxd ALERT", /* incoming ALERT message from L2 */
+ "EV_CONNECT - rxd CONNECT", /* incoming CONNECT message from L2 */
+ "EV_PROGIND - rxd PROG IND", /* incoming Progress IND from L2 */
+ "EV_DISCONN - rxd DISC", /* incoming DISCONNECT message from L2 */
+ "EV_CONACK - rxd CONN ACK", /* incoming CONNECT ACK message from L2 */
+ "EV_STATENQ - rxd STAT ENQ", /* incoming STATUS ENQ message from L2 */
+ "EV_INFO - rxd INFO", /* incoming INFO message from L2 */
+ "EV_FACILITY - rxd FACILITY", /* incoming FACILITY message */
+
+ "EV_T303EXP - T303 timeout", /* Timer T303 expired */
+ "EV_T305EXP - T305 timeout", /* Timer T305 expired */
+ "EV_T308EXP - T308 timeout", /* Timer T308 expired */
+ "EV_T309EXP - T309 timeout", /* Timer T309 expired */
+ "EV_T310EXP - T310 timeout", /* Timer T310 expired */
+ "EV_T313EXP - T313 timeout", /* Timer T313 expired */
+
+ "EV_DLESTIN - L2 DL_Est_Ind", /* dl establish indication from l2 */
+ "EV_DLRELIN - L2 DL_Rel_Ind", /* dl release indication from l2 */
+ "EV_DLESTCF - L2 DL_Est_Cnf", /* dl establish confirm from l2 */
+ "EV_DLRELCF - L2 DL_Rel_Cnf", /* dl release confirm from l2 */
+
+ "EV_ILL - Illegal event!!" /* Illegal */
+};
+
+/*---------------------------------------------------------------------------*
+ * layer 3 state transition table
+ *---------------------------------------------------------------------------*/
+struct l3state_tab {
+ void (*func) (call_desc_t *); /* function to execute */
+ int newstate; /* next state */
+} l3state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_SETUPRQ*/ {{F_00A, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DISCRQ */ {{F_ILL, ST_ILL}, {F_01B, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_NCNA, ST_U12}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELRQ */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_12C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ALERTRQ*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06D, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_09D, ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETACRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06E, ST_SUSE}, {F_07E, ST_U8}, {F_ILL, ST_ILL}, {F_09E, ST_U8}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETRJRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06F, ST_SUSE}, {F_07F, ST_U0}, {F_ILL, ST_ILL}, {F_09F, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETDCRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06G, ST_U0}, {F_07G, ST_U0}, {F_ILL, ST_ILL}, {F_09G, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_SETUP */ {{F_00H, ST_U6}, {F_SIGN, ST_U1}, {F_SIGN, ST_U3}, {F_SIGN, ST_U4}, {F_SIGN, ST_U6}, {F_SIGN, ST_U7}, {F_SIGN, ST_U8}, {F_SIGN, ST_U9}, {F_SIGN, ST_U10}, {F_SIGN, ST_U11}, {F_SIGN, ST_U12}, {F_SIGN, ST_U19}, {F_SIGN, ST_IWA}, {F_SIGN, ST_IWR}, {F_SIGN, ST_OW}, {F_SIGN, ST_IWL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_STATUS */ {{F_00I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_19I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELEASE*/ {{F_00J, ST_U0}, {F_UEM, ST_SUSE}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_06J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_11J, ST_U0}, {F_12J, ST_U0}, {F_19J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_RELCOMP*/ {{F_NCNA, ST_U0}, {F_01K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_19K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_SETUPAK*/ {{F_UEM, ST_SUSE}, {F_01L, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CALLPRC*/ {{F_UEM, ST_SUSE}, {F_01M, ST_U3}, {F_NCNA, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ALERT */ {{F_UEM, ST_SUSE}, {F_01N, ST_U4}, {F_03N, ST_U4}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CONNECT*/ {{F_UEM, ST_SUSE}, {F_01O, ST_U10}, {F_03O, ST_U10}, {F_04O, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_PROGIND*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_03P, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DISCONN*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_06Q, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_11Q, ST_U19}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_CONACK */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_08R, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_STATENQ*/ {{F_STENQ,ST_U0}, {F_STENQ,ST_U1}, {F_STENQ,ST_U3}, {F_STENQ,ST_U4}, {F_STENQ,ST_U6}, {F_STENQ,ST_U7}, {F_STENQ,ST_U8}, {F_STENQ,ST_U9}, {F_STENQ,ST_U10}, {F_STENQ,ST_U11}, {F_STENQ,ST_U12}, {F_STENQ,ST_U19}, {F_STENQ,ST_IWA}, {F_STENQ,ST_IWR}, {F_STENQ,ST_OW}, {F_STENQ,ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_INFO */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_INFO, ST_U3}, {F_INFO, ST_U4}, {F_UEM, ST_SUSE}, {F_INFO, ST_U7}, {F_INFO, ST_U8}, {F_INFO, ST_U9}, {F_INFO, ST_U10}, {F_INFO, ST_U11}, {F_INFO, ST_U12}, {F_UEM, ST_SUSE}, {F_INFO, ST_IWA}, {F_INFO, ST_IWR}, {F_INFO, ST_OW}, {F_INFO, ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_FACILITY*/ {{F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_T303EXP*/ {{F_ILL, ST_ILL}, {F_01U, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T305EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_11V, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T308EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_19W, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T309EXP*/ {{F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T310EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03Y, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_T313EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_08Z, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
+/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*EV_DLESTIN*/ {{F_ILL, ST_ILL}, {F_DLEI, ST_U1}, {F_DLEI, ST_U3}, {F_DLEI, ST_U4}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLRELIN*/ {{F_NCNA, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRIA,ST_U10}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLESTCF*/ {{F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF2,ST_U8}, {F_DECF3,ST_U0}, {F_DECF1,ST_U1}, {F_DECF4,ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_DLRELCF*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
+/*EV_ILL */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void next_l3state(call_desc_t *cd, int event)
+{
+ int currstate, newstate;
+
+ if(event > N_EVENTS)
+ panic("i4b_l3fsm.c: event > N_EVENTS\n");
+
+ currstate = cd->Q931state;
+
+ if(currstate > N_STATES)
+ panic("i4b_l3fsm.c: currstate > N_STATES\n");
+
+ newstate = l3state_tab[event][currstate].newstate;
+
+ if(newstate > N_STATES)
+ panic("i4b_l3fsm.c: newstate > N_STATES\n");
+
+ DBGL3(L3_F_MSG, "next_l3state", ("L3 FSM event [%s]: [%s => %s]\n",
+ l3event_text[event],
+ l3state_text[currstate],
+ l3state_text[newstate]));
+
+ /* execute function */
+
+ (*l3state_tab[event][currstate].func)(cd);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = currstate;
+ DBGL3(L3_F_ERR, "next_l3state", ("FSM illegal state, state = %s, event = %s!\n",
+ l3state_text[newstate],
+ l3event_text[event]));
+ }
+
+ if(newstate != ST_SUSE)
+ cd->Q931state = newstate;
+}
+
+/*---------------------------------------------------------------------------*
+ * resturn pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *print_l3state(call_desc_t *cd)
+{
+ return((char *) l3state_text[cd->Q931state]);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event L4 setup req
+ *---------------------------------------------------------------------------*/
+static void F_00A(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00A", ("FSM function F_00A executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_OW;
+ }
+ else
+ {
+ i4b_l3_tx_setup(cd);
+ cd->Q931state = ST_U1;
+ }
+
+ cd->T303_first_to = 1;
+ T303_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event SETUP from L2
+ *---------------------------------------------------------------------------*/
+static void F_00H(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00H", ("FSM function F_00H executing\n"));
+ i4b_l4_connect_ind(cd); /* tell l4 we have an incoming setup */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_00I(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00I", ("FSM function F_00I executing\n"));
+
+ if(cd->call_state != 0)
+ {
+ cd->cause_out = 101;
+ i4b_l3_tx_release_complete(cd, 1); /* 1 = send cause */
+ }
+ cd->Q931state = ST_U0;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U0 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_00J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_00J", ("FSM function F_00J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0); /* 0 = don't send cause */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event disconnect req from L4
+ *---------------------------------------------------------------------------*/
+static void F_01B(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01B", ("FSM function F_01B executing\n"));
+ /* cause from L4 */
+ i4b_l3_tx_disconnect(cd);
+ T303_stop(cd);
+ T305_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_01K(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01K", ("FSM function F_01K executing\n"));
+ T303_stop(cd);
+ i4b_l4_disconnect_ind(cd); /* tell l4 we were rejected */
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event SETUP ACK from L2
+ *---------------------------------------------------------------------------*/
+static void F_01L(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01L", ("FSM function F_01L executing\n"));
+ T303_stop(cd);
+
+ /*
+ * since this implementation does NOT support overlap sending,
+ * we react here as if we received a CALL PROCEEDING because
+ * several PBX's react with a SETUP ACK even if the called
+ * number is complete AND we sent a SENDING COMPLETE in the
+ * preceeding SETUP message. (-hm)
+ */
+
+ T310_start(cd);
+ i4b_l4_proceeding_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event CALL PROCEEDING from L2
+ *---------------------------------------------------------------------------*/
+static void F_01M(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01M", ("FSM function F_01M executing\n"));
+ T303_stop(cd);
+ T310_start(cd);
+ i4b_l4_proceeding_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event ALERT from L2 (XXX !)
+ *---------------------------------------------------------------------------*/
+static void F_01N(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01N", ("FSM function F_01N executing\n"));
+ T303_stop(cd);
+ i4b_l4_alert_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event CONNECT from L2 (XXX !)
+ *---------------------------------------------------------------------------*/
+static void F_01O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01O", ("FSM function F_01O executing\n"));
+ T303_stop(cd);
+ i4b_l3_tx_connect_ack(cd);
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U1 event T303 timeout
+ *---------------------------------------------------------------------------*/
+static void F_01U(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_01U", ("FSM function F_01U executing\n"));
+ if(cd->T303_first_to == 1)
+ {
+ cd->T303_first_to = 0;
+ i4b_l3_tx_setup(cd);
+ T303_start(cd);
+ cd->Q931state = ST_U1;
+ }
+ else
+ {
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event release req from L4
+ *---------------------------------------------------------------------------*/
+static void F_03C(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03C", ("FSM function F_03C executing\n"));
+ T310_stop(cd);
+ cd->cause_out = 6;
+ i4b_l3_tx_release(cd, 1); /* 0 = don't send cause */
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event ALERT from L2
+ *---------------------------------------------------------------------------*/
+static void F_03N(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03N", ("FSM function F_03N executing\n"));
+ T310_stop(cd);
+ i4b_l4_alert_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event CONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_03O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03O", ("FSM function F_03O executing\n"));
+ T310_stop(cd);
+ i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event PROGESS IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_03P(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03P", ("FSM function F_03P executing\n"));
+ T310_stop(cd);
+#ifdef NOTDEF
+ i4b_l4_progress_ind(cd);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U3 event T310 timeout
+ *---------------------------------------------------------------------------*/
+static void F_03Y(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_03Y", ("FSM function F_03Y executing\n"));
+ cd->cause_out = 102; /* recovery on timer expiry */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U4 event CONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_04O(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_04O", ("FSM function F_04O executing\n"));
+ i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event alert req from L4
+ *---------------------------------------------------------------------------*/
+static void F_06D(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06D", ("FSM function F_06D executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWL;
+ }
+ else
+ {
+ i4b_l3_tx_alert(cd);
+ cd->Q931state = ST_U7;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_06E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06E", ("FSM function F_06E executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWA;
+ }
+ else
+ {
+ i4b_l3_tx_connect(cd);
+ cd->Q931state = ST_U8;
+ }
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_06F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06F", ("FSM function F_06F executing\n"));
+
+ if(i4b_get_dl_stat(cd) == DL_DOWN)
+ {
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+ cd->Q931state = ST_IWR;
+ }
+ else
+ {
+ int s = SPLI4B();
+ i4b_l3_tx_release_complete(cd, 1);
+ cd->Q931state = ST_U0;
+ freecd_by_cd(cd);
+ splx(s);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event incoming setup ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_06G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06G", ("FSM function F_06G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_06J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06J", ("FSM function F_06J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U6 event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_06Q(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_06Q", ("FSM function F_06Q executing\n"));
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_07E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07E", ("FSM function F_07E executing\n"));
+ i4b_l3_tx_connect(cd);
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_07F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07F", ("FSM function F_07F executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U7 event setup response ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_07G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_07G", ("FSM function F_07G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U8 event CONNECT ACK from L2
+ *---------------------------------------------------------------------------*/
+static void F_08R(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_08R", ("FSM function F_08R executing\n"));
+ T313_stop(cd);
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U8 event T313 timeout
+ *---------------------------------------------------------------------------*/
+static void F_08Z(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_08Z", ("FSM function F_08Z executing\n"));
+ cd->cause_out = 102; /* recovery on timer expiry */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ i4b_l4_disconnect_ind(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event alert req from L4
+ *---------------------------------------------------------------------------*/
+static void F_09D(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09D", ("FSM function F_09D executing\n"));
+ i4b_l3_tx_alert(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response accept from L4
+ *---------------------------------------------------------------------------*/
+static void F_09E(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09E", ("FSM function F_09E executing\n"));
+ i4b_l3_tx_connect(cd);
+ T313_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response reject from L4
+ *---------------------------------------------------------------------------*/
+static void F_09F(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09F", ("FSM function F_09F executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U9 event setup response ignore from L4
+ *---------------------------------------------------------------------------*/
+static void F_09G(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_09G", ("FSM function F_09G executing\n"));
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_11J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11J", ("FSM function F_11J executing\n"));
+ T305_stop(cd);
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_11Q(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11Q", ("FSM function F_11Q executing\n"));
+ T305_stop(cd);
+ i4b_l3_tx_release(cd, 0);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U11 event T305 timeout
+ *---------------------------------------------------------------------------*/
+static void F_11V(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_11V", ("FSM function F_11V executing\n"));
+ cd->cause_out = 102;
+ i4b_l3_tx_release(cd, 1);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U12 event release req from L4
+ *---------------------------------------------------------------------------*/
+static void F_12C(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_12C", ("FSM function F_12C executing\n"));
+ i4b_l3_tx_release(cd, 1);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U12 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_12J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_12J", ("FSM function F_12J executing\n"));
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_19I(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19I", ("FSM function F_19I executing\n"));
+
+ if(cd->call_state == 0)
+ {
+ i4b_l4_status_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+ else
+ {
+ cd->Q931state = ST_U19;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_19J(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19J", ("FSM function F_19J executing\n"));
+ T308_stop(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_19K(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19K", ("FSM function F_19K executing\n"));
+ T308_stop(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U19 event T308 timeout
+ *---------------------------------------------------------------------------*/
+static void F_19W(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_19W", ("FSM function F_19W executing\n"));
+ if(cd->T308_first_to == 0)
+ {
+ cd->T308_first_to = 1;
+ i4b_l3_tx_release(cd, 0);
+ T308_start(cd);
+ cd->Q931state = ST_U19;
+ }
+ else
+ {
+ cd->T308_first_to = 0;
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+ cd->Q931state = ST_U0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM routine no change no action
+ *---------------------------------------------------------------------------*/
+static void F_NCNA(call_desc_t *cd)
+{
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event STATUS ENQ from L2
+ *---------------------------------------------------------------------------*/
+static void F_STENQ(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_STENQ", ("FSM function F_STENQ executing\n"));
+ i4b_l3_tx_status(cd, CAUSE_Q850_STENQRSP); /* 30, resonse to stat enq */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 & 19 event STATUS from L2
+ *---------------------------------------------------------------------------*/
+static void F_STAT(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_STAT", ("FSM function F_STAT executing\n"));
+ if(cd->call_state == 0)
+ {
+ i4b_l4_status_ind(cd);
+ cd->Q931state = ST_U0;
+ freecd_by_cd(cd);
+ }
+ else
+ {
+ /* XXX !!!!!!!!!!!!!!!!!! */
+
+ i4b_l4_status_ind(cd);
+ cd->cause_out = 101; /* message not compatible with call state */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ cd->Q931state = ST_U11;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event INFORMATION from L2
+ *---------------------------------------------------------------------------*/
+static void F_INFO(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_INFO", ("FSM function F_INFO executing\n"));
+ i4b_l4_info_ind(cd);
+ /* remain in current state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event RELEASE COMPLETE from L2
+ *---------------------------------------------------------------------------*/
+static void F_RELCP(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_RELCP", ("FSM function F_RELCP executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event RELEASE from L2
+ *---------------------------------------------------------------------------*/
+static void F_REL(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_REL", ("FSM function F_REL executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l3_tx_release_complete(cd, 0);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event DISCONNECT from L2
+ *---------------------------------------------------------------------------*/
+static void F_DISC(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DISC", ("FSM function F_DISC executing\n"));
+ i4b_l3_stop_all_timers(cd);
+
+ /*
+ * no disconnect ind to L4, no jump to state U12
+ * instead we issue a RELEASE and jump to U19
+ */
+
+ i4b_l3_tx_release(cd, 0);
+ cd->T308_first_to = 1;
+ T308_start(cd);
+ cd->Q931state = ST_U19;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM some states event disconnect request from L4
+ *---------------------------------------------------------------------------*/
+static void F_DCRQ(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DCRQ", ("FSM function F_DCRQ executing\n"));
+ /* cause from L4 */
+ i4b_l3_tx_disconnect(cd);
+ T305_start(cd);
+ cd->Q931state = ST_U11;
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 event unexpected message from L2
+ *---------------------------------------------------------------------------*/
+static void F_UEM(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_UEM", ("FSM function F_UEM executing, state = %s\n", print_l3state(cd)));
+ i4b_l3_tx_status(cd, CAUSE_Q850_MSGNCWCS); /* 101, message not compatible with call state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except 0 event SETUP from L2
+ *---------------------------------------------------------------------------*/
+static void F_SIGN(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_SIGN", ("FSM function F_SIGN executing\n"));
+
+/* XXX */ /* freecd_by_cd(cd); ?????????? XXX */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM relevant states event DL ESTABLISH IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLEI(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLEI", ("FSM function F_DLEI executing\n"));
+
+/* XXX */
+
+ /* remain in current state */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event illegal event occured
+ *---------------------------------------------------------------------------*/
+static void F_ILL(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_ILL", ("FSM function F_ILL executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event T309 timeout
+ *---------------------------------------------------------------------------*/
+static void F_309TO(call_desc_t *cd)
+{
+ DBGL3(L3_F_ERR, "F_309TO", ("FSM function F_309TO executing\n"));
+
+/* XXX */
+
+#ifdef NOTDEF
+ i4b_l4_dl_fail_ind(cd);
+#endif
+
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event FACILITY message received
+ *---------------------------------------------------------------------------*/
+static void F_FCTY(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_FCTY", ("FSM function F_FCTY executing\n"));
+ /* ST_SUSE, no change in state ! */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_OW event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF1(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF1", ("FSM function F_DECF1 executing\n"));
+ i4b_l3_tx_setup(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWA event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF2(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF2", ("FSM function F_DECF2 executing\n"));
+ i4b_l3_tx_connect(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWR event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF3(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF3", ("FSM function F_DECF3 executing\n"));
+ i4b_l3_tx_release_complete(cd, 1);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state ST_IWL event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF4(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF4", ("FSM function F_DECF4 executing\n"));
+ i4b_l3_tx_alert(cd);
+}
+
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state event DL ESTABLISH CONF from L2
+ *---------------------------------------------------------------------------*/
+static void F_DECF(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DECF", ("FSM function F_DECF executing\n"));
+ T309_stop(cd);
+ i4b_l3_tx_status(cd, CAUSE_Q850_NORMUNSP); /* 31, normal unspecified */
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM any state except U10 event DL RELEASE IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLRI(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLRI", ("FSM function F_DLRI executing\n"));
+ i4b_l3_stop_all_timers(cd);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L3 FSM state U10 event DL RELEASE IND from L2
+ *---------------------------------------------------------------------------*/
+static void F_DLRIA(call_desc_t *cd)
+{
+ DBGL3(L3_F_MSG, "F_DLRIA", ("FSM function F_DLRIA executing\n"));
+
+ if(cd->T309 == TIMER_IDLE)
+ T309_start(cd);
+
+ DL_Est_Req(ctrl_desc[cd->controller].unit);
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_l3fsm.h b/sys/i4b/layer3/i4b_l3fsm.h
new file mode 100644
index 000000000000..d69b810b45ad
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3fsm.h
@@ -0,0 +1,105 @@
+/*
+ * 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_l3fsm.c - layer 3 FSM
+ * -------------------------
+ *
+ * $Id: i4b_l3fsm.h,v 1.5 1998/12/05 18:05:33 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:32:45 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_L3FSM_H_
+#define _I4B_L3FSM_H_
+
+enum Q931_states {
+ ST_U0,
+ ST_U1,
+ ST_U3,
+ ST_U4,
+ ST_U6,
+ ST_U7,
+ ST_U8,
+ ST_U9,
+ ST_U10,
+ ST_U11,
+ ST_U12,
+ ST_U19,
+
+ ST_IWA, /* incoming call, wait establish, then accept */
+ ST_IWR, /* incoming call, wait establish, then reject */
+ ST_OW, /* outgoing call, wait establish */
+ ST_IWL, /* incoming call, wait establish, then alert */
+
+ ST_SUSE, /* SUBroutine SETs new state on exit */
+ ST_ILL, /* Illegal */
+
+ N_STATES /* number of states */
+};
+
+enum Q931_events {
+
+ EV_SETUPRQ, /* setup request from L4 */
+ EV_DISCRQ, /* disconnect request from L4 */
+ EV_RELRQ, /* release request from L4 */
+ EV_ALERTRQ, /* alerting request from L4 */
+ EV_SETACRS, /* setup response accept from l4 */
+ EV_SETRJRS, /* setup response reject from l4 */
+ EV_SETDCRS, /* setup response dontcare from l4 */
+
+ EV_SETUP, /* incoming SETUP message from L2 */
+ EV_STATUS, /* incoming STATUS message from L2 */
+ EV_RELEASE, /* incoming RELEASE message from L2 */
+ EV_RELCOMP, /* incoming RELEASE COMPLETE from L2 */
+ EV_SETUPAK, /* incoming SETUP ACK message from L2 */
+ EV_CALLPRC, /* incoming CALL PROCEEDING from L2 */
+ EV_ALERT, /* incoming ALERT message from L2 */
+ EV_CONNECT, /* incoming CONNECT message from L2 */
+ EV_PROGIND, /* incoming Progress IND from L2 */
+ EV_DISCONN, /* incoming DISCONNECT message from L2 */
+ EV_CONACK, /* incoming CONNECT ACK message from L2 */
+ EV_STATENQ, /* incoming STATUS ENQ message from L2 */
+ EV_INFO, /* incoming INFO message from L2 */
+ EV_FACILITY, /* FACILITY message */
+
+ EV_T303EXP, /* Timer T303 expired */
+ EV_T305EXP, /* Timer T305 expired */
+ EV_T308EXP, /* Timer T308 expired */
+ EV_T309EXP, /* Timer T309 expired */
+ EV_T310EXP, /* Timer T310 expired */
+ EV_T313EXP, /* Timer T313 expired */
+
+ EV_DLESTIN, /* dl establish indication from l2 */
+ EV_DLRELIN, /* dl release indication from l2 */
+ EV_DLESTCF, /* dl establish confirm from l2 */
+ EV_DLRELCF, /* dl release indication from l2 */
+
+ EV_ILL, /* Illegal */
+ N_EVENTS
+};
+
+#endif /* _I4B_L3FSM_H_ */
diff --git a/sys/i4b/layer3/i4b_l3timer.c b/sys/i4b/layer3/i4b_l3timer.c
new file mode 100644
index 000000000000..6c1a2d30122b
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l3timer.c
@@ -0,0 +1,347 @@
+/*
+ * 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_l3timer.c - timer and timeout handling for layer 3
+ * ------------------------------------------------------
+ *
+ * $Id: i4b_l3timer.c,v 1.9 1998/12/05 18:05:35 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:00 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 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/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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+/*---------------------------------------------------------------------------*
+ * stop all layer 3 timers
+ *---------------------------------------------------------------------------*/
+void i4b_l3_stop_all_timers(call_desc_t *cd)
+{
+ T303_stop(cd);
+ T305_stop(cd);
+ T308_stop(cd);
+ T309_stop(cd);
+ T310_stop(cd);
+ T313_stop(cd);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T303_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T303_timeout", ("SETUP not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T303EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 start
+ *---------------------------------------------------------------------------*/
+void
+T303_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T303_start", ("cr = %d\n", cd->cr));
+ cd->T303 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T303_callout = timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T303 stop
+ *---------------------------------------------------------------------------*/
+void
+T303_stop(call_desc_t *cd)
+{
+ if(cd->T303 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, cd->T303_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd);
+#endif
+ cd->T303 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T303_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T305_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T305_timeout", ("DISC not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T305EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 start
+ *---------------------------------------------------------------------------*/
+void
+T305_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T305_start", ("cr = %d\n", cd->cr));
+ cd->T305 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T305_callout = timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T305 stop
+ *---------------------------------------------------------------------------*/
+void
+T305_stop(call_desc_t *cd)
+{
+ if(cd->T305 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, cd->T305_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd);
+#endif
+ cd->T305 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T305_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T308_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T308_timeout", ("REL not answered, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T308EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 start
+ *---------------------------------------------------------------------------*/
+void
+T308_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T308_start", ("cr = %d\n", cd->cr));
+ cd->T308 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T308_callout = timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T308 stop
+ *---------------------------------------------------------------------------*/
+void
+T308_stop(call_desc_t *cd)
+{
+ if(cd->T308 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, cd->T308_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd);
+#endif
+ cd->T308 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T308_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T309_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T309_timeout", ("datalink not reconnected, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T309EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 start
+ *---------------------------------------------------------------------------*/
+void
+T309_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T309_start", ("cr = %d\n", cd->cr));
+ cd->T309 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T309_callout = timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T309 stop
+ *---------------------------------------------------------------------------*/
+void
+T309_stop(call_desc_t *cd)
+{
+ if(cd->T309 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, cd->T309_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd);
+#endif
+ cd->T309 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T309_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T310_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T310_timeout", ("CALL PROC timeout, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T310EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 start
+ *---------------------------------------------------------------------------*/
+void
+T310_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T310_start", ("cr = %d\n", cd->cr));
+ cd->T310 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T310_callout = timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T310 stop
+ *---------------------------------------------------------------------------*/
+void
+T310_stop(call_desc_t *cd)
+{
+ if(cd->T310 != TIMER_IDLE)
+ {
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, cd->T310_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd);
+#endif
+ cd->T310 = TIMER_IDLE;
+ }
+ DBGL3(L3_T_MSG, "T310_stop", ("cr = %d\n", cd->cr));
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 timeout function
+ *---------------------------------------------------------------------------*/
+static void
+T313_timeout(call_desc_t *cd)
+{
+ DBGL3(L3_T_ERR, "T313_timeout", ("CONN ACK not received, cr = %d\n", cd->cr));
+ next_l3state(cd, EV_T313EXP);
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 start
+ *---------------------------------------------------------------------------*/
+void
+T313_start(call_desc_t *cd)
+{
+ DBGL3(L3_T_MSG, "T313_start", ("cr = %d\n", cd->cr));
+ cd->T313 = TIMER_ACTIVE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ cd->T313_callout = timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL);
+#else
+ timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * timer T313 stop
+ *---------------------------------------------------------------------------*/
+void
+T313_stop(call_desc_t *cd)
+{
+ if(cd->T313 != TIMER_IDLE)
+ {
+ cd->T313 = TIMER_IDLE;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, cd->T313_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd);
+#endif
+ }
+ DBGL3(L3_T_MSG, "T313_stop", ("cr = %d\n", cd->cr));
+}
+
+#endif /* NI4BQ931 > 0 */
+
diff --git a/sys/i4b/layer3/i4b_l4if.c b/sys/i4b/layer3/i4b_l4if.c
new file mode 100644
index 000000000000..55d9bb9da445
--- /dev/null
+++ b/sys/i4b/layer3/i4b_l4if.c
@@ -0,0 +1,339 @@
+/*
+ * 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_l4if.c - Layer 3 interface to Layer 4
+ * -------------------------------------------
+ *
+ * $Id: i4b_l4if.c,v 1.17 1998/12/05 18:05:36 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:16 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 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/mbuf.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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+extern void isic_settrace(int unit, int val); /*XXX*/
+extern int isic_gettrace(int unit); /*XXX*/
+
+static void n_connect_request(u_int cdid);
+static void n_connect_response(u_int cdid, int response, int cause);
+static void n_disconnect_request(u_int cdid, int cause);
+static void n_alert_request(u_int cdid);
+static void n_mgmt_command(int unit, int cmd, int parm);
+
+/*---------------------------------------------------------------------------*
+ * i4b_mdl_status_ind - status indication from lower layers
+ *---------------------------------------------------------------------------*/
+int
+i4b_mdl_status_ind(int unit, int status, int parm)
+{
+ int sendup;
+ int i;
+
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("unit = %d, status = %d, parm = %d\n", unit, status, parm));
+
+ switch(status)
+ {
+ case STI_ATTACH:
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_ATTACH: attaching unit %d to controller %d\n", unit, nctrl));
+
+ /* init function pointers */
+
+ ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request;
+ ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response;
+ ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request;
+ ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request;
+ ctrl_desc[nctrl].N_SET_TRACE = isic_settrace;
+ ctrl_desc[nctrl].N_GET_TRACE = isic_gettrace;
+ ctrl_desc[nctrl].N_DOWNLOAD = NULL; /* only used by active cards */
+ ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* only used by active cards */
+ ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command;
+
+ /* init type and unit */
+
+ ctrl_desc[nctrl].unit = unit;
+ ctrl_desc[nctrl].ctrl_type = CTRL_PASSIVE;
+ ctrl_desc[nctrl].card_type = parm;
+
+ /* state fields */
+
+ ctrl_desc[nctrl].dl_est = DL_DOWN;
+ ctrl_desc[nctrl].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[nctrl].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[nctrl].tei = -1;
+
+ /* init unit to controller table */
+
+ utoc_tab[unit] = nctrl;
+
+ /* increment no. of controllers */
+
+ nctrl++;
+
+ break;
+
+ case STI_L1STAT:
+ i4b_l4_l12stat(unit, 1, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L1STAT: unit %d layer 1 = %s\n", unit, status ? "up" : "down"));
+ break;
+
+ case STI_L2STAT:
+ i4b_l4_l12stat(unit, 2, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L2STAT: unit %d layer 2 = %s\n", unit, status ? "up" : "down"));
+ break;
+
+ case STI_TEIASG:
+ ctrl_desc[unit].tei = parm;
+ i4b_l4_teiasg(unit, parm);
+ DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_TEIASG: unit %d TEI = %d = 0x%02x\n", unit, parm, parm));
+ break;
+
+ case STI_PDEACT: /* L1 T4 timeout */
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_PDEACT: unit %d TEI = %d = 0x%02x\n", unit, parm, parm));
+
+ sendup = 0;
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ if(call_desc[i].cdid != CDID_UNUSED)
+ sendup++;
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+
+ if(sendup)
+ i4b_l4_pdeact(unit, sendup);
+ break;
+
+ case STI_NOL1ACC: /* no outgoing access to S0 */
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_NOL1ACC: unit %d no outgoing access to S0\n", unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ if(call_desc[i].cdid != CDID_UNUSED)
+ {
+ SET_CAUSE_TYPE(call_desc[i].cause_in, CAUSET_I4B);
+ SET_CAUSE_VAL(call_desc[i].cause_in, CAUSE_I4B_L1ERROR);
+ i4b_l4_disconnect_ind(&(call_desc[i]));
+ }
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+ break;
+
+ default:
+ DBGL3(L3_ERR, "i4b_mdl_status_ind", ("ERROR, unit %d, unknown status value %d!\n", unit, status));
+ break;
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * send command to the lower layers
+ *---------------------------------------------------------------------------*/
+static void
+n_mgmt_command(int unit, int cmd, int parm)
+{
+ int i;
+
+ switch(cmd)
+ {
+ case CMR_DOPEN:
+ DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DOPEN for unit %d\n", unit));
+
+ for(i=0; i < N_CALL_DESC; i++)
+ {
+ if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) &&
+ (ctrl_desc[call_desc[i].controller].unit == unit))
+ {
+ call_desc[i].cdid = CDID_UNUSED;
+ }
+ }
+
+ ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
+ ctrl_desc[utoc_tab[unit]].tei = -1;
+ break;
+
+ case CMR_DCLOSE:
+ DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DCLOSE for unit %d\n", unit));
+ break;
+
+ default:
+ break;
+
+ }
+
+ MDL_Command_Req(unit, cmd, parm);
+
+}
+
+/*---------------------------------------------------------------------------*
+ * handle connect request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_connect_request(u_int cdid)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ next_l3state(cd, EV_SETUPRQ);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle setup response message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_connect_response(u_int cdid, int response, int cause)
+{
+ call_desc_t *cd;
+ int chstate;
+
+ cd = cd_by_cdid(cdid);
+
+ T400_stop(cd);
+
+ cd->response = response;
+ cd->cause_out = cause;
+
+ switch(response)
+ {
+ case SETUP_RESP_ACCEPT:
+ next_l3state(cd, EV_SETACRS);
+ chstate = BCH_ST_USED;
+ break;
+
+ case SETUP_RESP_REJECT:
+ next_l3state(cd, EV_SETRJRS);
+ chstate = BCH_ST_FREE;
+ break;
+
+ case SETUP_RESP_DNTCRE:
+ next_l3state(cd, EV_SETDCRS);
+ chstate = BCH_ST_FREE;
+ break;
+
+ default: /* failsafe */
+ next_l3state(cd, EV_SETDCRS);
+ chstate = BCH_ST_FREE;
+ DBGL3(L3_ERR, "n_connect_response", ("unknown response, doing SETUP_RESP_DNTCRE"));
+ break;
+ }
+
+ if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
+ {
+ ctrl_desc[cd->controller].bch_state[cd->channelid] = chstate;
+ }
+ else
+ {
+ DBGL3(L3_ERR, "n_connect_response", ("ERROR, invalid channel %d\n", cd->channelid));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * handle disconnect request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_disconnect_request(u_int cdid, int cause)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ cd->cause_out = cause;
+
+ next_l3state(cd, EV_DISCRQ);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle alert request message from userland
+ *---------------------------------------------------------------------------*/
+static void
+n_alert_request(u_int cdid)
+{
+ call_desc_t *cd;
+
+ cd = cd_by_cdid(cdid);
+
+ next_l3state(cd, EV_ALERTRQ);
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q931.c b/sys/i4b/layer3/i4b_q931.c
new file mode 100644
index 000000000000..6c111d101228
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q931.c
@@ -0,0 +1,624 @@
+/*
+ * 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_q931.c - Q931 received messages handling
+ * --------------------------------------------
+ *
+ * $Id: i4b_q931.c,v 1.18 1998/12/05 18:05:38 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+
+#if NI4BQ931 > 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/mbuf.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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#ifndef __FreeBSD__
+#define memcpy(d,s,l) bcopy(s,d,l)
+#endif
+
+unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT;
+
+call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */
+ctrl_desc_t ctrl_desc[MAX_CONTROLLERS]; /* controller description array */
+int utoc_tab[MAX_CONTROLLERS]; /* unit to controller conversion */
+
+/* protocol independent causes -> Q.931 causes */
+
+unsigned char cause_tab_q931[CAUSE_I4B_MAX] = {
+ CAUSE_Q850_NCCLR, /* CAUSE_I4B_NORMAL -> normal call clearing */
+ CAUSE_Q850_USRBSY, /* CAUSE_I4B_BUSY -> user busy */
+ CAUSE_Q850_NOCAVAIL, /* CAUSE_I4B_NOCHAN -> no circuit/channel available*/
+ CAUSE_Q850_INCDEST, /* CAUSE_I4B_INCOMP -> incompatible destination */
+ CAUSE_Q850_CALLREJ, /* CAUSE_I4B_REJECT -> call rejected */
+ CAUSE_Q850_DSTOOORDR, /* CAUSE_I4B_OOO -> destination out of order */
+ CAUSE_Q850_TMPFAIL, /* CAUSE_I4B_TMPFAIL -> temporary failure */
+};
+
+/*---------------------------------------------------------------------------*
+ * setup cr ref flag according to direction
+ *---------------------------------------------------------------------------*/
+unsigned char
+setup_cr(call_desc_t *cd, unsigned char cr)
+{
+ if(cd->crflag == CRF_ORIG)
+ return(cr & 0x7f); /* clear cr ref flag */
+ else if(cd->crflag == CRF_DEST)
+ return(cr | 0x80); /* set cr ref flag */
+ else
+ panic("setup_cr: invalid crflag!\n");
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process a Q.931 message
+ *---------------------------------------------------------------------------*/
+void
+i4b_decode_q931(int unit, int msg_len, u_char *msg_ptr)
+{
+ call_desc_t *cd;
+ int codeset = CODESET_0;
+ int old_codeset = CODESET_0;
+ int shift_flag = UNSHIFTED;
+ int crlen = 0;
+ int crval = 0;
+ int crflag = 0;
+ int i;
+ int offset;
+ int s;
+
+ /* check protocol discriminator */
+
+ if(*msg_ptr != PD_Q931)
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("protocol discriminator 0x%x != Q.931\n", *msg_ptr));
+ return;
+ }
+ msg_ptr++;
+ msg_len--;
+
+ s = SPLI4B(); /* this has to be protected ! */
+
+ /* extract call reference */
+
+ crlen = *msg_ptr & CRLENGTH_MASK;
+ msg_ptr++;
+ msg_len--;
+
+ if(crlen != 0)
+ {
+ crval += *msg_ptr & 0x7f;
+ crflag = (*msg_ptr >> 7) & 0x01;
+ msg_ptr++;
+ msg_len--;
+
+ for(i=1; i < crlen; i++)
+ {
+ crval += *msg_ptr;
+ msg_ptr++;
+ msg_len--;
+ }
+ }
+ else
+ {
+ crval = 0;
+ crflag = 0;
+ }
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931", ("Call Ref, len %d, val %d, flag %d\n", crlen, crval, crflag));
+
+ /* find or allocate calldescriptor */
+
+ if((cd = cd_by_unitcr(unit, crval,
+ crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL)
+ {
+ if(*msg_ptr == SETUP)
+ {
+ /* get and init new calldescriptor */
+
+ cd = reserve_cd(); /* cdid filled in */
+ cd->controller = utoc_tab[unit];
+ cd->cr = crval;
+ cd->crflag = CRF_DEST; /* we are the dest side */
+ cd->ilt = NULL; /* reset link tab ptrs */
+ cd->dlt = NULL;
+ }
+ else
+ {
+/*XXX*/ if(crval != 0) /* ignore global call references */
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("cannot find calldescriptor for cr = 0x%x, crflag = 0x%x, msg = 0x%x, frame = ", crval, crflag, *msg_ptr));
+ i4b_print_frame(msg_len, msg_ptr);
+ }
+ splx(s);
+ return;
+ }
+ }
+
+ splx(s);
+
+ /* decode and handle message type */
+
+ i4b_decode_q931_message(unit, cd, *msg_ptr);
+ msg_ptr++;
+ msg_len--;
+
+ /* process information elements */
+
+ while(msg_len > 0)
+ {
+ /* check for shift codeset IE */
+
+ if((*msg_ptr & 0x80) && ((*msg_ptr & 0xf0) == SOIE_SHIFT))
+ {
+ if(!(*msg_ptr & SHIFT_LOCK))
+ shift_flag = SHIFTED;
+
+ old_codeset = codeset;
+ codeset = *msg_ptr & CODESET_MASK;
+
+ if((shift_flag != SHIFTED) &&
+ (codeset <= old_codeset))
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("Q.931 lockingshift proc violation, shift %d -> %d\n", old_codeset, codeset));
+ codeset = old_codeset;
+ }
+ msg_len--;
+ msg_ptr++;
+ }
+
+ /* process one IE for selected codeset */
+
+ switch(codeset)
+ {
+ case CODESET_0:
+ offset = i4b_decode_q931_cs0_ie(unit, cd, msg_len, msg_ptr);
+ msg_len -= offset;
+ msg_ptr += offset;
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "i4b_decode_q931", ("unknown codeset %d, ", codeset));
+ i4b_print_frame(msg_len, msg_ptr);
+ msg_len = 0;
+ break;
+ }
+
+ /* check for non-locking shifts */
+
+ if(shift_flag == SHIFTED)
+ {
+ shift_flag = UNSHIFTED;
+ codeset = old_codeset;
+ }
+ }
+ next_l3state(cd, cd->event);
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process one Q.931 codeset 0 information element
+ *---------------------------------------------------------------------------*/
+int
+i4b_decode_q931_cs0_ie(int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr)
+{
+ int i, j;
+ char *p;
+
+ switch(*msg_ptr)
+ {
+ /* single byte IE's */
+
+ case IEI_SENDCOMPL:
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_SENDCOMPL\n"));
+ return(1);
+ break;
+
+ /* multi byte IE's */
+
+ case IEI_BEARERCAP: /* bearer capability */
+ switch(msg_ptr[2])
+ {
+ case 0x80: /* speech */
+ case 0x89: /* restricted digital info */
+ case 0x90: /* 3.1KHz audio */
+/* XXX */ cd->bprot = BPROT_NONE;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Telephony\n"));
+ break;
+
+ case 0x88: /* unrestricted digital info */
+/* XXX */ cd->bprot = BPROT_RHDLC;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Raw HDLC\n"));
+ break;
+
+ default:
+/* XXX */ cd->bprot = BPROT_NONE;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - No Protocol\n"));
+ break;
+ }
+ break;
+
+ case IEI_CAUSE: /* cause */
+ if(msg_ptr[2] & 0x80)
+ {
+ cd->cause_in = msg_ptr[3] & 0x7f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[3] & 0x7f));
+ }
+ else
+ {
+ cd->cause_in = msg_ptr[4] & 0x7f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[4] & 0x7f));
+ }
+ break;
+
+ case IEI_CHANNELID: /* channel id */
+ if((msg_ptr[2] & 0xf4) != 0x80)
+ {
+ cd->channelid = CHAN_NO;
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IEI_CHANNELID, unsupported value 0x%x\n", msg_ptr[2]));
+ }
+ else
+ {
+ switch(msg_ptr[2] & 0x03)
+ {
+ case IE_CHAN_ID_NO:
+ cd->channelid = CHAN_NO;
+ break;
+ case IE_CHAN_ID_B1:
+ cd->channelid = CHAN_B1;
+ break;
+ case IE_CHAN_ID_B2:
+ cd->channelid = CHAN_B2;
+ break;
+ case IE_CHAN_ID_ANY:
+ cd->channelid = CHAN_ANY;
+ break;
+ }
+ cd->channelexcl = (msg_ptr[2] & 0x08) >> 3;
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CHANNELID - channel %d, exclusive = %d\n", cd->channelid, cd->channelexcl));
+
+ /* if this is a setup message, reserve channel */
+
+ if(cd->event == EV_SETUP)
+ {
+ if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
+ {
+ if(ctrl_desc[cd->controller].bch_state[cd->channelid] == BCH_ST_FREE)
+ ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD;
+ else
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IE ChannelID, Channel NOT free!!\n"));
+ }
+ else if(cd->channelid == CHAN_NO)
+ {
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IE ChannelID, SETUP with channel = No channel (CW)\n"));
+ }
+ else /* cd->channelid == CHAN_ANY */
+ {
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("ERROR: IE ChannelID, SETUP with channel = Any channel!\n"));
+ }
+ }
+ }
+ break;
+
+ case IEI_CALLINGPN: /* calling party no */
+ if(msg_ptr[2] & 0x80) /* no presentation/screening indicator ? */
+ {
+ memcpy(cd->src_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
+ cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 1)] = '\0';
+ cd->scr_ind = SCR_NONE;
+ }
+ else
+ {
+ memcpy(cd->src_telno, &msg_ptr[4], min(TELNO_MAX, msg_ptr[1]-2));
+ cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 2)] = '\0';
+ cd->scr_ind = (msg_ptr[3] & 0x03) + SCR_USR_NOSC;
+ }
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLINGPN = %s\n", cd->src_telno));
+ break;
+
+ case IEI_CALLEDPN: /* called party number */
+ memcpy(cd->dst_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
+ cd->dst_telno[min(TELNO_MAX, msg_ptr [1] - 1)] = '\0';
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLED = %s\n", cd->dst_telno));
+ break;
+
+ case IEI_CALLSTATE: /* call state */
+ cd->call_state = msg_ptr[2] & 0x3f;
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLSTATE = %d\n", cd->call_state));
+ break;
+
+ case IEI_PROGRESSI: /* progress indicator */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_PROGRESSINDICATOR\n"));
+ break;
+
+ case IEI_DISPLAY: /* display */
+ /* CHANGED BY <chris@medis.de> */
+ memcpy(cd->display, &msg_ptr[2], min(DISPLAY_MAX, msg_ptr[1]));
+ cd->display[min(DISPLAY_MAX, msg_ptr[1])] = '\0';
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DISPLAY = %s\n", cd->display));
+ break;
+
+ case IEI_DATETIME: /* date/time */
+ i = 2;
+ j = msg_ptr[1];
+ p = &(cd->datetime[0]);
+ *p = '\0';
+
+ for(j = msg_ptr[1]; j > 0; j--, i++)
+ sprintf(p+strlen(p), "%02d", msg_ptr[i]);
+
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DATETIME = %s\n", cd->datetime));
+ break;
+
+ case IEI_FACILITY: /* facility */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_FACILITY\n"));
+ if(i4b_aoc(msg_ptr, cd) > -1)
+ i4b_l4_charging_ind(cd);
+ break;
+
+ case IEI_CONCTDNO: /* connected number */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CONCTDNO\n"));
+ break;
+
+ case IEI_NETSPCFAC: /* network specific fac */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_NETSPCFAC\n"));
+ break;
+
+ case IEI_LLCOMPAT: /* low layer compat */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_LLCOMPAT\n"));
+ break;
+
+ case IEI_HLCOMPAT: /* high layer compat */
+ DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_HLCOMPAT\n"));
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("Unknown IE %d - ", *msg_ptr));
+ i4b_print_frame(msg_ptr[1]+2, msg_ptr);
+ break;
+ }
+ return(msg_ptr[1] + 2);
+}
+
+/*---------------------------------------------------------------------------*
+ * decode and process one Q.931 codeset 0 information element
+ *---------------------------------------------------------------------------*/
+void
+i4b_decode_q931_message(int unit, call_desc_t *cd, u_char message_type)
+{
+ cd->event = EV_ILL;
+
+ switch(message_type)
+ {
+ /* call establishment */
+
+ case ALERT:
+ cd->event = EV_ALERT;
+ DBGL3(L3_PRIM, "rx ALERT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case CALL_PROCEEDING:
+ cd->event = EV_CALLPRC;
+ DBGL3(L3_PRIM, "rx CALL-PROC", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case PROGRESS:
+ cd->event = EV_PROGIND;
+ DBGL3(L3_PRIM, "rx PROGRESS", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SETUP:
+ DBGL3(L3_PRIM, "rx SETUP", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->bprot = BPROT_NONE;
+ cd->cause_in = 0;
+ cd->cause_out = 0;
+ cd->dst_telno[0] = '\0';
+ cd->src_telno[0] = '\0';
+ cd->channelid = CHAN_NO;
+ cd->channelexcl = 0;
+ cd->display[0] = '\0';
+ cd->datetime[0] = '\0';
+ cd->event = EV_SETUP;
+ break;
+
+ case CONNECT:
+ DBGL3(L3_PRIM, "rx CONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->datetime[0] = '\0';
+ cd->event = EV_CONNECT;
+ break;
+
+ case SETUP_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx SETUP-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_SETUPAK;
+ break;
+
+ case CONNECT_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_CONACK;
+ break;
+
+ /* call information */
+
+ case USER_INFORMATION:
+ DBGL3(L3_PRIM, "rx USER-INFO", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND_REJECT:
+ DBGL3(L3_PRIM, "rx SUSPEND-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME_REJECT:
+ DBGL3(L3_PRIM, "rx RESUME-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD:
+ DBGL3(L3_PRIM, "rx HOLD", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND:
+ DBGL3(L3_PRIM, "rx SUSPEND", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME:
+ DBGL3(L3_PRIM, "rx RESUME", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx HOLD-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case SUSPEND_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx SUSPEND-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RESUME_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RESUME-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case HOLD_REJECT:
+ DBGL3(L3_PRIM, "rx HOLD-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE:
+ DBGL3(L3_PRIM, "rx RETRIEVE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RETRIEVE-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RETRIEVE_REJECT:
+ DBGL3(L3_PRIM, "rx RETRIEVE-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ /* call clearing */
+
+ case DISCONNECT:
+ DBGL3(L3_PRIM, "rx DISCONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_DISCONN;
+ break;
+
+ case RESTART:
+ DBGL3(L3_PRIM, "rx RESTART", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RELEASE:
+ DBGL3(L3_PRIM, "rx RELEASE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_RELEASE;
+ break;
+
+ case RESTART_ACKNOWLEDGE:
+ DBGL3(L3_PRIM, "rx RESTART-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case RELEASE_COMPLETE:
+ DBGL3(L3_PRIM, "rx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_RELCOMP;
+ break;
+
+ /* misc messages */
+
+ case SEGMENT:
+ DBGL3(L3_PRIM, "rx SEGMENT", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case FACILITY:
+ DBGL3(L3_PRIM, "rx FACILITY", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_FACILITY;
+ break;
+
+ case REGISTER:
+ DBGL3(L3_PRIM, "rx REGISTER", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case NOTIFY:
+ DBGL3(L3_PRIM, "rx NOTIFY", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case STATUS_ENQUIRY:
+ DBGL3(L3_PRIM, "rx STATUS-ENQ", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_STATENQ;
+ break;
+
+ case CONGESTION_CONTROL:
+ DBGL3(L3_PRIM, "rx CONGESTION-CONTROL", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ break;
+
+ case INFORMATION:
+ DBGL3(L3_PRIM, "rx INFORMATION", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_INFO;
+ break;
+
+ case STATUS:
+ DBGL3(L3_PRIM, "rx STATUS", ("unit %d, cr = 0x%02x\n", unit, cd->cr));
+ cd->event = EV_STATUS;
+ break;
+
+ default:
+ DBGL3(L3_P_ERR, "rx UNKNOWN msg", ("unit %d, cr = 0x%02x, msg = 0x%02x\n", unit, cd->cr, message_type));
+ break;
+ }
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q931.h b/sys/i4b/layer3/i4b_q931.h
new file mode 100644
index 000000000000..cb916b045fd0
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q931.h
@@ -0,0 +1,116 @@
+/*
+ * 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_q931.h - Q931 handling header file
+ * --------------------------------------
+ *
+ * $Id: i4b_q931.h,v 1.5 1998/12/05 18:05:39 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:33:53 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_Q931_H_
+#define _I4B_Q931_H_
+
+/* extension bit */
+
+#define EXT_LAST 0x80 /* last octett */
+
+/* reserve space in mbuf */
+
+#define I_FRAME_HDRLEN 4 /* to be added by layer 2 */
+
+/* SHIFT */
+
+#define CODESET_MASK 0x07
+#define UNSHIFTED 0
+#define SHIFTED 1
+#define CRLENGTH_MASK 0x0f
+
+/* CONNECT */
+
+#define MSG_CONNECT_LEN 4 /* length of a connect message */
+
+/* DISCONNECT */
+
+#define MSG_DISCONNECT_LEN 8 /* length of a disconnect message */
+
+/* RELEASE COMPLETE */
+
+#define MSG_RELEASE_COMPLETE_LEN 8 /* length of release complete msg */
+
+/* for outgoing causes */
+
+#define CAUSE_LEN 2
+#define CAUSE_STD_LOC_OUT 0x80 /* std = CCITT, loc = user */
+
+/* SETUP */
+
+#define MSG_SETUP_LEN 18 /* without number strings ! */
+
+#define IEI_BEARERCAP_LEN 2 /* 2 octetts lenght */
+
+#define IT_CAP_SPEECH 0x80 /* BC: information xfer capability */
+#define IT_CAP_UNR_DIG_INFO 0x88 /* BC: information xfer capability */
+
+#define IT_RATE_64K 0x90 /* BC: information xfer rate */
+#define IT_UL1_G711A 0xa3 /* layer1 proto G.711 A-law */
+
+#define IEI_CHANNELID_LEN 0x01 /* length of channel id */
+#define CHANNELID_B1 0x81 /* channel = B1 (outgoing) */
+#define CHANNELID_B2 0x82 /* channel = B2 (outgoing) */
+#define CHANNELID_ANY 0x83 /* channel = any channel (outgoing) */
+
+#define IE_CHAN_ID_NO 0x00 /* no channel (incoming) */
+#define IE_CHAN_ID_B1 0x01 /* B1 channel (incoming) */
+#define IE_CHAN_ID_B2 0x02 /* B2 channel (incoming) */
+#define IE_CHAN_ID_ANY 0x03 /* ANY channel (incoming) */
+
+#define NUMBER_TYPEPLAN 0x81 /* type of number/numbering plan */
+
+#define IEI_CALLINGPN_LEN 1 /* without number string ! */
+
+#define IEI_CALLEDPN_LEN 1 /* without number string ! */
+
+/* CONNECT_ACK */
+
+#define MSG_CONNECT_ACK_LEN 4 /* length of a connect ack message */
+
+/* STATUS */
+
+#define MSG_STATUS_LEN 11
+#define CALLSTATE_LEN 1
+
+/* RELEASE */
+
+#define MSG_RELEASE_LEN 8 /* length of release msg */
+
+/* ALERT */
+
+#define MSG_ALERT_LEN 4 /* length of a alert message */
+
+#endif /* _I4B_Q931_H_ */
diff --git a/sys/i4b/layer3/i4b_q932fac.c b/sys/i4b/layer3/i4b_q932fac.c
new file mode 100644
index 000000000000..487ce004c144
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q932fac.c
@@ -0,0 +1,569 @@
+/*
+ * 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_q932fac.c - Q932 facility handling
+ * --------------------------------------
+ *
+ * $Id: i4b_q932fac.c,v 1.5 1998/12/05 18:05:41 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:34:11 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "i4bq931.h"
+#else
+#define NI4BQ931 1
+#endif
+#if NI4BQ931 > 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/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_isdnq931.h>
+#include <i4b/include/i4b_l2l3.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer3/i4b_l3.h>
+#include <i4b/layer3/i4b_l3fsm.h>
+#include <i4b/layer3/i4b_q931.h>
+#include <i4b/layer3/i4b_q932fac.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+static int do_component(int length);
+static void next_state(int class, int form, int code, int val);
+
+static int byte_len;
+static unsigned char *byte_buf;
+static int state;
+
+static int units;
+static int operation_value;
+
+/*---------------------------------------------------------------------------*
+ * decode Q.931/Q.932 facility info element
+ *---------------------------------------------------------------------------*/
+int
+i4b_aoc(unsigned char *buf, call_desc_t *cd)
+{
+ int len;
+
+ cd->units_type = CHARGE_INVALID;
+ cd->units = -1;
+
+ buf++; /* length */
+
+ len = *buf;
+
+ buf++; /* protocol profile */
+
+ switch(*buf & 0x1f)
+ {
+ case FAC_PROTO_ROP:
+ break;
+
+ case FAC_PROTO_CMIP:
+ DBGL3(L3_A_MSG, "i4b_facility", ("CMIP Protocol (Q.941), UNSUPPORTED\n"));
+ return(-1);
+ break;
+
+ case FAC_PROTO_ACSE:
+ DBGL3(L3_A_MSG, "i4b_facility", ("ACSE Protocol (X.217/X.227), UNSUPPORTED!\n"));
+ return(-1);
+ break;
+
+ default:
+ DBGL3(L3_A_ERR, "i4b_facility", ("Unknown Protocol, UNSUPPORTED!\n"));
+ return(-1);
+ break;
+ }
+
+ DBGL3(L3_A_MSG, "i4b_facility", ("Remote Operations Protocol\n"));
+
+ /* next byte */
+
+ buf++;
+ len--;
+
+ /* initialize variables for do_component */
+
+ byte_len = 0;
+ byte_buf = buf;
+ state = ST_EXP_COMP_TYP;
+
+ /* decode facility */
+
+ do_component(len);
+
+ switch(operation_value)
+ {
+ case FAC_OPVAL_AOC_D_CUR:
+ cd->units_type = CHARGE_AOCD;
+ cd->units = 0;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_D_UNIT:
+ cd->units_type = CHARGE_AOCD;
+ cd->units = units;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_E_CUR:
+ cd->units_type = CHARGE_AOCE;
+ cd->units = 0;
+ return(0);
+ break;
+
+ case FAC_OPVAL_AOC_E_UNIT:
+ cd->units_type = CHARGE_AOCE;
+ cd->units = units;
+ return(0);
+ break;
+
+ default:
+ cd->units_type = CHARGE_INVALID;
+ cd->units = -1;
+ return(-1);
+ break;
+ }
+ return(-1);
+}
+
+/*---------------------------------------------------------------------------*
+ * handle a component recursively
+ *---------------------------------------------------------------------------*/
+static int
+do_component(int length)
+{
+ int comp_tag_class; /* component tag class */
+ int comp_tag_form; /* component form: constructor or primitive */
+ int comp_tag_code; /* component code depending on class */
+ int comp_length = 0; /* component length */
+
+again:
+
+ /*----------------------------------------*/
+ /* first component element: component tag */
+ /*----------------------------------------*/
+
+ /* tag class bits */
+
+ comp_tag_class = (*byte_buf & 0xc0) >> 6;
+
+ switch(comp_tag_class)
+ {
+ case FAC_TAGCLASS_UNI:
+ break;
+ case FAC_TAGCLASS_APW:
+ break;
+ case FAC_TAGCLASS_COS:
+ break;
+ case FAC_TAGCLASS_PRU:
+ break;
+ }
+
+ /* tag form bit */
+
+ comp_tag_form = (*byte_buf & 0x20) > 5;
+
+ /* tag code bits */
+
+ comp_tag_code = *byte_buf & 0x1f;
+
+ if(comp_tag_code == 0x1f)
+ {
+ comp_tag_code = 0;
+
+ byte_buf++;
+ byte_len++;
+
+ while(*byte_buf & 0x80)
+ {
+ comp_tag_code += (*byte_buf & 0x7f);
+ byte_buf++;
+ byte_len++;
+ }
+ comp_tag_code += (*byte_buf & 0x7f);
+ }
+ else
+ {
+ comp_tag_code = (*byte_buf & 0x1f);
+ }
+
+ byte_buf++;
+ byte_len++;
+
+ /*--------------------------------------------*/
+ /* second component element: component length */
+ /*--------------------------------------------*/
+
+ comp_length = 0;
+
+ if(*byte_buf & 0x80)
+ {
+ int i = *byte_buf & 0x7f;
+
+ byte_len += i;
+
+ for(;i > 0;i++)
+ {
+ byte_buf++;
+ comp_length += (*byte_buf * (i*256));
+ }
+ }
+ else
+ {
+ comp_length = *byte_buf & 0x7f;
+ }
+
+ next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1);
+
+ byte_len++;
+ byte_buf++;
+
+ /*---------------------------------------------*/
+ /* third component element: component contents */
+ /*---------------------------------------------*/
+
+ if(comp_tag_form) /* == constructor */
+ {
+ do_component(comp_length);
+ }
+ else
+ {
+ int val = 0;
+ if(comp_tag_class == FAC_TAGCLASS_UNI)
+ {
+ switch(comp_tag_code)
+ {
+ case FAC_CODEUNI_INT:
+ case FAC_CODEUNI_ENUM:
+ case FAC_CODEUNI_BOOL:
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ val += (*byte_buf + (i*255));
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ break;
+ default:
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ break;
+ }
+ }
+
+ else /* comp_tag_class != FAC_TAGCLASS_UNI */
+ {
+ if(comp_length)
+ {
+ int i;
+
+ for(i = comp_length-1; i >= 0; i--)
+ {
+ val += (*byte_buf + (i*255));
+ byte_buf++;
+ byte_len++;
+ }
+ }
+ }
+ next_state(comp_tag_class, comp_tag_form, comp_tag_code, val);
+ }
+
+ if(byte_len < length)
+ goto again;
+
+ return(byte_len);
+}
+
+/*---------------------------------------------------------------------------*
+ * invoke component
+ *---------------------------------------------------------------------------*/
+static void
+F_1_1(int val)
+{
+ if(val == -1)
+ {
+ state = ST_EXP_INV_ID;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * return result
+ *---------------------------------------------------------------------------*/
+static void
+F_1_2(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+/*---------------------------------------------------------------------------*
+ * return error
+ *---------------------------------------------------------------------------*/
+static void
+F_1_3(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+/*---------------------------------------------------------------------------*
+ * reject
+ *---------------------------------------------------------------------------*/
+static void
+F_1_4(int val)
+{
+ if(val == -1)
+ state = ST_EXP_NIX;
+}
+
+/*---------------------------------------------------------------------------*
+ * invoke id
+ *---------------------------------------------------------------------------*/
+static void
+F_2(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Invoke ID = %d\n", val));
+ state = ST_EXP_OP_VAL;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * operation value
+ *---------------------------------------------------------------------------*/
+static void
+F_3(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Operation Value = %d\n", val));
+
+ operation_value = val;
+
+ if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT))
+ {
+ units = 0;
+ state = ST_EXP_INFO;
+ }
+ else
+ {
+ state = ST_EXP_NIX;
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * specific charging units
+ *---------------------------------------------------------------------------*/
+static void
+F_4(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RUL;
+}
+
+/*---------------------------------------------------------------------------*
+ * free of charge
+ *---------------------------------------------------------------------------*/
+static void
+F_4_1(int val)
+{
+ if(val == -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Free of Charge\n"));
+ /* units = 0; XXXX */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * charge not available
+ *---------------------------------------------------------------------------*/
+static void
+F_4_2(int val)
+{
+ if(val == -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Charge not available\n"));
+ /* units = -1; XXXXXX ??? */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * recorded units list
+ *---------------------------------------------------------------------------*/
+static void
+F_5(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RU;
+}
+
+/*---------------------------------------------------------------------------*
+ * recorded units
+ *---------------------------------------------------------------------------*/
+static void
+F_6(int val)
+{
+ if(val == -1)
+ state = ST_EXP_RNOU;
+}
+
+/*---------------------------------------------------------------------------*
+ * number of units
+ *---------------------------------------------------------------------------*/
+static void
+F_7(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Number of Units = %d\n", val));
+ units = val;
+ state = ST_EXP_TOCI;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * subtotal/total
+ *---------------------------------------------------------------------------*/
+static void
+F_8(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Subtotal/Total = %d\n", val));
+ /* type_of_charge = val; */
+ state = ST_EXP_DBID;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * billing_id
+ *---------------------------------------------------------------------------*/
+static void
+F_9(int val)
+{
+ if(val != -1)
+ {
+ DBGL3(L3_A_MSG, "i4b_facility", ("Billing ID = %d\n", val));
+ /* billing_id = val; */
+ state = ST_EXP_NIX;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static struct statetab {
+ int currstate; /* input: current state we are in */
+ int form; /* input: current tag form */
+ int class; /* input: current tag class */
+ int code; /* input: current tag code */
+ void (*func)(int); /* output: func to exec */
+} statetab[] = {
+
+/* current state tag form tag class tag code function */
+/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 },
+ {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 },
+ {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 },
+ {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 },
+ {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 },
+ {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 },
+ {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 },
+ {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 },
+ {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 },
+ {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 },
+ {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 },
+ {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 },
+ {-1, -1, -1, -1, NULL }
+};
+
+/*---------------------------------------------------------------------------*
+ * state decode for do_component
+ *---------------------------------------------------------------------------*/
+static void
+next_state(int class, int form, int code, int val)
+{
+ int i;
+
+ for(i=0; ; i++)
+ {
+ if((statetab[i].currstate > state) ||
+ (statetab[i].currstate == -1))
+ {
+ break;
+ }
+
+ if((statetab[i].currstate == state) &&
+ (statetab[i].form == form) &&
+ (statetab[i].class == class) &&
+ (statetab[i].code == code))
+ {
+ (*statetab[i].func)(val);
+ break;
+ }
+ }
+}
+
+#endif /* NI4BQ931 > 0 */
diff --git a/sys/i4b/layer3/i4b_q932fac.h b/sys/i4b/layer3/i4b_q932fac.h
new file mode 100644
index 000000000000..d7544a86e020
--- /dev/null
+++ b/sys/i4b/layer3/i4b_q932fac.h
@@ -0,0 +1,167 @@
+/*
+ * 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_q932fac.h - Q932 facility handling header file
+ * --------------------------------------------------
+ *
+ * $Id: i4b_q932fac.h,v 1.5 1998/12/18 17:17:57 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 18:17:23 1998]
+ *
+ *---------------------------------------------------------------------------
+ *
+ * - Q.932 (03/93) Generic Procedures for the Control of
+ * ISDN Supplementaty Services
+ * - Q.950 (03/93) Supplementary Services Protocols, Structure and
+ * General Principles
+ * - ETS 300 179 (10/92) Advice Of Charge: charging information during
+ * the call (AOC-D) supplementary service Service description
+ * - ETS 300 180 (10/92) Advice Of Charge: charging information at the
+ * end of call (AOC-E) supplementary service Service description
+ * - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service
+ * Functional capabilities and information flows
+ * - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service
+ * Digital Subscriber Signalling System No. one (DSS1) protocol
+ * - X.208 Specification of Abstract Syntax Notation One (ASN.1)
+ * - X.209 Specification of Basic Encoding Rules for
+ * Abstract Syntax Notation One (ASN.1)
+ * - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag
+ * 1992, 3rd Edition (ISBN 3-89238-062-7) (german !)
+ *
+ *---------------------------------------------------------------------------*/
+
+/* protocols */
+#define FAC_PROTO_ROP 0x11
+#define FAC_PROTO_CMIP 0x12
+#define FAC_PROTO_ACSE 0x13
+
+/* tag classes */
+#define FAC_TAGCLASS_UNI 0x00
+#define FAC_TAGCLASS_APW 0x01
+#define FAC_TAGCLASS_COS 0x02
+#define FAC_TAGCLASS_PRU 0x03
+
+/* tag forms */
+#define FAC_TAGFORM_PRI 0x00
+#define FAC_TAGFORM_CON 0x01
+
+/* class UNIVERSAL values */
+#define FAC_CODEUNI_BOOL 1
+#define FAC_CODEUNI_INT 2
+#define FAC_CODEUNI_BITS 3
+#define FAC_CODEUNI_OCTS 4
+#define FAC_CODEUNI_NULL 5
+#define FAC_CODEUNI_OBJI 6
+#define FAC_CODEUNI_OBJD 7
+#define FAC_CODEUNI_EXT 8
+#define FAC_CODEUNI_REAL 9
+#define FAC_CODEUNI_ENUM 10
+#define FAC_CODEUNI_R11 11
+#define FAC_CODEUNI_R12 12
+#define FAC_CODEUNI_R13 13
+#define FAC_CODEUNI_R14 14
+#define FAC_CODEUNI_R15 15
+#define FAC_CODEUNI_SEQ 16
+#define FAC_CODEUNI_SET 17
+#define FAC_CODEUNI_NSTR 18
+#define FAC_CODEUNI_PSTR 19
+#define FAC_CODEUNI_TSTR 20
+#define FAC_CODEUNI_VSTR 21
+#define FAC_CODEUNI_ISTR 22
+#define FAC_CODEUNI_UTIME 23
+#define FAC_CODEUNI_GTIME 24
+#define FAC_CODEUNI_GSTR 25
+#define FAC_CODEUNI_VISTR 26
+#define FAC_CODEUNI_GNSTR 27
+
+/* operation values */
+#define FAC_OPVAL_UUS 1
+#define FAC_OPVAL_CUG 2
+#define FAC_OPVAL_MCID 3
+#define FAC_OPVAL_BTPY 4
+#define FAC_OPVAL_ETPY 5
+#define FAC_OPVAL_ECT 6
+
+#define FAC_OPVAL_DIV_ACT 7
+#define FAC_OPVAL_DIV_DEACT 8
+#define FAC_OPVAL_DIV_ACTSN 9
+#define FAC_OPVAL_DIV_DEACTSN 10
+#define FAC_OPVAL_DIV_INTER 11
+#define FAC_OPVAL_DIV_INFO 12
+#define FAC_OPVAL_DIV_CALLDEF 13
+#define FAC_OPVAL_DIV_CALLRER 14
+#define FAC_OPVAL_DIV_LINF2 15
+#define FAC_OPVAL_DIV_INVS 16
+#define FAC_OPVAL_DIV_INTER1 17
+#define FAC_OPVAL_DIV_LINF1 18
+#define FAC_OPVAL_DIV_LINF3 19
+
+#define FAC_OPVAL_ER_CRCO 20
+#define FAC_OPVAL_ER_MGMT 21
+#define FAC_OPVAL_ER_CANC 22
+
+#define FAC_OPVAL_MLPP_QUERY 24
+#define FAC_OPVAL_MLPP_CALLR 25
+#define FAC_OPVAL_MLPP_CALLP 26
+
+#define FAC_OPVAL_AOC_REQ 30
+#define FAC_OPVAL_AOC_S_CUR 31
+#define FAC_OPVAL_AOC_S_SPC 32
+#define FAC_OPVAL_AOC_D_CUR 33
+#define FAC_OPVAL_AOC_D_UNIT 34
+#define FAC_OPVAL_AOC_E_CUR 35
+#define FAC_OPVAL_AOC_E_UNIT 36
+#define FAC_OPVAL_AOC_IDOFCRG 37
+
+#define FAC_OPVAL_CONF_BEG 40
+#define FAC_OPVAL_CONF_ADD 41
+#define FAC_OPVAL_CONF_SPLIT 42
+#define FAC_OPVAL_CONF_DROP 43
+#define FAC_OPVAL_CONF_ISOLATE 44
+#define FAC_OPVAL_CONF_REATT 45
+#define FAC_OPVAL_CONF_PDISC 46
+#define FAC_OPVAL_CONF_FCONF 47
+#define FAC_OPVAL_CONF_END 48
+#define FAC_OPVAL_CONF_IDCFE 49
+
+#define FAC_OPVAL_REVC_REQ 60
+
+enum states {
+ ST_EXP_COMP_TYP,
+ ST_EXP_INV_ID,
+ ST_EXP_OP_VAL,
+ ST_EXP_INFO,
+ ST_EXP_RUL,
+ ST_EXP_RU,
+ ST_EXP_RNOU,
+ ST_EXP_TOCI,
+ ST_EXP_DBID,
+
+ ST_EXP_NIX
+};
+
+/* EOF */
+
diff --git a/sys/i4b/layer4/i4b_i4bdrv.c b/sys/i4b/layer4/i4b_i4bdrv.c
new file mode 100644
index 000000000000..0c21e8ef7c5a
--- /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 000000000000..cecd5f4e2d66
--- /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 000000000000..e4ed863f383a
--- /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 000000000000..e8e1a967a696
--- /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 000000000000..7a38e13904dd
--- /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 */
diff --git a/sys/i4b/tina-dd/README b/sys/i4b/tina-dd/README
new file mode 100644
index 000000000000..6a2386f90bf4
--- /dev/null
+++ b/sys/i4b/tina-dd/README
@@ -0,0 +1,20 @@
+
+THIS DRIVER IS NOT YET WORKING !
+================================
+
+This adds support for the active ISDN card tina-dd manufactured by
+Stollmann E+V GmbH in Hamburg, Germany. This card was also sold by
+MIRO as the Miro P1.
+
+Christian Luehrs and Manfred Jung of Stollmann were very helpful
+giving out docs and sources to support the development of a driver
+for this card.
+
+The card supports many protocols. In order to make the card operable
+you'll need the downloadable firmware which also can be found on the
+www/ftp server, www.stollmann.de / ftp.stollmann.de.
+
+While developing this driver, i used fcdddss1.loc as of April 1994.
+
+The code is based in part on sources and header files written by
+Stollmann for their driver development kit for the tina-dd.
diff --git a/sys/i4b/tina-dd/i4b_tina_dd.c b/sys/i4b/tina-dd/i4b_tina_dd.c
new file mode 100644
index 000000000000..7a5e010b8048
--- /dev/null
+++ b/sys/i4b/tina-dd/i4b_tina_dd.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 1994, 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_tina_dd.c - i4b Stollman Tina-dd control device driver
+ * ----------------------------------------------------------
+ *
+ * $Id: i4b_tina_dd.c,v 1.3 1998/12/05 18:06:19 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:41:38 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "tina.h"
+
+#if NTINA > 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 <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/tina-dd/i4b_tina_ioctl.h>
+
+static int openflag = 0;
+
+int tinaprobe(struct isa_device *dev);
+int tinaattach(struct isa_device *dev);
+
+struct isa_driver tinadriver = {
+ tinaprobe,
+ tinaattach,
+ "tina",
+ 0
+};
+
+static struct tina_softc {
+ int sc_unit;
+ int sc_iobase;
+} tina_sc[NTINA];
+
+static d_open_t tinaopen;
+static d_close_t tinaclose;
+static d_ioctl_t tinaioctl;
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+static d_poll_t tinapoll;
+#endif
+
+#define CDEV_MAJOR 54
+static struct cdevsw tina_cdevsw =
+ { tinaopen, tinaclose, noread, nowrite,
+ tinaioctl, nostop, nullreset, nodevtotty,
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+ tinapoll, nommap, NULL, "tina", NULL, -1 };
+#else
+ noselect, nommap, NULL, "tina", NULL, -1 };
+#endif
+
+static void setupaddr(unsigned short iobase, unsigned int addr);
+static void readblock(unsigned short iobase, unsigned int addr,
+ unsigned char *dst, unsigned int len);
+static void writeblock(unsigned short iobase, unsigned char *src,
+ unsigned long addr, int len);
+
+/*---------------------------------------------------------------------------*
+ * tina - device driver probe routine
+ *---------------------------------------------------------------------------*/
+int
+tinaprobe(struct isa_device *dev)
+{
+ struct tina_softc *sc = &tina_sc[dev->id_unit];
+ u_char byte;
+
+#define SETLOW 0x55
+#define SETMID 0xaa
+#define SETHIGH 0x06
+
+ outb((dev->id_iobase + ADDR_CNTL), SETLOW);
+
+ if((byte = inb(dev->id_iobase + ADDR_CNTL)) != SETLOW)
+ {
+ printf("tina%d: probe low failed, 0x%x != 0x%x\n",
+ dev->id_unit, byte, SETLOW);
+ return(0);
+ }
+
+ outb((dev->id_iobase + ADDR_CNTM), SETMID);
+ if((byte = inb(dev->id_iobase + ADDR_CNTM)) != SETMID)
+ {
+ printf("tina%d: probe mid failed, 0x%x != 0x%x\n",
+ dev->id_unit, byte, SETMID);
+ return(0);
+ }
+
+ outb((dev->id_iobase + ADDR_CNTH), SETHIGH);
+ if(((byte = inb(dev->id_iobase + ADDR_CNTH)) & 0x0f) != SETHIGH)
+ {
+ printf("tina%d: probe high failed, 0x%x != 0x%x\n",
+ dev->id_unit, byte, SETHIGH);
+ return(0);
+ }
+
+ printf("tina%d: status register = 0x%x\n",
+ dev->id_unit, inb(dev->id_iobase + CTRL_STAT));
+
+ return(1); /* board found */
+}
+#undef SETLOW
+#undef SETMID
+#undef SETHIGH
+
+/*---------------------------------------------------------------------------*
+ * tina - device driver attach routine
+ *---------------------------------------------------------------------------*/
+int
+tinaattach(struct isa_device *dev)
+{
+ struct tina_softc *sc = &tina_sc[dev->id_unit];
+
+ sc->sc_unit = dev->id_unit;
+ sc->sc_iobase = dev->id_iobase;
+
+ printf("tina%d: attaching Tina-dd\n", dev->id_unit);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ * tina - device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+void
+tinaintr(int unit)
+{
+ struct tina_softc *sc = &tina_sc[unit];
+}
+
+#if BSD > 199306 && defined(__FreeBSD__)
+/*---------------------------------------------------------------------------*
+ * initialization at kernel load time
+ *---------------------------------------------------------------------------*/
+static void
+tinainit(void *unused)
+{
+ dev_t dev;
+
+ dev = makedev(CDEV_MAJOR, 0);
+
+ cdevsw_add(&dev, &tina_cdevsw, NULL);
+}
+
+SYSINIT(tinadev, SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, &tinainit, NULL);
+
+#endif /* BSD > 199306 && defined(__FreeBSD__) */
+
+/*---------------------------------------------------------------------------*
+ * tinaopen - device driver open routine
+ *---------------------------------------------------------------------------*/
+static int
+tinaopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ if(minor(dev))
+ return (ENXIO);
+
+ if(openflag)
+ return (EBUSY);
+
+ openflag = 1;
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * tinaclose - device driver close routine
+ *---------------------------------------------------------------------------*/
+static int
+tinaclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ openflag = 0;
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * tinaioctl - device driver ioctl routine
+ *---------------------------------------------------------------------------*/
+static int
+tinaioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct tina_softc *sc = &tina_sc[minor(dev)];
+ u_short iobase = sc->sc_iobase;
+ int error = 0;
+ char *ptr;
+ int s;
+
+ if(minor(dev))
+ return(ENODEV);
+
+ s = splimp();
+
+ switch(cmd)
+ {
+ /* hardware layer - control & status register */
+
+ case ISDN_GETCSR: /* return control register */
+ *(unsigned char *)data = inb(iobase + CTRL_STAT);
+ break;
+
+ case ISDN_SETCSR: /* set status register */
+ outb((iobase + CTRL_STAT), *(unsigned char *)data);
+ break;
+
+ /* hardware layer - dual ported memory */
+
+ case ISDN_GETBLK: /* get block from dual port mem */
+ readblock(iobase, (*(struct record *)data).addr,
+ (*(struct record *)data).data,
+ (*(struct record *)data).length);
+ break;
+
+ case ISDN_SETBLK: /* write block to dual port mem */
+ writeblock(iobase, (*(struct record *)data).data,
+ (*(struct record *)data).addr,
+ (*(struct record *)data).length);
+ break;
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return(error);
+}
+
+/*---------------------------------------------------------------------------*
+ * tinapoll - device driver poll routine
+ *---------------------------------------------------------------------------*/
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+static int
+tinapoll (dev_t dev, int events, struct proc *p)
+{
+ return (ENODEV);
+}
+#endif
+
+/*===========================================================================*
+ * tina dual ported memory access
+ *===========================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * setup address for accessing tina-dd ram
+ *---------------------------------------------------------------------------*/
+static void
+setupaddr(unsigned short iobase, unsigned int addr)
+{
+ outb((iobase + ADDR_CNTL), (unsigned char) addr & 0xff);
+ outb((iobase + ADDR_CNTM), (unsigned char) ((addr >> 8) & 0xff));
+ outb((iobase + ADDR_CNTH), (unsigned char) ((addr >> 16) & 0xff));
+}
+
+
+/*---------------------------------------------------------------------------*
+ * read block from tina-dd dual ported ram
+ *---------------------------------------------------------------------------*/
+static void
+readblock(unsigned short iobase, unsigned int addr,
+ unsigned char *dst, unsigned int len)
+{
+ setupaddr(iobase, addr); /* setup start address */
+
+ while(len--) /* tina-dd mem -> pc mem */
+ *dst++ = inb(iobase + DATA_LOW_INC);
+}
+
+/*---------------------------------------------------------------------------*
+ * write block to tina-dd dual ported ram
+ *---------------------------------------------------------------------------*/
+static void
+writeblock(unsigned short iobase, unsigned char *src,
+ unsigned long addr, int len)
+{
+ setupaddr(iobase, addr); /* setup start address */
+
+ while(len--) /* pc mem -> tina-dd mem */
+ outb((iobase + DATA_LOW_INC), *src++);
+}
+
+#endif /* NTINA > 0 */
diff --git a/sys/i4b/tina-dd/i4b_tina_ioctl.h b/sys/i4b/tina-dd/i4b_tina_ioctl.h
new file mode 100644
index 000000000000..d51f16d731a4
--- /dev/null
+++ b/sys/i4b/tina-dd/i4b_tina_ioctl.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1994, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Based on code written by Stollmann GmbH, Hamburg. Many thanks to
+ * Christian Luehrs and Manfred Jung for docs, sources and answers!
+ *
+ * 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_tina_ioctl.h - i4b Stollman Tina-dd ioctl header file
+ * ---------------------------------------------------------
+ *
+ * $Id: i4b_tina_ioctl.h,v 1.2 1998/12/05 18:06:20 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:41:51 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_TINA_IOCTL_H_
+#define _I4B_TINA_IOCTL_H_
+
+#define TINA_IOSIZE 8 /* 8 byte wide iospace occupied */
+
+/*---------------------------------------------------------------------------*
+ * register offsets in i/o address space
+ *---------------------------------------------------------------------------*/
+
+#define CTRL_STAT 0 /* control & status */
+
+#define ADDR_CNTL 1 /* address pointer low */
+#define ADDR_CNTM 2 /* address pointer mid */
+#define ADDR_CNTH 3 /* address pointer high */
+
+#define DATA_LOW 4 /* data register low */
+#define DATA_HIGH 5 /* data register high */
+
+#define DATA_LOW_INC 6 /* data register low, post inc */
+#define DATA_HIGH_INC 7 /* data register high, post inc */
+
+/*---------------------------------------------------------------------------*
+ * status register (CTRL_STAT read access)
+ *---------------------------------------------------------------------------*/
+
+#define CR_INTC 0x80 /* irq FROM tina-dd TO pc active */
+#define CR_INTP 0x40 /* irq FROM pc TO tina-dd active */
+#define CR_INTPA 0x20 /* irq FROM pc TO tina-dd active */
+#define CR_NMI 0x10 /* nmi FROM PC TO tina-dd active */
+#define CR_FLASHLD 0x08 /* read of the FLASHLD-bit (n/c) */
+#define CR_S2C 0x04 /* info bit */
+#define CR_S1C 0x02 /* info bit */
+#define CR_S0C 0x01 /* info bit */
+
+/*---------------------------------------------------------------------------*
+ * control register (CTRL_STAT write access)
+ *---------------------------------------------------------------------------*/
+
+#define CR_CLR_INTC 0x80 /* clear irq on tina-dd */
+#define CR_SET_INTP 0x40 /* trigger irq on tina-dd */
+#define CR_RESET 0x20 /* reset tina-dd */
+#define CR_SET_NMI 0x10 /* trigger nmi on tina-dd */
+#define CR_SET_FLASHLD 0x08 /* activates pin FLASHLD (n/c) */
+#define CR_S2P 0x04 /* info bit (not readable !) */
+#define CR_S1P 0x02 /* info bit (not readable !) */
+#define CR_S0P 0x01 /* info bit (not readable !) */
+
+/*---------------------------------------------------------------------------*
+ * misc definitions in dual-ported mem on board of tina-dd
+ *---------------------------------------------------------------------------*/
+
+#define FW_SYSCB 0x200 /* address of FW SYSCB / MJ 300392 */
+#define FW_SINFO_NAME 0x220 /* address of general info label */
+
+#define FW_HW_TYPE 0x224 /* address of hardware type byte: */
+#define FW_HW_UNDEF 0x00 /* undefined .. */
+#define FW_HW_TINA_DD 0x10 /* TINA-dd */
+#define FW_HW_TINA_DS 0x20 /* TINA-ds (B channel/ser ?) */
+#define FW_HW_TINA_D 0x30 /* TINA-d (one B channel ?) */
+#define FW_HW_TINA_DDM 0x40 /* TINA-dd with fax module */
+#define FW_HW_TINA_DDS 0x50 /* TINA-dd with fax/voice module */
+#define FW_HW_SICCE 0x80 /* X.25 board */
+#define FW_HW_ASIC 0x01 /* ASIC version bit */
+
+#define FW_STAT 0x228 /* address of firmware status byte */
+#define FW_READY 0x20 /* firmware ready bit */
+#define FW_BOOTPRM_RDY 0x02 /* boot PROM ready */
+#define FW_UNDEF_0 0x00 /* undefined */
+#define FW_UNDEF_1 0xFF /* undefined */
+
+#define FW_SINFO_ID "SYSI" /* general info label for FW > 2.13*/
+#define FW_SINFO_ID_LEN 4
+
+#define FW_ADDR_PROFPTR 0x260 /* addr of ptr to board profile */
+
+/*===========================================================================*
+ * Layer 0 - Hardware layer
+ *===========================================================================*/
+
+/* control and status register access */
+
+#define ISDN_GETCSR _IOR('I', 1, unsigned char) /* get csr */
+#define ISDN_SETCSR _IOW('I', 2, unsigned char) /* set csr */
+
+/* dual ported ram access */
+
+#define ISDN_GETBLK _IOWR('I', 3, struct record) /* get dpr record */
+#define ISDN_SETBLK _IOW('I', 4, struct record) /* set dpr record */
+
+/*---------------------------------------------------------------------------*
+ * record structure for dual ported ram block rd/wr
+ *---------------------------------------------------------------------------*/
+struct record {
+ unsigned int length; /* length of data block */
+ unsigned int addr; /* address of mem on tina-dd board */
+ unsigned char *data; /* pointer to the datablock itself */
+};
+
+#endif /* _I4B_TINA_IOCTL_H_ */