Mercurial > ecos
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; }
