summaryrefslogtreecommitdiff
path: root/hal
diff options
context:
space:
mode:
authorburet2007-12-14 16:53:53 +0000
committerburet2007-12-14 16:53:53 +0000
commitbad0aa732b5e7b04decae6c7f25769f209b136b5 (patch)
tree85339c0aeaf594a6a8b0f68bb61bc3979f4beec1 /hal
parentb5c90e360f34b7fcfde5481ee340bd14a0f7f557 (diff)
Maximus V2: Development of the IPMBOX and associated tests.
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@1149 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'hal')
-rw-r--r--hal/hle/ipmbox.h11
-rw-r--r--hal/hle/maximus/inc/maximus_defs.h2
-rw-r--r--hal/hle/maximus/inc/maximus_ether.h24
-rw-r--r--hal/hle/maximus/inc/maximus_ipmbox_ctx.h40
-rw-r--r--hal/hle/maximus/src/maximus_ether.c271
-rw-r--r--hal/hle/maximus/src/maximus_ipmbox.c177
-rw-r--r--hal/hle/maximus/test/Config2
-rw-r--r--hal/hle/maximus/test/inc/test_maximus_hle.h19
-rw-r--r--hal/hle/maximus/test/src/test_maximus_ether.c479
-rw-r--r--hal/hle/maximus/test/src/test_maximus_hle.c18
-rw-r--r--hal/hle/maximus/test/src/test_maximus_ipmbox.c240
11 files changed, 1136 insertions, 147 deletions
diff --git a/hal/hle/ipmbox.h b/hal/hle/ipmbox.h
index 13a6b3cf39..f12da7f6d0 100644
--- a/hal/hle/ipmbox.h
+++ b/hal/hle/ipmbox.h
@@ -18,18 +18,15 @@
struct ipmbox_msg_hdr_t
{
BITFIELDS_WORD(
- /** Message type. */
- u32 type:8;,
+ /** Optional parameters. */
+ u32 param:20;,
/** Number of parameter words (32 bits) following the header. */
u32 length:4;,
- /** Optional parameters. */
- u32 param:20;)
+ /** Message type. */
+ u32 type:8;)
};
typedef struct ipmbox_msg_hdr_t ipmbox_msg_hdr_t;
-/** Message data (length * 32 bits): any additional parameter words. */
-typedef u32 ipmbox_msg_data_t;
-
/**
* RX DSR callback function.
* \param user_data user data
diff --git a/hal/hle/maximus/inc/maximus_defs.h b/hal/hle/maximus/inc/maximus_defs.h
index 652cf5f9d3..69fa3de7e3 100644
--- a/hal/hle/maximus/inc/maximus_defs.h
+++ b/hal/hle/maximus/inc/maximus_defs.h
@@ -14,6 +14,6 @@
*/
/** Max size of Maximus mailbox. */
-#define MAXIMUS_MAILBOX_MAX_SIZE 1024
+#define MAXIMUS_HLE_MAILBOX_MAX_SIZE 1024
#endif /* hal_hle_maximus_inc_maximus_defs_h */
diff --git a/hal/hle/maximus/inc/maximus_ether.h b/hal/hle/maximus/inc/maximus_ether.h
index 00d15f4b31..984a73161b 100644
--- a/hal/hle/maximus/inc/maximus_ether.h
+++ b/hal/hle/maximus/inc/maximus_ether.h
@@ -15,18 +15,17 @@
#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, BUFFER_ADD, or BUFFER_RELEASE)
+ * \param type type of message (DATA, MME, DATA_BUFFER_ADD, MME_BUFFER_ADD, or BUFFER_RELEASED)
* \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);
+int maximus_ether_fill_hdr(ipmbox_t *ctx, sci_msg_t *msg, u8 type);
/**
* Process ether message received by the sci layer.
@@ -50,7 +49,20 @@ int maximus_ether_recv (sci_msg_t *msg, void *ipmbox);
int maximus_ether_recv_none (ipmbox_t *ctx, sci_msg_t *msg);
int maximus_ether_recv_data (ipmbox_t *ctx, sci_msg_t *msg);
int maximus_ether_recv_mme (ipmbox_t *ctx, sci_msg_t *msg);
-int maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg);
-int maximus_ether_recv_buffer_release (ipmbox_t *ctx, sci_msg_t *msg);
+int maximus_ether_recv_data_buffer_add (ipmbox_t *ctx, sci_msg_t *msg);
+int maximus_ether_recv_mme_buffer_add (ipmbox_t *ctx, sci_msg_t *msg);
+int maximus_ether_recv_buffer_released (ipmbox_t *ctx, sci_msg_t *msg);
+
+/**
+ * Send an Ether SCI message of type DATA, MME, or BUFFER_RELEASED to Maximus.
+ * \param ctx ipmbox current context
+ * \param type type of message (DATA, MME, or BUFFER_RELEASED)
+ * \param data_length sci message data length to send
+ * \param data pointer to sci message data to send
+ * \return 0 if ok, -1 if 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, uint data_length, u32 *data);
#endif /* hal_phy_maximus_inc_maximus_ether_h */
diff --git a/hal/hle/maximus/inc/maximus_ipmbox_ctx.h b/hal/hle/maximus/inc/maximus_ipmbox_ctx.h
index 0128fcc301..417fde63de 100644
--- a/hal/hle/maximus/inc/maximus_ipmbox_ctx.h
+++ b/hal/hle/maximus/inc/maximus_ipmbox_ctx.h
@@ -13,29 +13,47 @@
* \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
{
- /** Total length (in word) of received messages. */
- uint length;
- /** Pointer to the mailbox. */
- u32 *mailbox; // u32 mailbox[MAXIMUS_MAILBOX_MAX_SIZE]
+ /** 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 callback. */
+ /** RX DSR callback. */
ipmbox_rx_cb_t rx_cb;
- /** TX callback. */
- ipmbox_tx_cb_t tx_cb;
- /** DSR callback. */
- ipmbox_deferred_cb_t deferred_cb;
- /** Pointer to current ipmbox callback. */
- void *current_cb;
#ifdef ECOS
/** ipmbox interrupt descriptor for eCos: relates to RX and TX */
cyg_interrupt ipmbox_interrupt;
diff --git a/hal/hle/maximus/src/maximus_ether.c b/hal/hle/maximus/src/maximus_ether.c
index d05cb15f90..fee92d1193 100644
--- a/hal/hle/maximus/src/maximus_ether.c
+++ b/hal/hle/maximus/src/maximus_ether.c
@@ -14,30 +14,34 @@
#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_...'
#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_NB'
+#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 "mac/sar/inc/sar_mf.h" // for 'SAR_MSDU_PAYLOAD_MAX_SIZE' and 'SAR_MSDU_PAYLOAD_MIN_SIZE'
+#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 function_array[ETHERNET_TYPE_NB] = { &maximus_ether_recv_none,
&maximus_ether_recv_data,
&maximus_ether_recv_mme,
- &maximus_ether_recv_buffer_add,
- &maximus_ether_recv_buffer_release };
+ &maximus_ether_recv_data_buffer_add,
+ &maximus_ether_recv_mme_buffer_add,
+ &maximus_ether_recv_buffer_released };
/**
* 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, BUFFER_ADD, or BUFFER_RELEASE)
+ * \param type type of message (DATA, MME, DATA_BUFFER_ADD, MME_BUFFER_ADD, or BUFFER_RELEASED)
* \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)
+maximus_ether_fill_hdr(ipmbox_t *ctx, sci_msg_t *msg, u8 type)
{
int ret = -1;
@@ -107,9 +111,9 @@ maximus_ether_recv (sci_msg_t *msg, void *ipmbox)
/* Check ether header. */
dbg_assert_ptr(msg->hdr.ether);
- dbg_assert((ETHERNET_TYPE_NB > msg->hdr.ether->type) && (ETHERNET_TYPE_NONE < msg->hdr.ether->type));
+ dbg_assert(ETHERNET_TYPE_NB > msg->hdr.ether->type);
if ((NULL == msg->hdr.ether)
- || ((ETHERNET_TYPE_NB <= msg->hdr.ether->type) || (ETHERNET_TYPE_NONE >= msg->hdr.ether->type)))
+ || (ETHERNET_TYPE_NB <= msg->hdr.ether->type))
{
errno = EPROTO;
station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
@@ -140,7 +144,7 @@ maximus_ether_recv_none (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);
+ dbg_assert_print(false, "errno = %d because ether hdr type is incorrect (NONE)", errno);
return -1;
}
@@ -153,10 +157,14 @@ maximus_ether_recv_data (ipmbox_t *ctx, sci_msg_t *msg)
dbg_assert_ptr(msg);
dbg_assert_ptr(msg->hdr.ether);
dbg_assert_ptr(msg->sci_hdr);
+ dbg_assert((SAR_MSDU_PAYLOAD_MIN_SIZE <= msg->length) && (SAR_MSDU_PAYLOAD_MAX_SIZE >= msg->length));
+ dbg_assert_ptr(msg->data_begin);
if((NULL == ctx)
|| (NULL == msg)
|| (NULL == msg->hdr.ether)
- || (NULL == msg->sci_hdr))
+ || (NULL == msg->sci_hdr)
+ || ((SAR_MSDU_PAYLOAD_MIN_SIZE > msg->length) || (SAR_MSDU_PAYLOAD_MAX_SIZE < msg->length))
+ || (NULL == msg->data_begin))
{
errno = EINVAL;
station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
@@ -164,6 +172,30 @@ maximus_ether_recv_data (ipmbox_t *ctx, sci_msg_t *msg)
}
else
{
+ ipmbox_msg_hdr_t hdr;
+
+ // 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
+ hdr.param = msg->length;
+
+ /* Update mailbox. */
+ ctx->rx.length = hdr.length + 1;
+ // set hdr
+ memcpy(ctx->rx.mailbox, &hdr, sizeof(ipmbox_msg_hdr_t));
+ // set buffer pointer (32 bits): pointer to DATA buffer
+ ctx->rx.mailbox[1] = (u32)msg->data_begin;
+ sci_msg_pop(msg, msg->length);
+
+ // raise interruption
+ maximus_pending_isrs |= (1 << HAL_HLE_INTERRUPT_IPMBOX);
+
ret = 0;
}
@@ -179,10 +211,14 @@ maximus_ether_recv_mme (ipmbox_t *ctx, sci_msg_t *msg)
dbg_assert_ptr(msg);
dbg_assert_ptr(msg->hdr.ether);
dbg_assert_ptr(msg->sci_hdr);
+ dbg_assert((SAR_MSDU_PAYLOAD_MIN_SIZE <= msg->length) && (SAR_MSDU_PAYLOAD_MAX_SIZE >= msg->length));
+ dbg_assert_ptr(msg->data_begin);
if((NULL == ctx)
|| (NULL == msg)
|| (NULL == msg->hdr.ether)
- || (NULL == msg->sci_hdr))
+ || (NULL == msg->sci_hdr)
+ || ((SAR_MSDU_PAYLOAD_MIN_SIZE > msg->length) || (SAR_MSDU_PAYLOAD_MAX_SIZE < msg->length))
+ || (NULL == msg->data_begin))
{
errno = EINVAL;
station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
@@ -190,15 +226,38 @@ maximus_ether_recv_mme (ipmbox_t *ctx, sci_msg_t *msg)
}
else
{
+ ipmbox_msg_hdr_t hdr;
+
+ // 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): 1 for MME type
+ hdr.param = (1 << 11) | msg->length;
+
+ /* Update mailbox. */
+ ctx->rx.length = hdr.length + 1;
+ // set hdr
+ memcpy(ctx->rx.mailbox, &hdr, sizeof(ipmbox_msg_hdr_t));
+ // set buffer pointer (32 bits): pointer to DATA buffer
+ ctx->rx.mailbox[1] = (u32)msg->data_begin;
+ sci_msg_pop(msg, msg->length);
+
+ // 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)
+maximus_ether_recv_data_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
{
int ret = -1;
@@ -206,10 +265,14 @@ maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
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))
+ || (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,
@@ -217,6 +280,50 @@ maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
}
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 (1 bit): 0 for DATA allocation
+ hdr.param = 0;
+
+ // get requested buffer nb
+ memcpy(&buffer_nb, msg->data_begin, sizeof(u32));
+ sci_msg_pop(msg, sizeof(u32));
+
+ /* Update mailbox. */
+ ctx->rx.length = (hdr.length + 1) * buffer_nb;
+ for (i = 0; i < ctx->rx.length; 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));
+ sci_msg_pop(msg, sizeof(u32));
+
+ // 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;
+ }
+
+ // raise interruption
+ maximus_pending_isrs |= (1 << HAL_HLE_INTERRUPT_IPMBOX);
+
ret = 0;
}
@@ -224,7 +331,7 @@ maximus_ether_recv_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
}
int
-maximus_ether_recv_buffer_release (ipmbox_t *ctx, sci_msg_t *msg)
+maximus_ether_recv_mme_buffer_add (ipmbox_t *ctx, sci_msg_t *msg)
{
int ret = -1;
@@ -232,10 +339,14 @@ maximus_ether_recv_buffer_release (ipmbox_t *ctx, sci_msg_t *msg)
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))
+ || (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,
@@ -243,8 +354,134 @@ maximus_ether_recv_buffer_release (ipmbox_t *ctx, sci_msg_t *msg)
}
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 (1 bit): 1 for MME allocation
+ hdr.param = 1;
+
+ // get requested buffer nb
+ memcpy(&buffer_nb, msg->data_begin, sizeof(u32));
+ sci_msg_pop(msg, sizeof(u32));
+
+ /* Update mailbox. */
+ ctx->rx.length = (hdr.length + 1) * buffer_nb;
+ for (i = 0; i < ctx->rx.length; 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));
+ sci_msg_pop(msg, sizeof(u32));
+
+ // 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;
+ }
+
+ // raise interruption
+ maximus_pending_isrs |= (1 << HAL_HLE_INTERRUPT_IPMBOX);
+
ret = 0;
}
return ret;
}
+
+int
+maximus_ether_recv_buffer_released (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 (BUFFER_RELEASED)", errno);
+ return -1;
+}
+
+/**
+ * Send an Ether SCI message of type DATA, MME, or BUFFER_RELEASED to Maximus.
+ * \param ctx ipmbox current context
+ * \param type type of message (DATA, MME, or BUFFER_RELEASED)
+ * \param data_length sci message data length to send
+ * \param data pointer to sci message data to send
+ * \return 0 if ok, -1 if 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, 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));
+ 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)
+ || (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))
+ {
+ // fill sci data if any
+ if ((0 != data_length) && (data_length == (uint)sci_msg_push(&msg, data_length)))
+ {
+ memcpy(msg.data_begin, data, data_length);
+ }
+
+ // fill ether header
+ maximus_ether_fill_hdr(ctx, &msg, type);
+
+ // fill the sci header
+ sci_fill_hdr(my_station.sci, &msg, SCI_MSG_TYPE_ETHERNET, 0 /* flags */);
+
+ // 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/hal/hle/maximus/src/maximus_ipmbox.c b/hal/hle/maximus/src/maximus_ipmbox.c
index dac2c3afaf..90c16972b5 100644
--- a/hal/hle/maximus/src/maximus_ipmbox.c
+++ b/hal/hle/maximus/src/maximus_ipmbox.c
@@ -13,48 +13,24 @@
#include "common/std.h"
#include "hal/hle/ipmbox.h"
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...'
#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)
{
- int is_call_dsr;
- ipmbox_t *ctx;
- ctx = (ipmbox_t *)data;
cyg_drv_interrupt_mask(HAL_HLE_INTERRUPT_IPMBOX);
cyg_drv_interrupt_acknowledge(HAL_HLE_INTERRUPT_IPMBOX);
-
- /* check the callback to use */
- dbg_assert(ctx->current_cb);
- dbg_assert((ctx->current_cb == ctx->rx_cb) || (ctx->current_cb == ctx->tx_cb));
- if (ctx->current_cb == ctx->rx_cb)
- {
- is_call_dsr = (*ctx->rx_cb)(ctx->mailbox, ctx->length, ctx->user_data);
- }
- else if (ctx->current_cb == ctx->tx_cb)
- {
- is_call_dsr = (*ctx->tx_cb)(ctx->user_data);
- }
-
- /* reset current_cb pointer */
- ctx->current_cb = NULL;
-
- if(is_call_dsr)
- {
- return CYG_ISR_CALL_DSR; // cause DSR to be run
- }
- else
- {
- cyg_drv_interrupt_unmask(HAL_HLE_INTERRUPT_IPMBOX);
- return CYG_ISR_HANDLED;
- }
+ 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)
@@ -62,10 +38,10 @@ static void _ipmbox_ecos_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrwo
/* nothing to do except calling the hle dsr */
ipmbox_t *ctx;
ctx = (ipmbox_t *)data;
- dbg_assert(ctx->deferred_cb);
- if (NULL != ctx->deferred_cb)
+ dbg_assert(ctx->rx_cb);
+ if (NULL != ctx->rx_cb)
{
- (*ctx->deferred_cb)(ctx->user_data);
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
}
cyg_drv_interrupt_unmask(HAL_HLE_INTERRUPT_IPMBOX);
return;
@@ -74,29 +50,22 @@ static void _ipmbox_ecos_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrwo
/**
* Initialise the HAL HLE.
- * \param user_data user data passed to any callback, contains RX and TX data
- * \param rx_cb RX callback, callback used when an Ethernet packet is received
- * \param tx_cb TX callback, callback used when the Ethernet packet has been completely sent
- * \param deferred_cb DSR callback
+ * \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, ipmbox_tx_cb_t tx_cb,
- ipmbox_deferred_cb_t deferred_cb)
+ipmbox_init (void *user_data, ipmbox_rx_cb_t rx_cb)
{
static ipmbox_t ctx;
-
- static u32 mailbox[MAXIMUS_MAILBOX_MAX_SIZE];
- int i;
+ static maximus_hle_buffer_t first_buffer;
dbg_assert_ptr(user_data);
dbg_assert_ptr(rx_cb);
- dbg_assert_ptr(tx_cb);
- dbg_assert_ptr(deferred_cb);
if ((NULL == user_data)
- || (NULL == rx_cb)
- || (NULL == tx_cb)
- || (NULL == deferred_cb))
+ || (NULL == rx_cb))
{
errno = EINVAL;
station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
@@ -107,15 +76,13 @@ ipmbox_init (void *user_data, ipmbox_rx_cb_t rx_cb, ipmbox_tx_cb_t tx_cb,
memset(&ctx, '\0', sizeof(ipmbox_t));
ctx.user_data = user_data;
ctx.rx_cb = rx_cb;
- ctx.tx_cb = tx_cb;
- ctx.deferred_cb = deferred_cb;
- // initialize mailbox
- for (i=0; i<MAXIMUS_MAILBOX_MAX_SIZE; i++)
- {
- mailbox[i] = 0;
- }
- ctx.mailbox = mailbox;
+ // 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);
@@ -142,9 +109,111 @@ ipmbox_init (void *user_data, ipmbox_rx_cb_t rx_cb, ipmbox_tx_cb_t tx_cb,
* \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);
+ if ((NULL == ctx)
+ || (NULL == first_msg)
+ || (2 != 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(1 == hdr.length);
+ if ((HLE_MSG_TYPE_NB <= hdr.type) || (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)
+ {
+ // get DATA or MME length (11 bits): length of data into DATA or MME buffer
+ uint data_length = (uint)(hdr.param & 0x007FF);
+
+ // get type (1 bit): DATA or MME type
+ // 0: DATA type
+ // 1: MME type
+ u8 type = (u8)((hdr.param & 0x00800) >> 11);
+ if (0 == type)
+ {
+ type = ETHERNET_TYPE_DATA;
+ }
+ else
+ {
+ type = ETHERNET_TYPE_MME;
+ }
+
+ // get buffer pointer (32 bits): pointer to DATA or MME buffer
+ u32 data = *(first_msg + 1);
+
+ if (0 != maximus_ether_send(ctx, type, 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 packet", errno);
+ }
+ }
+ else if (HLE_MSG_TYPE_SEND_DONE == hdr.type)
+ {
+ bool found = false;
+
+ // get buffer pointer (32 bits): pointer to buffer to release
+ u32 data = *(first_msg + 1);
+
+ // before deallocating buffer, check that this pointer is still allocated
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer;
+ maximus_hle_buffer_t *previous_buffer = current_buffer;
+ while ((NULL != current_buffer->next) && !found)
+ {
+ previous_buffer = current_buffer;
+ current_buffer = current_buffer->next;
+ found = (data == (u32)current_buffer->data);
+ }
+ dbg_assert(found);
+ if (!found)
+ {
+ errno = EINVAL;
+ station_log(&my_station, STATION_LOG_ERROR, STATION_LOGTYPE_ETHER,
+ "%s: errno = %d", __FUNCTION__, errno);
+ }
+ else
+ {
+ u32 id = current_buffer->id;
+ free(current_buffer->data);
+
+ // before deallocating current_buffer, link previous to next
+ previous_buffer->next = current_buffer->next;
+ free(current_buffer);
+
+ if (0 != maximus_ether_send(ctx, ETHERNET_TYPE_BUFFER_RELEASED, 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 // HLE_MSG_TYPE_BUFFER_ADD
+ {
+ 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/hal/hle/maximus/test/Config b/hal/hle/maximus/test/Config
new file mode 100644
index 0000000000..5077dbafd3
--- /dev/null
+++ b/hal/hle/maximus/test/Config
@@ -0,0 +1,2 @@
+CONFIG_DEBUG = y
+CONFIG_DEBUG_FATAL_CATCH = y
diff --git a/hal/hle/maximus/test/inc/test_maximus_hle.h b/hal/hle/maximus/test/inc/test_maximus_hle.h
index b647afcbfd..68327f48c9 100644
--- a/hal/hle/maximus/test/inc/test_maximus_hle.h
+++ b/hal/hle/maximus/test/inc/test_maximus_hle.h
@@ -14,25 +14,12 @@
*/
/**
- * RX callback function.
+ * 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
- * \param user_data user data, contains RX and TX data
* \return true if a DSR is requested
*/
-bool ipmbox_rx_cb (u32 *first_msg, uint length, void *user_data);
-
-/**
- * TX callback function.
- * \param user_data user data, contains RX and TX data
- * \return true if a DSR is requested
- */
-bool ipmbox_tx_cb (void *user_data);
-
-/**
- * If a DSR was requested, this callback is called.
- * \param user user data, contains RX and TX data
- */
-void ipmbox_deferred_cb (void *user_data);
+void ipmbox_rx_cb (void *user_data, u32 *first_msg, uint length);
#endif /* hal_hle_maximus_test_inc_test_maximus_hle_h */
diff --git a/hal/hle/maximus/test/src/test_maximus_ether.c b/hal/hle/maximus/test/src/test_maximus_ether.c
index 66be14ef8e..0fff2cf669 100644
--- a/hal/hle/maximus/test/src/test_maximus_ether.c
+++ b/hal/hle/maximus/test/src/test_maximus_ether.c
@@ -16,42 +16,489 @@
#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;
-/** User data for Maximus. */
-struct maximus_user_data_t
-{
- /** RX data. */
- int rx_data;
- /** TX data. */
- int tx_data;
-};
-typedef struct maximus_user_data_t maximus_user_data_t;
-
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;
+
+ 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))
+ && (EINVAL != errno)
+ && (ETHERNET_VERSION == msg.hdr.ether->version)
+ && (type == msg.hdr.ether->type)
+ && (0 == 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))
+ && (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;
+ } 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")
+ {
+ // 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.flags = 0;
+ ether_hdr.reserved = 0;
+
+ // test ether type none
+ 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;
+
+ 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 ((data_length == (uint)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)
+ {
+ u32 buffer_nb = 1;
+ u32 buffer_id = 1;
+ test_fail_unless ((sizeof(u32) == (uint)sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buffer_nb, sizeof(u32));
+ test_fail_unless ((sizeof(u32) == (uint)sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buffer_id, sizeof(u32));
+ }
+
+ // ether type mme buffer add
+ else // ETHERNET_TYPE_MME_BUFFER_ADD
+ {
+ u32 buffer_nb = 10;
+ u32 buffer_id;
+ for (buffer_id = buffer_nb + 1; buffer_id > 1; buffer_id--)
+ {
+ test_fail_unless ((sizeof(u32) == (uint)sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buffer_id, sizeof(u32));
+ }
+ test_fail_unless ((sizeof(u32) == (uint)sci_msg_push(&msg, sizeof(u32)))
+ && (EINVAL != errno)
+ && (ENOSPC != errno));
+ memcpy(msg.data_begin, &buffer_nb, sizeof(u32));
+ }
+
+ // fill ether header
+ test_fail_unless ((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.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 = (HLE_MSG_TYPE_DATA << 24) | (1 << 20) | data_length; // ipmbox msg hdr
+ if (ETHERNET_TYPE_MME == ether_hdr.type)
+ {
+ hdr |= (1 << 11);
+ }
+
+ 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);
+ } 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];
+ mailbox[0] = (HLE_MSG_TYPE_BUFFER_ADD << 24) | (1 << 20); // ipmbox msg hdr
+ mailbox[1] = (u32)ctx->last_buffer->data; // ipmbox msg data
+
+ test_fail_unless ((maximus_pending_isrs & (1 << HAL_HLE_INTERRUPT_IPMBOX))
+ && (2 == ctx->rx.length)
+ && (0 == memcmp(ctx->rx.mailbox, mailbox, 2 * sizeof(u32)))
+ && (NULL == ctx->last_buffer->next)
+ && (1 == ctx->last_buffer->id)
+ && (NULL != ctx->last_buffer->data));
+ (*ctx->rx_cb)(ctx->user_data, ctx->rx.mailbox, ctx->rx.length);
+ maximus_pending_isrs &= (0 << HAL_HLE_INTERRUPT_IPMBOX);
+ } test_end;
+ }
+
+ // test ether type mme buffer add
+ else // ETHERNET_TYPE_MME_BUFFER_ADD
+ {
+ test_begin(t, "ether type mme buffer add")
+ {
+ uint i;
+ u32 mailbox[20];
+ u32 hdr = (HLE_MSG_TYPE_BUFFER_ADD << 24) | (1 << 20) | 1; // ipmbox msg hdr
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer->next->next;
+ for (i=0; i<20; 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))
+ && (20 == ctx->rx.length)
+ && (0 == memcmp(ctx->rx.mailbox, mailbox, 20 * sizeof(u32))));
+
+ // check list of the 10 allocated buffers
+ current_buffer = ctx->first_buffer->next->next;
+ for (i=1; i<10; i++)
+ {
+ test_fail_unless ((NULL != current_buffer->next)
+ && (i+1 == current_buffer->id)
+ && (NULL != current_buffer->data));
+ current_buffer = current_buffer->next;
+ }
+ test_fail_unless ((NULL == current_buffer->next)
+ && (11 == 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);
+ } test_end;
+
+ test_begin(t, "release allocated buffers")
+ {
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer->next;
+ maximus_hle_buffer_t *next_buffer = NULL;
+ uint buffer_nb = 0;
+ while (NULL != current_buffer)
+ {
+ next_buffer = current_buffer->next;
+ free(current_buffer->data);
+ free(current_buffer);
+ current_buffer = next_buffer;
+ buffer_nb++;
+ }
+ test_fail_unless (11 == buffer_nb);
+ } test_end;
+ }
+ }
+ } test_end;
+
+ // test ether type buffer released
+ 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;
+}
+
+void maximus_ether_send_test_case(test_t t)
+{
+ // ether type
+ u8 type = ETHERNET_TYPE_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 null")
+ {
+ dbg_fatal_try_begin
+ {
+ test_fail_unless ((0 > (maximus_ether_send(ctx, type, 0, NULL)))
+ && (EINVAL == errno));
+ }
+ dbg_fatal_try_catch (const char *fatal_message)
+ {
+ printf("send null\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, 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, or buffer released
+ else if ((ETHERNET_TYPE_DATA == type)
+ || (ETHERNET_TYPE_MME == type)
+ || (ETHERNET_TYPE_BUFFER_RELEASED == type))
+ {
+ // ether type data or mme
+ if ((ETHERNET_TYPE_DATA == type) || (ETHERNET_TYPE_MME == type))
+ {
+ // set data
+ int i;
+ for (i=0; i<data_length; i++)
+ {
+ data[i] = (u8)i;
+ }
+ }
+
+ // ether type buffer release
+ else // ETHERNET_TYPE_BUFFER_RELEASE
+ {
+ // 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, 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
+ fd_in = open(my_station.pipe_out_name, O_RDONLY);
+
+ // 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);
+
+ // 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
+ close(fd_in);
+ } test_end;
+ }
+ }
}
void ether_test_suite(test_t t)
{
- maximus_user_data_t user_data = { 123456789, 987654321 };
+ int user_data = 1234567890;
// reset errno
errno = 0;
@@ -59,17 +506,15 @@ void ether_test_suite(test_t t)
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;
ctx = ipmbox_init ((void*)&user_data,
- &ipmbox_rx_cb,
- &ipmbox_tx_cb,
- &ipmbox_deferred_cb);
+ &ipmbox_rx_cb);
ctx->warning_assert = 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/hal/hle/maximus/test/src/test_maximus_hle.c b/hal/hle/maximus/test/src/test_maximus_hle.c
index 8ef27812c0..2dc7e226fa 100644
--- a/hal/hle/maximus/test/src/test_maximus_hle.c
+++ b/hal/hle/maximus/test/src/test_maximus_hle.c
@@ -21,21 +21,11 @@ void ether_test_suite (test_t t);
uint32_t maximus_pending_isrs;
station_ctx_t my_station;
-bool
-ipmbox_rx_cb (u32 *first_msg, uint length, void *user_data)
-{
- return true;
-}
-
-bool
-ipmbox_tx_cb (void *user_data)
-{
- return true;
-}
-
void
-ipmbox_deferred_cb (void *user_data)
+ipmbox_rx_cb (void *user_data, u32 *first_msg, uint length)
{
+ int *my_data = (int *)user_data;
+ *my_data = 987654321;
return;
}
@@ -45,8 +35,8 @@ main (int argc, char **argv)
test_t t;
test_init(t, argc, argv);
- ipmbox_test_suite(t);
ether_test_suite(t);
+ ipmbox_test_suite(t);
test_result(t);
return test_nb_failed(t) == 0 ? 0 : 1;
diff --git a/hal/hle/maximus/test/src/test_maximus_ipmbox.c b/hal/hle/maximus/test/src/test_maximus_ipmbox.c
index 165438b7d6..f6d28485ff 100644
--- a/hal/hle/maximus/test/src/test_maximus_ipmbox.c
+++ b/hal/hle/maximus/test/src/test_maximus_ipmbox.c
@@ -14,13 +14,17 @@
#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/forward.h" // for 'ipmbox_t'
+#include "hal/hle/defs.h" // for 'HLE_MSG_TYPE_...'
#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'
@@ -29,12 +33,241 @@ 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));
+ 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;
+
+ 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[2];
+ 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', length * 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
+ if (HLE_MSG_TYPE_DATA == hdr.type)
+ {
+ // set hdr param
+ hdr.param = frame_length;
+
+ // set mailbox
+ memcpy(&mailbox[0], &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+ mailbox[1] = (u32)frame; // set data
+
+ test_begin(t, "tx data")
+ {
+ 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 // HLE_TYPE_SEND_DONE
+ {
+ maximus_hle_buffer_t *second_buffer = (maximus_hle_buffer_t *)malloc(sizeof(maximus_hle_buffer_t));
+ maximus_hle_buffer_t *last_buffer = (maximus_hle_buffer_t *)malloc(sizeof(maximus_hle_buffer_t));
+ last_buffer->next = NULL;
+ last_buffer->id = 100;
+ last_buffer->data = (u32 *)malloc(frame_length);
+ second_buffer->next = last_buffer;
+ second_buffer->id = 32;
+ second_buffer->data = (u32 *)malloc(frame_length);
+ ctx->first_buffer->next = second_buffer;
+
+ // set hdr param
+ hdr.param = 0;
+
+ // set mailbox
+ memcpy(&mailbox[0], &hdr, sizeof(ipmbox_msg_hdr_t)); // set first msg
+ mailbox[1] = (u32)second_buffer->data; // set data
+
+ test_begin(t, "tx send done")
+ {
+ ipmbox_tx(ctx, mailbox, length);
+ test_fail_unless (EINVAL != errno);
+ } test_end;
+
+ test_begin(t, "release allocated buffers")
+ {
+ maximus_hle_buffer_t *current_buffer = ctx->first_buffer->next;
+ maximus_hle_buffer_t *next_buffer = NULL;
+ uint buffer_nb = 0;
+ while (NULL != current_buffer)
+ {
+ next_buffer = current_buffer->next;
+ free(current_buffer->data);
+ free(current_buffer);
+ current_buffer = next_buffer;
+ buffer_nb++;
+ }
+ test_fail_unless (1 == buffer_nb);
+ } test_end;
+ }
+
+ /* Check results. */
+
+ // hle type data
+ if ((HLE_MSG_TYPE_DATA == hdr.type) || (HLE_MSG_TYPE_SEND_DONE == hdr.type))
+ {
+ // 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
+ fd_in = open(my_station.pipe_out_name, O_RDONLY);
+
+ // 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));
+
+ // test hle type data
+ if (HLE_MSG_TYPE_DATA == hdr.type)
+ {
+ // check ether header
+ test_fail_unless (ETHERNET_TYPE_DATA == ether_hdr->type);
+
+ // 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));
+ }
+
+ // test hle type send done
+ else // HLE_MSG_TYPE_SEND_DONE
+ {
+ // check ether header
+ test_fail_unless (ETHERNET_TYPE_BUFFER_RELEASED == ether_hdr->type);
+
+ // 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
+ close(fd_in);
+ } test_end;
+ }
+
+ // hle type buffer add
+ else if (HLE_MSG_TYPE_BUFFER_ADD == hdr.type)
+ {
+ test_begin(t, "tx buffer add")
+ {
+
+ } test_end;
+ }
+
+ // hle type send done
+ else // HLE_MSG_TYPE_SEND_DONE
+ {
+ test_begin(t, "tx send done")
+ {
+
+ } test_end;
+ }
+ }
}
void ipmbox_test_suite(test_t t)
@@ -45,7 +278,6 @@ void ipmbox_test_suite(test_t t)
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, "ipmbox");
ipmbox_init_test_case(t);