diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index 6c0e11e0d..9ccdf2804 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -142,9 +142,10 @@ BUILDLIB_SUFFIX = $(BUILDLIB_SUFFIX_$(SHARED_LIBRARIES)) #-------------------------------------------------- # vpath directories POSIX_YES = os/posix +OS_IMPL_DIRS = $(if $(OS_API),os/$(OS_CLASS)-$(OS_API),) os/$(OS_CLASS) GENERIC_SRC_DIRS = .. $(SRC_DIRS) OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ - $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default )) + $(addprefix $(dir)/, $(OS_IMPL_DIRS) $(POSIX_$(POSIX)) os/default )) CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default )) ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS) @@ -306,7 +307,7 @@ LDLIBS = $(POSIX_LDLIBS) $(ARCH_DEP_LDLIBS) $(DEBUG_LDLIBS) $(OP_SYS_LDLIBS)\ CPPFLAGS = $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\ $(DEBUG_CPPFLAGS) $(WARN_CPPFLAGS) $(BASE_CPPFLAGS) $(TARGET_CPPFLAGS)\ $(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\ - $(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS) $(API_CPPFLAGS) + $(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS) #-------------------------------------------------- # ar definition default diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index 7a2a616a2..86a037295 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -33,7 +33,7 @@ RTEMS_BSP ?= $(subst RTEMS-,,$(T_A)) #------------------------------------------------------- # Pick up the RTEMS tool/path definitions from the RTEMS BSP directory. -include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc +include $(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc include $(RTEMS_CUSTOM) include $(CONFIG.CC) @@ -94,16 +94,46 @@ MODEXT=.obj # operating system class (include/os/) OS_CLASS = RTEMS +#-------------------------------------------------- +#print warning +ifeq ($(RTEMS_HAS_POSIX_API),no) +ifeq ($(EPICS_VERSION),7) + $(error Warning: Epics Version $(EPICS_VERSION) must not be used without POSIX enabled on RTEMS !!!) +endif +endif +# operating system API (src/os/-) +ifeq ($(RTEMS_HAS_POSIX_API),yes) +OS_API = posix +else +OS_API = kernel +endif + #-------------------------------------------------- # Operating system flags -OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -lCom -lnfs -lm -OP_SYS_LDFLAGS += $(CPU_CFLAGS) -u Init \ +#OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -lCom -lnfs -lm +ifeq ($(RTEMS_API),5) +OP_SYS_CFLAGS += -D__LINUX_ERRNO_EXTENSIONS__ +#OP_SYS_LDLIBS += -lrtemsCom -lrtemscpu -lrtemsbsp -ltftpfs -ltelnetd -lbsd -lz -lm +OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -ltftpfs -lbsd -lz -lm +else +OP_SYS_LDLIBS += -lrtemsCom -lrtemscpu -lrtemsbsp +endif + +ifeq ($(RTEMS_HAS_NETWORKING),yes) +OP_SYS_CFLAGS += -DRTEMS_LEGACY_STACK +else +OP_SYS_CFLAGS += -DHAVE_SOCKADDR_SA_LEN=1 +endif + +OP_SYS_LDFLAGS_posix += -u POSIX_Init +OP_SYS_LDFLAGS_kernel += $(CPU_CFLAGS) -u Init \ $(PROJECT_RELEASE)/lib/no-dpmem.rel \ $(PROJECT_RELEASE)/lib/no-mp.rel \ $(PROJECT_RELEASE)/lib/no-part.rel \ $(PROJECT_RELEASE)/lib/no-signal.rel \ $(PROJECT_RELEASE)/lib/no-rtmon.rel +OP_SYS_LDFLAGS += $(CPU_CFLAGS) $(OP_SYS_LDFLAGS_$(OS_API)) MOD_SYS_LDFLAGS += $(CPU_CFLAGS) -Wl,-r -nostdlib # Do not link against libraries which are part of the Generic Image diff --git a/configure/os/CONFIG.Common.RTEMS-beagleboneblack b/configure/os/CONFIG.Common.RTEMS-beagleboneblack new file mode 100644 index 000000000..4b6107b05 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-beagleboneblack @@ -0,0 +1,18 @@ +# +# CONFIG.Common.RTEMS-beaglebineblack +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = beagleboneblack +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/beagleboneblack/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.Common.RTEMS-beatnik b/configure/os/CONFIG.Common.RTEMS-beatnik index aaa45e4c9..84ba42667 100644 --- a/configure/os/CONFIG.Common.RTEMS-beatnik +++ b/configure/os/CONFIG.Common.RTEMS-beatnik @@ -8,14 +8,18 @@ EXE = .elf RTEMS_BSP = beatnik RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems -ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL +# optimization trouble in postfix.c +ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 -OP_SYS_LDLIBS += -lbspExt +OP_SYS_LDLIBS += -lbspExt #does not use posix stuff ... want to ignore MUNCH_SUFFIX = .boot +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ endef diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu index 684f01a19..29196ff65 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu @@ -6,6 +6,7 @@ #------------------------------------------------------- # Include definitions from RTEMS-pc386 -include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386 +# For Tests overwrite it with pc686 +include $(CONFIG)/os/CONFIG.Common.RTEMS-pc686 RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-pc686 b/configure/os/CONFIG.Common.RTEMS-pc686 new file mode 100644 index 000000000..43849744f --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc686 @@ -0,0 +1,25 @@ +# +# Author: W. Eric Norum +# Canadian Light Source +# eric@cls.usask.ca +# +# All RTEMS targets use the same Makefile fragment +# +RTEMS_BSP = pc686 +RTEMS_TARGET_CPU = i386 +GNU_TARGET = i386-rtems + +MUNCH_SUFFIX = .boot +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@ +endef + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/pc686/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +# +# Put text segment where it will work with etherboot +# +OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 diff --git a/configure/os/CONFIG.Common.RTEMS-qoriq_e500 b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 new file mode 100644 index 000000000..9ea6aec5d --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 @@ -0,0 +1,48 @@ +# +# CONFIG.Common.RTEMS-qoriq_e500 +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +EXE = .elf +RTEMS_BSP = qoriq_e500 +RTEMS_TARGET_CPU = powerpc +GNU_TARGET = powerpc-rtems +# optimization trouble in postfix.c +#ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 + +#netbsdlib +#ARCH_DEP_CFLAGS += -I$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib/include + +#OP_SYS_LDLIBS += -lbspExt #does not use posix stuff ... want to ignore +OP_SYS_LDLIBS += -Wl,--gc-sections +#ARCH_DEP_LDFLAGS = -mcpu=8540 -meabi -msdata=sysv -mstrict-align -mspe -mabi=spe -mfloat-gprs=double +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib + +MUNCH_SUFFIX = .img +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ + gzip -9 -f $@ + mkimage -A ppc -O linux -T kernel -a 0x4000 -e 0x4000 -n $* -d $@.gz $*.img +endef + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +RTEMSSYMS=$(PRODNAME:%$(EXE)=%.sym) +RTEMSIMGS=$(PRODNAME:%$(EXE)=%.bin) +INSTALL_RTEMSSYMS=$(RTEMSSYMS:%=$(INSTALL_BIN)/%) +INSTALL_RTEMSIMGS=$(RTEMSIMGS:%=$(INSTALL_BIN)/%) + +%.sym: %$(EXE) + $(XSYMS) $^ $@ + +%.bin: %$(EXE) + $(OBJCOPY) -Obinary $^ $@ + +#PRODTARGETS+=$(INSTALL_RTEMSSYMS) $(INSTALL_RTEMSIMGS) diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu new file mode 100644 index 000000000..83b518b69 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu @@ -0,0 +1,20 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_a9_qemu +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +#use dhcp/bootp +ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_a9_qemu/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard new file mode 100644 index 000000000..bac33eb91 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard @@ -0,0 +1,19 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_zedboard +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_zedboard +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_zedboard/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.darwin-x86.Common b/configure/os/CONFIG.darwin-x86.Common index e779f7dc1..960c74b8a 100644 --- a/configure/os/CONFIG.darwin-x86.Common +++ b/configure/os/CONFIG.darwin-x86.Common @@ -3,6 +3,7 @@ # Definitions for darwin-x86 host builds # Sites may override these definitions in CONFIG_SITE.darwin-x86.Common #------------------------------------------------------- - +#support for IPv6 etc. +OP_SYS_CFLAGS += -DHAVE_SOCKADDR_SA_LEN=1 #Include definitions common to unix hosts include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG_SITE.Common.RTEMS b/configure/os/CONFIG_SITE.Common.RTEMS index 0b5d227ee..47de204dd 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS +++ b/configure/os/CONFIG_SITE.Common.RTEMS @@ -5,9 +5,9 @@ # Where to find RTEMS # -# APS: -RTEMS_VERSION = 4.10.2 -RTEMS_BASE = /usr/local/vw/rtems/rtems-$(RTEMS_VERSION) +# FHI: +RTEMS_VERSION = 5 +RTEMS_BASE = /home/travis/.rtems # Cross-compile toolchain in $(RTEMS_TOOLS)/bin # diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 8533f8276..5bbd1647b 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -71,6 +71,23 @@ This also fixes [lauchpad bug #1714455](https://bugs.launchpad.net/bugs/1714455) These changes are to more closely follow the JSON5 standard, which doesn't support octal character escapes or the `\a` (Bel, `\x07`) escape sequence. +### Support for RTEMS 5 + +The new major release of the RTEMS real-time OS contains many changes including +the ability to support SMP systems. The earlier EPICS support for RTEMS made use +of various RTEMS-specific kernel APIs which cannot be used on an SMP system, so +the changes here required acompletely new port to the Posix real-time APIs that +RTEMS-5 now recommends. +A new RTEMS configuration variable RTEMS_SERIES has been added which should be +set to the first two components of the OS version number, e.g. 4.9. When this +is 4.12 or greater, true for 5.0 as well, the new libCom/osi/os/RTEMS-posix +source files will be used; the older API source files can now be found in +libCom/osi/os/RTEMS-kernel, and those which are common to both installations are +in libCom/osi/os/RTEMS. The compiler options are read from the Makefile.inc of +the corresponding BSP and set in the configuration files. It checks that the BSP +was also built with the --enable-posix option. It also checks if the BSP was built +with the legacy stack or libbsd. + ### Filters in database input links Input database links can now use channel filters, it is not necessary to diff --git a/modules/libcom/RTEMS/Makefile b/modules/libcom/RTEMS/Makefile index b46889db1..5865ff8e8 100644 --- a/modules/libcom/RTEMS/Makefile +++ b/modules/libcom/RTEMS/Makefile @@ -11,22 +11,31 @@ TOP = ../../.. include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG_LIBCOM_VERSION +# check check +SRC_DIRS += ../$(OS_API) + PERL_SCRIPTS += epicsMakeMemFs.pl INC += epicsRtemsInitHooks.h INC += epicsMemFs.h +INC += epicsNtp.h ifeq ($(RTEMS_QEMU_FIXUPS),YES) rtems_init_CPPFLAGS += -DQEMU_FIXUPS endif rtemsCom_SRCS += rtems_init.c rtemsCom_SRCS += rtems_config.c +ifeq ($(RTEMS_HAS_NETWORKING), yes) rtemsCom_SRCS += rtems_netconfig.c +else +rtemsCom_SRCS += libbsd_netconfig.c +endif rtemsCom_SRCS += rtems_util.c rtemsCom_SRCS += setBootConfigFromNVRAM.c rtemsCom_SRCS += epicsRtemsInitHookPre.c rtemsCom_SRCS += epicsRtemsInitHookPost.c rtemsCom_SRCS += epicsMemFs.c +rtemsCom_SRCS += epicsNtp.c ifeq ($(RTEMS_BSP),pc386) rtemsCom_SRCS += ne2kpci.c diff --git a/modules/libcom/RTEMS/epicsNtp.c b/modules/libcom/RTEMS/epicsNtp.c new file mode 100644 index 000000000..9a28cb223 --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.c @@ -0,0 +1,85 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epicsNtp.h" + +int epicsNtpGetTime(char *ntpIp, struct timespec *now) +{ + + int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket. + int portno = 123; // NTP UDP port number. + + // Create and zero out the packet. All 48 bytes worth. + ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + memset( &packet, 0, sizeof( ntp_packet ) ); + // Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero. + *( ( char * ) &packet + 0 ) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2. + + // Create a UDP socket, convert the host-name to an IP address, set the port number, + // connect to the server, send the packet, and then read in the return packet. + struct sockaddr_in serv_addr; // Server address data structure. + + sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); // Create a UDP socket. + + if ( sockfd < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Zero out the server address structure. + bzero( ( char* ) &serv_addr, sizeof( serv_addr ) ); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(ntpIp); + serv_addr.sin_port = htons( portno ); + + // Call up the server using its IP address and port number. + if ( connect( sockfd, ( struct sockaddr * ) &serv_addr, sizeof( serv_addr) ) < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Send it the NTP packet it wants. If n == -1, it failed. + n = write( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + +// Wait and receive the packet back from the server. If n == -1, it failed. + n = read( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // These two fields contain the time-stamp seconds as the packet left the NTP server. + // The number of seconds correspond to the seconds passed since 1900. + // ntohl() converts the bit/byte order from the network's to host's "endianness". + packet.txTm_s = ntohl( packet.txTm_s ); // Time-stamp seconds. + packet.txTm_f = ntohl( packet.txTm_f ); // Time-stamp fraction of a second. + + // Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server. + // Subtract 70 years worth of seconds from the seconds since 1900. + // This leaves the seconds since the UNIX epoch of 1970. + // (1900)------------------(1970)**************************************(Time Packet Left the Server) + time_t txTm = ( time_t ) ( packet.txTm_s - NTP_TIMESTAMP_DELTA ); + now->tv_sec = txTm; + return 0; +} diff --git a/modules/libcom/RTEMS/epicsNtp.h b/modules/libcom/RTEMS/epicsNtp.h new file mode 100644 index 000000000..dfff00a6b --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.h @@ -0,0 +1,43 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#ifndef EPICSNTP_H +#define EPICSNTP_H + +#define NTP_TIMESTAMP_DELTA 2208988800ull + +int epicsNtpGetTime(char *ntpIp, struct timespec *now); + +typedef struct +{ + + uint8_t li_vn_mode; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + uint8_t stratum; // Eight bits. Stratum level of the local clock. + uint8_t poll; // Eight bits. Maximum interval between successive messages. + uint8_t precision; // Eight bits. Precision of the local clock. + + uint32_t rootDelay; // 32 bits. Total round trip delay time. + uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. + uint32_t refId; // 32 bits. Reference clock identifier. + + uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. + uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. + + uint32_t origTm_s; // 32 bits. Originate time-stamp seconds. + uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second. + + uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. + uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. + + uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. + +} ntp_packet; // Total: 384 bits or 48 bytes. +#endif // EPICSNTP_H diff --git a/modules/libcom/RTEMS/rtems_config.c b/modules/libcom/RTEMS/kernel/rtems_config.c similarity index 100% rename from modules/libcom/RTEMS/rtems_config.c rename to modules/libcom/RTEMS/kernel/rtems_config.c diff --git a/modules/libcom/RTEMS/rtems_init.c b/modules/libcom/RTEMS/kernel/rtems_init.c similarity index 100% rename from modules/libcom/RTEMS/rtems_init.c rename to modules/libcom/RTEMS/kernel/rtems_init.c diff --git a/modules/libcom/RTEMS/rtems_netconfig.c b/modules/libcom/RTEMS/kernel/rtems_netconfig.c similarity index 100% rename from modules/libcom/RTEMS/rtems_netconfig.c rename to modules/libcom/RTEMS/kernel/rtems_netconfig.c diff --git a/modules/libcom/RTEMS/posix/epicsRtemsInitHookPost.c b/modules/libcom/RTEMS/posix/epicsRtemsInitHookPost.c new file mode 100644 index 000000000..f589eb9cf --- /dev/null +++ b/modules/libcom/RTEMS/posix/epicsRtemsInitHookPost.c @@ -0,0 +1,18 @@ +/*************************************************************************\ +* Copyright (c) 2006 The University of Chicago, as Operator of Argonne +* National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Dummy version -- use if application does not provide its own version + */ +#include "epicsRtemsInitHooks.h" + +int +epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) +{ + return 0; +} diff --git a/modules/libcom/RTEMS/posix/epicsRtemsInitHookPre.c b/modules/libcom/RTEMS/posix/epicsRtemsInitHookPre.c new file mode 100644 index 000000000..08efe1fe2 --- /dev/null +++ b/modules/libcom/RTEMS/posix/epicsRtemsInitHookPre.c @@ -0,0 +1,18 @@ +/*************************************************************************\ +* Copyright (c) 2006 The University of Chicago, as Operator of Argonne +* National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Dummy version -- use if application does not provide its own version + */ +#include "epicsRtemsInitHooks.h" + +int +epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) +{ + return 0; +} diff --git a/modules/libcom/RTEMS/posix/epicsRtemsInitHooks.h b/modules/libcom/RTEMS/posix/epicsRtemsInitHooks.h new file mode 100644 index 000000000..8671bebbf --- /dev/null +++ b/modules/libcom/RTEMS/posix/epicsRtemsInitHooks.h @@ -0,0 +1,24 @@ +/*************************************************************************\ +* Copyright (c) 2006 The University of Chicago, as Operator of Argonne +* National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Hooks into RTEMS startup code + */ +#include + +extern char *env_nfsServer; +extern char *env_nfsPath; +extern char *env_nfsMountPoint; + +/* + * Return 0 for success, non-zero for failure (will cause panic) + */ +int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); +int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); +/* Return 0 if local file system was setup, or non-zero (will fall back to network */ +int epicsRtemsMountLocalFilesystem(char **argv); diff --git a/modules/libcom/RTEMS/posix/libbsd_netconfig.c b/modules/libcom/RTEMS/posix/libbsd_netconfig.c new file mode 100644 index 000000000..d9c9f704d --- /dev/null +++ b/modules/libcom/RTEMS/posix/libbsd_netconfig.c @@ -0,0 +1,116 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS network configuration for EPICS + * Author: W. Eric Norum + * eric.norum@usask.ca + * (306) 966-5394 + * + * This file can be copied to an application source dirctory + * and modified to override the values shown below. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "libbsd_netconfig.h" + +#include +#include + +#define IFACE_IPV4_DHCP(iface) \ + "ifconfig_" # iface "=\"SYNCDHCP\"\n" + +#define IFACE_IPV4(iface, addr) \ + "ifconfig_" # iface "=\"inet " # addr " netmask 255.255.255.0\"\n" + +static const char* rc_conf_text = \ + "\n" \ + "syslog_priority=\"debug\"\n" \ + "\n" \ + "#create_args_myvlan=\"vlan 102\"\n" \ + "#create_args_yourvlan=\"vlan 202\"\n" \ + IFACE_IPV4_DHCP(cgem0) \ + "\n" \ + "dhcpcd_priority=\"100\"\n" \ + "\n" \ + "#defaultrouter=\"" NET_CFG_GATEWAY_IP "\"\n" \ + "defaultroute_delay=\"5\"\n" \ + "\n" \ + "#telnetd_enable=\"YES\"\n" \ + "#telnetd_options=\"-C 2 -P 100 \"\n" \ + "\n" \ + "#ftpd_enable=\"YES\"\n" \ + "#ftpd_options=\"-v -p 21 -C 2 -P 150 -L -I 10 -R /\"\n" \ + "\n" \ + "#pf_enable=\"YES\"\n" \ + "#pf_rules=\"/etc/mypf.conf\"\n" \ + "#pf_flags=\"-q -z\"\n" \ + "\n"; + +static const char* dhcpcd_conf_text = \ + "\n" \ +"clientid RTEMS test client\n" \ +"\n" \ +"nodhcp6\n" \ +"ipv4only\n" \ +"option ntp_servers\n" \ +"option rtems_cmdline\n"; + +int +epicsRtemsPrepareAndRunRCConfFile(void) +{ + size_t len; + size_t written; + int fd; + int rv; + struct stat sb; + + mkdir("/etc", S_IRWXU | S_IRWXG | S_IRWXO); /* ignore errors, check the dir after. */ + assert(stat("/etc", &sb) == 0); + assert(S_ISDIR(sb.st_mode)); + + printf("--------------- dhcpcd.conf -----------------\n"); + printf(dhcpcd_conf_text); + printf("-----------------------------------------\n"); + + len = strlen(dhcpcd_conf_text); + fd = open("/etc/dhcpcd.conf", O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd != -1); + written = write(fd, dhcpcd_conf_text, len); + assert(written == len); + rv = close(fd); + assert(rv == 0); + + printf("--------------- rc.conf -----------------\n"); + printf(rc_conf_text); + printf("-----------------------------------------\n"); + + len = strlen(rc_conf_text); + fd = open("/etc/rc.conf", O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd != -1); + written = write(fd, rc_conf_text, len); + assert(written == len); + rv = close(fd); + assert(rv == 0); + + return (rtems_bsd_run_etc_rc_conf(20, true)); +} diff --git a/modules/libcom/RTEMS/posix/libbsd_netconfig.h b/modules/libcom/RTEMS/posix/libbsd_netconfig.h new file mode 100644 index 000000000..b253b652d --- /dev/null +++ b/modules/libcom/RTEMS/posix/libbsd_netconfig.h @@ -0,0 +1,24 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS network configuration header for EPICS + * + * This file can be copied to an application source dirctory + * and modified to override the values shown below. + */ +#include +#include + +#define NET_CFG_INTERFACE_0 "cgem0" +#define DEFAULT_NETWORK_DHCPCD_ENABLE +#define DEFAULT_NETWORK_NO_INTERFACE_0 + +// Tests +#define NET_CFG_SELF_IP "141.14.128.89" +#define NET_CFG_NETMASK "255.255.240.0" +#define NET_CFG_GATEWAY_IP "141.14.128.128" + +int epicsRtemsPrepareAndRunRCConfFile(void); diff --git a/modules/libcom/RTEMS/posix/rtems_config.c b/modules/libcom/RTEMS/posix/rtems_config.c new file mode 100644 index 000000000..9c8e29ea3 --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_config.c @@ -0,0 +1,153 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS configuration for EPICS + * Author: W. Eric Norum + * norume@aps.anl.gov + * (630) 252-4793 + */ + +#include + +/* + *********************************************************************** + * RTEMS CONFIGURATION * + *********************************************************************** + */ + +extern void *POSIX_Init(void *argument); + +#define CONFIGURE_POSIX_INIT_THREAD_TABLE +#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT POSIX_Init +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (64*1024) + +#define CONFIGURE_MAXIMUM_PERIODS 5 +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 +#define CONFIGURE_MALLOC_STATISTICS 1 +/* MINIMUM_STACK_SIZE == 8K */ +#define CONFIGURE_EXTRA_TASK_STACKS (4000 * RTEMS_MINIMUM_STACK_SIZE) + +#define CONFIGURE_FILESYSTEM_DEVFS +#define CONFIGURE_FILESYSTEM_TFTPFS +#define CONFIGURE_FILESYSTEM_NFS +#define CONFIGURE_FILESYSTEM_IMFS +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +/* + * Configure LibBSD. + */ +#define RTEMS_BSD_CONFIG_NET_PF_UNIX +#define RTEMS_BSD_CONFIG_NET_IF_BRIDGE +#define RTEMS_BSD_CONFIG_NET_IF_LAGG +#define RTEMS_BSD_CONFIG_NET_IF_VLAN +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_INIT + +#include + +/* + * Configure RTEMS. + */ +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 150 +#define CONFIGURE_IMFS_ENABLE_MKFIFO 2 + +#define CONFIGURE_MAXIMUM_NFS_MOUNTS 3 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5 + +#define CONFIGURE_UNLIMITED_ALLOCATION_SIZE 32 +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (64 * 1024) +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 4 +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (1 * 1024 * 1024) + +/* we are using POSIX_INIT +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT +*/ + +//#define RTEMS_PCI_CONFIG_LIB +//#define CONFIGURE_PCI_LIB PCI_LIB_AUTO + +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_HOSTNAME_Command, \ + &rtems_shell_PING_Command, \ + &rtems_shell_ROUTE_Command, \ + &rtems_shell_NETSTAT_Command, \ + &rtems_shell_IFCONFIG_Command, \ + &rtems_shell_TCPDUMP_Command, \ + &rtems_shell_PFCTL_Command, \ + &rtems_shell_SYSCTL_Command + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO +#define CONFIGURE_SHELL_COMMAND_SHUTDOWN + +#include +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_SERVICE_TELNETD +#define RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE (16 * 1024) +#define RTEMS_BSD_CONFIG_SERVICE_FTPD +#define RTEMS_BSD_CONFIG_FIREWALL_PF + +#define CONFIGURE_MAXIMUM_DRIVERS 40 + +/* + * This should be made BSP dependent, not CPU dependent but I know of no + * appropriate conditionals to use. + * The new general time support makes including the RTC driver less important. + */ +#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && \ + !defined(mpc7455) && !defined(__arm__) && !defined(__nios2__) + /* don't have RTC code */ +#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER +#endif + +#if defined(LIBBSP_I386_PC386_BSP_H) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (64 * 1024 * 1024) +#elif defined(LIBBSP_POWERPC_QORIQ_BSP_H) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (32 * 1024 * 1024) +#endif + +#define CONFIGURE_INIT + +#include + diff --git a/modules/libcom/RTEMS/posix/rtems_init.c b/modules/libcom/RTEMS/posix/rtems_init.c new file mode 100644 index 000000000..fe3e5586f --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_init.c @@ -0,0 +1,1007 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS startup task for EPICS + * Author: W. Eric Norum + * eric.norum@usask.ca + * (306) 966-5394 + */ + +/* + * This is the first implementation with posix and rtems5. + * Currently only dhcp is supported with libbsd. The reading of the + * environment variables from e.g. u-boot environment is still missing. + * Extensive tests so far only with qemu. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RTEMS_LEGACY_STACK +#include +#include +#else // libbsd stack +#include +#include +#include +#include "libbsd_netconfig.h" +#include +#endif + +#include +#include + +#include "epicsVersion.h" +#include "epicsThread.h" +#include "epicsTime.h" +#include "epicsExit.h" +#include "envDefs.h" +#include "errlog.h" +#include "logClient.h" +#include "osiUnistd.h" +#include "iocsh.h" +#include "osdTime.h" +#include "epicsMemFs.h" +#include "epicsEvent.h" + +#include "epicsRtemsInitHooks.h" + +#ifdef RTEMS_LEGACY_STACK +#pragma message "RTEMS uses legacy stack" +#else +#pragma message "RTEMS uses libbsd stack" +// setup own ntp-client to get time +#include "epicsNtp.h" +epicsEventId dhcpDone; +#endif + + +/* these settings are needed by the rtems startup + * may provide by dhcp/bootp + * or environments from the "BIOS" like u-boot, motboot etc. + */ +struct in_addr rtems_bsdnet_bootp_server_address; +char rtemsInit_NTP_server_ip[16]; +char bootp_server_name_init[128] = "1001.1001@141.14.128.9:/Volumes/Epics"; +char *rtems_bsdnet_bootp_server_name = bootp_server_name_init; +char bootp_boot_file_name_init[128] = "/Volumes/Epics/myExample/bin/RTEMS-qoriq_e500/myExample.boot"; +char *rtems_bsdnet_bootp_boot_file_name = bootp_boot_file_name_init; +char bootp_cmdline_init[128] = "/Volumes/Epics/myExample/iocBoot/iocmyExample/st.cmd"; +char *rtems_bsdnet_bootp_cmdline = bootp_cmdline_init; + +/* + * Prototypes for some functions not in header files + */ +//void tzset(void); +int fileno(FILE *); +int main(int argc, char **argv); + +static void +logReset (void) +{ + void rtems_bsp_reset_cause(char *buf, size_t capacity) __attribute__((weak)); + void (*fp)(char *buf, size_t capacity) = rtems_bsp_reset_cause; + + if (fp) { + char buf[80]; + fp(buf, sizeof buf); + errlogPrintf ("Startup after %s.\n", buf); + } + else { + errlogPrintf ("Startup.\n"); + } +} + +/* + *********************************************************************** + * FATAL ERROR REPORTING * + *********************************************************************** + */ +/* + * Delay for a while, then terminate + */ +static void +delayedPanic (const char *msg) +{ + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_panic (msg); +} + +/* + * Log error and terminate + */ +void +LogFatal (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + errlogVprintf (msg, ap); + va_end (ap); + delayedPanic (msg); +} + +/* + * Log RTEMS error and terminate + */ +void +LogRtemsFatal (const char *msg, rtems_status_code sc) +{ + errlogPrintf ("%s: %s\n", msg, rtems_status_text (sc)); + delayedPanic (msg); +} + +/* + * Log network error and terminate + */ +void +LogNetFatal (const char *msg, int err) +{ + errlogPrintf ("%s: %d\n", msg, err); + delayedPanic (msg); +} + +void * +mustMalloc(int size, const char *msg) +{ + void *p; + + if ((p = malloc (size)) == NULL) + LogFatal ("Can't allocate space for %s.\n", msg); + return p; +} + +/* + *********************************************************************** + * REMOTE FILE ACCESS * + *********************************************************************** + */ +#ifdef OMIT_NFS_SUPPORT +# include +#endif + +const epicsMemFS *epicsRtemsFSImage __attribute__((weak)); +const epicsMemFS *epicsRtemsFSImage = (void*)&epicsRtemsFSImage; + +/* hook to allow app specific FS setup */ +int +epicsRtemsMountLocalFilesystem(char **argv) __attribute__((weak)); +int +epicsRtemsMountLocalFilesystem(char **argv) +{ + if(epicsRtemsFSImage==(void*)&epicsRtemsFSImage) + return -1; /* no FS image provided. */ + else if(epicsRtemsFSImage==NULL) + return 0; /* no FS image provided, but none is needed. */ + else { + printf("***** Using compiled in file data *****\n"); + if (epicsMemFsLoad(epicsRtemsFSImage) != 0) { + printf("Can't unpack tar filesystem\n"); + return -1; + } else { + argv[1] = "/"; + return 0; + } + } +} + +static int +initialize_local_filesystem(char **argv) +{ + extern char _DownloadLocation[] __attribute__((weak)); + extern char _FlashBase[] __attribute__((weak)); + extern char _FlashSize[] __attribute__((weak)); + + argv[0] = rtems_bsdnet_bootp_boot_file_name; + if (epicsRtemsMountLocalFilesystem(argv)==0) { + return 1; /* FS setup successful */ + } +/* else if (_FlashSize && (_DownloadLocation || _FlashBase)) { + extern char _edata[]; + size_t flashIndex = _edata - _DownloadLocation; + char *header = _FlashBase + flashIndex; + + if (memcmp(header + 257, "ustar ", 8) == 0) { + int fd; + printf ("***** Unpack in-memory file system (IMFS) *****\n"); + if (rtems_tarfs_load("/", (unsigned char *)header, (size_t)_FlashSize - flashIndex) != 0) { + printf("Can't unpack tar filesystem\n"); + return 0; + } + if ((fd = open(rtems_bsdnet_bootp_cmdline, 0)) >= 0) { + close(fd); + printf ("***** Found startup script (%s) in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + argv[1] = rtems_bsdnet_bootp_cmdline; + return 1; + } + printf ("***** Startup script (%s) not in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + } + } */ + return 0; +} + +#ifndef OMIT_NFS_SUPPORT +int +nfsMount(char *uidhost, char *path, char *mntpoint) +{ + int devl = strlen(uidhost) + strlen(path) + 2; + char *dev; + int rval = -1; + + if ((dev = malloc(devl)) == NULL) { + fprintf(stderr,"nfsMount: out of memory\n"); + return -1; + } + sprintf(dev, "%s:%s", uidhost, path); + printf("Mount %s on %s\n", dev, mntpoint); + rval = mount_and_make_target_path ( + dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS, + RTEMS_FILESYSTEM_READ_WRITE, NULL ); + if(rval) + perror("mount failed"); + free(dev); + return rval; +} +#define NFS_INIT +#endif + + +static void +initialize_remote_filesystem(char **argv, int hasLocalFilesystem) +{ +#ifdef OMIT_NFS_SUPPORT + printf ("***** Initializing TFTP *****\n"); + mount_and_make_target_path(NULL, + "/TFTP", + RTEMS_FILESYSTEM_TYPE_TFTPFS, + RTEMS_FILESYSTEM_READ_WRITE, + NULL); + if (!hasLocalFilesystem) { + char *path; + int pathsize = 200; + int l; + + path = mustMalloc(pathsize, "Command path name "); + strcpy (path, "/TFTP/BOOTP_HOST/epics/"); + l = strlen (path); + if (gethostname (&path[l], pathsize - l - 10) || (path[l] == '\0')) + { + LogFatal ("Can't get host name"); + } + strcat (path, "/st.cmd"); + argv[1] = path; + } +#else + char *server_name; + char *server_path; + char *mount_point; + char *cp; + int l = 0; + + printf ("***** Initializing NFS *****\n"); + NFS_INIT + if (env_nfsServer && env_nfsPath && env_nfsMountPoint) { + server_name = env_nfsServer; + server_path = env_nfsPath; + mount_point = env_nfsMountPoint; + cp = mount_point; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (mount_point, 0755) != 0) + && (errno != EEXIST)) + LogFatal("Can't create directory \"%s\": %s.\n", + mount_point, strerror(errno)); + *cp = '/'; + } + argv[1] = rtems_bsdnet_bootp_cmdline; + } + else if (hasLocalFilesystem) { + return; + } + else { + /* + * Use first component of nvram/bootp command line pathname + * to set up initial NFS mount. A "/tftpboot/" is prepended + * if the pathname does not begin with a '/'. This allows + * NFS and TFTP to have a similar view of the remote system. + */ + if (rtems_bsdnet_bootp_cmdline[0] == '/') + cp = rtems_bsdnet_bootp_cmdline + 1; + else + cp = rtems_bsdnet_bootp_cmdline; + cp = strchr(cp, '/'); + if ((cp == NULL) + || ((l = cp - rtems_bsdnet_bootp_cmdline) == 0)) + LogFatal("\"%s\" is not a valid command pathname.\n", rtems_bsdnet_bootp_cmdline); + cp = mustMalloc(l + 20, "NFS mount paths"); + server_path = cp; +printf( " rtems_bootp_server_name: %s\n",rtems_bsdnet_bootp_server_name); + server_name = rtems_bsdnet_bootp_server_name; + if (rtems_bsdnet_bootp_cmdline[0] == '/') { + mount_point = server_path; + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + argv[1] = rtems_bsdnet_bootp_cmdline; + /* + * Its probably common to embed the mount point in the server + * name so, when this is occurring, dont clobber the mount point + * by appending the first node from the command path. This allows + * the mount point to be a different path then the server's mount + * path. + * + * This allows for example a line similar to as follows the DHCP + * configuration file. + * + * server-name "159.233@192.168.0.123:/vol/vol0/bootRTEMS"; + */ + if ( server_name ) { + const size_t allocSize = strlen ( server_name ) + 2; + char * const pServerName = mustMalloc( allocSize, + "NFS mount paths"); + char * const pServerPath = mustMalloc ( allocSize, + "NFS mount paths"); + const int scanfStatus = sscanf ( + server_name, + "%[^:] : / %s", + pServerName, + pServerPath + 1u ); + if ( scanfStatus == 2 ) { + pServerPath[0u]= '/'; + server_name = pServerName; + // is this a general solution? + server_path = mount_point = pServerPath; + } + else { + free ( pServerName ); + free ( pServerPath ); + } + } + } + else { + char *abspath = mustMalloc(strlen(rtems_bsdnet_bootp_cmdline)+2,"Absolute command path"); + strcpy(server_path, "/tftpboot/"); + mount_point = server_path + strlen(server_path); + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + mount_point--; + strcpy(abspath, "/"); + strcat(abspath, rtems_bsdnet_bootp_cmdline); + argv[1] = abspath; + } + } + errlogPrintf("nfsMount(\"%s\", \"%s\", \"%s\")\n", + server_name, server_path, mount_point); + nfsMount(server_name, server_path, mount_point); +#endif +} + +static +char rtems_etc_hosts[] = "127.0.0.1 localhost\n"; + +/* If it doesn't already exist, create /etc/hosts with an entry for 'localhost' */ +static +void fixup_hosts(void) +{ + FILE *fp; + int ret; + struct stat STAT; + + ret=stat("/etc/hosts", &STAT); + if(ret==0) + { + return; /* already exists, assume file */ + } else if(errno!=ENOENT) { + perror("error: fixup_hosts stat /etc/hosts"); + return; + } + + ret = mkdir("/etc", 0775); + if(ret!=0 && errno!=EEXIST) + { + perror("error: fixup_hosts create /etc"); + return; + } + + if((fp=fopen("/etc/hosts", "w"))==NULL) + { + perror("error: fixup_hosts create /etc/hosts"); + } + + if(fwrite(rtems_etc_hosts, 1, sizeof(rtems_etc_hosts)-1, fp)!=sizeof(rtems_etc_hosts)-1) + { + perror("error: failed to write /etc/hosts"); + } + + fclose(fp); +} + +/* + * Get to the startup script directory + * The TFTP filesystem requires a trailing '/' on chdir arguments. + */ +static void +set_directory (const char *commandline) +{ + const char *cp; + char *directoryPath; + int l; + + cp = strrchr(commandline, '/'); + if (cp == NULL) { + l = 0; + cp = "/"; + } + else { + l = cp - commandline; + cp = commandline; + } + directoryPath = mustMalloc(l + 2, "Command path directory "); + strncpy(directoryPath, cp, l); + directoryPath[l] = '/'; + directoryPath[l+1] = '\0'; + if (chdir (directoryPath) < 0) + LogFatal ("Can't set initial directory(%s): %s\n", directoryPath, strerror(errno)); + else + errlogPrintf("chdir(\"%s\")\n", directoryPath); + free(directoryPath); +} + +/* + *********************************************************************** + * RTEMS/EPICS COMMANDS * + *********************************************************************** + */ + +static const iocshArg rtshellArg0 = { "cmd", iocshArgString}; +static const iocshArg rtshellArg1 = { "args", iocshArgArgv}; +static const iocshArg * rtshellArgs[2] = { &rtshellArg0, &rtshellArg1}; +static const iocshFuncDef rtshellFuncDef = { "rt",2, rtshellArgs}; +static void rtshellCallFunc(const iocshArgBuf *args) +{ + rtems_shell_cmd_t *cmd = rtems_shell_lookup_cmd(args[0].sval); + int ret; + + if (!cmd) { + fprintf(stderr, "ERR: No such command\n"); + + } else { + fflush(stdout); + fflush(stderr); + ret = (*cmd->command)(args[1].aval.ac,args[1].aval.av); + fflush(stdout); + fflush(stderr); + if(ret) + fprintf(stderr, "ERR: %d\n",ret); + } +} + +/* + * RTEMS status + */ +static void +rtems_netstat (unsigned int level) +{ +/* + rtems_bsdnet_show_if_stats (); + rtems_bsdnet_show_mbuf_stats (); + if (level >= 1) { + rtems_bsdnet_show_inet_routes (); + } + if (level >= 2) { + rtems_bsdnet_show_ip_stats (); + rtems_bsdnet_show_icmp_stats (); + rtems_bsdnet_show_udp_stats (); + rtems_bsdnet_show_tcp_stats (); + } +*/ +} + +static const iocshArg netStatArg0 = { "level",iocshArgInt}; +static const iocshArg * const netStatArgs[1] = {&netStatArg0}; +static const iocshFuncDef netStatFuncDef = {"netstat",1,netStatArgs}; +static void netStatCallFunc(const iocshArgBuf *args) +{ + rtems_netstat(args[0].ival); +} + +static const iocshFuncDef heapSpaceFuncDef = {"heapSpace",0,NULL}; +static void heapSpaceCallFunc(const iocshArgBuf *args) +{ + Heap_Information_block info; + double x; + + malloc_info (&info); + x = info.Stats.size - (unsigned long) + (info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + if (x >= 1024*1024) + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); + else + printf("Heap space: %.1f kB\n", x / 1024); +} + +#ifndef OMIT_NFS_SUPPORT +static const iocshArg nfsMountArg0 = { "[uid.gid@]host",iocshArgString}; +static const iocshArg nfsMountArg1 = { "server path",iocshArgString}; +static const iocshArg nfsMountArg2 = { "mount point",iocshArgString}; +static const iocshArg * const nfsMountArgs[3] = {&nfsMountArg0,&nfsMountArg1, + &nfsMountArg2}; +static const iocshFuncDef nfsMountFuncDef = {"nfsMount",3,nfsMountArgs}; +static void nfsMountCallFunc(const iocshArgBuf *args) +{ + char *cp = args[2].sval; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (args[2].sval, 0755) != 0) && (errno != EEXIST)) { + printf("Can't create directory \"%s\": %s.\n", + args[2].sval, strerror(errno)); + return; + } + *cp = '/'; + } + nfsMount(args[0].sval, args[1].sval, args[2].sval); +} +#endif + + +void zoneset(const char *zone) +{ + if(zone) + setenv("TZ", zone, 1); + else + unsetenv("TZ"); + tzset(); +} + +static const iocshArg zonesetArg0 = {"zone string", iocshArgString}; +static const iocshArg * const zonesetArgs[1] = {&zonesetArg0}; +static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs}; +static void zonesetCallFunc(const iocshArgBuf *args) +{ + zoneset(args[0].sval); +} + + +/* + * Register RTEMS-specific commands + */ +static void iocshRegisterRTEMS (void) +{ + iocshRegister(&netStatFuncDef, netStatCallFunc); + iocshRegister(&heapSpaceFuncDef, heapSpaceCallFunc); +#ifndef OMIT_NFS_SUPPORT + iocshRegister(&nfsMountFuncDef, nfsMountCallFunc); +#endif + iocshRegister(&zonesetFuncDef, &zonesetCallFunc); + iocshRegister(&rtshellFuncDef, &rtshellCallFunc); + rtems_shell_init_environment(); +} + +/* + * Set up the console serial line (no handshaking) + */ +static void +initConsole (void) +{ + struct termios t; + +printf("\n initConsole --- Info ---\n"); +printf("stdin: fileno: %d, ttyname: %s\n", fileno(stdin), ttyname(fileno(stdin))); +printf("stdout: fileno: %d, ttyname: %s\n", fileno(stdout), ttyname(fileno(stdout))); +printf("stderr: fileno: %d, ttyname: %s\n", fileno(stderr), ttyname(fileno(stderr))); + + if (tcgetattr (fileno (stdin), &t) < 0) { + printf ("tcgetattr failed: %s\n", strerror (errno)); + return; + } + t.c_iflag &= ~(IXOFF | IXON | IXANY); + if (tcsetattr (fileno (stdin), TCSANOW, &t) < 0) { + printf ("tcsetattr failed: %s\n", strerror (errno)); + return; + } +} + +/* + * Hook to ensure that BSP cleanup code gets run on exit + */ +static void +exitHandler(void) +{ + rtems_shutdown_executive(0); +} + +static char* getPrimaryNetworkInterface(void) +{ + // lookup available network interfaces + char ifnamebuf[IF_NAMESIZE]; + char *ifname; + // get primary network interface + ifname = if_indextoname(1, &ifnamebuf[0]); + if (ifname == NULL) return (NULL); + printf("\n***** Primary Network interface : %s *****\n", ifname); + return (ifname); +} + +static void +dhcpcd_hook_handler(rtems_dhcpcd_hook *hook, char *const *env) +{ + int bound = 0; + char iName[16]; + char *name; + char *value; + + (void)hook; + + char ifnamebuf[IF_NAMESIZE]; + *ifnamebuf = getPrimaryNetworkInterface(); + + while (*env != NULL) { + name = strtok(*env,"="); + value = strtok(NULL,"="); + printf("all out ---> %s = %s\n", name, value); + if (!strncmp(name, "interface", 9) && !strcmp(value, ifnamebuf)) + strncpy(iName, value, 16); + if (!strncmp(name, "reason", 6) && !strncmp(value, "BOUND", 5)){ + printf ("Interface %s bounded\n", iName); + bound = 1; + } + if (bound) { + // as there is no ntp-support in rtems-libbsd, we call our own client + if(!strncmp(name, "new_ntp_servers", 15)) + strcpy(rtemsInit_NTP_server_ip,value); + if(!strncmp(name, "new_host_name", 13)) + sethostname (value, strlen (value)); + if(!strncmp(name, "new_tftp_server_name", 20)){ + //printf(" new_tftp_server_name : %s\n", value); + strncpy(rtems_bsdnet_bootp_server_name,value, sizeof(bootp_server_name_init)); + printf(" rtems_bsdnet_bootp_server_name : %s\n", rtems_bsdnet_bootp_server_name); + } + if(!strncmp(name, "new_bootfile_name", 20)){ + //printf(" new_bootfile_name : %s\n", value); + strncpy(rtems_bsdnet_bootp_boot_file_name,value, sizeof(bootp_boot_file_name_init)); + printf(" rtems_bsdnet_bootp_boot_file_name : %s\n", rtems_bsdnet_bootp_boot_file_name); + } + if(!strncmp(name, "new_rtems_cmdline", 20)){ + //printf(" new_rtems_cmdline : %s\n", value); + strncpy(rtems_bsdnet_bootp_cmdline,value, sizeof(bootp_cmdline_init)); + printf(" rtems_bsdnet_bootp_cmdline : %s\n", rtems_bsdnet_bootp_cmdline); + } + // printf("---> %s = %s\n", name, value); + } + ++env; + } + if (bound) + epicsEventSignal(dhcpDone); + } + +static rtems_dhcpcd_hook dhcpcd_hook = { + .name = "ioc boot", + .handler = dhcpcd_hook_handler +}; + +static void +default_network_on_exit(int exit_code, void *arg) +{ + rtems_printer printer; + + (void)arg; + + rtems_print_printer_printf(&printer); + rtems_stack_checker_report_usage_with_plugin(&printer); + + if (exit_code == 0) { + puts("*** END OF TEST ***"); + } +} + +static void +default_network_set_self_prio(rtems_task_priority prio) +{ + rtems_status_code sc; + + sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void +default_network_dhcpcd(void) +{ + static const char default_cfg[] = "clientid FHI test client\n"; + rtems_status_code sc; + int fd; + int rv; + ssize_t n; + + fd = open("/etc/dhcpcd.conf", O_CREAT | O_WRONLY, + S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd >= 0); + + n = write(fd, default_cfg, sizeof(default_cfg) - 1); + assert(n == (ssize_t) sizeof(default_cfg) - 1); + + static const char fhi_cfg[] = + "nodhcp6\n" \ + "ipv4only\n" \ + "option ntp_servers\n" \ + "option rtems_cmdline\n" \ + "option tftp_server_name\n" \ + "option bootfile_name"; + + n = write(fd, fhi_cfg, sizeof(fhi_cfg) - 1); + assert(n == (ssize_t) sizeof(fhi_cfg) - 1); + + rv = close(fd); + assert(rv == 0); + + sc = rtems_dhcpcd_start(NULL); + assert(sc == RTEMS_SUCCESSFUL); +} + +/* + * RTEMS Startup task + */ +void * +POSIX_Init (void *argument) +{ + int result; + char *argv[3] = { NULL, NULL, NULL }; + // char *cp; + rtems_status_code sc; + struct timespec now; + char timeBuff[100]; + + initConsole (); + + /* + * Use BSP-supplied time of day if available otherwise supply default time. + * It is very likely that other time synchronization facilities in EPICS + * will soon override this value. + */ + /* check for RTC ... unfortunately seems to be missing with libbsd and qemu ? + if (checkRealtime() >= 0) { + setRealTimeToRTEMS(); + } else + */ + { + // set time to 14.4.2014 + now.tv_sec = 1397460606; + now.tv_nsec = 0; + if (clock_settime(CLOCK_REALTIME, &now) < 0) + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } + if ( clock_gettime( CLOCK_REALTIME, &now) < 0) { + printf ("***** Can't get time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time set to : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + + /* + * Explain why we're here + */ + logReset(); + + /* TBD ... + * Architecture-specific hooks + if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM"); + if (rtems_bsdnet_config.bootp == NULL) { + extern void setBootConfigFromNVRAM(void); + setBootConfigFromNVRAM(); + } + if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM"); + + */ + + /* + * Override RTEMS Posix configuration, it gets started with posix prio 2 + */ + epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityIocsh); + + /* + * Create a reasonable environment + */ + + putenv ("TERM=xterm"); + putenv ("IOCSH_HISTSIZE=20"); + + /* + * Display some OS information + */ + printf("\n***** RTEMS Version: %s *****\n", + rtems_get_version_string()); + + + printf("\n***** Initializing network (dhcp) *****\n"); + rtems_bsd_setlogpriority("debug"); + on_exit(default_network_on_exit, NULL); + /* Let other tasks run to complete background work */ + default_network_set_self_prio(RTEMS_MAXIMUM_PRIORITY - 1U); + + /* supress all output from bsd network initialization + rtems_bsd_vprintf_handler bsd_vprintf_handler_old; + bsd_vprintf_handler_old = rtems_bsd_set_vprintf_handler(rtems_bsd_vprintf_handler_mute); + */ + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + /* Let the callout timer allocate its resources */ + sc = rtems_task_wake_after(2); + assert(sc == RTEMS_SUCCESSFUL); + + rtems_bsd_ifconfig_lo0(); + + // if MY_BOOTP??? + default_network_dhcpcd(); + + /* this seems to be hard coded in the BSP -> Sebastian Huber ? + printf("\n--Info (hpj)-- bsd task prio IRQS: %d -----\n", rtems_bsd_get_task_priority("IRQS")); + printf("\n--Info (hpj)-- bsd task prio TIME: %d -----\n", rtems_bsd_get_task_priority("TIME")); + */ + + // implement DHCP hook ... and wait for acknowledge + dhcpDone = epicsEventMustCreate(epicsEventEmpty); + rtems_dhcpcd_add_hook(&dhcpcd_hook); + + /* use /etc/rc.conf, /etc/dhclient.conf ... */ + //epicsRtemsPrepareAndRunRCConfFile(); + + // wait for dhcp done ... should be if SYNCDHCP is used + epicsEventWaitStatus stat; + int counter = 10; + do { + printf("\n ---- Wait for DHCP done ...\n"); + stat = epicsEventWaitWithTimeout(dhcpDone, 5.0); + } while ((stat == epicsEventWaitTimeout) && (--counter > 0)); + if (stat == epicsEventOK) + epicsEventDestroy(dhcpDone); + else + printf("\n ---- dhcpDone Event Unknown state %d\n", stat); + + const char* ifconfg_args[] = { + "ifconfig", NULL + }; + const char* netstat_args[] = { + "netstat", "-rn", NULL + }; + + printf("-------------- IFCONFIG -----------------\n"); + rtems_bsd_command_ifconfig(1, (char**) ifconfg_args); + printf("-------------- NETSTAT ------------------\n"); + rtems_bsd_command_netstat(2, (char**) netstat_args); + + /* until now there is no NTP support in libbsd -> Sebastian Huber ... */ + printf("\n***** Until now no NTP support in RTEMS 5 with rtems-libbsd *****\n"); + printf("\n***** Ask ntp server once... *****\n"); + if (epicsNtpGetTime(rtemsInit_NTP_server_ip, &now) < 0) { + printf ("***** Can't get time from ntp ...\n"); + } else { + if (clock_settime(CLOCK_REALTIME, &now) < 0){ + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time from ntp : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + } + + printf("\n***** Setting up file system *****\n"); + initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); + fixup_hosts(); + + /* + * More environment: iocsh prompt and hostname + */ + { + char hostname[1024]; + gethostname(hostname, 1023); + char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt"); + sprintf(cp, "%s> ", hostname); + epicsEnvSet ("IOCSH_PS1", cp); + epicsEnvSet("IOC_NAME", hostname); + } + + if (getenv("") == NULL) { + const char *tzp = envGetConfigParamPtr(&EPICS_TZ); + if (tzp == NULL) { + printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); + } + + } + tzset(); + printf(" check for time registered , C++ initialization ...\n"); + //osdTimeRegister(); + /*/Volumes/Epics/myExample/bin/RTEMS-xilinx_zynq_a9_qemu + * Run the EPICS startup script + */ + printf ("***** Preparing EPICS application *****\n"); + iocshRegisterRTEMS (); + set_directory (argv[1]); + epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]); + atexit(exitHandler); + errlogFlush(); + printf ("***** Starting EPICS application *****\n"); + result = main ((sizeof argv / sizeof argv[0]) - 1, argv); + printf ("***** IOC application terminating *****\n"); + epicsThreadSleep(1.0); + epicsExit(result); + return NULL; +} + +#if defined(QEMU_FIXUPS) +/* Override some hooks (weak symbols) + * if BSP defaults aren't configured for running tests. + */ + + +/* Ensure that stdio goes to serial (so it can be captured) */ +#if defined(__i386__) && !USE_COM1_AS_CONSOLE +#include +#include + +extern int BSPPrintkPort; +void bsp_predriver_hook(void) +{ + Console_Port_Minor = BSP_CONSOLE_PORT_COM1; + BSPPrintkPort = BSP_CONSOLE_PORT_COM1; +} +#endif + +/* reboot immediately when done. */ +#if defined(__i386__) && BSP_PRESS_KEY_FOR_RESET +void bsp_cleanup(void) +{ + void bsp_reset(); + bsp_reset(); +} +#endif + +#endif /* QEMU_FIXUPS */ + +int cexpdebug __attribute__((weak)); + +/* defines in rtems_config.c +#define CONFIGURE_SHELL_COMMANDS_INIT +#define CONFIGURE_SHELL_COMMANDS_ALL +// exclude commands which won't work right with our configuration +#define CONFIGURE_SHELL_NO_COMMAND_EXIT +#define CONFIGURE_SHELL_NO_COMMAND_LOGOFF +// exclude commands which unnecessarily pull in block driver +#define CONFIGURE_SHELL_NO_COMMAND_MSDOSFMT +#define CONFIGURE_SHELL_NO_COMMAND_BLKSYNC +#define CONFIGURE_SHELL_NO_COMMAND_MKRFS +#define CONFIGURE_SHELL_NO_COMMAND_DEBUGRFS +#define CONFIGURE_SHELL_NO_COMMAND_FDISK + +#include +*/ diff --git a/modules/libcom/RTEMS/posix/setBootConfigFromNVRAM.c b/modules/libcom/RTEMS/posix/setBootConfigFromNVRAM.c new file mode 100644 index 000000000..b029b3253 --- /dev/null +++ b/modules/libcom/RTEMS/posix/setBootConfigFromNVRAM.c @@ -0,0 +1,369 @@ +/*************************************************************************\ +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *env_nfsServer; +char *env_nfsPath; +char *env_nfsMountPoint; + +/* + * Split argument string of form nfs_server:nfs_export: + * The nfs_export component will be used as: + * - the path to the directory exported from the NFS server + * - the local mount point + * - a prefix of + * For example, the argument string: + * romeo:/export/users:smith/ioc/iocexample/st.cmd + * would: + * - mount /export/users from NFS server romeo on /export/users + * - chdir to /export/users/smith/ioc/iocexample + * - read commands from st.cmd + */ +static void +splitRtemsBsdnetBootpCmdline(void) +{ + char *cp1, *cp2, *cp3; + + if ((cp1 = rtems_bsdnet_bootp_cmdline) == NULL) + return; + if (((cp2 = strchr(cp1, ':')) != NULL) + && (((cp3 = strchr(cp2+1, ' ')) != NULL) + || ((cp3 = strchr(cp2+1, ':')) != NULL))) { + int l1 = cp2 - cp1; + int l2 = cp3 - cp2 - 1; + int l3 = strlen(cp3) - 1; + if (l1 && l2 && l3) { + *cp2++ = '\0'; + *cp3 = '\0'; + env_nfsServer = cp1; + env_nfsMountPoint = env_nfsPath = epicsStrDup(cp2); + *cp3 = '/'; + rtems_bsdnet_bootp_cmdline = cp2; + } + } +} + +/* + * Split NFS mount information of the form nfs_server:host_path:local_path + */ +static void +splitNfsMountPath(char *nfsString) +{ + char *cp2, *cp3; + + if (nfsString == NULL) + return; + if (((cp2 = strchr(nfsString, ':')) != NULL) + && (((cp3 = strchr(cp2+1, ' ')) != NULL) + || ((cp3 = strchr(cp2+1, ':')) != NULL))) { + int l1 = cp2 - nfsString; + int l2 = cp3 - cp2 - 1; + int l3 = strlen(cp3) - 1; + if (l1 && l2 && l3) { + *cp2++ = '\0'; + *cp3++ = '\0'; + env_nfsServer = nfsString; + env_nfsPath = cp2; + env_nfsMountPoint = cp3; + } + } +} + +#if defined(HAVE_MOTLOAD) + +/* + * Motorola MOTLOAD NVRAM Access + */ +static char * +gev(const char *parm, volatile char *nvp) +{ + const char *val; + const char *name; + char *ret; + char c; + + for (;;) { + if (*nvp == '\0') + return NULL; + name = parm; + while ((c = *nvp++) != '\0') { + if ((c == '=') && (*name == '\0')) { + val = (char *)nvp; + while (*nvp++ != '\0') + continue; + ret = malloc(nvp - val); + if (ret == NULL) + return NULL; + strcpy(ret, val); + return ret; + } + if (c != *name++) { + while (*nvp++ != '\0') + continue; + break; + } + } + } +} + +static char * +motScriptParm(const char *mot_script_boot, char parm) +{ + const char *cp; + char *ret; + int l; + + while (*mot_script_boot != '\0') { + if (isspace(*(unsigned char *)mot_script_boot) + && (*(mot_script_boot+1) == '-') + && (*(mot_script_boot+2) == parm)) { + mot_script_boot += 3; + cp = mot_script_boot; + while ((*mot_script_boot != '\0') && + !isspace(*(unsigned char *)mot_script_boot)) + mot_script_boot++; + l = mot_script_boot - cp; + ret = malloc(l+1); + if (ret == NULL) + return NULL; + strncpy(ret, cp, l); + *(ret+l) = '\0'; + return ret; + } + mot_script_boot++; + } + return NULL; +} + +void +setBootConfigFromNVRAM(void) +{ + char *cp; + const char *mot_script_boot; + char *nvp; + +# if defined(BSP_NVRAM_BASE_ADDR) + nvp = (volatile unsigned char *)(BSP_NVRAM_BASE_ADDR+0x70f8); +# elif defined(BSP_I2C_VPD_EEPROM_DEV_NAME) + char gev_buf[3592]; + int fd; + if ((fd = open(BSP_I2C_VPD_EEPROM_DEV_NAME, 0)) < 0) { + printf("Can't open %s: %s\n", BSP_I2C_VPD_EEPROM_DEV_NAME, strerror(errno)); + return; + } + lseek(fd, 0x10f8, SEEK_SET); + if (read(fd, gev_buf, sizeof gev_buf) != sizeof gev_buf) { + printf("Can't read %s: %s\n", BSP_I2C_VPD_EEPROM_DEV_NAME, strerror(errno)); + return; + } + close(fd); + nvp = gev_buf; +# else +# error "No way to read GEV!" +# endif + + if (rtems_bsdnet_config.bootp != NULL) + return; + mot_script_boot = gev("mot-script-boot", nvp); + if ((rtems_bsdnet_bootp_server_name = gev("mot-/dev/enet0-sipa", nvp)) == NULL) + rtems_bsdnet_bootp_server_name = motScriptParm(mot_script_boot, 's'); + if ((rtems_bsdnet_config.gateway = gev("mot-/dev/enet0-gipa", nvp)) == NULL) + rtems_bsdnet_config.gateway = motScriptParm(mot_script_boot, 'g'); + if ((rtems_bsdnet_config.ifconfig->ip_netmask = gev("mot-/dev/enet0-snma", nvp)) == NULL) + rtems_bsdnet_config.ifconfig->ip_netmask = motScriptParm(mot_script_boot, 'm'); + + rtems_bsdnet_config.name_server[0] = gev("rtems-dns-server", nvp); + if (rtems_bsdnet_config.name_server[0] == NULL) + rtems_bsdnet_config.name_server[0] = rtems_bsdnet_bootp_server_name; + cp = gev("rtems-dns-domainname", nvp); + if (cp) + rtems_bsdnet_config.domainname = cp; + + if ((rtems_bsdnet_config.ifconfig->ip_address = gev("mot-/dev/enet0-cipa", nvp)) == NULL) + rtems_bsdnet_config.ifconfig->ip_address = motScriptParm(mot_script_boot, 'c'); + rtems_bsdnet_config.hostname = gev("rtems-client-name", nvp); + if (rtems_bsdnet_config.hostname == NULL) + rtems_bsdnet_config.hostname = rtems_bsdnet_config.ifconfig->ip_address; + + if ((rtems_bsdnet_bootp_boot_file_name = gev("mot-/dev/enet0-file", nvp)) == NULL) + rtems_bsdnet_bootp_boot_file_name = motScriptParm(mot_script_boot, 'f'); + rtems_bsdnet_bootp_cmdline = gev("epics-script", nvp); + splitRtemsBsdnetBootpCmdline(); + splitNfsMountPath(gev("epics-nfsmount", nvp)); + rtems_bsdnet_config.ntp_server[0] = gev("epics-ntpserver", nvp); + if (rtems_bsdnet_config.ntp_server[0] == NULL) + rtems_bsdnet_config.ntp_server[0] = rtems_bsdnet_bootp_server_name; + if ((cp = gev("epics-tz", nvp)) != NULL) + epicsEnvSet("TZ", cp); +} + +#elif defined(HAVE_PPCBUG) +/* + * Motorola PPCBUG NVRAM Access + */ +struct ppcbug_nvram { + uint32_t PacketVersionIdentifier; + uint32_t NodeControlMemoryAddress; + uint32_t BootFileLoadAddress; + uint32_t BootFileExecutionAddress; + uint32_t BootFileExecutionDelay; + uint32_t BootFileLength; + uint32_t BootFileByteOffset; + uint32_t TraceBufferAddress; + uint32_t ClientIPAddress; + uint32_t ServerIPAddress; + uint32_t SubnetIPAddressMask; + uint32_t BroadcastIPAddressMask; + uint32_t GatewayIPAddress; + uint8_t BootpRarpRetry; + uint8_t TftpRarpRetry; + uint8_t BootpRarpControl; + uint8_t UpdateControl; + char BootFilenameString[64]; + char ArgumentFilenameString[64]; +}; + +static char *addr(char *cbuf, uint32_t addr) +{ + struct in_addr a; + if ((a.s_addr = addr) == 0) + return NULL; + return (char *)inet_ntop(AF_INET, &a, cbuf, INET_ADDRSTRLEN); +} + +void +setBootConfigFromNVRAM(void) +{ + static struct ppcbug_nvram nvram; + static char ip_address[INET_ADDRSTRLEN]; + static char ip_netmask[INET_ADDRSTRLEN]; + static char server[INET_ADDRSTRLEN]; + static char gateway[INET_ADDRSTRLEN]; + + if (rtems_bsdnet_config.bootp != NULL) + return; + + /* + * Get network configuation from PPCBUG. + * The 'correct' way to do this would be to issue a .NETCFIG PPCBUG + * system call. Unfortunately it is very difficult to issue such a + * call once RTEMS is up and running so we just copy from the 'known' + * location of the network configuration parameters. + * Care must be taken to access the NVRAM a byte at a time. + */ + +#if defined(NVRAM_INDIRECT) + { + volatile char *addrLo = (volatile char *)0x80000074; + volatile char *addrHi = (volatile char *)0x80000075; + volatile char *data = (volatile char *)0x80000077; + int addr = 0x1000; + char *d = (char *)&nvram; + + while (d < ((char *)&nvram + sizeof nvram)) { + *addrLo = addr & 0xFF; + *addrHi = (addr >> 8) & 0xFF; + *d++ = *data; + addr++; + } + } +#else + { + volatile char *s = (volatile char *)0xFFE81000; + char *d = (char *)&nvram; + + while (d < ((char *)&nvram + sizeof nvram)) + *d++ = *s++; + } +#endif + /* + * Assume that the boot server is also the name, log and ntp server! + */ + rtems_bsdnet_config.name_server[0] = + rtems_bsdnet_config.ntp_server[0] = + rtems_bsdnet_bootp_server_name = addr(server, nvram.ServerIPAddress); + rtems_bsdnet_bootp_server_address.s_addr = nvram.ServerIPAddress; + /* + * Nothing better to use as host name! + */ + rtems_bsdnet_config.ifconfig->ip_address = + rtems_bsdnet_config.hostname = addr(ip_address, nvram.ClientIPAddress); + + rtems_bsdnet_config.gateway = addr(gateway, nvram.GatewayIPAddress); + rtems_bsdnet_config.ifconfig->ip_netmask = addr(ip_netmask, nvram.SubnetIPAddressMask); + + rtems_bsdnet_bootp_boot_file_name = nvram.BootFilenameString; + rtems_bsdnet_bootp_cmdline = nvram.ArgumentFilenameString; + splitRtemsBsdnetBootpCmdline(); +} + +#elif defined(__mcf528x__) + +static char * +env(const char *parm, const char *defaultValue) +{ + const char *cp = bsp_getbenv(parm); + + if (!cp) { + if (!defaultValue) + return NULL; + cp = defaultValue; + printf ("%s environment variable missing -- using %s.\n", parm, cp); + } + return epicsStrDup(cp); +} + +void +setBootConfigFromNVRAM(void) +{ + const char *cp1; + + if (rtems_bsdnet_config.bootp != NULL) + return; + rtems_bsdnet_config.gateway = env("GATEWAY", NULL); + rtems_bsdnet_config.ifconfig->ip_netmask = env("NETMASK", "255.255.252.0"); + + rtems_bsdnet_bootp_server_name = env("SERVER", "192.168.0.1"); + rtems_bsdnet_config.name_server[0] = env("NAMESERVER", rtems_bsdnet_bootp_server_name); + rtems_bsdnet_config.ntp_server[0] = env("NTPSERVER", rtems_bsdnet_bootp_server_name); + cp1 = env("DOMAIN", NULL); + if (cp1 != NULL) + rtems_bsdnet_config.domainname = cp1; + rtems_bsdnet_config.hostname = env("HOSTNAME", "iocNobody"); + rtems_bsdnet_config.ifconfig->ip_address = env("IPADDR0", "192.168.0.2"); + rtems_bsdnet_bootp_boot_file_name = env("BOOTFILE", "uC5282App.boot"); + rtems_bsdnet_bootp_cmdline = env("CMDLINE", "epics/iocBoot/iocNobody/st.cmd"); + splitNfsMountPath(env("NFSMOUNT", NULL)); + if ((cp1 = env("TZ", NULL)) != NULL) + epicsEnvSet("TZ", cp1); +} + +#else +/* + * Placeholder for systems without NVRAM + */ +void +setBootConfigFromNVRAM(void) +{ + printf("SYSTEM HAS NO NON-VOLATILE RAM!\n"); + printf("YOU MUST USE SOME OTHER METHOD TO OBTAIN NETWORK CONFIGURATION\n"); +} +#endif diff --git a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS-kernel/devLibVMEOSD.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c rename to modules/libcom/src/osi/os/RTEMS-kernel/devLibVMEOSD.c diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp b/modules/libcom/src/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp rename to modules/libcom/src/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h b/modules/libcom/src/osi/os/RTEMS-kernel/epicsAtomicOSD.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h rename to modules/libcom/src/osi/os/RTEMS-kernel/epicsAtomicOSD.h diff --git a/modules/libcom/src/osi/os/RTEMS/epicsMath.h b/modules/libcom/src/osi/os/RTEMS-kernel/epicsMath.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsMath.h rename to modules/libcom/src/osi/os/RTEMS-kernel/epicsMath.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdEnv.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdEnv.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEnv.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdEnv.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdEvent.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdEvent.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdEvent.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdEvent.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdFindSymbol.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdFindSymbol.c diff --git a/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c new file mode 100644 index 000000000..c7a05fcc5 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.c @@ -0,0 +1,251 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * We want to access information which is + * normally hidden from application programs. + */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 + +#define epicsExportSharedSymbols +#include +#include +#include +#include +#include +#include +#include "epicsMessageQueue.h" +#include "errlog.h" + +LIBCOM_API epicsMessageQueueId epicsStdCall +epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize) +{ + rtems_status_code sc; + epicsMessageQueueId id = calloc(1, sizeof(*id)); + rtems_interrupt_level level; + static char c1 = 'a'; + static char c2 = 'a'; + static char c3 = 'a'; + + if(!id) + return NULL; + + sc = rtems_message_queue_create (rtems_build_name ('Q', c3, c2, c1), + capacity, + maximumMessageSize, + RTEMS_FIFO|RTEMS_LOCAL, + &id->id); + if (sc != RTEMS_SUCCESSFUL) { + free(id); + errlogPrintf ("Can't create message queue: %s\n", rtems_status_text (sc)); + return NULL; + } + id->maxSize = maximumMessageSize; + id->localBuf = NULL; + rtems_interrupt_disable (level); + if (c1 == 'z') { + if (c2 == 'z') { + if (c3 == 'z') { + c3 = 'a'; + } + else { + c3++; + } + c2 = 'a'; + } + else { + c2++; + } + c1 = 'a'; + } + else { + c1++; + } + rtems_interrupt_enable (level); + return id; +} + +static rtems_status_code rtems_message_queue_send_timeout( + rtems_id id, + void *buffer, + uint32_t size, + rtems_interval timeout) +{ + Message_queue_Control *the_message_queue; + Objects_Locations location; + CORE_message_queue_Status msg_status; + + the_message_queue = _Message_queue_Get( id, &location ); + switch ( location ) + { + case OBJECTS_ERROR: + return RTEMS_INVALID_ID; + + case OBJECTS_LOCAL: + msg_status = _CORE_message_queue_Send( + &the_message_queue->message_queue, + buffer, + size, + id, + NULL, + 1, + timeout + ); + + _Thread_Enable_dispatch(); + + /* + * If we had to block, then this is where the task returns + * after it wakes up. The returned status is correct for + * non-blocking operations but if we blocked, then we need + * to look at the status in our TCB. + */ + + if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT ) + msg_status = _Thread_Executing->Wait.return_code; + return _Message_queue_Translate_core_message_queue_return_code( msg_status ); + } + return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */ +} + +LIBCOM_API int epicsStdCall epicsMessageQueueSend( + epicsMessageQueueId id, + void *message, + unsigned int messageSize) +{ + if (rtems_message_queue_send_timeout(id->id, message, messageSize, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL) + return 0; + else + return -1; +} + +LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int messageSize, + double timeout) +{ + rtems_interval delay; + extern double rtemsTicksPerSecond_double; + + /* + * Convert time to ticks + */ + if (timeout <= 0.0) + return epicsMessageQueueTrySend(id, message, messageSize); + delay = (int)(timeout * rtemsTicksPerSecond_double); + if (delay == 0) + delay++; + if (rtems_message_queue_send_timeout(id->id, message, messageSize, delay) == RTEMS_SUCCESSFUL) + return 0; + else + return -1; +} + +static int receiveMessage( + epicsMessageQueueId id, + void *buffer, + uint32_t size, + uint32_t wait, + rtems_interval delay) +{ + size_t rsize; + rtems_status_code sc; + + if (size < id->maxSize) { + if (id->localBuf == NULL) { + id->localBuf = malloc(id->maxSize); + if (id->localBuf == NULL) + return -1; + } + rsize = receiveMessage(id, id->localBuf, id->maxSize, wait, delay); + if (rsize > size) + return -1; + memcpy(buffer, id->localBuf, rsize); + } + else { + sc = rtems_message_queue_receive(id->id, buffer, &rsize, wait, delay); + if (sc != RTEMS_SUCCESSFUL) + return -1; + } + return rsize; +} + +LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive( + epicsMessageQueueId id, + void *message, + unsigned int size) +{ + return receiveMessage(id, message, size, RTEMS_NO_WAIT, 0); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueReceive( + epicsMessageQueueId id, + void *message, + unsigned int size) +{ + return receiveMessage(id, message, size, RTEMS_WAIT, RTEMS_NO_TIMEOUT); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int size, + double timeout) +{ + rtems_interval delay; + uint32_t wait; + extern double rtemsTicksPerSecond_double; + + /* + * Convert time to ticks + */ + if (timeout <= 0.0) { + wait = RTEMS_NO_WAIT; + delay = 0; + } + else { + wait = RTEMS_WAIT; + delay = (int)(timeout * rtemsTicksPerSecond_double); + if (delay == 0) + delay++; + } + return receiveMessage(id, message, size, wait, delay); +} + +LIBCOM_API int epicsStdCall epicsMessageQueuePending( + epicsMessageQueueId id) +{ + uint32_t count; + rtems_status_code sc; + + sc = rtems_message_queue_get_number_pending(id->id, &count); + if (sc != RTEMS_SUCCESSFUL) { + errlogPrintf("Message queue %x get number pending failed: %s\n", + (unsigned int)id, + rtems_status_text(sc)); + return -1; + } + return count; +} + +LIBCOM_API void epicsStdCall epicsMessageQueueShow( + epicsMessageQueueId id, + int level) +{ + int pending = epicsMessageQueuePending(id); + if (pending >= 0) + printf ("Message queue %lx -- Pending: %d\n", (unsigned long)id, pending); +} diff --git a/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h new file mode 100644 index 000000000..0244a1f0b --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-kernel/osdMessageQueue.h @@ -0,0 +1,29 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * Very thin shims around RTEMS routines + */ +#include + +struct epicsMessageQueueOSD { + rtems_id id; + unsigned int maxSize; + void *localBuf; + +}; +#define epicsMessageQueueDestroy(q) (rtems_message_queue_delete((q)->id)) + +#define epicsMessageQueueTrySend(q,m,l) (rtems_message_queue_send((q)->id, (m), (l)) == RTEMS_SUCCESSFUL ? 0 : -1) diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdMutex.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdMutex.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdMutex.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdMutex.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdPoolStatus.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdPoolStatus.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdProcess.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdProcess.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdProcess.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdProcess.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdReadline.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdReadline.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdReadline.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdReadline.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdSignal.cpp b/modules/libcom/src/osi/os/RTEMS-kernel/osdSignal.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSignal.cpp rename to modules/libcom/src/osi/os/RTEMS-kernel/osdSignal.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdSock.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdSock.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSock.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdSock.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdSpin.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdSpin.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSpin.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdSpin.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdStrtod.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdStrtod.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdStrtod.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdStrtod.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdThread.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThread.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdThread.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdThread.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThread.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdThread.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c b/modules/libcom/src/osi/os/RTEMS-kernel/osdThreadExtra.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c rename to modules/libcom/src/osi/os/RTEMS-kernel/osdThreadExtra.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.cpp b/modules/libcom/src/osi/os/RTEMS-kernel/osdTime.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.cpp rename to modules/libcom/src/osi/os/RTEMS-kernel/osdTime.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.h b/modules/libcom/src/osi/os/RTEMS-kernel/osdTime.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osdTime.h diff --git a/modules/libcom/src/osi/os/RTEMS/osiUnistd.h b/modules/libcom/src/osi/os/RTEMS-kernel/osiUnistd.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osiUnistd.h rename to modules/libcom/src/osi/os/RTEMS-kernel/osiUnistd.h diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c new file mode 100644 index 000000000..3774ef2d8 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c @@ -0,0 +1,160 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * We want to access information which is + * normally hidden from application programs. + */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 + +#define epicsExportSharedSymbols +#include +#include +#include +#include +#include +#include +#include "epicsMessageQueue.h" +#include "errlog.h" +#include + +#include +#include +#include + +LIBCOM_API epicsMessageQueueId epicsStdCall +epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize) +{ + struct mq_attr the_attr; + epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id)); + + epicsAtomicIncrIntT(&id->idCnt); + sprintf(id->name, "MQ_%01d", epicsAtomicGetIntT(&id->idCnt)); + the_attr.mq_maxmsg = capacity; + the_attr.mq_msgsize = maximumMessageSize; + id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr); + if (id->id <0) { + fprintf (stderr, "Can't create message queue: %s\n", strerror (errno)); + return NULL; + } + return id; +} + +LIBCOM_API void epicsStdCall epicsMessageQueueDestroy( + epicsMessageQueueId id) +{ + int rv; + rv = mq_close(id->id); + if( rv ) { + fprintf(stderr, "epicsMessageQueueDestroy mq_close failed: %s\n", + strerror(rv)); + } + rv = mq_unlink(id->name); + if( rv ) { + fprintf(stderr,"epicsMessageQueueDestroy mq_unlink %s failed: %s\n", + id->name, strerror(rv)); + } + free(id); +} + + +LIBCOM_API int epicsStdCall epicsMessageQueueTrySend( + epicsMessageQueueId id, + void *message, + unsigned int messageSize) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int messageSize, + double timeout) +{ + struct timespec ts; + unsigned long micros; + + // assume timeout in sec + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive( + epicsMessageQueueId id, + void *message, + unsigned int size) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int size, + double timeout) +{ + unsigned long micros; + struct timespec ts; + + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueuePending( + epicsMessageQueueId id) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + return -1; + } + return the_attr.mq_curmsgs; +} +LIBCOM_API void epicsStdCall epicsMessageQueueShow( + epicsMessageQueueId id, + int level) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + } + + printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg); + if (level >= 1) + printf(" Maximum size:%lu", the_attr.mq_msgsize); + + printf("\n"); +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h new file mode 100644 index 000000000..0311ee486 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h @@ -0,0 +1,29 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * Very thin shims around RTEMS routines + */ +#include +#include + +struct epicsMessageQueueOSD { + mqd_t id; + char name[24]; + int idCnt; + +}; +#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0)) +#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL)) \ No newline at end of file diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c new file mode 100644 index 000000000..09b02e0a2 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c @@ -0,0 +1,6 @@ +#include +#include +#include +#include + +#include "../posix/osdMutex.c" \ No newline at end of file diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c new file mode 100644 index 000000000..43d2e2b28 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c @@ -0,0 +1,27 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#include +#include +#include +#define epicsExportSharedSymbols +#include "osiPoolStatus.h" + +/* + * osiSufficentSpaceInPool () + */ +LIBCOM_API int epicsStdCall osiSufficentSpaceInPool ( size_t contiguousBlockSize ) +{ + unsigned long n; + Heap_Information_block info; + + malloc_info( &info ); + n = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + return (n > (50000 + contiguousBlockSize)); +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h new file mode 100644 index 000000000..e5568fc1b --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h @@ -0,0 +1,81 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Linux specific socket include + */ + +#ifndef osdSockH +#define osdSockH + +#include + +#include +#include /* for MAXHOSTNAMELEN */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* close() and others */ + + +typedef int SOCKET; +#define INVALID_SOCKET (-1) +#define SOCKERRNO errno +#define socket_ioctl(A,B,C) ioctl(A,B,C) +typedef int osiSockIoctl_t; +typedef socklen_t osiSocklen_t; +typedef int osiSockOptMcastLoop_t; +typedef int osiSockOptMcastTTL_t; + +#define FD_IN_FDSET(FD) ((FD)ifr_name)) + +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED 5000 +#endif + +#endif /*osdSockH*/