summaryrefslogtreecommitdiff
path: root/cesar/hal/leon/maximus
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/hal/leon/maximus')
-rw-r--r--cesar/hal/leon/maximus/Module5
-rw-r--r--cesar/hal/leon/maximus/inc/maximus_interrupts.h20
-rw-r--r--cesar/hal/leon/maximus/inc/maximus_timer.h24
-rw-r--r--cesar/hal/leon/maximus/inc/maximus_timer_ctx.h53
-rw-r--r--cesar/hal/leon/maximus/inc/maximus_trace.h58
-rw-r--r--cesar/hal/leon/maximus/src/maximus_timer.c258
-rw-r--r--cesar/hal/leon/maximus/src/maximus_trace.c42
-rw-r--r--cesar/hal/leon/maximus/test/Config3
-rw-r--r--cesar/hal/leon/maximus/test/Makefile8
-rw-r--r--cesar/hal/leon/maximus/test/inc/test_maximus_timer.h40
-rw-r--r--cesar/hal/leon/maximus/test/src/test_maximus_timer.c306
11 files changed, 817 insertions, 0 deletions
diff --git a/cesar/hal/leon/maximus/Module b/cesar/hal/leon/maximus/Module
new file mode 100644
index 0000000000..79da1d4958
--- /dev/null
+++ b/cesar/hal/leon/maximus/Module
@@ -0,0 +1,5 @@
+SOURCES := maximus_timer.c
+
+ifeq ($(CONFIG_TRACE),y)
+SOURCES += maximus_trace.c
+endif \ No newline at end of file
diff --git a/cesar/hal/leon/maximus/inc/maximus_interrupts.h b/cesar/hal/leon/maximus/inc/maximus_interrupts.h
new file mode 100644
index 0000000000..62d23e6d2a
--- /dev/null
+++ b/cesar/hal/leon/maximus/inc/maximus_interrupts.h
@@ -0,0 +1,20 @@
+#ifndef hal_leon_maximus_inc_maximus_interrupts_h
+#define hal_leon_maximus_inc_maximus_interrupts_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/inc/maximus_interrupts.h
+ * \brief HAL interrupt register definition for Maximus.
+ * \ingroup hal_leon_maximus
+ */
+
+#define HAL_LEON_TIMER_INTERRUPT 9
+
+#define HAL_LEON_TIMER_INTERRUPT_PRIORITY 1 /* is it the right value? */
+
+#endif /* hal_leon_maximus_inc_maximus_interrupts_h */
diff --git a/cesar/hal/leon/maximus/inc/maximus_timer.h b/cesar/hal/leon/maximus/inc/maximus_timer.h
new file mode 100644
index 0000000000..21c51f7637
--- /dev/null
+++ b/cesar/hal/leon/maximus/inc/maximus_timer.h
@@ -0,0 +1,24 @@
+#ifndef hal_leon_maximus_inc_maximus_timer_h
+#define hal_leon_maximus_inc_maximus_timer_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/inc/maximus_timer.h
+ * \brief Hardware Abstact Layer for the Leon timer 2 for Maximus.
+ * \ingroup hal_leon_maximus
+ */
+
+/**
+ * Maximus leon timer program callback called when the corresponding netclock message is received.
+ * \param data pointer to 'leon_timer_t' structure.
+ * set errno to:
+ * - EINVAL if data or ctx->cb are null
+ */
+void maximus_leon_timer_cb (void *data);
+
+#endif /* hal_leon_maximus_inc_maximus_timer_h */
diff --git a/cesar/hal/leon/maximus/inc/maximus_timer_ctx.h b/cesar/hal/leon/maximus/inc/maximus_timer_ctx.h
new file mode 100644
index 0000000000..0ae1b6af19
--- /dev/null
+++ b/cesar/hal/leon/maximus/inc/maximus_timer_ctx.h
@@ -0,0 +1,53 @@
+#ifndef hal_leon_maximus_inc_maximus_timer_ctx_h
+#define hal_leon_maximus_inc_maximus_timer_ctx_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus_inc/maximus_timer_ctx.h
+ * \brief Leon Timer context for Maximus.
+ * \ingroup hal_leon_maximus
+ *
+ */
+
+#include "hal/leon/timer.h" // for 'leon_timer_cb_t'
+#include "host/netclock.h" // for 'netclock_id_t' and 'netclock_callback_t'
+#include "hal/leon/maximus/inc/maximus_trace.h"
+#ifdef ECOS
+#include <cyg/hal/drv_api.h>
+#endif /* ECOS */
+
+struct leon_timer_t
+{
+ /** Indicates the Leon timer status. false == stopped, true == launched. */
+ bool status;
+ /** Function callback to call. */
+ leon_timer_cb_t cb;
+ /** Callback user data. */
+ void *user_data;
+
+ /** Set to true to enable assertions on WARNING messages. */
+ bool warning_assert;
+ /** Id of netclock message sent by 'leon_timer_program()'. */
+ netclock_id_t netclock_id;
+ /** Callback context to insert into callback queue. */
+ netclock_callback_t *netclock_cb;
+
+#ifdef ECOS
+ /** leon timer interrupt descriptor for eCos */
+ cyg_interrupt it_timer;
+ /** leon timer interrupt handle */
+ cyg_handle_t it_handle;
+#endif /* ECOS */
+
+#if CONFIG_TRACE
+ /** PHY trace. */
+ trace_buffer_t trace;
+#endif /* CONFIG_TRACE */
+};
+
+#endif /* hal_leon_maximus_inc_maximus_timer_ctx_h */
diff --git a/cesar/hal/leon/maximus/inc/maximus_trace.h b/cesar/hal/leon/maximus/inc/maximus_trace.h
new file mode 100644
index 0000000000..880f43f632
--- /dev/null
+++ b/cesar/hal/leon/maximus/inc/maximus_trace.h
@@ -0,0 +1,58 @@
+#ifndef hal_leon_maximus_inc_trace_h
+#define hal_leon_maximus_inc_trace_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/inc/trace.h
+ * \brief Define leon timer trace events.
+ * \ingroup hal_leon_maximus
+ */
+#include "lib/trace.h"
+
+/** Shortcut for tracing inside Maximus. */
+#define MAXIMUS_LEON_TIMER_TRACE(id, args...) \
+ TRACE_FAST_SHORT (MAXIMUS_LEON_TIMER_TRACE_, &ctx->trace, id, ## args)
+
+#if CONFIG_TRACE
+
+enum
+{
+ MAXIMUS_LEON_TIMER_TRACE_INIT,
+ MAXIMUS_LEON_TIMER_TRACE_UNINIT,
+ MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_PROGRAM,
+ MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_CANCEL,
+ MAXIMUS_LEON_TIMER_TRACE_DEFERRED_CB,
+ MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_CB,
+};
+
+BEGIN_DECLS
+
+/**
+ * Initialise trace buffer.
+ * \param ctx phy context
+ */
+void
+maximus_leon_timer_trace_init (leon_timer_t *ctx);
+
+/**
+ * Uninitialise trace buffer.
+ * \param ctx phy context
+ */
+void
+maximus_leon_timer_trace_uninit (leon_timer_t *ctx);
+
+END_DECLS
+
+#else /* !CONFIG_TRACE */
+
+# define maximus_leon_timer_trace_init(ctx) ((void) 0)
+# define maximus_leon_timer_trace_uninit(ctx) ((void) 0)
+
+#endif /* !CONFIG_TRACE */
+
+#endif /* hal_leon_maximus_inc_trace_h */
diff --git a/cesar/hal/leon/maximus/src/maximus_timer.c b/cesar/hal/leon/maximus/src/maximus_timer.c
new file mode 100644
index 0000000000..8a1eeb771f
--- /dev/null
+++ b/cesar/hal/leon/maximus/src/maximus_timer.c
@@ -0,0 +1,258 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/src/maximus_timer.c
+ * \brief Hardware Abstact Layer for the Leon timer 2 for Maximus.
+ * \ingroup hal_leon_maximus
+ */
+
+#include "common/std.h"
+#include "ecos/packages/hal/maximus/arch/current/include/hal_host_intr.h"
+#include "hal/leon/maximus/inc/maximus_interrupts.h" // for 'HAL_LEON_TIMER_INTERRUPT_IPMBOX' and 'HAL_LEON_TIMER_INTERRUPT_PRIORITY'
+#include "hal/leon/maximus/inc/maximus_timer.h"
+#include "hal/leon/maximus/inc/maximus_timer_ctx.h"
+#include <errno.h>
+
+#ifdef ECOS
+static cyg_uint32 _leon_timer_ecos_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ // needed for traces
+ leon_timer_t *ctx;
+ ctx = (leon_timer_t *)data;
+ dbg_assert(ctx);
+
+ cyg_drv_interrupt_mask(HAL_LEON_TIMER_INTERRUPT);
+ cyg_drv_interrupt_acknowledge(HAL_LEON_TIMER_INTERRUPT);
+ MAXIMUS_LEON_TIMER_TRACE (LEON_TIMER_CB);
+ return CYG_ISR_CALL_DSR; // cause DSR to be run
+}
+
+static void _leon_timer_ecos_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ /* nothing to do except calling the leon timer dsr */
+ leon_timer_t *ctx;
+ ctx = (leon_timer_t *)data;
+ dbg_assert(ctx->cb);
+ if (NULL != ctx->cb)
+ {
+ MAXIMUS_LEON_TIMER_TRACE (DEFERRED_CB);
+ (*ctx->cb)(ctx->user_data);
+ }
+ cyg_drv_interrupt_unmask(HAL_LEON_TIMER_INTERRUPT);
+ return;
+}
+#endif /* ECOS */
+
+/**
+ * Initialise Leon timer.
+ * \param user_data user data passed to the callback
+ * \param cb timer callback, called in ISR context
+ * \param phy phy context used to get the phy date (not used for Maximus)
+ * \return the newly created context
+ * set errno to:
+ * - EINVAL if user_data or cb are null
+ */
+leon_timer_t *
+leon_timer_init (void *user_data, leon_timer_cb_t cb, phy_t *phy)
+{
+ /* Set the user_data value of leon timer context.
+ * Set the cb value of leon timer context. */
+
+ static leon_timer_t ctx;
+
+ static netclock_callback_t netclock_cb;
+
+ dbg_assert_ptr(user_data);
+ dbg_assert_ptr(cb);
+ if ((NULL == user_data)
+ || (NULL == cb))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ memset(&ctx, '\0', sizeof(leon_timer_t));
+ ctx.user_data = user_data;
+ ctx.cb = cb;
+ ctx.netclock_cb = &netclock_cb;
+
+#ifdef ECOS
+ // register the leon timer ISR and DSR into eCos
+ cyg_drv_interrupt_create(HAL_LEON_TIMER_INTERRUPT,
+ HAL_LEON_TIMER_INTERRUPT_PRIORITY,
+ (cyg_addrword_t)&ctx,
+ _leon_timer_ecos_isr,
+ _leon_timer_ecos_dsr,
+ &ctx.it_handle,
+ &ctx.it_timer);
+ cyg_drv_interrupt_attach(ctx.it_handle);
+ cyg_drv_interrupt_unmask(HAL_LEON_TIMER_INTERRUPT);
+#endif /* ECOS */
+
+ maximus_leon_timer_trace_init (&ctx);
+ TRACE_FAST_SHORT (MAXIMUS_LEON_TIMER_TRACE_, &ctx.trace, INIT);
+ }
+
+ return &ctx;
+}
+
+/**
+ * Uninitialise the Leon timer.
+ * \param ctx Leon timer context
+ */
+void
+leon_timer_uninit (leon_timer_t *ctx)
+{
+ dbg_assert_ptr(ctx);
+ if (NULL == ctx)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ MAXIMUS_LEON_TIMER_TRACE (UNINIT);
+
+ // unschedule sent netclock message
+ leon_timer_cancel(ctx);
+
+ maximus_leon_timer_trace_uninit(ctx);
+
+ // reset leon timer context
+ memset(ctx, '\0', sizeof(leon_timer_t));
+ }
+}
+
+/**
+ * Program the timer to the given date.
+ * \param ctx Leon timer context
+ * \param sysdate timer expiration date
+ * set errno to:
+ * - EINVAL if ctx is null
+ */
+void
+leon_timer_program (leon_timer_t *ctx, u32 sysdate)
+{
+ dbg_assert_ptr(ctx);
+ if (NULL == ctx)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ leon_timer_cancel(ctx);
+
+ MAXIMUS_LEON_TIMER_TRACE (LEON_TIMER_PROGRAM, sysdate);
+
+ /* Send a netclock message to Maximus simulator scheduled at the given date. */
+
+ if (-1 == netclock_schedule(my_station.netclock,
+ ctx->netclock_cb,
+ NETWORK_CLOCK_TYPE_STATION,
+ sysdate,
+ &maximus_leon_timer_cb,
+ (void*)ctx,
+ &ctx->netclock_id))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when scheduling a netclock message", errno);
+ }
+
+ // indicates that the leon timer is launched
+ ctx->status = true;
+ }
+}
+
+/**
+ * Cancel timer programmation.
+ * \param ctx Leon timer context
+ * set errno to:
+ * - EINVAL if ctx is null
+ */
+void
+leon_timer_cancel (leon_timer_t *ctx)
+{
+ dbg_assert_ptr(ctx);
+ if(NULL == ctx)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ MAXIMUS_LEON_TIMER_TRACE (LEON_TIMER_CANCEL);
+
+ /* Send a netclock message to Maximus simulator
+ * to unschedule the event sent in the previous function ('leon_timer_program()')
+ * according to ctx->netclok_id. */
+
+ if (0 != ctx->netclock_id)
+ {
+ if (-1 == netclock_unschedule(my_station.netclock, ctx->netclock_id))
+ {
+ if (ctx->warning_assert)
+ {
+ station_log(&my_station, STATION_LOG_WARNING, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d when unscheduling a netclock message", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when unscheduling a netclock message", errno);
+ }
+ }
+ ctx->netclock_id = 0;
+
+ // indicates that the leon timer is stopped
+ ctx->status = false;
+ }
+ }
+}
+
+/**
+ * Maximus leon timer program callback called when the corresponding netclock message is received.
+ * \param data pointer to 'leon_timer_t' structure.
+ * set errno to:
+ * - EINVAL if data or ctx->cb are null
+ */
+void maximus_leon_timer_cb (void *data)
+{
+ /* HAL leon timer calls the 'ctx->cb' when leon timer expires. */
+
+ dbg_assert_ptr(data);
+ if (NULL == data)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ leon_timer_t *ctx = (leon_timer_t*)data;
+
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(ctx->cb);
+ if ((NULL == ctx)
+ || (NULL == ctx->cb))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_LEON_TIMER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ maximus_pending_isrs |= (1 << HAL_LEON_TIMER_INTERRUPT);
+
+ // indicates that the leon timer is stopped
+ ctx->status = false;
+ }
+ }
+}
diff --git a/cesar/hal/leon/maximus/src/maximus_trace.c b/cesar/hal/leon/maximus/src/maximus_trace.c
new file mode 100644
index 0000000000..28ee4d13f7
--- /dev/null
+++ b/cesar/hal/leon/maximus/src/maximus_trace.c
@@ -0,0 +1,42 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/src/maximus_trace.c
+ * \brief Define leon timer trace events.
+ * \ingroup hal_leon_maximus
+ */
+#include "common/std.h"
+
+#include "inc/maximus_timer_ctx.h"
+
+void
+maximus_leon_timer_trace_init (leon_timer_t *ctx)
+{
+ static trace_namespace_t namespace;
+ static const trace_event_id_t event_ids[] =
+ {
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_INIT, "init"),
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_UNINIT, "uninit"),
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_PROGRAM,
+ "leon timer program %x"),
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_CANCEL, "leon timer cancel"),
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_DEFERRED_CB, "deferred cb"),
+ TRACE_EVENT (MAXIMUS_LEON_TIMER_TRACE_LEON_TIMER_CB, "leon timer cb"),
+ };
+ dbg_assert (ctx);
+ trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
+ trace_buffer_add (&ctx->trace, "leon timer", 8, 4, true, &namespace);
+}
+
+void
+maximus_leon_timer_trace_uninit (leon_timer_t *ctx)
+{
+ dbg_assert (ctx);
+ trace_buffer_remove (&ctx->trace);
+}
+
diff --git a/cesar/hal/leon/maximus/test/Config b/cesar/hal/leon/maximus/test/Config
new file mode 100644
index 0000000000..cba3c8284a
--- /dev/null
+++ b/cesar/hal/leon/maximus/test/Config
@@ -0,0 +1,3 @@
+CONFIG_DEBUG = y
+CONFIG_DEBUG_FATAL_CATCH = y
+CONFIG_TRACE = y \ No newline at end of file
diff --git a/cesar/hal/leon/maximus/test/Makefile b/cesar/hal/leon/maximus/test/Makefile
new file mode 100644
index 0000000000..305256daea
--- /dev/null
+++ b/cesar/hal/leon/maximus/test/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../../..
+EXTRA_HOST_CFLAGS+= -DUNIT_TEST
+HOST_PROGRAMS = test_maximus_timer
+test_maximus_timer_SOURCES = test_maximus_timer.c
+test_maximus_timer_MODULES = lib host hal/leon/maximus
+INCLUDES = hal/leon/maximus/test/inc
+
+include $(BASE)/common/make/top.mk \ No newline at end of file
diff --git a/cesar/hal/leon/maximus/test/inc/test_maximus_timer.h b/cesar/hal/leon/maximus/test/inc/test_maximus_timer.h
new file mode 100644
index 0000000000..ff8a323380
--- /dev/null
+++ b/cesar/hal/leon/maximus/test/inc/test_maximus_timer.h
@@ -0,0 +1,40 @@
+#ifndef hal_leon_maximus_test_inc_test_maximus_timer_h
+#define hal_leon_maximus_test_inc_test_maximus_timer_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/test/inc/test_maximus_timer.h
+ * \brief test header for Maximus.
+ * \ingroup hal_leon_maximus
+ */
+
+#include "host/fwd.h" // for 'station_ctx_t'
+
+/**
+ * DSR callback function.
+ * \param user_data user data
+ */
+void
+leon_timer_cb (void *user_data);
+
+/**
+ * Open pipe or socket.
+ * \param station pointer to the station context
+ * \return file descriptor for pipe or socket
+ */
+int
+maximus_timer_open (station_ctx_t *station);
+
+/**
+ * Close pipe.
+ * \param fd file descriptor for pipe or socket
+ */
+void
+maximus_timer_close (int fd);
+
+#endif /* hal_leon_maximus_test_inc_test_maximus_timer_h */
diff --git a/cesar/hal/leon/maximus/test/src/test_maximus_timer.c b/cesar/hal/leon/maximus/test/src/test_maximus_timer.c
new file mode 100644
index 0000000000..2702717174
--- /dev/null
+++ b/cesar/hal/leon/maximus/test/src/test_maximus_timer.c
@@ -0,0 +1,306 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/leon/maximus/test/src/test_maximus_timer.c
+ * \brief HAL leon timer test functions for Maximus.
+ * \ingroup hal_leon_maximus
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/trace.h"
+#include "hal/leon/maximus/inc/maximus_timer_ctx.h"
+#include "hal/leon/maximus/inc/maximus_timer.h"
+#include "hal/leon/maximus/inc/maximus_interrupts.h"
+#include "hal/leon/maximus/test/inc/test_maximus_timer.h"
+#include <stdio.h> // for 'printf'
+#include <string.h> // for 'memset'
+#include <netinet/in.h> // for 'ntohl' and 'ntohs' functions
+#include <unistd.h> // for 'read', 'open()' and 'close()'
+#include <fcntl.h> // for 'read', 'open()' and 'close()'
+#include <errno.h>
+
+#include "hal/phy/phy.h"
+
+void leon_timer_test_suite (test_t t);
+
+uint32_t maximus_pending_isrs;
+station_ctx_t my_station;
+leon_timer_t *ctx;
+phy_t *phy;
+
+void
+leon_timer_cb (void *user_data)
+{
+ int *my_data = (int *)user_data;
+ *my_data = 987654321;
+ return;
+}
+
+int
+maximus_timer_open (station_ctx_t *station)
+{
+ int fd;
+
+ #ifdef STATION_SOCK
+ fd = station->sock_pair_fd;
+ #else /* STATION_SOCK */
+ fd = open(station->pipe_out_name, O_RDONLY);
+ #endif /* STATION_SOCK */
+
+ return fd;
+}
+
+void
+maximus_timer_close (int fd)
+{
+ #ifndef STATION_SOCK
+ close(fd);
+ #endif /* !STATION_SOCK */
+}
+
+void
+leon_timer_init_test_case(test_t t)
+{
+ int user_data = 123456789;
+
+ printf("init\n");
+ phy = blk_alloc ();
+ test_case_begin(t, "init");
+
+ test_begin(t, "init")
+ {
+ ctx = leon_timer_init ((void *)&user_data, &leon_timer_cb, phy);
+ test_fail_unless ((EINVAL != errno)
+ && (NULL != ctx)
+ && (user_data == *((int *)ctx->user_data))
+ && (&leon_timer_cb == ctx->cb));
+ ctx->warning_assert = true;
+ } test_end;
+
+ test_begin(t, "cb")
+ {
+ (*ctx->cb)(ctx->user_data);
+ test_fail_unless (987654321 == *((int *)ctx->user_data));
+ } test_end;
+
+ maximus_pending_isrs = 0;
+
+ return;
+}
+
+void leon_timer_program_test_case(test_t t)
+{
+ u32 date = 0xDEADBEEE;
+ netclock_id_t id = 0;
+
+ printf("leon timer program\n");
+ test_case_begin(t, "leon timer program");
+
+ leon_timer_program (ctx, date);
+
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "netclock message")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_timer_open(&my_station);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock tick value
+ test_fail_unless (date == ntohl(netclock_hdr->tick_low));
+
+ // check netclock id for 'leon_timer_cancel()'
+ test_fail_unless (ntohs(netclock_hdr->id) == ctx->netclock_id);
+
+ // close pipe
+ maximus_timer_close(fd_in);
+ } test_end;
+
+ // test the callback
+ test_begin(t, "maximus leon timer cb")
+ {
+ maximus_leon_timer_cb ((void*)ctx);
+ test_fail_unless ((EINVAL != errno)
+ && (maximus_pending_isrs & (1 << HAL_LEON_TIMER_INTERRUPT)));
+ } test_end;
+
+ test_begin(t, "leon timer cb")
+ {
+ test_fail_unless (NULL != ctx->cb);
+ (*ctx->cb)(ctx->user_data);
+ maximus_pending_isrs &= (0 << HAL_LEON_TIMER_INTERRUPT);
+ } test_end;
+
+ id = ctx->netclock_id;
+ leon_timer_program (ctx, date+1);
+
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "cancel netclock message")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_timer_open(&my_station);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock id
+ test_fail_unless (ntohs(netclock_hdr->id) == id);
+
+ // close pipe
+ maximus_timer_close(fd_in);
+ } test_end;
+
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "program netclock message")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_timer_open(&my_station);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock tick value
+ test_fail_unless (date+1 == ntohl(netclock_hdr->tick_low));
+
+ // check netclock id for 'phy_access_timer_cancel'
+ test_fail_unless (ntohs(netclock_hdr->id) == ctx->netclock_id);
+
+ // close pipe
+ maximus_timer_close(fd_in);
+ } test_end;
+
+ return;
+}
+
+void leon_timer_cancel_test_case(test_t t)
+{
+ netclock_id_t id = 0;
+
+ printf("leon timer cancel\n");
+ test_case_begin(t, "leon timer cancel");
+
+ test_begin(t, "leon timer cancel")
+ {
+ id = ctx->netclock_id;
+ leon_timer_cancel (ctx);
+ test_fail_unless ((EINVAL != errno)
+ && (0 == ctx->netclock_id));
+ } test_end;
+
+ // check that the correct netclock message has been sent to Maximus
+ test_begin(t, "netclock message")
+ {
+ unsigned char data[256];
+ netclock_msg_hdr_t *netclock_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_timer_open(&my_station);
+
+ // read sci and netclock headers
+ memset(data, '\0', 256);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, data, sizeof(sci_msg_hdr_t)))
+ && (sizeof(netclock_msg_hdr_t) == read(fd_in, data+sizeof(sci_msg_hdr_t), sizeof(netclock_msg_hdr_t))));
+
+ // set netclock header pointer
+ netclock_hdr = (netclock_msg_hdr_t *)(data+sizeof(sci_msg_hdr_t));
+
+ // check netclock id
+ test_fail_unless (ntohs(netclock_hdr->id) == id);
+
+ // close pipe
+ maximus_timer_close(fd_in);
+ } test_end;
+
+ return;
+}
+
+void leon_timer_uninit_test_case(test_t t)
+{
+ printf("uninit\n");
+ test_case_begin(t, "uninit");
+
+ test_begin(t, "uninit")
+ {
+ leon_timer_uninit(ctx);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+
+ blk_release (phy);
+
+ return;
+}
+
+void leon_timer_test_suite(test_t t)
+{
+ // reset errno
+ errno = 0;
+
+ station_init (&my_station);
+ station_log_set_level(&my_station, STATION_LOG_DEBUG);
+ station_log_set_mask(&my_station, STATION_LOGTYPE_ALL);
+ //my_station.pipe_log_fd = 1;
+
+ test_suite_begin(t, "leon timer");
+ leon_timer_init_test_case(t);
+ leon_timer_program_test_case(t);
+ leon_timer_cancel_test_case(t);
+ printf("BEGIN_TRACE\n");
+ trace_buffer_dbg_dump(&ctx->trace);
+ printf("END_TRACE\n");
+ leon_timer_uninit_test_case(t);
+
+ station_down (&my_station);
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init(t, argc, argv);
+
+ trace_init();
+ leon_timer_test_suite(t);
+ trace_uninit();
+
+ test_result(t);
+ return test_nb_failed(t) == 0 ? 0 : 1;
+}