summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer1/isic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i4b/layer1/isic')
-rw-r--r--sys/i4b/layer1/isic/i4b_asuscom_ipac.c248
-rw-r--r--sys/i4b/layer1/isic/i4b_avm_a1.c420
-rw-r--r--sys/i4b/layer1/isic/i4b_bchan.c405
-rw-r--r--sys/i4b/layer1/isic/i4b_ctx_s0P.c261
-rw-r--r--sys/i4b/layer1/isic/i4b_drn_ngo.c271
-rw-r--r--sys/i4b/layer1/isic/i4b_dynalink.c239
-rw-r--r--sys/i4b/layer1/isic/i4b_elsa_pcc16.c408
-rw-r--r--sys/i4b/layer1/isic/i4b_elsa_qs1i.c249
-rw-r--r--sys/i4b/layer1/isic/i4b_elsa_qs1p.c365
-rw-r--r--sys/i4b/layer1/isic/i4b_hscx.c667
-rw-r--r--sys/i4b/layer1/isic/i4b_hscx.h299
-rw-r--r--sys/i4b/layer1/isic/i4b_ipac.h206
-rw-r--r--sys/i4b/layer1/isic/i4b_isac.c666
-rw-r--r--sys/i4b/layer1/isic/i4b_isac.h390
-rw-r--r--sys/i4b/layer1/isic/i4b_isic.c506
-rw-r--r--sys/i4b/layer1/isic/i4b_isic.h363
-rw-r--r--sys/i4b/layer1/isic/i4b_isic_ext.h50
-rw-r--r--sys/i4b/layer1/isic/i4b_isic_isa.c224
-rw-r--r--sys/i4b/layer1/isic/i4b_isic_pnp.c317
-rw-r--r--sys/i4b/layer1/isic/i4b_itk_ix1.c409
-rw-r--r--sys/i4b/layer1/isic/i4b_l1.c261
-rw-r--r--sys/i4b/layer1/isic/i4b_l1fsm.c520
-rw-r--r--sys/i4b/layer1/isic/i4b_siemens_isurf.c244
-rw-r--r--sys/i4b/layer1/isic/i4b_sws.c224
-rw-r--r--sys/i4b/layer1/isic/i4b_tel_s016.c384
-rw-r--r--sys/i4b/layer1/isic/i4b_tel_s0163.c387
-rw-r--r--sys/i4b/layer1/isic/i4b_tel_s08.c317
-rw-r--r--sys/i4b/layer1/isic/i4b_usr_sti.c678
28 files changed, 9978 insertions, 0 deletions
diff --git a/sys/i4b/layer1/isic/i4b_asuscom_ipac.c b/sys/i4b/layer1/isic/i4b_asuscom_ipac.c
new file mode 100644
index 0000000..5d696c1
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_asuscom_ipac.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 1999 Ari Suutari. All rights reserved.
+ *
+ * Copyright (c) 1997, 2000 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 Asuscom ISDNlink 128K PnP
+ * =====================================================================
+ *
+ * This driver works with Asuscom ISDNlink 128K PnP ISA adapter,
+ * which is based on Siemens IPAC chip (my card probes as ASU1690).
+ * Older Asuscom ISA cards are based on different chipset
+ * (containing two chips) - for those cards, one might want
+ * to try the Dynalink driver.
+ *
+ * This driver is heavily based on ELSA Quickstep 1000pro PCI
+ * driver written by Hellmuth Michaelis. Card initialization
+ * code is modeled after Linux i4l driver written by Karsten
+ * Keil.
+ *
+ * $Id: i4b_asuscom_ipac.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:41:56 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && defined (ASUSCOM_IPAC)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_ipac.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/* masks for register encoded in base addr */
+
+#define ASI_BASE_MASK 0x0ffff
+#define ASI_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ASI_IDISAC 0x00000
+#define ASI_IDHSCXA 0x10000
+#define ASI_IDHSCXB 0x20000
+#define ASI_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define ASI_OFF_ALE 0x00
+#define ASI_OFF_RW 0x01
+
+/*---------------------------------------------------------------------------*
+ * Asuscom ISDNlink 128K ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+asi_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Asuscom ISDNlink 128K ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+asi_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Asuscom ISDNlink 128K ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+asi_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_ISAC_OFF);
+ bus_space_write_1(t,h,ASI_OFF_RW,data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXA_OFF);
+ bus_space_write_1(t,h,ASI_OFF_RW,data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXB_OFF);
+ bus_space_write_1(t,h,ASI_OFF_RW,data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_IPAC_OFF);
+ bus_space_write_1(t,h,ASI_OFF_RW,data);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Asuscom ISDNlink 128K ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+asi_read_reg(struct l1_softc *sc,int what,bus_size_t reg)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_ISAC_OFF);
+ return bus_space_read_1(t,h,ASI_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXA_OFF);
+ return bus_space_read_1(t,h,ASI_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXB_OFF);
+ return bus_space_read_1(t,h,ASI_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_IPAC_OFF);
+ return bus_space_read_1(t,h,ASI_OFF_RW);
+ default:
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_siemens_isurf - attach for Asuscom ISDNlink 128K
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_asi(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = asi_read_reg;
+ sc->writereg = asi_write_reg;
+
+ sc->readfifo = asi_read_fifo;
+ sc->writefifo = asi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC;
+
+ /* 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 */
+/*
+ * This has been taken from Linux driver.
+ * (Removed initialization that was not applicaple to
+ * this board or was already register default setting.)
+ */
+ IPAC_WRITE (IPAC_ACFG, 0xff); /* Setup AUX pin modes */
+ IPAC_WRITE (IPAC_AOE, 0x0); /* Setup AUX pin modes */
+ IPAC_WRITE (IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ return(0);
+}
+#endif /* (NISIC > 0) && defined (ASUSCOM_IPAC) */
diff --git a/sys/i4b/layer1/isic/i4b_avm_a1.c b/sys/i4b/layer1/isic/i4b_avm_a1.c
new file mode 100644
index 0000000..ee076f0
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_avm_a1.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 1996 Andrew Gordon. All rights reserved.
+ *
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:42:06 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(AVM_A1)
+
+#include <sys/param.h>
+#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 <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/*---------------------------------------------------------------------------*
+ * 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 */
+
+#define AVM_ISAC_R_OFFS (0x1400-0x20)
+#define AVM_HSCXA_R_OFFS (0x400-0x20)
+#define AVM_HSCXB_R_OFFS (0xc00-0x20)
+#define AVM_ISAC_F_OFFS (0x1400-0x20-0x3e0)
+#define AVM_HSCXA_F_OFFS (0x400-0x20-0x3e0)
+#define AVM_HSCXB_F_OFFS (0xc00-0x20-0x3e0)
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+avma1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+4]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+4]);
+ bus_space_read_multi_1(t, h, 0, buf, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+avma1_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+4]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+4]);
+ bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routine
+ *---------------------------------------------------------------------------*/
+static void
+avma1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ bus_space_write_1(t, h, offs, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+avma1_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ return bus_space_read_1(t, h, offs);
+}
+
+/*---------------------------------------------------------------------------*
+ * allocate an io port
+ *---------------------------------------------------------------------------*/
+static int
+isic_alloc_port(device_t dev, int rid, u_int base, u_int len)
+{
+ size_t unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ sc->sc_resources.io_rid[rid] = rid;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, rid, base, len);
+
+ if(!(sc->sc_resources.io_base[rid] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[rid],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Error, failed to reserve io #%d!\n", unit, rid);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1 - probe for AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_avma1(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+ void *ih = 0; /* dummy */
+ bus_space_tag_t t; /* bus things */
+ bus_space_handle_t h;
+ u_char savebyte;
+ u_char byte;
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+ sc->sc_unit = unit; /* set unit */
+ sc->sc_flags = FLAG_AVM_A1; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get iobase for AVM A1/Fritz!\n",
+ unit);
+ return(ENXIO);
+ }
+
+ /* set io base */
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+
+ /* release io base */
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+
+ switch(sc->sc_port)
+ {
+ case 0x200:
+ case 0x240:
+ case 0x300:
+ case 0x340:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
+ unit, sc->sc_port);
+ return(ENXIO);
+ break;
+ }
+
+ if(isic_alloc_port(dev, 0, sc->sc_port+AVM_CONF_REG, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 1, sc->sc_port+AVM_ISAC_R_OFFS, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 2, sc->sc_port+AVM_HSCXA_R_OFFS, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 3, sc->sc_port+AVM_HSCXB_R_OFFS, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 4, sc->sc_port+AVM_ISAC_F_OFFS, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 5, sc->sc_port+AVM_HSCXA_F_OFFS, 0x20))
+ return(ENXIO);
+
+ if(isic_alloc_port(dev, 6, sc->sc_port+AVM_HSCXB_F_OFFS, 0x20))
+ return(ENXIO);
+
+ /* get our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get an irq for AVM A1/Fritz!\n",unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* get the irq number */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* register interupt routine */
+ bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ /* check IRQ validity */
+
+ switch(sc->sc_irq)
+ {
+ 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",
+ unit, sc->sc_irq);
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+ }
+
+ 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;
+
+ /*
+ * 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",
+ unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ unit, HSCX_READ(1, H_VSTR));
+ return(ENXIO);
+ }
+
+ /* 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 .....
+ */
+
+ t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ savebyte = bus_space_read_1(t, h, 0);
+
+ /* write low to test bit */
+
+ bus_space_write_1(t, h, 0, 0x00);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x00)
+ {
+ printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
+ unit, byte);
+ bus_space_write_1(t, h, 0, savebyte);
+ return(ENXIO);
+ }
+
+ /* write high to test bit */
+
+ bus_space_write_1(t, h, 0, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x10)
+ {
+ printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
+ unit, byte);
+ bus_space_write_1(t, h, 0, savebyte);
+ return(ENXIO);
+ }
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_avma1 - attach AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_avma1(device_t dev)
+{
+ size_t unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* reset ISAC/HSCX */
+
+ 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(0);
+}
+
+#endif /* NISIC > 0 && defined(AVM_A1) */
diff --git a/sys/i4b/layer1/isic/i4b_bchan.c b/sys/i4b/layer1/isic/i4b_bchan.c
new file mode 100644
index 0000000..1fb6cc6
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_bchan.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 1997, 2000 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.6 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:42:26 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#include <machine/clock.h>
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+static void isic_bchannel_start(int unit, int h_chan);
+static void isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp);
+
+/*---------------------------------------------------------------------------*
+ * 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)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+
+ int s = SPLI4B();
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
+ 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)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ register l1_bchan_state_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(!(i4b_l1_bchan_tel_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 = L0ISICUNIT(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);
+ i4b_l1_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 = L0ISICUNIT(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);
+ i4b_l1_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->isic_drvr_linktab->bch_activity)(chan->isic_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)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ l1_bchan_state_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
+ *---------------------------------------------------------------------------*/
+isdn_link_t *
+isic_ret_linktab(int unit, int channel)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ return(&chan->isic_isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+void
+isic_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ l1_bchan_state_t *chan = &sc->sc_chan[channel];
+
+ chan->isic_drvr_linktab = dlt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+void
+isic_init_linktab(struct l1_softc *sc)
+{
+ l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
+ isdn_link_t *lt = &chan->isic_isdn_linktab;
+
+ /* make sure the hardware driver is known to layer 4 */
+ ctrl_types[CTRL_PASSIVE].set_linktab = i4b_l1_set_linktab;
+ ctrl_types[CTRL_PASSIVE].get_linktab = i4b_l1_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->isic_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;
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_ctx_s0P.c b/sys/i4b/layer1/isic/i4b_ctx_s0P.c
new file mode 100644
index 0000000..c58b691
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_ctx_s0P.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1997, 2000 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/Teles PnP
+ * ============================================================
+ *
+ * $Id: i4b_ctx_s0P.c,v 1.4 2000/08/22 11:30:04 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Tue Aug 22 11:35:00 2000]
+ *
+ * Note: this driver works for the Creatix ISDN S0-16 P+P and
+ * for the Teles S0/16.3 PnP card. Although they are not
+ * the same hardware and don't share the same PnP config
+ * information, once the base addresses are set, the
+ * offsets are same and therefore they can use the same
+ * driver.
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && (defined(CRTX_S0_P) || defined(TEL_S0_16_3_P))
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * Creatix / Teles PnP ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+ctxs0P_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]);
+ bus_space_read_multi_1(t,h,0x3e,buf,size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Creatix / Teles PnP ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+ctxs0P_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]);
+ bus_space_write_multi_1(t,h,0x3e,buf,size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Creatix / Teles PnP ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+ctxs0P_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]);
+ bus_space_write_1(t,h,offs,data);
+}
+
+/*---------------------------------------------------------------------------*
+ * Creatix / Teles PnP ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+ctxs0P_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]);
+ return bus_space_read_1(t,h,offs);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Cs0P - attach Creatix / Teles PnP
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Cs0P(device_t dev)
+{
+ u_int32_t iobase1;
+ u_int32_t iobase2;
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /*
+ * this card needs a second io_base,
+ * free resources if we don't get it
+ */
+
+ sc->sc_resources.io_rid[1] = 1;
+
+ if(!(sc->sc_resources.io_base[1] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[1],
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get io area 1 for Creatix / Teles PnP!\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* remember the io base addresses */
+
+ iobase1 = rman_get_start(sc->sc_resources.io_base[0]);
+ iobase2 = rman_get_start(sc->sc_resources.io_base[1]);
+
+ /*
+ * because overlapping resources are invalid,
+ * release the first io port resource
+ */
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+
+ /* set and allocate a base io address for the ISAC chip */
+
+ sc->sc_resources.io_rid[2] = 2;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, 2, iobase1-0x20, 0x40);
+
+ if(!(sc->sc_resources.io_base[2] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[2],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get io area 2 for Creatix / Teles PnP!\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /*
+ * because overlapping resources are invalid,
+ * release the second io port resource
+ */
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[1],
+ sc->sc_resources.io_base[1]);
+
+ /* set and allocate a resource for the HSCX channel A */
+
+ sc->sc_resources.io_rid[3] = 3;
+
+/*XXX*/ /* FIXME !!!!
+ * the width of the resource is too small, there are accesses
+ * to it with an offset of 0x3e into the next resource. anyway,
+ * it seems to work and i have no idea how to do 2 resources
+ * overlapping each other.
+ */
+
+#if 0
+ bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x20);
+#else
+ bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x10);
+#endif
+
+ if(!(sc->sc_resources.io_base[3] =
+ bus_alloc_resource(dev,SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[3],
+ 0ul,~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get io area 3 for Creatix / Teles PnP!\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* set and allocate a resources for the HSCX channel B */
+
+ sc->sc_resources.io_rid[4] = 4;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, 4, iobase2, 0x40);
+
+ if(!(sc->sc_resources.io_base[4] =
+ bus_alloc_resource(dev,SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[4],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get io area 4 for Creatix / Teles PnP!\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* 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;
+
+ /* enable the card */
+
+ t = rman_get_bustag(sc->sc_resources.io_base[2]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[2]);
+
+ bus_space_write_1(t, h, 0x3c, 0);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0x3c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ return 0;
+}
+
+#endif /* (NISIC > 0) && (defined(CRTX_S0_P) || defined(TEL_S0_16_3_P)) */
+
diff --git a/sys/i4b/layer1/isic/i4b_drn_ngo.c b/sys/i4b/layer1/isic/i4b_drn_ngo.c
new file mode 100644
index 0000000..042dbb2
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_drn_ngo.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:43:21 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && defined(DRN_NGO)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/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 */
+
+#define ISAC_DATA 0
+#define HSCX_DATA 1
+
+#define ISAC_ADDR 0
+#define HSCX_ADDR 1
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t tdata, tadr;
+ bus_space_handle_t hdata, hadr;
+
+ tdata = rman_get_bustag(sc->sc_resources.io_base[0]);
+ hdata = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ tadr = rman_get_bustag(sc->sc_resources.io_base[1]);
+ hadr = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ switch(what)
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1 (tadr ,hadr, ISAC_ADDR,0x0);
+ bus_space_read_multi_1(tdata,hdata,ISAC_DATA,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,0x0);
+ bus_space_read_multi_1(tdata,hdata,HSCX_DATA,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,HSCX_BOFF);
+ bus_space_read_multi_1(tdata,hdata,HSCX_DATA,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t tdata, tadr;
+ bus_space_handle_t hdata, hadr;
+
+ tdata = rman_get_bustag(sc->sc_resources.io_base[0]);
+ hdata = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ tadr = rman_get_bustag(sc->sc_resources.io_base[1]);
+ hadr = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ switch(what)
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1 (tadr ,hadr, ISAC_ADDR,0x0);
+ bus_space_write_multi_1(tdata,hdata,ISAC_DATA,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,0x0);
+ bus_space_write_multi_1(tdata,hdata,HSCX_DATA,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,HSCX_BOFF);
+ bus_space_write_multi_1(tdata,hdata,HSCX_DATA,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write register routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_reg(struct l1_softc *sc, int what, bus_size_t reg, u_int8_t data)
+{
+ bus_space_tag_t tdata, tadr;
+ bus_space_handle_t hdata, hadr;
+
+ tdata = rman_get_bustag(sc->sc_resources.io_base[0]);
+ hdata = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ tadr = rman_get_bustag(sc->sc_resources.io_base[1]);
+ hadr = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ switch(what)
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(tadr ,hadr, ISAC_ADDR,reg);
+ bus_space_write_1(tdata,hdata,ISAC_DATA,data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg);
+ bus_space_write_1(tdata,hdata,HSCX_DATA,data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg+HSCX_BOFF);
+ bus_space_write_1(tdata,hdata,HSCX_DATA,data);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+drnngo_read_reg(struct l1_softc *sc, int what, bus_size_t reg)
+{
+ bus_space_tag_t tdata, tadr;
+ bus_space_handle_t hdata, hadr;
+
+ tdata = rman_get_bustag(sc->sc_resources.io_base[0]);
+ hdata = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ tadr = rman_get_bustag(sc->sc_resources.io_base[1]);
+ hadr = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ switch(what)
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(tadr ,hadr, ISAC_ADDR,reg);
+ return bus_space_read_1(tdata,hdata,ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg);
+ return bus_space_read_1(tdata,hdata,HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg+HSCX_BOFF);
+ return bus_space_read_1(tdata,hdata,HSCX_DATA);
+ default:
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * probe for ISA PnP cards
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_drnngo(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ sc->sc_resources.io_rid[1] = 1;
+
+ /*
+ * this card needs a second io_base,
+ * free resources if we don't get it
+ */
+
+ if(!(sc->sc_resources.io_base[1] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[1],
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Failed to get second io base.\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* 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;
+
+ return (0);
+}
+
+#endif /* (NISIC > 0) && defined(DRN_NGO) */
diff --git a/sys/i4b/layer1/isic/i4b_dynalink.c b/sys/i4b/layer1/isic/i4b_dynalink.c
new file mode 100644
index 0000000..67e6bbe
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_dynalink.c
@@ -0,0 +1,239 @@
+/*
+ * 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.1 2000/09/04 09:17:26 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Sep 4 09:47:18 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+/* 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.
+*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && defined(DYNALINK)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/* 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
+
+/* LOW-LEVEL DEVICE ACCESS
+*/
+
+static void
+dynalink_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+static void
+dynalink_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+static void
+dynalink_write_reg(struct l1_softc *sc, int what, bus_size_t reg, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, reg);
+ bus_space_write_1(t, h, ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+reg);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+reg);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ }
+}
+
+static u_int8_t
+dynalink_read_reg(struct l1_softc *sc, int what, bus_size_t reg)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, reg);
+ return bus_space_read_1(t, h, ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+reg);
+ return bus_space_read_1(t, h, HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+reg);
+ return bus_space_read_1(t, h, HSCX);
+ }
+ return 0;
+}
+
+/* attach callback routine */
+int
+isic_attach_Dyn(device_t dev)
+{
+ int unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = &l1_sc[unit]; /* pointer to softc */
+
+ struct i4b_info * info = &(sc->sc_resources);
+ bus_space_tag_t t = rman_get_bustag(info->io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(info->io_base[0]);
+
+ /* fill in l1_softc structure */
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+ sc->clearirq = NULL;
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+ 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("isic%d: HSCX VSTR test failed for Dynalink\n",
+ sc->sc_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ sc->sc_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ sc->sc_unit, HSCX_READ(1, H_VSTR));
+ return ENXIO;
+ }
+
+ /* reset card */
+ bus_space_write_1(t,h,ADDR,RESET);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t,h,ADDR,0);
+ DELAY(SEC_DELAY / 10);
+
+ return 0;
+}
+
+#endif /* (NISIC > 0) && defined(DYNALINK) */
diff --git a/sys/i4b/layer1/isic/i4b_elsa_pcc16.c b/sys/i4b/layer1/isic/i4b_elsa_pcc16.c
new file mode 100644
index 0000000..ef8786a
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_elsa_pcc16.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 1999, 2000 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 MicroLink ISDN/PCC-16
+ * =====================================================================
+ *
+ * This should now also work for an ELSA PCFpro.
+ *
+ * $Id: i4b_elsa_pcc16.c,v 1.4 2000/07/19 07:51:22 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Wed Jul 19 09:53:35 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && defined(ELSA_PCC16)
+
+#include <sys/param.h>
+#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 <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+static void i4b_epcc16_clrirq(struct l1_softc *sc);
+
+/* 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 MicroLink ISDN/PCC-16 clear IRQ routine
+ *---------------------------------------------------------------------------*/
+static void
+i4b_epcc16_clrirq(struct l1_softc *sc)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCC-16 ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+epcc16_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCC-16 ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+epcc16_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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, 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, 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, buf, size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCC-16 ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+epcc16_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCC-16 ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+epcc16_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_detach_Epcc16 - detach for ELSA MicroLink ISDN/PCC-16
+ *---------------------------------------------------------------------------*/
+static void
+isic_detach_Epcc16(device_t dev)
+{
+ struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
+
+ if ( sc->sc_resources.irq )
+ {
+ bus_teardown_intr(dev,sc->sc_resources.irq,
+ (void(*)(void *))isicintr);
+ bus_release_resource(dev,SYS_RES_IRQ,
+ sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ sc->sc_resources.irq = 0;
+ }
+
+ if ( sc->sc_resources.io_base[0] ) {
+ bus_release_resource(dev,SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ sc->sc_resources.io_base[0] = 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Epcc16 - probe for ELSA MicroLink ISDN/PCC-16
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Epcc16(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+ void *ih = 0; /* dummy */
+
+ /* check max unit range */
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA PCC-16!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+
+ sc->sc_unit = unit; /* set unit */
+
+ sc->sc_flags = FLAG_ELSA_PCC16; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get iobase for ELSA PCC-16.\n",
+ unit);
+ return(ENXIO);
+ }
+
+ /* check if we got an iobase */
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+
+ switch(sc->sc_port)
+ {
+ case 0x160:
+ case 0x170:
+ case 0x260:
+ case 0x360:
+ break;
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA MicroLink ISDN/PCC-16!\n",
+ unit, sc->sc_port);
+ isic_detach_Epcc16(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = i4b_epcc16_clrirq;
+ sc->readreg = epcc16_read_reg;
+ sc->writereg = epcc16_write_reg;
+
+ sc->readfifo = epcc16_read_fifo;
+ sc->writefifo = epcc16_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;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the ELSA PCC-16
+ * 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) )
+ {
+ /* patch from "Doobee R . Tzeck" <drt@ailis.de>:
+ * I own an ELSA PCFpro. To my knowledge, the ELSA PCC16 is
+ * a stripped down Version on the PCFpro. By patching the
+ * card detection routine for the PPC16 I was able to use
+ * the PPC16 driver for the PCFpro.
+ */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x85) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x85) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ELSA MicroLink ISDN/PCC-16\n",
+ unit);
+ isic_detach_Epcc16(dev);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ unit, HSCX_READ(1, H_VSTR));
+ return (ENXIO);
+ }
+ else
+ {
+ printf("isic%d: ELSA MicroLink ISDN/PCFpro found, going to tread it as PCC-16\n",
+ unit);
+ }
+ }
+
+ /* get our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get an irq.\n",unit);
+ isic_detach_Epcc16(dev);
+ return ENXIO;
+ }
+
+ /* get the irq number */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* check IRQ validity */
+ switch(sc->sc_irq)
+ {
+ case 2:
+ case 9:
+ case 3:
+ case 5:
+ case 10:
+ case 11:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for ELSA MicroLink ISDN/PCC-16!\n",
+ unit, sc->sc_irq);
+ isic_detach_Epcc16(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* register interupt routine */
+ bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc,&ih);
+
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Epcc16 - attach for ELSA MicroLink ISDN/PCC-16
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Epcc16(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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);
+
+ return 0;
+}
+
+#endif /* (NISIC > 0) && defined(ELSA_PCC16) */
diff --git a/sys/i4b/layer1/isic/i4b_elsa_qs1i.c b/sys/i4b/layer1/isic/i4b_elsa_qs1i.c
new file mode 100644
index 0000000..40d4705
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_elsa_qs1i.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:44:08 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 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>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+static void i4b_eq1i_clrirq(struct l1_softc *sc);
+
+/* 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
+ *---------------------------------------------------------------------------*/
+static void
+i4b_eq1i_clrirq(struct l1_softc *sc)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pi_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pi_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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, 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, 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, buf, size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pi_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+eqs1pi_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Eqs1pi - attach for ELSA QuickStep 1000pro/ISA
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Eqs1pi(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ u_char byte = ELSA_CTRL_SECRET;
+
+ /* 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;
+
+ /* enable the card */
+
+ 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);
+
+ return 0;
+}
+#endif /* (NISIC > 0) && defined(ELSA_QS1ISA) */
diff --git a/sys/i4b/layer1/isic/i4b_elsa_qs1p.c b/sys/i4b/layer1/isic/i4b_elsa_qs1p.c
new file mode 100644
index 0000000..9a94422
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_elsa_qs1p.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 1997, 2000 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 MicroLink ISDN/PCI
+ * ==================================================================
+ *
+ * $Id: i4b_elsa_qs1p.c,v 1.4 2000/06/02 11:58:56 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 13:57:26 2000]
+ *
+ * Note: ELSA Quickstep 1000pro PCI = ELSA MicroLink ISDN/PCI
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#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>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+#include <i4b/layer1/isic/i4b_ipac.h>
+
+#define MEM0_MAPOFF 0
+#define PORT0_MAPOFF 4
+#define PORT1_MAPOFF 12
+
+#define ELSA_PORT0_MAPOFF (PCIR_MAPS+PORT0_MAPOFF)
+#define ELSA_PORT1_MAPOFF (PCIR_MAPS+PORT1_MAPOFF)
+
+#define PCI_QS1000_DID 0x1000
+#define PCI_QS1000_VID 0x1048
+
+/* 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
+
+
+static int eqs1p_pci_probe(device_t dev);
+static int eqs1p_pci_attach(device_t dev);
+
+static device_method_t eqs1p_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, eqs1p_pci_probe),
+ DEVMETHOD(device_attach, eqs1p_pci_attach),
+ { 0, 0 }
+};
+
+static driver_t eqs1p_pci_driver = {
+ "isic",
+ eqs1p_pci_methods,
+ 0
+};
+
+static devclass_t eqs1p_pci_devclass;
+
+DRIVER_MODULE(eqs1p, pci, eqs1p_pci_driver, eqs1p_pci_devclass, 0, 0);
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCI fifo read routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCI fifo write routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pp_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCI register write routine
+ *---------------------------------------------------------------------------*/
+static void
+eqs1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ 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;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ELSA MicroLink ISDN/PCI register read routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+eqs1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]);
+
+ 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;
+}
+
+/*---------------------------------------------------------------------------*
+ * avma1pp_probe - probe for a card
+ *---------------------------------------------------------------------------*/
+static int
+eqs1p_pci_probe(device_t dev)
+{
+ if((pci_get_vendor(dev) == PCI_QS1000_VID) &&
+ (pci_get_device(dev) == PCI_QS1000_DID))
+ {
+ device_set_desc(dev, "ELSA MicroLink ISDN/PCI");
+ return(0);
+ }
+ return(ENXIO);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Eqs1pp - attach for ELSA MicroLink ISDN/PCI
+ *---------------------------------------------------------------------------*/
+static int
+eqs1p_pci_attach(device_t dev)
+{
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+ struct l1_softc *sc;
+ void *ih = 0;
+ int unit = device_get_unit(dev);
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA MicroLink ISDN/PCI!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get softc */
+
+ sc->sc_unit = unit;
+
+ /* get io_base */
+
+ sc->sc_resources.io_rid[0] = ELSA_PORT0_MAPOFF;
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Couldn't get first iobase for ELSA MicroLink ISDN/PCI!\n", unit);
+ return(ENXIO);
+ }
+
+ sc->sc_resources.io_rid[1] = ELSA_PORT1_MAPOFF;
+
+ if(!(sc->sc_resources.io_base[1] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[1],
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Couldn't get second iobase for ELSA MicroLink ISDN/PCI!\n", unit);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[1]);
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get irq for ELSA MicroLink ISDN/PCI!\n",unit);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* 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;
+
+ if(isic_attach_common(dev))
+ {
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void*))isicintr,
+ sc, &ih))
+ {
+ printf("isic%d: Couldn't set up irq for ELSA MicroLink ISDN/PCI!\n", unit);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ /* 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 */
+
+ t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ bus_space_write_1(t, h, 0x4c, 0x41); /* enable card interrupt */
+
+ return(0);
+}
+
+#endif /* (NISIC > 0) && (NPCI > 0) && defined(ELSA_QS1PCI) */
diff --git a/sys/i4b/layer1/isic/i4b_hscx.c b/sys/i4b/layer1/isic/i4b_hscx.c
new file mode 100644
index 0000000..7731cb2
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_hscx.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 1997, 2000 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.7 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:44:50 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/stdarg.h>
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * HSCX IRQ Handler
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq)
+{
+ register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
+ u_char exir = 0;
+ int activity = -1;
+ u_char cmd = 0;
+
+ NDBGL1(L1_H_IRQ, "%#x", ista);
+
+ if(ex_irq)
+ {
+ /* get channel extended irq reg */
+
+ exir = HSCX_READ(h_chan, H_EXIR);
+
+ if(exir & HSCX_EXIR_RFO)
+ {
+ chan->stat_RFO++;
+ NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
+ }
+
+ if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
+ {
+ chan->stat_XDU++;
+ NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
+ 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);
+ NDBGL1(L1_H_XFRERR, "received invalid Frame");
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RDO)
+ {
+ chan->stat_RDO++;
+ NDBGL1(L1_H_XFRERR, "receive data overflow");
+ error++;
+ }
+
+ if((rsta & HSCX_RSTA_CRC) == 0)
+ {
+ chan->stat_CRC++;
+ cmd |= (HSCX_CMDR_RHR);
+ NDBGL1(L1_H_XFRERR, "CRC check failed");
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RAB)
+ {
+ chan->stat_RAB++;
+ NDBGL1(L1_H_XFRERR, "Receive message aborted");
+ 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 = L0ISICUNIT(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);
+ i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
+
+ activity = ACT_RX;
+
+ /* mark buffer ptr as unused */
+
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ else
+ {
+ NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", 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 = L0ISICUNIT(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);
+ i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ /* silence detection */
+
+ if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ if(!(IF_QFULL(&chan->rx_queue)))
+ {
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+ }
+ else
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ }
+
+ /* signal upper driver that data is available */
+
+ (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
+
+ /* 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
+ {
+ NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", 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;
+
+ NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", 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->isic_drvr_linktab->bch_tx_queue_empty)(chan->isic_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 = L0ISICUNIT(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);
+ i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(i4b_l1_bchan_tel_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 = L0ISICUNIT(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);
+ i4b_l1_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->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);
+}
+
+/*---------------------------------------------------------------------------*
+ * HSCX initialization
+ *
+ * for telephony: extended transparent mode 1
+ * for raw hdlc: transparent mode 0
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_init(struct l1_softc *sc, int h_chan, int activate)
+{
+ l1_bchan_state_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);
+ }
+#if 0
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
+#else
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR);
+#endif
+ }
+ 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 l1_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)
+ {
+ NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
+ }
+
+ HSCX_WRITE(h_chan, H_CMDR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * wait for HSCX transmit FIFO write enable
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_waitxfw(struct l1_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)
+ {
+ NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
+ }
+ else if (timeout != WAITTO)
+ {
+ NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
+ }
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_hscx.h b/sys/i4b/layer1/isic/i4b_hscx.h
new file mode 100644
index 0000000..b4a9197
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_hscx.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1996, 2000 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.2 2000/03/09 16:12:51 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Dec 13 22:00:49 1999]
+ *
+ *---------------------------------------------------------------------------*/
+
+#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/isic/i4b_ipac.h b/sys/i4b/layer1/isic/i4b_ipac.h
new file mode 100644
index 0000000..623092d
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_ipac.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1997, 2000 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.1 2000/03/07 14:12:26 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Dec 13 22:00:58 1999]
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#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
+
+/* chip version */
+
+#define IPAC_V11 0x01 /* IPAC Version 1.1 */
+#define IPAC_V12 0x02 /* IPAC Version 1.2 */
+
+/*
+ * 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/isic/i4b_isac.c b/sys/i4b/layer1/isic/i4b_isac.c
new file mode 100644
index 0000000..792d46b
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isac.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 1997, 2000 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.7 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:45:08 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if NISIC > 0
+
+#include "opt_i4b.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/stdarg.h>
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char isic_isac_exir_hdlr(register struct l1_softc *sc, u_char exir);
+static void isic_isac_ind_hdlr(register struct l1_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_irq(struct l1_softc *sc, int ista)
+{
+ register u_char c = 0;
+ NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", 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++;
+ NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
+ }
+
+ if(error == 0)
+ NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", 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 = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled &&
+ (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
+ {
+ i4b_l1_ph_data_ind(L0ISICUNIT(sc->sc_unit), sc->sc_ibuf);
+ }
+ else
+ {
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
+ 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
+ {
+ NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
+ 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 l1_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Protocol Error");
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+isic_isac_ind_hdlr(register struct l1_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ default:
+ NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc));
+ event = EV_INFO0;
+ break;
+ }
+ isic_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_l1_cmd(struct l1_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)
+ {
+ NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+isic_isac_init(struct l1_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode");
+
+ /* 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
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
+
+ /* 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/isic/i4b_isac.h b/sys/i4b/layer1/isic/i4b_isac.h
new file mode 100644
index 0000000..2d92d000
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isac.h
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 1996, 2000 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.2 2000/03/09 16:12:51 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Dec 13 22:01:25 1999]
+ *
+ *---------------------------------------------------------------------------*/
+
+#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/isic/i4b_isic.c b/sys/i4b/layer1/isic/i4b_isic.c
new file mode 100644
index 0000000..97cbf73
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isic.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 1997, 2000 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.6 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:45:24 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 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>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isic_ext.h>
+#include <i4b/layer1/isic/i4b_ipac.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+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"
+};
+
+/* jump table for multiplex routines */
+struct i4b_l1mux_func isic_l1mux_func = {
+ isic_ret_linktab,
+ isic_set_linktab,
+ isic_mph_command_req,
+ isic_ph_data_req,
+ isic_ph_activate_req,
+};
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+void
+isicintr(struct l1_softc *sc)
+{
+ 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;
+ }
+ }
+
+ 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) && (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);
+ }
+ 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)
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & IPAC_ISTA_EXD)
+ {
+ /* force ISAC interrupt handling */
+ isic_isac_irq(sc, ISAC_ISTA_EXI);
+ was_ipac_irq = 1;
+ }
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+ }
+
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_recover - try to recover from irq lockup
+ *---------------------------------------------------------------------------*/
+void
+isic_recover(struct l1_softc *sc)
+{
+ u_char byte;
+
+ /* get hscx irq status from hscx b ista */
+
+ byte = HSCX_READ(HSCX_CH_B, H_ISTA);
+
+ NDBGL1(L1_ERROR, "HSCX B: ISTA = 0x%x", byte);
+
+ if(byte & HSCX_ISTA_ICA)
+ NDBGL1(L1_ERROR, "HSCX A: ISTA = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA));
+
+ if(byte & HSCX_ISTA_EXB)
+ NDBGL1(L1_ERROR, "HSCX B: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR));
+
+ if(byte & HSCX_ISTA_EXA)
+ NDBGL1(L1_ERROR, "HSCX A: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR));
+
+ /* get isac irq status */
+
+ byte = ISAC_READ(I_ISTA);
+
+ NDBGL1(L1_ERROR, " ISAC: ISTA = 0x%x", byte);
+
+ if(byte & ISAC_ISTA_EXI)
+ NDBGL1(L1_ERROR, " ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR));
+
+ if(byte & ISAC_ISTA_CISQ)
+ {
+ byte = ISAC_READ(I_CIRR);
+
+ NDBGL1(L1_ERROR, " ISAC: CISQ = 0x%x", byte);
+
+ if(byte & ISAC_CIRR_SQC)
+ NDBGL1(L1_ERROR, " ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR));
+ }
+
+ NDBGL1(L1_ERROR, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK);
+ NDBGL1(L1_ERROR, "HSCX A: IMASK = 0x%x", 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);
+
+ NDBGL1(L1_ERROR, " ISAC: IMASK = 0x%x", ISAC_IMASK);
+
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_common - common attach routine for all busses
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_common(device_t dev)
+{
+ char *drvid = NULL;
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ sc->sc_unit = unit;
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ if(sc->sc_ipac)
+ {
+ sc->sc_ipac_version = IPAC_READ(IPAC_ID);
+
+ switch(sc->sc_ipac_version)
+ {
+ case IPAC_V11:
+ case IPAC_V12:
+ break;
+
+ default:
+ printf("isic%d: Error, IPAC version %d unknown!\n",
+ unit, sc->sc_ipac_version);
+ 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:
+ break;
+
+ default:
+ printf("isic%d: Error, ISAC version %d unknown!\n",
+ unit, sc->sc_isac_version);
+ return ENXIO;
+ 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%d: Error, HSCX version %d unknown!\n",
+ unit, sc->sc_hscx_version);
+ return ENXIO;
+ break;
+ }
+ }
+
+ isic_isac_init(sc); /* ISAC setup */
+
+ /* 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);
+
+ isic_init_linktab(sc); /* setup linktab */
+
+ sc->sc_trace = TRACE_OFF; /* set trace level */
+
+ sc->sc_state = ISAC_IDLE; /* set state */
+
+ sc->sc_ibuf = NULL; /* input buffering */
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL; /* output buffering */
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL; /* second output buffer */
+ sc->sc_freeflag2 = 0;
+
+ /* timer setup */
+
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+
+ /* init higher protocol layers */
+
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &isic_l1mux_func);
+
+ /* announce manufacturer and card type for ISA cards */
+
+ switch(sc->sc_flags)
+ {
+ case FLAG_TELES_S0_8:
+ drvid = "Teles S0/8 (or compatible)";
+ break;
+
+ case FLAG_TELES_S0_16:
+ drvid = "Teles S0/16 (or compatible)";
+ break;
+
+ case FLAG_TELES_S0_163:
+ drvid = "Teles S0/16.3";
+ break;
+
+ case FLAG_AVM_A1:
+ drvid = "AVM A1 or Fritz!Card Classic";
+ break;
+
+ case FLAG_AVM_A1_PCMCIA:
+ drvid = "AVM Fritz!Card PCMCIA";
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ drvid = "USRobotics Sportster ISDN TA intern";
+ break;
+
+ case FLAG_ITK_IX1:
+ drvid = "ITK ix1 micro";
+ break;
+
+ case FLAG_ELSA_PCC16:
+ drvid = "ELSA MicroLink ISDN/PCC-16";
+ break;
+
+ default:
+ drvid = NULL; /* pnp/pci cards announce themselves */
+ break;
+ }
+
+ if(drvid)
+ printf("isic%d: %s\n", unit, drvid);
+
+ if(bootverbose)
+ {
+ /* announce chip versions */
+
+ if(sc->sc_ipac)
+ {
+ if(sc->sc_ipac_version == IPAC_V11)
+ printf("isic%d: IPAC PSB2115 Version 1.1\n", unit);
+ else
+ printf("isic%d: IPAC PSB2115 Version 1.2\n", unit);
+ }
+ else
+ {
+ printf("isic%d: ISAC %s (IOM-%c)\n",
+ unit,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+
+ printf("isic%d: HSCX %s\n",
+ unit,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_detach_common - common detach routine for all busses
+ *---------------------------------------------------------------------------*/
+void
+isic_detach_common(device_t dev)
+{
+ struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
+ int i;
+
+ sc->sc_flags = 0;
+
+ /* free interrupt resources */
+
+ if(sc->sc_resources.irq)
+ {
+ /* tear down interupt handler */
+ bus_teardown_intr(dev, sc->sc_resources.irq,
+ (void(*)(void *))isicintr);
+
+ /* free irq */
+ bus_release_resource(dev, SYS_RES_IRQ,
+ sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ sc->sc_resources.irq_rid = 0;
+ sc->sc_resources.irq = 0;
+ }
+
+ /* free memory resource */
+
+ if(sc->sc_resources.mem)
+ {
+ bus_release_resource(dev,SYS_RES_MEMORY,
+ sc->sc_resources.mem_rid,
+ sc->sc_resources.mem);
+ sc->sc_resources.mem_rid = 0;
+ sc->sc_resources.mem = 0;
+ }
+
+ /* free iobases */
+
+ for(i=0; i < INFO_IO_BASES ; i++)
+ {
+ if(sc->sc_resources.io_base[i])
+ {
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[i],
+ sc->sc_resources.io_base[i]);
+ sc->sc_resources.io_rid[i] = 0;
+ sc->sc_resources.io_base[i] = 0;
+ }
+ }
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/isic/i4b_isic.h b/sys/i4b/layer1/isic/i4b_isic.h
new file mode 100644
index 0000000..2cee7aa
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isic.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 1997, 2000 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_isic.h,v 1.4 2000/09/04 09:17:26 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Sep 4 09:34:38 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_ISIC_H_
+#define _I4B_ISIC_H_
+
+#include <sys/resource.h>
+#include <sys/bus.h>
+#include <i386/include/bus.h>
+#include <sys/rman.h>
+#include <i386/include/resource.h>
+
+#include <i4b/include/i4b_l3l4.h>
+
+#include <i4b/layer1/isic/i4b_isic_ext.h>
+
+/*---------------------------------------------------------------------------
+ * isic driver: max no of 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.
+ *---------------------------------------------------------------------------*/
+ #define ISIC_MAXUNIT 3 /* max no of supported units 0..3 */
+
+/*---------------------------------------------------------------------------
+ * kernel config file flags definition
+ *---------------------------------------------------------------------------*/
+#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
+#define FLAG_CREATIX_S0_PnP 6
+#define FLAG_USR_ISDN_TA_INT 7
+#define FLAG_DRN_NGO 8
+#define FLAG_SWS 9
+#define FLAG_AVM_A1_PCMCIA 10
+#define FLAG_DYNALINK 11
+#define FLAG_BLMASTER 12
+#define FLAG_ELSA_QS1P_ISA 13
+#define FLAG_ELSA_QS1P_PCI 14
+#define FLAG_SIEMENS_ITALK 15
+#define FLAG_ELSA_MLIMC 16
+#define FLAG_ELSA_MLMCALL 17
+#define FLAG_ITK_IX1 18
+#define FLAG_AVMA1PCI 19
+#define FLAG_ELSA_PCC16 20
+#define FLAG_AVM_PNP 21
+#define FLAG_SIEMENS_ISURF2 22
+#define FLAG_ASUSCOM_IPAC 23
+
+#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))
+
+#define INFO_IO_BASES 50 /* 49 needed for USR */
+
+struct i4b_info {
+ struct resource * io_base[INFO_IO_BASES];
+ int io_rid [INFO_IO_BASES];
+ struct resource * irq;
+ int irq_rid;
+ struct resource * mem;
+ int mem_rid;
+};
+
+/*---------------------------------------------------------------------------*
+ * l1_bchan_state: the state of one B channel
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ int unit; /* cards unit number */
+ int channel; /* which channel is this*/
+ caddr_t hscx; /* HSCX address */
+ 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 isic_isdn_linktab; /* b channel addresses */
+ drvr_link_t *isic_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 */
+
+} l1_bchan_state_t;
+
+/*---------------------------------------------------------------------------*
+ * l1_softc: the state of the layer 1 of the D channel
+ *---------------------------------------------------------------------------*/
+struct l1_softc
+{
+ int sc_unit; /* unit number */
+ int sc_irq; /* interrupt vector */
+ struct i4b_info sc_resources;
+ int sc_flags;
+
+ int sc_port; /* port base address */
+
+ 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 */
+
+ 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)
+
+ u_char sc_isac_mask; /* ISAC IRQ mask */
+#define ISAC_IMASK (sc->sc_isac_mask)
+
+ l1_bchan_state_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_ipac_version; /* version number of IPAC */
+
+ int sc_I430state; /* I.430 state F3 .... F8 */
+
+ int sc_I430T3; /* I.430 Timer T3 running */
+
+ struct callout_handle sc_T3_callout;
+
+ int sc_I430T4; /* Timer T4 running */
+
+ struct callout_handle sc_T4_callout;
+
+ /*
+ * byte fields for the AVM Fritz!Card PCI. These are packed into
+ * a u_int in the driver.
+ */
+ u_char avma1pp_cmd;
+ u_char avma1pp_txl;
+ u_char avma1pp_prot;
+
+ int sc_enabled; /* daemon is running */
+
+ int sc_ipac; /* flag, running on ipac */
+ int sc_bfifolen; /* length of b channel fifos */
+
+#define ISIC_WHAT_ISAC 0
+#define ISIC_WHAT_HSCXA 1
+#define ISIC_WHAT_HSCXB 2
+#define ISIC_WHAT_IPAC 3
+
+ u_int8_t (*readreg) (struct l1_softc *sc, int what, bus_size_t offs);
+ void (*writereg) (struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data);
+ void (*readfifo) (struct l1_softc *sc, int what, void *buf, size_t size);
+ void (*writefifo) (struct l1_softc *sc, int what, void *data, size_t size);
+ void (*clearirq) (struct l1_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))
+};
+
+/*---------------------------------------------------------------------------*
+ * 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
+
+extern struct l1_softc l1_sc[];
+
+extern void isicintr(struct l1_softc *sc);
+extern int isic_attach_common(device_t dev);
+extern void isic_detach_common(device_t dev);
+extern void isic_recover(struct l1_softc *sc);
+
+extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate );
+
+extern void isic_init_linktab ( struct l1_softc *sc );
+extern int isic_isac_init ( struct l1_softc *sc );
+extern void isic_isac_irq ( struct l1_softc *sc, int r );
+extern void isic_isac_l1_cmd ( struct l1_softc *sc, int command );
+extern void isic_next_state ( struct l1_softc *sc, int event );
+extern char *isic_printstate ( struct l1_softc *sc );
+
+extern int isic_hscx_fifo(l1_bchan_state_t *, struct l1_softc *);
+extern void isic_hscx_init ( struct l1_softc *sc, int hscx_channel, int activate );
+extern void isic_hscx_irq ( struct l1_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 l1_softc *sc, int h_chan, unsigned char cmd );
+extern void isic_hscx_waitxfw( struct l1_softc *sc, int h_chan );
+
+extern int isic_probe_s016 (device_t dev);
+extern int isic_attach_s016 (device_t dev);
+
+extern int isic_probe_s08 (device_t dev);
+extern int isic_attach_s08 (device_t dev);
+
+extern int isic_probe_Epcc16 (device_t dev);
+extern int isic_attach_Epcc16 (device_t dev);
+
+extern int isic_probe_s0163 (device_t dev);
+extern int isic_attach_s0163 (device_t dev);
+
+extern int isic_probe_avma1 (device_t dev);
+extern int isic_attach_avma1 (device_t dev);
+
+extern int isic_probe_usrtai (device_t dev);
+extern int isic_attach_usrtai (device_t dev);
+
+extern int isic_probe_itkix1 (device_t dev);
+extern int isic_attach_itkix1 (device_t dev);
+
+extern int isic_attach_drnngo (device_t dev);
+extern int isic_attach_Cs0P (device_t dev);
+extern int isic_attach_Eqs1pi(device_t dev);
+extern int isic_attach_sws(device_t dev);
+extern int isic_attach_siemens_isurf(device_t dev);
+extern int isic_attach_asi(device_t dev);
+extern int isic_attach_Dyn(device_t dev);
+
+#endif /* _I4B_ISIC_H_ */
diff --git a/sys/i4b/layer1/isic/i4b_isic_ext.h b/sys/i4b/layer1/isic/i4b_isic_ext.h
new file mode 100644
index 0000000..1e40058
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isic_ext.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997, 2000 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_isic_ext.h,v 1.3 2000/06/02 16:14:36 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 14:43:57 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_ISIC_EXT_H_
+#define _I4B_ISIC_EXT_H_
+
+#include <i4b/include/i4b_l3l4.h>
+
+int isic_ph_data_req(int unit, struct mbuf *m, int freeflag);
+int isic_ph_activate_req(int unit);
+int isic_mph_command_req(int unit, int command, void *parm);
+
+void isic_set_linktab(int unit, int channel, drvr_link_t *dlt);
+isdn_link_t *isic_ret_linktab(int unit, int channel);
+
+#endif /* _I4B_ISIC_H_ */
diff --git a/sys/i4b/layer1/isic/i4b_isic_isa.c b/sys/i4b/layer1/isic/i4b_isic_isa.c
new file mode 100644
index 0000000..40b05bd
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isic_isa.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:45:34 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 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>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_ipac.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <sys/resource.h>
+#include <sys/bus.h>
+#include <isa/isavar.h>
+
+struct l1_softc l1_sc[ISIC_MAXUNIT];
+
+static int isic_isa_probe(device_t dev);
+static int isic_isa_attach(device_t dev);
+
+static device_method_t isic_methods[] = {
+ DEVMETHOD(device_probe, isic_isa_probe),
+ DEVMETHOD(device_attach, isic_isa_attach),
+ { 0, 0 }
+};
+
+static driver_t isic_driver = {
+ "isic",
+ isic_methods,
+ 0
+};
+
+static devclass_t isic_devclass;
+
+DRIVER_MODULE(isic, isa, isic_driver, isic_devclass, 0, 0);
+
+/*---------------------------------------------------------------------------*
+ * probe for ISA non-PnP cards
+ *---------------------------------------------------------------------------*/
+static int
+isic_isa_probe(device_t dev)
+{
+ int ret = ENXIO;
+
+ if(isa_get_vendorid(dev)) /* no PnP probes here */
+ return ENXIO;
+
+ switch(device_get_flags(dev))
+ {
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(dev);
+ break;
+#endif
+
+#ifdef ELSA_PCC16
+ case FLAG_ELSA_PCC16:
+ ret = isic_probe_Epcc16(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:
+ printf("isic%d: probe, unknown flag: %d\n",
+ device_get_unit(dev), device_get_flags(dev));
+ break;
+ }
+ return(ret);
+}
+
+/*---------------------------------------------------------------------------*
+ * attach for ISA non-PnP cards
+ *---------------------------------------------------------------------------*/
+static int
+isic_isa_attach(device_t dev)
+{
+ int ret = ENXIO;
+
+ struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
+
+ sc->sc_unit = device_get_unit(dev);
+
+ /* card dependent setup */
+
+ switch(sc->sc_flags)
+ {
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_attach_s016(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_attach_s08(dev);
+ break;
+#endif
+
+#ifdef ELSA_PCC16
+ case FLAG_ELSA_PCC16:
+ ret = isic_attach_Epcc16(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_attach_s0163(dev);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_attach_avma1(dev);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_attach_usrtai(dev);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_attach_itkix1(dev);
+ break;
+#endif
+
+ default:
+ printf("isic%d: attach, unknown flag: %d\n",
+ device_get_unit(dev), device_get_flags(dev));
+ break;
+ }
+
+ if(ret)
+ return(ret);
+
+ ret = isic_attach_common(dev);
+
+ return(ret);
+}
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_isic_pnp.c b/sys/i4b/layer1/isic/i4b_isic_pnp.c
new file mode 100644
index 0000000..3fe6595
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_isic_pnp.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1998 Eivind Eklund. All rights reserved.
+ *
+ * Copyright (c) 1998, 1999 German Tischler. All rights reserved.
+ *
+ * Copyright (c) 1998, 2000 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.2 2000/03/09 16:12:51 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Thu Mar 9 16:04:10 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <i4b/include/i4b_global.h>
+#include <machine/i4b_ioctl.h>
+#include <i4b/layer1/isic/i4b_isic.h>
+
+#include <isa/isavar.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*/
+#define VID_ITK0025 0x25008b26 /* ITK Ix1 Micro V3 */
+#define VID_AVMPNP 0x0009cd06 /* AVM Fritz! PnP */
+#define VID_SIESURF2 0x2000254d /* Siemens I-Surf 2.0 PnP*/
+#define VID_ASUSCOM_IPAC 0x90167506 /* Asuscom (with IPAC) */
+
+static struct isic_pnp_ids {
+ u_long vend_id;
+ char *id_str;
+} isic_pnp_ids[] = {
+#if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P)
+ { VID_TEL163PNP, "Teles S0/16.3 PnP" },
+ { VID_CREATIXPP, "Creatix S0/16 PnP" },
+#endif
+#ifdef DYNALINK
+ { VID_DYNALINK, "Dynalink IS64PH" },
+#endif
+#ifdef SEDLBAUER
+ { VID_SEDLBAUER, "Sedlbauer WinSpeed" },
+#endif
+#ifdef DRN_NGO
+ { VID_NICCYGO, "Dr.Neuhaus Niccy Go@" },
+#endif
+#ifdef ELSA_QS1ISA
+ { VID_ELSAQS1P, "ELSA QuickStep 1000pro" },
+#endif
+#ifdef ITKIX1
+ { VID_ITK0025, "ITK ix1 Micro V3.0" },
+#endif
+#ifdef AVM_PNP
+ { VID_AVMPNP, "AVM Fritz!Card PnP" },
+#endif
+#ifdef SIEMENS_ISURF2
+ { VID_SIESURF2, "Siemens I-Surf 2.0 PnP" },
+#endif
+#ifdef ASUSCOM_IPAC
+ { VID_ASUSCOM_IPAC, "Asuscom ISDNLink 128 PnP" },
+#endif
+ { 0, 0 }
+};
+
+static int isic_pnp_probe(device_t dev);
+static int isic_pnp_attach(device_t dev);
+
+static device_method_t isic_pnp_methods[] = {
+ DEVMETHOD(device_probe, isic_pnp_probe),
+ DEVMETHOD(device_attach, isic_pnp_attach),
+ { 0, 0 }
+};
+
+static driver_t isic_pnp_driver = {
+ "isic",
+ isic_pnp_methods,
+ 0,
+};
+
+static devclass_t isic_devclass;
+
+DRIVER_MODULE(isicpnp, isa, isic_pnp_driver, isic_devclass, 0, 0);
+
+/*---------------------------------------------------------------------------*
+ * probe for ISA PnP cards
+ *---------------------------------------------------------------------------*/
+int
+isic_pnp_probe(device_t dev)
+{
+ struct isic_pnp_ids *ids; /* pnp id's */
+ char *string = NULL; /* the name */
+ u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */
+
+ /* search table of knowd id's */
+
+ for(ids = isic_pnp_ids; ids->vend_id != 0; ids++)
+ {
+ if(vend_id == ids->vend_id)
+ {
+ string = ids->id_str;
+ break;
+ }
+ }
+
+ if(string) /* set name if we have one */
+ {
+ device_set_desc(dev, string); /* set description */
+ return 0;
+ }
+ else
+ {
+ return ENXIO;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * attach for ISA PnP cards
+ *---------------------------------------------------------------------------*/
+int
+isic_pnp_attach(device_t dev)
+{
+ u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */
+ unsigned int unit = device_get_unit(dev); /* get unit */
+ const char *name = device_get_desc(dev); /* get description */
+ struct l1_softc *sc = 0; /* softc */
+ void *ih = 0; /* a dummy */
+ int ret;
+
+ /* see if we are out of bounds */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", unit, unit, name);
+ return ENXIO;
+ }
+
+ /* get information structure for this unit */
+
+ sc = &l1_sc[unit];
+
+ /* get io_base */
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0UL, ~0UL, 1, RF_ACTIVE ) ))
+ {
+ printf("isic_pnp_attach: Couldn't get my io_base.\n");
+ return ENXIO;
+ }
+
+ /* will not be used for pnp devices */
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+
+ /* get irq, release io_base if we don't get it */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get irq.\n",unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* not needed */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+
+ /* set flag so we know what this card is */
+
+ ret = ENXIO;
+
+ switch(vend_id)
+ {
+#if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P)
+ case VID_TEL163PNP:
+ sc->sc_flags = FLAG_TELES_S0_163_PnP;
+ ret = isic_attach_Cs0P(dev);
+ break;
+
+ case VID_CREATIXPP:
+ sc->sc_flags = FLAG_CREATIX_S0_PnP;
+ ret = isic_attach_Cs0P(dev);
+ break;
+#endif
+#ifdef DYNALINK
+ case VID_DYNALINK:
+ sc->sc_flags = FLAG_DYNALINK;
+ ret = isic_attach_Dyn(dev);
+ break;
+#endif
+#ifdef SEDLBAUER
+ case VID_SEDLBAUER:
+ sc->sc_flags = FLAG_SWS;
+ ret = isic_attach_sws(dev);
+ break;
+#endif
+#ifdef DRN_NGO
+ case VID_NICCYGO:
+ sc->sc_flags = FLAG_DRN_NGO;
+ ret = isic_attach_drnngo(dev);
+ break;
+#endif
+#ifdef ELSA_QS1ISA
+ case VID_ELSAQS1P:
+ sc->sc_flags = FLAG_ELSA_QS1P_ISA;
+ ret = isic_attach_Eqs1pi(dev);
+ break;
+#endif
+#ifdef ITKIX1
+ case VID_ITK0025:
+ sc->sc_flags = FLAG_ITK_IX1;
+ ret = isic_attach_itkix1(dev);
+ break;
+#endif
+#ifdef AVM_PNP
+ case VID_AVMPNP:
+ sc->sc_flags = FLAG_AVM_PNP;
+ ret = isic_attach_avm_pnp(dev);
+ break;
+#endif
+#ifdef SIEMENS_ISURF2
+ case VID_SIESURF2:
+ sc->sc_flags = FLAG_SIEMENS_ISURF2;
+ ret = isic_attach_siemens_isurf(dev);
+ break;
+#endif
+#ifdef ASUSCOM_IPAC
+ case VID_ASUSCOM_IPAC:
+ sc->sc_flags = FLAG_ASUSCOM_IPAC;
+ ret = isic_attach_asi(dev);
+ break;
+#endif
+ default:
+ printf("isic%d: Error, no driver for %s\n", unit, name);
+ ret = ENXIO;
+ break;
+ }
+
+ if(ret)
+ {
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ if(isic_attach_common(dev))
+ {
+ /* unset flag */
+ sc->sc_flags = 0;
+
+ /* free irq here, it hasn't been attached yet */
+ bus_release_resource(dev,SYS_RES_IRQ,sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ sc->sc_resources.irq = 0;
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+ else
+ {
+ /* setup intr routine */
+ bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET,
+ (void(*)(void*))isicintr,
+ sc,&ih);
+ return 0;
+ }
+}
+#endif /* (NISIC > 0) */
diff --git a/sys/i4b/layer1/isic/i4b_itk_ix1.c b/sys/i4b/layer1/isic/i4b_itk_ix1.c
new file mode 100644
index 0000000..9bf94c5
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_itk_ix1.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 1998, 1999 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 2000/08/24 14:08:41 hm Exp $
+ *
+ * last edit-date: [Thu Aug 24 15:44:33 2000]
+ *
+ * $FreeBSD$
+ *
+ *---------------------------------------------------------------------------
+ *
+ * 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).
+ *
+ * The probe routine was derived by trial and error from a representative
+ * sample of two cards ;-) The standard way (checking HSCX versions)
+ * was extended by reading a zero from a non existant HSCX register (register
+ * 0xff). Reading the config register gives varying results, so this doesn't
+ * seem to be used as an id register (like the Teles S0/16.3).
+ *
+ * If the probe fails for your card use "options ITK_PROBE_DEBUG" to get
+ * additional debug output.
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(ITKIX1)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+/* Register offsets */
+#define ITK_ISAC_DATA 0
+#define ITK_HSCX_DATA 1
+#define ITK_ALE 2
+#define ITK_CONFIG 3
+
+/* Size of IO range to allocate for this card */
+#define ITK_IO_SIZE 4
+
+/* Register offsets for the two HSCX channels */
+#define HSCXA 0
+#define HSCXB 0x40
+
+static void
+itkix1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ 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;
+ }
+}
+
+static void
+itkix1_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ 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;
+ }
+}
+
+static void
+itkix1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ 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;
+ }
+}
+
+static u_int8_t
+itkix1_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+ 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;
+}
+
+/*
+ * Probe for card
+ */
+int
+isic_probe_itkix1(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* softc */
+ void *ih = 0; /* dummy */
+ bus_space_tag_t t; /* bus things */
+ bus_space_handle_t h;
+ u_int8_t hd, hv1, hv2, saveale;
+ int ret;
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("Checking unit %u\n", unit);
+ #endif
+
+ /* check max unit range */
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ITK IX1!\n",
+ unit, unit);
+ return ENXIO;
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+ sc->sc_unit = unit; /* set unit */
+ sc->sc_flags = FLAG_ITK_IX1; /* set flags */
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("Allocating io base...");
+ #endif
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate i/o port for ITK IX1.\n", unit);
+ return ENXIO;
+ }
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+ #endif
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+ t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("Allocating irq...");
+ #endif
+
+ /* get our irq */
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate irq for ITK IX1.\n", unit);
+ bus_release_resource(dev,SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ return ENXIO;
+ }
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+ #endif
+
+ /* get the irq number */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("Setting up access routines...");
+ #endif
+
+ /* 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;
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+ #endif
+
+ /* register interupt routine */
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("Setting up access interupt...");
+ #endif
+
+ bus_setup_intr(dev, sc->sc_resources.irq,
+ INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+
+ printf("Doing probe stuff...");
+ #endif
+
+ /* save old value of this port, we're stomping over it */
+ saveale = bus_space_read_1(t, h, ITK_ALE);
+
+ /* select invalid register */
+ bus_space_write_1(t, h, ITK_ALE, 0xff);
+ /* get HSCX data for this non existent register */
+ hd = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ /* get HSCX version info */
+ bus_space_write_1(t, h, ITK_ALE, HSCXA + H_VSTR);
+ hv1 = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ bus_space_write_1(t, h, ITK_ALE, HSCXB + H_VSTR);
+ hv2 = bus_space_read_1(t, h, ITK_HSCX_DATA);
+
+ ret = (hd == 0) && ((hv1 & 0x0f) == 0x05) && ((hv2 & 0x0f) == 0x05);
+ /* succeed if version bits are OK and we got a zero from the
+ * non existent register. we found verison 0x05 and 0x04
+ * out there... */
+ ret = (hd == 0)
+ && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04))
+ && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04));
+
+ /* retstore save value if we fail (if we succeed the old value
+ * has no meaning) */
+ if (!ret)
+ bus_space_write_1(t, h, ITK_ALE, saveale);
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+
+ printf("Doing second probe stuff...");
+ #endif
+
+ hv1 = HSCX_READ(0, H_VSTR) & 0xf;
+ hv2 = HSCX_READ(1, H_VSTR) & 0xf;
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
+ if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
+ {
+ printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
+ unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ unit, HSCX_READ(1, H_VSTR));
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ #if defined(ITK_PROBE_DEBUG)
+ printf("done.\n");
+ #endif
+
+#if defined(ITK_PROBE_DEBUG)
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n",
+ hd, hv1, hv2, ret ? "succeeded" : "failed");
+ isic_detach_common(dev);
+ return ENXIO;
+#else
+ if ( ret )
+ {
+ return 0;
+ }
+ else
+ {
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+#endif
+}
+
+/*
+ * Attach card
+ */
+int
+isic_attach_itkix1(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* 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;
+
+ bus_space_write_1(t, h, ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+
+ return 0;
+}
+
+#endif /* ITKIX1 */
diff --git a/sys/i4b/layer1/isic/i4b_l1.c b/sys/i4b/layer1/isic/i4b_l1.c
new file mode 100644
index 0000000..f19eda8
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_l1.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1997, 2000 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.7 2000/06/02 16:14:36 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 18:09:53 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/stdarg.h>
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ *
+ * 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
+ *
+ *---------------------------------------------------------------------------*/
+int
+isic_ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+ struct l1_softc *sc = &l1_sc[unit];
+
+#ifdef NOTDEF
+ NDBGL1(L1_PRIM, "unit %d, freeflag=%d", unit, freeflag);
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ NDBGL1(L1_I_ERR, "still in state F3!");
+ isic_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 */
+
+ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0ISICUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", 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 = L0ISICUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");
+
+ 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
+ *
+ *---------------------------------------------------------------------------*/
+int
+isic_ph_activate_req(int unit)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+ NDBGL1(L1_PRIM, "unit %d", unit);
+ isic_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+int
+isic_mph_command_req(int unit, int command, void *parm)
+{
+ struct l1_softc *sc = &l1_sc[unit];
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DOPEN", unit);
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DCLOSE", unit);
+ sc->sc_enabled = 0;
+ break;
+
+ case CMR_SETTRACE:
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_SETTRACE, parm = %d", unit, (unsigned int)parm);
+ sc->sc_trace = (unsigned int)parm;
+ break;
+
+ case CMR_GCST:
+ {
+ struct chipstat *cst;
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_GCST, parm = %d", unit, (unsigned int)parm);
+ cst = (struct chipstat *)parm;
+ cst->driver_type = L1DRVR_ISIC;
+ cst->stats.hscxstat.unit = sc->sc_unit;
+ cst->stats.hscxstat.chan = cst->driver_bchannel;
+ cst->stats.hscxstat.vfr = sc->sc_chan[cst->driver_bchannel].stat_VFR;
+ cst->stats.hscxstat.rdo = sc->sc_chan[cst->driver_bchannel].stat_RDO;
+ cst->stats.hscxstat.crc = sc->sc_chan[cst->driver_bchannel].stat_CRC;
+ cst->stats.hscxstat.rab = sc->sc_chan[cst->driver_bchannel].stat_RAB;
+ cst->stats.hscxstat.xdu = sc->sc_chan[cst->driver_bchannel].stat_XDU;
+ cst->stats.hscxstat.rfo = sc->sc_chan[cst->driver_bchannel].stat_RFO;
+ break;
+ }
+ default:
+ NDBGL1(L1_ERROR, "ERROR, unknown command = %d, unit = %d, parm = %d", command, unit, (unsigned int)parm);
+ break;
+ }
+
+ return(0);
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_l1fsm.c b/sys/i4b/layer1/isic/i4b_l1fsm.c
new file mode 100644
index 0000000..d3ce147
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_l1fsm.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 1997, 2000 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.8 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:46:03 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/stdarg.h>
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/include/i4b_mbuf.h>
+
+#if DO_I4B_DEBUG
+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"
+};
+#endif
+
+/* Function prototypes */
+
+static void timer3_expired (struct l1_softc *sc);
+static void T3_start (struct l1_softc *sc);
+static void T3_stop (struct l1_softc *sc);
+static void F_T3ex (struct l1_softc *sc);
+static void timer4_expired (struct l1_softc *sc);
+static void T4_start (struct l1_softc *sc);
+static void T4_stop (struct l1_softc *sc);
+static void F_AI8 (struct l1_softc *sc);
+static void F_AI10 (struct l1_softc *sc);
+static void F_I01 (struct l1_softc *sc);
+static void F_I02 (struct l1_softc *sc);
+static void F_I03 (struct l1_softc *sc);
+static void F_I2 (struct l1_softc *sc);
+static void F_ill (struct l1_softc *sc);
+static void F_NULL (struct l1_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ NDBGL1(L1_T_ERR, "state = %s", 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);
+
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL);
+ }
+
+ isic_next_state(sc, EV_T3);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T3 = 1;
+ sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, 2*hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, sc->sc_T3_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T4 = 0;
+ i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_PDEACT, 0, NULL);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+ sc->sc_I430T4 = 1;
+ sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, sc->sc_T4_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit));
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+ isic_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = L0ISICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_ERR, "FSM function F_ill executing");
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct isic_state_tab {
+ void (*func) (struct l1_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 l1_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");
+
+ NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
+ state_text[currstate],
+ state_text[newstate]);
+
+ (*isic_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]);
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+#if DO_I4B_DEBUG
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+isic_printstate(struct l1_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+#endif
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/isic/i4b_siemens_isurf.c b/sys/i4b/layer1/isic/i4b_siemens_isurf.c
new file mode 100644
index 0000000..52a70ec
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_siemens_isurf.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1999, 2000 Udo Schweigert. 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.
+ *
+ *---------------------------------------------------------------------------
+ * Based on ELSA Quickstep 1000pro PCI driver (i4b_elsa_qs1p.c)
+ *---------------------------------------------------------------------------
+ * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de>
+ *---------------------------------------------------------------------------
+ *
+ * Siemens I-Surf 2.0 PnP specific routines for isic driver
+ * --------------------------------------------------------
+ *
+ * $Id: i4b_siemens_isurf.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:46:31 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(SIEMENS_ISURF2)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_ipac.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+/* masks for register encoded in base addr */
+
+#define SIE_ISURF_BASE_MASK 0x0ffff
+#define SIE_ISURF_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define SIE_ISURF_IDISAC 0x00000
+#define SIE_ISURF_IDHSCXA 0x10000
+#define SIE_ISURF_IDHSCXB 0x20000
+#define SIE_ISURF_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define SIE_ISURF_OFF_ALE 0x00
+#define SIE_ISURF_OFF_RW 0x01
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+siemens_isurf_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+siemens_isurf_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+siemens_isurf_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_ISAC_OFF);
+ bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXA_OFF);
+ bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXB_OFF);
+ bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_IPAC_OFF);
+ bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data);
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Siemens I-Surf 2.0 PnP ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+siemens_isurf_read_reg(struct l1_softc *sc,int what,bus_size_t reg)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what )
+ {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_ISAC_OFF);
+ return bus_space_read_1(t,h,SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXA_OFF);
+ return bus_space_read_1(t,h,SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXB_OFF);
+ return bus_space_read_1(t,h,SIE_ISURF_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_IPAC_OFF);
+ return bus_space_read_1(t,h,SIE_ISURF_OFF_RW);
+ default:
+ return 0;
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_siemens_isurf(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = siemens_isurf_read_reg;
+ sc->writereg = siemens_isurf_write_reg;
+
+ sc->readfifo = siemens_isurf_read_fifo;
+ sc->writefifo = siemens_isurf_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2;
+
+ /* 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 */
+
+ return(0);
+}
+#endif /* NISIC > 0 && defined(SIEMENS_ISURF2) */
diff --git a/sys/i4b/layer1/isic/i4b_sws.c b/sys/i4b/layer1/isic/i4b_sws.c
new file mode 100644
index 0000000..4815001
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_sws.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1998, 2000 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
+ * ====================================================
+ *
+ * $Id: i4b_sws.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:46:49 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#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 */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+sws_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) {
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what ) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SWS_RW,0x0);
+ bus_space_read_multi_1(t,h,SWS_ISAC,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SWS_RW,0x0);
+ bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SWS_RW,0x0+0x40);
+ bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size);
+ break;
+ }
+}
+
+static void
+sws_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) {
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what ) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SWS_RW,0x0);
+ bus_space_write_multi_1(t,h,SWS_ISAC,buf,size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SWS_RW,0x0);
+ bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SWS_RW,0x0+0x40);
+ bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size);
+ break;
+ }
+}
+
+static void
+sws_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) {
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what ) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SWS_RW,reg);
+ bus_space_write_1(t,h,SWS_ISAC,data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SWS_RW,reg);
+ bus_space_write_1(t,h,SWS_HSCX0,data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SWS_RW,reg+0x40);
+ bus_space_write_1(t,h,SWS_HSCX0,data);
+ break;
+ }
+}
+
+static u_char
+sws_read_reg (struct l1_softc *sc,int what,bus_size_t reg) {
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ switch ( what ) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t,h,SWS_RW,reg);
+ return bus_space_read_1(t,h,SWS_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t,h,SWS_RW,reg);
+ return bus_space_read_1(t,h,SWS_HSCX0);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t,h,SWS_RW,reg+0x40);
+ return bus_space_read_1(t,h,SWS_HSCX0);
+ default:
+ return 0;
+ }
+}
+
+/* attach callback routine */
+int
+isic_attach_sws(device_t dev)
+{
+ int unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+
+ struct i4b_info * info = &(sc->sc_resources);
+ bus_space_tag_t t = rman_get_bustag(info->io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(info->io_base[0]);
+
+ /* fill in l1_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_cardtyp = CARD_TYPEP_SWS;
+ 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("isic%d: HSCX VSTR test failed for SWS PnP\n",
+ sc->sc_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ sc->sc_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ sc->sc_unit, HSCX_READ(1, H_VSTR));
+ return (ENXIO);
+ }
+
+ /* reset card */
+ bus_space_write_1(t,h,SWS_RESON,0x3);
+ DELAY(SEC_DELAY / 5);
+ bus_space_write_1(t,h,SWS_RESOFF,0x0);
+ DELAY(SEC_DELAY / 5);
+
+ return(0);
+}
+#endif /* defined(SEDLBAUER) && NISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_tel_s016.c b/sys/i4b/layer1/isic/i4b_tel_s016.c
new file mode 100644
index 0000000..8f4cebb
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_tel_s016.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:46:56 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(TEL_S0_16)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+#include <machine/md_var.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#define TELES_S016_MEMSIZE 0x1000
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 write register routine
+ *---------------------------------------------------------------------------*/
+static void
+tels016_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 read register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+tels016_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+
+ offs += offset[what];
+
+ if(offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 fifo write routine
+ *---------------------------------------------------------------------------*/
+static void
+tels016_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 fifo read routine
+ *---------------------------------------------------------------------------*/
+static void
+tels016_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s016 - probe for Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_s016(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* softc */
+ void *ih = 0; /* dummy */
+ u_int8_t b0,b1,b2; /* for signature */
+ bus_space_tag_t t; /* bus things */
+ bus_space_handle_t h;
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+
+ sc->sc_unit = unit; /* set unit */
+
+ sc->sc_flags = FLAG_TELES_S0_16; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate i/o port for Teles S0/16.\n", unit);
+ return(ENXIO);
+ }
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+
+ /*
+ * check if the provided io port is valid
+ */
+
+ switch(sc->sc_port)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n",
+ unit, sc->sc_port);
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* allocate memory resource */
+
+ if(!(sc->sc_resources.mem =
+ bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &sc->sc_resources.mem_rid,
+ 0ul, ~0ul, TELES_S016_MEMSIZE,
+ RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate memory for Teles S0/16.\n", unit);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ /*
+ * get virtual addr.
+ */
+ sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem);
+
+ /*
+ * check for valid adresses
+ */
+ switch(kvtop(sc->sc_vmem_addr))
+ {
+ 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 memory address 0x%lx for Teles S0/16!\n",
+ unit, kvtop(sc->sc_vmem_addr));
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* setup ISAC 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;
+
+ /* setup ISAC base addr, though we don't really need it */
+
+ ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180);
+ HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0);
+
+ t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* get signature bytes */
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ /* check signature bytes */
+ if(b0 != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n",
+ unit, b0);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ if(b1 != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n",
+ unit, b1);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ if((b2 != 0x1e) && (b2 != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n",
+ unit, b2);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ /* get our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate irq for Teles S0/16.\n", unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* register interupt routine */
+
+ bus_setup_intr(dev, sc->sc_resources.irq,
+ INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ /* get the irq number */
+
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* check IRQ validity */
+
+ if((intr_no[sc->sc_irq]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ unit, sc->sc_irq);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s016 - attach Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_s016(device_t dev)
+{
+ struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
+ u_long irq;
+
+ bus_space_tag_t ta = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t ha = rman_get_bushandle(sc->sc_resources.mem);
+ bus_space_tag_t tb = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t hb = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* is this right for FreeBSD or off by one ? */
+ irq = intr_no[sc->sc_irq];
+
+ /* configure IRQ */
+
+ irq |= ((u_long) sc->sc_vmem_addr) >> 9;
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(tb, hb, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(tb, hb, 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ bus_space_write_1(ta, ha, 0x80, 0);
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ bus_space_write_1(ta, ha, 0x80, 1);
+ DELAY(SEC_DELAY / 5);
+
+ return 0;
+}
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_tel_s0163.c b/sys/i4b/layer1/isic/i4b_tel_s0163.c
new file mode 100644
index 0000000..fa31cd9
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_tel_s0163.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 2000 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.4 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:47:08 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(TEL_S0_16_3)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/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 };
+
+#define ISAC_OFFS 0x400
+#define HSCXA_OFFS 0xc00
+#define HSCXB_OFFS 0x800
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+tels0163_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ bus_space_read_multi_1(t,h,0x1e,buf,size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+tels0163_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ bus_space_write_multi_1(t,h,0x1e,buf,size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC put register routine
+ *---------------------------------------------------------------------------*/
+static void
+tels0163_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ bus_space_write_1(t,h,offs - 0x20,data);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC get register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+tels0163_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]);
+ return bus_space_read_1(t,h,offs - 0x20);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163 - probe routine for Teles S0/16.3
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_s0163(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+ void *ih = 0; /* dummy */
+ bus_space_tag_t t; /* bus things */
+ bus_space_handle_t h;
+ u_int8_t b0,b1,b2; /* signature */
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles 16.3!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+ sc->sc_unit = unit; /* set unit */
+ sc->sc_flags = FLAG_TELES_S0_163; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get iobase for Teles S0/16.3.\n",
+ unit);
+ return(ENXIO);
+ }
+
+ /* set io base */
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+ /* Release the resource - re-allocate later with correct size */
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+
+ switch(sc->sc_port)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ case 0x180:
+ case 0x280:
+ case 0x380:
+ printf("isic%d: Error, instead of using iobase 0x%x for your Teles S0/16.3,\n",
+ unit, sc->sc_port);
+ printf("isic%d: please use 0x%x in the kernel configuration file!\n",
+ unit, sc->sc_port+0xc00);
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
+ unit, sc->sc_port);
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* set io port resources */
+
+ sc->sc_resources.io_rid[0] = 0;
+ bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port, 0x20);
+ sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if(!sc->sc_resources.io_base[0])
+ {
+ printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
+ unit, sc->sc_port);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+ sc->sc_resources.io_rid[1] = 1;
+ bus_set_resource(dev, SYS_RES_IOPORT, 1,
+ sc->sc_port-ISAC_OFFS, 0x20);
+ sc->sc_resources.io_base[1] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[1],
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if(!sc->sc_resources.io_base[1])
+ {
+ printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
+ unit, sc->sc_port-ISAC_OFFS);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ sc->sc_resources.io_rid[2] = 2;
+ bus_set_resource(dev, SYS_RES_IOPORT, 2,
+ sc->sc_port-HSCXA_OFFS, 0x20);
+ sc->sc_resources.io_base[2] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[2],
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if(!sc->sc_resources.io_base[2])
+ {
+ printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
+ unit, sc->sc_port-HSCXA_OFFS);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ sc->sc_resources.io_rid[3] = 3;
+ bus_set_resource(dev, SYS_RES_IOPORT, 3,
+ sc->sc_port-HSCXB_OFFS, 0x20);
+ sc->sc_resources.io_base[3] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[3],
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if(!sc->sc_resources.io_base[3])
+ {
+ printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
+ unit, sc->sc_port-HSCXB_OFFS);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* 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;
+
+ t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ 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 && b0 != 0x10 ) {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n",
+ unit, b0);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ if ( b1 != 0x93 ) {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
+ unit, b1);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+ if (( b2 != 0x1c ) && ( b2 != 0x1f )) {
+ printf("isic%d: Error, signature 3 0x%x != (0x1c || 0x1f) for Teles S0/16.3!\n",
+ unit, b2);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /*
+ * 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",
+ unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ unit, HSCX_READ(1, H_VSTR));
+ isic_detach_common(dev);
+ return (ENXIO);
+ }
+
+ /* get our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get IRQ for Teles S0/16.3.\n",unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* get the irq number */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ switch(sc->sc_irq)
+ {
+ case 2:
+ case 9:
+ case 5:
+ case 10:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ unit, sc->sc_irq);
+ isic_detach_common(dev);
+ return(ENXIO);
+ break;
+ }
+
+ /* register interupt routine */
+ bus_setup_intr(dev, sc->sc_resources.irq,
+ INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163 - attach Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_s0163(device_t dev)
+{
+ unsigned int unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = &l1_sc[unit];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, intr_no[sc->sc_irq]);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, intr_no[sc->sc_irq] | 0x01);
+
+ return (0);
+}
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/isic/i4b_tel_s08.c b/sys/i4b/layer1/isic/i4b_tel_s08.c
new file mode 100644
index 0000000..c6578b1
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_tel_s08.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:47:20 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if NISIC > 0 && defined(TEL_S0_8)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <machine/clock.h>
+#include <machine/md_var.h>
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+/* #include <i4b/include/i4b_l1l2.h> */
+#include <i4b/include/i4b_mbuf.h>
+
+#define TELES_S08_MEMSIZE 0x1000
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 write register routine
+ *---------------------------------------------------------------------------*/
+static void
+tels08_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 read register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+tels08_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 fifo write access
+ *---------------------------------------------------------------------------*/
+static void
+tels08_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 fifo read access
+ *---------------------------------------------------------------------------*/
+static void
+tels08_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s08 - probe for Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_s08(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+ void *ih = 0; /* dummy */
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+
+ sc->sc_unit = unit; /* set unit */
+
+ sc->sc_flags = FLAG_TELES_S0_8; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if((sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ /* the S0/8 is completely memory mapped ! */
+
+ bus_release_resource(dev,SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ printf("isic%d: Error, iobase specified for Teles S0/8!\n", unit);
+ return(ENXIO);
+ }
+
+ /* allocate memory */
+
+ if(!(sc->sc_resources.mem =
+ bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &sc->sc_resources.mem_rid,
+ 0ul, ~0ul, TELES_S08_MEMSIZE, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate memory for Teles S0/8!\n", unit);
+ return(ENXIO);
+ }
+
+ /*
+ * get virtual addr. it's just needed to see if it is in
+ * the valid range
+ */
+
+ sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem);
+
+ /* check if inside memory range of 0xA0000 .. 0xDF000 */
+
+ if((kvtop(sc->sc_vmem_addr) < 0xa0000) ||
+ (kvtop(sc->sc_vmem_addr) > 0xdf000))
+ {
+ printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n",
+ unit, kvtop(sc->sc_vmem_addr));
+ bus_release_resource(dev,SYS_RES_MEMORY,
+ sc->sc_resources.mem_rid,
+ sc->sc_resources.mem);
+ sc->sc_resources.mem = 0;
+ return(ENXIO);
+ }
+
+ /* 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;
+
+ sc->sc_cardtyp = CARD_TYPEP_8; /* setup card type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1; /* setup IOM bus type */
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr, though we don't really need it */
+
+ ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180);
+ HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0);
+
+ /* allocate our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not allocate irq for Teles S0/8!\n",unit);
+
+ bus_release_resource(dev,SYS_RES_MEMORY,
+ sc->sc_resources.mem_rid,
+ sc->sc_resources.mem);
+
+ sc->sc_resources.mem = 0;
+ return ENXIO;
+ }
+
+ /* get the irq number */
+
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* check IRQ validity */
+
+ switch(sc->sc_irq)
+ {
+ 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",
+ unit, sc->sc_irq);
+ bus_release_resource(dev,SYS_RES_IRQ,
+ sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ sc->sc_resources.irq = 0;
+ bus_release_resource(dev,SYS_RES_MEMORY,
+ sc->sc_resources.mem_rid,
+ sc->sc_resources.mem);
+ sc->sc_resources.mem = 0;
+ return(ENXIO);
+ break;
+ }
+
+ /* register interupt routine */
+
+ bus_setup_intr(dev, sc->sc_resources.irq,
+ INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s08 - attach Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_s08(device_t dev)
+{
+ struct l1_softc *sc = &l1_sc[device_get_unit(dev)];
+ bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem);
+ bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem);
+
+ /* set card off */
+
+ bus_space_write_1(t, h, 0x80, 0);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card on */
+
+ bus_space_write_1(t, h, 0x80, 1);
+
+ DELAY(SEC_DELAY / 5);
+
+ return 0;
+}
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/isic/i4b_usr_sti.c b/sys/i4b/layer1/isic/i4b_usr_sti.c
new file mode 100644
index 0000000..0bf8430
--- /dev/null
+++ b/sys/i4b/layer1/isic/i4b_usr_sti.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 1997, 2000 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.3 2000/05/29 15:41:42 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:47:26 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#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>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.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/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/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))
+
+#ifdef USRTA_DEBUG_PORTACCESS
+int debugcntr;
+#define USRTA_DEBUG(fmt) \
+ if (++debugcntr < 1000) printf fmt;
+#else
+#define USRTA_DEBUG(fmt)
+#endif
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
+{
+ register int offset = 0;
+ register unsigned int base = 0;
+
+USRTA_DEBUG(("usrtai_read_fifo: what %d size %d\n", what, size))
+ switch (what)
+ {
+ case ISIC_WHAT_ISAC:
+ base = (unsigned int)ISAC_BASE;
+ break;
+ case ISIC_WHAT_HSCXA:
+ base = (unsigned int)HSCX_A_BASE;
+ break;
+ case ISIC_WHAT_HSCXB:
+ base = (unsigned int)HSCX_B_BASE;
+ break;
+ default:
+ printf("usrtai_read_fifo: invalid what %d\n", what);
+ return;
+ }
+
+ for(;size > 0; size--, offset++)
+ {
+ *((u_char *)buf + offset) = inb(base + ADDR(offset));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(struct l1_softc *sc, int what, void *data, size_t size)
+{
+ register int offset = 0;
+ register unsigned int base = 0;
+
+USRTA_DEBUG(("usrtai_write_fifo: what %d size %d\n", what, size))
+ switch (what)
+ {
+ case ISIC_WHAT_ISAC:
+ base = (unsigned int)ISAC_BASE;
+ break;
+ case ISIC_WHAT_HSCXA:
+ base = (unsigned int)HSCX_A_BASE;
+ break;
+ case ISIC_WHAT_HSCXB:
+ base = (unsigned int)HSCX_B_BASE;
+ break;
+ default:
+ printf("usrtai_write_fifo: invalid what %d\n", what);
+ return;
+ }
+
+
+ for(;size > 0; size--, offset++)
+ {
+ outb(base + ADDR(offset), *((u_char *)data + offset));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ register unsigned int base = 0;
+
+USRTA_DEBUG(("usrtai_write_reg: what %d ADDR(%d) %d data %#x\n", what, offs, ADDR(offs), data))
+ switch (what)
+ {
+ case ISIC_WHAT_ISAC:
+ base = (unsigned int)ISAC_BASE;
+ break;
+ case ISIC_WHAT_HSCXA:
+ base = (unsigned int)HSCX_A_BASE;
+ break;
+ case ISIC_WHAT_HSCXB:
+ base = (unsigned int)HSCX_B_BASE;
+ break;
+ default:
+ printf("usrtai_write_reg invalid what %d\n", what);
+ return;
+ }
+
+ outb(base + ADDR(offs), (u_char)data);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_int8_t
+usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
+{
+ register unsigned int base = 0;
+ u_int8_t byte;
+
+USRTA_DEBUG(("usrtai_read_reg: what %d ADDR(%d) %d..", what, offs, ADDR(offs)))
+ switch (what)
+ {
+ case ISIC_WHAT_ISAC:
+ base = (unsigned int)ISAC_BASE;
+ break;
+ case ISIC_WHAT_HSCXA:
+ base = (unsigned int)HSCX_A_BASE;
+ break;
+ case ISIC_WHAT_HSCXB:
+ base = (unsigned int)HSCX_B_BASE;
+ break;
+ default:
+ printf("usrtai_read_reg: invalid what %d\n", what);
+ return(0);
+ }
+
+ byte = inb(base + ADDR(offs));
+USRTA_DEBUG(("usrtai_read_reg: got %#x\n", byte))
+ return(byte);
+}
+
+/*---------------------------------------------------------------------------*
+ * allocate an io port - based on code in isa_isic.c
+ *---------------------------------------------------------------------------*/
+static int
+usrtai_alloc_port(device_t dev)
+{
+ size_t unit = device_get_unit(dev);
+ struct l1_softc *sc = &l1_sc[unit];
+ int i, num = 0;
+ bus_size_t base;
+
+ /* 49 io mappings: 1 config and 48x8 registers */
+
+ /* config at offset 0x8000 */
+ base = sc->sc_port + 0x8000;
+ if (base < 0 || base > 0x0ffff)
+ return 1;
+ sc->sc_resources.io_rid[num] = num;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, num, base, 1);
+
+ if(!(sc->sc_resources.io_base[num] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[num],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Error, failed to reserve io #%dport %#x!\n", unit, num, base);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+ num++;
+
+ /* HSCX A at offset 0 */
+ base = sc->sc_port;
+ for (i = 0; i < 16; i++) {
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ sc->sc_resources.io_rid[num] = num;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
+
+ if(!(sc->sc_resources.io_base[num] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[num],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+ ++num;
+ }
+
+ /* HSCX B at offset 0x4000 */
+ base = sc->sc_port + 0x4000;
+ for (i = 0; i < 16; i++) {
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ sc->sc_resources.io_rid[num] = num;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
+
+ if(!(sc->sc_resources.io_base[num] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[num],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+ ++num;
+ }
+
+ /* ISAC at offset 0xc000 */
+ base = sc->sc_port + 0xc000;
+ for (i = 0; i < 16; i++) {
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ sc->sc_resources.io_rid[num] = num;
+
+ bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8);
+
+ if(!(sc->sc_resources.io_base[num] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[num],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+ ++num;
+ }
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(device_t dev)
+{
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+ void *ih = 0; /* dummy */
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n",
+ unit, unit);
+ return(ENXIO);
+ }
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+ sc->sc_unit = unit; /* set unit */
+ sc->sc_flags = FLAG_USR_ISDN_TA_INT; /* set flags */
+
+ /* see if an io base was supplied */
+
+ if(!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get iobase for USR Sportster TA!\n",
+ unit);
+ return(ENXIO);
+ }
+
+ /* set io base */
+
+ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
+
+ /* release io base */
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+
+
+ /* check if we got an iobase */
+
+ switch(sc->sc_port)
+ {
+ 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",
+ unit, sc->sc_port);
+ return(0);
+ break;
+ }
+
+ /* allocate all the ports needed */
+
+ if(usrtai_alloc_port(dev))
+ {
+ printf("isic%d: Could not get the ports for USR Sportster TA!\n", unit);
+ isic_detach_common(dev);
+ return(ENXIO);
+ }
+
+ /* get our irq */
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0ul, ~0ul, 1, RF_ACTIVE)))
+ {
+ printf("isic%d: Could not get an irq for USR Sportster TA!\n",unit);
+ isic_detach_common(dev);
+ return ENXIO;
+ }
+
+ /* get the irq number */
+ sc->sc_irq = rman_get_start(sc->sc_resources.irq);
+
+ /* register interrupt routine */
+ bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void *))(isicintr),
+ sc, &ih);
+
+ /* check IRQ validity */
+
+ if(intr_no[sc->sc_irq] == 0)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ unit, sc->sc_irq);
+ return(1);
+ }
+
+ /* 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)sc->sc_port + USR_ISAC_OFF;
+ HSCX_A_BASE = (caddr_t)sc->sc_port + USR_HSCXA_OFF;
+ HSCX_B_BASE = (caddr_t)sc->sc_port + 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",
+ unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ unit, HSCX_READ(1, H_VSTR));
+ return (1);
+ }
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(device_t dev)
+{
+ u_char irq = 0;
+ size_t unit = device_get_unit(dev); /* get unit */
+ struct l1_softc *sc = 0; /* pointer to softc */
+
+ sc = &l1_sc[unit]; /* get pointer to softc */
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(sc->sc_port + USR_INTL_OFF, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ outb(sc->sc_port + USR_INTL_OFF, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ if((irq = intr_no[sc->sc_irq]) == 0)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ unit, sc->sc_irq);
+ return(1);
+ }
+
+ /* configure and enable irq */
+
+ outb(sc->sc_port + USR_INTL_OFF, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (0);
+}
+
+#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 */
OpenPOWER on IntegriCloud