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