cs8900a for big endian targets

Bob Koninckx bob.koninckx@mech.kuleuven.ac.be
Mon Mar 3 20:54:00 GMT 2003


Oops ... Better send it with the attachment ...

Attached patch makes a number of modifications to the code to support
both big endian and little endian targets. Thoroughly tested with big
endian target (powerpc), not been tested with a little endian target as
I don't have one.

Notice that this patch supposes that the data bytes are swapped by
_hardware_ for big endian as recommended in the cs8900a datasheet

I hope that someone has the possibility to test this with a little
endian target and that it eventually makes it into the source tree.

Best,
Bob

-- 
----------------------------------------------------------------------
ir. Bob Koninckx
Katholieke Universiteit Leuven
Division Production Engineering,                   tel.  +32 16 322535
Machine Design and Automation                      fax.  +32 16 322987
Celestijnenlaan 300B                  bob.koninckx@mech.kuleuven.ac.be
B-3001 Leuven Belgium               http://www.mech.kuleuven.ac.be/pma
----------------------------------------------------------------------
-------------- next part --------------
? cs8900a.patch
Index: current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog,v
retrieving revision 1.6
diff -u -5 -r1.6 ChangeLog
--- current/ChangeLog	14 Jun 2002 22:01:15 -0000	1.6
+++ current/ChangeLog	3 Mar 2003 20:47:22 -0000
@@ -1,5 +1,10 @@
+2003-03-03  Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be>
+    * src/if_cs8900a.c:
+    * include/cs8900a.h:
+    Changes to support both little and big endian targets
+
 2002-06-14  Gary Thomas  <gary@chez-thomas.org>
 
 	* src/if_cs8900a.c: 
 	Need to include <pkgconf/io_eth_drivers.h> for proper configuration
 	of stand-alone (polled) vs. system (interrupt driven) mode.
Index: current/include/cs8900.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h,v
retrieving revision 1.4
diff -u -5 -r1.4 cs8900.h
--- current/include/cs8900.h	31 May 2002 01:05:54 -0000	1.4
+++ current/include/cs8900.h	3 Mar 2003 20:47:22 -0000
@@ -165,21 +165,35 @@
 # define CS8900A_ISQ    (4*CS8900A_step)
 # define CS8900A_PPTR   (5*CS8900A_step)
 # define CS8900A_PDATA  (6*CS8900A_step)
 #endif
 
-#define ISQ_RxEvent     0x04
-#define ISQ_TxEvent     0x08
-#define ISQ_BufEvent    0x0C
-#define ISQ_RxMissEvent 0x10
-#define ISQ_TxColEvent  0x12
-#define ISQ_EventMask   0x3F
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#define ISQ_RxEvent     0x0004
+#define ISQ_TxEvent     0x0008
+#define ISQ_BufEvent    0x000C
+#define ISQ_RxMissEvent 0x0010
+#define ISQ_TxColEvent  0x0012
+#define ISQ_EventMask   0x003F
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+#define ISQ_RxEvent     0x0400
+#define ISQ_TxEvent     0x0800
+#define ISQ_BufEvent    0x0C00
+#define ISQ_RxMissEvent 0x1000
+#define ISQ_TxColEvent  0x1200
+#define ISQ_EventMask   0x3F00
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
 
 // ------------------------------------------------------------------------
 // Registers available via "page pointer" (indirect access)
-#define PP_ChipID    0x0000  // Chip identifier - must be 0x630E
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
+
+#define PP_ChipID    0x0000  // Chip identifier - must be 0x630e
 #define PP_ChipRev   0x0002  // Chip revision, model codes
+#define PP_ChipID_CL           0x630e
 
 #define PP_IntReg    0x0022  // Interrupt configuration
 #define PP_IntReg_IRQ0         0x0000  // Use INTR0 pin
 #define PP_IntReg_IRQ1         0x0001  // Use INTR1 pin
 #define PP_IntReg_IRQ2         0x0002  // Use INTR2 pin
