summaryrefslogtreecommitdiff
path: root/cesar/hal/phy/test
diff options
context:
space:
mode:
authorsave2008-04-07 14:17:42 +0000
committersave2008-04-07 14:17:42 +0000
commit3d58a62727346b7ac1a6cb36fed1a06ed72228dd (patch)
treed7788c3cf9f76426aef0286d0202e2097f0fa0eb /cesar/hal/phy/test
parent095dca4b0a8d4924093bab424f71f588fdd84613 (diff)
Moved the complete svn base into the cesar directory.
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@1769 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cesar/hal/phy/test')
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/Makefile13
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/sparc-Makefile14
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/sparc-ecos.ecc.sh5
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/src/bridgedma-init-test.c382
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/src/data.c546
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/src/test_bridgedma.c_old1003
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/synth-Makefile13
-rw-r--r--cesar/hal/phy/test/bridgedma-proto/synth-ecos.ecc.sh5
-rw-r--r--cesar/hal/phy/test/phy/Makefile3
-rw-r--r--cesar/hal/phy/test/phy/inc/access.h27
-rw-r--r--cesar/hal/phy/test/phy/inc/basic.h27
-rw-r--r--cesar/hal/phy/test/phy/inc/clk_sync.h45
-rw-r--r--cesar/hal/phy/test/phy/inc/context.h149
-rw-r--r--cesar/hal/phy/test/phy/inc/data.h27
-rw-r--r--cesar/hal/phy/test/phy/inc/gen.h64
-rw-r--r--cesar/hal/phy/test/phy/inc/msg.h168
-rw-r--r--cesar/hal/phy/test/phy/inc/test_phy.h92
-rw-r--r--cesar/hal/phy/test/phy/maximus-Makefile17
-rw-r--r--cesar/hal/phy/test/phy/maximus-ecos.ecc.sh8
-rw-r--r--cesar/hal/phy/test/phy/sparc-Makefile19
-rw-r--r--cesar/hal/phy/test/phy/sparc-ecos.ecc.sh5
-rw-r--r--cesar/hal/phy/test/phy/src/access.c532
-rw-r--r--cesar/hal/phy/test/phy/src/basic.c190
-rw-r--r--cesar/hal/phy/test/phy/src/clk_sync.c182
-rw-r--r--cesar/hal/phy/test/phy/src/data.c488
-rw-r--r--cesar/hal/phy/test/phy/src/gen.c84
-rw-r--r--cesar/hal/phy/test/phy/src/host_test_phy.cpp235
-rw-r--r--cesar/hal/phy/test/phy/src/test_phy.c412
28 files changed, 4755 insertions, 0 deletions
diff --git a/cesar/hal/phy/test/bridgedma-proto/Makefile b/cesar/hal/phy/test/bridgedma-proto/Makefile
new file mode 100644
index 0000000000..0423c997a8
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/Makefile
@@ -0,0 +1,13 @@
+all: synth sparc
+
+synth:
+ $(MAKE) -f synth-Makefile
+
+sparc:
+ $(MAKE) -f sparc-Makefile
+
+debug: obj/sparc/test-bridgedma-proto.elf
+ $(CROSS_COMPILE_sparc)objdump -DSt $< > $<.dis
+
+clean:
+ rm -rf obj
diff --git a/cesar/hal/phy/test/bridgedma-proto/sparc-Makefile b/cesar/hal/phy/test/bridgedma-proto/sparc-Makefile
new file mode 100644
index 0000000000..aa34c81fa3
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/sparc-Makefile
@@ -0,0 +1,14 @@
+BASE = ../../../..
+
+TARGET = sparc
+
+ECOS = y
+DEFS = -DCONFIG_BRIDGEDMA_PROTO
+
+TARGET_PROGRAMS = test-bridgedma-proto
+
+test-bridgedma-proto_SOURCES = bridgedma-init-test.c
+test-bridgedma-proto_MODULES = hal/phy lib
+
+VARIANT = sparc
+include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/phy/test/bridgedma-proto/sparc-ecos.ecc.sh b/cesar/hal/phy/test/bridgedma-proto/sparc-ecos.ecc.sh
new file mode 100644
index 0000000000..db2208c6cc
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/sparc-ecos.ecc.sh
@@ -0,0 +1,5 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new sparc_leon default
+cat >> $config <<'EOF'
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/hal/phy/test/bridgedma-proto/src/bridgedma-init-test.c b/cesar/hal/phy/test/bridgedma-proto/src/bridgedma-init-test.c
new file mode 100644
index 0000000000..fdc897c3a5
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/src/bridgedma-init-test.c
@@ -0,0 +1,382 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bridgedma-init-test.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "common/defs/ethernet.h"
+
+#include "lib/test.h"
+#include "lib/list.h"
+#include "lib/read_word.h"
+#include "lib/bitstream.h"
+
+#include "hal/phy/inc/bridgedma.h"
+#include "hal/phy/inc/bridgedma_proto.h"
+
+#include "mac/common/pb.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <cyg/infra/diag.h>
+
+#define START_OFFSET 128
+
+cyg_thread my_test_thread;
+cyg_handle_t my_test_thread_handle;
+u8 my_test_thread_stack [CYGNUM_HAL_STACK_SIZE_TYPICAL];
+
+pb_t *my_pb_first;
+pb_t *my_pb_last;
+phy_bridgedma_job_t *job_current;
+
+phy_bridgedma_job_t job1, job2, job3;
+phy_bridgedma_t *bridgedma_ctx;
+u8 frame_buffer [2048] __attribute__((aligned(2048)));
+crc_t crc_ctx;
+blk_t *pb_first, *pb_last, *pb_current;
+u32 mf_header;
+u32 enc_tab[256];
+uint ats;
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+bool _bridgedma_segmentation_cb(void *data, u32 status)
+{
+ // If no more jobs to process by the bridgedma wake up the test thread to
+ // continue
+ if (!job_current)
+ {
+ cyg_thread_resume (my_test_thread_handle);
+ }
+
+ if (job_current)
+ {
+ diag_printf ("----- Bridge Cb ----\n");
+ diag_printf ("SSN : %d\n",
+ ((pb_t*)job_current->first_pb_desc)->header.ssn);
+ diag_printf ("offset : %d\n", job_current->first_pb_offset);
+ diag_printf ("length : %d\n", read_u16_from_word
+ (((pb_t *)job_current->first_pb_desc)->data +
+ job_current->first_pb_offset) >> 2);
+ diag_printf ("---- END Bridge Cb ----\n");
+ }
+
+ job_current = job_current->next;
+ return true;
+}
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+void _bridgedma_deffered_cb(void *data)
+{
+}
+
+void bridgedma_init_test_case(test_t t)
+{
+ int user_data;
+
+ test_case_begin(t, "init");
+
+ test_begin(t, "init")
+ {
+ bridgedma_ctx = NULL;
+ bridgedma_ctx = phy_bridgedma_init(&user_data, _bridgedma_segmentation_cb, _bridgedma_deffered_cb);
+ test_fail_unless(
+ (bridgedma_ctx != NULL)
+ && (bridgedma_ctx->job_first == NULL)
+ && (bridgedma_ctx->job_current == NULL)
+ && (bridgedma_ctx->job_last == NULL)
+ && (bridgedma_ctx->user_data == &user_data)
+ && (bridgedma_ctx->bridgedma_cb == _bridgedma_segmentation_cb)
+ && (bridgedma_ctx->deferred_cb == _bridgedma_deffered_cb)
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+ } test_end;
+ return;
+}
+
+void bridgedma_segmentation_test_case(test_t t)
+{
+ uint i;
+ pb_t *my_current;
+ dbg_assert (bridgedma_ctx);
+ test_case_begin(t, "segmentation");
+
+ pb_first = blk_alloc_desc_range(5, &pb_last);
+ pb_last->next = NULL;
+
+ my_pb_first = (pb_t *) pb_first;
+ my_pb_last = (pb_t *)pb_last;
+
+ my_current = my_pb_first;
+ for (i = 0; i < 5; i++)
+ {
+ my_current->header.ssn = i;
+ my_current = my_current->next;
+ }
+
+ crc_ctx.width = 32;
+ crc_ctx.generator = HPAV_CRC32_GENERATOR;
+ crc_ctx.init = HPAV_CRC32_INIT;
+ crc_ctx.refin = true;
+ crc_ctx.refout = true;
+ crc_ctx.xorout = 0xffffffff;
+ crc_ctx.reg_init = 0;
+ crc_ctx.table.t32 = enc_tab;
+ crc_init(&crc_ctx);
+ ats = 0x12345678;
+
+ /************************************************************************
+ * simple segmentation with 3 mac frames into 5 PBs
+ * 1st mac frame: len=1518, offset=128, ATS, ICV into 1st to 4th PB
+ * 2nd mac frame: len=64, ATS, ICV into 4th PB
+ * 3nd mac frame: len=466, ATS, ICV, padding into 4th to 5th PB
+ ***********************************************************************/
+
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = &job2;
+ job1.data_addr = frame_buffer;
+ job1.header_len = 6;
+ job1.data_len = ETH_PACKET_MAX_SIZE;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = START_OFFSET;
+ job1.segment_len = 512;
+ job1.direction = 0;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.job_it = 1;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job1.mf_header1 = (((job1.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job1.mf_header2 = (ats >> 16);
+
+ memset(&job2, '\0', sizeof(job2));
+ job2.next = &job3;
+ job2.data_addr = frame_buffer + job1.data_len;
+ job2.header_len = 6;
+ job2.data_len = ETH_PACKET_MIN_SIZE;
+ job2.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job2.first_pb_offset = (START_OFFSET + job1.data_len + 10) % 512;
+ job2.segment_len = 512;
+ job2.direction = 0;
+ job2.crc_reset = 1;
+ job2.crc_store = 1;
+ job2.job_it = 1;
+ job2.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job2.mf_header1 = (((job2.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job2.mf_header2 = (ats >> 16);
+
+ memset(&job3, '\0', sizeof(job3));
+ job3.next = NULL;
+ job3.data_addr = frame_buffer + job1.data_len + job2.data_len;
+ job3.header_len = 6;
+ job3.data_len = sizeof(frame_buffer) - ETH_PACKET_MAX_SIZE - ETH_PACKET_MIN_SIZE;
+ job3.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job3.first_pb_offset = (START_OFFSET + job1.data_len + 10 + job2.data_len + 10) % 512;
+ job3.segment_len = 512;
+ job3.last = 1;
+ job3.direction = 0;
+ job3.crc_reset = 1;
+ job3.crc_store = 1;
+ job3.append_zero = 1;
+ job3.job_it = 1;
+ job3.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job3.mf_header1 = (((job3.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job3.mf_header2 = (ats >> 16);
+
+ job_current = &job1;
+ phy_bridgedma_start (bridgedma_ctx, &job1, &job3);
+
+ return;
+}
+
+void
+bridgedma_segmentation_verify_test_case (test_t test)
+{
+ uint payload_cnt;
+ uint crc_current;
+ pb_t *my_pb_current;
+
+ uint i;
+ uint length;
+ uint pb_offset;
+ uint qte_pb;
+ uint frame_offset;
+ bool cont;
+
+ test_begin(test, "segmentation of 3 frames")
+ {
+ for (i = 0, my_pb_current = my_pb_first; my_pb_current; my_pb_current =
+ my_pb_current->next, i++)
+ {
+ test_fail_if (my_pb_current->header.ssn != i, "Wong sequence");
+ }
+
+ /* check pb content */
+ /* check 1st mac frame into PB */
+ payload_cnt = 0;
+ crc_current = crc_compute_begin(&crc_ctx);
+
+ pb_offset = START_OFFSET;
+ job_current = &job1;
+ frame_offset = 0;
+ for (pb_current = pb_first, i = 0; i < 3; i++, job_current =
+ job_current->next)
+ {
+ cont = true;
+ length = 1 + (read_u16_from_word (pb_current->data + pb_offset) >> 2);
+
+ // To get the payload length, the frame length is 10
+ // bytes greater.
+ length -= 4;
+
+ diag_printf ("Length read in pb : %d\n", length);
+ diag_printf ("pb ssn : %d\n", ((pb_t *)pb_current)->header.ssn);
+ diag_printf ("pb offset : %d\n", pb_offset);
+ test_fail_unless (length == job_current->data_len,
+ "Data length is wrong.");
+
+ // Copy the data of the current pb.
+
+ // Jump directly to the start of the payload.
+ pb_offset += 6;
+ if (length + pb_offset > BLK_SIZE)
+ {
+ test_fail_unless (
+ bitstream_memcmp (frame_buffer + frame_offset,
+ pb_current->data + pb_offset,
+ BLK_SIZE - pb_offset),
+ "data corrupted");
+
+ frame_offset += BLK_SIZE - pb_offset;
+ length -= BLK_SIZE - pb_offset;
+ }
+ else
+ {
+ test_fail_unless (
+ bitstream_memcmp (frame_buffer + frame_offset,
+ pb_current->data + pb_offset,
+ length),
+ "data corrupted");
+
+ frame_offset += length;
+ cont = false;
+ }
+
+
+ if (cont)
+ {
+ // Add 10 to the length to use the complete MF length
+ // (ATS + MFH + ICV), the ATS and MFH are already include in the
+ // pb_offset.
+ for (qte_pb = (pb_offset + length + 4) / BLK_SIZE + 1;
+ qte_pb;
+ qte_pb --)
+ {
+ pb_current = pb_current->next;
+
+ if (length > BLK_SIZE)
+ {
+ test_fail_unless(
+ bitstream_memcmp (frame_buffer + frame_offset,
+ pb_current->data ,
+ BLK_SIZE),
+ "data corrupted");
+
+ length -= BLK_SIZE;
+ frame_offset += BLK_SIZE;
+ }
+ else
+ {
+ test_fail_unless(
+ bitstream_memcmp (frame_buffer + frame_offset,
+ pb_current->data ,
+ length),
+ "data corrupted");
+
+ frame_offset += length;
+ }
+ }
+ }
+
+ // The futur offset is length + 4 cause of the ICV of the MF.
+ // The ATS and the MFH has already been jumped above in the
+ // pb_offset.
+ pb_offset = (pb_offset + job_current->data_len + 4) % BLK_SIZE;
+ }
+ } test_end;
+
+ blk_release_desc_range((blk_t *)my_pb_first, (blk_t *) my_pb_last);
+}
+
+void
+test_thread_process (cyg_addrword_t data)
+{
+ test_t *test;
+
+ test = (test_t *) data;
+
+ bridgedma_init_test_case (*test);
+
+ bridgedma_segmentation_test_case (*test);
+
+
+ /* Just to test. */
+ diag_printf ("Job 1 header : %x\n", job1.mf_header1);
+ diag_printf ("Job 2 header : %x\n", job2.mf_header1);
+ diag_printf ("Job 3 header : %x\n", job3.mf_header1);
+
+ /* */
+
+ bridgedma_segmentation_verify_test_case (*test);
+
+ phy_bridgedma_uninit (bridgedma_ctx);
+
+ test_result (*test);
+
+#ifndef __sparc__
+ HAL_PLATFORM_EXIT (test_nb_failed (*test) == 0 ? 0 : 1);
+#endif
+}
+
+int
+main (void)
+{
+ test_t test;
+ uint i;
+
+ test_init (test, 0, NULL);
+
+ pb_first = NULL;
+ pb_last = NULL;
+
+ my_pb_first = NULL;
+ my_pb_last = NULL;
+
+ for (i = 0; i < 2048; i++)
+ frame_buffer[i] = i;
+
+ // Create the thread.
+ cyg_thread_create( 9,
+ &test_thread_process,
+ (cyg_addrword_t) &test,
+ "TEST_THREAD",
+ my_test_thread_stack,
+ CYGNUM_HAL_STACK_SIZE_TYPICAL,
+ &my_test_thread_handle,
+ &my_test_thread);
+ cyg_thread_resume (my_test_thread_handle);
+
+ return 0;
+}
diff --git a/cesar/hal/phy/test/bridgedma-proto/src/data.c b/cesar/hal/phy/test/bridgedma-proto/src/data.c
new file mode 100644
index 0000000000..20a7170cfb
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/src/data.c
@@ -0,0 +1,546 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file bridgedma-init-test.c
+ * \brief « brief description »
+ * \ingroup « module »
+ *
+ * « long description »
+ */
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "common/std.h"
+#include "common/defs/ethernet.h"
+
+#include "lib/test.h"
+#include "lib/list.h"
+#include "lib/read_word.h"
+
+#include "hal/phy/inc/bridgedma.h"
+#include "hal/phy/inc/bridgedma_proto.h"
+
+#include "mac/common/pb.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <cyg/infra/diag.h>
+
+#define START_OFFSET 128
+
+cyg_thread my_test_thread;
+cyg_handle_t my_test_thread_handle;
+u8 my_test_thread_stack [CYGNUM_HAL_STACK_SIZE_TYPICAL];
+
+pb_t *my_pb_first;
+pb_t *my_pb_last;
+phy_bridgedma_job_t *job_current;
+
+phy_bridgedma_job_t job1, job2, job3;
+phy_bridgedma_t *bridgedma_ctx;
+u8 frame_buffer [2048] __attribute__((aligned(2048)));
+crc_t crc_ctx;
+blk_t *pb_first, *pb_last, *pb_current;
+u32 mf_header;
+u32 enc_tab[256];
+uint ats;
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+bool _bridgedma_segmentation_cb(void *data, u32 status)
+{
+ job_current = job_current->next;
+
+ // If no more jobs to process by the bridgedma wake up the test thread to
+ // continue
+ if (!job_current)
+ {
+ cyg_thread_resume (my_test_thread_handle);
+ }
+
+ return true;
+}
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+void _bridgedma_deffered_cb(void *data)
+{
+}
+
+void bridgedma_init_test_case(test_t t)
+{
+ int user_data;
+
+ test_case_begin(t, "init");
+
+ test_begin(t, "init")
+ {
+ bridgedma_ctx = NULL;
+ bridgedma_ctx = phy_bridgedma_init(&user_data, _bridgedma_segmentation_cb, _bridgedma_deffered_cb);
+ test_fail_unless(
+ (bridgedma_ctx != NULL)
+ && (bridgedma_ctx->job_first == NULL)
+ && (bridgedma_ctx->job_current == NULL)
+ && (bridgedma_ctx->job_last == NULL)
+ && (bridgedma_ctx->user_data == &user_data)
+ && (bridgedma_ctx->bridgedma_cb == _bridgedma_segmentation_cb)
+ && (bridgedma_ctx->deferred_cb == _bridgedma_deffered_cb)
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+ } test_end;
+ return;
+}
+
+void bridgedma_segmentation_test_case(test_t t)
+{
+ uint i;
+ pb_t *my_current;
+ dbg_assert (bridgedma_ctx);
+ test_case_begin(t, "segmentation");
+
+ pb_first = blk_alloc_desc_range(5, &pb_last);
+ pb_last->next = NULL;
+
+ my_pb_first = (pb_t *) pb_first;
+ my_pb_last = (pb_t *)pb_last;
+
+ my_current = my_pb_first;
+ for (i = 0; i < 5; i++)
+ {
+ my_current->header.ssn = i;
+ my_current = my_current->next;
+ }
+
+ crc_ctx.width = 32;
+ crc_ctx.generator = HPAV_CRC32_GENERATOR;
+ crc_ctx.init = HPAV_CRC32_INIT;
+ crc_ctx.refin = true;
+ crc_ctx.refout = true;
+ crc_ctx.xorout = 0xffffffff;
+ crc_ctx.reg_init = 0;
+ crc_ctx.table.t32 = enc_tab;
+ crc_init(&crc_ctx);
+ ats = 0x12345678;
+
+ /************************************************************************
+ * simple segmentation with 3 mac frames into 5 PBs
+ * 1st mac frame: len=1518, offset=128, ATS, ICV into 1st to 4th PB
+ * 2nd mac frame: len=64, ATS, ICV into 4th PB
+ * 3nd mac frame: len=466, ATS, ICV, padding into 4th to 5th PB
+ ***********************************************************************/
+
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = &job2;
+ job1.data_addr = frame_buffer;
+ job1.header_len = 6;
+ job1.data_len = ETH_PACKET_MAX_SIZE;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = START_OFFSET;
+ job1.segment_len = 512;
+ job1.direction = 0;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.job_it = 1;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job1.mf_header1 = (((job1.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job1.mf_header2 = (ats >> 16);
+
+ memset(&job2, '\0', sizeof(job2));
+ job2.next = &job3;
+ job2.data_addr = frame_buffer + job1.data_len;
+ job2.header_len = 6;
+ job2.data_len = ETH_PACKET_MIN_SIZE;
+ job2.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job2.first_pb_offset = (START_OFFSET + job1.data_len + 10) % 512;
+ job2.segment_len = 512;
+ job2.direction = 0;
+ job2.crc_reset = 1;
+ job2.crc_store = 1;
+ job2.job_it = 1;
+ job2.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job2.mf_header1 = (((job2.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job2.mf_header2 = (ats >> 16);
+
+ memset(&job3, '\0', sizeof(job3));
+ job3.next = NULL;
+ job3.data_addr = frame_buffer + job1.data_len + job2.data_len;
+ job3.header_len = 6;
+ job3.data_len = sizeof(frame_buffer) - ETH_PACKET_MAX_SIZE - ETH_PACKET_MIN_SIZE;
+ job3.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job3.first_pb_offset = (START_OFFSET + job1.data_len + 10 + job2.data_len + 10) % 512;
+ job3.segment_len = 512;
+ job3.last = 1;
+ job3.direction = 0;
+ job3.crc_reset = 1;
+ job3.crc_store = 1;
+ job3.append_zero = 1;
+ job3.job_it = 1;
+ job3.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job3.mf_header1 = (((job3.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job3.mf_header2 = (ats >> 16);
+
+ job_current = &job1;
+ phy_bridgedma_start (bridgedma_ctx, &job1, &job3);
+
+
+// /************************************************************
+// * icv substitution + no ATS + no interrupt
+// ************************************************************/
+// memset(&job1, '\0', sizeof(job1));
+// job1.next = NULL;
+// job1.data_addr = frame_buffer;
+// job1.header_len = 2;
+// job1.data_len = 256;
+// job1.first_pb_desc = pb_first;
+// job1.first_pb_offset = 0;
+// job1.segment_len = 512;
+// job1.last = 1;
+// job1.direction = 0;
+// job1.crc_error = 1;
+// job1.crc_reset = 1;
+// job1.crc_store = 1;
+// job1.append_zero = 1;
+// job1.job_it = 0;
+// job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+// job1.mf_header1 = ((job1.data_len - 1) << 2) | 0x01; /* Payload */
+// bridgedma_ctx->proto_ctx.icv_substitution = 0xdeadbeef;
+// bridgedma_ctx->proto_ctx.icv_current = 0;
+//
+// test_begin(t, "icv substitution + no ATS + no interrupt")
+// {
+// phy_bridgedma_start(bridgedma_ctx, &job1, &job1);
+// pb_current = pb_first;
+// /* check for no ats */
+// mf_header = *((u32 *)(pb_current->data));
+// test_fail_unless(
+// ((u32) (mf_header & 0x0000ffff)
+// == (u32)((((unsigned int)job1.data_len - 1) << 2) | 0x01))
+// && !memcmp(pb_current->data + 2, frame_buffer, 256)
+// );
+// /* check for icv substitution */
+// mf_header = *((u32 *)(pb_current->data + 2 + 256));
+// test_fail_unless(
+// (mf_header == 0xdeadbeef)
+// );
+//
+// } test_end;
+//
+// phy_bridgedma_start(bridgedma_ctx, &job1, &job3);
+//
+// /***************************************************************
+// * no ATS + no ICV store + no append zero
+// ***************************************************************/
+//
+// memset(&job1, '\0', sizeof(job1));
+// job1.next = NULL;
+// job1.data_addr = frame_buffer;
+// job1.header_len = 2;
+// job1.data_len = 256;
+// job1.first_pb_desc = pb_first;
+// job1.first_pb_offset = 0;
+// job1.segment_len = 512;
+// job1.last = 1;
+// job1.direction = 0;
+// job1.crc_error = 1;
+// job1.crc_reset = 1;
+// job1.crc_store = 0;
+// job1.append_zero = 0;
+// job1.job_it = 1;
+// job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+// job1.mf_header1 = ((job1.data_len - 1) << 2) | 0x01; /* Payload */
+// *(u32 *)(pb_first->data + 256 +2) = 0xdeadbeef;
+//
+// test_begin(t, "no icv store + no append zero for padding")
+// {
+// int i, total;
+// phy_bridgedma_start(bridgedma_ctx, &job1, &job1);
+// /* check for no icv */
+// test_fail_unless(
+// (*(u32 *)(pb_first->data + 256 +2) == 0xdeadbeef)
+// );
+// /* check no zero padding */
+// for(i = 256 + 2 + 4, total = 0; i < 512; i++)
+// {
+// total |= pb_first->data[i];
+// }
+// test_fail_unless(
+// (total != 0)
+// );
+// } test_end;
+//
+// blk_release_desc_range(pb_first, pb_last);
+
+ return;
+}
+
+void
+bridgedma_segmentation_verify_test_case (test_t test)
+{
+ uint payload_cnt;
+ uint crc_current;
+ pb_t *my_pb_current;
+
+ uint i;
+ uint length;
+ uint pb_offset;
+ uint qte_pb;
+ uint frame_offset;
+ bool cont;
+
+ test_begin(test, "segmentation of 3 frames")
+ {
+ for (i = 0, my_pb_current = my_pb_first; my_pb_current; my_pb_current =
+ my_pb_current->next, i++)
+ {
+ test_fail_if (my_pb_current->header.ssn != i, "Wong sequence");
+ }
+
+ /* check pb content */
+ /* check 1st mac frame into PB */
+ payload_cnt = 0;
+ crc_current = crc_compute_begin(&crc_ctx);
+
+ pb_offset = START_OFFSET;
+ job_current = &job1;
+ frame_offset = 0;
+ for (pb_current = pb_first, i = 0; i < 3; i++, job_current =
+ job_current->next)
+ {
+ cont = true;
+ length = 1 + (read_u16_from_word (pb_current->data + pb_offset) >> 2);
+
+ // To get the payload length, the frame length is 10
+ // bytes greater.
+ length -= 4;
+
+ test_fail_unless (length == job_current->data_len,
+ "Data length is wrong.");
+
+ // Copy the data of the current pb.
+
+ // Jump directly to the start of the payload.
+ pb_offset += 6;
+ if (length + pb_offset > BLK_SIZE)
+ {
+ test_fail_unless (
+ !memcmp (frame_buffer + frame_offset,
+ pb_current->data + pb_offset,
+ BLK_SIZE - pb_offset),
+ "data corrupted");
+
+ frame_offset += BLK_SIZE - pb_offset;
+ length -= BLK_SIZE - pb_offset;
+ }
+ else
+ {
+ test_fail_unless (
+ !memcmp (frame_buffer + frame_offset,
+ pb_current->data + pb_offset,
+ length),
+ "data corrupted");
+
+ frame_offset += length;
+ cont = false;
+ }
+
+
+ if (cont)
+ {
+ // Add 10 to the length to use the complete MF length
+ // (ATS + MFH + ICV), the ATS and MFH are already include in the
+ // pb_offset.
+ for (qte_pb = (pb_offset + length + 4) / BLK_SIZE + 1;
+ qte_pb;
+ qte_pb --)
+ {
+ pb_current = pb_current->next;
+
+ if (length > BLK_SIZE)
+ {
+ test_fail_unless(
+ !memcmp (frame_buffer + frame_offset,
+ pb_current->data ,
+ BLK_SIZE),
+ "data corrupted");
+
+ length -= BLK_SIZE;
+ frame_offset += BLK_SIZE;
+ }
+ else
+ {
+ test_fail_unless(
+ !memcmp (frame_buffer + frame_offset,
+ pb_current->data ,
+ length),
+ "data corrupted");
+
+ frame_offset += length;
+ }
+ }
+ }
+
+ // The futur offset is length + 4 cause of the ICV of the MF.
+ // The ATS and the MFH has already been jumped above in the
+ // pb_offset.
+ pb_offset = (pb_offset + job_current->data_len + 4) % BLK_SIZE;
+ }
+
+/* data_cnt += 2;
+ mf_header = *((u32 *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer, 512 - data_cnt)
+ );
+ payload_cnt += 512 - data_cnt;
+ data_cnt = 0;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, 512)
+ );
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, 512)
+ );
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, ETH_PACKET_MAX_SIZE - payload_cnt)
+ );
+ data_cnt = ETH_PACKET_MAX_SIZE - payload_cnt;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer, ETH_PACKET_MAX_SIZE);
+ test_fail_unless(
+ (*((u32 *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+ payload_cnt = ETH_PACKET_MAX_SIZE;
+ data_cnt += 4;
+ */
+
+ /* check 2nd mac frame into PB */
+ /*
+ crc_current = crc_compute_begin(&crc_ctx);
+ mf_header = *((u32 *)(pb_current->data + data_cnt));
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == (((ETH_PACKET_MIN_SIZE + 4 - 1) << 2) | 0x02))
+ );
+ data_cnt += 2;
+ mf_header = *((u32 *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer + payload_cnt, ETH_PACKET_MIN_SIZE)
+ );
+ data_cnt += ETH_PACKET_MIN_SIZE;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + ETH_PACKET_MAX_SIZE, ETH_PACKET_MIN_SIZE);
+ test_fail_unless(
+ (*((u32 *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+ payload_cnt += ETH_PACKET_MIN_SIZE;
+ data_cnt += 4;
+ */
+
+ /* check 3rd mac frame into PB */
+ /*
+ crc_current = crc_compute_begin(&crc_ctx);
+ mf_header = *((u32 *)(pb_current->data + data_cnt));
+
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == (((sizeof(frame_buffer) - ETH_PACKET_MAX_SIZE - ETH_PACKET_MIN_SIZE + 4 - 1) << 2) | 0x02))
+ );
+
+ data_cnt += 2;
+ mf_header = *((u32 *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer + payload_cnt, 512 - data_cnt)
+ );
+
+ payload_cnt += (512 - data_cnt);
+ data_cnt = 0;
+ pb_current = pb_current->next;
+
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, sizeof(frame_buffer) - payload_cnt)
+ );
+
+ data_cnt += sizeof(frame_buffer) - payload_cnt;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + ETH_PACKET_MAX_SIZE + ETH_PACKET_MIN_SIZE, sizeof(frame_buffer) - ETH_PACKET_MAX_SIZE - ETH_PACKET_MIN_SIZE);
+
+ test_fail_unless(
+ (*((u32 *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+
+ data_cnt += 4;
+ */
+
+ /* check if there is a zeroed padding */
+ /*
+ {
+ int i, total;
+ for(i = data_cnt, total = 0; i < 512; i++)
+ total |= (pb_current->data[i]);
+ test_fail_unless(
+ (total == 0)
+ );
+ }
+ */
+ } test_end;
+
+ blk_release_desc_range((blk_t *)my_pb_first, (blk_t *) my_pb_last);
+}
+
+void
+test_thread_process (cyg_addrword_t data)
+{
+ test_t *test;
+
+ test = (test_t *) data;
+
+ bridgedma_init_test_case (*test);
+
+ bridgedma_segmentation_test_case (*test);
+ bridgedma_segmentation_verify_test_case (*test);
+
+ phy_bridgedma_uninit (bridgedma_ctx);
+
+ test_result (*test);
+ HAL_PLATFORM_EXIT (test_nb_failed (*test) == 0 ? 0 : 1);
+}
+
+int
+main (void)
+{
+ test_t test;
+ uint i;
+
+ test_init (test, 0, NULL);
+
+ pb_first = NULL;
+ pb_last = NULL;
+
+ my_pb_first = NULL;
+ my_pb_last = NULL;
+
+ for (i = 0; i < 2048; i++)
+ frame_buffer[i] = i;
+
+ // Create the thread.
+ cyg_thread_create( 9,
+ &test_thread_process,
+ (cyg_addrword_t) &test,
+ "TEST_THREAD",
+ my_test_thread_stack,
+ CYGNUM_HAL_STACK_SIZE_TYPICAL,
+ &my_test_thread_handle,
+ &my_test_thread);
+ cyg_thread_resume (my_test_thread_handle);
+
+ return 0;
+}
diff --git a/cesar/hal/phy/test/bridgedma-proto/src/test_bridgedma.c_old b/cesar/hal/phy/test/bridgedma-proto/src/test_bridgedma.c_old
new file mode 100644
index 0000000000..06ab4fe40e
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/src/test_bridgedma.c_old
@@ -0,0 +1,1003 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/phy/maximus/test/src/test_bridgedma.c
+ * \brief HAL Phy Bridge DMA test functions for Maximus.
+ * \ingroup hal_phy_maximus
+ */
+
+#include "common/std.h"
+#include "lib/test.h"
+
+
+#include "hal/phy/maximus/inc/maximus_bridgedma_ctx.h"
+
+#define MAC_FRAME_MAX_LEN 1518
+#define MAC_FRAME_MIN_LEN 64
+#define START_OFFSET 128
+
+unsigned char frame_buffer[2048] __attribute__((aligned(2048)));
+unsigned char eth_buffer[2048] __attribute__((aligned(2048)));
+
+static int _buffer_random_fill(unsigned char *buffer, int length)
+{
+ lib_rnd_t my_rnd;
+ uint i;
+
+ lib_rnd_init (&my_rnd, 0x81245452);
+
+ for (i = 0; i < length; i++)
+ {
+ buffer[i] = lib_rnd32 (&my_rnd);
+ }
+
+ return i;
+}
+
+struct segmentation_cb_data
+{
+ phy_bridgedma_job_t *job;
+};
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+static bool _bridgedma_segmentation_cb(void *data, uint32_t status)
+{
+ int *counter;
+ counter = (int *)data;
+ counter++;
+ return 0;
+}
+
+/* WARNING: callback are not possible to test inside UNIT TEST */
+static void _bridgedma_deffered_cb(void *data)
+{
+ return;
+}
+
+void bridgedma_init_test_case(test_t t)
+{
+ phy_bridgedma_t *bridgedma_ctx;
+ int user_data;
+
+ test_case_begin(t, "init");
+
+ test_begin(t, "init")
+ {
+ bridgedma_ctx = NULL;
+ bridgedma_ctx = phy_bridgedma_init(&user_data, _bridgedma_segmentation_cb, _bridgedma_deffered_cb);
+ test_fail_unless(
+ (bridgedma_ctx != NULL)
+ && (bridgedma_ctx->job_first == NULL)
+ && (bridgedma_ctx->job_current == NULL)
+ && (bridgedma_ctx->job_last == NULL)
+ && (bridgedma_ctx->user_data == &user_data)
+ && (bridgedma_ctx->bridgedma_cb == _bridgedma_segmentation_cb)
+ && (bridgedma_ctx->deferred_cb == _bridgedma_deffered_cb)
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+ } test_end;
+ return;
+}
+
+void bridgedma_pb_data_add_test_case(test_t t)
+{
+ blk_t *pb_first, *pb_last, *pb_current;
+ unsigned char frame_buffer[2048], copy_buffer[2048], *pb_data_ptr;
+
+ test_case_begin(t, "pb_data_add");
+
+ pb_first = blk_alloc_desc_range(3, &pb_last);
+ pb_current = pb_first;
+ pb_data_ptr = pb_first->data + 128;
+ _buffer_random_fill(frame_buffer, sizeof(frame_buffer));
+
+ /* adding 1280 bytes into 3 PBs with 1st PB offset=128 */
+ test_begin(t, "adding 1280 bytes from mac-frame into 3 pbs")
+ {
+ _pb_data_add(&pb_current, &pb_data_ptr, 512, frame_buffer, 1280, MACFRAME_TO_PB);
+ test_fail_unless(
+ (pb_current == pb_last)
+ && (pb_data_ptr == pb_last->data + 384)
+ && !memcmp(pb_first->data + 128, frame_buffer, 384)
+ && !memcmp(pb_first->next->data, frame_buffer + 512 - 128, 512)
+ && !memcmp(pb_last->data, frame_buffer + 1024 - 128, 384)
+ );
+ } test_end;
+
+ /* adding 1280 bytes into 3 PBs with 1st PB offset=128 */
+ pb_current = pb_first;
+ pb_data_ptr = pb_first->data + 128;
+ memset(copy_buffer, '\0', sizeof(copy_buffer));
+ test_begin(t, "adding 1280 bytes from 3 pbs into mac-frame")
+ {
+ _pb_data_add(&pb_current, &pb_data_ptr, 512, copy_buffer, 1280, PB_TO_MACFRAME);
+ test_fail_unless(
+ (pb_current == pb_last)
+ && (pb_data_ptr == pb_last->data + 384)
+ && !memcmp(copy_buffer, frame_buffer, 1280)
+ );
+ } test_end;
+
+ blk_release_desc_range(pb_first, pb_last);
+ return;
+}
+
+void bridgedma_segmentation_test_case(test_t t)
+{
+ phy_bridgedma_job_t job1, job2, job3;
+ phy_bridgedma_t *bridgedma_ctx;
+ blk_t *pb_first, *pb_last, *pb_current;
+ struct segmentation_cb_data bridgedma_data;
+ sci_msg_hdr_t *sci_hdr;
+ netclock_msg_hdr_t *netclock_hdr;
+ unsigned char msg_buffer[256];
+ int fd_in, fd_out, data_cnt, payload_cnt;
+ tick_t end_of_dma_tck, max_end_of_dma_tck, min_end_of_dma_tck;
+ uint32_t mf_header;
+ u32 enc_tab[256];
+ crc_t crc_ctx;
+ unsigned long crc_current;
+ time_t ats;
+
+ test_case_begin(t, "segmentation");
+
+ bridgedma_ctx = phy_bridgedma_init(&bridgedma_data, _bridgedma_segmentation_cb, _bridgedma_deffered_cb);
+ pb_first = blk_alloc_desc_range(5, &pb_last);
+ _buffer_random_fill(frame_buffer, sizeof(frame_buffer));
+ crc_ctx.width = 32;
+ crc_ctx.generator = HPAV_CRC32_GENERATOR;
+ crc_ctx.init = HPAV_CRC32_INIT;
+ crc_ctx.refin = true;
+ crc_ctx.refout = true;
+ crc_ctx.xorout = 0xffffffff;
+ crc_ctx.reg_init = 0;
+ crc_ctx.table.t32 = enc_tab;
+ crc_init(&crc_ctx);
+ time(&ats);
+
+ /************************************************************************
+ * simple segmentation with 3 mac frames into 5 PBs
+ * 1st mac frame: len=1518, offset=128, ATS, ICV into 1st to 4th PB
+ * 2nd mac frame: len=64, ATS, ICV into 4th PB
+ * 3nd mac frame: len=466, ATS, ICV, padding into 4th to 5th PB
+ ***********************************************************************/
+
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = &job2;
+ job1.data_addr = frame_buffer;
+ job1.header_len = 6;
+ job1.data_len = MAC_FRAME_MAX_LEN;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = START_OFFSET;
+ job1.segment_len = 512;
+ job1.direction = 0;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.job_it = 1;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job1.mf_header1 = (((job1.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job1.mf_header2 = (ats >> 16);
+
+ memset(&job2, '\0', sizeof(job2));
+ job2.next = &job3;
+ job2.data_addr = frame_buffer + job1.data_len;
+ job2.header_len = 6;
+ job2.data_len = MAC_FRAME_MIN_LEN;
+ job2.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job2.first_pb_offset = (START_OFFSET + job1.data_len + 10) % 512;
+ job2.segment_len = 512;
+ job2.direction = 0;
+ job2.crc_reset = 1;
+ job2.crc_store = 1;
+ job2.job_it = 0;
+ job2.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job2.mf_header1 = (((job2.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job2.mf_header2 = (ats >> 16);
+
+ memset(&job3, '\0', sizeof(job3));
+ job3.next = NULL;
+ job3.data_addr = frame_buffer + job1.data_len + job2.data_len;
+ job3.header_len = 6;
+ job3.data_len = sizeof(frame_buffer) - MAC_FRAME_MAX_LEN - MAC_FRAME_MIN_LEN;
+ job3.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job3.first_pb_offset = (START_OFFSET + job1.data_len + 10 + job2.data_len + 10) % 512;
+ job3.segment_len = 512;
+ job3.last = 1;
+ job3.direction = 0;
+ job3.crc_reset = 1;
+ job3.crc_store = 1;
+ job3.append_zero = 1;
+ job3.job_it = 1;
+ job3.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job3.mf_header1 = (((job3.data_len + 4 - 1) << 2) | 0x02) | (ats << 16); /* Payload + ATS */
+ job3.mf_header2 = (ats >> 16);
+
+ test_begin(t, "segmentation of 3 frames")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job3);
+
+ /* 1st job */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job1)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* 2nd job */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job2)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* 3rd job */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job3)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* check final status */
+ test_fail_unless(
+ !bridgedma_ctx->status.ahb_response_error
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+
+ /* check pb content */
+ /* check 1st mac frame into PB */
+ pb_current = pb_first;
+ data_cnt = START_OFFSET;
+ payload_cnt = 0;
+ crc_current = crc_compute_begin(&crc_ctx);
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == (((MAC_FRAME_MAX_LEN + 4 - 1) << 2) | 0x02))
+ );
+ data_cnt += 2;
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer, 512 - data_cnt)
+ );
+ payload_cnt += 512 - data_cnt;
+ data_cnt = 0;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, 512)
+ );
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, 512)
+ );
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, MAC_FRAME_MAX_LEN - payload_cnt)
+ );
+ data_cnt = MAC_FRAME_MAX_LEN - payload_cnt;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer, MAC_FRAME_MAX_LEN);
+ test_fail_unless(
+ (*((uint32_t *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+ payload_cnt = MAC_FRAME_MAX_LEN;
+ data_cnt += 4;
+
+ /* check 2nd mac frame into PB */
+ crc_current = crc_compute_begin(&crc_ctx);
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == (((MAC_FRAME_MIN_LEN + 4 - 1) << 2) | 0x02))
+ );
+ data_cnt += 2;
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer + payload_cnt, MAC_FRAME_MIN_LEN)
+ );
+ data_cnt += MAC_FRAME_MIN_LEN;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + MAC_FRAME_MAX_LEN, MAC_FRAME_MIN_LEN);
+ test_fail_unless(
+ (*((uint32_t *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+ payload_cnt += MAC_FRAME_MIN_LEN;
+ data_cnt += 4;
+
+ /* check 3rd mac frame into PB */
+ crc_current = crc_compute_begin(&crc_ctx);
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == (((sizeof(frame_buffer) - MAC_FRAME_MAX_LEN - MAC_FRAME_MIN_LEN + 4 - 1) << 2) | 0x02))
+ );
+ data_cnt += 2;
+ mf_header = *((uint32_t *)(pb_current->data + data_cnt));
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, (unsigned char *)&mf_header, 4);
+ data_cnt += 4;
+ test_fail_unless(
+ !memcmp(pb_current->data + data_cnt, frame_buffer + payload_cnt, 512 - data_cnt)
+ );
+ payload_cnt += (512 - data_cnt);
+ data_cnt = 0;
+ pb_current = pb_current->next;
+ test_fail_unless(
+ !memcmp(pb_current->data, frame_buffer + payload_cnt, sizeof(frame_buffer) - payload_cnt)
+ );
+ data_cnt += sizeof(frame_buffer) - payload_cnt;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + MAC_FRAME_MAX_LEN + MAC_FRAME_MIN_LEN, sizeof(frame_buffer) - MAC_FRAME_MAX_LEN - MAC_FRAME_MIN_LEN);
+ test_fail_unless(
+ (*((uint32_t *)(pb_current->data + data_cnt)) == crc_compute_end(&crc_ctx, crc_current))
+ );
+ data_cnt += 4;
+
+ /* check if there is a zeroed padding */
+ {
+ int i, total;
+ for(i = data_cnt, total = 0; i < 512; i++)
+ total |= (pb_current->data[i]);
+ test_fail_unless(
+ (total == 0)
+ );
+ }
+ } test_end;
+
+ /************************************************************
+ * icv substitution + no ATS + no interrupt
+ ************************************************************/
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = NULL;
+ job1.data_addr = frame_buffer;
+ job1.header_len = 2;
+ job1.data_len = 256;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = 0;
+ job1.segment_len = 512;
+ job1.last = 1;
+ job1.direction = 0;
+ job1.crc_error = 1;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.append_zero = 1;
+ job1.job_it = 0;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job1.mf_header1 = ((job1.data_len - 1) << 2) | 0x01; /* Payload */
+ bridgedma_ctx->icv_substitution = 0xdeadbeef;
+ bridgedma_ctx->icv_current = 0;
+
+ test_begin(t, "icv substitution + no ATS + no interrupt")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job1);
+ pb_current = pb_first;
+ test_fail_unless(
+ (read(fd_in, msg_buffer, sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t)) == sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t))
+ );
+ /* check for no ats */
+ mf_header = *((uint32_t *)(pb_current->data));
+ test_fail_unless(
+ ((mf_header & 0x0000ffff) == ((((unsigned int)job1.data_len - 1) << 2) | 0x01))
+ && !memcmp(pb_current->data + 2, frame_buffer, 256)
+ );
+ /* check for icv substitution */
+ mf_header = *((uint32_t *)(pb_current->data + 2 + 256));
+ test_fail_unless(
+ (mf_header == 0xdeadbeef)
+ );
+
+ } test_end;
+
+ /***************************************************************
+ * CRC reset !!!!!!!!!!!!!!!!
+ ***************************************************************/
+ /* not made yet */
+
+ /***************************************************************
+ * no ATS + no ICV store + no append zero
+ ***************************************************************/
+ _buffer_random_fill(pb_first->data, 512);
+
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = NULL;
+ job1.data_addr = frame_buffer;
+ job1.header_len = 2;
+ job1.data_len = 256;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = 0;
+ job1.segment_len = 512;
+ job1.last = 1;
+ job1.direction = 0;
+ job1.crc_error = 1;
+ job1.crc_reset = 1;
+ job1.crc_store = 0;
+ job1.append_zero = 0;
+ job1.job_it = 1;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job1.mf_header1 = ((job1.data_len - 1) << 2) | 0x01; /* Payload */
+ *(uint32_t *)(pb_first->data + 256 +2) = 0xdeadbeef;
+
+ test_begin(t, "no icv store + no append zero for padding")
+ {
+ int i, total;
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job1);
+ test_fail_unless(
+ (read(fd_in, msg_buffer, sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t)) == sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t))
+ );
+ /* check for no icv */
+ test_fail_unless(
+ (*(uint32_t *)(pb_first->data + 256 +2) == 0xdeadbeef)
+ );
+ /* check no zero padding */
+ for(i = 256 + 2 + 4, total = 0; i < 512; i++)
+ {
+ total |= pb_first->data[i];
+ }
+ test_fail_unless(
+ (total != 0)
+ );
+ } test_end;
+
+ blk_release_desc_range(pb_first, pb_last);
+
+ return;
+}
+
+struct reassembly_cb_data
+{
+ phy_bridgedma_job_t *job;
+};
+
+static bool _bridgedma_reassembly_cb(void *data, uint32_t status)
+{
+ return 0;
+}
+
+void bridgedma_reassembly_test_case(test_t t)
+{
+ phy_bridgedma_job_t job1, job2, job3;
+ phy_bridgedma_t *bridgedma_ctx;
+ blk_t *pb_first, *pb_last, *pb_current;
+ struct reassembly_cb_data bridgedma_data;
+ sci_msg_hdr_t *sci_hdr;
+ netclock_msg_hdr_t *netclock_hdr;
+ unsigned char msg_buffer[256];
+ int fd_in, fd_out, data_cnt, payload_cnt;
+ tick_t end_of_dma_tck, max_end_of_dma_tck, min_end_of_dma_tck;
+ u32 enc_tab[256];
+ crc_t crc_ctx;
+ unsigned long crc_current;
+
+ test_case_begin(t, "reassembly");
+
+ bridgedma_ctx = phy_bridgedma_init(&bridgedma_data, _bridgedma_reassembly_cb, _bridgedma_deffered_cb);
+
+ pb_first = blk_alloc_desc_range(4, &pb_last);
+ _buffer_random_fill(frame_buffer, sizeof(frame_buffer));
+ crc_ctx.width = 32;
+ crc_ctx.generator = HPAV_CRC32_GENERATOR;
+ crc_ctx.init = HPAV_CRC32_INIT;
+ crc_ctx.refin = true;
+ crc_ctx.refout = true;
+ crc_ctx.xorout = 0xffffffff;
+ crc_ctx.reg_init = 0;
+ crc_ctx.table.t32 = enc_tab;
+ crc_init(&crc_ctx);
+
+ /***********************************************************************
+ * simple reassembly from 3 mac frames into 5 PBs
+ * 1st mac frame: len=1024, mac-offset=1536, pb-offset=128, ATS, ICV into 1st to 3rd PB
+ * 2nd : len=512, no-ATS, ICV into 3rd to 4th pb
+ * 3rd : len=256, no-ATS, ICV, padding into 4th PB
+ ***********************************************************************/
+ pb_current = pb_first;
+ data_cnt = START_OFFSET;
+ payload_cnt = 0;
+ crc_current = crc_compute_begin(&crc_ctx);
+ *(uint16_t *)(pb_current->data + data_cnt) = ((1024 + 4 - 1) << 2) | 0x02;
+ data_cnt += 2;
+ *(uint32_t *)(pb_current->data + data_cnt) = time(NULL);
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, pb_current->data + data_cnt, 4);
+ data_cnt += 4;
+ memcpy(pb_current->data + data_cnt, frame_buffer, 512 - data_cnt);
+ payload_cnt += 512 - data_cnt;
+ pb_current = pb_current->next;
+ memcpy(pb_current->data, frame_buffer + payload_cnt, 512);
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ memcpy(pb_current->data, frame_buffer + payload_cnt, 1024 - payload_cnt);
+ data_cnt = 1024 - payload_cnt;
+ payload_cnt = 1024;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer, 1024);
+ *(uint32_t *)(pb_current->data + data_cnt) = crc_compute_end(&crc_ctx, crc_current);
+ data_cnt += 4;
+
+ crc_current = crc_compute_begin(&crc_ctx);
+ *(uint16_t *)(pb_current->data + data_cnt) = ((512 - 1) << 2) | 0x01;
+ data_cnt += 2;
+ memcpy(pb_current->data + data_cnt, frame_buffer + payload_cnt, 512 - data_cnt);
+ payload_cnt += 512 - data_cnt;
+ pb_current = pb_current->next;
+ memcpy(pb_current->data, frame_buffer + payload_cnt, 1024 + 512 - payload_cnt);
+ data_cnt = 1024 + 512 - payload_cnt;
+ payload_cnt = 1024 + 512;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + 1024, 512);
+ *(uint32_t *)(pb_current->data + data_cnt) = crc_compute_end(&crc_ctx, crc_current);
+ data_cnt += 4;
+
+ crc_current = crc_compute_begin(&crc_ctx);
+ *(uint16_t *)(pb_current->data + data_cnt) = ((256 - 1) << 2) | 0x01;
+ data_cnt += 2;
+ memcpy(pb_current->data + data_cnt, frame_buffer + payload_cnt, 256);
+ payload_cnt += 256;
+ data_cnt += 256;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer + 1024 + 512, 256);
+ *(uint32_t *)(pb_current->data + data_cnt) = crc_compute_end(&crc_ctx, crc_current);
+ data_cnt += 4;
+
+ memset(pb_current->data + data_cnt, '\0', 512 - data_cnt);
+
+ /* prepare jobs */
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = &job2;
+ job1.data_addr = eth_buffer + 1536;
+ job1.header_len = 6;
+ job1.data_len = 1024;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = START_OFFSET;
+ job1.segment_len = 512;
+ job1.direction = 1;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.job_it = 0;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ memset(&job2, '\0', sizeof(job2));
+ job2.next = &job3;
+ job2.data_addr = eth_buffer + 512;
+ job2.header_len = 2;
+ job2.data_len = 512;
+ job2.first_pb_desc = pb_first->next->next; /* 3rd PB */
+ job2.first_pb_offset = (START_OFFSET + job1.data_len + 10) % 512;
+ job2.segment_len = 512;
+ job2.direction = 1;
+ job2.crc_reset = 1;
+ job3.crc_store = 1;
+ job2.job_it = 1;
+ job2.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ memset(&job3, '\0', sizeof(job3));
+ job3.next = NULL;
+ job3.data_addr = eth_buffer + 1024;
+ job3.header_len = 2;
+ job3.data_len = 256;
+ job3.first_pb_desc = pb_first->next->next->next; /* 4th PB */
+ job3.first_pb_offset = (START_OFFSET + job1.data_len + 10 + job2.data_len + 6) % 512;
+ job3.segment_len = 512;
+ job3.last = 1;
+ job3.direction = 1;
+ job3.crc_reset = 1;
+ job3.crc_store = 1;
+ job3.job_it = 1;
+ job3.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ test_begin(t, "reassembly of 3 frames")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job3);
+
+ /* check job1 */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job1)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* check job2 */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job2)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* check job3 */
+ test_fail_unless(
+ (bridgedma_ctx->job_current == &job3)
+ && bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* check the eth_buffer content */
+ test_fail_unless(
+ !memcmp(eth_buffer + 1536, frame_buffer, 512)
+ && !memcmp(eth_buffer, frame_buffer + 512, 512)
+ );
+ test_fail_unless(
+ !memcmp(eth_buffer + 512, frame_buffer + 1024, 512)
+ );
+ test_fail_unless(
+ !memcmp(eth_buffer + 1024, frame_buffer + 1536, 256)
+ );
+
+ /* check status */
+ test_fail_unless(
+ !job1.crc_error
+ && !job2.crc_error
+ && !job3.crc_error
+ && !bridgedma_ctx->status.ahb_response_error
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+ } test_end;
+
+ /****************************************************************
+ * bad ICV detected
+ ****************************************************************/
+ *(uint16_t *)(pb_first->data) = ((256 - 1) << 2) | 0x01;
+ memcpy(pb_first->data + 2, frame_buffer, 256);
+ *(uint32_t *)(pb_current->data + 2 + 256) = 0xdeadbeef;
+ memset(&job1, '\0', sizeof(job1));
+
+ job1.next = NULL;
+ job1.data_addr = eth_buffer;
+ job1.header_len = 2;
+ job1.data_len = 256;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = 0;
+ job1.segment_len = 512;
+ job1.direction = 1;
+ job1.crc_reset = 1;
+ job1.crc_store = 1;
+ job1.job_it = 0;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ test_begin(t, "bad ICV")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job1);
+ test_fail_unless(
+ (read(fd_in, msg_buffer, sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t)) == sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t))
+ );
+
+ test_fail_unless(
+ job1.crc_error
+ && !bridgedma_ctx->status.ahb_response_error
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+
+ } test_end;
+
+ /**************************************************************************/
+ /* 2 continuous jobs for the same mac frame */
+ /* 2nd job has header_len=0 and doesn't reset the current icv computation */
+ /* getting 1024 bytes of data from 3 PBs, offset=128, no ATS */
+ /**************************************************************************/
+ pb_current = pb_first;
+ data_cnt = START_OFFSET;
+ payload_cnt = 0;
+ crc_current = crc_compute_begin(&crc_ctx);
+ *(uint16_t *)(pb_current->data + data_cnt) = ((1024 + 4 - 1) << 2) | 0x01;
+ data_cnt += 2;
+ memcpy(pb_current->data + data_cnt, frame_buffer, 512 - data_cnt);
+ payload_cnt += 512 - data_cnt;
+ pb_current = pb_current->next;
+ memcpy(pb_current->data, frame_buffer + payload_cnt, 512);
+ payload_cnt += 512;
+ pb_current = pb_current->next;
+ memcpy(pb_current->data, frame_buffer + payload_cnt, 1024 - payload_cnt);
+ data_cnt = 1024 - payload_cnt;
+ payload_cnt = 1024;
+ crc_current = crc_compute_continue_block(&crc_ctx, crc_current, frame_buffer, 1024);
+ *(uint32_t *)(pb_current->data + data_cnt) = crc_compute_end(&crc_ctx, crc_current);
+ data_cnt += 4;
+ memset(pb_current->data + data_cnt, '\0', 512 - data_cnt); // padding
+
+ /* prepare jobs */
+ memset(&job1, '\0', sizeof(job1));
+ job1.next = &job2;
+ job1.data_addr = eth_buffer;
+ job1.header_len = 2;
+ job1.data_len = 256;
+ job1.first_pb_desc = pb_first;
+ job1.first_pb_offset = START_OFFSET;
+ job1.segment_len = 512;
+ job1.direction = 1;
+ job1.crc_reset = 1;
+ job1.crc_store = 0;
+ job1.job_it = 0;
+ job1.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ memset(&job2, '\0', sizeof(job1));
+ job2.next = NULL;
+ job2.data_addr = eth_buffer + 256;
+ job2.header_len = 0;
+ job2.data_len = 1024 - 256;
+ job2.first_pb_desc = pb_first;
+ job2.first_pb_offset = START_OFFSET + 2 + 256;
+ job2.segment_len = 512;
+ job2.direction = 1;
+ job2.crc_reset = 0;
+ job2.crc_store = 1;
+ job2.job_it = 0;
+ job2.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ test_begin(t, "2 jobs for 1 mac frame")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job1, &job2);
+ /* 1st job */
+ test_fail_unless(
+ (read(fd_in, msg_buffer, sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t)) == sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t))
+ );
+
+ /* 2nd job */
+ test_fail_unless(
+ (read(fd_in, msg_buffer, sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t)) == sizeof(sci_msg_hdr_t) + sizeof(netclock_msg_hdr_t))
+ );
+
+ test_fail_unless(
+ !memcmp(eth_buffer, frame_buffer, 1024)
+ );
+
+ test_fail_unless(
+ !job2.crc_error
+ && !bridgedma_ctx->status.ahb_response_error
+ && !bridgedma_ctx->status.running
+ && bridgedma_ctx->status.stop
+ );
+ } test_end;
+
+ blk_release_desc_range(pb_first, pb_last);
+}
+
+#if 1
+/*************************************************************************************
+ * ticket #3 fixing test unit
+ * description: segmentation of a 1470 bytes length frame into 3 PBs
+ * then reassembly of them
+ * - during reassembly, bridge try to get a 4th unexisting PB et raise an assert failure
+ * ***********************************************************************************/
+unsigned char ticket_3_packet[] __attribute__((aligned(2048))) =
+{ 0xd4, 0xc3, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x9c, 0x2f, 0x9f, 0x46, 0xd1, 0x78,
+ 0x02, 0x00, 0x96, 0x05, 0x00, 0x00, 0x96, 0x05, 0x00, 0x00, 0x08,
+ 0x00, 0x27, 0x52, 0x20, 0x4c, 0x52, 0x54, 0x00, 0x12, 0x35, 0x02,
+ 0x08, 0x00, 0x45, 0x08, 0x05, 0x88, 0x00, 0x6e, 0x00, 0x00, 0x40,
+ 0x06, 0x15, 0xf1, 0xd1, 0x55, 0x81, 0xa5, 0x0a, 0x00, 0x02, 0x0f,
+ 0x00, 0x50, 0x04, 0x17, 0x01, 0x76, 0x1c, 0xf4, 0xc2, 0xcc, 0x6e,
+ 0x38, 0x50, 0x18, 0x22, 0x38, 0xe2, 0xf1, 0x00, 0x00, 0x7e, 0x94,
+ 0xbd, 0x94, 0x2c, 0x97, 0x22, 0xd4, 0x84, 0x34, 0x0c, 0x8c, 0xfe,
+ 0xfc, 0x13, 0x85, 0xd9, 0x5b, 0xc0, 0xbb, 0xb0, 0x8e, 0xb8, 0x7f,
+ 0x0c, 0xa2, 0xf5, 0x7a, 0x10, 0xad, 0x45, 0x10, 0xad, 0xb7, 0x82,
+ 0x68, 0xfd, 0x8f, 0x83, 0xa8, 0x2a, 0x77, 0x5a, 0xb2, 0xb3, 0xd2,
+ 0x8d, 0xc0, 0x2b, 0x46, 0x76, 0x0c, 0x0c, 0xb1, 0x0b, 0x27, 0xbc,
+ 0x6a, 0xd9, 0xe5, 0xdc, 0xf5, 0x69, 0x34, 0x0b, 0x6c, 0x96, 0x09,
+ 0x27, 0x7c, 0x9c, 0xcd, 0x56, 0xee, 0xa3, 0x8a, 0x0b, 0x1b, 0xb2,
+ 0xc7, 0x48, 0x54, 0x2d, 0xdf, 0x47, 0x9d, 0x6d, 0x81, 0x9d, 0xac,
+ 0xde, 0xf0, 0x00, 0xb6, 0x43, 0x55, 0x74, 0x17, 0x79, 0x93, 0x57,
+ 0x39, 0x11, 0xb9, 0x65, 0x12, 0x91, 0xfc, 0xbf, 0xf3, 0x39, 0xb5,
+ 0xd5, 0xe5, 0x0a, 0x45, 0xbd, 0xa9, 0xfe, 0x72, 0xd9, 0x8e, 0x93,
+ 0x2b, 0x2a, 0x7f, 0x26, 0x0f, 0x80, 0xfb, 0x4a, 0x74, 0x25, 0x3d,
+ 0x7a, 0xaa, 0xc3, 0x5f, 0xe7, 0x08, 0x8e, 0x8c, 0x88, 0xd9, 0x06,
+ 0x9c, 0xde, 0xd6, 0xda, 0x96, 0x0b, 0x54, 0xd0, 0x5b, 0x0d, 0xd9,
+ 0x30, 0x1d, 0xc3, 0xa9, 0xd5, 0x67, 0x48, 0xf5, 0x25, 0x14, 0x1d,
+ 0xc4, 0x03, 0xe2, 0x33, 0xf2, 0x60, 0x40, 0x0a, 0x4b, 0x8f, 0x45,
+ 0x45, 0x3a, 0x01, 0x0f, 0x15, 0x60, 0xd8, 0x01, 0xc7, 0x45, 0x46,
+ 0x0e, 0xb6, 0xaf, 0xbd, 0xbd, 0x62, 0x5a, 0x9f, 0x72, 0x30, 0x3c,
+ 0xe6, 0x71, 0x44, 0x61, 0x35, 0x01, 0x4c, 0xc9, 0xfc, 0xd6, 0xb8,
+ 0x3a, 0x62, 0x6c, 0xb3, 0xa4, 0xea, 0x89, 0x8f, 0xa3, 0xc8, 0x50,
+ 0x16, 0x27, 0x27, 0x93, 0x65, 0x9f, 0x20, 0x42, 0x7d, 0x3f, 0x3b,
+ 0xce, 0x1a, 0x5a, 0xd2, 0x53, 0xa7, 0x9c, 0xb4, 0x97, 0x6e, 0xc3,
+ 0x86, 0x06, 0x5c, 0x02, 0xfe, 0x6d, 0x34, 0xc1, 0x3e, 0x73, 0x03,
+ 0x63, 0x0c, 0x27, 0x18, 0xb5, 0xd7, 0xe2, 0xa5, 0x1c, 0x89, 0x92,
+ 0x68, 0x2f, 0x42, 0xc2, 0x88, 0xff, 0xf0, 0x5b, 0x84, 0x0d, 0x7f,
+ 0x17, 0x33, 0xa3, 0x2b, 0x07, 0x0f, 0x1f, 0x67, 0xac, 0xe1, 0x5c,
+ 0x3d, 0x3e, 0xd6, 0xfa, 0xd8, 0xd2, 0x4a, 0xe6, 0x80, 0x78, 0x8f,
+ 0xd7, 0xac, 0x7f, 0xee, 0xdc, 0x32, 0x76, 0xd1, 0x1f, 0x93, 0x38,
+ 0x36, 0xa3, 0xde, 0xb9, 0x9c, 0x9e, 0x5c, 0x7a, 0xee, 0xf0, 0xd2,
+ 0xbc, 0x72, 0xbb, 0xa7, 0xa7, 0x73, 0x8b, 0x4f, 0x2f, 0xb9, 0x79,
+ 0xef, 0x9a, 0x5f, 0x7e, 0xef, 0xcf, 0xc3, 0xf7, 0x93, 0xc6, 0x9d,
+ 0xfa, 0x4d, 0x3f, 0xb8, 0xa5, 0xbb, 0xa0, 0xe9, 0x72, 0xf7, 0x6c,
+ 0x6c, 0x9e, 0x5c, 0xf2, 0xbb, 0xdb, 0x4f, 0x8f, 0xee, 0xf1, 0xd9,
+ 0x79, 0xff, 0x56, 0x1b, 0x8e, 0x48, 0x7d, 0x38, 0x1a, 0xce, 0xcf,
+ 0xad, 0xd3, 0xee, 0xc7, 0x9a, 0x5d, 0xb3, 0x67, 0xf5, 0x7b, 0x12,
+ 0xf8, 0x73, 0xfb, 0xe3, 0x87, 0x08, 0xdf, 0x70, 0x79, 0x5b, 0x3d,
+ 0x94, 0xd6, 0xcd, 0xd7, 0x18, 0xdf, 0x5c, 0xd5, 0x07, 0xe3, 0xba,
+ 0x6f, 0x0f, 0x78, 0xb7, 0x77, 0x7f, 0x3c, 0x1b, 0x9e, 0xb8, 0xb3,
+ 0xf3, 0x7e, 0xd7, 0xb9, 0xbd, 0xb9, 0x38, 0x35, 0x2f, 0x4f, 0xb0,
+ 0xf9, 0x19, 0x10, 0x78, 0x72, 0x35, 0xfd, 0xc4, 0x9a, 0x13, 0x90,
+ 0x52, 0x1b, 0x8c, 0xcf, 0x67, 0xf4, 0xe6, 0x5c, 0xbb, 0xbd, 0x7e,
+ 0x0a, 0x29, 0xd3, 0xef, 0xad, 0xaa, 0x2e, 0xed, 0xeb, 0x7a, 0x68,
+ 0x9f, 0x3c, 0xc4, 0xd6, 0xf8, 0xab, 0x36, 0x68, 0x3c, 0xf4, 0x7a,
+ 0x5f, 0x9f, 0xfe, 0x98, 0x8f, 0x86, 0xa1, 0x9c, 0x37, 0xb8, 0x39,
+ 0x3d, 0x39, 0x35, 0xa7, 0x0e, 0x37, 0xb5, 0x09, 0x4f, 0xde, 0xa5,
+ 0xd3, 0x0f, 0x0d, 0xf3, 0xa2, 0x6b, 0x4e, 0xbe, 0xf4, 0x4d, 0x73,
+ 0x68, 0x9a, 0xe6, 0x6e, 0x10, 0x8f, 0x0d, 0x7d, 0xd7, 0x75, 0x7d,
+ 0x6c, 0xbb, 0x22, 0x34, 0x6a, 0xd5, 0xba, 0xf6, 0xfe, 0xfd, 0xfb,
+ 0x7a, 0x32, 0x44, 0x04, 0xc5, 0xd2, 0xa8, 0x1f, 0x1c, 0xd4, 0x6b,
+ 0x55, 0xbd, 0xa6, 0xef, 0xc2, 0xe9, 0x55, 0xf8, 0x0b, 0x44, 0x38,
+ 0x50, 0x20, 0x08, 0x14, 0x02, 0x41, 0x1c, 0x1c, 0xc9, 0x04, 0x06,
+ 0x70, 0xfa, 0x84, 0xeb, 0x93, 0x39, 0x8f, 0x05, 0x8d, 0xa3, 0xbb,
+ 0x6a, 0xb9, 0x5e, 0xd6, 0xca, 0xd5, 0x32, 0x5c, 0x90, 0x76, 0x21,
+ 0xb5, 0x20, 0x9b, 0x0c, 0x82, 0x4b, 0x61, 0x6c, 0x95, 0x0e, 0x0f,
+ 0xb5, 0x43, 0x4d, 0x6f, 0x34, 0x35, 0xbd, 0x79, 0xd8, 0xa8, 0x69,
+ 0x75, 0x75, 0x80, 0xd1, 0x92, 0xc4, 0x5c, 0xcb, 0xc3, 0x1c, 0x6c,
+ 0x48, 0xab, 0xac, 0xfa, 0xef, 0x93, 0x30, 0x2b, 0x46, 0x9b, 0x9c,
+ 0x69, 0x61, 0x35, 0xee, 0xa0, 0x4c, 0x00, 0x38, 0x43, 0x1c, 0x74,
+ 0x46, 0xdf, 0xbf, 0xf9, 0x94, 0x78, 0x6a, 0x5c, 0xa0, 0x6c, 0x09,
+ 0x68, 0xc4, 0x25, 0xf6, 0x01, 0x6a, 0x8a, 0xe0, 0xa8, 0x82, 0x37,
+ 0x33, 0xd8, 0x4a, 0x78, 0xbe, 0x7f, 0x5b, 0x30, 0x01, 0xf4, 0x65,
+ 0xcc, 0x64, 0x84, 0x6c, 0x8a, 0x1c, 0x46, 0x3c, 0x46, 0x45, 0x84,
+ 0xd4, 0xfd, 0x0a, 0x61, 0x8b, 0x07, 0x41, 0x52, 0x71, 0x8a, 0x50,
+ 0x98, 0x40, 0x24, 0xc2, 0x84, 0x7c, 0xff, 0x2b, 0x42, 0x6b, 0xb0,
+ 0x5c, 0x48, 0x8d, 0x3b, 0xea, 0xc6, 0xb9, 0xe6, 0xd5, 0x8c, 0xa6,
+ 0x22, 0x6d, 0xf5, 0x10, 0xea, 0xa1, 0x80, 0xb3, 0x80, 0x74, 0xc5,
+ 0x67, 0xeb, 0x38, 0xd6, 0x7f, 0x1e, 0xc7, 0xfa, 0x1b, 0x2e, 0xd4,
+ 0xdf, 0xc6, 0xb1, 0xfe, 0x7f, 0x82, 0x63, 0xef, 0xe6, 0xb2, 0xfb,
+ 0x2a, 0x8e, 0x07, 0xe3, 0x3b, 0xf7, 0xf3, 0xa3, 0x7f, 0x6f, 0x5d,
+ 0xd4, 0x33, 0x1c, 0x9b, 0xec, 0xe9, 0xf8, 0xd2, 0xf4, 0xdc, 0xde,
+ 0x06, 0x8e, 0xcf, 0x4a, 0xa2, 0x84, 0xcd, 0xde, 0xed, 0xc5, 0xa4,
+ 0x7e, 0x77, 0x7a, 0x76, 0xda, 0x0b, 0xdd, 0xae, 0x76, 0x76, 0x51,
+ 0xed, 0x3f, 0x2a, 0x1c, 0x5e, 0x56, 0xcf, 0xfb, 0xc7, 0xb5, 0x4f,
+ 0xa3, 0xe3, 0xf9, 0x70, 0x7e, 0x3d, 0x33, 0xaf, 0x24, 0x20, 0x8f,
+ 0xc4, 0xb7, 0xb5, 0xdf, 0xeb, 0xa4, 0x76, 0xe5, 0x59, 0x1f, 0xfd,
+ 0xc6, 0xe0, 0xfa, 0x7c, 0x62, 0x5d, 0xeb, 0xba, 0x35, 0xf6, 0x35,
+ 0xfa, 0xb9, 0x1e, 0xff, 0x71, 0xf3, 0xb9, 0x61, 0x5e, 0xf2, 0xa7,
+ 0xe1, 0x7d, 0xf7, 0x60, 0x78, 0x7f, 0x39, 0xbd, 0xa9, 0x7e, 0x98,
+ 0xcf, 0xcc, 0xe3, 0x6e, 0xd5, 0x3d, 0xbe, 0xc7, 0x27, 0x57, 0x1a,
+ 0xe9, 0xf3, 0xc9, 0xe0, 0x67, 0xea, 0x40, 0xaf, 0x64, 0x9a, 0xee,
+ 0xc7, 0xd0, 0x04, 0xec, 0x5d, 0x13, 0x6d, 0x7e, 0x66, 0x91, 0xd2,
+ 0xa3, 0x39, 0xec, 0xce, 0xcc, 0xe1, 0x49, 0xc3, 0x3c, 0x1f, 0x34,
+ 0x92, 0xf7, 0x05, 0xeb, 0x52, 0xb7, 0x3f, 0xbd, 0x1c, 0xe8, 0xe6,
+ 0xd4, 0xec, 0x2f, 0x40, 0x5c, 0xdd, 0x84, 0xa7, 0xca, 0x22, 0x97,
+ 0x06, 0x10, 0x7d, 0x16, 0x4c, 0x68, 0x06, 0x50, 0x47, 0xfc, 0x3c,
+ 0x12, 0xf5, 0x6d, 0x24, 0xea, 0xaf, 0x23, 0xf1, 0xe7, 0xd3, 0x68,
+ 0x1b, 0x89, 0xfa, 0xeb, 0x48, 0xec, 0xf1, 0x71, 0x28, 0xe9, 0x02,
+ 0x4e, 0x88, 0x06, 0xe8, 0x73, 0xcc, 0xa2, 0x88, 0xbe, 0x8d, 0xc3,
+ 0xcf, 0x00, 0xc2, 0x58, 0x30, 0xf9, 0xfd, 0x1b, 0xa2, 0x12, 0xc1,
+ 0x95, 0x9c, 0x88, 0xef, 0xdf, 0xb2, 0xf3, 0x98, 0xc0, 0x81, 0x64,
+ 0x34, 0x42, 0x17, 0x82, 0x3b, 0x70, 0x73, 0x9e, 0x03, 0x3a, 0x01,
+ 0x90, 0x13, 0x18, 0x85, 0xc4, 0x02, 0xd3, 0x22, 0xc0, 0x6a, 0x44,
+ 0x70, 0xfc, 0xf4, 0x36, 0x18, 0x5f, 0x71, 0xe3, 0xcf, 0x80, 0xb2,
+ 0xa2, 0x76, 0xd8, 0xcd, 0x7d, 0x57, 0xca, 0xe5, 0xbe, 0xab, 0xba,
+ 0xb0, 0xcd, 0xaf, 0x00, 0x9c, 0x0e, 0x38, 0x6f, 0x33, 0xc3, 0x85,
+ 0x56, 0x01, 0x24, 0x81, 0xc5, 0xaf, 0x9c, 0x4a, 0xd4, 0x2b, 0x09,
+ 0xe4, 0x6f, 0x72, 0x16, 0x52, 0xa3, 0xbe, 0x2b, 0xa8, 0xcd, 0xc4,
+ 0xdd, 0x22, 0x57, 0x76, 0x6a, 0x66, 0xa5, 0x12, 0x51, 0x31, 0x61,
+ 0x84, 0x46, 0x99, 0xa4, 0x74, 0x95, 0x94, 0xda, 0xea, 0x5e, 0x5c,
+ 0x01, 0xcd, 0x3b, 0xb5, 0x0f, 0x40, 0xbf, 0x53, 0xeb, 0x2f, 0x39,
+ 0x94, 0x63, 0x88, 0x98, 0xc1, 0xd5, 0xc9, 0x67, 0x73, 0xb8, 0x34,
+ 0x8f, 0xc7, 0x71, 0xc0, 0xe4, 0xac, 0x1c, 0x50, 0x59, 0xd9, 0xa9,
+ 0x36, 0x3c, 0x45, 0xec, 0x08, 0x68, 0xa5, 0x09, 0x07, 0xbd, 0x37,
+ 0x52, 0x0e, 0x48, 0xb0, 0xfd, 0x05, 0xe6, 0xb7, 0xea, 0x5e, 0x32,
+ 0x3e, 0x82, 0xf1, 0xd1, 0x4e, 0xb5, 0xde, 0xab, 0xc1, 0xc3, 0x3c,
+ 0x5c, 0x56, 0xe8, 0x9d, 0x6a, 0x37, 0xab, 0xd1, 0xd0, 0x4a, 0xaa,
+ 0xf4, 0x86, 0x98, 0x57, 0x22, 0xb6, 0x14, 0x97, 0xa6, 0x17, 0xb0,
+ 0x65, 0x09, 0x06, 0x2d, 0x1a, 0xc0, 0x23, 0x4d, 0x32, 0x20, 0xb3,
+ 0x79, 0x40, 0x81, 0x4e, 0x87, 0xa6, 0xab, 0x56, 0xf1, 0xe1, 0x6a,
+ 0x99, 0xa4, 0x96, 0x8f, 0x83, 0x87, 0x34, 0x4d, 0x51, 0x72, 0xcb,
+ 0x37, 0x72, 0x8b, 0x0f, 0x40, 0x2c, 0x48, 0x3e, 0xdd, 0x64, 0xdf,
+ 0x81, 0x98, 0x2f, 0xa9, 0x68, 0x85, 0x82, 0xbb, 0xcc, 0x6e, 0xf5,
+ 0x6f, 0x4e, 0xc7, 0x10, 0x83, 0x91, 0xfa, 0x10, 0xe7, 0x70, 0x31,
+ 0x2e, 0x0f, 0x19, 0x11, 0x3c, 0xe2, 0x8e, 0x2c, 0x9b, 0x3e, 0x1c,
+ 0x5f, 0x93, 0xd9, 0x01, 0x9c, 0x08, 0xa9, 0xc8, 0xab, 0x23, 0xe7,
+ 0xde, 0xaf, 0x44, 0x17, 0x82, 0xe3, 0x73, 0x97, 0xab, 0x77, 0xc9,
+ 0x11, 0x25, 0xd8, 0x82, 0x49, 0x29, 0xfd, 0x36, 0x55, 0x0e, 0x03,
+ 0x17, 0xae, 0xa0, 0x8b, 0x4f, 0x26, 0x8d, 0xe5, 0x77, 0x8a, 0x43,
+ 0x3d, 0x7c, 0xca, 0x75, 0x8e, 0xd8, 0xd8, 0x45, 0xd8, 0x97, 0x46,
+ 0xce, 0x0c, 0x02, 0x80, 0x3a, 0x20, 0xe1, 0x63, 0xa2, 0x28, 0xb7,
+ 0xac, 0xd2, 0x28, 0xe5, 0x35, 0xf4, 0xc6, 0x2f, 0x1f, 0x85, 0xff,
+ 0xde, 0xac, 0xcc, 0x79, 0xbf, 0xe6, 0xa6, 0x3c, 0x57, 0xdb, 0x88,
+ 0x9c, 0x19, 0x5a, 0x01, 0x25, 0x0b, 0x31, 0x0e, 0xf5, 0xce, 0x7a,
+ 0x51, 0xc8, 0xb0, 0x97, 0x3e, 0xd3, 0xf3, 0x70, 0xf2, 0xc1, 0xb6,
+ 0xf3, 0x1f, 0xed, 0x35, 0x17, 0x11, 0xfe, 0x15, 0x00, 0x00};
+unsigned int ticket_3_packet_len = 1470;
+
+void bridgedma_ticket_3(test_t t)
+{
+ phy_bridgedma_job_t job;
+ phy_bridgedma_t *bridgedma_ctx;
+ blk_t *pb_first, *pb_last;
+ struct reassembly_cb_data bridgedma_data;
+ unsigned long ats = 0x12345678;
+ sci_msg_hdr_t *sci_hdr;
+ netclock_msg_hdr_t *netclock_hdr;
+ unsigned char msg_buffer[256];
+ int fd_in, fd_out;
+
+ test_case_begin(t, "ticket #3");
+
+ bridgedma_ctx = phy_bridgedma_init(&bridgedma_data, _bridgedma_reassembly_cb, _bridgedma_deffered_cb);
+#ifdef STATION_SOCK
+ fd_in = my_station.sock_pair_fd;
+ fd_out = my_station.sock_pair_fd;
+#else /* STATION_SOCK */
+ fd_in = open(bridgedma_ctx->station->pipe_out_name, O_RDONLY);
+ fd_out = open(bridgedma_ctx->station->pipe_in_name, O_WRONLY);
+#endif /* STATION_SOCK */
+
+ pb_first = blk_alloc_desc_range(3, &pb_last);
+
+ /* prepare job for fragmentation */
+ //memcpy(frame_buffer, ticket_3_packet, ticket_3_packet_len);
+ memset(&job, '\0', sizeof(job));
+ job.next = NULL;
+ job.data_addr = ticket_3_packet;
+ job.header_len = 6;
+ job.data_len = ticket_3_packet_len;
+ job.first_pb_desc = pb_first;
+ job.first_pb_offset = 0;
+ job.segment_len = 512;
+ job.direction = 0;
+ job.crc_reset = 1;
+ job.crc_store = 1;
+ job.job_it = 0;
+ job.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+ job.mf_header1 = (((job.data_len + 4 - 1) << 2) | 0x02) | (ats >> 16); /* Payload + ATS */
+ job.mf_header2 = (ats << 16);
+
+ test_begin(t, "segmentation")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job, &job);
+ test_fail_unless(
+ bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+ } test_end;
+
+
+ /* reassembly: prepare jobs */
+ memset(&job, '\0', sizeof(job));
+ job.next = NULL;
+ job.data_addr = frame_buffer;
+ job.header_len = 6;
+ job.data_len = ticket_3_packet_len;
+ job.first_pb_desc = pb_first;
+ job.first_pb_offset = 0;
+ job.segment_len = 512;
+ job.direction = 1;
+ job.crc_reset = 1;
+ job.crc_store = 1;
+ job.job_it = 0;
+ job.eth_buffer_mask = 0x1fffff0; /* 2048 bytes mask */
+
+ test_begin(t, "reassembly of 3 frames")
+ {
+ phy_bridgedma_start(bridgedma_ctx, &job, &job);
+ test_fail_unless(
+ bridgedma_ctx->status.running
+ && !bridgedma_ctx->status.stop
+ );
+
+ /* check the buffer content */
+ test_fail_unless(
+ !memcmp(frame_buffer, ticket_3_packet, ticket_3_packet_len)
+ );
+ } test_end;
+
+ blk_release_desc_range(pb_first, pb_last);
+
+}
+#endif /* 0 */
+
+void bridgedma_test_suite(test_t t)
+{
+ test_suite_begin(t, "bridgedma");
+
+ 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;
+
+ bridgedma_init_test_case(t);
+ bridgedma_pb_data_add_test_case(t);
+ bridgedma_segmentation_test_case(t);
+ bridgedma_reassembly_test_case(t);
+ bridgedma_ticket_3(t);
+
+ station_down(&my_station);
+}
diff --git a/cesar/hal/phy/test/bridgedma-proto/synth-Makefile b/cesar/hal/phy/test/bridgedma-proto/synth-Makefile
new file mode 100644
index 0000000000..6f95c473f7
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/synth-Makefile
@@ -0,0 +1,13 @@
+BASE = ../../../..
+
+ECOS = y
+DEFS = -DCONFIG_BRIDGEDMA_PROTO
+
+TARGET_PROGRAMS = test-bridgedma-proto
+
+test-bridgedma-proto_SOURCES = bridgedma-init-test.c
+test-bridgedma-proto_MODULES = hal/phy lib
+
+VARIANT = synth
+
+include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/phy/test/bridgedma-proto/synth-ecos.ecc.sh b/cesar/hal/phy/test/bridgedma-proto/synth-ecos.ecc.sh
new file mode 100644
index 0000000000..8253d98c9a
--- /dev/null
+++ b/cesar/hal/phy/test/bridgedma-proto/synth-ecos.ecc.sh
@@ -0,0 +1,5 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new linux default
+cat >> $config <<EOF
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/hal/phy/test/phy/Makefile b/cesar/hal/phy/test/phy/Makefile
new file mode 100644
index 0000000000..b6eb91b1e3
--- /dev/null
+++ b/cesar/hal/phy/test/phy/Makefile
@@ -0,0 +1,3 @@
+all:
+ $(MAKE) -f maximus-Makefile
+ #$(MAKE) -f sparc-Makefile
diff --git a/cesar/hal/phy/test/phy/inc/access.h b/cesar/hal/phy/test/phy/inc/access.h
new file mode 100644
index 0000000000..dd3939fcec
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/access.h
@@ -0,0 +1,27 @@
+#ifndef inc_access_h
+#define inc_access_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/access.h
+ * \brief Test phy access.
+ * \ingroup test
+ */
+
+BEGIN_DECLS
+
+void
+test_phy_access (test_t t, test_phy_t *ctx, test_phy_msg_access_t *msg);
+
+int
+test_phy_access_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data);
+
+END_DECLS
+
+#endif /* inc_access_h */
diff --git a/cesar/hal/phy/test/phy/inc/basic.h b/cesar/hal/phy/test/phy/inc/basic.h
new file mode 100644
index 0000000000..96f17b64c8
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/basic.h
@@ -0,0 +1,27 @@
+#ifndef inc_basic_h
+#define inc_basic_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/basic.h
+ * \brief Test Phy basic tests.
+ * \ingroup test
+ */
+
+BEGIN_DECLS
+
+void
+test_phy_basic (test_t t, test_phy_t *ctx, test_phy_msg_basic_t *msg);
+
+int
+test_phy_basic_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data);
+
+END_DECLS
+
+#endif /* inc_basic_h */
diff --git a/cesar/hal/phy/test/phy/inc/clk_sync.h b/cesar/hal/phy/test/phy/inc/clk_sync.h
new file mode 100644
index 0000000000..c9fd5566ed
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/clk_sync.h
@@ -0,0 +1,45 @@
+#ifndef inc_clk_sync_h
+#define inc_clk_sync_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/clk_sync.h
+ * \brief Test phy clock synchronisation.
+ * \ingroup test
+ */
+
+BEGIN_DECLS
+
+void
+test_phy_clk_sync (test_t t, test_phy_t *ctx, test_phy_msg_clk_sync_t *msg);
+
+int
+test_phy_clk_sync_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data);
+
+/**
+ * Wait for a synchronisation message from the peer and synchronise clocks.
+ * \param t test context
+ * \param ctx test phy context
+ * \param report function to call to report waiting
+ */
+void
+test_phy_clk_sync_wait (test_t t, test_phy_t *ctx,
+ void (*report) (test_phy_t *ctx));
+
+/**
+ * Give the start signal to the peer and synchronise clocks.
+ * \param t test context
+ * \param ctx test phy context
+ */
+void
+test_phy_clk_sync_go (test_t t, test_phy_t *ctx);
+
+END_DECLS
+
+#endif /* inc_clk_sync_h */
diff --git a/cesar/hal/phy/test/phy/inc/context.h b/cesar/hal/phy/test/phy/inc/context.h
new file mode 100644
index 0000000000..0dd557a323
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/context.h
@@ -0,0 +1,149 @@
+#ifndef inc_context_h
+#define inc_context_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/context.h
+ * \brief Test Phy context.
+ * \ingroup test
+ */
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/kernel/kapi.h>
+
+#include "host/fcall.h"
+#include "lib/rnd.h"
+
+#include "inc/msg.h"
+#include "inc/gen.h"
+#include "hal/phy/pbdma.h"
+
+/** Test Phy statistics. */
+struct test_phy_stats_t
+{
+ /** Number of errors (DSR). */
+ int error;
+ /** Number of unexpected ACCESS event (ISR). */
+ int access_unexpected;
+ /** Number of unexpected ACCESS_CONF event (ISR). */
+ int access_conf_unexpected;
+ /** Number of unexpected RX_FC event (ISR). */
+ int rx_fc_unexpected;
+ /** Number of unexpected PB DMA event (ISR). */
+ int pbdma_unexpected;
+ /** Number of unexpected DSR event (DSR). */
+ int deferred_unexpected;
+ /** Number of unexpected extra timer event (ISR). */
+ int extra_timer_unexpected;
+ /** Number of RX_FC (ISR). */
+ int rx_fc_count;
+ /** Number of RX_FC with bad FC CRC (ISR). */
+ int rx_fc_bad_crc;
+};
+typedef struct test_phy_stats_t test_phy_stats_t;
+
+/** Test Phy context. */
+struct test_phy_t
+{
+ /** Phy context. */
+ phy_t *phy;
+ /** Clock zero. This is the phy clock value when the test clock is
+ * considered zero. */
+ u32 clk_zero_tck;
+
+ /** Event semaphore. */
+ cyg_sem_t event_sem;
+ /** Mailbox handle. */
+ cyg_handle_t mbox;
+ /** Mailbox storage. */
+ cyg_mbox mbox_storage;
+ /** Static message. */
+ test_phy_msg_t static_msg;
+ /** Test result function call pending. */
+ bool result_pending;
+
+ /** RX FC event callback. */
+ phy_rx_fc_cb_t rx_fc_cb;
+ /** ACCESS event callback. */
+ phy_access_cb_t access_cb;
+ /** ACCESS CONFIRM event callback. */
+ phy_access_conf_cb_t access_conf_cb;
+ /** PB DMA callback. */
+ phy_pbdma_cb_t pbdma_cb;
+ /** TX FALSE ALARM callback. */
+ phy_tx_false_alarm_cb_t tx_false_alarm_cb;
+ /** DSR callback. */
+ phy_deferred_cb_t deferred_cb;
+ /** Extra timer event callback. */
+ phy_extra_timer_cb_t extra_timer_cb;
+ /** Place to store date of preamble reception. */
+ u32 received_pre_date;
+ /** Frame control CRC OK? */
+ bool received_fc_crc_ok;
+ /** Place to store Frame control received by ISR. */
+ u32 received_fc[4];
+ /** Date at RX_FC event callback execution. */
+ u32 rx_fc_date;
+ /** Incremented at RX_FC event callback execution. */
+ uint rx_fc_count;
+ /** Date at ACCESS event callback execution. */
+ u32 access_date;
+ /** Incremented at ACCESS event callback execution. */
+ uint access_count;
+ /** PB DMA status. */
+ phy_pbdma_status_t pbdma_status;
+ /** Date at PB DMA event callback execution. */
+ u32 pbdma_date;
+ /** Incremented at PB DMA event callback execution. */
+ uint pbdma_count;
+ /** Incremented at extra timer expiration. */
+ u32 extra_timer_count;
+
+ /** Statistics. */
+ test_phy_stats_t stats;
+ /** Tests results, number of attempted tests. */
+ uint test_nb;
+ /** Tests results, number of failed tests. */
+ uint fail_nb;
+ /** Number of errors detected during ISR. The ISR should request a DSR if
+ * any error is detected. The default DSR will unlock the task using the
+ * event semaphore and will not run the overridden DSR. */
+ int isr_error;
+
+ /** Ticks per RTC. */
+ uint tck_per_rtc;
+
+ /** Function call context for return. */
+ fcall_ctx_t *fcall;
+ /** Function call identifier for return. */
+ unsigned short fcall_msg_id;
+
+ /** Tone mask carrier number. */
+ uint tonemask_carrier_nb;
+ /** Tone mask. */
+ u8 tonemask[PHY_TONEMASK_SIZE];
+
+ /** Default tone map. */
+ u8 tonemap[PHY_TONEMAP_SIZE];
+ /** Ok, this should work for maximus. */
+ blk_t tonemap_blk[2];
+
+ /** Random context. */
+ lib_rnd_t rnd[1];
+ /** Generator. */
+ gen_t gen;
+ /** Kernel thread handle. */
+ cyg_handle_t thread;
+ /** Kernel thread storage. */
+ cyg_thread thread_storage;
+ /* Thread stack. */
+ u8 thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+};
+typedef struct test_phy_t test_phy_t;
+
+#endif /* inc_context_h */
diff --git a/cesar/hal/phy/test/phy/inc/data.h b/cesar/hal/phy/test/phy/inc/data.h
new file mode 100644
index 0000000000..fb7985456a
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/data.h
@@ -0,0 +1,27 @@
+#ifndef inc_data_h
+#define inc_data_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/data.h
+ * \brief Test phy frame control and data.
+ * \ingroup test
+ */
+
+BEGIN_DECLS
+
+void
+test_phy_data (test_t t, test_phy_t *ctx, test_phy_msg_data_t *msg);
+
+int
+test_phy_data_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data);
+
+END_DECLS
+
+#endif /* inc_data_h */
diff --git a/cesar/hal/phy/test/phy/inc/gen.h b/cesar/hal/phy/test/phy/inc/gen.h
new file mode 100644
index 0000000000..7ac9d1ba98
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/gen.h
@@ -0,0 +1,64 @@
+#ifndef inc_gen_h
+#define inc_gen_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/gen.h
+ * \brief Data and Tonemap generator.
+ * \ingroup test
+ */
+
+#include "lib/rnd.h"
+
+#include "hal/phy/pbdma.h"
+
+/** Generator context. */
+struct gen_t
+{
+ /** Random context. */
+ lib_rnd_t rnd[1];
+ /** Cache list head. */
+ phy_pb_t *cache_head;
+ /** Cache list tail. */
+ phy_pb_t *cache_tail;
+ /** Cache list size. */
+ uint cache_nb;
+};
+typedef struct gen_t gen_t;
+
+BEGIN_DECLS
+
+/**
+ * Initialise generator.
+ * \param ctx generator context
+ */
+void
+gen_init (gen_t *ctx);
+
+/**
+ * Uninitialise generator.
+ * \param ctx generator context
+ */
+void
+gen_uninit (gen_t *ctx);
+
+/**
+ * Allocate a number of randomly created blocks and cache result for future
+ * usage.
+ * \param ctx generator context
+ * \param n number of block
+ * \param last where to write the last block descriptor pointer or NULL if
+ * information is not desired
+ * \return a list of newly reference to blocks in cache
+ */
+phy_pb_t *
+gen_data_blk_cached (gen_t *ctx, uint n, phy_pb_t **last);
+
+END_DECLS
+
+#endif /* inc_gen_h */
diff --git a/cesar/hal/phy/test/phy/inc/msg.h b/cesar/hal/phy/test/phy/inc/msg.h
new file mode 100644
index 0000000000..04f07c97af
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/msg.h
@@ -0,0 +1,168 @@
+#ifndef inc_msg_h
+#define inc_msg_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/msg.h
+ * \brief Test Phy messages.
+ * \ingroup test
+ */
+#include "hal/phy/phy.h"
+
+#include "mac/common/tonemap.h"
+
+/** Test Phy messages identifiers. */
+enum test_phy_msg_id_t
+{
+ TEST_PHY_MSG_ID_NONE,
+ TEST_PHY_MSG_ID_BASIC,
+ TEST_PHY_MSG_ID_CLK_SYNC,
+ TEST_PHY_MSG_ID_ACCESS,
+ TEST_PHY_MSG_ID_DATA,
+};
+typedef enum test_phy_msg_id_t test_phy_msg_id_t;
+
+/** Test Phy messages. */
+/*@{*/
+
+/** Basic test. */
+struct test_phy_msg_basic_t
+{
+ /** Do the re-initialisation test, i.e. uninit, init, set_tonemask. */
+ bool do_init;
+ /** Do the reset test. */
+ bool do_reset;
+ /** Do the date test, i.e. read date, wait, read date again. */
+ bool do_date;
+ /** Wait duration in the date test. */
+ uint date_delay_tck;
+ /** Do the date rollover test, i.e. do the date test until the 32 bit
+ * date value rolls over. */
+ bool do_date_rollover;
+ /** Do the preamble test, i.e. send a short PPDU, non hybrid frame control
+ * with a predetermined pattern, the receiver will check the pattern. */
+ bool do_preamble;
+ /** True if this station is the receiver. */
+ bool preamble_receiver;
+ /** True if the function call should return early. */
+ bool preamble_async;
+};
+typedef struct test_phy_msg_basic_t test_phy_msg_basic_t;
+
+/** Clock synchronisation test.
+ *
+ * First send an AV frame control, the date "zero" is given by: preamble start
+ * date + preamble length + frame control length + RIFS_AV_default.
+ *
+ * The receiving STA will wait for a given delay, then send an AV frame
+ * control. */
+struct test_phy_msg_clk_sync_t
+{
+ /** True for the receiver station. */
+ bool receiver;
+ /** Delay for the receiving station. */
+ uint delay_tck;
+};
+typedef struct test_phy_msg_clk_sync_t test_phy_msg_clk_sync_t;
+
+/** Access mechanisms test. */
+struct test_phy_msg_access_t
+{
+ /** Do the ACCESS_TIMER basic tests. */
+ bool do_timer_basic;
+ /** Number of iterations for the above test. */
+ uint timer_basic_iter;
+ /** Do the ACCESS_TIMER rollover test. */
+ bool do_timer_rollover;
+ /** Do the ACCESS_TIMER preamble interruption test. */
+ bool do_timer_preamble_stop;
+ /** Send the preamble for the above test. */
+ bool timer_preamble_stop_sender;
+ /** Do the PRS test. */
+ bool do_prs;
+ /** Second station for the PRS test. */
+ bool prs_second;
+ /** Do the slot counter test. */
+ bool do_slot_counter;
+ /** Second station for the slot counter test. */
+ bool slot_counter_second;
+};
+typedef struct test_phy_msg_access_t test_phy_msg_access_t;
+
+/** Data test parameters. */
+struct test_phy_data_parameters_t
+{
+ /** FC mode. */
+ phy_fc_mode_t fc_mode;
+ /** True for no data. */
+ bool short_ppdu;
+ /** Modulation. */
+ phy_mod_t mod;
+ /** Number of bits per carrier if using a tonemap. */
+ uint tonemap_bits;
+ /** Tonemap. */
+ tonemap_t *tonemap;
+ /** FEC rate. */
+ phy_fecrate_t fecrate;
+ /** PB Size. */
+ phy_pb_size_t pb_size;
+ /** Guard interval for third symbol and following symbols. */
+ phy_gil_t gil;
+ /** Bypass AES. */
+ bool bypass_aes;
+ /** Total number of transmitted PB. */
+ uint tx_nb_total;
+ /** Total number of ready transmitted PB (will send null after this
+ * number). */
+ uint tx_nb_ready;
+ /** PB Pool for RX. */
+ phy_pb_t *pool_head;
+};
+typedef struct test_phy_data_parameters_t test_phy_data_parameters_t;
+
+/** Frame control and data test. */
+struct test_phy_msg_data_t
+{
+ /** Do the frame control without data test. */
+ bool do_fc;
+ /** Test FC reception when modem set on bad FC mode. */
+ bool fc_bad_mode;
+ /** Number of iterations for the FC test. */
+ uint fc_iter;
+ /** Receiver station for the FC test. */
+ bool fc_receiver;
+ /** Do the data test. */
+ bool do_data;
+ /** Receiver station for the Data test. */
+ bool data_receiver;
+ /** Wait for the other station for synchronisation, used for no receiver
+ * tests. */
+ bool data_sync_wait;
+ /** Data test parameters. */
+ test_phy_data_parameters_t data_parameters;
+};
+typedef struct test_phy_msg_data_t test_phy_msg_data_t;
+
+/** Message union. */
+struct test_phy_msg_t
+{
+ /** Message identifier. */
+ test_phy_msg_id_t id;
+ /** Message itself. */
+ union {
+ struct test_phy_msg_basic_t basic;
+ struct test_phy_msg_clk_sync_t clk_sync;
+ struct test_phy_msg_access_t access;
+ struct test_phy_msg_data_t data;
+ } msg;
+};
+typedef struct test_phy_msg_t test_phy_msg_t;
+
+/*@}*/
+
+#endif /* inc_msg_h */
diff --git a/cesar/hal/phy/test/phy/inc/test_phy.h b/cesar/hal/phy/test/phy/inc/test_phy.h
new file mode 100644
index 0000000000..9e72b0df9d
--- /dev/null
+++ b/cesar/hal/phy/test/phy/inc/test_phy.h
@@ -0,0 +1,92 @@
+#ifndef inc_test_phy_h
+#define inc_test_phy_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/test_phy.h
+ * \brief Phy test header.
+ * \ingroup test
+ */
+#include "lib/test.h"
+
+#define TEST_PHY_ANTICIP_TCK (5u * 25u)
+
+/**
+ * Helper for parameter binding.
+ * \param name parameter string
+ * \param var parameter storage
+ * \return true if binding successful.
+ */
+#define test_phy_fcall_bind(name, var) \
+ (fcall_param_bind (*param, *msg, (name), sizeof (var), &(var)) \
+ == sizeof (var))
+
+#define test_phy_fcall_bind_long(name, var) \
+ (fcall_param_bind_long (*param, *msg, (name), &(var)) == sizeof (var))
+
+/**
+ * Helper for parameter adding.
+ * \param name parameter string
+ * \param var parameter storage
+ */
+#define test_phy_fcall_add(name, var) \
+ dbg_check (fcall_param_add (&param, &msg, (name), sizeof (var), &(var)) \
+ != -1)
+
+#define test_phy_fcall_add_long(name, var) \
+ dbg_check (fcall_param_add_long (&param, &msg, (name), &(var)) != -1)
+
+BEGIN_DECLS
+
+bool
+test_phy_access_cb (void *user);
+
+bool
+test_phy_access_conf_cb (void *user);
+
+bool
+test_phy_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av);
+
+bool
+test_phy_pbdma_cb (void *user, u32 status_word);
+
+bool
+test_phy_tx_false_alarm_cb (void *user);
+
+void
+test_phy_deferred_cb (void *user);
+
+bool
+test_phy_extra_timer_cb (void *user);
+
+bool
+test_phy_default_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av);
+
+bool
+test_phy_default_access_cb (void *user);
+
+bool
+test_phy_default_access_conf_cb (void *user);
+
+void
+test_phy_default_deferred_cb (void *user);
+
+bool
+test_phy_default_extra_timer_cb (void *user);
+
+/**
+ * Check for errors detected during ISR or DSR.
+ * \param t test context
+ * \param ctx test Phy context
+ */
+void
+test_phy_check_error (test_t t, test_phy_t *ctx);
+
+END_DECLS
+
+#endif /* inc_test_phy_h */
diff --git a/cesar/hal/phy/test/phy/maximus-Makefile b/cesar/hal/phy/test/phy/maximus-Makefile
new file mode 100644
index 0000000000..836e3c0ca1
--- /dev/null
+++ b/cesar/hal/phy/test/phy/maximus-Makefile
@@ -0,0 +1,17 @@
+BASE = ../../../..
+
+ECOS = y
+
+DEFS = -DTEST_PHY_SIMU=1
+
+TARGET_PROGRAMS = test_phy
+test_phy_SOURCES = test_phy.c basic.c clk_sync.c access.c data.c gen.c
+test_phy_MODULES = lib host hal/phy/maximus mac/common
+mac_common_MODULES_SOURCES = tonemask.c
+
+HOST_PROGRAMS = host_test_phy
+host_test_phy_SOURCES = host_test_phy.cpp
+host_test_phy_MODULES = maximus lib
+
+VARIANT = maximus
+include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/phy/test/phy/maximus-ecos.ecc.sh b/cesar/hal/phy/test/phy/maximus-ecos.ecc.sh
new file mode 100644
index 0000000000..006f477341
--- /dev/null
+++ b/cesar/hal/phy/test/phy/maximus-ecos.ecc.sh
@@ -0,0 +1,8 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new maximus default
+cat >> $config <<'EOF'
+cdl_option CYGBLD_GLOBAL_CFLAGS {
+ user_value "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority"
+}
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/hal/phy/test/phy/sparc-Makefile b/cesar/hal/phy/test/phy/sparc-Makefile
new file mode 100644
index 0000000000..94e3596cb1
--- /dev/null
+++ b/cesar/hal/phy/test/phy/sparc-Makefile
@@ -0,0 +1,19 @@
+BASE = ../../../..
+
+ECOS = y
+
+TARGET = sparc
+
+DEFS = -DTEST_PHY_SIMU=0
+
+TARGET_PROGRAMS = test_phy
+test_phy_SOURCES = test_phy.c basic.c clk_sync.c access.c data.c gen.c
+test_phy_MODULES = lib host hal/phy mac/common
+mac_common_MODULES_SOURCES = tonemask.c
+
+HOST_PROGRAMS = host_test_phy
+host_test_phy_SOURCES = host_test_phy.cpp
+host_test_phy_MODULES = maximus lib
+
+VARIANT = sparc
+include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/phy/test/phy/sparc-ecos.ecc.sh b/cesar/hal/phy/test/phy/sparc-ecos.ecc.sh
new file mode 100644
index 0000000000..db2208c6cc
--- /dev/null
+++ b/cesar/hal/phy/test/phy/sparc-ecos.ecc.sh
@@ -0,0 +1,5 @@
+config=${1:-ecos-gen.ecc}
+ecosconfig --config=$config new sparc_leon default
+cat >> $config <<'EOF'
+EOF
+ecosconfig --config=$config check
diff --git a/cesar/hal/phy/test/phy/src/access.c b/cesar/hal/phy/test/phy/src/access.c
new file mode 100644
index 0000000000..914b992b1b
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/access.c
@@ -0,0 +1,532 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/access.c
+ * \brief Test phy access.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/context.h"
+#include "inc/test_phy.h"
+#include "inc/access.h"
+
+#include "inc/clk_sync.h"
+
+#include "mac/common/timings.h"
+
+static void
+test_phy_access_fcall_return (test_phy_t *ctx);
+
+static void
+test_phy_access_timer_basic (test_t t, test_phy_t *ctx,
+ test_phy_msg_access_t *msg)
+{
+ test_begin (t, "timer basic expire")
+ {
+ uint i;
+ ctx->access_cb = test_phy_default_access_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ for (i = 0; i < msg->timer_basic_iter; i++)
+ {
+ /* Start timer. */
+ u32 now = phy_date (ctx->phy);
+ u32 due_date = now + TEST_PHY_ANTICIP_TCK
+ + lib_rnd_uniform (ctx->rnd, 20 * TEST_PHY_ANTICIP_TCK);
+ phy_access_timer_program (ctx->phy, due_date);
+ /* Wait. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ /* Check. */
+ test_phy_check_error (t, ctx);
+ if (TEST_PHY_SIMU)
+ test_fail_unless (ctx->access_date == due_date);
+ else
+ test_fail_unless
+ (lesseq_mod2p32 (due_date, ctx->access_date)
+ && less_mod2p32 (ctx->access_date, due_date
+ + TEST_PHY_ANTICIP_TCK));
+ }
+ ctx->access_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+ test_begin (t, "timer basic cancel")
+ {
+ phy_access_timer_program (ctx->phy, phy_date (ctx->phy)
+ + 2 * ctx->tck_per_rtc);
+ cyg_thread_delay (1);
+ phy_access_timer_cancel (ctx->phy);
+ cyg_thread_delay (3);
+ test_phy_check_error (t, ctx);
+ } test_end;
+}
+
+static void
+test_phy_access_timer_rollover (test_t t, test_phy_t *ctx)
+{
+ test_begin (t, "timer rollover")
+ {
+ /* Aim right before rollover. */
+ ctx->access_cb = test_phy_default_access_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_access_timer_program (ctx->phy, 0u - TEST_PHY_ANTICIP_TCK);
+ /* Wait. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_fail_unless (ctx->access_date >= 0u - TEST_PHY_ANTICIP_TCK);
+ /* Now program after rollover. */
+ phy_access_timer_program (ctx->phy, TEST_PHY_ANTICIP_TCK);
+ /* Wait. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_fail_unless (ctx->access_date >= TEST_PHY_ANTICIP_TCK
+ && ctx->access_date < 0u - TEST_PHY_ANTICIP_TCK);
+ ctx->access_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ } test_end;
+}
+
+static void
+test_phy_access_timer_preamble_stop (test_t t, test_phy_t *ctx,
+ const int delta[], uint delta_count)
+{
+ uint i;
+ test_begin (t, "timer preamble stop")
+ {
+ test_phy_clk_sync_go (t, ctx);
+ u32 pre = ctx->clk_zero_tck;
+ u32 acc;
+ for (i = 0; i < delta_count * 2; i++)
+ {
+ /* RX activate. */
+ bool rx_act = i >= delta_count;
+ if (rx_act)
+ phy_rx_activate (ctx->phy, true, 0, true);
+ /* Access setup. */
+ acc = pre + delta[i % delta_count];
+ ctx->rx_fc_count = 0;
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->access_count = 0;
+ ctx->access_cb = test_phy_default_access_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ ctx->extra_timer_count = 0;
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ phy_access_timer_program (ctx->phy, acc);
+ phy_extra_timer_program (ctx->phy, pre + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK
+ + MAC_RIFS_DEFAULT_TCK
+ - TEST_PHY_ANTICIP_TCK);
+ /* Wait until extra timer expiration. */
+ while (ctx->extra_timer_count == 0)
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ /* Check. */
+ ctx->access_cb = NULL;
+ ctx->rx_fc_cb = NULL;
+ ctx->deferred_cb = NULL;
+ ctx->extra_timer_cb = NULL;
+ test_phy_check_error (t, ctx);
+ test_fail_unless (ctx->access_count <= 1);
+ test_fail_unless ((rx_act && ctx->rx_fc_count == 1)
+ || (!rx_act && ctx->rx_fc_count == 0));
+ if (!rx_act)
+ test_fail_unless (ctx->access_count == 1);
+ else if (acc < pre + MAC_PREAMBLE_TCK - TEST_PHY_ANTICIP_TCK)
+ test_fail_unless (ctx->access_count == 1
+ && less_mod2p32 (ctx->access_date,
+ ctx->rx_fc_date));
+ else if (acc < pre + MAC_PREAMBLE_TCK + TEST_PHY_ANTICIP_TCK)
+ test_fail_unless ((ctx->access_count == 1
+ && less_mod2p32 (ctx->access_date,
+ ctx->rx_fc_date))
+ || ctx->access_count == 0);
+ else
+ test_fail_unless (ctx->access_count == 0);
+ /* Next one. */
+ pre += MAC_PREAMBLE_TCK + MAC_FC_AV_TCK + MAC_RIFS_DEFAULT_TCK;
+ }
+ } test_end;
+}
+
+static void
+test_phy_access_timer_preamble_stop_sender (test_t t, test_phy_t *ctx,
+ uint delta_count,
+ volatile bool *fcall_returned)
+{
+ uint i;
+ test_begin (t, "timer preamble stop sender")
+ {
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_access_fcall_return);
+ *fcall_returned = true;
+ u32 pre = ctx->clk_zero_tck;
+ for (i = 0; i < 2 * delta_count; i++)
+ {
+ u32 fc[4];
+ fc[0] = 0x7; fc[1] = fc[2] = fc[3] = 0;
+ ctx->access_conf_cb = test_phy_default_access_conf_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ //XXX
+ /**/ ctx->extra_timer_count = 0;
+ /**/ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ /**/ phy_extra_timer_program (ctx->phy, pre + MAC_PREAMBLE_TCK
+ + MAC_FC_AV_TCK
+ + MAC_RIFS_DEFAULT_TCK
+ - TEST_PHY_ANTICIP_TCK);
+ phy_tx_param_short (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_tx_frame (ctx->phy, phy_date (ctx->phy), true, false, fc);
+ /* Wait until transmission done. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ /**/ while (ctx->extra_timer_count == 0)
+ /**/ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->access_conf_cb = NULL;
+ ctx->deferred_cb = NULL;
+ /**/ ctx->extra_timer_cb = NULL;
+ test_phy_check_error (t, ctx);
+ pre += MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_RIFS_DEFAULT_TCK;
+ }
+ } test_end;
+}
+
+static uint
+test_phy_prs_updated (uint original, uint updated, uint update)
+{
+ dbg_assert (original < 4);
+ dbg_assert (updated < 4);
+ dbg_assert (update < 4);
+ if (update == 0 || update == 3)
+ return original;
+ else if (update == 1)
+ return updated;
+ else
+ {
+ if (updated > original)
+ return original | 0x1;
+ else if (updated < original)
+ return original & 0x2;
+ else
+ return original;
+ }
+}
+
+static void
+test_phy_access_prs (test_t t, test_phy_t *ctx)
+{
+ uint both, me, peer, update, me_update;
+ u32 prp_date;
+ test_begin (t, "prs")
+ {
+ for (both = 0; both < 2; both++)
+ {
+ /* Synchronise. */
+ if (both)
+ {
+ test_phy_clk_sync_go (t, ctx);
+ prp_date = ctx->clk_zero_tck;
+ }
+ else
+ prp_date = phy_date (ctx->phy) + TEST_PHY_ANTICIP_TCK;
+ prp_date += 2 * MAC_SLOT_TCK;
+ /* Prepare callbacks. */
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Activate RX. */
+ phy_rx_activate (ctx->phy, true, 0, true);
+ /* Loop over all possible configurations.
+ * update: 0: none, 1: before PRP, 2: during PRP0, 3: during PRP1.
+ */
+ for (update = 0; update < 4; update++)
+ for (me = 0; me < 4; me++)
+ for (peer = 0; peer < 4; peer++)
+ for (me_update = 0; me_update < (update ? 4 : 1);
+ me_update++)
+ {
+ /* Start backoff and wait. */
+ phy_access_backoff_start (ctx->phy, prp_date, me);
+ if (update)
+ {
+ /* ...until update. */
+ phy_extra_timer_program (ctx->phy, prp_date
+ - 2 * MAC_SLOT_TCK
+ + update * MAC_SLOT_TCK
+ + TEST_PHY_ANTICIP_TCK);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Update CAP. */
+ phy_access_backoff_update (ctx->phy, me_update);
+ }
+ phy_extra_timer_program (ctx->phy, prp_date
+ + 2 * MAC_SLOT_TCK
+ + TEST_PHY_ANTICIP_TCK);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Check and next. */
+ uint cap_mpdu = update ? me_update : me;
+ uint cap_sent = test_phy_prs_updated (me, me_update,
+ update);
+ uint cap_medium = !both || cap_sent > peer
+ ? cap_sent : peer;
+ bool should_win = cap_sent == cap_medium
+ || cap_mpdu >= cap_medium;
+ bool win = phy_access_backoff_prp_won (ctx->phy);
+ test_fail_unless ((should_win && win)
+ || (!should_win && !win));
+ prp_date += 3 * MAC_SLOT_TCK;
+ }
+ /* Deactivate RX. */
+ phy_rx_activate (ctx->phy, true, 0, false);
+ /* Cleanup. */
+ ctx->extra_timer_cb = NULL;
+ ctx->deferred_cb = NULL;
+ }
+ } test_end;
+}
+
+static void
+test_phy_access_prs_second (test_t t, test_phy_t *ctx,
+ volatile bool *fcall_returned)
+{
+ uint update, peer, me, peer_update;
+ u32 prp_date;
+ test_begin (t, "prs second")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_access_fcall_return);
+ *fcall_returned = true;
+ prp_date = ctx->clk_zero_tck + 2 * MAC_SLOT_TCK;
+ /* Prepare callbacks. */
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Activate RX. */
+ phy_rx_activate (ctx->phy, true, 0, true);
+ /* Loop over all possible configurations. */
+ for (update = 0; update < 4; update++)
+ for (peer = 0; peer < 4; peer++)
+ for (me = 0; me < 4; me++)
+ for (peer_update = 0; peer_update < (update ? 4 : 1);
+ peer_update++)
+ {
+ /* Start backoff and wait. */
+ phy_access_backoff_start (ctx->phy, prp_date, me);
+ phy_extra_timer_program (ctx->phy, prp_date
+ + 2 * MAC_SLOT_TCK
+ + TEST_PHY_ANTICIP_TCK);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Next. */
+ prp_date += 3 * MAC_SLOT_TCK;
+ }
+ /* Deactivate RX. */
+ phy_rx_activate (ctx->phy, true, 0, false);
+ /* Cleanup. */
+ ctx->extra_timer_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+static void
+test_phy_access_slot_counter (test_t t, test_phy_t *ctx)
+{
+ const uint slot_nb = 16;
+ uint slot;
+ u32 pre_date;
+ test_begin (t, "slot counter")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_go (t, ctx);
+ pre_date = ctx->clk_zero_tck;
+ /* Prepare callbacks. */
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Loop over a number of slots. */
+ for (slot = 2; slot < slot_nb; slot++)
+ {
+ /* Setup backoff procedure and wait. */
+ phy_rx_activate (ctx->phy, true, 0, true);
+ phy_access_backoff_start (ctx->phy, pre_date, 0);
+ ctx->rx_fc_count = 0;
+ ctx->extra_timer_count = 0;
+ phy_extra_timer_program (ctx->phy, pre_date
+ + slot_nb * MAC_SLOT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + TEST_PHY_ANTICIP_TCK);
+ while (ctx->extra_timer_count == 0)
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ test_fail_unless (ctx->rx_fc_count == 1);
+ /* Check slot counter. */
+ test_fail_unless (phy_access_backoff_slot_count (ctx->phy) - 1
+ == slot);
+ pre_date += slot_nb * MAC_SLOT_TCK + MAC_PREAMBLE_TCK +
+ MAC_FC_AV_TCK + MAC_RIFS_DEFAULT_TCK;
+ }
+ /* Cleanup. */
+ ctx->rx_fc_cb = NULL;
+ ctx->extra_timer_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+static void
+test_phy_access_slot_counter_second (test_t t, test_phy_t *ctx,
+ volatile bool *fcall_returned)
+{
+ const uint slot_nb = 16;
+ uint slot;
+ u32 pre_date;
+ test_begin (t, "slot counter second")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_access_fcall_return);
+ pre_date = ctx->clk_zero_tck;
+ *fcall_returned = true;
+ /* Prepare callbacks. */
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Loop over a number of slots. */
+ for (slot = 2; slot < slot_nb; slot++)
+ {
+ /* Program a TX. */
+ u32 fc[4];
+ fc[0] = 0x7; fc[1] = fc[2] = fc[3] = 0;
+ phy_tx_param_short (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_tx_frame (ctx->phy, pre_date + slot * MAC_SLOT_TCK, false,
+ false, fc);
+ phy_extra_timer_program (ctx->phy, pre_date
+ + slot_nb * MAC_SLOT_TCK
+ + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + TEST_PHY_ANTICIP_TCK);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Next. */
+ pre_date += slot_nb * MAC_SLOT_TCK + MAC_PREAMBLE_TCK +
+ MAC_FC_AV_TCK + MAC_RIFS_DEFAULT_TCK;
+ }
+ /* Cleanup. */
+ ctx->extra_timer_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+void
+test_phy_access (test_t t, test_phy_t *ctx, test_phy_msg_access_t *msg)
+{
+ volatile bool fcall_returned = false; /* Be careful of the longjmp. */
+ dbg_assert (ctx);
+ dbg_assert (msg);
+ test_case_begin (t, "access");
+ /* Do tests. */
+ if (msg->do_timer_basic)
+ test_phy_access_timer_basic (t, ctx, msg);
+ if (msg->do_timer_rollover)
+ test_phy_access_timer_rollover (t, ctx);
+ if (msg->do_timer_preamble_stop)
+ {
+ static const int delta[] = {
+ 0,
+ TEST_PHY_ANTICIP_TCK,
+ PHY_PREAMBLE_DETECTION_DELAY_TCK - 1,
+ PHY_PREAMBLE_DETECTION_DELAY_TCK,
+ PHY_PREAMBLE_DETECTION_DELAY_TCK + 1,
+ PHY_PREAMBLE_DETECTION_DELAY_TCK + TEST_PHY_ANTICIP_TCK,
+ MAC_PREAMBLE_TCK,
+ };
+ if (!msg->timer_preamble_stop_sender)
+ test_phy_access_timer_preamble_stop (t, ctx, delta,
+ COUNT (delta));
+ else
+ test_phy_access_timer_preamble_stop_sender (t, ctx,
+ COUNT (delta),
+ &fcall_returned);
+ }
+ if (msg->do_prs)
+ {
+ if (!msg->prs_second)
+ test_phy_access_prs (t, ctx);
+ else
+ test_phy_access_prs_second (t, ctx, &fcall_returned);
+ }
+ if (msg->do_slot_counter)
+ {
+ if (!msg->slot_counter_second)
+ test_phy_access_slot_counter (t, ctx);
+ else
+ test_phy_access_slot_counter_second (t, ctx, &fcall_returned);
+ }
+ if (!fcall_returned)
+ {
+ test_phy_access_fcall_return (ctx);
+ fcall_returned = true;
+ }
+}
+
+int
+test_phy_access_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ dbg_assert (fcall);
+ dbg_assert (param && *param);
+ dbg_assert (msg && *msg);
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* Only one message at a time. */
+ if (ctx->static_msg.id != TEST_PHY_MSG_ID_NONE)
+ return -1;
+ ctx->static_msg.id = TEST_PHY_MSG_ID_ACCESS;
+ /* Read message. */
+ test_phy_msg_access_t *m = &ctx->static_msg.msg.access;
+ if (!test_phy_fcall_bind ("timer_basic", m->do_timer_basic))
+ m->do_timer_basic = false;
+ if (m->do_timer_basic && !test_phy_fcall_bind_long ("timer_basic_iter",
+ m->timer_basic_iter))
+ return -1;
+ if (!test_phy_fcall_bind ("timer_rollover", m->do_timer_rollover))
+ m->do_timer_rollover = false;
+ if (!test_phy_fcall_bind ("timer_preamble_stop",
+ m->do_timer_preamble_stop))
+ m->do_timer_preamble_stop = false;
+ if (m->do_timer_preamble_stop
+ && !test_phy_fcall_bind ("timer_preamble_stop_sender",
+ m->timer_preamble_stop_sender))
+ m->timer_preamble_stop_sender = false;
+ if (!test_phy_fcall_bind ("prs", m->do_prs))
+ m->do_prs = false;
+ if (m->do_prs && !test_phy_fcall_bind ("prs_second", m->prs_second))
+ m->prs_second = false;
+ if (!test_phy_fcall_bind ("slot_counter", m->do_slot_counter))
+ m->do_slot_counter = false;
+ if (m->do_slot_counter
+ && !test_phy_fcall_bind ("slot_counter_second",
+ m->slot_counter_second))
+ m->slot_counter_second = false;
+ /* Message accepted, will return later. */
+ fcall_param_set_async (*param, 1);
+ dbg_assert (ctx->fcall == NULL);
+ ctx->fcall = fcall;
+ ctx->fcall_msg_id = fcall_param_get_msg_id (*param);
+ /* Post message. */
+ dbg_check (cyg_mbox_put (ctx->mbox, &ctx->static_msg));
+ return 0;
+}
+
+static void
+test_phy_access_fcall_return (test_phy_t *ctx)
+{
+ fcall_param_t param;
+ sci_msg_t msg;
+ u8 buffer[64];
+ dbg_assert (ctx);
+ dbg_assert (ctx->fcall);
+ fcall_param_init (&param, "test_phy_access", ctx->fcall_msg_id);
+ sci_msg_init (&msg, buffer, sizeof (buffer));
+ fcall_param_reset (&param);
+ dbg_check (fcall_return (ctx->fcall, &param, &msg) != -1);
+ ctx->fcall = NULL;
+}
+
diff --git a/cesar/hal/phy/test/phy/src/basic.c b/cesar/hal/phy/test/phy/src/basic.c
new file mode 100644
index 0000000000..490b4d8588
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/basic.c
@@ -0,0 +1,190 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/basic.c
+ * \brief Test Phy basic tests.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/context.h"
+#include "inc/test_phy.h"
+#include "inc/basic.h"
+
+static void
+test_phy_basic_fcall_return (test_phy_t *ctx);
+
+void
+test_phy_basic (test_t t, test_phy_t *ctx, test_phy_msg_basic_t *msg)
+{
+ volatile bool fcall_returned = false; /* Be careful of the longjmp. */
+ dbg_assert (ctx);
+ dbg_assert (msg);
+ test_case_begin (t, "basic");
+ /* Do tests. */
+ if (msg->do_init)
+ {
+ test_begin (t, "init")
+ {
+ phy_uninit (ctx->phy);
+ ctx->phy = phy_init (ctx, test_phy_rx_fc_cb, test_phy_access_cb,
+ test_phy_access_conf_cb, test_phy_pbdma_cb,
+ test_phy_tx_false_alarm_cb, test_phy_deferred_cb);
+ phy_set_tonemask (ctx->phy, ctx->tonemask,
+ ctx->tonemask_carrier_nb);
+ phy_extra_timer_init (ctx->phy, ctx, test_phy_extra_timer_cb);
+ test_phy_check_error (t, ctx);
+ } test_end;
+ }
+ if (msg->do_reset)
+ {
+ test_begin (t, "reset")
+ {
+ phy_reset (ctx->phy);
+ test_phy_check_error (t, ctx);
+ } test_end;
+ }
+ if (msg->do_date)
+ {
+ test_begin (t, "date")
+ {
+ u32 date0, date1;
+ uint delay_rtc = msg->date_delay_tck / ctx->tck_per_rtc;
+ date1 = phy_date (ctx->phy);
+ do
+ {
+ date0 = date1;
+ cyg_thread_delay (delay_rtc);
+ date1 = phy_date (ctx->phy);
+ /* Resolution will only be as good as tck_per_rtc. */
+ test_fail_unless (
+ date1 - date0 > (delay_rtc - 1) * ctx->tck_per_rtc
+ && date1 - date0 <= delay_rtc * ctx->tck_per_rtc);
+ } while (msg->do_date_rollover && date0 < date1);
+ test_phy_check_error (t, ctx);
+ } test_end;
+ }
+ if (msg->do_preamble)
+ {
+ test_begin (t, "preamble")
+ {
+ if (!msg->preamble_receiver)
+ {
+ u32 fc[4];
+ fc[0] = 0x7;
+ fc[1] = 0x01234567;
+ fc[2] = 0x98765432;
+ fc[3] = 0xa55aa55a;
+ ctx->access_conf_cb = test_phy_default_access_conf_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_tx_param_short (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_tx_frame (ctx->phy, phy_date (ctx->phy), true, false, fc);
+ /* Report waiting. */
+ if (msg->preamble_async)
+ {
+ test_phy_basic_fcall_return (ctx);
+ fcall_returned = true;
+ }
+ /* Wait until transmission done. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->access_conf_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ }
+ else
+ {
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_rx_param (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_rx_activate (ctx->phy, true, 0, true);
+ /* Report waiting. */
+ if (msg->preamble_async)
+ {
+ test_phy_basic_fcall_return (ctx);
+ fcall_returned = true;
+ }
+ /* Wait until PPDU is received. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->rx_fc_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ test_fail_unless (ctx->received_fc_crc_ok
+ && ctx->received_fc[0] == 0x7
+ && ctx->received_fc[1] == 0x01234567
+ && ctx->received_fc[2] == 0x98765432
+ && ctx->received_fc[3] == 0xa55aa55a);
+ }
+ } test_end;
+ }
+ if (!fcall_returned)
+ {
+ test_phy_basic_fcall_return (ctx);
+ fcall_returned = true;
+ }
+}
+
+int
+test_phy_basic_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ dbg_assert (fcall);
+ dbg_assert (param && *param);
+ dbg_assert (msg && *msg);
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* Only one message at a time. */
+ if (ctx->static_msg.id != TEST_PHY_MSG_ID_NONE)
+ return -1;
+ ctx->static_msg.id = TEST_PHY_MSG_ID_BASIC;
+ /* Read message. */
+ test_phy_msg_basic_t *m = &ctx->static_msg.msg.basic;
+ if (!test_phy_fcall_bind ("init", m->do_init))
+ m->do_init = false;
+ if (!test_phy_fcall_bind ("reset", m->do_reset))
+ m->do_reset = false;
+ if (!test_phy_fcall_bind ("date", m->do_date))
+ m->do_date = false;
+ if (m->do_date && !test_phy_fcall_bind_long ("date_delay_tck",
+ m->date_delay_tck))
+ return -1;
+ if (m->do_date
+ && !test_phy_fcall_bind ("date_rollover", m->do_date_rollover))
+ m->do_date_rollover = false;
+ if (!test_phy_fcall_bind ("preamble", m->do_preamble))
+ m->do_preamble = false;
+ if (m->do_preamble
+ && !test_phy_fcall_bind ("preamble_receiver", m->preamble_receiver))
+ m->preamble_receiver = false;
+ if (m->do_preamble
+ && !test_phy_fcall_bind ("preamble_async", m->preamble_async))
+ m->preamble_async = false;
+ /* Message accepted, will return later. */
+ fcall_param_set_async (*param, 1);
+ dbg_assert (ctx->fcall == NULL);
+ ctx->fcall = fcall;
+ ctx->fcall_msg_id = fcall_param_get_msg_id (*param);
+ /* Post message. */
+ dbg_check (cyg_mbox_put (ctx->mbox, &ctx->static_msg));
+ return 0;
+}
+
+static void
+test_phy_basic_fcall_return (test_phy_t *ctx)
+{
+ fcall_param_t param;
+ sci_msg_t msg;
+ u8 buffer[64];
+ dbg_assert (ctx);
+ dbg_assert (ctx->fcall);
+ fcall_param_init (&param, "test_phy_basic", ctx->fcall_msg_id);
+ sci_msg_init (&msg, buffer, sizeof (buffer));
+ fcall_param_reset (&param);
+ dbg_check (fcall_return (ctx->fcall, &param, &msg) != -1);
+ ctx->fcall = NULL;
+}
+
diff --git a/cesar/hal/phy/test/phy/src/clk_sync.c b/cesar/hal/phy/test/phy/src/clk_sync.c
new file mode 100644
index 0000000000..113f948b9b
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/clk_sync.c
@@ -0,0 +1,182 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/clk_sync.c
+ * \brief Test phy clock synchronisation.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/context.h"
+#include "inc/test_phy.h"
+#include "inc/clk_sync.h"
+
+#include "mac/common/timings.h"
+
+static const u32 sync_tag = 'S' | 'y' << 8 | 'n' << 16 | 'c' << 24;
+
+static void
+test_phy_clk_sync_fcall_return (test_phy_t *ctx);
+
+void
+test_phy_clk_sync (test_t t, test_phy_t *ctx, test_phy_msg_clk_sync_t *msg)
+{
+ dbg_assert (ctx);
+ dbg_assert (msg);
+ const u32 synr_tag = 'S' | 'y' << 8 | 'n' << 16 | 'r' << 24;
+ test_case_begin (t, "clk_sync");
+ /* Do test. */
+ test_begin (t, "clk_sync")
+ {
+ if (!msg->receiver)
+ {
+ /* Unblock the waiting STA. */
+ test_phy_clk_sync_go (t, ctx);
+ test_fail_unless (phy_date (ctx->phy) < ctx->clk_zero_tck);
+ /* Activate reception after TX. */
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_rx_param (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_rx_activate (ctx->phy, false, ctx->clk_zero_tck, true);
+ /* Wait until the response is received. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->rx_fc_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ /* Check response date. */
+ u32 expected_date = ctx->clk_zero_tck + ctx->received_fc[2];
+ test_fail_unless (ctx->received_fc_crc_ok
+ && ctx->received_fc[0] == 0x7
+ && ctx->received_fc[1] == synr_tag
+ && ctx->received_fc[3] == 0
+ && expected_date == ctx->received_pre_date);
+ /* Report end. */
+ test_phy_clk_sync_fcall_return (ctx);
+ }
+ else
+ {
+ /* Wait. */
+ test_phy_clk_sync_wait (t, ctx, test_phy_clk_sync_fcall_return);
+ /* Send the response at the specified delay. */
+ u32 fc[4];
+ fc[0] = 0x7;
+ fc[1] = synr_tag;
+ fc[2] = msg->delay_tck;
+ fc[3] = 0;
+ ctx->access_conf_cb = test_phy_default_access_conf_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_tx_param_short (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_tx_frame (ctx->phy, ctx->clk_zero_tck + msg->delay_tck, true,
+ false, fc);
+ /* Wait until transmission done. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->access_conf_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ }
+ } test_end;
+}
+
+int
+test_phy_clk_sync_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ dbg_assert (fcall);
+ dbg_assert (param && *param);
+ dbg_assert (msg && *msg);
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* Only one message at a time. */
+ if (ctx->static_msg.id != TEST_PHY_MSG_ID_NONE)
+ return -1;
+ ctx->static_msg.id = TEST_PHY_MSG_ID_CLK_SYNC;
+ /* Read message. */
+ test_phy_msg_clk_sync_t *m = &ctx->static_msg.msg.clk_sync;
+ if (!test_phy_fcall_bind ("receiver", m->receiver))
+ m->receiver = false;
+ if (m->receiver && !test_phy_fcall_bind_long ("delay_tck", m->delay_tck))
+ return -1;
+ /* Message accepted, will return later. */
+ fcall_param_set_async (*param, 1);
+ dbg_assert (ctx->fcall == NULL);
+ ctx->fcall = fcall;
+ ctx->fcall_msg_id = fcall_param_get_msg_id (*param);
+ /* Post message. */
+ dbg_check (cyg_mbox_put (ctx->mbox, &ctx->static_msg));
+ return 0;
+}
+
+static void
+test_phy_clk_sync_fcall_return (test_phy_t *ctx)
+{
+ fcall_param_t param;
+ sci_msg_t msg;
+ u8 buffer[64];
+ dbg_assert (ctx);
+ dbg_assert (ctx->fcall);
+ fcall_param_init (&param, "test_phy_clk_sync", ctx->fcall_msg_id);
+ sci_msg_init (&msg, buffer, sizeof (buffer));
+ fcall_param_reset (&param);
+ dbg_check (fcall_return (ctx->fcall, &param, &msg) != -1);
+ ctx->fcall = NULL;
+}
+
+void
+test_phy_clk_sync_wait (test_t t, test_phy_t *ctx,
+ void (*report) (test_phy_t *ctx))
+{
+ test_within (t);
+ dbg_assert (ctx);
+ /* Activate reception. */
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_rx_param (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_rx_activate (ctx->phy, true, 0, true);
+ /* Report waiting. */
+ if (report)
+ report (ctx);
+ /* Wait for the synchronisation frame. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->rx_fc_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+ /* Check response. */
+ test_fail_unless (ctx->received_fc_crc_ok
+ && ctx->received_fc[0] == 0x7
+ && ctx->received_fc[1] == sync_tag
+ && ctx->received_fc[2] == 0
+ && ctx->received_fc[3] == 0);
+ /* Record zero date. */
+ ctx->clk_zero_tck = ctx->received_pre_date + MAC_PREAMBLE_TCK +
+ MAC_FC_AV_TCK + MAC_RIFS_DEFAULT_TCK;
+}
+
+void
+test_phy_clk_sync_go (test_t t, test_phy_t *ctx)
+{
+ dbg_assert (ctx);
+ u32 pre_date = phy_date (ctx->phy) + TEST_PHY_ANTICIP_TCK;
+ /* Record zero date. */
+ ctx->clk_zero_tck = pre_date + MAC_PREAMBLE_TCK + MAC_FC_AV_TCK
+ + MAC_RIFS_DEFAULT_TCK;
+ /* Send the synchronisation frame. */
+ u32 fc[4];
+ fc[0] = 0x7;
+ fc[1] = sync_tag;
+ fc[2] = 0; fc[3] = 0;
+ ctx->access_conf_cb = test_phy_default_access_conf_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ phy_tx_param_short (ctx->phy, PHY_FC_MODE_AV_1);
+ phy_tx_frame (ctx->phy, pre_date, true, false, fc);
+ /* Wait until transmission done. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ ctx->access_conf_cb = NULL;
+ ctx->deferred_cb = NULL;
+ test_phy_check_error (t, ctx);
+}
+
diff --git a/cesar/hal/phy/test/phy/src/data.c b/cesar/hal/phy/test/phy/src/data.c
new file mode 100644
index 0000000000..8c7d9fc225
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/data.c
@@ -0,0 +1,488 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/data.c
+ * \brief Test phy frame control and data.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/context.h"
+#include "inc/test_phy.h"
+#include "inc/data.h"
+
+#include "inc/clk_sync.h"
+
+#include "mac/common/timings.h"
+
+static void
+test_phy_data_fcall_return (test_phy_t *ctx);
+
+static const uint test_phy_data_pre_fc_dur[PHY_FC_MODE_NB] = {
+ MAC_PREAMBLE_HYBRID_TCK + MAC_FC_AV_TCK + MAC_FC_10_TCK,
+ MAC_PREAMBLE_HYBRID_TCK + 2 * MAC_FC_AV_TCK + MAC_FC_10_TCK,
+ MAC_PREAMBLE_TCK + MAC_FC_AV_TCK,
+ MAC_PREAMBLE_TCK + 2 * MAC_FC_AV_TCK,
+};
+
+static void
+test_phy_data_fc (test_t t, test_phy_t *ctx, uint iter)
+{
+ uint i;
+ phy_fc_mode_t mode;
+ u32 pre_date;
+ test_begin (t, "fc")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_go (t, ctx);
+ pre_date = ctx->clk_zero_tck;
+ /* Prepare callbacks. */
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->access_conf_cb = test_phy_default_access_conf_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Do this again and again. */
+ for (i = 0; i < iter; i++)
+ for (mode = PHY_FC_MODE_HYBRID_1; mode < PHY_FC_MODE_NB; mode++)
+ {
+ /* Wait before next TX. */
+ phy_extra_timer_program (ctx->phy, pre_date
+ - TEST_PHY_ANTICIP_TCK);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* FC 1.0 preparation. */
+ if (PHY_FC_MODE_IS_HYBRID (mode))
+ {
+ phy_tx_fc10 (ctx->phy, 0xfc10);
+ pre_date += PHY_FC_10_PREPARATION_DELAY_TCK;
+ }
+ /* Program a TX. */
+ u32 fc[4];
+ fc[0] = 0x7; fc[1] = pre_date; fc[2] = (u32) mode; fc[3] = i;
+ phy_tx_param_short (ctx->phy, mode);
+ phy_tx_frame (ctx->phy, pre_date, true, false, fc);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Next. */
+ pre_date += test_phy_data_pre_fc_dur[mode] +
+ MAC_RIFS_DEFAULT_TCK;
+ }
+ /* Cleanup. */
+ ctx->extra_timer_cb = NULL;
+ ctx->access_conf_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+static void
+test_phy_data_fc_receiver (test_t t, test_phy_t *ctx, uint iter,
+ bool bad_mode,
+ volatile bool *fcall_returned)
+{
+ uint i;
+ phy_fc_mode_t tx_mode, rx_mode;
+ u32 pre_date;
+ test_begin (t, "fc receiver")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_data_fcall_return);
+ pre_date = ctx->clk_zero_tck;
+ *fcall_returned = true;
+ /* Prepare callbacks. */
+ ctx->rx_fc_cb = test_phy_default_rx_fc_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Do this again and again. */
+ for (i = 0; i < iter; i++)
+ for (tx_mode = PHY_FC_MODE_HYBRID_1; tx_mode < PHY_FC_MODE_NB;
+ tx_mode++)
+ {
+ if (PHY_FC_MODE_IS_HYBRID (tx_mode))
+ pre_date += PHY_FC_10_PREPARATION_DELAY_TCK;
+ /* Wait for RX. */
+ rx_mode = !bad_mode ? tx_mode
+ : (tx_mode + i + 1) % PHY_FC_MODE_NB;
+ phy_rx_param (ctx->phy, rx_mode);
+ phy_rx_activate (ctx->phy, true, 0, true);
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ u32 fc_date = pre_date + test_phy_data_pre_fc_dur[tx_mode];
+ test_fail_unless (
+ ctx->received_pre_date == pre_date
+ && ctx->rx_fc_date > fc_date - TEST_PHY_ANTICIP_TCK
+ && ctx->rx_fc_date < fc_date + 2 * TEST_PHY_ANTICIP_TCK);
+ if (tx_mode == rx_mode)
+ test_fail_unless (ctx->received_fc_crc_ok
+ && ctx->received_fc[0] == 0x7
+ && ctx->received_fc[1] == pre_date
+ && ctx->received_fc[2] == (u32) tx_mode
+ && ctx->received_fc[3] == i);
+ else
+ test_fail_unless (!ctx->received_fc_crc_ok);
+ if (PHY_FC_MODE_IS_HYBRID (rx_mode))
+ {
+ u32 fc_10 = phy_rx_fc10 (ctx->phy);
+ if (PHY_FC_MODE_IS_HYBRID (tx_mode))
+ test_fail_unless (fc_10 != (u32)-1
+ && fc_10 == 0xfc10);
+ else
+ test_fail_unless (fc_10 == (u32)-1);
+ }
+ /* Next. */
+ pre_date += test_phy_data_pre_fc_dur[tx_mode] +
+ MAC_RIFS_DEFAULT_TCK;
+ }
+ /* Cleanup. */
+ ctx->rx_fc_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+static void
+test_phy_data_tonemap (test_t t, test_phy_t *ctx,
+ test_phy_data_parameters_t *d)
+{
+ /* Create a tonemap. */
+ tonemap_t *tm = tonemap_alloc ();
+ d->tonemap = tm;
+ /* Fill tonemap. */
+ static const u8 tm_data[] = {
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0, 0x55, 0, 0x66, 0, 0x77
+ };
+ uint bits = d->tonemap_bits;
+ dbg_assert (bits < COUNT (tm_data) && tm_data[bits]);
+ memset (tm->tmdma_desc_head->data, tm_data[bits], BLK_SIZE);
+ memset (tm->tmdma_desc_head->next->data, tm_data[bits], BLK_SIZE / 2);
+}
+
+static bool
+test_phy_data_data_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av)
+{
+ uint i;
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ /* Basic treatments. */
+ ctx->rx_fc_date = phy_date (ctx->phy);
+ ctx->rx_fc_count++;
+ ctx->received_pre_date = rx_date;
+ ctx->received_fc_crc_ok = !!fc_av;
+ if (fc_av)
+ for (i = 0; i < 4; i++)
+ ctx->received_fc[i] = fc_av[i];
+ /* This is different from the default: */
+ dbg_assert (ctx->static_msg.id == TEST_PHY_MSG_ID_DATA);
+ test_phy_data_parameters_t *d = &ctx->static_msg.msg.data.data_parameters;
+ if (d->mod == PHY_MOD_TM)
+ phy_set_tonemap (ctx->phy, 0, d->tonemap->tmdma_desc_head);
+ phy_rx_prepare (ctx->phy, d->short_ppdu, d->mod, d->fecrate,
+ d->pb_size, d->gil, 0, d->tx_nb_total);
+ if (!d->short_ppdu)
+ {
+ phy_pbdma_start (ctx->phy, d->bypass_aes, NULL, NULL, d->tx_nb_total,
+ d->tx_nb_total, d->tx_nb_total, d->pool_head);
+ }
+ return true;
+}
+
+static bool
+test_phy_data_data_pbdma_cb (void *user, u32 status_word)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ ctx->pbdma_date = phy_date (ctx->phy);
+ ctx->pbdma_count++;
+ ctx->pbdma_status = PHY_PBDMA_STATUS (status_word);
+ dbg_assert (!ctx->pbdma_status.rx_header_load_error
+ && !ctx->pbdma_status.ahb_response_error
+ && !ctx->pbdma_status.chandata_type_forbidden
+ && !ctx->pbdma_status.chandata_size_forbidden);
+ return true;
+}
+
+static bool
+test_phy_data_data_access_conf_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ dbg_assert (ctx->static_msg.id == TEST_PHY_MSG_ID_DATA);
+ test_phy_data_parameters_t *d = &ctx->static_msg.msg.data.data_parameters;
+ phy_pbdma_update (ctx->phy, d->tx_nb_ready, d->tx_nb_total);
+ return true;
+}
+
+static void
+test_phy_data_data (test_t t, test_phy_t *ctx, test_phy_data_parameters_t *d,
+ volatile bool *fcall_returned)
+{
+ u32 pre_date;
+ test_begin (t, "data")
+ {
+ /* Synchronise. */
+ if (fcall_returned == NULL)
+ {
+ test_phy_clk_sync_go (t, ctx);
+ }
+ else
+ {
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_data_fcall_return);
+ *fcall_returned = true;
+ }
+ pre_date = ctx->clk_zero_tck;
+ /* Prepare callbacks. */
+ ctx->extra_timer_cb = test_phy_default_extra_timer_cb;
+ ctx->access_conf_cb = test_phy_data_data_access_conf_cb;
+ ctx->pbdma_cb = test_phy_data_data_pbdma_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Optionally prepare FC 1.0. */
+ if (PHY_FC_MODE_IS_HYBRID (d->fc_mode))
+ {
+ phy_tx_fc10 (ctx->phy, 0xfc10);
+ }
+ /* Program PB DMA. */
+ if (d->mod == PHY_MOD_TM)
+ phy_set_tonemap (ctx->phy, 0, d->tonemap->tmdma_desc_head);
+ phy_pb_t *pbs = gen_data_blk_cached (&ctx->gen, d->tx_nb_total, NULL);
+ phy_pbdma_start (ctx->phy, d->bypass_aes, NULL, NULL, d->tx_nb_total,
+ d->tx_nb_ready < 4 ? d->tx_nb_ready : 4, 0, pbs);
+ uint i;
+ for (i = 0; i < d->tx_nb_ready; i++)
+ pbs = PARENT_OF (phy_pb_t, blk, pbs->blk.next);
+ /* Program TX. */
+ phy_tx_param (ctx->phy, d->fc_mode, d->short_ppdu, d->mod, d->fecrate,
+ d->pb_size, d->gil, 0);
+ u32 fc[4];
+ fc[0] = 0x1; //XXX
+ fc[1] = pre_date;
+ fc[2] = 0x01234567;
+ fc[3] = 0x89abcdef;
+ phy_tx_frame (ctx->phy, pre_date, true, false, fc);
+ /* Wait ACCESS_CONF. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ /* Wait PB DMA end. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ test_fail_unless (!ctx->pbdma_status.pb_null
+ && !ctx->pbdma_status.pb_crc_error
+ && ctx->pbdma_status.pb_it
+ && !ctx->pbdma_status.end_rx_pb
+ && ctx->pbdma_status.end_tx_pb
+ && !ctx->pbdma_status.end_chandata);
+ /* Cleanup. */
+ ctx->extra_timer_cb = NULL;
+ ctx->access_conf_cb = NULL;
+ ctx->pbdma_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+static void
+test_phy_data_data_receiver (test_t t, test_phy_t *ctx,
+ test_phy_data_parameters_t *d,
+ volatile bool *fcall_returned)
+{
+ u32 pre_date;
+ test_begin (t, "data receiver")
+ {
+ /* Synchronise. */
+ test_phy_clk_sync_wait (t, ctx, *fcall_returned ? NULL
+ : test_phy_data_fcall_return);
+ pre_date = ctx->clk_zero_tck;
+ *fcall_returned = true;
+ /* Prepare callbacks. */
+ ctx->rx_fc_cb = test_phy_data_data_rx_fc_cb;
+ ctx->pbdma_cb = test_phy_data_data_pbdma_cb;
+ ctx->deferred_cb = test_phy_default_deferred_cb;
+ /* Prepare pool. */
+ blk_t *pool_tail;
+ d->pool_head =
+ (phy_pb_t *) blk_alloc_desc_range (d->tx_nb_total, &pool_tail);
+ /* Activate RX. */
+ phy_rx_param (ctx->phy, d->fc_mode);
+ phy_rx_activate (ctx->phy, false, pre_date - TEST_PHY_ANTICIP_TCK,
+ true);
+ /* Wait FC. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ test_fail_unless (ctx->received_pre_date == pre_date
+ && ctx->received_fc_crc_ok
+ && ctx->received_fc[0] == 0x1 //XXX
+ && ctx->received_fc[1] == pre_date
+ && ctx->received_fc[2] == 0x01234567
+ && ctx->received_fc[3] == 0x89abcdef);
+ /* Wait PB DMA end. */
+ dbg_check (cyg_semaphore_wait (&ctx->event_sem));
+ test_phy_check_error (t, ctx);
+ test_fail_unless (!ctx->pbdma_status.pb_null
+ && !ctx->pbdma_status.pb_crc_error
+ && ctx->pbdma_status.pb_it
+ && ctx->pbdma_status.end_rx_pb
+ && !ctx->pbdma_status.end_tx_pb
+ && !ctx->pbdma_status.end_chandata);
+ /* Release pool. */
+ blk_release_desc_range (&d->pool_head->blk, pool_tail);
+ /* Cleanup. */
+ ctx->rx_fc_cb = NULL;
+ ctx->pbdma_cb = NULL;
+ ctx->deferred_cb = NULL;
+ } test_end;
+}
+
+void
+test_phy_data (test_t t, test_phy_t *ctx, test_phy_msg_data_t *msg)
+{
+ volatile bool fcall_returned = false; /* Be careful of the longjmp. */
+ dbg_assert (ctx);
+ dbg_assert (msg);
+ test_case_begin (t, "data");
+ /* Do tests. */
+ if (msg->do_fc)
+ {
+ if (!msg->fc_receiver)
+ test_phy_data_fc (t, ctx, msg->fc_iter);
+ else
+ test_phy_data_fc_receiver (t, ctx, msg->fc_iter, msg->fc_bad_mode,
+ &fcall_returned);
+ }
+ if (msg->do_data)
+ {
+ if (msg->data_parameters.mod == PHY_MOD_TM)
+ test_phy_data_tonemap (t, ctx, &msg->data_parameters);
+ else
+ msg->data_parameters.tonemap = NULL;
+ if (!msg->data_receiver)
+ test_phy_data_data (t, ctx, &msg->data_parameters,
+ msg->data_sync_wait ? &fcall_returned : NULL);
+ else
+ test_phy_data_data_receiver (t, ctx, &msg->data_parameters,
+ &fcall_returned);
+ if (msg->data_parameters.tonemap)
+ tonemap_free (msg->data_parameters.tonemap);
+ }
+ if (!fcall_returned)
+ {
+ test_phy_data_fcall_return (ctx);
+ fcall_returned = true;
+ }
+}
+
+int
+test_phy_data_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ dbg_assert (fcall);
+ dbg_assert (param && *param);
+ dbg_assert (msg && *msg);
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* Only one message at a time. */
+ if (ctx->static_msg.id != TEST_PHY_MSG_ID_NONE)
+ return -1;
+ ctx->static_msg.id = TEST_PHY_MSG_ID_DATA;
+ /* Read message. */
+ test_phy_msg_data_t *m = &ctx->static_msg.msg.data;
+ if (!test_phy_fcall_bind ("fc", m->do_fc))
+ m->do_fc = false;
+ if (m->do_fc)
+ {
+ if (!test_phy_fcall_bind ("fc_bad_mode", m->fc_bad_mode))
+ m->fc_bad_mode = false;
+ if (!test_phy_fcall_bind_long ("fc_iter", m->fc_iter))
+ m->fc_iter = m->fc_bad_mode ? 4 : 1;
+ if (!test_phy_fcall_bind ("fc_receiver", m->fc_receiver))
+ m->fc_receiver = false;
+ }
+ /* Data test is used by default when no other test. */
+ if (!test_phy_fcall_bind ("data", m->do_data))
+ m->do_data = !m->do_fc;
+ if (m->do_data)
+ {
+ test_phy_data_parameters_t *d = &m->data_parameters;
+ uint v;
+ if (!test_phy_fcall_bind ("receiver", m->data_receiver))
+ m->data_receiver = false;
+ if (!test_phy_fcall_bind ("sync_wait", m->data_sync_wait))
+ m->data_sync_wait = false;
+ if (!test_phy_fcall_bind_long ("fc_mode", d->fc_mode))
+ d->fc_mode = PHY_FC_MODE_AV_1;
+ if (!test_phy_fcall_bind ("short_ppdu", d->short_ppdu))
+ d->short_ppdu = false;
+ if (!d->short_ppdu)
+ {
+ if (!test_phy_fcall_bind_long ("mod", d->mod))
+ d->mod = PHY_MOD_ROBO;
+ if (d->mod == PHY_MOD_TM)
+ {
+ if (!test_phy_fcall_bind_long ("tonemap_bits",
+ d->tonemap_bits))
+ d->tonemap_bits = 10;
+ }
+ if (!test_phy_fcall_bind_long ("fecrate", d->fecrate))
+ d->fecrate = PHY_FEC_RATE_1_2;
+ if (!test_phy_fcall_bind_long ("pb_size", v))
+ d->pb_size = PHY_PB_SIZE_520;
+ else
+ {
+ if (v == PHY_PB_SIZE_136 || v == PHY_PB_SIZE_520)
+ d->pb_size = v;
+ else if (v == 520)
+ d->pb_size = PHY_PB_SIZE_520;
+ else if (v == 136)
+ d->pb_size = PHY_PB_SIZE_136;
+ else
+ return -1;
+ }
+ if (!test_phy_fcall_bind_long ("gil", v))
+ d->gil = PHY_GIL_567;
+ else
+ {
+ if (v < PHY_GIL_NB)
+ d->gil = v;
+ else if (v == 417)
+ d->gil = PHY_GIL_417;
+ else if (v == 567)
+ d->gil = PHY_GIL_567;
+ else if (v == 3534)
+ d->gil = PHY_GIL_3534;
+ else
+ return -1;
+ }
+ if (!test_phy_fcall_bind ("bypass_aes", d->bypass_aes))
+ d->bypass_aes = true;
+ if (!test_phy_fcall_bind_long ("tx_nb_total", d->tx_nb_total))
+ return -1;
+ if (!test_phy_fcall_bind_long ("tx_nb_ready", d->tx_nb_ready))
+ d->tx_nb_ready = d->tx_nb_total;
+ }
+ d->pool_head = NULL;
+ }
+ /* Message accepted, will return later. */
+ fcall_param_set_async (*param, 1);
+ dbg_assert (ctx->fcall == NULL);
+ ctx->fcall = fcall;
+ ctx->fcall_msg_id = fcall_param_get_msg_id (*param);
+ /* Post message. */
+ dbg_check (cyg_mbox_put (ctx->mbox, &ctx->static_msg));
+ return 0;
+}
+
+static void
+test_phy_data_fcall_return (test_phy_t *ctx)
+{
+ fcall_param_t param;
+ sci_msg_t msg;
+ u8 buffer[64];
+ dbg_assert (ctx);
+ dbg_assert (ctx->fcall);
+ fcall_param_init (&param, "test_phy_data", ctx->fcall_msg_id);
+ sci_msg_init (&msg, buffer, sizeof (buffer));
+ fcall_param_reset (&param);
+ dbg_check (fcall_return (ctx->fcall, &param, &msg) != -1);
+ ctx->fcall = NULL;
+}
+
diff --git a/cesar/hal/phy/test/phy/src/gen.c b/cesar/hal/phy/test/phy/src/gen.c
new file mode 100644
index 0000000000..d5406f77f6
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/gen.c
@@ -0,0 +1,84 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/gen.c
+ * \brief Data and Tonemap generator.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/gen.h"
+
+void
+gen_init (gen_t *ctx)
+{
+ dbg_assert (ctx);
+ lib_rnd_init (ctx->rnd, 0x47fe4621);
+ ctx->cache_head = ctx->cache_tail = NULL;
+ ctx->cache_nb = 0;
+}
+
+void
+gen_uninit (gen_t *ctx)
+{
+ dbg_assert (ctx);
+ blk_release_desc_range (&ctx->cache_head->blk, &ctx->cache_tail->blk);
+}
+
+phy_pb_t *
+gen_data_blk_cached (gen_t *ctx, uint n, phy_pb_t **last)
+{
+ dbg_assert (ctx);
+ /* May need to generate new blocks to cache. */
+ if (n > ctx->cache_nb)
+ {
+ blk_t *head_blk, *tail_blk, *p_blk, *p_last_blk;
+ uint add = n - ctx->cache_nb;
+ /* Alloc new blocks. */
+ head_blk = blk_alloc_desc_range (add, &tail_blk);
+ /* Fill with random data. */
+ for (p_blk = head_blk; p_last_blk != tail_blk;
+ p_last_blk = p_blk, p_blk = p_blk->next)
+ {
+ lib_rnd_buffer (ctx->rnd, p_blk->data, BLK_SIZE);
+ PARENT_OF (phy_pb_t, blk, p_blk)->pb_tx.header =
+ lib_rnd32 (ctx->rnd);
+ }
+ /* Chain in cache. */
+ if (!ctx->cache_nb)
+ {
+ ctx->cache_head = (phy_pb_t *) head_blk;
+ ctx->cache_tail = (phy_pb_t *) tail_blk;
+ }
+ else
+ {
+ ctx->cache_tail->blk.next = head_blk;
+ ctx->cache_tail = (phy_pb_t *) tail_blk;
+ }
+ ctx->cache_nb += add;
+ }
+ if (last)
+ {
+ if (n == ctx->cache_nb)
+ {
+ /* No lookup needed. */
+ *last = ctx->cache_tail;
+ }
+ else
+ {
+ /* Lookup tail. */
+ uint i;
+ phy_pb_t *p = ctx->cache_head;
+ for (i = 1; i < n; i++)
+ p = PARENT_OF (phy_pb_t, blk, p->blk.next);
+ *last = p;
+ }
+ }
+ return ctx->cache_head;
+}
+
diff --git a/cesar/hal/phy/test/phy/src/host_test_phy.cpp b/cesar/hal/phy/test/phy/src/host_test_phy.cpp
new file mode 100644
index 0000000000..a3051bf606
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/host_test_phy.cpp
@@ -0,0 +1,235 @@
+// Cesar project {{{
+//
+// Copyright (C) 2007 Spidcom
+//
+// <<<Licence>>>
+//
+// }}}
+/// \file src/host_test_phy.cpp
+/// \brief Test Phy host part.
+/// \ingroup test
+#include "Maximus.h"
+#include "Sta.h"
+#include "Msg.h"
+
+#include "mac/common/defs.h"
+
+#include <iostream>
+
+uint
+quick_print_test_result (Maximus &maximus, Sta &sta, const char *msg)
+{
+ Msg rsp = maximus.create_fc ("test_phy_result")
+ .send (sta);
+ uint fail_nb = rsp.bind_param<int> ("fail_nb");
+ uint test_nb = rsp.bind_param<int> ("test_nb");
+ uint error = rsp.bind_param<int> ("error");
+ std::cout << msg << ": fail: " << fail_nb << '/' << test_nb << " error: "
+ << error << std::endl;
+ return fail_nb + error;
+}
+
+uint
+basic_test_case (Maximus &maximus, Sta &sta0, Sta &sta1, bool slow)
+{
+ uint failled = 0;
+
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("init", true)
+ .add_param ("reset", true)
+ .add_param ("date", true)
+ .add_param ("date_delay_tck", 2500000)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "basic tests");
+
+ if (slow)
+ {
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("date", true)
+ .add_param ("date_delay_tck", 25000000)
+ .add_param ("date_rollover", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "rollover tests");
+ }
+
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("preamble", true)
+ .add_param ("preamble_receiver", true)
+ .add_param ("preamble_async", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("preamble", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "preamble test, sta0");
+ failled += quick_print_test_result (maximus, sta1, "preamble test, sta1");
+
+ return failled;
+}
+
+uint
+clk_sync_test_case (Maximus &maximus, Sta &sta0, Sta &sta1)
+{
+ uint failled = 0;
+
+ // Test reset by the way.
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("reset", true)
+ .send (sta0);
+ maximus.create_fc ("test_phy_basic")
+ .add_param ("reset", true)
+ .send (sta1);
+
+ maximus.create_fc ("test_phy_clk_sync")
+ .add_param ("receiver", true)
+ .add_param ("delay_tck", 2500)
+ .send (sta1);
+ maximus.create_fc ("test_phy_clk_sync")
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "clk sync test, sta0");
+ failled += quick_print_test_result (maximus, sta1, "clk sync test, sta1");
+
+ return failled;
+}
+
+uint
+access_test_case (Maximus &maximus, Sta &sta0, Sta &sta1, bool slow)
+{
+ uint failled = 0;
+
+ maximus.create_fc ("test_phy_access")
+ .add_param ("timer_basic", true)
+ .add_param ("timer_basic_iter", 100)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "timer basic tests");
+
+ if (slow)
+ {
+ maximus.create_fc ("test_phy_access")
+ .add_param ("timer_rollover", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "timer rollover tests");
+ }
+
+ maximus.create_fc ("test_phy_access")
+ .add_param ("timer_preamble_stop", true)
+ .add_param ("timer_preamble_stop_sender", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_access")
+ .add_param ("timer_preamble_stop", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "timer preamble stop test, sta0");
+ failled += quick_print_test_result (maximus, sta1, "timer preamble stop test, sta1");
+
+ maximus.create_fc ("test_phy_access")
+ .add_param ("prs", true)
+ .add_param ("prs_second", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_access")
+ .add_param ("prs", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "prs test, sta0");
+ failled += quick_print_test_result (maximus, sta1, "prs test, sta1");
+
+ maximus.create_fc ("test_phy_access")
+ .add_param ("slot_counter", true)
+ .add_param ("slot_counter_second", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_access")
+ .add_param ("slot_counter", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "slot counter test, sta0");
+ failled += quick_print_test_result (maximus, sta1, "slot counter test, sta1");
+
+ return failled;
+}
+
+uint
+data_test_case (Maximus &maximus, Sta &sta0, Sta &sta1)
+{
+ uint failled = 0;
+
+ maximus.create_fc ("test_phy_data")
+ .add_param ("fc", true)
+ .add_param ("fc_iter", 100)
+ .add_param ("fc_receiver", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_data")
+ .add_param ("fc", true)
+ .add_param ("fc_iter", 100)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "fc, sta0");
+ failled += quick_print_test_result (maximus, sta1, "fc, sta1");
+
+ maximus.create_fc ("test_phy_data")
+ .add_param ("fc", true)
+ .add_param ("fc_bad_mode", true)
+ .add_param ("fc_receiver", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_data")
+ .add_param ("fc", true)
+ .add_param ("fc_bad_mode", true)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "fc, sta0");
+ failled += quick_print_test_result (maximus, sta1, "fc, sta1");
+
+ for (uint i = 1; i <= 6; i += 1)
+ {
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .add_param ("receiver", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "data, sta0");
+ failled += quick_print_test_result (maximus, sta1, "data, sta1");
+
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .add_param ("sync_wait", true)
+ .send (sta1);
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "data coll, sta0");
+ failled += quick_print_test_result (maximus, sta1, "data coll, sta1");
+ }
+
+ for (uint i = 1; i <= 188; i += 10)
+ {
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .add_param ("receiver", true)
+ .add_param ("mod", (uint) PHY_MOD_TM)
+ .add_param ("fecrate", (uint) PHY_FEC_RATE_16_21)
+ .add_param ("gil", (uint) PHY_GIL_417)
+ .send (sta1);
+ maximus.create_fc ("test_phy_data")
+ .add_param ("tx_nb_total", i)
+ .add_param ("mod", (uint) PHY_MOD_TM)
+ .add_param ("fecrate", (uint) PHY_FEC_RATE_16_21)
+ .add_param ("gil", (uint) PHY_GIL_417)
+ .send (sta0);
+ failled += quick_print_test_result (maximus, sta0, "data qam1024, sta0");
+ failled += quick_print_test_result (maximus, sta1, "data qam1024, sta1");
+ }
+
+ return failled;
+}
+
+int
+main (int argc, char **argv)
+{
+ uint failled = 0;
+ Maximus maximus;
+ maximus.init (argc, argv);
+ Sta sta0 = maximus.create_sta ();
+ Sta sta1 = maximus.create_sta ();
+
+ failled += basic_test_case (maximus, sta0, sta1, false);
+ failled += clk_sync_test_case (maximus, sta0, sta1);
+ failled += access_test_case (maximus, sta0, sta1, false);
+ failled += data_test_case (maximus, sta0, sta1);
+
+ return failled == 0 ? failled : 1;
+}
diff --git a/cesar/hal/phy/test/phy/src/test_phy.c b/cesar/hal/phy/test/phy/src/test_phy.c
new file mode 100644
index 0000000000..2525f06645
--- /dev/null
+++ b/cesar/hal/phy/test/phy/src/test_phy.c
@@ -0,0 +1,412 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/test_phy.c
+ * \brief Phy test.
+ * \ingroup test
+ */
+#include "common/std.h"
+
+#include "inc/context.h"
+
+#include "hal/arch/arch.h"
+#include "mac/common/timings.h"
+
+#include "inc/test_phy.h"
+#include "inc/basic.h"
+#include "inc/clk_sync.h"
+#include "inc/access.h"
+#include "inc/data.h"
+
+#include "mac/common/tonemask.h"
+
+#include "lib/trace.h"
+
+#include <string.h>
+
+#define TEST_PHY_PRIORITY 16
+
+/** Global test Phy context. */
+static test_phy_t test_phy_global;
+
+static void
+test_phy_result_fcall_return (test_phy_t *ctx);
+
+bool
+test_phy_access_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ if (!ctx->access_cb)
+ {
+ ctx->stats.access_unexpected++;
+ ctx->isr_error++;
+ return true;
+ }
+ else
+ return ctx->access_cb (user);
+}
+
+bool
+test_phy_access_conf_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ if (!ctx->access_conf_cb)
+ {
+ ctx->stats.access_conf_unexpected++;
+ ctx->isr_error++;
+ return true;
+ }
+ else
+ return ctx->access_conf_cb (user);
+}
+
+bool
+test_phy_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ ctx->stats.rx_fc_count++;
+ if (!fc_av)
+ ctx->stats.rx_fc_bad_crc++;
+ if (!ctx->rx_fc_cb)
+ {
+ ctx->stats.rx_fc_unexpected++;
+ ctx->isr_error++;
+ return true;
+ }
+ else
+ return ctx->rx_fc_cb (user, rx_date, fc_av);
+}
+
+bool
+test_phy_pbdma_cb (void *user, u32 status_word)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ if (!ctx->pbdma_cb)
+ {
+ ctx->stats.pbdma_unexpected++;
+ ctx->isr_error++;
+ return true;
+ }
+ else
+ return ctx->pbdma_cb (user, status_word);
+}
+
+bool
+test_phy_tx_false_alarm_cb (void *user)
+{
+ // TODO
+ return false;
+}
+
+void
+test_phy_deferred_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ if (ctx->isr_error)
+ {
+ uint isr_error = ctx->isr_error;
+ arch_atomic_add (&ctx->isr_error, -isr_error);
+ ctx->stats.error += isr_error;
+ cyg_semaphore_post (&ctx->event_sem);
+ }
+ else if (!ctx->deferred_cb)
+ {
+ ctx->stats.deferred_unexpected++;
+ ctx->stats.error++;
+ cyg_semaphore_post (&ctx->event_sem);
+ }
+ else
+ ctx->deferred_cb (user);
+}
+
+bool
+test_phy_extra_timer_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ if (!ctx->extra_timer_cb)
+ {
+ ctx->stats.extra_timer_unexpected++;
+ ctx->isr_error++;
+ return true;
+ }
+ else
+ return ctx->extra_timer_cb (user);
+}
+
+bool
+test_phy_default_rx_fc_cb (void *user, u32 rx_date, const u32 *fc_av)
+{
+ uint i;
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ ctx->rx_fc_date = phy_date (ctx->phy);
+ ctx->rx_fc_count++;
+ ctx->received_pre_date = rx_date;
+ ctx->received_fc_crc_ok = !!fc_av;
+ if (fc_av)
+ for (i = 0; i < 4; i++)
+ ctx->received_fc[i] = fc_av[i];
+ phy_rx_prepare_short (ctx->phy);
+ return true;
+}
+
+bool
+test_phy_default_access_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ ctx->access_date = phy_date (ctx->phy);
+ ctx->access_count++;
+ return true;
+}
+
+bool
+test_phy_default_access_conf_cb (void *user)
+{
+ dbg_assert (user);
+ return true;
+}
+
+void
+test_phy_default_deferred_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ cyg_semaphore_post (&ctx->event_sem);
+}
+
+bool
+test_phy_default_extra_timer_cb (void *user)
+{
+ test_phy_t *ctx = (void *) user;
+ dbg_assert (ctx);
+ ctx->extra_timer_count++;
+ return true;
+}
+
+void
+test_phy_check_error (test_t t, test_phy_t *ctx)
+{
+ test_within (t);
+ cyg_scheduler_lock ();
+ uint error = ctx->stats.error;
+ ctx->stats.error = 0;
+ cyg_scheduler_unlock ();
+ test_fail_unless (error == 0);
+}
+
+static int
+test_phy_result_fcall (fcall_ctx_t *fcall, fcall_param_t **param,
+ sci_msg_t **msg, void *data)
+{
+ dbg_assert (fcall);
+ dbg_assert (param && *param);
+ dbg_assert (msg && *msg);
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* If a call is pending, this is an error. */
+ if (ctx->fcall)
+ return -1;
+ /* Record parameters for return. */
+ fcall_param_set_async (*param, 1);
+ dbg_assert (ctx->fcall == NULL);
+ ctx->fcall = fcall;
+ ctx->fcall_msg_id = fcall_param_get_msg_id (*param);
+ /* Is test finished? */
+ if (ctx->static_msg.id == TEST_PHY_MSG_ID_NONE)
+ {
+ test_phy_result_fcall_return (ctx);
+ }
+ else
+ {
+ /* Will return later. */
+ ctx->result_pending = true;
+ }
+ return 0;
+}
+
+static void
+test_phy_result_fcall_return (test_phy_t *ctx)
+{
+ fcall_param_t param;
+ sci_msg_t msg;
+ u8 buffer[512];
+ dbg_assert (ctx);
+ dbg_assert (ctx->fcall);
+ fcall_param_init (&param, "test_phy_result", ctx->fcall_msg_id);
+ sci_msg_init (&msg, buffer, sizeof (buffer));
+ fcall_param_reset (&param);
+ /* Fill parameters. */
+ test_phy_fcall_add_long ("error", ctx->stats.error);
+ test_phy_fcall_add_long ("access_unexpected",
+ ctx->stats.access_unexpected);
+ test_phy_fcall_add_long ("access_conf_unexpected",
+ ctx->stats.access_conf_unexpected);
+ test_phy_fcall_add_long ("rx_fc_unexpected", ctx->stats.rx_fc_unexpected);
+ test_phy_fcall_add_long ("pbdma_unexpected", ctx->stats.pbdma_unexpected);
+ test_phy_fcall_add_long ("deferred_unexpected",
+ ctx->stats.deferred_unexpected);
+ test_phy_fcall_add_long ("extra_timer_unexpected",
+ ctx->stats.extra_timer_unexpected);
+ test_phy_fcall_add_long ("rx_fc_count", ctx->stats.rx_fc_count);
+ test_phy_fcall_add_long ("rx_fc_bad_crc", ctx->stats.rx_fc_bad_crc);
+ test_phy_fcall_add_long ("test_nb", ctx->test_nb);
+ test_phy_fcall_add_long ("fail_nb", ctx->fail_nb);
+ /* Send return message. */
+ dbg_check (fcall_return (ctx->fcall, &param, &msg) != -1);
+ ctx->fcall = NULL;
+}
+
+/**
+ * Test Phy thread.
+ * \param data test Phy context
+ *
+ * Receive and dispatch messages.
+ */
+static void
+test_phy_thread (cyg_addrword_t data)
+{
+ test_phy_t *ctx = (void *) data;
+ dbg_assert (ctx);
+ /* Initialise Phy. */
+ ctx->phy = phy_init (ctx, test_phy_rx_fc_cb, test_phy_access_cb,
+ test_phy_access_conf_cb, test_phy_pbdma_cb,
+ test_phy_tx_false_alarm_cb, test_phy_deferred_cb);
+ phy_set_tonemask (ctx->phy, ctx->tonemask, ctx->tonemask_carrier_nb);
+ phy_extra_timer_init (ctx->phy, ctx, test_phy_extra_timer_cb);
+ /* Handle messages. */
+ test_phy_msg_t *msg;
+ while ((msg = cyg_mbox_get (ctx->mbox)))
+ {
+ test_t t;
+ test_init_basic (t, 3);
+ ctx->test_nb = ctx->fail_nb = 0;
+ test_suite_begin (t, "phy");
+ switch (msg->id)
+ {
+ case TEST_PHY_MSG_ID_BASIC:
+ test_phy_basic (t, ctx, &msg->msg.basic);
+ break;
+ case TEST_PHY_MSG_ID_CLK_SYNC:
+ test_phy_clk_sync (t, ctx, &msg->msg.clk_sync);
+ break;
+ case TEST_PHY_MSG_ID_ACCESS:
+ test_phy_access (t, ctx, &msg->msg.access);
+ break;
+ case TEST_PHY_MSG_ID_DATA:
+ test_phy_data (t, ctx, &msg->msg.data);
+ break;
+ default:
+ break;
+ }
+ msg->id = TEST_PHY_MSG_ID_NONE;
+ ctx->test_nb = test_nb_attempted (t);
+ ctx->fail_nb = test_nb_failed (t);
+ if (ctx->result_pending)
+ {
+ test_phy_result_fcall_return (ctx);
+ ctx->result_pending = false;
+ }
+ memset (&ctx->stats, 0, sizeof (ctx->stats));
+ arch_atomic_add (&ctx->isr_error, -ctx->isr_error);
+ }
+}
+
+/**
+ * Initialise test Phy.
+ * \param ctx test Phy context
+ *
+ * Start the test thread.
+ */
+static void
+test_phy_init (test_phy_t *ctx)
+{
+ cyg_resolution_t res;
+ /* Phy is initialised later, here, initialise the test Phy context. */
+ ctx->phy = NULL;
+ ctx->clk_zero_tck = 0;
+ cyg_semaphore_init (&ctx->event_sem, 0);
+ cyg_mbox_create (&ctx->mbox, &ctx->mbox_storage);
+ ctx->static_msg.id = TEST_PHY_MSG_ID_NONE;
+ ctx->result_pending = false;
+ ctx->rx_fc_cb = NULL;
+ ctx->access_cb = NULL;
+ ctx->access_conf_cb = NULL;
+ ctx->pbdma_cb = NULL;
+ ctx->deferred_cb = NULL;
+ ctx->extra_timer_cb = NULL;
+ ctx->rx_fc_count = 0;
+ ctx->access_count = 0;
+ ctx->pbdma_count = 0;
+ ctx->extra_timer_count = 0;
+ memset (&ctx->stats, 0, sizeof (ctx->stats));
+ ctx->test_nb = 0;
+ ctx->fail_nb = 0;
+ ctx->isr_error = 0;
+ res = cyg_clock_get_resolution (cyg_real_time_clock ());
+ ctx->tck_per_rtc = MAC_MS_TO_TCK (1000LL) * res.dividend / res.divisor /
+ 1000000000LL;
+ ctx->fcall = NULL;
+ ctx->fcall_msg_id = 0;
+ ctx->tonemask_carrier_nb = tonemask_default (ctx->tonemask);
+ lib_rnd_init (ctx->rnd, 1234);
+ gen_init (&ctx->gen);
+ /* Initialise tonemap. Mix of modulations:
+ * 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2... */
+ uint i, j, mod;
+ mod = 0;
+ for (i = 0; i < PHY_TONEMAP_SIZE; i++)
+ ctx->tonemap[i] = 0;
+ for (i = 0; i < PHY_TONEMASK_SIZE; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ if (ctx->tonemask[i] & (1 << j))
+ ctx->tonemap[i * 4 + j / 2] |= (mod++ % 8) << (4 * (j % 2));
+ }
+ }
+ dbg_assert (mod == ctx->tonemask_carrier_nb);
+ ctx->tonemap_blk[0].data = ctx->tonemap;
+ ctx->tonemap_blk[0].next = &ctx->tonemap_blk[1];
+ ctx->tonemap_blk[1].data = ctx->tonemap + BLK_SIZE;
+ dbg_invalid_ptr (ctx->tonemap_blk[0].next);
+ /* Go. */
+ cyg_thread_create (TEST_PHY_PRIORITY, &test_phy_thread,
+ (cyg_addrword_t) ctx, "test_phy", ctx->thread_stack,
+ COUNT (ctx->thread_stack), &ctx->thread,
+ &ctx->thread_storage);
+ cyg_thread_resume (ctx->thread);
+}
+
+/** Entry point. */
+void
+cyg_user_start (void)
+{
+ fcall_register (my_station.fcall, "test_phy_basic",
+ test_phy_basic_fcall, &test_phy_global);
+ fcall_register (my_station.fcall, "test_phy_clk_sync",
+ test_phy_clk_sync_fcall, &test_phy_global);
+ fcall_register (my_station.fcall, "test_phy_access",
+ test_phy_access_fcall, &test_phy_global);
+ fcall_register (my_station.fcall, "test_phy_data",
+ test_phy_data_fcall, &test_phy_global);
+ fcall_register (my_station.fcall, "test_phy_result",
+ test_phy_result_fcall, &test_phy_global);
+ //my_station.pipe_log_fd = 1;
+ //my_station.log_level = STATION_LOG_DEBUG;
+ //my_station.log_mask = STATION_LOGTYPE_FCALL;
+ trace_init ();
+ test_phy_init (&test_phy_global);
+}
+