Driver for Winbond W6692 passive ISDN cards.
Ported from the FreeBSD driver by Ilpo Ruotsalainen <lonewolf@cubical.fi>, and reviewed by Martin.
This commit is contained in:
parent
646628d7fa
commit
218f60746c
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: files.pci,v 1.177 2002/09/03 18:54:41 augustss Exp $
|
# $NetBSD: files.pci,v 1.178 2002/09/24 22:05:19 pooka Exp $
|
||||||
#
|
#
|
||||||
# Config file and device description for machine-independent PCI code.
|
# Config file and device description for machine-independent PCI code.
|
||||||
# Included by ports that need it. Requires that the SCSI files be
|
# Included by ports that need it. Requires that the SCSI files be
|
||||||
|
@ -552,6 +552,14 @@ device ifpci: isdndev, passive_isdn
|
||||||
attach ifpci at pci
|
attach ifpci at pci
|
||||||
file dev/pci/ifpci.c ifpci
|
file dev/pci/ifpci.c ifpci
|
||||||
|
|
||||||
|
# Winbond W6692
|
||||||
|
device iwic: isdndev, passive_isdn
|
||||||
|
attach iwic at pci with iwic_pci
|
||||||
|
file dev/pci/iwic_pci.c iwic
|
||||||
|
file dev/pci/iwic_bchan.c iwic
|
||||||
|
file dev/pci/iwic_dchan.c iwic
|
||||||
|
file dev/pci/iwic_fsm.c iwic
|
||||||
|
|
||||||
# IrDA devices
|
# IrDA devices
|
||||||
# Toshiba Fast Infrared Type O IrDA driver
|
# Toshiba Fast Infrared Type O IrDA driver
|
||||||
device oboe: irbus, irdasir
|
device oboe: irbus, irdasir
|
||||||
|
|
|
@ -0,0 +1,765 @@
|
||||||
|
/* $NetBSD: iwic_bchan.c,v 1.1 2002/09/24 22:05:19 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2000, 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_iwic - isdn4bsd Winbond W6692 driver
|
||||||
|
* ----------------------------------------
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*
|
||||||
|
* last edit-date: [Tue Jan 16 13:21:24 2001]
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: iwic_bchan.c,v 1.1 2002/09/24 22:05:19 pooka Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/device.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#include <dev/pci/pcireg.h>
|
||||||
|
#include <dev/pci/pcivar.h>
|
||||||
|
#include <dev/pci/pcidevs.h>
|
||||||
|
|
||||||
|
#include <dev/pci/iwicreg.h>
|
||||||
|
#include <dev/pci/iwicvar.h>
|
||||||
|
|
||||||
|
#include <netisdn/i4b_debug.h>
|
||||||
|
#include <netisdn/i4b_ioctl.h>
|
||||||
|
#include <netisdn/i4b_trace.h>
|
||||||
|
|
||||||
|
#include <netisdn/i4b_l2.h>
|
||||||
|
#include <netisdn/i4b_l1l2.h>
|
||||||
|
#include <netisdn/i4b_mbuf.h>
|
||||||
|
#include <netisdn/i4b_global.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, "%s: EXIR B-channel Receive Data Overflow", sc->sc_dev.dv_xname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irq_stat & B_EXIR_XDUN)
|
||||||
|
{
|
||||||
|
NDBGL1(L1_H_XFRERR, "%s: EXIR B-channel Transmit Data Underrun", sc->sc_dev.dv_xname);
|
||||||
|
cmd |= (B_CMDR_XRST); /*XXX must retransmit frame ! */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RX message end interrupt */
|
||||||
|
|
||||||
|
if(irq_stat & B_EXIR_RME)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
NDBGL1(L1_H_IRQ, "B_EXIR_RME");
|
||||||
|
|
||||||
|
error = (IWIC_READ(sc,chan->offset+B_STAR) &
|
||||||
|
(B_STAR_RDOV | B_STAR_CRCE | B_STAR_RMB));
|
||||||
|
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
if(error & B_STAR_RDOV)
|
||||||
|
NDBGL1(L1_H_XFRERR, "%s: B-channel Receive Data Overflow", sc->sc_dev.dv_xname);
|
||||||
|
if(error & B_STAR_CRCE)
|
||||||
|
NDBGL1(L1_H_XFRERR, "%s: B-channel CRC Error", sc->sc_dev.dv_xname);
|
||||||
|
if(error & B_STAR_RMB)
|
||||||
|
NDBGL1(L1_H_XFRERR, "%s: B-channel Receive Message Aborted", sc->sc_dev.dv_xname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all error conditions checked, now decide and take action */
|
||||||
|
|
||||||
|
if(error == 0)
|
||||||
|
{
|
||||||
|
register int fifo_data_len;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
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 hdr;
|
||||||
|
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;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
|
||||||
|
|
||||||
|
|
||||||
|
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 hdr;
|
||||||
|
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;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* silence detection */
|
||||||
|
|
||||||
|
if(!(isdn_bchan_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->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
|
||||||
|
|
||||||
|
/* 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->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc);
|
||||||
|
}
|
||||||
|
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 hdr;
|
||||||
|
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;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chan->bprot == BPROT_NONE)
|
||||||
|
{
|
||||||
|
if(!(isdn_bchan_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 hdr;
|
||||||
|
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;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &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(isdn_layer1token t, int chan_no, int bprot, int activate)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = t;
|
||||||
|
struct iwic_bchan *chan = &sc->sc_bchan[chan_no];
|
||||||
|
|
||||||
|
int s = splnet();
|
||||||
|
|
||||||
|
NDBGL1(L1_BCHAN, "%s: chan %d, bprot %d, activate %d",
|
||||||
|
sc->sc_dev.dv_xname, 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 */
|
||||||
|
|
||||||
|
chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||||
|
|
||||||
|
#if defined (__FreeBSD__) && __FreeBSD__ > 4
|
||||||
|
if(!mtx_initialized(&chan->rx_queue.ifq_mtx))
|
||||||
|
mtx_init(&chan->rx_queue.ifq_mtx, "i4b_iwic_rx", NULL, 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
|
||||||
|
if(!mtx_initialized(&chan->tx_queue.ifq_mtx))
|
||||||
|
mtx_init(&chan->tx_queue.ifq_mtx, "i4b_iwic_tx", NULL, 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 */
|
||||||
|
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(isdn_layer1token t,int h_chan)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = (void *)t;
|
||||||
|
struct iwic_bchan *chan = &sc->sc_bchan[h_chan];
|
||||||
|
register int len;
|
||||||
|
register int next_len;
|
||||||
|
|
||||||
|
int s;
|
||||||
|
int activity = -1;
|
||||||
|
int cmd = 0;
|
||||||
|
|
||||||
|
s = splnet(); /* enter critical section */
|
||||||
|
|
||||||
|
NDBGL1(L1_BCHAN, "%s: channel %d", sc->sc_dev.dv_xname, h_chan);
|
||||||
|
|
||||||
|
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(!(isdn_bchan_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 hdr;
|
||||||
|
hdr.type = (h_chan == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
|
||||||
|
hdr.dir = FROM_TE;
|
||||||
|
hdr.count = ++sc->sc_bchan[h_chan].sc_trace_bcount;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &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 hdr;
|
||||||
|
hdr.type = (h_chan == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
|
||||||
|
hdr.dir = FROM_TE;
|
||||||
|
hdr.count = ++sc->sc_bchan[h_chan].sc_trace_bcount;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &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 the chip. if there 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->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
|
||||||
|
|
||||||
|
if(cmd)
|
||||||
|
{
|
||||||
|
cmd |= B_CMDR_RACT;
|
||||||
|
IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
splx(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* return B-channel statistics
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
iwic_bchannel_stat(isdn_layer1token t, int h_chan, bchan_statistics_t *bsp)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = t;
|
||||||
|
struct iwic_bchan *bchan = &sc->sc_bchan[h_chan];
|
||||||
|
|
||||||
|
int s = splnet();
|
||||||
|
|
||||||
|
bsp->outbytes = bchan->txcount;
|
||||||
|
bsp->inbytes = bchan->rxcount;
|
||||||
|
|
||||||
|
bchan->txcount = 0;
|
||||||
|
bchan->rxcount = 0;
|
||||||
|
|
||||||
|
splx(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* initialize our local linktab
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static const struct isdn_l4_bchannel_functions iwic_bchan_driver = {
|
||||||
|
iwic_bchannel_setup,
|
||||||
|
iwic_bchannel_start,
|
||||||
|
iwic_bchannel_stat
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
iwic_init_linktab(struct iwic_softc *sc)
|
||||||
|
{
|
||||||
|
struct iwic_bchan *chan;
|
||||||
|
isdn_link_t *lt;
|
||||||
|
|
||||||
|
/* channel A */
|
||||||
|
|
||||||
|
chan = &sc->sc_bchan[IWIC_BCH_A];
|
||||||
|
lt = &chan->iwic_isdn_linktab;
|
||||||
|
|
||||||
|
lt->l1token = sc;
|
||||||
|
lt->channel = IWIC_BCH_A;
|
||||||
|
lt->bchannel_driver = &iwic_bchan_driver;
|
||||||
|
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->l1token = sc;
|
||||||
|
lt->channel = IWIC_BCH_B;
|
||||||
|
lt->bchannel_driver = &iwic_bchan_driver;
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,462 @@
|
||||||
|
/* $NetBSD: iwic_dchan.c,v 1.1 2002/09/24 22:05:19 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* ----------------------------------------
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*
|
||||||
|
* last edit-date: [Tue Jan 16 13:20:14 2001]
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: iwic_dchan.c,v 1.1 2002/09/24 22:05:19 pooka Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#include <dev/pci/pcivar.h>
|
||||||
|
|
||||||
|
#include <dev/pci/iwicreg.h>
|
||||||
|
#include <dev/pci/iwicvar.h>
|
||||||
|
|
||||||
|
#include <netisdn/i4b_global.h>
|
||||||
|
#include <netisdn/i4b_mbuf.h>
|
||||||
|
|
||||||
|
#define MAX_DFRAME_LEN 264
|
||||||
|
|
||||||
|
static void dchan_receive(struct iwic_softc *sc, int ista);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* initialize D-channel variables and registers
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* Extended IRQ handler for the D-channel
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
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));
|
||||||
|
IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST);
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
IWIC_WRITE(sc, D_CMDR, D_CMDR_XRST);
|
||||||
|
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);
|
||||||
|
isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE);
|
||||||
|
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));
|
||||||
|
isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
|
||||||
|
iwic_next_state(sc, EV_INFO48);
|
||||||
|
break;
|
||||||
|
case CIR_AI10:
|
||||||
|
NDBGL1(L1_I_CICO, "rx AI10 in state %s", iwic_printstate(sc));
|
||||||
|
isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* disable D-channel
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
iwic_dchan_disable(struct iwic_softc *sc)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
s = splnet();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* queue D-channel message for transmission
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if (!m)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
s = splnet();
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* allocate an mbuf
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* D-channel receive data interrupt
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
dchan_receive(struct iwic_softc *sc, int ista)
|
||||||
|
{
|
||||||
|
int command = D_CMDR_RACK;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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 status;
|
||||||
|
|
||||||
|
status = IWIC_READ(sc, D_RSTA);
|
||||||
|
|
||||||
|
if (status & (D_RSTA_RDOV | D_RSTA_CRCE | D_RSTA_RMB))
|
||||||
|
{
|
||||||
|
if (status & D_RSTA_RDOV)
|
||||||
|
NDBGL1(L1_I_ERR, "%s: D-channel Receive Data Overflow", sc->sc_dev.dv_xname);
|
||||||
|
if (status & D_RSTA_CRCE)
|
||||||
|
NDBGL1(L1_I_ERR, "%s: D-channel CRC Error", sc->sc_dev.dv_xname);
|
||||||
|
if (status & D_RSTA_RMB)
|
||||||
|
NDBGL1(L1_I_ERR, "%s: D-channel Receive Message Aborted", sc->sc_dev.dv_xname);
|
||||||
|
command |= D_CMDR_RRST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int hi, lo;
|
||||||
|
int total_frame_len;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
sc->sc_dchan.ibuf->m_len = sc->sc_dchan.ibuf_len;
|
||||||
|
|
||||||
|
if(sc->sc_trace & TRACE_D_RX)
|
||||||
|
{
|
||||||
|
i4b_trace_hdr hdr;
|
||||||
|
hdr.type = TRC_CH_D;
|
||||||
|
hdr.dir = FROM_NT;
|
||||||
|
hdr.count = ++sc->sc_dchan.trace_count;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_dchan.ibuf->m_len, sc->sc_dchan.ibuf->m_data);
|
||||||
|
}
|
||||||
|
isdn_layer2_data_ind(&sc->sc_l2,sc->sc_l3token,sc->sc_dchan.ibuf);
|
||||||
|
|
||||||
|
sc->sc_dchan.ibuf = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IWIC_WRITE(sc, D_CMDR, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* transmit D-channel frame
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
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 hdr;
|
||||||
|
hdr.type = TRC_CH_D;
|
||||||
|
hdr.dir = FROM_TE;
|
||||||
|
hdr.count = ++sc->sc_dchan.trace_count;
|
||||||
|
isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &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);
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
/* $NetBSD: iwic_fsm.c,v 1.1 2002/09/24 22:05:19 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* ----------------------------------------
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*
|
||||||
|
* last edit-date: [Sun Jan 21 11:09:24 2001]
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: iwic_fsm.c,v 1.1 2002/09/24 22:05:19 pooka Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/device.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#include <dev/pci/pcireg.h>
|
||||||
|
#include <dev/pci/pcivar.h>
|
||||||
|
#include <dev/pci/pcidevs.h>
|
||||||
|
|
||||||
|
#include <dev/pci/iwicreg.h>
|
||||||
|
#include <dev/pci/iwicvar.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);
|
||||||
|
isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
F_AI8(struct iwic_softc *sc)
|
||||||
|
{
|
||||||
|
NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
|
||||||
|
iwic_dchan_transmit(sc);
|
||||||
|
isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
F_AI10(struct iwic_softc *sc)
|
||||||
|
{
|
||||||
|
NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
|
||||||
|
iwic_dchan_transmit(sc);
|
||||||
|
isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
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
|
|
@ -0,0 +1,448 @@
|
||||||
|
/* $NetBSD: iwic_pci.c,v 1.1 2002/09/24 22:05:19 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* ----------------------------------------
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*
|
||||||
|
* last edit-date: [Tue Jan 16 10:53:03 2001]
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__KERNEL_RCSID(0, "$NetBSD: iwic_pci.c,v 1.1 2002/09/24 22:05:19 pooka Exp $");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/callout.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#include <dev/pci/pcivar.h>
|
||||||
|
#include <dev/pci/pcidevs.h>
|
||||||
|
|
||||||
|
#include <netisdn/i4b_global.h>
|
||||||
|
|
||||||
|
#include <dev/pci/iwicreg.h>
|
||||||
|
#include <dev/pci/iwicvar.h>
|
||||||
|
|
||||||
|
/* Winbond PCI Configuration Space */
|
||||||
|
|
||||||
|
#define IWIC_PCI_IOBA (PCI_MAPREG_START+0x04)
|
||||||
|
|
||||||
|
static int iwic_pci_intr(void *sc);
|
||||||
|
static int iwic_pci_probe(struct device * dev, struct cfdata * match, void *aux);
|
||||||
|
static void iwic_pci_attach(struct device * parent, struct device * dev, void *aux);
|
||||||
|
static int iwic_pci_activate(struct device * dev, enum devact);
|
||||||
|
|
||||||
|
struct cfattach iwic_pci_ca = {
|
||||||
|
sizeof(struct iwic_softc),
|
||||||
|
iwic_pci_probe,
|
||||||
|
iwic_pci_attach,
|
||||||
|
0,
|
||||||
|
iwic_pci_activate
|
||||||
|
};
|
||||||
|
|
||||||
|
static int iwic_attach_bri(struct iwic_softc * sc);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* 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 {
|
||||||
|
pcireg_t type;
|
||||||
|
int sv;
|
||||||
|
int sd;
|
||||||
|
const char *desc;
|
||||||
|
} win_ids[] = {
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
|
||||||
|
0x144F,
|
||||||
|
0x1707,
|
||||||
|
"Planet PCI ISDN Adapter (Model IA128P-STDV)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_WINBOND,PCI_PRODUCT_WINBOND_W6692),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"Generic Winbond W6692 ISDN PCI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_DYNALINK,PCI_PRODUCT_DYNALINK_IS64PH),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
#if 0
|
||||||
|
/* XXX */
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1703),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_DYNALINK,0x1707),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_CITICORP,0x105E),
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x2000,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x1702,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x1707,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x1443,
|
||||||
|
0x1702,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x1443,
|
||||||
|
0x1707,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x2000,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x2000,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PCI_ID_CODE(PCI_VENDOR_ASUSTEK,PCI_PRODUCT_ASUSTEK_HFCPCI),
|
||||||
|
0x144F,
|
||||||
|
0x2000,
|
||||||
|
"ASUSCOM P-IN100-ST-D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
iwic_find_card(const struct pci_attach_args * pa)
|
||||||
|
{
|
||||||
|
pcireg_t type = pa->pa_id;
|
||||||
|
pcireg_t reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
|
||||||
|
int sv = PCI_VENDOR(reg);
|
||||||
|
int sd = PCI_PRODUCT(reg);
|
||||||
|
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)
|
||||||
|
return wip->desc;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* iwic PCI probe
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
iwic_pci_probe(struct device * dev, struct cfdata * match, void *aux)
|
||||||
|
{
|
||||||
|
if (iwic_find_card(aux))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* PCI attach
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
iwic_pci_attach(struct device * parent, struct device * dev, void *aux)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = (void *) dev;
|
||||||
|
struct iwic_bchan *bchan;
|
||||||
|
pci_intr_handle_t ih;
|
||||||
|
const char *intrstr;
|
||||||
|
struct pci_attach_args *pa = aux;
|
||||||
|
pci_chipset_tag_t pc = pa->pa_pc;
|
||||||
|
|
||||||
|
sc->sc_cardname = iwic_find_card(pa);
|
||||||
|
|
||||||
|
if (!sc->sc_cardname)
|
||||||
|
return; /* Huh? */
|
||||||
|
|
||||||
|
printf(": %s\n", sc->sc_cardname);
|
||||||
|
|
||||||
|
if (pci_mapreg_map(pa, IWIC_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0,
|
||||||
|
&sc->sc_io_bt, &sc->sc_io_bh, &sc->sc_iobase, &sc->sc_iosize)) {
|
||||||
|
printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pci_intr_map(pa, &ih)) {
|
||||||
|
printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intrstr = pci_intr_string(pc, ih);
|
||||||
|
sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, iwic_pci_intr, sc);
|
||||||
|
if (sc->sc_ih == NULL) {
|
||||||
|
printf("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
|
||||||
|
if (intrstr != NULL)
|
||||||
|
printf(" at %s", intrstr);
|
||||||
|
printf("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sc->sc_pc = pc;
|
||||||
|
printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
|
||||||
|
|
||||||
|
/* disable interrupts */
|
||||||
|
IWIC_WRITE(sc, IMASK, 0xff);
|
||||||
|
IWIC_READ(sc, ISTA);
|
||||||
|
|
||||||
|
iwic_dchan_init(sc);
|
||||||
|
|
||||||
|
bchan = &sc->sc_bchan[IWIC_BCH_A];
|
||||||
|
bchan->offset = B1_CHAN_OFFSET;
|
||||||
|
bchan->channel = IWIC_BCH_A;
|
||||||
|
bchan->state = ST_IDLE;
|
||||||
|
|
||||||
|
iwic_bchannel_setup(sc, IWIC_BCH_A, BPROT_NONE, 0);
|
||||||
|
|
||||||
|
bchan = &sc->sc_bchan[IWIC_BCH_B];
|
||||||
|
bchan->offset = B2_CHAN_OFFSET;
|
||||||
|
bchan->channel = IWIC_BCH_B;
|
||||||
|
bchan->state = ST_IDLE;
|
||||||
|
|
||||||
|
iwic_bchannel_setup(sc, IWIC_BCH_B, BPROT_NONE, 0);
|
||||||
|
|
||||||
|
iwic_init_linktab(sc);
|
||||||
|
|
||||||
|
iwic_attach_bri(sc);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* IRQ handler
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
static int
|
||||||
|
iwic_pci_intr(void *p)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = p;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwic_pci_activate(struct device * dev, enum devact act)
|
||||||
|
{
|
||||||
|
int error = EOPNOTSUPP;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag);
|
||||||
|
int iwic_ph_activate_req(isdn_layer1token t);
|
||||||
|
int iwic_mph_command_req(isdn_layer1token t, int command, void *parm);
|
||||||
|
|
||||||
|
struct isdn_layer1_bri_driver iwic_bri_driver = {
|
||||||
|
iwic_ph_data_req,
|
||||||
|
iwic_ph_activate_req,
|
||||||
|
iwic_mph_command_req
|
||||||
|
};
|
||||||
|
|
||||||
|
void iwic_set_link(void *, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc);
|
||||||
|
isdn_link_t *iwic_ret_linktab(void *, int channel);
|
||||||
|
|
||||||
|
/* XXX Should be prototyped in some header, not here XXX */
|
||||||
|
void n_connect_request(struct call_desc * cd);
|
||||||
|
void n_connect_response(struct call_desc * cd, int response, int cause);
|
||||||
|
void n_disconnect_request(struct call_desc * cd, int cause);
|
||||||
|
void n_alert_request(struct call_desc * cd);
|
||||||
|
void n_mgmt_command(struct isdn_l3_driver * drv, int cmd, void *parm);
|
||||||
|
|
||||||
|
const struct isdn_l3_driver_functions iwic_l3_driver = {
|
||||||
|
iwic_ret_linktab,
|
||||||
|
iwic_set_link,
|
||||||
|
n_connect_request,
|
||||||
|
n_connect_response,
|
||||||
|
n_disconnect_request,
|
||||||
|
n_alert_request,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
n_mgmt_command
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
iwic_attach_bri(struct iwic_softc * sc)
|
||||||
|
{
|
||||||
|
struct isdn_l3_driver *drv;
|
||||||
|
|
||||||
|
drv = isdn_attach_bri(sc->sc_dev.dv_xname, sc->sc_cardname, &sc->sc_l2, &iwic_l3_driver);
|
||||||
|
|
||||||
|
sc->sc_l3token = drv;
|
||||||
|
sc->sc_l2.driver = &iwic_bri_driver;
|
||||||
|
sc->sc_l2.l1_token = sc;
|
||||||
|
sc->sc_l2.drv = drv;
|
||||||
|
|
||||||
|
isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
|
||||||
|
|
||||||
|
isdn_bri_ready(drv->bri);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iwic_ph_data_req(isdn_layer1token t, struct mbuf * m, int freeflag)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = t;
|
||||||
|
|
||||||
|
return iwic_dchan_data_req(sc, m, freeflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iwic_ph_activate_req(isdn_layer1token t)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = t;
|
||||||
|
|
||||||
|
iwic_next_state(sc, EV_PHAR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iwic_mph_command_req(isdn_layer1token t, int command, void *parm)
|
||||||
|
{
|
||||||
|
struct iwic_softc *sc = t;
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case CMR_DOPEN: /* Daemon running */
|
||||||
|
NDBGL1(L1_PRIM, "CMR_DOPEN");
|
||||||
|
IWIC_WRITE(sc, IMASK, IMASK_XINT0 | IMASK_XINT1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMR_DCLOSE: /* Daemon not running */
|
||||||
|
NDBGL1(L1_PRIM, "CMR_DCLOSE");
|
||||||
|
IWIC_WRITE(sc, IMASK, 0xff);
|
||||||
|
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(void *t, int channel)
|
||||||
|
{
|
||||||
|
struct l2_softc *l2sc = t;
|
||||||
|
struct iwic_softc *sc = l2sc->l1_token;
|
||||||
|
struct iwic_bchan *bchan = &sc->sc_bchan[channel];
|
||||||
|
|
||||||
|
return &bchan->iwic_isdn_linktab;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iwic_set_link(void *t, int channel, const struct isdn_l4_driver_functions * l4_driver, void *l4_driver_softc)
|
||||||
|
{
|
||||||
|
struct l2_softc *l2sc = t;
|
||||||
|
struct iwic_softc *sc = l2sc->l1_token;
|
||||||
|
struct iwic_bchan *bchan = &sc->sc_bchan[channel];
|
||||||
|
|
||||||
|
bchan->l4_driver = l4_driver;
|
||||||
|
bchan->l4_driver_softc = l4_driver_softc;
|
||||||
|
}
|
|
@ -0,0 +1,264 @@
|
||||||
|
/* $NetBSD: iwicreg.h,v 1.1 2002/09/24 22:05:20 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* ----------------------------------------
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/sys/i4b/layer1/iwic/i4b_iwic.h,v 1.1 2000/10/09 13:28:59 hm Exp $
|
||||||
|
*
|
||||||
|
* last edit-date: [Sun Jan 21 11:08:44 2001]
|
||||||
|
*
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _IWICREG_H_
|
||||||
|
#define _IWICREG_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 /* !_IWICREG_H_ */
|
|
@ -0,0 +1,200 @@
|
||||||
|
/* $NetBSD: iwicvar.h,v 1.1 2002/09/24 22:05:20 pooka Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IWICVAR_H_
|
||||||
|
#define _IWICVAR_H_
|
||||||
|
|
||||||
|
#include <netisdn/i4b_debug.h>
|
||||||
|
#include <netisdn/i4b_ioctl.h>
|
||||||
|
#include <netisdn/i4b_trace.h>
|
||||||
|
|
||||||
|
#include <netisdn/i4b_l2.h>
|
||||||
|
#include <netisdn/i4b_l1l2.h>
|
||||||
|
#include <netisdn/i4b_l3l4.h>
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* state of a B channel
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
struct iwic_bchan {
|
||||||
|
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 */
|
||||||
|
|
||||||
|
unsigned 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;
|
||||||
|
const struct isdn_l4_driver_functions *l4_driver;
|
||||||
|
void *l4_driver_softc;
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* 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 {
|
||||||
|
struct device sc_dev;
|
||||||
|
|
||||||
|
const char *sc_cardname;
|
||||||
|
|
||||||
|
bus_addr_t sc_iobase;
|
||||||
|
bus_size_t sc_iosize;
|
||||||
|
bus_space_handle_t sc_io_bh;
|
||||||
|
bus_space_tag_t sc_io_bt;
|
||||||
|
|
||||||
|
struct iwic_dchan sc_dchan;
|
||||||
|
struct iwic_bchan sc_bchan[2];
|
||||||
|
|
||||||
|
void *sc_ih; /* interrupt handler */
|
||||||
|
pci_chipset_tag_t sc_pc;
|
||||||
|
|
||||||
|
void *sc_l3token; /* pointer to registered L3 instance */
|
||||||
|
struct l2_softc sc_l2; /* D-channel variables */
|
||||||
|
|
||||||
|
int sc_I430state;
|
||||||
|
int sc_I430T3;
|
||||||
|
|
||||||
|
int sc_trace;
|
||||||
|
};
|
||||||
|
/*---------------------------------------------------------------------------*
|
||||||
|
* rd/wr register/fifo macros
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <machine/bus.h>
|
||||||
|
|
||||||
|
#define IWIC_READ(sc,reg) bus_space_read_1((sc)->sc_io_bt,(sc)->sc_io_bh,(reg))
|
||||||
|
#define IWIC_WRITE(sc,reg,val) bus_space_write_1((sc)->sc_io_bt,(sc)->sc_io_bh,(reg),(val))
|
||||||
|
#define IWIC_WRDFIFO(sc,p,l) bus_space_write_multi_1((sc)->sc_io_bt,(sc)->sc_io_bh,D_XFIFO,(p),(l))
|
||||||
|
#define IWIC_RDDFIFO(sc,p,l) bus_space_read_multi_1((sc)->sc_io_bt,(sc)->sc_io_bh,D_RFIFO,(p),(l))
|
||||||
|
#define IWIC_WRBFIFO(sc,b,p,l) bus_space_write_multi_1((sc)->sc_io_bt,(sc)->sc_io_bh,(b)->offset + B_XFIFO,(p),(l))
|
||||||
|
#define IWIC_RDBFIFO(sc,b,p,l) bus_space_read_multi_1((sc)->sc_io_bt,(sc)->sc_io_bh,(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 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(isdn_layer1token t, int h_chan, int bprot, int activate);
|
||||||
|
|
||||||
|
#endif /* _IWICVAR_H_ */
|
Loading…
Reference in New Issue