Forum Discussion
Altera_Forum
Honored Contributor
20 years agoOk I think I fixed the odd buffer size issue, but the checksum issue remains.
Since this is calculated further up the stack, and my cursory glance didn't reveal any areas in the driver that may be corrupting the header I think there is another issue. When I went in the debugger and manually corrected the CRC in the header the remaining data looked fine, so hopefully this can help! Unfortunately I can't spend more time on this since I won't be using this driver once our boards arrive, and the issue isn't affecting me right this instant. I went ahead and put a patch together. It's not well tested, but the tests I have done indicate that it is working as designed. If you take the following text save it to a file and execute patch -p0 < patchFile from your nios2 shell in the ecos-current dirctory (probably /cygdrive/c/altera/kits/nios2_51/components/ecos/ecos-current). It should resolve the buffer issue (I think http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif ).diff -Naru packagesOrig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c
--- packagesOrig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 2005-01-07 12:50:34.000000000 -0500
+++ packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 2006-02-24 11:30:49.525340400 -0500
@@ -860,13 +860,53 @@
// packet length (includes status, byte-count and control shorts)
put_data(sc, CYG_CPU_TO_LE16(0x7FE & (plen + 6)) ); // Always even, always < 15xx(dec)
+ //Since this driver transfers 2 bytes at a time buffers in the beginning of
+ //the scatter gather list with odd lengths must be combined with their
+ //next neighbor to create 2 byte sets. The oddHandled variable tracks if
+ //the PRIOR iteration handled one of these conditions
+ bool oddHandled = false;
// Put data into buffer
for (i = 0; i < sg_len; i++) {
- sdata = (unsigned short *)sg_list.buf;
- len = sg_list.len;
+ // 2006.02.24 - THW - Odd lengths now handled.
+ //CYG_ASSERT(0 == (len & 1) || (i == (sg_len-1)), "odd length");
- CYG_ASSERT(0 == (len & 1) || (i == (sg_len-1)), "odd length");
- CYG_ASSERT( sdata, "No sg data pointer here" );
+ //If this is the first buffer then just process as normal
+ //If this is a middle buffer then inspect the previous buffer:
+ // - If previous length was odd and the last iteration didn't handle an
+ // odd buffer then we need to combine.
+ // - If the previous iteration did handle an odd buffer and it's length
+ // is even it total transfer was odd and I need to combine.
+ bool lastLenOdd = sg_list.len & 1;
+ if(i && (lastLenOdd ^ oddHandled)){
+ //Notify the next iteration that this iteration handled an odd
+ //buffer.
+ oddHandled = true;
+
+ //Get the last byte of the last buffer and shift it into MSB.
+ short data = ((char*)sg_list.buf).len - 1)];
+ data = data << 8;
+
+ //Add in the first byte from my buffer to the LSB.
+ data |= ((char*)sg_list.buf);
+ //correct my current pointer (since I just sent one of my bytes).
+ sdata = (unsigned short *)(sg_list.buf + 1);
+
+ //Send this off.
+ put_data(sc, *sdata);
+ len = sg_list.len - 1;
+ }
+ else {
+ oddHandled = false;
+ sdata = (unsigned short *)sg_list.buf;
+ len = sg_list.len;
+ }
+ CYG_ASSERT( sdata, "No sg data pointer here" );
+
+ //If this isn't the last buffer and my len is odd then don't transfer
+ //the last byte (the next iteration will handle it).
+ if(i != (sg_len - 1) && (len & 1))
+ len--;
+
while(len >= sizeof(*sdata)) {
put_data(sc, *sdata++);
len -= sizeof(*sdata);