This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
lan91cxx enhancements
- From: Mark Salter <msalter at redhat dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: Wed, 28 Aug 2002 13:13:17 -0400
- Subject: lan91cxx enhancements
Index: devs/eth/smsc/lan91cxx/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/ChangeLog,v
retrieving revision 1.10
diff -u -p -5 -r1.10 ChangeLog
--- devs/eth/smsc/lan91cxx/current/ChangeLog 16 Aug 2002 13:16:25 -0000 1.10
+++ devs/eth/smsc/lan91cxx/current/ChangeLog 28 Aug 2002 16:59:48 -0000
@@ -1,5 +1,11 @@
+2002-08-28 Mark Salter <msalter@redhat.com>
+
+ * src/smsc_lan91cxx.h: Support 32-bit data reads.
+ * src/if_lan91cxx.c: Fix standalone (RedBoot) interrupt handling.
+ Support 32-bit data reads.
+
2002-08-16 Mark Salter <msalter@redhat.com>
* src/if_lan91cxx.c: Add support for 91C111. Platform-specific
include file is now included from within smsc_lan91cxx.h so
that register access functions may be overridden if necessary.
Index: devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c,v
retrieving revision 1.9
diff -u -p -5 -r1.9 if_lan91cxx.c
--- devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 16 Aug 2002 13:16:26 -0000 1.9
+++ devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 28 Aug 2002 16:59:49 -0000
@@ -133,10 +133,12 @@ static void lan91cxx_write_phy(struct et
static cyg_uint16 lan91cxx_read_phy(struct eth_drv_sc *sc, cyg_uint8 phyaddr,
cyg_uint8 phyreg);
#endif
static void lan91cxx_poll(struct eth_drv_sc *sc);
+
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
static cyg_interrupt lan91cxx_interrupt;
static cyg_handle_t lan91cxx_interrupt_handle;
// This ISR is called when the ethernet interrupt occurs
static int
@@ -153,10 +155,11 @@ lan91cxx_isr(cyg_vector_t vector, cyg_ad
cyg_drv_interrupt_mask(cpd->interrupt);
cyg_drv_interrupt_acknowledge(cpd->interrupt);
return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Run the DSR
}
+#endif
// The deliver function (ex-DSR) handles the ethernet [logical] processing
static void
lan91cxx_deliver(struct eth_drv_sc *sc)
{
@@ -236,21 +239,25 @@ smsc_lan91cxx_init(struct cyg_netdevtab_
#endif
put_att(sc, LAN91CXX_ECSR, ecsr);
#endif
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
// Initialize environment, setup interrupt handler
cyg_drv_interrupt_create(cpd->interrupt,
99, // Priority - what goes here?
(cyg_addrword_t)sc, // Data item passed to interrupt handler
(cyg_ISR_t *)lan91cxx_isr,
(cyg_DSR_t *)eth_drv_dsr, // The logical driver DSR
&lan91cxx_interrupt_handle,
&lan91cxx_interrupt);
cyg_drv_interrupt_attach(lan91cxx_interrupt_handle);
+#endif // !CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
cyg_drv_interrupt_acknowledge(cpd->interrupt);
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
cyg_drv_interrupt_unmask(cpd->interrupt);
+#endif // !CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
// probe chip by reading the signature in BS register
val = get_banksel(sc);
#if DEBUG & 9
diag_printf("LAN91CXX - supposed BankReg @ %x = %04x\n",
@@ -360,10 +367,12 @@ lan91cxx_start(struct eth_drv_sc *sc, un
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
#endif
DEBUG_FUNCTION();
#ifdef LAN91CXX_IS_LAN91C111
+ HAL_DELAY_US(100000);
+
// 91C111 Errata. Internal PHY comes up disabled. Must enable here.
phy_ctl = lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_CTRL);
phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS;
lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, phy_ctl);
@@ -916,10 +925,13 @@ static void
lan91cxx_RxEvent(struct eth_drv_sc *sc)
{
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
unsigned short stat, len;
+#ifdef LAN91CXX_32BIT_RX
+ cyg_uint32 val;
+#endif
DEBUG_FUNCTION();
stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
#if DEBUG & 1
@@ -943,12 +955,18 @@ lan91cxx_RxEvent(struct eth_drv_sc *sc)
cpd->rxpacket = 0xff & (stat >> 8);
// Read status and (word) length
put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
LAN91CXX_POINTER_AUTO_INCR | 0x0000));
+#ifdef LAN91CXX_32BIT_RX
+ val = get_data(sc);
+ stat = val & 0xffff;
+ len = ((val >> 16) & 0xffff) - 6; // minus header/footer words
+#else
stat = get_data(sc);
len = get_data(sc) - 6; // minus header/footer words
+#endif
#ifdef KEEP_STATISTICS
if ( stat & LAN91CXX_RX_STATUS_ALIGNERR ) INCR_STAT( rx_align_errors );
//if ( stat & LAN91CXX_RX_STATUS_BCAST ) INCR_STAT( );
if ( stat & LAN91CXX_RX_STATUS_BADCRC ) INCR_STAT( rx_crc_errors );
@@ -1000,29 +1018,36 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
#if (4 & DEBUG) || defined(CYGPKG_INFRA_DEBUG) || defined(KEEP_STATISTICS)
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
#endif
int i, mlen=0, plen;
- unsigned short *data=NULL, val;
+ rxd_t *data=NULL, val;
unsigned char *cp, cval;
DEBUG_FUNCTION();
INCR_STAT( rx_deliver );
put_reg(sc, LAN91CXX_POINTER, (LAN91CXX_POINTER_RCV | LAN91CXX_POINTER_READ |
LAN91CXX_POINTER_AUTO_INCR));
- // Skip status word
- (void)get_data(sc);
+ val = get_data(sc);
- plen = get_data(sc) - 6; // packet length (minus header/footer)
+ // packet length (minus header/footer)
+#ifdef LAN91CXX_32BIT_RX
+ plen = (val >> 16) - 6;
+#else
+ plen = get_data(sc) - 6;
+#endif
+ if (val & LAN91CXX_RX_STATUS_ODDFRM)
+ plen++;
for (i = 0; i < sg_len; i++) {
- data = (unsigned short *)sg_list[i].buf;
+ data = (rxd_t *)sg_list[i].buf;
mlen = sg_list[i].len;
- CYG_ASSERT(0 == (mlen & 1) || (i == (sg_len-1)), "odd length");
+ CYG_ASSERT(0 == (mlen & (sizeof(*data) - 1)) || (i == (sg_len-1)), "odd length");
+
#if DEBUG & 1
diag_printf("%s : mlen %x, plen %x\n", __FUNCTION__, mlen, plen);
#endif
if (data) {
while (mlen >= sizeof(*data)) {
@@ -1037,18 +1062,28 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
mlen -= sizeof(*data);
plen -= sizeof(*data);
}
}
}
- val = get_data(sc); // Read control word unconditionally
+ val = get_data(sc); // Read control word (and potential data) unconditionally
+#ifdef LAN91CXX_32BIT_RX
+ if (plen & 2) {
+ if (data)
+ *(cyg_uint16 *)data = val & 0xffff;
+ cp = (unsigned char *)data + 2;
+ val >>= 16;
+ mlen -= 2;
+ } else
+#endif
+ cp = (unsigned char *)data;
+
CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX,
"Controlbyte is not for Rx");
CYG_ASSERT( (1 == mlen) == (0 != (val & LAN91CXX_CONTROLBYTE_ODD)),
"Controlbyte does not match");
if (data && (1 == mlen) && (val & LAN91CXX_CONTROLBYTE_ODD)) {
cval = val & 0x00ff; // last byte contains data
- cp = (unsigned char*)data;
*cp = cval;
}
val = get_reg(sc, LAN91CXX_FIFO_PORTS);
#if DEBUG & 4
Index: devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h,v
retrieving revision 1.6
diff -u -p -5 -r1.6 smsc_lan91cxx.h
--- devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 16 Aug 2002 13:16:26 -0000 1.6
+++ devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 28 Aug 2002 16:59:49 -0000
@@ -326,10 +326,16 @@ typedef struct lan91cxx_priv_data {
// ------------------------------------------------------------------------
#include CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL
+#ifdef LAN91CXX_32BIT_RX
+typedef cyg_uint32 rxd_t;
+#else
+typedef cyg_uint16 rxd_t;
+#endif
+
#ifndef SMSC_PLATFORM_DEFINED_GET_REG
static __inline__ unsigned short
get_reg(struct eth_drv_sc *sc, int regno)
{
struct lan91cxx_priv_data *cpd =
@@ -378,21 +384,25 @@ put_data(struct eth_drv_sc *sc, unsigned
}
#endif // SMSC_PLATFORM_DEFINED_PUT_DATA
#ifndef SMSC_PLATFORM_DEFINED_GET_DATA
// Assumes bank2 has been selected
-static __inline__ unsigned short
+static __inline__ rxd_t
get_data(struct eth_drv_sc *sc)
{
- unsigned short val;
+ rxd_t val;
struct lan91cxx_priv_data *cpd =
(struct lan91cxx_priv_data *)sc->driver_private;
+#ifdef LAN91CXX_32BIT_RX
+ HAL_READ_UINT32(cpd->base+((LAN91CXX_DATA_HIGH & 0x7) << cpd->addrsh), val);
+#else
HAL_READ_UINT16(cpd->base+((LAN91CXX_DATA & 0x7) << cpd->addrsh), val);
+#endif
#if DEBUG & 2
- diag_printf("read data 0x%04x\n", val);
+ diag_printf("read data 0x%x\n", val);
#endif
return val;
}
#endif // SMSC_PLATFORM_DEFINED_GET_DATA