summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer1
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
committerphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
commitc7ecc129d72ba32b5d83c9a6019e93fd181d719c (patch)
tree8d5099bc7ef24151b4f6deb00d1d34a7e7ac694a /sys/i4b/layer1
parent3f431df8ec46b86090ad59ee153872c45d4d429d (diff)
downloadFreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.zip
FreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.tar.gz
Initial entry of ISDN4BSD into the FreeBSD tree.
ISDN4BSD is the work of our brand-new comitter: Hellmuth Michaelis, who has done a tremendous amount of work to bring us this far. There are still some outstanding issues and files to bring into the tree, and for now it will be needed to pick up all the extra docs from the isdn4bsd release. It is probably also a very good idea to subscribe to the isdn@freebsd.org mailing list before you try this out. These files correspond to release "beta Version 0.70.00 / December 1998" from Hellmuth.
Diffstat (limited to 'sys/i4b/layer1')
-rw-r--r--sys/i4b/layer1/i4b_avm_a1.c508
-rw-r--r--sys/i4b/layer1/i4b_avm_fritz_pcmcia.c504
-rw-r--r--sys/i4b/layer1/i4b_bchan.c484
-rw-r--r--sys/i4b/layer1/i4b_ctx_s0P.c366
-rw-r--r--sys/i4b/layer1/i4b_drn_ngo.c542
-rw-r--r--sys/i4b/layer1/i4b_dynalink.c438
-rw-r--r--sys/i4b/layer1/i4b_elsa_isdnmc.c305
-rw-r--r--sys/i4b/layer1/i4b_elsa_mcall.c251
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1i.c511
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1p.c458
-rw-r--r--sys/i4b/layer1/i4b_hscx.c672
-rw-r--r--sys/i4b/layer1/i4b_hscx.h301
-rw-r--r--sys/i4b/layer1/i4b_ipac.h199
-rw-r--r--sys/i4b/layer1/i4b_isac.c679
-rw-r--r--sys/i4b/layer1/i4b_isac.h391
-rw-r--r--sys/i4b/layer1/i4b_isic.c345
-rw-r--r--sys/i4b/layer1/i4b_isic_isa.c591
-rw-r--r--sys/i4b/layer1/i4b_isic_pci.c424
-rw-r--r--sys/i4b/layer1/i4b_isic_pcmcia.c164
-rw-r--r--sys/i4b/layer1/i4b_isic_pnp.c296
-rw-r--r--sys/i4b/layer1/i4b_itk_ix1.c430
-rw-r--r--sys/i4b/layer1/i4b_l1.c315
-rw-r--r--sys/i4b/layer1/i4b_l1.h438
-rw-r--r--sys/i4b/layer1/i4b_l1fsm.c546
-rw-r--r--sys/i4b/layer1/i4b_sws.c392
-rw-r--r--sys/i4b/layer1/i4b_tel_s016.c455
-rw-r--r--sys/i4b/layer1/i4b_tel_s0163.c432
-rw-r--r--sys/i4b/layer1/i4b_tel_s08.c389
-rw-r--r--sys/i4b/layer1/i4b_tel_s0P.c378
-rw-r--r--sys/i4b/layer1/i4b_usr_sti.c440
-rw-r--r--sys/i4b/layer1/isa_isic.c828
-rw-r--r--sys/i4b/layer1/isapnp_isic.c386
-rw-r--r--sys/i4b/layer1/isic_supio.c374
-rw-r--r--sys/i4b/layer1/pci_isic.c327
-rw-r--r--sys/i4b/layer1/pcmcia_isic.c358
-rw-r--r--sys/i4b/layer1/pcmcia_isic.h60
36 files changed, 14977 insertions, 0 deletions
diff --git a/sys/i4b/layer1/i4b_avm_a1.c b/sys/i4b/layer1/i4b_avm_a1.c
new file mode 100644
index 0000000..bb55979
--- /dev/null
+++ b/sys/i4b/layer1/i4b_avm_a1.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 1996 Andrew Gordon. All rights reserved.
+ *
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_avm_a1.c - AVM A1/Fritz passive card driver for isdn4bsd
+ * ------------------------------------------------------------
+ *
+ * $Id: i4b_avm_a1.c,v 1.20 1998/12/16 13:57:21 hm Exp $
+ *
+ * last edit-date: [Wed Dec 16 14:59:59 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(AVM_A1)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifndef __FreeBSD__
+static u_int8_t avma1_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void avma1_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void avma1_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM A1 and AVM Fritz! Card special registers
+ *---------------------------------------------------------------------------*/
+
+#define AVM_CONF_REG 0x1800 /* base offset for config register */
+#define AVM_CONF_IRQ 0x1801 /* base offset for IRQ register */
+ /* config register write */
+#define AVM_CONF_WR_RESET 0x01 /* 1 = RESET ISAC and HSCX */
+#define AVM_CONF_WR_CCL 0x02 /* 1 = clear counter low nibble */
+#define AVM_CONF_WR_CCH 0x04 /* 1 = clear counter high nibble */
+#define AVM_CONF_WR_IRQEN 0x08 /* 1 = enable IRQ */
+#define AVM_CONF_WR_TEST 0x10 /* test bit */
+ /* config register read */
+#define AVM_CONF_RD_IIRQ 0x01 /* 0 = ISAC IRQ active */
+#define AVM_CONF_RD_HIRQ 0x02 /* 0 = HSCX IRQ active */
+#define AVM_CONF_RD_CIRQ 0x04 /* 0 = counter IRQ active */
+#define AVM_CONF_RD_ZER1 0x08 /* unused, always read 0 */
+#define AVM_CONF_RD_TEST 0x10 /* test bit read back */
+#define AVM_CONF_RD_ZER2 0x20 /* unused, always read 0 */
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_read_multi_1(t, h, 0, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base - 0x3e0, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+4].t;
+ bus_space_handle_t h = sc->sc_maps[what+4].h;
+ bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+#else
+static void
+avma1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+#else
+static u_int8_t
+avma1_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1 - probe for AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char savebyte;
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for AVM A1/Fritz!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x240:
+ case 0x300:
+ case 0x340:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + 0x1400 - 0x20;
+
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + 0x400 - 0x20;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + 0xc00 - 0x20;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = inb(dev->id_iobase + AVM_CONF_REG);
+
+ /* write low to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x00)
+ {
+ printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ /* write high to test bit */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x10)
+ {
+ printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
+ dev->id_unit, byte);
+ outb(dev->id_iobase + AVM_CONF_REG, savebyte);
+ return (0);
+ }
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_avma1(struct isic_attach_args *ia)
+{
+ u_int8_t savebyte, v1, v2;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ v1 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXA+1].t, ia->ia_maps[ISIC_WHAT_HSCXA+1].h, H_VSTR) & 0x0f;
+ v2 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXB+1].t, ia->ia_maps[ISIC_WHAT_HSCXB+1].h, H_VSTR) & 0x0f;
+ if (v1 != v2 || (v1 != 0x05 && v1 != 0x04))
+ return 0;
+
+ /* AVM A1 or Fritz! control register bits: */
+ /* read write */
+ /* 0x01 hscx irq* RESET */
+ /* 0x02 isac irq* clear counter1 */
+ /* 0x04 counter irq* clear counter2 */
+ /* 0x08 always 0 irq enable */
+ /* 0x10 read test bit set test bit */
+ /* 0x20 always 0 unused */
+
+ /*
+ * XXX the following test may be destructive, to prevent the
+ * worst case, we save the byte first, and in case the test
+ * fails, we write back the saved byte .....
+ */
+
+ savebyte = bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0);
+
+ /* write low to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0);
+
+ /* test bit and next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x00)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ /* write high to test bit */
+
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0x10);
+
+ /* test bit must be high, next higher and lower bit must be 0 */
+
+ if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x10)
+ {
+ bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte);
+ return 0;
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_avma1 - attach AVM A1 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_avma1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + AVM_CONF_REG, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_IRQ, (ffs(sc->sc_irq)) - 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else
+
+int
+isic_attach_avma1(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_read_reg;
+ sc->writereg = avma1_write_reg;
+
+ sc->readfifo = avma1_read_fifo;
+ sc->writefifo = avma1_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_AVMA1;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_RESET);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 1, sc->sc_irq);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, 0, AVM_CONF_WR_IRQEN |
+ AVM_CONF_WR_CCH | AVM_CONF_WR_CCL);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+#endif
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c
new file mode 100644
index 0000000..483eb66
--- /dev/null
+++ b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1998 Matthias Apitz. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Fritz!Card pcmcia specific routines for isic driver
+ * ---------------------------------------------------
+ *
+ * $Id: i4b_avm_fritz_pcmcia.c,v 1.7 1998/12/01 21:25:53 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 22:03:51 1998]
+ *
+ * -ap added support for AVM PCMCIA Fritz!Card
+ * -mh split into separate file
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(AVM_PCMCIA)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t avma1_pcmcia_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void avma1_pcmcia_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void avma1_pcmcia_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void avma1_pcmcia_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM PCMCIA Fritz!Card special registers
+ *---------------------------------------------------------------------------*/
+
+/*
+ * register offsets from i/o base 0x140 or 0x300
+ */
+#define ADDR_REG_OFFSET 0x02
+#define DATA_REG_OFFSET 0x03
+#define STAT0_OFFSET 0x04
+#define STAT1_OFFSET 0x05
+#define MODREG_OFFSET 0x06
+#define VERREG_OFFSET 0x07
+/*
+ * AVM PCMCIA Status Latch 0 read only bits
+ */
+#define ASL_IRQ_TIMER 0x10 /* Timer interrupt, active low */
+#define ASL_IRQ_ISAC 0x20 /* ISAC interrupt, active low */
+#define ASL_IRQ_HSCX 0x40 /* HSX interrupt, active low */
+#define ASL_IRQ_BCHAN ASL_IRQ_HSCX
+#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
+/*
+ * AVM Status Latch 0 write only bits
+ */
+#define ASL_RESET_ALL 0x01 /* reset siemens IC's, active 1 */
+#define ASL_TIMERDISABLE 0x02 /* active high */
+#define ASL_TIMERRESET 0x04 /* active high */
+#define ASL_ENABLE_INT 0x08 /* active high */
+/*
+ * AVM Status Latch 1 write only bits
+ */
+#define ASL1_LED0 0x10 /* active high */
+#define ASL1_LED1 0x20 /* active high */
+
+#define ASL1_ENABLE_S0 0xc0 /* enable active S0 I/F */
+
+/*----- EEpromless controller -----*/
+/*
+ * AVM Status Latch read/write bit
+ */
+
+#define ASL_TESTBIT 0x80
+
+
+/*---------------------------------------------------------------------------*
+ * AVM read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+avma1_pcmcia_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ insb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+/* offsets of the different 'what' arguments */
+static u_int8_t what_map[] = {
+ 0x20-0x20, /* ISIC_WHAT_ISAC */
+ 0xA0-0x20, /* ISIC_WHAT_HSCXA */
+ 0xE0-0x20 /* ISIC_WHAT_HSCXB */
+};
+static void
+avma1_pcmcia_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_read_multi_1(t, h, DATA_REG_OFFSET, buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20);
+ outsb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len);
+}
+#else
+static void
+avma1_pcmcia_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]);
+ bus_space_write_multi_1(t, h, DATA_REG_OFFSET, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+avma1_pcmcia_write_reg(u_char *base, u_int offset, u_int v)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ outb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char)v);
+}
+#else
+static void
+avma1_pcmcia_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ bus_space_write_1(t, h, DATA_REG_OFFSET, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * AVM read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+avma1_pcmcia_read_reg(u_char *base, u_int offset)
+{
+ /* offset includes 0x20 FIFO ! */
+ outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20);
+ return (inb(PCMCIA_IO_BASE + DATA_REG_OFFSET));
+}
+#else
+static u_int8_t
+avma1_pcmcia_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs);
+ return bus_space_read_1(t, h, DATA_REG_OFFSET);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_avma1_pcmcia - probe for AVM PCMCIA Fritz!Card
+ * This is in the bus attachemnt part on NetBSD (pcmcia_isic.c), no
+ * card specicfic probe is needed on direct config buses like pcmcia.
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_avma1_pcmcia(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+ int i;
+ u_int cardinfo;
+
+ /* check max unit range */
+
+ if(dev->id_unit > 1)
+ {
+ printf("isic%d: Error, unit %d > MAXUNIT for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /*
+ * we trust the IRQ we got from PCCARD service
+ */
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x140:
+ case 0x300:
+ break;
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for AVM PCMCIA Fritz!Card.\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* ResetController */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 20);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+
+ /*
+ * CheckController
+ * The logic to check for the PCMCIA was adapted as
+ * described by AVM.
+ */
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0x21); /* ISAC STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, ISAC STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ outb(dev->id_iobase + ADDR_REG_OFFSET, 0xa1); /* HSCX STAR */
+ if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
+ {
+ printf("isic%d: Error, HSCX STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = ASL_TESTBIT;
+ for (i=0; i<256; i++) {
+ byte = byte ? 0 : ASL_TESTBIT;
+ outb(dev->id_iobase + STAT0_OFFSET, byte);
+ if ((inb(dev->id_iobase+STAT0_OFFSET)&ASL_TESTBIT)!=byte) {
+ printf("isic%d: Error during toggle of AVM PCMCIA Status Latch0\n",
+ dev->id_unit);
+ return(0);
+ }
+ }
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2; /* ap: XXX ??? */
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ /*
+ * NOTE: for PCMCIA these are no real addrs; they are
+ * offsets to be written into the base+ADDR_REG_OFFSET register
+ * to pick up the values of the bytes fro base+DATA_REG_OFFSET
+ *
+ * see also the logic in the avma1_pcmcia_* routines;
+ * therefore we also must have the base addr in some static
+ * space or struct; XXX better solution?
+ */
+
+ PCMCIA_IO_BASE = dev->id_iobase;
+ ISAC_BASE = (caddr_t)0x20;
+
+ HSCX_A_BASE = (caddr_t)0xA0;
+ HSCX_B_BASE = (caddr_t)0xE0;
+
+ /*
+ * Read HSCX A/B VSTR.
+ * Expected value for AVM A1 is 0x04 or 0x05 and for the
+ * AVM Fritz!Card is 0x05 in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for AVM PCMCIA Fritz!Card\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: 0x%0x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /*
+ * seems we really have an AVM PCMCIA Fritz!Card controller
+ */
+ cardinfo = inb(dev->id_iobase + VERREG_OFFSET)<<8 | inb(dev->id_iobase + MODREG_OFFSET);
+ printf("isic%d: successfully detect AVM PCMCIA cardinfo = 0x%0x\n",
+ dev->id_unit, cardinfo);
+ dev->id_flags = FLAG_AVM_A1_PCMCIA;
+ return (1);
+}
+#endif /* __FreeBSD__ */
+
+
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_fritzpcmcia - attach Fritz!Card
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_fritzpcmica(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* ResetController again just to make sure... */
+
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ outb(dev->id_iobase + STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+ /* DELAY(SEC_DELAY / 10); */
+
+ return(1);
+}
+
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_fritzpcmcia(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space - exactly as dictated by the card */
+ if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start, cfe->iospace[0].length,
+ 0, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = avma1_pcmcia_read_reg;
+ sc->writereg = avma1_pcmcia_write_reg;
+
+ sc->readfifo = avma1_pcmcia_read_fifo;
+ sc->writefifo = avma1_pcmcia_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_PCFRITZ;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Reset controller again just to make sure... */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x01);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, STAT0_OFFSET, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* enable IRQ, disable counter IRQ */
+
+ bus_space_write_1(t, h, STAT0_OFFSET, ASL_TIMERDISABLE |
+ ASL_TIMERRESET | ASL_ENABLE_INT);
+
+ return 1;
+}
+#endif
+
+#endif /* NISIC > 0 && defined(AVM_PCMCIA) */
diff --git a/sys/i4b/layer1/i4b_bchan.c b/sys/i4b/layer1/i4b_bchan.c
new file mode 100644
index 0000000..17ee273
--- /dev/null
+++ b/sys/i4b/layer1/i4b_bchan.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_bchan.c - B channel handling L1 procedures
+ * ----------------------------------------------
+ *
+ * $Id: i4b_bchan.c,v 1.28 1998/12/05 18:04:28 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:21:57 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __FreeBSD__
+static void isic_bchannel_start(int unit, int h_chan);
+static void isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp);
+#else
+static void isic_bchannel_start __P((int unit, int h_chan));
+static void isic_bchannel_stat __P((int unit, int h_chan, bchan_statistics_t *bsp));
+#endif
+
+static void isic_set_linktab(int unit, int channel, drvr_link_t *dlt);
+static isdn_link_t *isic_ret_linktab(int unit, int channel);
+
+/*---------------------------------------------------------------------------*
+ * initialize one B channels rx/tx data structures and init/deinit HSCX
+ *---------------------------------------------------------------------------*/
+void
+isic_bchannel_setup(int unit, int h_chan, int bprot, int activate)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+
+ int s = SPLI4B();
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ DBGL1(L1_BCHAN, "isic_bchannel_setup", ("unit=%d, channel=%d, %s\n",
+ sc->sc_unit, h_chan, activate ? "activate" : "deactivate"));
+
+ /* general part */
+
+ chan->unit = sc->sc_unit; /* unit number */
+ chan->channel = h_chan; /* B channel */
+ chan->bprot = bprot; /* B channel protocol */
+ chan->state = HSCX_IDLE; /* B channel state */
+
+ /* receiver part */
+
+ i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
+
+ chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->rxcount = 0; /* reset rx counter */
+
+ i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
+
+ chan->in_mbuf = NULL; /* reset mbuf ptr */
+ chan->in_cbptr = NULL; /* reset mbuf curr ptr */
+ chan->in_len = 0; /* reset mbuf data len */
+
+ /* transmitter part */
+
+ i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
+
+ chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->txcount = 0; /* reset tx counter */
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
+
+ chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
+ chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
+ chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
+ chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
+
+ if(activate != 0)
+ {
+ /* activation */
+ isic_hscx_init(sc, h_chan, activate);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * start transmission on a b channel
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_start(int unit, int h_chan)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ register isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ register int next_len;
+ register int len;
+
+ int s;
+ int activity = -1;
+ int cmd = 0;
+
+ s = SPLI4B(); /* enter critical section */
+ if(chan->state & HSCX_TX_ACTIVE) /* already running ? */
+ {
+ splx(s);
+ return; /* yes, leave */
+ }
+
+ /* get next mbuf from queue */
+
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL) /* queue empty ? */
+ {
+ splx(s); /* leave critical section */
+ return; /* yes, exit */
+ }
+
+ /* init current mbuf values */
+
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+
+ /* activity indicator for timeout handling */
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+
+ chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */
+
+ if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ len = 0; /* # of chars put into HSCX tx fifo this time */
+
+ /*
+ * fill the HSCX tx fifo with data from the current mbuf. if
+ * current mbuf holds less data than HSCX fifo length, try to
+ * get the next mbuf from (a possible) mbuf chain. if there is
+ * not enough data in a single mbuf or in a chain, then this
+ * is the last mbuf and we tell the HSCX that it has to send
+ * CRC and closing flag
+ */
+
+ while((len < sc->sc_bfifolen) && chan->out_mbuf_cur)
+ {
+ /*
+ * put as much data into the HSCX fifo as is
+ * available from the current mbuf
+ */
+
+ if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen)
+ next_len = sc->sc_bfifolen - len;
+ else
+ next_len = chan->out_mbuf_cur_len;
+
+#ifdef NOTDEF
+ printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ /* wait for tx fifo write enabled */
+
+ isic_hscx_waitxfw(sc, h_chan);
+
+ /* write what we have from current mbuf to HSCX fifo */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len);
+
+ len += next_len; /* update # of bytes written */
+ chan->txcount += next_len; /* statistics */
+ chan->out_mbuf_cur_ptr += next_len; /* data ptr */
+ chan->out_mbuf_cur_len -= next_len; /* data len */
+
+ /*
+ * in case the current mbuf (of a possible chain) data
+ * has been put into the fifo, check if there is a next
+ * mbuf in the chain. If there is one, get ptr to it
+ * and update the data ptr and the length
+ */
+
+ if((chan->out_mbuf_cur_len <= 0) &&
+ ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ }
+
+ /*
+ * if there is either still data in the current mbuf and/or
+ * there is a successor on the chain available issue just
+ * a XTF (transmit) command to HSCX. if ther is no more
+ * data available from the current mbuf (-chain), issue
+ * an XTF and an XME (message end) command which will then
+ * send the CRC and the closing HDLC flag sequence
+ */
+
+ if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
+ {
+ /*
+ * more data available, send current fifo out.
+ * next xfer to HSCX tx fifo is done in the
+ * HSCX interrupt routine.
+ */
+
+ cmd |= HSCX_CMDR_XTF;
+ }
+ else
+ {
+ /* end of mbuf chain */
+
+ if(chan->bprot == BPROT_NONE)
+ cmd |= HSCX_CMDR_XTF;
+ else
+ cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME;
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */
+
+ chan->out_mbuf_head = NULL;
+ chan->out_mbuf_cur = NULL;
+ chan->out_mbuf_cur_ptr = NULL;
+ chan->out_mbuf_cur_len = 0;
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+
+ if(cmd)
+ isic_hscx_cmd(sc, h_chan, cmd);
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * fill statistics struct
+ *---------------------------------------------------------------------------*/
+static void
+isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ int s;
+
+ s = SPLI4B();
+
+ bsp->outbytes = chan->txcount;
+ bsp->inbytes = chan->rxcount;
+
+ chan->txcount = 0;
+ chan->rxcount = 0;
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * return the address of isic drivers linktab
+ *---------------------------------------------------------------------------*/
+static isdn_link_t *
+isic_ret_linktab(int unit, int channel)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[channel];
+
+ return(&chan->isdn_linktab);
+}
+
+/*---------------------------------------------------------------------------*
+ * set the driver linktab in the b channel softc
+ *---------------------------------------------------------------------------*/
+static void
+isic_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ isic_Bchan_t *chan = &sc->sc_chan[channel];
+
+ chan->drvr_linktab = dlt;
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+void
+isic_init_linktab(struct isic_softc *sc)
+{
+ isic_Bchan_t *chan = &sc->sc_chan[HSCX_CH_A];
+ isdn_link_t *lt = &chan->isdn_linktab;
+
+ /* make sure the hardware driver is known to layer 4 */
+ ctrl_types[CTRL_PASSIVE].set_linktab = isic_set_linktab;
+ ctrl_types[CTRL_PASSIVE].get_linktab = isic_ret_linktab;
+
+ /* local setup */
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_A;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+
+ chan = &sc->sc_chan[HSCX_CH_B];
+ lt = &chan->isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = HSCX_CH_B;
+ lt->bch_config = isic_bchannel_setup;
+ lt->bch_tx_start = isic_bchannel_start;
+ lt->bch_stat = isic_bchannel_stat;
+ lt->tx_queue = &chan->tx_queue;
+
+ /* used by non-HDLC data transfers, i.e. telephony drivers */
+ lt->rx_queue = &chan->rx_queue;
+
+ /* used by HDLC data transfers, i.e. ipr and isp drivers */
+ lt->rx_mbuf = &chan->in_mbuf;
+}
+
+/*---------------------------------------------------------------------------*
+ * telephony silence detection
+ *---------------------------------------------------------------------------*/
+
+#define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
+
+int
+isic_hscx_silence(unsigned char *data, int len)
+{
+ register int i = 0;
+ register int j = 0;
+
+ /* count idle bytes */
+
+ for(;i < len; i++)
+ {
+ if((*data >= 0xaa) && (*data <= 0xac))
+ j++;
+ data++;
+ }
+
+#ifdef NOTDEF
+ printf("isic_hscx_silence: got %d silence bytes in frame\n", j);
+#endif
+
+ if(j < (TEL_IDLE_MIN))
+ return(0);
+ else
+ return(1);
+
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_ctx_s0P.c b/sys/i4b/layer1/i4b_ctx_s0P.c
new file mode 100644
index 0000000..f9e6b7f
--- /dev/null
+++ b/sys/i4b/layer1/i4b_ctx_s0P.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Creatix PnP cards
+ * ============================================================
+ *
+ * $Id: i4b_ctx_s0P.c,v 1.17 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:26:30 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P)
+
+#include <sys/param.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t ctxs0P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void ctxs0P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void ctxs0P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void ctxs0P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_Cs0P(struct isic_softc *sc);
+#endif
+
+#ifdef __FreeBSD__
+#include <i386/isa/pnp.h>
+extern void isicintr ( int unit );
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+ctxs0P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+ctxs0P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+ctxs0P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Creatix ISDN-S0 P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+ctxs0P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+ctxs0P_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Cs0P - probe for Creatix ISDN-S0 P&P and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x120:
+ case 0x180:
+/*XXX*/ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Creatix ISDN-S0 P&P!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) dev->id_iobase - 0x20;
+ HSCX_A_BASE = (caddr_t) iobase2 - 0x20;
+ HSCX_B_BASE = (caddr_t) iobase2;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the Creatix PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Creatix PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Creatix ISDN-S0 P&P
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Cs0P(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Cs0P(struct isic_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = ctxs0P_read_reg;
+ sc->writereg = ctxs0P_write_reg;
+
+ sc->readfifo = ctxs0P_read_fifo;
+ sc->writefifo = ctxs0P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_CS0P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P) */
+
diff --git a/sys/i4b/layer1/i4b_drn_ngo.c b/sys/i4b/layer1/i4b_drn_ngo.c
new file mode 100644
index 0000000..a5f3d69
--- /dev/null
+++ b/sys/i4b/layer1/i4b_drn_ngo.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod
+ * --------------------------------------------------------
+ *
+ * $Id: i4b_drn_ngo.c,v 1.19 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:26:03 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+/*---------------------------------------------------------------------------*
+ * Niccy GO@ definitions
+ *
+ * the card uses 2 i/o addressranges each using 2 bytes
+ *
+ * addressrange 0:
+ * offset 0 - ISAC dataregister
+ * offset 1 - HSCX dataregister
+ * addressrange 1:
+ * offset 0 - ISAC addressregister
+ * offset 1 - HSCX addressregister
+ *
+ * to access an ISAC/HSCX register, you have to write the register
+ * number into the ISAC or HSCX addressregister and then read/write
+ * data for the ISAC/HSCX register into/from the corresponding
+ * dataregister.
+ *
+ * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving
+ * out this information!
+ *
+ *---------------------------------------------------------------------------*/
+#define NICCY_PORT_MIN 0x200
+#define NICCY_PORT_MAX 0x3e0
+
+#define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */
+#define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */
+
+#define HSCX_BOFF 0x40
+
+#define ADDR_OFF 2 /* address register range offset XXX */
+
+#define ISAC_DATA 0
+#define HSCX_DATA 1
+
+#define ISAC_ADDR 0
+#define HSCX_ADDR 1
+
+#ifdef __FreeBSD__
+
+#if 0
+#define HSCXADEBUG
+#define HSCXBDEBUG
+#define ISACDEBUG
+#else
+#undef HSCXADEBUG
+#undef HSCXBDEBUG
+#undef ISACDEBUG
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ *((u_char *)buf + offset) = inb((int)data);
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset;
+ register u_int data;
+
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = 0;
+#ifdef HSCXADEBUG
+printf("GO/A/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ (u_int)data = ((u_int)base + HSCX_DATA);
+ (u_int)base += (ADDR_OFF + HSCX_ADDR);
+ offset = HSCX_BOFF;
+#ifdef HSCXBDEBUG
+printf("GO/B/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+ else
+ {
+ (u_int)data = ((u_int)base + ISAC_DATA);
+ (u_int)base += (ADDR_OFF + ISAC_ADDR);
+ offset = 0;
+#ifdef ISACDEBUG
+printf("GO/I/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len);
+#endif
+ }
+
+ for(;len > 0; len--, offset++)
+ {
+ outb((int)base, (u_char)offset);
+ outb((int)data, *((u_char *)buf + offset));
+ }
+
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ write register routine
+ *---------------------------------------------------------------------------*/
+static void
+drnngo_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int x = SPLI4B();
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXADEBUG
+printf("GO/A/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ outb((int)base + HSCX_DATA, (u_char)v);
+#ifdef HSCXBDEBUG
+printf("GO/B/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)v);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ outb((int)base + ISAC_DATA, (u_char)v);
+#ifdef ISACDEBUG
+printf("GO/I/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)v);
+#endif
+ }
+ splx(x);
+}
+
+/*---------------------------------------------------------------------------*
+ * Dr. Neuhaus Niccy GO@ read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+drnngo_read_reg(u_char *base, u_int offset)
+{
+ u_char val;
+ int x = SPLI4B();
+
+ if((u_int)base & HSCX_ABIT)
+ {
+ (u_int)base &= ~HSCX_ABIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset);
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXADEBUG
+printf("GO/A/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ else if((u_int)base & HSCX_BBIT)
+ {
+ (u_int)base &= ~HSCX_BBIT;
+ outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF));
+ val = inb((int)base + HSCX_DATA);
+#ifdef HSCXBDEBUG
+printf("GO/B/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA,
+ (u_char)(offset + HSCX_BOFF), (u_char)val);
+#endif
+ }
+ else
+ {
+ outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset);
+ val = inb((int)base + ISAC_DATA);
+#ifdef ISACDEBUG
+printf("GO/I/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
+ (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA,
+ (u_char)offset, (u_char)val);
+#endif
+ }
+ splx(x);
+ return(val);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_drnngo - probe for Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase < NICCY_PORT_MIN || dev->id_iobase > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if(iobase2 == 0)
+ {
+ printf("isic%d: Error, iobase2 is 0 for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ if(iobase2 < NICCY_PORT_MIN || iobase2 > NICCY_PORT_MAX)
+ {
+ printf("isic%d: Error, invalid port1 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
+ dev->id_unit, iobase2);
+ return(0);
+ }
+
+/*XXX*/ if((dev->id_iobase + 2) != iobase2)
+ {
+ printf("isic%d: Error, port1 must be (port0+2) for Dr.Neuhaus Niccy GO@!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase;
+ HSCX_A_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_ABIT);
+ HSCX_B_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_BBIT);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for Dr. Neuhaus Niccy GO@ based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dr. Neuhaus Niccy GO@\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_drnngo - attach Dr. Neuhaus Niccy GO@
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_drnngo(struct isa_device *dev, unsigned int iobase2)
+{
+ return (1);
+}
+
+#else
+
+static u_int8_t drnngo_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void drnngo_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void drnngo_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void drnngo_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_drnngo __P((struct isic_softc *sc));
+
+/*
+ * Mapping from "what" parameter to offsets into the io map
+ */
+static struct {
+ bus_size_t oa, /* address register offset */
+ od, /* data register offset */
+ or; /* additional chip register offset */
+} offset[] =
+{
+ { ISAC_ADDR, ISAC_DATA, 0 }, /* ISAC access */
+ { HSCX_ADDR, HSCX_DATA, 0 }, /* HSCX A access */
+ { HSCX_ADDR, HSCX_DATA, HSCX_BOFF } /* HSCX B access */
+};
+
+static void
+drnngo_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_read_multi_1(t, hd, offset[what].od, buf, size);
+}
+
+static void
+drnngo_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offset[what].or);
+ bus_space_write_multi_1(t, hd, offset[what].od, (u_int8_t*)buf, size);
+}
+
+static void
+drnngo_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ bus_space_write_1(t, hd, offset[what].od, data);
+}
+
+static u_int8_t
+drnngo_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h;
+ bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or);
+ return bus_space_read_1(t, hd, offset[what].od);
+}
+
+void
+isic_attach_drnngo(struct isic_softc *sc)
+{
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = drnngo_read_reg;
+ sc->writereg = drnngo_write_reg;
+
+ sc->readfifo = drnngo_read_fifo;
+ sc->writefifo = drnngo_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_DRNNGO;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO) */
diff --git a/sys/i4b/layer1/i4b_dynalink.c b/sys/i4b/layer1/i4b_dynalink.c
new file mode 100644
index 0000000..846e79a
--- /dev/null
+++ b/sys/i4b/layer1/i4b_dynalink.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 1998 Martijn Plak. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA
+ * ==================================================
+ *
+ * $Id: i4b_dynalink.c,v 1.8 1998/12/17 04:55:38 hm Exp $
+ *
+ * last edit-date: [Thu Dec 17 05:50:39 1998]
+ *
+ * written by Martijn Plak <tigrfhur@xs4all.nl>
+ *
+ * -mp 11 jun 1998 first try, code borrowed from Creatix driver
+ * -mp 18 jun 1998 cleaned up code
+ * -hm FreeBSD PnP
+ * -mp 17 dec 1998 made it compile again
+ *
+ *---------------------------------------------------------------------------*/
+
+/* NOTES:
+
+ This driver was written for the Dynalink IS64PH ISDN TA, based on two
+ Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands.
+
+ model numbers found on (my) card:
+ IS64PH, TAS100H-N, P/N:89590555, TA200S100045521
+
+ chips:
+ Siemens PSB 21525N, HSCX TE V2.1
+ Siemens PSB 2186N, ISAC-S TE V1.1
+ 95MS14, PNP
+
+ plug-and-play info:
+ device id "ASU1688"
+ vendor id 0x88167506
+ serial 0x00000044
+ i/o port 4 byte alignment, 4 bytes requested,
+ 10 bit i/o decoding, 0x100-0x3f8 (?)
+ irq 3,4,5,9,10,11,12,15, high true, edge sensitive
+
+ At the moment I'm writing this Dynalink is replacing this card with
+ one based on a single Siemens chip (IPAC). It will apparently be sold
+ under the same model name.
+
+ This driver might also work for Asuscom cards.
+*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(DYNALINK)
+
+/* HEADERS
+*/
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifdef __FreeBSD__
+static void dynalink_read_fifo(void *buf, const void *base, size_t len);
+static void dynalink_write_fifo(void *base, const void *buf, size_t len);
+static void dynalink_write_reg(u_char *base, u_int offset, u_int v);
+static u_char dynalink_read_reg(u_char *base, u_int offset);
+
+extern struct isa_driver isicdriver;
+
+#else
+static void dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
+static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
+static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
+void isic_attach_Dyn(struct isic_softc *sc);
+#endif
+
+/* io address mapping */
+#define ISAC 0
+#define HSCX 1
+#define ADDR 2
+
+/* ADDR bits */
+#define ADDRMASK 0x7F
+#define RESET 0x80
+
+/* HSCX register offsets */
+#define HSCXA 0x00
+#define HSCXB 0x40
+
+#ifdef __FreeBSD__
+/* base address juggling */
+#define HSCXB_HACK 0x400
+#define IOBASE(addr) (((int)addr)&0x3FC)
+#define IOADDR(addr) (((int)addr)&0x3FF)
+#define IS_HSCXB_HACK(addr) ((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA)
+
+/* ISIC probe and attach
+*/
+
+int
+isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return (0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ if ( (dev->id_iobase < 0x100) ||
+ (dev->id_iobase > 0x3f8) ||
+ (dev->id_iobase & 3) )
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Dynalink\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+int
+isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2)
+{
+ outb((dev->id_iobase)+ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void isic_attach_Dyn(struct isic_softc *sc)
+{
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = dynalink_read_reg;
+ sc->writereg = dynalink_write_reg;
+ sc->readfifo = dynalink_read_fifo;
+ sc->writefifo = dynalink_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0);
+ DELAY(SEC_DELAY / 10);
+}
+
+#endif /* ISIC>0 && NPNP>0 && defined(DYNALINK) */
+
+/* LOW-LEVEL DEVICE ACCESS
+
+ NOTE: The isdn4bsd code expects the two HSCX channels at different
+ base addresses. I'm faking this, and remap them to the same address
+ in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK.
+
+ REM: this is only true for the FreeBSD version of I4B!
+*/
+
+#ifdef __FreeBSD__
+static void
+dynalink_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ insb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void
+dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_read_multi_1(t, h, ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_read_multi_1(t, h, HSCX, buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+dynalink_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base));
+ outsb(IOADDR(base), (u_char *)buf, (u_int)len);
+}
+#else
+static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, 0);
+ bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB);
+ bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+dynalink_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ outb(IOADDR(base), (u_char)v);
+}
+#else
+static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ bus_space_write_1(t, h, ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ bus_space_write_1(t, h, HSCX, data);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static u_char
+dynalink_read_reg(u_char *base, u_int offset)
+{
+ outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK);
+ return (inb(IOADDR(base)));
+}
+#else
+static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR, offs);
+ return bus_space_read_1(t, h, ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR, HSCXA+offs);
+ return bus_space_read_1(t, h, HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR, HSCXB+offs);
+ return bus_space_read_1(t, h, HSCX);
+ }
+ return 0;
+}
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(DYNALINK) */
diff --git a/sys/i4b/layer1/i4b_elsa_isdnmc.c b/sys/i4b/layer1/i4b_elsa_isdnmc.c
new file mode 100644
index 0000000..c6987f5
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_isdnmc.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink ISDN/MC card specific routines
+ * ---------------------------------------------
+ *
+ * $Id: i4b_elsa_isdnmc.c,v 1.2 1998/12/05 18:04:33 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 07:45:53 1998]
+ *
+ * -mh added support for elsa ISDN/mc
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(ELSA_ISDNMC)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_isdnmc_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void elsa_isdnmc_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_isdnmc_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void elsa_isdnmc_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*
+ * The ELSA MicroLink ISDN/MC uses one contigous IO region,
+ * mapped by the pcmcia code.
+ * The chip access is via three ports:
+ */
+#define ISAC_DATA 1 /* ISAC dataport at offset 1 */
+#define HSCX_DATA 2 /* HSCX dataport at offset 2 */
+#define ADDR_LATCH 4 /* address latch at offset 4 */
+
+/* This is very similar to the ELSA QuickStep 1000 (ISA) card */
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_read_multi_1(t, h, HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_isdnmc_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, 0);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40);
+ bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_isdnmc_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_isdnmc_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ bus_space_write_1(t, h, HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_isdnmc_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_isdnmc_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ADDR_LATCH, offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs);
+ return bus_space_read_1(t, h, HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsaisdnmc(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* OK, this will work! */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLIMC;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = elsa_isdnmc_read_reg;
+ sc->writereg = elsa_isdnmc_write_reg;
+
+ sc->readfifo = elsa_isdnmc_read_fifo;
+ sc->writefifo = elsa_isdnmc_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_elsa_mcall.c b/sys/i4b/layer1/i4b_elsa_mcall.c
new file mode 100644
index 0000000..36882e9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_mcall.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * ELSA MicroLink MC/all card specific routines
+ * --------------------------------------------
+ *
+ * $Id: i4b_elsa_mcall.c,v 1.1 1998/12/02 06:44:27 hm Exp $
+ *
+ * last edit-date: [Tue Dec 1 07:45:53 1998]
+ *
+ * -mh started support for ELSA MC/all
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0 && defined(ELSA_MCALL)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_ipac.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+#ifndef __FreeBSD__
+/* PCMCIA support routines */
+static u_int8_t elsa_mcall_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void elsa_mcall_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void elsa_mcall_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void elsa_mcall_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */
+static void
+elsa_mcall_read_fifo(void *buf, const void *base, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write fifo routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_fifo(void *base, const void *buf, size_t len)
+{
+}
+#else
+static void
+elsa_mcall_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * write register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+elsa_mcall_write_reg(u_char *base, u_int offset, u_int v)
+{
+}
+#else
+static void
+elsa_mcall_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * read register routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static u_char
+elsa_mcall_read_reg(u_char *base, u_int offset)
+{
+ return 0;
+}
+#else
+static u_int8_t
+elsa_mcall_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ /*
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ */
+ return 0;
+}
+#endif
+
+#ifdef __FreeBSD__
+#else
+
+/*
+ * XXX - one time only! Some of this has to go into an enable
+ * function, with apropriate counterpart in disable, so a card
+ * could be removed an inserted again. But never mind for now,
+ * this won't work anyway for several reasons (both in NetBSD
+ * and in I4B).
+ */
+int
+isic_attach_elsamcall(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa)
+{
+ struct isic_softc *sc = &psc->sc_isic;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ /* Validate config info */
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of memory spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ /* Allocate pcmcia space */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+
+ /* map them */
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0,
+ cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return 0;
+ }
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ELSAMLMCALL;
+
+ /* Setup bus space maps */
+ sc->sc_num_mappings = 1;
+ MALLOC_MAPS(sc);
+
+ /* Copy our handles/tags to the MI maps */
+ sc->sc_maps[0].t = psc->sc_pcioh.iot;
+ sc->sc_maps[0].h = psc->sc_pcioh.ioh;
+ sc->sc_maps[0].offset = 0;
+ sc->sc_maps[0].size = 0; /* not our mapping */
+
+ t = sc->sc_maps[0].t;
+ h = sc->sc_maps[0].h;
+
+ sc->clearirq = NULL;
+ sc->readreg = elsa_mcall_read_reg;
+ sc->writereg = elsa_mcall_write_reg;
+
+ sc->readfifo = elsa_mcall_read_fifo;
+ sc->writefifo = elsa_mcall_write_fifo;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ return 1;
+}
+#endif
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_elsa_qs1i.c b/sys/i4b/layer1/i4b_elsa_qs1i.c
new file mode 100644
index 0000000..a3c8ddc
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_qs1i.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1i.c,v 1.12 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:27:08 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pnp.h"
+
+#else
+
+#define NISIC 1
+#define NPNP 1
+
+#endif
+
+#if (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#ifdef __FreeBSD__
+static void i4b_eq1i_clrirq(void* base);
+#else
+static void i4b_eq1i_clrirq(struct isic_softc *sc);
+void isic_attach_Eqs1pi __P((struct isic_softc *sc));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ISAC 0x00
+#define ELSA_OFF_HSCX 0x02
+#define ELSA_OFF_OFF 0x03
+#define ELSA_OFF_CTRL 0x04
+#define ELSA_OFF_CFG 0x05
+#define ELSA_OFF_TIMR 0x06
+#define ELSA_OFF_IRQ 0x07
+
+/* control register (write access) */
+
+#define ELSA_CTRL_LED_YELLOW 0x02
+#define ELSA_CTRL_LED_GREEN 0x08
+#define ELSA_CTRL_RESET 0x20
+#define ELSA_CTRL_TIMEREN 0x80
+#define ELSA_CTRL_SECRET 0x50
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA clear IRQ routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+static void
+i4b_eq1i_clrirq(void* base)
+{
+ outb((u_int)base + ELSA_OFF_IRQ, 0);
+}
+
+#else
+static void
+i4b_eq1i_clrirq(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40);
+ bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pi_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ bus_space_write_1(t, h, ELSA_OFF_HSCX, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/ISA ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pi_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX));
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset);
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_HSCX);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360)))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+/* XXX no "sc_clearirq" in sight... /phk
+ sc->sc_clearirq = i4b_eq1i_clrirq;
+*/
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the ELSA QuickStep 1000pro
+ * ISA card is 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2)
+{
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ outb(dev->id_iobase + ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_Eqs1pi(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char byte = ELSA_CTRL_SECRET;
+
+ byte &= ~ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+ DELAY(20);
+ byte |= ELSA_CTRL_RESET;
+ bus_space_write_1(t, h, ELSA_OFF_CTRL, byte);
+
+ DELAY(20);
+ bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff);
+
+ /* setup access routines */
+
+ sc->clearirq = i4b_eq1i_clrirq;
+ sc->readreg = eqs1pi_read_reg;
+ sc->writereg = eqs1pi_write_reg;
+
+ sc->readfifo = eqs1pi_read_fifo;
+ sc->writefifo = eqs1pi_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+
+#endif
+
+#endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */
diff --git a/sys/i4b/layer1/i4b_elsa_qs1p.c b/sys/i4b/layer1/i4b_elsa_qs1p.c
new file mode 100644
index 0000000..b2b35d0
--- /dev/null
+++ b/sys/i4b/layer1/i4b_elsa_qs1p.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro PCI
+ * =====================================================================
+ *
+ * $Id: i4b_elsa_qs1p.c,v 1.4 1998/12/05 18:04:36 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:22:41 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+#else
+#define NISIC 1
+#endif
+
+#if (NISIC > 0) && /* (NPCI > 0) && */ defined(ELSA_QS1PCI)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_ipac.h>
+
+#ifndef __FreeBSD__
+/* we don't have the function prototypes in the global i4b_l1.h any more */
+void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa));
+#endif
+
+/* masks for register encoded in base addr */
+
+#define ELSA_BASE_MASK 0x0ffff
+#define ELSA_OFF_MASK 0xf0000
+
+/* register id's to be encoded in base addr */
+
+#define ELSA_IDISAC 0x00000
+#define ELSA_IDHSCXA 0x10000
+#define ELSA_IDHSCXB 0x20000
+#define ELSA_IDIPAC 0x40000
+
+/* offsets from base address */
+
+#define ELSA_OFF_ALE 0x00
+#define ELSA_OFF_RW 0x01
+
+#define ELSA_PORT0_MAPOFF PCI_MAPREG_START+4
+#define ELSA_PORT1_MAPOFF PCI_MAPREG_START+12
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_read_fifo(void *buf, const void *base, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_fifo(void *base, const void *buf, size_t len)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+ else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF);
+ bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+eqs1pp_write_reg(u_char *base, u_int offset, u_int v)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+ else /* IPAC */
+ {
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v);
+ }
+}
+
+#else
+
+static void
+eqs1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ case ISIC_WHAT_IPAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ bus_space_write_1(t, h, ELSA_OFF_RW, data);
+ break;
+ }
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * ELSA QuickStep 1000pro/PCI ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+eqs1pp_read_reg(u_char *base, u_int offset)
+{
+ if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC)
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+ else /* IPAC */
+ {
+ outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF));
+ return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW));
+ }
+}
+
+#else
+
+static u_int8_t
+eqs1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ case ISIC_WHAT_IPAC:
+ {
+ bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs);
+ return bus_space_read_1(t, h, ELSA_OFF_RW);
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_Eqs1pp - attach for ELSA QuickStep 1000pro/PCI
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2)
+{
+ struct isic_softc *sc = &isic_sc[unit];
+
+ /* check max unit range */
+
+ if(unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/PCI!\n",
+ unit, unit);
+ return(0);
+ }
+ sc->sc_unit = unit;
+
+ /* setup iobase */
+
+ if((iobase2 <= 0) || (iobase2 > 0xffff))
+ {
+ printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/PCI!\n",
+ unit, iobase2);
+ return(0);
+ }
+ sc->sc_port = iobase2;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDISAC);
+ HSCX_A_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXA);
+ HSCX_B_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXB);
+ IPAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDIPAC);
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ outb(iobase1 + 0x4c, 0x41); /* enable card interrupt */
+
+ return (1);
+}
+
+#else /* !FreeBSD */
+
+void
+isic_attach_Eqs1pp(sc, pa)
+ struct isic_softc *sc;
+ struct pci_attach_args *pa;
+{
+ /* setup io mappings */
+ sc->sc_num_mappings = 2;
+ MALLOC_MAPS(sc);
+ sc->sc_maps[0].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT0_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[0].t, &sc->sc_maps[0].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ sc->sc_maps[1].size = 0;
+ if (pci_mapreg_map(pa, ELSA_PORT1_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
+ &sc->sc_maps[1].t, &sc->sc_maps[1].h, NULL, NULL)) {
+ printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = eqs1pp_read_reg;
+ sc->writereg = eqs1pp_write_reg;
+
+ sc->readfifo = eqs1pp_read_fifo;
+ sc->writefifo = eqs1pp_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ /* setup chip type = IPAC ! */
+
+ sc->sc_ipac = 1;
+ sc->sc_bfifolen = IPAC_BFIFO_LEN;
+
+ /* enable hscx/isac irq's */
+ IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0));
+
+ IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */
+ IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */
+ (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2));
+ IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x41); /* enable card interrupt */
+}
+
+#endif
+
+#endif /* (NISIC > 0) && defined(ELSA_QS1PCI) */
diff --git a/sys/i4b/layer1/i4b_hscx.c b/sys/i4b/layer1/i4b_hscx.c
new file mode 100644
index 0000000..ed80a51
--- /dev/null
+++ b/sys/i4b/layer1/i4b_hscx.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b - Siemens HSCX chip (B-channel) handling
+ * --------------------------------------------
+ *
+ * $Id: i4b_hscx.c,v 1.37 1998/12/05 18:04:38 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* doesn't matter in non-FreeBSD, config(8) d.t.r.t. */
+#endif
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+/*---------------------------------------------------------------------------*
+ * HSCX IRQ Handler
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_irq(register struct isic_softc *sc, u_char ista, int h_chan, u_char ex_irq)
+{
+ register isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+ u_char exir = 0;
+ int activity = -1;
+ u_char cmd = 0;
+
+ DBGL1(L1_H_IRQ, "isic_hscx_irq", ("%#x\n", ista));
+
+ if(ex_irq)
+ {
+ /* get channel extended irq reg */
+
+ exir = HSCX_READ(h_chan, H_EXIR);
+
+ if(exir & HSCX_EXIR_RFO)
+ {
+ chan->stat_RFO++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: receive data overflow\n"));
+ }
+
+ if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
+ {
+ chan->stat_XDU++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: xmit data underrun\n"));
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);
+
+ if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */
+ {
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
+ }
+ }
+
+ }
+
+ /* rx message end, end of frame */
+
+ if(ista & HSCX_ISTA_RME)
+ {
+ register int fifo_data_len;
+ u_char rsta;
+ int error = 0;
+
+ rsta = HSCX_READ(h_chan, H_RSTA);
+
+ if((rsta & 0xf0) != 0xa0)
+ {
+ if((rsta & HSCX_RSTA_VFR) == 0)
+ {
+ chan->stat_VFR++;
+ cmd |= (HSCX_CMDR_RHR);
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("received invalid Frame\n"));
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RDO)
+ {
+ chan->stat_RDO++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("receive data overflow\n"));
+ error++;
+ }
+
+ if((rsta & HSCX_RSTA_CRC) == 0)
+ {
+ chan->stat_CRC++;
+ cmd |= (HSCX_CMDR_RHR);
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("CRC check failed\n"));
+ error++;
+ }
+
+ if(rsta & HSCX_RSTA_RAB)
+ {
+ chan->stat_RAB++;
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("Receive message aborted\n"));
+ error++;
+ }
+ }
+
+ fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
+ ((sc->sc_bfifolen)-1));
+
+ if(fifo_data_len == 0)
+ fifo_data_len = sc->sc_bfifolen;
+
+ /* all error conditions checked, now decide and take action */
+
+ if(error == 0)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ fifo_data_len -= 1; /* last byte in fifo is RSTA ! */
+
+ if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);
+
+ cmd |= (HSCX_CMDR_RMC);
+ isic_hscx_cmd(sc, h_chan, cmd);
+ cmd = 0;
+
+ chan->in_len += fifo_data_len;
+ chan->rxcount += fifo_data_len;
+
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ activity = ACT_RX;
+
+ /* mark buffer ptr as unused */
+
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ else
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d\n", chan->in_len, fifo_data_len));
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
+ }
+ }
+ else
+ {
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ cmd |= (HSCX_CMDR_RMC);
+ }
+ }
+
+ /* rx fifo full */
+
+ if(ista & HSCX_ISTA_RPF)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ chan->rxcount += sc->sc_bfifolen;
+
+ if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
+ {
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len += sc->sc_bfifolen;
+ }
+ else
+ {
+ if(chan->bprot == BPROT_NONE)
+ {
+ /* setup mbuf data length */
+
+ chan->in_mbuf->m_len = chan->in_len;
+ chan->in_mbuf->m_pkthdr.len = chan->in_len;
+
+ if(sc->sc_trace & TRACE_B_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ /* move rx'd data to rx queue */
+
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+
+ (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit);
+
+ if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ /* alloc new buffer */
+
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n");
+
+ /* setup new data ptr */
+
+ chan->in_cbptr = chan->in_mbuf->m_data;
+
+ /* read data from HSCX fifo */
+
+ HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);
+
+ chan->in_cbptr += sc->sc_bfifolen;
+ chan->in_len = sc->sc_bfifolen;
+
+ chan->rxcount += sc->sc_bfifolen;
+ }
+ else
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RPF, in_len=%d\n", chan->in_len));
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ cmd |= (HSCX_CMDR_RHR);
+ }
+ }
+
+ /* command to release fifo space */
+
+ cmd |= HSCX_CMDR_RMC;
+ }
+
+ /* transmit fifo empty, new data can be written to fifo */
+
+ if(ista & HSCX_ISTA_XPR)
+ {
+ /*
+ * for a description what is going on here, please have
+ * a look at isic_bchannel_start() in i4b_bchan.c !
+ */
+
+ int activity = -1;
+ int len;
+ int nextlen;
+
+ DBGL1(L1_H_IRQ, "isic_hscx_irq", ("unit %d, chan %d - XPR, Tx Fifo Empty!\n", sc->sc_unit, h_chan));
+
+ if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */
+ {
+ IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
+
+ if(chan->out_mbuf_head == NULL)
+ {
+ chan->state &= ~HSCX_TX_ACTIVE;
+ (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit);
+ }
+ else
+ {
+ chan->state |= HSCX_TX_ACTIVE;
+ chan->out_mbuf_cur = chan->out_mbuf_head;
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+
+ if(chan->bprot == BPROT_NONE)
+ {
+ if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
+ activity = ACT_TX;
+ }
+ else
+ {
+ activity = ACT_TX;
+ }
+ }
+ }
+
+ len = 0;
+
+ while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
+ {
+ nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
+
+#ifdef NOTDEF
+ printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
+ chan->out_mbuf_head,
+ chan->out_mbuf_cur,
+ chan->out_mbuf_cur_ptr,
+ chan->out_mbuf_cur_len,
+ len,
+ next_len);
+#endif
+
+ isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */
+
+ HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
+ cmd |= HSCX_CMDR_XTF;
+
+ len += nextlen;
+ chan->txcount += nextlen;
+
+ chan->out_mbuf_cur_ptr += nextlen;
+ chan->out_mbuf_cur_len -= nextlen;
+
+ if(chan->out_mbuf_cur_len == 0)
+ {
+ if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
+ {
+ chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
+ chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
+
+ if(sc->sc_trace & TRACE_B_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_bcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
+ }
+ }
+ else
+ {
+ if (chan->bprot != BPROT_NONE)
+ cmd |= HSCX_CMDR_XME;
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_head = NULL;
+ }
+
+ }
+ }
+ }
+
+ if(cmd) /* is there a command for the HSCX ? */
+ {
+ isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */
+ }
+
+ /* call timeout handling routine */
+
+ if(activity == ACT_RX || activity == ACT_TX)
+ (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity);
+}
+
+/*---------------------------------------------------------------------------*
+ * HSCX initialization
+ *
+ * for telephony: extended transparent mode 1
+ * for raw hdlc: transparent mode 0
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_init(struct isic_softc *sc, int h_chan, int activate)
+{
+ isic_Bchan_t *chan = &sc->sc_chan[h_chan];
+
+ HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */
+
+ if(sc->sc_ipac)
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM1); /* IPAC clock mode 5 */
+ }
+ else
+ {
+ /* CCR1: Power Up, Clock Mode 5 */
+ HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */
+ HSCX_CCR1_CM2 | /* HSCX clock mode 5 */
+ HSCX_CCR1_CM0);
+ }
+
+ /* XAD1: Transmit Address Byte 1 */
+ HSCX_WRITE(h_chan, H_XAD1, 0xff);
+
+ /* XAD2: Transmit Address Byte 2 */
+ HSCX_WRITE(h_chan, H_XAD2, 0xff);
+
+ /* RAH2: Receive Address Byte High Reg. 2 */
+ HSCX_WRITE(h_chan, H_RAH2, 0xff);
+
+ /* XBCH: reset Transmit Byte Count High */
+ HSCX_WRITE(h_chan, H_XBCH, 0x00);
+
+ /* RLCR: reset Receive Length Check Register */
+ HSCX_WRITE(h_chan, H_RLCR, 0x00);
+
+ /* CCR2: set tx/rx clock shift bit 0 */
+ /* disable CTS irq, disable RIE irq*/
+ HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);
+
+ /* XCCR: tx bit count per time slot */
+ HSCX_WRITE(h_chan, H_XCCR, 0x07);
+
+ /* RCCR: rx bit count per time slot */
+ HSCX_WRITE(h_chan, H_RCCR, 0x07);
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ {
+ switch(h_chan)
+ {
+ case HSCX_CH_A: /* Prepare HSCX channel A */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x2f);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x2f);
+ break;
+
+ case HSCX_CH_B: /* Prepare HSCX channel B */
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x03);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x03);
+ break;
+ }
+ }
+ else /* IOM 1 setup */
+ {
+ /* TSAX: tx clock shift bits 1 & 2 */
+ /* tx time slot number */
+ HSCX_WRITE(h_chan, H_TSAX, 0x07);
+
+ /* TSAR: rx clock shift bits 1 & 2 */
+ /* rx time slot number */
+ HSCX_WRITE(h_chan, H_TSAR, 0x07);
+ }
+
+ if(activate)
+ {
+ if(chan->bprot == BPROT_RHDLC)
+ {
+ /* HDLC Frames, transparent mode 0 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
+ }
+ else
+ {
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
+ }
+ else
+ {
+ /* TSAX: tx time slot */
+ HSCX_WRITE(h_chan, H_TSAX, 0xff);
+
+ /* TSAR: rx time slot */
+ HSCX_WRITE(h_chan, H_TSAR, 0xff);
+
+ /* Raw Telephony, extended transparent mode 1 */
+ HSCX_WRITE(h_chan, H_MODE,
+ HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
+ }
+
+ /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
+ /* always disable RSC and TIN */
+
+ chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;
+
+ if(activate)
+ {
+ /* enable */
+ chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
+ }
+ else
+ {
+ /* disable */
+ chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
+ }
+
+ /* handle ICA, EXA, and EXB via interrupt mask of channel b */
+
+ if (h_chan == HSCX_CH_A)
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
+ HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+ else
+ {
+ if (activate)
+ HSCX_B_IMASK &= ~HSCX_MASK_EXB;
+ else
+ HSCX_B_IMASK |= HSCX_MASK_EXB;
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+
+ /* clear spurious interrupts left over */
+
+ if(h_chan == HSCX_CH_A)
+ {
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ }
+ else /* mask ICA, because it must not be cleared by reading ISTA */
+ {
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
+ HSCX_READ(h_chan, H_EXIR);
+ HSCX_READ(h_chan, H_ISTA);
+ HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * write command to HSCX command register
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_cmd(struct isic_softc *sc, int h_chan, unsigned char cmd)
+{
+ int timeout = 20;
+
+ while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
+ {
+ DELAY(10);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ DBGL1(L1_H_ERR, "isic_hscx_cmd", ("HSCX wait for CEC timeout!\n"));
+ }
+
+ HSCX_WRITE(h_chan, H_CMDR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * wait for HSCX transmit FIFO write enable
+ *---------------------------------------------------------------------------*/
+void
+isic_hscx_waitxfw(struct isic_softc *sc, int h_chan)
+{
+#define WAITVAL 50
+#define WAITTO 200
+
+ int timeout = WAITTO;
+
+ while((!(((HSCX_READ(h_chan, H_STAR)) &
+ (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
+ {
+ DELAY(WAITVAL);
+ timeout--;
+ }
+
+ if(timeout == 0)
+ {
+ DBGL1(L1_H_ERR, "isic_hscx_waitxfw", ("HSCX wait for XFW timeout!\n"));
+ }
+ else if (timeout != WAITTO)
+ {
+ DBGL1(L1_H_XFRERR, "isic_hscx_waitxfw", ("HSCX wait for XFW time: %d uS\n", (WAITTO-timeout)*50));
+ }
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_hscx.h b/sys/i4b/layer1/i4b_hscx.h
new file mode 100644
index 0000000..1b1640d
--- /dev/null
+++ b/sys/i4b/layer1/i4b_hscx.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_hscx.h,v 1.3 1998/02/13 17:00:31 hm Exp $
+ *
+ * last edit-date: [Thu Feb 5 13:38:50 1998]
+ *
+ * -hm added AVM config register defs
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_HSCX_H_
+#define I4B_HSCX_H_
+
+enum HSCX_VERSIONS {
+ HSCX_VA1, /* 82525 A1 */
+ HSCX_UNKN1, /* unknown 1 */
+ HSCX_VA2, /* 82525 A2 */
+ HSCX_UNKN3, /* unknown 3 */
+ HSCX_VA3, /* 82525 A3 */
+ HSCX_V21, /* 82525 2.1 */
+ HSCX_UNKN /* unknown version */
+};
+
+#define HSCX_CH_A 0 /* channel A */
+#define HSCX_CH_B 1 /* channel B */
+
+#define HSCX_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the HSCX ISDN chip.
+ */
+
+typedef struct hscx_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char hscx_fifo [HSCX_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char hscx_ista;
+ unsigned char hscx_star;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_exir;
+ unsigned char hscx_rbcl;
+ unsigned char dummy_26;
+ unsigned char hscx_rsta;
+ unsigned char hscx_ral1;
+ unsigned char hscx_rhcr;
+ unsigned char dummy_2a;
+ unsigned char dummy_2b;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_rbch;
+ unsigned char hscx_vstr;
+ unsigned char hscx_ccr;
+ unsigned char dummy_30;
+ unsigned char dummy_31;
+ unsigned char dummy_32;
+ unsigned char dummy_33;
+ } hscx_r;
+ struct {
+ unsigned char hscx_mask;
+ unsigned char hscx_cmdr;
+ unsigned char hscx_mode;
+ unsigned char hscx_timr;
+ unsigned char hscx_xad1;
+ unsigned char hscx_xad2;
+ unsigned char hscx_rah1;
+ unsigned char hscx_rah2;
+ unsigned char hscx_ral1;
+ unsigned char hscx_ral2;
+ unsigned char hscx_xbcl;
+ unsigned char hscx_bgr;
+ unsigned char hscx_ccr2;
+ unsigned char hscx_xbch;
+ unsigned char hscx_rlcr;
+ unsigned char hscx_ccr1;
+ unsigned char hscx_tsax;
+ unsigned char hscx_tsar;
+ unsigned char hscx_xccr;
+ unsigned char hscx_rccr;
+ } hscx_w;
+ } hscx_rw;
+} hscx_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* HSCX read registers */
+
+#define h_ista hscx_rw.hscx_r.hscx_ista
+#define H_ISTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ista)
+#define h_star hscx_rw.hscx_r.hscx_star
+#define H_STAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_star)
+#define h_mode hscx_rw.hscx_r.hscx_mode
+#define H_MODE REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_mode)
+#define h_timr hscx_rw.hscx_r.hscx_timr
+#define H_TIMR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_timr)
+#define h_exir hscx_rw.hscx_r.hscx_exir
+#define H_EXIR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_exir)
+#define h_rbcl hscx_rw.hscx_r.hscx_rbcl
+#define H_RBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbcl)
+#define h_rsta hscx_rw.hscx_r.hscx_rsta
+#define H_RSTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rsta)
+#define h_ral1 hscx_rw.hscx_r.hscx_ral1
+#define H_RAL1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ral1)
+#define h_rhcr hscx_rw.hscx_r.hscx_rhcr
+#define H_RHCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rhcr)
+#define h_ccr2 hscx_rw.hscx_r.hscx_ccr2
+#define H_CCR2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr2)
+#define h_rbch hscx_rw.hscx_r.hscx_rbch
+#define H_RBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbch)
+#define h_vstr hscx_rw.hscx_r.hscx_vstr
+#define H_VSTR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_vstr)
+#define h_ccr hscx_rw.hscx_r.hscx_ccr
+#define H_CCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr)
+
+/* HSCX write registers - for hscx_mode, hscx_timr, hscx_ral1, hscx_ccr2 */
+/* see read registers */
+
+#define h_mask hscx_rw.hscx_w.hscx_mask
+#define H_MASK REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_mask)
+#define h_cmdr hscx_rw.hscx_w.hscx_cmdr
+#define H_CMDR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_cmdr)
+#define h_xad1 hscx_rw.hscx_w.hscx_xad1
+#define H_XAD1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad1)
+#define h_xad2 hscx_rw.hscx_w.hscx_xad2
+#define H_XAD2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad2)
+#define h_rah1 hscx_rw.hscx_w.hscx_rah1
+#define H_RAH1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah1)
+#define h_rah2 hscx_rw.hscx_w.hscx_rah2
+#define H_RAH2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah2)
+#define h_ral2 hscx_rw.hscx_w.hscx_ral2
+#define H_RAL2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ral2)
+#define h_xbcl hscx_rw.hscx_w.hscx_xbcl
+#define H_XBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbcl)
+#define h_bgr hscx_rw.hscx_w.hscx_bgr
+#define H_BGR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_bgr)
+#define h_xbch hscx_rw.hscx_w.hscx_xbch
+#define H_XBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbch)
+#define h_rlcr hscx_rw.hscx_w.hscx_rlcr
+#define H_RLCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rlcr)
+#define h_ccr1 hscx_rw.hscx_w.hscx_ccr1
+#define H_CCR1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ccr1)
+#define h_tsax hscx_rw.hscx_w.hscx_tsax
+#define H_TSAX REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsax)
+#define h_tsar hscx_rw.hscx_w.hscx_tsar
+#define H_TSAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsar)
+#define h_xccr hscx_rw.hscx_w.hscx_xccr
+#define H_XCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xccr)
+#define h_rccr hscx_rw.hscx_w.hscx_rccr
+#define H_RCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rccr)
+
+#define HSCX_ISTA_RME 0x80
+#define HSCX_ISTA_RPF 0x40
+#define HSCX_ISTA_RSC 0x20
+#define HSCX_ISTA_XPR 0x10
+#define HSCX_ISTA_TIN 0x08
+#define HSCX_ISTA_ICA 0x04
+#define HSCX_ISTA_EXA 0x02
+#define HSCX_ISTA_EXB 0x01
+
+#define HSCX_MASK_RME 0x80
+#define HSCX_MASK_RPF 0x40
+#define HSCX_MASK_RSC 0x20
+#define HSCX_MASK_XPR 0x10
+#define HSCX_MASK_TIN 0x08
+#define HSCX_MASK_ICA 0x04
+#define HSCX_MASK_EXA 0x02
+#define HSCX_MASK_EXB 0x01
+
+#define HSCX_EXIR_XMR 0x80
+#define HSCX_EXIR_XDU 0x40
+#define HSCX_EXIR_PCE 0x20
+#define HSCX_EXIR_RFO 0x10
+#define HSCX_EXIR_CSC 0x08
+#define HSCX_EXIR_RFS 0x04
+
+/* the other bits are always 0 */
+
+#define HSCX_STAR_XDOV 0x80
+#define HSCX_STAR_XFW 0x40
+#define HSCX_STAR_XRNR 0x20
+#define HSCX_STAR_RRNR 0x10
+#define HSCX_STAR_RLI 0x08
+#define HSCX_STAR_CEC 0x04
+#define HSCX_STAR_CTS 0x02
+#define HSCX_STAR_WFA 0x01
+
+#define HSCX_CMDR_RMC 0x80
+#define HSCX_CMDR_RHR 0x40
+/* also known as XREP in transparent mode */
+#define HSCX_CMDR_RNR 0x20
+#define HSCX_CMDR_STI 0x10
+#define HSCX_CMDR_XTF 0x08
+#define HSCX_CMDR_XIF 0x04
+#define HSCX_CMDR_XME 0x02
+#define HSCX_CMDR_XRES 0x01
+
+#define HSCX_MODE_MDS1 0x80
+#define HSCX_MODE_MDS0 0x40
+#define HSCX_MODE_ADM 0x20
+#define HSCX_MODE_TMD 0x10
+#define HSCX_MODE_RAC 0x08
+#define HSCX_MODE_RTS 0x04
+#define HSCX_MODE_TRS 0x02
+#define HSCX_MODE_TLP 0x01
+
+#define HSCX_RSTA_VFR 0x80
+#define HSCX_RSTA_RDO 0x40
+#define HSCX_RSTA_CRC 0x20
+#define HSCX_RSTA_RAB 0x10
+#define HSCX_RSTA_HA1 0x08
+#define HSCX_RSTA_HA0 0x04
+#define HSCX_RSTA_CR 0x02
+#define HSCX_RSTA_LA 0x01
+
+#define HSCX_RSTA_MASK 0xf0 /* the interesting ones */
+
+/* only used in DMA mode */
+#define HSCX_XBCH_DMA 0x80
+#define HSCX_XBCH_NRM 0x40
+#define HSCX_XBCH_CAS 0x20
+#define HSCX_XBCH_XC 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_RBCH_DMA 0x80
+#define HSCX_RBCH_NRM 0x40
+#define HSCX_RBCH_CAS 0x20
+#define HSCX_RBCH_OV 0x10
+/* the rest are bits 11 thru 8 of the byte count */
+
+#define HSCX_VSTR_CD 0x80
+/* bits 6 thru 4 are 0 */
+/* bits 3 thru 0 are the version number */
+
+#define HSCX_RLCR_RC 0x80
+/* the rest of the bits are used to set the received length */
+
+#define HSCX_CCR1_PU 0x80
+/* bits 6 and 5 are SC1 SC0 */
+#define HSCX_CCR1_ODS 0x10
+#define HSCX_CCR1_ITF 0x08
+#define HSCX_CCR1_CM2 0x04
+#define HSCX_CCR1_CM1 0x02
+#define HSCX_CCR1_CM0 0x01
+
+/* for clock mode 5 */
+#define HSCX_CCR2_SOC2 0x80
+#define HSCX_CCR2_SOC1 0x40
+#define HSCX_CCR2_XCS0 0x20
+#define HSCX_CCR2_RCS0 0x10
+#define HSCX_CCR2_TIO 0x08
+#define HSCX_CCR2_CIE 0x04
+#define HSCX_CCR2_RIE 0x02
+#define HSCX_CCR2_DIV 0x01
+
+/* bits 7 thru 2 are TSNX */
+#define HSCX_TSAX_XCS2 0x02
+#define HSCX_TSAX_XCS1 0x01
+
+/* bits 7 thru 2 are TSNR */
+#define HSCX_TSAR_RCS2 0x02
+#define HSCX_TSAR_RCS1 0x01
+
+#endif /* I4B_HSCX_H_ */
diff --git a/sys/i4b/layer1/i4b_ipac.h b/sys/i4b/layer1/i4b_ipac.h
new file mode 100644
index 0000000..79d8bc9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_ipac.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ipac.h - definitions for the Siemens IPAC PSB2115 chip
+ * ==========================================================
+ *
+ * $Id: i4b_ipac.h,v 1.4 1998/12/05 18:04:39 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:50 1998]
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef _I4B_IPAC_H_
+#define _I4B_IPAC_H_
+
+#define IPAC_BFIFO_LEN 64 /* 64 bytes B-channel FIFO on chip */
+
+#define IPAC_HSCXA_OFF 0x00
+#define IPAC_HSCXB_OFF 0x40
+#define IPAC_ISAC_OFF 0x80
+#define IPAC_IPAC_OFF 0xc0
+
+/*
+ * definitions of registers and bits for the IPAC ISDN chip.
+ */
+
+typedef struct ipac_reg {
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_ista;
+ unsigned char ipac_id;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_arx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_r;
+ struct {
+ unsigned char ipac_conf;
+ unsigned char ipac_mask;
+ unsigned char ipac_dummy;
+ unsigned char ipac_acfg;
+ unsigned char ipac_aoe;
+ unsigned char ipac_atx;
+ unsigned char ipac_pita1;
+ unsigned char ipac_pita2;
+ unsigned char ipac_pota1;
+ unsigned char ipac_pota2;
+ unsigned char ipac_pcfg;
+ unsigned char ipac_scfg;
+ unsigned char ipac_timr2;
+ } ipac_w;
+ } ipac_rw;
+} ipac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* IPAC read registers */
+
+#define IPAC_CONF REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_conf)
+#define IPAC_ISTA REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_ista)
+#define IPAC_ID REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_id)
+#define IPAC_ACFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_acfg)
+#define IPAC_AOE REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_aoe)
+#define IPAC_ARX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_arx)
+#define IPAC_PITA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita1)
+#define IPAC_PITA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita2)
+#define IPAC_POTA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota1)
+#define IPAC_POTA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota2)
+#define IPAC_PCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pcfg)
+#define IPAC_SCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_scfg)
+#define IPAC_TIMR2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_timr2)
+
+/* IPAC write registers */
+
+#define IPAC_MASK REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_mask)
+#define IPAC_ATX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_atx)
+
+/* register bits */
+
+#define IPAC_CONF_AMP 0x80
+#define IPAC_CONF_CFS 0x40
+#define IPAC_CONF_TEM 0x20
+#define IPAC_CONF_PDS 0x10
+#define IPAC_CONF_IDH 0x08
+#define IPAC_CONF_SGO 0x04
+#define IPAC_CONF_ODS 0x02
+#define IPAC_CONF_IOF 0x01
+
+#define IPAC_ISTA_INT1 0x80
+#define IPAC_ISTA_INT0 0x40
+#define IPAC_ISTA_ICD 0x20
+#define IPAC_ISTA_EXD 0x10
+#define IPAC_ISTA_ICA 0x08
+#define IPAC_ISTA_EXA 0x04
+#define IPAC_ISTA_ICB 0x02
+#define IPAC_ISTA_EXB 0x01
+
+#define IPAC_MASK_INT1 0x80
+#define IPAC_MASK_INT0 0x40
+#define IPAC_MASK_ICD 0x20
+#define IPAC_MASK_EXD 0x10
+#define IPAC_MASK_ICA 0x08
+#define IPAC_MASK_EXA 0x04
+#define IPAC_MASK_ICB 0x02
+#define IPAC_MASK_EXB 0x01
+
+#define IPAC_ACFG_OD7 0x80
+#define IPAC_ACFG_OD6 0x40
+#define IPAC_ACFG_OD5 0x20
+#define IPAC_ACFG_OD4 0x10
+#define IPAC_ACFG_OD3 0x08
+#define IPAC_ACFG_OD2 0x04
+#define IPAC_ACFG_EL1 0x02
+#define IPAC_ACFG_EL2 0x01
+
+#define IPAC_AOE_OE7 0x80
+#define IPAC_AOE_OE6 0x40
+#define IPAC_AOE_OE5 0x20
+#define IPAC_AOE_OE4 0x10
+#define IPAC_AOE_OE3 0x08
+#define IPAC_AOE_OE2 0x04
+
+#define IPAC_ARX_AR7 0x80
+#define IPAC_ARX_AR6 0x40
+#define IPAC_ARX_AR5 0x20
+#define IPAC_ARX_AR4 0x10
+#define IPAC_ARX_AR3 0x08
+#define IPAC_ARX_AR2 0x04
+
+#define IPAC_ATX_AT7 0x80
+#define IPAC_ATX_AT6 0x40
+#define IPAC_ATX_AT5 0x20
+#define IPAC_ATX_AT4 0x10
+#define IPAC_ATX_AT3 0x08
+#define IPAC_ATX_AT2 0x04
+
+#define IPAC_PITA1_ENA 0x80
+#define IPAC_PITA1_DUDD 0x40
+
+#define IPAC_PITA2_ENA 0x80
+#define IPAC_PITA2_DUDD 0x40
+
+#define IPAC_POTA1_ENA 0x80
+#define IPAC_POTA1_DUDD 0x40
+
+#define IPAC_POTA2_ENA 0x80
+#define IPAC_POTA2_DUDD 0x40
+
+#define IPAC_PCFG_DPS 0x80
+#define IPAC_PCFG_ACL 0x40
+#define IPAC_PCFG_LED 0x20
+#define IPAC_PCFG_PLD 0x10
+#define IPAC_PCFG_FBS 0x08
+#define IPAC_PCFG_CSL2 0x04
+#define IPAC_PCFG_CSL1 0x02
+#define IPAC_PCFG_CSL0 0x01
+
+#define IPAC_SCFG_PRI 0x80
+#define IPAC_SCFG_TXD 0x40
+#define IPAC_SCFG_TLEN 0x20
+
+#define IPAC_TIMR2_TMD 0x80
+
+#endif /* _I4B_IPAC_H_ */
diff --git a/sys/i4b/layer1/i4b_isac.c b/sys/i4b/layer1/i4b_isac.c
new file mode 100644
index 0000000..4065c9a
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isac.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isac.c - i4b siemens isdn chipset driver ISAC handler
+ * ---------------------------------------------------------
+ *
+ * $Id: i4b_isac.c,v 1.28 1998/12/05 18:04:41 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:23:59 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* non-FreeBSD handles this via config(8) */
+#endif
+#if NISIC > 0
+
+#ifdef __FreeBSD__
+#include "opt_i4b.h"
+#endif
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir);
+static void isic_isac_ind_hdlr(register struct isic_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_irq(struct isic_softc *sc, int ista)
+{
+ register u_char c = 0;
+ DBGL1(L1_F_MSG, "isic_isac_irq", ("unit %d: ista = 0x%02x\n", sc->sc_unit, ista));
+
+ if(ista & ISAC_ISTA_EXI) /* extended interrupt */
+ {
+ c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
+ }
+
+ if(ista & ISAC_ISTA_RME) /* receive message end */
+ {
+ register int rest;
+ u_char rsta;
+
+ /* get rx status register */
+
+ rsta = ISAC_READ(I_RSTA);
+
+ if((rsta & ISAC_RSTA_MASK) != 0x20)
+ {
+ int error = 0;
+
+ if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: CRC error\n", sc->sc_unit));
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Data Overrun error\n", sc->sc_unit));
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Receive Aborted error\n", sc->sc_unit));
+ }
+
+ if(error == 0)
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: RME unknown error, RSTA = 0x%02x!\n", sc->sc_unit, rsta));
+
+ i4b_Dfreembuf(sc->sc_ibuf);
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
+ ISACCMDRWRDELAY();
+
+ return;
+ }
+
+ rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
+
+ if(rest == 0)
+ rest = ISAC_FIFO_LEN;
+
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
+ sc->sc_ib = sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
+ {
+ ISAC_RDFIFO(sc->sc_ib, rest);
+ sc->sc_ilen += rest;
+
+ sc->sc_ibuf->m_pkthdr.len =
+ sc->sc_ibuf->m_len = sc->sc_ilen;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled)
+ PH_Data_Ind(sc->sc_unit, sc->sc_ibuf);
+ else
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ else
+ {
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("RME, input buffer overflow!\n"));
+ i4b_Dfreembuf(sc->sc_ibuf);
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ }
+
+ if(ista & ISAC_ISTA_RPF) /* receive fifo full */
+ {
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
+ sc->sc_ib= sc->sc_ibuf->m_data;
+ else
+ panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
+ {
+ ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
+ sc->sc_ilen += ISAC_FIFO_LEN;
+ sc->sc_ib += ISAC_FIFO_LEN;
+ c |= ISAC_CMDR_RMC;
+ }
+ else
+ {
+ DBGL1(L1_I_ERR, "isic_isac_irq", ("RPF, input buffer overflow!\n"));
+ i4b_Dfreembuf(sc->sc_ibuf);
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+ }
+
+ if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */
+ {
+ if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
+ {
+ sc->sc_freeflag = sc->sc_freeflag2;
+ sc->sc_obuf = sc->sc_obuf2;
+ sc->sc_op = sc->sc_obuf->m_data;
+ sc->sc_ol = sc->sc_obuf->m_len;
+ sc->sc_obuf2 = NULL;
+#ifdef NOTDEF
+ printf("ob2=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+ else
+ {
+#ifdef NOTDEF
+ printf("ob=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+
+ if(sc->sc_obuf)
+ {
+ ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
+
+ if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */
+ {
+ sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
+ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
+ c |= ISAC_CMDR_XTF; /* set XTF bit */
+ }
+ else
+ {
+ if(sc->sc_freeflag)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_freeflag = 0;
+ }
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+ }
+ else
+ {
+ sc->sc_state &= ~ISAC_TX_ACTIVE;
+ }
+ }
+
+ if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */
+ {
+ register u_char ci;
+
+ /* get command/indication rx register*/
+
+ ci = ISAC_READ(I_CIRR);
+
+ /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
+
+ if(ci & ISAC_CIRR_SQC)
+ (void) ISAC_READ(I_SQRR);
+
+ /* C/I code change IRQ (flag already cleared by CIRR read) */
+
+ if(ci & ISAC_CIRR_CIC0)
+ isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
+ }
+
+ if(c)
+ {
+ ISAC_WRITE(I_CMDR, c);
+ ISACCMDRWRDELAY();
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Extended IRQ handler
+ *---------------------------------------------------------------------------*/
+static u_char
+isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Message Repeat\n"));
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Data Underrun\n"));
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Protocol Error\n"));
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Rx Frame Overflow\n"));
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Sync Xfer Overflow\n"));
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ DBGL1(L1_I_ERR, "L1 isic_isac_exir_hdlr", ("EXIRQ Monitor Status\n"));
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Subscriber Awake\n"));
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Watchdog Timer Overflow\n"));
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+isic_isac_ind_hdlr(register struct isic_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI8 in state %s\n", isic_printstate(sc)));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI10 in state %s\n", isic_printstate(sc)));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ isic_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx RSY in state %s\n", isic_printstate(sc)));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx PU in state %s\n", isic_printstate(sc)));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DR in state %s\n", isic_printstate(sc)));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DID in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_IDLE);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DIS in state %s\n", isic_printstate(sc)));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx EI in state %s\n", isic_printstate(sc)));
+ isic_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ARD in state %s\n", isic_printstate(sc)));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx TI in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ATI in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx SD in state %s\n", isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+
+ default:
+ DBGL1(L1_I_ERR, "isic_isac_ind_hdlr", ("UNKNOWN Indication 0x%x in state %s\n", ind, isic_printstate(sc)));
+ event = EV_INFO0;
+ break;
+ }
+ isic_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+isic_isac_l1_cmd(struct isic_softc *sc, int command)
+{
+ u_char cmd;
+
+#ifdef I4B_SMP_WORKAROUND
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+ /*
+ * patch from Wolfgang Helbig:
+ *
+ * Here is a patch that makes i4b work on an SMP:
+ * The card (TELES 16.3) didn't interrupt on an SMP machine.
+ * This is a gross workaround, but anyway it works *and* provides
+ * some information as how to finally fix this problem.
+ */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+#endif /* I4B_SMP_WORKAROUND */
+
+ if(command < 0 || command > CMD_ILL)
+ {
+ DBGL1(L1_I_ERR, "isic_isac_l1_cmd", ("illegal cmd 0x%x in state %s\n", command, isic_printstate(sc)));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx TIM in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx RS in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR8 in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR10 in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx DIU in state %s\n", isic_printstate(sc)));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+isic_isac_init(struct isic_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-1 mode\n"));
+
+ /* ADF2: Select mode IOM-1 */
+ ISAC_WRITE(I_ADF2, 0x00);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SAC - SIP port high Z
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 and B2 switched to/from SPa
+ */
+ ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);
+
+ /* SQXR: S/Q channel xmit register:
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * CFS - IOM clock/frame always active
+ * FSC1/2 - polarity of 8kHz strobe
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+ else
+ {
+ DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-2 mode\n"));
+
+ /* ADF2: Select mode IOM-2 */
+ ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
+ */
+ ISAC_WRITE(I_SPCR, 0x00);
+
+ /* SQXR: S/Q channel xmit register:
+ * IDC - IOM direction = 0 (master)
+ * CFS - Config Select = 0 (clock always active)
+ * CI1E - C/I channel 1 IRQ enable = 0
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * IOF - IOM i/f off = 0
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, 0x00);
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+
+#ifdef NOTDEF
+ /*
+ * XXX a transmitter reset causes an ISAC tx IRQ which will not
+ * be serviced at attach time under some circumstances leaving
+ * the associated IRQ line on the ISA bus active. This prevents
+ * any further interrupts to be serviced because no low -> high
+ * transition can take place anymore. (-hm)
+ */
+
+ /* command register:
+ * RRES - HDLC receiver reset
+ * XRES - transmitter reset
+ */
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
+ ISACCMDRWRDELAY();
+#endif
+
+ /* enabled interrupts:
+ * ===================
+ * RME - receive message end
+ * RPF - receive pool full
+ * XPR - transmit pool ready
+ * CISQ - CI or S/Q channel change
+ * EXI - extended interrupt
+ */
+
+ ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */
+ ISAC_MASK_TIN | /* timer irq */
+ ISAC_MASK_SIN; /* sync xfer irq */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ return(0);
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_isac.h b/sys/i4b/layer1/i4b_isac.h
new file mode 100644
index 0000000..56a4241
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isac.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * $Id: i4b_isac.h,v 1.5 1998/03/28 15:11:03 hm Exp $
+ *
+ * last edit-date: [Fri Mar 27 15:52:40 1998]
+ *
+ * -hm split up for rewrite of Siemens chipset driver
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef I4B_ISAC_H_
+#define I4B_ISAC_H_
+
+/*
+ * The ISAC databook specifies a delay of 2.5 DCL clock cycles between
+ * writes to the ISAC command register CMDR. This is the delay used to
+ * satisfy this requirement.
+ */
+
+#define I4B_ISAC_CMDRWRDELAY 30
+
+#if (I4B_ISAC_CMDRWRDELAY > 0)
+#define ISACCMDRWRDELAY() DELAY(I4B_ISAC_CMDRWRDELAY)
+#else
+#warning "I4B_ISAC_CMDRWRDELAY set to 0!"
+#define ISACCMDRWRDELAY()
+#endif
+
+enum ISAC_VERSIONS {
+ ISAC_VA, /* 2085 A1 or A2, 2086/2186 V1.1 */
+ ISAC_VB1, /* 2085 B1 */
+ ISAC_VB2, /* 2085 B2 */
+ ISAC_VB3, /* 2085 B3/V2.3 */
+ ISAC_UNKN /* unknown version */
+};
+
+#define ISAC_FIFO_LEN 32 /* 32 bytes FIFO on chip */
+
+/*
+ * definitions of registers and bits for the ISAC ISDN chip.
+ */
+
+typedef struct isac_reg {
+
+ /* 32 byte deep FIFO always first */
+
+ unsigned char isac_fifo [ISAC_FIFO_LEN];
+
+ /* most registers can be read/written, but have different names */
+ /* so define a union with read/write names to make that clear */
+
+ union {
+ struct {
+ unsigned char isac_ista;
+ unsigned char isac_star;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_exir;
+ unsigned char isac_rbcl;
+ unsigned char isac_sapr;
+ unsigned char isac_rsta;
+ unsigned char dummy_28;
+ unsigned char isac_rhcr;
+ unsigned char isac_rbch;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cirr;
+ unsigned char isac_mor;
+ unsigned char isac_sscr;
+ unsigned char isac_sfcr;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_b1cr;
+ unsigned char isac_b2cr;
+ unsigned char isac_adf2;
+ unsigned char isac_mosr;
+ unsigned char isac_sqrr;
+ } isac_r;
+ struct {
+ unsigned char isac_mask;
+ unsigned char isac_cmdr;
+ unsigned char isac_mode;
+ unsigned char isac_timr;
+ unsigned char isac_xad1;
+ unsigned char isac_xad2;
+ unsigned char isac_sap1;
+ unsigned char isac_sap2;
+ unsigned char isac_tei1;
+ unsigned char isac_tei2;
+ unsigned char dummy_2a;
+ unsigned char isac_star2;
+ unsigned char dummy_2c;
+ unsigned char dummy_2d;
+ unsigned char dummy_2e;
+ unsigned char dummt_2f;
+ unsigned char isac_spcr;
+ unsigned char isac_cixr;
+ unsigned char isac_mox;
+ unsigned char isac_sscx;
+ unsigned char isac_sfcw;
+ unsigned char isac_c1r;
+ unsigned char isac_c2r;
+ unsigned char isac_stcr;
+ unsigned char isac_adf1;
+ unsigned char isac_adf2;
+ unsigned char isac_mocr;
+ unsigned char isac_sqxr;
+ } isac_w;
+ } isac_rw;
+} isac_reg_t;
+
+#define REG_OFFSET(type, field) (int)(&(((type *)0)->field))
+
+/* ISAC read registers */
+
+#define i_ista isac_rw.isac_r.isac_ista
+#define I_ISTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_ista)
+#define i_star isac_rw.isac_r.isac_star
+#define I_STAR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star)
+#define i_mode isac_rw.isac_r.isac_mode
+#define I_MODE REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mode)
+#define i_timr isac_rw.isac_r.isac_timr
+#define I_TIMR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_timr)
+#define i_exir isac_rw.isac_r.isac_exir
+#define I_EXIR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_exir)
+#define i_rbcl isac_rw.isac_r.isac_rbcl
+#define I_RBCL REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbcl)
+#define i_sapr isac_rw.isac_r.isac_sapr
+#define I_SAPR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sapr)
+#define i_rsta isac_rw.isac_r.isac_rsta
+#define I_RSTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rsta)
+#define i_rhcr isac_rw.isac_r.isac_rhcr
+#define I_RHCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rhcr)
+#define i_rbch isac_rw.isac_r.isac_rbch
+#define I_RBCH REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbch)
+#define i_star2 isac_rw.isac_r.isac_star2
+#define I_STAR2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star2)
+#define i_spcr isac_rw.isac_r.isac_spcr
+#define I_SPCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_spcr)
+#define i_cirr isac_rw.isac_r.isac_cirr
+#define I_CIRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_cirr)
+#define i_mor isac_rw.isac_r.isac_mor
+#define I_MOR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mor)
+#define i_sscr isac_rw.isac_r.isac_sscr
+#define I_SSCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sscr)
+#define i_sfcr isac_rw.isac_r.isac_sfcr
+#define I_SFCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sfcr)
+#define i_c1r isac_rw.isac_r.isac_c1r
+#define I_C1R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c1r)
+#define i_c2r isac_rw.isac_r.isac_c2r
+#define I_C2R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c2r)
+#define i_b1cr isac_rw.isac_r.isac_b1cr
+#define I_B1CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b1cr)
+#define i_b2cr isac_rw.isac_r.isac_b2cr
+#define I_B2CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b2cr)
+#define i_adf2 isac_rw.isac_r.isac_adf2
+#define I_ADF2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_adf2)
+#define i_mosr isac_rw.isac_r.isac_mosr
+#define I_MOSR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mosr)
+#define i_sqrr isac_rw.isac_r.isac_sqrr
+#define I_SQRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sqrr)
+
+/* ISAC write registers - isac_mode, isac_timr, isac_star2, isac_spcr, */
+/* isac_c1r, isac_c2r, isac_adf2 see read registers */
+
+#define i_mask isac_rw.isac_w.isac_mask
+#define I_MASK REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mask)
+#define i_cmdr isac_rw.isac_w.isac_cmdr
+#define I_CMDR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cmdr)
+#define i_xad1 isac_rw.isac_w.isac_xad1
+#define I_XAD1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad1)
+#define i_xad2 isac_rw.isac_w.isac_xad2
+#define I_XAD2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad2)
+#define i_sap1 isac_rw.isac_w.isac_sap1
+#define I_SAP1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap1)
+#define i_sap2 isac_rw.isac_w.isac_sap2
+#define I_SAP2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap2)
+#define i_tei1 isac_rw.isac_w.isac_tei1
+#define i_tei2 isac_rw.isac_w.isac_tei2
+#define i_cixr isac_rw.isac_w.isac_cixr
+#define I_CIXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cixr)
+#define I_CIX0 I_CIXR
+#define i_mox isac_rw.isac_w.isac_mox
+#define I_MOX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mox)
+#define i_sscx isac_rw.isac_w.isac_sscx
+#define I_SSCX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sscx)
+#define i_sfcw isac_rw.isac_w.isac_sfcw
+#define I_SFCW REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sfcw)
+#define i_stcr isac_rw.isac_w.isac_stcr
+#define I_STCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_stcr)
+#define i_adf1 isac_rw.isac_w.isac_adf1
+#define I_ADF1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_adf1)
+#define i_mocr isac_rw.isac_w.isac_mocr
+#define I_MOCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mocr)
+#define i_sqxr isac_rw.isac_w.isac_sqxr
+#define I_SQXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sqxr)
+
+#define ISAC_ISTA_RME 0x80
+#define ISAC_ISTA_RPF 0x40
+#define ISAC_ISTA_RSC 0x20
+#define ISAC_ISTA_XPR 0x10
+#define ISAC_ISTA_TIN 0x08
+#define ISAC_ISTA_CISQ 0x04
+#define ISAC_ISTA_SIN 0x02
+#define ISAC_ISTA_EXI 0x01
+
+#define ISAC_MASK_RME 0x80
+#define ISAC_MASL_RPF 0x40
+#define ISAC_MASK_RSC 0x20
+#define ISAC_MASK_XPR 0x10
+#define ISAC_MASK_TIN 0x08
+#define ISAC_MASK_CISQ 0x04
+#define ISAC_MASK_SIN 0x02
+#define ISAC_MASK_EXI 0x01
+#define ISAC_MASK_ALL 0xff
+
+#define ISAC_STAR_XDOV 0x80
+#define ISAC_STAR_XFW 0x40
+#define ISAC_STAR_XRNR 0x20
+#define ISAC_STAR_RRNR 0x10
+#define ISAC_STAR_MBR 0x08
+#define ISAC_STAR_MAC1 0x04
+#define ISAC_STAR_BVS 0x02
+#define ISAC_STAR_MAC0 0x01
+
+#define ISAC_CMDR_RMC 0x80
+#define ISAC_CMDR_RRES 0x40
+#define ISAC_CMDR_RNR 0x20
+#define ISAC_CMDR_STI 0x10
+#define ISAC_CMDR_XTF 0x08
+#define ISAC_CMDR_XIF 0x04
+#define ISAC_CMDR_XME 0x02
+#define ISAC_CMDR_XRES 0x01
+
+#define ISAC_MODE_MDS2 0x80
+#define ISAC_MODE_MDS1 0x40
+#define ISAC_MODE_MDS0 0x20
+#define ISAC_MODE_TMD 0x10
+#define ISAC_MODE_RAC 0x08
+#define ISAC_MODE_DIM2 0x04
+#define ISAC_MODE_DIM1 0x02
+#define ISAC_MODE_DIM0 0x01
+
+#define ISAC_EXIR_XMR 0x80
+#define ISAC_EXIR_XDU 0x40
+#define ISAC_EXIR_PCE 0x20
+#define ISAC_EXIR_RFO 0x10
+#define ISAC_EXIR_SOV 0x08
+#define ISAC_EXIR_MOS 0x04
+#define ISAC_EXIR_SAW 0x02
+#define ISAC_EXIR_WOV 0x01
+
+#define ISAC_RSTA_RDA 0x80
+#define ISAC_RSTA_RDO 0x40
+#define ISAC_RSTA_CRC 0x20
+#define ISAC_RSTA_RAB 0x10
+#define ISAC_RSTA_SA1 0x08
+#define ISAC_RSTA_SA0 0x04
+#define ISAC_RSTA_CR 0x02
+#define ISAC_RSTA_TA 0x01
+
+#define ISAC_RSTA_MASK 0x70 /* the interesting bits */
+
+#define ISAC_RBCH_XAC 0x80
+#define ISAC_RBCH_VN1 0x40
+#define ISAC_RBCH_VN0 0x20
+#define ISAC_RBCH_OV 0x10
+/* the other 4 bits are the high bits of the receive byte count */
+
+#define ISAC_SPCR_SPU 0x80
+#define ISAC_SPCR_SAC 0x40
+#define ISAC_SPCR_SPM 0x20
+#define ISAC_SPCR_TLP 0x10
+#define ISAC_SPCR_C1C1 0x08
+#define ISAC_SPCR_C1C0 0x04
+#define ISAC_SPCR_C2C1 0x02
+#define ISAC_SPCR_C2C0 0x01
+
+#define ISAC_CIRR_SQC 0x80
+#define ISAC_CIRR_BAS 0x40
+/* bits 5-2 CODR */
+#define ISAC_CIRR_CIC0 0x02
+/* bit 0 is always 0 */
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the indications */
+#define ISAC_CIRR_IPU 0x07
+#define ISAC_CIRR_IDR 0x00
+#define ISAC_CIRR_ISD 0x02
+#define ISAC_CIRR_IDIS 0x03
+#define ISAC_CIRR_IEI 0x06
+#define ISAC_CIRR_IRSY 0x04
+#define ISAC_CIRR_IARD 0x08
+#define ISAC_CIRR_ITI 0x0a
+#define ISAC_CIRR_IATI 0x0b
+#define ISAC_CIRR_IAI8 0x0c
+#define ISAC_CIRR_IAI10 0x0d
+#define ISAC_CIRR_IDID 0x0f
+
+#define ISAC_CI_MASK 0x0f
+
+#define ISAC_CIXR_RSS 0x80
+#define ISAC_CIXR_BAC 0x40
+/* bits 5-2 CODX */
+#define ISAC_CIXR_TCX 0x02
+#define ISAC_CIXR_ECX 0x01
+/* in IOM-2 mode the low bits are always 1 */
+#define ISAC_CIX0_LOW 0x03
+/* C/I codes from bits 5-2 (>> 2 & 0xf) */
+/* the commands */
+#define ISAC_CIXR_CTIM 0
+#define ISAC_CIXR_CRS 0x01
+#define ISAC_CIXR_CSCZ 0x04
+#define ISAC_CIXR_CSSZ 0x02
+#define ISAC_CIXR_CAR8 0x08
+#define ISAC_CIXR_CAR10 0x09
+#define ISAC_CIXR_CARL 0x0a
+#define ISAC_CIXR_CDIU 0x0f
+
+#define ISAC_STCR_TSF 0x80
+#define ISAC_STCR_TBA2 0x40
+#define ISAC_STCR_TBA1 0x20
+#define ISAC_STCR_TBA0 0x10
+#define ISAC_STCR_ST1 0x08
+#define ISAC_STCR_ST0 0x04
+#define ISAC_STCR_SC1 0x02
+#define ISAC_STCR_SC0 0x01
+
+#define ISAC_ADF1_WTC1 0x80
+#define ISAC_ADF1_WTC2 0x40
+#define ISAC_ADF1_TEM 0x20
+#define ISAC_ADF1_PFS 0x10
+#define ISAC_ADF1_CFS 0x08
+#define ISAC_ADF1_FC2 0x04
+#define ISAC_ADF1_FC1 0x02
+#define ISAC_ADF1_ITF 0x01
+
+#define ISAC_ADF2_IMS 0x80
+/* all other bits are 0 */
+
+/* bits 7-5 are always 0 */
+#define ISAC_SQRR_SYN 0x10
+#define ISAC_SQRR_SQR1 0x08
+#define ISAC_SQRR_SQR2 0x04
+#define ISAC_SQRR_SQR3 0x02
+#define ISAC_SQRR_SQR4 0x01
+
+#define ISAC_SQXR_IDC 0x80
+#define ISAC_SQXR_CFS 0x40
+#define ISAC_SQXR_CI1E 0x20
+#define ISAC_SQXR_SQIE 0x10
+#define ISAC_SQXR_SQX1 0x08
+#define ISAC_SQXR_SQX2 0x04
+#define ISAC_SQXR_SQX3 0x02
+#define ISAC_SQXR_SQX4 0x01
+
+#endif /* I4B_ISAC_H_ */
diff --git a/sys/i4b/layer1/i4b_isic.c b/sys/i4b/layer1/i4b_isic.c
new file mode 100644
index 0000000..922df79
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic.c - global isic stuff
+ * ==============================
+ *
+ * $Id: i4b_isic.c,v 1.44 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 12:14:07 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <sys/device.h>
+#if defined(__NetBSD__) && defined(amiga)
+#include <machine/bus.h>
+#else
+#include <dev/isa/isavar.h>
+#endif
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+void isic_settrace(int unit, int val);
+int isic_gettrace(int unit);
+
+#ifdef __FreeBSD__
+void isicintr_sc(struct isic_softc *sc);
+#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+void isicintr(int unit);
+#endif
+#else
+/* XXX - hack, going away soon! */
+struct isic_softc *isic_sc[ISIC_MAXUNIT];
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+void
+isicintr_sc(struct isic_softc *sc)
+{
+ isicintr(sc->sc_unit);
+}
+
+void
+isicintr(int unit)
+{
+ register struct isic_softc *sc = &isic_sc[unit];
+#else
+int
+isicintr(void *arg)
+{
+ struct isic_softc *sc = arg;
+#endif
+
+ if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */
+ {
+ u_char was_hscx_irq = 0;
+ u_char was_isac_irq = 0;
+
+ register u_char hscx_irq_stat;
+ register u_char isac_irq_stat;
+
+ for(;;)
+ {
+ /* get hscx irq status from hscx b ista */
+ hscx_irq_stat =
+ HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
+
+ /* get isac irq status */
+ isac_irq_stat = ISAC_READ(I_ISTA);
+
+ /* do as long as there are pending irqs in the chips */
+ if(!hscx_irq_stat && !isac_irq_stat)
+ break;
+
+ if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
+ HSCX_ISTA_RSC | HSCX_ISTA_XPR |
+ HSCX_ISTA_TIN | HSCX_ISTA_EXB))
+ {
+ isic_hscx_irq(sc, hscx_irq_stat,
+ HSCX_CH_B,
+ hscx_irq_stat & HSCX_ISTA_EXB);
+ was_hscx_irq = 1;
+ }
+
+ if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
+ {
+ isic_hscx_irq(sc,
+ HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
+ HSCX_CH_A,
+ hscx_irq_stat & HSCX_ISTA_EXA);
+ was_hscx_irq = 1;
+ }
+
+ if(isac_irq_stat)
+ {
+ isic_isac_irq(sc, isac_irq_stat); /* isac handler */
+ was_isac_irq = 1;
+ }
+ }
+#ifndef amiga /* XXX should be: #if INTERUPTS_ARE_SHARED */
+#ifdef ELSA_QS1ISA
+ if(sc->sc_cardtyp != CARD_TYPEP_ELSAQS1ISA)
+ {
+#endif
+ if((was_hscx_irq == 0) && (was_isac_irq == 0))
+ DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from HSCX/ISAC!\n", sc->sc_unit));
+#ifdef ELSA_QS1ISA
+ }
+#endif
+#endif /* AMIGA */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+
+#ifdef ELSA_QS1ISA
+ DELAY(80);
+
+ if(sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA)
+ if (sc->clearirq)
+ {
+ sc->clearirq(sc);
+ }
+#else
+ DELAY(100);
+#endif
+
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+#ifndef __FreeBSD__
+ return(was_hscx_irq || was_isac_irq);
+#endif
+ }
+ else /* IPAC interrupt routine */
+ {
+ register u_char ipac_irq_stat;
+ register u_char was_ipac_irq = 0;
+
+ for(;;)
+ {
+ /* get global irq status */
+
+ ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
+
+ /* check hscx a */
+
+ if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
+ {
+ /* HSCX A interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
+ HSCX_CH_A,
+ ipac_irq_stat & IPAC_ISTA_EXA);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
+ {
+ /* HSCX B interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
+ HSCX_CH_B,
+ ipac_irq_stat & IPAC_ISTA_EXB);
+ was_ipac_irq = 1;
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD))
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ was_ipac_irq = 1;
+ }
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+ }
+
+ if(was_ipac_irq == 0)
+ DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from IPAC!\n", sc->sc_unit));
+
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+
+#ifndef __FreeBSD__
+ return(was_ipac_irq);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_settrace
+ *---------------------------------------------------------------------------*/
+void
+isic_settrace(int unit, int val)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ sc->sc_trace = val;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_gettrace
+ *---------------------------------------------------------------------------*/
+int
+isic_gettrace(int unit)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+ return(sc->sc_trace);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_recovery - try to recover from irq lockup
+ *---------------------------------------------------------------------------*/
+void
+isic_recover(struct isic_softc *sc)
+{
+ u_char byte;
+
+ /* get hscx irq status from hscx b ista */
+
+ byte = HSCX_READ(HSCX_CH_B, H_ISTA);
+
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: ISTA = 0x%x\n", byte));
+
+ if(byte & HSCX_ISTA_ICA)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: ISTA = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA)));
+
+ if(byte & HSCX_ISTA_EXB)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR)));
+
+ if(byte & HSCX_ISTA_EXA)
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR)));
+
+ /* get isac irq status */
+
+ byte = ISAC_READ(I_ISTA);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: ISTA = 0x%x\n", byte));
+
+ if(byte & ISAC_ISTA_EXI)
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: EXIR = 0x%x\n", (u_char)ISAC_READ(I_EXIR)));
+
+ if(byte & ISAC_ISTA_CISQ)
+ {
+ byte = ISAC_READ(I_CIRR);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: CISQ = 0x%x\n", byte));
+
+ if(byte & ISAC_CIRR_SQC)
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: SQRR = 0x%x\n", (u_char)ISAC_READ(I_SQRR)));
+ }
+
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX B: IMASK = 0x%x\n", HSCX_B_IMASK));
+ DBGL1(L1_ERROR, "isic_recover", ("HSCX A: IMASK = 0x%x\n", HSCX_A_IMASK));
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ DELAY(100);
+
+ DBGL1(L1_ERROR, "isic_recover", (" ISAC: IMASK = 0x%x\n", ISAC_IMASK));
+
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_isic_isa.c b/sys/i4b/layer1/i4b_isic_isa.c
new file mode 100644
index 0000000..c0e11b9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_isa.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic_isa.c - ISA bus interface
+ * ==================================
+ *
+ * $Id: i4b_isic_isa.c,v 1.14 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 12:00:26 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <sys/device.h>
+#if defined(__NetBSD__) && defined(amiga)
+#include <machine/bus.h>
+#else
+#include <dev/isa/isavar.h>
+#endif
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __FreeBSD__
+
+#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+void isicintr ( int unit );
+#endif
+
+void isicintr_sc(struct isic_softc *sc);
+
+static int isicprobe(struct isa_device *dev);
+int isicattach(struct isa_device *dev);
+
+struct isa_driver isicdriver = {
+ isicprobe,
+ isicattach,
+ "isic",
+ 0
+};
+
+int next_isic_unit = 0;
+struct isic_softc isic_sc[ISIC_MAXUNIT];
+
+#else
+
+#ifdef NetBSD1_3
+#if NetBSD1_3 < 2
+struct cfdriver isic_cd = {
+ NULL, "isic", DV_DULL
+};
+#endif
+#endif
+
+#if defined (__OpenBSD__)
+struct cfdriver isic_cd = {
+ NULL, "isic", DV_DULL
+};
+#endif
+
+#endif
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+extern void isic_settrace(int unit, int val); /*XXX*/
+extern int isic_gettrace(int unit); /*XXX*/
+
+#ifdef __FreeBSD__
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp device driver probe routine
+ *---------------------------------------------------------------------------*/
+static int
+isicprobe(struct isa_device *dev)
+{
+ int ret = 0;
+
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("isicprobe: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return(0);
+ }
+
+ switch(dev->id_flags)
+ {
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(dev);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_probe_s0163(dev);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_probe_avma1(dev);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_probe_usrtai(dev);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_probe_itkix1(dev);
+ break;
+#endif
+
+ default:
+ break;
+ }
+ return(ret);
+}
+
+#else
+
+/*---------------------------------------------------------------------------*
+ * isic - device driver probe routine, dummy for NetBSD/OpenBSD
+ *---------------------------------------------------------------------------*/
+int
+isicprobe(struct isic_attach_args *args)
+{
+ return 1;
+}
+
+#endif /* __FreeBSD__ */
+
+#ifdef __FreeBSD__
+
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp device driver attach routine
+ *---------------------------------------------------------------------------*/
+int
+isicattach(struct isa_device *dev)
+{
+ return(isic_realattach(dev, 0));
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - non-pnp and pnp device driver attach routine
+ *---------------------------------------------------------------------------*/
+int
+isic_realattach(struct isa_device *dev, unsigned int iobase2)
+
+#else /* ! __FreeBSD__ */
+
+int
+isicattach(int flags, struct isic_softc *sc)
+
+#endif /* __FreeBSD__ */
+{
+ int ret = 0;
+ char *drvid;
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#define PARM dev
+#define PARM2 dev, iobase2
+#define FLAGS dev->id_flags
+#else
+#define PARM sc
+#define PARM2 sc
+#define FLAGS flags
+#endif
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ /* done in bus specific attach code for other OS */
+
+#ifdef __FreeBSD__
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return(0);
+ }
+
+ sc->sc_unit = dev->id_unit;
+#else
+ isic_sc[sc->sc_unit] = sc;
+#endif
+
+ /* card dependent setup */
+ switch(FLAGS)
+ {
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_attach_Dyn(PARM2);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_attach_s08(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_attach_s016(PARM);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_attach_s0163(PARM);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_attach_avma1(PARM);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_attach_usrtai(PARM);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_attach_itkix1(PARM);
+ break;
+#endif
+
+/* ======================================================================
+ * Only P&P cards follow below!!!
+ */
+#ifdef __FreeBSD__ /* we've already splitted all non-ISA stuff
+ out of this ISA specific part for the other
+ OS */
+
+#ifdef AVM_PCMCIA
+ case FLAG_AVM_A1_PCMCIA:
+ ret = isic_attach_fritzpcmcia(PARM);
+ break;
+#endif
+
+#ifndef __FreeBSD__
+#ifdef TEL_S0_16_3_P
+ case FLAG_TELES_S0_163_PnP:
+ ret = isic_attach_s0163P(PARM2);
+ break;
+#endif
+#endif
+
+#ifdef CRTX_S0_P
+ case FLAG_CREATIX_S0_PnP:
+ ret = isic_attach_Cs0P(PARM2);
+ break;
+#endif
+
+#ifdef DRN_NGO
+ case FLAG_DRN_NGO:
+ ret = isic_attach_drnngo(PARM2);
+ break;
+#endif
+
+#ifdef SEDLBAUER
+ case FLAG_SWS:
+ ret = isic_attach_sws(PARM);
+ break;
+#endif
+
+#ifdef ELSA_QS1ISA
+ case FLAG_ELSA_QS1P_ISA:
+ ret = isic_attach_Eqs1pi(PARM2);
+ break;
+#endif
+
+#endif /* __FreeBSD__ / P&P specific part */
+
+/* --- XXX - don't know how to handle this - should be removed!!!! ---- */
+#ifdef amiga
+ case FLAG_BLMASTER:
+ ret = 1; /* full detection was done in caller */
+ break;
+#endif
+/* ------------------------------------------------------------------- */
+
+ default:
+ break;
+ }
+
+ if(ret == 0)
+ return(0);
+
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce manufacturer and card type */
+
+ switch(FLAGS)
+ {
+ case FLAG_TELES_S0_8:
+ drvid = "Teles S0/8 or Niccy 1008";
+ break;
+
+ case FLAG_TELES_S0_16:
+ drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
+ break;
+
+ case FLAG_TELES_S0_163:
+ drvid = "Teles S0/16.3";
+ break;
+
+ case FLAG_AVM_A1:
+ drvid = "AVM A1 or AVM Fritz!Card";
+ break;
+
+ case FLAG_AVM_A1_PCMCIA:
+ drvid = "AVM PCMCIA Fritz!Card";
+ break;
+
+ case FLAG_TELES_S0_163_PnP:
+ drvid = "Teles S0/PnP";
+ break;
+
+ case FLAG_CREATIX_S0_PnP:
+ drvid = "Creatix ISDN S0-16 P&P";
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ drvid = "USRobotics Sportster ISDN TA intern";
+ break;
+
+ case FLAG_DRN_NGO:
+ drvid = "Dr. Neuhaus NICCY Go@";
+ break;
+
+ case FLAG_DYNALINK:
+ drvid = "Dynalink IS64PH";
+ break;
+
+ case FLAG_SWS:
+ drvid = "Sedlbauer WinSpeed";
+ break;
+
+ case FLAG_BLMASTER:
+ /* board announcement was done by caller */
+ drvid = (char *)0;
+ break;
+
+ case FLAG_ELSA_QS1P_ISA:
+ drvid = "ELSA QuickStep 1000pro (ISA)";
+ break;
+
+ case FLAG_ITK_IX1:
+ drvid = "ITK ix1 micro";
+ break;
+
+ default:
+ drvid = "ERROR, unknown flag used";
+ break;
+ }
+#ifndef __FreeBSD__
+ printf("\n");
+#endif
+ if (drvid)
+ printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+#ifdef __FreeBSD__
+ printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
+#endif
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+#ifdef __FreeBSD__
+ printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);
+
+ next_isic_unit++;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003
+
+ /* set the interrupt handler - no need to change isa_device.h */
+ dev->id_intr = (inthand2_t *)isicintr;
+
+#endif
+
+#endif /* __FreeBSD__ */
+
+ return(1);
+#undef PARM
+#undef FLAGS
+}
+
+#endif /* NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_isic_pci.c b/sys/i4b/layer1/i4b_isic_pci.c
new file mode 100644
index 0000000..3aebf08
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pci.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic_pci.c - PCI bus interface
+ * ==================================
+ *
+ * $Id: i4b_isic_pci.c,v 1.9 1998/12/05 18:04:48 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:24:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "isic.h"
+
+#if defined(__FreeBSD__)
+#include "opt_i4b.h"
+#include "pci.h"
+#endif
+
+#if (NISIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#if __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#define PCI_QS1000_ID 0x10001048
+
+#define MEM0_MAPOFF 0
+#define PORT0_MAPOFF 4
+#define PORT1_MAPOFF 12
+
+static char* i4b_pci_probe(pcici_t tag, pcidi_t type);
+static void i4b_pci_attach(pcici_t config_id, int unit);
+static int isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2);
+
+static u_long i4b_pci_count = 0;
+
+static struct pci_device i4b_pci_driver = {
+ "isic",
+ i4b_pci_probe,
+ i4b_pci_attach,
+ &i4b_pci_count,
+ NULL
+};
+
+DATA_SET (pcidevice_set, i4b_pci_driver);
+
+static void isic_pci_intr_sc(struct isic_softc *sc);
+
+
+/*---------------------------------------------------------------------------*
+ * PCI probe routine
+ *---------------------------------------------------------------------------*/
+static char *
+i4b_pci_probe(pcici_t tag, pcidi_t type)
+{
+ switch(type)
+ {
+ case PCI_QS1000_ID:
+ return("ELSA QuickStep 1000pro PCI ISDN adaptor");
+ break;
+
+ default:
+ if(bootverbose)
+ printf("i4b_pci_probe: unknown PCI type %ul!\n", (u_int)type);
+ return(NULL);
+ }
+ return(NULL);
+}
+
+/*---------------------------------------------------------------------------*
+ * PCI attach routine
+ *---------------------------------------------------------------------------*/
+static void
+i4b_pci_attach(pcici_t config_id, int unit)
+{
+ unsigned short iobase1;
+ unsigned short iobase2;
+ unsigned long type;
+ struct isic_softc *sc = &isic_sc[unit];
+
+ if(unit != next_isic_unit)
+ {
+ printf("i4b_pci_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", unit, next_isic_unit);
+ return;
+ }
+
+ if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT0_MAPOFF, &iobase1)))
+ {
+ printf("i4b_pci_attach: pci_map_port 1 failed!\n");
+ return;
+ }
+
+ if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT1_MAPOFF, &iobase2)))
+ {
+ printf("i4b_pci_attach: pci_map_port 2 failed!\n");
+ return;
+ }
+
+ if(bootverbose)
+ printf("i4b_pci_attach: unit %d, port0 0x%x, port1 0x%x\n", unit, iobase1, iobase2);
+
+ type = pci_conf_read(config_id, PCI_ID_REG);
+
+ if((isic_pciattach(unit, type, iobase1, iobase2)) == 0)
+ return;
+
+ if(!(pci_map_int(config_id, (void *)isic_pci_intr_sc, (void *)sc, &net_imask)))
+ return;
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pci device driver attach routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2)
+{
+ int ret = 0;
+ struct isic_softc *sc = &isic_sc[unit];
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ switch(type)
+ {
+#ifdef ELSA_QS1PCI
+ case PCI_QS1000_ID:
+ ret = isic_attach_Eqs1pp(unit, iobase1, iobase2);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if(ret == 0)
+ return(ret);
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ sc->sc_unit = unit;
+
+ if(sc->sc_ipac)
+ {
+ ret = IPAC_READ(IPAC_ID);
+
+ switch(ret)
+ {
+ case 0x01:
+ printf("isic%d: IPAC PSB2115 Version 1.1\n", unit);
+ break;
+
+ default:
+ printf("isic%d: Error, IPAC version %d unknown!\n",
+ unit, ret);
+ return(0);
+ break;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ printf("isic%d: ISAC %s (IOM-%c)\n",
+ unit,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ break;
+
+ default:
+ printf("isic%d: Error, ISAC version %d unknown!\n",
+ unit, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ printf("isic%d: HSCX %s\n",
+ unit,
+ HSCXversion[sc->sc_hscx_version]);
+ break;
+
+ default:
+ printf("isic%d: Error, HSCX version %d unknown!\n",
+ unit, sc->sc_hscx_version);
+ return(0);
+ break;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ next_isic_unit++;
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - PCI device driver interrupt routine
+ *---------------------------------------------------------------------------*/
+static void
+isic_pci_intr_sc(struct isic_softc *sc)
+{
+ if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */
+ {
+ register u_char hscx_irq_stat;
+ register u_char isac_irq_stat;
+
+ for(;;)
+ {
+ /* get hscx irq status from hscx b ista */
+ hscx_irq_stat =
+ HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
+
+ /* get isac irq status */
+ isac_irq_stat = ISAC_READ(I_ISTA);
+
+ /* do as long as there are pending irqs in the chips */
+ if(!hscx_irq_stat && !isac_irq_stat)
+ break;
+
+ if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
+ HSCX_ISTA_RSC | HSCX_ISTA_XPR |
+ HSCX_ISTA_TIN | HSCX_ISTA_EXB))
+ {
+ isic_hscx_irq(sc, hscx_irq_stat,
+ HSCX_CH_B,
+ hscx_irq_stat & HSCX_ISTA_EXB);
+ }
+
+ if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
+ {
+ isic_hscx_irq(sc,
+ HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
+ HSCX_CH_A,
+ hscx_irq_stat & HSCX_ISTA_EXA);
+ }
+
+ if(isac_irq_stat)
+ { /* isac handler */
+ isic_isac_irq(sc, isac_irq_stat);
+ }
+ }
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+
+ DELAY(100);
+
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ }
+ else /* IPAC interrupt routine */
+ {
+ register u_char ipac_irq_stat;
+
+ for(;;)
+ {
+ /* get global irq status */
+
+ ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
+
+ /* do as long as there are pending irqs in the chip */
+ if(!ipac_irq_stat)
+ break;
+
+ /* check hscx a */
+
+ if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
+ {
+ /* HSCX A interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
+ HSCX_CH_A,
+ ipac_irq_stat & IPAC_ISTA_EXA);
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
+ {
+ /* HSCX B interrupt */
+ isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
+ HSCX_CH_B,
+ ipac_irq_stat & IPAC_ISTA_EXB);
+ }
+ if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD))
+ {
+ /* ISAC interrupt */
+ isic_isac_irq(sc, ISAC_READ(I_ISTA));
+ }
+ }
+
+ IPAC_WRITE(IPAC_MASK, 0xff);
+ DELAY(50);
+ IPAC_WRITE(IPAC_MASK, 0xc0);
+ }
+}
+
+#endif /* (NISIC > 0) && (NPCI > 0) */
+
diff --git a/sys/i4b/layer1/i4b_isic_pcmcia.c b/sys/i4b/layer1/i4b_isic_pcmcia.c
new file mode 100644
index 0000000..a1fb22a
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pcmcia.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1998 Matthias Apitz. All rights reserved.
+ *
+ * Copyright (c) 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic_pcmcia.c - i4b FreeBSD PCMCIA support
+ * ----------------------------------------------
+ *
+ * $Id: i4b_isic_pcmcia.c,v 1.3 1998/12/16 09:32:50 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 17:30:09 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "isic.h"
+#include "opt_i4b.h"
+#include "card.h"
+
+#if (NISIC > 0) && (NCARD > 0)
+
+#include "apm.h"
+#include <sys/param.h>
+#include <sys/select.h>
+#include <i386/isa/isa_device.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <pccard/cardinfo.h>
+#include <pccard/slot.h>
+#include <pccard/driver.h>
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+/*
+ * PC-Card (PCMCIA) specific code.
+ */
+static int isic_pccard_init __P((struct pccard_devinfo *));
+static void isic_unload __P((struct pccard_devinfo *));
+static int isic_card_intr __P((struct pccard_devinfo *));
+
+static struct pccard_device isic_info = {
+ "isic",
+ isic_pccard_init,
+ isic_unload,
+ isic_card_intr,
+ 0, /* Attributes - presently unused */
+ &net_imask
+};
+
+DATA_SET(pccarddrv_set, isic_info);
+
+/*
+ * Initialize the device - called from Slot manager.
+ */
+
+static int opened = 0; /* our cards status */
+
+static int isic_pccard_init(devi)
+struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ struct isic_softc *sc = &isic_sc[is->id_unit];
+
+ if ((1 << is->id_unit) & opened)
+ return(EBUSY);
+
+ opened |= 1 << is->id_unit;
+ printf("isic%d: PCMCIA init, irqmask = 0x%x (%d), iobase = 0x%x\n",
+ is->id_unit, is->id_irq, devi->slt->irq, is->id_iobase);
+
+#if 0
+ /* XXX: problems resolving isic_probe_avma1_pcmcia() /phk */
+ /*
+ * look if there is really an AVM PCMCIA Fritz!Card and
+ * setup the card specific stuff
+ */
+ isic_probe_avma1_pcmcia(is);
+#endif
+
+ /* ap:
+ * XXX what's to do with the return value?
+ */
+
+ /*
+ * try to attach the PCMCIA card as a normal A1 card
+ */
+ isicattach(is);
+ return(0);
+}
+
+static void isic_unload(devi)
+struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ printf("isic%d: unloaded\n", is->id_unit);
+ opened &= ~(1 << is->id_unit);
+}
+
+/*
+ * card_intr - Shared interrupt called from
+ * front end of PC-Card handler.
+ */
+static int isic_card_intr(devi)
+struct pccard_devinfo *devi;
+{
+ isicintr(devi->isahd.id_unit);
+ return(1);
+}
+
+#endif /* (NISIC > 0) && (NCARD > 0) */
+#endif /* __FreeBSD__ */
diff --git a/sys/i4b/layer1/i4b_isic_pnp.c b/sys/i4b/layer1/i4b_isic_pnp.c
new file mode 100644
index 0000000..ed1892d9
--- /dev/null
+++ b/sys/i4b/layer1/i4b_isic_pnp.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 1998 Eivind Eklund. All rights reserved.
+ *
+ * Copyright (c) 1998 German Tischler. All rights reserved.
+ *
+ * Copyright (c) 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_isic_pnp.c - i4b pnp support
+ * --------------------------------
+ *
+ * $Id: i4b_isic_pnp.c,v 1.15 1998/12/20 11:07:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 18 20:54:56 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+#include "pnp.h"
+#include "isic.h"
+#include "opt_i4b.h"
+
+#if (NISIC > 0) && (NPNP > 0)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+#include "ioconf.h"
+extern void isicintr(int unit); /* XXX this gives a compiler warning */
+ /* on one 2.2.7 machine but no */
+ /* warning on another one !? (-hm) */
+#endif
+
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300006)
+extern void isicintr(int unit);
+#endif
+
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/pnp.h>
+
+#include <i4b/include/i4b_global.h>
+#include <machine/i4b_ioctl.h>
+#include <i4b/layer1/i4b_l1.h>
+
+#define VID_TEL163PNP 0x10212750 /* Teles 16.3 PnP */
+#define VID_CREATIXPP 0x0000980e /* Creatix S0/16 P+P */
+#define VID_DYNALINK 0x88167506 /* Dynalink */
+#define VID_SEDLBAUER 0x0100274c /* Sedlbauer WinSpeed */
+#define VID_NICCYGO 0x5001814c /* Neuhaus Niccy GO@ */
+#define VID_ELSAQS1P 0x33019315 /* ELSA Quickstep1000pro*/
+
+static struct i4b_pnp_ids {
+ u_long vend_id;
+ char *id_str;
+} i4b_pnp_ids[] = {
+ { VID_TEL163PNP, "Teles 16.3 PnP" },
+ { VID_CREATIXPP, "Creatix S0/16 P+P" },
+ { VID_DYNALINK, "Dynalink IS64PH" },
+ { VID_SEDLBAUER, "Sedlbauer WinSpeed" },
+ { VID_NICCYGO, "Dr.Neuhaus Niccy Go@" },
+ { VID_ELSAQS1P, "ELSA QuickStep 1000pro"},
+ { 0 }
+};
+
+extern struct isa_driver isicdriver;
+
+static int isic_pnpprobe(struct isa_device *dev, unsigned int iobase2);
+static char *i4b_pnp_probe(u_long csn, u_long vend_id);
+static void i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev);
+
+static u_long ni4b_pnp = 0;
+
+static struct pnp_device i4b_pnp = {
+ "i4b_pnp",
+ i4b_pnp_probe,
+ i4b_pnp_attach,
+ &ni4b_pnp,
+ &net_imask
+};
+
+DATA_SET(pnpdevice_set, i4b_pnp);
+
+/*---------------------------------------------------------------------------*
+ * PnP probe routine
+ *---------------------------------------------------------------------------*/
+static char *
+i4b_pnp_probe(u_long csn, u_long vend_id)
+{
+ struct i4b_pnp_ids *ids;
+ char *string = NULL;
+
+ /* search table of knowd id's */
+
+ for(ids = i4b_pnp_ids; ids->vend_id != 0; ids++)
+ {
+ if(vend_id == ids->vend_id)
+ {
+ string = ids->id_str;
+ break;
+ }
+ }
+
+ if(string)
+ {
+ struct pnp_cinfo spci;
+
+ read_pnp_parms(&spci, 0);
+
+ if((spci.enable == 0) || (spci.flags & 0x01))
+ {
+ printf("CSN %d (%s) is disabled.\n", (int)csn, string);
+ return (NULL);
+ }
+ }
+ return(string);
+}
+
+/*---------------------------------------------------------------------------*
+ * PnP attach routine
+ *---------------------------------------------------------------------------*/
+static void
+i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
+{
+ struct pnp_cinfo spci;
+ struct isa_device *isa_devp;
+
+ if(dev->id_unit != next_isic_unit)
+ {
+ printf("i4b_pnp_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
+ return;
+ }
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n",
+ dev->id_unit, dev->id_unit, name);
+ return;
+ }
+
+ if(read_pnp_parms(&spci, 0) == 0)
+ {
+ printf("isic%d: read_pnp_parms error for %s\n",
+ dev->id_unit, name);
+ return;
+ }
+
+ if(bootverbose)
+ {
+ printf("isic%d: vendorid = 0x%08x port0 = 0x%04x, port1 = 0x%04x, irq = %d\n",
+ dev->id_unit, spci.vendor_id, spci.port[0], spci.port[1], spci.irq[0]);
+ }
+
+ dev->id_iobase = spci.port[0];
+ dev->id_irq = (1 << spci.irq[0]);
+ dev->id_intr = (inthand2_t *) isicintr;
+ dev->id_drq = -1;
+
+/* XXX add dev->id_alive init here ! ?? */
+
+ switch(spci.vendor_id)
+ {
+ case VID_TEL163PNP:
+ dev->id_flags = FLAG_TELES_S0_163_PnP;
+ break;
+ case VID_CREATIXPP:
+ dev->id_flags = FLAG_CREATIX_S0_PnP;
+ break;
+ case VID_DYNALINK:
+ dev->id_flags = FLAG_DYNALINK;
+ break;
+ case VID_SEDLBAUER:
+ dev->id_flags = FLAG_SWS;
+ break;
+ case VID_NICCYGO:
+ dev->id_flags = FLAG_DRN_NGO;
+ break;
+ case VID_ELSAQS1P:
+ dev->id_flags = FLAG_ELSA_QS1P_ISA;
+ break;
+ }
+
+ write_pnp_parms(&spci, 0);
+ enable_pnp_card();
+
+ if(dev->id_driver == NULL)
+ {
+ dev->id_driver = &isicdriver;
+
+ isa_devp = find_isadev(isa_devtab_net, &isicdriver, 0);
+
+ if(isa_devp != NULL)
+ {
+ dev->id_id = isa_devp->id_id;
+ }
+ }
+
+ if((dev->id_alive = isic_pnpprobe(dev, spci.port[1])) != 0)
+ {
+/* XXX dev->id_alive is the size of the port area used ! */
+ isic_realattach(dev, spci.port[1]);
+ }
+ else
+ {
+ printf("isic%d: probe failed!\n", dev->id_unit);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pnp device driver probe routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pnpprobe(struct isa_device *dev, unsigned int iobase2)
+{
+ int ret = 0;
+
+ switch(dev->id_flags)
+ {
+#ifndef __FreeBSD__
+#ifdef TEL_S0_16_3_P
+ case FLAG_TELES_S0_163_PnP:
+ ret = isic_probe_s0163P(dev, iobase2);
+ break;
+#endif
+#endif
+
+#ifdef CRTX_S0_P
+ case FLAG_CREATIX_S0_PnP:
+ ret = isic_probe_Cs0P(dev, iobase2);
+ break;
+#endif
+
+#ifdef DRN_NGO
+ case FLAG_DRN_NGO:
+ ret = isic_probe_drnngo(dev, iobase2);
+ break;
+#endif
+
+#ifdef SEDLBAUER
+ case FLAG_SWS:
+ ret = 8; /* pnp only, nothing to probe */
+ break;
+#endif
+
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_probe_Dyn(dev, iobase2);
+ break;
+#endif
+
+#ifdef ELSA_QS1ISA
+ case FLAG_ELSA_QS1P_ISA:
+ ret = isic_probe_Eqs1pi(dev, iobase2);
+ break;
+#endif
+ default:
+ break;
+ }
+ return(ret);
+}
+
+#endif /* (NISIC > 0) && (NPNP > 0) */
+#endif /* __FreeBSD__ */
diff --git a/sys/i4b/layer1/i4b_itk_ix1.c b/sys/i4b/layer1/i4b_itk_ix1.c
new file mode 100644
index 0000000..f7491cd
--- /dev/null
+++ b/sys/i4b/layer1/i4b_itk_ix1.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 1998 Martin Husemann <martin@rumolt.teuto.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_itk_ix1.c - ITK ix1 micro passive card driver for isdn4bsd
+ * --------------------------------------------------------------
+ *
+ * $Id: i4b_itk_ix1.c,v 1.1 1998/12/16 13:43:20 hm Exp $
+ *
+ * last edit-date: [Wed Dec 16 14:46:36 1998]
+ *
+ *---------------------------------------------------------------------------
+ *
+ * The ITK ix1 micro ISDN card is an ISA card with one region
+ * of four io ports mapped and a fixed irq all jumpered on the card.
+ * Access to the board is straight forward and simmilar to
+ * the ELSA and DYNALINK cards. If a PCI version of this card
+ * exists all we need is probably a pci-bus attachment, all
+ * this low level routines should work imediately.
+ *
+ * To reset the card:
+ * - write 0x01 to ITK_CONFIG
+ * - wait >= 10 ms
+ * - write 0x00 to ITK_CONFIG
+ *
+ * To read or write data:
+ * - write address to ITK_ALE port
+ * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port
+ * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40).
+ *
+ * XXX - A reasonable probe routine has to be written.
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(ITKIX1)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+
+#define ITK_ISAC_DATA 0
+#define ITK_HSCX_DATA 1
+#define ITK_ALE 2
+#define ITK_CONFIG 3
+#define ITK_IO_SIZE 4
+
+#define HSCXA 0
+#define HSCXB 0x40
+
+#ifndef __FreeBSD__
+static void itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
+static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
+static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
+static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
+#else
+static u_char itkix1_read_reg(u_char *base, u_int offset);
+static void itkix1_write_reg(u_char *base, u_int offset, u_int v);
+static void itkix1_read_fifo(void *base, const void *buf, size_t len);
+static void itkix1_write_fifo(void *base, const void *buf, size_t len);
+#endif
+
+/*
+ * Probe for card
+ */
+#ifdef __FreeBSD__
+int
+isic_probe_itkix1(struct isa_device *dev)
+{
+ u_int8_t hd, cd;
+ int ret;
+
+ hd = inb(dev->id_iobase + ITK_HSCX_DATA);
+ cd = inb(dev->id_iobase + ITK_CONFIG);
+
+ ret = (hd == 0 && cd == 0xfc);
+
+#define ITK_PROBE_DEBUG
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n",
+ hd, cd, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#else
+int
+isic_probe_itkix1(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t hd, cd;
+ int ret;
+
+ hd = bus_space_read_1(t, h, ITK_HSCX_DATA);
+ cd = bus_space_read_1(t, h, ITK_CONFIG);
+
+ ret = (hd == 0 && cd == 0xfc);
+
+#define ITK_PROBE_DEBUG
+#ifdef ITK_PROBE_DEBUG
+ printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n",
+ hd, cd, ret ? "succeeded" : "failed");
+ return 1;
+#else
+ return ret;
+#endif
+}
+#endif
+
+/*
+ * Attach card
+ */
+#ifdef __FreeBSD__
+int
+isic_attach_itkix1(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ sc->sc_irq = dev->id_irq;
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+ ISAC_BASE = (caddr_t) sc->sc_port;
+ HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
+ HSCX_B_BASE = (caddr_t) sc->sc_port + 2;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ outb((dev->id_iobase)+ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase)+ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+int isic_attach_itkix1(struct isic_softc *sc)
+{
+ /* setup access routines */
+ sc->clearirq = NULL;
+ sc->readreg = itkix1_read_reg;
+ sc->writereg = itkix1_write_reg;
+ sc->readfifo = itkix1_read_fifo;
+ sc->writefifo = itkix1_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_ITKIX1;
+
+ /* setup IOM bus type */
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for ITK ix1 micro\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return 0;
+ }
+
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0);
+ DELAY(SEC_DELAY / 10);
+ return 1;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_read_fifo(void *buf, const void *base, size_t len)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ insb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void
+itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_fifo(void *base, const void *buf, size_t len)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, 0);
+ outsb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB);
+ outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len);
+ break;
+ }
+}
+#else
+static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, 0);
+ bus_space_write_multi_1(t, h, ITK_ISAC_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB);
+ bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static void
+itkix1_write_reg(u_char *base, u_int offset, u_int v)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ outb(port+ITK_ISAC_DATA, (u_char)v);
+ break;
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ outb(port+ITK_HSCX_DATA, (u_char)v);
+ break;
+ }
+}
+#else
+static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ bus_space_write_1(t, h, ITK_ISAC_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ bus_space_write_1(t, h, ITK_HSCX_DATA, data);
+ break;
+ }
+}
+#endif
+
+#ifdef __FreeBSD__
+static u_char
+itkix1_read_reg(u_char *base, u_int offset)
+{
+ int port = (u_long)base & ~0x0003;
+ switch ((u_long)base & 3) {
+ case 0: /* ISAC */
+ outb(port+ITK_ALE, offset);
+ return (inb(port+ITK_ISAC_DATA));
+ case 1: /* HSCXA */
+ outb(port+ITK_ALE, HSCXA+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ case 2: /* HSCXB */
+ outb(port+ITK_ALE, HSCXB+offset);
+ return (inb(port+ITK_HSCX_DATA));
+ }
+}
+#else
+static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, ITK_ALE, offs);
+ return bus_space_read_1(t, h, ITK_ISAC_DATA);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, ITK_ALE, HSCXA+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, ITK_ALE, HSCXB+offs);
+ return bus_space_read_1(t, h, ITK_HSCX_DATA);
+ }
+ return 0;
+}
+#endif
+
+#endif /* ITKIX1 */
diff --git a/sys/i4b/layer1/i4b_l1.c b/sys/i4b/layer1/i4b_l1.c
new file mode 100644
index 0000000..96497c5
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l1.c - isdn4bsd layer 1 handler
+ * -----------------------------------
+ *
+ * $Id: i4b_l1.c,v 1.27 1998/12/05 18:04:51 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:24:52 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+#include "isic.h"
+#else
+#define NISIC 1 /* don't bother */
+#endif
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT;
+
+static int ph_data_req(int, struct mbuf *, int);
+static int ph_activate_req(int);
+
+/* from i4btrc driver i4b_trace.c */
+extern int get_trace_data_from_l1(int unit, int what, int len, char *buf);
+
+/* from layer 2 */
+extern int i4b_ph_data_ind(int unit, struct mbuf *m);
+extern int i4b_ph_activate_ind(int unit);
+extern int i4b_ph_deactivate_ind(int unit);
+extern int i4b_mph_attach_ind(int unit);
+extern int i4b_mph_status_ind(int, int, int);
+
+/* layer 1 lme */
+static int i4b_mph_command_req(int, int, int);
+
+/* jump table */
+struct i4b_l1l2_func i4b_l1l2_func = {
+
+ /* Layer 1 --> Layer 2 */
+
+ (int (*)(int, struct mbuf *)) i4b_ph_data_ind,
+ (int (*)(int)) i4b_ph_activate_ind,
+ (int (*)(int)) i4b_ph_deactivate_ind,
+
+ /* Layer 2 --> Layer 1 */
+
+ (int (*)(int, struct mbuf *, int)) ph_data_req,
+ (int (*)(int)) ph_activate_req,
+
+ /* Layer 1 --> upstream, ISDN trace data */
+
+ (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1,
+
+ /* Driver control and status information */
+
+ (int (*)(int, int, int)) i4b_mph_status_ind,
+ (int (*)(int, int, int)) i4b_mph_command_req,
+};
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-DATA-REQUEST
+ * =========================
+ *
+ * parms:
+ * unit physical interface unit number
+ * m mbuf containing L2 frame to be sent out
+ * freeflag MBUF_FREE: free mbuf here after having sent
+ * it out
+ * MBUF_DONTFREE: mbuf is freed by Layer 2
+ * returns:
+ * ==0 fail, nothing sent out
+ * !=0 ok, frame sent out
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+#ifdef NOTDEF
+ DBGL1(L1_PRIM, "PH-DATA-REQ", ("unit %d, freeflag=%d\n", unit, freeflag));
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ DBGL1(L1_I_ERR, "ph_data_req", ("still in state F3!\n"));
+ ph_activate_req(unit);
+ }
+
+ if(sc->sc_state & ISAC_TX_ACTIVE)
+ {
+ if(sc->sc_obuf2 == NULL)
+ {
+ sc->sc_obuf2 = m; /* save mbuf ptr */
+
+ if(freeflag)
+ sc->sc_freeflag2 = 1; /* IRQ must mfree */
+ else
+ sc->sc_freeflag2 = 0; /* IRQ must not mfree */
+
+ DBGL1(L1_I_MSG, "ph_data_req", ("using 2nd ISAC TX buffer, state = %s\n", isic_printstate(sc)));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ DBGL1(L1_I_ERR, "ph_data_req", ("No Space in TX FIFO, state = %s\n", isic_printstate(sc)));
+
+ if(freeflag == MBUF_FREE)
+ i4b_Dfreembuf(m);
+
+ splx(s);
+ return (0);
+ }
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = unit;
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ DBGL1(L1_I_MSG, "ph_data_req", ("ISAC_TX_ACTIVE set\n"));
+
+ sc->sc_freeflag = 0; /* IRQ must NOT mfree */
+
+ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */
+
+ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */
+ {
+ sc->sc_obuf = m; /* save mbuf ptr */
+ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */
+ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */
+
+ if(freeflag)
+ sc->sc_freeflag = 1; /* IRQ must mfree */
+
+ cmd = ISAC_CMDR_XTF;
+ }
+ else
+ {
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ if(freeflag)
+ i4b_Dfreembuf(m);
+
+ cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+
+ ISAC_WRITE(I_CMDR, cmd);
+ ISACCMDRWRDELAY();
+
+ splx(s);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-ACTIVATE-REQUEST
+ * =============================
+ *
+ * parms:
+ * unit physical interface unit number
+ *
+ * returns:
+ * ==0
+ * !=0
+ *
+ *---------------------------------------------------------------------------*/
+static int
+ph_activate_req(int unit)
+{
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ DBGL1(L1_PRIM, "PH-ACTIVATE-REQ", ("unit %d\n", unit));
+ isic_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+static int
+i4b_mph_command_req(int unit, int command, int parm)
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[unit];
+#else
+ struct isic_softc *sc = isic_find_sc(unit);
+#endif
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DOPEN\n", unit));
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DCLOSE\n", unit));
+ sc->sc_enabled = 0;
+ break;
+
+ default:
+ DBGL1(L1_ERROR, "i4b_mph_command_req", ("ERROR, unknown command = %d, unit = %d, parm = %d\n", command, unit, parm));
+ break;
+ }
+
+ return(0);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_l1.h b/sys/i4b/layer1/i4b_l1.h
new file mode 100644
index 0000000..2b15ccc
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------*
+ *
+ * i4b_l1.h - isdn4bsd layer 1 header file
+ * ---------------------------------------
+ *
+ * $Id: i4b_l1.h,v 1.54 1998/12/17 04:55:39 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:41:36 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef I4B_L1_H_
+#define I4B_L1_H_
+
+#include <i4b/include/i4b_l3l4.h>
+
+/*---------------------------------------------------------------------------
+ * kernel config file flags definition
+ *---------------------------------------------------------------------------*/
+ /* XXX: we do need these only for real ISA (not even ISAPNP cards), and only
+ * because we are not confident enough in the general ISA probe routine (as
+ * practiced by the NetBSD variant). *And* it is completely redundant to the
+ * various options enabling only a few card's support routines to be compiled
+ * in. Probably the current truth is: this is usefull for anybody with more
+ * than one supported real ISA card. It is not usefull in generic configs,
+ * nor in typical one-controller-only configurations.
+ * Further - it is identical to the CARD_TYPEP_xxx definitions in
+ * ../machine/i4b_ioctl.h.
+ */
+#define FLAG_TELES_S0_8 1
+#define FLAG_TELES_S0_16 2
+#define FLAG_TELES_S0_163 3
+#define FLAG_AVM_A1 4
+#define FLAG_TELES_S0_163_PnP 5 /* XXX - not needed, remove! */
+#define FLAG_CREATIX_S0_PnP 6 /* XXX - not needed, remove! */
+#define FLAG_USR_ISDN_TA_INT 7
+#define FLAG_DRN_NGO 8 /* XXX - not needed, remove! */
+#define FLAG_SWS 9 /* XXX - not needed, remove! */
+#define FLAG_AVM_A1_PCMCIA 10 /* XXX - not needed, remove! */
+#define FLAG_DYNALINK 11 /* XXX - not needed, remove! */
+#define FLAG_BLMASTER 12
+#define FLAG_ELSA_QS1P_ISA 13 /* XXX - not needed, remove! */
+#define FLAG_ELSA_QS1P_PCI 14 /* XXX - not needed, remove! */
+#define FLAG_SIEMENS_ITALK 15
+#define FLAG_ELSA_MLIMC 16 /* XXX - not needed, remove! */
+#define FLAG_ELSA_MLMCALL 17 /* XXX - not needed, remove! */
+#define FLAG_ITK_IX1 18
+
+#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/
+
+#define MAX_DFRAME_LEN 264 /* max length of a D frame */
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+#ifndef __FreeBSD__
+/* We try to map as few as possible as small as possible io and/or
+ memory regions. Each card defines its own interpretation of this
+ mapping array. At probe time we have a fixed size array, later
+ (when the card type is known) we allocate a minimal array
+ dynamically. */
+
+#define ISIC_MAX_IO_MAPS 49 /* no cardtype needs more yet */
+
+/* one entry in mapping array */
+struct isic_io_map {
+ bus_space_tag_t t; /* which bus-space is this? */
+ bus_space_handle_t h; /* handle of mapped bus space region */
+ bus_size_t offset; /* offset into region */
+ bus_size_t size; /* size of region, zero if not ours
+ (i.e.: don't ever unmap it!) */
+};
+
+/* this is passed around at probe time (no struct isic_softc yet) */
+struct isic_attach_args {
+ int ia_flags; /* flags from config file */
+ int ia_num_mappings; /* number of io mappings provided */
+ struct isic_io_map ia_maps[ISIC_MAX_IO_MAPS];
+};
+#endif
+
+#ifdef __FreeBSD__
+extern int next_isic_unit;
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_Bchan: the state of one B channel
+ *---------------------------------------------------------------------------*/
+typedef struct
+{
+ int unit; /* cards unit number */
+ int channel; /* which channel is this*/
+
+#ifdef __FreeBSD__
+ caddr_t hscx; /* HSCX address */
+#endif
+
+ u_char hscx_mask; /* HSCX interrupt mask */
+
+ int bprot; /* B channel protocol */
+
+ int state; /* this channels state */
+#define HSCX_IDLE 0x00 /* channel idle */
+#define HSCX_TX_ACTIVE 0x01 /* tx running */
+
+ /* receive data from ISDN */
+
+ struct ifqueue rx_queue; /* receiver queue */
+
+ int rxcount; /* rx statistics counter*/
+
+ struct mbuf *in_mbuf; /* rx input buffer */
+ u_char *in_cbptr; /* curr buffer pointer */
+ int in_len; /* rx input buffer len */
+
+ /* transmit data to ISDN */
+
+ struct ifqueue tx_queue; /* transmitter queue */
+
+ int txcount; /* tx statistics counter*/
+
+ struct mbuf *out_mbuf_head; /* first mbuf in possible chain */
+ struct mbuf *out_mbuf_cur; /* current mbuf in possbl chain */
+ unsigned char *out_mbuf_cur_ptr; /* data pointer into mbuf */
+ int out_mbuf_cur_len; /* remaining bytes in mbuf */
+
+ /* link between b channel and driver */
+
+ isdn_link_t isdn_linktab; /* b channel addresses */
+ drvr_link_t *drvr_linktab; /* ptr to driver linktab*/
+
+ /* statistics */
+
+ /* RSTA */
+
+ int stat_VFR; /* HSCX RSTA Valid FRame */
+ int stat_RDO; /* HSCX RSTA Rx Data Overflow */
+ int stat_CRC; /* HSCX RSTA CRC */
+ int stat_RAB; /* HSCX RSTA Rx message ABorted */
+
+ /* EXIR */
+
+ int stat_XDU; /* HSCX EXIR tx data underrun */
+ int stat_RFO; /* HSCX EXIR rx frame overflow */
+
+} isic_Bchan_t;
+
+/*---------------------------------------------------------------------------*
+ * isic_softc: the state of the layer 1 of the D channel
+ *---------------------------------------------------------------------------*/
+struct isic_softc
+{
+#ifndef __FreeBSD__
+ /* We are inherited from this class. All drivers must have this
+ as their first entry in struct softc. */
+ struct device sc_dev;
+#endif
+
+ int sc_unit; /* unit number */
+ int sc_irq; /* interrupt vector */
+
+#ifdef __FreeBSD__
+ int sc_port; /* port base address */
+#else
+ u_int sc_maddr; /* "memory address" for card config register */
+ int sc_num_mappings; /* number of io mappings provided */
+ struct isic_io_map *sc_maps;
+#define MALLOC_MAPS(sc) \
+ (sc)->sc_maps = (struct isic_io_map*)malloc(sizeof((sc)->sc_maps[0])*(sc)->sc_num_mappings, M_DEVBUF, 0)
+#endif
+
+ int sc_cardtyp; /* CARD_TYPEP_xxxx */
+
+ int sc_bustyp; /* IOM1 or IOM2 */
+#define BUS_TYPE_IOM1 0x01
+#define BUS_TYPE_IOM2 0x02
+
+ int sc_trace; /* output protocol data for tracing */
+ unsigned int sc_trace_dcount;/* d channel trace frame counter */
+ unsigned int sc_trace_bcount;/* b channel trace frame counter */
+
+ int sc_state; /* ISAC state flag */
+#define ISAC_IDLE 0x00 /* state = idle */
+#define ISAC_TX_ACTIVE 0x01 /* state = transmitter active */
+
+ int sc_init_tries; /* no of out tries to access S0 */
+
+#ifdef __FreeBSD__
+ caddr_t sc_vmem_addr; /* card RAM virtual memory base */
+ caddr_t sc_isac; /* ISAC port base addr */
+#define ISAC_BASE (sc->sc_isac)
+
+ caddr_t sc_ipacbase; /* IPAC port base addr */
+#define IPAC_BASE (sc->sc_ipacbase)
+#endif
+
+ u_char sc_isac_mask; /* ISAC IRQ mask */
+#define ISAC_IMASK (sc->sc_isac_mask)
+
+ isic_Bchan_t sc_chan[2]; /* B-channel state */
+#define HSCX_A_BASE (sc->sc_chan[0].hscx)
+#define HSCX_A_IMASK (sc->sc_chan[0].hscx_mask)
+#define HSCX_B_BASE (sc->sc_chan[1].hscx)
+#define HSCX_B_IMASK (sc->sc_chan[1].hscx_mask)
+
+ struct mbuf *sc_ibuf; /* input buffer mgmt */
+ u_short sc_ilen;
+ u_char *sc_ib;
+ /* this is for the irq TX routine */
+ struct mbuf *sc_obuf; /* pointer to an mbuf with TX frame */
+ u_char *sc_op; /* ptr to next chunk of frame to tx */
+ int sc_ol; /* length of remaining frame to tx */
+ int sc_freeflag; /* m_freem mbuf if set */
+
+ struct mbuf *sc_obuf2; /* pointer to an mbuf with TX frame */
+ int sc_freeflag2; /* m_freem mbuf if set */
+
+ int sc_isac_version; /* version number of ISAC */
+ int sc_hscx_version; /* version number of HSCX */
+
+ int sc_I430state; /* I.430 state F3 .... F8 */
+
+ int sc_I430T3; /* I.430 Timer T3 running */
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ struct callout_handle sc_T3_callout;
+#endif
+
+ int sc_I430T4; /* Timer T4 running */
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ struct callout_handle sc_T4_callout;
+#endif
+
+ int sc_enabled; /* daemon is running */
+
+ int sc_ipac; /* flag, running on ipac */
+ int sc_bfifolen; /* length of b channel fifos */
+
+#ifdef __FreeBSD__
+
+ u_char (*readreg)(u_char *, u_int);
+ void (*writereg)(u_char *, u_int, u_int);
+ void (*readfifo)(void *, const void *, size_t);
+ void (*writefifo)(void *, const void *, size_t);
+ void (*clearirq)(void *);
+
+#define ISAC_READ(r) (*sc->readreg)(ISAC_BASE, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(ISAC_BASE, (r), (v));
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)((b), ISAC_BASE, (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(ISAC_BASE, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc->sc_chan[(n)].hscx, (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc->sc_chan[(n)].hscx, (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)((b), sc->sc_chan[(n)].hscx, (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc->sc_chan[(n)].hscx, (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(IPAC_BASE, (r))
+#define IPAC_WRITE(r,v) (*sc->writereg)(IPAC_BASE, (r), (v));
+
+#else /* ! __FreeBSD__ */
+
+#define ISIC_WHAT_ISAC 0
+#define ISIC_WHAT_HSCXA 1
+#define ISIC_WHAT_HSCXB 2
+#define ISIC_WHAT_IPAC 3
+
+ u_int8_t (*readreg) __P((struct isic_softc *sc, int what, bus_size_t offs));
+ void (*writereg) __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+ void (*readfifo) __P((struct isic_softc *sc, int what, void *buf, size_t size));
+ void (*writefifo) __P((struct isic_softc *sc, int what, const void *data, size_t size));
+ void (*clearirq) __P((struct isic_softc *sc));
+
+#define ISAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_ISAC, (r))
+#define ISAC_WRITE(r,v) (*sc->writereg)(sc, ISIC_WHAT_ISAC, (r), (v))
+#define ISAC_RDFIFO(b,s) (*sc->readfifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+#define ISAC_WRFIFO(b,s) (*sc->writefifo)(sc, ISIC_WHAT_ISAC, (b), (s))
+
+#define HSCX_READ(n,r) (*sc->readreg)(sc, ISIC_WHAT_HSCXA+(n), (r))
+#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc, ISIC_WHAT_HSCXA+(n), (r), (v))
+#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s))
+
+#define IPAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_IPAC, (r))
+#define IPAC_WRITE(r, v) (*sc->writereg)(sc, ISIC_WHAT_IPAC, (r), (v))
+
+#endif /* __FreeBSD__ */
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC states
+ *---------------------------------------------------------------------------*/
+enum I430states {
+ ST_F3, /* F3 Deactivated */
+ ST_F4, /* F4 Awaiting Signal */
+ ST_F5, /* F5 Identifying Input */
+ ST_F6, /* F6 Synchronized */
+ ST_F7, /* F7 Activated */
+ ST_F8, /* F8 Lost Framing */
+ ST_ILL, /* Illegal State */
+ N_STATES
+};
+
+/*---------------------------------------------------------------------------*
+ * possible I.430/ISAC events
+ *---------------------------------------------------------------------------*/
+enum I430events {
+ EV_PHAR, /* PH ACTIVATE REQUEST */
+ EV_T3, /* Timer 3 expired */
+ EV_INFO0, /* receiving INFO0 */
+ EV_RSY, /* receiving any signal */
+ EV_INFO2, /* receiving INFO2 */
+ EV_INFO48, /* receiving INFO4 pri 8/9 */
+ EV_INFO410, /* receiving INFO4 pri 10/11 */
+ EV_DR, /* Deactivate Request */
+ EV_PU, /* Power UP */
+ EV_DIS, /* Disconnected (only 2085) */
+ EV_EI, /* Error Indication */
+ EV_ILL, /* Illegal Event */
+ N_EVENTS
+};
+
+enum I430commands {
+ CMD_TIM, /* Timing */
+ CMD_RS, /* Reset */
+ CMD_AR8, /* Activation request pri 8 */
+ CMD_AR10, /* Activation request pri 10 */
+ CMD_DIU, /* Deactivate Indication Upstream */
+ CMD_ILL /* Illegal command */
+};
+
+#define N_COMMANDS CMD_ILL
+
+#ifdef __FreeBSD__
+
+extern struct isic_softc isic_sc[];
+
+extern void isic_recover(struct isic_softc *sc);
+extern int isic_realattach(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_avma1 ( struct isa_device *dev );
+extern int isic_attach_fritzpcmcia ( struct isa_device *dev );
+extern int isic_attach_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_s016 ( struct isa_device *dev );
+extern int isic_attach_s0163 ( struct isa_device *dev );
+extern int isic_attach_s0163P ( struct isa_device *dev );
+extern int isic_attach_s08 ( struct isa_device *dev );
+extern int isic_attach_usrtai ( struct isa_device *dev );
+extern int isic_attach_itkix1 ( struct isa_device *dev );
+extern int isic_attach_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_sws ( struct isa_device *dev );
+extern int isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+extern int isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2);
+extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate );
+extern void isic_hscx_init ( struct isic_softc *sc, int hscx_channel, int activate );
+extern void isic_hscx_irq ( struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq );
+extern int isic_hscx_silence ( unsigned char *data, int len );
+extern void isic_hscx_cmd( struct isic_softc *sc, int h_chan, unsigned char cmd );
+extern void isic_hscx_waitxfw( struct isic_softc *sc, int h_chan );
+extern void isic_init_linktab ( struct isic_softc *sc );
+extern int isic_isac_init ( struct isic_softc *sc );
+extern void isic_isac_irq ( struct isic_softc *sc, int r );
+extern void isic_isac_l1_cmd ( struct isic_softc *sc, int command );
+extern void isic_next_state ( struct isic_softc *sc, int event );
+extern char *isic_printstate ( struct isic_softc *sc );
+extern int isic_probe_avma1 ( struct isa_device *dev );
+extern int isic_probe_avma1_pcmcia ( struct isa_device *dev );
+extern int isic_probe_Cs0P ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_Dyn ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_s016 ( struct isa_device *dev );
+extern int isic_probe_s0163 ( struct isa_device *dev );
+extern int isic_probe_s0163P ( struct isa_device *dev );
+extern int isic_probe_s08 ( struct isa_device *dev );
+extern int isic_probe_usrtai ( struct isa_device *dev );
+extern int isic_probe_itkix1 ( struct isa_device *dev );
+extern int isic_probe_drnngo ( struct isa_device *dev, unsigned int iobase2);
+extern int isic_probe_sws ( struct isa_device *dev );
+extern int isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2);
+
+#else /* not FreeBSD */
+
+extern void isic_recover __P((struct isic_softc *sc));
+extern int isicattach __P((int flags, struct isic_softc *sc));
+extern int isicintr __P((void *));
+extern int isicprobe __P((struct isic_attach_args *ia));
+extern int isic_attach_avma1 __P((struct isic_softc *sc));
+extern int isic_attach_s016 __P((struct isic_softc *sc));
+extern int isic_attach_s0163 __P((struct isic_softc *sc));
+extern int isic_attach_s08 __P((struct isic_softc *sc));
+extern int isic_attach_usrtai __P((struct isic_softc *sc));
+extern int isic_attach_itkix1 __P((struct isic_softc *sc));
+extern void isic_bchannel_setup __P((int unit, int hscx_channel, int bprot, int activate));
+extern void isic_hscx_init __P((struct isic_softc *sc, int hscx_channel, int activate));
+extern void isic_hscx_irq __P((struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq));
+extern int isic_hscx_silence __P(( unsigned char *data, int len ));
+extern void isic_hscx_cmd __P(( struct isic_softc *sc, int h_chan, unsigned char cmd ));
+extern void isic_hscx_waitxfw __P(( struct isic_softc *sc, int h_chan ));
+extern void isic_init_linktab __P((struct isic_softc *sc));
+extern int isic_isac_init __P((struct isic_softc *sc));
+extern void isic_isac_irq __P((struct isic_softc *sc, int r));
+extern void isic_isac_l1_cmd __P((struct isic_softc *sc, int command));
+extern void isic_next_state __P((struct isic_softc *sc, int event));
+extern char * isic_printstate __P((struct isic_softc *sc));
+extern int isic_probe_avma1 __P((struct isic_attach_args *ia));
+extern int isic_probe_s016 __P((struct isic_attach_args *ia));
+extern int isic_probe_s0163 __P((struct isic_attach_args *ia));
+extern int isic_probe_s08 __P((struct isic_attach_args *ia));
+extern int isic_probe_usrtai __P((struct isic_attach_args *ia));
+extern int isic_probe_itkix1 __P((struct isic_attach_args *ia));
+
+extern struct isic_softc *isic_sc[];
+
+#define isic_find_sc(unit) (isic_sc[(unit)])
+
+#endif /* __FreeBSD__ */
+
+#endif /* I4B_L1_H_ */
diff --git a/sys/i4b/layer1/i4b_l1fsm.c b/sys/i4b/layer1/i4b_l1fsm.c
new file mode 100644
index 0000000..397ce11
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1fsm.c
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine
+ * --------------------------------------------------
+ *
+ * $Id: i4b_l1fsm.c,v 1.26 1998/12/05 18:04:55 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:25:12 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#else
+#define NISIC 1
+#endif
+
+#if NISIC > 0
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#include <machine/stdarg.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+
+static char *state_text[N_STATES] = {
+ "F3 Deactivated",
+ "F4 Awaiting Signal",
+ "F5 Identifying Input",
+ "F6 Synchronized",
+ "F7 Activated",
+ "F8 Lost Framing",
+ "Illegal State"
+};
+
+static char *event_text[N_EVENTS] = {
+ "EV_PHAR PH_ACT_REQ",
+ "EV_T3 Timer 3 expired",
+ "EV_INFO0 INFO0 received",
+ "EV_RSY Level Detected",
+ "EV_INFO2 INFO2 received",
+ "EV_INFO48 INFO4 received",
+ "EV_INFO410 INFO4 received",
+ "EV_DR Deactivate Req",
+ "EV_PU Power UP",
+ "EV_DIS Disconnected",
+ "EV_EI Error Ind",
+ "Illegal Event"
+};
+
+/* Function prototypes */
+
+static void timer3_expired (struct isic_softc *sc);
+static void T3_start (struct isic_softc *sc);
+static void T3_stop (struct isic_softc *sc);
+static void F_T3ex (struct isic_softc *sc);
+static void timer4_expired (struct isic_softc *sc);
+static void T4_start (struct isic_softc *sc);
+static void T4_stop (struct isic_softc *sc);
+static void F_AI8 (struct isic_softc *sc);
+static void F_AI10 (struct isic_softc *sc);
+static void F_I01 (struct isic_softc *sc);
+static void F_I02 (struct isic_softc *sc);
+static void F_I03 (struct isic_softc *sc);
+static void F_I2 (struct isic_softc *sc);
+static void F_ill (struct isic_softc *sc);
+static void F_NULL (struct isic_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct isic_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ DBGL1(L1_T_ERR, "timer3_expired", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T3 = 0;
+
+ /* XXX try some recovery here XXX */
+
+ isic_recover(sc);
+
+ sc->sc_init_tries++; /* increment retry count */
+
+/*XXX*/ if(sc->sc_init_tries > 4)
+ {
+ int s = SPLI4B();
+
+ sc->sc_init_tries = 0;
+
+ if(sc->sc_obuf2 != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf2);
+ sc->sc_obuf2 = NULL;
+ }
+ if(sc->sc_obuf != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_obuf = NULL;
+ sc->sc_freeflag = 0;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ }
+
+ splx(s);
+
+ MPH_Status_Ind(sc->sc_unit, STI_NOL1ACC, 0);
+ }
+
+ isic_next_state(sc, EV_T3);
+ }
+ else
+ {
+ DBGL1(L1_T_ERR, "timer3_expired", ("expired without starting it ....\n"));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T3_start", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T3 = 1;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz);
+#else
+ timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T3_stop", ("state = %s\n", isic_printstate(sc)));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, sc->sc_T3_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_T3ex", ("FSM function F_T3ex executing\n"));
+ PH_Deact_Ind(sc->sc_unit);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct isic_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ DBGL1(L1_T_ERR, "timer4_expired", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T4 = 0;
+ MPH_Status_Ind(sc->sc_unit, STI_PDEACT, 0);
+ }
+ else
+ {
+ DBGL1(L1_T_ERR, "timer4_expired", ("expired without starting it ....\n"));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T4_start", ("state = %s\n", isic_printstate(sc)));
+ sc->sc_I430T4 = 1;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz);
+#else
+ timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz);
+#endif
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct isic_softc *sc)
+{
+ DBGL1(L1_T_MSG, "T4_stop", ("state = %s\n", isic_printstate(sc)));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, sc->sc_T4_callout);
+#else
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc);
+#endif
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct isic_softc *sc)
+{
+ T4_stop(sc);
+
+ DBGL1(L1_F_MSG, "F_AI8", ("FSM function F_AI8 executing\n"));
+
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct isic_softc *sc)
+{
+ T4_stop(sc);
+
+ DBGL1(L1_F_MSG, "F_AI10", ("FSM function F_AI10 executing\n"));
+
+ PH_Act_Ind(sc->sc_unit);
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I01", ("FSM function F_I01 executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I02", ("FSM function F_I02 executing\n"));
+
+ PH_Deact_Ind(sc->sc_unit);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I03", ("FSM function F_I03 executing\n"));
+
+ PH_Deact_Ind(sc->sc_unit);
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_AR", ("FSM function F_AR executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+ isic_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_I2", ("FSM function F_I2 executing\n"));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = sc->sc_unit;
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ MPH_Trace_Ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct isic_softc *sc)
+{
+ DBGL1(L1_F_ERR, "F_ill", ("FSM function F_ill executing\n"));
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct isic_softc *sc)
+{
+ DBGL1(L1_F_MSG, "F_NULL", ("FSM function F_NULL executing\n"));
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct isic_state_tab {
+ void (*func) (struct isic_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} isic_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}},
+/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}},
+/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}},
+/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}},
+/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}},
+/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}},
+/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void
+isic_next_state(struct isic_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ if(event >= N_EVENTS)
+ panic("i4b_l1fsm.c: event >= N_EVENTS\n");
+
+ currstate = sc->sc_I430state;
+
+ if(currstate >= N_STATES)
+ panic("i4b_l1fsm.c: currstate >= N_STATES\n");
+
+ newstate = isic_state_tab[event][currstate].newstate;
+
+ if(newstate >= N_STATES)
+ panic("i4b_l1fsm.c: newstate >= N_STATES\n");
+
+ DBGL1(L1_F_MSG, "isic_next_state", ("FSM event [%s]: [%s => %s]\n", event_text[event],
+ state_text[currstate],
+ state_text[newstate]));
+
+ (*isic_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ DBGL1(L1_F_ERR, "isic_next_state", ("FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!\n",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]));
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+isic_printstate(struct isic_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+
+#endif /* NISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_sws.c b/sys/i4b/layer1/i4b_sws.c
new file mode 100644
index 0000000..c5182b4
--- /dev/null
+++ b/sys/i4b/layer1/i4b_sws.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 1998 German Tischler. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * Card format:
+ *
+ * iobase + 0 : reset on (0x03)
+ * iobase + 1 : reset off (0x0)
+ * iobase + 2 : isac read/write
+ * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 ,
+ * offset 0x40-0x7f hscx1 )
+ * iobase + 4 : offset for indirect adressing
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for SWS cards
+ * ====================================================
+ *
+ * EXPERIMENTAL !!!!
+ * =================
+ *
+ * $Id: i4b_sws.c,v 1.12 1998/12/18 09:32:45 hm Exp $
+ *
+ * last edit-date: [Sun Dec 13 10:49:25 1998]
+ *
+ * -hm adding driver to i4b
+ * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+
+#include "isic.h"
+#include "opt_i4b.h"
+
+#else
+
+#define NISIC 1
+
+#endif
+
+#if defined (SEDLBAUER) && NISIC > 0
+
+#define SWS_RESON 0 /* reset on */
+#define SWS_RESOFF 1 /* reset off */
+#define SWS_ISAC 2 /* ISAC */
+#define SWS_HSCX0 3 /* HSCX0 */
+#define SWS_RW 4 /* indirect access register */
+#define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */
+ /* access is done through hscx0 */
+
+#define SWS_REGS 8 /* we use an area of 8 bytes for io */
+
+#define SWS_BASE(X) ((unsigned int)X&~(SWS_REGS-1))
+#define SWS_PART(X) ((unsigned int)X& (SWS_REGS-1))
+#define SWS_ADDR(X) ((SWS_PART(X) == SWS_ISAC) ? (SWS_BASE(X)+SWS_ISAC) : (SWS_BASE(X)+SWS_HSCX0) )
+#define SWS_REG(X,Y) ((SWS_PART(X) != SWS_HSCX1) ? Y : (Y+0x40) )
+#define SWS_IDO(X) (SWS_BASE(X)+SWS_RW)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t sws_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void sws_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void sws_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void sws_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_sws __P((struct isic_softc *sc));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_read_fifo(void *buf, const void *base, size_t len)
+{
+ outb(SWS_IDO(base),SWS_REG(base,0));
+ insb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_ISAC, buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put fifo routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_fifo(void *base, const void *buf, size_t len)
+{
+ outb (SWS_IDO(base),SWS_REG(base,0));
+ outsb(SWS_ADDR(base),buf,len);
+}
+
+#else
+
+static void
+sws_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_ISAC, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, 0);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40);
+ bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC put register routine
+ *---------------------------------------------------------------------------*/
+
+#ifdef __FreeBSD__
+
+static void
+sws_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ outb(SWS_ADDR(base),v);
+}
+
+#else
+
+static void
+sws_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_ISAC, data);
+ break;
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ bus_space_write_1(t, h, SWS_HSCX0, data);
+ break;
+ }
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * SWS P&P ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+sws_read_reg(u_char *base, u_int offset)
+{
+ outb(SWS_IDO(base),SWS_REG(base,offset));
+ return inb(SWS_ADDR(base));
+}
+
+#else
+
+static u_int8_t
+sws_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ switch (what) {
+ case ISIC_WHAT_ISAC:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_ISAC);
+ case ISIC_WHAT_HSCXA:
+ bus_space_write_1(t, h, SWS_RW, offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ case ISIC_WHAT_HSCXB:
+ bus_space_write_1(t, h, SWS_RW, 0x40+offs);
+ return bus_space_read_1(t, h, SWS_HSCX0);
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef __FreeBSD__
+
+/* attach callback routine */
+
+int
+isic_attach_sws(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* fill in isic_softc structure */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+ sc->clearirq = NULL;
+ sc->sc_unit = dev->id_unit;
+ sc->sc_irq = dev->id_irq;
+ sc->sc_port = dev->id_iobase;
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+ dev->id_msize = 0;
+
+ ISAC_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_ISAC);
+ HSCX_A_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX0);
+ HSCX_B_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX1);
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ /* reset card */
+
+ outb( ((u_int) sc->sc_port) + SWS_RESON , 0x3);
+ DELAY(SEC_DELAY / 5);
+ outb( ((u_int) sc->sc_port) + SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+
+ return(1);
+}
+
+#else /* !__FreeBSD__ */
+
+void
+isic_attach_sws(struct isic_softc *sc)
+{
+ /* setup access routines */
+
+ sc->readreg = sws_read_reg;
+ sc->writereg = sws_write_reg;
+
+ sc->readfifo = sws_read_fifo;
+ sc->writefifo = sws_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_SWS;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
+ * 0x05 ( = version 2.1 ) in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("%s: HSCX VSTR test failed for SWS PnP\n",
+ sc->sc_dev.dv_xname);
+ printf("%s: HSC0: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
+ printf("%s: HSC1: VSTR: %#x\n",
+ sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
+ return;
+ }
+
+ /* reset card */
+ {
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, SWS_RESON, 0x3);
+ DELAY(SEC_DELAY / 5);
+ bus_space_write_1(t, h, SWS_RESOFF, 0);
+ DELAY(SEC_DELAY / 5);
+ }
+}
+
+#endif /* !__FreeBSD__ */
+
+#endif /* defined(SEDLBAUER) && NISIC > 0 */
diff --git a/sys/i4b/layer1/i4b_tel_s016.c b/sys/i4b/layer1/i4b_tel_s016.c
new file mode 100644
index 0000000..f77a3c1
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s016.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16 and clones
+ * =================================================================
+ *
+ * $Id: i4b_tel_s016.c,v 1.12 1998/12/05 18:04:56 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:40:17 1998]
+ *
+ * -hm clean up
+ * -hm checked with a Creatix ISDN-S0 (PCB version: mp 130.1)
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#ifndef __FreeBSD__
+static u_int8_t tels016_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels016_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels016_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels016_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels016_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels016_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels016_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+
+ offs += offset[what];
+
+ if(offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16 fifo read/write routines
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels016_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels016_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels016_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[1].t;
+ bus_space_handle_t h = sc->sc_maps[1].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s016 - probe for Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s016(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* check if valid memory addr */
+
+ switch((unsigned int)kvtop(dev->id_maddr))
+ {
+ case 0xc0000:
+ case 0xc2000:
+ case 0xc4000:
+ case 0xc6000:
+ case 0xc8000:
+ case 0xca000:
+ case 0xcc000:
+ case 0xce000:
+ case 0xd0000:
+ case 0xd2000:
+ case 0xd4000:
+ case 0xd6000:
+ case 0xd8000:
+ case 0xda000:
+ case 0xdc000:
+ case 0xde000:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid mem addr 0x%lx for Teles S0/16!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ break;
+ }
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* check card signature */
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ byte = inb(sc->sc_port + 2);
+
+ if((byte != 0x1e) && (byte != 0x1f))
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_memcpyb;
+ sc->writefifo = tels016_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t) ((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t) ((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t) ((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s016(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && (b2 == 0x1e || b2 == 0x1f))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s016 - attach Teles S0/16 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s016(struct isa_device *dev)
+#else
+isic_attach_s016(struct isic_softc *sc)
+#endif
+{
+
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#endif
+
+ u_long irq;
+
+#ifndef __FreeBSD__
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels016_read_reg;
+ sc->writereg = tels016_write_reg;
+
+ sc->readfifo = tels016_read_fifo;
+ sc->writefifo = tels016_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+#ifdef __FreeBSD__
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+#else
+ irq = intr_no[sc->sc_irq];
+#endif
+
+ /* configure IRQ */
+
+#ifdef __FreeBSD__
+ irq |= ((u_long) sc->sc_vmem_addr) >> 9;
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(sc->sc_port + 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ sc->sc_vmem_addr[0x80] = 0;
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ sc->sc_vmem_addr[0x80] = 1;
+ DELAY(SEC_DELAY / 5);
+
+#else
+
+ irq |= ((sc->sc_maddr >> 9) & 0x000000f0);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq | 0x01);
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit off */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 0);
+ DELAY(SEC_DELAY / 5);
+
+ /* set card bit on */
+
+ bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 1);
+ DELAY(SEC_DELAY / 5);
+#endif
+
+ return (1);
+}
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s0163.c b/sys/i4b/layer1/i4b_tel_s0163.c
new file mode 100644
index 0000000..5fdd329
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s0163.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3
+ * ========================================================
+ *
+ * $Id: i4b_tel_s0163.c,v 1.15 1998/12/05 18:04:58 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:40:58 1998]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm VSTR detection for older 16.3 cards
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16_3)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 };
+
+#ifndef __FreeBSD__
+static u_int8_t tels0163_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels0163_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels0163_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 read fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x1e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 write fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x1e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC put register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs - 0x20, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 ISAC get register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels0163_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs - 0x20);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163 - probe for Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+ u_char byte;
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ case 0xe80:
+ case 0xf80:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ if((byte = inb(sc->sc_port)) != 0x51)
+ {
+ printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 1)) != 0x93)
+ {
+ printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ if((byte = inb(sc->sc_port + 2)) != 0x1c)
+ {
+ printf("isic%d: Error, signature 3 0x%x != 0x1c for Teles S0/16.3!",
+ dev->id_unit, byte);
+ return(0);
+ }
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0xd80:
+ ISAC_BASE = (caddr_t) 0x960;
+ HSCX_A_BASE = (caddr_t) 0x160;
+ HSCX_B_BASE = (caddr_t) 0x560;
+ break;
+
+ case 0xe80:
+ ISAC_BASE = (caddr_t) 0xa60;
+ HSCX_A_BASE = (caddr_t) 0x260;
+ HSCX_B_BASE = (caddr_t) 0x660;
+ break;
+
+ case 0xf80:
+ ISAC_BASE = (caddr_t) 0xb60;
+ HSCX_A_BASE = (caddr_t) 0x360;
+ HSCX_B_BASE = (caddr_t) 0x760;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is
+ * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
+ */
+
+ if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) ||
+ (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s0163(struct isic_attach_args *ia)
+{
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t b0, b1, b2;
+
+ b0 = bus_space_read_1(t, h, 0);
+ b1 = bus_space_read_1(t, h, 1);
+ b2 = bus_space_read_1(t, h, 2);
+
+ if (b0 == 0x51 && b1 == 0x93 && b2 == 0x1c)
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163 - attach Teles S0/16.3 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163(struct isa_device *dev)
+{
+ u_char irq;
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ outb(dev->id_iobase + 4, irq | 0x01);
+
+ return (1);
+}
+
+#else
+
+int
+isic_attach_s0163(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_int8_t irq = intr_no[sc->sc_irq];
+
+ /* configure IRQ */
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq);
+
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 4, irq | 0x01);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163_read_reg;
+ sc->writereg = tels0163_write_reg;
+
+ sc->readfifo = tels0163_read_fifo;
+ sc->writefifo = tels0163_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp= CARD_TYPEP_16_3;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ return (1);
+}
+#endif
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s08.c b/sys/i4b/layer1/i4b_tel_s08.c
new file mode 100644
index 0000000..6115e12
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s08.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1996 Arne Helme. All rights reserved.
+ *
+ * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
+ *
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones
+ * ================================================================
+ *
+ * $Id: i4b_tel_s08.c,v 1.13 1998/12/05 18:04:59 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:39:12 1998]
+ *
+ * -hm clean up
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ * -hm making it finally work (checked with board revision 1.2)
+ * -hm converting asm -> C
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_8)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels08_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels08_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels08_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+static void tels08_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_write_reg(u_char *base, u_int i, u_int v)
+{
+ if(i & 0x01)
+ i |= 0x200;
+ base[i] = v;
+}
+
+#else
+
+static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 };
+
+static void
+tels08_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ bus_space_write_1(t, h, offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels08_read_reg(u_char *base, u_int i)
+{
+ if(i & 0x1)
+ i |= 0x200;
+ return(base[i]);
+}
+
+#else
+
+static u_int8_t
+tels08_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+
+ offs += offset[what];
+
+ if (offs & 0x01)
+ offs |= 0x200;
+
+ return bus_space_read_1(t, h, offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/8 fifo read/write access
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels08_memcpyb(void *to, const void *from, size_t len)
+{
+ for(;len > 0; len--)
+ *((unsigned char *)to)++ = *((unsigned char *)from)++;
+}
+
+#else
+
+static void
+tels08_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_region_1(t, h, offset[what], data, size);
+}
+
+static void
+tels08_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_read_region_1(t, h, offset[what], buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s08 - probe for Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+int
+isic_probe_s08(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq)-1)
+ {
+ case 2:
+ case 9: /* XXX */
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if we got an iobase */
+
+ if(dev->id_iobase > 0)
+ {
+ printf("isic%d: Error, iobase specified for Teles S0/8!\n",
+ dev->id_unit);
+ return(0);
+ }
+
+ /* check if inside memory range of 0xA0000 .. 0xDF000 */
+
+ if( (kvtop(dev->id_maddr) < 0xa0000) ||
+ (kvtop(dev->id_maddr) > 0xdf000) )
+ {
+ printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n",
+ dev->id_unit, kvtop(dev->id_maddr));
+ return(0);
+ }
+
+ sc->sc_vmem_addr = (caddr_t) dev->id_maddr;
+ dev->id_msize = 0x1000;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+
+ sc->readfifo = tels08_memcpyb;
+ sc->writefifo = tels08_memcpyb;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC base addr */
+
+ ISAC_BASE = (caddr_t)((dev->id_maddr) + 0x100);
+
+ /* setup HSCX base addr */
+
+ HSCX_A_BASE = (caddr_t)((dev->id_maddr) + 0x180);
+ HSCX_B_BASE = (caddr_t)((dev->id_maddr) + 0x1c0);
+
+ return (1);
+}
+
+#else
+
+int
+isic_probe_s08(struct isic_attach_args *ia)
+{
+ /* no real sensible probe is easy - write to fifo memory
+ and read back to verify there is memory doesn't work,
+ because you talk to tx fifo and rcv fifo. So, just check
+ HSCX version, which at least fails if no card present
+ at the given location. */
+ bus_space_tag_t t = ia->ia_maps[0].t;
+ bus_space_handle_t h = ia->ia_maps[0].h;
+ u_int8_t v1, v2;
+
+ /* HSCX A VSTR */
+ v1 = bus_space_read_1(t, h, offset[1] + H_VSTR) & 0x0f;
+ if (v1 != HSCX_VA1 && v1 != HSCX_VA2 && v1 != HSCX_VA3 && v1 != HSCX_V21)
+ return 0;
+
+ /* HSCX B VSTR */
+ v2 = bus_space_read_1(t, h, offset[2] + H_VSTR) & 0x0f;
+ if (v2 != HSCX_VA1 && v2 != HSCX_VA2 && v2 != HSCX_VA3 && v2 != HSCX_V21)
+ return 0;
+
+ /* both HSCX channels should have the same version... */
+ if (v1 != v2)
+ return 0;
+
+ return 1;
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s08 - attach Teles S0/8 and compatibles
+ *---------------------------------------------------------------------------*/
+int
+#ifdef __FreeBSD__
+isic_attach_s08(struct isa_device *dev)
+#else
+isic_attach_s08(struct isic_softc *sc)
+#endif
+{
+#ifdef __FreeBSD__
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+#else
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+#endif
+
+ /* set card off */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 0;
+#else
+ bus_space_write_1(t, h, 0x80, 0);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+ /* set card on */
+
+#ifdef __FreeBSD__
+ sc->sc_vmem_addr[0x80] = 1;
+#else
+ bus_space_write_1(t, h, 0x80, 1);
+#endif
+
+ DELAY(SEC_DELAY / 5);
+
+#ifndef __FreeBSD__
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels08_read_reg;
+ sc->writereg = tels08_write_reg;
+ sc->readfifo = tels08_read_fifo;
+ sc->writefifo = tels08_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_8;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM1;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+#endif
+
+ return (1);
+}
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_tel_s0P.c b/sys/i4b/layer1/i4b_tel_s0P.c
new file mode 100644
index 0000000..9bccd77
--- /dev/null
+++ b/sys/i4b/layer1/i4b_tel_s0P.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 1997 Andrew Gordon. All rights reserved.
+ *
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic - I4B Siemens ISDN Chipset Driver for Teles S0 PnP
+ * =======================================================
+ *
+ * EXPERIMENTAL !!!
+ * ================
+ *
+ * $Id: i4b_tel_s0P.c,v 1.12 1998/12/13 09:52:34 hm Exp $
+ *
+ * last edit-date: [Thu Dec 10 07:11:15 1998]
+ *
+ * -hm rudimentary PnP support, hint from Andrew Gordon
+ * -hm more cleanup
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(TEL_S0_16_3_P)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#ifndef __FreeBSD__
+static u_int8_t tels0163P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs));
+static void tels0163P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data));
+static void tels0163P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size));
+static void tels0163P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size));
+void isic_attach_s0163P __P((struct isic_softc *sc));
+#endif
+
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_read_fifo(void *buf, const void *base, size_t len)
+{
+ insb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_read_multi_1(t, h, o + 0x3e, buf, size);
+}
+
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write fifo routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_fifo(void *base, const void *buf, size_t len)
+{
+ outsb((int)base + 0x3e, (u_char *)buf, (u_int)len);
+}
+
+#else
+
+static void
+tels0163P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP write register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static void
+tels0163P_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + offset, (u_char)v);
+}
+
+#else
+
+static void
+tels0163P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ bus_space_write_1(t, h, o + offs, data);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * Teles S0/16.3 PnP read register routine
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+
+static u_char
+tels0163P_read_reg(u_char *base, u_int offset)
+{
+ return (inb((int)base + offset));
+}
+
+#else
+
+static u_int8_t
+tels0163P_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what+1].t;
+ bus_space_handle_t h = sc->sc_maps[what+1].h;
+ bus_size_t o = sc->sc_maps[what+1].offset;
+ return bus_space_read_1(t, h, o + offs);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_s0163P - probe for Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_probe_s0163P(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ switch(ffs(dev->id_irq) - 1)
+ {
+ case 3:
+ case 5:
+ case 7:
+ case 10:
+ case 11:
+ case 12:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ break;
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ case 0x500:
+ case 0x680:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3 PnP!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ switch(dev->id_iobase)
+ {
+ case 0x580:
+ ISAC_BASE = (caddr_t) 0x580 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x180 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x180;
+ break;
+
+ case 0x500:
+ ISAC_BASE = (caddr_t) 0x500 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x100 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x100;
+ break;
+
+ case 0x680:
+ ISAC_BASE = (caddr_t) 0x680 - 0x20;
+ HSCX_A_BASE = (caddr_t) 0x280 - 0x20;
+ HSCX_B_BASE = (caddr_t) 0x280;
+ break;
+ }
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for the S0/16.3 PnP card is
+ * 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for Teles S0/16.3 PnP\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+#endif
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_s0163P - attach Teles S0/16.3 PnP and compatibles
+ *---------------------------------------------------------------------------*/
+#ifdef __FreeBSD__
+int
+isic_attach_s0163P(struct isa_device *dev)
+{
+ outb((dev->id_iobase) + 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ outb((dev->id_iobase) + 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+ return(1);
+}
+
+#else
+
+void
+isic_attach_s0163P(struct isic_softc *sc)
+{
+ /* init card */
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ bus_space_write_1(t, h, 0x1c, 0);
+ DELAY(SEC_DELAY / 10);
+ bus_space_write_1(t, h, 0x1c, 1);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = tels0163P_read_reg;
+ sc->writereg = tels0163P_write_reg;
+
+ sc->readfifo = tels0163P_read_fifo;
+ sc->writefifo = tels0163P_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_163P;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+}
+#endif
+
+#endif /* ISIC > 0 */
+
diff --git a/sys/i4b/layer1/i4b_usr_sti.c b/sys/i4b/layer1/i4b_usr_sti.c
new file mode 100644
index 0000000..db89296
--- /dev/null
+++ b/sys/i4b/layer1/i4b_usr_sti.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp)
+ * -------------------------------------------------------------
+ *
+ * $Id: i4b_usr_sti.c,v 1.16 1998/12/05 18:05:02 hm Exp $
+ *
+ * last edit-date: [Sat Dec 5 18:25:34 1998]
+ *
+ *---------------------------------------------------------------------------*/
+
+#if defined(__FreeBSD__)
+#include "isic.h"
+#include "opt_i4b.h"
+#else
+#define NISIC 1
+#endif
+#if NISIC > 0 && defined(USR_STI)
+
+#include <sys/param.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+
+#ifdef __FreeBSD__
+#include <machine/clock.h>
+#include <i386/isa/isa_device.h>
+#else
+#include <machine/bus.h>
+#include <sys/device.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_debug.h>
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ * USR Sportster TA intern special registers
+ *---------------------------------------------------------------------------*/
+#define USR_HSCXA_OFF 0x0000
+#define USR_HSCXB_OFF 0x4000
+#define USR_INTL_OFF 0x8000
+#define USR_ISAC_OFF 0xc000
+
+#define USR_RES_BIT 0x80 /* 0 = normal, 1 = reset ISAC/HSCX */
+#define USR_INTE_BIT 0x40 /* 0 = IRQ disabled, 1 = IRQ's enabled */
+#define USR_IL_MASK 0x07 /* IRQ level config */
+
+static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 };
+
+#ifdef __FreeBSD__
+
+#define ADDR(reg) \
+ (((reg/4) * 1024) + ((reg%4) * 2))
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(void *buf, const void *base, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ *((u_char *)buf + offset) = inb((int)base + ADDR(offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(void *base, const void *buf, size_t len)
+{
+ register int offset = 0;
+
+ for(;len > 0; len--, offset++)
+ outb((int)base + ADDR(offset), *((u_char *)buf + offset));
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(u_char *base, u_int offset, u_int v)
+{
+ outb((int)base + ADDR(offset), (u_char)v);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(u_char *base, u_int offset)
+{
+ return(inb((int)base + ADDR(offset)));
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isa_device *dev)
+{
+ struct isic_softc *sc = &isic_sc[dev->id_unit];
+
+ /* check max unit range */
+
+ if(dev->id_unit >= ISIC_MAXUNIT)
+ {
+ printf("isic%d: Error, unit %d >= MAXUNIT for USR Sportster TA!\n",
+ dev->id_unit, dev->id_unit);
+ return(0);
+ }
+ sc->sc_unit = dev->id_unit;
+
+ /* check IRQ validity */
+
+ if((intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, (ffs(dev->id_irq))-1);
+ return(0);
+ }
+ sc->sc_irq = dev->id_irq;
+
+ /* check if memory addr specified */
+
+ if(dev->id_maddr)
+ {
+ printf("isic%d: Error, mem addr 0x%lx specified for USR Sportster TA!\n",
+ dev->id_unit, (u_long)dev->id_maddr);
+ return(0);
+ }
+ dev->id_msize = 0;
+
+ /* check if we got an iobase */
+
+ switch(dev->id_iobase)
+ {
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ case 0x220:
+ case 0x228:
+ case 0x230:
+ case 0x238:
+ case 0x240:
+ case 0x248:
+ case 0x250:
+ case 0x258:
+ case 0x260:
+ case 0x268:
+ case 0x270:
+ case 0x278:
+ break;
+
+ default:
+ printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
+ dev->id_unit, dev->id_iobase);
+ return(0);
+ break;
+ }
+ sc->sc_port = dev->id_iobase;
+
+ /* setup ISAC access routines */
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* setup ISAC and HSCX base addr */
+
+ ISAC_BASE = (caddr_t)dev->id_iobase + USR_ISAC_OFF;
+ HSCX_A_BASE = (caddr_t)dev->id_iobase + USR_HSCXA_OFF;
+ HSCX_B_BASE = (caddr_t)dev->id_iobase + USR_HSCXB_OFF;
+
+ /*
+ * Read HSCX A/B VSTR. Expected value for USR Sportster TA based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
+ ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
+ {
+ printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
+ dev->id_unit);
+ printf("isic%d: HSC0: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(0, H_VSTR));
+ printf("isic%d: HSC1: VSTR: %#x\n",
+ dev->id_unit, HSCX_READ(1, H_VSTR));
+ return (0);
+ }
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct isa_device *dev)
+{
+ u_char irq = 0;
+
+ /* reset the HSCX and ISAC chips */
+
+ outb(dev->id_iobase + USR_INTL_OFF, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ outb(dev->id_iobase + USR_INTL_OFF, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ if((irq = intr_no[ffs(dev->id_irq) - 1]) == 0)
+ {
+ printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n",
+ dev->id_unit, ffs(dev->id_irq)-1);
+ return(0);
+ }
+
+ /* configure and enable irq */
+
+ outb(dev->id_iobase + USR_INTL_OFF, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#else /* end of FreeBSD, start NetBSD */
+
+/*
+ * Use of sc->sc_maps:
+ * 0 : config register
+ * 1 - 16 : HSCX A registers
+ * 17 - 32 : HSCX B registers
+ * 33 - 48 : ISAC registers
+ */
+
+#define USR_REG_OFFS(reg) ((reg % 4) * 2)
+#define USR_HSCXA_MAP(reg) ((reg / 4) + 1)
+#define USR_HSCXB_MAP(reg) ((reg / 4) + 17)
+#define USR_ISAC_MAP(reg) ((reg / 4) + 33)
+
+static int map_base[] = { 33, 1, 17, 0 }; /* ISAC, HSCX A, HSCX B */
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ int map, off, offset;
+ u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ *p++ = bus_space_read_1(t, h, off);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write fifo routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ int map, off, offset;
+ const u_char * p = buf;
+ bus_space_tag_t t;
+ bus_space_handle_t h;
+ u_char v;
+
+ for (offset = 0; size > 0; size--, offset++) {
+ map = map_base[what] + (offset / 4);
+ t = sc->sc_maps[map].t;
+ h = sc->sc_maps[map].h;
+ off = USR_REG_OFFS(offset);
+
+ v = *p++;
+ bus_space_write_1(t, h, off, v);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics write register routine
+ *---------------------------------------------------------------------------*/
+static void
+usrtai_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ bus_space_write_1(t, h, off, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * USRobotics read register routine
+ *---------------------------------------------------------------------------*/
+static u_char
+usrtai_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ int map = map_base[what] + (offs / 4),
+ off = USR_REG_OFFS(offs);
+ bus_space_tag_t t = sc->sc_maps[map].t;
+ bus_space_handle_t h = sc->sc_maps[map].h;
+
+ return bus_space_read_1(t, h, off);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_probe_usrtai - probe for USR
+ *---------------------------------------------------------------------------*/
+int
+isic_probe_usrtai(struct isic_attach_args *ia)
+{
+ /*
+ * Read HSCX A/B VSTR. Expected value for IOM2 based
+ * boards is 0x05 in the least significant bits.
+ */
+
+ if(((bus_space_read_1(ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05) ||
+ ((bus_space_read_1(ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05))
+ return 0;
+
+ return (1);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic_attach_usrtai - attach USR
+ *---------------------------------------------------------------------------*/
+int
+isic_attach_usrtai(struct isic_softc *sc)
+{
+ bus_space_tag_t t = sc->sc_maps[0].t;
+ bus_space_handle_t h = sc->sc_maps[0].h;
+ u_char irq = intr_no[sc->sc_irq];
+
+ sc->clearirq = NULL;
+ sc->readreg = usrtai_read_reg;
+ sc->writereg = usrtai_write_reg;
+
+ sc->readfifo = usrtai_read_fifo;
+ sc->writefifo = usrtai_write_fifo;
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_USRTA;
+
+ /* setup IOM bus type */
+
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* reset the HSCX and ISAC chips */
+
+ bus_space_write_1(t, h, 0, USR_RES_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ bus_space_write_1(t, h, 0, 0x00);
+ DELAY(SEC_DELAY / 10);
+
+ /* setup IRQ */
+
+ bus_space_write_1(t, h, 0, irq | USR_INTE_BIT);
+ DELAY(SEC_DELAY / 10);
+
+ return (1);
+}
+
+#endif /* __FreeBSD__ */
+
+#endif /* ISIC > 0 */
diff --git a/sys/i4b/layer1/isa_isic.c b/sys/i4b/layer1/isa_isic.c
new file mode 100644
index 0000000..94e4bf7
--- /dev/null
+++ b/sys/i4b/layer1/isa_isic.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright (c) 1997, 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isa_isic.c - ISA bus frontend for i4b_isic driver
+ * --------------------------------------------------
+ *
+ * $Id: isa_isic.c,v 1.18 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:53:16 1998]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+
+#if defined(__OpenBSD__)
+#define __BROKEN_INDIRECT_CONFIG
+#endif
+
+/* local functions */
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isa_isic_probe __P((struct device *, void *, void *));
+#else
+static int isa_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+
+static void isa_isic_attach __P((struct device *, struct device *, void *));
+static int setup_io_map __P((int flags, bus_space_tag_t iot,
+ bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr,
+ int *num_mappings, struct isic_io_map *maps, int *iosize,
+ int *msize));
+static void args_unmap __P((int *num_mappings, struct isic_io_map *maps));
+
+struct cfattach isa_isic_ca = {
+ sizeof(struct isic_softc), isa_isic_probe, isa_isic_attach
+};
+
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isa_isic_probe(parent, match, aux)
+#else
+isa_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+#ifdef __BROKEN_INDIRECT_CONFIG
+ struct cfdata *cf = ((struct device*)match)->dv_cfdata;
+#endif
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot;
+ int flags = cf->cf_flags;
+ struct isic_attach_args args;
+ int ret = 0;
+
+ /* check irq */
+ if (ia->ia_irq == IRQUNK) {
+ printf("isic%d: config error: no IRQ specified\n", cf->cf_unit);
+ return 0;
+ }
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* if card type specified setup io map for that card */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ case FLAG_ITK_IX1:
+ if (setup_io_map(flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &ia->ia_msize)) {
+ ret = 0;
+ goto done;
+ }
+ break;
+
+ default:
+ /* no io map now, will figure card type later */
+ break;
+ }
+
+ /* probe card */
+ switch(flags)
+ {
+#ifdef DYNALINK
+ case FLAG_DYNALINK:
+ ret = isic_probe_Dyn(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_8
+ case FLAG_TELES_S0_8:
+ ret = isic_probe_s08(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_16
+ case FLAG_TELES_S0_16:
+ ret = isic_probe_s016(&args);
+ break;
+#endif
+
+#ifdef TEL_S0_16_3
+ case FLAG_TELES_S0_163:
+ ret = isic_probe_s0163(&args);
+ break;
+#endif
+
+#ifdef AVM_A1
+ case FLAG_AVM_A1:
+ ret = isic_probe_avma1(&args);
+ break;
+#endif
+
+#ifdef USR_STI
+ case FLAG_USR_ISDN_TA_INT:
+ ret = isic_probe_usrtai(&args);
+ break;
+#endif
+
+#ifdef ITKIX1
+ case FLAG_ITK_IX1:
+ ret = isic_probe_itkix1(&args);
+ break;
+#endif
+
+ default:
+ /* No card type given, try to figure ... */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ ret = 0;
+#ifdef TEL_S0_16_3
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16_3 */
+#ifdef AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* AVM_A1 */
+#ifdef USR_STI
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ break;
+ }
+#endif /* USR_STI */
+
+#ifdef ITKIX1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_ITK_IX1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ break;
+ }
+#endif /* ITKIX1 */
+
+ } else {
+#ifdef TEL_S0_16_3
+ /* could be anything */
+ args.ia_flags = FLAG_TELES_S0_163;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16_3 */
+#ifdef TEL_S0_16
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_16;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s016(&args);
+ if (ret)
+ break;
+ }
+#endif /* TEL_S0_16 */
+#ifdef AVM_A1
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_AVM_A1;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ break;
+ }
+#endif /* AVM_A1 */
+#ifdef TEL_S0_8
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ args.ia_flags = FLAG_TELES_S0_8;
+ if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0],
+ &(ia->ia_iosize), &(ia->ia_msize)) == 0)
+ {
+ ret = isic_probe_s08(&args);
+ }
+#endif /* TEL_S0_8 */
+ }
+ break;
+ }
+
+done:
+ /* unmap resources */
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+
+ return ret;
+}
+
+/*
+ * Attach the card
+ */
+static void
+isa_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isic_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ int flags = sc->sc_dev.dv_cfdata->cf_flags;
+ int ret = 0;
+ struct isic_attach_args args;
+
+ /* Setup parameters */
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_maddr = ia->ia_maddr;
+ sc->sc_num_mappings = 0;
+ sc->sc_maps = NULL;
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ case FLAG_TELES_S0_16:
+ case FLAG_TELES_S0_163:
+ case FLAG_AVM_A1:
+ case FLAG_USR_ISDN_TA_INT:
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), NULL, NULL, NULL);
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ break;
+
+ default:
+ /* No card type given, try to figure ... */
+
+ /* setup MI attach args */
+ bzero(&args, sizeof(args));
+ args.ia_flags = flags;
+
+ /* Probe cards */
+ if (ia->ia_iobase == IOBASEUNK) {
+ ret = 0;
+#ifdef TEL_S0_8
+ /* only Teles S0/8 will work without IO */
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_8 */
+ } else if (ia->ia_maddr == MADDRUNK) {
+ /* no shared memory, only a 16.3 based card,
+ AVM A1, the usr sportster or an ITK would work */
+ ret = 0;
+#ifdef TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16_3 */
+#ifdef AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* AVM_A1 */
+#ifdef USR_STI
+ args.ia_flags = FLAG_USR_ISDN_TA_INT;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_usrtai(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* USR_STI */
+#ifdef ITKIX1
+ args.ia_flags = FLAG_ITK_IX1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_itkix1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* ITKIX1 */
+ } else {
+ /* could be anything */
+ ret = 0;
+#ifdef TEL_S0_16_3
+ args.ia_flags = FLAG_TELES_S0_163;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s0163(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16_3 */
+#ifdef TEL_S0_16
+ args.ia_flags = FLAG_TELES_S0_16;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s016(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_16 */
+#ifdef AVM_A1
+ args.ia_flags = FLAG_AVM_A1;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_avma1(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* AVM_A1 */
+#ifdef TEL_S0_8
+ args.ia_flags = FLAG_TELES_S0_8;
+ setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL);
+ ret = isic_probe_s08(&args);
+ if (ret)
+ goto found;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+#endif /* TEL_S0_8 */
+ }
+ break;
+
+ found:
+ flags = args.ia_flags;
+ sc->sc_num_mappings = args.ia_num_mappings;
+ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]);
+ if (ret) {
+ MALLOC_MAPS(sc);
+ setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr,
+ &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL);
+ } else {
+ printf(": could not determine card type - not configured!\n");
+ return;
+ }
+ break;
+ }
+
+#if defined(__OpenBSD__)
+ isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc, sc->sc_dev.dv_xname);
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+#else
+
+ /* MI initialization of card */
+ isicattach(flags, sc);
+
+ /*
+ * Try to get a level-triggered interrupt first. If that doesn't
+ * work (like on NetBSD/Atari, try to establish an edge triggered
+ * interrupt.
+ */
+ if (isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_LEVEL,
+ IPL_NET, isicintr, sc) == NULL) {
+ if(isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, isicintr, sc) == NULL) {
+ args_unmap(&(sc->sc_num_mappings), &(sc->sc_maps[0]));
+ free((sc)->sc_maps, M_DEVBUF);
+ }
+ else {
+ /*
+ * XXX: This is a hack that probably needs to be
+ * solved by setting an interrupt type in the sc
+ * structure. I don't feel familiar enough with the
+ * code to do this currently. Feel free to contact
+ * me about it (leo@netbsd.org).
+ */
+ isicintr(sc);
+ }
+ }
+#endif
+}
+
+/*
+ * Setup card specific io mapping. Return 0 on success,
+ * any other value on config error.
+ * Be prepared to get NULL as maps array.
+ * Make sure to keep *num_mappings in sync with the real
+ * mappings already setup when returning!
+ */
+static int
+setup_io_map(flags, iot, memt, iobase, maddr, num_mappings, maps, iosize, msize)
+ int flags, *num_mappings, *iosize, *msize;
+ bus_size_t iobase, maddr;
+ bus_space_tag_t iot, memt;
+ struct isic_io_map *maps;
+{
+ /* nothing mapped yet */
+ *num_mappings = 0;
+
+ /* which resources do we need? */
+ switch(flags)
+ {
+ case FLAG_TELES_S0_8:
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/8!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 0; /* no i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* this card uses a single memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = memt;
+ maps[0].offset = 0;
+ maps[0].size = 0x1000;
+ if (bus_space_map(maps[0].t, maddr,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_16:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (maddr == MADDRUNK) {
+ printf("isic: config error: no shared memory specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* i/o ports */
+ if (msize) *msize = 0x1000; /* shared memory size */
+
+ /* one io and one memory mapping */
+ if (maps == NULL) {
+ *num_mappings = 2;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = memt;
+ maps[1].offset = 0;
+ maps[1].size = 0x1000;
+ if (bus_space_map(maps[1].t, maddr,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_TELES_S0_163:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for Teles S0/16!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Four io mappings: config, isac, 2 * hscx */
+ if (maps == NULL) {
+ *num_mappings = 4;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if (bus_space_map(maps[0].t, iobase,
+ maps[0].size, 0, &maps[0].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[1].t = iot;
+ maps[1].offset = 0;
+ maps[1].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x980) < 0 || (iobase - 0xd80 + 0x980) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase - 0xd80 + 0x980,
+ maps[1].size, 0, &maps[1].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[2].t = iot;
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x180) < 0 || (iobase - 0xd80 + 0x180) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase - 0xd80 + 0x180,
+ maps[2].size, 0, &maps[2].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ maps[3].t = iot;
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase - 0xd80 + 0x580) < 0 || (iobase - 0xd80 + 0x580) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase - 0xd80 + 0x580,
+ maps[3].size, 0, &maps[3].h)) {
+ return 1;
+ }
+ (*num_mappings)++;
+ break;
+
+ case FLAG_AVM_A1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no i/o address specified for AVM A1/Fritz! card!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* only some i/o ports shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* Seven io mappings: config, isac, 2 * hscx,
+ isac-fifo, 2 * hscx-fifo */
+ if (maps == NULL) {
+ *num_mappings = 7;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].t = iot; /* config */
+ maps[0].offset = 0;
+ maps[0].size = 8;
+ if ((iobase + 0x1800) < 0 || (iobase + 0x1800) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[0].t, iobase + 0x1800, maps[0].size, 0, &maps[0].h))
+ return 1;
+ (*num_mappings)++;
+ maps[1].t = iot; /* isac */
+ maps[1].offset = 0;
+ maps[1].size = 0x80; /* XXX - ??? */
+ if ((iobase + 0x1400 - 0x20) < 0 || (iobase + 0x1400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[1].t, iobase + 0x1400 - 0x20, maps[1].size, 0, &maps[1].h))
+ return 1;
+ (*num_mappings)++;
+ maps[2].t = iot; /* hscx 0 */
+ maps[2].offset = 0;
+ maps[2].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0x400 - 0x20) < 0 || (iobase + 0x400 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[2].t, iobase + 0x400 - 0x20, maps[2].size, 0, &maps[2].h))
+ return 1;
+ (*num_mappings)++;
+ maps[3].t = iot; /* hscx 1 */
+ maps[3].offset = 0;
+ maps[3].size = 0x40; /* XXX - ??? */
+ if ((iobase + 0xc00 - 0x20) < 0 || (iobase + 0xc00 - 0x20) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[3].t, iobase + 0xc00 - 0x20, maps[3].size, 0, &maps[3].h))
+ return 1;
+ (*num_mappings)++;
+ maps[4].t = iot; /* isac-fifo */
+ maps[4].offset = 0;
+ maps[4].size = 1;
+ if ((iobase + 0x1400 - 0x20 -0x3e0) < 0 || (iobase + 0x1400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[4].t, iobase + 0x1400 - 0x20 -0x3e0, maps[4].size, 0, &maps[4].h))
+ return 1;
+ (*num_mappings)++;
+ maps[5].t = iot; /* hscx 0 fifo */
+ maps[5].offset = 0;
+ maps[5].size = 1;
+ if ((iobase + 0x400 - 0x20 -0x3e0) < 0 || (iobase + 0x400 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[5].t, iobase + 0x400 - 0x20 -0x3e0, maps[5].size, 0, &maps[5].h))
+ return 1;
+ (*num_mappings)++;
+ maps[6].t = iot; /* hscx 1 fifo */
+ maps[6].offset = 0;
+ maps[6].size = 1;
+ if ((iobase + 0xc00 - 0x20 -0x3e0) < 0 || (iobase + 0xc00 - 0x20 -0x3e0) > 0x0ffff)
+ return 1;
+ if (bus_space_map(maps[6].t, iobase + 0xc00 - 0x20 -0x3e0, maps[6].size, 0, &maps[6].h))
+ return 1;
+ (*num_mappings)++;
+ break;
+
+ case FLAG_USR_ISDN_TA_INT:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for USR Sportster TA intern!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 8; /* scattered ports, only some shown */
+ if (msize) *msize = 0; /* no shared memory */
+
+ /* 49 io mappings: 1 config and 48x8 registers */
+ if (maps == NULL) {
+ *num_mappings = 49;
+ return 0;
+ }
+ *num_mappings = 0;
+ {
+ int i, num;
+ bus_size_t base;
+
+ /* config at offset 0x8000 */
+ base = iobase + 0x8000;
+ maps[0].size = 1;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (base < 0 || base > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base, 1, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = num = 1;
+
+ /* HSCX A at offset 0 */
+ base = iobase;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* HSCX B at offset 0x4000 */
+ base = iobase + 0x4000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ /* ISAC at offset 0xc000 */
+ base = iobase + 0xc000;
+ for (i = 0; i < 16; i++) {
+ maps[num].size = 8;
+ maps[num].offset = 0;
+ maps[num].t = iot;
+ if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff)
+ return 1;
+ if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) {
+ return 1;
+ }
+ *num_mappings = ++num;
+ }
+ }
+ break;
+
+ case FLAG_ITK_IX1:
+ if (iobase == IOBASEUNK) {
+ printf("isic: config error: no I/O base specified for ITK ix1 micro!\n");
+ return 1;
+ }
+ if (iosize) *iosize = 4;
+ if (msize) *msize = 0;
+ if (maps == NULL) {
+ *num_mappings = 1;
+ return 0;
+ }
+ *num_mappings = 0;
+ maps[0].size = 4;
+ maps[0].t = iot;
+ maps[0].offset = 0;
+ if (bus_space_map(iot, iobase, 4, 0, &maps[0].h)) {
+ return 1;
+ }
+ *num_mappings = 1;
+ break;
+
+ default:
+ printf("isic: config error: flags do not specify any known card!\n");
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static void
+args_unmap(num_mappings, maps)
+ int *num_mappings;
+ struct isic_io_map *maps;
+{
+ int i, n;
+ for (i = 0, n = *num_mappings; i < n; i++)
+ if (maps[i].size)
+ bus_space_unmap(maps[i].t, maps[i].h, maps[i].size);
+ *num_mappings = 0;
+}
diff --git a/sys/i4b/layer1/isapnp_isic.c b/sys/i4b/layer1/isapnp_isic.c
new file mode 100644
index 0000000..9dfdf68
--- /dev/null
+++ b/sys/i4b/layer1/isapnp_isic.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 1997, 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isapnp_isic.c - ISA-P&P bus frontend for i4b_isic driver
+ * --------------------------------------------------------
+ *
+ * $Id: isapnp_isic.c,v 1.9 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Dec 14 10:54:23 1998]
+ *
+ * -mh original implementation
+ * -hm NetBSD patches from Martin
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isapnp/isapnpreg.h>
+#include <dev/isapnp/isapnpvar.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+
+#ifdef __BROKEN_INDIRECT_CONFIG
+static int isapnp_isic_probe __P((struct device *, void *, void *));
+#else
+static int isapnp_isic_probe __P((struct device *, struct cfdata *, void *));
+#endif
+static void isapnp_isic_attach __P((struct device *, struct device *, void *));
+
+struct cfattach isapnp_isic_ca = {
+ sizeof(struct isic_softc), isapnp_isic_probe, isapnp_isic_attach
+};
+
+typedef void (*allocmaps_func)(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+typedef void (*attach_func)(struct isic_softc *sc);
+
+/* map allocators */
+static void generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+static void ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+static void tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc);
+
+/* card attach functions */
+extern void isic_attach_Cs0P __P((struct isic_softc *sc));
+extern void isic_attach_Dyn __P((struct isic_softc *sc));
+extern void isic_attach_s0163P __P((struct isic_softc *sc));
+extern void isic_attach_drnngo __P((struct isic_softc *sc));
+extern void isic_attach_sws __P((struct isic_softc *sc));
+extern void isic_attach_Eqs1pi __P((struct isic_softc *sc));
+
+struct isapnp_isic_card_desc {
+ char *devlogic; /* ISAPNP logical device ID */
+ char *name; /* Name of the card */
+ int card_type; /* isic card type identifier */
+ allocmaps_func allocmaps; /* map allocator function */
+ attach_func attach; /* card attach and init function */
+};
+static const struct isapnp_isic_card_desc
+isapnp_isic_descriptions[] =
+{
+#ifdef CRTX_S0_P
+ { "CTX0000", "Creatix ISDN S0-16 P&P", CARD_TYPEP_CS0P,
+ tls_pnp_mapalloc, isic_attach_Cs0P },
+#endif
+#ifdef TEL_S0_16_3_P
+ { "TAG2110", "Teles S0/PnP", CARD_TYPEP_163P,
+ tls_pnp_mapalloc, isic_attach_s0163P },
+#endif
+#ifdef DRN_NGO
+ { "SDA0150", "Dr. Neuhaus NICCY GO@", CARD_TYPEP_DRNNGO,
+ ngo_pnp_mapalloc, isic_attach_drnngo },
+#endif
+#ifdef ELSA_QS1ISA
+ { "ELS0133", "Elsa QuickStep 1000 (ISA)", CARD_TYPEP_ELSAQS1ISA,
+ generic_pnp_mapalloc, isic_attach_Eqs1pi },
+#endif
+#ifdef SEDLBAUER
+ { "SAG0001", "Sedlbauer WinSpeed", CARD_TYPEP_SWS,
+ generic_pnp_mapalloc, isic_attach_sws },
+#endif
+#ifdef DYNALINK
+ { "ASU1688", "Dynalink IS64PH", CARD_TYPEP_DYNALINK,
+ generic_pnp_mapalloc, isic_attach_Dyn },
+#endif
+};
+#define NUM_DESCRIPTIONS (sizeof(isapnp_isic_descriptions)/sizeof(isapnp_isic_descriptions[0]))
+
+/*
+ * Probe card
+ */
+static int
+#ifdef __BROKEN_INDIRECT_CONFIG
+isapnp_isic_probe(parent, match, aux)
+#else
+isapnp_isic_probe(parent, cf, aux)
+#endif
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *cf;
+#endif
+ void *aux;
+{
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ return 1;
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for ISA P&P cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+static void
+isapnp_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ struct isic_softc *sc = (void *)self;
+ struct isapnp_attach_args *ipa = aux;
+ const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions;
+ int i;
+
+ for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
+ if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
+ break;
+ if (i >= NUM_DESCRIPTIONS)
+ panic("could not identify isic PnP device");
+
+ /* setup parameters */
+ sc->sc_cardtyp = desc->card_type;
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ sc->sc_irq = ipa->ipa_irq[0].num;
+ desc->allocmaps(ipa, sc);
+
+ /* announce card name */
+ printf(": %s\n", desc->name);
+
+ /* establish interrupt handler */
+ isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, IST_EDGE,
+ IPL_NET, isicintr, sc);
+
+ /* init card */
+ isic_sc[sc->sc_unit] = sc;
+ desc->attach(sc);
+
+ /* announce chip versions */
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return;
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return;
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+}
+
+static void
+generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 1; /* most cards have just one mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+}
+
+static void
+ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 2; /* one data, one address mapping */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[1].h;
+ sc->sc_maps[1].size = 0;
+}
+
+static void
+tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc)
+{
+ sc->sc_num_mappings = 4; /* config, isac, 2 * hscx */
+ MALLOC_MAPS(sc); /* malloc the maps */
+ sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */
+ sc->sc_maps[0].h = ipa->ipa_io[0].h;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+ sc->sc_maps[1].t = ipa->ipa_iot;
+ sc->sc_maps[1].h = ipa->ipa_io[0].h;
+ sc->sc_maps[1].size = 0;
+ sc->sc_maps[1].offset = - 0x20;
+ sc->sc_maps[2].t = ipa->ipa_iot;
+ sc->sc_maps[2].offset = - 0x20;
+ sc->sc_maps[2].h = ipa->ipa_io[1].h;
+ sc->sc_maps[2].size = 0;
+ sc->sc_maps[3].t = ipa->ipa_iot;
+ sc->sc_maps[3].offset = 0;
+ sc->sc_maps[3].h = ipa->ipa_io[1].h;
+ sc->sc_maps[3].size = 0;
+}
diff --git a/sys/i4b/layer1/isic_supio.c b/sys/i4b/layer1/isic_supio.c
new file mode 100644
index 0000000..6c58ad2
--- /dev/null
+++ b/sys/i4b/layer1/isic_supio.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 1998 Ignatios Souvatzis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * isic_supio.c - Amiga supio pseudo bus frontend for i4b_isic driver
+ * supports:
+ * - ISDN Blaster 5001/1
+ * - ISDN Master 2092/64
+ * But we attach to the supio, so just see "isic".
+ * -----------------------------------------------
+ *
+ * $Id: isic_supio.c,v 1.5 1998/12/19 12:07:55 hm Exp $
+ *
+ * last edit-date: [Mon Nov 16 12:29:19 1998]
+ *
+ * -is original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <amiga/dev/supio.h>
+
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/layer1/i4b_isac.h>
+
+/*static*/ int isic_supio_match __P((struct device *, struct cfdata *, void *));
+/*static*/ void isic_supio_attach __P((struct device *, struct device *, void *));
+
+/*static*/ u_int8_t aster_read_reg __P((struct isic_softc *sc, int what,
+ bus_size_t offs));
+/*static*/ void aster_write_reg __P((struct isic_softc *sc, int what,
+ bus_size_t offs, u_int8_t data));
+/*static*/ void aster_read_fifo __P((struct isic_softc *sc, int what,
+ void *buf, size_t size));
+/*static*/ void aster_write_fifo __P((struct isic_softc *sc, int what,
+ const void *data, size_t size));
+
+static int supio_isicattach __P((struct isic_softc *sc));
+
+struct isic_supio_softc {
+ struct isic_softc sc_isic;
+ struct isr sc_isr;
+ struct bus_space_tag sc_bst;
+};
+
+struct cfattach isic_supio_ca = {
+ sizeof(struct isic_supio_softc), isic_supio_match, isic_supio_attach
+};
+
+/*
+ * Probe card
+ */
+/*static*/ int
+isic_supio_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct supio_attach_args *sap = aux;
+
+ /* ARGSUSED */
+ return (!strcmp("isic", sap->supio_name));
+}
+
+int isic_supio_ipl = 2;
+/*
+ * Attach the card
+ */
+/*static*/ void
+isic_supio_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isic_supio_softc *ssc = (void *)self;
+ struct isic_softc *sc = &ssc->sc_isic;
+ struct supio_attach_args *sap = aux;
+
+ bus_space_tag_t bst;
+ bus_space_handle_t h;
+
+ /* setup parameters */
+ sc->sc_cardtyp = CARD_TYPEP_BLMASTER;
+ sc->sc_num_mappings = 3;
+ sc->sc_unit = sc->sc_dev.dv_unit; /* XXX ??? */
+
+ /* create io mappings */
+ MALLOC_MAPS(sc);
+
+ bst = sap->supio_iot;
+ bus_space_map(bst, sap->supio_iobase, 0x400, 0, &h);
+
+ /* ISAC */
+ sc->sc_maps[0].t = bst;
+ sc->sc_maps[0].h = h;
+ sc->sc_maps[0].offset = 0x300/2;
+ sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */
+
+ /* HSCX A */
+ sc->sc_maps[1].t = bst;
+ sc->sc_maps[1].h = h;
+ sc->sc_maps[1].offset = 0x100/2;
+ sc->sc_maps[1].size = 0; /* foreign mapping, leave it alone */
+
+ /* HSCX B */
+ sc->sc_maps[2].t = bst;
+ sc->sc_maps[2].h = h;
+ sc->sc_maps[2].offset = 0x180/2;
+ sc->sc_maps[2].size = 0; /* foreign mapping, leave it alone */
+
+ sc->clearirq = NULL;
+ sc->readreg = aster_read_reg;
+ sc->writereg = aster_write_reg;
+ sc->readfifo = aster_read_fifo;
+ sc->writefifo = aster_write_fifo;
+
+ /* setup card type */
+ sc->sc_cardtyp = CARD_TYPEP_BLMASTER;
+ sc->sc_bustyp = BUS_TYPE_IOM2;
+
+ sc->sc_ipac = 0;
+ sc->sc_bfifolen = HSCX_FIFO_LEN;
+
+ /* enable RTS on HSCX A */
+ aster_write_reg(sc, ISIC_WHAT_HSCXA, H_MODE, HSCX_MODE_RTS);
+
+ /* MI initialization of card */
+
+ printf("\n");
+ supio_isicattach(sc);
+
+ ssc->sc_isr.isr_intr = isicintr;
+ ssc->sc_isr.isr_arg = sc;
+ ssc->sc_isr.isr_ipl = isic_supio_ipl; /* XXX */
+ add_isr(&ssc->sc_isr);
+}
+
+#if 0
+int
+isic_supiointr(p)
+ void *p;
+{
+ /* XXX should test whether it is our interupt at all */
+ add_sicallback((sifunc_t)isicintr, p, NULL);
+ return 1;
+}
+#endif
+
+/*static*/ void
+aster_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_read_multi_1(t, h, o, buf, size);
+}
+
+/*static*/ void
+aster_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_write_multi_1(t, h, o, (u_int8_t*)buf, size);
+}
+
+/*static*/ u_int8_t
+aster_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ return bus_space_read_1(t, h, o + offs);
+}
+
+/*static*/ void
+aster_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
+{
+ bus_space_tag_t t = sc->sc_maps[what].t;
+ bus_space_handle_t h = sc->sc_maps[what].h;
+ bus_size_t o = sc->sc_maps[what].offset;
+
+ bus_space_write_1(t, h, o + offs, data);
+}
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for pcmcia^Wsupio cards
+ * XXX this should be centralized!
+ *---------------------------------------------------------------------------*/
+
+/*
+ * parameter and format for message producing e.g. "isic0: "
+ * there is no FreeBSD/Amiga, so just:
+ */
+
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+
+int
+supio_isicattach(struct isic_softc *sc)
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc;
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pci_isic.c b/sys/i4b/layer1/pci_isic.c
new file mode 100644
index 0000000..6f929e5
--- /dev/null
+++ b/sys/i4b/layer1/pci_isic.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pci_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pci_isic.c,v 1.1 1998/12/16 13:39:47 hm Exp $
+ *
+ * last edit-date: [Mon Nov 16 20:37:32 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l1l2.h>
+
+static int pci_isic_match __P((struct device *, struct cfdata *, void *));
+static void pci_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pci_product * find_matching_card __P((struct pci_attach_args *pa));
+
+extern void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa));
+static int isic_pciattach __P((struct isic_softc *sc));
+
+struct pci_isic_softc {
+ struct isic_softc sc_isic; /* parent class */
+
+ /* PCI-specific goo */
+ void *sc_ih; /* interrupt handler */
+};
+
+struct cfattach pci_isic_ca = {
+ sizeof(struct pci_isic_softc), pci_isic_match, pci_isic_attach
+};
+
+
+static const struct isic_pci_product {
+ pci_vendor_id_t npp_vendor;
+ pci_product_id_t npp_product;
+ int cardtype;
+ int flag;
+ const char * name;
+ void (*attach)(struct isic_softc *sc, struct pci_attach_args *pa);
+} isic_pci_products[] = {
+ { PCI_VENDOR_ELSA, 0x1000,
+ CARD_TYPEP_ELSAQS1PCI, FLAG_ELSA_QS1P_PCI,
+ "ELSA QuickStep 1000pro/PCI",
+ isic_attach_Eqs1pp },
+
+ { 0, 0, 0, 0, NULL, NULL },
+};
+
+static const struct isic_pci_product * find_matching_card(pa)
+ struct pci_attach_args *pa;
+{
+ const struct isic_pci_product * pp = NULL;
+
+ for (pp = isic_pci_products; pp->npp_vendor; pp++)
+ if (PCI_VENDOR(pa->pa_id) == pp->npp_vendor &&
+ PCI_PRODUCT(pa->pa_id) == pp->npp_product)
+ return pp;
+
+ return NULL;
+}
+
+/*
+ * Match card
+ */
+static int
+pci_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pci_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_isic_softc *psc = (void*) self;
+ struct isic_softc *sc = &psc->sc_isic;
+ struct pci_attach_args *pa = aux;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pci_intr_handle_t ih;
+ const struct isic_pci_product * prod;
+ const char *intrstr;
+
+ /* Redo probe */
+ prod = find_matching_card(pa);
+ if (prod == NULL) return; /* oops - not found?!? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+ printf(": %s\n", prod->name);
+
+ /* card initilization and sc setup */
+ prod->attach(sc, pa);
+
+ /* generic setup */
+ isic_pciattach(sc);
+
+ /* Map and establish the interrupt. */
+ if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &ih)) {
+ printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, ih);
+ psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, isicintr, sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ sc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+}
+
+/*---------------------------------------------------------------------------*
+ * isic - pci device driver attach routine
+ *---------------------------------------------------------------------------*/
+static int
+isic_pciattach(sc)
+ struct isic_softc *sc;
+{
+ int ret = 0;
+
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc; /* XXX - hack! */
+
+ sc->sc_isac_version = 0;
+ sc->sc_hscx_version = 0;
+
+ if(sc->sc_ipac)
+ {
+ ret = IPAC_READ(IPAC_ID);
+
+ switch(ret)
+ {
+ case 0x01:
+ printf("%s: IPAC PSB2115 Version 1.1\n", sc->sc_dev.dv_xname);
+ break;
+
+ default:
+ printf("%s: Error, IPAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, ret);
+ return(0);
+ break;
+ }
+ }
+ else
+ {
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ printf("%s: ISAC %s (IOM-%c)\n",
+ sc->sc_dev.dv_xname,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ break;
+
+ default:
+ printf("%s: Error, ISAC version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ printf("%s: HSCX %s\n",
+ sc->sc_dev.dv_xname,
+ HSCXversion[sc->sc_hscx_version]);
+ break;
+
+ default:
+ printf("%s: Error, HSCX version %d unknown!\n",
+ sc->sc_dev.dv_xname, sc->sc_hscx_version);
+ return(0);
+ break;
+ }
+ }
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+#if defined(__FreeBSD__) && __FreeBSD__ >=3
+ callout_handle_init(&sc->sc_T3_callout);
+ callout_handle_init(&sc->sc_T4_callout);
+#endif
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pcmcia_isic.c b/sys/i4b/layer1/pcmcia_isic.c
new file mode 100644
index 0000000..9d428a1
--- /dev/null
+++ b/sys/i4b/layer1/pcmcia_isic.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.c - pcmcia bus frontend for i4b_isic driver
+ * -------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.c,v 1.3 1998/12/05 18:05:04 hm Exp $
+ *
+ * last edit-date: [Fri Dec 4 10:38:43 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+#ifdef __FreeBSD__
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+#else
+#include <i4b/i4b_ioctl.h>
+#include <i4b/i4b_trace.h>
+#endif
+
+#include <i4b/layer1/i4b_l1.h>
+#include <i4b/layer1/i4b_ipac.h>
+#include <i4b/layer1/i4b_isac.h>
+#include <i4b/layer1/i4b_hscx.h>
+
+#include <i4b/include/i4b_l1l2.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer1/pcmcia_isic.h>
+
+static int pcmcia_isic_match __P((struct device *, struct cfdata *, void *));
+static void pcmcia_isic_attach __P((struct device *, struct device *, void *));
+static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa));
+static int pcmcia_isicattach __P((struct isic_softc *sc));
+
+struct cfattach pcmcia_isic_ca = {
+ sizeof(struct pcmcia_isic_softc), pcmcia_isic_match, pcmcia_isic_attach
+};
+
+struct isic_pcmcia_card_entry {
+ int32_t vendor; /* vendor ID */
+ int32_t product; /* product ID */
+ char *cis1_info[4]; /* CIS info to match */
+ char *name; /* name of controller */
+ int function; /* expected PCMCIA function type */
+ int card_type; /* card type found */
+ isic_pcmcia_attach_func attach; /* card initialization */
+};
+
+static const struct isic_pcmcia_card_entry card_list[] = {
+
+#ifdef AVM_PCMCIA
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "AVM", "ISDN A", NULL, NULL },
+ "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia },
+#endif
+
+#ifdef ELSA_ISDNMC
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+ { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
+ { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL },
+ "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc },
+#endif
+
+#ifdef ELSA_MCALL
+ { 0x105, 0x410a,
+ { "ELSA", "MicroLink MC all", NULL, NULL },
+ "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK,
+ CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall },
+#endif
+
+};
+#define NUM_MATCH_ENTRIES (sizeof(card_list)/sizeof(card_list[0]))
+
+static const struct isic_pcmcia_card_entry *
+find_matching_card(pa)
+ struct pcmcia_attach_args *pa;
+{
+ int i, j;
+
+ for (i = 0; i < NUM_MATCH_ENTRIES; i++) {
+ if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor)
+ continue;
+ if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product)
+ continue;
+ if (pa->pf->function != card_list[i].function)
+ continue;
+ for (j = 0; j < 4; j++) {
+ if (card_list[i].cis1_info[j] == NULL)
+ continue; /* wildcard */
+ if (pa->card->cis1_info[j] == NULL)
+ break; /* not available */
+ if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0)
+ break; /* mismatch */
+ }
+ if (j >= 4)
+ break;
+ }
+ if (i >= NUM_MATCH_ENTRIES)
+ return NULL;
+
+ return &card_list[i];
+}
+
+/*
+ * Match card
+ */
+static int
+pcmcia_isic_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct pcmcia_attach_args *pa = aux;
+
+ if (!find_matching_card(pa))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Attach the card
+ */
+static void
+pcmcia_isic_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_isic_softc *psc = (void*) self;
+ struct isic_softc *sc = &psc->sc_isic;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ const struct isic_pcmcia_card_entry * cde;
+
+ /* Which card is it? */
+ cde = find_matching_card(pa);
+ if (cde == NULL) return; /* oops - not found?!? */
+
+ psc->sc_pf = pa->pf;
+ cfe = pa->pf->cfe_head.sqh_first;
+
+ /* Enable the card */
+ pcmcia_function_init(pa->pf, cfe);
+ pcmcia_function_enable(pa->pf);
+
+ if (!cde->attach(psc, cfe, pa))
+ return; /* Ooops ? */
+
+ sc->sc_unit = sc->sc_dev.dv_unit;
+
+ /* Announce card name */
+ printf(": %s\n", cde->name);
+
+ /* MI initilization */
+ pcmcia_isicattach(sc);
+
+ /* setup interrupt */
+ psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * card independend attach for pcmicia cards
+ *---------------------------------------------------------------------------*/
+
+/* parameter and format for message producing e.g. "isic0: " */
+
+#ifdef __FreeBSD__
+#define ISIC_FMT "isic%d: "
+#define ISIC_PARM dev->id_unit
+#define TERMFMT " "
+#else
+#define ISIC_FMT "%s: "
+#define ISIC_PARM sc->sc_dev.dv_xname
+#define TERMFMT "\n"
+#endif
+
+int
+pcmcia_isicattach(struct isic_softc *sc)
+{
+ static char *ISACversion[] = {
+ "2085 Version A1/A2 or 2086/2186 Version 1.1",
+ "2085 Version B1",
+ "2085 Version B2",
+ "2085 Version V2.3 (B3)",
+ "Unknown Version"
+ };
+
+ static char *HSCXversion[] = {
+ "82525 Version A1",
+ "Unknown (0x01)",
+ "82525 Version A2",
+ "Unknown (0x03)",
+ "82525 Version A3",
+ "82525 or 21525 Version 2.1",
+ "Unknown Version"
+ };
+
+ isic_sc[sc->sc_unit] = sc;
+ sc->sc_isac_version = 0;
+ sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
+
+ switch(sc->sc_isac_version)
+ {
+ case ISAC_VA:
+ case ISAC_VB1:
+ case ISAC_VB2:
+ case ISAC_VB3:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
+ ISIC_PARM, sc->sc_isac_version);
+ return(0);
+ break;
+ }
+
+ sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;
+
+ switch(sc->sc_hscx_version)
+ {
+ case HSCX_VA1:
+ case HSCX_VA2:
+ case HSCX_VA3:
+ case HSCX_V21:
+ break;
+
+ default:
+ printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
+ ISIC_PARM, sc->sc_hscx_version);
+ return(0);
+ break;
+ };
+
+ /* ISAC setup */
+
+ isic_isac_init(sc);
+
+ /* HSCX setup */
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
+
+ isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
+
+ /* setup linktab */
+
+ isic_init_linktab(sc);
+
+ /* set trace level */
+
+ sc->sc_trace = TRACE_OFF;
+
+ sc->sc_state = ISAC_IDLE;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ sc->sc_freeflag = 0;
+
+ sc->sc_obuf2 = NULL;
+ sc->sc_freeflag2 = 0;
+
+ /* init higher protocol layers */
+
+ MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
+
+ /* announce chip versions */
+
+ if(sc->sc_isac_version >= ISAC_UNKN)
+ {
+ printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_isac_version);
+ sc->sc_isac_version = ISAC_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
+ ISIC_PARM,
+ ISACversion[sc->sc_isac_version],
+ sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
+ }
+
+ if(sc->sc_hscx_version >= HSCX_UNKN)
+ {
+ printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
+ ISIC_PARM,
+ sc->sc_hscx_version);
+ sc->sc_hscx_version = HSCX_UNKN;
+ }
+ else
+ {
+ printf(ISIC_FMT "HSCX %s" TERMFMT,
+ ISIC_PARM,
+ HSCXversion[sc->sc_hscx_version]);
+ }
+
+ return(1);
+}
+
diff --git a/sys/i4b/layer1/pcmcia_isic.h b/sys/i4b/layer1/pcmcia_isic.h
new file mode 100644
index 0000000..73f52d6
--- /dev/null
+++ b/sys/i4b/layer1/pcmcia_isic.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1998 Martin Husemann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 4. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software and/or documentation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * pcmcia_isic.h - common definitions for pcmcia isic cards
+ * --------------------------------------------------------
+ *
+ * $Id: pcmcia_isic.h,v 1.1 1998/12/02 06:44:30 hm Exp $
+ *
+ * last edit-date: [Mon Nov 30 21:19:14 1998]
+ *
+ * -mh original implementation
+ *
+ *---------------------------------------------------------------------------*/
+
+struct pcmcia_isic_softc {
+ struct isic_softc sc_isic; /* parent class */
+
+ /* PCMCIA-specific goo */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+ void *sc_ih; /* interrupt handler */
+};
+
+typedef int (*isic_pcmcia_attach_func)(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+extern int isic_attach_fritzpcmcia(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsaisdnmc(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+extern int isic_attach_elsamcall(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa);
+
+
OpenPOWER on IntegriCloud