Update the iwic driver: fix error handling for rx errors on the D-channel

which prevents erroneous packets from being put onto the protocol stack;
enhance error detection for B-channel HDLC errors; remove old cvs id´s.
This commit is contained in:
hm 2001-01-21 10:12:50 +00:00
parent 23a51a21e2
commit edaa19fd37
8 changed files with 103 additions and 111 deletions

View File

@ -27,11 +27,9 @@
* 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]
* last edit-date: [Sun Jan 21 11:08:44 2001]
*
*---------------------------------------------------------------------------*/

View File

@ -31,7 +31,7 @@
*
* $FreeBSD$
*
* last edit-date: [Fri Jan 12 16:57:01 2001]
* last edit-date: [Tue Jan 16 13:21:24 2001]
*
*---------------------------------------------------------------------------*/
@ -88,33 +88,48 @@ iwic_bchan_xirq(struct iwic_softc *sc, int chan_no)
if (irq_stat & B_EXIR_RDOV)
{
NDBGL1(L1_H_XFRERR, "RDOV");
NDBGL1(L1_H_XFRERR, "iwic%d: EXIR B-channel Receive Data Overflow", sc->sc_unit);
}
if (irq_stat & B_EXIR_XDUN)
{
NDBGL1(L1_H_XFRERR, "XDUN");
NDBGL1(L1_H_XFRERR, "iwic%d: EXIR B-channel Transmit Data Underrun", sc->sc_unit);
cmd |= (B_CMDR_XRST); /*XXX must retransmit frame ! */
}
/* RX message end interrupt */
if(irq_stat & B_EXIR_RME)
{
/* XXXX */ int error = 0;
register int fifo_data_len;
int error;
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;
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, "iwic%d: B-channel Receive Data Overflow", sc->sc_unit);
if(error & B_STAR_CRCE)
NDBGL1(L1_H_XFRERR, "iwic%d: B-channel CRC Error", sc->sc_unit);
if(error & B_STAR_RMB)
NDBGL1(L1_H_XFRERR, "iwic%d: B-channel Receive Message Aborted", sc->sc_unit);
}
/* 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)
@ -684,7 +699,7 @@ iwic_bchannel_start(int unit, int chan_no)
}
/*---------------------------------------------------------------------------*
*
* return B-channel statistics
*---------------------------------------------------------------------------*/
static void
iwic_bchannel_stat(int unit, int chan_no, bchan_statistics_t *bsp)

View File

@ -27,11 +27,9 @@
* 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]
* last edit-date: [Tue Jan 16 13:20:14 2001]
*
*---------------------------------------------------------------------------*/
@ -66,12 +64,8 @@
static void dchan_receive(struct iwic_softc *sc, int ista);
#ifdef NOTDEF
static void output_bytes(char *prefix, u_char * ptr, int len);
#endif
/*---------------------------------------------------------------------------*
*
* initialize D-channel variables and registers
*---------------------------------------------------------------------------*/
void
iwic_dchan_init(struct iwic_softc *sc)
@ -106,7 +100,7 @@ iwic_dchan_init(struct iwic_softc *sc)
}
/*---------------------------------------------------------------------------*
*
* Extended IRQ handler for the D-channel
*---------------------------------------------------------------------------*/
void
iwic_dchan_xirq(struct iwic_softc *sc)
@ -119,6 +113,7 @@ iwic_dchan_xirq(struct iwic_softc *sc)
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)
{
@ -128,6 +123,7 @@ iwic_dchan_xirq(struct iwic_softc *sc)
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)
@ -226,7 +222,7 @@ iwic_dchan_xfer_irq(struct iwic_softc *sc, int ista)
}
/*---------------------------------------------------------------------------*
*
* disable D-channel
*---------------------------------------------------------------------------*/
void
iwic_dchan_disable(struct iwic_softc *sc)
@ -255,7 +251,7 @@ iwic_dchan_disable(struct iwic_softc *sc)
}
/*---------------------------------------------------------------------------*
*
* queue D-channel message for transmission
*---------------------------------------------------------------------------*/
int
iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
@ -297,7 +293,7 @@ iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
}
/*---------------------------------------------------------------------------*
*
* allocate an mbuf
*---------------------------------------------------------------------------*/
static void
dchan_get_mbuf(struct iwic_softc *sc, int len)
@ -313,11 +309,13 @@ dchan_get_mbuf(struct iwic_softc *sc, int len)
}
/*---------------------------------------------------------------------------*
*
* 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 */
@ -330,7 +328,7 @@ dchan_receive(struct iwic_softc *sc, int ista)
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");
panic("dchan_receive: not enough space in buffer!\n");
}
IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, 64);
@ -342,61 +340,69 @@ dchan_receive(struct iwic_softc *sc, int ista)
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);
if (status & D_RSTA_RDOV)
NDBGL1(L1_I_ERR, "iwic%d: D-channel Receive Data Overflow", sc->sc_unit);
if (status & D_RSTA_CRCE)
NDBGL1(L1_I_ERR, "iwic%d: D-channel CRC Error", sc->sc_unit);
if (status & D_RSTA_RMB)
NDBGL1(L1_I_ERR, "iwic%d: D-channel Receive Message Aborted", sc->sc_unit);
command |= D_CMDR_RRST;
}
sc->sc_dchan.ibuf->m_len = sc->sc_dchan.ibuf_len;
if(sc->sc_trace & TRACE_D_RX)
else
{
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);
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_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;
}
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);
IWIC_WRITE(sc, D_CMDR, command);
}
/*---------------------------------------------------------------------------*
*
* transmit D-channel frame
*---------------------------------------------------------------------------*/
void
iwic_dchan_transmit(struct iwic_softc *sc)
@ -464,29 +470,4 @@ iwic_dchan_transmit(struct iwic_softc *sc)
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
#endif /* (NIWIC > 0) && (NPCI > 0) */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Hellmuth Michaelis. 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
@ -27,11 +27,9 @@
* 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]
* last edit-date: [Sun Jan 21 11:09:14 2001]
*
*---------------------------------------------------------------------------*/

View File

@ -27,11 +27,9 @@
* 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]
* last edit-date: [Sun Jan 21 11:09:24 2001]
*
*---------------------------------------------------------------------------*/

View File

@ -27,11 +27,9 @@
* 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]
* last edit-date: [Sun Jan 21 11:09:33 2001]
*
*---------------------------------------------------------------------------*/

View File

@ -29,7 +29,7 @@
*
* $FreeBSD$
*
* last edit-date: [Wed Jan 10 14:33:08 2001]
* last edit-date: [Tue Jan 16 10:53:03 2001]
*
*---------------------------------------------------------------------------*/
@ -266,6 +266,12 @@ iwic_pci_attach(device_t dev)
iwic_init_linktab(sc);
if(bootverbose)
{
int ver = IWIC_READ(sc, D_RBCH);
printf("iwic%d: W6692 chip version = %d\n", unit, D_RBCH_VN(ver));
}
i4b_l1_mph_status_ind(L0IWICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &iwic_l1mux_func);
IWIC_READ(sc, ISTA);

View File

@ -27,11 +27,9 @@
* 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]
* last edit-date: [Sun Jan 21 11:09:46 2001]
*
*---------------------------------------------------------------------------*/