@@ -293,10 +307,137 @@
 #define PP_BusStat_TxBid       0x0080  // Tx error
 #define PP_BusStat_TxRDY       0x0100  // Ready for Tx data
 
 #define PP_LAF       0x0150  // Logical address filter (6 bytes)
 #define PP_IA        0x0158  // Individual address (MAC)
+
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+
+#define PP_ChipID    0x0000  // Chip identifier - must be 0x0e63
+#define PP_ChipRev   0x0200  // Chip revision, model codes
+#define PP_ChipID_CL           0x0e63
+
+#define PP_IntReg    0x2200  // Interrupt configuration
+#define PP_IntReg_IRQ0         0x0000  // Use INTR0 pin
+#define PP_IntReg_IRQ1         0x0100  // Use INTR1 pin
+#define PP_IntReg_IRQ2         0x0200  // Use INTR2 pin
+#define PP_IntReg_IRQ3         0x0300  // Use INTR3 pin
+
+#define PP_RxCFG     0x0201  // Receiver configuration
+#define PP_RxCFG_Skip1         0x4000  // Skip (i.e. discard) current frame
+#define PP_RxCFG_Stream        0x8000  // Enable streaming mode
+#define PP_RxCFG_RxOK          0x0001  // RxOK interrupt enable
+#define PP_RxCFG_RxDMAonly     0x0002  // Use RxDMA for all frames
+#define PP_RxCFG_AutoRxDMA     0x0004  // Select RxDMA automatically
+#define PP_RxCFG_BufferCRC     0x0008  // Include CRC characters in frame
+#define PP_RxCFG_CRC           0x0010  // Enable interrupt on CRC error
+#define PP_RxCFG_RUNT          0x0020  // Enable interrupt on RUNT frames
+#define PP_RxCFG_EXTRA         0x0040  // Enable interrupt on frames with extra data
+
+#define PP_RxCTL     0x0401  // Receiver control
+#define PP_RxCTL_IAHash        0x4000  // Accept frames that match hash
+#define PP_RxCTL_Promiscuous   0x8000  // Accept any frame
+#define PP_RxCTL_RxOK          0x0001  // Accept well formed frames
+#define PP_RxCTL_Multicast     0x0002  // Accept multicast frames
+#define PP_RxCTL_IA            0x0004  // Accept frame that matches IA
+#define PP_RxCTL_Broadcast     0x0008  // Accept broadcast frames
+#define PP_RxCTL_CRC           0x0010  // Accept frames with bad CRC
+#define PP_RxCTL_RUNT          0x0020  // Accept runt frames
+#define PP_RxCTL_EXTRA         0x0040  // Accept frames that are too long
+
+#define PP_TxCFG     0x0601  // Transmit configuration
+#define PP_TxCFG_CRS           0x4000  // Enable interrupt on loss of carrier
+#define PP_TxCFG_SQE           0x8000  // Enable interrupt on Signal Quality Error
+#define PP_TxCFG_TxOK          0x0001  // Enable interrupt on successful xmits
+#define PP_TxCFG_Late          0x0002  // Enable interrupt on "out of window" 
+#define PP_TxCFG_Jabber        0x0004  // Enable interrupt on jabber detect
+#define PP_TxCFG_Collision     0x0008  // Enable interrupt if collision
+#define PP_TxCFG_16Collisions  0x0080  // Enable interrupt if > 16 collisions
+
+#define PP_TxCmd     0x0801  // Transmit command status
+#define PP_TxCmd_TxStart_5     0x0000  // Start after 5 bytes in buffer
+#define PP_TxCmd_TxStart_381   0x4000  // Start after 381 bytes in buffer
+#define PP_TxCmd_TxStart_1021  0x8000  // Start after 1021 bytes in buffer
+#define PP_TxCmd_TxStart_Full  0xC000  // Start after all bytes loaded
+#define PP_TxCmd_Force         0x0001  // Discard any pending packets
+#define PP_TxCmd_OneCollision  0x0002  // Abort after a single collision
+#define PP_TxCmd_NoCRC         0x0010  // Do not add CRC
+#define PP_TxCmd_NoPad         0x0020  // Do not pad short packets
+
+#define PP_BufCFG    0x0A01  // Buffer configuration
+#define PP_BufCFG_SWI          0x4000  // Force interrupt via software
+#define PP_BufCFG_RxDMA        0x8000  // Enable interrupt on Rx DMA
+#define PP_BufCFG_TxRDY        0x0001  // Enable interrupt when ready for Tx
+#define PP_BufCFG_TxUE         0x0002  // Enable interrupt in Tx underrun
+#define PP_BufCFG_RxMiss       0x0004  // Enable interrupt on missed Rx packets
+#define PP_BufCFG_Rx128        0x0008  // Enable Rx interrupt after 128 bytes
+#define PP_BufCFG_TxCol        0x0010  // Enable int on Tx collision ctr overflow
+#define PP_BufCFG_Miss         0x0020  // Enable int on Rx miss ctr overflow
+#define PP_BufCFG_RxDest       0x0080  // Enable int on Rx dest addr match
+
+#define PP_LineCTL   0x1201  // Line control
+#define PP_LineCTL_Rx          0x4000  // Enable receiver
+#define PP_LineCTL_Tx          0x8000  // Enable transmitter
+
+#define PP_RER       0x2401  // Receive event
+#define PP_RER_IAHash          0x4000  // Frame hash match
+#define PP_RER_Dribble         0x8000  // Frame had 1-7 extra bits after last byte
+#define PP_RER_RxOK            0x0001  // Frame received with no errors
+#define PP_RER_Hashed          0x0002  // Frame address hashed OK
+#define PP_RER_IA              0x0004  // Frame address matched IA
+#define PP_RER_Broadcast       0x0008  // Broadcast frame
+#define PP_RER_CRC             0x0010  // Frame had CRC error
+#define PP_RER_RUNT            0x0020  // Runt frame
+#define PP_RER_EXTRA           0x0040  // Frame was too long
+
+#define PP_TER       0x2801 // Transmit event
+#define PP_TER_CRS             0x4000  // Carrier lost
+#define PP_TER_SQE             0x8000  // Signal Quality Error
+#define PP_TER_TxOK            0x0001  // Packet sent without error
+#define PP_TER_Late            0x0002  // Out of window
+#define PP_TER_Jabber          0x0004  // Stuck transmit?
+#define PP_TER_NumCollisions   0x0078  // Number of collisions
+#define PP_TER_16Collisions    0x0080  // > 16 collisions
+
+#define PP_SelfCtl   0x1401  // Chip control
+#define PP_SelfCtl_Reset       0x4000  // Self-clearing reset
+
+#define PP_BusCtl    0x1601  // Bus control
+#define PP_BusCtl_ResetRxDMA   0x4000  // Reset receiver DMA engine
+#define PP_BusCtl_DMAextend    0x0001
+#define PP_BusCtl_UseSA        0x0002
+#define PP_BusCtl_MemoryE      0x0004  // Enable "memory mode"
+#define PP_BusCtl_DMAburst     0x0008
+#define PP_BusCtl_IOCH_RDYE    0x0010
+#define PP_BusCtl_RxDMAsize    0x0020
+#define PP_BusCtl_EnableIRQ    0x0080  // Enable interrupts
+
+#define PP_LineStat  0x3401  // Line status
+#define PP_LineStat_LinkOK     0x8000  // Line is connected and working
+#define PP_LineStat_AUI        0x0001  // Connected via AUI
+#define PP_LineStat_10BT       0x0002  // Connected via twisted pair
+#define PP_LineStat_Polarity   0x0010  // Line polarity OK (10BT only)
+#define PP_LineStat_CRS        0x0040  // Frame being received
+
+#define PP_SelfStat  0x3601  // Chip status
+#define PP_SelfStat_InitD      0x8000  // Chip initialization complete
+#define PP_SelfStat_SIBSY      0x0001  // EEPROM is busy
+#define PP_SelfStat_EEPROM     0x0002  // EEPROM present
+#define PP_SelfStat_EEPROM_OK  0x0004  // EEPROM checks out
+#define PP_SelfStat_ELPresent  0x0008  // External address latch logic available
+#define PP_SelfStat_EEsize     0x0010  // Size of EEPROM
+
+#define PP_BusStat   0x3801  // Bus status
+#define PP_BusStat_TxBid       0x8000  // Tx error
+#define PP_BusStat_TxRDY       0x0001  // Ready for Tx data
+
+#define PP_LAF       0x5001  // Logical address filter (6 bytes)
+#define PP_IA        0x5801  // Individual address (MAC)
+
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
 
 // ------------------------------------------------------------------------
 // "page pointer" access functions
 static __inline__ cyg_uint16
 get_reg(cyg_addrword_t base, int regno)
