diff options
32 files changed, 10643 insertions, 0 deletions
diff --git a/contrib/bind/lib/isc/movefile.c b/contrib/bind/lib/isc/movefile.c new file mode 100644 index 000000000000..1b64b6cb18e9 --- /dev/null +++ b/contrib/bind/lib/isc/movefile.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2000 by Internet Software Consortium, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + +#include <port_before.h> +#include <stdio.h> +#include <isc/misc.h> +#include <port_after.h> +#ifndef HAVE_MOVEFILE +/* + * rename() is lame (can't overwrite an existing file) on some systems. + * use movefile() instead, and let lame OS ports do what they need to. + */ + +int +isc_movefile(const char *oldname, const char *newname) { + return (rename(oldname, newname)); +} +#else + static int os_port_has_isc_movefile = 1; +#endif diff --git a/sys/dev/ar/if_arregs.h b/sys/dev/ar/if_arregs.h new file mode 100644 index 000000000000..552d20e81ac7 --- /dev/null +++ b/sys/dev/ar/if_arregs.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1995 - 2001 John Hay. 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. + * + * THIS SOFTWARE IS PROVIDED BY [your name] 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 REGENTS 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. + * + * $FreeBSD$ + */ +#ifndef _IF_ARREGS_H_ +#define _IF_ARREGS_H_ + +#define NCHAN 2 /* A HD64570 chip have 2 channels */ +#define NPORT 4 /* A ArNet board can have 4 ports or */ + /* channels */ + +#define AR_BUF_SIZ 512 +#define AR_TX_BLOCKS 2 +#define ARC_IO_SIZ 0x10 +#define ARC_WIN_SIZ 0x00004000 +#define ARC_WIN_MSK (ARC_WIN_SIZ - 1) +#define ARC_WIN_SHFT 14 + +/* Some PCI specific offsets. */ +#define AR_PCI_SCA_1_OFFSET 0x00040000 +#define AR_PCI_SCA_2_OFFSET 0x00040400 +#define AR_PCI_ORBASE_OFFSET 0x00041000 +#define AR_PCI_SCA_PCR 0x0208 +#define AR_PCI_SCA_DMER 0x0309 +/* PCI Legacy (below 1M) offsets. */ +#define AR_PCI_L_SCA_1_OFFSET 0x00004000 +#define AR_PCI_L_SCA_2_OFFSET 0x00004400 +#define AR_PCI_L_ORBASE_OFFSET 0x00005000 + +#define AR_ID_5 0x00 /* RO, Card probe '5' */ +#define AR_ID_7 0x01 /* RO, Card probe '7' */ +#define AR_ID_0 0x02 /* RO, Card probe '0' */ +#define AR_BMI 0x03 /* RO, Bus, mem and interface type */ +#define AR_REV 0x04 /* RO, Adapter revision */ +#define AR_PNUM 0x05 /* RO, Port number */ +#define AR_HNDSH 0x06 /* RO, Supported handshake */ +#define AR_ISTAT 0x07 /* RO, DCD and Interrupt status */ +#define AR_MSCA_EN 0x08 /* WO, Memory and SCA enable */ +#define AR_TXC_DTR0 0x09 /* WO, Tx Clock and DTR control 0 + 1 */ +#define AR_SEC_PAL 0x0A /* RW, Security PAL */ +#define AR_INT_ACK0 0x0B /* RO, Interrupt Acknowledge 0 + 1 */ +#define AR_INT_SEL 0x0C /* RW, Interrupt Select */ +#define AR_MEM_SEL 0x0D /* RW, Memory Select */ +#define AR_INT_ACK2 0x0E /* RO, Interrupt Acknowledge 2 + 3 */ +#define AR_TXC_DTR2 0x0E /* WO, Tx Clock and DTR control 2 + 3 */ +/* PCI only */ +#define AR_PIMCTRL 0x4C /* RW, PIM and LEDs */ +#define AR_INT_SCB 0x50 /* RO, Interrupt Scoreboard */ + +#define AR_REV_MSK 0x0F +#define AR_WSIZ_MSK 0xE0 +#define AR_WSIZ_SHFT 5 +/* Bus memory and interface type */ +#define AR_BUS_MSK 0x03 +#define AR_BUS_ISA 0x00 +#define AR_BUS_MCA 0x01 +#define AR_BUS_EISA 0x02 +#define AR_BUS_PCI 0x03 + +#define AR_MEM_MSK 0x1C +#define AR_MEM_SHFT 0x02 +#define AR_MEM_64K 0x00 +#define AR_MEM_128K 0x04 +#define AR_MEM_256K 0x08 +#define AR_MEM_512K 0x0C + +/* + * EIA-232 + * V.35/EIA-232 + * EIA-530 + * X.21 + * EIA-530/X.21 Combo + */ +#define AR_IFACE_MSK 0xE0 +#define AR_IFACE_SHFT 0x05 +#define AR_IFACE_EIA_232 0x00 /* Only on the 570 card, not 570i */ +#define AR_IFACE_V_35 0x20 /* Selectable between V.35 and EIA-232 */ +#define AR_IFACE_EIA_530 0x40 +#define AR_IFACE_X_21 0x60 +#define AR_IFACE_COMBO 0xC0 /* X.21 / EIA-530 */ +#define AR_IFACE_PIM 0xE0 /* PIM module */ +#define AR_IFACE_LOOPBACK 0xFE +#define AR_IFACE_UNKNOWN 0xFF + +/* Supported Handshake signals */ +#define AR_SHSK_DTR 0x01 +#define AR_SHSK_RTS 0x02 +#define AR_SHSK_CTS 0x10 +#define AR_SHSK_DSR 0x20 +#define AR_SHSK_RI 0x40 +#define AR_SHSK_DCD 0x80 + +/* DCD and Interrupt status */ +#define AR_BD_INT 0x01 +#define AR_INT_0 0x20 +#define AR_INT_1 0x40 + +#define AR_DCD_MSK 0x1E +#define AR_DCD_SHFT 0x01 +#define AR_DCD_0 0x02 +#define AR_DCD_1 0x04 +#define AR_DCD_2 0x08 +#define AR_DCD_3 0x10 + +/* Memory and SCA enable */ +#define AR_WIN_MSK 0x1F + +#define AR_SEL_SCA_0 0x00 +#define AR_SEL_SCA_1 0x20 +#define AR_ENA_SCA 0x40 +#define AR_ENA_MEM 0x80 + +/* Transmit Clock and DTR and RESET */ +#define AR_TXC_DTR_TX0 0x01 +#define AR_TXC_DTR_TX1 0x02 +#define AR_TXC_DTR_DTR0 0x04 +#define AR_TXC_DTR_DTR1 0x08 +#define AR_TXC_DTR_TXCS0 0x10 +#define AR_TXC_DTR_TXCS1 0x20 +#define AR_TXC_DTR_NOTRESET 0x40 +#define AR_TXC_DTR_RESET 0x00 + +/* Interrupt select register */ +#define AR_INTS_CEN 0x01 +#define AR_INTS_ISEL0 0x02 +#define AR_INTS_ISEL1 0x04 +#define AR_INTS_ISEL2 0x08 +#define AR_INTS_CMA14 0x10 +#define AR_INTS_CMA15 0x20 + +/* Advanced PIM Control */ +#define AR_PIM_STROBE 0x01 +#define AR_PIM_DATA 0x02 +#define AR_PIM_MODEG 0x04 +#define AR_PIM_A2D_STROBE 0x04 +#define AR_PIM_MODEY 0x08 +#define AR_PIM_A2D_DOUT 0x08 +#define AR_PIM_AUTO_LED 0x10 +#define AR_PIM_INT 0x20 + +#define AR_PIM_RESET 0x00 /* MODEG and MODEY 0 */ +#define AR_PIM_READ AR_PIM_MODEG +#define AR_PIM_WRITE AR_PIM_MODEY + +#define ARC_GET_WIN(addr) ((addr >> ARC_WIN_SHFT) & AR_WIN_MSK) + +#define ARC_SET_MEM(iobase,win) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \ + ARC_GET_WIN(win)) +#define ARC_SET_SCA(iobase,ch) outb(iobase+AR_MSCA_EN, AR_ENA_MEM | \ + AR_ENA_SCA | (ch ? AR_SEL_SCA_1:AR_SEL_SCA_0)) +#define ARC_SET_OFF(iobase) outb(iobase+AR_MSCA_EN, 0) + +struct ar_hardc { + int cunit; + struct ar_softc *sc; + u_short iobase; + int isa_irq; + int numports; + caddr_t mem_start; + caddr_t mem_end; + caddr_t plx_mem; + u_char *orbase; + + u_int memsize; /* in bytes */ + u_int winsize; /* in bytes */ + u_int winmsk; + u_char bustype; /* ISA, MCA, PCI.... */ + u_char interface[NPORT];/* X21, V.35, EIA-530.... */ + u_char revision; + u_char handshake; /* handshake lines supported by card. */ + + u_char txc_dtr[NPORT/NCHAN]; /* the register is write only */ + u_int txc_dtr_off[NPORT/NCHAN]; + + sca_regs *sca[NPORT/NCHAN]; + + bus_space_tag_t bt; + bus_space_handle_t bh; + int rid_ioport; + int rid_memory; + int rid_plx_memory; + int rid_irq; + int rid_drq; + struct resource* res_ioport; /* resource for port range */ + struct resource* res_memory; /* resource for mem range */ + struct resource* res_plx_memory; + struct resource* res_irq; /* resource for irq range */ + struct resource* res_drq; /* resource for dma channel */ + void *intr_cookie; +}; + +extern devclass_t ar_devclass; + +int ar_allocate_ioport(device_t device, int rid, u_long size); +int ar_allocate_irq(device_t device, int rid, u_long size); +int ar_allocate_memory(device_t device, int rid, u_long size); +int ar_allocate_plx_memory(device_t device, int rid, u_long size); +int ar_deallocate_resources(device_t device); +int ar_attach(device_t device); +int ar_detach (device_t); + +#endif /* _IF_ARREGS_H_ */ diff --git a/sys/i4b/layer1/ihfc/i4b_ihfc_pnp.c b/sys/i4b/layer1/ihfc/i4b_ihfc_pnp.c new file mode 100644 index 000000000000..ac5658b4a57c --- /dev/null +++ b/sys/i4b/layer1/ihfc/i4b_ihfc_pnp.c @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2000 Hans Petter Selasky. 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_ihfc_pnp.c - common hfc ISA PnP-bus interface + * ------------------------------------------------- + * + * - Everything which has got anything to to with "PnP" bus setup has + * been put here, except the chip spesific "PnP" setup. + * + * + * last edit-date: [Tue Jan 23 16:03:33 2001] + * + * $Id: i4b_ihfc_pnp.c,v 1.9 2000/09/19 13:50:36 hm Exp $ + * + * $FreeBSD$ + * + *---------------------------------------------------------------------------*/ + +#include "ihfc.h" + +#if (NIHFC > 0) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <net/if.h> + + +#include <i4b/include/i4b_global.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/ihfc/i4b_ihfc.h> +#include <i4b/layer1/ihfc/i4b_ihfc_ext.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <isa/isavar.h> + +/*---------------------------------------------------------------------------* + * Softc + *---------------------------------------------------------------------------*/ +ihfc_sc_t ihfc_softc[IHFC_MAXUNIT]; + +/*---------------------------------------------------------------------------* + * Prototypes + *---------------------------------------------------------------------------*/ +static int ihfc_isa_probe (device_t dev); +static int ihfc_pnp_probe (device_t dev); +static int ihfc_pnp_attach (device_t dev); +static int ihfc_pnp_detach (device_t dev, u_int flag); +static int ihfc_pnp_shutdown (device_t dev); + +const struct ihfc_pnp_ids +{ + u_long vid; /* vendor id */ + int flag; /* */ + u_char hfc; /* chip type */ + u_char iirq; /* internal irq */ + u_short iio; /* internal io-address */ + u_char stdel; /* S/T delay compensation */ +} + ihfc_pnp_ids[] = +{ + { 0x10262750, CARD_TYPEP_16_3C, HFC_S, 2, 0x200, 0x2d}, + { 0x20262750, CARD_TYPEP_16_3C, HFC_SP, 0, 0x000, 0x0f}, + { 0x1411d805, CARD_TYPEP_ACERP10, HFC_S, 1, 0x300, 0x0e}, + { 0 } +}; + +typedef const struct ihfc_pnp_ids ihfc_id_t; + +/*---------------------------------------------------------------------------* + * PCB layout + * + * IIRQx: Internal IRQ cross reference for a card + * IRQx : Supported IRQ's for a card + * IOx : Supported IO-bases for a card + * + * IO0, IRQ0, IIRQ0: TELEINT ISDN SPEED No. 1 + * IIRQ3: Teles 16.3c PnP (B version) + *---------------------------------------------------------------------------*/ + /* IRQ -> 0 1 2 3 4 5 6 7 8 9 a b c d e f */ +#define IIRQ0 ((const u_char []){ 0, 0, 0, 1, 2, 3, 0, 4, 0, 0, 5, 6, 0, 0, 0, 0 }) +#define IRQ0 ((const u_char []){ 3, 4, 5, 7, 0xa, 0xb, 0 }) + +#define IO0 ((const u_long []){ 0x300, 0x330, 0x278, 0x2e8, 0 }) + +#define IIRQ3 ((const u_char []){ 0, 0, 0, 7, 0, 1, 0, 0, 0, 2, 3, 4, 5, 0, 0, 6 }) + +/*---------------------------------------------------------------------------* + * ISA PnP setup + *---------------------------------------------------------------------------*/ +static device_method_t ihfc_pnp_methods[] = +{ + DEVMETHOD(device_probe, ihfc_pnp_probe), + DEVMETHOD(device_attach, ihfc_pnp_attach), + DEVMETHOD(device_shutdown, ihfc_pnp_shutdown), + { 0, 0 } +}; + +static driver_t ihfc_pnp_driver = +{ + "ihfc", + ihfc_pnp_methods, + 0, +}; + +static devclass_t ihfc_devclass; + +DRIVER_MODULE(ihfcpnp, isa, ihfc_pnp_driver, ihfc_devclass, 0, 0); + +/*---------------------------------------------------------------------------* + * probe for ISA "PnP" card + *---------------------------------------------------------------------------*/ +int +ihfc_pnp_probe(device_t dev) +{ + u_int unit = device_get_unit(dev); /* get unit */ + u_int32_t vid = isa_get_vendorid(dev); /* vendor id */ + ihfc_id_t *ids = &ihfc_pnp_ids[0]; /* ids ptr */ + ihfc_sc_t *sc = &ihfc_softc[unit]; /* softc */ + u_char flag = 0; /* flag */ + void *dummy = 0; /* a dummy */ + + HFC_VAR; + + if (unit >= IHFC_MAXUNIT) + { + printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit); + return ENXIO; + } + + if (!vid) return ihfc_isa_probe(dev); + + HFC_BEG; + + for ( ;(ids->vid); ids++) + { + if (ids->vid == vid) + { + flag = 0; + + bzero(sc, sizeof(ihfc_sc_t)); /* reset data structure.* + * Zero is default for * + * most, so calling the * + * int. handler now will* + * not be a problem. */ + + S_IOBASE[0] = bus_alloc_resource( + dev, SYS_RES_IOPORT, &S_IORID[0], + 0UL, ~0UL, 2, RF_ACTIVE + ); + + S_IRQ = bus_alloc_resource( + dev, SYS_RES_IRQ, &S_IRQRID, + 0UL, ~0UL, 1, RF_ACTIVE + ); + + S_DLP = IHFC_DLP; /* set D-priority */ + S_HFC = ids->hfc; /* set chip type */ + S_I4BFLAG = ids->flag; /* set flag */ + S_NTMODE = IHFC_NTMODE; /* set mode */ + S_STDEL = ids->stdel; /* set delay */ + + S_I4BUNIT = L0IHFCUNIT(unit); /* set "i4b" unit */ + S_TRACE = TRACE_OFF; /* set trace mask */ + S_UNIT = unit; /* set up unit numbers */ + + if (S_IOBASE[0] && S_IRQ) + { + if (ids->iio) + { + S_IIO = ids->iio; + S_IIRQ = ids->iirq; + } + else + { + S_IIO = rman_get_start(S_IOBASE[0]) & 0x3ff; + S_IIRQ = IIRQ3[rman_get_start(S_IRQ) & 0xf]; + } + + /* setup interrupt routine now to avvoid stray * + * interrupts. */ + + bus_setup_intr(dev, S_IRQ, INTR_TYPE_NET, (void(*)(void*)) + HFC_INTR, sc, &dummy); + + flag = 1; + + if (!HFC_CONTROL(sc, 1)) + { + HFC_END; + return 0; /* success */ + } + else + { + printf("ihfc%d: Chip seems corrupted. " + "Please hard reboot your computer!\n", + unit); + } + } + + ihfc_pnp_detach(dev, flag); + } + } + + HFC_END; + return ENXIO; /* failure */ +} + +/*---------------------------------------------------------------------------* + * probe for "ISA" cards + *---------------------------------------------------------------------------*/ +int +ihfc_isa_probe(device_t dev) +{ + u_int unit = device_get_unit(dev); /* get unit */ + ihfc_sc_t *sc = &ihfc_softc[unit]; /* softc */ + const u_char *irq = &IRQ0[0]; /* irq's to try */ + const u_long *iobase = &IO0[0]; /* iobases to try */ + u_char flag = 0; /* flag */ + void *dummy = 0; /* a dummy */ + + HFC_VAR; + + bzero(sc, sizeof(ihfc_sc_t)); /* reset data structure * + * We must reset the * + * datastructure here, * + * else we risk zero-out * + * our gotten resources. */ + HFC_BEG; + + j0: while(*irq) /* get supported IRQ */ + { + if ((S_IRQ = bus_alloc_resource( + dev, SYS_RES_IRQ, &S_IRQRID, + *irq, *irq, 1, RF_ACTIVE + ) + )) + break; + else + irq++; + } + + while(*iobase) /* get supported IO-PORT */ + { + if ((S_IOBASE[0] = bus_alloc_resource( + dev, SYS_RES_IOPORT, &S_IORID[0], + *iobase, *iobase, 2, RF_ACTIVE + ) + )) + break; + else + iobase++; + } + + flag = 0; + + if (*irq && *iobase) /* we got our resources, now test chip */ + { + S_DLP = IHFC_DLP; /* set D-priority */ + S_HFC = HFC_1; /* set chip type */ + S_I4BFLAG = CARD_TYPEP_TELEINT_NO_1; /* set flag */ + S_NTMODE = IHFC_NTMODE; /* set mode */ + S_STDEL = 0x00; /* set delay (not used) */ + + S_I4BUNIT = L0IHFCUNIT(unit); /* set "i4b" unit */ + S_TRACE = TRACE_OFF; /* set trace mask */ + S_UNIT = unit; /* set up unit numbers */ + + S_IIRQ = IIRQ0[*irq]; /* set internal irq */ + S_IIO = *iobase; /* set internal iobase */ + + /* setup interrupt routine now to avvoid stray * + * interrupts. */ + + bus_setup_intr(dev, S_IRQ, INTR_TYPE_NET, (void(*)(void*)) + HFC_INTR, sc, &dummy); + + flag = 1; + + if (!HFC_CONTROL(sc, 1)) + { + device_set_desc(dev, "TELEINT ISDN SPEED No. 1"); + + HFC_END; + return 0; /* success */ + } + } + + ihfc_pnp_detach(dev, flag); + + if (*irq && *++iobase) goto j0; /* try again */ + + HFC_END; + + printf("ihfc%d: Chip not found. " + "A hard reboot may help!\n", unit); + + return ENXIO; /* failure */ +} + +/*---------------------------------------------------------------------------* + * attach ISA "PnP" card + *---------------------------------------------------------------------------*/ +int +ihfc_pnp_attach(device_t dev) +{ + u_int unit = device_get_unit(dev); /* get unit */ + ihfc_sc_t *sc = &ihfc_softc[unit]; /* softc */ + HFC_VAR; + + HFC_BEG; + + ihfc_B_linkinit(sc); /* Setup B-Channel linktabs */ + + i4b_l1_mph_status_ind(S_I4BUNIT, STI_ATTACH, S_I4BFLAG, &ihfc_l1mux_func); + + HFC_INIT(sc, 0, 0, 1); /* Setup D - Channel */ + + HFC_INIT(sc, 2, 0, 0); /* Init B1 - Channel */ + HFC_INIT(sc, 4, 0, 0); /* Init B2 - Channel */ + + HFC_END; + return 0; /* success */ + + HFC_END; + return ENXIO; /* failure */ +} + +/*---------------------------------------------------------------------------* + * shutdown for our ISA PnP card + *---------------------------------------------------------------------------*/ +int +ihfc_pnp_shutdown(device_t dev) +{ + u_int unit = device_get_unit(dev); /* get unit */ + ihfc_sc_t *sc = &ihfc_softc[unit]; /* softc */ + HFC_VAR; + + HFC_BEG; + + if (unit >= IHFC_MAXUNIT) + { + printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit); + goto f0; + } + + HFC_CONTROL(sc, 2); /* shutdown chip */ + + HFC_END; + return 0; + f0: + HFC_END; + return ENXIO; + +} + +/*---------------------------------------------------------------------------* + * detach for our ISA PnP card + * + * flag: bit[0] set: teardown interrupt handler too + *---------------------------------------------------------------------------*/ +int +ihfc_pnp_detach (device_t dev, u_int flag) +{ + u_int unit = device_get_unit(dev); /* get unit */ + ihfc_sc_t *sc = &ihfc_softc[unit]; /* softc */ + u_char i; + + if (unit >= IHFC_MAXUNIT) + { + printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit); + return 0; + } + + /* free interrupt resources */ + + if(S_IRQ) + { + if (flag & 1) + { + /* tear down interrupt handler */ + bus_teardown_intr(dev, S_IRQ, (void(*)(void *))HFC_INTR); + } + + /* free irq */ + bus_release_resource(dev, SYS_RES_IRQ, S_IRQRID, S_IRQ); + + S_IRQRID = 0; + S_IRQ = 0; + } + + + /* free iobases */ + + for (i = IHFC_IO_BASES; i--;) + { + if(S_IOBASE[i]) + { + bus_release_resource(dev, SYS_RES_IOPORT, + S_IORID[i], S_IOBASE[i]); + S_IORID[i] = 0; + S_IOBASE[i] = 0; + } + } + + return 0; +} + +#endif /* NIHFC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_asuscom_ipac.c b/sys/i4b/layer1/isic/i4b_asuscom_ipac.c new file mode 100644 index 000000000000..9d440b35c333 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_asuscom_ipac.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1999 Ari Suutari. All rights reserved. + * + * Copyright (c) 1997, 2001 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. + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:06:30 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined (ASUSCOM_IPAC) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_ipac.h> + +/* masks for register encoded in base addr */ + +#define ASI_BASE_MASK 0x0ffff +#define ASI_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ASI_IDISAC 0x00000 +#define ASI_IDHSCXA 0x10000 +#define ASI_IDHSCXB 0x20000 +#define ASI_IDIPAC 0x40000 + +/* offsets from base address */ + +#define ASI_OFF_ALE 0x00 +#define ASI_OFF_RW 0x01 + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +asi_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_ISAC_OFF); + bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_read_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K ISAC put fifo routine + *---------------------------------------------------------------------------*/ +static void +asi_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_ISAC_OFF); + bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,ASI_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_write_multi_1(t,h,ASI_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +asi_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_ISAC_OFF); + bus_space_write_1(t,h,ASI_OFF_RW,data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXA_OFF); + bus_space_write_1(t,h,ASI_OFF_RW,data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXB_OFF); + bus_space_write_1(t,h,ASI_OFF_RW,data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_IPAC_OFF); + bus_space_write_1(t,h,ASI_OFF_RW,data); + break; + } +} + +/*---------------------------------------------------------------------------* + * Asuscom ISDNlink 128K ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +asi_read_reg(struct l1_softc *sc,int what,bus_size_t reg) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_ISAC_OFF); + return bus_space_read_1(t,h,ASI_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXA_OFF); + return bus_space_read_1(t,h,ASI_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_HSCXB_OFF); + return bus_space_read_1(t,h,ASI_OFF_RW); + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,ASI_OFF_ALE,reg+IPAC_IPAC_OFF); + return bus_space_read_1(t,h,ASI_OFF_RW); + default: + return 0; + } +} + +/*---------------------------------------------------------------------------* + * isic_attach_siemens_isurf - attach for Asuscom ISDNlink 128K + *---------------------------------------------------------------------------*/ +int +isic_attach_asi(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = asi_read_reg; + sc->writereg = asi_write_reg; + + sc->readfifo = asi_read_fifo; + sc->writefifo = asi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* enable hscx/isac irq's */ +/* + * This has been taken from Linux driver. + * (Removed initialization that was not applicaple to + * this board or was already register default setting.) + */ + IPAC_WRITE (IPAC_ACFG, 0xff); /* Setup AUX pin modes */ + IPAC_WRITE (IPAC_AOE, 0x0); /* Setup AUX pin modes */ + IPAC_WRITE (IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + return(0); +} +#endif /* (NISIC > 0) && defined (ASUSCOM_IPAC) */ diff --git a/sys/i4b/layer1/isic/i4b_avm_a1.c b/sys/i4b/layer1/isic/i4b_avm_a1.c new file mode 100644 index 000000000000..3fbfafbf2cc6 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_avm_a1.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 1996 Andrew Gordon. All rights reserved. + * + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_avm_a1.c - AVM A1/Fritz passive card driver for isdn4bsd + * ------------------------------------------------------------ + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:25:23 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(AVM_A1) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * AVM A1 and AVM Fritz! Card special registers + *---------------------------------------------------------------------------*/ + +#define AVM_CONF_REG 0x1800 /* base offset for config register */ +#define AVM_CONF_IRQ 0x1801 /* base offset for IRQ register */ + /* config register write */ +#define AVM_CONF_WR_RESET 0x01 /* 1 = RESET ISAC and HSCX */ +#define AVM_CONF_WR_CCL 0x02 /* 1 = clear counter low nibble */ +#define AVM_CONF_WR_CCH 0x04 /* 1 = clear counter high nibble */ +#define AVM_CONF_WR_IRQEN 0x08 /* 1 = enable IRQ */ +#define AVM_CONF_WR_TEST 0x10 /* test bit */ + /* config register read */ +#define AVM_CONF_RD_IIRQ 0x01 /* 0 = ISAC IRQ active */ +#define AVM_CONF_RD_HIRQ 0x02 /* 0 = HSCX IRQ active */ +#define AVM_CONF_RD_CIRQ 0x04 /* 0 = counter IRQ active */ +#define AVM_CONF_RD_ZER1 0x08 /* unused, always read 0 */ +#define AVM_CONF_RD_TEST 0x10 /* test bit read back */ +#define AVM_CONF_RD_ZER2 0x20 /* unused, always read 0 */ + +#define AVM_ISAC_R_OFFS (0x1400-0x20) +#define AVM_HSCXA_R_OFFS (0x400-0x20) +#define AVM_HSCXB_R_OFFS (0xc00-0x20) +#define AVM_ISAC_F_OFFS (0x1400-0x20-0x3e0) +#define AVM_HSCXA_F_OFFS (0x400-0x20-0x3e0) +#define AVM_HSCXB_F_OFFS (0xc00-0x20-0x3e0) + +/*---------------------------------------------------------------------------* + * AVM read fifo routine + *---------------------------------------------------------------------------*/ +static void +avma1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+4]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+4]); + bus_space_read_multi_1(t, h, 0, buf, size); +} + +/*---------------------------------------------------------------------------* + * AVM write fifo routine + *---------------------------------------------------------------------------*/ +static void +avma1_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+4]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+4]); + bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size); +} + +/*---------------------------------------------------------------------------* + * AVM write register routine + *---------------------------------------------------------------------------*/ +static void +avma1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + bus_space_write_1(t, h, offs, data); +} + +/*---------------------------------------------------------------------------* + * AVM read register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +avma1_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + return bus_space_read_1(t, h, offs); +} + +/*---------------------------------------------------------------------------* + * allocate an io port + *---------------------------------------------------------------------------*/ +static int +isic_alloc_port(device_t dev, int rid, u_int base, u_int len) +{ + size_t unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + sc->sc_resources.io_rid[rid] = rid; + + bus_set_resource(dev, SYS_RES_IOPORT, rid, base, len); + + if(!(sc->sc_resources.io_base[rid] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[rid], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Error, failed to reserve io #%d!\n", unit, rid); + isic_detach_common(dev); + return(ENXIO); + } + return(0); +} + +/*---------------------------------------------------------------------------* + * isic_probe_avma1 - probe for AVM A1 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_probe_avma1(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ + bus_space_tag_t t; /* bus things */ + bus_space_handle_t h; + u_char savebyte; + u_char byte; + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get iobase for AVM A1/Fritz!\n", + unit); + return(ENXIO); + } + + /* set io base */ + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + + /* release io base */ + + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + + switch(sc->sc_port) + { + case 0x200: + case 0x240: + case 0x300: + case 0x340: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n", + unit, sc->sc_port); + return(ENXIO); + break; + } + + if(isic_alloc_port(dev, 0, sc->sc_port+AVM_CONF_REG, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 1, sc->sc_port+AVM_ISAC_R_OFFS, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 2, sc->sc_port+AVM_HSCXA_R_OFFS, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 3, sc->sc_port+AVM_HSCXB_R_OFFS, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 4, sc->sc_port+AVM_ISAC_F_OFFS, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 5, sc->sc_port+AVM_HSCXA_F_OFFS, 0x20)) + return(ENXIO); + + if(isic_alloc_port(dev, 6, sc->sc_port+AVM_HSCXB_F_OFFS, 0x20)) + return(ENXIO); + + /* get our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get an irq for AVM A1/Fritz!\n",unit); + isic_detach_common(dev); + return ENXIO; + } + + /* get the irq number */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* register interupt routine */ + bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + /* check IRQ validity */ + + switch(sc->sc_irq) + { + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n", + unit, sc->sc_irq); + isic_detach_common(dev); + return(ENXIO); + break; + } + + sc->clearirq = NULL; + sc->readreg = avma1_read_reg; + sc->writereg = avma1_write_reg; + + sc->readfifo = avma1_read_fifo; + sc->writefifo = avma1_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_AVMA1; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* + * Read HSCX A/B VSTR. + * Expected value for AVM A1 is 0x04 or 0x05 and for the + * AVM Fritz!Card is 0x05 in the least significant bits. + */ + + if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) || + (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) ) + { + printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n", + unit); + printf("isic%d: HSC0: VSTR: %#x\n", + unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + unit, HSCX_READ(1, H_VSTR)); + return(ENXIO); + } + + /* AVM A1 or Fritz! control register bits: */ + /* read write */ + /* 0x01 hscx irq* RESET */ + /* 0x02 isac irq* clear counter1 */ + /* 0x04 counter irq* clear counter2 */ + /* 0x08 always 0 irq enable */ + /* 0x10 read test bit set test bit */ + /* 0x20 always 0 unused */ + + /* + * XXX the following test may be destructive, to prevent the + * worst case, we save the byte first, and in case the test + * fails, we write back the saved byte ..... + */ + + t = rman_get_bustag(sc->sc_resources.io_base[0]); + h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + savebyte = bus_space_read_1(t, h, 0); + + /* write low to test bit */ + + bus_space_write_1(t, h, 0, 0x00); + + /* test bit and next higher and lower bit must be 0 */ + + if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x00) + { + printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n", + unit, byte); + bus_space_write_1(t, h, 0, savebyte); + return(ENXIO); + } + + /* write high to test bit */ + + bus_space_write_1(t, h, 0, 0x10); + + /* test bit must be high, next higher and lower bit must be 0 */ + + if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x10) + { + printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n", + unit, byte); + bus_space_write_1(t, h, 0, savebyte); + return(ENXIO); + } + return(0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_avma1 - attach AVM A1 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_attach_avma1(device_t dev) +{ + size_t unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* reset ISAC/HSCX */ + + bus_space_write_1(t, h, 0, 0x00); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0, AVM_CONF_WR_RESET); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + bus_space_write_1(t, h, 1, sc->sc_irq); + DELAY(SEC_DELAY / 10); + + /* enable IRQ, disable counter IRQ */ + + bus_space_write_1(t, h, 0, AVM_CONF_WR_IRQEN | + AVM_CONF_WR_CCH | AVM_CONF_WR_CCL); + DELAY(SEC_DELAY / 10); + + return(0); +} + +#endif /* NISIC > 0 && defined(AVM_A1) */ diff --git a/sys/i4b/layer1/isic/i4b_bchan.c b/sys/i4b/layer1/isic/i4b_bchan.c new file mode 100644 index 000000000000..1226c175c63a --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_bchan.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_bchan.c - B channel handling L1 procedures + * ---------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:07:12 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +static void isic_bchannel_start(int unit, int h_chan); +static void isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp); + +/*---------------------------------------------------------------------------* + * initialize one B channels rx/tx data structures and init/deinit HSCX + *---------------------------------------------------------------------------*/ +void +isic_bchannel_setup(int unit, int h_chan, int bprot, int activate) +{ + struct l1_softc *sc = &l1_sc[unit]; + l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; + + int s = SPLI4B(); + + if(activate == 0) + { + /* deactivation */ + isic_hscx_init(sc, h_chan, activate); + } + + NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s", + sc->sc_unit, h_chan, activate ? "activate" : "deactivate"); + + /* general part */ + + chan->unit = sc->sc_unit; /* unit number */ + chan->channel = h_chan; /* B channel */ + chan->bprot = bprot; /* B channel protocol */ + chan->state = HSCX_IDLE; /* B channel state */ + + /* receiver part */ + + chan->rx_queue.ifq_maxlen = IFQ_MAXLEN; + +#if defined (__FreeBSD__) && __FreeBSD__ > 4 + mtx_init(&chan->rx_queue.ifq_mtx, "i4b_isic_rx", MTX_DEF); +#endif + + i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */ + + 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 */ + + chan->tx_queue.ifq_maxlen = IFQ_MAXLEN; + +#if defined (__FreeBSD__) && __FreeBSD__ > 4 + mtx_init(&chan->tx_queue.ifq_mtx, "i4b_isic_tx", MTX_DEF); +#endif + + i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */ + + chan->txcount = 0; /* reset tx counter */ + + i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */ + + chan->out_mbuf_head = NULL; /* reset head mbuf ptr */ + chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */ + chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */ + chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */ + + if(activate != 0) + { + /* activation */ + isic_hscx_init(sc, h_chan, activate); + } + + splx(s); +} + +/*---------------------------------------------------------------------------* + * start transmission on a b channel + *---------------------------------------------------------------------------*/ +static void +isic_bchannel_start(int unit, int h_chan) +{ + struct l1_softc *sc = &l1_sc[unit]; + register l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; + register int next_len; + register int len; + + int s; + int activity = -1; + int cmd = 0; + + s = SPLI4B(); /* enter critical section */ + if(chan->state & HSCX_TX_ACTIVE) /* already running ? */ + { + splx(s); + return; /* yes, leave */ + } + + /* get next mbuf from queue */ + + IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); + + if(chan->out_mbuf_head == NULL) /* queue empty ? */ + { + splx(s); /* leave critical section */ + return; /* yes, exit */ + } + + /* init current mbuf values */ + + chan->out_mbuf_cur = chan->out_mbuf_head; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + + /* activity indicator for timeout handling */ + + if(chan->bprot == BPROT_NONE) + { + if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) + activity = ACT_TX; + } + else + { + activity = ACT_TX; + } + + chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */ + + if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */ + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + + len = 0; /* # of chars put into HSCX tx fifo this time */ + + /* + * fill the HSCX tx fifo with data from the current mbuf. if + * current mbuf holds less data than HSCX fifo length, try to + * get the next mbuf from (a possible) mbuf chain. if there is + * not enough data in a single mbuf or in a chain, then this + * is the last mbuf and we tell the HSCX that it has to send + * CRC and closing flag + */ + + while((len < sc->sc_bfifolen) && chan->out_mbuf_cur) + { + /* + * put as much data into the HSCX fifo as is + * available from the current mbuf + */ + + if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen) + next_len = sc->sc_bfifolen - len; + else + next_len = chan->out_mbuf_cur_len; + +#ifdef NOTDEF + printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ", + chan->out_mbuf_head, + chan->out_mbuf_cur, + chan->out_mbuf_cur_ptr, + chan->out_mbuf_cur_len, + len, + next_len); +#endif + + /* wait for tx fifo write enabled */ + + isic_hscx_waitxfw(sc, h_chan); + + /* write what we have from current mbuf to HSCX fifo */ + + HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len); + + len += next_len; /* update # of bytes written */ + chan->txcount += next_len; /* statistics */ + chan->out_mbuf_cur_ptr += next_len; /* data ptr */ + chan->out_mbuf_cur_len -= next_len; /* data len */ + + /* + * in case the current mbuf (of a possible chain) data + * has been put into the fifo, check if there is a next + * mbuf in the chain. If there is one, get ptr to it + * and update the data ptr and the length + */ + + if((chan->out_mbuf_cur_len <= 0) && + ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)) + { + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + } + } + + /* + * if there is either still data in the current mbuf and/or + * there is a successor on the chain available issue just + * a XTF (transmit) command to HSCX. if ther is no more + * data available from the current mbuf (-chain), issue + * an XTF and an XME (message end) command which will then + * send the CRC and the closing HDLC flag sequence + */ + + if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0)) + { + /* + * more data available, send current fifo out. + * next xfer to HSCX tx fifo is done in the + * HSCX interrupt routine. + */ + + cmd |= HSCX_CMDR_XTF; + } + else + { + /* end of mbuf chain */ + + if(chan->bprot == BPROT_NONE) + cmd |= HSCX_CMDR_XTF; + else + cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME; + + i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */ + + chan->out_mbuf_head = NULL; + chan->out_mbuf_cur = NULL; + chan->out_mbuf_cur_ptr = NULL; + chan->out_mbuf_cur_len = 0; + } + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity); + + if(cmd) + isic_hscx_cmd(sc, h_chan, cmd); + + splx(s); +} + +/*---------------------------------------------------------------------------* + * fill statistics struct + *---------------------------------------------------------------------------*/ +static void +isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp) +{ + struct l1_softc *sc = &l1_sc[unit]; + l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; + int s; + + s = SPLI4B(); + + bsp->outbytes = chan->txcount; + bsp->inbytes = chan->rxcount; + + chan->txcount = 0; + chan->rxcount = 0; + + splx(s); +} + +/*---------------------------------------------------------------------------* + * return the address of isic drivers linktab + *---------------------------------------------------------------------------*/ +isdn_link_t * +isic_ret_linktab(int unit, int channel) +{ + struct l1_softc *sc = &l1_sc[unit]; + l1_bchan_state_t *chan = &sc->sc_chan[channel]; + + return(&chan->isic_isdn_linktab); +} + +/*---------------------------------------------------------------------------* + * set the driver linktab in the b channel softc + *---------------------------------------------------------------------------*/ +void +isic_set_linktab(int unit, int channel, drvr_link_t *dlt) +{ + struct l1_softc *sc = &l1_sc[unit]; + l1_bchan_state_t *chan = &sc->sc_chan[channel]; + + chan->isic_drvr_linktab = dlt; +} + +/*---------------------------------------------------------------------------* + * initialize our local linktab + *---------------------------------------------------------------------------*/ +void +isic_init_linktab(struct l1_softc *sc) +{ + l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A]; + isdn_link_t *lt = &chan->isic_isdn_linktab; + + /* make sure the hardware driver is known to layer 4 */ + ctrl_types[CTRL_PASSIVE].set_linktab = i4b_l1_set_linktab; + ctrl_types[CTRL_PASSIVE].get_linktab = i4b_l1_ret_linktab; + + /* local setup */ + lt->unit = sc->sc_unit; + lt->channel = HSCX_CH_A; + lt->bch_config = isic_bchannel_setup; + lt->bch_tx_start = isic_bchannel_start; + lt->bch_stat = isic_bchannel_stat; + lt->tx_queue = &chan->tx_queue; + + /* used by non-HDLC data transfers, i.e. telephony drivers */ + lt->rx_queue = &chan->rx_queue; + + /* used by HDLC data transfers, i.e. ipr and isp drivers */ + lt->rx_mbuf = &chan->in_mbuf; + + chan = &sc->sc_chan[HSCX_CH_B]; + lt = &chan->isic_isdn_linktab; + + lt->unit = sc->sc_unit; + lt->channel = HSCX_CH_B; + lt->bch_config = isic_bchannel_setup; + lt->bch_tx_start = isic_bchannel_start; + lt->bch_stat = isic_bchannel_stat; + lt->tx_queue = &chan->tx_queue; + + /* used by non-HDLC data transfers, i.e. telephony drivers */ + lt->rx_queue = &chan->rx_queue; + + /* used by HDLC data transfers, i.e. ipr and isp drivers */ + lt->rx_mbuf = &chan->in_mbuf; +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_ctx_s0P.c b/sys/i4b/layer1/isic/i4b_ctx_s0P.c new file mode 100644 index 000000000000..8be6979b8094 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_ctx_s0P.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Creatix/Teles PnP + * ============================================================ + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:07:22 2001] + * + * Note: this driver works for the Creatix ISDN S0-16 P+P and + * for the Teles S0/16.3 PnP card. Although they are not + * the same hardware and don't share the same PnP config + * information, once the base addresses are set, the + * offsets are same and therefore they can use the same + * driver. + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && (defined(CRTX_S0_P) || defined(TEL_S0_16_3_P)) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * Creatix / Teles PnP ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +ctxs0P_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]); + bus_space_read_multi_1(t,h,0x3e,buf,size); +} + +/*---------------------------------------------------------------------------* + * Creatix / Teles PnP ISAC put fifo routine + *---------------------------------------------------------------------------*/ +static void +ctxs0P_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]); + bus_space_write_multi_1(t,h,0x3e,buf,size); +} + +/*---------------------------------------------------------------------------* + * Creatix / Teles PnP ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +ctxs0P_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]); + bus_space_write_1(t,h,offs,data); +} + +/*---------------------------------------------------------------------------* + * Creatix / Teles PnP ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +ctxs0P_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+2]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+2]); + return bus_space_read_1(t,h,offs); +} + +/*---------------------------------------------------------------------------* + * isic_attach_Cs0P - attach Creatix / Teles PnP + *---------------------------------------------------------------------------*/ +int +isic_attach_Cs0P(device_t dev) +{ + u_int32_t iobase1; + u_int32_t iobase2; + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t; + bus_space_handle_t h; + + /* + * this card needs a second io_base, + * free resources if we don't get it + */ + + sc->sc_resources.io_rid[1] = 1; + + if(!(sc->sc_resources.io_base[1] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[1], + 0UL, ~0UL, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get io area 1 for Creatix / Teles PnP!\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* remember the io base addresses */ + + iobase1 = rman_get_start(sc->sc_resources.io_base[0]); + iobase2 = rman_get_start(sc->sc_resources.io_base[1]); + + /* + * because overlapping resources are invalid, + * release the first io port resource + */ + + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + + /* set and allocate a base io address for the ISAC chip */ + + sc->sc_resources.io_rid[2] = 2; + + bus_set_resource(dev, SYS_RES_IOPORT, 2, iobase1-0x20, 0x40); + + if(!(sc->sc_resources.io_base[2] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[2], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get io area 2 for Creatix / Teles PnP!\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* + * because overlapping resources are invalid, + * release the second io port resource + */ + + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[1], + sc->sc_resources.io_base[1]); + + /* set and allocate a resource for the HSCX channel A */ + + sc->sc_resources.io_rid[3] = 3; + +/*XXX*/ /* FIXME !!!! + * the width of the resource is too small, there are accesses + * to it with an offset of 0x3e into the next resource. anyway, + * it seems to work and i have no idea how to do 2 resources + * overlapping each other. + */ + +#if 0 + bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x20); +#else + bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x10); +#endif + + if(!(sc->sc_resources.io_base[3] = + bus_alloc_resource(dev,SYS_RES_IOPORT, + &sc->sc_resources.io_rid[3], + 0ul,~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get io area 3 for Creatix / Teles PnP!\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* set and allocate a resources for the HSCX channel B */ + + sc->sc_resources.io_rid[4] = 4; + + bus_set_resource(dev, SYS_RES_IOPORT, 4, iobase2, 0x40); + + if(!(sc->sc_resources.io_base[4] = + bus_alloc_resource(dev,SYS_RES_IOPORT, + &sc->sc_resources.io_rid[4], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get io area 4 for Creatix / Teles PnP!\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = ctxs0P_read_reg; + sc->writereg = ctxs0P_write_reg; + + sc->readfifo = ctxs0P_read_fifo; + sc->writefifo = ctxs0P_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_CS0P; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* enable the card */ + + t = rman_get_bustag(sc->sc_resources.io_base[2]); + h = rman_get_bushandle(sc->sc_resources.io_base[2]); + + bus_space_write_1(t, h, 0x3c, 0); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0x3c, 1); + DELAY(SEC_DELAY / 10); + + return 0; +} + +#endif /* (NISIC > 0) && (defined(CRTX_S0_P) || defined(TEL_S0_16_3_P)) */ + diff --git a/sys/i4b/layer1/isic/i4b_diva.c b/sys/i4b/layer1/isic/i4b_diva.c new file mode 100644 index 000000000000..0177961653ff --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_diva.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2001 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. + * + *--------------------------------------------------------------------------- + * + * Eicon Diehl DIVA 2.0 or 2.02 (ISA PnP) support for isic driver + * -------------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Fri Jan 26 13:57:10 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined EICON_DIVA + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_ipac.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/* offsets from base address */ + +#define DIVA_IPAC_OFF_ALE 0x00 +#define DIVA_IPAC_OFF_RW 0x01 + +#define DIVA_ISAC_OFF_RW 0x02 +#define DIVA_ISAC_OFF_ALE 0x06 + +#define DIVA_HSCX_OFF_RW 0x00 +#define DIVA_HSCX_OFF_ALE 0x04 + +#define DIVA_CTRL_OFF 0x07 +#define DIVA_CTRL_RDIST 0x01 +#define DIVA_CTRL_WRRST 0x08 +#define DIVA_CTRL_WRLDA 0x20 +#define DIVA_CTRL_WRLDB 0x40 +#define DIVA_CTRL_WRICL 0x80 + +/* HSCX channel base offsets */ + +#define DIVA_HSCXA 0x00 +#define DIVA_HSCXB 0x40 + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.02 + *---------------------------------------------------------------------------*/ +static void +diva_ipac_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_ISAC_OFF); + bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.02 + *---------------------------------------------------------------------------*/ +static void +diva_ipac_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_ISAC_OFF); + bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_write_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.02 + *---------------------------------------------------------------------------*/ +static void +diva_ipac_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_ISAC_OFF); + bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXA_OFF); + bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXB_OFF); + bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_IPAC_OFF); + bus_space_write_1(t,h,DIVA_IPAC_OFF_RW,data); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.02 + *---------------------------------------------------------------------------*/ +static u_int8_t +diva_ipac_read_reg(struct l1_softc *sc,int what,bus_size_t reg) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_ISAC_OFF); + return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXA_OFF); + return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_HSCXB_OFF); + return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW); + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,reg+IPAC_IPAC_OFF); + return bus_space_read_1(t,h,DIVA_IPAC_OFF_RW); + default: + return 0; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.02 + *---------------------------------------------------------------------------*/ +int +isic_attach_diva_ipac(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = diva_ipac_read_reg; + sc->writereg = diva_ipac_write_reg; + + sc->readfifo = diva_ipac_read_fifo; + sc->writefifo = diva_ipac_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* enable hscx/isac irq's */ + + IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */ + + IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */ + (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2)); + + IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */ + + return(0); +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.0 + *---------------------------------------------------------------------------*/ +static void +diva_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,0); + bus_space_read_multi_1(t,h,DIVA_ISAC_OFF_RW,buf,size); + break; + + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXA); + bus_space_read_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size); + break; + + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXB); + bus_space_read_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.0 + *---------------------------------------------------------------------------*/ +static void +diva_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,0); + bus_space_write_multi_1(t,h,DIVA_ISAC_OFF_RW,buf,size); + break; + + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXA); + bus_space_write_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size); + break; + + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,DIVA_HSCXB); + bus_space_write_multi_1(t,h,DIVA_HSCX_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.0 + *---------------------------------------------------------------------------*/ +static void +diva_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,reg); + bus_space_write_1(t,h,DIVA_ISAC_OFF_RW,data); + break; + + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXA); + bus_space_write_1(t,h,DIVA_HSCX_OFF_RW,data); + break; + + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXB); + bus_space_write_1(t,h,DIVA_HSCX_OFF_RW,data); + break; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.0 + *---------------------------------------------------------------------------*/ +static u_int8_t +diva_read_reg(struct l1_softc *sc,int what,bus_size_t reg) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,DIVA_ISAC_OFF_ALE,reg); + return bus_space_read_1(t,h,DIVA_ISAC_OFF_RW); + + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXA); + return bus_space_read_1(t,h,DIVA_HSCX_OFF_RW); + + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,DIVA_HSCX_OFF_ALE,reg+DIVA_HSCXB); + return bus_space_read_1(t,h,DIVA_HSCX_OFF_RW); + + default: + return 0; + } +} + +/*---------------------------------------------------------------------------* + * Eicon Diehl DIVA 2.0 + *---------------------------------------------------------------------------*/ +int +isic_attach_diva(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = diva_read_reg; + sc->writereg = diva_write_reg; + + sc->readfifo = diva_read_fifo; + sc->writefifo = diva_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = ISAC/HSCX */ + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Eicon DIVA 2.0\n", + sc->sc_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(1, H_VSTR)); + return ENXIO; + } + /* reset on */ + bus_space_write_1(t,h,DIVA_CTRL_OFF,0); + DELAY(100); + /* reset off */ + bus_space_write_1(t,h,DIVA_CTRL_OFF,DIVA_CTRL_WRRST); + return(0); +} + +#endif /* NISIC > 0 && defined EICON_DIVA */ diff --git a/sys/i4b/layer1/isic/i4b_drn_ngo.c b/sys/i4b/layer1/isic/i4b_drn_ngo.c new file mode 100644 index 000000000000..ae9b58980fd6 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_drn_ngo.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod + * -------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:07:44 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined(DRN_NGO) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * Niccy GO@ definitions + * + * the card uses 2 i/o addressranges each using 2 bytes + * + * addressrange 0: + * offset 0 - ISAC dataregister + * offset 1 - HSCX dataregister + * addressrange 1: + * offset 0 - ISAC addressregister + * offset 1 - HSCX addressregister + * + * to access an ISAC/HSCX register, you have to write the register + * number into the ISAC or HSCX addressregister and then read/write + * data for the ISAC/HSCX register into/from the corresponding + * dataregister. + * + * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving + * out this information! + * + *---------------------------------------------------------------------------*/ +#define NICCY_PORT_MIN 0x200 +#define NICCY_PORT_MAX 0x3e0 + +#define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */ +#define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */ + +#define HSCX_BOFF 0x40 + +#define ADDR_OFF 2 /* address register range offset */ + +#define ISAC_DATA 0 +#define HSCX_DATA 1 + +#define ISAC_ADDR 0 +#define HSCX_ADDR 1 + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ read fifo routine + *---------------------------------------------------------------------------*/ +static void +drnngo_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t tdata, tadr; + bus_space_handle_t hdata, hadr; + + tdata = rman_get_bustag(sc->sc_resources.io_base[0]); + hdata = rman_get_bushandle(sc->sc_resources.io_base[0]); + tadr = rman_get_bustag(sc->sc_resources.io_base[1]); + hadr = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1 (tadr ,hadr, ISAC_ADDR,0x0); + bus_space_read_multi_1(tdata,hdata,ISAC_DATA,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,0x0); + bus_space_read_multi_1(tdata,hdata,HSCX_DATA,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,HSCX_BOFF); + bus_space_read_multi_1(tdata,hdata,HSCX_DATA,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ write fifo routine + *---------------------------------------------------------------------------*/ +static void +drnngo_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t tdata, tadr; + bus_space_handle_t hdata, hadr; + + tdata = rman_get_bustag(sc->sc_resources.io_base[0]); + hdata = rman_get_bushandle(sc->sc_resources.io_base[0]); + tadr = rman_get_bustag(sc->sc_resources.io_base[1]); + hadr = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1 (tadr ,hadr, ISAC_ADDR,0x0); + bus_space_write_multi_1(tdata,hdata,ISAC_DATA,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,0x0); + bus_space_write_multi_1(tdata,hdata,HSCX_DATA,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1 (tadr ,hadr ,HSCX_ADDR,HSCX_BOFF); + bus_space_write_multi_1(tdata,hdata,HSCX_DATA,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ write register routine + *---------------------------------------------------------------------------*/ +static void +drnngo_write_reg(struct l1_softc *sc, int what, bus_size_t reg, u_int8_t data) +{ + bus_space_tag_t tdata, tadr; + bus_space_handle_t hdata, hadr; + + tdata = rman_get_bustag(sc->sc_resources.io_base[0]); + hdata = rman_get_bushandle(sc->sc_resources.io_base[0]); + tadr = rman_get_bustag(sc->sc_resources.io_base[1]); + hadr = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(tadr ,hadr, ISAC_ADDR,reg); + bus_space_write_1(tdata,hdata,ISAC_DATA,data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg); + bus_space_write_1(tdata,hdata,HSCX_DATA,data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg+HSCX_BOFF); + bus_space_write_1(tdata,hdata,HSCX_DATA,data); + break; + } +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ read register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +drnngo_read_reg(struct l1_softc *sc, int what, bus_size_t reg) +{ + bus_space_tag_t tdata, tadr; + bus_space_handle_t hdata, hadr; + + tdata = rman_get_bustag(sc->sc_resources.io_base[0]); + hdata = rman_get_bushandle(sc->sc_resources.io_base[0]); + tadr = rman_get_bustag(sc->sc_resources.io_base[1]); + hadr = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(tadr ,hadr, ISAC_ADDR,reg); + return bus_space_read_1(tdata,hdata,ISAC_DATA); + case ISIC_WHAT_HSCXA: + bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg); + return bus_space_read_1(tdata,hdata,HSCX_DATA); + case ISIC_WHAT_HSCXB: + bus_space_write_1(tadr ,hadr ,HSCX_ADDR,reg+HSCX_BOFF); + return bus_space_read_1(tdata,hdata,HSCX_DATA); + default: + return 0; + } +} + +/*---------------------------------------------------------------------------* + * probe for ISA PnP cards + *---------------------------------------------------------------------------*/ +int +isic_attach_drnngo(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + sc->sc_resources.io_rid[1] = 1; + + /* + * this card needs a second io_base, + * free resources if we don't get it + */ + + if(!(sc->sc_resources.io_base[1] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[1], + 0UL, ~0UL, 1, RF_ACTIVE))) + { + printf("isic%d: Failed to get second io base.\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = drnngo_read_reg; + sc->writereg = drnngo_write_reg; + + sc->readfifo = drnngo_read_fifo; + sc->writefifo = drnngo_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_DRNNGO; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + return (0); +} + +#endif /* (NISIC > 0) && defined(DRN_NGO) */ diff --git a/sys/i4b/layer1/isic/i4b_dynalink.c b/sys/i4b/layer1/isic/i4b_dynalink.c new file mode 100644 index 000000000000..3ed0aea3bcbb --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_dynalink.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1998 Martijn Plak. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA + * ================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:08:03 2001] + * + *---------------------------------------------------------------------------*/ + +/* NOTES: + + This driver was written for the Dynalink IS64PH ISDN TA, based on two + Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands. + + model numbers found on (my) card: + IS64PH, TAS100H-N, P/N:89590555, TA200S100045521 + + chips: + Siemens PSB 21525N, HSCX TE V2.1 + Siemens PSB 2186N, ISAC-S TE V1.1 + 95MS14, PNP + + plug-and-play info: + device id "ASU1688" + vendor id 0x88167506 + serial 0x00000044 + i/o port 4 byte alignment, 4 bytes requested, + 10 bit i/o decoding, 0x100-0x3f8 (?) + irq 3,4,5,9,10,11,12,15, high true, edge sensitive + + At the moment I'm writing this Dynalink is replacing this card with + one based on a single Siemens chip (IPAC). It will apparently be sold + under the same model name. + + This driver might also work for Asuscom cards. +*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined(DYNALINK) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/* io address mapping */ +#define ISAC 0 +#define HSCX 1 +#define ADDR 2 + +/* ADDR bits */ +#define ADDRMASK 0x7F +#define RESET 0x80 + +/* HSCX register offsets */ +#define HSCXA 0x00 +#define HSCXB 0x40 + +/* LOW-LEVEL DEVICE ACCESS +*/ + +static void +dynalink_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, 0); + bus_space_read_multi_1(t, h, ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA); + bus_space_read_multi_1(t, h, HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB); + bus_space_read_multi_1(t, h, HSCX, buf, size); + break; + } +} + +static void +dynalink_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, 0); + bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA); + bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB); + bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size); + break; + } +} + +static void +dynalink_write_reg(struct l1_softc *sc, int what, bus_size_t reg, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, reg); + bus_space_write_1(t, h, ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA+reg); + bus_space_write_1(t, h, HSCX, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB+reg); + bus_space_write_1(t, h, HSCX, data); + break; + } +} + +static u_int8_t +dynalink_read_reg(struct l1_softc *sc, int what, bus_size_t reg) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, reg); + return bus_space_read_1(t, h, ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA+reg); + return bus_space_read_1(t, h, HSCX); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB+reg); + return bus_space_read_1(t, h, HSCX); + } + return 0; +} + +/* attach callback routine */ +int +isic_attach_Dyn(device_t dev) +{ + int unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = &l1_sc[unit]; /* pointer to softc */ + + struct i4b_info * info = &(sc->sc_resources); + bus_space_tag_t t = rman_get_bustag(info->io_base[0]); + bus_space_handle_t h = rman_get_bushandle(info->io_base[0]); + + /* fill in l1_softc structure */ + sc->readreg = dynalink_read_reg; + sc->writereg = dynalink_write_reg; + sc->readfifo = dynalink_read_fifo; + sc->writefifo = dynalink_write_fifo; + sc->clearirq = NULL; + sc->sc_cardtyp = CARD_TYPEP_DYNALINK; + sc->sc_bustyp = BUS_TYPE_IOM2; + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Dynalink\n", + sc->sc_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(1, H_VSTR)); + return ENXIO; + } + + /* reset card */ + bus_space_write_1(t,h,ADDR,RESET); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t,h,ADDR,0); + DELAY(SEC_DELAY / 10); + + return 0; +} + +#endif /* (NISIC > 0) && defined(DYNALINK) */ diff --git a/sys/i4b/layer1/isic/i4b_elsa_pcc16.c b/sys/i4b/layer1/isic/i4b_elsa_pcc16.c new file mode 100644 index 000000000000..5fdfe8c6421b --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_elsa_pcc16.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 1999, 2001 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 driver for ELSA MicroLink ISDN/PCC-16 and ELSA PCFpro + * ================================================================ + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:26:33 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined(ELSA_PCC16) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +static void i4b_epcc16_clrirq(struct l1_softc *sc); + +/* masks for register encoded in base addr */ + +#define ELSA_BASE_MASK 0x0ffff +#define ELSA_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ELSA_IDISAC 0x00000 +#define ELSA_IDHSCXA 0x10000 +#define ELSA_IDHSCXB 0x20000 + +/* offsets from base address */ + +#define ELSA_OFF_ISAC 0x00 +#define ELSA_OFF_HSCX 0x02 +#define ELSA_OFF_OFF 0x03 +#define ELSA_OFF_CTRL 0x04 +#define ELSA_OFF_CFG 0x05 +#define ELSA_OFF_TIMR 0x06 +#define ELSA_OFF_IRQ 0x07 + +/* control register (write access) */ + +#define ELSA_CTRL_LED_YELLOW 0x02 +#define ELSA_CTRL_LED_GREEN 0x08 +#define ELSA_CTRL_RESET 0x20 +#define ELSA_CTRL_TIMEREN 0x80 +#define ELSA_CTRL_SECRET 0x50 + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCC-16 clear IRQ routine + *---------------------------------------------------------------------------*/ +static void +i4b_epcc16_clrirq(struct l1_softc *sc) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0); +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCC-16 ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +epcc16_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCC-16 ISAC put fifo routine + *---------------------------------------------------------------------------*/ +static void +epcc16_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCC-16 ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +epcc16_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCC-16 ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +epcc16_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + } + return 0; +} + +/*---------------------------------------------------------------------------* + * isic_detach_Epcc16 - detach for ELSA MicroLink ISDN/PCC-16 + *---------------------------------------------------------------------------*/ +static void +isic_detach_Epcc16(device_t dev) +{ + struct l1_softc *sc = &l1_sc[device_get_unit(dev)]; + + if ( sc->sc_resources.irq ) + { + bus_teardown_intr(dev,sc->sc_resources.irq, + (void(*)(void *))isicintr); + bus_release_resource(dev,SYS_RES_IRQ, + sc->sc_resources.irq_rid, + sc->sc_resources.irq); + sc->sc_resources.irq = 0; + } + + if ( sc->sc_resources.io_base[0] ) { + bus_release_resource(dev,SYS_RES_IOPORT, + sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + sc->sc_resources.io_base[0] = 0; + } +} + +/*---------------------------------------------------------------------------* + * isic_probe_Epcc16 - probe for ELSA MicroLink ISDN/PCC-16 + *---------------------------------------------------------------------------*/ +int +isic_probe_Epcc16(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ + + /* check max unit range */ + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA PCC-16!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get iobase for ELSA PCC-16.\n", + unit); + return(ENXIO); + } + + /* check if we got an iobase */ + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + + switch(sc->sc_port) + { + case 0x160: + case 0x170: + case 0x260: + case 0x360: + break; + default: + printf("isic%d: Error, invalid iobase 0x%x specified for ELSA MicroLink ISDN/PCC-16!\n", + unit, sc->sc_port); + isic_detach_Epcc16(dev); + return(ENXIO); + break; + } + + /* setup access routines */ + + sc->clearirq = i4b_epcc16_clrirq; + sc->readreg = epcc16_read_reg; + sc->writereg = epcc16_write_reg; + + sc->readfifo = epcc16_read_fifo; + sc->writefifo = epcc16_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* + * Read HSCX A/B VSTR. Expected value for the ELSA PCC-16 + * is 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + /* patch from "Doobee R . Tzeck" <drt@ailis.de>: + * I own an ELSA PCFpro. To my knowledge, the ELSA PCC16 is + * a stripped down Version on the PCFpro. By patching the + * card detection routine for the PPC16 I was able to use + * the PPC16 driver for the PCFpro. + */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x85) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x85) ) + { + printf("isic%d: HSCX VSTR test failed for ELSA MicroLink ISDN/PCC-16\n", + unit); + isic_detach_Epcc16(dev); + printf("isic%d: HSC0: VSTR: %#x\n", + unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + unit, HSCX_READ(1, H_VSTR)); + return (ENXIO); + } + else + { + printf("isic%d: ELSA MicroLink ISDN/PCFpro found, going to tread it as PCC-16\n", + unit); + } + } + + /* get our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get an irq.\n",unit); + isic_detach_Epcc16(dev); + return ENXIO; + } + + /* get the irq number */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* check IRQ validity */ + switch(sc->sc_irq) + { + case 2: + case 9: + case 3: + case 5: + case 10: + case 11: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for ELSA MicroLink ISDN/PCC-16!\n", + unit, sc->sc_irq); + isic_detach_Epcc16(dev); + return(ENXIO); + break; + } + + /* register interupt routine */ + bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc,&ih); + + + return (0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_Epcc16 - attach for ELSA MicroLink ISDN/PCC-16 + *---------------------------------------------------------------------------*/ +int +isic_attach_Epcc16(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + u_char byte = ELSA_CTRL_SECRET; + + byte &= ~ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + DELAY(20); + byte |= ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + + DELAY(20); + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff); + + return 0; +} + +#endif /* (NISIC > 0) && defined(ELSA_PCC16) */ diff --git a/sys/i4b/layer1/isic/i4b_elsa_qs1i.c b/sys/i4b/layer1/isic/i4b_elsa_qs1i.c new file mode 100644 index 000000000000..9b184e90992e --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_elsa_qs1i.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA + * ===================================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:09:03 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined(ELSA_QS1ISA) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +static void i4b_eq1i_clrirq(struct l1_softc *sc); + +/* masks for register encoded in base addr */ + +#define ELSA_BASE_MASK 0x0ffff +#define ELSA_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ELSA_IDISAC 0x00000 +#define ELSA_IDHSCXA 0x10000 +#define ELSA_IDHSCXB 0x20000 + +/* offsets from base address */ + +#define ELSA_OFF_ISAC 0x00 +#define ELSA_OFF_HSCX 0x02 +#define ELSA_OFF_OFF 0x03 +#define ELSA_OFF_CTRL 0x04 +#define ELSA_OFF_CFG 0x05 +#define ELSA_OFF_TIMR 0x06 +#define ELSA_OFF_IRQ 0x07 + +/* control register (write access) */ + +#define ELSA_CTRL_LED_YELLOW 0x02 +#define ELSA_CTRL_LED_GREEN 0x08 +#define ELSA_CTRL_RESET 0x20 +#define ELSA_CTRL_TIMEREN 0x80 +#define ELSA_CTRL_SECRET 0x50 + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA clear IRQ routine + *---------------------------------------------------------------------------*/ +static void +i4b_eq1i_clrirq(struct l1_softc *sc) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0); +} + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +eqs1pi_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC put fifo routine + *---------------------------------------------------------------------------*/ +static void +eqs1pi_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +eqs1pi_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +eqs1pi_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + } + return 0; +} + +/*---------------------------------------------------------------------------* + * isic_attach_Eqs1pi - attach for ELSA QuickStep 1000pro/ISA + *---------------------------------------------------------------------------*/ +int +isic_attach_Eqs1pi(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + u_char byte = ELSA_CTRL_SECRET; + + /* setup access routines */ + + sc->clearirq = i4b_eq1i_clrirq; + sc->readreg = eqs1pi_read_reg; + sc->writereg = eqs1pi_write_reg; + + sc->readfifo = eqs1pi_read_fifo; + sc->writefifo = eqs1pi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* enable the card */ + + byte &= ~ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + DELAY(20); + byte |= ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + + DELAY(20); + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff); + + return 0; +} +#endif /* (NISIC > 0) && defined(ELSA_QS1ISA) */ diff --git a/sys/i4b/layer1/isic/i4b_elsa_qs1p.c b/sys/i4b/layer1/isic/i4b_elsa_qs1p.c new file mode 100644 index 000000000000..88caee710a7e --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_elsa_qs1p.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for ELSA MicroLink ISDN/PCI + * ================================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:09:28 2001] + * + * Note: ELSA Quickstep 1000pro PCI = ELSA MicroLink ISDN/PCI + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" +#include "pci.h" + +#if (NISIC > 0) && (NPCI > 0) && defined(ELSA_QS1PCI) + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/bus.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_ipac.h> + +#define MEM0_MAPOFF 0 +#define PORT0_MAPOFF 4 +#define PORT1_MAPOFF 12 + +#define ELSA_PORT0_MAPOFF (PCIR_MAPS+PORT0_MAPOFF) +#define ELSA_PORT1_MAPOFF (PCIR_MAPS+PORT1_MAPOFF) + +#define PCI_QS1000_DID 0x1000 +#define PCI_QS1000_VID 0x1048 + +/* masks for register encoded in base addr */ + +#define ELSA_BASE_MASK 0x0ffff +#define ELSA_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ELSA_IDISAC 0x00000 +#define ELSA_IDHSCXA 0x10000 +#define ELSA_IDHSCXB 0x20000 +#define ELSA_IDIPAC 0x40000 + +/* offsets from base address */ + +#define ELSA_OFF_ALE 0x00 +#define ELSA_OFF_RW 0x01 + + +static int eqs1p_pci_probe(device_t dev); +static int eqs1p_pci_attach(device_t dev); + +static device_method_t eqs1p_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, eqs1p_pci_probe), + DEVMETHOD(device_attach, eqs1p_pci_attach), + { 0, 0 } +}; + +static driver_t eqs1p_pci_driver = { + "isic", + eqs1p_pci_methods, + 0 +}; + +static devclass_t eqs1p_pci_devclass; + +DRIVER_MODULE(eqs1p, pci, eqs1p_pci_driver, eqs1p_pci_devclass, 0, 0); + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCI fifo read routine + *---------------------------------------------------------------------------*/ +static void +eqs1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCI fifo write routine + *---------------------------------------------------------------------------*/ +static void +eqs1pp_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCI register write routine + *---------------------------------------------------------------------------*/ +static void +eqs1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + } +} + +/*---------------------------------------------------------------------------* + * ELSA MicroLink ISDN/PCI register read routine + *---------------------------------------------------------------------------*/ +static u_int8_t +eqs1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[1]); + + switch(what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_IPAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + } + return 0; +} + +/*---------------------------------------------------------------------------* + * avma1pp_probe - probe for a card + *---------------------------------------------------------------------------*/ +static int +eqs1p_pci_probe(device_t dev) +{ + if((pci_get_vendor(dev) == PCI_QS1000_VID) && + (pci_get_device(dev) == PCI_QS1000_DID)) + { + device_set_desc(dev, "ELSA MicroLink ISDN/PCI"); + return(0); + } + return(ENXIO); +} + +/*---------------------------------------------------------------------------* + * isic_attach_Eqs1pp - attach for ELSA MicroLink ISDN/PCI + *---------------------------------------------------------------------------*/ +static int +eqs1p_pci_attach(device_t dev) +{ + bus_space_tag_t t; + bus_space_handle_t h; + struct l1_softc *sc; + void *ih = 0; + int unit = device_get_unit(dev); + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA MicroLink ISDN/PCI!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get softc */ + + sc->sc_unit = unit; + + /* get io_base */ + + sc->sc_resources.io_rid[0] = ELSA_PORT0_MAPOFF; + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0UL, ~0UL, 1, RF_ACTIVE))) + { + printf("isic%d: Couldn't get first iobase for ELSA MicroLink ISDN/PCI!\n", unit); + return(ENXIO); + } + + sc->sc_resources.io_rid[1] = ELSA_PORT1_MAPOFF; + + if(!(sc->sc_resources.io_base[1] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[1], + 0UL, ~0UL, 1, RF_ACTIVE))) + { + printf("isic%d: Couldn't get second iobase for ELSA MicroLink ISDN/PCI!\n", unit); + isic_detach_common(dev); + return(ENXIO); + } + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[1]); + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0UL, ~0UL, 1, RF_ACTIVE | RF_SHAREABLE))) + { + printf("isic%d: Could not get irq for ELSA MicroLink ISDN/PCI!\n",unit); + isic_detach_common(dev); + return(ENXIO); + } + + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = eqs1pp_read_reg; + sc->writereg = eqs1pp_write_reg; + + sc->readfifo = eqs1pp_read_fifo; + sc->writefifo = eqs1pp_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + if(isic_attach_common(dev)) + { + isic_detach_common(dev); + return(ENXIO); + } + + if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET, + (void(*)(void*))isicintr, + sc, &ih)) + { + printf("isic%d: Couldn't set up irq for ELSA MicroLink ISDN/PCI!\n", unit); + isic_detach_common(dev); + return(ENXIO); + } + + /* enable hscx/isac irq's */ + + IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */ + IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */ + (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2)); + IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */ + + t = rman_get_bustag(sc->sc_resources.io_base[0]); + h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + bus_space_write_1(t, h, 0x4c, 0x41); /* enable card interrupt */ + + return(0); +} + +#endif /* (NISIC > 0) && (NPCI > 0) && defined(ELSA_QS1PCI) */ diff --git a/sys/i4b/layer1/isic/i4b_hscx.c b/sys/i4b/layer1/isic/i4b_hscx.c new file mode 100644 index 000000000000..cac4a13650b6 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_hscx.c @@ -0,0 +1,663 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b - Siemens HSCX chip (B-channel) handling + * -------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:09:42 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> + +/*---------------------------------------------------------------------------* + * HSCX IRQ Handler + *---------------------------------------------------------------------------*/ +void +isic_hscx_irq(register struct l1_softc *sc, u_char ista, int h_chan, u_char ex_irq) +{ + register l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; + u_char exir = 0; + int activity = -1; + u_char cmd = 0; + + NDBGL1(L1_H_IRQ, "%#x", ista); + + if(ex_irq) + { + /* get channel extended irq reg */ + + exir = HSCX_READ(h_chan, H_EXIR); + + if(exir & HSCX_EXIR_RFO) + { + chan->stat_RFO++; + NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow"); + } + + if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */ + { + chan->stat_XDU++; + NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun"); + isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES); + + if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */ + { + i4b_Bfreembuf(chan->out_mbuf_head); + chan->out_mbuf_cur = chan->out_mbuf_head = NULL; + } + } + + } + + /* rx message end, end of frame */ + + if(ista & HSCX_ISTA_RME) + { + register int fifo_data_len; + u_char rsta; + int error = 0; + + rsta = HSCX_READ(h_chan, H_RSTA); + + if((rsta & 0xf0) != 0xa0) + { + if((rsta & HSCX_RSTA_VFR) == 0) + { + chan->stat_VFR++; + cmd |= (HSCX_CMDR_RHR); + NDBGL1(L1_H_XFRERR, "received invalid Frame"); + error++; + } + + if(rsta & HSCX_RSTA_RDO) + { + chan->stat_RDO++; + NDBGL1(L1_H_XFRERR, "receive data overflow"); + error++; + } + + if((rsta & HSCX_RSTA_CRC) == 0) + { + chan->stat_CRC++; + cmd |= (HSCX_CMDR_RHR); + NDBGL1(L1_H_XFRERR, "CRC check failed"); + error++; + } + + if(rsta & HSCX_RSTA_RAB) + { + chan->stat_RAB++; + NDBGL1(L1_H_XFRERR, "Receive message aborted"); + error++; + } + } + + fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) & + ((sc->sc_bfifolen)-1)); + + if(fifo_data_len == 0) + fifo_data_len = sc->sc_bfifolen; + + /* all error conditions checked, now decide and take action */ + + if(error == 0) + { + if(chan->in_mbuf == NULL) + { + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n"); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + } + + fifo_data_len -= 1; /* last byte in fifo is RSTA ! */ + + if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN) + { + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len); + + cmd |= (HSCX_CMDR_RMC); + isic_hscx_cmd(sc, h_chan, cmd); + cmd = 0; + + chan->in_len += fifo_data_len; + chan->rxcount += fifo_data_len; + + /* setup mbuf data length */ + + chan->in_mbuf->m_len = chan->in_len; + chan->in_mbuf->m_pkthdr.len = chan->in_len; + + if(sc->sc_trace & TRACE_B_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); + } + + (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit); + + activity = ACT_RX; + + /* mark buffer ptr as unused */ + + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + else + { + NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC); + } + } + else + { + if (chan->in_mbuf != NULL) + { + i4b_Bfreembuf(chan->in_mbuf); + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + cmd |= (HSCX_CMDR_RMC); + } + } + + /* rx fifo full */ + + if(ista & HSCX_ISTA_RPF) + { + if(chan->in_mbuf == NULL) + { + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n"); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + } + + chan->rxcount += sc->sc_bfifolen; + + if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN) + { + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen); + + chan->in_cbptr += sc->sc_bfifolen; + chan->in_len += sc->sc_bfifolen; + } + else + { + if(chan->bprot == BPROT_NONE) + { + /* setup mbuf data length */ + + chan->in_mbuf->m_len = chan->in_len; + chan->in_mbuf->m_pkthdr.len = chan->in_len; + + if(sc->sc_trace & TRACE_B_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); + } + + /* silence detection */ + + if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len))) + activity = ACT_RX; + +#if defined (__FreeBSD__) && __FreeBSD__ > 4 + (void) IF_HANDOFF(&chan->rx_queue, chan->in_mbuf, NULL); +#else + if(!(IF_QFULL(&chan->rx_queue))) + { + IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf); + } + else + { + i4b_Bfreembuf(chan->in_mbuf); + } +#endif + /* signal upper driver that data is available */ + + (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit); + + /* alloc new buffer */ + + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n"); + + /* setup new data ptr */ + + chan->in_cbptr = chan->in_mbuf->m_data; + + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen); + + chan->in_cbptr += sc->sc_bfifolen; + chan->in_len = sc->sc_bfifolen; + + chan->rxcount += sc->sc_bfifolen; + } + else + { + NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + cmd |= (HSCX_CMDR_RHR); + } + } + + /* command to release fifo space */ + + cmd |= HSCX_CMDR_RMC; + } + + /* transmit fifo empty, new data can be written to fifo */ + + if(ista & HSCX_ISTA_XPR) + { + /* + * for a description what is going on here, please have + * a look at isic_bchannel_start() in i4b_bchan.c ! + */ + + int activity = -1; + int len; + int nextlen; + + NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan); + + if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */ + { + IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); + + if(chan->out_mbuf_head == NULL) + { + chan->state &= ~HSCX_TX_ACTIVE; + (*chan->isic_drvr_linktab->bch_tx_queue_empty)(chan->isic_drvr_linktab->unit); + } + else + { + chan->state |= HSCX_TX_ACTIVE; + chan->out_mbuf_cur = chan->out_mbuf_head; + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + + if(chan->bprot == BPROT_NONE) + { + if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) + activity = ACT_TX; + } + else + { + activity = ACT_TX; + } + } + } + + len = 0; + + while(chan->out_mbuf_cur && len != sc->sc_bfifolen) + { + nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len); + +#ifdef NOTDEF + printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ", + chan->out_mbuf_head, + chan->out_mbuf_cur, + chan->out_mbuf_cur_ptr, + chan->out_mbuf_cur_len, + len, + next_len); +#endif + + isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */ + + HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen); + cmd |= HSCX_CMDR_XTF; + + len += nextlen; + chan->txcount += nextlen; + + chan->out_mbuf_cur_ptr += nextlen; + chan->out_mbuf_cur_len -= nextlen; + + if(chan->out_mbuf_cur_len == 0) + { + if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL) + { + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + } + else + { + if (chan->bprot != BPROT_NONE) + cmd |= HSCX_CMDR_XME; + i4b_Bfreembuf(chan->out_mbuf_head); + chan->out_mbuf_head = NULL; + } + + } + } + } + + if(cmd) /* is there a command for the HSCX ? */ + { + isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */ + } + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity); +} + +/*---------------------------------------------------------------------------* + * HSCX initialization + * + * for telephony: extended transparent mode 1 + * for raw hdlc: transparent mode 0 + *---------------------------------------------------------------------------*/ +void +isic_hscx_init(struct l1_softc *sc, int h_chan, int activate) +{ + l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; + + HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */ + + if(sc->sc_ipac) + { + /* CCR1: Power Up, Clock Mode 5 */ + HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */ + HSCX_CCR1_CM1); /* IPAC clock mode 5 */ + } + else + { + /* CCR1: Power Up, Clock Mode 5 */ + HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */ + HSCX_CCR1_CM2 | /* HSCX clock mode 5 */ + HSCX_CCR1_CM0); + } + + /* XAD1: Transmit Address Byte 1 */ + HSCX_WRITE(h_chan, H_XAD1, 0xff); + + /* XAD2: Transmit Address Byte 2 */ + HSCX_WRITE(h_chan, H_XAD2, 0xff); + + /* RAH2: Receive Address Byte High Reg. 2 */ + HSCX_WRITE(h_chan, H_RAH2, 0xff); + + /* XBCH: reset Transmit Byte Count High */ + HSCX_WRITE(h_chan, H_XBCH, 0x00); + + /* RLCR: reset Receive Length Check Register */ + HSCX_WRITE(h_chan, H_RLCR, 0x00); + + /* CCR2: set tx/rx clock shift bit 0 */ + /* disable CTS irq, disable RIE irq*/ + HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0); + + /* XCCR: tx bit count per time slot */ + HSCX_WRITE(h_chan, H_XCCR, 0x07); + + /* RCCR: rx bit count per time slot */ + HSCX_WRITE(h_chan, H_RCCR, 0x07); + + if(sc->sc_bustyp == BUS_TYPE_IOM2) + { + switch(h_chan) + { + case HSCX_CH_A: /* Prepare HSCX channel A */ + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x2f); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x2f); + break; + + case HSCX_CH_B: /* Prepare HSCX channel B */ + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x03); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x03); + break; + } + } + else /* IOM 1 setup */ + { + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x07); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x07); + } + + if(activate) + { + if(chan->bprot == BPROT_RHDLC) + { + /* HDLC Frames, transparent mode 0 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS); + } + else + { + /* Raw Telephony, extended transparent mode 1 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS); + } +#if 0 + isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES); +#else + isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR); +#endif + } + else + { + /* TSAX: tx time slot */ + HSCX_WRITE(h_chan, H_TSAX, 0xff); + + /* TSAR: rx time slot */ + HSCX_WRITE(h_chan, H_TSAR, 0xff); + + /* Raw Telephony, extended transparent mode 1 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS); + } + + /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */ + /* always disable RSC and TIN */ + + chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN; + + if(activate) + { + /* enable */ + chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR); + } + else + { + /* disable */ + chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR; + } + + /* handle ICA, EXA, and EXB via interrupt mask of channel b */ + + if (h_chan == HSCX_CH_A) + { + if (activate) + HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA); + else + HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA; + HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } + else + { + if (activate) + HSCX_B_IMASK &= ~HSCX_MASK_EXB; + else + HSCX_B_IMASK |= HSCX_MASK_EXB; + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } + + /* clear spurious interrupts left over */ + + if(h_chan == HSCX_CH_A) + { + HSCX_READ(h_chan, H_EXIR); + HSCX_READ(h_chan, H_ISTA); + } + else /* mask ICA, because it must not be cleared by reading ISTA */ + { + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA); + HSCX_READ(h_chan, H_EXIR); + HSCX_READ(h_chan, H_ISTA); + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } +} + +/*---------------------------------------------------------------------------* + * write command to HSCX command register + *---------------------------------------------------------------------------*/ +void +isic_hscx_cmd(struct l1_softc *sc, int h_chan, unsigned char cmd) +{ + int timeout = 20; + + while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout) + { + DELAY(10); + timeout--; + } + + if(timeout == 0) + { + NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!"); + } + + HSCX_WRITE(h_chan, H_CMDR, cmd); +} + +/*---------------------------------------------------------------------------* + * wait for HSCX transmit FIFO write enable + *---------------------------------------------------------------------------*/ +void +isic_hscx_waitxfw(struct l1_softc *sc, int h_chan) +{ +#define WAITVAL 50 +#define WAITTO 200 + + int timeout = WAITTO; + + while((!(((HSCX_READ(h_chan, H_STAR)) & + (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout) + { + DELAY(WAITVAL); + timeout--; + } + + if(timeout == 0) + { + NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!"); + } + else if (timeout != WAITTO) + { + NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50); + } +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_hscx.h b/sys/i4b/layer1/isic/i4b_hscx.h new file mode 100644 index 000000000000..d65d2fcfe82c --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_hscx.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1996, 2000 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:09:51 2001] + * + *---------------------------------------------------------------------------*/ + +#ifndef I4B_HSCX_H_ +#define I4B_HSCX_H_ + +enum HSCX_VERSIONS { + HSCX_VA1, /* 82525 A1 */ + HSCX_UNKN1, /* unknown 1 */ + HSCX_VA2, /* 82525 A2 */ + HSCX_UNKN3, /* unknown 3 */ + HSCX_VA3, /* 82525 A3 */ + HSCX_V21, /* 82525 2.1 */ + HSCX_UNKN /* unknown version */ +}; + +#define HSCX_CH_A 0 /* channel A */ +#define HSCX_CH_B 1 /* channel B */ + +#define HSCX_FIFO_LEN 32 /* 32 bytes FIFO on chip */ + +/* + * definitions of registers and bits for the HSCX ISDN chip. + */ + +typedef struct hscx_reg { + + /* 32 byte deep FIFO always first */ + + unsigned char hscx_fifo [HSCX_FIFO_LEN]; + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char hscx_ista; + unsigned char hscx_star; + unsigned char hscx_mode; + unsigned char hscx_timr; + unsigned char hscx_exir; + unsigned char hscx_rbcl; + unsigned char dummy_26; + unsigned char hscx_rsta; + unsigned char hscx_ral1; + unsigned char hscx_rhcr; + unsigned char dummy_2a; + unsigned char dummy_2b; + unsigned char hscx_ccr2; + unsigned char hscx_rbch; + unsigned char hscx_vstr; + unsigned char hscx_ccr; + unsigned char dummy_30; + unsigned char dummy_31; + unsigned char dummy_32; + unsigned char dummy_33; + } hscx_r; + struct { + unsigned char hscx_mask; + unsigned char hscx_cmdr; + unsigned char hscx_mode; + unsigned char hscx_timr; + unsigned char hscx_xad1; + unsigned char hscx_xad2; + unsigned char hscx_rah1; + unsigned char hscx_rah2; + unsigned char hscx_ral1; + unsigned char hscx_ral2; + unsigned char hscx_xbcl; + unsigned char hscx_bgr; + unsigned char hscx_ccr2; + unsigned char hscx_xbch; + unsigned char hscx_rlcr; + unsigned char hscx_ccr1; + unsigned char hscx_tsax; + unsigned char hscx_tsar; + unsigned char hscx_xccr; + unsigned char hscx_rccr; + } hscx_w; + } hscx_rw; +} hscx_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* HSCX read registers */ + +#define h_ista hscx_rw.hscx_r.hscx_ista +#define H_ISTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ista) +#define h_star hscx_rw.hscx_r.hscx_star +#define H_STAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_star) +#define h_mode hscx_rw.hscx_r.hscx_mode +#define H_MODE REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_mode) +#define h_timr hscx_rw.hscx_r.hscx_timr +#define H_TIMR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_timr) +#define h_exir hscx_rw.hscx_r.hscx_exir +#define H_EXIR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_exir) +#define h_rbcl hscx_rw.hscx_r.hscx_rbcl +#define H_RBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbcl) +#define h_rsta hscx_rw.hscx_r.hscx_rsta +#define H_RSTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rsta) +#define h_ral1 hscx_rw.hscx_r.hscx_ral1 +#define H_RAL1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ral1) +#define h_rhcr hscx_rw.hscx_r.hscx_rhcr +#define H_RHCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rhcr) +#define h_ccr2 hscx_rw.hscx_r.hscx_ccr2 +#define H_CCR2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr2) +#define h_rbch hscx_rw.hscx_r.hscx_rbch +#define H_RBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbch) +#define h_vstr hscx_rw.hscx_r.hscx_vstr +#define H_VSTR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_vstr) +#define h_ccr hscx_rw.hscx_r.hscx_ccr +#define H_CCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr) + +/* HSCX write registers - for hscx_mode, hscx_timr, hscx_ral1, hscx_ccr2 */ +/* see read registers */ + +#define h_mask hscx_rw.hscx_w.hscx_mask +#define H_MASK REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_mask) +#define h_cmdr hscx_rw.hscx_w.hscx_cmdr +#define H_CMDR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_cmdr) +#define h_xad1 hscx_rw.hscx_w.hscx_xad1 +#define H_XAD1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad1) +#define h_xad2 hscx_rw.hscx_w.hscx_xad2 +#define H_XAD2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad2) +#define h_rah1 hscx_rw.hscx_w.hscx_rah1 +#define H_RAH1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah1) +#define h_rah2 hscx_rw.hscx_w.hscx_rah2 +#define H_RAH2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah2) +#define h_ral2 hscx_rw.hscx_w.hscx_ral2 +#define H_RAL2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ral2) +#define h_xbcl hscx_rw.hscx_w.hscx_xbcl +#define H_XBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbcl) +#define h_bgr hscx_rw.hscx_w.hscx_bgr +#define H_BGR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_bgr) +#define h_xbch hscx_rw.hscx_w.hscx_xbch +#define H_XBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbch) +#define h_rlcr hscx_rw.hscx_w.hscx_rlcr +#define H_RLCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rlcr) +#define h_ccr1 hscx_rw.hscx_w.hscx_ccr1 +#define H_CCR1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ccr1) +#define h_tsax hscx_rw.hscx_w.hscx_tsax +#define H_TSAX REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsax) +#define h_tsar hscx_rw.hscx_w.hscx_tsar +#define H_TSAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsar) +#define h_xccr hscx_rw.hscx_w.hscx_xccr +#define H_XCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xccr) +#define h_rccr hscx_rw.hscx_w.hscx_rccr +#define H_RCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rccr) + +#define HSCX_ISTA_RME 0x80 +#define HSCX_ISTA_RPF 0x40 +#define HSCX_ISTA_RSC 0x20 +#define HSCX_ISTA_XPR 0x10 +#define HSCX_ISTA_TIN 0x08 +#define HSCX_ISTA_ICA 0x04 +#define HSCX_ISTA_EXA 0x02 +#define HSCX_ISTA_EXB 0x01 + +#define HSCX_MASK_RME 0x80 +#define HSCX_MASK_RPF 0x40 +#define HSCX_MASK_RSC 0x20 +#define HSCX_MASK_XPR 0x10 +#define HSCX_MASK_TIN 0x08 +#define HSCX_MASK_ICA 0x04 +#define HSCX_MASK_EXA 0x02 +#define HSCX_MASK_EXB 0x01 + +#define HSCX_EXIR_XMR 0x80 +#define HSCX_EXIR_XDU 0x40 +#define HSCX_EXIR_PCE 0x20 +#define HSCX_EXIR_RFO 0x10 +#define HSCX_EXIR_CSC 0x08 +#define HSCX_EXIR_RFS 0x04 + +/* the other bits are always 0 */ + +#define HSCX_STAR_XDOV 0x80 +#define HSCX_STAR_XFW 0x40 +#define HSCX_STAR_XRNR 0x20 +#define HSCX_STAR_RRNR 0x10 +#define HSCX_STAR_RLI 0x08 +#define HSCX_STAR_CEC 0x04 +#define HSCX_STAR_CTS 0x02 +#define HSCX_STAR_WFA 0x01 + +#define HSCX_CMDR_RMC 0x80 +#define HSCX_CMDR_RHR 0x40 +/* also known as XREP in transparent mode */ +#define HSCX_CMDR_RNR 0x20 +#define HSCX_CMDR_STI 0x10 +#define HSCX_CMDR_XTF 0x08 +#define HSCX_CMDR_XIF 0x04 +#define HSCX_CMDR_XME 0x02 +#define HSCX_CMDR_XRES 0x01 + +#define HSCX_MODE_MDS1 0x80 +#define HSCX_MODE_MDS0 0x40 +#define HSCX_MODE_ADM 0x20 +#define HSCX_MODE_TMD 0x10 +#define HSCX_MODE_RAC 0x08 +#define HSCX_MODE_RTS 0x04 +#define HSCX_MODE_TRS 0x02 +#define HSCX_MODE_TLP 0x01 + +#define HSCX_RSTA_VFR 0x80 +#define HSCX_RSTA_RDO 0x40 +#define HSCX_RSTA_CRC 0x20 +#define HSCX_RSTA_RAB 0x10 +#define HSCX_RSTA_HA1 0x08 +#define HSCX_RSTA_HA0 0x04 +#define HSCX_RSTA_CR 0x02 +#define HSCX_RSTA_LA 0x01 + +#define HSCX_RSTA_MASK 0xf0 /* the interesting ones */ + +/* only used in DMA mode */ +#define HSCX_XBCH_DMA 0x80 +#define HSCX_XBCH_NRM 0x40 +#define HSCX_XBCH_CAS 0x20 +#define HSCX_XBCH_XC 0x10 +/* the rest are bits 11 thru 8 of the byte count */ + +#define HSCX_RBCH_DMA 0x80 +#define HSCX_RBCH_NRM 0x40 +#define HSCX_RBCH_CAS 0x20 +#define HSCX_RBCH_OV 0x10 +/* the rest are bits 11 thru 8 of the byte count */ + +#define HSCX_VSTR_CD 0x80 +/* bits 6 thru 4 are 0 */ +/* bits 3 thru 0 are the version number */ + +#define HSCX_RLCR_RC 0x80 +/* the rest of the bits are used to set the received length */ + +#define HSCX_CCR1_PU 0x80 +/* bits 6 and 5 are SC1 SC0 */ +#define HSCX_CCR1_ODS 0x10 +#define HSCX_CCR1_ITF 0x08 +#define HSCX_CCR1_CM2 0x04 +#define HSCX_CCR1_CM1 0x02 +#define HSCX_CCR1_CM0 0x01 + +/* for clock mode 5 */ +#define HSCX_CCR2_SOC2 0x80 +#define HSCX_CCR2_SOC1 0x40 +#define HSCX_CCR2_XCS0 0x20 +#define HSCX_CCR2_RCS0 0x10 +#define HSCX_CCR2_TIO 0x08 +#define HSCX_CCR2_CIE 0x04 +#define HSCX_CCR2_RIE 0x02 +#define HSCX_CCR2_DIV 0x01 + +/* bits 7 thru 2 are TSNX */ +#define HSCX_TSAX_XCS2 0x02 +#define HSCX_TSAX_XCS1 0x01 + +/* bits 7 thru 2 are TSNR */ +#define HSCX_TSAR_RCS2 0x02 +#define HSCX_TSAR_RCS1 0x01 + +#endif /* I4B_HSCX_H_ */ diff --git a/sys/i4b/layer1/isic/i4b_ipac.h b/sys/i4b/layer1/isic/i4b_ipac.h new file mode 100644 index 000000000000..8892288957ca --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_ipac.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ipac.h - definitions for the Siemens IPAC PSB2115 chip + * ========================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:10:09 2001] + * + *--------------------------------------------------------------------------- + */ + +#ifndef _I4B_IPAC_H_ +#define _I4B_IPAC_H_ + +#define IPAC_BFIFO_LEN 64 /* 64 bytes B-channel FIFO on chip */ + +#define IPAC_HSCXA_OFF 0x00 +#define IPAC_HSCXB_OFF 0x40 +#define IPAC_ISAC_OFF 0x80 +#define IPAC_IPAC_OFF 0xc0 + +/* chip version */ + +#define IPAC_V11 0x01 /* IPAC Version 1.1 */ +#define IPAC_V12 0x02 /* IPAC Version 1.2 */ + +/* + * definitions of registers and bits for the IPAC ISDN chip. + */ + +typedef struct ipac_reg { + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char ipac_conf; + unsigned char ipac_ista; + unsigned char ipac_id; + unsigned char ipac_acfg; + unsigned char ipac_aoe; + unsigned char ipac_arx; + unsigned char ipac_pita1; + unsigned char ipac_pita2; + unsigned char ipac_pota1; + unsigned char ipac_pota2; + unsigned char ipac_pcfg; + unsigned char ipac_scfg; + unsigned char ipac_timr2; + } ipac_r; + struct { + unsigned char ipac_conf; + unsigned char ipac_mask; + unsigned char ipac_dummy; + unsigned char ipac_acfg; + unsigned char ipac_aoe; + unsigned char ipac_atx; + unsigned char ipac_pita1; + unsigned char ipac_pita2; + unsigned char ipac_pota1; + unsigned char ipac_pota2; + unsigned char ipac_pcfg; + unsigned char ipac_scfg; + unsigned char ipac_timr2; + } ipac_w; + } ipac_rw; +} ipac_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* IPAC read registers */ + +#define IPAC_CONF REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_conf) +#define IPAC_ISTA REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_ista) +#define IPAC_ID REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_id) +#define IPAC_ACFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_acfg) +#define IPAC_AOE REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_aoe) +#define IPAC_ARX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_arx) +#define IPAC_PITA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita1) +#define IPAC_PITA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita2) +#define IPAC_POTA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota1) +#define IPAC_POTA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota2) +#define IPAC_PCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pcfg) +#define IPAC_SCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_scfg) +#define IPAC_TIMR2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_timr2) + +/* IPAC write registers */ + +#define IPAC_MASK REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_mask) +#define IPAC_ATX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_atx) + +/* register bits */ + +#define IPAC_CONF_AMP 0x80 +#define IPAC_CONF_CFS 0x40 +#define IPAC_CONF_TEM 0x20 +#define IPAC_CONF_PDS 0x10 +#define IPAC_CONF_IDH 0x08 +#define IPAC_CONF_SGO 0x04 +#define IPAC_CONF_ODS 0x02 +#define IPAC_CONF_IOF 0x01 + +#define IPAC_ISTA_INT1 0x80 +#define IPAC_ISTA_INT0 0x40 +#define IPAC_ISTA_ICD 0x20 +#define IPAC_ISTA_EXD 0x10 +#define IPAC_ISTA_ICA 0x08 +#define IPAC_ISTA_EXA 0x04 +#define IPAC_ISTA_ICB 0x02 +#define IPAC_ISTA_EXB 0x01 + +#define IPAC_MASK_INT1 0x80 +#define IPAC_MASK_INT0 0x40 +#define IPAC_MASK_ICD 0x20 +#define IPAC_MASK_EXD 0x10 +#define IPAC_MASK_ICA 0x08 +#define IPAC_MASK_EXA 0x04 +#define IPAC_MASK_ICB 0x02 +#define IPAC_MASK_EXB 0x01 + +#define IPAC_ACFG_OD7 0x80 +#define IPAC_ACFG_OD6 0x40 +#define IPAC_ACFG_OD5 0x20 +#define IPAC_ACFG_OD4 0x10 +#define IPAC_ACFG_OD3 0x08 +#define IPAC_ACFG_OD2 0x04 +#define IPAC_ACFG_EL1 0x02 +#define IPAC_ACFG_EL2 0x01 + +#define IPAC_AOE_OE7 0x80 +#define IPAC_AOE_OE6 0x40 +#define IPAC_AOE_OE5 0x20 +#define IPAC_AOE_OE4 0x10 +#define IPAC_AOE_OE3 0x08 +#define IPAC_AOE_OE2 0x04 + +#define IPAC_ARX_AR7 0x80 +#define IPAC_ARX_AR6 0x40 +#define IPAC_ARX_AR5 0x20 +#define IPAC_ARX_AR4 0x10 +#define IPAC_ARX_AR3 0x08 +#define IPAC_ARX_AR2 0x04 + +#define IPAC_ATX_AT7 0x80 +#define IPAC_ATX_AT6 0x40 +#define IPAC_ATX_AT5 0x20 +#define IPAC_ATX_AT4 0x10 +#define IPAC_ATX_AT3 0x08 +#define IPAC_ATX_AT2 0x04 + +#define IPAC_PITA1_ENA 0x80 +#define IPAC_PITA1_DUDD 0x40 + +#define IPAC_PITA2_ENA 0x80 +#define IPAC_PITA2_DUDD 0x40 + +#define IPAC_POTA1_ENA 0x80 +#define IPAC_POTA1_DUDD 0x40 + +#define IPAC_POTA2_ENA 0x80 +#define IPAC_POTA2_DUDD 0x40 + +#define IPAC_PCFG_DPS 0x80 +#define IPAC_PCFG_ACL 0x40 +#define IPAC_PCFG_LED 0x20 +#define IPAC_PCFG_PLD 0x10 +#define IPAC_PCFG_FBS 0x08 +#define IPAC_PCFG_CSL2 0x04 +#define IPAC_PCFG_CSL1 0x02 +#define IPAC_PCFG_CSL0 0x01 + +#define IPAC_SCFG_PRI 0x80 +#define IPAC_SCFG_TXD 0x40 +#define IPAC_SCFG_TLEN 0x20 + +#define IPAC_TIMR2_TMD 0x80 + +#endif /* _I4B_IPAC_H_ */ diff --git a/sys/i4b/layer1/isic/i4b_isac.c b/sys/i4b/layer1/isic/i4b_isac.c new file mode 100644 index 000000000000..f66aaa0cc6fd --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isac.c @@ -0,0 +1,660 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isac.c - i4b siemens isdn chipset driver ISAC handler + * --------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:10:36 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if NISIC > 0 + +#include "opt_i4b.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_isac.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> + +static u_char isic_isac_exir_hdlr(register struct l1_softc *sc, u_char exir); +static void isic_isac_ind_hdlr(register struct l1_softc *sc, int ind); + +/*---------------------------------------------------------------------------* + * ISAC interrupt service routine + *---------------------------------------------------------------------------*/ +void +isic_isac_irq(struct l1_softc *sc, int ista) +{ + register u_char c = 0; + NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista); + + if(ista & ISAC_ISTA_EXI) /* extended interrupt */ + { + c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR)); + } + + if(ista & ISAC_ISTA_RME) /* receive message end */ + { + register int rest; + u_char rsta; + + /* get rx status register */ + + rsta = ISAC_READ(I_RSTA); + + if((rsta & ISAC_RSTA_MASK) != 0x20) + { + int error = 0; + + if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */ + { + error++; + NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit); + } + + if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */ + { + error++; + NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit); + } + + if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */ + { + error++; + NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit); + } + + if(error == 0) + NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta); + + i4b_Dfreembuf(sc->sc_ibuf); + + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES); + ISACCMDRWRDELAY(); + + return; + } + + rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1)); + + if(rest == 0) + rest = ISAC_FIFO_LEN; + + if(sc->sc_ibuf == NULL) + { + if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL) + sc->sc_ib = sc->sc_ibuf->m_data; + else + panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n"); + sc->sc_ilen = 0; + } + + if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest)) + { + ISAC_RDFIFO(sc->sc_ib, rest); + sc->sc_ilen += rest; + + sc->sc_ibuf->m_pkthdr.len = + sc->sc_ibuf->m_len = sc->sc_ilen; + + if(sc->sc_trace & TRACE_D_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_D; + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data); + } + + c |= ISAC_CMDR_RMC; + + if(sc->sc_enabled && + (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)) + { + i4b_l1_ph_data_ind(L0ISICUNIT(sc->sc_unit), sc->sc_ibuf); + } + else + { + i4b_Dfreembuf(sc->sc_ibuf); + } + } + else + { + NDBGL1(L1_I_ERR, "RME, input buffer overflow!"); + i4b_Dfreembuf(sc->sc_ibuf); + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + } + + if(ista & ISAC_ISTA_RPF) /* receive fifo full */ + { + if(sc->sc_ibuf == NULL) + { + if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL) + sc->sc_ib= sc->sc_ibuf->m_data; + else + panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n"); + sc->sc_ilen = 0; + } + + if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN)) + { + ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN); + sc->sc_ilen += ISAC_FIFO_LEN; + sc->sc_ib += ISAC_FIFO_LEN; + c |= ISAC_CMDR_RMC; + } + else + { + NDBGL1(L1_I_ERR, "RPF, input buffer overflow!"); + i4b_Dfreembuf(sc->sc_ibuf); + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + } + + if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */ + { + if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL)) + { + sc->sc_freeflag = sc->sc_freeflag2; + sc->sc_obuf = sc->sc_obuf2; + sc->sc_op = sc->sc_obuf->m_data; + sc->sc_ol = sc->sc_obuf->m_len; + sc->sc_obuf2 = NULL; +#ifdef NOTDEF + printf("ob2=%x, op=%x, ol=%d, f=%d #", + sc->sc_obuf, + sc->sc_op, + sc->sc_ol, + sc->sc_state); +#endif + } + else + { +#ifdef NOTDEF + printf("ob=%x, op=%x, ol=%d, f=%d #", + sc->sc_obuf, + sc->sc_op, + sc->sc_ol, + sc->sc_state); +#endif + } + + if(sc->sc_obuf) + { + ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN)); + + if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */ + { + sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */ + sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */ + c |= ISAC_CMDR_XTF; /* set XTF bit */ + } + else + { + if(sc->sc_freeflag) + { + i4b_Dfreembuf(sc->sc_obuf); + sc->sc_freeflag = 0; + } + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + + c |= ISAC_CMDR_XTF | ISAC_CMDR_XME; + } + } + else + { + sc->sc_state &= ~ISAC_TX_ACTIVE; + } + } + + if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */ + { + register u_char ci; + + /* get command/indication rx register*/ + + ci = ISAC_READ(I_CIRR); + + /* if S/Q IRQ, read SQC reg to clr SQC IRQ */ + + if(ci & ISAC_CIRR_SQC) + (void) ISAC_READ(I_SQRR); + + /* C/I code change IRQ (flag already cleared by CIRR read) */ + + if(ci & ISAC_CIRR_CIC0) + isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf); + } + + if(c) + { + ISAC_WRITE(I_CMDR, c); + ISACCMDRWRDELAY(); + } +} + +/*---------------------------------------------------------------------------* + * ISAC L1 Extended IRQ handler + *---------------------------------------------------------------------------*/ +static u_char +isic_isac_exir_hdlr(register struct l1_softc *sc, u_char exir) +{ + u_char c = 0; + + if(exir & ISAC_EXIR_XMR) + { + NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat"); + + c |= ISAC_CMDR_XRES; + } + + if(exir & ISAC_EXIR_XDU) + { + NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun"); + + c |= ISAC_CMDR_XRES; + } + + if(exir & ISAC_EXIR_PCE) + { + NDBGL1(L1_I_ERR, "EXIRQ Protocol Error"); + } + + if(exir & ISAC_EXIR_RFO) + { + NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow"); + + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + + if(exir & ISAC_EXIR_SOV) + { + NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow"); + } + + if(exir & ISAC_EXIR_MOS) + { + NDBGL1(L1_I_ERR, "EXIRQ Monitor Status"); + } + + if(exir & ISAC_EXIR_SAW) + { + /* cannot happen, STCR:TSF is set to 0 */ + + NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake"); + } + + if(exir & ISAC_EXIR_WOV) + { + /* cannot happen, STCR:TSF is set to 0 */ + + NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow"); + } + + return(c); +} + +/*---------------------------------------------------------------------------* + * ISAC L1 Indication handler + *---------------------------------------------------------------------------*/ +static void +isic_isac_ind_hdlr(register struct l1_softc *sc, int ind) +{ + register int event; + + switch(ind) + { + case ISAC_CIRR_IAI8: + NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc)); + if(sc->sc_bustyp == BUS_TYPE_IOM2) + isic_isac_l1_cmd(sc, CMD_AR8); + event = EV_INFO48; + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL); + break; + + case ISAC_CIRR_IAI10: + NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc)); + if(sc->sc_bustyp == BUS_TYPE_IOM2) + isic_isac_l1_cmd(sc, CMD_AR10); + event = EV_INFO410; + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL); + break; + + case ISAC_CIRR_IRSY: + NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc)); + event = EV_RSY; + break; + + case ISAC_CIRR_IPU: + NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc)); + event = EV_PU; + break; + + case ISAC_CIRR_IDR: + NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc)); + isic_isac_l1_cmd(sc, CMD_DIU); + event = EV_DR; + break; + + case ISAC_CIRR_IDID: + NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc)); + event = EV_INFO0; + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL); + break; + + case ISAC_CIRR_IDIS: + NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc)); + event = EV_DIS; + break; + + case ISAC_CIRR_IEI: + NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc)); + isic_isac_l1_cmd(sc, CMD_DIU); + event = EV_EI; + break; + + case ISAC_CIRR_IARD: + NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc)); + event = EV_INFO2; + break; + + case ISAC_CIRR_ITI: + NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc)); + event = EV_INFO0; + break; + + case ISAC_CIRR_IATI: + NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc)); + event = EV_INFO0; + break; + + case ISAC_CIRR_ISD: + NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc)); + event = EV_INFO0; + break; + + default: + NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc)); + event = EV_INFO0; + break; + } + isic_next_state(sc, event); +} + +/*---------------------------------------------------------------------------* + * execute a layer 1 command + *---------------------------------------------------------------------------*/ +void +isic_isac_l1_cmd(struct l1_softc *sc, int command) +{ + u_char cmd; + +#ifdef I4B_SMP_WORKAROUND + + /* XXXXXXXXXXXXXXXXXXX */ + + /* + * patch from Wolfgang Helbig: + * + * Here is a patch that makes i4b work on an SMP: + * The card (TELES 16.3) didn't interrupt on an SMP machine. + * This is a gross workaround, but anyway it works *and* provides + * some information as how to finally fix this problem. + */ + + HSCX_WRITE(0, H_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + ISAC_WRITE(I_MASK, 0xff); + DELAY(100); + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + ISAC_WRITE(I_MASK, ISAC_IMASK); + + /* XXXXXXXXXXXXXXXXXXX */ + +#endif /* I4B_SMP_WORKAROUND */ + + if(command < 0 || command > CMD_ILL) + { + NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc)); + return; + } + + if(sc->sc_bustyp == BUS_TYPE_IOM2) + cmd = ISAC_CIX0_LOW; + else + cmd = 0; + + switch(command) + { + case CMD_TIM: + NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc)); + cmd |= (ISAC_CIXR_CTIM << 2); + break; + + case CMD_RS: + NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc)); + cmd |= (ISAC_CIXR_CRS << 2); + break; + + case CMD_AR8: + NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc)); + cmd |= (ISAC_CIXR_CAR8 << 2); + break; + + case CMD_AR10: + NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc)); + cmd |= (ISAC_CIXR_CAR10 << 2); + break; + + case CMD_DIU: + NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc)); + cmd |= (ISAC_CIXR_CDIU << 2); + break; + } + ISAC_WRITE(I_CIXR, cmd); +} + +/*---------------------------------------------------------------------------* + * L1 ISAC initialization + *---------------------------------------------------------------------------*/ +int +isic_isac_init(struct l1_softc *sc) +{ + ISAC_IMASK = 0xff; /* disable all irqs */ + + ISAC_WRITE(I_MASK, ISAC_IMASK); + + if(sc->sc_bustyp != BUS_TYPE_IOM2) + { + NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode"); + + /* ADF2: Select mode IOM-1 */ + ISAC_WRITE(I_ADF2, 0x00); + + /* SPCR: serial port control register: + * SPU - software power up = 0 + * SAC - SIP port high Z + * SPM - timing mode 0 + * TLP - test loop = 0 + * C1C, C2C - B1 and B2 switched to/from SPa + */ + ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1); + + /* SQXR: S/Q channel xmit register: + * SQIE - S/Q IRQ enable = 0 + * SQX1-4 - Fa bits = 1 + */ + ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4); + + /* ADF1: additional feature reg 1: + * WTC - watchdog = 0 + * TEM - test mode = 0 + * PFS - pre-filter = 0 + * CFS - IOM clock/frame always active + * FSC1/2 - polarity of 8kHz strobe + * ITF - interframe fill = idle + */ + ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */ + + /* STCR: sync transfer control reg: + * TSF - terminal secific functions = 0 + * TBA - TIC bus address = 7 + * STx/SCx = 0 + */ + ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0); + + /* MODE: Mode Register: + * MDSx - transparent mode 2 + * TMD - timer mode = external + * RAC - Receiver enabled + * DIMx - digital i/f mode + */ + ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0); + } + else + { + NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode"); + + /* ADF2: Select mode IOM-2 */ + ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS); + + /* SPCR: serial port control register: + * SPU - software power up = 0 + * SPM - timing mode 0 + * TLP - test loop = 0 + * C1C, C2C - B1 + C1 and B2 + IC2 monitoring + */ + ISAC_WRITE(I_SPCR, 0x00); + + /* SQXR: S/Q channel xmit register: + * IDC - IOM direction = 0 (master) + * CFS - Config Select = 0 (clock always active) + * CI1E - C/I channel 1 IRQ enable = 0 + * SQIE - S/Q IRQ enable = 0 + * SQX1-4 - Fa bits = 1 + */ + ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4); + + /* ADF1: additional feature reg 1: + * WTC - watchdog = 0 + * TEM - test mode = 0 + * PFS - pre-filter = 0 + * IOF - IOM i/f off = 0 + * ITF - interframe fill = idle + */ + ISAC_WRITE(I_ADF1, 0x00); + + /* STCR: sync transfer control reg: + * TSF - terminal secific functions = 0 + * TBA - TIC bus address = 7 + * STx/SCx = 0 + */ + ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0); + + /* MODE: Mode Register: + * MDSx - transparent mode 2 + * TMD - timer mode = external + * RAC - Receiver enabled + * DIMx - digital i/f mode + */ + ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0); + } + +#ifdef NOTDEF + /* + * XXX a transmitter reset causes an ISAC tx IRQ which will not + * be serviced at attach time under some circumstances leaving + * the associated IRQ line on the ISA bus active. This prevents + * any further interrupts to be serviced because no low -> high + * transition can take place anymore. (-hm) + */ + + /* command register: + * RRES - HDLC receiver reset + * XRES - transmitter reset + */ + ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES); + ISACCMDRWRDELAY(); +#endif + + /* enabled interrupts: + * =================== + * RME - receive message end + * RPF - receive pool full + * XPR - transmit pool ready + * CISQ - CI or S/Q channel change + * EXI - extended interrupt + */ + + ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */ + ISAC_MASK_TIN | /* timer irq */ + ISAC_MASK_SIN; /* sync xfer irq */ + + ISAC_WRITE(I_MASK, ISAC_IMASK); + + return(0); +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_isac.h b/sys/i4b/layer1/isic/i4b_isac.h new file mode 100644 index 000000000000..42c6a5c296be --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isac.h @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1996, 2000 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:10:42 2001] + * + *---------------------------------------------------------------------------*/ + +#ifndef I4B_ISAC_H_ +#define I4B_ISAC_H_ + +/* + * The ISAC databook specifies a delay of 2.5 DCL clock cycles between + * writes to the ISAC command register CMDR. This is the delay used to + * satisfy this requirement. + */ + +#define I4B_ISAC_CMDRWRDELAY 30 + +#if (I4B_ISAC_CMDRWRDELAY > 0) +#define ISACCMDRWRDELAY() DELAY(I4B_ISAC_CMDRWRDELAY) +#else +#warning "I4B_ISAC_CMDRWRDELAY set to 0!" +#define ISACCMDRWRDELAY() +#endif + +enum ISAC_VERSIONS { + ISAC_VA, /* 2085 A1 or A2, 2086/2186 V1.1 */ + ISAC_VB1, /* 2085 B1 */ + ISAC_VB2, /* 2085 B2 */ + ISAC_VB3, /* 2085 B3/V2.3 */ + ISAC_UNKN /* unknown version */ +}; + +#define ISAC_FIFO_LEN 32 /* 32 bytes FIFO on chip */ + +/* + * definitions of registers and bits for the ISAC ISDN chip. + */ + +typedef struct isac_reg { + + /* 32 byte deep FIFO always first */ + + unsigned char isac_fifo [ISAC_FIFO_LEN]; + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char isac_ista; + unsigned char isac_star; + unsigned char isac_mode; + unsigned char isac_timr; + unsigned char isac_exir; + unsigned char isac_rbcl; + unsigned char isac_sapr; + unsigned char isac_rsta; + unsigned char dummy_28; + unsigned char isac_rhcr; + unsigned char isac_rbch; + unsigned char isac_star2; + unsigned char dummy_2c; + unsigned char dummy_2d; + unsigned char dummy_2e; + unsigned char dummt_2f; + unsigned char isac_spcr; + unsigned char isac_cirr; + unsigned char isac_mor; + unsigned char isac_sscr; + unsigned char isac_sfcr; + unsigned char isac_c1r; + unsigned char isac_c2r; + unsigned char isac_b1cr; + unsigned char isac_b2cr; + unsigned char isac_adf2; + unsigned char isac_mosr; + unsigned char isac_sqrr; + } isac_r; + struct { + unsigned char isac_mask; + unsigned char isac_cmdr; + unsigned char isac_mode; + unsigned char isac_timr; + unsigned char isac_xad1; + unsigned char isac_xad2; + unsigned char isac_sap1; + unsigned char isac_sap2; + unsigned char isac_tei1; + unsigned char isac_tei2; + unsigned char dummy_2a; + unsigned char isac_star2; + unsigned char dummy_2c; + unsigned char dummy_2d; + unsigned char dummy_2e; + unsigned char dummt_2f; + unsigned char isac_spcr; + unsigned char isac_cixr; + unsigned char isac_mox; + unsigned char isac_sscx; + unsigned char isac_sfcw; + unsigned char isac_c1r; + unsigned char isac_c2r; + unsigned char isac_stcr; + unsigned char isac_adf1; + unsigned char isac_adf2; + unsigned char isac_mocr; + unsigned char isac_sqxr; + } isac_w; + } isac_rw; +} isac_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* ISAC read registers */ + +#define i_ista isac_rw.isac_r.isac_ista +#define I_ISTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_ista) +#define i_star isac_rw.isac_r.isac_star +#define I_STAR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star) +#define i_mode isac_rw.isac_r.isac_mode +#define I_MODE REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mode) +#define i_timr isac_rw.isac_r.isac_timr +#define I_TIMR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_timr) +#define i_exir isac_rw.isac_r.isac_exir +#define I_EXIR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_exir) +#define i_rbcl isac_rw.isac_r.isac_rbcl +#define I_RBCL REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbcl) +#define i_sapr isac_rw.isac_r.isac_sapr +#define I_SAPR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sapr) +#define i_rsta isac_rw.isac_r.isac_rsta +#define I_RSTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rsta) +#define i_rhcr isac_rw.isac_r.isac_rhcr +#define I_RHCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rhcr) +#define i_rbch isac_rw.isac_r.isac_rbch +#define I_RBCH REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbch) +#define i_star2 isac_rw.isac_r.isac_star2 +#define I_STAR2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star2) +#define i_spcr isac_rw.isac_r.isac_spcr +#define I_SPCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_spcr) +#define i_cirr isac_rw.isac_r.isac_cirr +#define I_CIRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_cirr) +#define i_mor isac_rw.isac_r.isac_mor +#define I_MOR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mor) +#define i_sscr isac_rw.isac_r.isac_sscr +#define I_SSCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sscr) +#define i_sfcr isac_rw.isac_r.isac_sfcr +#define I_SFCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sfcr) +#define i_c1r isac_rw.isac_r.isac_c1r +#define I_C1R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c1r) +#define i_c2r isac_rw.isac_r.isac_c2r +#define I_C2R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c2r) +#define i_b1cr isac_rw.isac_r.isac_b1cr +#define I_B1CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b1cr) +#define i_b2cr isac_rw.isac_r.isac_b2cr +#define I_B2CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b2cr) +#define i_adf2 isac_rw.isac_r.isac_adf2 +#define I_ADF2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_adf2) +#define i_mosr isac_rw.isac_r.isac_mosr +#define I_MOSR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mosr) +#define i_sqrr isac_rw.isac_r.isac_sqrr +#define I_SQRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sqrr) + +/* ISAC write registers - isac_mode, isac_timr, isac_star2, isac_spcr, */ +/* isac_c1r, isac_c2r, isac_adf2 see read registers */ + +#define i_mask isac_rw.isac_w.isac_mask +#define I_MASK REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mask) +#define i_cmdr isac_rw.isac_w.isac_cmdr +#define I_CMDR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cmdr) +#define i_xad1 isac_rw.isac_w.isac_xad1 +#define I_XAD1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad1) +#define i_xad2 isac_rw.isac_w.isac_xad2 +#define I_XAD2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad2) +#define i_sap1 isac_rw.isac_w.isac_sap1 +#define I_SAP1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap1) +#define i_sap2 isac_rw.isac_w.isac_sap2 +#define I_SAP2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap2) +#define i_tei1 isac_rw.isac_w.isac_tei1 +#define i_tei2 isac_rw.isac_w.isac_tei2 +#define i_cixr isac_rw.isac_w.isac_cixr +#define I_CIXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cixr) +#define I_CIX0 I_CIXR +#define i_mox isac_rw.isac_w.isac_mox +#define I_MOX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mox) +#define i_sscx isac_rw.isac_w.isac_sscx +#define I_SSCX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sscx) +#define i_sfcw isac_rw.isac_w.isac_sfcw +#define I_SFCW REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sfcw) +#define i_stcr isac_rw.isac_w.isac_stcr +#define I_STCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_stcr) +#define i_adf1 isac_rw.isac_w.isac_adf1 +#define I_ADF1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_adf1) +#define i_mocr isac_rw.isac_w.isac_mocr +#define I_MOCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mocr) +#define i_sqxr isac_rw.isac_w.isac_sqxr +#define I_SQXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sqxr) + +#define ISAC_ISTA_RME 0x80 +#define ISAC_ISTA_RPF 0x40 +#define ISAC_ISTA_RSC 0x20 +#define ISAC_ISTA_XPR 0x10 +#define ISAC_ISTA_TIN 0x08 +#define ISAC_ISTA_CISQ 0x04 +#define ISAC_ISTA_SIN 0x02 +#define ISAC_ISTA_EXI 0x01 + +#define ISAC_MASK_RME 0x80 +#define ISAC_MASL_RPF 0x40 +#define ISAC_MASK_RSC 0x20 +#define ISAC_MASK_XPR 0x10 +#define ISAC_MASK_TIN 0x08 +#define ISAC_MASK_CISQ 0x04 +#define ISAC_MASK_SIN 0x02 +#define ISAC_MASK_EXI 0x01 +#define ISAC_MASK_ALL 0xff + +#define ISAC_STAR_XDOV 0x80 +#define ISAC_STAR_XFW 0x40 +#define ISAC_STAR_XRNR 0x20 +#define ISAC_STAR_RRNR 0x10 +#define ISAC_STAR_MBR 0x08 +#define ISAC_STAR_MAC1 0x04 +#define ISAC_STAR_BVS 0x02 +#define ISAC_STAR_MAC0 0x01 + +#define ISAC_CMDR_RMC 0x80 +#define ISAC_CMDR_RRES 0x40 +#define ISAC_CMDR_RNR 0x20 +#define ISAC_CMDR_STI 0x10 +#define ISAC_CMDR_XTF 0x08 +#define ISAC_CMDR_XIF 0x04 +#define ISAC_CMDR_XME 0x02 +#define ISAC_CMDR_XRES 0x01 + +#define ISAC_MODE_MDS2 0x80 +#define ISAC_MODE_MDS1 0x40 +#define ISAC_MODE_MDS0 0x20 +#define ISAC_MODE_TMD 0x10 +#define ISAC_MODE_RAC 0x08 +#define ISAC_MODE_DIM2 0x04 +#define ISAC_MODE_DIM1 0x02 +#define ISAC_MODE_DIM0 0x01 + +#define ISAC_EXIR_XMR 0x80 +#define ISAC_EXIR_XDU 0x40 +#define ISAC_EXIR_PCE 0x20 +#define ISAC_EXIR_RFO 0x10 +#define ISAC_EXIR_SOV 0x08 +#define ISAC_EXIR_MOS 0x04 +#define ISAC_EXIR_SAW 0x02 +#define ISAC_EXIR_WOV 0x01 + +#define ISAC_RSTA_RDA 0x80 +#define ISAC_RSTA_RDO 0x40 +#define ISAC_RSTA_CRC 0x20 +#define ISAC_RSTA_RAB 0x10 +#define ISAC_RSTA_SA1 0x08 +#define ISAC_RSTA_SA0 0x04 +#define ISAC_RSTA_CR 0x02 +#define ISAC_RSTA_TA 0x01 + +#define ISAC_RSTA_MASK 0x70 /* the interesting bits */ + +#define ISAC_RBCH_XAC 0x80 +#define ISAC_RBCH_VN1 0x40 +#define ISAC_RBCH_VN0 0x20 +#define ISAC_RBCH_OV 0x10 +/* the other 4 bits are the high bits of the receive byte count */ + +#define ISAC_SPCR_SPU 0x80 +#define ISAC_SPCR_SAC 0x40 +#define ISAC_SPCR_SPM 0x20 +#define ISAC_SPCR_TLP 0x10 +#define ISAC_SPCR_C1C1 0x08 +#define ISAC_SPCR_C1C0 0x04 +#define ISAC_SPCR_C2C1 0x02 +#define ISAC_SPCR_C2C0 0x01 + +#define ISAC_CIRR_SQC 0x80 +#define ISAC_CIRR_BAS 0x40 +/* bits 5-2 CODR */ +#define ISAC_CIRR_CIC0 0x02 +/* bit 0 is always 0 */ +/* C/I codes from bits 5-2 (>> 2 & 0xf) */ +/* the indications */ +#define ISAC_CIRR_IPU 0x07 +#define ISAC_CIRR_IDR 0x00 +#define ISAC_CIRR_ISD 0x02 +#define ISAC_CIRR_IDIS 0x03 +#define ISAC_CIRR_IEI 0x06 +#define ISAC_CIRR_IRSY 0x04 +#define ISAC_CIRR_IARD 0x08 +#define ISAC_CIRR_ITI 0x0a +#define ISAC_CIRR_IATI 0x0b +#define ISAC_CIRR_IAI8 0x0c +#define ISAC_CIRR_IAI10 0x0d +#define ISAC_CIRR_IDID 0x0f + +#define ISAC_CI_MASK 0x0f + +#define ISAC_CIXR_RSS 0x80 +#define ISAC_CIXR_BAC 0x40 +/* bits 5-2 CODX */ +#define ISAC_CIXR_TCX 0x02 +#define ISAC_CIXR_ECX 0x01 +/* in IOM-2 mode the low bits are always 1 */ +#define ISAC_CIX0_LOW 0x03 +/* C/I codes from bits 5-2 (>> 2 & 0xf) */ +/* the commands */ +#define ISAC_CIXR_CTIM 0 +#define ISAC_CIXR_CRS 0x01 +#define ISAC_CIXR_CSCZ 0x04 +#define ISAC_CIXR_CSSZ 0x02 +#define ISAC_CIXR_CAR8 0x08 +#define ISAC_CIXR_CAR10 0x09 +#define ISAC_CIXR_CARL 0x0a +#define ISAC_CIXR_CDIU 0x0f + +#define ISAC_STCR_TSF 0x80 +#define ISAC_STCR_TBA2 0x40 +#define ISAC_STCR_TBA1 0x20 +#define ISAC_STCR_TBA0 0x10 +#define ISAC_STCR_ST1 0x08 +#define ISAC_STCR_ST0 0x04 +#define ISAC_STCR_SC1 0x02 +#define ISAC_STCR_SC0 0x01 + +#define ISAC_ADF1_WTC1 0x80 +#define ISAC_ADF1_WTC2 0x40 +#define ISAC_ADF1_TEM 0x20 +#define ISAC_ADF1_PFS 0x10 +#define ISAC_ADF1_CFS 0x08 +#define ISAC_ADF1_FC2 0x04 +#define ISAC_ADF1_FC1 0x02 +#define ISAC_ADF1_ITF 0x01 + +#define ISAC_ADF2_IMS 0x80 +/* all other bits are 0 */ + +/* bits 7-5 are always 0 */ +#define ISAC_SQRR_SYN 0x10 +#define ISAC_SQRR_SQR1 0x08 +#define ISAC_SQRR_SQR2 0x04 +#define ISAC_SQRR_SQR3 0x02 +#define ISAC_SQRR_SQR4 0x01 + +#define ISAC_SQXR_IDC 0x80 +#define ISAC_SQXR_CFS 0x40 +#define ISAC_SQXR_CI1E 0x20 +#define ISAC_SQXR_SQIE 0x10 +#define ISAC_SQXR_SQX1 0x08 +#define ISAC_SQXR_SQX2 0x04 +#define ISAC_SQXR_SQX3 0x02 +#define ISAC_SQXR_SQX4 0x01 + +#endif /* I4B_ISAC_H_ */ diff --git a/sys/i4b/layer1/isic/i4b_isic.c b/sys/i4b/layer1/isic/i4b_isic.c new file mode 100644 index 000000000000..751c568cd5dd --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isic.c @@ -0,0 +1,499 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic.c - global isic stuff + * ============================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:29:42 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_isic_ext.h> +#include <i4b/layer1/isic/i4b_ipac.h> +#include <i4b/layer1/isic/i4b_isac.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> + +static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" +}; + +static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" +}; + +/* jump table for multiplex routines */ +struct i4b_l1mux_func isic_l1mux_func = { + isic_ret_linktab, + isic_set_linktab, + isic_mph_command_req, + isic_ph_data_req, + isic_ph_activate_req, +}; + +/*---------------------------------------------------------------------------* + * isic - device driver interrupt routine + *---------------------------------------------------------------------------*/ +void +isicintr(struct l1_softc *sc) +{ + if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */ + { + u_char was_hscx_irq = 0; + u_char was_isac_irq = 0; + + register u_char hscx_irq_stat; + register u_char isac_irq_stat; + + for(;;) + { + /* get hscx irq status from hscx b ista */ + hscx_irq_stat = + HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK; + + /* get isac irq status */ + isac_irq_stat = ISAC_READ(I_ISTA); + + /* do as long as there are pending irqs in the chips */ + if(!hscx_irq_stat && !isac_irq_stat) + break; + + if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF | + HSCX_ISTA_RSC | HSCX_ISTA_XPR | + HSCX_ISTA_TIN | HSCX_ISTA_EXB)) + { + isic_hscx_irq(sc, hscx_irq_stat, + HSCX_CH_B, + hscx_irq_stat & HSCX_ISTA_EXB); + was_hscx_irq = 1; + } + + if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA)) + { + isic_hscx_irq(sc, + HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK, + HSCX_CH_A, + hscx_irq_stat & HSCX_ISTA_EXA); + was_hscx_irq = 1; + } + + if(isac_irq_stat) + { + isic_isac_irq(sc, isac_irq_stat); /* isac handler */ + was_isac_irq = 1; + } + } + + HSCX_WRITE(0, H_MASK, 0xff); + ISAC_WRITE(I_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + +#ifdef ELSA_QS1ISA + DELAY(80); + + if((sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA) && (sc->clearirq)) + { + sc->clearirq(sc); + } +#else + DELAY(100); +#endif + + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + ISAC_WRITE(I_MASK, ISAC_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + } + else /* IPAC interrupt routine */ + { + register u_char ipac_irq_stat; + register u_char was_ipac_irq = 0; + + for(;;) + { + /* get global irq status */ + + ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f; + + /* check hscx a */ + + if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA)) + { + /* HSCX A interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA), + HSCX_CH_A, + ipac_irq_stat & IPAC_ISTA_EXA); + was_ipac_irq = 1; + } + if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB)) + { + /* HSCX B interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA), + HSCX_CH_B, + ipac_irq_stat & IPAC_ISTA_EXB); + was_ipac_irq = 1; + } + if(ipac_irq_stat & IPAC_ISTA_ICD) + { + /* ISAC interrupt */ + isic_isac_irq(sc, ISAC_READ(I_ISTA)); + was_ipac_irq = 1; + } + if(ipac_irq_stat & IPAC_ISTA_EXD) + { + /* force ISAC interrupt handling */ + isic_isac_irq(sc, ISAC_ISTA_EXI); + was_ipac_irq = 1; + } + + /* do as long as there are pending irqs in the chip */ + if(!ipac_irq_stat) + break; + } + + IPAC_WRITE(IPAC_MASK, 0xff); + DELAY(50); + IPAC_WRITE(IPAC_MASK, 0xc0); + } +} + +/*---------------------------------------------------------------------------* + * isic_recover - try to recover from irq lockup + *---------------------------------------------------------------------------*/ +void +isic_recover(struct l1_softc *sc) +{ + u_char byte; + + /* get hscx irq status from hscx b ista */ + + byte = HSCX_READ(HSCX_CH_B, H_ISTA); + + NDBGL1(L1_ERROR, "HSCX B: ISTA = 0x%x", byte); + + if(byte & HSCX_ISTA_ICA) + NDBGL1(L1_ERROR, "HSCX A: ISTA = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA)); + + if(byte & HSCX_ISTA_EXB) + NDBGL1(L1_ERROR, "HSCX B: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR)); + + if(byte & HSCX_ISTA_EXA) + NDBGL1(L1_ERROR, "HSCX A: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR)); + + /* get isac irq status */ + + byte = ISAC_READ(I_ISTA); + + NDBGL1(L1_ERROR, " ISAC: ISTA = 0x%x", byte); + + if(byte & ISAC_ISTA_EXI) + NDBGL1(L1_ERROR, " ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR)); + + if(byte & ISAC_ISTA_CISQ) + { + byte = ISAC_READ(I_CIRR); + + NDBGL1(L1_ERROR, " ISAC: CISQ = 0x%x", byte); + + if(byte & ISAC_CIRR_SQC) + NDBGL1(L1_ERROR, " ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR)); + } + + NDBGL1(L1_ERROR, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK); + NDBGL1(L1_ERROR, "HSCX A: IMASK = 0x%x", HSCX_A_IMASK); + + HSCX_WRITE(0, H_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + DELAY(100); + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + DELAY(100); + + NDBGL1(L1_ERROR, " ISAC: IMASK = 0x%x", ISAC_IMASK); + + ISAC_WRITE(I_MASK, 0xff); + DELAY(100); + ISAC_WRITE(I_MASK, ISAC_IMASK); +} + +/*---------------------------------------------------------------------------* + * isic_attach_common - common attach routine for all busses + *---------------------------------------------------------------------------*/ +int +isic_attach_common(device_t dev) +{ + char *drvid = NULL; + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + sc->sc_unit = unit; + + sc->sc_isac_version = 0; + sc->sc_hscx_version = 0; + + if(sc->sc_ipac) + { + sc->sc_ipac_version = IPAC_READ(IPAC_ID); + + switch(sc->sc_ipac_version) + { + case IPAC_V11: + case IPAC_V12: + break; + + default: + printf("isic%d: Error, IPAC version %d unknown!\n", + unit, sc->sc_ipac_version); + return(0); + break; + } + } + else + { + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + break; + + default: + printf("isic%d: Error, ISAC version %d unknown!\n", + unit, sc->sc_isac_version); + return ENXIO; + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + break; + + default: + printf("isic%d: Error, HSCX version %d unknown!\n", + unit, sc->sc_hscx_version); + return ENXIO; + break; + } + } + + isic_isac_init(sc); /* ISAC setup */ + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + isic_init_linktab(sc); /* setup linktab */ + + sc->sc_trace = TRACE_OFF; /* set trace level */ + + sc->sc_state = ISAC_IDLE; /* set state */ + + sc->sc_ibuf = NULL; /* input buffering */ + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; /* output buffering */ + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; /* second output buffer */ + sc->sc_freeflag2 = 0; + + /* timer setup */ + + callout_handle_init(&sc->sc_T3_callout); + callout_handle_init(&sc->sc_T4_callout); + + /* init higher protocol layers */ + + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &isic_l1mux_func); + + /* announce manufacturer and card type for ISA cards */ + + switch(sc->sc_cardtyp) + { + case CARD_TYPEP_8: + drvid = "Teles S0/8 (or compatible)"; + break; + + case CARD_TYPEP_16: + drvid = "Teles S0/16 (or compatible)"; + break; + + case CARD_TYPEP_16_3: + drvid = "Teles S0/16.3"; + break; + + case CARD_TYPEP_AVMA1: + drvid = "AVM A1 or Fritz!Card Classic"; + break; + + case CARD_TYPEP_PCFRITZ: + drvid = "AVM Fritz!Card PCMCIA"; + break; + + case CARD_TYPEP_USRTA: + drvid = "USRobotics Sportster ISDN TA intern"; + break; + + case CARD_TYPEP_ITKIX1: + drvid = "ITK ix1 micro"; + break; + + case CARD_TYPEP_PCC16: + drvid = "ELSA MicroLink ISDN/PCC-16"; + break; + + default: + drvid = NULL; /* pnp/pci cards announce themselves */ + break; + } + + if(drvid) + printf("isic%d: %s\n", unit, drvid); + + if(bootverbose) + { + /* announce chip versions */ + + if(sc->sc_ipac) + { + if(sc->sc_ipac_version == IPAC_V11) + printf("isic%d: IPAC PSB2115 Version 1.1\n", unit); + else + printf("isic%d: IPAC PSB2115 Version 1.2\n", unit); + } + else + { + printf("isic%d: ISAC %s (IOM-%c)\n", + unit, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + + printf("isic%d: HSCX %s\n", + unit, + HSCXversion[sc->sc_hscx_version]); + } + } + return 0; +} + +/*---------------------------------------------------------------------------* + * isic_detach_common - common detach routine for all busses + *---------------------------------------------------------------------------*/ +void +isic_detach_common(device_t dev) +{ + struct l1_softc *sc = &l1_sc[device_get_unit(dev)]; + int i; + + sc->sc_cardtyp = CARD_TYPEP_UNK; + + /* free interrupt resources */ + + if(sc->sc_resources.irq) + { + /* tear down interupt handler */ + bus_teardown_intr(dev, sc->sc_resources.irq, + (void(*)(void *))isicintr); + + /* free irq */ + bus_release_resource(dev, SYS_RES_IRQ, + sc->sc_resources.irq_rid, + sc->sc_resources.irq); + sc->sc_resources.irq_rid = 0; + sc->sc_resources.irq = 0; + } + + /* free memory resource */ + + if(sc->sc_resources.mem) + { + bus_release_resource(dev,SYS_RES_MEMORY, + sc->sc_resources.mem_rid, + sc->sc_resources.mem); + sc->sc_resources.mem_rid = 0; + sc->sc_resources.mem = 0; + } + + /* free iobases */ + + for(i=0; i < INFO_IO_BASES ; i++) + { + if(sc->sc_resources.io_base[i]) + { + bus_release_resource(dev, SYS_RES_IOPORT, + sc->sc_resources.io_rid[i], + sc->sc_resources.io_base[i]); + sc->sc_resources.io_rid[i] = 0; + sc->sc_resources.io_base[i] = 0; + } + } +} + +#endif /* NISIC > 0 */ + diff --git a/sys/i4b/layer1/isic/i4b_isic.h b/sys/i4b/layer1/isic/i4b_isic.h new file mode 100644 index 000000000000..feb06afe6463 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isic.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *---------------------------------------------------------------------------* + * + * i4b_l1.h - isdn4bsd layer 1 header file + * --------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Fri Jan 26 13:55:12 2001] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_ISIC_H_ +#define _I4B_ISIC_H_ + +#include <sys/resource.h> +#include <sys/bus.h> +#include <i386/include/bus.h> +#include <sys/rman.h> +#include <i386/include/resource.h> + +#include <i4b/include/i4b_l3l4.h> + +#include <i4b/layer1/isic/i4b_isic_ext.h> + +/*--------------------------------------------------------------------------- + * isic driver: max no of units + * Teles/Creatix/Neuhaus cards have a hardware limitation + * as one is able to set 3 (sometimes 4) different configurations by + * jumpers so a maximum of 3 (4) cards per ISA bus is possible. + *---------------------------------------------------------------------------*/ +#define ISIC_MAXUNIT 3 /* max no of supported units 0..3 */ + +#define INFO_IO_BASES 50 /* 49 needed for USR */ + +struct i4b_info { + struct resource * io_base[INFO_IO_BASES]; + int io_rid [INFO_IO_BASES]; + struct resource * irq; + int irq_rid; + struct resource * mem; + int mem_rid; +}; + +/*---------------------------------------------------------------------------* + * l1_bchan_state: the state of one B channel + *---------------------------------------------------------------------------*/ +typedef struct +{ + int unit; /* cards unit number */ + int channel; /* which channel is this*/ + caddr_t hscx; /* HSCX address */ + u_char hscx_mask; /* HSCX interrupt mask */ + int bprot; /* B channel protocol */ + int state; /* this channels state */ +#define HSCX_IDLE 0x00 /* channel idle */ +#define HSCX_TX_ACTIVE 0x01 /* tx running */ + + /* receive data from ISDN */ + + struct ifqueue rx_queue; /* receiver queue */ + + int rxcount; /* rx statistics counter*/ + + struct mbuf *in_mbuf; /* rx input buffer */ + u_char *in_cbptr; /* curr buffer pointer */ + int in_len; /* rx input buffer len */ + + /* transmit data to ISDN */ + + struct ifqueue tx_queue; /* transmitter queue */ + + int txcount; /* tx statistics counter*/ + + struct mbuf *out_mbuf_head; /* first mbuf in possible chain */ + struct mbuf *out_mbuf_cur; /* current mbuf in possbl chain */ + unsigned char *out_mbuf_cur_ptr; /* data pointer into mbuf */ + int out_mbuf_cur_len; /* remaining bytes in mbuf */ + + /* link between b channel and driver */ + + isdn_link_t isic_isdn_linktab; /* b channel addresses */ + drvr_link_t *isic_drvr_linktab; /* ptr to driver linktab*/ + + /* statistics */ + + /* RSTA */ + + int stat_VFR; /* HSCX RSTA Valid FRame */ + int stat_RDO; /* HSCX RSTA Rx Data Overflow */ + int stat_CRC; /* HSCX RSTA CRC */ + int stat_RAB; /* HSCX RSTA Rx message ABorted */ + + /* EXIR */ + + int stat_XDU; /* HSCX EXIR tx data underrun */ + int stat_RFO; /* HSCX EXIR rx frame overflow */ + +} l1_bchan_state_t; + +/*---------------------------------------------------------------------------* + * l1_softc: the state of the layer 1 of the D channel + *---------------------------------------------------------------------------*/ +struct l1_softc +{ + int sc_unit; /* unit number */ + int sc_irq; /* interrupt vector */ + struct i4b_info sc_resources; + + int sc_port; /* port base address */ + + int sc_cardtyp; /* CARD_TYPEP_xxxx */ + + int sc_bustyp; /* IOM1 or IOM2 */ +#define BUS_TYPE_IOM1 0x01 +#define BUS_TYPE_IOM2 0x02 + + int sc_trace; /* output protocol data for tracing */ + unsigned int sc_trace_dcount;/* d channel trace frame counter */ + unsigned int sc_trace_bcount;/* b channel trace frame counter */ + + int sc_state; /* ISAC state flag */ +#define ISAC_IDLE 0x00 /* state = idle */ +#define ISAC_TX_ACTIVE 0x01 /* state = transmitter active */ + + int sc_init_tries; /* no of out tries to access S0 */ + + caddr_t sc_vmem_addr; /* card RAM virtual memory base */ + caddr_t sc_isac; /* ISAC port base addr */ +#define ISAC_BASE (sc->sc_isac) + + caddr_t sc_ipacbase; /* IPAC port base addr */ +#define IPAC_BASE (sc->sc_ipacbase) + + u_char sc_isac_mask; /* ISAC IRQ mask */ +#define ISAC_IMASK (sc->sc_isac_mask) + + l1_bchan_state_t sc_chan[2]; /* B-channel state */ +#define HSCX_A_BASE (sc->sc_chan[0].hscx) +#define HSCX_A_IMASK (sc->sc_chan[0].hscx_mask) +#define HSCX_B_BASE (sc->sc_chan[1].hscx) +#define HSCX_B_IMASK (sc->sc_chan[1].hscx_mask) + + struct mbuf *sc_ibuf; /* input buffer mgmt */ + u_short sc_ilen; + u_char *sc_ib; + /* this is for the irq TX routine */ + struct mbuf *sc_obuf; /* pointer to an mbuf with TX frame */ + u_char *sc_op; /* ptr to next chunk of frame to tx */ + int sc_ol; /* length of remaining frame to tx */ + int sc_freeflag; /* m_freem mbuf if set */ + + struct mbuf *sc_obuf2; /* pointer to an mbuf with TX frame */ + int sc_freeflag2; /* m_freem mbuf if set */ + + int sc_isac_version; /* version number of ISAC */ + int sc_hscx_version; /* version number of HSCX */ + int sc_ipac_version; /* version number of IPAC */ + + int sc_I430state; /* I.430 state F3 .... F8 */ + + int sc_I430T3; /* I.430 Timer T3 running */ + + struct callout_handle sc_T3_callout; + + int sc_I430T4; /* Timer T4 running */ + + struct callout_handle sc_T4_callout; + + /* + * byte fields for the AVM Fritz!Card PCI. These are packed into + * a u_int in the driver. + */ + u_char avma1pp_cmd; + u_char avma1pp_txl; + u_char avma1pp_prot; + + int sc_enabled; /* daemon is running */ + + int sc_ipac; /* flag, running on ipac */ + int sc_bfifolen; /* length of b channel fifos */ + +#define ISIC_WHAT_ISAC 0 +#define ISIC_WHAT_HSCXA 1 +#define ISIC_WHAT_HSCXB 2 +#define ISIC_WHAT_IPAC 3 + + u_int8_t (*readreg) (struct l1_softc *sc, int what, bus_size_t offs); + void (*writereg) (struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data); + void (*readfifo) (struct l1_softc *sc, int what, void *buf, size_t size); + void (*writefifo) (struct l1_softc *sc, int what, void *data, size_t size); + void (*clearirq) (struct l1_softc *sc); + +#define ISAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_ISAC, (r)) +#define ISAC_WRITE(r,v) (*sc->writereg)(sc, ISIC_WHAT_ISAC, (r), (v)) +#define ISAC_RDFIFO(b,s) (*sc->readfifo)(sc, ISIC_WHAT_ISAC, (b), (s)) +#define ISAC_WRFIFO(b,s) (*sc->writefifo)(sc, ISIC_WHAT_ISAC, (b), (s)) + +#define HSCX_READ(n,r) (*sc->readreg)(sc, ISIC_WHAT_HSCXA+(n), (r)) +#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc, ISIC_WHAT_HSCXA+(n), (r), (v)) +#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s)) +#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s)) + +#define IPAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_IPAC, (r)) +#define IPAC_WRITE(r, v) (*sc->writereg)(sc, ISIC_WHAT_IPAC, (r), (v)) +}; + +/*---------------------------------------------------------------------------* + * possible I.430/ISAC states + *---------------------------------------------------------------------------*/ +enum I430states { + ST_F3, /* F3 Deactivated */ + ST_F4, /* F4 Awaiting Signal */ + ST_F5, /* F5 Identifying Input */ + ST_F6, /* F6 Synchronized */ + ST_F7, /* F7 Activated */ + ST_F8, /* F8 Lost Framing */ + ST_ILL, /* Illegal State */ + N_STATES +}; + +/*---------------------------------------------------------------------------* + * possible I.430/ISAC events + *---------------------------------------------------------------------------*/ +enum I430events { + EV_PHAR, /* PH ACTIVATE REQUEST */ + EV_T3, /* Timer 3 expired */ + EV_INFO0, /* receiving INFO0 */ + EV_RSY, /* receiving any signal */ + EV_INFO2, /* receiving INFO2 */ + EV_INFO48, /* receiving INFO4 pri 8/9 */ + EV_INFO410, /* receiving INFO4 pri 10/11 */ + EV_DR, /* Deactivate Request */ + EV_PU, /* Power UP */ + EV_DIS, /* Disconnected (only 2085) */ + EV_EI, /* Error Indication */ + EV_ILL, /* Illegal Event */ + N_EVENTS +}; + +enum I430commands { + CMD_TIM, /* Timing */ + CMD_RS, /* Reset */ + CMD_AR8, /* Activation request pri 8 */ + CMD_AR10, /* Activation request pri 10 */ + CMD_DIU, /* Deactivate Indication Upstream */ + CMD_ILL /* Illegal command */ +}; + +#define N_COMMANDS CMD_ILL + +extern struct l1_softc l1_sc[]; + +extern void isicintr(struct l1_softc *sc); +extern int isic_attach_common(device_t dev); +extern void isic_detach_common(device_t dev); +extern void isic_recover(struct l1_softc *sc); + +extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate ); + +extern void isic_init_linktab ( struct l1_softc *sc ); +extern int isic_isac_init ( struct l1_softc *sc ); +extern void isic_isac_irq ( struct l1_softc *sc, int r ); +extern void isic_isac_l1_cmd ( struct l1_softc *sc, int command ); +extern void isic_next_state ( struct l1_softc *sc, int event ); +extern char *isic_printstate ( struct l1_softc *sc ); + +extern int isic_hscx_fifo(l1_bchan_state_t *, struct l1_softc *); +extern void isic_hscx_init ( struct l1_softc *sc, int hscx_channel, int activate ); +extern void isic_hscx_irq ( struct l1_softc *sc, u_char ista, int hscx_channel, u_char ex_irq ); +extern int isic_hscx_silence ( unsigned char *data, int len ); +extern void isic_hscx_cmd( struct l1_softc *sc, int h_chan, unsigned char cmd ); +extern void isic_hscx_waitxfw( struct l1_softc *sc, int h_chan ); + +extern int isic_probe_s016 (device_t dev); +extern int isic_attach_s016 (device_t dev); + +extern int isic_probe_s08 (device_t dev); +extern int isic_attach_s08 (device_t dev); + +extern int isic_probe_Epcc16 (device_t dev); +extern int isic_attach_Epcc16 (device_t dev); + +extern int isic_probe_s0163 (device_t dev); +extern int isic_attach_s0163 (device_t dev); + +extern int isic_probe_avma1 (device_t dev); +extern int isic_attach_avma1 (device_t dev); + +extern int isic_probe_usrtai (device_t dev); +extern int isic_attach_usrtai (device_t dev); + +extern int isic_probe_itkix1 (device_t dev); +extern int isic_attach_itkix1 (device_t dev); + +extern int isic_attach_drnngo (device_t dev); +extern int isic_attach_Cs0P (device_t dev); +extern int isic_attach_Eqs1pi(device_t dev); +extern int isic_attach_sws(device_t dev); +extern int isic_attach_siemens_isurf(device_t dev); +extern int isic_attach_asi(device_t dev); +extern int isic_attach_Dyn(device_t dev); +extern int isic_attach_diva(device_t dev); +extern int isic_attach_diva_ipac(device_t dev); + +#endif /* _I4B_ISIC_H_ */ diff --git a/sys/i4b/layer1/isic/i4b_isic_ext.h b/sys/i4b/layer1/isic/i4b_isic_ext.h new file mode 100644 index 000000000000..ba5ae4cc7594 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isic_ext.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *---------------------------------------------------------------------------* + * + * i4b_l1.h - isdn4bsd layer 1 header file + * --------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:11:12 2001] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_ISIC_EXT_H_ +#define _I4B_ISIC_EXT_H_ + +#include <i4b/include/i4b_l3l4.h> + +int isic_ph_data_req(int unit, struct mbuf *m, int freeflag); +int isic_ph_activate_req(int unit); +int isic_mph_command_req(int unit, int command, void *parm); + +void isic_set_linktab(int unit, int channel, drvr_link_t *dlt); +isdn_link_t *isic_ret_linktab(int unit, int channel); + +#endif /* _I4B_ISIC_H_ */ diff --git a/sys/i4b/layer1/isic/i4b_isic_isa.c b/sys/i4b/layer1/isic/i4b_isic_isa.c new file mode 100644 index 000000000000..87c9f0477cd5 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isic_isa.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_isa.c - ISA bus interface + * ================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:30:19 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> + +#include <sys/bus.h> +#include <isa/isavar.h> + +struct l1_softc l1_sc[ISIC_MAXUNIT]; + +static int isic_isa_probe(device_t dev); +static int isic_isa_attach(device_t dev); + +static device_method_t isic_methods[] = { + DEVMETHOD(device_probe, isic_isa_probe), + DEVMETHOD(device_attach, isic_isa_attach), + { 0, 0 } +}; + +static driver_t isic_driver = { + "isic", + isic_methods, + 0 +}; + +static devclass_t isic_devclass; + +DRIVER_MODULE(isic, isa, isic_driver, isic_devclass, 0, 0); + +/*---------------------------------------------------------------------------* + * probe for ISA non-PnP cards + *---------------------------------------------------------------------------*/ +static int +isic_isa_probe(device_t dev) +{ + int ret = ENXIO; + + if(isa_get_vendorid(dev)) /* no PnP probes here */ + return ENXIO; + + switch(device_get_flags(dev)) + { +#ifdef TEL_S0_16 + case CARD_TYPEP_16: + ret = isic_probe_s016(dev); + break; +#endif + +#ifdef TEL_S0_8 + case CARD_TYPEP_8: + ret = isic_probe_s08(dev); + break; +#endif + +#ifdef ELSA_PCC16 + case CARD_TYPEP_PCC16: + ret = isic_probe_Epcc16(dev); + break; +#endif + +#ifdef TEL_S0_16_3 + case CARD_TYPEP_16_3: + ret = isic_probe_s0163(dev); + break; +#endif + +#ifdef AVM_A1 + case CARD_TYPEP_AVMA1: + ret = isic_probe_avma1(dev); + break; +#endif + +#ifdef USR_STI + case CARD_TYPEP_USRTA: + ret = isic_probe_usrtai(dev); + break; +#endif + +#ifdef ITKIX1 + case CARD_TYPEP_ITKIX1: + ret = isic_probe_itkix1(dev); + break; +#endif + + default: + printf("isic%d: probe, unknown flag: %d\n", + device_get_unit(dev), device_get_flags(dev)); + break; + } + return(ret); +} + +/*---------------------------------------------------------------------------* + * attach for ISA non-PnP cards + *---------------------------------------------------------------------------*/ +static int +isic_isa_attach(device_t dev) +{ + int ret = ENXIO; + + struct l1_softc *sc = &l1_sc[device_get_unit(dev)]; + + sc->sc_unit = device_get_unit(dev); + + /* card dependent setup */ + + switch(sc->sc_cardtyp) + { +#ifdef TEL_S0_16 + case CARD_TYPEP_16: + ret = isic_attach_s016(dev); + break; +#endif + +#ifdef TEL_S0_8 + case CARD_TYPEP_8: + ret = isic_attach_s08(dev); + break; +#endif + +#ifdef ELSA_PCC16 + case CARD_TYPEP_PCC16: + ret = isic_attach_Epcc16(dev); + break; +#endif + +#ifdef TEL_S0_16_3 + case CARD_TYPEP_16_3: + ret = isic_attach_s0163(dev); + break; +#endif + +#ifdef AVM_A1 + case CARD_TYPEP_AVMA1: + ret = isic_attach_avma1(dev); + break; +#endif + +#ifdef USR_STI + case CARD_TYPEP_USRTA: + ret = isic_attach_usrtai(dev); + break; +#endif + +#ifdef ITKIX1 + case CARD_TYPEP_ITKIX1: + ret = isic_attach_itkix1(dev); + break; +#endif + + default: + printf("isic%d: attach, unknown flag: %d\n", + device_get_unit(dev), device_get_flags(dev)); + break; + } + + if(ret) + return(ret); + + ret = isic_attach_common(dev); + + return(ret); +} +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_isic_pnp.c b/sys/i4b/layer1/isic/i4b_isic_pnp.c new file mode 100644 index 000000000000..e02878d31a96 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_isic_pnp.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 1998 Eivind Eklund. All rights reserved. + * + * Copyright (c) 1998, 1999 German Tischler. All rights reserved. + * + * Copyright (c) 1998, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_pnp.c - i4b pnp support + * -------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Fri Jan 26 14:01:04 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <i4b/layer1/isic/i4b_isic.h> + +#include <isa/isavar.h> + +#define VID_TEL163PNP 0x10212750 /* Teles 16.3 PnP */ +#define VID_CREATIXPP 0x0000980e /* Creatix S0/16 P+P */ +#define VID_DYNALINK 0x88167506 /* Dynalink */ +#define VID_SEDLBAUER 0x0100274c /* Sedlbauer WinSpeed */ +#define VID_NICCYGO 0x5001814c /* Neuhaus Niccy GO@ */ +#define VID_ELSAQS1P 0x33019315 /* ELSA Quickstep1000pro*/ +#define VID_ITK0025 0x25008b26 /* ITK Ix1 Micro V3 */ +#define VID_AVMPNP 0x0009cd06 /* AVM Fritz! PnP */ +#define VID_SIESURF2 0x2000254d /* Siemens I-Surf 2.0 PnP*/ +#define VID_ASUSCOM_IPAC 0x90167506 /* Asuscom (with IPAC) */ +#define VID_EICON_DIVA_20 0x7100891c /* Eicon DIVA 2.0 ISAC/HSCX */ +#define VID_EICON_DIVA_202 0xa100891c /* Eicon DIVA 2.02 IPAC */ + +static struct isic_pnp_ids { + u_long vend_id; + char *id_str; +} isic_pnp_ids[] = { +#if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P) + { VID_TEL163PNP, "Teles S0/16.3 PnP" }, + { VID_CREATIXPP, "Creatix S0/16 PnP" }, +#endif +#ifdef DYNALINK + { VID_DYNALINK, "Dynalink IS64PH" }, +#endif +#ifdef SEDLBAUER + { VID_SEDLBAUER, "Sedlbauer WinSpeed" }, +#endif +#ifdef DRN_NGO + { VID_NICCYGO, "Dr.Neuhaus Niccy Go@" }, +#endif +#ifdef ELSA_QS1ISA + { VID_ELSAQS1P, "ELSA QuickStep 1000pro" }, +#endif +#ifdef ITKIX1 + { VID_ITK0025, "ITK ix1 Micro V3.0" }, +#endif +#ifdef AVM_PNP + { VID_AVMPNP, "AVM Fritz!Card PnP" }, +#endif +#ifdef SIEMENS_ISURF2 + { VID_SIESURF2, "Siemens I-Surf 2.0 PnP" }, +#endif +#ifdef ASUSCOM_IPAC + { VID_ASUSCOM_IPAC, "Asuscom ISDNLink 128 PnP" }, +#endif +#ifdef EICON_DIVA + { VID_EICON_DIVA_20, "Eicon.Diehl DIVA 2.0 ISA PnP" }, + { VID_EICON_DIVA_202, "Eicon.Diehl DIVA 2.02 ISA PnP" }, +#endif + { 0, 0 } +}; + +static int isic_pnp_probe(device_t dev); +static int isic_pnp_attach(device_t dev); + +static device_method_t isic_pnp_methods[] = { + DEVMETHOD(device_probe, isic_pnp_probe), + DEVMETHOD(device_attach, isic_pnp_attach), + { 0, 0 } +}; + +static driver_t isic_pnp_driver = { + "isic", + isic_pnp_methods, + 0, +}; + +static devclass_t isic_devclass; + +DRIVER_MODULE(isicpnp, isa, isic_pnp_driver, isic_devclass, 0, 0); + +/*---------------------------------------------------------------------------* + * probe for ISA PnP cards + *---------------------------------------------------------------------------*/ +int +isic_pnp_probe(device_t dev) +{ + struct isic_pnp_ids *ids; /* pnp id's */ + char *string = NULL; /* the name */ + u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */ + + /* search table of knowd id's */ + + for(ids = isic_pnp_ids; ids->vend_id != 0; ids++) + { + if(vend_id == ids->vend_id) + { + string = ids->id_str; + break; + } + } + + if(string) /* set name if we have one */ + { + device_set_desc(dev, string); /* set description */ + return 0; + } + else + { + return ENXIO; + } +} + +/*---------------------------------------------------------------------------* + * attach for ISA PnP cards + *---------------------------------------------------------------------------*/ +int +isic_pnp_attach(device_t dev) +{ + u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */ + unsigned int unit = device_get_unit(dev); /* get unit */ + const char *name = device_get_desc(dev); /* get description */ + struct l1_softc *sc = 0; /* softc */ + void *ih = 0; /* a dummy */ + int ret; + + /* see if we are out of bounds */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", unit, unit, name); + return ENXIO; + } + + /* get information structure for this unit */ + + sc = &l1_sc[unit]; + + /* get io_base */ + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0UL, ~0UL, 1, RF_ACTIVE ) )) + { + printf("isic_pnp_attach: Couldn't get my io_base.\n"); + return ENXIO; + } + + /* will not be used for pnp devices */ + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + + /* get irq, release io_base if we don't get it */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0UL, ~0UL, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get irq.\n",unit); + isic_detach_common(dev); + return ENXIO; + } + + /* not needed */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + + /* set flag so we know what this card is */ + + ret = ENXIO; + + switch(vend_id) + { +#if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P) + case VID_TEL163PNP: + sc->sc_cardtyp = CARD_TYPEP_163P; + ret = isic_attach_Cs0P(dev); + break; + + case VID_CREATIXPP: + sc->sc_cardtyp = CARD_TYPEP_CS0P; + ret = isic_attach_Cs0P(dev); + break; +#endif +#ifdef DYNALINK + case VID_DYNALINK: + sc->sc_cardtyp = CARD_TYPEP_DYNALINK; + ret = isic_attach_Dyn(dev); + break; +#endif +#ifdef SEDLBAUER + case VID_SEDLBAUER: + sc->sc_cardtyp = CARD_TYPEP_SWS; + ret = isic_attach_sws(dev); + break; +#endif +#ifdef DRN_NGO + case VID_NICCYGO: + sc->sc_cardtyp = CARD_TYPEP_DRNNGO; + ret = isic_attach_drnngo(dev); + break; +#endif +#ifdef ELSA_QS1ISA + case VID_ELSAQS1P: + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; + ret = isic_attach_Eqs1pi(dev); + break; +#endif +#ifdef ITKIX1 + case VID_ITK0025: + sc->sc_cardtyp = CARD_TYPEP_ITKIX1; + ret = isic_attach_itkix1(dev); + break; +#endif +#ifdef SIEMENS_ISURF2 + case VID_SIESURF2: + sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; + ret = isic_attach_siemens_isurf(dev); + break; +#endif +#ifdef ASUSCOM_IPAC + case VID_ASUSCOM_IPAC: + sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; + ret = isic_attach_asi(dev); + break; +#endif +#ifdef EICON_DIVA + case VID_EICON_DIVA_20: + sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; + ret = isic_attach_diva(dev); + break; + + case VID_EICON_DIVA_202: + sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; + ret = isic_attach_diva_ipac(dev); + break; +#endif + default: + printf("isic%d: Error, no driver for %s\n", unit, name); + ret = ENXIO; + break; + } + + if(ret) + { + isic_detach_common(dev); + return ENXIO; + } + + if(isic_attach_common(dev)) + { + /* unset flag */ + sc->sc_cardtyp = CARD_TYPEP_UNK; + + /* free irq here, it hasn't been attached yet */ + bus_release_resource(dev,SYS_RES_IRQ,sc->sc_resources.irq_rid, + sc->sc_resources.irq); + sc->sc_resources.irq = 0; + isic_detach_common(dev); + return ENXIO; + } + else + { + /* setup intr routine */ + bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET, + (void(*)(void*))isicintr, + sc,&ih); + return 0; + } +} +#endif /* (NISIC > 0) */ diff --git a/sys/i4b/layer1/isic/i4b_itk_ix1.c b/sys/i4b/layer1/isic/i4b_itk_ix1.c new file mode 100644 index 000000000000..71307736cd7a --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_itk_ix1.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 1998, 1999 Martin Husemann <martin@rumolt.teuto.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_itk_ix1.c - ITK ix1 micro passive card driver for isdn4bsd + * -------------------------------------------------------------- + * + * last edit-date: [Wed Jan 24 09:27:06 2001] + * + * $FreeBSD$ + * + *--------------------------------------------------------------------------- + * + * The ITK ix1 micro ISDN card is an ISA card with one region + * of four io ports mapped and a fixed irq all jumpered on the card. + * Access to the board is straight forward and simmilar to + * the ELSA and DYNALINK cards. If a PCI version of this card + * exists all we need is probably a pci-bus attachment, all + * this low level routines should work imediately. + * + * To reset the card: + * - write 0x01 to ITK_CONFIG + * - wait >= 10 ms + * - write 0x00 to ITK_CONFIG + * + * To read or write data: + * - write address to ITK_ALE port + * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port + * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40). + * + * The probe routine was derived by trial and error from a representative + * sample of two cards ;-) The standard way (checking HSCX versions) + * was extended by reading a zero from a non existant HSCX register (register + * 0xff). Reading the config register gives varying results, so this doesn't + * seem to be used as an id register (like the Teles S0/16.3). + * + * If the probe fails for your card use "options ITK_PROBE_DEBUG" to get + * additional debug output. + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(ITKIX1) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/* Register offsets */ +#define ITK_ISAC_DATA 0 +#define ITK_HSCX_DATA 1 +#define ITK_ALE 2 +#define ITK_CONFIG 3 + +/* Size of IO range to allocate for this card */ +#define ITK_IO_SIZE 4 + +/* Register offsets for the two HSCX channels */ +#define HSCXA 0 +#define HSCXB 0x40 + +static void +itkix1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + switch (what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, 0); + bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA); + bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB); + bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); + break; + } +} + +static void +itkix1_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + switch (what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, 0); + bus_space_write_multi_1(t, h, ITK_ISAC_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA); + bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB); + bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size); + break; + } +} + +static void +itkix1_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + switch (what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, offs); + bus_space_write_1(t, h, ITK_ISAC_DATA, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA+offs); + bus_space_write_1(t, h, ITK_HSCX_DATA, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB+offs); + bus_space_write_1(t, h, ITK_HSCX_DATA, data); + break; + } +} + +static u_int8_t +itkix1_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + switch (what) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, offs); + return bus_space_read_1(t, h, ITK_ISAC_DATA); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA+offs); + return bus_space_read_1(t, h, ITK_HSCX_DATA); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB+offs); + return bus_space_read_1(t, h, ITK_HSCX_DATA); + } + return 0; +} + +/* + * Probe for card + */ +int +isic_probe_itkix1(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* softc */ + void *ih = 0; /* dummy */ + bus_space_tag_t t; /* bus things */ + bus_space_handle_t h; + u_int8_t hd, hv1, hv2, saveale; + int ret; + + #if defined(ITK_PROBE_DEBUG) + printf("Checking unit %u\n", unit); + #endif + + /* check max unit range */ + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ITK IX1!\n", + unit, unit); + return ENXIO; + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + #if defined(ITK_PROBE_DEBUG) + printf("Allocating io base..."); + #endif + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not allocate i/o port for ITK IX1.\n", unit); + return ENXIO; + } + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + #endif + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + t = rman_get_bustag(sc->sc_resources.io_base[0]); + h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + #if defined(ITK_PROBE_DEBUG) + printf("Allocating irq..."); + #endif + + /* get our irq */ + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not allocate irq for ITK IX1.\n", unit); + bus_release_resource(dev,SYS_RES_IOPORT, + sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + return ENXIO; + } + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + #endif + + /* get the irq number */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + #if defined(ITK_PROBE_DEBUG) + printf("Setting up access routines..."); + #endif + + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = itkix1_read_reg; + sc->writereg = itkix1_write_reg; + sc->readfifo = itkix1_read_fifo; + sc->writefifo = itkix1_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_ITKIX1; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + #endif + + /* register interupt routine */ + + #if defined(ITK_PROBE_DEBUG) + printf("Setting up access interupt..."); + #endif + + bus_setup_intr(dev, sc->sc_resources.irq, + INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + + printf("Doing probe stuff..."); + #endif + + /* save old value of this port, we're stomping over it */ + saveale = bus_space_read_1(t, h, ITK_ALE); + + /* select invalid register */ + bus_space_write_1(t, h, ITK_ALE, 0xff); + /* get HSCX data for this non existent register */ + hd = bus_space_read_1(t, h, ITK_HSCX_DATA); + /* get HSCX version info */ + bus_space_write_1(t, h, ITK_ALE, HSCXA + H_VSTR); + hv1 = bus_space_read_1(t, h, ITK_HSCX_DATA); + bus_space_write_1(t, h, ITK_ALE, HSCXB + H_VSTR); + hv2 = bus_space_read_1(t, h, ITK_HSCX_DATA); + + ret = (hd == 0) && ((hv1 & 0x0f) == 0x05) && ((hv2 & 0x0f) == 0x05); + /* succeed if version bits are OK and we got a zero from the + * non existent register. we found verison 0x05 and 0x04 + * out there... */ + ret = (hd == 0) + && (((hv1 & 0x0f) == 0x05) || ((hv1 & 0x0f) == 0x04)) + && (((hv2 & 0x0f) == 0x05) || ((hv2 & 0x0f) == 0x04)); + + /* retstore save value if we fail (if we succeed the old value + * has no meaning) */ + if (!ret) + bus_space_write_1(t, h, ITK_ALE, saveale); + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + + printf("Doing second probe stuff..."); + #endif + + hv1 = HSCX_READ(0, H_VSTR) & 0xf; + hv2 = HSCX_READ(1, H_VSTR) & 0xf; + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1) or 0x04 (V2.0). */ + if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04)) + { + printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n", + unit); + printf("isic%d: HSC0: VSTR: %#x\n", + unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + unit, HSCX_READ(1, H_VSTR)); + isic_detach_common(dev); + return ENXIO; + } + + #if defined(ITK_PROBE_DEBUG) + printf("done.\n"); + #endif + +#if defined(ITK_PROBE_DEBUG) + printf("\nITK ix1 micro probe: hscx = 0x%02x, v1 = 0x%02x, v2 = 0x%02x, would have %s\n", + hd, hv1, hv2, ret ? "succeeded" : "failed"); + isic_detach_common(dev); + return ENXIO; +#else + if ( ret ) + { + return 0; + } + else + { + isic_detach_common(dev); + return ENXIO; + } +#endif +} + +/* + * Attach card + */ +int +isic_attach_itkix1(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = itkix1_read_reg; + sc->writereg = itkix1_write_reg; + sc->readfifo = itkix1_read_fifo; + sc->writefifo = itkix1_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_ITKIX1; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + bus_space_write_1(t, h, ITK_CONFIG, 1); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, ITK_CONFIG, 0); + DELAY(SEC_DELAY / 10); + + return 0; +} + +#endif /* ITKIX1 */ diff --git a/sys/i4b/layer1/isic/i4b_l1.c b/sys/i4b/layer1/isic/i4b_l1.c new file mode 100644 index 000000000000..d68a480b2281 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_l1.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1.c - isdn4bsd layer 1 handler + * ----------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:12:03 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_isac.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +/*---------------------------------------------------------------------------* + * + * L2 -> L1: PH-DATA-REQUEST + * ========================= + * + * parms: + * unit physical interface unit number + * m mbuf containing L2 frame to be sent out + * freeflag MBUF_FREE: free mbuf here after having sent + * it out + * MBUF_DONTFREE: mbuf is freed by Layer 2 + * returns: + * ==0 fail, nothing sent out + * !=0 ok, frame sent out + * + *---------------------------------------------------------------------------*/ +int +isic_ph_data_req(int unit, struct mbuf *m, int freeflag) +{ + u_char cmd; + int s; + struct l1_softc *sc = &l1_sc[unit]; + +#ifdef NOTDEF + NDBGL1(L1_PRIM, "unit %d, freeflag=%d", unit, freeflag); +#endif + + if(m == NULL) /* failsafe */ + return (0); + + s = SPLI4B(); + + if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */ + { + NDBGL1(L1_I_ERR, "still in state F3!"); + isic_ph_activate_req(unit); + } + + if(sc->sc_state & ISAC_TX_ACTIVE) + { + if(sc->sc_obuf2 == NULL) + { + sc->sc_obuf2 = m; /* save mbuf ptr */ + + if(freeflag) + sc->sc_freeflag2 = 1; /* IRQ must mfree */ + else + sc->sc_freeflag2 = 0; /* IRQ must not mfree */ + + NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc)); + + if(sc->sc_trace & TRACE_D_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(unit); + hdr.type = TRC_CH_D; + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); + } + splx(s); + return(1); + } + + NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", isic_printstate(sc)); + + if(freeflag == MBUF_FREE) + i4b_Dfreembuf(m); + + splx(s); + return (0); + } + + if(sc->sc_trace & TRACE_D_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = L0ISICUNIT(unit); + hdr.type = TRC_CH_D; + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, m->m_len, m->m_data); + } + + sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */ + + NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set"); + + sc->sc_freeflag = 0; /* IRQ must NOT mfree */ + + ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */ + + if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */ + { + sc->sc_obuf = m; /* save mbuf ptr */ + sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */ + sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */ + + if(freeflag) + sc->sc_freeflag = 1; /* IRQ must mfree */ + + cmd = ISAC_CMDR_XTF; + } + else + { + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + + if(freeflag) + i4b_Dfreembuf(m); + + cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME; + } + + ISAC_WRITE(I_CMDR, cmd); + ISACCMDRWRDELAY(); + + splx(s); + + return(1); +} + +/*---------------------------------------------------------------------------* + * + * L2 -> L1: PH-ACTIVATE-REQUEST + * ============================= + * + * parms: + * unit physical interface unit number + * + * returns: + * ==0 + * !=0 + * + *---------------------------------------------------------------------------*/ +int +isic_ph_activate_req(int unit) +{ + struct l1_softc *sc = &l1_sc[unit]; + NDBGL1(L1_PRIM, "unit %d", unit); + isic_next_state(sc, EV_PHAR); + return(0); +} + +/*---------------------------------------------------------------------------* + * command from the upper layers + *---------------------------------------------------------------------------*/ +int +isic_mph_command_req(int unit, int command, void *parm) +{ + struct l1_softc *sc = &l1_sc[unit]; + + switch(command) + { + case CMR_DOPEN: /* daemon running */ + NDBGL1(L1_PRIM, "unit %d, command = CMR_DOPEN", unit); + sc->sc_enabled = 1; + break; + + case CMR_DCLOSE: /* daemon not running */ + NDBGL1(L1_PRIM, "unit %d, command = CMR_DCLOSE", unit); + sc->sc_enabled = 0; + break; + + case CMR_SETTRACE: + NDBGL1(L1_PRIM, "unit %d, command = CMR_SETTRACE, parm = %d", unit, (unsigned int)parm); + sc->sc_trace = (unsigned int)parm; + break; + + case CMR_GCST: + { + struct chipstat *cst; + NDBGL1(L1_PRIM, "unit %d, command = CMR_GCST, parm = %d", unit, (unsigned int)parm); + cst = (struct chipstat *)parm; + cst->driver_type = L1DRVR_ISIC; + cst->stats.hscxstat.unit = sc->sc_unit; + cst->stats.hscxstat.chan = cst->driver_bchannel; + cst->stats.hscxstat.vfr = sc->sc_chan[cst->driver_bchannel].stat_VFR; + cst->stats.hscxstat.rdo = sc->sc_chan[cst->driver_bchannel].stat_RDO; + cst->stats.hscxstat.crc = sc->sc_chan[cst->driver_bchannel].stat_CRC; + cst->stats.hscxstat.rab = sc->sc_chan[cst->driver_bchannel].stat_RAB; + cst->stats.hscxstat.xdu = sc->sc_chan[cst->driver_bchannel].stat_XDU; + cst->stats.hscxstat.rfo = sc->sc_chan[cst->driver_bchannel].stat_RFO; + break; + } + default: + NDBGL1(L1_ERROR, "ERROR, unknown command = %d, unit = %d, parm = %d", command, unit, (unsigned int)parm); + break; + } + + return(0); +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_l1fsm.c b/sys/i4b/layer1/isic/i4b_l1fsm.c new file mode 100644 index 000000000000..11c261d9e377 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_l1fsm.c @@ -0,0 +1,512 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine + * -------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:12:18 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if NISIC > 0 + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/isic/i4b_isic.h> + +#include <i4b/layer1/i4b_l1.h> + +#include <i4b/include/i4b_global.h> + +#include <i4b/include/i4b_mbuf.h> + +#if DO_I4B_DEBUG +static char *state_text[N_STATES] = { + "F3 Deactivated", + "F4 Awaiting Signal", + "F5 Identifying Input", + "F6 Synchronized", + "F7 Activated", + "F8 Lost Framing", + "Illegal State" +}; + +static char *event_text[N_EVENTS] = { + "EV_PHAR PH_ACT_REQ", + "EV_T3 Timer 3 expired", + "EV_INFO0 INFO0 received", + "EV_RSY Level Detected", + "EV_INFO2 INFO2 received", + "EV_INFO48 INFO4 received", + "EV_INFO410 INFO4 received", + "EV_DR Deactivate Req", + "EV_PU Power UP", + "EV_DIS Disconnected", + "EV_EI Error Ind", + "Illegal Event" +}; +#endif + +/* Function prototypes */ + +static void timer3_expired (struct l1_softc *sc); +static void T3_start (struct l1_softc *sc); +static void T3_stop (struct l1_softc *sc); +static void F_T3ex (struct l1_softc *sc); +static void timer4_expired (struct l1_softc *sc); +static void T4_start (struct l1_softc *sc); +static void T4_stop (struct l1_softc *sc); +static void F_AI8 (struct l1_softc *sc); +static void F_AI10 (struct l1_softc *sc); +static void F_I01 (struct l1_softc *sc); +static void F_I02 (struct l1_softc *sc); +static void F_I03 (struct l1_softc *sc); +static void F_I2 (struct l1_softc *sc); +static void F_ill (struct l1_softc *sc); +static void F_NULL (struct l1_softc *sc); + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 expire function + *---------------------------------------------------------------------------*/ +static void +timer3_expired(struct l1_softc *sc) +{ + if(sc->sc_I430T3) + { + NDBGL1(L1_T_ERR, "state = %s", isic_printstate(sc)); + sc->sc_I430T3 = 0; + + /* XXX try some recovery here XXX */ + + isic_recover(sc); + + sc->sc_init_tries++; /* increment retry count */ + +/*XXX*/ if(sc->sc_init_tries > 4) + { + int s = SPLI4B(); + + sc->sc_init_tries = 0; + + if(sc->sc_obuf2 != NULL) + { + i4b_Dfreembuf(sc->sc_obuf2); + sc->sc_obuf2 = NULL; + } + if(sc->sc_obuf != NULL) + { + i4b_Dfreembuf(sc->sc_obuf); + sc->sc_obuf = NULL; + sc->sc_freeflag = 0; + sc->sc_op = NULL; + sc->sc_ol = 0; + } + + splx(s); + + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL); + } + + isic_next_state(sc, EV_T3); + } + else + { + NDBGL1(L1_T_ERR, "expired without starting it ...."); + } +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 start + *---------------------------------------------------------------------------*/ +static void +T3_start(struct l1_softc *sc) +{ + NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); + sc->sc_I430T3 = 1; + sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, 2*hz); +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 stop + *---------------------------------------------------------------------------*/ +static void +T3_stop(struct l1_softc *sc) +{ + NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); + + sc->sc_init_tries = 0; /* init connect retry count */ + + if(sc->sc_I430T3) + { + sc->sc_I430T3 = 0; + untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, sc->sc_T3_callout); + } +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 expiry + *---------------------------------------------------------------------------*/ +static void +F_T3ex(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_T3ex executing"); + if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S) + i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit)); +} + +/*---------------------------------------------------------------------------* + * Timer T4 expire function + *---------------------------------------------------------------------------*/ +static void +timer4_expired(struct l1_softc *sc) +{ + if(sc->sc_I430T4) + { + NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); + sc->sc_I430T4 = 0; + i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_PDEACT, 0, NULL); + } + else + { + NDBGL1(L1_T_ERR, "expired without starting it ...."); + } +} + +/*---------------------------------------------------------------------------* + * Timer T4 start + *---------------------------------------------------------------------------*/ +static void +T4_start(struct l1_softc *sc) +{ + NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); + sc->sc_I430T4 = 1; + sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, hz); +} + +/*---------------------------------------------------------------------------* + * Timer T4 stop + *---------------------------------------------------------------------------*/ +static void +T4_stop(struct l1_softc *sc) +{ + NDBGL1(L1_T_MSG, "state = %s", isic_printstate(sc)); + + if(sc->sc_I430T4) + { + sc->sc_I430T4 = 0; + untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, sc->sc_T4_callout); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received AI8 + *---------------------------------------------------------------------------*/ +static void +F_AI8(struct l1_softc *sc) +{ + T4_stop(sc); + + NDBGL1(L1_F_MSG, "FSM function F_AI8 executing"); + + if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S) + i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit)); + + T3_stop(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO4_8; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received AI10 + *---------------------------------------------------------------------------*/ +static void +F_AI10(struct l1_softc *sc) +{ + T4_stop(sc); + + NDBGL1(L1_F_MSG, "FSM function F_AI10 executing"); + + if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S) + i4b_l1_ph_activate_ind(L0ISICUNIT(sc->sc_unit)); + + T3_stop(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO4_10; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in states F3 .. F5 + *---------------------------------------------------------------------------*/ +static void +F_I01(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_I01 executing"); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in state F6 + *---------------------------------------------------------------------------*/ +static void +F_I02(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_I02 executing"); + + if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S) + i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit)); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in state F7 or F8 + *---------------------------------------------------------------------------*/ +static void +F_I03(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_I03 executing"); + + if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S) + i4b_l1_ph_deactivate_ind(L0ISICUNIT(sc->sc_unit)); + + T4_start(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: activate request + *---------------------------------------------------------------------------*/ +static void +F_AR(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_AR executing"); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO1_8; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_TE; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } + + isic_isac_l1_cmd(sc, CMD_AR8); + + T3_start(sc); +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO2 + *---------------------------------------------------------------------------*/ +static void +F_I2(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_I2 executing"); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO2; + + hdr.unit = L0ISICUNIT(sc->sc_unit); + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + i4b_l1_trace_ind(&hdr, 1, &info); + } + +} + +/*---------------------------------------------------------------------------* + * illegal state default action + *---------------------------------------------------------------------------*/ +static void +F_ill(struct l1_softc *sc) +{ + NDBGL1(L1_F_ERR, "FSM function F_ill executing"); +} + +/*---------------------------------------------------------------------------* + * No action + *---------------------------------------------------------------------------*/ +static void +F_NULL(struct l1_softc *sc) +{ + NDBGL1(L1_F_MSG, "FSM function F_NULL executing"); +} + + +/*---------------------------------------------------------------------------* + * layer 1 state transition table + *---------------------------------------------------------------------------*/ +struct isic_state_tab { + void (*func) (struct l1_softc *sc); /* function to execute */ + int newstate; /* next state */ +} isic_state_tab[N_EVENTS][N_STATES] = { + +/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */ +/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}}, +/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}}, +/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}}, +/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}}, +/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}}, +/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}} +}; + +/*---------------------------------------------------------------------------* + * event handler + *---------------------------------------------------------------------------*/ +void +isic_next_state(struct l1_softc *sc, int event) +{ + int currstate, newstate; + + if(event >= N_EVENTS) + panic("i4b_l1fsm.c: event >= N_EVENTS\n"); + + currstate = sc->sc_I430state; + + if(currstate >= N_STATES) + panic("i4b_l1fsm.c: currstate >= N_STATES\n"); + + newstate = isic_state_tab[event][currstate].newstate; + + if(newstate >= N_STATES) + panic("i4b_l1fsm.c: newstate >= N_STATES\n"); + + NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event], + state_text[currstate], + state_text[newstate]); + + (*isic_state_tab[event][currstate].func)(sc); + + if(newstate == ST_ILL) + { + newstate = ST_F3; + NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!", + state_text[currstate], + state_text[newstate], + event_text[event]); + } + + sc->sc_I430state = newstate; +} + +#if DO_I4B_DEBUG +/*---------------------------------------------------------------------------* + * return pointer to current state description + *---------------------------------------------------------------------------*/ +char * +isic_printstate(struct l1_softc *sc) +{ + return((char *) state_text[sc->sc_I430state]); +} +#endif + +#endif /* NISIC > 0 */ + diff --git a/sys/i4b/layer1/isic/i4b_siemens_isurf.c b/sys/i4b/layer1/isic/i4b_siemens_isurf.c new file mode 100644 index 000000000000..d846d437503e --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_siemens_isurf.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999, 2000 Udo Schweigert. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * Siemens I-Surf 2.0 PnP specific routines for isic driver + * -------------------------------------------------------- + * + * Based on ELSA Quickstep 1000pro PCI driver (i4b_elsa_qs1p.c) + * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de> + + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:13:25 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(SIEMENS_ISURF2) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> + +#include <machine/i4b_ioctl.h> + +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_ipac.h> + +/* masks for register encoded in base addr */ + +#define SIE_ISURF_BASE_MASK 0x0ffff +#define SIE_ISURF_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define SIE_ISURF_IDISAC 0x00000 +#define SIE_ISURF_IDHSCXA 0x10000 +#define SIE_ISURF_IDHSCXB 0x20000 +#define SIE_ISURF_IDIPAC 0x40000 + +/* offsets from base address */ + +#define SIE_ISURF_OFF_ALE 0x00 +#define SIE_ISURF_OFF_RW 0x01 + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +siemens_isurf_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_ISAC_OFF); + bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_read_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC put fifo routine + *---------------------------------------------------------------------------*/ +static void +siemens_isurf_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_ISAC_OFF); + bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXA_OFF); + bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,IPAC_HSCXB_OFF); + bus_space_write_multi_1(t,h,SIE_ISURF_OFF_RW,buf,size); + break; + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +siemens_isurf_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_ISAC_OFF); + bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXA_OFF); + bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXB_OFF); + bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_IPAC_OFF); + bus_space_write_1(t,h,SIE_ISURF_OFF_RW,data); + break; + } +} + +/*---------------------------------------------------------------------------* + * Siemens I-Surf 2.0 PnP ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +siemens_isurf_read_reg(struct l1_softc *sc,int what,bus_size_t reg) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) + { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_ISAC_OFF); + return bus_space_read_1(t,h,SIE_ISURF_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXA_OFF); + return bus_space_read_1(t,h,SIE_ISURF_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_HSCXB_OFF); + return bus_space_read_1(t,h,SIE_ISURF_OFF_RW); + case ISIC_WHAT_IPAC: + bus_space_write_1(t,h,SIE_ISURF_OFF_ALE,reg+IPAC_IPAC_OFF); + return bus_space_read_1(t,h,SIE_ISURF_OFF_RW); + default: + return 0; + } +} + +/*---------------------------------------------------------------------------* + * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP + *---------------------------------------------------------------------------*/ +int +isic_attach_siemens_isurf(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = siemens_isurf_read_reg; + sc->writereg = siemens_isurf_write_reg; + + sc->readfifo = siemens_isurf_read_fifo; + sc->writefifo = siemens_isurf_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* enable hscx/isac irq's */ + + IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */ + IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */ + (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2)); + IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */ + + return(0); +} +#endif /* NISIC > 0 && defined(SIEMENS_ISURF2) */ diff --git a/sys/i4b/layer1/isic/i4b_sws.c b/sys/i4b/layer1/isic/i4b_sws.c new file mode 100644 index 000000000000..cfe9372ca7d2 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_sws.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 1998, 2000 German Tischler. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * Card format: + * + * iobase + 0 : reset on (0x03) + * iobase + 1 : reset off (0x0) + * iobase + 2 : isac read/write + * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 , + * offset 0x40-0x7f hscx1 ) + * iobase + 4 : offset for indirect adressing + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for SWS cards + * ==================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 08:58:57 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if defined (SEDLBAUER) && NISIC > 0 + +#define SWS_RESON 0 /* reset on */ +#define SWS_RESOFF 1 /* reset off */ +#define SWS_ISAC 2 /* ISAC */ +#define SWS_HSCX0 3 /* HSCX0 */ +#define SWS_RW 4 /* indirect access register */ +#define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */ + /* access is done through hscx0 */ + +#define SWS_REGS 8 /* we use an area of 8 bytes for io */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * SWS P&P ISAC get fifo routine + *---------------------------------------------------------------------------*/ +static void +sws_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) { + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SWS_RW,0x0); + bus_space_read_multi_1(t,h,SWS_ISAC,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SWS_RW,0x0); + bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SWS_RW,0x0+0x40); + bus_space_read_multi_1(t,h,SWS_HSCX0,buf,size); + break; + } +} + +static void +sws_write_fifo(struct l1_softc *sc,int what,void *buf,size_t size) { + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SWS_RW,0x0); + bus_space_write_multi_1(t,h,SWS_ISAC,buf,size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SWS_RW,0x0); + bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SWS_RW,0x0+0x40); + bus_space_write_multi_1(t,h,SWS_HSCX0,buf,size); + break; + } +} + +static void +sws_write_reg(struct l1_softc *sc,int what,bus_size_t reg,u_int8_t data) { + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SWS_RW,reg); + bus_space_write_1(t,h,SWS_ISAC,data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SWS_RW,reg); + bus_space_write_1(t,h,SWS_HSCX0,data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SWS_RW,reg+0x40); + bus_space_write_1(t,h,SWS_HSCX0,data); + break; + } +} + +static u_char +sws_read_reg (struct l1_softc *sc,int what,bus_size_t reg) { + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + switch ( what ) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t,h,SWS_RW,reg); + return bus_space_read_1(t,h,SWS_ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t,h,SWS_RW,reg); + return bus_space_read_1(t,h,SWS_HSCX0); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t,h,SWS_RW,reg+0x40); + return bus_space_read_1(t,h,SWS_HSCX0); + default: + return 0; + } +} + +/* attach callback routine */ +int +isic_attach_sws(device_t dev) +{ + int unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + + struct i4b_info * info = &(sc->sc_resources); + bus_space_tag_t t = rman_get_bustag(info->io_base[0]); + bus_space_handle_t h = rman_get_bushandle(info->io_base[0]); + + /* fill in l1_softc structure */ + sc->readreg = sws_read_reg; + sc->writereg = sws_write_reg; + sc->readfifo = sws_read_fifo; + sc->writefifo = sws_write_fifo; + sc->clearirq = NULL; + sc->sc_cardtyp = CARD_TYPEP_SWS; + sc->sc_bustyp = BUS_TYPE_IOM2; + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* + * Read HSCX A/B VSTR. Expected value for the SWS PnP card is + * 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for SWS PnP\n", + sc->sc_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + sc->sc_unit, HSCX_READ(1, H_VSTR)); + return (ENXIO); + } + + /* reset card */ + bus_space_write_1(t,h,SWS_RESON,0x3); + DELAY(SEC_DELAY / 5); + bus_space_write_1(t,h,SWS_RESOFF,0x0); + DELAY(SEC_DELAY / 5); + + return(0); +} +#endif /* defined(SEDLBAUER) && NISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_tel_s016.c b/sys/i4b/layer1/isic/i4b_tel_s016.c new file mode 100644 index 000000000000..4e2b67fc1874 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_tel_s016.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16 and clones + * ================================================================= + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:27:24 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(TEL_S0_16) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/md_var.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#define TELES_S016_MEMSIZE 0x1000 + +static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 }; +static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 }; + +/*---------------------------------------------------------------------------* + * Teles S0/16 write register routine + *---------------------------------------------------------------------------*/ +static void +tels016_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + + offs += offset[what]; + + if (offs & 0x01) + offs |= 0x200; + + bus_space_write_1(t, h, offs, data); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16 read register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +tels016_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + + offs += offset[what]; + + if(offs & 0x01) + offs |= 0x200; + + return bus_space_read_1(t, h, offs); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16 fifo write routine + *---------------------------------------------------------------------------*/ +static void +tels016_write_fifo(struct l1_softc *sc, int what, void *data, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + bus_space_write_region_1(t, h, offset[what], data, size); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16 fifo read routine + *---------------------------------------------------------------------------*/ +static void +tels016_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + bus_space_read_region_1(t, h, offset[what], buf, size); +} + +/*---------------------------------------------------------------------------* + * isic_probe_s016 - probe for Teles S0/16 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_probe_s016(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* softc */ + void *ih = 0; /* dummy */ + u_int8_t b0,b1,b2; /* for signature */ + bus_space_tag_t t; /* bus things */ + bus_space_handle_t h; + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not allocate i/o port for Teles S0/16.\n", unit); + return(ENXIO); + } + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + + /* + * check if the provided io port is valid + */ + + switch(sc->sc_port) + { + case 0xd80: + case 0xe80: + case 0xf80: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n", + unit, sc->sc_port); + isic_detach_common(dev); + return(ENXIO); + break; + } + + /* allocate memory resource */ + + if(!(sc->sc_resources.mem = + bus_alloc_resource(dev, SYS_RES_MEMORY, + &sc->sc_resources.mem_rid, + 0ul, ~0ul, TELES_S016_MEMSIZE, + RF_ACTIVE))) + { + printf("isic%d: Could not allocate memory for Teles S0/16.\n", unit); + isic_detach_common(dev); + return(ENXIO); + } + + /* + * get virtual addr. + */ + sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem); + + /* + * check for valid adresses + */ + switch(kvtop(sc->sc_vmem_addr)) + { + case 0xc0000: + case 0xc2000: + case 0xc4000: + case 0xc6000: + case 0xc8000: + case 0xca000: + case 0xcc000: + case 0xce000: + case 0xd0000: + case 0xd2000: + case 0xd4000: + case 0xd6000: + case 0xd8000: + case 0xda000: + case 0xdc000: + case 0xde000: + break; + + default: + printf("isic%d: Error, invalid memory address 0x%lx for Teles S0/16!\n", + unit, kvtop(sc->sc_vmem_addr)); + isic_detach_common(dev); + return(ENXIO); + break; + } + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + + sc->readreg = tels016_read_reg; + sc->writereg = tels016_write_reg; + + sc->readfifo = tels016_read_fifo; + sc->writefifo = tels016_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_16; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC base addr, though we don't really need it */ + + ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100); + + /* setup HSCX base addr */ + + HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180); + HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0); + + t = rman_get_bustag(sc->sc_resources.io_base[0]); + h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* get signature bytes */ + b0 = bus_space_read_1(t, h, 0); + b1 = bus_space_read_1(t, h, 1); + b2 = bus_space_read_1(t, h, 2); + + /* check signature bytes */ + if(b0 != 0x51) + { + printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n", + unit, b0); + isic_detach_common(dev); + return(ENXIO); + } + + if(b1 != 0x93) + { + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n", + unit, b1); + isic_detach_common(dev); + return(ENXIO); + } + + if((b2 != 0x1e) && (b2 != 0x1f)) + { + printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n", + unit, b2); + isic_detach_common(dev); + return(ENXIO); + } + + /* get our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not allocate irq for Teles S0/16.\n", unit); + isic_detach_common(dev); + return ENXIO; + } + + /* register interupt routine */ + + bus_setup_intr(dev, sc->sc_resources.irq, + INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + /* get the irq number */ + + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* check IRQ validity */ + + if((intr_no[sc->sc_irq]) == 1) + { + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n", + unit, sc->sc_irq); + isic_detach_common(dev); + return(ENXIO); + } + + return (0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_s016 - attach Teles S0/16 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_attach_s016(device_t dev) +{ + struct l1_softc *sc = &l1_sc[device_get_unit(dev)]; + u_long irq; + + bus_space_tag_t ta = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t ha = rman_get_bushandle(sc->sc_resources.mem); + bus_space_tag_t tb = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t hb = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* is this right for FreeBSD or off by one ? */ + irq = intr_no[sc->sc_irq]; + + /* configure IRQ */ + + irq |= ((u_long) sc->sc_vmem_addr) >> 9; + + DELAY(SEC_DELAY / 10); + bus_space_write_1(tb, hb, 4, irq); + + DELAY(SEC_DELAY / 10); + bus_space_write_1(tb, hb, 4, irq | 0x01); + + DELAY(SEC_DELAY / 5); + + /* set card bit off */ + + bus_space_write_1(ta, ha, 0x80, 0); + DELAY(SEC_DELAY / 5); + + /* set card bit on */ + + bus_space_write_1(ta, ha, 0x80, 1); + DELAY(SEC_DELAY / 5); + + return 0; +} +#endif /* ISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_tel_s0163.c b/sys/i4b/layer1/isic/i4b_tel_s0163.c new file mode 100644 index 000000000000..150306df8861 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_tel_s0163.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3 + * ======================================================== + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:27:40 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(TEL_S0_16_3) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 }; + +#define ISAC_OFFS 0x400 +#define HSCXA_OFFS 0xc00 +#define HSCXB_OFFS 0x800 + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 read fifo routine + *---------------------------------------------------------------------------*/ +static void +tels0163_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + bus_space_read_multi_1(t,h,0x1e,buf,size); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 write fifo routine + *---------------------------------------------------------------------------*/ +static void +tels0163_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + bus_space_write_multi_1(t,h,0x1e,buf,size); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 ISAC put register routine + *---------------------------------------------------------------------------*/ +static void +tels0163_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + bus_space_write_1(t,h,offs - 0x20,data); +} + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 ISAC get register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +tels0163_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+1]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+1]); + return bus_space_read_1(t,h,offs - 0x20); +} + +/*---------------------------------------------------------------------------* + * isic_probe_s0163 - probe routine for Teles S0/16.3 + *---------------------------------------------------------------------------*/ +int +isic_probe_s0163(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ + bus_space_tag_t t; /* bus things */ + bus_space_handle_t h; + u_int8_t b0,b1,b2; /* signature */ + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles 16.3!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get iobase for Teles S0/16.3.\n", + unit); + return(ENXIO); + } + + /* set io base */ + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + /* Release the resource - re-allocate later with correct size */ + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + + switch(sc->sc_port) + { + case 0xd80: + case 0xe80: + case 0xf80: + break; + + case 0x180: + case 0x280: + case 0x380: + printf("isic%d: Error, instead of using iobase 0x%x for your Teles S0/16.3,\n", + unit, sc->sc_port); + printf("isic%d: please use 0x%x in the kernel configuration file!\n", + unit, sc->sc_port+0xc00); + isic_detach_common(dev); + return(ENXIO); + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n", + unit, sc->sc_port); + isic_detach_common(dev); + return(ENXIO); + break; + } + + /* set io port resources */ + + sc->sc_resources.io_rid[0] = 0; + bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port, 0x20); + sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE); + if(!sc->sc_resources.io_base[0]) + { + printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n", + unit, sc->sc_port); + isic_detach_common(dev); + return ENXIO; + } + sc->sc_resources.io_rid[1] = 1; + bus_set_resource(dev, SYS_RES_IOPORT, 1, + sc->sc_port-ISAC_OFFS, 0x20); + sc->sc_resources.io_base[1] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[1], + 0ul, ~0ul, 1, RF_ACTIVE); + if(!sc->sc_resources.io_base[1]) + { + printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n", + unit, sc->sc_port-ISAC_OFFS); + isic_detach_common(dev); + return ENXIO; + } + + sc->sc_resources.io_rid[2] = 2; + bus_set_resource(dev, SYS_RES_IOPORT, 2, + sc->sc_port-HSCXA_OFFS, 0x20); + sc->sc_resources.io_base[2] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[2], + 0ul, ~0ul, 1, RF_ACTIVE); + if(!sc->sc_resources.io_base[2]) + { + printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n", + unit, sc->sc_port-HSCXA_OFFS); + isic_detach_common(dev); + return ENXIO; + } + + sc->sc_resources.io_rid[3] = 3; + bus_set_resource(dev, SYS_RES_IOPORT, 3, + sc->sc_port-HSCXB_OFFS, 0x20); + sc->sc_resources.io_base[3] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[3], + 0ul, ~0ul, 1, RF_ACTIVE); + if(!sc->sc_resources.io_base[3]) + { + printf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n", + unit, sc->sc_port-HSCXB_OFFS); + isic_detach_common(dev); + return ENXIO; + } + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels0163_read_reg; + sc->writereg = tels0163_write_reg; + + sc->readfifo = tels0163_read_fifo; + sc->writefifo = tels0163_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp= CARD_TYPEP_16_3; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + t = rman_get_bustag(sc->sc_resources.io_base[0]); + h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + b0 = bus_space_read_1(t, h, 0); + b1 = bus_space_read_1(t, h, 1); + b2 = bus_space_read_1(t, h, 2); + + if ( b0 != 0x51 && b0 != 0x10 ) { + printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n", + unit, b0); + isic_detach_common(dev); + return ENXIO; + } + + if ( b1 != 0x93 ) { + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n", + unit, b1); + isic_detach_common(dev); + return ENXIO; + } + if (( b2 != 0x1c ) && ( b2 != 0x1f )) { + printf("isic%d: Error, signature 3 0x%x != (0x1c || 0x1f) for Teles S0/16.3!\n", + unit, b2); + isic_detach_common(dev); + return ENXIO; + } + + /* + * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is + * 0x05 or 0x04 (for older 16.3's) in the least significant bits. + */ + + if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) || + (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) ) + { + printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n", + unit); + printf("isic%d: HSC0: VSTR: %#x\n", + unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + unit, HSCX_READ(1, H_VSTR)); + isic_detach_common(dev); + return (ENXIO); + } + + /* get our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get IRQ for Teles S0/16.3.\n",unit); + isic_detach_common(dev); + return ENXIO; + } + + /* get the irq number */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + switch(sc->sc_irq) + { + case 2: + case 9: + case 5: + case 10: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n", + unit, sc->sc_irq); + isic_detach_common(dev); + return(ENXIO); + break; + } + + /* register interupt routine */ + bus_setup_intr(dev, sc->sc_resources.irq, + INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + return (0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_s0163 - attach Teles S0/16.3 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_attach_s0163(device_t dev) +{ + unsigned int unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = &l1_sc[unit]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); + + /* configure IRQ */ + + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 4, intr_no[sc->sc_irq]); + + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 4, intr_no[sc->sc_irq] | 0x01); + + return (0); +} + +#endif /* ISIC > 0 */ + diff --git a/sys/i4b/layer1/isic/i4b_tel_s08.c b/sys/i4b/layer1/isic/i4b_tel_s08.c new file mode 100644 index 000000000000..d1d69b2f631a --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_tel_s08.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones + * ================================================================ + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:27:58 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if NISIC > 0 && defined(TEL_S0_8) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/md_var.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +#define TELES_S08_MEMSIZE 0x1000 + +static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 }; + +/*---------------------------------------------------------------------------* + * Teles S0/8 write register routine + *---------------------------------------------------------------------------*/ +static void +tels08_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + + offs += offset[what]; + + if (offs & 0x01) + offs |= 0x200; + + bus_space_write_1(t, h, offs, data); +} + +/*---------------------------------------------------------------------------* + * Teles S0/8 read register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +tels08_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + + offs += offset[what]; + + if (offs & 0x01) + offs |= 0x200; + + return bus_space_read_1(t, h, offs); +} + +/*---------------------------------------------------------------------------* + * Teles S0/8 fifo write access + *---------------------------------------------------------------------------*/ +static void +tels08_write_fifo(struct l1_softc *sc, int what, void *data, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + bus_space_write_region_1(t, h, offset[what], data, size); +} + +/*---------------------------------------------------------------------------* + * Teles S0/8 fifo read access + *---------------------------------------------------------------------------*/ +static void +tels08_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + bus_space_read_region_1(t, h, offset[what], buf, size); +} + +/*---------------------------------------------------------------------------* + * isic_probe_s08 - probe for Teles S0/8 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_probe_s08(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if((sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + /* the S0/8 is completely memory mapped ! */ + + bus_release_resource(dev,SYS_RES_IOPORT, + sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + printf("isic%d: Error, iobase specified for Teles S0/8!\n", unit); + return(ENXIO); + } + + /* allocate memory */ + + if(!(sc->sc_resources.mem = + bus_alloc_resource(dev, SYS_RES_MEMORY, + &sc->sc_resources.mem_rid, + 0ul, ~0ul, TELES_S08_MEMSIZE, RF_ACTIVE))) + { + printf("isic%d: Could not allocate memory for Teles S0/8!\n", unit); + return(ENXIO); + } + + /* + * get virtual addr. it's just needed to see if it is in + * the valid range + */ + + sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem); + + /* check if inside memory range of 0xA0000 .. 0xDF000 */ + + if((kvtop(sc->sc_vmem_addr) < 0xa0000) || + (kvtop(sc->sc_vmem_addr) > 0xdf000)) + { + printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n", + unit, kvtop(sc->sc_vmem_addr)); + bus_release_resource(dev,SYS_RES_MEMORY, + sc->sc_resources.mem_rid, + sc->sc_resources.mem); + sc->sc_resources.mem = 0; + return(ENXIO); + } + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + + sc->readreg = tels08_read_reg; + sc->writereg = tels08_write_reg; + + sc->readfifo = tels08_read_fifo; + sc->writefifo = tels08_write_fifo; + + sc->sc_cardtyp = CARD_TYPEP_8; /* setup card type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; /* setup IOM bus type */ + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC base addr, though we don't really need it */ + + ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100); + + /* setup HSCX base addr */ + + HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180); + HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0); + + /* allocate our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not allocate irq for Teles S0/8!\n",unit); + + bus_release_resource(dev,SYS_RES_MEMORY, + sc->sc_resources.mem_rid, + sc->sc_resources.mem); + + sc->sc_resources.mem = 0; + return ENXIO; + } + + /* get the irq number */ + + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* check IRQ validity */ + + switch(sc->sc_irq) + { + case 2: + case 9: /* XXX */ + case 3: + case 4: + case 5: + case 6: + case 7: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n", + unit, sc->sc_irq); + bus_release_resource(dev,SYS_RES_IRQ, + sc->sc_resources.irq_rid, + sc->sc_resources.irq); + sc->sc_resources.irq = 0; + bus_release_resource(dev,SYS_RES_MEMORY, + sc->sc_resources.mem_rid, + sc->sc_resources.mem); + sc->sc_resources.mem = 0; + return(ENXIO); + break; + } + + /* register interupt routine */ + + bus_setup_intr(dev, sc->sc_resources.irq, + INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + return (0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_s08 - attach Teles S0/8 and compatibles + *---------------------------------------------------------------------------*/ +int +isic_attach_s08(device_t dev) +{ + struct l1_softc *sc = &l1_sc[device_get_unit(dev)]; + bus_space_tag_t t = rman_get_bustag(sc->sc_resources.mem); + bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.mem); + + /* set card off */ + + bus_space_write_1(t, h, 0x80, 0); + + DELAY(SEC_DELAY / 5); + + /* set card on */ + + bus_space_write_1(t, h, 0x80, 1); + + DELAY(SEC_DELAY / 5); + + return 0; +} +#endif /* ISIC > 0 */ diff --git a/sys/i4b/layer1/isic/i4b_usr_sti.c b/sys/i4b/layer1/isic/i4b_usr_sti.c new file mode 100644 index 000000000000..4a3a0e024568 --- /dev/null +++ b/sys/i4b/layer1/isic/i4b_usr_sti.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp) + * ------------------------------------------------------------- + * + * $FreeBSD$ + * + * last edit-date: [Wed Jan 24 09:28:12 2001] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && defined(USR_STI) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <sys/socket.h> +#include <net/if.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/isic/i4b_isic.h> +#include <i4b/layer1/isic/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * USR Sportster TA intern special registers + *---------------------------------------------------------------------------*/ +#define USR_HSCXA_OFF 0x0000 +#define USR_HSCXB_OFF 0x4000 +#define USR_INTL_OFF 0x8000 +#define USR_ISAC_OFF 0xc000 + +#define USR_RES_BIT 0x80 /* 0 = normal, 1 = reset ISAC/HSCX */ +#define USR_INTE_BIT 0x40 /* 0 = IRQ disabled, 1 = IRQ's enabled */ +#define USR_IL_MASK 0x07 /* IRQ level config */ + +static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 }; + +#define ADDR(reg) \ + (((reg/4) * 1024) + ((reg%4) * 2)) + +#ifdef USRTA_DEBUG_PORTACCESS +int debugcntr; +#define USRTA_DEBUG(fmt) \ + if (++debugcntr < 1000) printf fmt; +#else +#define USRTA_DEBUG(fmt) +#endif + +/*---------------------------------------------------------------------------* + * USRobotics read fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) +{ + register int offset = 0; + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_read_fifo: what %d size %d\n", what, size)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_read_fifo: invalid what %d\n", what); + return; + } + + for(;size > 0; size--, offset++) + { + *((u_char *)buf + offset) = inb(base + ADDR(offset)); + } +} + +/*---------------------------------------------------------------------------* + * USRobotics write fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_fifo(struct l1_softc *sc, int what, void *data, size_t size) +{ + register int offset = 0; + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_write_fifo: what %d size %d\n", what, size)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_write_fifo: invalid what %d\n", what); + return; + } + + + for(;size > 0; size--, offset++) + { + outb(base + ADDR(offset), *((u_char *)data + offset)); + } +} + +/*---------------------------------------------------------------------------* + * USRobotics write register routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_write_reg: what %d ADDR(%d) %d data %#x\n", what, offs, ADDR(offs), data)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_write_reg invalid what %d\n", what); + return; + } + + outb(base + ADDR(offs), (u_char)data); +} + +/*---------------------------------------------------------------------------* + * USRobotics read register routine + *---------------------------------------------------------------------------*/ +static u_int8_t +usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs) +{ + register unsigned int base = 0; + u_int8_t byte; + +USRTA_DEBUG(("usrtai_read_reg: what %d ADDR(%d) %d..", what, offs, ADDR(offs))) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_read_reg: invalid what %d\n", what); + return(0); + } + + byte = inb(base + ADDR(offs)); +USRTA_DEBUG(("usrtai_read_reg: got %#x\n", byte)) + return(byte); +} + +/*---------------------------------------------------------------------------* + * allocate an io port - based on code in isa_isic.c + *---------------------------------------------------------------------------*/ +static int +usrtai_alloc_port(device_t dev) +{ + size_t unit = device_get_unit(dev); + struct l1_softc *sc = &l1_sc[unit]; + int i, num = 0; + bus_size_t base; + + /* 49 io mappings: 1 config and 48x8 registers */ + + /* config at offset 0x8000 */ + base = sc->sc_port + 0x8000; + if (base < 0 || base > 0x0ffff) + return 1; + sc->sc_resources.io_rid[num] = num; + + bus_set_resource(dev, SYS_RES_IOPORT, num, base, 1); + + if(!(sc->sc_resources.io_base[num] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[num], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Error, failed to reserve io #%dport %#x!\n", unit, num, base); + isic_detach_common(dev); + return(ENXIO); + } + num++; + + /* HSCX A at offset 0 */ + base = sc->sc_port; + for (i = 0; i < 16; i++) { + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + sc->sc_resources.io_rid[num] = num; + + bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); + + if(!(sc->sc_resources.io_base[num] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[num], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); + isic_detach_common(dev); + return(ENXIO); + } + ++num; + } + + /* HSCX B at offset 0x4000 */ + base = sc->sc_port + 0x4000; + for (i = 0; i < 16; i++) { + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + sc->sc_resources.io_rid[num] = num; + + bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); + + if(!(sc->sc_resources.io_base[num] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[num], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); + isic_detach_common(dev); + return(ENXIO); + } + ++num; + } + + /* ISAC at offset 0xc000 */ + base = sc->sc_port + 0xc000; + for (i = 0; i < 16; i++) { + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + sc->sc_resources.io_rid[num] = num; + + bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); + + if(!(sc->sc_resources.io_base[num] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[num], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); + isic_detach_common(dev); + return(ENXIO); + } + ++num; + } + + return(0); +} + +/*---------------------------------------------------------------------------* + * isic_probe_usrtai - probe for USR + *---------------------------------------------------------------------------*/ +int +isic_probe_usrtai(device_t dev) +{ + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n", + unit, unit); + return(ENXIO); + } + + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + + /* see if an io base was supplied */ + + if(!(sc->sc_resources.io_base[0] = + bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->sc_resources.io_rid[0], + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get iobase for USR Sportster TA!\n", + unit); + return(ENXIO); + } + + /* set io base */ + + sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); + + /* release io base */ + + bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0], + sc->sc_resources.io_base[0]); + + + /* check if we got an iobase */ + + switch(sc->sc_port) + { + case 0x200: + case 0x208: + case 0x210: + case 0x218: + case 0x220: + case 0x228: + case 0x230: + case 0x238: + case 0x240: + case 0x248: + case 0x250: + case 0x258: + case 0x260: + case 0x268: + case 0x270: + case 0x278: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n", + unit, sc->sc_port); + return(0); + break; + } + + /* allocate all the ports needed */ + + if(usrtai_alloc_port(dev)) + { + printf("isic%d: Could not get the ports for USR Sportster TA!\n", unit); + isic_detach_common(dev); + return(ENXIO); + } + + /* get our irq */ + + if(!(sc->sc_resources.irq = + bus_alloc_resource(dev, SYS_RES_IRQ, + &sc->sc_resources.irq_rid, + 0ul, ~0ul, 1, RF_ACTIVE))) + { + printf("isic%d: Could not get an irq for USR Sportster TA!\n",unit); + isic_detach_common(dev); + return ENXIO; + } + + /* get the irq number */ + sc->sc_irq = rman_get_start(sc->sc_resources.irq); + + /* register interrupt routine */ + bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + /* check IRQ validity */ + + if(intr_no[sc->sc_irq] == 0) + { + printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n", + unit, sc->sc_irq); + return(1); + } + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = usrtai_read_reg; + sc->writereg = usrtai_write_reg; + + sc->readfifo = usrtai_read_fifo; + sc->writefifo = usrtai_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_USRTA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t)sc->sc_port + USR_ISAC_OFF; + HSCX_A_BASE = (caddr_t)sc->sc_port + USR_HSCXA_OFF; + HSCX_B_BASE = (caddr_t)sc->sc_port + USR_HSCXB_OFF; + + /* + * Read HSCX A/B VSTR. Expected value for USR Sportster TA based + * boards is 0x05 in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n", + unit); + printf("isic%d: HSC0: VSTR: %#x\n", + unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + unit, HSCX_READ(1, H_VSTR)); + return (1); + } + + return (0); +} + +/*---------------------------------------------------------------------------* + * isic_attach_usrtai - attach USR + *---------------------------------------------------------------------------*/ +int +isic_attach_usrtai(device_t dev) +{ + u_char irq = 0; + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + + sc = &l1_sc[unit]; /* get pointer to softc */ + + /* reset the HSCX and ISAC chips */ + + outb(sc->sc_port + USR_INTL_OFF, USR_RES_BIT); + DELAY(SEC_DELAY / 10); + + outb(sc->sc_port + USR_INTL_OFF, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + if((irq = intr_no[sc->sc_irq]) == 0) + { + printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n", + unit, sc->sc_irq); + return(1); + } + + /* configure and enable irq */ + + outb(sc->sc_port + USR_INTL_OFF, irq | USR_INTE_BIT); + DELAY(SEC_DELAY / 10); + + return (0); +} + +#endif /* ISIC > 0 */ |