summaryrefslogtreecommitdiff
path: root/cesar/hle/src
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/hle/src')
-rw-r--r--cesar/hle/src/hle.c381
-rw-r--r--cesar/hle/src/trace.c68
2 files changed, 449 insertions, 0 deletions
diff --git a/cesar/hle/src/hle.c b/cesar/hle/src/hle.c
new file mode 100644
index 0000000000..5410d87f1c
--- /dev/null
+++ b/cesar/hle/src/hle.c
@@ -0,0 +1,381 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hle.c
+ * \brief function of the HLE
+ * \ingroup hle
+ *
+ */
+#include "common/std.h"
+#include "common/defs/ethernet.h"
+
+#include "hal/hle/defs.h"
+#include "hal/hle/ipmbox.h"
+#include "hle/hle.h"
+#include "cl/cl.h"
+
+#include "hle/inc/context.h"
+#include "hle/inc/trace.h"
+
+#include "mac/common/ntb.h"
+
+/** Hle global context */
+static hle_t hle_global;
+
+/**
+ * Initialize the HLE.
+ *
+ * \param cl the convergence layer context.
+ * \return the hle context
+ */
+hle_t *hle_init (cl_t *cl)
+{
+ hle_t *ctx;
+ dbg_assert (cl);
+
+ ctx = &hle_global;
+ hle_global.cl = cl;
+
+ /** Intialize the CL data call backs. */
+ cl_data_recv_init (cl, (cl_data_recv_cb_t) hle_data_recv, &hle_global);
+ cl_data_send_done_init (cl, (cl_data_send_done_cb_t) hle_data_send_done,
+ &hle_global);
+
+ /** Intialize the CL MMEs call backs. */
+ cl_mme_init_ul_as_data (cl, (cl_mme_ul_send_done_cb_t) hle_mme_recv,
+ &hle_global);
+ cl_mme_ul_init_send_done (cl,
+ (cl_mme_ul_recv_done_cb_t) hle_mme_send_done, &hle_global);
+
+ /** Intialize the ipmbox */
+ hle_global.ipmbox = ipmbox_init (&hle_global,
+ (ipmbox_rx_cb_t) hle_ipmbox_recv);
+
+ /** Initialize the trace system. */
+ hle_trace_init (&hle_global);
+
+ /* Tracing */
+ HLE_TRACE (INIT, mac_ntb());
+
+ return &hle_global;
+}
+
+/**
+ * Unitialize the HLE.
+ *
+ * \param ctx the hle context.
+ */
+void hle_uninit (hle_t *ctx)
+{
+ dbg_assert (ctx);
+ /* tracing data */
+ HLE_TRACE(UNINIT, mac_ntb());
+
+ hle_trace_uninit (ctx);
+}
+
+/**
+ * Initialise the interface to add an Interface buffer.
+ *
+ * \param ctx the hle context.
+ * \param cb the function to call on interface buffer reception.
+ * \param user_data the user_data to provide on function call.
+ */
+void
+hle_init_interface_buffer_add_cb (hle_t *ctx, hle_interface_buffer_add_cb_t
+ cb, void *user_data)
+{
+ dbg_assert (ctx);
+ dbg_assert (cb);
+
+ ctx->interface_buffer_add_cb = cb;
+ ctx->interface_buffer_add_user_data = user_data;
+}
+
+/**
+ * Send a data to the Convergence Layer to be sent over the PWL.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer containing the data to send.
+ * \param length the data length
+ */
+void hle_data_send (hle_t *ctx, u8 *buffer, uint length)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (length >= ETH_PACKET_MIN_SIZE && length <= ETH_PACKET_MAX_SIZE);
+
+ /* tracing data */
+ HLE_TRACE(DATA_SEND, mac_ntb(), length, buffer);
+
+ cl_data_send (ctx->cl, buffer, length);
+}
+
+/**
+ * Called by the Convergence layer when the data has been sent to the PWL.
+ * This allows the HLE to know which buffer is newly available to be used or
+ * give it back to the ARM. (the buffer is borrowed by the linux).
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer used to send the data.
+ */
+void hle_data_send_done (hle_t *ctx, u8 *buffer)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ctx->ipmbox);
+
+ uint word[2];
+
+ /* Tracing data. */
+ HLE_TRACE (DATA_SEND_DONE, mac_ntb(), buffer);
+
+ word[0] = BF_FILL (IPMBOX_REG, (MSG_TYPE, HLE_MSG_TYPE_SEND_DONE),
+ (MSG_LENGTH, 1), (PARAM_BUFFER_TYPE, 0));
+
+ word[1] = (uint) buffer;
+
+ ipmbox_tx (ctx->ipmbox, word, 2);
+}
+
+/**
+ * Receives a data from the Convergence layer.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer used to receive the data
+ * \param length the length of the data received.
+ */
+void hle_data_recv (hle_t *ctx, u8 *buffer, uint length)
+{
+ uint word[2];
+
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ETH_PACKET_MIN_SIZE <= length && length <=
+ ETH_PACKET_MAX_SIZE);
+
+ /* Tracing data. */
+ HLE_TRACE (DATA_RECV, mac_ntb(), length, buffer);
+
+ word[0] = BF_FILL (IPMBOX_REG, (MSG_TYPE, HLE_MSG_TYPE_DATA),
+ (MSG_LENGTH, 1), (PARAM_MSG_TYPE, 0),
+ (PARAM_MSG_LENGTH, length));
+
+ word[1] = (uint) buffer;
+
+ ipmbox_tx (ctx->ipmbox, word, 2);
+}
+
+/**
+ * Provides a buffer to the CL in order to receive new MMEs from the CP.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer to provide to the CL.
+ */
+void hle_data_buffer_add (hle_t *ctx, u8 *buffer)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ctx->cl);
+
+ /* Tracing data. */
+ HLE_TRACE (DATA_BUFFER_ADD, mac_ntb(), buffer);
+
+ cl_data_buffer_add (ctx->cl, buffer);
+}
+
+/**
+ * Send a MME to the Convergence Layer to be provide to the CP.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer containing the data to send.
+ * \param length the data length
+ */
+void hle_mme_send (hle_t *ctx, u8 *buffer, uint length)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ETH_PACKET_MIN_SIZE <= length && length <= ETH_PACKET_MAX_SIZE);
+
+ /* Tracing data. */
+ HLE_TRACE (MME_BUFFER_ADD, mac_ntb(), buffer);
+
+ cl_mme_ul_send (ctx->cl, buffer, length);
+}
+
+/**
+ * Called by the Convergence layer when the data has been sent to the CP.
+ * This allows the HLE to know which buffer is newly available to be used or
+ * give it back to the ARM. (the buffer is borrowed by the linux).
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer used to send the data.
+ */
+void hle_mme_send_done (hle_t *ctx, u8 *buffer)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ctx->ipmbox);
+
+ uint word[2];
+
+ /* Tracing data. */
+ HLE_TRACE (MME_SEND_DONE, mac_ntb(), buffer);
+
+ word[0] = BF_FILL (IPMBOX_REG, (MSG_TYPE, HLE_MSG_TYPE_SEND_DONE),
+ (MSG_LENGTH, 1), (PARAM_BUFFER_TYPE, 1));
+ word[1] = (uint) buffer;
+
+ ipmbox_tx (ctx->ipmbox, word, 2);
+}
+
+/**
+ * Receives a MME from the Convergence layer.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer used to receive the data
+ * \param length the length of the data received.
+ */
+void hle_mme_recv (hle_t *ctx, u8 *buffer, uint length)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (60 <= length && length <= 1518);
+
+ uint word[2];
+
+ /* Tracing data. */
+ HLE_TRACE (MME_RECV, mac_ntb(), length, buffer);
+
+ word[0] = BF_FILL (IPMBOX_REG, (MSG_TYPE, HLE_MSG_TYPE_DATA),
+ (MSG_LENGTH, 1), (PARAM_MSG_TYPE, 1),
+ (PARAM_MSG_LENGTH, length));
+ word[1] = (uint) buffer;
+
+ ipmbox_tx (ctx->ipmbox, word, 2);
+}
+
+/**
+ * Provides a buffer to the CL in order to receive new MMEs from the CP.
+ *
+ * \param hle the hle context.
+ * \param buffer the buffer to provide to the CL.
+ */
+void hle_mme_buffer_add (hle_t *ctx, u8 *buffer)
+{
+ dbg_assert (ctx);
+ dbg_assert (buffer);
+ dbg_assert (ctx->cl);
+
+ /* Tracing data. */
+ HLE_TRACE (MME_BUFFER_ADD, mac_ntb(), buffer);
+
+ cl_mme_buffer_add (ctx->cl, buffer);
+}
+
+/**
+ * Receives a message from the Linux.
+ *
+ * \param ctx the hle context.
+ * \param msg_buffer the pointer of the buffer containing the messages to read
+ * \param length the length of the messages in words.
+ */
+bool hle_ipmbox_recv (hle_t *ctx, u32 *msg_buffer, uint length)
+{
+ dbg_assert (msg_buffer);
+ dbg_assert (ctx);
+
+ uint length_processed;
+ uint msg;
+ uint type;
+
+ uint data_length;
+ uint data_type;
+
+ length_processed = 0;
+ while (length_processed < length)
+ {
+ msg = read_u32_from_word ((u8 *) (msg_buffer + length_processed));
+ type = BF_GET (IPMBOX_REG__MSG_TYPE, msg);
+
+ switch (type)
+ {
+ case HLE_MSG_TYPE_DATA /* Data type */:
+ data_type = BF_GET(IPMBOX_REG__PARAM_MSG_TYPE, msg); /* data type MME or DATA */
+ data_length = BF_GET (IPMBOX_REG__PARAM_MSG_LENGTH, msg);
+
+ if (data_type == 0) /* Data */
+ hle_data_send (ctx,
+ (u8 *) msg_buffer[length_processed + 1], data_length);
+ else
+ hle_mme_send (ctx,
+ (u8 *) msg_buffer[length_processed + 1], data_length);
+ break;
+ case HLE_MSG_TYPE_BUFFER_ADD /* Buffer ADD */ :
+ data_type = BF_GET (IPMBOX_REG__PARAM_BUFFER_TYPE, msg);
+
+ switch (data_type)
+ {
+ case HLE_BUFFER_ALLOC_MME:
+ hle_mme_buffer_add (ctx, (u8 *) *(msg_buffer
+ + length_processed + 1));
+ break;
+ case HLE_BUFFER_ALLOC_DATA:
+ hle_data_buffer_add (ctx, (u8 *) *(msg_buffer
+ + length_processed + 1));
+ break;
+ case HLE_BUFFER_ALLOC_INTERFACE:
+ (*ctx->interface_buffer_add_cb)
+ (ctx->interface_buffer_add_user_data, (u8 *)
+ *(msg_buffer + length_processed + 1));
+ break;
+ }
+ break;
+ }
+
+ /** Message length + the message header. */
+ length_processed += BF_GET (IPMBOX_REG__MSG_LENGTH, msg) + 1;
+ }
+
+ return true;
+}
+
+/**
+ * Activate the HLE to receive messages from the IPMbox.
+ *
+ * \param ctx the HLE context.
+ * \param active boolean to active or unactive the reception of messages.
+ */
+void
+hle_activate (hle_t *ctx, bool active)
+{
+ dbg_assert (ctx);
+
+ ipmbox_activate (ctx->ipmbox, active);
+
+ /* Trace system. */
+ HLE_TRACE (IPMBOX, mac_ntb, active);
+}
+
+/**
+ * Send a packet to the ipmbox.
+ *
+ * \param ctx the hle context.
+ * \param msg the message address to post the message in the ipmbox.
+ * \param length the length of the message in words.
+ */
+void
+hle_ipmbox_send (hle_t *ctx, u32 *msg, uint length)
+{
+ dbg_assert (ctx);
+ dbg_assert (msg);
+ dbg_assert (length);
+
+ ipmbox_tx (ctx->ipmbox, msg, length);
+}
+
diff --git a/cesar/hle/src/trace.c b/cesar/hle/src/trace.c
new file mode 100644
index 0000000000..ac3cbeb6cf
--- /dev/null
+++ b/cesar/hle/src/trace.c
@@ -0,0 +1,68 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hle/src/trace.c
+ * \brief trace buffer for the HLE
+ * \ingroup hle
+ *
+ */
+#include "common/std.h"
+
+#include "hle/hle.h"
+#include "hle/inc/context.h"
+#include "hle/inc/trace.h"
+
+/**
+ * Initialize the trace buffer
+ * \param ctx the hle context.
+ */
+void
+hle_trace_init (hle_t *ctx)
+{
+ static trace_namespace_t namespace;
+ static const trace_event_id_t event_ids[] =
+ {
+ TRACE_EVENT (HLE_TRACE_INIT, "HLE_INIT", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_UNINIT, "HLE_UNINIT", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_DATA_SEND, "HLE_DATA_SEND length : %d, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_DATA_SEND_DONE, "HLE_DATA_SEND_DONE buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_DATA_BUFFER_ADD, "HLE_DATA_BUFFER_ADD buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_DATA_RECV, "HLE_DATA_RECV length : %d, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_MME_BUFFER_ADD, "HLE_MME_BUFFER_ADD buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_MME_SEND, "HLE_MME_SEND length : %d, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_MME_SEND_DONE, "HLE_MME_SEND_DONE buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_MME_RECV, "HLE_MME_RECV length : %d, buffer @ : %x", TIMESTAMP),
+ TRACE_EVENT (HLE_TRACE_IPMBOX, "HLE_IPMBOX_ACTIVATE avctive : %d", TIMESTAMP),
+ };
+ dbg_assert (ctx);
+ trace_namespace_init (&namespace, event_ids, COUNT (event_ids));
+ trace_buffer_add (&ctx->trace, "hle", 8, 4, true, &namespace);
+}
+
+/**
+ * Uninit the trace buffer
+ * \param ctx the hle context
+ */
+void
+hle_trace_uninit (hle_t *ctx)
+{
+ dbg_assert (ctx);
+ trace_buffer_remove (&ctx->trace);
+}
+
+/**
+ * Print the trace buffers
+ * \param ctx the hle context
+ */
+void
+hle_trace_print (hle_t *ctx)
+{
+ dbg_assert(ctx);
+ trace_buffer_dbg_dump(&ctx->trace);
+}
+