diff options
author | hm <hm@FreeBSD.org> | 1999-08-06 14:05:10 +0000 |
---|---|---|
committer | hm <hm@FreeBSD.org> | 1999-08-06 14:05:10 +0000 |
commit | c318ffb377724b7eab997d3ddd7f16e229f18e4d (patch) | |
tree | 4dd20754e94db3bc400654765c985e981925a884 /sys/i4b/layer1 | |
parent | 29c67703e3751c283a1bdfe7764effe015c13b83 (diff) | |
download | FreeBSD-src-c318ffb377724b7eab997d3ddd7f16e229f18e4d.zip FreeBSD-src-c318ffb377724b7eab997d3ddd7f16e229f18e4d.tar.gz |
updating isdn4bsd to beta version 0.83
Diffstat (limited to 'sys/i4b/layer1')
-rw-r--r-- | sys/i4b/layer1/i4b_asuscom_ipac.c | 510 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_avm_fritz_pci.c | 24 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_avm_fritz_pnp.c | 1268 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_bsdi_ibc.c | 559 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_dynalink.c | 156 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_ipac.h | 8 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_isic.c | 25 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_isic_isa.c | 220 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_isic_pnp.c | 75 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_l1.h | 56 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_siemens_isurf.c | 317 | ||||
-rw-r--r-- | sys/i4b/layer1/i4b_tel_s0163.c | 26 | ||||
-rw-r--r-- | sys/i4b/layer1/isa_isic.c | 12 |
13 files changed, 2550 insertions, 706 deletions
diff --git a/sys/i4b/layer1/i4b_asuscom_ipac.c b/sys/i4b/layer1/i4b_asuscom_ipac.c new file mode 100644 index 0000000..5018e08 --- /dev/null +++ b/sys/i4b/layer1/i4b_asuscom_ipac.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 1999 Ari Suutari. All rights reserved. + * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Asuscom ISDNlink 128K PnP + * ===================================================================== + * + * This driver works with Asuscom ISDNlink 128K PnP ISA adapter, + * which is based on Siemens IPAC chip (my card probes as ASU1690). + * Older Asuscom ISA cards are based on different chipset + * (containing two chips) - for those cards, one might want + * to try the Dynalink driver. + * + * This driver is heavily based on ELSA Quickstep 1000pro PCI + * driver written by Hellmuth Michaelis. Card initialization + * code is modeled after Linux i4l driver written by Karsten + * Keil. + * + * $Id: i4b_asuscom_ipac.c,v 1.1 1999/07/05 13:46:46 hm Exp $ + * + * last edit-date: [Mon May 31 20:53:17 EEST 1999] + * + *---------------------------------------------------------------------------*/ + +#if defined(__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(ASUSCOM_IPAC) + +#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> +#include <i4b/layer1/i4b_ipac.h> + +#ifndef __FreeBSD__ +#include <i4b/layer1/pci_isic.h> +#endif + +/* masks for register encoded in base addr */ + +#define ASI_BASE_MASK 0x0ffff +#define ASI_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ASI_IDISAC 0x00000 +#define ASI_IDHSCXA 0x10000 +#define ASI_IDHSCXB 0x20000 +#define ASI_IDIPAC 0x40000 + +/* offsets from base address */ + +#define ASI_OFF_ALE 0x00 +#define ASI_OFF_RW 0x01 + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K PnP ISAC get fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +asi_read_fifo(void *buf, const void *base, size_t len) +{ + u_int asus_base; + + asus_base = ((u_int) base) & ASI_BASE_MASK; + switch (((u_int) base) & ASI_OFF_MASK) { + case ASI_IDHSCXB: + outb(asus_base + ASI_OFF_ALE, IPAC_HSCXB_OFF); + insb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + case ASI_IDHSCXA: + outb(asus_base + ASI_OFF_ALE, IPAC_HSCXA_OFF); + insb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + case ASI_IDISAC: + outb(asus_base + ASI_OFF_ALE, IPAC_ISAC_OFF); + insb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + } +} + +#else + +static void +asi_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, ASI_OFF_ALE, IPAC_ISAC_OFF); + bus_space_read_multi_1(t, h, ASI_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_read_multi_1(t, h, ASI_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_read_multi_1(t, h, ASI_OFF_RW, buf, size); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K PnP ISAC put fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +asi_write_fifo(void *base, const void *buf, size_t len) +{ + u_int asus_base; + + asus_base = ((u_int) base) & ASI_BASE_MASK; + switch (((u_int) base) & ASI_OFF_MASK) { + case ASI_IDHSCXB: + outb(asus_base + ASI_OFF_ALE, IPAC_HSCXB_OFF); + outsb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + case ASI_IDHSCXA: + outb(asus_base + ASI_OFF_ALE, IPAC_HSCXA_OFF); + outsb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + case ASI_IDISAC: + outb(asus_base + ASI_OFF_ALE, IPAC_ISAC_OFF); + outsb(asus_base + ASI_OFF_RW, (u_char *)buf, (u_int)len); + break; + } +} + +#else + +static void +asi_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, ASI_OFF_ALE, IPAC_ISAC_OFF); + bus_space_write_multi_1(t, h, ASI_OFF_RW, (u_int8_t*)buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_write_multi_1(t, h, ASI_OFF_RW, (u_int8_t*)buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_write_multi_1(t, h, ASI_OFF_RW, (u_int8_t*)buf,size); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K PnP ISAC put register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +asi_write_reg(u_char *base, u_int offset, u_int v) +{ + u_int asus_base; + + asus_base = ((u_int) base) & ASI_BASE_MASK; + switch (((u_int) base) & ASI_OFF_MASK) { + case ASI_IDHSCXB: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + outb(asus_base + ASI_OFF_RW, (u_char)v); + break; + case ASI_IDHSCXA: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + outb(asus_base + ASI_OFF_RW, (u_char)v); + break; + case ASI_IDISAC: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + outb(asus_base + ASI_OFF_RW, (u_char)v); + break; + case ASI_IDIPAC: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + outb(asus_base + ASI_OFF_RW, (u_char)v); + break; + } +} + +#else + +static void +asi_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, ASI_OFF_ALE, IPAC_ISAC_OFF+offs); + bus_space_write_1(t, h, ASI_OFF_RW, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXA_OFF+offs); + bus_space_write_1(t, h, ASI_OFF_RW, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXB_OFF+offs); + bus_space_write_1(t, h, ASI_OFF_RW, data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_IPAC_OFF+offs); + bus_space_write_1(t, h, ASI_OFF_RW, data); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K PnP ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +asi_read_reg(u_char *base, u_int offset) +{ + u_int asus_base; + + asus_base = ((u_int) base) & ASI_BASE_MASK; + switch (((u_int) base) & ASI_OFF_MASK) { + case ASI_IDHSCXB: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + return(inb(asus_base + ASI_OFF_RW)); + case ASI_IDHSCXA: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + return(inb(asus_base + ASI_OFF_RW)); + case ASI_IDISAC: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + return(inb(asus_base + ASI_OFF_RW)); + case ASI_IDIPAC: + outb(asus_base + ASI_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + return(inb(asus_base + ASI_OFF_RW)); + } + + return 0; /* NOTREACHED */ +} + +#else + +static u_int8_t +asi_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, ASI_OFF_ALE, IPAC_ISAC_OFF+offs); + return bus_space_read_1(t, h, ASI_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXA_OFF+offs); + return bus_space_read_1(t, h, ASI_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_HSCXB_OFF+offs); + return bus_space_read_1(t, h, ASI_OFF_RW); + case ISIC_WHAT_IPAC: + bus_space_write_1(t, h, ASI_OFF_ALE, IPAC_IPAC_OFF+offs); + return bus_space_read_1(t, h, ASI_OFF_RW); + } + + return 0; +} + +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_asi - attach for Asuscom ISDNlink 128K PnP + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_asi(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 Asuscom ISDNlink 128K PnP!\n", + dev->id_unit, dev->id_unit); + + return(0); + } + sc->sc_unit = dev->id_unit; + + /* setup iobase */ + + if((dev->id_iobase <= 0) || (dev->id_iobase > 0xffff)) + { + printf("isic%d: Error, invalid iobase 0x%x specified " + "for Asuscom ISDNlink 128K PnP\n", + dev->id_unit, iobase2); + + return(0); + } + + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = asi_read_reg; + sc->writereg = asi_write_reg; + + sc->readfifo = asi_read_fifo; + sc->writefifo = asi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ASI_IDISAC); + HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ASI_IDHSCXA); + HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ASI_IDHSCXB); + IPAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ASI_IDIPAC); + + return (1); +} + +int +isic_attach_asi(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + /* enable hscx/isac irq's */ +#if 0 +/* + * This is for ELSA driver + */ + 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(dev->id_iobase + 0x4c, 0x41); /* enable card interrupt */ +#endif +/* + * This has been taken from Linux driver. + * XXX Figure out bits to use defines as original driver did. + */ + IPAC_WRITE (IPAC_CONF, 0x0); + IPAC_WRITE (IPAC_ACFG, 0xff); + IPAC_WRITE (IPAC_AOE, 0x0); + IPAC_WRITE (IPAC_MASK, 0xc0); + IPAC_WRITE (IPAC_PCFG, 0x12); + + return (1); +} + +#else /* !FreeBSD */ + +void +isic_attach_asi(psc, pa) + struct pci_isic_softc *psc; + struct pci_attach_args *pa; +{ + struct isic_softc *sc = &psc->sc_isic; + + /* setup io mappings */ + sc->sc_num_mappings = 2; + MALLOC_MAPS(sc); + sc->sc_maps[0].size = 0; + if (pci_mapreg_map(pa, ASI_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, ASI_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 = asi_read_reg; + sc->writereg = asi_write_reg; + + sc->readfifo = asi_read_fifo; + sc->writefifo = asi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + +#if 0 +/* + * This for ELSA card in original driver. + */ + /* 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 +/* + * This has been taken from Linux driver. + * XXX Figure out bits to use defines as original driver did. + */ + IPAC_WRITE (IPAC_CONF, 0x0); + IPAC_WRITE (IPAC_ACFG, 0xff); + IPAC_WRITE (IPAC_AOE, 0x0); + IPAC_WRITE (IPAC_MASK, 0xc0); + IPAC_WRITE (IPAC_PCFG, 0x12); +} + + +#endif + +#endif /* (NISIC > 0) && defined(ASUSCOM_IPAC) */ diff --git a/sys/i4b/layer1/i4b_avm_fritz_pci.c b/sys/i4b/layer1/i4b_avm_fritz_pci.c index 2da4f89..c5f2d8a 100644 --- a/sys/i4b/layer1/i4b_avm_fritz_pci.c +++ b/sys/i4b/layer1/i4b_avm_fritz_pci.c @@ -35,9 +35,9 @@ * Fritz!Card PCI specific routines for isic driver * ------------------------------------------------ * - * $Id: i4b_avm_fritz_pci.c,v 1.5 1999/05/05 11:50:21 hm Exp $ + * $Id: i4b_avm_fritz_pci.c,v 1.6 1999/06/01 12:10:25 hm Exp $ * - * last edit-date: [Tue Mar 16 16:18:35 1999] + * last edit-date: [Tue Jun 1 14:08:01 1999] * *---------------------------------------------------------------------------*/ @@ -390,30 +390,31 @@ avma1pp_write_fifo(void *base, const void *buf, size_t len) } /* tell the board to use the ISAC fifo */ outb(sc->sc_port + ADDR_REG_OFFSET, ISAC_FIFO); - outsb(sc->sc_port + ISAC_REG_OFFSET, (u_char *)buf, len); + outsb(sc->sc_port + ISAC_REG_OFFSET, (const u_char *)buf, len); } static void hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc) { - register u_int *ip; + register const u_int *ip; register size_t cnt; isic_Bchan_t *Bchan = &sc->sc_chan[chan]; sc->avma1pp_cmd &= ~HSCX_CMD_XME; sc->avma1pp_txl = 0; - if (len != sc->sc_bfifolen) + if (Bchan->out_mbuf_cur == NULL) { if (Bchan->bprot != BPROT_NONE) sc->avma1pp_cmd |= HSCX_CMD_XME; - sc->avma1pp_txl = len; } - + if (len != sc->sc_bfifolen) + sc->avma1pp_txl = len; + cnt = 0; /* borrow cnt */ AVMA1PPSETCMDLONG(cnt); hscx_write_reg(chan, HSCX_STAT, cnt, sc); - ip = (u_int *)buf; + ip = (const u_int *)buf; cnt = 0; while (cnt < len) { @@ -450,12 +451,13 @@ hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc) sc->avma1pp_cmd &= ~HSCX_CMD_XME; sc->avma1pp_txl = 0; - if (len != sc->sc_bfifolen) + if (Bchan->out_mbuf_cur == NULL) { if (Bchan->bprot != BPROT_NONE) sc->avma1pp_cmd |= HSCX_CMD_XME; - sc->avma1pp_txl = len; } + if (len != sc->sc_bfifolen) + sc->avma1pp_txl = len; cnt = 0; /* borrow cnt */ AVMA1PPSETCMDLONG(cnt); @@ -492,7 +494,7 @@ avma1pp_write_reg(u_char *base, u_int offset, u_int v) hscx_write_reg(0, offset, v, sc); return; } - if (((int)base & IS_HSCX_MASK) == HSCX0FAKE) + if (((int)base & IS_HSCX_MASK) == HSCX1FAKE) { hscx_write_reg(1, offset, v, sc); return; diff --git a/sys/i4b/layer1/i4b_avm_fritz_pnp.c b/sys/i4b/layer1/i4b_avm_fritz_pnp.c new file mode 100644 index 0000000..6da4969 --- /dev/null +++ b/sys/i4b/layer1/i4b_avm_fritz_pnp.c @@ -0,0 +1,1268 @@ +/* + * Copyright (c) 1999 Udo Schweigert. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * A lot of code was borrowed from i4b_bchan.c and i4b_hscx.c + * Based on AVM Fritz!PCI driver by Gary Jennejohn + *--------------------------------------------------------------------------- + * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de> + *--------------------------------------------------------------------------- + * + * Fritz!Card PnP specific routines for isic driver + * ------------------------------------------------ + * + * $Id: i4b_avm_fritz_pnp.c,v 1.3 1999/07/05 13:22:12 hm Exp $ + * + * last edit-date: [Thu 10 Jun 08:50:28 CEST 1999] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(AVM_PNP) + +#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/clock.h> +#include <i386/isa/isa_device.h> + +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +static void hscx_write_reg(int, u_int, struct isic_softc *, int); +static void hscx_write_reg_val(int, u_int, u_char, struct isic_softc *); +static u_char hscx_read_reg(int, u_int, struct isic_softc *); +static void hscx_read_fifo(int, void *, size_t, struct isic_softc *); +static void hscx_write_fifo(int, const void *, size_t, struct isic_softc *); +static void avm_pnp_hscx_int_handler(struct isic_softc *); +static void avm_pnp_hscx_intr(int, int, int, struct isic_softc *); +static void avm_pnp_init_linktab(struct isic_softc *); +static void avm_pnp_bchannel_setup(int, int, int, int); +static void avm_pnp_bchannel_start(int, int); +static void avm_pnp_hscx_init(struct isic_softc *, int, int); +static void avm_pnp_bchannel_stat(int, int, bchan_statistics_t *); +static void avm_pnp_set_linktab(int, int, drvr_link_t *); +static void avm_pnp_intr(int); +static isdn_link_t * avm_pnp_ret_linktab(int, int); +extern void isicintr_sc(struct isic_softc *); + +/*---------------------------------------------------------------------------* + * AVM PnP Fritz!Card special registers + *---------------------------------------------------------------------------*/ + +/* + * register offsets from i/o base + */ +#define STAT0_OFFSET 0x02 +#define STAT1_OFFSET 0x03 +#define ADDR_REG_OFFSET 0x04 + +/* these 2 are used to select an ISAC register set */ +#define ISAC_LO_REG_OFFSET 0x04 +#define ISAC_HI_REG_OFFSET 0x06 + +/* offset higher than this goes to the HI register set */ +#define MAX_LO_REG_OFFSET 0x2f + +/* mask for the offset */ +#define ISAC_REGSET_MASK 0x0f + +/* the offset from the base to the ISAC registers */ +#define ISAC_REG_OFFSET 0x10 + +/* the offset from the base to the ISAC FIFO */ +#define ISAC_FIFO 0x02 + +/* not really the HSCX, but sort of */ +#define HSCX_FIFO 0x00 +#define HSCX_STAT 0x04 + +/* + * AVM PnP Status Latch 0 read only bits + */ +#define ASL_IRQ_ISAC 0x01 /* ISAC interrupt, active low */ +#define ASL_IRQ_HSCX 0x02 /* HSX interrupt, active low */ +#define ASL_IRQ_TIMER 0x04 /* Timer interrupt, active low */ +#define ASL_IRQ_BCHAN ASL_IRQ_HSCX +/* actually active LOW */ +#define ASL_IRQ_Pending 0x07 + +/* + * 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 */ +#define ASL_TESTBIT 0x10 /* active high */ + +/* + * AVM Status Latch 1 write only bits + */ +#define ASL1_INTSEL 0x0f /* active high */ +#define ASL1_ENABLE_IOM 0x80 /* active high */ + +/* + * "HSCX" mode bits + */ +#define HSCX_MODE_ITF_FLG 0x01 +#define HSCX_MODE_TRANS 0x02 +#define HSCX_MODE_CCR_7 0x04 +#define HSCX_MODE_CCR_16 0x08 +#define HSCX_MODE_TESTLOOP 0x80 + +/* + * "HSCX" status bits + */ +#define HSCX_STAT_RME 0x01 +#define HSCX_STAT_RDO 0x10 +#define HSCX_STAT_CRCVFRRAB 0x0E +#define HSCX_STAT_CRCVFR 0x06 +#define HSCX_STAT_RML_MASK 0x3f00 + +/* + * "HSCX" interrupt bits + */ +#define HSCX_INT_XPR 0x80 +#define HSCX_INT_XDU 0x40 +#define HSCX_INT_RPR 0x20 +#define HSCX_INT_MASK 0xE0 + +/* + * "HSCX" command bits + */ +#define HSCX_CMD_XRS 0x80 +#define HSCX_CMD_XME 0x01 +#define HSCX_CMD_RRS 0x20 +#define HSCX_CMD_XML_MASK 0x3f00 + +/* "fake" addresses for the non-existent HSCX */ +/* note: the unit number is in the lower byte for both the ISAC and "HSCX" */ +#define HSCX0FAKE 0xfa000 /* read: fake0 */ +#define HSCX1FAKE 0xfa100 /* read: fake1 */ +#define IS_HSCX_MASK 0xfff00 + +/* + * to prevent deactivating the "HSCX" when both channels are active we + * define an HSCX_ACTIVE flag which is or'd into the channel's state + * flag in avm_pnp_bchannel_setup upon active and cleared upon deactivation. + * It is set high to allow room for new flags. + */ +#define HSCX_AVMPNP_ACTIVE 0x1000 + +/*---------------------------------------------------------------------------* + * AVM read fifo routines + *---------------------------------------------------------------------------*/ + +static void +avm_pnp_read_fifo(void *buf, const void *base, size_t len) +{ + int unit; + struct isic_softc *sc; + + unit = (int)base & 0xff; + sc = &isic_sc[unit]; + + /* check whether the target is an HSCX */ + if (((int)base & IS_HSCX_MASK) == HSCX0FAKE) + { + hscx_read_fifo(0, buf, len, sc); + return; + } + if (((int)base & IS_HSCX_MASK) == HSCX1FAKE) + { + hscx_read_fifo(1, buf, len, sc); + return; + } + /* tell the board to access the ISAC fifo */ + outb(sc->sc_port + ADDR_REG_OFFSET, ISAC_FIFO); + insb(sc->sc_port + ISAC_REG_OFFSET, (u_char *)buf, len); +} + +static void +hscx_read_fifo(int chan, void *buf, size_t len, struct isic_softc *sc) +{ + u_char *ip; + size_t cnt; + + outb(sc->sc_port + ADDR_REG_OFFSET, chan); + ip = (u_char *)buf; + cnt = 0; + + while (cnt < len) + { + *ip++ = inb(sc->sc_port + ISAC_REG_OFFSET); + cnt++; + } +} + +/*---------------------------------------------------------------------------* + * AVM write fifo routines + *---------------------------------------------------------------------------*/ +static void +avm_pnp_write_fifo(void *base, const void *buf, size_t len) +{ + int unit; + struct isic_softc *sc; + + unit = (int)base & 0xff; + sc = &isic_sc[unit]; + + /* check whether the target is an HSCX */ + if (((int)base & IS_HSCX_MASK) == HSCX0FAKE) + { + hscx_write_fifo(0, buf, len, sc); + return; + } + if (((int)base & IS_HSCX_MASK) == HSCX1FAKE) + { + hscx_write_fifo(1, buf, len, sc); + return; + } + /* tell the board to use the ISAC fifo */ + outb(sc->sc_port + ADDR_REG_OFFSET, ISAC_FIFO); + outsb(sc->sc_port + ISAC_REG_OFFSET, (const u_char *)buf, len); +} + +static void +hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc) +{ + register const u_char *ip; + register size_t cnt; + isic_Bchan_t *Bchan = &sc->sc_chan[chan]; + + sc->avma1pp_cmd &= ~HSCX_CMD_XME; + sc->avma1pp_txl = 0; + + if (Bchan->out_mbuf_cur == NULL && Bchan->bprot != BPROT_NONE) + sc->avma1pp_cmd |= HSCX_CMD_XME; + + if (len != sc->sc_bfifolen) + sc->avma1pp_txl = len; + + hscx_write_reg(chan, HSCX_STAT, sc, 3); + + ip = (const u_char *)buf; + cnt = 0; + while (cnt < len) + { + outb(sc->sc_port + ISAC_REG_OFFSET, *ip++); + cnt++; + } +} + +/*---------------------------------------------------------------------------* + * AVM write register routines + *---------------------------------------------------------------------------*/ +static void +avm_pnp_write_reg(u_char *base, u_int offset, u_int v) +{ + int unit; + struct isic_softc *sc; + u_char reg_bank; + + unit = (int)base & 0xff; + sc = &isic_sc[unit]; + + /* check whether the target is an HSCX */ + if (((int)base & IS_HSCX_MASK) == HSCX0FAKE) + { + hscx_write_reg_val(0, offset, v, sc); + return; + } + if (((int)base & IS_HSCX_MASK) == HSCX1FAKE) + { + hscx_write_reg_val(1, offset, v, sc); + return; + } + /* must be the ISAC */ + reg_bank = (offset > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET; + /* set the register bank */ + outb(sc->sc_port + ADDR_REG_OFFSET, reg_bank); + outb(sc->sc_port + ISAC_REG_OFFSET + (offset & ISAC_REGSET_MASK), v); +} + +static void +hscx_write_reg(int chan, u_int off, struct isic_softc *sc, int which) +{ + /* HACK */ + if (off == H_MASK) + return; + /* point at the correct channel */ + outb(sc->sc_port + ADDR_REG_OFFSET, chan); + if (which & 4) + outb(sc->sc_port + ISAC_REG_OFFSET + off + 2, sc->avma1pp_prot); + if (which & 2) + outb(sc->sc_port + ISAC_REG_OFFSET + off + 1, sc->avma1pp_txl); + if (which & 1) + outb(sc->sc_port + ISAC_REG_OFFSET + off, sc->avma1pp_cmd); +} + +static void +hscx_write_reg_val(int chan, u_int off, u_char val, struct isic_softc *sc) +{ + /* HACK */ + if (off == H_MASK) + return; + /* point at the correct channel */ + outb(sc->sc_port + ADDR_REG_OFFSET, chan); + outb(sc->sc_port + ISAC_REG_OFFSET + off, val); +} + +/*---------------------------------------------------------------------------* + * AVM read register routines + *---------------------------------------------------------------------------*/ + +static u_char +avm_pnp_read_reg(u_char *base, u_int offset) +{ + int unit; + struct isic_softc *sc; + u_char reg_bank; + + unit = (int)base & 0xff; + sc = &isic_sc[unit]; + + /* check whether the target is an HSCX */ + if (((int)base & IS_HSCX_MASK) == HSCX0FAKE) + return(hscx_read_reg(0, offset, sc)); + if (((int)base & IS_HSCX_MASK) == HSCX1FAKE) + return(hscx_read_reg(1, offset, sc)); + /* must be the ISAC */ + reg_bank = (offset > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET; + /* set the register bank */ + outb(sc->sc_port + ADDR_REG_OFFSET, reg_bank); + return(inb(sc->sc_port + ISAC_REG_OFFSET + + (offset & ISAC_REGSET_MASK))); +} + +static u_char +hscx_read_reg(int chan, u_int off, struct isic_softc *sc) +{ + /* HACK */ + if (off == H_ISTA) + return(0); + /* point at the correct channel */ + outb(sc->sc_port + ADDR_REG_OFFSET, chan); + return(inb(sc->sc_port + ISAC_REG_OFFSET + off)); +} + +/*---------------------------------------------------------------------------* + * isic_probe_avm_pnp - probe Fritz!Card PnP + *---------------------------------------------------------------------------*/ + +int +isic_probe_avm_pnp(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 AVM Fritz! 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 4: + case 5: + case 7: + case 10: + case 11: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for AVM Fritz! PnP!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + dev->id_intr = (inthand2_t *) avm_pnp_intr; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for AVM Fritz! PnP!\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 AVM Fritz! PnP!\n", + dev->id_unit, dev->id_iobase); + return(0); + } + sc->sc_port = dev->id_iobase; + + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = avm_pnp_read_reg; + sc->writereg = avm_pnp_write_reg; + + sc->readfifo = avm_pnp_read_fifo; + sc->writefifo = avm_pnp_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_AVM_PNP; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* the ISAC lives at offset 0x10, but we can't use that. */ + /* instead, put the unit number into the lower byte - HACK */ + ISAC_BASE = (caddr_t)((int)(dev->id_iobase & ~0xff) + dev->id_unit); + + outb(sc->sc_port + STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE); + ISAC_WRITE(I_MASK, 0x0); + outb(sc->sc_port + STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE); + ISAC_WRITE(I_MASK, 0x41); + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_avm_pnp - attach Fritz!Card PnP + *---------------------------------------------------------------------------*/ +int +isic_attach_avm_pnp(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc; + u_int v; + int unit; + + unit = dev->id_unit; + sc = &isic_sc[unit]; + + /* this thing doesn't have an HSCX, so fake the base addresses */ + /* put the unit number into the lower byte - HACK */ + HSCX_A_BASE = (caddr_t)(HSCX0FAKE + unit); + HSCX_B_BASE = (caddr_t)(HSCX1FAKE + unit); + + + /* reset the card */ + + /* the Linux driver does this to clear any pending ISAC interrupts */ + v = 0; + v = ISAC_READ(I_STAR); + v = ISAC_READ(I_MODE); + v = ISAC_READ(I_ADF2); + v = ISAC_READ(I_ISTA); + if (v & ISAC_ISTA_EXI) + { + v = ISAC_READ(I_EXIR); + } + v = ISAC_READ(I_CIRR); + ISAC_WRITE(I_MASK, 0xff); + + /* the Linux driver does this to clear any pending HSCX interrupts */ + v = hscx_read_reg(0, HSCX_STAT, sc); + v = hscx_read_reg(0, HSCX_STAT+1, sc); + v = hscx_read_reg(0, HSCX_STAT+2, sc); + v = hscx_read_reg(0, HSCX_STAT+3, sc); + v = hscx_read_reg(1, HSCX_STAT, sc); + v = hscx_read_reg(1, HSCX_STAT+1, sc); + v = hscx_read_reg(1, HSCX_STAT+2, sc); + v = hscx_read_reg(1, HSCX_STAT+3, sc); + + outb(sc->sc_port + STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE); + DELAY(SEC_DELAY/100); /* 10 ms */ + outb(sc->sc_port + STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE); + DELAY(SEC_DELAY/100); /* 10 ms */ + outb(sc->sc_port + STAT1_OFFSET, ASL1_ENABLE_IOM+(ffs(sc->sc_irq)-1)); + DELAY(SEC_DELAY/100); /* 10 ms */ + + printf("isic%d: ISAC %s (IOM-%c)\n", unit, + "2085 Version A1/A2 or 2086/2186 Version 1.1", + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + + /* init the ISAC */ + isic_isac_init(sc); + + /* init the "HSCX" */ + avm_pnp_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + avm_pnp_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* can't use the normal B-Channel stuff */ + avm_pnp_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(0); +} + +/* + * this is the real interrupt routine + */ +static void +avm_pnp_hscx_intr(int h_chan, int stat, int cnt, struct isic_softc *sc) +{ + register isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + int activity = -1; + + DBGL1(L1_H_IRQ, "avm_pnp_hscx_intr", ("%#x\n", stat)); + + if((stat & HSCX_INT_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */ + { + chan->stat_XDU++; + DBGL1(L1_H_XFRERR, "avm_pnp_hscx_intr", ("xmit data underrun\n")); + /* abort the transmission */ + sc->avma1pp_txl = 0; + sc->avma1pp_cmd |= HSCX_CMD_XRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + sc->avma1pp_cmd &= ~HSCX_CMD_XRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + + 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; + } + } + + /* + * The following is based on examination of the Linux driver. + * + * The logic here is different than with a "real" HSCX; all kinds + * of information (interrupt/status bits) are in stat. + * HSCX_INT_RPR indicates a receive interrupt + * HSCX_STAT_RDO indicates an overrun condition, abort - + * otherwise read the bytes ((stat & HSCX_STZT_RML_MASK) >> 8) + * HSCX_STAT_RME indicates end-of-frame and apparently any + * CRC/framing errors are only reported in this state. + * if ((stat & HSCX_STAT_CRCVFRRAB) != HSCX_STAT_CRCVFR) + * CRC/framing error + */ + + if(stat & HSCX_INT_RPR) + { + register int fifo_data_len; + int error = 0; + /* always have to read the FIFO, so use a scratch buffer */ + u_char scrbuf[HSCX_FIFO_LEN]; + + if(stat & HSCX_STAT_RDO) + { + chan->stat_RDO++; + DBGL1(L1_H_XFRERR, "avm_pnp_hscx_intr", ("receive data overflow\n")); + error++; + } + + fifo_data_len = cnt; + + if(fifo_data_len == 0) + fifo_data_len = sc->sc_bfifolen; + + /* ALWAYS read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, scrbuf, fifo_data_len); + chan->rxcount += fifo_data_len; + + /* 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 avm_pnp_hscx_intr: RME, cannot allocate mbuf!\n"); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + } + + if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN) + { + /* OK to copy the data */ + bcopy(scrbuf, chan->in_cbptr, fifo_data_len); + chan->in_cbptr += fifo_data_len; + chan->in_len += 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); + } + + if (stat & HSCX_STAT_RME) + { + if((stat & HSCX_STAT_CRCVFRRAB) == HSCX_STAT_CRCVFR) + { + (*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 + { + chan->stat_CRC++; + DBGL1(L1_H_XFRERR, "avm_pnp_hscx_intr", ("CRC/RAB\n")); + if (chan->in_mbuf != NULL) + { + i4b_Bfreembuf(chan->in_mbuf); + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + } + } + } /* END enough space in mbuf */ + 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 avm_pnp_hscx_intr: RPF, cannot allocate new mbuf!\n"); + + /* setup new data ptr */ + + chan->in_cbptr = chan->in_mbuf->m_data; + + /* OK to copy the data */ + bcopy(scrbuf, chan->in_cbptr, fifo_data_len); + + chan->in_cbptr += fifo_data_len; + chan->in_len = fifo_data_len; + + chan->rxcount += fifo_data_len; + } + else + { + DBGL1(L1_H_XFRERR, "avm_pnp_hscx_intr", ("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; + } + } + } /* if(error == 0) */ + else + { + /* land here for RDO */ + if (chan->in_mbuf != NULL) + { + i4b_Bfreembuf(chan->in_mbuf); + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + sc->avma1pp_txl = 0; + sc->avma1pp_cmd |= HSCX_CMD_RRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + sc->avma1pp_cmd &= ~HSCX_CMD_RRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + } + } + + + /* transmit fifo empty, new data can be written to fifo */ + + if(stat & HSCX_INT_XPR) + { + /* + * for a description what is going on here, please have + * a look at isic_bchannel_start() in i4b_bchan.c ! + */ + + DBGL1(L1_H_IRQ, "avm_pnp_hscx_intr", ("unit %d, chan %d - XPR, Tx Fifo Empty!\n", sc->sc_unit, h_chan)); + + if(chan->out_mbuf_cur == NULL || chan->out_mbuf_head == 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; + } + } + } + + isic_hscx_fifo(chan, sc); + } + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity); +} + +/* + * this is the main routine which checks each channel and then calls + * the real interrupt routine as appropriate + */ +static void +avm_pnp_hscx_int_handler(struct isic_softc *sc) +{ + u_char stat = 0; + u_char cnt = 0; + + stat = hscx_read_reg(0, HSCX_STAT, sc); + if (stat & HSCX_INT_RPR) + cnt = hscx_read_reg(0, HSCX_STAT+1, sc); + if (stat & HSCX_INT_MASK) + avm_pnp_hscx_intr(0, stat, cnt, sc); + + cnt = 0; + stat = hscx_read_reg(1, HSCX_STAT, sc); + if (stat & HSCX_INT_RPR) + cnt = hscx_read_reg(1, HSCX_STAT+1, sc); + if (stat & HSCX_INT_MASK) + avm_pnp_hscx_intr(1, stat, cnt, sc); +} + +static void +avm_pnp_hscx_init(struct isic_softc *sc, int h_chan, int activate) +{ + isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + + DBGL1(L1_BCHAN, "avm_pnp_hscx_init", ("unit=%d, channel=%d, %s\n", + sc->sc_unit, h_chan, activate ? "activate" : "deactivate")); + + if (activate == 0) + { + /* only deactivate if both channels are idle */ + if (sc->sc_chan[HSCX_CH_A].state != HSCX_IDLE || + sc->sc_chan[HSCX_CH_B].state != HSCX_IDLE) + { + return; + } + sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; + sc->avma1pp_prot = HSCX_MODE_TRANS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 5); + return; + } + if(chan->bprot == BPROT_RHDLC) + { + DBGL1(L1_BCHAN, "avm_pnp_hscx_init", ("BPROT_RHDLC\n")); + + /* HDLC Frames, transparent mode 0 */ + sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; + sc->avma1pp_prot = HSCX_MODE_ITF_FLG; + hscx_write_reg(h_chan, HSCX_STAT, sc, 5); + sc->avma1pp_cmd = HSCX_CMD_XRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + sc->avma1pp_cmd = 0; + } + else + { + DBGL1(L1_BCHAN, "avm_pnp_hscx_init", ("BPROT_NONE??\n")); + + /* Raw Telephony, extended transparent mode 1 */ + sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; + sc->avma1pp_prot = HSCX_MODE_TRANS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 5); + sc->avma1pp_cmd = HSCX_CMD_XRS; + hscx_write_reg(h_chan, HSCX_STAT, sc, 1); + sc->avma1pp_cmd = 0; + } +} + +static void +avm_pnp_bchannel_setup(int unit, int h_chan, int bprot, int activate) +{ + struct isic_softc *sc = &isic_sc[unit]; + isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + + int s = SPLI4B(); + + if(activate == 0) + { + /* deactivation */ + chan->state &= ~HSCX_AVMPNP_ACTIVE; + avm_pnp_hscx_init(sc, h_chan, activate); + } + + DBGL1(L1_BCHAN, "avm_pnp_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 */ + avm_pnp_hscx_init(sc, h_chan, activate); + chan->state |= HSCX_AVMPNP_ACTIVE; + } + + splx(s); +} + +static void +avm_pnp_bchannel_start(int unit, int h_chan) +{ + struct isic_softc *sc = &isic_sc[unit]; + register isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + int s; + int activity = -1; + + 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); + } + + isic_hscx_fifo(chan, sc); + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity); + + splx(s); +} + +/*---------------------------------------------------------------------------* + * return the address of isic drivers linktab + *---------------------------------------------------------------------------*/ +static isdn_link_t * +avm_pnp_ret_linktab(int unit, int channel) +{ + struct isic_softc *sc = &isic_sc[unit]; + isic_Bchan_t *chan = &sc->sc_chan[channel]; + + return(&chan->isdn_linktab); +} + +/*---------------------------------------------------------------------------* + * set the driver linktab in the b channel softc + *---------------------------------------------------------------------------*/ +static void +avm_pnp_set_linktab(int unit, int channel, drvr_link_t *dlt) +{ + struct isic_softc *sc = &isic_sc[unit]; + isic_Bchan_t *chan = &sc->sc_chan[channel]; + + chan->drvr_linktab = dlt; +} + + +/*---------------------------------------------------------------------------* + * initialize our local linktab + *---------------------------------------------------------------------------*/ +static void +avm_pnp_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 */ + /* avoid overwriting if already set */ + if (ctrl_types[CTRL_PASSIVE].set_linktab == NULL) + { + ctrl_types[CTRL_PASSIVE].set_linktab = avm_pnp_set_linktab; + ctrl_types[CTRL_PASSIVE].get_linktab = avm_pnp_ret_linktab; + } + + /* local setup */ + lt->unit = sc->sc_unit; + lt->channel = HSCX_CH_A; + lt->bch_config = avm_pnp_bchannel_setup; + lt->bch_tx_start = avm_pnp_bchannel_start; + lt->bch_stat = avm_pnp_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 = avm_pnp_bchannel_setup; + lt->bch_tx_start = avm_pnp_bchannel_start; + lt->bch_stat = avm_pnp_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; +} + +/* + * use this instead of isic_bchannel_stat in i4b_bchan.c because it's static + */ +static void +avm_pnp_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp) +{ + struct isic_softc *sc = &isic_sc[unit]; + 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); +} + +/*---------------------------------------------------------------------------* + * fill HSCX fifo with data from the current mbuf + * Put this here until it can go into i4b_hscx.c + *---------------------------------------------------------------------------*/ +int +isic_hscx_fifo(isic_Bchan_t *chan, struct isic_softc *sc) +{ + int len; + int nextlen; + int i; + /* using a scratch buffer simplifies writing to the FIFO */ + u_char scrbuf[HSCX_FIFO_LEN]; + + len = 0; + + /* + * 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(chan->out_mbuf_cur && len != sc->sc_bfifolen) + { + nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len); + +#ifdef NOTDEF + printf("i:mh=%p, mc=%p, mcp=%p, 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, + nextlen); +#endif + + /* collect the data in the scratch buffer */ + for (i = 0; i < nextlen; i++) + scrbuf[i + len] = chan->out_mbuf_cur_ptr[i]; + + 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 = (chan->channel == 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 + { + i4b_Bfreembuf(chan->out_mbuf_head); + chan->out_mbuf_head = NULL; + } + } + } + /* write what we have from the scratch buf to the HSCX fifo */ + if (len != 0) + HSCX_WRFIFO(chan->channel, scrbuf, len); + + return(0); +} + +void +avm_pnp_intr(int unit) +{ + struct isic_softc *sc; + u_char stat; + register u_char isac_irq_stat; + int was_isac = 0; + + sc = &isic_sc[unit]; + + for(;;) { + stat = inb(sc->sc_port + STAT0_OFFSET); + + DBGL1(L1_H_IRQ, "avm_pnp_intr", ("stat %x\n", stat)); + + /* was there an interrupt from this card ? */ + if ((stat & ASL_IRQ_Pending) == ASL_IRQ_Pending) + break; /* no */ + + /* interrupts are low active */ + if (!(stat & ASL_IRQ_TIMER)) + DBGL1(L1_H_IRQ, "avm_pnp_intr", ("timer interrupt ???\n")); + + if (!(stat & ASL_IRQ_ISAC)) + { + DBGL1(L1_H_IRQ, "avm_pnp_intr", ("ISAC\n")); + isac_irq_stat = ISAC_READ(I_ISTA); + isic_isac_irq(sc, isac_irq_stat); + was_isac = 1; + } + + if (!(stat & ASL_IRQ_HSCX)) + { + DBGL1(L1_H_IRQ, "avm_pnp_intr", ("HSCX\n")); + avm_pnp_hscx_int_handler(sc); + } + } + if (was_isac) { + ISAC_WRITE(0x20, 0xFF); + ISAC_WRITE(0x20, 0x0); + } +} +#endif /* NISIC > 0 && defined(AVM_PNP) */ +#endif /* FreeBSD */ diff --git a/sys/i4b/layer1/i4b_bsdi_ibc.c b/sys/i4b/layer1/i4b_bsdi_ibc.c deleted file mode 100644 index 9168815..0000000 --- a/sys/i4b/layer1/i4b_bsdi_ibc.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) 1998, 1999 Bert Driehuis. All rights reserved. - * - * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *--------------------------------------------------------------------------- - * - * i4b_bsdi_ibc.c - isdn4bsd kernel BSD/OS point to point driver - * ------------------------------------------------------------- - * - * $Id: i4b_bsdi_ibc.c,v 1.1 1999/04/23 08:35:07 hm Exp $ - * - * last edit-date: [Fri Apr 23 10:27:57 1999] - * - *---------------------------------------------------------------------------*/ - -#include "ibc.h" - -#if NIBC > 0 - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <sys/ioccom.h> -#include <sys/ttycom.h> -#include <sys/sockio.h> -#include <sys/kernel.h> -#include <sys/protosw.h> - -#include <net/if.h> -#include <net/if_types.h> -#include <net/if_p2p.h> -#include <net/netisr.h> -#include <net/route.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> - -#include <i4b/i4b_ioctl.h> -#include <i4b/i4b_cause.h> -#include <i4b/include/i4b_global.h> -#include <i4b/include/i4b_mbuf.h> -#include <i4b/include/i4b_l3l4.h> -#include <i4b/layer4/i4b_l4.h> - -#define IFP2UNIT(ifp) (ifp)->if_unit - -#define IOCTL_CMD_T u_long - -void ibcattach(void *); - -#define IBCACCT 1 /* enable accounting messages */ -#define IBCACCTINTVL 2 /* accounting msg interval in secs */ - -#define PPP_HDRLEN 4 /* 4 octets PPP header length */ - -struct ibc_softc { - struct p2pcom sc_p2pcom; - - int sc_state; /* state of the interface */ - call_desc_t *sc_cdp; /* ptr to call descriptor */ - -#ifdef IBCACCT - int sc_iinb; /* isdn driver # of inbytes */ - int sc_ioutb; /* isdn driver # of outbytes */ - int sc_inb; /* # of bytes rx'd */ - int sc_outb; /* # of bytes tx'd */ - int sc_linb; /* last # of bytes rx'd */ - int sc_loutb; /* last # of bytes tx'd */ - int sc_fn; /* flag, first null acct */ -#endif -} ibc_softc[NIBC]; - -static void ibc_init_linktab(int unit); - -static int ibc_start(struct ifnet *ifp); - -static int ibc_watchdog(int unit); -static int ibc_mdmctl(struct p2pcom *pp, int flag); -static int ibc_getmdm(struct p2pcom *pp, caddr_t arg); - -/* initialized by L4 */ - -static drvr_link_t ibc_drvr_linktab[NIBC]; -static isdn_link_t *isdn_ibc_lt[NIBC]; - -enum ibc_states { - ST_IDLE, /* initialized, ready, idle */ - ST_DIALING, /* dialling out to remote */ - ST_CONNECTED, /* connected to remote */ -}; - -int ibcdebug = 0; /* Use bpatch to set this for debug printf's */ -#define DBG(x) if (ibcdebug) printf x - -/*===========================================================================* - * DEVICE DRIVER ROUTINES - *===========================================================================*/ - -/*---------------------------------------------------------------------------* - * interface attach routine at kernel boot time - *---------------------------------------------------------------------------*/ -void -ibcattach(void *dummy) -{ - struct ibc_softc *sc = ibc_softc; - struct ifnet *ifp; - int i; - -#ifndef HACK_NO_PSEUDO_ATTACH_MSG - printf("ibc: %d ISDN ibc device(s) attached\n", - NIBC); -#endif - - for(i = 0; i < NIBC; sc++, i++) { - ibc_init_linktab(i); - - sc->sc_p2pcom.p2p_mdmctl = ibc_mdmctl; - sc->sc_p2pcom.p2p_getmdm = ibc_getmdm; - sc->sc_state = ST_IDLE; - ifp = &sc->sc_p2pcom.p2p_if; - ifp->if_name = "ibc"; - ifp->if_next = NULL; - ifp->if_unit = i; - ifp->if_mtu = 1500 /*XXX*/; - ifp->if_baudrate = 64000; - ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT; - ifp->if_type = IFT_ISDNBASIC; - ifp->if_start = ibc_start; - ifp->if_output = 0; - ifp->if_ioctl = p2p_ioctl; - - ifp->if_hdrlen = 0; - ifp->if_addrlen = 0; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - - ifp->if_ipackets = 0; - ifp->if_ierrors = 0; - ifp->if_opackets = 0; - ifp->if_oerrors = 0; - ifp->if_collisions = 0; - ifp->if_ibytes = 0; - ifp->if_obytes = 0; - ifp->if_imcasts = 0; - ifp->if_omcasts = 0; - ifp->if_iqdrops = 0; - ifp->if_noproto = 0; -#if IBCACCT - ifp->if_timer = 0; - ifp->if_watchdog = ibc_watchdog; - sc->sc_iinb = 0; - sc->sc_ioutb = 0; - sc->sc_inb = 0; - sc->sc_outb = 0; - sc->sc_linb = 0; - sc->sc_loutb = 0; - sc->sc_fn = 1; -#endif - if_attach(ifp); - p2p_attach(&sc->sc_p2pcom); - } -} - -static struct mbuf * -p2p_dequeue(struct p2pcom *pp) -{ - struct ifqueue *ifq; - struct mbuf *m; - - ifq = &pp->p2p_isnd; - m = ifq->ifq_head; - if (m == 0) { - ifq = &pp->p2p_if.if_snd; - m = ifq->ifq_head; - } - if (m == 0) - return 0; - IF_DEQUEUE(ifq, m); - return m; -} - -/*---------------------------------------------------------------------------* - * start output to ISDN B-channel - *---------------------------------------------------------------------------*/ -static int -ibc_start(struct ifnet *ifp) -{ - int unit = IFP2UNIT(ifp); - struct ibc_softc *sc = (struct ibc_softc *)&ibc_softc[unit]; - struct p2pcom *pp = &sc->sc_p2pcom; - struct mbuf *m; - int s; - - if(sc->sc_state != ST_CONNECTED) { - DBG(("ibc%d: ibc_start called with sc_state=%d\n", - unit, sc->sc_state)); - return 0; - } - - s = SPLI4B(); - - if (IF_QFULL(isdn_ibc_lt[unit]->tx_queue)) { - splx(s); - return 0; - } - - m = p2p_dequeue(pp); - if (m == NULL) { - splx(s); - return 0; - } - - do { - microtime(&ifp->if_lastchange); - - IF_ENQUEUE(isdn_ibc_lt[unit]->tx_queue, m); - - ifp->if_obytes += m->m_pkthdr.len; - sc->sc_outb += m->m_pkthdr.len; - ifp->if_opackets++; - } while (!IF_QFULL(isdn_ibc_lt[unit]->tx_queue) && - (m = p2p_dequeue(pp)) != NULL); - isdn_ibc_lt[unit]->bch_tx_start(isdn_ibc_lt[unit]->unit, - isdn_ibc_lt[unit]->channel); - splx(s); - return 0; -} - -#ifdef IBCACCT -/*---------------------------------------------------------------------------* - * watchdog routine - *---------------------------------------------------------------------------*/ -static int -ibc_watchdog(int unit) -{ - struct ibc_softc *sc = &ibc_softc[unit]; - struct ifnet *ifp = &sc->sc_p2pcom.p2p_if; - bchan_statistics_t bs; - - (*isdn_ibc_lt[unit]->bch_stat) - (isdn_ibc_lt[unit]->unit, isdn_ibc_lt[unit]->channel, &bs); - - sc->sc_ioutb += bs.outbytes; - sc->sc_iinb += bs.inbytes; - - if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn) - { - int ri = (sc->sc_iinb - sc->sc_linb)/IBCACCTINTVL; - int ro = (sc->sc_ioutb - sc->sc_loutb)/IBCACCTINTVL; - - if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb)) - sc->sc_fn = 0; - else - sc->sc_fn = 1; - - sc->sc_linb = sc->sc_iinb; - sc->sc_loutb = sc->sc_ioutb; - - i4b_l4_accounting(BDRV_IBC, unit, ACCT_DURING, - sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb); - } - ifp->if_timer = IBCACCTINTVL; - return 0; -} -#endif /* IBCACCT */ - -/* - *===========================================================================* - * P2P layer interface routines - *===========================================================================* - */ - -#if 0 -/*---------------------------------------------------------------------------* - * PPP interface phase change - *---------------------------------------------------------------------------* - */ -static void -ibc_state_changed(struct sppp *sp, int new_state) -{ - struct ibc_softc *sc = (struct ibc_softc *)sp; - - i4b_l4_ifstate_changed(sc->sc_cdp, new_state); -} - -/*---------------------------------------------------------------------------* - * PPP control protocol negotiation complete (run ip-up script now) - *---------------------------------------------------------------------------* - */ -static void -ibc_negotiation_complete(struct sppp *sp) -{ - struct ibc_softc *sc = (struct ibc_softc *)sp; - - i4b_l4_negcomplete(sc->sc_cdp); -} -#endif - -/*===========================================================================* - * ISDN INTERFACE ROUTINES - *===========================================================================*/ - -/*---------------------------------------------------------------------------* - * this routine is called from L4 handler at connect time - *---------------------------------------------------------------------------*/ -static void -ibc_connect(int unit, void *cdp) -{ - struct ibc_softc *sc = &ibc_softc[unit]; - struct ifnet *ifp = &sc->sc_p2pcom.p2p_if; - int s; - - DBG(("ibc%d: ibc_connect\n", unit)); - - s = splimp(); - - sc->sc_cdp = (call_desc_t *)cdp; - sc->sc_state = ST_CONNECTED; - -#if IBCACCT - sc->sc_iinb = 0; - sc->sc_ioutb = 0; - sc->sc_inb = 0; - sc->sc_outb = 0; - sc->sc_linb = 0; - sc->sc_loutb = 0; - ifp->if_timer = IBCACCTINTVL; -#endif - - splx(s); - if (sc->sc_p2pcom.p2p_modem) - (*sc->sc_p2pcom.p2p_modem)(&sc->sc_p2pcom, 1); - - /* This is a lie... PPP is just starting to negociate :-) */ - i4b_l4_negcomplete(sc->sc_cdp); -} - -/*---------------------------------------------------------------------------* - * this routine is called from L4 handler at disconnect time - *---------------------------------------------------------------------------*/ -static void -ibc_disconnect(int unit, void *cdp) -{ - call_desc_t *cd = (call_desc_t *)cdp; - struct ibc_softc *sc = &ibc_softc[unit]; - struct ifnet *ifp = &sc->sc_p2pcom.p2p_if; - int s; - - DBG(("ibc%d: ibc_disconnect\n", unit)); - - s = splimp(); - - /* new stuff to check that the active channel is being closed */ - if (cd != sc->sc_cdp) - { - DBG(("ibc_disconnect: ibc%d channel%d not active\n", - cd->driver_unit, cd->channelid)); - splx(s); - return; - } - -#if IBCACCT - ifp->if_timer = 0; -#endif - - i4b_l4_accounting(BDRV_IBC, unit, ACCT_FINAL, - sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb); - - if (sc->sc_state == ST_CONNECTED) - { - sc->sc_cdp = (call_desc_t *)0; - sc->sc_state = ST_IDLE; - if (sc->sc_p2pcom.p2p_modem) - (*sc->sc_p2pcom.p2p_modem)(&sc->sc_p2pcom, 0); - } - - splx(s); -} - -/*---------------------------------------------------------------------------* - * this routine is used to give a feedback from userland demon - * in case of dial problems - *---------------------------------------------------------------------------*/ -static void -ibc_dialresponse(int unit, int status) -{ - DBG(("ibc%d: ibc_dialresponse %d\n", unit, status)); -/* struct ibc_softc *sc = &ibc_softc[unit]; */ -} - -/*---------------------------------------------------------------------------* - * interface up/down - *---------------------------------------------------------------------------*/ -static void -ibc_updown(int unit, int updown) -{ - DBG(("ibc%d: ibc_updown %d\n", unit, updown)); - /* could probably do something useful here */ -} - -/*---------------------------------------------------------------------------* - * this routine is called from the HSCX interrupt handler - * when a new frame (mbuf) has been received and was put on - * the rx queue. - *---------------------------------------------------------------------------*/ -static void -ibc_rx_data_rdy(int unit) -{ - struct ibc_softc *sc = &ibc_softc[unit]; - struct ifnet *ifp = &sc->sc_p2pcom.p2p_if; - struct mbuf *m, *m0; - char *buf; - int s; - - if((m = *isdn_ibc_lt[unit]->rx_mbuf) == NULL) - return; - - microtime(&ifp->if_lastchange); - ifp->if_ipackets++; - - /* Walk the mbuf chain */ - s = splimp(); - for (m0 = m; m != 0; m = m->m_next) { - if (m->m_len == 0) - continue; - ifp->if_ibytes += m->m_len; -#if IBCACCT - sc->sc_inb += m->m_len; -#endif - buf = mtod(m, caddr_t); - if ((*sc->sc_p2pcom.p2p_hdrinput)( - &sc->sc_p2pcom, buf, m->m_len) >= 0) - (*sc->sc_p2pcom.p2p_input)(&sc->sc_p2pcom, 0); - } - splx(s); - m_freem(m0); -} - -/*---------------------------------------------------------------------------* - * this routine is called from the HSCX interrupt handler - * when the last frame has been sent out and there is no - * further frame (mbuf) in the tx queue. - *---------------------------------------------------------------------------*/ -static void -ibc_tx_queue_empty(int unit) -{ - ibc_start(&ibc_softc[unit].sc_p2pcom.p2p_if); -} - -/*---------------------------------------------------------------------------* - * this routine is called from the HSCX interrupt handler - * each time a packet is received or transmitted. It should - * be used to implement an activity timeout mechanism. - *---------------------------------------------------------------------------*/ -static void -ibc_activity(int unit, int rxtx) -{ - ibc_softc[unit].sc_cdp->last_active_time = SECOND; -} - -/*---------------------------------------------------------------------------* - * return this drivers linktab address - *---------------------------------------------------------------------------*/ -drvr_link_t * -ibc_ret_linktab(int unit) -{ - return(&ibc_drvr_linktab[unit]); -} - -/*---------------------------------------------------------------------------* - * setup the isdn_ibc_lt for this driver - *---------------------------------------------------------------------------*/ -void -ibc_set_linktab(int unit, isdn_link_t *ilt) -{ - isdn_ibc_lt[unit] = ilt; -} - -/*---------------------------------------------------------------------------* - * initialize this drivers linktab - *---------------------------------------------------------------------------*/ -static void -ibc_init_linktab(int unit) -{ - ibc_drvr_linktab[unit].unit = unit; - ibc_drvr_linktab[unit].bch_rx_data_ready = ibc_rx_data_rdy; - ibc_drvr_linktab[unit].bch_tx_queue_empty = ibc_tx_queue_empty; - ibc_drvr_linktab[unit].bch_activity = ibc_activity; - ibc_drvr_linktab[unit].line_connected = ibc_connect; - ibc_drvr_linktab[unit].line_disconnected = ibc_disconnect; - ibc_drvr_linktab[unit].dial_response = ibc_dialresponse; - ibc_drvr_linktab[unit].updown_ind = ibc_updown; -} - -/*===========================================================================*/ - -static int -ibc_mdmctl(pp, flag) - struct p2pcom *pp; - int flag; -{ - register struct ifnet *ifp = &pp->p2p_if; - struct ibc_softc *sc = (struct ibc_softc *)&ibc_softc[ifp->if_unit]; - - DBG(("ibc%d: ibc_mdmctl called flags=%d\n", IFP2UNIT(ifp), flag)); - - if (flag == 1 && sc->sc_state == ST_IDLE) { - sc->sc_state = ST_DIALING; - i4b_l4_dialout(BDRV_IBC, IFP2UNIT(ifp)); - } else if (flag == 0 && sc->sc_state != ST_IDLE) { - sc->sc_state = ST_IDLE; - i4b_l4_drvrdisc(BDRV_IBC, IFP2UNIT(ifp)); - } - return 0; -} - -static int -ibc_getmdm(pp, arg) - struct p2pcom *pp; - caddr_t arg; -{ - register struct ifnet *ifp = &pp->p2p_if; - struct ibc_softc *sc = (struct ibc_softc *)&ibc_softc[ifp->if_unit]; - - if (sc->sc_state == ST_CONNECTED) - *(int *)arg = TIOCM_CAR; - else - *(int *)arg = 0; - return 0; - - DBG(("ibc%d: ibc_getmdm called ret=%d\n", IFP2UNIT(ifp), *(int *)arg)); -} -#endif diff --git a/sys/i4b/layer1/i4b_dynalink.c b/sys/i4b/layer1/i4b_dynalink.c index e316682..1f75302 100644 --- a/sys/i4b/layer1/i4b_dynalink.c +++ b/sys/i4b/layer1/i4b_dynalink.c @@ -33,7 +33,7 @@ * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA * ================================================== * - * $Id: i4b_dynalink.c,v 1.9 1999/02/14 09:44:58 hm Exp $ + * $Id: i4b_dynalink.c,v 1.10 1999/07/26 09:03:49 hm Exp $ * * last edit-date: [Sun Feb 14 10:26:21 1999] * @@ -108,6 +108,8 @@ #include <machine/clock.h> #include <i386/isa/isa_device.h> #include <i386/isa/pnp.h> +#elif defined(__bsdi__) +#include <i386/isa/pnp.h> #else #include <machine/bus.h> #include <sys/device.h> @@ -129,15 +131,21 @@ #include <i4b/layer1/i4b_isac.h> #include <i4b/layer1/i4b_hscx.h> -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) 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); +#endif +#ifdef __FreeBSD__ extern struct isa_driver isicdriver; +#endif +#ifdef __bsdi__ +extern struct cfdriver isiccd; +#endif -#else +#if !defined(__FreeBSD__) && !defined(__bsdi__) 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); @@ -158,13 +166,15 @@ void isic_attach_Dyn(struct isic_softc *sc); #define HSCXA 0x00 #define HSCXB 0x40 -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) /* 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) +#endif +#ifdef __FreeBSD__ /* ISIC probe and attach */ @@ -271,6 +281,136 @@ isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2) return(1); } +#elif defined(__bsdi__) + +/* ISIC probe and attach +*/ + +static int +set_softc(struct isic_softc *sc, struct isa_attach_args *ia, int unit) +{ + if (unit >= NISIC) + return 0; + sc->sc_unit = unit; + switch(ffs(ia->ia_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", + unit, ffs(ia->ia_irq)-1); + return(0); + break; + } + sc->sc_irq = ia->ia_irq; + + /* check if memory addr specified */ + + if(ia->ia_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n", + unit, (u_long)ia->ia_maddr); + return (0); + } + + /* check if we got an iobase */ + if ( (ia->ia_iobase < 0x100) || + (ia->ia_iobase > 0x3f8) || + (ia->ia_iobase & 3) ) + { + printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", unit, ia->ia_iobase); + return(0); + } + sc->sc_port = ia->ia_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; + return 1; +} + +int +isapnp_match_dynalink(struct device *parent, struct cfdata *cf, + struct isa_attach_args *ia) +{ + struct isic_softc dummysc, *sc = &dummysc; + pnp_resource_t res; + char *ids[] = {"ASU1688", NULL}; + bzero(&res, sizeof res); + res.res_irq[0].irq_level = ia->ia_irq; + res.res_port[0].prt_base = ia->ia_iobase; + res.res_port[0].prt_length = 4; + + if (!pnp_assigndev(ids, isiccd.cd_name, &res)) + return (0); + + ia->ia_irq = res.res_irq[0].irq_level; + ia->ia_iobase = res.res_port[0].prt_base; + ia->ia_iosize = res.res_port[0].prt_length; + + if (set_softc(sc, ia, cf->cf_unit) == 0) + return 0; + + /* 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", + cf->cf_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + cf->cf_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + cf->cf_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + cf->cf_flags = FLAG_DYNALINK; + return (1); +} + +int +isic_attach_Dyn(struct device *parent, struct device *self, + struct isa_attach_args *ia) +{ + struct isic_softc *sc = (struct isic_softc *)self; + int unit = sc->sc_dev.dv_unit; + + /* Commit the probed attachment values */ + if (set_softc(sc, ia, unit) == 0) + panic("isic_attach_Dyn: set_softc"); + + outb((ia->ia_iobase)+ADDR, RESET); + DELAY(SEC_DELAY / 10); + outb((ia->ia_iobase)+ADDR, 0); + DELAY(SEC_DELAY / 10); + return(1); +} + #else void isic_attach_Dyn(struct isic_softc *sc) @@ -320,7 +460,7 @@ void isic_attach_Dyn(struct isic_softc *sc) REM: this is only true for the FreeBSD version of I4B! */ -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) static void dynalink_read_fifo(void *buf, const void *base, size_t len) { @@ -350,7 +490,7 @@ dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) } #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) static void dynalink_write_fifo(void *base, const void *buf, size_t len) { @@ -379,7 +519,7 @@ static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf } #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) static void dynalink_write_reg(u_char *base, u_int offset, u_int v) { @@ -408,7 +548,7 @@ static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, } #endif -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__bsdi__) static u_char dynalink_read_reg(u_char *base, u_int offset) { diff --git a/sys/i4b/layer1/i4b_ipac.h b/sys/i4b/layer1/i4b_ipac.h index d820271..e58c4b8 100644 --- a/sys/i4b/layer1/i4b_ipac.h +++ b/sys/i4b/layer1/i4b_ipac.h @@ -27,9 +27,9 @@ * i4b_ipac.h - definitions for the Siemens IPAC PSB2115 chip * ========================================================== * - * $Id: i4b_ipac.h,v 1.5 1999/02/14 09:44:59 hm Exp $ + * $Id: i4b_ipac.h,v 1.6 1999/06/08 08:13:00 hm Exp $ * - * last edit-date: [Sun Feb 14 10:27:03 1999] + * last edit-date: [Tue Jun 8 09:53:26 1999] * *--------------------------------------------------------------------------- */ @@ -44,6 +44,10 @@ #define IPAC_ISAC_OFF 0x80 #define IPAC_IPAC_OFF 0xc0 +/* chip version */ + +#define IPAC_V11 0x01 /* IPAC Version 1.1 */ + /* * definitions of registers and bits for the IPAC ISDN chip. */ diff --git a/sys/i4b/layer1/i4b_isic.c b/sys/i4b/layer1/i4b_isic.c index f403faf..a2361b9 100644 --- a/sys/i4b/layer1/i4b_isic.c +++ b/sys/i4b/layer1/i4b_isic.c @@ -27,9 +27,9 @@ * i4b_isic.c - global isic stuff * ============================== * - * $Id: i4b_isic.c,v 1.47 1999/04/20 09:34:14 hm Exp $ + * $Id: i4b_isic.c,v 1.51 1999/07/26 09:03:49 hm Exp $ * - * last edit-date: [Sun Feb 14 10:27:20 1999] + * last edit-date: [Mon Jul 26 10:59:56 1999] * *---------------------------------------------------------------------------*/ @@ -97,6 +97,7 @@ struct cfdriver isiccd = sizeof(struct isic_softc) }; int isa_isicmatch(struct device *parent, struct cfdata *cf, struct isa_attach_args *); +int isapnp_isicmatch(struct device *parent, struct cfdata *cf, struct isa_attach_args *); int isa_isicattach(struct device *parent, struct device *self, struct isa_attach_args *ia); static int @@ -109,8 +110,7 @@ isicmatch(struct device *parent, struct cfdata *cf, void *aux) return 0; /* for now */ } if (ia->ia_bustype == BUS_PNP) { - /* return isapnp_isicmatch(parent, cf, ia); */ - return 0; /* for now */ + return isapnp_isicmatch(parent, cf, ia); } return isa_isicmatch(parent, cf, ia); } @@ -209,6 +209,9 @@ isicintr(void *arg) was_isac_irq = 1; } } + +#ifdef NOTDEF + #if !defined(amiga) && !defined(atari) /* XXX should be: #if INTS_ARE_SHARED */ #ifdef ELSA_QS1ISA if(sc->sc_cardtyp != CARD_TYPEP_ELSAQS1ISA) @@ -220,6 +223,8 @@ isicintr(void *arg) } #endif #endif /* !AMIGA && !ATARI */ + +#endif /* NOTDEF */ HSCX_WRITE(0, H_MASK, 0xff); ISAC_WRITE(I_MASK, 0xff); @@ -273,21 +278,27 @@ isicintr(void *arg) ipac_irq_stat & IPAC_ISTA_EXB); was_ipac_irq = 1; } - if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD)) + if(ipac_irq_stat & IPAC_ISTA_ICD) { /* ISAC interrupt */ isic_isac_irq(sc, ISAC_READ(I_ISTA)); was_ipac_irq = 1; } + if(ipac_irq_stat & IPAC_ISTA_EXD) + { + /* force ISAC interrupt handling */ + isic_isac_irq(sc, ISAC_ISTA_EXI); + was_ipac_irq = 1; + } /* do as long as there are pending irqs in the chip */ if(!ipac_irq_stat) break; } - +#ifdef NOTDEF if(was_ipac_irq == 0) DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from IPAC!\n", sc->sc_unit)); - +#endif IPAC_WRITE(IPAC_MASK, 0xff); DELAY(50); IPAC_WRITE(IPAC_MASK, 0xc0); diff --git a/sys/i4b/layer1/i4b_isic_isa.c b/sys/i4b/layer1/i4b_isic_isa.c index 4147355..ba927c4 100644 --- a/sys/i4b/layer1/i4b_isic_isa.c +++ b/sys/i4b/layer1/i4b_isic_isa.c @@ -27,9 +27,9 @@ * i4b_isic_isa.c - ISA bus interface * ================================== * - * $Id: i4b_isic_isa.c,v 1.20 1999/05/10 09:37:35 hm Exp $ + * $Id: i4b_isic_isa.c,v 1.24 1999/07/26 09:03:49 hm Exp $ * - * last edit-date: [Tue Apr 20 11:47:59 1999] + * last edit-date: [Mon Jul 26 10:59:51 1999] * *---------------------------------------------------------------------------*/ @@ -211,6 +211,18 @@ isicprobe(struct isa_device *dev) } #elif defined(__bsdi__) /*---------------------------------------------------------------------------* + * isic - pnp device driver probe routine + *---------------------------------------------------------------------------*/ +int +isapnp_isicmatch(struct device *parent, struct cfdata *cf, struct isa_attach_args *ia) +{ +#ifdef DYNALINK + if (isapnp_match_dynalink(parent, cf, ia)) + return 1; +#endif + return 0; +} +/*---------------------------------------------------------------------------* * isic - non-pnp device driver probe routine *---------------------------------------------------------------------------*/ int @@ -305,6 +317,7 @@ isic_realattach(struct isa_device *dev, unsigned int iobase2) *---------------------------------------------------------------------------*/ int isa_isicattach(struct device *parent, struct device *self, struct isa_attach_args *ia) + #else /* ! __FreeBSD__ */ int @@ -316,19 +329,26 @@ isicattach(int flags, struct isic_softc *sc) 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 + #elif defined(__bsdi__) + struct isic_softc *sc = (struct isic_softc *)self; #define PARM parent, self, ia +#define PARM2 parent, self, ia #define FLAGS sc->sc_flags + #else + #define PARM sc #define PARM2 sc #define FLAGS flags -#endif + +#endif /* __FreeBSD__ */ static char *ISACversion[] = { "2085 Version A1/A2 or 2086/2186 Version 1.1", @@ -353,7 +373,7 @@ isicattach(int flags, struct isic_softc *sc) #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); +/*XXX*/ printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit); return(0); } @@ -413,9 +433,16 @@ isicattach(int flags, struct isic_softc *sc) break; #endif +#ifdef amiga + case FLAG_BLMASTER: + ret = 1; /* full detection was done in caller */ + 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 */ @@ -456,15 +483,26 @@ isicattach(int flags, struct isic_softc *sc) break; #endif -#endif /* __FreeBSD__ / P&P specific part */ +#ifdef AVM_PNP + case FLAG_AVM_PNP: + ret = isic_attach_avm_pnp(PARM2); + ret = 0; + break; +#endif -/* --- XXX - don't know how to handle this - should be removed!!!! ---- */ -#ifdef amiga - case FLAG_BLMASTER: - ret = 1; /* full detection was done in caller */ +#ifdef SIEMENS_ISURF2 + case FLAG_SIEMENS_ISURF2: + ret = isic_attach_siemens_isurf(PARM2); + break; +#endif + +#ifdef ASUSCOM_IPAC + case FLAG_ASUSCOM_IPAC: + ret = isic_attach_asi(PARM2); break; #endif -/* ------------------------------------------------------------------- */ + +#endif /* __FreeBSD__ / P&P specific part */ default: break; @@ -473,40 +511,78 @@ isicattach(int flags, struct isic_softc *sc) 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) + if(sc->sc_ipac) { - case ISAC_VA: - case ISAC_VB1: - case ISAC_VB2: - case ISAC_VB3: - break; + ret = IPAC_READ(IPAC_ID); - default: - printf(ISIC_FMT "Error, ISAC version %d unknown!\n", - ISIC_PARM, sc->sc_isac_version); + if(ret != IPAC_V11) + { + printf("isic%d: Error, IPAC version %d unknown!\n", + sc->sc_unit, ret); return(0); - break; + } } + else + { - sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + sc->sc_isac_version = 0; + sc->sc_hscx_version = 0; - switch(sc->sc_hscx_version) + if(sc->sc_ipac) + { + ret = IPAC_READ(IPAC_ID); + + switch(ret) + { + case 0x01: + printf("isic%d: IPAC PSB2115 Version 1.1\n", sc->sc_unit); + break; + + default: + printf("isic%d: Error, IPAC version %d unknown!\n", + sc->sc_unit, ret); + return(0); + break; + } + } + else { - 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; - }; + 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 */ @@ -614,6 +690,14 @@ isicattach(int flags, struct isic_softc *sc) drvid = "ELSA PCC-16"; break; + case FLAG_ASUSCOM_IPAC: + drvid = "Asuscom ISDNlink 128K PnP"; + break; + + case FLAG_SIEMENS_ISURF2: + drvid = "Siemens I-Surf 2.0"; + break; + default: drvid = "ERROR, unknown flag used"; break; @@ -626,42 +710,52 @@ isicattach(int flags, struct isic_softc *sc) /* announce chip versions */ - if(sc->sc_isac_version >= ISAC_UNKN) + if(sc->sc_ipac) { - printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, - ISIC_PARM, - sc->sc_isac_version); - sc->sc_isac_version = ISAC_UNKN; + printf(ISIC_FMT "IPAC PSB2115 Version 1.1\n", ISIC_PARM); } 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_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); + 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]); + 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); + +#endif /* __FreeBSD__ */ } #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 diff --git a/sys/i4b/layer1/i4b_isic_pnp.c b/sys/i4b/layer1/i4b_isic_pnp.c index a9f056a..0e534eb 100644 --- a/sys/i4b/layer1/i4b_isic_pnp.c +++ b/sys/i4b/layer1/i4b_isic_pnp.c @@ -37,9 +37,9 @@ * i4b_isic_pnp.c - i4b pnp support * -------------------------------- * - * $Id: i4b_isic_pnp.c,v 1.17 1999/04/20 14:28:46 hm Exp $ + * $Id: i4b_isic_pnp.c,v 1.23 1999/07/05 14:00:04 hm Exp $ * - * last edit-date: [Tue Apr 20 16:12:27 1999] + * last edit-date: [Mon Jul 5 15:57:01 1999] * *---------------------------------------------------------------------------*/ @@ -76,23 +76,31 @@ extern void isicintr(int unit); #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*/ +#define VID_TEL163PNP 0x10212750 /* Teles 16.3 PnP */ +#define VID_CREATIXPP 0x0000980e /* Creatix S0/16 P+P */ +#define VID_DYNALINK 0x88167506 /* Dynalink */ +#define VID_SEDLBAUER 0x0100274c /* Sedlbauer WinSpeed */ +#define VID_NICCYGO 0x5001814c /* Neuhaus Niccy GO@ */ +#define VID_ELSAQS1P 0x33019315 /* ELSA Quickstep1000pro*/ +#define VID_ITK0025 0x25008b26 /* ITK Ix1 Micro V3 */ +#define VID_AVMPNP 0x0009cd06 /* AVM Fritz! PnP */ +#define VID_SIESURF2 0x2000254d /* Siemens I-Surf 2.0 PnP*/ +#define VID_ASUSCOM_IPAC 0x90167506 /* Asuscom (with IPAC) */ static struct 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"}, + { 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" }, + { VID_ITK0025, "ITK ix1 Micro V3.0" }, + { VID_AVMPNP, "AVM Fritz!Card PnP" }, + { VID_SIESURF2, "Siemens I-Surf 2.0 PnP" }, + { VID_ASUSCOM_IPAC, "Asuscom ISDNLink 128 PnP" }, { 0 } }; @@ -156,7 +164,9 @@ static void i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo spci; +#if !((defined(__FreeBSD_version) && __FreeBSD_version >= 400004)) struct isa_device *isa_devp; +#endif if(dev->id_unit != next_isic_unit) { @@ -211,6 +221,18 @@ i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) case VID_ELSAQS1P: dev->id_flags = FLAG_ELSA_QS1P_ISA; break; + case VID_ITK0025: + dev->id_flags = FLAG_ITK_IX1; + break; + case VID_AVMPNP: + dev->id_flags = FLAG_AVM_PNP; + break; + case VID_SIESURF2: + dev->id_flags = FLAG_SIEMENS_ISURF2; + break; + case VID_ASUSCOM_IPAC: + dev->id_flags = FLAG_ASUSCOM_IPAC; + break; } write_pnp_parms(&spci, 0); @@ -287,6 +309,31 @@ isic_pnpprobe(struct isa_device *dev, unsigned int iobase2) ret = isic_probe_Eqs1pi(dev, iobase2); break; #endif + +#ifdef ITKIX1 + case FLAG_ITK_IX1: + ret = isic_probe_itkix1(dev); + break; +#endif + +#ifdef AVM_PNP + case FLAG_AVM_PNP: + ret = isic_probe_avm_pnp(dev, iobase2); + break; +#endif + +#ifdef SIEMENS_ISURF2 + case FLAG_SIEMENS_ISURF2: + ret = isic_probe_siemens_isurf(dev, iobase2); + break; +#endif + +#ifdef ASUSCOM_IPAC + case FLAG_ASUSCOM_IPAC: + ret = isic_probe_asi(dev, iobase2); + break; +#endif + default: break; } diff --git a/sys/i4b/layer1/i4b_l1.h b/sys/i4b/layer1/i4b_l1.h index 6b455fa..f013bbb 100644 --- a/sys/i4b/layer1/i4b_l1.h +++ b/sys/i4b/layer1/i4b_l1.h @@ -27,9 +27,9 @@ * i4b_l1.h - isdn4bsd layer 1 header file * --------------------------------------- * - * $Id: i4b_l1.h,v 1.61 1999/04/21 07:50:31 hm Exp $ + * $Id: i4b_l1.h,v 1.64 1999/07/05 13:46:46 hm Exp $ * - * last edit-date: [Tue Mar 16 15:50:24 1999] + * last edit-date: [Mon Jul 5 15:32:02 1999] * *---------------------------------------------------------------------------*/ @@ -48,42 +48,36 @@ /*--------------------------------------------------------------------------- * 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_TELES_S0_163_PnP 5 +#define FLAG_CREATIX_S0_PnP 6 #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_DRN_NGO 8 +#define FLAG_SWS 9 +#define FLAG_AVM_A1_PCMCIA 10 +#define FLAG_DYNALINK 11 #define FLAG_BLMASTER 12 -#define FLAG_ELSA_QS1P_ISA 13 /* XXX - not needed, remove! */ -#define FLAG_ELSA_QS1P_PCI 14 /* XXX - not needed, remove! */ +#define FLAG_ELSA_QS1P_ISA 13 +#define FLAG_ELSA_QS1P_PCI 14 #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_ELSA_MLIMC 16 +#define FLAG_ELSA_MLMCALL 17 #define FLAG_ITK_IX1 18 -#define FLAG_ELSA_PCC16 19 +#define FLAG_AVMA1PCI 19 +#define FLAG_ELSA_PCC16 20 +#define FLAG_AVM_PNP 21 +#define FLAG_SIEMENS_ISURF2 22 +#define FLAG_ASUSCOM_IPAC 23 -#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/ +#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/ -#define MAX_DFRAME_LEN 264 /* max length of a D frame */ +#define MAX_DFRAME_LEN 264 /* max length of a D frame */ #ifndef __bsdi__ -#define min(a,b) ((a)<(b)?(a):(b)) +#define min(a,b) ((a)<(b)?(a):(b)) #endif #if !defined(__FreeBSD__) && !defined(__bsdi__) @@ -190,7 +184,7 @@ struct isic_softc #endif int sc_unit; /* unit number */ - int sc_irq; /* interrupt vector */ + int sc_irq; /* interrupt vector */ #ifdef __FreeBSD__ int sc_port; /* port base address */ @@ -205,6 +199,7 @@ struct isic_softc 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 @@ -266,6 +261,7 @@ struct isic_softc #endif int sc_I430T4; /* Timer T4 running */ + #if defined(__FreeBSD__) && __FreeBSD__ >=3 struct callout_handle sc_T4_callout; #endif @@ -396,7 +392,10 @@ 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_avm_pnp(struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_siemens_isurf(struct isa_device *dev, unsigned int iobase2); extern int isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2); +extern int isic_attach_asi(struct isa_device *dev, unsigned int iobase2); extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate ); extern int isic_hscx_fifo(isic_Bchan_t *, struct isic_softc *); extern void isic_hscx_init ( struct isic_softc *sc, int hscx_channel, int activate ); @@ -412,6 +411,8 @@ 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_avm_pnp ( struct isa_device *dev, unsigned int iobase2); +extern int isic_probe_siemens_isurf ( struct isa_device *dev, unsigned int iobase2); 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 ); @@ -423,6 +424,7 @@ 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); +extern int isic_probe_asi(struct isa_device *dev, unsigned int iobase2); #elif defined(__bsdi__) diff --git a/sys/i4b/layer1/i4b_siemens_isurf.c b/sys/i4b/layer1/i4b_siemens_isurf.c new file mode 100644 index 0000000..09e6f47 --- /dev/null +++ b/sys/i4b/layer1/i4b_siemens_isurf.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1999 Udo Schweigert. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * Based on ELSA Quickstep 1000pro PCI driver (i4b_elsa_qs1p.c) + *--------------------------------------------------------------------------- + * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de> + *--------------------------------------------------------------------------- + * + * Siemens I-Surf 2.0 PnP specific routines for isic driver + * -------------------------------------------------------- + * + * $Id: i4b_siemens_isurf.c,v 1.2 1999/07/05 13:22:12 hm Exp $ + * + * last edit-date: [Mon 14 Jun 16:46:27 CEST 1999] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(SIEMENS_ISURF2) + +#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/clock.h> +#include <i386/isa/isa_device.h> + +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +/* masks for register encoded in base addr */ + +#define SIE_ISURF_BASE_MASK 0x0ffff +#define SIE_ISURF_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define SIE_ISURF_IDISAC 0x00000 +#define SIE_ISURF_IDHSCXA 0x10000 +#define SIE_ISURF_IDHSCXB 0x20000 +#define SIE_ISURF_IDIPAC 0x40000 + +/* offsets from base address */ + +#define SIE_ISURF_OFF_ALE 0x00 +#define SIE_ISURF_OFF_RW 0x01 + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC get fifo routine + *---------------------------------------------------------------------------*/ + +static void +siemens_isurf_read_fifo(void *buf, const void *base, size_t len) +{ + if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF); + insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF); + insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */ + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF); + insb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (u_char *)buf, (u_int)len); + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC put fifo routine + *---------------------------------------------------------------------------*/ + +static void +siemens_isurf_write_fifo(void *base, const void *buf, size_t len) +{ + if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF); + outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF); + outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */ + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF); + outsb((((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW), (const u_char *)buf, (u_int)len); + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC put register routine + *---------------------------------------------------------------------------*/ + +static void +siemens_isurf_write_reg(u_char *base, u_int offset, u_int v) +{ + if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) + { + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) + { + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) + { + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v); + } + else /* IPAC */ + { + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + outb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW, (u_char)v); + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC get register routine + *---------------------------------------------------------------------------*/ + +static u_char +siemens_isurf_read_reg(u_char *base, u_int offset) +{ + if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW)); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW)); + } + else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW)); + } + else /* IPAC */ + { + outb((u_int)((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + return(inb(((u_int)base & SIE_ISURF_BASE_MASK) + SIE_ISURF_OFF_RW)); + } +} + +/*---------------------------------------------------------------------------* + * isic_probe_siemens_isurf - probe for Siemens I-Surf 2.0 PnP + *---------------------------------------------------------------------------*/ + +int +isic_probe_siemens_isurf(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 Siemens I-Surf 2.0 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 4: + case 5: + case 7: + case 10: + case 11: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Siemens I-Surf 2.0 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 Siemens I-Surf 2.0 PnP!\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 <= 0xff0))) + { + printf("isic%d: Error, invalid iobase 0x%x specified for Siemens I-Surf 2.0 PnP!\n", + dev->id_unit, dev->id_iobase); + return(0); + } + sc->sc_port = dev->id_iobase; + + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = siemens_isurf_read_reg; + sc->writereg = siemens_isurf_write_reg; + + sc->readfifo = siemens_isurf_read_fifo; + sc->writefifo = siemens_isurf_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP + *---------------------------------------------------------------------------*/ +int +isic_attach_siemens_isurf(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDISAC); + HSCX_A_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDHSCXA); + HSCX_B_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_IDHSCXB); + IPAC_BASE = (caddr_t) ((u_int)sc->sc_port | SIE_ISURF_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 */ + + return(1); +} +#endif /* NISIC > 0 && defined(SIEMENS_ISURF2) */ +#endif /* FreeBSD */ diff --git a/sys/i4b/layer1/i4b_tel_s0163.c b/sys/i4b/layer1/i4b_tel_s0163.c index efe9f34..4b6f1b5 100644 --- a/sys/i4b/layer1/i4b_tel_s0163.c +++ b/sys/i4b/layer1/i4b_tel_s0163.c @@ -37,9 +37,9 @@ * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3 * ======================================================== * - * $Id: i4b_tel_s0163.c,v 1.18 1999/02/14 19:51:02 hm Exp $ + * $Id: i4b_tel_s0163.c,v 1.19 1999/07/26 09:03:25 hm Exp $ * - * last edit-date: [Sun Feb 14 10:28:45 1999] + * last edit-date: [Mon Jul 26 10:59:38 1999] * * -hm clean up * -hm more cleanup @@ -212,7 +212,7 @@ isic_probe_s0163(struct isa_device *dev) if(dev->id_unit >= ISIC_MAXUNIT) { - printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!", + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!\n", dev->id_unit, dev->id_unit); return(0); } @@ -232,7 +232,7 @@ isic_probe_s0163(struct isa_device *dev) if(dev->id_maddr) { - printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!", + printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n", dev->id_unit, (u_long)dev->id_maddr); return(0); } @@ -249,7 +249,7 @@ isic_probe_s0163(struct isa_device *dev) break; default: - printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!", + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n", dev->id_unit, dev->id_iobase); return(0); break; @@ -258,21 +258,21 @@ isic_probe_s0163(struct isa_device *dev) if(((byte = inb(sc->sc_port)) != 0x51) && (byte != 0x10)) { - printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!", + printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\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.3!", + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n", 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!", + printf("isic%d: Error, signature 3 0x%x != 0x1c for Teles S0/16.3!\n", dev->id_unit, byte); return(0); } @@ -359,7 +359,7 @@ set_softc(struct isic_softc *sc, struct isa_attach_args *ia, int unit) break; default: - printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!", + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n", unit, ia->ia_iobase); return(0); break; @@ -429,7 +429,7 @@ isic_probe_s0163(struct device *dev, struct cfdata *cf, if(ia->ia_maddr) { - printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!", + printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n", cf->cf_unit, (u_long)ia->ia_maddr); return 0; } @@ -441,21 +441,21 @@ isic_probe_s0163(struct device *dev, struct cfdata *cf, if((byte = inb(sc->sc_port)) != 0x51) { - printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!", + printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!\n", cf->cf_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!", + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n", cf->cf_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!", + printf("isic%d: Error, signature 3 0x%x != 0x1c for Teles S0/16.3!\n", cf->cf_unit, byte); return(0); } diff --git a/sys/i4b/layer1/isa_isic.c b/sys/i4b/layer1/isa_isic.c index 7165e24..bd6b8c5 100644 --- a/sys/i4b/layer1/isa_isic.c +++ b/sys/i4b/layer1/isa_isic.c @@ -33,9 +33,9 @@ * isa_isic.c - ISA bus frontend for i4b_isic driver * -------------------------------------------------- * - * $Id: isa_isic.c,v 1.21 1999/02/23 14:51:18 hm Exp $ + * $Id: isa_isic.c,v 1.23 1999/07/19 14:40:47 hm Exp $ * - * last edit-date: [Sun Feb 14 10:29:11 1999] + * last edit-date: [Mon Jul 19 16:39:02 1999] * * -mh original implementation * -hm NetBSD patches from Martin @@ -115,6 +115,10 @@ isa_isic_probe(parent, cf, aux) struct isic_attach_args args; int ret = 0; +#if 0 + printf("isic%d: enter isa_isic_probe\n", cf->cf_unit); +#endif + /* check irq */ if (ia->ia_irq == IRQUNK) { printf("isic%d: config error: no IRQ specified\n", cf->cf_unit); @@ -314,6 +318,10 @@ done: /* unmap resources */ args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#if 0 + printf("isic%d: exit isa_isic_probe, return = %d\n", cf->cf_unit, ret); +#endif + return ret; } |