summaryrefslogtreecommitdiff
path: root/cesar/hal/hle
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/hal/hle')
-rw-r--r--cesar/hal/hle/defs.h68
-rw-r--r--cesar/hal/hle/doc/claudia_ipmbox.odtbin0 -> 194344 bytes
-rw-r--r--cesar/hal/hle/forward.h19
-rw-r--r--cesar/hal/hle/ipmbox.h62
-rw-r--r--cesar/hal/hle/maximus/Module1
-rw-r--r--cesar/hal/hle/maximus/inc/maximus_defs.h19
-rw-r--r--cesar/hal/hle/maximus/inc/maximus_ether.h69
-rw-r--r--cesar/hal/hle/maximus/inc/maximus_interrupts.h20
-rw-r--r--cesar/hal/hle/maximus/inc/maximus_ipmbox_ctx.h70
-rw-r--r--cesar/hal/hle/maximus/src/maximus_ether.c472
-rw-r--r--cesar/hal/hle/maximus/src/maximus_ipmbox.c367
-rw-r--r--cesar/hal/hle/maximus/test/Config2
-rw-r--r--cesar/hal/hle/maximus/test/Makefile8
-rw-r--r--cesar/hal/hle/maximus/test/inc/test_maximus_hle.h42
-rw-r--r--cesar/hal/hle/maximus/test/src/test_maximus_ether.c754
-rw-r--r--cesar/hal/hle/maximus/test/src/test_maximus_hle.c67
-rw-r--r--cesar/hal/hle/maximus/test/src/test_maximus_ipmbox.c414
17 files changed, 2454 insertions, 0 deletions
diff --git a/cesar/hal/hle/defs.h b/cesar/hal/hle/defs.h
new file mode 100644
index 0000000000..57f3008f7b
--- /dev/null
+++ b/cesar/hal/hle/defs.h
@@ -0,0 +1,68 @@
+#ifndef hal_hle_defs_h
+#define hal_hle_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/defs.h
+ * \brief HAL HLE types and defines.
+ * \ingroup hal_hle
+ */
+
+#define IPMBOX_REG__MSG_TYPE 7, 0 /* 8 bits. */
+#define IPMBOX_REG__MSG_LENGTH 11, 8 /* 4 bits. */
+
+#define IPMBOX_REG__PARAM_MSG_TYPE 12, 12 /* 1 bit. */
+#define IPMBOX_REG__PARAM_MSG_LENGTH 24, 13 /* 11 bits. */
+
+#define IPMBOX_REG__PARAM_BUFFER_TYPE 14, 12 /* 3 bits. */
+
+/* Still in the header message. */
+#define IPMBOX_REG__PARAM_INTERFACE_TYPE 19, 12 /* 8 bits. */
+#define IPMBOX_REG__PARAM_INTERFACE_LENGTH 30, 20 /* 11 bits. */
+
+/* In the param word message. */
+#define IPMBOX_REG__PARAM_MODULE_WAY 0, 0 /* 1 bit. */
+#define IPMBOX_REG__PARAM_MODULE_ENC 1, 1 /* 1 bit. */
+#define IPMBOX_REG__PARAM_MODULE_TYPE 4, 2 /* 3 bits. */
+
+/** Message header (32 bits). */
+struct ipmbox_msg_hdr_t
+{
+ BITFIELDS_WORD(
+ /** Message type. */
+ u32 type:8;,
+ /** Number of parameter words (32 bits) following the header. */
+ u32 length:4;,
+ /** Optional parameters. */
+ u32 param:20;)
+};
+typedef struct ipmbox_msg_hdr_t ipmbox_msg_hdr_t;
+
+/** Message types. */
+enum hle_msg_type_t
+{
+ HLE_MSG_TYPE_DATA = 0x00, /*< Data or MME message type. */
+ HLE_MSG_TYPE_BUFFER_ADD = 0x01, /*< Buffer alloc message type. */
+ HLE_MSG_TYPE_SEND_DONE = 0x02, /*< Buffer dealloc message type. */
+ HLE_MSG_TYPE_INTERFACE = 0x03, /*< Interface message type. */
+ HLE_MSG_TYPE_NB, /*< Number of defined message types. */
+ HLE_MSG_TYPE_NONE = HLE_MSG_TYPE_NB /*< Invalid message type. */
+ };
+typedef enum hle_msg_type_t hle_msg_type_t;
+
+/** Buffer allocation type. */
+enum hle_buffer_alloc_type_t
+{
+ HLE_BUFFER_ALLOC_DATA,
+ HLE_BUFFER_ALLOC_MME,
+ HLE_BUFFER_ALLOC_INTERFACE,
+ HLE_BUFFER_ALLOC_NB
+};
+typedef enum hle_buffer_alloc_type_t hle_buffer_alloc_type_t;
+
+#endif /* hal_hle_defs_h */
diff --git a/cesar/hal/hle/doc/claudia_ipmbox.odt b/cesar/hal/hle/doc/claudia_ipmbox.odt
new file mode 100644
index 0000000000..5f7f036ed1
--- /dev/null
+++ b/cesar/hal/hle/doc/claudia_ipmbox.odt
Binary files differ
diff --git a/cesar/hal/hle/forward.h b/cesar/hal/hle/forward.h
new file mode 100644
index 0000000000..93aac0bf24
--- /dev/null
+++ b/cesar/hal/hle/forward.h
@@ -0,0 +1,19 @@
+#ifndef hal_hle_forward_h
+#define hal_hle_forward_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/forward.h
+ * \brief HAL HLE ipmbox context forward declaration.
+ * \ingroup hal_hle
+ */
+
+/* Forward declaration. */
+typedef struct ipmbox_t ipmbox_t;
+
+#endif /* hal_hle_forward_h */
diff --git a/cesar/hal/hle/ipmbox.h b/cesar/hal/hle/ipmbox.h
new file mode 100644
index 0000000000..077a778a8e
--- /dev/null
+++ b/cesar/hal/hle/ipmbox.h
@@ -0,0 +1,62 @@
+#ifndef hal_hle_ipmbox_h
+#define hal_hle_ipmbox_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/ipmbox.h
+ * \brief HAL HLE public interface.
+ * \ingroup hal_hle
+ */
+#include "hal/hle/forward.h" // for 'ipmbox_t'
+
+/**
+ * RX DSR callback function.
+ * \param user_data user data
+ * \param first_msg pointer to the first received message header
+ * \param length total length (in word) of received messages
+ */
+typedef void (*ipmbox_rx_cb_t) (void *user_data, u32 *first_msg, uint length);
+
+BEGIN_DECLS
+
+/**
+ * Initialise the HAL HLE.
+ * \param user_data user data passed to any callback
+ * \param rx_cb RX DSR callback, callback used when an Ethernet packet is received
+ * \return the newly created context
+ */
+ipmbox_t *
+ipmbox_init (void *user_data, ipmbox_rx_cb_t rx_cb);
+
+/**
+ * Activate ipmbox interruptions.
+ * \param ctx ipmbox context
+ * \param activation indicates if interruptions are activated or deactivated
+ */
+void
+ipmbox_activate (ipmbox_t *ctx, bool activation);
+
+/**
+ * Uninitialise the HAL HLE.
+ * \param ctx ipmbox context
+ */
+void
+ipmbox_uninit (ipmbox_t *ctx);
+
+/**
+ * Transmit an Ethernet packet.
+ * \param ctx ipmbox context
+ * \param first_msg pointer to the first received message header
+ * \param length total length (in word) of messages to transmit
+ */
+void
+ipmbox_tx (ipmbox_t *ctx, u32 *first_msg, uint length);
+
+END_DECLS
+
+#endif /* hal_hle_ipmbox_h */
diff --git a/cesar/hal/hle/maximus/Module b/cesar/hal/hle/maximus/Module
new file mode 100644
index 0000000000..8b80d1ba66
--- /dev/null
+++ b/cesar/hal/hle/maximus/Module
@@ -0,0 +1 @@
+SOURCES := maximus_ipmbox.c maximus_ether.c
diff --git a/cesar/hal/hle/maximus/inc/maximus_defs.h b/cesar/hal/hle/maximus/inc/maximus_defs.h
new file mode 100644
index 0000000000..69fa3de7e3
--- /dev/null
+++ b/cesar/hal/hle/maximus/inc/maximus_defs.h
@@ -0,0 +1,19 @@
+#ifndef hal_hle_maximus_inc_maximus_defs_h
+#define hal_hle_maximus_inc_maximus_defs_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/inc/maximus_defs.h
+ * \brief HAL HLE declarations for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+/** Max size of Maximus mailbox. */
+#define MAXIMUS_HLE_MAILBOX_MAX_SIZE 1024
+
+#endif /* hal_hle_maximus_inc_maximus_defs_h */
diff --git a/cesar/hal/hle/maximus/inc/maximus_ether.h b/cesar/hal/hle/maximus/inc/maximus_ether.h
new file mode 100644
index 0000000000..a8ddcec861
--- /dev/null
+++ b/cesar/hal/hle/maximus/inc/maximus_ether.h
@@ -0,0 +1,69 @@
+#ifndef hal_hle_maximus_inc_maximus_ether_h
+#define hal_hle_maximus_inc_maximus_ether_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/inc/maximus_ether.h
+ * \brief HAL HLE declarations for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "hal/hle/forward.h" // for 'ipmbox_t'
+#include "host/fwd.h" // for 'sci_msg_t'
+#include "hal/hle/ipmbox.h" // for 'ipmbox_msg_data_t'
+
+/**
+ * Fill a blank ether header
+ * \param ctx current ipmbox context
+ * \param msg pointer to sci message to fill header
+ * \param type type of message (DATA, MME, DATA_BUFFER_ADD, MME_BUFFER_ADD, BUFFER_RELEASED, or SNIFFER)
+ * \param sniffer_type type of sniffed packet (MME or BEACON)
+ * \param flags indicates sniffed packet encryption and way
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx or msg are NULL, or if arguments are out-of-range
+ */
+int maximus_ether_fill_hdr(ipmbox_t *ctx, sci_msg_t *msg, u8 type, u8 sniffer_type, u8 flags);
+
+/**
+ * Process ether message received by the sci layer.
+ * This function must be registred to SCI layer with SCI_MSG_TYPE_ETHERNET type.
+ * \param msg message to process
+ * \param ipmbox ipmbox current context
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if msg or ctx are NULL
+ * - EPROTO if msg->hdr.ether is null, or if msg->hdr.ether values are out-of-range
+ */
+int maximus_ether_recv (sci_msg_t *msg, void *ipmbox);
+
+/**
+ * Process ether message received by the sci layer, depending on the ether header type.
+ * \param ctx ipmbox current context
+ * \param msg message to process
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx, msg, msg->sci_hdr or ctx->rx_cb are null
+ * - EPROTO if msg->hdr.ether->type is incorrect, or if msg->hdr.ether values are out-of-range
+ */
+int maximus_ether_recv_invalid (ipmbox_t *ctx, sci_msg_t *msg);
+int maximus_ether_recv_data (ipmbox_t *ctx, sci_msg_t *msg);
+int maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg);
+
+/**
+ * Send an Ether SCI message of type DATA, MME, BUFFER_RELEASED, or SNIFFER to Maximus.
+ * \param ctx ipmbox current context
+ * \param type type of message (DATA, MME, BUFFER_RELEASED, or SNIFFER)
+ * \param sniffer_type type of sniffed packet (MME or BEACON)
+ * \param flags indicates sniffed packet encryption and way
+ * \param data_length sci message data length to send
+ * \param data pointer to sci message data to send
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx or data are null, or if data length equals 0
+ * if 'sci_send()' fails, it sets errno
+ */
+int maximus_ether_send (ipmbox_t *ctx, u8 type, u8 sniffer_type, u8 flags, uint data_length, u32 *data);
+
+#endif /* hal_phy_maximus_inc_maximus_ether_h */
diff --git a/cesar/hal/hle/maximus/inc/maximus_interrupts.h b/cesar/hal/hle/maximus/inc/maximus_interrupts.h
new file mode 100644
index 0000000000..8b51d00aab
--- /dev/null
+++ b/cesar/hal/hle/maximus/inc/maximus_interrupts.h
@@ -0,0 +1,20 @@
+#ifndef hal_hle_maximus_inc_maximus_interrupts_h
+#define hal_hle_maximus_inc_maximus_interrupts_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/inc/maximus_interrupts.h
+ * \brief HAL interrupt register definition for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#define HAL_HLE_INTERRUPT_IPMBOX 7
+
+#define HAL_HLE_INTERRUPT_PRIORITY 1 /* is it the right value? */
+
+#endif /* hal_hle_maximus_inc_maximus_interrupts_h */
diff --git a/cesar/hal/hle/maximus/inc/maximus_ipmbox_ctx.h b/cesar/hal/hle/maximus/inc/maximus_ipmbox_ctx.h
new file mode 100644
index 0000000000..417fde63de
--- /dev/null
+++ b/cesar/hal/hle/maximus/inc/maximus_ipmbox_ctx.h
@@ -0,0 +1,70 @@
+#ifndef hal_hle_maximus_inc_maximus_ipmbox_context_h
+#define hal_hle_maximus_inc_maximus_ipmbox_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/inc/maximus_ipmbox_context.h
+ * \brief HAL HLE ipmbox context for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+#include "hal/hle/ipmbox.h" // for 'ipmbox_rx_cb_t', 'ipmbox_tx_cb_t', and 'ipmbox_deferred_cb_t'
+#include "hal/hle/maximus/inc/maximus_defs.h" // for 'MAXIMUS_HLE_MAILBOX_MAX_SIZE'
+#include "maximus/common/types/sci_types.h" // for 'SCI_MSG_MAX_SIZE'
+#include <stdint.h> // for 'u32'
+#ifdef ECOS
+#include <cyg/hal/drv_api.h>
+#endif /* ECOS */
+
+/** HLE mailbox structure for Maximus */
+struct maximus_hle_mailbox_t
+{
+ /** Total length (in word) of messages. */
+ uint length;
+ /** Mailbox. */
+ u32 mailbox[MAXIMUS_HLE_MAILBOX_MAX_SIZE];
+};
+typedef struct maximus_hle_mailbox_t maximus_hle_mailbox_t;
+
+struct maximus_hle_buffer_t
+{
+ /** Pointer to next allocated buffer. */
+ struct maximus_hle_buffer_t *next;
+ /** Buffer id.*/
+ u32 id;
+ /** Pointer to data. */
+ u32 *data;
+};
+typedef struct maximus_hle_buffer_t maximus_hle_buffer_t;
+
+/** HLE ipmbox context structure for Maximus */
+struct ipmbox_t
+{
+ /** HLE reception mailbox structure. */
+ maximus_hle_mailbox_t rx;
+ /** Pointer to first element in linked list of allocated buffers. */
+ maximus_hle_buffer_t *first_buffer;
+ /** Pointer to last element in linked list of allocated buffers. */
+ maximus_hle_buffer_t *last_buffer;
+ /** User data passed to any callback. */
+ void *user_data;
+ /** RX DSR callback. */
+ ipmbox_rx_cb_t rx_cb;
+#ifdef ECOS
+ /** ipmbox interrupt descriptor for eCos: relates to RX and TX */
+ cyg_interrupt ipmbox_interrupt;
+ /** ipmbox interrupt handle */
+ cyg_handle_t ipmbox_interrupt_handle;
+#endif /* ECOS */
+ /** For ether messages. */
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ /** Set to true to enable assertions on WARNING messages. */
+ bool warning_assert;
+};
+/* Forward declaration in hal/hle/forward.h. */
+
+#endif /* hal_hle_maximus_inc_maximus_ipmbox_context_h */
diff --git a/cesar/hal/hle/maximus/src/maximus_ether.c b/cesar/hal/hle/maximus/src/maximus_ether.c
new file mode 100644
index 0000000000..e0d0f8ac8b
--- /dev/null
+++ b/cesar/hal/hle/maximus/src/maximus_ether.c
@@ -0,0 +1,472 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/src/maximus_ether.c
+ * \brief HAL HLE functions for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "common/std.h"
+#include "hal/hle/maximus/inc/maximus_ether.h"
+#include "hal/hle/maximus/inc/maximus_ipmbox_ctx.h"
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...' and 'ipmbox_msg_hdr_t'
+#include "host/fwd.h" // for 'sci_msg_t' and 'ether_msg_hdr_t'
+#include "host/station.h" // for 'station_log()'
+#include "maximus/common/types/ethernet_types.h" // for 'ETHERNET_TYPE_...'
+#include "hal/hle/maximus/inc/maximus_interrupts.h" // for 'HAL_HLE_INTERRUPT_IPMBOX'
+#include "ecos/packages/hal/maximus/arch/current/include/hal_host_intr.h"
+#include "common/defs/ethernet.h" // for 'ETH_PACKET_MAX_SIZE' and 'ETH_PACKET_MIN_SIZE'
+#include "interface/sniffer/defs.h" // for 'SNIFFER_BEACON' and 'SNIFFER_MME'
+#include <stdlib.h> // for 'malloc'
+#include <errno.h>
+
+typedef int (*maximus_ether_recv_function)(ipmbox_t *ctx, sci_msg_t *msg);
+maximus_ether_recv_function maximus_ether_function_array[ETHERNET_TYPE_NB] = { &maximus_ether_recv_invalid, // none
+ &maximus_ether_recv_data, // data
+ &maximus_ether_recv_data, // mme
+ &maximus_ether_recv_buffer_add, // data buffer add
+ &maximus_ether_recv_buffer_add, // mme buffer add
+ &maximus_ether_recv_buffer_add, // interface buffer add
+ &maximus_ether_recv_invalid, // buffer released
+ &maximus_ether_recv_invalid }; // sniffer
+
+/**
+ * Fill a blank ether header
+ * \param ctx current ipmbox context
+ * \param msg pointer to sci message to fill header
+ * \param type type of message (DATA, MME, DATA_BUFFER_ADD, MME_BUFFER_ADD, INTERFACE_BUFFER_ADD, BUFFER_RELEASED, or SNIFFER)
+ * \param sniffer_type type of sniffed packet (MME or BEACON)
+ * \param flags indicates sniffed packet encryption and way
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx or msg are NULL, or if arguments are out-of-range
+ */
+int
+maximus_ether_fill_hdr(ipmbox_t *ctx, sci_msg_t *msg, u8 type, u8 sniffer_type, u8 flags)
+{
+ int ret = -1;
+
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(msg);
+ dbg_assert((ETHERNET_TYPE_NB > type) && (ETHERNET_TYPE_NONE < type));
+ dbg_assert((SNIFFER_BEACON == sniffer_type) || (SNIFFER_MME == sniffer_type));
+ dbg_assert(ETHERNET_FLAG_MAX >= flags);
+ if ((NULL == ctx)
+ || (NULL == msg)
+ || ((ETHERNET_TYPE_NB <= type) || (ETHERNET_TYPE_NONE >= type))
+ || ((SNIFFER_BEACON != sniffer_type) && (SNIFFER_MME != sniffer_type))
+ || (ETHERNET_FLAG_MAX < flags))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // reserve space
+ if ((int)sizeof(ether_msg_hdr_t) != sci_msg_push(msg, sizeof(ether_msg_hdr_t)))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when pushing SCI message", errno);
+ }
+ else
+ {
+ // fill the reserved header
+ msg->hdr.ether = (ether_msg_hdr_t*)msg->data_begin;
+ msg->hdr.ether->version = ETHERNET_VERSION;
+ msg->hdr.ether->type = type;
+ msg->hdr.ether->sniffer_type = sniffer_type;
+ msg->hdr.ether->flags = flags;
+ msg->hdr.ether->reserved = 0;
+
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Process ether message received by the sci layer.
+ * This function must be registred to SCI layer with SCI_MSG_TYPE_ETHERNET type.
+ * \param msg message to process
+ * \param ipmbox ipmbox current context
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if msg or ctx are NULL
+ * - EPROTO if msg->hdr.ether is null, or if msg->hdr.ether values are out-of-range
+ */
+int
+maximus_ether_recv (sci_msg_t *msg, void *ipmbox)
+{
+ int ret = -1;
+ ipmbox_t *ctx;
+ ether_msg_hdr_t ether_hdr;
+
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(ipmbox);
+ if((NULL == msg) || (NULL == ipmbox))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // set ipmbox context
+ ctx = (ipmbox_t *)ipmbox;
+
+ // set header pointer in case of not already done
+ memcpy(&ether_hdr , msg->data_begin, sizeof(ether_msg_hdr_t));
+ if ((int)sizeof(ether_msg_hdr_t) != sci_msg_pop(msg, sizeof(ether_msg_hdr_t)))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when poping SCI message", errno);
+ }
+ else
+ {
+ msg->hdr.ether = &ether_hdr;
+
+ /* Check ether header. */
+
+ dbg_assert_ptr(msg->hdr.ether);
+ dbg_assert(ETHERNET_TYPE_NB > msg->hdr.ether->type);
+ dbg_assert((SNIFFER_BEACON == msg->hdr.ether->sniffer_type)
+ || (SNIFFER_MME == msg->hdr.ether->sniffer_type));
+ dbg_assert(ETHERNET_FLAG_MAX >= msg->hdr.ether->flags);
+ if ((NULL == msg->hdr.ether)
+ || (ETHERNET_TYPE_NB <= msg->hdr.ether->type)
+ || ((SNIFFER_BEACON != msg->hdr.ether->sniffer_type)
+ && (SNIFFER_MME != msg->hdr.ether->sniffer_type))
+ || (ETHERNET_FLAG_MAX < msg->hdr.ether->flags))
+ {
+ errno = EPROTO;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // depending on the ether header type, different actions have to be done
+ ret = (*(maximus_ether_function_array[msg->hdr.ether->type]))(ctx, msg);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Process ether message received by the sci layer, depending on the ether header type.
+ * \param ctx ipmbox current context
+ * \param msg message to process
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx, msg, msg->sci_hdr or ctx->rx_cb are null
+ * - EPROTO if msg->hdr.ether->type is incorrect, or if msg->hdr.ether values are out-of-range
+ */
+
+int
+maximus_ether_recv_invalid (ipmbox_t *ctx, sci_msg_t *msg)
+{
+ errno = EPROTO;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d because ether hdr type is incorrect", errno);
+ return -1;
+}
+
+int
+maximus_ether_recv_data (ipmbox_t *ctx, sci_msg_t *msg)
+{
+ int ret = -1;
+
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(msg->hdr.ether);
+ dbg_assert_ptr(msg->sci_hdr);
+ dbg_assert((ETH_PACKET_MIN_SIZE <= msg->length) && (ETH_PACKET_MAX_SIZE >= msg->length));
+ dbg_assert_ptr(msg->data_begin);
+ if((NULL == ctx)
+ || (NULL == msg)
+ || (NULL == msg->hdr.ether)
+ || (NULL == msg->sci_hdr)
+ || ((ETH_PACKET_MIN_SIZE > msg->length) || (ETH_PACKET_MAX_SIZE < msg->length))
+ || (NULL == msg->data_begin))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ ipmbox_msg_hdr_t hdr;
+ u8 *data;
+ int len = msg->length;
+
+ // set hdr type
+ hdr.type = HLE_MSG_TYPE_DATA;
+
+ // set hdr length
+ hdr.length = 1;
+
+ // set hdr param
+ // DATA length (11 bits): length of data into DATA buffer
+ // type (1 bit):
+ // 0 for DATA type
+ // 1 for MME type
+ hdr.param = msg->length << 1;
+ if (ETHERNET_TYPE_MME == msg->hdr.ether->type)
+ {
+ hdr.param |= 1;
+ }
+
+ // get data
+ data = (u8 *)malloc(2048);
+ memset(data, 0, 2048);
+ memcpy(data, msg->data_begin, msg->length);
+ if (len != sci_msg_pop(msg, len))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when poping SCI message", errno);
+ }
+ else
+ {
+ if (MAXIMUS_HLE_MAILBOX_MAX_SIZE <= ctx->rx.length + hdr.length + 1)
+ {
+ errno = ENOSPC;
+ station_log(&my_station, STATION_LOG_WARNING, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d because mailbox is full", __FUNCTION__, errno);
+ dbg_assert_print(!ctx->warning_assert, "errno = %d because mailbox is full", errno);
+ // reset total length of messages
+ ctx->rx.length = 0;
+ }
+
+ /* Update mailbox. */
+ // set hdr
+ memcpy(&ctx->rx.mailbox[ctx->rx.length], &hdr, sizeof(ipmbox_msg_hdr_t));
+ // set buffer pointer (32 bits): pointer to DATA buffer
+ ctx->rx.mailbox[ctx->rx.length + 1] = (u32)data;
+ // update total length of messages
+ ctx->rx.length += hdr.length + 1;
+
+ // raise interruption
+ maximus_pending_isrs |= (1 << HAL_HLE_INTERRUPT_IPMBOX);
+
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+int
+maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
+{
+ int ret = -1;
+
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(msg);
+ dbg_assert_ptr(msg->hdr.ether);
+ dbg_assert_ptr(msg->sci_hdr);
+ dbg_assert((int)(2 * sizeof(u32)) <= msg->length);
+ dbg_assert_ptr(msg->data_begin);
+ if((NULL == ctx)
+ || (NULL == msg)
+ || (NULL == msg->hdr.ether)
+ || (NULL == msg->sci_hdr)
+ || ((int)(2 * sizeof(u32)) > msg->length)
+ || (NULL == msg->data_begin))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ ipmbox_msg_hdr_t hdr;
+ u32 buffer_nb; // number of buffers to be allocated
+ uint i;
+
+ // set hdr type
+ hdr.type = HLE_MSG_TYPE_BUFFER_ADD;
+
+ // set hdr length
+ hdr.length = 1;
+
+ // set hdr param
+ // alloc type (3 bits):
+ // 0 for DATA buffer allocation
+ // 1 for MME buffer allocation
+ // 2 for INTERFACE buffer allocation
+ hdr.param = 0;
+ if (ETHERNET_TYPE_MME_BUFFER_ADD == msg->hdr.ether->type)
+ {
+ hdr.param = 1;
+ }
+ if (ETHERNET_TYPE_INTERFACE_BUFFER_ADD == msg->hdr.ether->type)
+ {
+ hdr.param = 2;
+ }
+
+ // get requested buffer nb
+ memcpy(&buffer_nb, msg->data_begin, sizeof(u32));
+ if ((int)sizeof(u32) != sci_msg_pop(msg, sizeof(u32)))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when poping SCI message", errno);
+ }
+ else
+ {
+ if (MAXIMUS_HLE_MAILBOX_MAX_SIZE <= ctx->rx.length + (hdr.length + 1) * buffer_nb)
+ {
+ errno = ENOSPC;
+ station_log(&my_station, STATION_LOG_WARNING, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d because mailbox is full", __FUNCTION__, errno);
+ dbg_assert_print(!ctx->warning_assert, "errno = %d because mailbox is full", errno);
+ // reset total length of messages
+ ctx->rx.length = 0;
+ }
+
+ /* Update mailbox. */
+ for (i = ctx->rx.length; i < ctx->rx.length + (hdr.length + 1) * buffer_nb; i += hdr.length + 1)
+ {
+ u32 buffer_id;
+ maximus_hle_buffer_t *buffer = (maximus_hle_buffer_t *)malloc(sizeof(maximus_hle_buffer_t));
+
+ // get buffer id
+ memcpy(&buffer_id, msg->data_begin, sizeof(u32));
+ if ((int)sizeof(u32) != sci_msg_pop(msg, sizeof(u32)))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when poping SCI message", errno);
+ }
+ else
+ {
+ // set hdr
+ memcpy(&ctx->rx.mailbox[i], &hdr, sizeof(ipmbox_msg_hdr_t));
+
+ // set buffer pointer (32 bits): pointer to allocated buffer
+ ctx->last_buffer->next = buffer;
+ ctx->last_buffer = buffer;
+ ctx->last_buffer->next = NULL;
+ ctx->last_buffer->id = buffer_id;
+ ctx->last_buffer->data = (u32 *)malloc(2048);
+ ctx->rx.mailbox[i+1] = (u32)ctx->last_buffer->data;
+ }
+ }
+ // update total length of messages
+ ctx->rx.length += (hdr.length + 1) * buffer_nb;
+
+ // raise interruption
+ maximus_pending_isrs |= (1 << HAL_HLE_INTERRUPT_IPMBOX);
+
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Send an Ether SCI message of type DATA, MME, BUFFER_RELEASED, or SNIFFER to Maximus.
+ * \param ctx ipmbox current context
+ * \param type type of message (DATA, MME, BUFFER_RELEASED, or SNIFFER)
+ * \param sniffer_type type of sniffed packet (MME or BEACON)
+ * \param flags indicates sniffed packet encryption and way
+ * \param data_length sci message data length to send
+ * \param data pointer to sci message data to send
+ * \return 0 if ok, -1 if it fails with errno =
+ * - EINVAL if ctx or data are null, or of data length equals 0
+ * if 'sci_send()' fails, it sets errno
+ */
+int
+maximus_ether_send (ipmbox_t *ctx, u8 type, u8 sniffer_type, u8 flags, uint data_length, u32 *data)
+{
+ int ret = -1;
+
+ dbg_assert_ptr(ctx);
+ dbg_assert((ETHERNET_TYPE_NB > type)
+ && (ETHERNET_TYPE_NONE < type)
+ && (ETHERNET_TYPE_DATA_BUFFER_ADD != type)
+ && (ETHERNET_TYPE_MME_BUFFER_ADD != type)
+ && (ETHERNET_TYPE_INTERFACE_BUFFER_ADD != type));
+ dbg_assert((SNIFFER_BEACON == sniffer_type) || (SNIFFER_MME == sniffer_type));
+ dbg_assert(ETHERNET_FLAG_MAX >= flags);
+ dbg_assert(0 != data_length);
+ dbg_assert_ptr(data);
+ if ( (NULL == ctx)
+ || (ETHERNET_TYPE_NB <= type)
+ || (ETHERNET_TYPE_NONE >= type)
+ || (ETHERNET_TYPE_DATA_BUFFER_ADD == type)
+ || (ETHERNET_TYPE_MME_BUFFER_ADD == type)
+ || (ETHERNET_TYPE_INTERFACE_BUFFER_ADD == type)
+ || ((SNIFFER_BEACON != sniffer_type) && (SNIFFER_MME != sniffer_type))
+ || (ETHERNET_FLAG_MAX < flags)
+ || (0 == data_length)
+ || (NULL == data) )
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // for ether message
+ sci_msg_t msg;
+
+ // init for ether message
+ memset(ctx->buffer, '\0', SCI_MSG_MAX_SIZE);
+ if (0 != sci_msg_init(&msg, ctx->buffer, SCI_MSG_MAX_SIZE))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when initializing SCI message", errno);
+ }
+ else
+ {
+ // fill sci data
+ if ((int)data_length != sci_msg_push(&msg, data_length))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when pushing SCI message", errno);
+ }
+ else
+ {
+ memcpy(msg.data_begin, data, data_length);
+
+ // fill ether and sci header
+ if ( (0 != maximus_ether_fill_hdr(ctx, &msg, type, sniffer_type, flags))
+ || (0 != sci_fill_hdr(my_station.sci, &msg, SCI_MSG_TYPE_ETHERNET, 0 /* flags */)) )
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when filling header", errno);
+ }
+ else
+ {
+ // send the message
+ if (msg.length != sci_send(my_station.sci, &msg))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when sending an Ether SCI message", errno);
+ }
+ else
+ {
+ ret = 0;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/cesar/hal/hle/maximus/src/maximus_ipmbox.c b/cesar/hal/hle/maximus/src/maximus_ipmbox.c
new file mode 100644
index 0000000000..69eaf86490
--- /dev/null
+++ b/cesar/hal/hle/maximus/src/maximus_ipmbox.c
@@ -0,0 +1,367 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/src/maximus_ipmbox.c
+ * \brief HAL HLE functions for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "common/std.h"
+#include "hal/hle/ipmbox.h"
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...' and 'ipmbox_msg_hdr_t'
+#include "hal/hle/maximus/inc/maximus_ipmbox_ctx.h"
+#include "hal/hle/maximus/inc/maximus_ether.h" // for 'maximus_ether_recv()'
+#include "hal/hle/maximus/inc/maximus_defs.h" // for 'MAXIMUS_MAILBOX_MAX_SIZE'
+#include "hal/hle/maximus/inc/maximus_interrupts.h" // for 'HAL_HLE_INTERRUPT_IPMBOX' and 'HAL_HLE_INTERRUPT_PRIORITY'
+#include "maximus/common/types/ethernet_types.h" // for 'ETHERNET_TYPE_...'
+#include "host/station.h" // for 'station_log()'
+#include "ecos/packages/hal/maximus/arch/current/include/hal_host_intr.h"
+#include <string.h> // for 'memset'
+#include <stdlib.h> // for 'free'
+#include <errno.h>
+
+#ifdef ECOS
+static cyg_uint32 _ipmbox_ecos_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+ cyg_drv_interrupt_mask(HAL_HLE_INTERRUPT_IPMBOX);
+ cyg_drv_interrupt_acknowledge(HAL_HLE_INTERRUPT_IPMBOX);
+ return CYG_ISR_CALL_DSR; // cause DSR to be run
+}
+
+static void _ipmbox_ecos_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+ /* nothing to do except calling the hle dsr */
+ ipmbox_t *ctx = (ipmbox_t *)data;
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(ctx->rx_cb);
+ dbg_assert_ptr(ctx->user_data);
+ if ((NULL != ctx)
+ && (NULL != ctx->rx_cb)
+ && (NULL != ctx->user_data))
+ {
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ // reset total length of messages
+ ctx->rx.length = 0;
+ }
+ cyg_drv_interrupt_unmask(HAL_HLE_INTERRUPT_IPMBOX);
+ return;
+}
+#endif /* ECOS */
+
+/**
+ * Initialise the HAL HLE.
+ * \param user_data user data passed to any callback
+ * \param rx_cb RX DSR callback, callback used when an Ethernet packet is received
+ * \return the newly created context
+ * set errno to:
+ * - EINVAL if user_data or rx_cb are null
+ */
+ipmbox_t *
+ipmbox_init (void *user_data, ipmbox_rx_cb_t rx_cb)
+{
+ static ipmbox_t ctx;
+ static maximus_hle_buffer_t first_buffer;
+
+ dbg_assert_ptr(user_data);
+ dbg_assert_ptr(rx_cb);
+ if ((NULL == user_data)
+ || (NULL == rx_cb))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ memset(&ctx, '\0', sizeof(ipmbox_t));
+ ctx.user_data = user_data;
+ ctx.rx_cb = rx_cb;
+
+ // initialize linked list of allocated buffers
+ ctx.first_buffer = &first_buffer;
+ ctx.first_buffer->next = NULL;
+ ctx.first_buffer->id = 0;
+ ctx.first_buffer->data = NULL;
+ ctx.last_buffer = ctx.first_buffer;
+
+ // register ether_recv to the sci layer
+ sci_register_callback(my_station.sci, SCI_MSG_TYPE_ETHERNET, maximus_ether_recv, &ctx);
+
+#ifdef ECOS
+ // register the ipmbox ISR and DSR into eCos
+ cyg_drv_interrupt_create(HAL_HLE_INTERRUPT_IPMBOX,
+ HAL_HLE_INTERRUPT_PRIORITY,
+ (cyg_addrword_t)&ctx,
+ _ipmbox_ecos_isr,
+ _ipmbox_ecos_dsr,
+ &ctx.ipmbox_interrupt_handle,
+ &ctx.ipmbox_interrupt);
+ cyg_drv_interrupt_attach(ctx.ipmbox_interrupt_handle);
+ cyg_drv_interrupt_mask(HAL_HLE_INTERRUPT_IPMBOX);
+#endif /* ECOS */
+ }
+
+ return &ctx;
+}
+
+/**
+ * Activate ipmbox interruptions.
+ * \param ctx ipmbox context
+ * \param activation indicates if interruptions are activated or deactivated
+ * set errno to:
+ * - EINVAL if ctx is NULL
+ */
+void
+ipmbox_activate (ipmbox_t *ctx, bool activation)
+{
+ dbg_assert_ptr(ctx);
+ if (NULL == ctx)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+#ifdef ECOS
+ if (activation)
+ {
+ cyg_drv_interrupt_unmask(HAL_HLE_INTERRUPT_IPMBOX);
+ }
+ else
+ {
+ cyg_drv_interrupt_mask(HAL_HLE_INTERRUPT_IPMBOX);
+ }
+#endif /* ECOS */
+ }
+}
+
+/**
+ * Uninitialise the HAL HLE.
+ * \param ctx ipmbox context
+ * set errno to:
+ * - EINVAL if ctx is NULL
+ */
+void
+ipmbox_uninit (ipmbox_t *ctx)
+{
+ dbg_assert_ptr(ctx);
+ if (NULL == ctx)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // release allocated buffers
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer->next;
+ maximus_hle_buffer_t *next_buffer = NULL;
+ while (NULL != current_buffer)
+ {
+ next_buffer = current_buffer->next;
+ free(current_buffer->data);
+ free(current_buffer);
+ current_buffer = next_buffer;
+ }
+
+ // reset ipmbox context
+ memset(ctx, '\0', sizeof(ipmbox_t));
+ }
+}
+
+/**
+ * Transmit an Ethernet packet.
+ * \param ctx ipmbox context
+ * \param first_msg pointer to the first received message header
+ * \param length total length (in word) of messages to transmit
+ * set errno to:
+ * - EINVAL if ctx or first_msg are null, if length is incorrect, or if first_msg values are incorrect
+ */
+void
+ipmbox_tx (ipmbox_t *ctx, u32 *first_msg, uint length)
+{
+ dbg_assert_ptr(ctx);
+ dbg_assert_ptr(first_msg);
+ dbg_assert((2 <= length) && (3 >= length));
+ if ((NULL == ctx)
+ || (NULL == first_msg)
+ || (2 > length)
+ || (3 < length))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ ipmbox_msg_hdr_t hdr = *(ipmbox_msg_hdr_t *)first_msg;
+ dbg_assert(HLE_MSG_TYPE_NB > hdr.type);
+ dbg_assert(((HLE_MSG_TYPE_INTERFACE != hdr.type) && (2 == length))
+ || (HLE_MSG_TYPE_INTERFACE == hdr.type));
+ dbg_assert(length - 1 == hdr.length);
+ if ((HLE_MSG_TYPE_NB <= hdr.type)
+ || ((HLE_MSG_TYPE_INTERFACE != hdr.type) && (2 != length))
+ || (length - 1 != hdr.length))
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ if ((HLE_MSG_TYPE_DATA == hdr.type)
+ || (HLE_MSG_TYPE_INTERFACE == hdr.type))
+ {
+ // to send message
+ u8 type = ETHERNET_TYPE_NONE;
+ u8 sniffer_type = 0;
+ u8 flags = ETHERNET_FLAG_NONE;
+ uint data_length = 0;
+ u32 data = 0;
+
+ // to release buffer
+ bool found = false;
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer;
+ maximus_hle_buffer_t *previous_buffer = current_buffer;
+
+ if (HLE_MSG_TYPE_DATA == hdr.type)
+ {
+ // get type (1 bit): DATA or MME type
+ // 0: DATA type
+ // 1: MME type
+ if (0 == (u8)(hdr.param & 0x00001))
+ {
+ type = ETHERNET_TYPE_DATA;
+ }
+ else // (1 == (u8)(hdr.param & 0x001))
+ {
+ type = ETHERNET_TYPE_MME;
+ }
+
+ // get DATA or MME length (11 bits): length of data into DATA or MME buffer
+ data_length = (uint)((hdr.param & 0x00FFE) >> 1);
+
+ // get buffer pointer (32 bits): pointer to DATA or MME buffer
+ data = *(first_msg + 1);
+ }
+
+ else // (HLE_MSG_TYPE_INTERFACE == hdr.type)
+ {
+ int data_index = 1;
+
+ // get module type (8 bits):
+ // 0: interface
+ // 1: sniffer
+ // 1-255: unused
+ if (1 == (u8)(hdr.param & 0x000FF))
+ {
+ type = ETHERNET_TYPE_SNIFFER;
+ }
+
+ // get data length (11 bits): length of data into buffer
+ data_length = (uint)((hdr.param & 0x7FF00) >> 8);
+
+ if (3 == length) // get module param (32 bits)
+ {
+ u32 module_param = *(first_msg + data_index);
+ data_index++;
+
+ // get way (1 bit): Tx or Rx
+ // 0: Tx
+ // 1: Rx
+ // get encryption (1 bit): encrypted or not
+ // 0: false
+ // 1: true
+ flags = (u8)(module_param & 0x00000003);
+
+ // get data type (3 bits): Beacon or MME type
+ // 0: Beacon type
+ // 1: MME type
+ // 2-7: unused
+ sniffer_type = (u8)((module_param & 0x0000001C) >> 2);
+ }
+
+ // get buffer pointer (32 bits): pointer to buffer
+ data = *(first_msg + data_index);
+ }
+
+ // send DATA, MME or SNIFFER (sniffed Beacon or MME) to Maximus
+ if (0 != maximus_ether_send(ctx, type, sniffer_type, flags, data_length, (u32 *)data))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when transmitting an Ethernet or a sniffed packet", errno);
+ }
+
+ // check that this pointer is still allocated
+ while ((NULL != current_buffer->next) && !found)
+ {
+ previous_buffer = current_buffer;
+ current_buffer = current_buffer->next;
+ found = (data == (u32)current_buffer->data); // pointer to buffer to release
+ }
+ dbg_assert(found);
+ if (!found)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ // for BUFFER RELEASED message
+ u32 id = current_buffer->id;
+
+ // before deallocating buffer, link previous to next,
+ // and update last buffer if needed
+ previous_buffer->next = current_buffer->next;
+ if (current_buffer == ctx->last_buffer)
+ {
+ ctx->last_buffer = previous_buffer;
+ }
+ free(current_buffer->data);
+ free(current_buffer);
+
+ // send BUFFER RELEASED to Maximus
+ if (0 != maximus_ether_send(ctx, ETHERNET_TYPE_BUFFER_RELEASED, 0 /* sniffer_type */, ETHERNET_FLAG_NONE, sizeof(u32), &id))
+ {
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d when transmitting an Ethernet packet", errno);
+ }
+ }
+ }
+ else if (HLE_MSG_TYPE_SEND_DONE == hdr.type)
+ {
+ // get buffer pointer (32 bits): pointer to buffer to release
+ u32 *data = (u32 *)(*(first_msg + 1));
+
+ // deallocate buffer
+ dbg_assert_ptr(data);
+ if (NULL != data)
+ {
+ free(data);
+ }
+ else
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ }
+ else // (HLE_MSG_TYPE_BUFFER_ADD == hdr.type)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ dbg_assert_print(false, "errno = %d because cannot transmit an Ethernet packet of type BUFFER_ADD", errno);
+ }
+ }
+ }
+}
diff --git a/cesar/hal/hle/maximus/test/Config b/cesar/hal/hle/maximus/test/Config
new file mode 100644
index 0000000000..5077dbafd3
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/Config
@@ -0,0 +1,2 @@
+CONFIG_DEBUG = y
+CONFIG_DEBUG_FATAL_CATCH = y
diff --git a/cesar/hal/hle/maximus/test/Makefile b/cesar/hal/hle/maximus/test/Makefile
new file mode 100644
index 0000000000..1829c194d9
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/Makefile
@@ -0,0 +1,8 @@
+BASE = ../../../..
+EXTRA_HOST_CFLAGS+= -DUNIT_TEST
+HOST_PROGRAMS = test_maximus_hle
+test_maximus_hle_SOURCES = test_maximus_hle.c test_maximus_ipmbox.c test_maximus_ether.c
+test_maximus_hle_MODULES = lib hal/hle/maximus host
+INCLUDES = hal/hle/maximus/test/inc
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/hle/maximus/test/inc/test_maximus_hle.h b/cesar/hal/hle/maximus/test/inc/test_maximus_hle.h
new file mode 100644
index 0000000000..a2999d606c
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/inc/test_maximus_hle.h
@@ -0,0 +1,42 @@
+#ifndef hal_hle_maximus_test_inc_test_maximus_hle_h
+#define hal_hle_maximus_test_inc_test_maximus_hle_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/test/inc/test_maximus_hle.h
+ * \brief test header for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "host/fwd.h" // for 'station_ctx_t'
+
+/**
+ * RX DSR callback function.
+ * \param user_data user data
+ * \param first_msg pointer to the first received message header
+ * \param length total length (in word) of received messages
+ * \return true if a DSR is requested
+ */
+void ipmbox_rx_cb (void *user_data, u32 *first_msg, uint length);
+
+/**
+ * Open pipe or socket.
+ * \param station pointer to the station context
+ * \return file descriptor for pipe or socket
+ */
+int
+maximus_ether_open (station_ctx_t *station);
+
+/**
+ * Close pipe.
+ * \param fd file descriptor for pipe or socket
+ */
+void
+maximus_ether_close (int fd);
+
+#endif /* hal_hle_maximus_test_inc_test_maximus_hle_h */
diff --git a/cesar/hal/hle/maximus/test/src/test_maximus_ether.c b/cesar/hal/hle/maximus/test/src/test_maximus_ether.c
new file mode 100644
index 0000000000..21318d3863
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/src/test_maximus_ether.c
@@ -0,0 +1,754 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/test/src/test_maximus_ipmbox.c
+ * \brief HAL HLE ipmbox test functions for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "hal/hle/maximus/test/inc/test_maximus_hle.h"
+#include "hal/hle/maximus/inc/maximus_ether.h"
+#include "hal/hle/maximus/inc/maximus_ipmbox_ctx.h"
+#include "hal/hle/maximus/inc/maximus_interrupts.h" // for 'HAL_HLE_INTERRUPT_IPMBOX'
+#include "hal/hle/ipmbox.h"
+#include "hal/hle/forward.h" // for 'ipmbox_t'
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...'
+#include "host/station.h" // for 'station_ctx_t'
+#include "maximus/common/types/ethernet_types.h" // for 'ETHERNET_TYPE_...'
+#include <stdio.h> // for 'printf'
+#include <string.h> // for 'memset'
+#include <unistd.h> // for 'read'
+#include <fcntl.h> // for 'read'
+#include <stdlib.h> // for 'free'
+#include <errno.h>
+
+extern uint32_t maximus_pending_isrs; // used in 'station.c'
+extern station_ctx_t my_station;
+ipmbox_t *ctx;
+
+void maximus_ether_fill_hdr_test_case(test_t t)
+{
+ printf("fill hdr\n");
+ test_case_begin(t, "fill hdr");
+
+ sci_msg_t msg;
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ uint8_t type = ETHERNET_TYPE_DATA;
+ uint8_t sniffer_type = 0;
+ uint8_t flags = ETHERNET_FLAG_NONE;
+
+ test_begin(t, "sci init")
+ {
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((0 == sci_msg_init(&msg, buffer, SCI_MSG_MAX_SIZE))
+ && (EINVAL != errno));
+ msg.length = 0;
+ } test_end;
+
+ test_begin(t, "fill hdr")
+ {
+ test_fail_unless ((0 == maximus_ether_fill_hdr(ctx, &msg, type, sniffer_type, flags))
+ && (EINVAL != errno)
+ && (ETHERNET_VERSION == msg.hdr.ether->version)
+ && (type == msg.hdr.ether->type)
+ && (sniffer_type == msg.hdr.ether->sniffer_type)
+ && (flags == msg.hdr.ether->flags)
+ && (0 == msg.hdr.ether->reserved));
+ } test_end;
+
+ test_begin(t, "fill hdr with incorrect type")
+ {
+ type = ETHERNET_TYPE_NONE;
+
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((-1 == maximus_ether_fill_hdr(ctx, &msg, type, sniffer_type, flags))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("fill hdr with incorrect type\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+
+ // reset type to correct value
+ type = ETHERNET_TYPE_DATA;
+ } test_end;
+
+ test_begin(t, "fill hdr with incorrect sniffer type")
+ {
+ sniffer_type = 2;
+
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((-1 == maximus_ether_fill_hdr(ctx, &msg, type, sniffer_type, flags))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("fill hdr with incorrect sniffer type\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+
+ // reset sniffer type to correct value
+ sniffer_type = 0;
+ } test_end;
+
+ test_begin(t, "fill hdr with incorrect flags")
+ {
+ flags = ETHERNET_FLAG_MAX + 1;
+
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((-1 == maximus_ether_fill_hdr(ctx, &msg, type, sniffer_type, flags))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("fill hdr with incorrect flags\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+}
+
+void maximus_ether_recv_test_case(test_t t)
+{
+ sci_msg_t msg;
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+
+ printf("recv\n");
+ test_case_begin(t, "recv");
+
+ test_begin(t, "sci init")
+ {
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((0 == sci_msg_init(&msg, buffer, SCI_MSG_MAX_SIZE))
+ && (EINVAL != errno));
+ msg.length = 0;
+ } test_end;
+
+ test_begin(t, "NULL msg")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_recv(NULL, ctx)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("NULL msg\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "NULL ipmbox")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_recv(&msg, NULL)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("NULL ipmbox\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "recv")
+ {
+ u32 buf_nb = 1;
+ u32 buf_id = 1;
+ u32 total_buf_nb = buf_nb;
+ maximus_hle_buffer_t *first_buffer = NULL;
+ maximus_hle_buffer_t *current_buffer = NULL;
+
+ // ether header
+ ether_msg_hdr_t ether_hdr;
+
+ // sci header
+ sci_msg_hdr_t sci_hdr;
+
+ // sci data
+ uint data_length = 1500;
+ u8 data[data_length];
+
+ // initialize sci data
+ memset(data, '\0', data_length);
+
+ // set ether header values
+ ether_hdr.version = ETHERNET_VERSION;
+ ether_hdr.type = ETHERNET_TYPE_NONE;
+ ether_hdr.sniffer_type = 0;
+ ether_hdr.flags = ETHERNET_FLAG_NONE;
+ ether_hdr.reserved = 0;
+
+ for (ether_hdr.type = ETHERNET_TYPE_DATA; ether_hdr.type < ETHERNET_TYPE_BUFFER_RELEASED; ether_hdr.type++)
+ {
+ /* Fill sci data. */
+
+ // ether type data or mme
+ if ((ETHERNET_TYPE_DATA == ether_hdr.type) || (ETHERNET_TYPE_MME == ether_hdr.type))
+ {
+ uint i;
+ for (i=0; i<data_length; i++)
+ {
+ data[i] = (u8)i;
+ }
+ test_fail_unless (((int)data_length == sci_msg_push(&msg, data_length))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, data, data_length);
+ }
+
+ // ether type data buffer add
+ else if (ETHERNET_TYPE_DATA_BUFFER_ADD == ether_hdr.type)
+ {
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_nb, sizeof(u32));
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_id, sizeof(u32));
+ }
+
+ // ether type mme buffer add
+ else if (ETHERNET_TYPE_MME_BUFFER_ADD == ether_hdr.type)
+ {
+ buf_nb = 10;
+ for (buf_id = total_buf_nb + buf_nb; buf_id > total_buf_nb; buf_id--)
+ {
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_id, sizeof(u32));
+ }
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_nb, sizeof(u32));
+ total_buf_nb += buf_nb;
+ }
+
+ // ether type interface buffer add
+ else // (ETHERNET_TYPE_INTERFACE_BUFFER_ADD == ether_hdr.type)
+ {
+ buf_nb = 2;
+ for (buf_id = total_buf_nb + buf_nb; buf_id > total_buf_nb; buf_id--)
+ {
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_id, sizeof(u32));
+ }
+ test_fail_unless (((int)sizeof(u32) == sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buf_nb, sizeof(u32));
+ total_buf_nb += buf_nb;
+ }
+
+ // fill ether header
+ test_fail_unless (((int)sizeof(ether_msg_hdr_t) == sci_msg_push(&msg, sizeof(ether_msg_hdr_t)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &ether_hdr, sizeof(ether_msg_hdr_t));
+
+ // fill sci header
+ memcpy((u8 *)&sci_hdr.magic_id, SCI_MSG_MAGIC, 4);
+ sci_hdr.version = SCI_MSG_VERSION;
+ sci_hdr.type = SCI_MSG_TYPE_ETHERNET;
+ sci_hdr.flags = 0;
+ sci_hdr.station_id = my_station.id;
+ sci_hdr.length = msg.length - sizeof(sci_msg_hdr_t);
+ sci_hdr.msg_id = my_station.sci->current_msg_id | SCI_MSG_ID_STATION;
+ sci_hdr.netclock_high = my_station.current_tick_tck >> 32;
+ sci_hdr.netclock_low = my_station.current_tick_tck & 0xffffffff;
+ msg.sci_hdr = &sci_hdr;
+
+ test_fail_unless ((0 <= (maximus_ether_recv(&msg, ctx)))
+ && (EINVAL != errno)
+ && (EPROTO != errno));
+
+ test_fail_unless ((ether_hdr.version == msg.hdr.ether->version)
+ && (ether_hdr.type == msg.hdr.ether->type)
+ && (ether_hdr.sniffer_type == msg.hdr.ether->sniffer_type)
+ && (ether_hdr.flags == msg.hdr.ether->flags)
+ && (ether_hdr.reserved == msg.hdr.ether->reserved));
+
+ /* Check results. */
+
+ // test ether type data or mme
+ if ((ETHERNET_TYPE_DATA == ether_hdr.type) || (ETHERNET_TYPE_MME == ether_hdr.type))
+ {
+ u32 hdr = (data_length << 13) | (1 << 8) | HLE_MSG_TYPE_DATA; // ipmbox msg hdr
+ if (ETHERNET_TYPE_MME == ether_hdr.type)
+ {
+ hdr |= (1 << 12);
+ }
+
+ test_begin(t, "ether type data or mme")
+ {
+ test_fail_unless ((maximus_pending_isrs & (1 << HAL_HLE_INTERRUPT_IPMBOX))
+ && (2 == ctx->rx.length)
+ && (ctx->rx.mailbox[0] == hdr)
+ && (0 == memcmp((u8 *)ctx->rx.mailbox[1], data, data_length)));
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ maximus_pending_isrs &= (0 << HAL_HLE_INTERRUPT_IPMBOX);
+ ctx->rx.length = 0;
+
+ // release allocated buffer
+ test_fail_unless (NULL != (u32 *)ctx->rx.mailbox[1]);
+ free((u32 *)ctx->rx.mailbox[1]);
+ } test_end;
+ }
+
+ // test ether type data buffer add
+ else if (ETHERNET_TYPE_DATA_BUFFER_ADD == ether_hdr.type)
+ {
+ test_begin(t, "ether type data buffer add")
+ {
+ u32 mailbox[2 * buf_nb];
+ mailbox[0] = (1 << 8) | HLE_MSG_TYPE_BUFFER_ADD; // ipmbox msg hdr
+ mailbox[1] = (u32)ctx->last_buffer->data; // ipmbox msg data
+ first_buffer = ctx->first_buffer->next;
+ current_buffer = first_buffer;
+
+ test_fail_unless ((maximus_pending_isrs & (1 << HAL_HLE_INTERRUPT_IPMBOX))
+ && (2 * buf_nb == ctx->rx.length)
+ && (0 == memcmp(ctx->rx.mailbox, mailbox, 2 * buf_nb * sizeof(u32)))
+ && (NULL == current_buffer->next)
+ && (total_buf_nb == current_buffer->id)
+ && (NULL != current_buffer->data));
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ maximus_pending_isrs &= (0 << HAL_HLE_INTERRUPT_IPMBOX);
+ ctx->rx.length = 0;
+ } test_end;
+ }
+
+ // test ether type mme buffer add
+ else if (ETHERNET_TYPE_MME_BUFFER_ADD == ether_hdr.type)
+ {
+ test_begin(t, "ether type mme buffer add")
+ {
+ uint i;
+ u32 mailbox[2 * buf_nb];
+ u32 hdr = (1 << 12) | (1 << 8) | HLE_MSG_TYPE_BUFFER_ADD; // ipmbox msg hdr
+ first_buffer = current_buffer->next;
+ current_buffer = first_buffer;
+ for (i=0; i<2*buf_nb; i+=2)
+ {
+ mailbox[i] = hdr;
+ mailbox[i+1] = (u32)current_buffer->data; // ipmbox msg data
+ current_buffer = current_buffer->next;
+ }
+
+ // check mailbox contents
+ test_fail_unless ((maximus_pending_isrs & (1 << HAL_HLE_INTERRUPT_IPMBOX))
+ && (2 * buf_nb == ctx->rx.length)
+ && (0 == memcmp(ctx->rx.mailbox, mailbox, 2 * buf_nb * sizeof(u32))));
+
+ // check list of the 10 allocated buffers
+ current_buffer = first_buffer;
+ for (i=total_buf_nb-buf_nb+1; i<total_buf_nb; i++)
+ {
+ test_fail_unless ((NULL != current_buffer->next)
+ && (i == current_buffer->id)
+ && (NULL != current_buffer->data));
+ current_buffer = current_buffer->next;
+ }
+ test_fail_unless ((NULL == current_buffer->next)
+ && (total_buf_nb == current_buffer->id)
+ && (NULL != current_buffer->data));
+
+ // call rx_cb
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ maximus_pending_isrs &= (0 << HAL_HLE_INTERRUPT_IPMBOX);
+ ctx->rx.length = 0;
+ } test_end;
+ }
+
+ // test ether type interface buffer add
+ else // (ETHERNET_TYPE_INTERFACE_BUFFER_ADD == ether_hdr.type)
+ {
+ test_begin(t, "ether type interface buffer add")
+ {
+ uint i;
+ u32 mailbox[2 * buf_nb];
+ u32 hdr = (2 << 12) | (1 << 8) | HLE_MSG_TYPE_BUFFER_ADD; // ipmbox msg hdr
+ first_buffer = current_buffer->next;
+ current_buffer = first_buffer;
+ for (i=0; i<2*buf_nb; i+=2)
+ {
+ mailbox[i] = hdr;
+ mailbox[i+1] = (u32)current_buffer->data; // ipmbox msg data
+ current_buffer = current_buffer->next;
+ }
+
+ // check mailbox contents
+ test_fail_unless ((maximus_pending_isrs & (1 << HAL_HLE_INTERRUPT_IPMBOX))
+ && (2 * buf_nb == ctx->rx.length)
+ && (0 == memcmp(ctx->rx.mailbox, mailbox, 2 * buf_nb * sizeof(u32))));
+
+ // check list of the 2 allocated buffers
+ current_buffer = first_buffer;
+ for (i=total_buf_nb-buf_nb+1; i<total_buf_nb; i++)
+ {
+ test_fail_unless ((NULL != current_buffer->next)
+ && (i == current_buffer->id)
+ && (NULL != current_buffer->data));
+ current_buffer = current_buffer->next;
+ }
+ test_fail_unless ((NULL == current_buffer->next)
+ && (total_buf_nb == current_buffer->id)
+ && (NULL != current_buffer->data));
+
+ // call rx_cb
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ maximus_pending_isrs &= (0 << HAL_HLE_INTERRUPT_IPMBOX);
+ ctx->rx.length = 0;
+ } test_end;
+
+ test_begin(t, "release allocated buffers")
+ {
+ uint rls_buf_nb = 0;
+ maximus_hle_buffer_t *next_buffer = NULL;
+ current_buffer = ctx->first_buffer->next;
+ while (NULL != current_buffer)
+ {
+ next_buffer = current_buffer->next;
+ free(current_buffer->data);
+ free(current_buffer);
+ current_buffer = next_buffer;
+ rls_buf_nb++;
+ }
+ test_fail_unless (total_buf_nb == rls_buf_nb);
+ } test_end;
+ }
+ }
+
+ // test ether type none
+ ether_hdr.type = ETHERNET_TYPE_NONE;
+
+ // fill ether header
+ test_fail_unless (((int)sizeof(ether_msg_hdr_t) == sci_msg_push(&msg, sizeof(ether_msg_hdr_t)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &ether_hdr, sizeof(ether_msg_hdr_t));
+
+ test_begin(t, "ether type none")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_recv(&msg, ctx)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("ether type none\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ // test ether type buffer released
+ ether_hdr.type = ETHERNET_TYPE_BUFFER_RELEASED;
+
+ // fill ether header
+ test_fail_unless (((int)sizeof(ether_msg_hdr_t) == sci_msg_push(&msg, sizeof(ether_msg_hdr_t)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &ether_hdr, sizeof(ether_msg_hdr_t));
+
+ test_begin(t, "ether type buffer released")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_recv(&msg, ctx)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("ether type buffer released\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ // test ether type sniffer
+ ether_hdr.type = ETHERNET_TYPE_SNIFFER;
+
+ // fill ether header
+ test_fail_unless (((int)sizeof(ether_msg_hdr_t) == sci_msg_push(&msg, sizeof(ether_msg_hdr_t)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &ether_hdr, sizeof(ether_msg_hdr_t));
+
+ test_begin(t, "ether type sniffer")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_recv(&msg, ctx)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("ether type sniffer\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+ } test_end;
+}
+
+void maximus_ether_send_test_case(test_t t)
+{
+ // ether type
+ u8 type = ETHERNET_TYPE_DATA;
+ u8 sniffer_type = 0;
+ u8 flags = ETHERNET_FLAG_NONE;
+
+ // data
+ int data_length = 1500;
+ u8 data[1500];
+
+ // initialize data
+ memset(data, '\0', data_length);
+
+ printf("send\n");
+ test_case_begin(t, "send");
+
+ test_begin(t, "send incorrect sniffer type")
+ {
+ sniffer_type = 2;
+
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, sniffer_type, flags, data_length, (u32 *)data)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send incorrect sniffer type\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+
+ // set sniffer type to correct value
+ sniffer_type = 1;
+ } test_end;
+
+ test_begin(t, "send incorrect flags")
+ {
+ flags = ETHERNET_FLAG_MAX + 1;
+
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, sniffer_type, flags, data_length, (u32 *)data)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send incorrect flags\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+
+ // set flags to correct value
+ flags = ETHERNET_FLAG_ENCRYPTED;
+ } test_end;
+
+ test_begin(t, "send incorrect data length")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, sniffer_type, flags, 0, (u32 *)data)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send incorrect data length\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "send null data")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, sniffer_type, flags, data_length, NULL)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send null data\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ for (type = ETHERNET_TYPE_NONE; type < ETHERNET_TYPE_NB; type++)
+ {
+ // ether type none, data buffer add, or mme buffer add
+ if ((ETHERNET_TYPE_NONE == type)
+ || (ETHERNET_TYPE_DATA_BUFFER_ADD == type)
+ || (ETHERNET_TYPE_MME_BUFFER_ADD == type))
+ {
+ test_begin(t, "send invalid")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, sniffer_type, flags, data_length, (u32 *)data)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send invalid\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+ }
+
+ // ether type data, mme, buffer released, or sniffer
+ else if ((ETHERNET_TYPE_DATA == type)
+ || (ETHERNET_TYPE_MME == type)
+ || (ETHERNET_TYPE_BUFFER_RELEASED == type)
+ || (ETHERNET_TYPE_SNIFFER == type))
+ {
+ // ether type data, mme, or sniffer
+ if ((ETHERNET_TYPE_DATA == type)
+ || (ETHERNET_TYPE_MME == type)
+ || (ETHERNET_TYPE_SNIFFER == type))
+ {
+ // set data
+ int i;
+ for (i=0; i<data_length; i++)
+ {
+ data[i] = (u8)i;
+ }
+ }
+
+ // ether type buffer released
+ else // ETHERNET_TYPE_BUFFER_RELEASED
+ {
+ // set data length and data
+ int i;
+ data_length = 4;
+ for (i=0; i<data_length; i++)
+ {
+ data[i] = i;
+ }
+ }
+
+ test_begin(t, "send ether")
+ {
+ test_fail_unless ((0 == maximus_ether_send(ctx, type, sniffer_type, flags, data_length, (u32 *)data))
+ && (EINVAL != errno));
+ } test_end;
+
+ /* Check results. */
+
+ // check that the correct ether message has been sent to Maximus
+ test_begin(t, "ether message")
+ {
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_hdr_t *sci_hdr;
+ ether_msg_hdr_t *ether_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_ether_open(&my_station);
+
+ // read sci and ether headers
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, buffer, sizeof(sci_msg_hdr_t)))
+ && (sizeof(ether_msg_hdr_t) == read(fd_in, buffer + sizeof(sci_msg_hdr_t), sizeof(ether_msg_hdr_t))));
+
+ // set sci and ether headers pointers
+ sci_hdr = (sci_msg_hdr_t *)buffer;
+ ether_hdr = (ether_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t));
+
+ // check ether header
+ test_fail_unless ((type == ether_hdr->type)
+ && (sniffer_type == ether_hdr->sniffer_type)
+ && (flags == ether_hdr->flags));
+
+ // read the remaining part of message
+ test_fail_unless (data_length == read(fd_in, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), data_length));
+
+ // check ether data
+ test_fail_unless (0 == memcmp(data, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), data_length));
+
+ // close pipe
+ maximus_ether_close(fd_in);
+ } test_end;
+ }
+ }
+}
+
+void ether_test_suite(test_t t)
+{
+ int user_data = 1234567890;
+
+ // 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);
+
+ ctx = ipmbox_init ((void*)&user_data,
+ &ipmbox_rx_cb);
+ ctx->warning_assert = true;
+ ipmbox_activate (ctx, true);
+
+ test_suite_begin(t, "ether");
+ maximus_ether_fill_hdr_test_case(t);
+ maximus_ether_recv_test_case(t);
+ maximus_ether_send_test_case(t);
+
+ station_down (&my_station);
+}
diff --git a/cesar/hal/hle/maximus/test/src/test_maximus_hle.c b/cesar/hal/hle/maximus/test/src/test_maximus_hle.c
new file mode 100644
index 0000000000..cce8d7e000
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/src/test_maximus_hle.c
@@ -0,0 +1,67 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/test/src/test_maximus_hle.c
+ * \brief HAL HLE main test function for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "host/station.h" // for 'station_ctx_t'
+#include <unistd.h> // for 'open()' and 'close()'
+#include <fcntl.h> // for 'open()' and 'close()'
+
+void ipmbox_test_suite (test_t t);
+void ether_test_suite (test_t t);
+
+uint32_t maximus_pending_isrs;
+station_ctx_t my_station;
+
+void
+ipmbox_rx_cb (void *user_data, u32 *first_msg, uint length)
+{
+ int *my_data = (int *)user_data;
+ *my_data = 987654321;
+ return;
+}
+
+int
+maximus_ether_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_ether_close (int fd)
+{
+ #ifndef STATION_SOCK
+ close(fd);
+ #endif /* !STATION_SOCK */
+}
+
+int
+main (int argc, char **argv)
+{
+ test_t t;
+ test_init(t, argc, argv);
+
+ ether_test_suite(t);
+ ipmbox_test_suite(t);
+
+ test_result(t);
+ return test_nb_failed(t) == 0 ? 0 : 1;
+}
diff --git a/cesar/hal/hle/maximus/test/src/test_maximus_ipmbox.c b/cesar/hal/hle/maximus/test/src/test_maximus_ipmbox.c
new file mode 100644
index 0000000000..8d5f85cdf1
--- /dev/null
+++ b/cesar/hal/hle/maximus/test/src/test_maximus_ipmbox.c
@@ -0,0 +1,414 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/hle/maximus/test/src/test_maximus_ipmbox.c
+ * \brief HAL HLE ipmbox test functions for Maximus.
+ * \ingroup hal_hle_maximus
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+#include "hal/hle/maximus/test/inc/test_maximus_hle.h"
+#include "hal/hle/maximus/inc/maximus_ipmbox_ctx.h" // for 'ipmbox_t'
+#include "hal/hle/ipmbox.h"
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...' and 'ipmbox_msg_hdr_t'
+#include "host/station.h" // for 'station_ctx_t'
+#include "host/fwd.h" // for 'sci_msg_t'
+#include "maximus/common/types/ethernet_types.h" // for 'ether_msg_hdr_t'
+#include <stdio.h> // for 'printf'
+#include <string.h> // for 'memset'
+#include <unistd.h> // for 'read'
+#include <fcntl.h> // for 'read'
+#include <stdlib.h> // for 'malloc'
+#include <errno.h>
+
+extern uint32_t maximus_pending_isrs; // used in 'station.c'
+extern station_ctx_t my_station;
+ipmbox_t *ctx;
+
+void ipmbox_init_test_case(test_t t)
+{
+ int user_data = 123456789;
+
+ printf("init\n");
+ test_case_begin(t, "init");
+
+ test_begin(t, "init")
+ {
+ ctx = ipmbox_init ((void *)&user_data, &ipmbox_rx_cb);
+ test_fail_unless ((EINVAL != errno)
+ && (NULL != ctx)
+ && (user_data == *((int *)ctx->user_data))
+ && (&ipmbox_rx_cb == ctx->rx_cb)
+ && (NULL != ctx->first_buffer)
+ && (NULL == ctx->first_buffer->next)
+ && (0 == ctx->first_buffer->id)
+ && (NULL == ctx->first_buffer->data)
+ && (ctx->last_buffer == ctx->first_buffer)
+ && (0 == ctx->rx.length));
+ ctx->warning_assert = true;
+ } test_end;
+
+ test_begin(t, "rx cb")
+ {
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ test_fail_unless (987654321 == *((int *)ctx->user_data));
+ } test_end;
+
+ maximus_pending_isrs = 0;
+ ctx->rx.length = 0;
+
+ return;
+}
+
+void ipmbox_activate_test_case(test_t t)
+{
+ printf("activate\n");
+ test_case_begin(t, "activate");
+
+ test_begin(t, "NULL ipmbox")
+ {
+ dbg_fatal_try_begin
+ {
+ ipmbox_activate (NULL, false);
+ test_fail_unless (EINVAL == errno);
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("NULL ipmbox\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ test_begin(t, "activate")
+ {
+ ipmbox_activate (ctx, true);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+
+ return;
+}
+
+void ipmbox_uninit_test_case(test_t t)
+{
+ printf("uninit\n");
+ test_case_begin(t, "uninit");
+
+ test_begin(t, "uninit")
+ {
+ ipmbox_uninit(ctx);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+
+ return;
+}
+
+void ipmbox_tx_test_case(test_t t)
+{
+ // ethernet frame data
+ int frame_length = 1200;
+ u8 frame[1200];
+ memset(frame, '\0', frame_length); // init frame
+
+ // mailbox msg
+ ipmbox_msg_hdr_t hdr;
+ u32 mailbox[3];
+ uint length = 2; // init length
+ hdr.type = HLE_MSG_TYPE_NONE; // init hdr type
+ hdr.length = 1; // init hdr length
+ hdr.param = 0; // init hdr param
+ memset(mailbox, '\0', 3 * sizeof(u32)); // init mailbox
+
+ printf("tx\n");
+ test_case_begin(t, "tx");
+
+ test_begin(t, "tx none")
+ {
+ dbg_fatal_try_begin
+ {
+ // set mailbox
+ memcpy(mailbox, &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+
+ ipmbox_tx (ctx, mailbox, length);
+ test_fail_unless (EINVAL == errno);
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("tx none\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+
+ for (hdr.type = HLE_MSG_TYPE_DATA; hdr.type < HLE_MSG_TYPE_NB; hdr.type++)
+ {
+ /* Fill sci data. */
+
+ // hle type data or hle type interface
+ if ((HLE_MSG_TYPE_DATA == hdr.type) || (HLE_MSG_TYPE_INTERFACE == hdr.type))
+ {
+ int i;
+ int msg_index = 1; // init message index
+ maximus_hle_buffer_t *second_buffer = (maximus_hle_buffer_t *)malloc(sizeof(maximus_hle_buffer_t));
+ second_buffer->next = NULL;
+ second_buffer->id = 32;
+ second_buffer->data = (u32 *)malloc(frame_length);
+ for (i=0; i<frame_length; i++)
+ {
+ frame[i] = (u8)i;
+ *((u8*)second_buffer->data+i) = frame[i];
+ }
+ ctx->first_buffer->next = second_buffer;
+
+ if (HLE_MSG_TYPE_DATA == hdr.type)
+ {
+ // set hdr param
+ hdr.param = frame_length << 1;
+ }
+ else // (HLE_MSG_TYPE_INTERFACE == hdr.type)
+ {
+ u32 module_param = 0; // init module param
+
+ // set length
+ length = 3;
+
+ // set hdr length
+ hdr.length = 2;
+
+ // set hdr param
+ hdr.param = frame_length << 8; // data length
+ hdr.param |= 1; // module type
+
+ // set module param
+ module_param = 1 << 2; // data type
+ module_param |= 1 << 1; // encryption
+ module_param |= 1; // way
+
+ // set mailbox
+ mailbox[msg_index] = module_param; // set module param
+
+ // update message index
+ msg_index++;
+ }
+
+ // set mailbox
+ memcpy(&mailbox[0], &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+ mailbox[msg_index] = (u32)second_buffer->data; // set data
+
+ test_begin(t, "tx data or interface")
+ {
+ ipmbox_tx (ctx, mailbox, length);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+ }
+
+ // hle type buffer add
+ else if (HLE_MSG_TYPE_BUFFER_ADD == hdr.type)
+ {
+ // set mailbox
+ memcpy(mailbox, &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+
+ test_begin(t, "tx buffer add")
+ {
+ dbg_fatal_try_begin
+ {
+ // set mailbox
+ memcpy(mailbox, &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+
+ ipmbox_tx(ctx, mailbox, length);
+ test_fail_unless (EINVAL == errno);
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("tx buffer add\n%s\n", fatal_message);
+ }
+ dbg_fatal_try_end;
+
+ // reset errno
+ errno = 0;
+ } test_end;
+ }
+
+ // hle type send done
+ else if (HLE_MSG_TYPE_SEND_DONE == hdr.type)
+ {
+ test_begin(t, "tx send done")
+ {
+ // allocate buffer
+ u32 *data = (u32 *)malloc(1500);
+
+ // set mailbox
+ memcpy(mailbox, &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+ mailbox[1] = (u32)data;
+
+ ipmbox_tx(ctx, mailbox, length);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+ }
+
+ /* Check results. */
+
+ // hle type data
+ if (HLE_MSG_TYPE_DATA == hdr.type)
+ {
+ // check that the correct ether message has been sent to Maximus
+ test_begin(t, "ether message DATA")
+ {
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_hdr_t *sci_hdr;
+ ether_msg_hdr_t *ether_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_ether_open(&my_station);
+
+ // read sci and ether headers
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, buffer, sizeof(sci_msg_hdr_t)))
+ && (sizeof(ether_msg_hdr_t) == read(fd_in, buffer + sizeof(sci_msg_hdr_t), sizeof(ether_msg_hdr_t))));
+
+ // set sci and ether headers pointers
+ sci_hdr = (sci_msg_hdr_t *)buffer;
+ ether_hdr = (ether_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t));
+
+ // check ether header
+ test_fail_unless ((ETHERNET_TYPE_DATA == ether_hdr->type)
+ && (0 == ether_hdr->sniffer_type)
+ && (ETHERNET_FLAG_NONE == ether_hdr->flags));
+
+ // read the remaining part of message
+ test_fail_unless (frame_length == read(fd_in, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), frame_length));
+
+ // check ether data
+ test_fail_unless (0 == memcmp(frame, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), frame_length));
+
+ // close pipe
+ maximus_ether_close(fd_in);
+ } test_end;
+ }
+
+ // hle type buffer add
+ else if (HLE_MSG_TYPE_BUFFER_ADD == hdr.type)
+ {
+ // nothing to check
+ }
+
+ // hle type send done
+ else if (HLE_MSG_TYPE_SEND_DONE == hdr.type)
+ {
+ // check that the allocated buffer has been released
+ test_begin(t, "SEND DONE")
+ {
+ test_fail_unless (NULL == (u32 *)ctx->rx.mailbox[1]);
+ } test_end;
+ }
+
+ // hle type interface
+ else // HLE_MSG_TYPE_INTERFACE
+ {
+ // check that the correct ether message has been sent to Maximus
+ test_begin(t, "ether message SNIFFER")
+ {
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_hdr_t *sci_hdr;
+ ether_msg_hdr_t *ether_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_ether_open(&my_station);
+
+ // read sci and ether headers
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, buffer, sizeof(sci_msg_hdr_t)))
+ && (sizeof(ether_msg_hdr_t) == read(fd_in, buffer + sizeof(sci_msg_hdr_t), sizeof(ether_msg_hdr_t))));
+
+ // set sci and ether headers pointers
+ sci_hdr = (sci_msg_hdr_t *)buffer;
+ ether_hdr = (ether_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t));
+
+ // check ether header
+ test_fail_unless ((ETHERNET_TYPE_SNIFFER == ether_hdr->type)
+ && (1 == ether_hdr->sniffer_type)
+ && (ETHERNET_FLAG_MAX == ether_hdr->flags));
+
+ // read the remaining part of message
+ test_fail_unless (frame_length == read(fd_in, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), frame_length));
+
+ // check ether data
+ test_fail_unless (0 == memcmp(frame, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), frame_length));
+
+ // close pipe
+ maximus_ether_close(fd_in);
+ } test_end;
+ }
+
+ // hle type data or hle type interface
+ if ((HLE_MSG_TYPE_DATA == hdr.type) || (HLE_MSG_TYPE_INTERFACE == hdr.type))
+ {
+ test_begin(t, "ether message BUFFER RELEASED")
+ {
+ unsigned char buffer[SCI_MSG_MAX_SIZE];
+ sci_msg_hdr_t *sci_hdr;
+ ether_msg_hdr_t *ether_hdr;
+ int fd_in = -1;
+
+ // open pipe or socket
+ fd_in = maximus_ether_open(&my_station);
+
+ // read sci and ether headers
+ memset(buffer, '\0', SCI_MSG_MAX_SIZE);
+ test_fail_unless ((-1 != fd_in)
+ && (sizeof(sci_msg_hdr_t) == read(fd_in, buffer, sizeof(sci_msg_hdr_t)))
+ && (sizeof(ether_msg_hdr_t) == read(fd_in, buffer + sizeof(sci_msg_hdr_t), sizeof(ether_msg_hdr_t))));
+
+ // set sci and ether headers pointers
+ sci_hdr = (sci_msg_hdr_t *)buffer;
+ ether_hdr = (ether_msg_hdr_t *)(buffer + sizeof(sci_msg_hdr_t));
+
+ // check ether header
+ test_fail_unless ((ETHERNET_TYPE_BUFFER_RELEASED == ether_hdr->type)
+ && (0 == ether_hdr->sniffer_type)
+ && (ETHERNET_FLAG_NONE == ether_hdr->flags));
+
+ // read the remaining part of message
+ test_fail_unless (sizeof(u32) == read(fd_in, buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t), sizeof(u32)));
+
+ // check ether data
+ test_fail_unless (32 == *(buffer + sizeof(sci_msg_hdr_t) + sizeof(ether_msg_hdr_t)));
+
+ // close pipe
+ maximus_ether_close(fd_in);
+ } test_end;
+ }
+ }
+}
+
+void ipmbox_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);
+
+ test_suite_begin(t, "ipmbox");
+ ipmbox_init_test_case(t);
+ ipmbox_activate_test_case(t);
+ ipmbox_tx_test_case(t);
+ ipmbox_uninit_test_case(t);
+
+ station_down (&my_station);
+}