This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

SMSC LAN91CXX patch


Another patch flushed from eCosCentric. This includes a different implementation allowing 32-bit RX access. IMO this version is more elegant and clear than what was previously in anoncvs, and thus replaces it. It also removes the need for the CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT, which I could not find used anywhere in anoncvs anyway.

I forgot to say in my previous message that I cannot guarantee all the patches are error free due to the merge process (although they should be). I do not have the ability or time to test with the variety of hardware required, although the original changes in our tree were extensively tested by eCosCentric of course.

Jifl
--
eCosCentric    http://www.eCosCentric.com/    The eCos and RedBoot experts
------["The best things in life aren't things."]------      Opinions==mine
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/ChangeLog,v
retrieving revision 1.21
diff -u -5 -p -r1.21 ChangeLog
--- ChangeLog	29 Jun 2005 20:06:04 -0000	1.21
+++ ChangeLog	20 Jul 2006 16:37:23 -0000
@@ -10,10 +10,31 @@
 2005-06-12  Yoshinori Sato <ysato@users.sourceforge.jp>
 
 	* src/if_lan91cxx.c: Reset the physical layer before configuring
 	it, otherwise it might not work.
 
+2005-01-24  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/if_lan91cxx.c (lan91cxx_send): Rewrote parts of transmit
+	machinery to deal with odd sized message buffers. The TCP/IP stack
+	generates these in rare circumstances.
+
+2005-01-21  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/smsc_lan91cxx.h: 	
+	* src/if_lan91cxx.c:
+	Rewrote parts of receive machinery to properly deal with 32 bit
+	wide access to the device. The original code didn't quite work.
+	Switched all calls the HAL_DELAY_US() to CYGACC_CALL_IF_DELAY_US().
+	Various small changes to debugging code.
+
+2004-12-01  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/if_lan91cxx.c (lan91cxx_start): Added option to force speed
+	negotiation to 10MHz. Some embedded boards cannot handle 100MHz.
+	Generally added some small improvements to debugging messages.
+
 2004-05-22  Andrew Dyer  <adyer@righthandtech.com>
 
 	* src/if_lan91cxx.c: Fail initialization if no device found.
 
 2004-01-07  Uwe Kindler <ukindler@htwm.de>
@@ -183,10 +204,11 @@
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2005 eCosCentric Ltd.
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
Index: cdl/smsc_lan91cxx_eth_drivers.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/cdl/smsc_lan91cxx_eth_drivers.cdl,v
retrieving revision 1.7
diff -u -5 -p -r1.7 smsc_lan91cxx_eth_drivers.cdl
--- cdl/smsc_lan91cxx_eth_drivers.cdl	29 Jun 2005 20:06:05 -0000	1.7
+++ cdl/smsc_lan91cxx_eth_drivers.cdl	20 Jul 2006 16:37:23 -0000
@@ -107,19 +107,10 @@ cdl_package CYGPKG_DEVS_ETH_SMSC_LAN91CX
 	description "
 	    If this is nonzero, then the chip is assumed to be hardware
             configured in PCMCIA mode."
     }
 
-    cdl_option CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT {
-	display "use 32 bit data access"
-	default_value 0
-	description   "
-	    The device driver uses 32 bit data access if
-	    this option is enabled, otherwise 16 bit data access is
-	    used."
-    }
-
     cdl_component CYGPKG_DEVS_ETH_SMSC_LAN91CXX_OPTIONS {
         display "LAN91CXX ethernet driver build options"
         flavor  none
 	no_define
 
Index: src/if_lan91cxx.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c,v
retrieving revision 1.19
diff -u -5 -p -r1.19 if_lan91cxx.c
--- src/if_lan91cxx.c	29 Jun 2005 20:06:05 -0000	1.19
+++ src/if_lan91cxx.c	20 Jul 2006 16:37:25 -0000
@@ -9,10 +9,11 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
 // Copyright (C) 2003 Nick Garnett 
 // Copyright (C) 2004 Andrew Lunn
+// Copyright (C) 2004 eCosCentric Ltd.
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -33,12 +34,10 @@
 // in accordance with section (3) of the GNU General Public License.
 //
 // This exception does not invalidate any other reasons why a work based on
 // this file might be covered by the GNU General Public License.
 //
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
 // -------------------------------------------
 //####ECOSGPLCOPYRIGHTEND####
 //####BSDCOPYRIGHTBEGIN####
 //
 // -------------------------------------------
@@ -125,15 +124,41 @@ static void db_printf( char *fmt, ... )
     diag_vprintf( fmt, a );
     end_console(old_console);
     va_end( a );
 }
 #else
+#if 0
+static void db_printf( char *fmt, ... )
+{
+    va_list a;
+    int old_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
+    va_start( a, fmt );
+    CYGACC_CALL_IF_SET_CONSOLE_COMM( 0 );
+    diag_vprintf( fmt, a );
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
+    va_end( a );
+}
+#else
 #define db_printf diag_printf
 #endif
+#endif
+#else
+#if 0
+static void db_printf( char *fmt, ... )
+{
+    va_list a;
+    int old_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
+    va_start( a, fmt );
+    CYGACC_CALL_IF_SET_CONSOLE_COMM( 0 );
+    diag_vprintf( fmt, a );
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
+    va_end( a );
+}
 #else
 #define db_printf( fmt, ... )
 #endif
+#endif
 
 
 #if DEBUG & 1
 #define DEBUG_FUNCTION() do { db_printf("%s\n", __FUNCTION__); } while (0)
 #else
@@ -190,11 +215,11 @@ static int lan91cxx_isr(cyg_vector_t vec
 {
     struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
     struct lan91cxx_priv_data *cpd =
         (struct lan91cxx_priv_data *)sc->driver_private;
 
-    DEBUG_FUNCTION();
+//    DEBUG_FUNCTION();
 
     INCR_STAT( interrupts );
 
     cyg_drv_interrupt_mask(cpd->interrupt);
     cyg_drv_interrupt_acknowledge(cpd->interrupt);
@@ -208,11 +233,11 @@ static void
 lan91cxx_deliver(struct eth_drv_sc *sc)
 {
     struct lan91cxx_priv_data *cpd =
         (struct lan91cxx_priv_data *)sc->driver_private;
 
-    DEBUG_FUNCTION();
+//    DEBUG_FUNCTION();
 
     // Service the interrupt:
     lan91cxx_poll(sc);
     // Allow interrupts to happen again
     cyg_drv_interrupt_unmask(cpd->interrupt);
@@ -260,11 +285,11 @@ smsc_lan91cxx_init(struct cyg_netdevtab_
     
     // pulse SRESET on ECOR
     ecor |= LAN91CXX_ECOR_RESET;
     put_att(sc, LAN91CXX_ECOR, ecor);
     
-    HAL_DELAY_US(1);
+    CYGACC_CALL_IF_DELAY_US(1);
     
     ecor &= ~LAN91CXX_ECOR_RESET;
     put_att(sc, LAN91CXX_ECOR, ecor);
 
     // then, enable I/O map
@@ -296,13 +321,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);
 #if DEBUG & 9
     db_printf("LAN91CXX - supposed BankReg @ %x = %04x\n",
@@ -338,11 +361,11 @@ smsc_lan91cxx_init(struct cyg_netdevtab_
     val = get_reg(sc, LAN91CXX_EPH_STATUS);
 #ifndef LAN91CXX_IS_LAN91C111
     // LINK_OK on 91C111 is just a general purpose input and may not
     // have anything to do with the link.
     if (!(val & LAN91CXX_STATUS_LINK_OK)) {
- db_printf("no link\n");
+        db_printf("no link\n");
         return false;  // Link not connected
     }
 #endif
 
 
@@ -462,25 +485,29 @@ lan91cxx_start(struct eth_drv_sc *sc, un
     DEBUG_FUNCTION();
 
 #ifdef LAN91CXX_IS_LAN91C111
     // 91C111 Errata. Internal PHY comes up disabled. Must enable here.
     lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, LAN91CXX_PHY_CTRL_RST);
-    HAL_DELAY_US(500000);
+    CYGACC_CALL_IF_DELAY_US(500000);
     lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, LAN91CXX_PHY_CTRL_ANEG_EN |
 		                                 LAN91CXX_PHY_CTRL_SPEED);
 
+#ifdef LAN91CXX_FORCE_10MHZ
+    lan91cxx_write_phy( sc, 0, LAN91CXX_PHY_AUTO_AD, 0x0061);
+#endif
+
     // Start auto-negotiation
     put_reg(sc, LAN91CXX_RPCR,
 	    LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | LAN91CXX_RPCR_ANEG);
 
     // wait for auto-negotiation to finish.
     // give it ~5 seconds before giving up (no cable?)
     delay = 50;
     while (!(lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_STAT) & 0x20)) {
 	if (--delay <= 0)
 	    break;
-	HAL_DELAY_US(100000);
+	CYGACC_CALL_IF_DELAY_US(100000);
     }
 #if DEBUG & 1
     if (delay <= 0)
 	    diag_printf("auto-negotiation failed.\n");
 #endif
@@ -730,11 +757,11 @@ lan91cxx_can_send(struct eth_drv_sc *sc)
 {
     struct lan91cxx_priv_data *cpd =
         (struct lan91cxx_priv_data *)sc->driver_private;
     int tcr;
 
-    DEBUG_FUNCTION();
+//    DEBUG_FUNCTION();
 
 #ifndef LAN91CXX_IS_LAN91C111
     // LINK_OK on 91C111 is just a general purpose input and may not
     // have anything to do with the link.
     if ((get_reg(sc, LAN91CXX_EPH_STATUS) & LAN91CXX_STATUS_LINK_OK) == 0) {
@@ -778,18 +805,25 @@ lan91cxx_send(struct eth_drv_sc *sc, str
 {
     struct lan91cxx_priv_data *cpd = 
         (struct lan91cxx_priv_data *)sc->driver_private;
     int i, len, plen, tcr;
 
-    unsigned short *sdata = NULL;
+    cyg_uint8 *sdata;
+    cyg_uint16 data = 0;
+    int dpos = 0;
     unsigned short ints, control;
     cyg_uint16 packet, status;
 
     DEBUG_FUNCTION();
 
     INCR_STAT( tx_count );
 
+#if DEBUG & 1
+    ints = get_reg(sc, LAN91CXX_INTERRUPT);
+    db_printf("%s:START: ints: %04x\n", __FUNCTION__, ints);
+#endif
+    
     // Worry about the TX engine stopping.
     tcr = get_reg(sc, LAN91CXX_TCR);
     if ( 0 == (LAN91CXX_TCR_TXENA & tcr) ) {
 #if DEBUG & 1
         db_printf("%s: ENGINE RESTART: tcr 0x%04x\n", __FUNCTION__, tcr );
@@ -860,36 +894,36 @@ lan91cxx_send(struct eth_drv_sc *sc, str
     // Prepare header:
     put_data(sc, CYG_CPU_TO_LE16(0));        // reserve space for status word
     // packet length (includes status, byte-count and control shorts)
     put_data(sc, CYG_CPU_TO_LE16(0x7FE & (plen + 6)) ); // Always even, always < 15xx(dec)
 
-    // Put data into buffer
     for (i = 0;  i < sg_len;  i++) {
-        sdata = (unsigned short *)sg_list[i].buf;
+        sdata = (cyg_uint8 *)sg_list[i].buf;
         len = sg_list[i].len;
-
-        CYG_ASSERT(0 == (len & 1) || (i == (sg_len-1)), "odd length");
-        CYG_ASSERT( sdata, "No sg data pointer here" );
-        while(len >= sizeof(*sdata)) {
-            put_data(sc, *sdata++);
-            len -= sizeof(*sdata);
+        while( len > 0 )
+        {
+            data |= *sdata<<((dpos&1)*8);
+            dpos++, len--, sdata++;
+            if( (dpos & 1) == 0 )
+            {
+                put_data(sc, CYG_CPU_TO_LE16(data));
+                data = 0;
+            }
         }
     }
-    CYG_ASSERT( sdata, "No sg data pointer outside" );
 
     // Lay down the control short unconditionally at the end.
     // (or it might use random memory contents)
     control = 0;
-    if ( 1 & plen ) {
+    if( 1 & plen ) {
         // Need to set ODD flag and insert the data
-        unsigned char onebyte = *(unsigned char*)sdata;
-        control = onebyte;
+        control = data;
         control |= LAN91CXX_CONTROLBYTE_ODD;
     }
     control |= LAN91CXX_CONTROLBYTE_CRC; // Just in case...
     put_data(sc, CYG_CPU_TO_LE16(control));
-
+    
     // Enqueue the packet
     put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_enq_packet);
 
     // Ack TX empty int and unmask it.
     ints = get_reg(sc, LAN91CXX_INTERRUPT) & 0xff00;
@@ -962,11 +996,11 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc, 
     // 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) ) {
 #if DEBUG & 1
-        db_printf("%s: ENGINE RESTART: tcr 0x%04x ints %04x\n", __FUNCTION__, tcr, ints);
+        db_printf("%s: ENGINE RESTART: tcr 0x%04x eph 0x%04x ints 0x%04x\n", __FUNCTION__, tcr, get_reg(sc, LAN91CXX_EPH_STATUS), ints);
 #endif
         tcr |= LAN91CXX_TCR_TXENA;
         put_reg(sc, LAN91CXX_TCR, tcr);
         success = 0; // And treat this as an error...
     }
@@ -1008,10 +1042,47 @@ lan91cxx_TxEvent(struct eth_drv_sc *sc, 
         cpd->txbusy = 0;
         (sc->funs->eth_drv->tx_done)(sc, cpd->txkey, success);
     }
 }
 
+void get_data_init(struct eth_drv_sc *sc)
+{
+    struct lan91cxx_priv_data *cpd =
+        (struct lan91cxx_priv_data *)sc->driver_private;
+
+    cpd->data_buf = 0xa5a5a5a5;
+    cpd->data_pos = sizeof(rxd_t);
+}
+
+cyg_uint8 get_data_byte(struct eth_drv_sc *sc)
+{
+    cyg_uint8 c;
+    struct lan91cxx_priv_data *cpd =
+        (struct lan91cxx_priv_data *)sc->driver_private;
+
+    if( cpd->data_pos == sizeof(rxd_t) )
+    {
+        cpd->data_buf = get_data(sc);
+        cpd->data_pos = 0;
+    }
+
+    c = (cpd->data_buf>>(cpd->data_pos*8))&0xFF;
+    cpd->data_pos++;
+    
+    return c;
+
+}
+
+cyg_uint16 get_data_short(struct eth_drv_sc *sc)
+{
+    cyg_uint16 val;
+
+    val = get_data_byte(sc);
+    val |= get_data_byte(sc)<<8;
+    
+    return CYG_LE16_TO_CPU(val);
+}
 
 //
 // This function is called when a packet has been received.  Its job is
 // to prepare to unload the packet from the hardware.  Once the length of
 // the packet is known, the upper layer of the driver can be told.  When
@@ -1022,13 +1093,10 @@ 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 CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-    cyg_uint32 val;
-#endif
 
     DEBUG_FUNCTION();
 
     stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
 #if DEBUG & 1
@@ -1052,21 +1120,15 @@ 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 CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-    val = get_data(sc);
-    val = CYG_LE32_TO_CPU(val);
-    stat = val & 0xffff;
-    len = ((val >> 16) & 0xffff) - 6;   // minus header/footer words
-#else
-    stat = get_data(sc);
-    stat = CYG_LE16_TO_CPU(stat);
-    len = get_data(sc);
-    len = CYG_LE16_TO_CPU(len) - 6;     // minus header/footer words
-#endif
+    get_data_init(sc);
+    
+    stat = get_data_short(sc);
+    len = get_data_short(sc);
+    len = len - 6;     // minus header/footer words
 
 #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 );
@@ -1097,16 +1159,28 @@ lan91cxx_RxEvent(struct eth_drv_sc *sc)
     }
 
     // Not OK for one reason or another...
 #if DEBUG & 1
     db_printf("RxEvent - bad rx: stat: 0x%04x, len: 0x%04x\n", stat, len);
+    db_printf("PHY %2d: %04x\n",0,lan91cxx_read_phy( sc, 0, 0));
+    db_printf("PHY %2d: %04x\n",1,lan91cxx_read_phy( sc, 0, 1));
+    db_printf("PHY %2d: %04x\n",2,lan91cxx_read_phy( sc, 0, 2));
+    db_printf("PHY %2d: %04x\n",3,lan91cxx_read_phy( sc, 0, 3));
+    db_printf("PHY %2d: %04x\n",4,lan91cxx_read_phy( sc, 0, 4));
+    db_printf("PHY %2d: %04x\n",5,lan91cxx_read_phy( sc, 0, 5));
+    db_printf("PHY %2d: %04x\n",16,lan91cxx_read_phy( sc, 0, 16));
+    db_printf("PHY %2d: %04x\n",17,lan91cxx_read_phy( sc, 0, 17));
+    db_printf("PHY %2d: %04x\n",18,lan91cxx_read_phy( sc, 0, 18));
+    db_printf("PHY %2d: %04x\n",19,lan91cxx_read_phy( sc, 0, 19));
+    db_printf("PHY %2d: %04x\n",20,lan91cxx_read_phy( sc, 0, 20));
 #endif
 
     // Free packet
     put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);
 }
 
+
 //
 // This function is called as a result of the "eth_drv_recv()" call above.
 // Its job is to actually fetch data for a packet from the hardware once
 // memory buffers have been allocated for the packet.  Note that the buffers
 // may come in pieces, using a scatter-gather list.  This allows for more
@@ -1120,102 +1194,63 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
     struct lan91cxx_priv_data *cpd = 
         (struct lan91cxx_priv_data *)sc->driver_private;
 #endif
     int i;
     short mlen=0, plen;
-    cyg_uint16 *data=NULL;
-    unsigned char *cp, cval, odd_even = 0;
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-    cyg_uint32 val;
-#else
-    cyg_uint16 val;
-#endif
+    cyg_uint8 *data=NULL;
+    short 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));
-    val = get_data(sc);
-
-    // packet length (minus header/footer)
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-    val = CYG_LE32_TO_CPU(val);
-    plen = (val >> 16) - 6;
-#else
-    val = CYG_LE16_TO_CPU(val);
-    plen = get_data(sc);
-    plen = CYG_LE16_TO_CPU(plen) - 6;
-#endif
-
-    if( LAN91CXX_RX_STATUS_IS_ODD(cpd,val) )
-	plen++;
+    get_data_init(sc);
+    
+    val = get_data_short(sc);
+    plen = get_data_short(sc);
+    plen = plen - 6;
 
     for (i = 0;  i < sg_len;  i++) {
-        data = (cyg_uint16 *)sg_list[i].buf;
+        int clen;
+        data = (cyg_uint8 *)sg_list[i].buf;
         mlen = sg_list[i].len;
 
-        CYG_ASSERT(0 == (mlen & (sizeof(*data) - 1)) || (i == (sg_len-1)), "odd length");
+        clen = mlen;
+        if( clen > plen )
+            clen = plen;
 
 #if DEBUG & 1
-        db_printf("%s : mlen 0x%04x, plen 0x%04x\n", __FUNCTION__, mlen, plen);
+        db_printf("%s : mlen 0x%04x plen 0x%04x clen 0x%04x\n", __FUNCTION__, mlen, plen, clen);
 #endif
+        mlen -= clen;
+        plen -= clen;
+        
         if (data) {
-            while (mlen >= sizeof(*data)) {
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-            	if (!(odd_even)) {        // because of the 32bit to 16bit conversion, read only every 2nd word
-#endif
-                   val = get_data(sc);
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-                   odd_even = 1;
-               }
-               else {
-                	  val >>= 16;
-                	  odd_even = 0;
-               }
-#endif
-                *data++ = val;
-                mlen -= sizeof(*data);
-                plen -= sizeof(*data);
+            while( clen > 0 ) {
+                *data++ = get_data_byte(sc);
+                clen--;
             }
         }
         else { // must actively discard ie. read it from the chip anyway.
-            while (mlen >= sizeof(*data)) {
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-                if (!(odd_even)) {
-#endif
-                    val = get_data(sc);
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-                    odd_even = 1;
-               }
-               else {
-                   val >>= 16;
-                   odd_even = 0;
-               }
+#if DEBUG & 1            
+            db_printf("lan91cxx_recv: No data!!!!!\n");
 #endif
-                mlen -= sizeof(*data);
-                plen -= sizeof(*data);
+            while( clen > 0 ) {            
+                (void)get_data_byte(sc);
+                clen--;                
             }
         }
-    }
-    if (!(odd_even)) {      // read the control word only if we not already have it because of a 32bit access
-    val = get_data(sc); // Read control word (and potential data) unconditionally
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
-    val = CYG_LE32_TO_CPU(val);
-    if (plen & 2) {
-	if (data)
-	    *(cyg_uint16 *)data = val & 0xffff;
-	cp = (unsigned char *)data + 2;
-	val >>= 16;
-	mlen -= 2;
-        }
-#else
-    val = CYG_LE16_TO_CPU(val);
+#if DEBUG & 1
+        diag_dump_buf( sg_list[i].buf, sg_list[i].len > 64 ? 64 : sg_list[i].len );
 #endif
     }
-	cp = (unsigned char *)data;
+    val = get_data_short(sc); // Read control word (and potential data) unconditionally
+
+    cp = (unsigned char *)data;
 
     CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX, 
                "Controlbyte is not for Rx");
     CYG_ASSERT( (1 == mlen) == (0 != LAN91CXX_CONTROLBYTE_IS_ODD(cpd,val)), 
                 "Controlbyte does not match");
@@ -1237,10 +1272,11 @@ lan91cxx_recv(struct eth_drv_sc *sc, str
 
     // Free packet
     put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame);
 }
 
+
 static void
 lan91cxx_poll(struct eth_drv_sc *sc)
 {
     unsigned short event;
     struct lan91cxx_priv_data *cpd = 
@@ -1250,24 +1286,29 @@ lan91cxx_poll(struct eth_drv_sc *sc)
     while (1) {
         cyg_drv_interrupt_acknowledge(cpd->interrupt);
         // Get the (unmasked) requests
         event = get_reg(sc, LAN91CXX_INTERRUPT);
         event = event & (event >> 8) & 0xff;
+
         if (0 == event)
             break;
 #if 0
         if (event & LAN91CXX_INTERRUPT_ERCV_INT) {
             // Early receive interrupt
+            db_printf("Early receive interrupt\n");
         }
         else if (event & LAN91CXX_INTERRUPT_EPH_INT) {
             // ethernet protocol handler failures
+            db_printf("Ethernet protocol handler failures\n");
         }
         else if (event & LAN91CXX_INTERRUPT_RX_OVRN_INT) {
             // receive overrun
+            db_printf("Receive overrun\n");
         }
         else if (event & LAN91CXX_INTERRUPT_ALLOC_INT) {
             // allocation interrupt
+            db_printf("Allocation interrupt\n");
         }
         else
 #endif
         if (event & LAN91CXX_INTERRUPT_TX_SET) {
             lan91cxx_TxEvent(sc, event);
@@ -1340,22 +1381,22 @@ lan91cxx_read_phy(struct eth_drv_sc *sc,
 
     // Clock all 64 cycles
     for (i = 0; i < sizeof(bits); ++i) {
 	// Clock Low - output data
 	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);
-	HAL_DELAY_US(50);
+	CYGACC_CALL_IF_DELAY_US(50);
 
 	// Clock Hi - input data
 	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
-	HAL_DELAY_US(50);
+	CYGACC_CALL_IF_DELAY_US(50);
 
 	bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;
     }
 
     // Return to idle state
     put_reg(sc, LAN91CXX_MGMT, mii_reg);
-    HAL_DELAY_US(50);
+    CYGACC_CALL_IF_DELAY_US(50);
 
     // Recover input data
     for (value = 0, i = 0; i < 16; ++i) {
 	value <<= 1;
 	if (bits[input_idx++] & LAN91CXX_MGMT_MDI)
@@ -1424,21 +1465,21 @@ lan91cxx_write_phy(struct eth_drv_sc *sc
 
     // Clock all cycles
     for (i = 0; i < sizeof(bits); ++i) {
 	// Clock Low - output data
 	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i]);
-	HAL_DELAY_US(50);
+	CYGACC_CALL_IF_DELAY_US(50);
 
 	// Clock Hi - input data
 	put_reg(sc, LAN91CXX_MGMT, mii_reg | bits[i] | LAN91CXX_MGMT_MCLK);
-	HAL_DELAY_US(50);
+	CYGACC_CALL_IF_DELAY_US(50);
 
 //	bits[i] |= get_reg(sc, LAN91CXX_MGMT) & LAN91CXX_MGMT_MDI;
     }
 
     // Return to idle state
     put_reg(sc, LAN91CXX_MGMT, mii_reg);
-    HAL_DELAY_US(50);
+    CYGACC_CALL_IF_DELAY_US(50);
 }
 #endif // LAN91CXX_IS_LAN91C111
 
 // EOF if_lan91cxx.c
Index: src/smsc_lan91cxx.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h,v
retrieving revision 1.12
diff -u -5 -p -r1.12 smsc_lan91cxx.h
--- src/smsc_lan91cxx.h	29 Jun 2005 20:06:05 -0000	1.12
+++ src/smsc_lan91cxx.h	20 Jul 2006 16:37:26 -0000
@@ -328,20 +328,22 @@ typedef struct lan91cxx_priv_data {
     int txpacket;
     int rxpacket;
     int within_send;
     int addrsh;                         // Address bits to shift
     int c111_reva;                      // true if this is a revA LAN91C111
+    cyg_uint32 data_buf;
+    int   data_pos;
 #ifdef KEEP_STATISTICS
     struct smsc_lan91cxx_stats stats;
 #endif
 } lan91cxx_priv_data;
 
 // ------------------------------------------------------------------------
 
 #include CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL
 
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
+#ifdef LAN91CXX_32BIT_RX
 typedef cyg_uint32 rxd_t;
 #else
 typedef cyg_uint16 rxd_t;
 #endif
 
@@ -404,11 +406,11 @@ get_data(struct eth_drv_sc *sc)
 {
     rxd_t val;
     struct lan91cxx_priv_data *cpd =
         (struct lan91cxx_priv_data *)sc->driver_private;
 	
-#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT
+#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
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]