This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Improved big-endian support
- From: Bob Koninckx <bob dot koninckx at o-3s dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: Tue, 20 Apr 2004 12:12:56 +0200
- Subject: Improved big-endian support
- Organization: o-3s
- Reply-to: bob dot koninckx at o-3s dot com
As before, but fixing a recently found problem as well :-)
? cs8900a.patch
Index: current/ChangeLog
===================================================================
RCS file: /cvs/o3s/software/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -5 -r1.1.1.2 -r1.3
--- current/ChangeLog 24 Nov 2003 19:46:27 -0000 1.1.1.2
+++ current/ChangeLog 19 Apr 2004 08:08:14 -0000 1.3
@@ -1,5 +1,16 @@
+2004-04-19 Bob Koninckx <bob.koninckx@o-3s.com>
+ * src/if_cs8900a.c: function cs8900a_int_vector, return the vector
+ instead of a boolean.
+
+2004-04-08 Bob Koninckx <bob.koninckx@o-3s.com>
+ * cdl/cl_cs8900a_eth_drivers.cdl
+ * include/if_cs8900a.c
+ * src/if_cs8900a.c: Made hardware swapping or software swapping of
+ data bytes (mostly relevant to big endian machines) a configuration
+ option
+
2003-11-05 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be>
* src/if_cs8900a.c: Fix handling of odd bytes on big endian machines
2003-04-12 Jonathan Larmour <jifl@eCosCentric.com>
Index: current/cdl/cl_cs8900a_eth_drivers.cdl
===================================================================
RCS file: /cvs/o3s/software/ecos/packages/devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -5 -r1.1.1.1 -r1.2
--- current/cdl/cl_cs8900a_eth_drivers.cdl 7 Jun 2003 09:01:57 -0000 1.1.1.1
+++ current/cdl/cl_cs8900a_eth_drivers.cdl 8 Apr 2004 19:33:30 -0000 1.2
@@ -66,10 +66,33 @@
define_proc {
puts $::cdl_header "#include <pkgconf/system.h>";
puts $::cdl_header "#include CYGDAT_DEVS_ETH_CL_CS8900A_CFG";
}
+ cdl_option CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED {
+ display "Byte swapped data bus"
+ flavor bool
+ default_value 0
+ description "
+ From the application note AN205 from Cirrus Logic ...The CS8900a
+ assumes a litte-endian ISA type system. However, network byte order
+ is always big-endian.Therefore to minimize software manipulation of
+ frame data in ISA systems, the CS8900 byte-swaps frame data
+ internally. The control and status registers are not byte-swapped.
+ In a big-endian system you can either byte-swap the network data
+ (to reverse the byte swapping done internally to the CS8900) in
+ software or you can do it in hardware (byte swap the data lines to
+ the chip). Byte swapping the data lines is much more efficient; you
+ will only need to byte swap the control/status/counter values in
+ software and not the frame data. (Most of the read/writes to the chip
+ are frame data.) Since network byte order is always big endian, this
+ scheme works without special support on the other end of the network...
+ Normally, you won't need to check this option unless you are using a
+ CS8900a ethernet controller with a big endian machine and hardware
+ that has been designed with the cs8900a in mind."
+ }
+
cdl_component CYGPKG_DEVS_ETH_CL_CS8900A_OPTIONS {
display "Cirrus Logic ethernet driver build options"
flavor none
no_define
Index: current/include/cs8900.h
===================================================================
RCS file: /cvs/o3s/software/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -5 -r1.1.1.1 -r1.2
--- current/include/cs8900.h 7 Jun 2003 09:01:57 -0000 1.1.1.1
+++ current/include/cs8900.h 8 Apr 2004 19:33:30 -0000 1.2
@@ -165,31 +165,29 @@
# define CS8900A_ISQ (4*CS8900A_step)
# define CS8900A_PPTR (5*CS8900A_step)
# define CS8900A_PDATA (6*CS8900A_step)
#endif
-#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
#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)
+#else
#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)
-#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
#define PP_ChipID 0x0000 // Chip identifier - must be 0x630e
#define PP_ChipRev 0x0002 // Chip revision, model codes
#define PP_ChipID_CL 0x630e
@@ -308,11 +306,11 @@
#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)
+#else
#define PP_ChipID 0x0000 // Chip identifier - must be 0x0e63
#define PP_ChipRev 0x0200 // Chip revision, model codes
#define PP_ChipID_CL 0x0e63
@@ -431,12 +429,10 @@
#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
Index: current/src/if_cs8900a.c
===================================================================
RCS file: /cvs/o3s/software/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -5 -r1.1.1.2 -r1.4
--- current/src/if_cs8900a.c 24 Nov 2003 19:46:27 -0000 1.1.1.2
+++ current/src/if_cs8900a.c 19 Apr 2004 08:08:14 -0000 1.4
@@ -157,11 +157,11 @@
static int
cs8900a_int_vector(struct eth_drv_sc *sc)
{
cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private;
- return (cpd->interrupt) ? 1 : 0;
+ return (cpd->interrupt);
}
static bool
cs8900a_init(struct cyg_netdevtab_entry *tab)
{
@@ -262,20 +262,18 @@
}
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)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
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)
+#else
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) {
@@ -285,21 +283,21 @@
return false;
}
// Tell the chip what ESA to use
for (i = 0; i < sizeof(cpd->esa); i += 2) {
-#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
put_reg(base, PP_IA+i, cpd->esa[i] | (cpd->esa[i+1] << 8));
-#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+#else
put_reg(base, PP_IA+CYG_SWAP16(i), cpd->esa[i+1] | (cpd->esa[i] << 8));
#endif
}
// Set logical address mask
for (i = 0; i < 8; i += 2) {
-#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
put_reg(base, PP_LAF+i, 0xFFFF);
-#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+#else
put_reg(base, PP_LAF+CYG_SWAP16(i), 0xFFFF);
#endif
}
# if DEBUG & 8
diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -436,11 +434,11 @@
#ifdef CYGPKG_KERNEL
cpd->txstart = cyg_current_time();
#endif
// Start the xmit sequence
-#if(CYG_BYTEORDER == CYG_MSBFIRST)
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
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
@@ -470,34 +468,42 @@
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
+// This new byte must get on the bus _after_ the last saved odd byte, it therefore
+// belongs in the MSB of the CS8900a
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
saved_data |= *data++;
+#else
+ saved_data |= ((cyg_uint16)*data++) << 8;
#endif
HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
len--;
odd_byte = false;
}
if (((CYG_ADDRESS)data & 0x1) == 0) {
/* Aligned on 16-bit boundary, so output contiguous words. */
sdata = (cyg_uint16 *)data;
while (len > 1) {
+ // Make sure data get on the bus in Big Endian format
+#if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
+ (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
+#else
+ HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, CYG_SWAP16(*sdata++));
+#endif
len -= sizeof(cyg_uint16);
}
data = (cyg_uint8 *)sdata;
} else {
/* Not 16-bit aligned, so byte copy */
while (len > 1) {
saved_data = (cyg_uint16)*data++; // reuse saved_data
-#if CYG_BYTEORDER == CYG_MSBFIRST
+ // Make sure data get on the bus in Big Endian format, the first byte belongs in the
+ // LSB of the CS8900A
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
saved_data = ((cyg_uint16)*data++) | (saved_data << 8);
#else
saved_data |= ((cyg_uint16)*data++) << 8;
#endif
HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
@@ -505,11 +511,13 @@
}
}
/* Save last byte, if necessary. */
if (len == 1) {
saved_data = (cyg_uint16)*data;
-#if CYG_BYTEORDER == CYG_MSBFIRST
+// This _last_ byte must get on the bus _first_, it therefore belongs in the LSB of
+// the CS8900a
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
saved_data = (saved_data << 8);
#endif
odd_byte = true;
}
}
@@ -532,11 +540,11 @@
cyg_uint16 stat, len;
HAL_READ_UINT16(base+CS8900A_RTDATA, stat);
HAL_READ_UINT16(base+CS8900A_RTDATA, len);
-#if(CYG_BYTEORDER == CYG_MSBFIRST)
+#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
len = CYG_SWAP16(len);
#endif
#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
if (cyg_io_eth_net_debug) {
@@ -564,17 +572,22 @@
data = (cyg_uint16 *)sg_list[i].buf;
mlen = sg_list[i].len;
while (mlen >= sizeof(*data)) {
HAL_READ_UINT16(base+CS8900A_RTDATA, val);
if (data) {
+#if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \
+ (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED ))
*data++ = val;
+#else
+ *data++ = CYG_SWAP16(val);
+#endif
}
mlen -= sizeof(*data);
}
if (mlen) {
HAL_READ_UINT16(base+CS8900A_RTDATA, val);
-#if(CYG_BYTEORDER == CYG_LSBFIRST)
+#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED
// 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);