From 6347b1daf91c0943dde77f6caa037090d53763db Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 10 May 2013 16:22:16 -0400 Subject: [PATCH 1/9] add MMIO API From devLib2 adds calls to handle 8, 16, and 32 bit Memory Mapped I/O reads and writes. Adds X_iowriteY() and X_ioreadY(). where X is nat (native), be, or le. Y is 16 or 32. Also adds ioread8() and iowrite8(). --- src/libCom/osi/Makefile | 2 + src/libCom/osi/os/RTEMS/epicsMMIO.h | 58 +++++ src/libCom/osi/os/default/epicsMMIO.h | 2 + src/libCom/osi/os/default/epicsMMIODef.h | 268 +++++++++++++++++++++++ src/libCom/osi/os/vxWorks/epicsMMIO.h | 127 +++++++++++ 5 files changed, 457 insertions(+) create mode 100644 src/libCom/osi/os/RTEMS/epicsMMIO.h create mode 100644 src/libCom/osi/os/default/epicsMMIO.h create mode 100644 src/libCom/osi/os/default/epicsMMIODef.h create mode 100644 src/libCom/osi/os/vxWorks/epicsMMIO.h diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index 94fe92c61..d48716e05 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -61,6 +61,8 @@ INC += devLib.h INC += devLibVME.h INC += devLibVMEImpl.h INC += osdVME.h +INC += epicsMMIO.h +INC += epicsMMIODef.h Com_SRCS += epicsThread.cpp Com_SRCS += epicsMutex.cpp diff --git a/src/libCom/osi/os/RTEMS/epicsMMIO.h b/src/libCom/osi/os/RTEMS/epicsMMIO.h new file mode 100644 index 000000000..7625d54bf --- /dev/null +++ b/src/libCom/osi/os/RTEMS/epicsMMIO.h @@ -0,0 +1,58 @@ +/*************************************************************************\ +* Copyright (c) 2010 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* devLib2 is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author: Michael Davidsaver + */ + +#ifndef EPICSMMIO_H +#define EPICSMMIO_H + +#include + +#if defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) +# include + +/*NOTE: All READ/WRITE operations have an implicit read or write barrier */ + +# define ioread8(A) in_8((volatile epicsUInt8*)(A)) +# define iowrite8(A,D) out_8((volatile epicsUInt8*)(A), D) +# define le_ioread16(A) in_le16((volatile epicsUInt16*)(A)) +# define le_ioread32(A) in_le32((volatile epicsUInt32*)(A)) +# define le_iowrite16(A,D) out_le16((volatile epicsUInt16*)(A), D) +# define le_iowrite32(A,D) out_le32((volatile epicsUInt32*)(A), D) +# define be_ioread16(A) in_be16((volatile epicsUInt16*)(A)) +# define be_ioread32(A) in_be32((volatile epicsUInt32*)(A)) +# define be_iowrite16(A,D) out_be16((volatile epicsUInt16*)(A), D) +# define be_iowrite32(A,D) out_be32((volatile epicsUInt32*)(A), D) + +# define rbarr() iobarrier_r() +# define wbarr() iobarrier_w() +# define rwbarr() iobarrier_rw() + +/* Define native operations */ +# define nat_ioread16 be_ioread16 +# define nat_ioread32 be_ioread32 +# define nat_iowrite16 be_iowrite16 +# define nat_iowrite32 be_iowrite32 + +#elif defined(i386) ||defined(__i386__) || defined(__i386) + +/* X86 does not need special handling for read/write width. + * + * TODO: Memory barriers? + */ + +#include "epicsMMIODef.h" + +#else +# warning I/O operations not defined for this RTEMS architecture + +#include "epicsMMIODef.h" + +#endif /* if defined PPC */ + +#endif /* EPICSMMIO_H */ diff --git a/src/libCom/osi/os/default/epicsMMIO.h b/src/libCom/osi/os/default/epicsMMIO.h new file mode 100644 index 000000000..79040932a --- /dev/null +++ b/src/libCom/osi/os/default/epicsMMIO.h @@ -0,0 +1,2 @@ + +#include "epicsMMIODef.h" diff --git a/src/libCom/osi/os/default/epicsMMIODef.h b/src/libCom/osi/os/default/epicsMMIODef.h new file mode 100644 index 000000000..5345a9274 --- /dev/null +++ b/src/libCom/osi/os/default/epicsMMIODef.h @@ -0,0 +1,268 @@ +/*************************************************************************\ +* Copyright (c) 2010 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* devLib2 is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author: Michael Davidsaver + */ + +#ifndef EPICSMMIODEF_H +#define EPICSMMIODEF_H + +#include +#include +#include + +#ifdef __cplusplus +# ifndef INLINE +# define INLINE inline +# endif +#endif + +/** @ingroup mmio + *@{ + */ + +/** @brief Read a single byte. + */ +INLINE +epicsUInt8 +ioread8(volatile void* addr) +{ + return *(volatile epicsUInt8*)(addr); +} + +/** @brief Write a single byte. + */ +INLINE +void +iowrite8(volatile void* addr, epicsUInt8 val) +{ + *(volatile epicsUInt8*)(addr) = val; +} + +/** @brief Read two bytes in host order. + * Not byte swapping + */ +INLINE +epicsUInt16 +nat_ioread16(volatile void* addr) +{ + return *(volatile epicsUInt16*)(addr); +} + +/** @brief Write two byte in host order. + * Not byte swapping + */ +INLINE +void +nat_iowrite16(volatile void* addr, epicsUInt16 val) +{ + *(volatile epicsUInt16*)(addr) = val; +} + +/** @brief Read four bytes in host order. + * Not byte swapping + */ +INLINE +epicsUInt32 +nat_ioread32(volatile void* addr) +{ + return *(volatile epicsUInt32*)(addr); +} + +/** @brief Write four byte in host order. + * Not byte swapping + */ +INLINE +void +nat_iowrite32(volatile void* addr, epicsUInt32 val) +{ + *(volatile epicsUInt32*)(addr) = val; +} + +#if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG + +/** @ingroup mmio + *@{ + */ + +#define bswap16(value) ((epicsUInt16) ( \ + (((epicsUInt16)(value) & 0x00ff) << 8) | \ + (((epicsUInt16)(value) & 0xff00) >> 8))) + +#define bswap32(value) ( \ + (((epicsUInt32)(value) & 0x000000ff) << 24) | \ + (((epicsUInt32)(value) & 0x0000ff00) << 8) | \ + (((epicsUInt32)(value) & 0x00ff0000) >> 8) | \ + (((epicsUInt32)(value) & 0xff000000) >> 24)) + +# define be_ioread16(A) nat_ioread16(A) +# define be_ioread32(A) nat_ioread32(A) +# define be_iowrite16(A,D) nat_iowrite16(A,D) +# define be_iowrite32(A,D) nat_iowrite32(A,D) + +# define le_ioread16(A) bswap16(nat_ioread16(A)) +# define le_ioread32(A) bswap32(nat_ioread32(A)) +# define le_iowrite16(A,D) nat_iowrite16(A,bswap16(D)) +# define le_iowrite32(A,D) nat_iowrite32(A,bswap32(D)) + +/** @} */ + +#elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE + +#include +#ifdef __rtems__ + /* some rtems bsps (pc386) don't provide htonl correctly */ +# include +#endif + +/** @ingroup mmio + *@{ + */ + +/* hton* is optimized or a builtin for most compilers + * so use it if possible + */ +#define bswap16(v) htons(v) +#define bswap32(v) htonl(v) + +# define be_ioread16(A) bswap16(nat_ioread16(A)) +# define be_ioread32(A) bswap32(nat_ioread32(A)) +# define be_iowrite16(A,D) nat_iowrite16(A,bswap16(D)) +# define be_iowrite32(A,D) nat_iowrite32(A,bswap32(D)) + +# define le_ioread16(A) nat_ioread16(A) +# define le_ioread32(A) nat_ioread32(A) +# define le_iowrite16(A,D) nat_iowrite16(A,D) +# define le_iowrite32(A,D) nat_iowrite32(A,D) + +/** @} */ + +#else +# error Unable to determine native byte order +#endif + +/** @def bswap16 + * @brief Unconditional two byte swap + */ +/** @def bswap32 + * @brief Unconditional four byte swap + */ +/** @def be_ioread16 + * @brief Read two byte in big endian order. + */ +/** @def be_iowrite16 + * @brief Write two byte in big endian order. + */ +/** @def be_ioread32 + * @brief Read four byte in big endian order. + */ +/** @def be_iowrite32 + * @brief Write four byte in big endian order. + */ +/** @def le_ioread16 + * @brief Read two byte in little endian order. + */ +/** @def le_iowrite16 + * @brief Write two byte in little endian order. + */ +/** @def le_ioread32 + * @brief Read four byte in little endian order. + */ +/** @def le_iowrite32 + * @brief Write four byte in little endian order. + */ + +/** @ingroup mmio + *@{ + */ + +/** @brief Explicit read memory barrier + * Prevents reordering of reads around it. + */ +#define rbarr() do{}while(0) +/** @brief Explicit write memory barrier + * Prevents reordering of writes around it. + */ +#define wbarr() do{}while(0) +/** @brief Explicit read/write memory barrier + * Prevents reordering of reads or writes around it. + */ +#define rwbarr() do{}while(0) + +/** @} */ + +/** @defgroup mmio Memory Mapped I/O + * + * Safe operations on I/O memory. + * + *This files defines a set of macros for access to Memory Mapped I/O + * + *They are named T_ioread# and T_iowrite# where # can be 8, 16, or 32. + *'T' can either be 'le', 'be', or 'nat' (except ioread8 and + *iowrite8). + * + *The macros defined use OS specific extensions (when available) + *to ensure the following. + * + *@li Width. A 16 bit operation will not be broken into two 8 bit operations, + * or one half of a 32 bit operation. + * + *@li Order. Writes to two different registers will not be reordered. + * This only applies to MMIO operations, not between MMIO and + * normal memory operations. + * + *PCI access should use either 'le_' or 'be_' as determined by the + *device byte order. + * + *VME access should always use 'nat_'. If the device byte order is + *little endian then an explicit swap is required. + * + *@section mmioex Examples: + * + *@subsection mmioexbe Big endian device: + * + *@b PCI + * + @code + be_iowrite16(base+off, 14); + var = be_ioread16(base+off); + @endcode + * + *@b VME + * + @code + nat_iowrite16(base+off, 14); + var = nat_ioread16(base+off); + @endcode + * + *@subsection mmioexle Little endian device + * + *@b PCI + @code + le_iowrite16(base+off, 14); + var = le_ioread16(base+off); + @endcode + *@b VME + @code + nat_iowrite16(base+off, bswap16(14)); + var = bswap16(nat_iowrite16(base+off)); + @endcode + *This difference arises because VME bridges implement hardware byte + *swapping on little endian systems, while PCI bridges do not. + *Software accessing PCI devices must know if byte swapping is required. + *This conditional swap is implemented by the 'be_' and 'le_' macros. + * + *This is a fundamental difference between PCI and VME. + * + *Software accessing PCI @b must do conditional swapping. + * + *Software accessing VME must @b not do conditional swapping. + * + *@note All read and write operations have an implicit read or write barrier. + */ + +#endif /* EPICSMMIODEF_H */ diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h new file mode 100644 index 000000000..180cfec65 --- /dev/null +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -0,0 +1,127 @@ +/*************************************************************************\ +* Copyright (c) 2010 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* Copyright (c) 2006 The University of Chicago, +* as Operator of Argonne National Laboratory. +* Copyright (c) 2006 The Regents of the University of California, +* as Operator of Los Alamos National Laboratory. +* Copyright (c) 2006 The Board of Trustees of the Leland Stanford Junior +* University, as Operator of the Stanford Linear Accelerator Center. +* devLib2 is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Original Author: Eric Bjorklund (was called mrfSyncIO.h) + * Author: Michael Davidsaver + */ + +#ifndef EPICSMMIO_H +#define EPICSMMIO_H + +/**************************************************************************************************/ +/* Required Header Files */ +/**************************************************************************************************/ + +/* This is needed on vxWorks 6.8 */ +#ifndef _VSB_CONFIG_FILE +# define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h> +#endif + +#include /* vxWorks common definitions */ +#include /* vxWorks System Library Definitions */ +#include /* vxWorks Version Definitions */ + +#include /* EPICS Common Type Definitions */ +#include /* EPICS Byte Order Definitions */ + +/*===================== + * vxAtomicLib.h (which defines the memory barrier macros) + * is available on vxWorks 6.6 and above. + */ + +#if _WRS_VXWORKS_MAJOR > 6 +# include +#elif _WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR >= 6 +# include +#endif + +/**************************************************************************************************/ +/* Function Prototypes for Routines Not Defined in sysLib.h */ +/**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +epicsUInt16 sysIn16 (volatile void*); /* Synchronous 16 bit read */ +epicsUInt32 sysIn32 (volatile void*); /* Synchronous 32 bit read */ +void sysOut16 (volatile void*, epicsUInt16); /* Synchronous 16 bit write */ +void sysOut32 (volatile void*, epicsUInt32); /* Synchronous 32 bit write */ + + +#ifdef __cplusplus +} +#endif + +#define bswap16(value) ((epicsUInt16) ( \ + (((epicsUInt16)(value) & 0x00ff) << 8) | \ + (((epicsUInt16)(value) & 0xff00) >> 8))) + +#define bswap32(value) ( \ + (((epicsUInt32)(value) & 0x000000ff) << 24) | \ + (((epicsUInt32)(value) & 0x0000ff00) << 8) | \ + (((epicsUInt32)(value) & 0x00ff0000) >> 8) | \ + (((epicsUInt32)(value) & 0xff000000) >> 24)) + +#if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG +# define be16_to_cpu(X) (X) +# define be32_to_cpu(X) (X) +# define le16_to_cpu(X) bswap16(X) +# define le32_to_cpu(X) bswap32(X) + +#elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE +# define be16_to_cpu(X) bswap16(X) +# define be32_to_cpu(X) bswap32(X) +# define le16_to_cpu(X) (X) +# define le32_to_cpu(X) (X) + +#else +# error Unable to determine native byte order +#endif + +#define ioread8(address) sysInByte ((epicsUInt32)(address)) +#define iowrite8(address,data) sysOutByte ((epicsUInt32)(address), (epicsUInt8)(data)) + +#define nat_ioread16(address) sysIn16 ((address)) +#define nat_ioread32(address) sysIn32 ((address)) + +#define nat_iowrite16(address,data) sysOut16(address,data) +#define nat_iowrite32(address,data) sysOut32(address,data) + +#define be_ioread16(address) be16_to_cpu (sysIn16 ((address))) +#define be_ioread32(address) be32_to_cpu (sysIn32 ((address))) + +#define be_iowrite16(address,data) sysOut16 ((address), be16_to_cpu((epicsUInt16)(data))) +#define be_iowrite32(address,data) sysOut32 ((address), be32_to_cpu((epicsUInt32)(data))) + +#define le_ioread16(address) le16_to_cpu (sysIn16 ((address))) +#define le_ioread32(address) le32_to_cpu (sysIn32 ((address))) + +#define le_iowrite16(address,data) sysOut16 ((address), le16_to_cpu((epicsUInt16)(data))) +#define le_iowrite32(address,data) sysOut32 ((address), le32_to_cpu((epicsUInt32)(data))) + +#ifndef VX_MEM_BARRIER_R +# define VX_MEM_BARRIER_R() do{}while(0) +#endif +#ifndef VX_MEM_BARRIER_W +# define VX_MEM_BARRIER_W() do{}while(0) +#endif +#ifndef VX_MEM_BARRIER_RW +# define VX_MEM_BARRIER_RW() do{}while(0) +#endif + +#define rbarr() VX_MEM_BARRIER_R() +#define wbarr() VX_MEM_BARRIER_W() +#define rwbarr() VX_MEM_BARRIER_RW() + +#endif /* EPICSMMIO_H */ From 01041abd327d6bc324b3c3394f196fb49c2ace46 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 23 Aug 2013 18:14:56 -0400 Subject: [PATCH 2/9] rtems: mmio for m68k --- src/libCom/osi/os/RTEMS/epicsMMIO.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libCom/osi/os/RTEMS/epicsMMIO.h b/src/libCom/osi/os/RTEMS/epicsMMIO.h index 7625d54bf..e25c8facf 100644 --- a/src/libCom/osi/os/RTEMS/epicsMMIO.h +++ b/src/libCom/osi/os/RTEMS/epicsMMIO.h @@ -39,7 +39,7 @@ # define nat_iowrite16 be_iowrite16 # define nat_iowrite32 be_iowrite32 -#elif defined(i386) ||defined(__i386__) || defined(__i386) +#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(__m68k__) /* X86 does not need special handling for read/write width. * From 7adb9c38815a32a8b4179e6c195ca8eed878bd39 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Nov 2013 15:29:10 -0500 Subject: [PATCH 3/9] update release notes --- documentation/RELEASE_NOTES.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 441425505..db72bf54a 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -15,6 +15,13 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.

