Mercurial > ecos
diff packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c @ 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 | ae8511176102 |
| children | 9c818dd5d9fa |
line wrap: on
line diff
--- 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; }
