summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer1/iwic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i4b/layer1/iwic')
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic.h224
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_bchan.c749
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_dchan.c494
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_ext.h50
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_fsm.c235
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_l1if.c166
-rw-r--r--sys/i4b/layer1/iwic/i4b_iwic_pci.c317
-rw-r--r--sys/i4b/layer1/iwic/i4b_w6692.h264
8 files changed, 2499 insertions, 0 deletions
diff --git a/sys/i4b/layer1/iwic/i4b_iwic.h b/sys/i4b/layer1/iwic/i4b_iwic.h
new file mode 100644
index 0000000..1da90d7
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic.h,v 1.5 2000/03/13 15:23:43 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Mar 13 16:23:15 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_IWIC_H_
+#define _I4B_IWIC_H_
+
+#include <i4b/layer1/iwic/i4b_iwic_ext.h>
+
+/*---------------------------------------------------------------------------*
+ * PCI resources used
+ *---------------------------------------------------------------------------*/
+
+#define INFO_IO_BASES 2
+
+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;
+};
+
+/*---------------------------------------------------------------------------*
+ * state of a B channel
+ *---------------------------------------------------------------------------*/
+struct iwic_bchan
+{
+ int unit; /* unit number */
+ int channel; /* channel number */
+ int offset; /* offset from iobase */
+ int bprot; /* b channel protocol used */
+ int state; /* transceiver state: */
+#define ST_IDLE 0x00 /* channel idle */
+#define ST_TX_ACTIVE 0x01 /* tx running */
+
+ int sc_trace_bcount;
+
+ /* 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 */
+
+ /* linktab */
+
+ isdn_link_t iwic_isdn_linktab;
+ drvr_link_t *iwic_drvr_linktab;
+};
+
+/*---------------------------------------------------------------------------*
+ * state of a D channel
+ *---------------------------------------------------------------------------*/
+struct iwic_dchan
+{
+ int enabled;
+ int trace_count;
+ struct mbuf *ibuf;
+ u_char *ibuf_ptr; /* Input buffer pointer */
+ int ibuf_len; /* Current length of input buffer */
+ int ibuf_max_len; /* Max length in input buffer */
+ int rx_count;
+
+ int tx_ready; /* Can send next 64 bytes of data. */
+ int tx_count;
+
+ struct mbuf *obuf;
+ int free_obuf;
+ u_char *obuf_ptr;
+ int obuf_len;
+
+ struct mbuf *obuf2;
+ int free_obuf2;
+};
+
+/*---------------------------------------------------------------------------*
+ * state of one iwic unit
+ *---------------------------------------------------------------------------*/
+struct iwic_softc
+{
+ int sc_unit;
+ u_int32_t sc_iobase;
+ int sc_trace;
+ int sc_cardtyp;
+
+ int sc_I430state;
+ int sc_I430T3;
+
+ int enabled;
+
+ struct iwic_dchan sc_dchan;
+ struct iwic_bchan sc_bchan[2];
+
+ struct i4b_info sc_resources;
+};
+
+/*---------------------------------------------------------------------------*
+ * rd/wr register/fifo macros
+ *---------------------------------------------------------------------------*/
+#define IWIC_READ(sc,reg) (inb ((sc)->sc_iobase + (u_int32_t)(reg)))
+#define IWIC_WRITE(sc,reg,val) (outb ((sc)->sc_iobase + (u_int32_t)(reg), (val)))
+#define IWIC_WRDFIFO(sc,p,l) (outsb ((sc)->sc_iobase + D_XFIFO, (p), (l)))
+#define IWIC_RDDFIFO(sc,p,l) (insb ((sc)->sc_iobase + D_RFIFO, (p), (l)))
+#define IWIC_WRBFIFO(sc,b,p,l) (outsb (((sc)->sc_iobase + (b)->offset + B_XFIFO), (p), (l)))
+#define IWIC_RDBFIFO(sc,b,p,l) (insb (((sc)->sc_iobase + (b)->offset + B_RFIFO), (p), (l)))
+
+/*---------------------------------------------------------------------------*
+ * possible I.430 states
+ *---------------------------------------------------------------------------*/
+enum I430states
+{
+ ST_F3N, /* F3 Deactivated, no clock */
+ 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 events
+ *---------------------------------------------------------------------------*/
+enum I430events
+{
+ EV_PHAR, /* PH ACTIVATE REQUEST */
+ EV_CE, /* Clock enabled */
+ 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
+};
+
+/*---------------------------------------------------------------------------*
+ * available commands
+ *---------------------------------------------------------------------------*/
+enum I430commands
+{
+ CMD_ECK, /* Enable clock */
+ CMD_TIM, /* Timing */
+ CMD_RT, /* Reset */
+ CMD_AR8, /* Activation request pri 8 */
+ CMD_AR10, /* Activation request pri 10 */
+ CMD_DIU, /* Deactivate Indication Upstream */
+ CMD_ILL /* Illegal command */
+};
+
+
+extern struct iwic_softc iwic_sc[];
+
+#define iwic_find_sc(unit) (&iwic_sc[(unit)])
+
+extern void iwic_init(struct iwic_softc *);
+extern void iwic_next_state(struct iwic_softc *, int);
+
+extern void iwic_dchan_init(struct iwic_softc *);
+extern void iwic_dchan_xirq(struct iwic_softc *);
+extern void iwic_dchan_xfer_irq(struct iwic_softc *, int);
+extern void iwic_dchan_disable(struct iwic_softc *sc);
+extern int iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag);
+extern void iwic_dchan_transmit(struct iwic_softc *sc);
+
+char *iwic_printstate(struct iwic_softc *sc);
+
+void iwic_init_linktab(struct iwic_softc *sc);
+void iwic_bchan_xirq(struct iwic_softc *, int);
+void iwic_bchannel_setup(int unit, int h_chan, int bprot, int activate);
+
+#endif /* _I4B_IWIC_H_ */
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_bchan.c b/sys/i4b/layer1/iwic/i4b_iwic_bchan.c
new file mode 100644
index 0000000..e6bbaca
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_bchan.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
+ *
+ * Copyright (c) 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_bchan.c,v 1.8 2000/05/29 15:41:42 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 16:48:56 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "iwic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#if (NIWIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/iwic/i4b_iwic.h>
+#include <i4b/layer1/iwic/i4b_w6692.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static void iwic_bchan_init(struct iwic_softc *sc, int chan_no, int activate);
+
+/*---------------------------------------------------------------------------*
+ * B-channel interrupt handler
+ *---------------------------------------------------------------------------*/
+void
+iwic_bchan_xirq(struct iwic_softc *sc, int chan_no)
+{
+ int irq_stat;
+ struct iwic_bchan *chan;
+ int cmd = 0;
+ int activity = 0;
+
+ chan = &sc->sc_bchan[chan_no];
+
+ irq_stat = IWIC_READ(sc, chan->offset + B_EXIR);
+
+ NDBGL1(L1_H_IRQ, "irq_stat = 0x%x", irq_stat);
+
+ if((irq_stat & (B_EXIR_RMR | B_EXIR_RME | B_EXIR_RDOV | B_EXIR_XFR | B_EXIR_XDUN)) == 0)
+ {
+ NDBGL1(L1_H_XFRERR, "spurious IRQ!");
+ return;
+ }
+
+ if (irq_stat & B_EXIR_RDOV)
+ {
+ NDBGL1(L1_H_XFRERR, "RDOV");
+ }
+
+ if (irq_stat & B_EXIR_XDUN)
+ {
+ NDBGL1(L1_H_XFRERR, "XDUN");
+ }
+
+/* RX message end interrupt */
+
+ if(irq_stat & B_EXIR_RME)
+ {
+/* XXXX */ int error = 0;
+ register int fifo_data_len;
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_RME");
+
+ fifo_data_len = ((IWIC_READ(sc,chan->offset+B_RBCL)) &
+ ((IWIC_BCHAN_FIFO_LEN)-1));
+
+ if(fifo_data_len == 0)
+ fifo_data_len = IWIC_BCHAN_FIFO_LEN;
+
+ /* all error conditions checked, now decide and take action */
+
+ if(error == 0)
+ {
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 iwic_bchan_irq: RME, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
+ {
+ /* read data from fifo */
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_RME, rd fifo, len = %d", fifo_data_len);
+
+ IWIC_RDBFIFO(sc, chan, chan->in_cbptr, fifo_data_len);
+
+ cmd |= (B_CMDR_RACK | B_CMDR_RACT);
+ IWIC_WRITE(sc, chan->offset + B_CMDR, 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 = L0IWICUNIT(sc->sc_unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ (*chan->iwic_drvr_linktab->bch_rx_data_ready)(chan->iwic_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 |= (B_CMDR_RRST | B_CMDR_RACK);
+ }
+ }
+ else
+ {
+ if (chan->in_mbuf != NULL)
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ chan->in_mbuf = NULL;
+ chan->in_cbptr = NULL;
+ chan->in_len = 0;
+ }
+ cmd |= (B_CMDR_RRST | B_CMDR_RACK);
+ }
+ }
+
+/* RX fifo full interrupt */
+
+ if(irq_stat & B_EXIR_RMR)
+ {
+ NDBGL1(L1_H_IRQ, "B_EXIR_RMR");
+
+ if(chan->in_mbuf == NULL)
+ {
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 iwic_bchan_irq: RMR, cannot allocate mbuf!\n");
+ chan->in_cbptr = chan->in_mbuf->m_data;
+ chan->in_len = 0;
+ }
+
+ chan->rxcount += IWIC_BCHAN_FIFO_LEN;
+
+ if((chan->in_len + IWIC_BCHAN_FIFO_LEN) <= BCH_MAX_DATALEN)
+ {
+ /* read data from fifo */
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo, len = max (64)");
+
+ IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);
+
+ chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
+ chan->in_len += IWIC_BCHAN_FIFO_LEN;
+ }
+ 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 = L0IWICUNIT(sc->sc_unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
+ }
+
+ /* silence detection */
+
+ if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
+ activity = ACT_RX;
+
+ if(!(IF_QFULL(&chan->rx_queue)))
+ {
+ IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
+ }
+ else
+ {
+ i4b_Bfreembuf(chan->in_mbuf);
+ }
+
+ /* signal upper driver that data is available */
+
+ (*chan->iwic_drvr_linktab->bch_rx_data_ready)(chan->iwic_drvr_linktab->unit);
+
+ /* alloc new buffer */
+
+ if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
+ panic("L1 iwic_bchan_irq: RMR, cannot allocate new mbuf!\n");
+
+ /* setup new data ptr */
+
+ chan->in_cbptr = chan->in_mbuf->m_data;
+
+ /* read data from fifo */
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo1, len = max (64)");
+
+ IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);
+
+ chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
+ chan->in_len = IWIC_BCHAN_FIFO_LEN;
+
+ chan->rxcount += IWIC_BCHAN_FIFO_LEN;
+ }
+ 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 |= (B_CMDR_RRST | B_CMDR_RACK);
+ }
+ }
+
+ /* command to release fifo space */
+
+ cmd |= B_CMDR_RACK;
+ }
+
+/* TX interrupt */
+
+ if (irq_stat & B_EXIR_XFR)
+ {
+ /* transmit fifo empty, new data can be written to fifo */
+
+ int activity = -1;
+ int len;
+ int nextlen;
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_XFR");
+
+ 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 &= ~ST_TX_ACTIVE;
+ (*chan->iwic_drvr_linktab->bch_tx_queue_empty)(chan->iwic_drvr_linktab->unit);
+ }
+ else
+ {
+ chan->state |= ST_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 = L0IWICUNIT(sc->sc_unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_bchan[chan_no].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 != IWIC_BCHAN_FIFO_LEN)
+ {
+ nextlen = min(chan->out_mbuf_cur_len, IWIC_BCHAN_FIFO_LEN - len);
+
+ NDBGL1(L1_H_IRQ, "B_EXIR_XFR, wr fifo, len = %d", nextlen);
+
+ IWIC_WRBFIFO(sc, chan, chan->out_mbuf_cur_ptr, nextlen);
+
+ cmd |= B_CMDR_XMS;
+
+ 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 = L0IWICUNIT(sc->sc_unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_bchan[chan_no].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 |= B_CMDR_XME;
+ i4b_Bfreembuf(chan->out_mbuf_head);
+ chan->out_mbuf_head = NULL;
+ }
+ }
+ }
+ }
+ if(cmd)
+ {
+ cmd |= B_CMDR_RACT;
+ IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize one B channels rx/tx data structures
+ *---------------------------------------------------------------------------*/
+void
+iwic_bchannel_setup(int unit, int chan_no, int bprot, int activate)
+{
+ struct iwic_softc *sc = &iwic_sc[unit];
+ struct iwic_bchan *chan = &sc->sc_bchan[chan_no];
+
+ int s = SPLI4B();
+
+ NDBGL1(L1_BCHAN, "unit %d, chan %d, bprot %d, activate %d", unit, chan_no, bprot, activate);
+
+ /* general part */
+
+ chan->bprot = bprot; /* B channel protocol */
+ chan->state = ST_IDLE; /* B channel state */
+
+ if(activate == 0)
+ {
+ /* deactivation */
+ iwic_bchan_init(sc, chan_no, activate);
+ }
+
+ /* receiver part */
+
+ i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
+
+ chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->rxcount = 0; /* reset rx counter */
+
+ i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */
+
+ chan->in_mbuf = NULL; /* reset mbuf ptr */
+ chan->in_cbptr = NULL; /* reset mbuf curr ptr */
+ chan->in_len = 0; /* reset mbuf data len */
+
+ /* transmitter part */
+
+ i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
+
+ chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+ chan->txcount = 0; /* reset tx counter */
+
+ i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */
+
+ chan->out_mbuf_head = NULL; /* reset head mbuf ptr */
+ chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */
+ chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */
+ chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */
+
+ if(activate != 0)
+ {
+ /* activation */
+ iwic_bchan_init(sc, chan_no, activate);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * initalize / deinitialize B-channel hardware
+ *---------------------------------------------------------------------------*/
+static void
+iwic_bchan_init(struct iwic_softc *sc, int chan_no, int activate)
+{
+ struct iwic_bchan *bchan = &sc->sc_bchan[chan_no];
+
+ NDBGL1(L1_BCHAN, "chan %d, activate %d", chan_no, activate);
+
+ if(activate)
+ {
+ if(bchan->bprot == BPROT_NONE)
+ {
+ /* Extended transparent mode */
+ IWIC_WRITE(sc, bchan->offset + B_MODE, B_MODE_MMS);
+ }
+ else
+ {
+ /* Transparent mode */
+ IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
+ /* disable address comparation */
+ IWIC_WRITE (sc, bchan->offset+B_ADM1, 0xff);
+ IWIC_WRITE (sc, bchan->offset+B_ADM2, 0xff);
+ }
+
+ /* reset & start receiver */
+ IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST|B_CMDR_RACT);
+
+ /* clear irq mask */
+ IWIC_WRITE(sc, bchan->offset + B_EXIM, 0);
+ }
+ else
+ {
+ /* mask all irqs */
+ IWIC_WRITE(sc, bchan->offset + B_EXIM, 0xff);
+
+ /* reset mode */
+ IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
+
+ /* Bring interface down */
+ IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST | B_CMDR_XRST);
+
+ /* Flush pending interrupts */
+ IWIC_READ(sc, bchan->offset + B_EXIR);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * start transmission on a b channel
+ *---------------------------------------------------------------------------*/
+static void
+iwic_bchannel_start(int unit, int chan_no)
+{
+ struct iwic_softc *sc = &iwic_sc[unit];
+ register struct iwic_bchan *chan = &sc->sc_bchan[chan_no];
+ register int next_len;
+ register int len;
+
+ int s;
+ int activity = -1;
+ int cmd = 0;
+
+ s = SPLI4B(); /* enter critical section */
+
+ NDBGL1(L1_BCHAN, "unit %d, channel %d", unit, chan_no);
+
+ if(chan->state & ST_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 |= ST_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 = L0IWICUNIT(unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_bchan[chan_no].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 tx fifo this time */
+
+ /*
+ * fill the tx fifo with data from the current mbuf. if
+ * current mbuf holds less data than 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 chip that it has to send
+ * CRC and closing flag
+ */
+
+ while((len < IWIC_BCHAN_FIFO_LEN) && chan->out_mbuf_cur)
+ {
+ /*
+ * put as much data into the fifo as is
+ * available from the current mbuf
+ */
+
+ if((len + chan->out_mbuf_cur_len) >= IWIC_BCHAN_FIFO_LEN)
+ next_len = IWIC_BCHAN_FIFO_LEN - len;
+ else
+ next_len = chan->out_mbuf_cur_len;
+
+ /* write what we have from current mbuf to fifo */
+
+ IWIC_WRBFIFO(sc, 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 = L0IWICUNIT(unit);
+ hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_bchan[chan_no].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 teh chip. 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 tx fifo is done in the
+ * interrupt routine.
+ */
+
+ cmd |= B_CMDR_XMS;
+ }
+ else
+ {
+ /* end of mbuf chain */
+
+ if(chan->bprot == BPROT_NONE)
+ cmd |= B_CMDR_XMS;
+ else
+ cmd |= (B_CMDR_XMS | B_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->iwic_drvr_linktab->bch_activity)(chan->iwic_drvr_linktab->unit, activity);
+
+ if(cmd)
+ {
+ cmd |= B_CMDR_RACT;
+ IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
+ }
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+iwic_bchannel_stat(int unit, int chan_no, bchan_statistics_t *bsp)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+ struct iwic_bchan *bchan = &sc->sc_bchan[chan_no];
+
+ int s = SPLI4B();
+
+ bsp->outbytes = bchan->txcount;
+ bsp->inbytes = bchan->rxcount;
+
+ bchan->txcount = 0;
+ bchan->rxcount = 0;
+
+ splx(s);
+}
+
+/*---------------------------------------------------------------------------*
+ * initialize our local linktab
+ *---------------------------------------------------------------------------*/
+void
+iwic_init_linktab(struct iwic_softc *sc)
+{
+ struct iwic_bchan *chan;
+ isdn_link_t *lt;
+
+ /* 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;
+
+ /* channel A */
+
+ chan = &sc->sc_bchan[IWIC_BCH_A];
+ lt = &chan->iwic_isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = IWIC_BCH_A;
+ lt->bch_config = iwic_bchannel_setup;
+ lt->bch_tx_start = iwic_bchannel_start;
+ lt->bch_stat = iwic_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;
+
+ /* channel B */
+
+ chan = &sc->sc_bchan[IWIC_BCH_B];
+ lt = &chan->iwic_isdn_linktab;
+
+ lt->unit = sc->sc_unit;
+ lt->channel = IWIC_BCH_B;
+ lt->bch_config = iwic_bchannel_setup;
+ lt->bch_tx_start = iwic_bchannel_start;
+ lt->bch_stat = iwic_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 /* NIWIC > 0 */
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_dchan.c b/sys/i4b/layer1/iwic/i4b_iwic_dchan.c
new file mode 100644
index 0000000..b088505
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_dchan.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_dchan.c,v 1.5 2000/05/29 15:41:42 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Wed Mar 8 16:17:16 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "iwic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#if (NIWIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/iwic/i4b_iwic.h>
+#include <i4b/layer1/iwic/i4b_w6692.h>
+
+#define MAX_DFRAME_LEN 264
+
+static void dchan_receive(struct iwic_softc *sc, int ista);
+
+#ifdef NOTDEF
+static void output_bytes(char *prefix, u_char * ptr, int len);
+#endif
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_dchan_init(struct iwic_softc *sc)
+{
+ sc->sc_dchan.ibuf = NULL;
+ sc->sc_dchan.rx_count = 0;
+
+ sc->sc_dchan.obuf = NULL;
+ sc->sc_dchan.obuf2 = NULL;
+ sc->sc_dchan.tx_count = 0;
+ sc->sc_dchan.tx_ready = 0;
+
+ IWIC_WRITE(sc, D_CTL, D_CTL_SRST);
+
+ DELAY(5000);
+
+ IWIC_WRITE(sc, D_CTL, 0);
+
+ IWIC_WRITE(sc, SQX, SQX_SCIE);
+
+ IWIC_WRITE(sc, PCTL, 0x00);
+ IWIC_WRITE(sc, MOCR, 0x00);
+ IWIC_WRITE(sc, GCR, 0x00);
+
+ IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST | D_CMDR_XRST);
+ IWIC_WRITE(sc, D_MODE, D_MODE_RACT);
+
+ IWIC_WRITE(sc, D_SAM, 0xff);
+ IWIC_WRITE(sc, D_TAM, 0xff);
+
+ IWIC_WRITE(sc, D_EXIM, 0x00);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_dchan_xirq(struct iwic_softc *sc)
+{
+ int irq_stat;
+ int stat;
+
+ irq_stat = IWIC_READ(sc, D_EXIR);
+
+ if (irq_stat & D_EXIR_RDOV)
+ {
+ NDBGL1(L1_I_ERR, "RDOV in state %s", iwic_printstate(sc));
+ }
+ if (irq_stat & D_EXIR_XDUN)
+ {
+ NDBGL1(L1_I_ERR, "XDUN in state %s", iwic_printstate(sc));
+ sc->sc_dchan.tx_ready = 0;
+ }
+ if (irq_stat & D_EXIR_XCOL)
+ {
+ NDBGL1(L1_I_ERR, "XCOL in state %s", iwic_printstate(sc));
+ sc->sc_dchan.tx_ready = 0;
+ }
+ if (irq_stat & D_EXIR_TIN2)
+ {
+ NDBGL1(L1_I_ERR, "TIN2 in state %s", iwic_printstate(sc));
+ }
+ if (irq_stat & D_EXIR_MOC)
+ {
+ stat = IWIC_READ(sc, MOR);
+ NDBGL1(L1_I_ERR, "MOC in state %s, byte = 0x%x", iwic_printstate(sc), stat);
+ }
+
+ if (irq_stat & D_EXIR_ISC)
+ {
+ stat = (IWIC_READ(sc, CIR)) & 0x0f;
+
+ switch (stat)
+ {
+ case CIR_CE:
+ NDBGL1(L1_I_CICO, "rx CE in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_CE);
+ break;
+ case CIR_DRD:
+ NDBGL1(L1_I_CICO, "rx DRD in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_INFO0);
+ i4b_l1_mph_status_ind(L0IWICUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL);
+ break;
+ case CIR_LD:
+ NDBGL1(L1_I_CICO, "rx LD in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_RSY);
+ break;
+ case CIR_ARD:
+ NDBGL1(L1_I_CICO, "rx ARD in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_INFO2);
+ break;
+ case CIR_TI:
+ NDBGL1(L1_I_CICO, "rx TI in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_INFO0);
+ break;
+ case CIR_ATI:
+ NDBGL1(L1_I_CICO, "rx ATI in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_INFO0);
+ break;
+ case CIR_AI8:
+ NDBGL1(L1_I_CICO, "rx AI8 in state %s", iwic_printstate(sc));
+ i4b_l1_mph_status_ind(L0IWICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ iwic_next_state(sc, EV_INFO48);
+ break;
+ case CIR_AI10:
+ NDBGL1(L1_I_CICO, "rx AI10 in state %s", iwic_printstate(sc));
+ i4b_l1_mph_status_ind(L0IWICUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ iwic_next_state(sc, EV_INFO410);
+ break;
+ case CIR_CD:
+ NDBGL1(L1_I_CICO, "rx DIS in state %s", iwic_printstate(sc));
+ iwic_next_state(sc, EV_DIS);
+ break;
+ default:
+ NDBGL1(L1_I_ERR, "ERROR, unknown indication 0x%x in state %s", stat, iwic_printstate(sc));
+ iwic_next_state(sc, EV_INFO0);
+ break;
+ }
+ }
+
+ if (irq_stat & D_EXIR_TEXP)
+ {
+ NDBGL1(L1_I_ERR, "TEXP in state %s", iwic_printstate(sc));
+ }
+
+ if (irq_stat & D_EXIR_WEXP)
+ {
+ NDBGL1(L1_I_ERR, "WEXP in state %s", iwic_printstate(sc));
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * All receiving and transmitting takes place here.
+ *---------------------------------------------------------------------------*/
+void
+iwic_dchan_xfer_irq(struct iwic_softc *sc, int ista)
+{
+ NDBGL1(L1_I_MSG, "ISTA = 0x%x", ista);
+
+ if (ista & (ISTA_D_RMR | ISTA_D_RME))
+ {
+ /* Receive message ready */
+ dchan_receive(sc, ista);
+ }
+ if (ista & ISTA_D_XFR)
+ {
+ /* Transmitter ready */
+ sc->sc_dchan.tx_ready = 1;
+
+ iwic_dchan_transmit(sc);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_dchan_disable(struct iwic_softc *sc)
+{
+ int s;
+
+ s = SPLI4B();
+
+ if (sc->sc_dchan.obuf)
+ {
+ if (sc->sc_dchan.free_obuf)
+ i4b_Dfreembuf(sc->sc_dchan.obuf);
+ sc->sc_dchan.obuf = NULL;
+ }
+
+ if (sc->sc_dchan.obuf2)
+ {
+ if (sc->sc_dchan.free_obuf2)
+ i4b_Dfreembuf(sc->sc_dchan.obuf2);
+ sc->sc_dchan.obuf2 = NULL;
+ }
+
+ splx(s);
+
+ IWIC_WRITE(sc, CIX, CIX_DRC);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+int
+iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
+{
+ int s;
+
+ if (!m)
+ return 0;
+
+ s = SPLI4B();
+
+ /* Queue message */
+
+ if (sc->sc_dchan.obuf)
+ {
+ if (sc->sc_dchan.obuf2)
+ {
+ NDBGL1(L1_I_ERR, "no buffer space!");
+ }
+ else
+ {
+ sc->sc_dchan.obuf2 = m;
+ sc->sc_dchan.free_obuf2 = freeflag;
+ }
+ }
+ else
+ {
+ sc->sc_dchan.obuf = m;
+ sc->sc_dchan.obuf_ptr = m->m_data;
+ sc->sc_dchan.obuf_len = m->m_len;
+ sc->sc_dchan.free_obuf = freeflag;
+ }
+
+ iwic_dchan_transmit(sc);
+
+ splx(s);
+
+ return (0);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+dchan_get_mbuf(struct iwic_softc *sc, int len)
+{
+ sc->sc_dchan.ibuf = i4b_Dgetmbuf(len);
+
+ if (!sc->sc_dchan.ibuf)
+ panic("dchan_get_mbuf: unable to allocate %d bytes for mbuf!\n", len);
+
+ sc->sc_dchan.ibuf_ptr = sc->sc_dchan.ibuf->m_data;
+ sc->sc_dchan.ibuf_max_len = sc->sc_dchan.ibuf->m_len;
+ sc->sc_dchan.ibuf_len = 0;
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+dchan_receive(struct iwic_softc *sc, int ista)
+{
+ if (ista & ISTA_D_RMR)
+ {
+ /* Got 64 bytes in FIFO */
+
+ if (!sc->sc_dchan.ibuf)
+ {
+ dchan_get_mbuf(sc, MAX_DFRAME_LEN);
+
+ }
+ else if ((sc->sc_dchan.ibuf_len + MAX_DFRAME_LEN) >
+ sc->sc_dchan.ibuf_max_len)
+ {
+/*XXX*/ panic("dchan_receive: not enough space in buffer!\n");
+ }
+
+ IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, 64);
+
+ sc->sc_dchan.ibuf_ptr += 64;
+ sc->sc_dchan.ibuf_len += 64;
+ sc->sc_dchan.rx_count += 64;
+ }
+ if (ista & ISTA_D_RME)
+ {
+ /* Got end of frame */
+ int hi, lo;
+ int total_frame_len;
+ int status;
+
+ lo = IWIC_READ(sc, D_RBCL);
+ hi = IWIC_READ(sc, D_RBCH);
+ total_frame_len = D_RBC(hi, lo);
+ lo = lo & 0x3f;
+
+ if (lo == 0)
+ lo = IWIC_DCHAN_FIFO_LEN;
+
+ if (!sc->sc_dchan.ibuf)
+ {
+ dchan_get_mbuf(sc, lo);
+ }
+ else if ((sc->sc_dchan.ibuf_len + lo) >
+ sc->sc_dchan.ibuf_max_len)
+ {
+ panic("dchan_receive: buffer not long enough");
+ }
+
+ IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, lo);
+ sc->sc_dchan.ibuf_len += lo;
+ sc->sc_dchan.rx_count += lo;
+
+ status = IWIC_READ(sc, D_RSTA);
+
+ if (status & (D_RSTA_RDOV | D_RSTA_CRCE | D_RSTA_RMB))
+ {
+ NDBGL1(L1_I_ERR, "bad read status 0x%x", status);
+ }
+
+ sc->sc_dchan.ibuf->m_len = sc->sc_dchan.ibuf_len;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IWICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_dchan.trace_count;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, sc->sc_dchan.ibuf->m_len, sc->sc_dchan.ibuf->m_data);
+ }
+
+ i4b_l1_ph_data_ind(L0IWICUNIT(sc->sc_unit), sc->sc_dchan.ibuf);
+
+ sc->sc_dchan.ibuf = NULL;
+ }
+ IWIC_WRITE(sc, D_CMDR, D_CMDR_RACK);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_dchan_transmit(struct iwic_softc *sc)
+{
+ int cmd;
+ u_char *ptr;
+ int len;
+
+ if (!sc->sc_dchan.tx_ready)
+ return;
+
+ if (!sc->sc_dchan.obuf)
+ return;
+
+ if (sc->sc_I430state != ST_F7)
+ return;
+
+ ptr = sc->sc_dchan.obuf_ptr;
+ len = min(sc->sc_dchan.obuf_len, IWIC_DCHAN_FIFO_LEN);
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IWICUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_dchan.trace_count;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, len, ptr);
+ }
+
+ IWIC_WRDFIFO(sc, ptr, len);
+
+ sc->sc_dchan.tx_count += len;
+
+ if (len < sc->sc_dchan.obuf_len)
+ {
+ sc->sc_dchan.obuf_ptr += len;
+ sc->sc_dchan.obuf_len -= len;
+
+ cmd = D_CMDR_XMS;
+
+ }
+ else
+ {
+ if (sc->sc_dchan.free_obuf)
+ i4b_Dfreembuf(sc->sc_dchan.obuf);
+
+ sc->sc_dchan.obuf = NULL;
+ sc->sc_dchan.obuf_ptr = NULL;
+ sc->sc_dchan.obuf_len = 0;
+
+ if (sc->sc_dchan.obuf2)
+ {
+ sc->sc_dchan.obuf = sc->sc_dchan.obuf2;
+ sc->sc_dchan.obuf_ptr = sc->sc_dchan.obuf->m_data;
+ sc->sc_dchan.obuf_len = sc->sc_dchan.obuf->m_len;
+ sc->sc_dchan.free_obuf = sc->sc_dchan.free_obuf2;
+
+ sc->sc_dchan.obuf2 = NULL;
+ }
+ cmd = D_CMDR_XMS | D_CMDR_XME;
+ }
+ sc->sc_dchan.tx_ready = 0;
+ IWIC_WRITE(sc, D_CMDR, cmd);
+}
+
+#ifdef NOTDEF
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+output_bytes(char *prefix, u_char * ptr, int len)
+{
+ char buf[400];
+ char tmp[10];
+ int i;
+
+ sprintf(buf, "%s bytes ", prefix);
+ for (i = 0; i < len; i++)
+ {
+ if (i != (len - 1))
+ sprintf(tmp, "0x%x, ", ptr[i] & 0xff);
+ else
+ sprintf(tmp, "0x%x", ptr[i] & 0xff);
+ strcat(buf, tmp);
+ }
+ strcat(buf, "\n";
+ printf(buf);
+}
+#endif
+
+#endif
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_ext.h b/sys/i4b/layer1/iwic/i4b_iwic_ext.h
new file mode 100644
index 0000000..7f75797
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_ext.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2000 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_ext.h,v 1.4 2000/06/02 16:14:36 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 14:52:10 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_IWIC_EXT_H_
+#define _I4B_IWIC_EXT_H_
+
+#include <i4b/include/i4b_l3l4.h>
+
+void iwic_set_linktab(int unit, int channel, drvr_link_t * dlt);
+isdn_link_t *iwic_ret_linktab(int unit, int channel);
+
+int iwic_ph_data_req(int unit, struct mbuf *m, int freeflag);
+int iwic_ph_activate_req(int unit);
+int iwic_mph_command_req(int unit, int command, void *parm);
+
+#endif /* _I4B_IWIC_EXT_H_ */
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_fsm.c b/sys/i4b/layer1/iwic/i4b_iwic_fsm.c
new file mode 100644
index 0000000..2737fc6
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_fsm.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_fsm.c,v 1.4 2000/05/29 15:41:42 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Thu Apr 27 14:56:54 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "iwic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#if (NIWIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/iwic/i4b_iwic.h>
+#include <i4b/layer1/iwic/i4b_w6692.h>
+
+#if DO_I4B_DEBUG
+static char *state_names[] = {
+ "F3N",
+ "F3",
+ "F4",
+ "F5",
+ "F6",
+ "F7",
+ "F8",
+ "ILLEGAL",
+};
+
+static char *event_names[] = {
+ "PHAR",
+ "CE",
+ "T3",
+ "INFO0",
+ "RSY",
+ "INFO2",
+ "INFO48",
+ "INFO410",
+ "DR",
+ "PU",
+ "DIS",
+ "EI",
+ "ILLEGAL"
+};
+#endif
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR executing");
+ IWIC_WRITE(sc, CIX, CIX_ECK);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_AR3(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR3 executing");
+ IWIC_WRITE(sc, CIX, CIX_AR8);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_I0I(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_IOI executing");
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_I0A(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_IOA executing");
+ iwic_dchan_disable(sc);
+ i4b_l1_ph_deactivate_ind(L0IWICUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
+ iwic_dchan_transmit(sc);
+ i4b_l1_ph_activate_ind(L0IWICUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct iwic_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
+ iwic_dchan_transmit(sc);
+ i4b_l1_ph_activate_ind(L0IWICUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+struct iwic_state_tab {
+ void (*func) (struct iwic_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} iwic_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3N F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ */
+/* EV_PHAR */ {{F_AR, ST_F3 }, {F_AR3, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_F5 }, {F_NULL, ST_F6 }, {F_NULL, ST_F7 }, {F_NULL, ST_F8 }, {F_NULL, ST_ILL }},
+/* EV_CE */ {{F_NULL, ST_F3 }, {F_AR3, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_F4 }, {F_NULL, ST_ILL }},
+/* EV_T3 */ {{F_NULL, ST_F3N }, {F_NULL, ST_F3 }, {F_NULL, ST_F3 }, {F_NULL, ST_F3 }, {F_NULL, ST_F3 }, {F_NULL, ST_F7 }, {F_NULL, ST_F8 }, {F_NULL, ST_ILL }},
+/* EV_INFO0 */ {{F_I0I, ST_F3 }, {F_I0I, ST_F3 }, {F_I0I, ST_F3 }, {F_I0I, ST_F3 }, {F_I0A, ST_F3 }, {F_I0A, ST_F3 }, {F_I0A, ST_F3 }, {F_NULL, ST_ILL }},
+/* EV_RSY */ {{F_NULL, ST_F3 }, {F_NULL, ST_F5 }, {F_NULL, ST_F5 }, {F_NULL, ST_F5 }, {F_NULL, ST_F8 }, {F_NULL, ST_F8 }, {F_NULL, ST_F8 }, {F_NULL, ST_ILL }},
+/* EV_INFO2 */ {{F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_F6 }, {F_NULL, ST_ILL }},
+/* EV_INFO48 */ {{F_AI8 , ST_F7 }, {F_AI8, ST_F7 }, {F_AI8, ST_F7 }, {F_AI8, ST_F7 }, {F_AI8, ST_F7 }, {F_AI8, ST_F7 }, {F_AI8, ST_F7 }, {F_NULL, ST_ILL }},
+/* EV_INFO410*/ {{F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_AI10, ST_F7 }, {F_NULL, ST_ILL }},
+/* EV_DR */ {{F_NULL, ST_F3 }, {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_NULL, ST_ILL }},
+/* EV_PU */ {{F_NULL, ST_F3 }, {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_NULL, ST_ILL }},
+/* EV_DIS */ {{F_NULL, ST_F3N }, {F_NULL, ST_F3N }, {F_NULL, ST_F3N }, {F_NULL, ST_F3N }, {F_NULL, ST_F3N }, {F_I0A, ST_F3N }, {F_I0A, ST_F3N }, {F_NULL, 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_NULL, ST_F3 }, {F_NULL, ST_ILL }},
+/* EV_ILL */ {{F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }, {F_NULL, ST_ILL }},
+};
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_next_state(struct iwic_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ NDBGL1(L1_F_MSG, "event %s", event_names[event]);
+
+ if (event >= N_EVENTS)
+ {
+ printf("iwic_next_state: event >= N_EVENTS\n");
+ return;
+ }
+
+ currstate = sc->sc_I430state;
+
+ newstate = iwic_state_tab[event][currstate].newstate;
+ if (newstate >= N_STATES)
+ {
+ printf("iwic_next_state: newstate >= N_STATES\n");
+ return;
+ }
+
+ NDBGL1(L1_F_MSG, "state %s -> %s",
+ state_names[currstate], state_names[newstate]);
+
+ sc->sc_I430state = newstate;
+
+ (*iwic_state_tab[event][currstate].func) (sc);
+}
+
+#if DO_I4B_DEBUG
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+iwic_printstate(struct iwic_softc *sc)
+{
+ return((char *)state_names[sc->sc_I430state]);
+}
+#endif
+
+#endif
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_l1if.c b/sys/i4b/layer1/iwic/i4b_iwic_l1if.c
new file mode 100644
index 0000000..e0208cc
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_l1if.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_l1if.c,v 1.3 2000/06/02 16:14:36 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 14:52:39 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "iwic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#if (NIWIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/iwic/i4b_iwic.h>
+#include <i4b/layer1/iwic/i4b_iwic_ext.h>
+#include <i4b/layer1/iwic/i4b_w6692.h>
+
+/* jump table for multiplex routines */
+
+struct i4b_l1mux_func iwic_l1mux_func = {
+ iwic_ret_linktab,
+ iwic_set_linktab,
+ iwic_mph_command_req,
+ iwic_ph_data_req,
+ iwic_ph_activate_req,
+};
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+int
+iwic_ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+
+ return iwic_dchan_data_req(sc, m, freeflag);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+int
+iwic_ph_activate_req(int unit)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+
+ iwic_next_state(sc, EV_PHAR);
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+int
+iwic_mph_command_req(int unit, int command, void *parm)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+
+ switch (command)
+ {
+ case CMR_DOPEN: /* Daemon running */
+ NDBGL1(L1_PRIM, "CMR_DOPEN");
+ sc->enabled = TRUE;
+ break;
+
+ case CMR_DCLOSE: /* Daemon not running */
+ NDBGL1(L1_PRIM, "CMR_DCLOSE");
+ sc->enabled = FALSE;
+ break;
+
+ case CMR_SETTRACE:
+ NDBGL1(L1_PRIM, "CMR_SETTRACE, parm = %d", (unsigned int)parm);
+ sc->sc_trace = (unsigned int)parm;
+ break;
+
+ default:
+ NDBGL1(L1_PRIM, "unknown command = %d", command);
+ break;
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+isdn_link_t *
+iwic_ret_linktab(int unit, int channel)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+ struct iwic_bchan *bchan = &sc->sc_bchan[channel];
+
+ return &bchan->iwic_isdn_linktab;
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+void
+iwic_set_linktab (int unit, int channel, drvr_link_t *dlt)
+{
+ struct iwic_softc *sc = iwic_find_sc(unit);
+ struct iwic_bchan *bchan = &sc->sc_bchan[channel];
+
+ bchan->iwic_drvr_linktab = dlt;
+}
+
+#endif
diff --git a/sys/i4b/layer1/iwic/i4b_iwic_pci.c b/sys/i4b/layer1/iwic/i4b_iwic_pci.c
new file mode 100644
index 0000000..e503b2f
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_iwic_pci.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_iwic_pci.c,v 1.14 2000/09/04 09:08:45 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Sep 4 09:49:03 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "iwic.h"
+#include "opt_i4b.h"
+#include "pci.h"
+
+#if (NIWIC > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/iwic/i4b_iwic.h>
+#include <i4b/layer1/iwic/i4b_iwic_ext.h>
+#include <i4b/layer1/iwic/i4b_w6692.h>
+
+extern struct i4b_l1mux_func iwic_l1mux_func;
+
+/* Winbond PCI Configuration Space */
+
+#define BASEREG0_MAPOFF 0x00
+#define BASEREG1_MAPOFF 0x04
+
+#define BADDR0 (PCIR_MAPS + BASEREG0_MAPOFF)
+#define BADDR1 (PCIR_MAPS + BASEREG1_MAPOFF)
+
+
+static void iwic_pci_intr(struct iwic_softc *sc);
+static int iwic_pci_probe(device_t dev);
+static int iwic_pci_attach(device_t dev);
+
+static device_method_t iwic_pci_methods[] =
+{
+ DEVMETHOD(device_probe, iwic_pci_probe),
+ DEVMETHOD(device_attach, iwic_pci_attach),
+ { 0, 0 }
+};
+
+static driver_t iwic_pci_driver =
+{
+ "iwic",
+ iwic_pci_methods,
+ 0
+};
+
+static devclass_t iwic_pci_devclass;
+
+DRIVER_MODULE(iwic, pci, iwic_pci_driver, iwic_pci_devclass, 0, 0);
+
+#define IWIC_MAXUNIT 4
+
+struct iwic_softc iwic_sc[IWIC_MAXUNIT];
+
+/*---------------------------------------------------------------------------*
+ * PCI ID list for ASUSCOM card got from Asuscom in March 2000:
+ *
+ * Vendor ID: 0675 Device ID: 1702
+ * Vendor ID: 0675 Device ID: 1703
+ * Vendor ID: 0675 Device ID: 1707
+ * Vendor ID: 10CF Device ID: 105E
+ * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 2000
+ * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 1702
+ * Vendor ID: 1043 Device ID: 0675 SubVendor: 144F SubDevice ID: 1707
+ * Vendor ID: 1043 Device ID: 0675 SubVendor: 1043 SubDevice ID: 1702
+ * Vendor ID: 1043 Device ID: 0675 SubVendor: 1043 SubDevice ID: 1707
+ * Vendor ID: 1050 Device ID: 6692 SubVendor: 0675 SubDevice ID: 1702
+ *---------------------------------------------------------------------------*/
+
+static struct winids {
+ u_int32_t type;
+ int sv;
+ int sd;
+ const char *desc;
+} win_ids[] = {
+ { 0x66921050, -1, -1, "Generic Winbond W6692 ISDN PCI (0x66921050)" },
+ { 0x17020675, -1, -1, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x17020675)" },
+ { 0x17030675, -1, -1, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x17030675)" },
+ { 0x17070675, -1, -1, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x17070675)" },
+ { 0x105e10cf, -1, -1, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x105e10cf)" },
+ { 0x06751043, 0x144F, 0x2000, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x144F, 0x1702, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x144F, 0x1707, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x1443, 0x1702, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x1443, 0x1707, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x144F, 0x2000, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x144F, 0x2000, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x06751043, 0x144F, 0x2000, "ASUSCOM P-IN100-ST-D (Winbond W6692, 0x06751043)" },
+ { 0x00000000, 0, 0, NULL }
+};
+
+/*---------------------------------------------------------------------------*
+ * iwic PCI probe
+ *---------------------------------------------------------------------------*/
+static int
+iwic_pci_probe(device_t dev)
+{
+ u_int32_t type = pci_get_devid(dev);
+ u_int32_t sv = pci_get_subvendor(dev);
+ u_int32_t sd = pci_get_subdevice(dev);
+
+ struct winids *wip = win_ids;
+
+ while(wip->type)
+ {
+ if(wip->type == type)
+ {
+ if(((wip->sv == -1) && (wip->sd == -1)) ||
+ ((wip->sv == sv) && (wip->sd == sd)))
+ break;
+ }
+ ++wip;
+ }
+
+ if(wip->desc)
+ {
+ if(bootverbose)
+ {
+ printf("iwic_pci_probe: vendor = 0x%x, device = 0x%x\n", pci_get_vendor(dev), pci_get_device(dev));
+ printf("iwic_pci_probe: subvendor = 0x%x, subdevice = 0x%x\n", sv, sd);
+ }
+ device_set_desc(dev, wip->desc);
+ return(0);
+ }
+ else
+ {
+ return(ENXIO);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * PCI attach
+ *---------------------------------------------------------------------------*/
+static int
+iwic_pci_attach(device_t dev)
+{
+ unsigned short iobase;
+ struct iwic_softc *sc;
+ void *ih = 0;
+ int unit = device_get_unit(dev);
+ struct iwic_bchan *bchan;
+
+ /* check max unit range */
+
+ if(unit >= IWIC_MAXUNIT)
+ {
+ printf("iwic%d: Error, unit %d >= IWIC_MAXUNIT!\n", unit, unit);
+ return(ENXIO);
+ }
+
+ sc = iwic_find_sc(unit); /* get softc */
+
+ sc->sc_unit = unit;
+
+ /* use the i/o mapped base address */
+
+ sc->sc_resources.io_rid[0] = BADDR1;
+
+ 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("iwic%d: Couldn't alloc io port!\n", unit);
+ return(ENXIO);
+ }
+
+ iobase = rman_get_start(sc->sc_resources.io_base[0]);
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0UL, ~0UL, 1, RF_SHAREABLE|RF_ACTIVE)))
+ {
+ printf("iwic%d: Couldn't alloc irq!\n",unit);
+ return(ENXIO);
+ }
+
+ /* setup card type */
+
+ sc->sc_cardtyp = CARD_TYPEP_WINB6692;
+ sc->sc_iobase = (u_int32_t) iobase;
+ sc->sc_trace = TRACE_OFF;
+ sc->sc_I430state = ST_F3N; /* Deactivated */
+ sc->enabled = FALSE;
+
+ if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void*))iwic_pci_intr,
+ sc, &ih))
+ {
+ printf("iwic%d: Couldn't set up irq!\n", unit);
+ return(ENXIO);
+ }
+
+ /* disable interrupts */
+ IWIC_WRITE(sc, IMASK, 0xff);
+
+ iwic_dchan_init(sc);
+
+ bchan = &sc->sc_bchan[IWIC_BCH_A];
+ bchan->unit = unit;
+ bchan->offset = B1_CHAN_OFFSET;
+ bchan->channel = IWIC_BCH_A;
+ bchan->state = ST_IDLE;
+
+ iwic_bchannel_setup(unit, IWIC_BCH_A, BPROT_NONE, 0);
+
+ bchan = &sc->sc_bchan[IWIC_BCH_B];
+ bchan->unit = unit;
+ bchan->offset = B2_CHAN_OFFSET;
+ bchan->channel = IWIC_BCH_B;
+ bchan->state = ST_IDLE;
+
+ iwic_bchannel_setup(unit, IWIC_BCH_B, BPROT_NONE, 0);
+
+ iwic_init_linktab(sc);
+
+ i4b_l1_mph_status_ind(L0IWICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &iwic_l1mux_func);
+
+ IWIC_READ(sc, ISTA);
+
+ /* Enable interrupts */
+ IWIC_WRITE(sc, IMASK, IMASK_XINT0 | IMASK_XINT1);
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * IRQ handler
+ *---------------------------------------------------------------------------*/
+static void
+iwic_pci_intr(struct iwic_softc *sc)
+{
+ while (1)
+ {
+ int irq_stat = IWIC_READ(sc, ISTA);
+
+ if (irq_stat == 0)
+ break;
+
+ if (irq_stat & (ISTA_D_RME | ISTA_D_RMR | ISTA_D_XFR))
+ {
+ iwic_dchan_xfer_irq(sc, irq_stat);
+ }
+ if (irq_stat & ISTA_D_EXI)
+ {
+ iwic_dchan_xirq(sc);
+ }
+ if (irq_stat & ISTA_B1_EXI)
+ {
+ iwic_bchan_xirq(sc, 0);
+ }
+ if (irq_stat & ISTA_B2_EXI)
+ {
+ iwic_bchan_xirq(sc, 1);
+ }
+ }
+}
+
+#endif
diff --git a/sys/i4b/layer1/iwic/i4b_w6692.h b/sys/i4b/layer1/iwic/i4b_w6692.h
new file mode 100644
index 0000000..3fb1d15
--- /dev/null
+++ b/sys/i4b/layer1/iwic/i4b_w6692.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 1999, 2000 Dave Boyce. 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_iwic - isdn4bsd Winbond W6692 driver
+ * ----------------------------------------
+ *
+ * $Id: i4b_w6692.h,v 1.1 2000/03/07 14:12:26 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon Mar 6 12:19:55 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#ifndef _I4B_W6692_H_
+#define _I4B_W6692_H_
+
+#define IWIC_BCH_A 0 /* channel A */
+#define IWIC_BCH_B 1 /* channel B */
+
+/*---------------------------------------------------------------------------*
+ * FIFO depths
+ *---------------------------------------------------------------------------*/
+#define IWIC_DCHAN_FIFO_LEN 64
+#define IWIC_BCHAN_FIFO_LEN 64
+
+/*---------------------------------------------------------------------------*
+ * D-Channel register offsets
+ *---------------------------------------------------------------------------*/
+#define D_RFIFO 0x00 /* D channel receive FIFO */
+#define D_XFIFO 0x04 /* D channel transmit FIFO */
+#define D_CMDR 0x08 /* D channel command register */
+#define D_MODE 0x0c /* D channel mode control */
+#define D_TIMR 0x10 /* D channel timer control */
+#define D_EXIR 0x1c /* D channel extended interrupt */
+#define D_EXIM 0x20 /* D channel extended interrupt mask */
+#define D_STAR 0x24 /* D channel status register */
+#define D_RSTA 0x28 /* D channel receive status */
+#define D_SAM 0x2c /* D channel address mask 1 */
+#define D_SAP1 0x30 /* D channel individual SAPI 1 */
+#define D_SAP2 0x34 /* D channel individual SAPI 2 */
+#define D_TAM 0x38 /* D channel address mask 2 */
+#define D_TEI1 0x3c /* D channel individual TEI 1 */
+#define D_TEI2 0x40 /* D channel individual TEI 2 */
+#define D_RBCH 0x44 /* D channel receive frame byte count high */
+#define D_RBCL 0x48 /* D channel receive frame byte count low */
+#define D_CTL 0x54 /* D channel control register */
+
+/*---------------------------------------------------------------------------*
+ * B-channel base offsets
+ *---------------------------------------------------------------------------*/
+#define B1_CHAN_OFFSET 0x80 /* B1 channel offset */
+#define B2_CHAN_OFFSET 0xc0 /* B2 channel offset */
+
+/*---------------------------------------------------------------------------*
+ * B-channel register offsets, from base
+ *---------------------------------------------------------------------------*/
+#define B_RFIFO 0x00 /* B channel receive FIFO */
+#define B_XFIFO 0x04 /* B channel transmit FIFO */
+#define B_CMDR 0x08 /* B channel command register */
+#define B_MODE 0x0c /* B channel mode control */
+#define B_EXIR 0x10 /* B channel extended interrupt */
+#define B_EXIM 0x14 /* B channel extended interrupt mask */
+#define B_STAR 0x18 /* B channel status register */
+#define B_ADM1 0x1c /* B channel address mask 1 */
+#define B_ADM2 0x20 /* B channel address mask 2 */
+#define B_ADR1 0x24 /* B channel address 1 */
+#define B_ADR2 0x28 /* B channel address 2 */
+#define B_RBCL 0x2c /* B channel receive frame byte count high */
+#define B_RBCH 0x30 /* B channel receive frame byte count low */
+
+/*---------------------------------------------------------------------------*
+ * Remaining control register offsets.
+ *---------------------------------------------------------------------------*/
+#define ISTA 0x14 /* Interrupt status register */
+#define IMASK 0x18 /* Interrupt mask register */
+#define TIMR2 0x4c /* Timer 2 */
+#define L1_RC 0x50 /* GCI layer 1 ready code */
+#define CIR 0x58 /* Command/Indication receive */
+#define CIX 0x5c /* Command/Indication transmit */
+#define SQR 0x60 /* S/Q channel receive register */
+#define SQX 0x64 /* S/Q channel transmit register */
+#define PCTL 0x68 /* Peripheral control register */
+#define MOR 0x6c /* Monitor receive channel */
+#define MOX 0x70 /* Monitor transmit channel */
+#define MOSR 0x74 /* Monitor channel status register */
+#define MOCR 0x78 /* Monitor channel control register */
+#define GCR 0x7c /* GCI mode control register */
+#define XADDR 0xf4 /* Peripheral address register */
+#define XDATA 0xf8 /* Peripheral data register */
+#define EPCTL 0xfc /* Serial EEPROM control */
+
+/*---------------------------------------------------------------------------*
+ * register bits
+ *---------------------------------------------------------------------------*/
+#define D_CMDR_RACK 0x80
+#define D_CMDR_RRST 0x40
+#define D_CMDR_STT 0x10
+#define D_CMDR_XMS 0x08
+#define D_CMDR_XME 0x02
+#define D_CMDR_XRST 0x01
+
+#define D_MODE_MMS 0x80
+#define D_MODE_RACT 0x40
+#define D_MODE_TMS 0x10
+#define D_MODE_TEE 0x08
+#define D_MODE_MFD 0x04
+#define D_MODE_DLP 0x02
+#define D_MODE_RLP 0x01
+
+#define D_TIMR_CNT(i) (((i) >> 5) & 0x07)
+#define D_TIMR_VAL(i) ((i) & 0x1f)
+
+#define ISTA_D_RMR 0x80
+#define ISTA_D_RME 0x40
+#define ISTA_D_XFR 0x20
+#define ISTA_XINT1 0x10
+#define ISTA_XINT0 0x08
+#define ISTA_D_EXI 0x04
+#define ISTA_B1_EXI 0x02
+#define ISTA_B2_EXI 0x01
+
+#define IMASK_D_RMR 0x80
+#define IMASK_D_RME 0x40
+#define IMASK_D_XFR 0x20
+#define IMASK_XINT1 0x10
+#define IMASK_XINT0 0x08
+#define IMASK_D_EXI 0x04
+#define IMASK_B1_EXI 0x02
+#define IMASK_B2_EXI 0x01
+
+#define D_EXIR_RDOV 0x80
+#define D_EXIR_XDUN 0x40
+#define D_EXIR_XCOL 0x20
+#define D_EXIR_TIN2 0x10
+#define D_EXIR_MOC 0x08
+#define D_EXIR_ISC 0x04
+#define D_EXIR_TEXP 0x02
+#define D_EXIR_WEXP 0x01
+
+#define D_EXIM_RDOV 0x80
+#define D_EXIM_XDUN 0x40
+#define D_EXIM_XCOL 0x20
+#define D_EXIM_TIM2 0x10
+#define D_EXIM_MOC 0x08
+#define D_EXIM_ISC 0x04
+#define D_EXIM_TEXP 0x02
+#define D_EXIM_WEXP 0x01
+
+#define D_STAR_XDOW 0x80
+#define D_STAR_XBZ 0x20
+#define D_STAR_DRDY 0x10
+
+#define D_RSTA_RDOV 0x40
+#define D_RSTA_CRCE 0x20
+#define D_RSTA_RMB 0x10
+
+#define D_RBCH_VN(i) (((i) >> 6) & 0x03)
+#define D_RBCH_LOV 0x20
+#define D_RBC(h,l) (((((h) & 0x1f)) << 8) + (l))
+
+#define D_TIMR2_TMD 0x80
+#define D_TIMR2_TBCN(i) ((i) & 0x3f)
+
+#define L1_RC_RC(i) ((i) & 0x0f)
+
+#define D_CTL_WTT(i) (((i) > 6) & 0x03)
+#define D_CTL_SRST 0x20
+#define D_CTL_TPS 0x04
+#define D_CTL_OPS(i) ((i) & 0x03)
+
+#define CIR_SCC 0x80
+#define CIR_ICC 0x40
+#define CIR_CODR(i) ((i) & 0x0f)
+
+#define CIX_ECK 0x00
+#define CIX_RST 0x01
+#define CIX_SCP 0x04
+#define CIX_SSP 0x02
+#define CIX_AR8 0x08
+#define CIX_AR10 0x09
+#define CIX_EAL 0x0a
+#define CIX_DRC 0x0f
+
+#define CIR_CE 0x07
+#define CIR_DRD 0x00
+#define CIR_LD 0x04
+#define CIR_ARD 0x08
+#define CIR_TI 0x0a
+#define CIR_ATI 0x0b
+#define CIR_AI8 0x0c
+#define CIR_AI10 0x0d
+#define CIR_CD 0x0f
+
+#define SQR_XIND1 0x80
+#define SQR_XIND0 0x40
+#define SQR_MSYN 0x20
+#define SQR_SCIE 0x10
+#define SQR_S(i) ((i) & 0x0f)
+
+#define SQX_SCIE 0x10
+#define SQX_Q(i) ((i) & 0x0f)
+
+
+#define B_CMDR_RACK 0x80
+#define B_CMDR_RRST 0x40
+#define B_CMDR_RACT 0x20
+#define B_CMDR_XMS 0x04
+#define B_CMDR_XME 0x02
+#define B_CMDR_XRST 0x01
+
+#define B_MODE_MMS 0x80
+#define B_MODE_ITF 0x40
+#define B_MODE_EPCM 0x20
+#define B_MODE_BSW1 0x10
+#define B_MODE_BSW0 0x08
+#define B_MODE_SW56 0x04
+#define B_MODE_FTS1 0x02
+#define B_MODE_FTS0 0x01
+
+#define B_EXIR_RMR 0x40
+#define B_EXIR_RME 0x20
+#define B_EXIR_RDOV 0x10
+#define B_EXIR_XFR 0x02
+#define B_EXIR_XDUN 0x01
+
+#define B_EXIM_RMR 0x40
+#define B_EXIM_RME 0x20
+#define B_EXIM_RDOV 0x10
+#define B_EXIM_XFR 0x02
+#define B_EXIM_XDUN 0x01
+
+#define B_STAR_RDOV 0x40
+#define B_STAR_CRCE 0x20
+#define B_STAR_RMB 0x10
+#define B_STAR_XDOW 0x04
+#define B_STAR_XBZ 0x01
+
+#define B_RBC(h,l) (((((h) & 0x1f)) << 8) + (l))
+
+#endif /* _I4B_W6692_H_ */
OpenPOWER on IntegriCloud