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