Index: current/src/if_cs8900a.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c,v
retrieving revision 1.6
diff -u -5 -r1.6 if_cs8900a.c
--- current/src/if_cs8900a.c	14 Jun 2002 22:01:17 -0000	1.6
+++ current/src/if_cs8900a.c	3 Mar 2003 20:47:23 -0000
@@ -73,10 +73,11 @@
 #include <pkgconf/io_eth_drivers.h>
 
 #include <cyg/infra/cyg_type.h>
 #include <cyg/hal/hal_arch.h>
 #include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_endian.h>
 #include <cyg/infra/diag.h>
 #include <cyg/hal/drv_api.h>
 #undef __ECOS
 #define __ECOS
 #include <cyg/io/eth/eth_drv.h>
@@ -166,11 +167,11 @@
 {
     struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
     cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
     cyg_addrword_t base = cpd->base;
     cyg_uint16 chip_type, chip_rev, chip_status;
-    int i;
+    cyg_uint16 i;
     long timeout = 500000;
     cyg_bool esa_configured = false;
     
     cpd->tab = tab;
 
@@ -210,11 +211,11 @@
     chip_type = get_reg(base, PP_ChipID);
     chip_rev = get_reg(base, PP_ChipRev);
 #if DEBUG & 8
     diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", base, chip_type, chip_rev);
 #endif
-    if (chip_type != 0x630e) {
+    if (chip_type != PP_ChipID_CL) {
 #if DEBUG & 8
         diag_printf("CS8900 - invalid type (0x%04x), must be 0x630e\n", chip_type);
 #endif
         return false;
     }
@@ -261,13 +262,21 @@
     }
     if (!esa_configured && (chip_status & PP_SelfStat_EEPROM)) {
         // Get ESA from EEPROM - via the PP_IA registers
         cyg_uint16 esa_word;
         for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
             esa_word = get_reg(base, PP_IA+i);
             cpd->esa[i] = (esa_word & 0xFF);
             cpd->esa[i+1] = (esa_word >> 8) & 0xFF;
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+            esa_word = get_reg(base, PP_IA+CYG_SWAP16(i));
+            cpd->esa[i+1] = (esa_word & 0xFF);
+            cpd->esa[i] = (esa_word >> 8) & 0xFF;
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
         }
         esa_configured = true;
     }
     if (!esa_configured) {
 # if DEBUG & 8
@@ -276,15 +285,27 @@
         return false;
     }
 
     // Tell the chip what ESA to use
     for (i = 0;  i < sizeof(cpd->esa);  i += 2) {
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
         put_reg(base, PP_IA+i, cpd->esa[i] | (cpd->esa[i+1] << 8));
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+        put_reg(base, PP_IA+CYG_SWAP16(i), cpd->esa[i+1] | (cpd->esa[i] << 8));
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
     }
     // Set logical address mask
     for (i = 0;  i < 8;  i += 2) {
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
         put_reg(base, PP_LAF+i, 0xFFFF);
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+        put_reg(base, PP_LAF+CYG_SWAP16(i), 0xFFFF);
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
     }
 # if DEBUG & 8
     diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n",
                 cpd->esa[0], cpd->esa[1], cpd->esa[2],
                 cpd->esa[3], cpd->esa[4], cpd->esa[5]);
