This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
LAN9218 driver porting problem
- From: "m mariga" <ma_ariga at yahoo dot co dot jp>
- To: <ecos-discuss at ecos dot sourceware dot org>
- Date: Thu, 11 Feb 2010 09:24:29 +0900
- Subject: [ECOS] LAN9218 driver porting problem
Hello,
I am compelled to develop LAN device driver for SMSC LAN9218.
I am endeavouring to make it by consulting to LAN91C111 driver,but because
there are too much differences between them it is a very hard way.
I am in a severe predicament,so I beseech you to help me.
I am making xxx_recv() routines.
I learned lan91cxx_recv() is call-backed when I call
(sc->funs->eth_drv->recv)(sc, len) in lan91cxx_RxEvent().
But I am encountered with next problem in xxxx_RxEvent().
What value should I set cpd->rxpacket ?
In case of LAN91C111 we could get packet number from LAN91CXX_FIFO_PORTS
Register which is set to cpd->rxpacket(please refer to excerts below),
but in LAN9218 there is no way to know packet number,just only data length
from RX_STATUS_FIFO.
I am worried because if I could not set correct value into cpd->rxpacket,I
suppose I could not get argument 'sg_len' correctly in xxx_recv() routine.
For example lan91cxx_recv's arguments are like next.
static void
lan91cxx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
What shall I do ?
Please help me.
In the same context,also in lan91cxx_RxEvent(), it is getting packet from
Register and comparing it to cpd->txpacket.
How shall I circumvent the problem ?
--- excerpts lan91cxx_RxEvent() begin
lan91cxx_RxEvent(struct eth_drv_sc *sc)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
unsigned short stat, len;
DEBUG_FUNCTION();
stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
if ( 0x8000 & stat ) {
// Then the Rx FIFO is empty
return;
}
INCR_STAT( rx_count );
// There is an Rx Packet ready
cpd->rxpacket = 0xff & (stat >> 8);
|
|
(sc->funs->eth_drv->recv)(sc, len);
return;
}
--- excerpts lan91cxx_RxEvent() end
--- lan91cxx_TxEvent begin
static void
lan91cxx_TxEvent(struct eth_drv_sc *sc, int stat)
{
unsigned short packet, ints, tcr;
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
int success = 1;
DEBUG_FUNCTION();
INCR_STAT( tx_complete );
// Ack and mask TX interrupt set
ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
ints |= LAN91CXX_INTERRUPT_TX_SET_ACK;
ints &= ~LAN91CXX_INTERRUPT_TX_SET_M;
put_reg(sc, LAN91CXX_INTERRUPT, ints);
// Get number of completed packet and read the status word
packet = get_reg(sc, LAN91CXX_FIFO_PORTS);
// We do not really care about Tx failure. Ethernet is not a reliable
// medium. But we do care about the TX engine stopping.
tcr = get_reg(sc, LAN91CXX_TCR);
if ( 0 == (LAN91CXX_TCR_TXENA & tcr) ) {
tcr |= LAN91CXX_TCR_TXENA;
put_reg(sc, LAN91CXX_TCR, tcr);
success = 0; // And treat this as an error...
}
packet &= 0xff;
// It certainly appears that occasionally the tx fifo tells lies; we
// get the wrong packet number. Freeing the one we allocated seems to
// give correct operation.
#ifdef CYGPKG_INFRA_DEBUG
// Then we log, OOI, the number of times we get a bad packet number
// from the tx done fifo.
if (cpd->txpacket != packet )
lan91cxx_txfifo_bad++;
else
lan91cxx_txfifo_good++;
#endif
// and then free the packet
put_reg(sc, LAN91CXX_PNR, cpd->txpacket);
put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_rel_packet);
// Ack the TX int which is supposed to clear the packet from the TX
// completion queue.
ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
ints |= LAN91CXX_INTERRUPT_TX_FIFO_ACK;
put_reg(sc, LAN91CXX_INTERRUPT, ints);
if ( cpd->txbusy ) {
cpd->txbusy = 0;
(sc->funs->eth_drv->tx_done)(sc, cpd->txkey, success);
}
}
--- lan91cxx_TxEvent end
m mariga
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss