/* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file test_general/hard/bridgedma/src/bridgedma-tx.c * \brief « brief description » * \ingroup « module » * * « long description » */ #include "common/std.h" #include #include #include "common/defs/ethernet.h" #include "common/defs/homeplugAV.h" #include "lib/test.h" #include "lib/list.h" #include "lib/crc.h" #include "lib/read_word.h" #include "lib/bitstream.h" #include "mac/common/pb.h" #include "hal/phy/inc/bridgedma.h" #include "hal/phy/inc/bridgedma_regs.h" #include "hal/phy/inc/bridgedma_soft.h" #include #include #include #include "hal/arch/arch.h" #define TEST_BRIDGEDMA_PB_NB 5 #define TEST_BRIDGEDMA_JOB_OFFSET 18 cyg_thread my_test_thread; cyg_handle_t my_test_thread_handle; u8 my_test_thread_stack [CYGNUM_HAL_STACK_SIZE_TYPICAL]; static test_t test; static bool it_recv = false; static phy_bridgedma_t *bridgedma_ctx; static phy_bridgedma_job_t *job1, *job2, *job3; #ifdef __sparc__ static u8 frame_buffer [2048] __attribute__((section(".private"))); #else static u8 frame_buffer [2048]; #endif u8 *hard_buffer; /* WARNING: callback are not possible to test inside UNIT TEST */ bool _bridgedma_segmentation_cb(void *data, u32 status) { it_recv = true; return true; } /* WARNING: callback are not possible to test inside UNIT TEST */ void _bridgedma_deffered_cb(void *data) { } void bridgedma_segmentation_test_case(void) { uint ats; pb_t *pb_current, *pb_first, *pb_last; hard_buffer = ARCH_CPU_TO_UNCACHEABLE (frame_buffer); memset (hard_buffer, 0, 2048); /* Allocate jobs. */ job1 = (phy_bridgedma_job_t *) blk_alloc(); job2 = (phy_bridgedma_job_t *) blk_alloc(); job3 = (phy_bridgedma_job_t *) blk_alloc(); test_case_begin(test, "segmentation"); pb_first = (pb_t*) blk_alloc_desc_range(TEST_BRIDGEDMA_PB_NB, (blk_t **) &pb_last); pb_last->next = NULL; pb_current = pb_first; for (pb_current = pb_first; pb_current; pb_current = pb_current->next) { /* Reset the PBs. */ memset (&pb_current->header, 0, sizeof (pb_current->header)); memset (pb_current->data, 0, BLK_SIZE); } ats = 0x12345678; memset (job1, 0, sizeof (phy_bridgedma_job_t)); job1->next = job2; job1->data_addr = hard_buffer; job1->header_len = 6; job1->data_len = 1490; job1->first_pb_desc = (blk_t *)pb_first; job1->first_pb_offset = TEST_BRIDGEDMA_JOB_OFFSET; job1->segment_len = 512; job1->direction = 0; job1->crc_reset = 1; job1->crc_store = 1; job1->append_zero = 1; job1->job_it = 0; job1->eth_buffer_mask = 0x0; /* Payload + ATS */ job1->mf_header1 = (((job1->data_len + 4 - 1) << 2) | 0x02) | (ats << 16); job1->mf_header2 = (ats >> 16); memset (job2, 0, sizeof (phy_bridgedma_job_t)); job2->next = job3; job2->data_addr = hard_buffer; job2->header_len = 6; job2->data_len = 390; job2->first_pb_desc = (blk_t *)pb_first->next->next; job2->first_pb_offset = 494; job2->segment_len = 512; job2->direction = 0; job2->crc_reset = 1; job2->crc_store = 1; job2->append_zero = 1; job2->job_it = 0; job2->eth_buffer_mask = 0x0; /* Payload + ATS */ job2->mf_header1 = (((job2->data_len + 4 - 1) << 2) | 0x02) | (ats << 16); job2->mf_header2 = (ats >> 16); memset (job3, 0, sizeof (phy_bridgedma_job_t)); job3->next = NULL; job3->data_addr = hard_buffer; job3->header_len = 6; job3->data_len = 290; job3->first_pb_desc = (blk_t *)pb_first->next->next->next; job3->first_pb_offset = 382; job3->segment_len = 512; job3->direction = 0; job3->crc_reset = 1; job3->crc_store = 1; job3->append_zero = 1; job3->job_it = 1; job3->eth_buffer_mask = 0x0; /* Payload + ATS */ job3->mf_header1 = (((job3->data_len + 4 - 1) << 2) | 0x02) | (ats << 16); job3->mf_header2 = (ats >> 16); /* Initialise the frame buffer. */ memset (frame_buffer, 0xFF, 2048); bridgedma_ctx = phy_bridgedma_init(NULL, _bridgedma_segmentation_cb, _bridgedma_deffered_cb); cyg_thread_delay (1); phy_bridgedma_start (bridgedma_ctx, job1, job3); } void bridgedma_segmentation_verify_test_case (void) { uint payload_cnt; pb_t *pb_current; pb_t *pb_first; pb_t *pb_last; crc_t crc_ctx; u32 enc_tab[256]; uint crc; uint crc_in_pb; uint length; uint pb_offset; uint frame_offset; uint i; while (phy_bridgedma_current_job (bridgedma_ctx) != 0x0) cyg_thread_delay (1); cyg_thread_delay (1); test_begin (test, "It reception") { test_fail_if (it_recv == false); } test_end; test_begin(test, "segmentation of a frame") { /* check pb content */ /* check 1st mac frame into PB */ payload_cnt = 0; arch_load_cache ((u32*) job1, sizeof (phy_bridgedma_job_t) / 4 + 1); arch_load_cache ((u32*) job2, sizeof (phy_bridgedma_job_t) / 4 + 1); arch_load_cache ((u32*) job3, sizeof (phy_bridgedma_job_t) / 4 + 1); /********************* First Frame *********************/ pb_offset = TEST_BRIDGEDMA_JOB_OFFSET; frame_offset = 0; pb_current = (pb_t *) job1->first_pb_desc; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); 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 == job1->data_len, "Data length is wrong."); payload_cnt = TEST_BRIDGEDMA_JOB_OFFSET + job1->header_len; for (i = 0; i < BLK_SIZE - payload_cnt; i++) test_fail_if (0xFF != read_u8_from_word(pb_current->data + i + payload_cnt)); pb_current = pb_current->next; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); payload_cnt = BLK_SIZE - payload_cnt; for (i = 0; i < BLK_SIZE; i++) test_fail_if (0xFF != read_u8_from_word(pb_current->data + i)); pb_current = pb_current->next; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); for (i = 0; i < 490; i++) test_fail_if ( 0xFF != read_u8_from_word(pb_current->data + i)); /********************* Second Frame *********************/ pb_offset = 494; frame_offset = 0; pb_current = (pb_t *) job2->first_pb_desc; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); 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 == job2->data_len, "Data length is wrong."); payload_cnt = pb_offset + job2->header_len; for (i = 0; i < BLK_SIZE - payload_cnt; i++) test_fail_if ( 0xFF != read_u8_from_word(pb_current->data + i + payload_cnt)); pb_current = pb_current->next; for (i = 0; i < 378; i++) test_fail_if ( 0xFF != read_u8_from_word(pb_current->data + i)); /********************* Third Frame *********************/ pb_offset = 382; frame_offset = 0; pb_current = (pb_t *) job3->first_pb_desc; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); 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 == job3->data_len, "Data length is wrong."); payload_cnt = pb_offset + job3->header_len; for (i = 0; i < BLK_SIZE - payload_cnt; i++) test_fail_if ( 0xFF != read_u8_from_word(pb_current->data + i + payload_cnt)); pb_current = pb_current->next; arch_load_cache ((u32*) pb_current, sizeof (pb_header_t) / 4); arch_load_cache ((u32*) pb_current->data, BLK_SIZE / 4); for (i = 0; i < 166; i++) test_fail_if ( 0xFF != read_u8_from_word(pb_current->data + i)); } test_end; /* Test the CRC computation. */ 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); test_case_begin (test, "Verifying the CRC"); test_begin (test, "First frame") { pb_current = (pb_t *) job1->first_pb_desc; crc = bridgedma_crc_compute_block (&crc_ctx, frame_buffer, job1->data_len); crc_in_pb = read_u32_from_word (pb_current->next->next->data + 490); test_fail_if (crc != crc_in_pb); } test_end; test_begin (test, "Second Frame") { pb_current = (pb_t *) job2->first_pb_desc; crc = bridgedma_crc_compute_block (&crc_ctx, frame_buffer, job2->data_len); crc_in_pb = read_u32_from_word (pb_current->next->data + 378); test_fail_if (crc != crc_in_pb); } test_end; test_begin (test, "Third Frame") { pb_current = (pb_t *) job3->first_pb_desc; crc = bridgedma_crc_compute_block (&crc_ctx, frame_buffer, job3->data_len); crc_in_pb = read_u32_from_word (pb_current->next->data + 166); test_fail_if (crc != crc_in_pb); } test_end; pb_first = (pb_t *) job1->first_pb_desc; for (pb_current = pb_first ; pb_current; pb_current = pb_current->next) { pb_last = pb_current; } blk_release_desc_range((blk_t *)pb_first, (blk_t *) pb_last); blk_release (job1); blk_release (job2); blk_release (job3); } void test_thread_process (cyg_addrword_t data) { bridgedma_segmentation_test_case (); bridgedma_segmentation_verify_test_case (); test_result (test); #ifndef __sparc__ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1); #endif } int main (void) { uint i; test_init (test, 0, 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; }