@@ -417,12 +438,16 @@
     cpd->txbusy = true;
     cpd->txkey = key;
 #ifdef CYGPKG_KERNEL
     cpd->txstart = cyg_current_time();
 #endif
-    // Start the xmit sequence
 
+    // Start the xmit sequence
+#if(CYG_BYTEORDER == CYG_MSBFIRST)	
+	total_len = CYG_SWAP16(total_len);
+#endif
+	
     // The hardware indicates that there are options as to when the actual
     // packet transmission will start wrt moving of data into the transmit
     // buffer.  However, impirical results seem to indicate that if the
     // packet is large and transmission is allowed to start before the
     // entire packet has been pushed into the buffer, the hardware gets
@@ -449,11 +474,19 @@
         len = sg_list[i].len;
 
         if (len > 0) {
             /* Finish the last word. */
             if (odd_byte) {
+#if(CYG_BYTEORDER == CYG_LSBFIRST)				
+				// Add data to the most significant byte
                 saved_data |= ((cyg_uint16)*data++) << 8;
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+				// Add data to the least significant byte
+				saved_data |= *data++;
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
                 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
                 len--;
                 odd_byte = false;
             }
             /* Output contiguous words. */
@@ -462,12 +495,20 @@
                 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
                 len -= sizeof(cyg_uint16);
             }
             /* Save last byte, if necessary. */
             if (len == 1) {
-                data = (cyg_uint8 *)sdata;
-                saved_data = (cyg_uint16)*data;
+                saved_data = *sdata;
+#if(CYG_BYTEORDER == CYG_LSBFIRST)
+				// The data is now in the least significant byte
+				saved_data &= 0x00ff;
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+				// The data is now in the most significant byte
+				saved_data &= 0xff00;
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
                 odd_byte = true;
             }
         }
     }
     if (odd_byte) {
@@ -487,10 +528,15 @@
     cyg_addrword_t base = cpd->base;
     cyg_uint16 stat, len;
 
     HAL_READ_UINT16(base+CS8900A_RTDATA, stat);
     HAL_READ_UINT16(base+CS8900A_RTDATA, len);
+
+#if(CYG_BYTEORDER == CYG_MSBFIRST)
+    len = CYG_SWAP16(len);
+#endif
+	
 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
     if (cyg_io_eth_net_debug) {
         diag_printf("RxEvent - stat: %x, len: %d\n", stat, len);
     }
 #endif
@@ -520,13 +566,21 @@
                 *data++ = val;
             }
             mlen -= sizeof(*data);
         }
         if (mlen) {
-            // Fetch last odd byte
-            HAL_READ_UINT16(base+CS8900A_RTDATA, cval);
-            cval &= 0xFF;
+            HAL_READ_UINT16(base+CS8900A_RTDATA, val);
+#if(CYG_BYTEORDER == CYG_LSBFIRST)			
+            // last odd byte will be in the LSB
+            cval = (cyg_uint8)(val);
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+            // last odd byte will be in the MSB
+			cval = (cyg_uint8)(val >> 8);
+#else
+# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
+#endif
+			cval &= 0xff;
             if ((cp = (cyg_uint8 *)data) != 0) {
                 *cp = cval;
             }
         }
     }


More information about the Ecos-patches mailing list