changeset 941:01d8c3c977d9

* src/if_cs8900a.c (cs8900a_send): Allow for data not being 16-bit aligned. Thanks to Laurent Gonzalez <laurent.gonzalez@ri.silicomp.fr> for reporting this and his initial patch. * src/if_cs8900a.c: * include/cs8900a.h: Changes to support both little and big endian targets
author jlarmour
date Sat, 12 Apr 2003 03:50:18 +0000
parents 26aa16c08c2e
children a1acc9055298
files packages/devs/eth/cl/cs8900a/current/ChangeLog packages/devs/eth/cl/cs8900a/current/include/cs8900.h packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c
diffstat 3 files changed, 223 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/cl/cs8900a/current/ChangeLog
+++ b/packages/devs/eth/cl/cs8900a/current/ChangeLog
@@ -1,3 +1,15 @@
+2003-04-12  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/if_cs8900a.c (cs8900a_send): Allow for data not being 16-bit
+	aligned. Thanks to Laurent Gonzalez <laurent.gonzalez@ri.silicomp.fr>
+	for reporting this and his initial patch.
+
+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: 
--- a/packages/devs/eth/cl/cs8900a/current/include/cs8900.h
+++ b/packages/devs/eth/cl/cs8900a/current/include/cs8900.h
@@ -167,17 +167,31 @@ typedef struct cs8900a_priv_data {
 # 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
@@ -296,6 +310,133 @@ typedef struct cs8900a_priv_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
--- a/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c
+++ b/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c
@@ -75,6 +75,7 @@
 #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
@@ -168,7 +169,7 @@ cs8900a_init(struct cyg_netdevtab_entry 
     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;
     
@@ -212,7 +213,7 @@ cs8900a_init(struct cyg_netdevtab_entry 
 #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
@@ -263,9 +264,17 @@ cs8900a_init(struct cyg_netdevtab_entry 
         // 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;
     }
@@ -278,11 +287,19 @@ cs8900a_init(struct cyg_netdevtab_entry 
 
     // 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));
+#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);
+#endif
     }
 # if DEBUG & 8
     diag_printf("ESA %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -419,8 +436,12 @@ cs8900a_send(struct eth_drv_sc *sc, stru
 #ifdef CYGPKG_KERNEL
     cpd->txstart = cyg_current_time();
 #endif
+
     // 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
@@ -451,20 +472,39 @@ cs8900a_send(struct eth_drv_sc *sc, stru
         if (len > 0) {
             /* Finish the last word. */
             if (odd_byte) {
+                // Add data to the most significant byte
+#if(CYG_BYTEORDER == CYG_LSBFIRST)                              
                 saved_data |= ((cyg_uint16)*data++) << 8;
+#elif(CYG_BYTEORDER == CYG_MSBFIRST)
+                saved_data = ((cyg_uint16)*data++) | (saved_data << 8);
+#endif
                 HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data);
                 len--;
                 odd_byte = false;
             }
-            /* Output contiguous words. */
-            sdata = (cyg_uint16 *)data;
-            while (len > 1) {
-                HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
-                len -= sizeof(cyg_uint16);
+            if ((CYG_ADDRESS)data & 0x1 == 0) {
+                /* Aligned on 16-bit boundary, so output contiguous words. */
+                sdata = (cyg_uint16 *)data;
+                while (len > 1) {
+                    HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++);
+                    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
+                    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);
+                    len -= sizeof(cyg_uint16);
+                }
             }
             /* Save last byte, if necessary. */
             if (len == 1) {
-                data = (cyg_uint8 *)sdata;
                 saved_data = (cyg_uint16)*data;
                 odd_byte = true;
             }
@@ -489,6 +529,11 @@ cs8900a_RxEvent(struct eth_drv_sc *sc)
 
     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);
@@ -522,9 +567,15 @@ cs8900a_recv(struct eth_drv_sc *sc, stru
             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);
+#endif
+            cval &= 0xff;
             if ((cp = (cyg_uint8 *)data) != 0) {
                 *cp = cval;
             }