summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-12 15:41:43 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-09-12 15:41:43 +0000
commit2a2b206ba357c45d090496916910e13e26288813 (patch)
tree6df4666c170f0f247d6e5036337da69339dbebbb /c
parent2007-09-12 Daniel Hellstrom <daniel@gaisler.com> (diff)
downloadrtems-2a2b206ba357c45d090496916910e13e26288813.tar.bz2
2007-09-12 Daniel Hellstrom <daniel@gaisler.com>
* libchip/network/smc91111.c, libchip/network/smc91111.h: Multiple fixes. - Odd bit bug in some chips taken care of. - Buggy ASSERT removed, it seem to be inserted to detect if MBUF data alignment but failing to do so must have made the driver writer to make some incorrect assumptions about MBUFs. - Fixed MBUF handling to handle mbuf chains better. The Data length of MBUFs in middle of the mbuf chain are now checked for odd number of bytes. - Made while loop responsible for copying data to fifo port copy 16 shorts per loop instead of 1 short, increasing the copying process.
Diffstat (limited to 'c')
-rw-r--r--c/src/ChangeLog12
-rw-r--r--c/src/libchip/network/smc91111.c127
-rw-r--r--c/src/libchip/network/smc91111.h15
3 files changed, 115 insertions, 39 deletions
diff --git a/c/src/ChangeLog b/c/src/ChangeLog
index e43d2eace7..0ba92e85db 100644
--- a/c/src/ChangeLog
+++ b/c/src/ChangeLog
@@ -1,3 +1,15 @@
+2007-09-12 Daniel Hellstrom <daniel@gaisler.com>
+
+ * libchip/network/smc91111.c, libchip/network/smc91111.h: Multiple fixes.
+ - Odd bit bug in some chips taken care of.
+ - Buggy ASSERT removed, it seem to be inserted to detect if MBUF data
+ alignment but failing to do so must have made the driver writer to make
+ some incorrect assumptions about MBUFs.
+ - Fixed MBUF handling to handle mbuf chains better. The Data length of
+ MBUFs in middle of the mbuf chain are now checked for odd number of bytes.
+ - Made while loop responsible for copying data to fifo port copy 16 shorts
+ per loop instead of 1 short, increasing the copying process.
+
2007-09-07 Daniel Hellstrom <daniel@gaisler.com>
* libchip/network/greth.c, libchip/network/greth.h: GRETH_GBIT support
diff --git a/c/src/libchip/network/smc91111.c b/c/src/libchip/network/smc91111.c
index 767ca3fc93..e6ac775c9a 100644
--- a/c/src/libchip/network/smc91111.c
+++ b/c/src/libchip/network/smc91111.c
@@ -181,7 +181,7 @@ static void lan91cxx_recv(struct lan91cxx_priv_data *cpd, struct mbuf *m)
plen = CYG_LE16_TO_CPU(plen) - 6;
#endif
- if (LAN91CXX_RX_STATUS_IS_ODD(cpd, val))
+ if ( cpd->c111_reva || LAN91CXX_RX_STATUS_IS_ODD(cpd, val) ) /* RevA Odd-bit BUG */
plen++;
for (n = m; n; n = n->m_next) {
@@ -257,13 +257,14 @@ static void lan91cxx_recv(struct lan91cxx_priv_data *cpd, struct mbuf *m)
val = get_data(cpd); /* Read control word (and potential data) unconditionally */
#ifdef LAN91CXX_32BIT_RX
if (plen & 2) {
- if (data) {
+ if (data && (mlen>1) ) {
*(unsigned short *)data = (val >> 16) & 0xffff;
- data = (rxd_t *)((unsigned short *)data + 1);
+ data = (rxd_t *)((unsigned short *)data + 1);
val <<= 16;
+ mlen-=2;
}
}
- if (plen & 1)
+ if ( (plen & 1) && data && (mlen>0) )
*(unsigned char *)data = val >> 24;
#else
val = CYG_LE16_TO_CPU(val);
@@ -421,7 +422,7 @@ static int readpacket(struct lan91cxx_priv_data *cpd)
INCR_STAT(cpd, rx_good);
/* Then it's OK */
- if (LAN91CXX_RX_STATUS_IS_ODD(cpd, stat))
+ if (cpd->c111_reva || LAN91CXX_RX_STATUS_IS_ODD(cpd, stat)) /* RevA Odd-bit BUG */
complen++;
#if DEBUG & 1
@@ -491,7 +492,7 @@ static void smc91111_rxDaemon(void *arg)
static void sendpacket(struct ifnet *ifp, struct mbuf *m)
{
struct lan91cxx_priv_data *cpd = ifp->if_softc;
- int i, len, plen, tcr;
+ int i, len, plen, tcr, odd;
struct mbuf *n = m;
unsigned short *sdata = NULL;
unsigned short ints, control;
@@ -562,58 +563,89 @@ static void sendpacket(struct ifnet *ifp, struct mbuf *m)
put_data(cpd, CYG_CPU_TO_LE16(0x7FE & (plen + 6))); /* Always even, always < 15xx(dec) */
/* Put data into buffer */
+ odd = 0;
n = m;
while (n) {
sdata = (unsigned short *)n->m_data;
len = n->m_len;
- CYG_ASSERT((0 == (len & 1)
- || !(n->m_next)), "!odd length");
CYG_ASSERT(sdata, "!No sg data pointer here");
- while (len >= sizeof(*sdata)) {
+ /* start on an odd offset?
+ * If last byte also (1byte mbuf with different pointer should not occur)
+ * let following code handle it
+ */
+ if ( ((unsigned int)sdata & 1) && (len>1) ){
+ put_data8(cpd,*(unsigned char *)sdata);
+ sdata = (unsigned short *)((unsigned int)sdata + 1);
+ odd = ~odd;
+ len--;
+ }
+
+ /* speed up copying a bit, never copy last word */
+ while(len >= 17){
+ put_data(cpd, *(sdata));
+ put_data(cpd, *(sdata+1));
+ put_data(cpd, *(sdata+2));
+ put_data(cpd, *(sdata+3));
+ put_data(cpd, *(sdata+4));
+ put_data(cpd, *(sdata+5));
+ put_data(cpd, *(sdata+6));
+ put_data(cpd, *(sdata+7));
+ sdata += 8;
+ len -= 16;
+ }
+
+ /* copy word wise, skip last word */
+ while (len >= 3) {
put_data(cpd, *sdata++);
len -= sizeof(*sdata);
}
- n = n->m_next;
- }
-#if DEBUG & 64
- n = m;
- while (n) {
- int lp = 0;
- unsigned char *start = (unsigned char *)n->m_data;
- len = n->m_len;
- while (len > 0) {
- unsigned char a = *(start++);
- unsigned char b = *(start++);
- db64_printf("%02x %02x ", a, b);
- lp += 2;
- if (lp >= 16) {
- db64_printf("\n");
- lp = 0;
+
+ /* one or two bytes left to put into fifo */
+ if ( len > 1 ){
+ /* the last 2bytes */
+ if ( !odd || n->m_next ){
+ put_data(cpd, *sdata++);
+ len -= sizeof(*sdata);
+ }else{
+ /* write next byte, mark that we are not at an odd offset any more,
+ * remaining byte will be written outside while together with control byte.
+ */
+ put_data8(cpd,*(unsigned char *)sdata);
+ sdata = (unsigned short *)((unsigned int)sdata + 1);
+ odd = 0;
+ len--;
+ /*break;*/
}
- len -= 2;
+ }else if ( (len>0) && (n->m_next) ){
+ /* one byte left to write, and more bytes is comming in next mbuf */
+ put_data8(cpd,*(unsigned char *)sdata);
+ odd = ~odd;
}
+
n = n->m_next;
}
- db64_printf(" \n");
-#endif
-
- m_freem(m);
- CYG_ASSERT(sdata, "!No sg data pointer outside");
/* Lay down the control short unconditionally at the end. */
/* (or it might use random memory contents) */
control = 0;
- if (1 & plen) {
- /* Need to set ODD flag and insert the data */
- unsigned char onebyte = *(unsigned char *)sdata;
- control = onebyte;
- control |= LAN91CXX_CONTROLBYTE_ODD;
+ if ( len > 0 ){
+ if ( !odd ) {
+ /* Need to set ODD flag and insert the data */
+ unsigned char onebyte = *(unsigned char *)sdata;
+ control = onebyte;
+ control |= LAN91CXX_CONTROLBYTE_ODD;
+ }else{
+ put_data8(cpd,*(unsigned char *)sdata);
+ }
}
control |= LAN91CXX_CONTROLBYTE_CRC; /* Just in case... */
put_data(cpd, CYG_CPU_TO_LE16(control));
+ m_freem(m);
+ CYG_ASSERT(sdata, "!No sg data pointer outside");
+
/* ############ start transmit ############ */
/* Ack TX empty int and unmask it. */
@@ -1057,7 +1089,7 @@ int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd)
(val >> 4) & 0xf, val & 0xf);
/* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */
- cpd->c111_reva = (val == 0x3390);
+ cpd->c111_reva = (val == 0x3390); /* 90=A, 91=B, 92=C */
/* The controller may provide a function used to set up the ESA */
if (cpd->config_enaddr)
@@ -1595,3 +1627,24 @@ lan91cxx_write_phy(struct lan91cxx_priv_data *cpd, uint8_t phyaddr,
}
#endif
+
+#if 0
+void lan91cxx_print_bank(int bank){
+ struct lan91cxx_priv_data *cpd = &smc91111;
+ int regno;
+ unsigned short regval[8];
+ int i;
+
+ if ( bank >= 4 )
+ return;
+ for(i=0; i<8; i++){
+ regno=i+bank<<3;
+ regval[i] = get_reg(cpd, regno);
+ }
+ printk("---- BANK %d ----\n\r",bank);
+ for(i=0; i<8; i++){
+ printk("0x%x: 0x%x\n\r",i,regval[i]);
+ }
+
+}
+#endif
diff --git a/c/src/libchip/network/smc91111.h b/c/src/libchip/network/smc91111.h
index 7cf047e42c..c3a6f32e10 100644
--- a/c/src/libchip/network/smc91111.h
+++ b/c/src/libchip/network/smc91111.h
@@ -460,7 +460,7 @@ get_reg(struct lan91cxx_priv_data *cpd, int regno)
}
dbg++;
}
-#else
+#else
db2_printf("%sread reg %d:%x -> 0x%04x\n", dbg_prefix, regno>>3,(regno&0x7)*2, val);
#endif
@@ -483,7 +483,7 @@ put_reg(struct lan91cxx_priv_data *cpd, int regno, unsigned short val)
}
dbg++;
}
-#else
+#else
db2_printf("%swrite reg %d:%x <- 0x%04x\n", dbg_prefix, regno>>3,(regno&0x7)*2, val);
#endif
@@ -508,6 +508,17 @@ put_data(struct lan91cxx_priv_data *cpd, unsigned short val)
HAL_WRITE_UINT16(cpd->base+((LAN91CXX_DATA & 0x7)), val);
}
+
+/* Assumes bank2 has been selected*/
+static __inline__ void
+put_data8(struct lan91cxx_priv_data *cpd, unsigned char val)
+{
+ db2_printf("%s[bdata] <- 0x%02x\n", dbg_prefix, val);
+
+ HAL_WRITE_UINT8(((unsigned char *)(cpd->base+((LAN91CXX_DATA & 0x7))))+1, val);
+
+}
+
#endif /* SMSC_PLATFORM_DEFINED_PUT_DATA*/
#ifndef SMSC_PLATFORM_DEFINED_GET_DATA