changeset 314:8628bd7bd9bd

lan91cxx enhancements
author msalter
date Wed, 28 Aug 2002 17:12:25 +0000
parents 2b873df9a058
children 865310daf950
files packages/devs/eth/smsc/lan91cxx/current/ChangeLog packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h
diffstat 3 files changed, 62 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/smsc/lan91cxx/current/ChangeLog
+++ b/packages/devs/eth/smsc/lan91cxx/current/ChangeLog
@@ -1,3 +1,9 @@
+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
--- a/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c
+++ b/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c
@@ -135,6 +135,8 @@ static cyg_uint16 lan91cxx_read_phy(stru
 #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;
 
@@ -155,6 +157,7 @@ lan91cxx_isr(cyg_vector_t vector, cyg_ad
     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
@@ -238,6 +241,7 @@ smsc_lan91cxx_init(struct cyg_netdevtab_
         
 #endif
 
+#ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
     // Initialize environment, setup interrupt handler
     cyg_drv_interrupt_create(cpd->interrupt,
                             99, // Priority - what goes here?
@@ -247,8 +251,11 @@ smsc_lan91cxx_init(struct cyg_netdevtab_
                              &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);
@@ -362,6 +369,8 @@ lan91cxx_start(struct eth_drv_sc *sc, un
     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;
@@ -918,6 +927,9 @@ 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();
 
@@ -945,8 +957,14 @@ lan91cxx_RxEvent(struct eth_drv_sc *sc)
     // 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 );
@@ -1002,7 +1020,7 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
         (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();
@@ -1011,16 +1029,23 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
 
     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
@@ -1039,14 +1064,24 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
             }
         }
     }
-    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;
     }
 
--- a/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h
+++ b/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h
@@ -328,6 +328,12 @@ 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)
@@ -380,17 +386,21 @@ put_data(struct eth_drv_sc *sc, unsigned
 
 #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;
 }