This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
cs8900a problem
- From: Bob Koninckx <bob dot koninckx at o-3s dot com>
- To: ecos-discuss at sources dot redhat dot com
- Date: Wed, 05 May 2004 23:41:18 +0200
- Subject: [ECOS] cs8900a problem
- Organization: o-3s
- Reply-to: bob dot koninckx at o-3s dot com
After some (a lot) digging, I've come closer to my ethernet redboot
problem.
Problem seems to originate from the following function
static void
cs8900a_RxEvent(struct eth_drv_sc *sc)
{
cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t*)sc->driver_private;
cyg_addrword_t base = cpd->base;
cyg_uint16 stat, len;
HAL_READ_UINT16(base+CS8900A_RTDATA, stat);
HAL_READ_UINT16(base+CS8900A_RTDATA, len);
#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
len = CYG_SWAP16(len);
#endif
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
if (cyg_io_eth_net_debug) {
diag_printf("RxEvent - stat: %x, len: %d\n", stat, len);
}
#endif
(sc->funs->eth_drv->recv)(sc, len);
}
sometimes a frame length of zero is read (status is always four in this
case). Further in the stack this value is diminished by 14, cast to an
unsigned (resulting in a huge number) and the result is then used as a
length for copying the buffer.
Consequently, most or even the whole ram gets overwritten and redboot
crashes ... so far for what's happening.
I further noticed that this zero length frame is only seen if the while
loop in the main polling function gets entered at least three times. I
have no idea what could be wrong, Hints or tips are welcome here!
Thanks,
Bob
static void
cs8900a_poll(struct eth_drv_sc *sc)
{
cyg_uint16 event;
cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t*)sc->driver_private;
cyg_addrword_t base = cpd->base;
HAL_READ_UINT16(base+CS8900A_ISQ, event);
while (event != 0) {
switch (event & ISQ_EventMask) {
case ISQ_RxEvent:
if(event & 0xf000)
diag_printf("RxEvent, %d\n", event);
cs8900a_RxEvent(sc); <<--third RxEvent on a row causes
problems
break;
case ISQ_TxEvent:
cs8900a_TxEvent(sc, event);
break;
case ISQ_BufEvent:
cs8900a_BufEvent(sc, event);
break;
case ISQ_RxMissEvent:
diag_printf("ISQ_RxMissEvent\n");
// Receive miss counter has overflowed
break;
case ISQ_TxColEvent:
diag_printf("ISQ_TxColEvent\n");
// Transmit collision counter has overflowed
break;
default:
#if DEBUG & 1
diag_printf("%s: Unknown event: %x\n", __FUNCTION__, event);
#endif
break;
}
HAL_READ_UINT16(base+CS8900A_ISQ, event);
}
CYGHWR_CL_CS8900A_PLF_INT_CLEAR(cpd);
}
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss