This is the mail archive of the ecos-discuss@sources.redhat.com 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]

eCos DP83902a driver


Hi, 

I have been using the eCos NS DP83902a driver together with an Asix 
ax88796 chip (ne2000 compatible). I have included a diff with a few 
things I had to fix to get it to work. 

1. The Asix device can't change page and start DMA in the same command. 
Command has been spitted in two commands. 
2. Implementation of ETH_DRV_SET_MAC_ADDRESS has been added 
3. The packet header and packet data was word-swapped. I am not sure if 
this is because I use the device in 80186 mode or if there is any other 
reason. Anyway I made it possible to configure that the driver should 
swap the bytes (maybe this should be a CDL option instead). 
4. There is a bug in the Asix chip that implies that DMA complete status 
is never set (according to the data sheet the DMA is always ready). An 
option has been added that can be used to disable the wait for DMA 
complete. 

Please comment on the changes and suggest improvements. 

PS. I have only tested the driver with RedBoot but we also have a Linux 
driver (where we had to fix item 4 above) that has been tested for 
several days with maximum load. DS. 

Thanks 
/Mikael 

Index: if_dp83902a.c 
=================================================================== 
RCS file: /usr/local/cvs/linux/os/ecos/packages/devs/eth/ns/dp83902a/current/src/if_dp83902a.c,v 
retrieving revision 1.1.1.3 
diff -u -r1.1.1.3 if_dp83902a.c 
--- if_dp83902a.c       26 Feb 2002 13:40:52 -0000      1.1.1.3 
+++ if_dp83902a.c       21 Mar 2003 14:39:56 -0000 
@@ -58,6 +58,7 @@ 
 #include <pkgconf/system.h> 
 #include <cyg/infra/cyg_type.h> 
 #include <cyg/hal/hal_arch.h> 
+#include <cyg/hal/hal_endian.h> 
 #include <cyg/infra/diag.h> 
 #include <cyg/hal/drv_api.h> 
 #define __ECOS 
@@ -247,6 +248,7 @@ 
         DP_OUT(base, DP_P1_PAR0+i, enaddr[i]); 
     } 
     // Enable and start device 
+    DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); 
     DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);  
     DP_OUT(base, DP_TCR, DP_TCR_NORMAL); // Normal transmit operations 
     DP_OUT(base, DP_RCR, DP_RCR_AB);  // Accept broadcast, no errors, no multicast 
@@ -261,8 +263,16 @@ 
 dp83902a_control(struct eth_drv_sc *sc, unsigned long key, 
                void *data, int data_len) 
 { 
+    dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *)sc->driver_private; 
+    int i; 
+ 
     switch (key) { 
     case ETH_DRV_SET_MAC_ADDRESS: 
+        if (data_len != ETHER_ADDR_LEN) 
+            return -2; 
+        memcpy(dp->esa, data, ETHER_ADDR_LEN); 
+        for (i = 0; i < ETHER_ADDR_LEN; i++) 
+            DP_OUT(dp->base, DP_P1_PAR0+i, dp->esa[i]); 
         return 0; 
         break; 
     default: 
@@ -410,6 +420,9 @@ 
             len -= 2; 
             if (len >= 0) 
                 tmp |= *data++; 
+#ifdef CYGHWR_NS_DP83902A_PLF_WORD_SWAP 
+            tmp = CYG_SWAP16(tmp); 
+#endif 
             DP_OUT_DATA(dp->data, tmp); 
 #if DEBUG & 4 
             diag_printf(" %04x", tmp); 
@@ -450,12 +463,14 @@ 
     CYGACC_CALL_IF_DELAY_US(1); 
 #endif 
  
+#ifndef CYGHWR_NS_DP83902A_PLF_NO_DMA_COMPLETE 
     // Wait for DMA to complete 
     do { 
         DP_IN(base, DP_ISR, isr); 
     } while ((isr & DP_ISR_RDC) == 0); 
     // Then disable DMA 
     DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 
+#endif 
     CR_DOWN(); 
  
     // Start transmit if not already going 
@@ -518,8 +533,13 @@ 
 #ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA 
             cyg_uint16 tmp; 
             DP_IN_DATA(dp->data, tmp); 
+#ifdef CYGHWR_NS_DP83902A_PLF_WORD_SWAP 
+            rcv_hdr[i++] = tmp & 0xff; 
+            rcv_hdr[i++] = (tmp >> 8) & 0xff; 
+#else 
             rcv_hdr[i++] = (tmp >> 8) & 0xff; 
             rcv_hdr[i++] = tmp & 0xff; 
+#endif 
 #else 
             DP_IN_DATA(dp->data, rcv_hdr[i++]); 
 #endif 
@@ -605,6 +625,17 @@ 
                     diag_printf(" %04x", tmp); 
                     if (0 == (++dx % 8)) diag_printf("\n "); 
 #endif 
+#ifdef CYGHWR_NS_DP83902A_PLF_WORD_SWAP 
+                    *data++ = tmp & 0xff; 
+                    mlen--; 
+                    if (0 == mlen) { 
+                      saved_char = (tmp >> 8) & 0xff; 
+                        saved = true; 
+                    } else { 
+                      *data++ = (tmp >> 8) & 0xff; 
+                        mlen--; 
+                    } 
+#else 
                     *data++ = (tmp >> 8) & 0xff; 
                     mlen--; 
                     if (0 == mlen) { 
@@ -614,6 +645,7 @@ 
                         *data++ = tmp & 0xff; 
                         mlen--; 
                     } 
+#endif 
                 } 
 #else 
                 { 

  

-- 
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss


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