Changes between 3.15.0.1 and 3.15.0.2

+

merge MMIO API from devLib2

+ +

adds calls to handle 8, 16, and 32 bit Memory Mapped I/O reads and writes. +The calls added include X_iowriteY() and X_ioreadY(). +Where X is nat (native), be, or le, and Y is 16 or 32. +Also added are ioread8() and iowrite8().

+

New build target tapfiles

This new make target runs the same tests as the runtests target, but From d24ed309e99d6db5a0192ce4137d8480df04539b Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Nov 2013 15:31:59 -0500 Subject: [PATCH 4/9] fix copyright header --- src/libCom/osi/os/RTEMS/epicsMMIO.h | 2 +- src/libCom/osi/os/default/epicsMMIODef.h | 2 +- src/libCom/osi/os/vxWorks/epicsMMIO.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libCom/osi/os/RTEMS/epicsMMIO.h b/src/libCom/osi/os/RTEMS/epicsMMIO.h index e25c8facf..7db66704f 100644 --- a/src/libCom/osi/os/RTEMS/epicsMMIO.h +++ b/src/libCom/osi/os/RTEMS/epicsMMIO.h @@ -1,7 +1,7 @@ /*************************************************************************\ * Copyright (c) 2010 Brookhaven Science Associates, as Operator of * Brookhaven National Laboratory. -* devLib2 is distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* diff --git a/src/libCom/osi/os/default/epicsMMIODef.h b/src/libCom/osi/os/default/epicsMMIODef.h index 5345a9274..77a57d215 100644 --- a/src/libCom/osi/os/default/epicsMMIODef.h +++ b/src/libCom/osi/os/default/epicsMMIODef.h @@ -1,7 +1,7 @@ /*************************************************************************\ * Copyright (c) 2010 Brookhaven Science Associates, as Operator of * Brookhaven National Laboratory. -* devLib2 is distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h index 180cfec65..7141bf777 100644 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.h +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -7,7 +7,7 @@ * as Operator of Los Alamos National Laboratory. * Copyright (c) 2006 The Board of Trustees of the Leland Stanford Junior * University, as Operator of the Stanford Linear Accelerator Center. -* devLib2 is distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* From 841d66993a7127bf50f55895d399c0c053fae6e6 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 30 Nov 2013 16:40:07 -0500 Subject: [PATCH 5/9] test epicsMMIO.h Check byte order swapping. --- src/libCom/test/Makefile | 5 ++ src/libCom/test/epicsMMIOTest.c | 87 +++++++++++++++++++++++++++ src/libCom/test/epicsRunLibComTests.c | 3 + 3 files changed, 95 insertions(+) create mode 100644 src/libCom/test/epicsMMIOTest.c diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index bef859a8f..01f078088 100755 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -37,6 +37,11 @@ epicsMathTest_SRCS += epicsMathTest.c testHarness_SRCS += epicsMathTest.c TESTS += epicsMathTest +TESTPROD_HOST += epicsMMIOTest +epicsMMIOTest_SRCS += epicsMMIOTest.c +testHarness_SRCS += epicsMMIOTest.c +TESTS += epicsMMIOTest + TESTPROD_HOST += epicsEllTest epicsEllTest_SRCS += epicsEllTest.c testHarness_SRCS += epicsEllTest.c diff --git a/src/libCom/test/epicsMMIOTest.c b/src/libCom/test/epicsMMIOTest.c new file mode 100644 index 000000000..0bf13fbd2 --- /dev/null +++ b/src/libCom/test/epicsMMIOTest.c @@ -0,0 +1,87 @@ +/*************************************************************************\ +* Copyright (c) 2013 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author: Michael Davidsaver + */ + +#include "epicsAssert.h" +#include "epicsEndian.h" +#include "epicsTypes.h" +#include "epicsUnitTest.h" +#include "testMain.h" + +#include "epicsMMIO.h" + +#if EPICS_BYTE_ORDER==EPICS_ENDIAN_BIG +#define BE16 0x1234 +#define BE32 0x12345678 +#define LE16 0x3412 +#define LE32 0x78563412 +#else +#define LE16 0x1234 +#define LE32 0x12345678 +#define BE16 0x3412 +#define BE32 0x78563412 +#endif + +union hydra16 { + epicsUInt16 u16; + epicsUInt8 bytes[2]; +}; + +union hydra32 { + epicsUInt32 u32; + epicsUInt8 bytes[4]; +}; + +MAIN(epicsMMIOTest) +{ + epicsUInt8 B; + union hydra16 H16; + union hydra32 H32; + + STATIC_ASSERT(sizeof(H16)==2); + STATIC_ASSERT(sizeof(H32)==4); + + testPlan(0); + + testDiag("8-bit ops"); + + iowrite8(&B, 5); + testOk1(B==5); + testOk1(ioread8(&B)==5); + + testDiag("16-bit ops"); + + nat_iowrite16(&H16.bytes, 0x1234); + testOk1(H16.u16==0x1234); + testOk1(nat_ioread16(&H16.bytes)==0x1234); + + be_iowrite16(&H16.bytes, 0x1234); + testOk1(H16.u16==BE16); + testOk1(be_ioread16(&H16.bytes)==0x1234); + + le_iowrite16(&H16.bytes, 0x1234); + testOk1(H16.u16==LE16); + testOk1(le_ioread16(&H16.bytes)==0x1234); + + testDiag("32-bit ops"); + + nat_iowrite32(&H32.bytes, 0x12345678); + testOk1(H32.u32==0x12345678); + testOk1(nat_ioread32(&H32.bytes)==0x12345678); + + be_iowrite32(&H32.bytes, 0x12345678); + testOk1(H32.u32==BE32); + testOk1(be_ioread32(&H32.bytes)==0x12345678); + + le_iowrite32(&H32.bytes, 0x12345678); + testOk1(H32.u32==LE32); + testOk1(le_ioread32(&H32.bytes)==0x12345678); + + return testDone(); +} diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index c80f0244c..26adf814d 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -18,6 +18,7 @@ int epicsThreadTest(void); int epicsTimerTest(void); +int epicsMMIOTest(void); int epicsAlgorithm(void); int epicsEllTest(void); int epicsErrlogTest(void); @@ -59,6 +60,8 @@ void epicsRunLibComTests(void) */ runTest(epicsTimerTest); + runTest(epicsMMIOTest); + runTest(epicsAlgorithm); runTest(epicsEllTest); From 0bf17be9e33050324b510f047536ff12fc886514 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 16 Jul 2014 15:12:56 -0400 Subject: [PATCH 6/9] mmio: vxWorks m68k use default, add weak symbols for old versions --- src/libCom/osi/Makefile | 2 ++ src/libCom/osi/os/vxWorks/epicsMMIO.c | 40 +++++++++++++++++++++++++++ src/libCom/osi/os/vxWorks/epicsMMIO.h | 5 ++++ 3 files changed, 47 insertions(+) create mode 100644 src/libCom/osi/os/vxWorks/epicsMMIO.c diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index d48716e05..7794601e3 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -120,6 +120,8 @@ Com_SRCS += osdMessageQueue.c Com_SRCS += devLibVME.c Com_SRCS += devLibVMEOSD.c +Com_SRCS_vxWorks += epicsMMIO.c + Com_SRCS_vxWorks += atReboot.cpp # For old vxWorks applications diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.c b/src/libCom/osi/os/vxWorks/epicsMMIO.c new file mode 100644 index 000000000..947d7bc46 --- /dev/null +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.c @@ -0,0 +1,40 @@ +/*************************************************************************\ +* Copyright (c) 2014 Brookhaven Science Associates, as Operator of +* Brookhaven National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author: Michael Davidsaver + */ + +#ifndef __m68k__ + +#include "epicsMMIODef.h" + +epicsUInt16 sysIn16 (volatile void*) __attribute__((weak)); +epicsUInt32 sysIn32 (volatile void*) __attribute__((weak)); +void sysOut16 (volatile void*, epicsUInt16) __attribute__((weak)); +void sysOut32 (volatile void*, epicsUInt32) __attribute__((weak)); + +epicsUInt16 sysIn16 (volatile void* addr) +{ + return nat_read16(addr); +} + +epicsUInt32 sysIn32 (volatile void* addr) +{ + return nat_read32(addr); +} + +void sysOut16 (volatile void* addr, epicsUInt16 val) +{ + nat_write16(addr, val); +} + +void sysOut32 (volatile void* addr, epicsUInt32 val) +{ + nat_write32(addr, val); +} + +#endif /* m68k */ diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h index 7141bf777..6b391da3a 100644 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.h +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -15,6 +15,10 @@ * Author: Michael Davidsaver */ +#ifdef __m68k__ +#include "epicsMMIODef.h" +#else + #ifndef EPICSMMIO_H #define EPICSMMIO_H @@ -125,3 +129,4 @@ void sysOut32 (volatile void*, epicsUInt32); /* Synchronous 32 bit w #define rwbarr() VX_MEM_BARRIER_RW() #endif /* EPICSMMIO_H */ +#endif /* m68k */ From b5fe4abfa8f18761a14b5b5fd2abb85e7b911ae7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 25 Jul 2014 11:15:27 -0400 Subject: [PATCH 7/9] switch to use sysInWord and friends --- src/libCom/osi/Makefile | 2 -- src/libCom/osi/os/vxWorks/epicsMMIO.c | 40 --------------------------- src/libCom/osi/os/vxWorks/epicsMMIO.h | 32 ++++++++++----------- 3 files changed, 16 insertions(+), 58 deletions(-) delete mode 100644 src/libCom/osi/os/vxWorks/epicsMMIO.c diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index 7794601e3..d48716e05 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -120,8 +120,6 @@ Com_SRCS += osdMessageQueue.c Com_SRCS += devLibVME.c Com_SRCS += devLibVMEOSD.c -Com_SRCS_vxWorks += epicsMMIO.c - Com_SRCS_vxWorks += atReboot.cpp # For old vxWorks applications diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.c b/src/libCom/osi/os/vxWorks/epicsMMIO.c deleted file mode 100644 index 947d7bc46..000000000 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.c +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2014 Brookhaven Science Associates, as Operator of -* Brookhaven National Laboratory. -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * Author: Michael Davidsaver - */ - -#ifndef __m68k__ - -#include "epicsMMIODef.h" - -epicsUInt16 sysIn16 (volatile void*) __attribute__((weak)); -epicsUInt32 sysIn32 (volatile void*) __attribute__((weak)); -void sysOut16 (volatile void*, epicsUInt16) __attribute__((weak)); -void sysOut32 (volatile void*, epicsUInt32) __attribute__((weak)); - -epicsUInt16 sysIn16 (volatile void* addr) -{ - return nat_read16(addr); -} - -epicsUInt32 sysIn32 (volatile void* addr) -{ - return nat_read32(addr); -} - -void sysOut16 (volatile void* addr, epicsUInt16 val) -{ - nat_write16(addr, val); -} - -void sysOut32 (volatile void* addr, epicsUInt32 val) -{ - nat_write32(addr, val); -} - -#endif /* m68k */ diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h index 6b391da3a..2c14c983c 100644 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.h +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -57,10 +57,10 @@ extern "C" { #endif -epicsUInt16 sysIn16 (volatile void*); /* Synchronous 16 bit read */ -epicsUInt32 sysIn32 (volatile void*); /* Synchronous 32 bit read */ -void sysOut16 (volatile void*, epicsUInt16); /* Synchronous 16 bit write */ -void sysOut32 (volatile void*, epicsUInt32); /* Synchronous 32 bit write */ +epicsUInt16 sysInWord (volatile void*); /* Synchronous 16 bit read */ +epicsUInt32 sysInLong (volatile void*); /* Synchronous 32 bit read */ +void sysOutWord (volatile void*, epicsUInt16); /* Synchronous 16 bit write */ +void sysOutLong (volatile void*, epicsUInt32); /* Synchronous 32 bit write */ #ifdef __cplusplus @@ -96,23 +96,23 @@ void sysOut32 (volatile void*, epicsUInt32); /* Synchronous 32 bit w #define ioread8(address) sysInByte ((epicsUInt32)(address)) #define iowrite8(address,data) sysOutByte ((epicsUInt32)(address), (epicsUInt8)(data)) -#define nat_ioread16(address) sysIn16 ((address)) -#define nat_ioread32(address) sysIn32 ((address)) +#define nat_ioread16(address) sysInWord ((address)) +#define nat_ioread32(address) sysInLong ((address)) -#define nat_iowrite16(address,data) sysOut16(address,data) -#define nat_iowrite32(address,data) sysOut32(address,data) +#define nat_iowrite16(address,data) sysOutWord(address,data) +#define nat_iowrite32(address,data) sysOutLong(address,data) -#define be_ioread16(address) be16_to_cpu (sysIn16 ((address))) -#define be_ioread32(address) be32_to_cpu (sysIn32 ((address))) +#define be_ioread16(address) be16_to_cpu (sysInWord ((address))) +#define be_ioread32(address) be32_to_cpu (sysInLong ((address))) -#define be_iowrite16(address,data) sysOut16 ((address), be16_to_cpu((epicsUInt16)(data))) -#define be_iowrite32(address,data) sysOut32 ((address), be32_to_cpu((epicsUInt32)(data))) +#define be_iowrite16(address,data) sysOutWord ((address), be16_to_cpu((epicsUInt16)(data))) +#define be_iowrite32(address,data) sysOutLong ((address), be32_to_cpu((epicsUInt32)(data))) -#define le_ioread16(address) le16_to_cpu (sysIn16 ((address))) -#define le_ioread32(address) le32_to_cpu (sysIn32 ((address))) +#define le_ioread16(address) le16_to_cpu (sysInWord ((address))) +#define le_ioread32(address) le32_to_cpu (sysInLong ((address))) -#define le_iowrite16(address,data) sysOut16 ((address), le16_to_cpu((epicsUInt16)(data))) -#define le_iowrite32(address,data) sysOut32 ((address), le32_to_cpu((epicsUInt32)(data))) +#define le_iowrite16(address,data) sysOutWord ((address), le16_to_cpu((epicsUInt16)(data))) +#define le_iowrite32(address,data) sysOutLong ((address), le32_to_cpu((epicsUInt32)(data))) #ifndef VX_MEM_BARRIER_R # define VX_MEM_BARRIER_R() do{}while(0) From fcd0a4c75d4c5b8ad987869625fa547c557852dd Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 31 Jul 2014 15:43:35 -0500 Subject: [PATCH 8/9] Fixes for VxWorks implementation. --- src/libCom/osi/os/vxWorks/epicsMMIO.h | 58 +++++++++------------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h index 2c14c983c..5eb245e06 100644 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.h +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -1,8 +1,8 @@ /*************************************************************************\ -* Copyright (c) 2010 Brookhaven Science Associates, as Operator of +* Copyright (c) 2014 Brookhaven Science Associates, as Operator of * Brookhaven National Laboratory. -* Copyright (c) 2006 The University of Chicago, -* as Operator of Argonne National Laboratory. +* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. * Copyright (c) 2006 The Regents of the University of California, * as Operator of Los Alamos National Laboratory. * Copyright (c) 2006 The Board of Trustees of the Leland Stanford Junior @@ -15,13 +15,13 @@ * Author: Michael Davidsaver */ -#ifdef __m68k__ -#include "epicsMMIODef.h" -#else - #ifndef EPICSMMIO_H #define EPICSMMIO_H +#if CPU_FAMILY == MC680X0 +# include "epicsMMIODef.h" +#else + /**************************************************************************************************/ /* Required Header Files */ /**************************************************************************************************/ @@ -49,24 +49,6 @@ # include #endif -/**************************************************************************************************/ -/* Function Prototypes for Routines Not Defined in sysLib.h */ -/**************************************************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -epicsUInt16 sysInWord (volatile void*); /* Synchronous 16 bit read */ -epicsUInt32 sysInLong (volatile void*); /* Synchronous 32 bit read */ -void sysOutWord (volatile void*, epicsUInt16); /* Synchronous 16 bit write */ -void sysOutLong (volatile void*, epicsUInt32); /* Synchronous 32 bit write */ - - -#ifdef __cplusplus -} -#endif - #define bswap16(value) ((epicsUInt16) ( \ (((epicsUInt16)(value) & 0x00ff) << 8) | \ (((epicsUInt16)(value) & 0xff00) >> 8))) @@ -96,23 +78,23 @@ void sysOutLong (volatile void*, epicsUInt32); /* Synchronous 32 bit #define ioread8(address) sysInByte ((epicsUInt32)(address)) #define iowrite8(address,data) sysOutByte ((epicsUInt32)(address), (epicsUInt8)(data)) -#define nat_ioread16(address) sysInWord ((address)) -#define nat_ioread32(address) sysInLong ((address)) +#define nat_ioread16(address) sysInWord ((epicsUInt32)(address)) +#define nat_ioread32(address) sysInLong ((epicsUInt32)(address)) -#define nat_iowrite16(address,data) sysOutWord(address,data) -#define nat_iowrite32(address,data) sysOutLong(address,data) +#define nat_iowrite16(address,data) sysOutWord((epicsUInt32)(address),(data)) +#define nat_iowrite32(address,data) sysOutLong((epicsUInt32)(address),(data)) -#define be_ioread16(address) be16_to_cpu (sysInWord ((address))) -#define be_ioread32(address) be32_to_cpu (sysInLong ((address))) +#define be_ioread16(address) be16_to_cpu (sysInWord ((epicsUInt32)(address))) +#define be_ioread32(address) be32_to_cpu (sysInLong ((epicsUInt32)(address))) -#define be_iowrite16(address,data) sysOutWord ((address), be16_to_cpu((epicsUInt16)(data))) -#define be_iowrite32(address,data) sysOutLong ((address), be32_to_cpu((epicsUInt32)(data))) +#define be_iowrite16(address,data) sysOutWord ((epicsUInt32)(address), be16_to_cpu((epicsUInt16)(data))) +#define be_iowrite32(address,data) sysOutLong ((epicsUInt32)(address), be32_to_cpu((epicsUInt32)(data))) -#define le_ioread16(address) le16_to_cpu (sysInWord ((address))) -#define le_ioread32(address) le32_to_cpu (sysInLong ((address))) +#define le_ioread16(address) le16_to_cpu (sysInWord ((epicsUInt32)(address))) +#define le_ioread32(address) le32_to_cpu (sysInLong ((epicsUInt32)(address))) -#define le_iowrite16(address,data) sysOutWord ((address), le16_to_cpu((epicsUInt16)(data))) -#define le_iowrite32(address,data) sysOutLong ((address), le32_to_cpu((epicsUInt32)(data))) +#define le_iowrite16(address,data) sysOutWord ((epicsUInt32)(address), le16_to_cpu((epicsUInt16)(data))) +#define le_iowrite32(address,data) sysOutLong ((epicsUInt32)(address), le32_to_cpu((epicsUInt32)(data))) #ifndef VX_MEM_BARRIER_R # define VX_MEM_BARRIER_R() do{}while(0) @@ -128,5 +110,5 @@ void sysOutLong (volatile void*, epicsUInt32); /* Synchronous 32 bit #define wbarr() VX_MEM_BARRIER_W() #define rwbarr() VX_MEM_BARRIER_RW() +#endif /* !MC680X0 */ #endif /* EPICSMMIO_H */ -#endif /* m68k */ From 59a0fa93644faddebfc6d615675f2bed3f628510 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 1 Aug 2014 16:06:17 -0500 Subject: [PATCH 9/9] Fix vxWorks again, passes the tests on all my CPUs now. --- src/libCom/osi/os/vxWorks/epicsMMIO.h | 62 +++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/src/libCom/osi/os/vxWorks/epicsMMIO.h b/src/libCom/osi/os/vxWorks/epicsMMIO.h index 5eb245e06..06301fdbe 100644 --- a/src/libCom/osi/os/vxWorks/epicsMMIO.h +++ b/src/libCom/osi/os/vxWorks/epicsMMIO.h @@ -18,7 +18,7 @@ #ifndef EPICSMMIO_H #define EPICSMMIO_H -#if CPU_FAMILY == MC680X0 +#if (CPU_FAMILY != PPC) && (CPU_FAMILY != I80X86) # include "epicsMMIODef.h" #else @@ -60,21 +60,64 @@ (((epicsUInt32)(value) & 0xff000000) >> 24)) #if EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG -# define be16_to_cpu(X) (X) -# define be32_to_cpu(X) (X) +# define be16_to_cpu(X) (epicsUInt16)(X) +# define be32_to_cpu(X) (epicsUInt32)(X) # define le16_to_cpu(X) bswap16(X) # define le32_to_cpu(X) bswap32(X) #elif EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE -# define be16_to_cpu(X) bswap16(X) -# define be32_to_cpu(X) bswap32(X) -# define le16_to_cpu(X) (X) -# define le32_to_cpu(X) (X) +# define be16_to_cpu(X) bswap16(X) +# define be32_to_cpu(X) bswap32(X) +# define le16_to_cpu(X) (epicsUInt16)(X) +# define le32_to_cpu(X) (epicsUInt32)(X) #else # error Unable to determine native byte order #endif +#if CPU_FAMILY == PPC + +/* All PowerPC BSPs that I have studied implement these functions + * with the same definition, byte-swapping the data and adding a + * sync and/or eieio instruction as necessary on that CPU board. + * They do *not* all implement the sys{In/Out}{Byte/Word/Long} + * functions to do the same thing though, so we can't use them. + */ + +UINT8 sysPciInByte(UINT8 *addr); +void sysPciOutByte(UINT8 *addr, UINT8 data); +UINT16 sysPciInWord(UINT16 *addr); +void sysPciOutWord(UINT16 *addr, UINT16 data); +UINT32 sysPciInLong (UINT32 *addr); +void sysPciOutLong (UINT32 *addr, UINT32 data); + +#define ioread8(address) sysPciInByte((UINT8 *)(address)) +#define iowrite8(address,data) sysPciOutByte((UINT8 *)(address), (epicsUInt8)(data)) + +#define nat_ioread16(address) bswap16(sysPciInWord((UINT16 *)(address))) +#define nat_ioread32(address) bswap32(sysPciInLong((UINT32 *)(address))) + +#define nat_iowrite16(address,data) sysPciOutWord((UINT16 *)(address), bswap16(data)) +#define nat_iowrite32(address,data) sysPciOutLong((UINT32 *)(address), bswap32(data)) + +#define be_ioread16(address) bswap16(sysPciInWord((UINT16 *)(address))) +#define be_ioread32(address) bswap32(sysPciInLong((UINT32 *)(address))) + +#define be_iowrite16(address,data) sysPciOutWord((UINT16 *)(address), bswap16(data)) +#define be_iowrite32(address,data) sysPciOutLong((UINT32 *)(address), bswap32(data)) + +#define le_ioread16(address) sysPciInWord((UINT16 *)(address)) +#define le_ioread32(address) sysPciInLong((UINT32 *)(address)) + +#define le_iowrite16(address,data) sysPciOutWord((UINT16 *)(address), (data)) +#define le_iowrite32(address,data) sysPciOutLong((UINT32 *)(address), (data)) + +#else /* CPU_FAMILY == I80X86 */ + +/* All Intel BSPs should implement the sys{In/Out}{Byte/Word/Long} + * functions, which are declared in the sysLib.h header. + */ + #define ioread8(address) sysInByte ((epicsUInt32)(address)) #define iowrite8(address,data) sysOutByte ((epicsUInt32)(address), (epicsUInt8)(data)) @@ -96,6 +139,9 @@ #define le_iowrite16(address,data) sysOutWord ((epicsUInt32)(address), le16_to_cpu((epicsUInt16)(data))) #define le_iowrite32(address,data) sysOutLong ((epicsUInt32)(address), le32_to_cpu((epicsUInt32)(data))) +#endif /* I80X86 */ + + #ifndef VX_MEM_BARRIER_R # define VX_MEM_BARRIER_R() do{}while(0) #endif @@ -110,5 +156,5 @@ #define wbarr() VX_MEM_BARRIER_W() #define rwbarr() VX_MEM_BARRIER_RW() -#endif /* !MC680X0 */ +#endif /* CPU_FAMILY */ #endif /* EPICSMMIO_H */