Skip to content
Snippets Groups Projects
Unverified Commit 7a5895a0 authored by aluntzer's avatar aluntzer Committed by GitHub
Browse files

Merge pull request #4 from dloidolt/endianness_fix

add little-endian support
parents 1e7bed01 dd3c4058
No related branches found
No related tags found
No related merge requests found
/**
* @file byteorder.h
* @author Armin Luntzer (armin.luntzer@univie.ac.at),
* @date 2015
*
* @copyright GPLv2
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* This is a set of macros for consistent endianess conversion. They work
* for both little and big endian cpus.
*
* conversion of XX-bit integers (16- or 32-) between native CPU format
* and little/big endian format:
* cpu_to_[bl]eXX(uintXX_t x)
* [bl]eXX_to_cpu(uintXX_t x)
*
* the same, but change in situ:
* cpu_to_[bl]eXXs(uintXX_t x)
* [bl]eXX_to_cpus(uintXX_t x)
*
*
* This is based on the byte order macros from the linux kernel, see:
* include/linux/byteorder/generic.h
* include/uapi/linux/swab.h
* include/uapi/linux/byteorder/big_endian.h
* include/uapi/linux/byteorder/little_endian.h
* by @author Linus Torvalds et al.
*
*/
#ifndef BYTEORDER_H
#define BYTEORDER_H
#include <stdint.h>
#ifdef __BIG_ENDIAN
#undef __BIG_ENDIAN
#endif
#ifdef __LITTLE_ENDIAN
#undef __LITTLE_ENDIAN
#endif
#if (__sparc__)
#ifndef __BIG_ENDIAN
#define __BIG_ENDIAN 4321
#endif
#endif
#if (__i386__ || __x86_64__)
#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN 1234
#endif
#endif
#define ___constant_swab16(x) ((uint16_t)( \
(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
#define ___constant_swab32(x) ((uint32_t)( \
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
#ifdef USE_BUILTIN_BSWAP
#if GCC_VERSION >= 40400
#define __HAVE_BUILTIN_BSWAP32__
#endif
#if GCC_VERSION >= 40800
#define __HAVE_BUILTIN_BSWAP16__
#endif
#endif /* USE_BUILTIN_BSWAP */
static inline __attribute__((const)) uint16_t __fswab16(uint16_t val)
{
#ifdef __HAVE_BUILTIN_BSWAP16__
return __builtin_bswap16(val);
#else
return ___constant_swab16(val);
#endif
}
static inline __attribute__((const)) uint32_t __fswab32(uint32_t val)
{
#ifdef __HAVE_BUILTIN_BSWAP32__
return __builtin_bswap32(val);
#else
return ___constant_swab32(val);
#endif
}
/**
* @brief return a byteswapped 16-bit value
* @param x value to byteswap
*/
#define __swab16(x) \
(__builtin_constant_p((uint16_t)(x)) ? \
___constant_swab16(x) : \
__fswab16(x))
/**
* @brief return a byteswapped 32-bit value
* @param x a value to byteswap
*/
#define __swab32(x) \
(__builtin_constant_p((uint32_t)(x)) ? \
___constant_swab32(x) : \
__fswab32(x))
/**
* @brief return a byteswapped 16-bit value from a pointer
* @param p a pointer to a naturally-aligned 16-bit value
*/
static inline uint16_t __swab16p(const uint16_t *p)
{
return __swab16(*p);
}
/**
* @brief return a byteswapped 32-bit value from a pointer
* @param p a pointer to a naturally-aligned 32-bit value
*/
static inline uint32_t __swab32p(const uint32_t *p)
{
return __swab32(*p);
}
/**
* @brief byteswap a 16-bit value in-place
* @param p a pointer to a naturally-aligned 16-bit value
*/
static inline void __swab16s(uint16_t *p)
{
*p = __swab16p(p);
}
/**
* @brief byteswap a 32-bit value in-place
* @param p a pointer to a naturally-aligned 32-bit value
*/
static inline void __swab32s(uint32_t *p)
{
*p = __swab32p(p);
}
#ifdef __BIG_ENDIAN
#define __cpu_to_le16(x) ((uint16_t)__swab16((x)))
#define __cpu_to_le32(x) ((uint32_t)__swab32((x)))
#define __cpu_to_le16s(x) __swab16s((x))
#define __cpu_to_le32s(x) __swab32s((x))
#define __cpu_to_be16(x) ((uint16_t)(x))
#define __cpu_to_be32(x) ((uint32_t)(x))
#define __cpu_to_be16s(x) { (void)(x); }
#define __cpu_to_be32s(x) { (void)(x); }
#define __le16_to_cpu(x) __swab16((uint16_t)(x))
#define __le32_to_cpu(x) __swab32((uint32_t)(x))
#define __le16_to_cpus(x) __swab16s((x))
#define __le32_to_cpus(x) __swab32s((x))
#define __be16_to_cpu(x) ((uint16_t)(x))
#define __be32_to_cpu(x) ((uint32_t)(x))
#define __be16_to_cpus(x) { (void)(x); }
#define __be32_to_cpus(x) { (void)(x); }
#endif /* __BIG_ENDIAN */
#ifdef __LITTLE_ENDIAN
#define __cpu_to_le16(x) ((uint16_t)(x))
#define __cpu_to_le32(x) ((uint32_t)(x))
#define __cpu_to_le16s(x) { (void)(x); }
#define __cpu_to_le32s(x) { (void)(x); }
#define __cpu_to_be16(x) ((uint16_t)__swab16((x)))
#define __cpu_to_be32(x) ((uint32_t)__swab32((x)))
#define __cpu_to_be16s(x) __swab16s((x))
#define __cpu_to_be32s(x) __swab32s((x))
#define __le16_to_cpu(x) ((uint16_t)(x))
#define __le32_to_cpu(x) ((uint32_t)(x))
#define __le32_to_cpus(x) { (void)(x); }
#define __le16_to_cpus(x) { (void)(x); }
#define __be16_to_cpu(x) __swab16((uint16_t)(uint16_t)(x))
#define __be32_to_cpu(x) __swab32((uint32_t)(uint32_t)(x))
#define __be16_to_cpus(x) __swab16s((x))
#define __be32_to_cpus(x) __swab32s((x))
#endif /* __LITTLE_ENDIAN */
/** these are the conversion macros */
/** convert cpu order to little endian */
#define cpu_to_le16 __cpu_to_le16
#define cpu_to_le32 __cpu_to_le32
/** in-place convert cpu order to little endian */
#define cpu_to_le16s __cpu_to_le16s
#define cpu_to_le32s __cpu_to_le32s
/** convert cpu order to big endian */
#define cpu_to_be16 __cpu_to_be16
#define cpu_to_be32 __cpu_to_be32
/** in-place convert cpu order to big endian */
#define cpu_to_be16s __cpu_to_be16s
#define cpu_to_be32s __cpu_to_be32s
/* same, but in reverse */
/** convert little endian to cpu order*/
#define le16_to_cpu __le16_to_cpu
#define le32_to_cpu __le32_to_cpu
/** in-place convert little endian to cpu order*/
#define le16_to_cpus __le16_to_cpus
#define le32_to_cpus __le32_to_cpus
/** convert big endian to cpu order*/
#define be16_to_cpu __be16_to_cpu
#define be32_to_cpu __be32_to_cpu
/** in-place convert big endian to cpu order*/
#define be16_to_cpus __be16_to_cpus
#define be32_to_cpus __be32_to_cpus
#endif /* BYTEORDER_H */
......@@ -272,7 +272,9 @@ uint8_t rdcu_edac_get_scrub_info(void);
/* SRAM */
int rdcu_read_sram(void *buf, uint32_t addr, uint32_t size);
int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size);
int rdcu_write_sram_8(uint8_t *buf, uint32_t addr, uint32_t size);
int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size);
int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size);
void rdcu_ctrl_init(void);
......
......@@ -61,6 +61,7 @@
#include <stdlib.h>
#include <string.h>
#include <byteorder.h>
#include <rmap.h>
#include <rdcu_cmd.h>
#include <rdcu_ctrl.h>
......@@ -462,7 +463,7 @@ uint32_t rdcu_get_adc_logic_enabled(void)
}
/*
/**
* @brief get RDCU Interrupt status
* @see RDCU-FRS-FN-0632
*
......@@ -1453,7 +1454,7 @@ uint8_t rdcu_edac_get_scrub_info(void)
/**
* @brief read data from SRAM
* @brief read data from the local SRAM mirror
*
* @param buf the buffer to read to (if NULL, the required size is returned)
*
......@@ -1477,12 +1478,12 @@ int rdcu_read_sram(void *buf, uint32_t addr, uint32_t size)
if (buf)
memcpy(buf, &rdcu->sram[addr], size);
return size; /* lol */
return (int)size; /* lol */
}
/**
* @brief write data to SRAM
* @brief write arbitrary big-endian data to the local SRAM mirror
*
* @param buf the buffer to read from
*
......@@ -1509,7 +1510,117 @@ int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size)
if (buf)
memcpy(&rdcu->sram[addr], buf, size);
return size; /* lol */
return (int)size; /* lol */
}
/**
* @brief write uint8_t formatted data to the local SRAM mirror. (This function
* is endian-safe.)
*
* @param buf the buffer to read from
*
* @param addr an address within the RDCU SRAM
* @param size the number of bytes read
*
* @returns the number of bytes written, < 0 on error
*/
int rdcu_write_sram_8(uint8_t *buf, uint32_t addr, uint32_t size)
{
return rdcu_write_sram(buf, addr, size);
}
/**
* @brief write uint16_t formatted data to the local SRAM mirror. This function
* is endian-safe.
*
* @param buf the buffer to read from
*
* @param addr an address within the RDCU SRAM
* @param size the number of bytes read
*
* @returns the number of bytes written, < 0 on error
*/
int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size)
{
if (!buf)
return 0;
if (size & 0x1)
return -1;
if (addr > RDCU_SRAM_END)
return -1;
if (size > RDCU_SRAM_SIZE)
return -1;
if (addr + size > RDCU_SRAM_END)
return -1;
#if __BIG_ENDIAN
return rdcu_write_sram(buf, addr, size);
#else
{
uint32_t i;
for (i = 0; i < size/sizeof(uint16_t); i++) {
uint16_t *sram_buf = (uint16_t *)&rdcu->sram[addr];
sram_buf[i] = cpu_to_be16(buf[i]);
}
}
return (int)size; /* lol */
#endif /* __BIG_ENDIAN */
}
/**
* @brief write uint32_t formatted data to the local SRAM mirror. This function
* is endian-safe.
*
* @param buf the buffer to read from
*
* @param addr an address within the RDCU SRAM
* @param size the number of bytes read
*
* @returns the number of bytes written, < 0 on error
*/
int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size)
{
if (!buf)
return 0;
if (size & 0x3)
return -1;
if (addr > RDCU_SRAM_END)
return -1;
if (size > RDCU_SRAM_SIZE)
return -1;
if (addr + size > RDCU_SRAM_END)
return -1;
#if __BIG_ENDIAN
return rdcu_write_sram(buf, addr, size);
#else
{
uint32_t i;
for (i = 0; i < size/sizeof(uint32_t); i++) {
uint32_t *sram_buf = (uint32_t *)&rdcu->sram[addr];
sram_buf[i] = cpu_to_be32(buf[i]);
}
}
return (int)size; /* lol */
#endif /* __BIG_ENDIAN */
}
......@@ -2130,7 +2241,8 @@ int rdcu_sync_sram_to_mirror(uint32_t addr, uint32_t size, uint32_t mtu)
&rdcu->sram[addr + recv], mtu, 1);
#if 1
while (rdcu_rmap_sync_status() > 3);
while (rdcu_rmap_sync_status() > 3)
;
#endif
if (ret > 0)
......
......@@ -66,6 +66,7 @@
#include <stdlib.h>
#include <string.h>
#include <byteorder.h>
#include <rmap.h>
#include <rdcu_rmap.h>
......@@ -229,7 +230,7 @@ static int rdcu_process_rx(void)
int n;
int cnt = 0;
void *local_addr;
uint32_t *local_addr;
uint8_t *spw_pckt;
......@@ -250,6 +251,7 @@ static int rdcu_process_rx(void)
/* read the packet */
n = rmap_rx(spw_pckt);
if (!n) {
printf("Unknown error in rmap_rx()\n");
free(spw_pckt);
......@@ -279,8 +281,21 @@ static int rdcu_process_rx(void)
continue;
}
if (rp->data_len)
if (rp->data_len) {
memcpy(local_addr, rp->data, rp->data_len);
#if __LITTLE_ENDIAN
if (rp->data_len & 0x3)
printf("warning: length of response packet"
"received is not a multiple of 4 bytes\n");
{
uint32_t i;
for (i = 0; i < rp->data_len/4; i++)
be32_to_cpus(&local_addr[i]);
}
#endif /* __LITTLE_ENDIAN */
}
trans_log_release_slot(rp->tr_id);
rmap_erase_packet(rp);
......@@ -314,7 +329,7 @@ int rdcu_submit_tx(const uint8_t *cmd, int cmd_size,
printf("Transmitting RMAP command\n");
if (rmap_tx(cmd, cmd_size, dpath_len, data, data_size)) {
printf("rmap_tx() returned error!");
printf("rmap_tx() returned error!\n");
return -1;
}
......@@ -401,8 +416,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd),
int slot;
uint8_t *rmap_cmd;
uint8_t *data = addr;
slot = trans_log_grab_slot(addr);
if (slot < 0)
......@@ -426,8 +440,26 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd),
return -1;
}
n = rdcu_submit_tx(rmap_cmd, n, addr, data_len);
#if __LITTLE_ENDIAN
if (data_len & 0x3)
printf("warning: length of send packet is not a multiple of "
"4 bytes\n");
if (data_len) {
int i;
data = (uint8_t *) malloc(data_len);
for (i = 0; i < data_len/4; i++)
((uint32_t *)data)[i] =
cpu_to_be32(((uint32_t *)addr)[i]);
}
#endif /* __LITTLE_ENDIAN */
n = rdcu_submit_tx(rmap_cmd, n, data, data_len);
free(rmap_cmd);
#if __LITTLE_ENDIAN
free(data);
#endif /* __LITTLE_ENDIAN */
return n;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment