kern/100425: sbni drivers does not work under 5.x
Rashid N. Achilov
shelton at granch.ru
Mon Jul 17 08:00:46 UTC 2006
>Number: 100425
>Category: kern
>Synopsis: sbni drivers does not work under 5.x
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Jul 17 08:00:34 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Rashid N. Achilov
>Release: FreeBSD 5.5-PRERELEASE i386
>Organization:
>Environment:
System: FreeBSD www.granch.ru 5.5-PRERELEASE FreeBSD 5.5-PRERELEASE #2: Thu May 18 19:26:36 NOVST 2006 shelton at www.granch.ru:/usr/obj/usr/src/sys/Proxy i386
>Description:
Driver for device sbni does not work correctly under 5.4 and high. When connect between
two devices established (with any OS - FreeBSD, linux, Windows), all incoming packets
qualified as 'bad' and drop down. So, data exchange is impossible. A trouble source is
a calc_crc32 procedure, which was sometime written by ASM insertions. GCC 3.x produced
code, which calcs CRC incorrectly, so calc_crc32 decline ALL incoming packets. A sbni
driver has also (still unusable) C-sourced calc_crc32 procedure. When I have switched
to use it, driver start to work.
>How-To-Repeat:
Install a couple sbni devices at a couple boxes, one side with FreeBSD 5.x, two with
any other supported system. Install sbni device into a kernel or load kernel module.
Install sbniconfig utility. Connect devices. You can see in a sbniconfig output, that
"rx" will increased, and "bad rx" will increased too and all received packets will
'bad'.
>Fix:
Go to /usr/src/sys and appy this patch
--- modules/sbni/Makefile Thu Nov 22 04:29:35 2001
+++ Makefile.new Mon Jul 17 14:10:21 2006
@@ -7,4 +7,7 @@
SRCS+= bus_if.h device_if.h isa_if.h pci_if.h
+# To build with lost of debug messages, uncomment here
+#CFLAGS += -DDEBUG
+
.include <bsd.kmod.mk>
--- dev/sbni/if_sbni.c Sun Jan 30 07:00:01 2005
+++ if_sbni.c.new Fri Jul 14 12:35:47 2006
@@ -57,6 +57,9 @@
* Revision 4.1 2001/01/21
* Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
*
+ * Revision 4.2 2006/07/12 by Rashid N. "CityCat" Achilov
+ * Incorrect checksum calculation under 5.x eliminated
+ *
* Written with reference to NE2000 driver developed by David Greenman.
*/
@@ -84,7 +87,12 @@
#include <dev/sbni/if_sbnireg.h>
#include <dev/sbni/if_sbnivar.h>
+/* In 5.x ASM source for CRC caclulations produced incorrect CRC check */
+#if __FreeBSD_version < 500000
#define ASM_CRC 1
+#else
+#undef ASM_CRC
+#endif
static void sbni_init(void *);
static void sbni_start(struct ifnet *);
@@ -374,7 +382,7 @@
*/
csr0 = sbni_inb(sc, CSR0);
if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
- printf("sbni: internal error!\n");
+ printf("sbni: incorrect state, TR not ready, but RC ready\n");
/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
if (req_ans || sc->tx_frameno != 0)
@@ -406,21 +414,41 @@
frame_ok = framelen > 4 ?
upload_data(sc, framelen, frameno, is_first, crc) :
skip_tail(sc, framelen, crc);
+#ifdef DEBUG
+ printf("[RF]header OK, frame_ok=%d, framelen=%d\n",frame_ok,framelen);
+#endif
if (frame_ok)
interpret_ack(sc, ack);
} else
+ {
+#ifdef DEBUG
+ printf("[RF]Header BAD!\n");
+#endif
frame_ok = 0;
+ }
sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
if (frame_ok) {
+#ifdef DEBUG
+ printf("[RF]Good: frame_ok=%d,framelen=%d\n",frame_ok,framelen);
+#endif
sc->state |= FL_PREV_OK;
if (framelen > 4)
+ {
sc->in_stats.all_rx_number++;
+#ifdef DEBUG
+ printf("[RF]Good: received: %d\n",sc->in_stats.all_rx_number);
+#endif
+ }
} else {
sc->state &= ~FL_PREV_OK;
change_level(sc);
sc->in_stats.all_rx_number++;
sc->in_stats.bad_rx_number++;
+#ifdef DEBUG
+ printf("[RF]Bad: received all: %d\n",sc->in_stats.all_rx_number);
+ printf("[RF]Bad: received bad: %d\n",sc->in_stats.bad_rx_number);
+#endif
}
return (!frame_ok || framelen > 4);
@@ -548,29 +576,46 @@
if (sc->inppos + framelen <= ETHER_MAX_LEN) {
frame_ok = append_frame_to_pkt(sc, framelen, crc);
+#ifdef DEBUG
+ printf("[UD]Append frame,frame_ok=%d\n",frame_ok);
+#endif
/*
* if CRC is right but framelen incorrect then transmitter
* error was occured... drop entire packet
*/
} else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
+#ifdef DEBUG
+ printf("[UD]CRC OK, but framelen incorrect\n");
+#endif
sc->wait_frameno = 0;
sc->inppos = 0;
sc->arpcom.ac_if.if_ierrors++;
/* now skip all frames until is_first != 0 */
}
} else
+ {
frame_ok = skip_tail(sc, framelen, crc);
+#ifdef DEBUG
+ printf("[UD]sc->wait_frameno=%d != frameno=%d\n",sc->wait_frameno,frameno);
+#endif
+ }
if (is_first && !frame_ok) {
/*
* Frame has been violated, but we have stored
* is_first already... Drop entire packet.
*/
+#ifdef DEBUG
+ printf("[UD]is_first (%ud) && !frame_ok (%d)\n",is_first,frame_ok);
+#endif
sc->wait_frameno = 0;
sc->arpcom.ac_if.if_ierrors++;
}
+#ifdef DEBUG
+ printf("[UD]returning frame_ok=%d\n",frame_ok);
+#endif
return (frame_ok);
}
@@ -620,15 +665,30 @@
caddr_t p;
if (sc->inppos + framelen > ETHER_MAX_LEN)
+ {
+#ifdef DEBUG
+ printf("[AF]sc->inppos + framelen (%d) > ETHER_MAX\n",sc->inppos + framelen);
+#endif
return (0);
+ }
if (!sc->rx_buf_p && !get_rx_buf(sc))
+ {
+#ifdef DEBUG
+ printf("[AF]Cannot get RX buffer\n");
+#endif
return (0);
+ }
p = sc->rx_buf_p->m_data + sc->inppos;
sbni_insb(sc, p, framelen);
if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
+ {
+#ifdef DEBUG
+ printf("[AF]calc_crc32 != CRC32_REMAINDER\n");
+#endif
return (0);
+ }
sc->inppos += framelen - 4;
if (--sc->wait_frameno == 0) { /* last frame received */
@@ -636,6 +696,9 @@
sc->arpcom.ac_if.if_ipackets++;
}
+#ifdef DEBUG
+ printf("[AF]Append OK, sc->inppos = %d\n",sc->inppos);
+#endif
return (1);
}
@@ -1144,8 +1207,10 @@
/* -------------------------------------------------------------------------- */
+/* Beware! Under 5.x ASM code produced incorrect CRC!, so you MUST *
+ * use C procedure for CRC calculations. So, this code will in play *
+ * only under 4.x */
#ifdef ASM_CRC
-
static u_int32_t
calc_crc32(u_int32_t crc, caddr_t p, u_int len)
{
@@ -1223,7 +1288,6 @@
return (_crc);
}
-
#else /* ASM_CRC */
static u_int32_t
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list