OpenCores
URL https://opencores.org/ocsvn/spacewire_light/spacewire_light/trunk

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [sw/] [rtems_driver/] [spwltest.c] - Diff between revs 6 and 9

Only display areas with differences | Details | Blame | View Log

Rev 6 Rev 9
/*
/*
 * Test program for SpaceWire Light RTEMS driver.
 * Test program for SpaceWire Light RTEMS driver.
 * Joris van Rantwijk, 2010.
 * Joris van Rantwijk, 2010.
 */
 */
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <termios.h>
#include <termios.h>
#include <rtems.h>
#include <rtems.h>
#include <rtems/error.h>
#include <rtems/error.h>
#include <bsp.h>
#include <bsp.h>
#include "spacewirelight.h"
#include "spacewirelight.h"
 
 
void Init(rtems_task_argument);
void Init(rtems_task_argument);
 
 
#define CONFIGURE_INIT
#define CONFIGURE_INIT
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT_TASK_ENTRY_POINT             Init
#define CONFIGURE_INIT_TASK_ENTRY_POINT             Init
#define CONFIGURE_MAXIMUM_TASKS                     10
#define CONFIGURE_MAXIMUM_TASKS                     10
#define CONFIGURE_MAXIMUM_SEMAPHORES                10
#define CONFIGURE_MAXIMUM_SEMAPHORES                10
#include <rtems/confdefs.h>
#include <rtems/confdefs.h>
 
 
 
 
struct data_test_context {
struct data_test_context {
    int queued;
    int queued;
    unsigned int rxpackets;
    unsigned int rxpackets;
    unsigned int rxblocksize;
    unsigned int rxblocksize;
    unsigned int txpackets;
    unsigned int txpackets;
    unsigned int txpacketsize;
    unsigned int txpacketsize;
    unsigned int txblocksize;
    unsigned int txblocksize;
    int verify;
    int verify;
    rtems_id semaphore;
    rtems_id semaphore;
    volatile unsigned int txdone_packets;
    volatile unsigned int txdone_packets;
    volatile unsigned int rxdone_packets;
    volatile unsigned int rxdone_packets;
    volatile unsigned int rxdone_bytes;
    volatile unsigned int rxdone_bytes;
    volatile unsigned int rxminsize;
    volatile unsigned int rxminsize;
    volatile unsigned int rxmaxsize;
    volatile unsigned int rxmaxsize;
    volatile int mismatch;
    volatile int mismatch;
};
};
 
 
static spwl_handle      spwh;
static spwl_handle      spwh;
static unsigned int     spw_index;
static unsigned int     spw_index;
static struct spwl_options spw_opt = SPWL_OPTIONS_DEFAULT;
static struct spwl_options spw_opt = SPWL_OPTIONS_DEFAULT;
static spwl_linkmode    spw_mode;
static spwl_linkmode    spw_mode;
 
 
#define MAX_BLOCK_SIZE 16384            /* do not change */
#define MAX_BLOCK_SIZE 16384            /* do not change */
static unsigned char rxbuf[MAX_BLOCK_SIZE];
static unsigned char rxbuf[MAX_BLOCK_SIZE];
static unsigned char txpool[2*MAX_BLOCK_SIZE];
static unsigned char txpool[2*MAX_BLOCK_SIZE];
static spwl_txbuf_t  txbuf_desc[16];
static spwl_txbuf_t  txbuf_desc[16];
 
 
static const unsigned int autotest_blocksize[] = {
static const unsigned int autotest_blocksize[] = {
    1, 101, 500, 2048, 4000, 0 };
    1, 101, 500, 2048, 4000, 0 };
static const unsigned int autotest_packetsize[] = {
static const unsigned int autotest_packetsize[] = {
    1, 2, 3, 4, 100, 101, 1000, 4096, 10000, 100000, 1000000, 0 };
    1, 2, 3, 4, 100, 101, 1000, 4096, 10000, 100000, 1000000, 0 };
 
 
/* Report error and stop program. */
/* Report error and stop program. */
static void fatal_error(const char *s, rtems_status_code err)
static void fatal_error(const char *s, rtems_status_code err)
{
{
    fprintf(stderr, "ERROR: %s", s);
    fprintf(stderr, "ERROR: %s", s);
    if (err)
    if (err)
        fprintf(stderr, " (%s)", rtems_status_text(err));
        fprintf(stderr, " (%s)", rtems_status_text(err));
    fprintf(stderr, "\n");
    fprintf(stderr, "\n");
    rtems_shutdown_executive(1);
    rtems_shutdown_executive(1);
}
}
 
 
 
 
/* Wait for user to enter a string. */
/* Wait for user to enter a string. */
static void get_string(char *buf, size_t maxlen)
static void get_string(char *buf, size_t maxlen)
{
{
    unsigned int i;
    unsigned int i;
    int k;
    int k;
    char c;
    char c;
 
 
    i = strlen(buf);
    i = strlen(buf);
    printf("%s", buf);
    printf("%s", buf);
    fflush(stdout);
    fflush(stdout);
 
 
    while (1) {
    while (1) {
        k = read(STDIN_FILENO, &c, 1);
        k = read(STDIN_FILENO, &c, 1);
        if (k != 1)
        if (k != 1)
            fatal_error("read from console", 0);
            fatal_error("read from console", 0);
        if (c == '\b' && i > 0) {
        if (c == '\b' && i > 0) {
            i--;
            i--;
            printf("\b \b");
            printf("\b \b");
            fflush(stdout);
            fflush(stdout);
        } else if (c == '\n' || c == '\r') {
        } else if (c == '\n' || c == '\r') {
            buf[i] = '\0';
            buf[i] = '\0';
            printf("\n");
            printf("\n");
            fflush(stdout);
            fflush(stdout);
            return;
            return;
        } else if (i + 1 < maxlen && c >= 32 && c < 127) {
        } else if (i + 1 < maxlen && c >= 32 && c < 127) {
            buf[i++] = c;
            buf[i++] = c;
            printf("%c", c);
            printf("%c", c);
            fflush(stdout);
            fflush(stdout);
        }
        }
    }
    }
}
}
 
 
 
 
/* Wait for user to enter a non-negative number. */
/* Wait for user to enter a non-negative number. */
static int get_num(const char *prompt, int low, int high, int deflt)
static int get_num(const char *prompt, int low, int high, int deflt)
{
{
    char buf[20];
    char buf[20];
    char *p;
    char *p;
    unsigned long v;
    unsigned long v;
 
 
    while (1) {
    while (1) {
        printf("%s ", prompt);
        printf("%s ", prompt);
        fflush(stdout);
        fflush(stdout);
 
 
        if (deflt >= 0)
        if (deflt >= 0)
            sprintf(buf, "%d", deflt);
            sprintf(buf, "%d", deflt);
        else
        else
            buf[0] = '\0';
            buf[0] = '\0';
        get_string(buf, sizeof(buf));
        get_string(buf, sizeof(buf));
 
 
        v = strtoul(buf, &p, 10);
        v = strtoul(buf, &p, 10);
        while (p != buf && *p == ' ')
        while (p != buf && *p == ' ')
            p++;
            p++;
 
 
        if (p != buf && *p == '\0' && v >= low && v <= high)
        if (p != buf && *p == '\0' && v >= low && v <= high)
            return v;
            return v;
    }
    }
}
}
 
 
 
 
/* Wait for user to enter an option index.
/* Wait for user to enter an option index.
   Return entered number, or -1 if an empty string was entered. */
   Return entered number, or -1 if an empty string was entered. */
static int get_opt(int high)
static int get_opt(int high)
{
{
    char buf[20];
    char buf[20];
    char *p;
    char *p;
    unsigned long v;
    unsigned long v;
 
 
    while (1) {
    while (1) {
        printf("Option (0 .. %d) ? ", high);
        printf("Option (0 .. %d) ? ", high);
        fflush(stdout);
        fflush(stdout);
 
 
        buf[0] = '\0';
        buf[0] = '\0';
        get_string(buf, sizeof(buf));
        get_string(buf, sizeof(buf));
 
 
        if (buf[0] == '\0')
        if (buf[0] == '\0')
            return -1;
            return -1;
 
 
        v = strtoul(buf, &p, 10);
        v = strtoul(buf, &p, 10);
        while (p != buf && *p == ' ')
        while (p != buf && *p == ' ')
            p++;
            p++;
 
 
        if (p != buf && *p == '\0' && v <= high)
        if (p != buf && *p == '\0' && v <= high)
            return v;
            return v;
    }
    }
}
}
 
 
 
 
/* Set console to non-blocking. */
/* Set console to non-blocking. */
void set_nonblocking(int fd, struct termios *tcattr_orig)
void set_nonblocking(int fd, struct termios *tcattr_orig)
{
{
    cc_t vmin_orig;
    cc_t vmin_orig;
    tcgetattr(STDIN_FILENO, tcattr_orig);
    tcgetattr(STDIN_FILENO, tcattr_orig);
    vmin_orig = tcattr_orig->c_cc[VMIN];
    vmin_orig = tcattr_orig->c_cc[VMIN];
    tcattr_orig->c_cc[VMIN] = 0;
    tcattr_orig->c_cc[VMIN] = 0;
    tcsetattr(STDIN_FILENO, TCSANOW, tcattr_orig);
    tcsetattr(STDIN_FILENO, TCSANOW, tcattr_orig);
    tcattr_orig->c_cc[VMIN] = vmin_orig;
    tcattr_orig->c_cc[VMIN] = vmin_orig;
}
}
 
 
 
 
/* Open driver. */
/* Open driver. */
void open_driver(void)
void open_driver(void)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
 
 
    printf("Opening driver for device index %u\n"
    printf("Opening driver for device index %u\n"
           "  options: rxbufs=%u, txbufs=%u, rxbufsize=%u, txbufsize=%u\n",
           "  options: rxbufs=%u, txbufs=%u, rxbufsize=%u, txbufsize=%u\n",
           spw_index,
           spw_index,
           spw_opt.rxbufs, spw_opt.txbufs,
           spw_opt.rxbufs, spw_opt.txbufs,
           spw_opt.rxbufsize, spw_opt.txbufsize);
           spw_opt.rxbufsize, spw_opt.txbufsize);
 
 
    ret = spwl_open(&spwh, spw_index, &spw_opt);
    ret = spwl_open(&spwh, spw_index, &spw_opt);
    if (ret != RTEMS_SUCCESSFUL) {
    if (ret != RTEMS_SUCCESSFUL) {
        if (ret == RTEMS_INVALID_NUMBER)
        if (ret == RTEMS_INVALID_NUMBER)
            fprintf(stderr, "ERROR: SpaceWire Light core not found\n");
            fprintf(stderr, "ERROR: SpaceWire Light core not found\n");
        fatal_error("spwl_open", ret);
        fatal_error("spwl_open", ret);
    }
    }
 
 
    spw_mode = SPWL_LINKMODE_NOP;
    spw_mode = SPWL_LINKMODE_NOP;
 
 
    printf("  ok\n");
    printf("  ok\n");
}
}
 
 
 
 
/* Show current link mode and status. */
/* Show current link mode and status. */
void show_status(void)
void show_status(void)
{
{
    spwl_linkstatus status;
    spwl_linkstatus status;
    unsigned int speed;
    unsigned int speed;
 
 
    spwl_get_linkstatus(spwh, &status, NULL);
    spwl_get_linkstatus(spwh, &status, NULL);
    speed = 100 * (spwl_get_default_linkspeed(spwh) + 1) / (spwl_get_linkspeed(spwh) + 1);
    speed = 100 * (spwl_get_default_linkspeed(spwh) + 1) / (spwl_get_linkspeed(spwh) + 1);
    printf("[ mode=%s,  status=%s,  speed=%u.%uMbit ]\n",
    printf("[ mode=%s,  status=%s,  speed=%u.%uMbit ]\n",
           ((spw_mode == SPWL_LINKMODE_START) ?     "start" :
           ((spw_mode == SPWL_LINKMODE_START) ?     "start" :
            (spw_mode == SPWL_LINKMODE_AUTOSTART) ? "autostart" :
            (spw_mode == SPWL_LINKMODE_AUTOSTART) ? "autostart" :
            (spw_mode == SPWL_LINKMODE_DISABLE) ?   "disable" : "nop"),
            (spw_mode == SPWL_LINKMODE_DISABLE) ?   "disable" : "nop"),
           ((status == SPWL_LINK_STARTED) ?    "started" :
           ((status == SPWL_LINK_STARTED) ?    "started" :
            (status == SPWL_LINK_CONNECTING) ? "connecting" :
            (status == SPWL_LINK_CONNECTING) ? "connecting" :
            (status == SPWL_LINK_RUN) ?        "RUN" : "off"),
            (status == SPWL_LINK_RUN) ?        "RUN" : "off"),
           speed/10, speed%10);
           speed/10, speed%10);
}
}
 
 
 
 
/* Re-initialize driver. */
/* Re-initialize driver. */
void do_init_driver(void)
void do_init_driver(void)
{
{
    amba_apb_device apbdev;
    amba_apb_device apbdev;
    unsigned int i;
    unsigned int i;
 
 
    printf("\n---- Re-initialize driver ----\n");
    printf("\n---- Re-initialize driver ----\n");
    printf("Closing driver\n");
    printf("Closing driver\n");
    spwl_close(spwh);
    spwl_close(spwh);
 
 
    printf("Detected SpaceWire Light devices:\n");
    printf("Detected SpaceWire Light devices:\n");
    for (i = 0; ; i++) {
    for (i = 0; ; i++) {
        if (!amba_find_next_apbslv(&amba_conf, VENDOR_OPENCORES, DEVICE_SPACEWIRELIGHT, &apbdev, i))
        if (!amba_find_next_apbslv(&amba_conf, VENDOR_OPENCORES, DEVICE_SPACEWIRELIGHT, &apbdev, i))
            break;
            break;
        printf(" index=%u, addr=0x%08x, irq=%u\n", i, apbdev.start, apbdev.irq);
        printf(" index=%u, addr=0x%08x, irq=%u\n", i, apbdev.start, apbdev.irq);
    }
    }
 
 
    spw_index = get_num("Enter index of device to open:", 0, 100, -1);
    spw_index = get_num("Enter index of device to open:", 0, 100, -1);
    spw_opt.rxbufs    = get_num("Number of RX buffers (min 0, max 4096):",
    spw_opt.rxbufs    = get_num("Number of RX buffers (min 0, max 4096):",
                                0, 4096, spw_opt.rxbufs);
                                0, 4096, spw_opt.rxbufs);
    spw_opt.txbufs    = get_num("Number of TX buffers (min 0, max 4096):",
    spw_opt.txbufs    = get_num("Number of TX buffers (min 0, max 4096):",
                                0, 4096, spw_opt.txbufs);
                                0, 4096, spw_opt.txbufs);
    spw_opt.rxbufsize = get_num("RX buffer size (bytes, min 32, max 16384):",
    spw_opt.rxbufsize = get_num("RX buffer size (bytes, min 32, max 16384):",
                                0, MAX_BLOCK_SIZE, spw_opt.rxbufsize);
                                0, MAX_BLOCK_SIZE, spw_opt.rxbufsize);
    spw_opt.txbufsize = get_num("TX buffer size (bytes, min 32, max 16384):",
    spw_opt.txbufsize = get_num("TX buffer size (bytes, min 32, max 16384):",
                                0, MAX_BLOCK_SIZE, spw_opt.txbufsize);
                                0, MAX_BLOCK_SIZE, spw_opt.txbufsize);
 
 
    open_driver();
    open_driver();
}
}
 
 
 
 
/* Change link mode. */
/* Change link mode. */
void do_set_link_mode(void)
void do_set_link_mode(void)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    int opt;
    int opt;
 
 
    printf("\n---- Change link mode ----\n");
    printf("\n---- Change link mode ----\n");
    show_status();
    show_status();
    printf(" 1.  Start     - start link; restart link after error\n");
    printf(" 1.  Start     - start link; restart link after error\n");
    printf(" 2.  Autostart - wait for remote activity before starting the link\n");
    printf(" 2.  Autostart - wait for remote activity before starting the link\n");
    printf(" 3.  Disable   - disable link\n");
    printf(" 3.  Disable   - disable link\n");
    printf(" 4.  Nop       - keep current link status; do not restart after error\n");
    printf(" 4.  Nop       - keep current link status; do not restart after error\n");
 
 
    opt = get_opt(4);
    opt = get_opt(4);
    if (opt > 0) {
    if (opt > 0) {
        printf("\n");
        printf("\n");
 
 
        switch (opt) {
        switch (opt) {
            case 1:
            case 1:
                printf("Setting link mode = start\n");
                printf("Setting link mode = start\n");
                spw_mode = SPWL_LINKMODE_START;
                spw_mode = SPWL_LINKMODE_START;
                break;
                break;
            case 2:
            case 2:
                printf("Setting link mode = autostart\n");
                printf("Setting link mode = autostart\n");
                spw_mode = SPWL_LINKMODE_AUTOSTART;
                spw_mode = SPWL_LINKMODE_AUTOSTART;
                break;
                break;
            case 3:
            case 3:
                printf("Setting link mode = disable\n");
                printf("Setting link mode = disable\n");
                spw_mode = SPWL_LINKMODE_DISABLE;
                spw_mode = SPWL_LINKMODE_DISABLE;
                break;
                break;
            case 4:
            case 4:
                printf("Setting link mode = nop\n");
                printf("Setting link mode = nop\n");
                spw_mode = SPWL_LINKMODE_NOP;
                spw_mode = SPWL_LINKMODE_NOP;
                break;
                break;
        }
        }
 
 
        ret = spwl_set_linkmode(spwh, spw_mode);
        ret = spwl_set_linkmode(spwh, spw_mode);
        if (ret != RTEMS_SUCCESSFUL)
        if (ret != RTEMS_SUCCESSFUL)
            fatal_error("spwl_set_linkmode", ret);
            fatal_error("spwl_set_linkmode", ret);
        printf("  ok\n");
        printf("  ok\n");
    }
    }
}
}
 
 
 
 
/* Change link speed. */
/* Change link speed. */
void do_set_link_speed(void)
void do_set_link_speed(void)
{
{
    char prompt[80];
    char prompt[80];
    rtems_status_code ret;
    rtems_status_code ret;
    int maxspeed, speed, scaler, scaler10;
    int maxspeed, speed, scaler, scaler10;
 
 
    printf("\n---- Change link speed ----\n");
    printf("\n---- Change link speed ----\n");
 
 
    scaler10 = spwl_get_default_linkspeed(spwh);
    scaler10 = spwl_get_default_linkspeed(spwh);
    scaler = spwl_get_linkspeed(spwh);
    scaler = spwl_get_linkspeed(spwh);
    speed = (10 * (scaler10 + 1) + scaler / 2) / (scaler + 1);
    speed = (10 * (scaler10 + 1) + scaler / 2) / (scaler + 1);
    maxspeed = 10 * (scaler10 + 1);
    maxspeed = 10 * (scaler10 + 1);
 
 
    sprintf(prompt, "New link speed in Mbit/s (2 .. %d) ?", maxspeed);
    sprintf(prompt, "New link speed in Mbit/s (2 .. %d) ?", maxspeed);
    speed = get_num(prompt, 2, maxspeed, speed);
    speed = get_num(prompt, 2, maxspeed, speed);
 
 
    scaler = (10 * (scaler10 + 1) + speed / 2) / speed - 1;
    scaler = (10 * (scaler10 + 1) + speed / 2) / speed - 1;
    if (scaler > 255)
    if (scaler > 255)
        scaler = 255;
        scaler = 255;
 
 
    speed = 100 * (scaler10 + 1) / (scaler + 1);
    speed = 100 * (scaler10 + 1) / (scaler + 1);
    printf("Setting speed = %d.%d Mbit/s, scaler = %d\n", speed/10, speed%10, scaler);
    printf("Setting speed = %d.%d Mbit/s, scaler = %d\n", speed/10, speed%10, scaler);
    ret = spwl_set_linkspeed(spwh, scaler);
    ret = spwl_set_linkspeed(spwh, scaler);
    if (ret != RTEMS_SUCCESSFUL)
    if (ret != RTEMS_SUCCESSFUL)
        fatal_error("spwl_set_linkmode", ret);
        fatal_error("spwl_set_linkmode", ret);
    printf("  ok\n");
    printf("  ok\n");
}
}
 
 
 
 
/* RX/TX event loop. */
/* RX/TX event loop. */
static int do_data_test_eventloop(struct data_test_context *ctx)
static int do_data_test_eventloop(struct data_test_context *ctx)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
    unsigned int rxminsize = 0, rxmaxsize = 0;
    unsigned int rxminsize = 0, rxmaxsize = 0;
    unsigned int txdone_packets = 0;
    unsigned int txdone_packets = 0;
    unsigned int rxpos = 0, txpos = 0, txbufp = 0, txbufn = 0;
    unsigned int rxpos = 0, txpos = 0, txbufp = 0, txbufn = 0;
    unsigned int cond;
    unsigned int cond;
    unsigned int f, offset;
    unsigned int f, offset;
    void *buf;
    void *buf;
    size_t p;
    size_t p;
    int k;
    int k;
    char c;
    char c;
 
 
    /* Flush pending reclaimable buffers from previous test. */
    /* Flush pending reclaimable buffers from previous test. */
    {
    {
        spwl_txbuf_t *tmp;
        spwl_txbuf_t *tmp;
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
            ;
            ;
    }
    }
 
 
    /* Run until test completes or user aborts. */
    /* Run until test completes or user aborts. */
    while (txdone_packets < ctx->txpackets ||
    while (txdone_packets < ctx->txpackets ||
           rxdone_packets < ctx->rxpackets ||
           rxdone_packets < ctx->rxpackets ||
           txbufn > 0) {
           txbufn > 0) {
 
 
        /* Abort test when user hits Enter. */
        /* Abort test when user hits Enter. */
        do {
        do {
            k = read(STDIN_FILENO, &c, 1);
            k = read(STDIN_FILENO, &c, 1);
        } while (k == 1 && c != '\n' && c != '\r');
        } while (k == 1 && c != '\n' && c != '\r');
        if (k == 1 && (c == '\n' || c == '\r'))
        if (k == 1 && (c == '\n' || c == '\r'))
            return -1;
            return -1;
 
 
        /* Wait until progress can be made. */
        /* Wait until progress can be made. */
        cond = 0;
        cond = 0;
        if (txbufn > 0)
        if (txbufn > 0)
            cond |= SPWL_COND_RECLAIM;
            cond |= SPWL_COND_RECLAIM;
        if (ctx->queued && txdone_packets < ctx->txpackets && txbufn < 16)
        if (ctx->queued && txdone_packets < ctx->txpackets && txbufn < 16)
            cond |= SPWL_COND_RDYSENDBUF;
            cond |= SPWL_COND_RDYSENDBUF;
        if (!ctx->queued && txdone_packets < ctx->txpackets)
        if (!ctx->queued && txdone_packets < ctx->txpackets)
            cond |= SPWL_COND_RDYSEND;
            cond |= SPWL_COND_RDYSEND;
        if (rxdone_packets < ctx->rxpackets)
        if (rxdone_packets < ctx->rxpackets)
            cond |= SPWL_COND_RDYRECV;
            cond |= SPWL_COND_RDYRECV;
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
            fatal_error("spwl_wait", ret);
            fatal_error("spwl_wait", ret);
 
 
        /* Send data. */
        /* Send data. */
        if ((cond & (SPWL_COND_RDYSEND | SPWL_COND_RDYSENDBUF)) != 0) {
        if ((cond & (SPWL_COND_RDYSEND | SPWL_COND_RDYSENDBUF)) != 0) {
            if (((cond & SPWL_COND_RDYSEND) != 0 && ctx->queued) ||
            if (((cond & SPWL_COND_RDYSEND) != 0 && ctx->queued) ||
                ((cond & SPWL_COND_RDYSENDBUF) != 0 && !ctx->queued) ||
                ((cond & SPWL_COND_RDYSENDBUF) != 0 && !ctx->queued) ||
                txbufn == 16 ||
                txbufn == 16 ||
                txdone_packets >= ctx->txpackets)
                txdone_packets >= ctx->txpackets)
                fatal_error("spwl_wait, unexpected condition", 0);
                fatal_error("spwl_wait, unexpected condition", 0);
            f = SPWL_EOP;
            f = SPWL_EOP;
            p = ctx->txpacketsize - txpos;
            p = ctx->txpacketsize - txpos;
            if (p > ctx->txblocksize) {
            if (p > ctx->txblocksize) {
                p = ctx->txblocksize;
                p = ctx->txblocksize;
                f = 0;
                f = 0;
            }
            }
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
            if (ctx->queued) {
            if (ctx->queued) {
                txbuf_desc[txbufp].data = txpool + offset;
                txbuf_desc[txbufp].data = txpool + offset;
                txbuf_desc[txbufp].nbytes = p;
                txbuf_desc[txbufp].nbytes = p;
                txbuf_desc[txbufp].eop = f;
                txbuf_desc[txbufp].eop = f;
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_send_txbuf", ret);
                    fatal_error("spwl_send_txbuf", ret);
                txbufp = (txbufp + 1) & 15;
                txbufp = (txbufp + 1) & 15;
                txbufn++;
                txbufn++;
            } else {
            } else {
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_NO_WAIT);
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_NO_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_send", ret);
                    fatal_error("spwl_send", ret);
            }
            }
            txpos += p;
            txpos += p;
            if (txpos >= ctx->txpacketsize) {
            if (txpos >= ctx->txpacketsize) {
                txdone_packets++;
                txdone_packets++;
                txpos = 0;
                txpos = 0;
            }
            }
        }
        }
 
 
        /* Receive data. */
        /* Receive data. */
        if ((cond & SPWL_COND_RDYRECV) != 0) {
        if ((cond & SPWL_COND_RDYRECV) != 0) {
            if (rxdone_packets >= ctx->rxpackets)
            if (rxdone_packets >= ctx->rxpackets)
                fatal_error("spwl_wait, unexpected condition", 0);
                fatal_error("spwl_wait, unexpected condition", 0);
            if (ctx->queued) {
            if (ctx->queued) {
                uint16_t nbytes;
                uint16_t nbytes;
                ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_NO_WAIT);
                ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_NO_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_recv_rxbuf", ret);
                    fatal_error("spwl_recv_rxbuf", ret);
                p = nbytes;
                p = nbytes;
            } else {
            } else {
                ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_NO_WAIT);
                ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_NO_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_recv", ret);
                    fatal_error("spwl_recv", ret);
                buf = rxbuf;
                buf = rxbuf;
            }
            }
            if (ctx->verify) {
            if (ctx->verify) {
                offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
                offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
                if (memcmp(buf, txpool + offset, p) != 0)
                if (memcmp(buf, txpool + offset, p) != 0)
                    ctx->mismatch = 1;
                    ctx->mismatch = 1;
            }
            }
            rxpos += p;
            rxpos += p;
            rxdone_bytes += p;
            rxdone_bytes += p;
            if (f == SPWL_EEP || f == SPWL_EOP) {
            if (f == SPWL_EEP || f == SPWL_EOP) {
                if (f == SPWL_EEP)
                if (f == SPWL_EEP)
                    ctx->mismatch = 1;
                    ctx->mismatch = 1;
                if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
                if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
                    ctx->mismatch = 1;
                    ctx->mismatch = 1;
                if (rxpos > 0)
                if (rxpos > 0)
                    rxdone_packets++;
                    rxdone_packets++;
                if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
                if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
                    rxminsize = rxpos;
                    rxminsize = rxpos;
                if (rxpos > rxmaxsize)
                if (rxpos > rxmaxsize)
                    rxmaxsize = rxpos;
                    rxmaxsize = rxpos;
                rxpos = 0;
                rxpos = 0;
            }
            }
            if (ctx->queued) {
            if (ctx->queued) {
                ret = spwl_release_rxbuf(spwh, buf);
                ret = spwl_release_rxbuf(spwh, buf);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_release_rxbuf", ret);
                    fatal_error("spwl_release_rxbuf", ret);
            }
            }
        }
        }
 
 
        /* Reclaim TX buffers (queued mode). */
        /* Reclaim TX buffers (queued mode). */
        if ((cond & SPWL_COND_RECLAIM) != 0) {
        if ((cond & SPWL_COND_RECLAIM) != 0) {
            spwl_txbuf_t *tmp;
            spwl_txbuf_t *tmp;
            if (txbufn == 0)
            if (txbufn == 0)
                fatal_error("spwl_wait, unexpeced condition", 0);
                fatal_error("spwl_wait, unexpeced condition", 0);
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT);
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("spwl_reclaim_txbuf", ret);
                fatal_error("spwl_reclaim_txbuf", ret);
            txbufn--;
            txbufn--;
        }
        }
 
 
        /* Update results. */
        /* Update results. */
        ctx->txdone_packets = txdone_packets;
        ctx->txdone_packets = txdone_packets;
        ctx->rxdone_packets = rxdone_packets;
        ctx->rxdone_packets = rxdone_packets;
        ctx->rxdone_bytes   = rxdone_bytes;
        ctx->rxdone_bytes   = rxdone_bytes;
        ctx->rxminsize      = rxminsize;
        ctx->rxminsize      = rxminsize;
        ctx->rxmaxsize      = rxmaxsize;
        ctx->rxmaxsize      = rxmaxsize;
    }
    }
 
 
    return 0;
    return 0;
}
}
 
 
 
 
/* RX worker thread. */
/* RX worker thread. */
static void rxtask_main(uintptr_t arg)
static void rxtask_main(uintptr_t arg)
{
{
    struct data_test_context *ctx = (struct data_test_context *)arg;
    struct data_test_context *ctx = (struct data_test_context *)arg;
    rtems_status_code ret;
    rtems_status_code ret;
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
    unsigned int rxdone_packets = 0, rxdone_bytes = 0;
    unsigned int rxminsize = 0, rxmaxsize = 0;
    unsigned int rxminsize = 0, rxmaxsize = 0;
    unsigned int rxpos = 0;
    unsigned int rxpos = 0;
    unsigned int f, offset;
    unsigned int f, offset;
    size_t p;
    size_t p;
    void *buf;
    void *buf;
 
 
    /* Receive data until test complete. */
    /* Receive data until test complete. */
    while (rxdone_packets < ctx->rxpackets) {
    while (rxdone_packets < ctx->rxpackets) {
 
 
        if (ctx->queued) {
        if (ctx->queued) {
            uint16_t nbytes;
            uint16_t nbytes;
            ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_WAIT);
            ret = spwl_recv_rxbuf(spwh, &buf, &nbytes, &f, SPWL_WAIT);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("spwl_recv_rxbuf", ret);
                fatal_error("spwl_recv_rxbuf", ret);
            p = nbytes;
            p = nbytes;
        } else {
        } else {
            ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_WAIT);
            ret = spwl_recv(spwh, rxbuf, ctx->rxblocksize, &p, &f, SPWL_WAIT);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("spwl_recv", ret);
                fatal_error("spwl_recv", ret);
            buf = rxbuf;
            buf = rxbuf;
        }
        }
 
 
        if (ctx->verify) {
        if (ctx->verify) {
            offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
            offset = (rxdone_packets * 4 + rxpos) & (MAX_BLOCK_SIZE-1);
            if (memcmp(buf, txpool + offset, p) != 0)
            if (memcmp(buf, txpool + offset, p) != 0)
                ctx->mismatch = 1;
                ctx->mismatch = 1;
        }
        }
 
 
        rxpos += p;
        rxpos += p;
        rxdone_bytes += p;
        rxdone_bytes += p;
 
 
        if (f == SPWL_EEP || f == SPWL_EOP) {
        if (f == SPWL_EEP || f == SPWL_EOP) {
            if (f == SPWL_EEP)
            if (f == SPWL_EEP)
                ctx->mismatch = 1;
                ctx->mismatch = 1;
            if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
            if (ctx->verify && rxpos > 0 && rxpos != ctx->txpacketsize)
                ctx->mismatch = 1;
                ctx->mismatch = 1;
            if (rxpos > 0)
            if (rxpos > 0)
                rxdone_packets++;
                rxdone_packets++;
            if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
            if (rxpos > 0 && (rxpos < rxminsize || rxminsize == 0))
                rxminsize = rxpos;
                rxminsize = rxpos;
            if (rxpos > rxmaxsize)
            if (rxpos > rxmaxsize)
                rxmaxsize = rxpos;
                rxmaxsize = rxpos;
            rxpos = 0;
            rxpos = 0;
        }
        }
 
 
        if (ctx->queued) {
        if (ctx->queued) {
            ret = spwl_release_rxbuf(spwh, buf);
            ret = spwl_release_rxbuf(spwh, buf);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("spwl_release_rxbuf", ret);
                fatal_error("spwl_release_rxbuf", ret);
        }
        }
 
 
        /* Update results. */
        /* Update results. */
        ctx->rxdone_packets = rxdone_packets;
        ctx->rxdone_packets = rxdone_packets;
        ctx->rxdone_bytes   = rxdone_bytes;
        ctx->rxdone_bytes   = rxdone_bytes;
        ctx->rxminsize      = rxminsize;
        ctx->rxminsize      = rxminsize;
        ctx->rxmaxsize      = rxmaxsize;
        ctx->rxmaxsize      = rxmaxsize;
    }
    }
 
 
    /* Release semaphore, then sleep forever. */
    /* Release semaphore, then sleep forever. */
    rtems_semaphore_release(ctx->semaphore);
    rtems_semaphore_release(ctx->semaphore);
    rtems_task_suspend(RTEMS_SELF);
    rtems_task_suspend(RTEMS_SELF);
}
}
 
 
 
 
/* TX worker thread. */
/* TX worker thread. */
static void txtask_main(uintptr_t arg)
static void txtask_main(uintptr_t arg)
{
{
    struct data_test_context *ctx = (struct data_test_context *)arg;
    struct data_test_context *ctx = (struct data_test_context *)arg;
    rtems_status_code ret;
    rtems_status_code ret;
    unsigned int txdone_packets = 0;
    unsigned int txdone_packets = 0;
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
    unsigned int f, offset;
    unsigned int f, offset;
    size_t p;
    size_t p;
 
 
    /* Flush pending reclaimable buffers from previous test. */
    /* Flush pending reclaimable buffers from previous test. */
    {
    {
        spwl_txbuf_t *tmp;
        spwl_txbuf_t *tmp;
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
            ;
            ;
    }
    }
 
 
    /* Send data until test completes. */
    /* Send data until test completes. */
    while (txdone_packets < ctx->txpackets || txbufn > 0) {
    while (txdone_packets < ctx->txpackets || txbufn > 0) {
 
 
        /* Send data. */
        /* Send data. */
        if (txdone_packets < ctx->txpackets && txbufn < 16) {
        if (txdone_packets < ctx->txpackets && txbufn < 16) {
            f = SPWL_EOP;
            f = SPWL_EOP;
            p = ctx->txpacketsize - txpos;
            p = ctx->txpacketsize - txpos;
            if (p > ctx->txblocksize) {
            if (p > ctx->txblocksize) {
                p = ctx->txblocksize;
                p = ctx->txblocksize;
                f = 0;
                f = 0;
            }
            }
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
            offset = (txdone_packets * 4 + txpos) & (MAX_BLOCK_SIZE-1);
            if (ctx->queued) {
            if (ctx->queued) {
                txbuf_desc[txbufp].data = txpool + offset;
                txbuf_desc[txbufp].data = txpool + offset;
                txbuf_desc[txbufp].nbytes = p;
                txbuf_desc[txbufp].nbytes = p;
                txbuf_desc[txbufp].eop = f;
                txbuf_desc[txbufp].eop = f;
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_WAIT);
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_send_txbuf", ret);
                    fatal_error("spwl_send_txbuf", ret);
                txbufp = (txbufp + 1) & 15;
                txbufp = (txbufp + 1) & 15;
                txbufn++;
                txbufn++;
            } else {
            } else {
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_WAIT);
                ret = spwl_send(spwh, txpool + offset, p, &p, f | SPWL_WAIT);
                if (ret != RTEMS_SUCCESSFUL)
                if (ret != RTEMS_SUCCESSFUL)
                    fatal_error("spwl_send", ret);
                    fatal_error("spwl_send", ret);
            }
            }
            txpos += p;
            txpos += p;
            if (txpos >= ctx->txpacketsize) {
            if (txpos >= ctx->txpacketsize) {
                txdone_packets++;
                txdone_packets++;
                txpos = 0;
                txpos = 0;
            }
            }
        }
        }
 
 
        /* Reclaim TX buffers (queued mode). */
        /* Reclaim TX buffers (queued mode). */
        if (ctx->queued && (txbufn == 16 || txdone_packets == ctx->txpackets)) {
        if (ctx->queued && (txbufn == 16 || txdone_packets == ctx->txpackets)) {
            spwl_txbuf_t *tmp;
            spwl_txbuf_t *tmp;
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_WAIT);
            ret = spwl_reclaim_txbuf(spwh, &tmp, SPWL_WAIT);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("spwl_reclaim_txbuf", ret);
                fatal_error("spwl_reclaim_txbuf", ret);
            if (tmp != txbuf_desc + ((16+txbufp-txbufn)&15))
            if (tmp != txbuf_desc + ((16+txbufp-txbufn)&15))
                fatal_error("spwl_reclaim_txbuf returned unexpected pointer", 0);
                fatal_error("spwl_reclaim_txbuf returned unexpected pointer", 0);
            txbufn--;
            txbufn--;
        }
        }
 
 
        /* Update results. */
        /* Update results. */
        ctx->txdone_packets = txdone_packets;
        ctx->txdone_packets = txdone_packets;
    }
    }
 
 
    /* Release semaphore, then sleep forever. */
    /* Release semaphore, then sleep forever. */
    rtems_semaphore_release(ctx->semaphore);
    rtems_semaphore_release(ctx->semaphore);
    rtems_task_suspend(RTEMS_SELF);
    rtems_task_suspend(RTEMS_SELF);
}
}
 
 
 
 
/* Run a data send/receive test. Return 0 if ok, -1 if an error occurred. */
/* Run a data send/receive test. Return 0 if ok, -1 if an error occurred. */
int do_data_test(int queued, int eventloop,
int do_data_test(int queued, int eventloop,
                 unsigned int rxpackets, unsigned int rxblocksize,
                 unsigned int rxpackets, unsigned int rxblocksize,
                 unsigned int txpackets, unsigned int txpacketsize,
                 unsigned int txpackets, unsigned int txpacketsize,
                 unsigned int txblocksize, int verify)
                 unsigned int txblocksize, int verify)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    struct termios tcattr;
    struct termios tcattr;
    struct data_test_context ctx;
    struct data_test_context ctx;
    struct timespec tstart, tend;
    struct timespec tstart, tend;
    rtems_id rxtask = 0, txtask = 0;
    rtems_id rxtask = 0, txtask = 0;
    int aborted = 0;
    int aborted = 0;
    int activethreads;
    int activethreads;
    unsigned int elapsedms;
    unsigned int elapsedms;
 
 
    if (queued && txpackets > 0 && (txblocksize & 3) != 0)
    if (queued && txpackets > 0 && (txblocksize & 3) != 0)
        fatal_error("invalid txblocksize in queued mode", 0);
        fatal_error("invalid txblocksize in queued mode", 0);
 
 
    printf("\nStarting data test:\n");
    printf("\nStarting data test:\n");
    printf("  api:     %s, %s\n", queued ? "queue" : "copy",
    printf("  api:     %s, %s\n", queued ? "queue" : "copy",
                                  eventloop ? "eventloop" : "blocking");
                                  eventloop ? "eventloop" : "blocking");
    if (txpackets > 0) {
    if (txpackets > 0) {
        printf("  send:    %u packets of %u bytes, blocksize=%u\n",
        printf("  send:    %u packets of %u bytes, blocksize=%u\n",
               txpackets, txpacketsize, txblocksize);
               txpackets, txpacketsize, txblocksize);
    }
    }
    if (rxpackets > 0) {
    if (rxpackets > 0) {
        printf("  receive: %u packets", rxpackets);
        printf("  receive: %u packets", rxpackets);
        if (!queued)
        if (!queued)
            printf(", blocksize=%u", rxblocksize);
            printf(", blocksize=%u", rxblocksize);
        printf(", verify=%s", verify ? "yes" : "no");
        printf(", verify=%s", verify ? "yes" : "no");
        printf("\n");
        printf("\n");
    }
    }
 
 
    set_nonblocking(STDIN_FILENO, &tcattr);
    set_nonblocking(STDIN_FILENO, &tcattr);
    printf("  test started ... press Enter to abort\n");
    printf("  test started ... press Enter to abort\n");
 
 
    /* Set up context structure. */
    /* Set up context structure. */
    ctx.queued      = queued;
    ctx.queued      = queued;
    ctx.rxpackets   = rxpackets;
    ctx.rxpackets   = rxpackets;
    ctx.rxblocksize = rxblocksize;
    ctx.rxblocksize = rxblocksize;
    ctx.txpackets   = txpackets;
    ctx.txpackets   = txpackets;
    ctx.txpacketsize = txpacketsize;
    ctx.txpacketsize = txpacketsize;
    ctx.txblocksize = txblocksize;
    ctx.txblocksize = txblocksize;
    ctx.verify      = verify;
    ctx.verify      = verify;
    ctx.semaphore   = 0;
    ctx.semaphore   = 0;
    ctx.txdone_packets = 0;
    ctx.txdone_packets = 0;
    ctx.rxdone_packets = 0;
    ctx.rxdone_packets = 0;
    ctx.rxdone_bytes   = 0;
    ctx.rxdone_bytes   = 0;
    ctx.rxminsize      = 0;
    ctx.rxminsize      = 0;
    ctx.rxmaxsize      = 0;
    ctx.rxmaxsize      = 0;
    ctx.mismatch       = 0;
    ctx.mismatch       = 0;
 
 
    /* Create worker threads and completion semaphore for multi-thread test. */
    /* Create worker threads and completion semaphore for multi-thread test. */
    if (!eventloop) {
    if (!eventloop) {
        ret = rtems_semaphore_create(rtems_build_name('d','o','n','e'),
        ret = rtems_semaphore_create(rtems_build_name('d','o','n','e'),
                                     0,
                                     0,
                                     RTEMS_COUNTING_SEMAPHORE,
                                     RTEMS_COUNTING_SEMAPHORE,
                                     RTEMS_NO_PRIORITY,
                                     RTEMS_NO_PRIORITY,
                                     &ctx.semaphore);
                                     &ctx.semaphore);
        if (ret != RTEMS_SUCCESSFUL)
        if (ret != RTEMS_SUCCESSFUL)
            fatal_error("rtems_semaphore_create", ret);
            fatal_error("rtems_semaphore_create", ret);
        if (rxpackets > 0) {
        if (rxpackets > 0) {
            ret = rtems_task_create(rtems_build_name('r','x','t','s'),
            ret = rtems_task_create(rtems_build_name('r','x','t','s'),
                                    200,
                                    200,
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
                                    RTEMS_PREEMPT,
                                    RTEMS_PREEMPT,
                                    RTEMS_NO_FLOATING_POINT,
                                    RTEMS_NO_FLOATING_POINT,
                                    &rxtask);
                                    &rxtask);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("rtems_task_create", ret);
                fatal_error("rtems_task_create", ret);
        }
        }
        if (txpackets > 0) {
        if (txpackets > 0) {
            ret = rtems_task_create(rtems_build_name('t','x','t','s'),
            ret = rtems_task_create(rtems_build_name('t','x','t','s'),
                                    200,
                                    200,
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
                                    RTEMS_CONFIGURED_MINIMUM_STACK_SIZE,
                                    RTEMS_PREEMPT | RTEMS_NO_TIMESLICE,
                                    RTEMS_PREEMPT | RTEMS_NO_TIMESLICE,
                                    RTEMS_LOCAL,
                                    RTEMS_LOCAL,
                                    &txtask);
                                    &txtask);
            if (ret != RTEMS_SUCCESSFUL)
            if (ret != RTEMS_SUCCESSFUL)
                fatal_error("rtems_task_create", ret);
                fatal_error("rtems_task_create", ret);
        }
        }
    }
    }
 
 
    /* Start timer. */
    /* Start timer. */
    rtems_clock_get_uptime(&tstart);
    rtems_clock_get_uptime(&tstart);
 
 
    /* Run test. */
    /* Run test. */
    if (eventloop) {
    if (eventloop) {
 
 
        if (do_data_test_eventloop(&ctx) != 0)
        if (do_data_test_eventloop(&ctx) != 0)
            aborted = 1;
            aborted = 1;
 
 
    } else {
    } else {
 
 
        /* Start worker threads. */
        /* Start worker threads. */
        if (rxpackets > 0)
        if (rxpackets > 0)
            rtems_task_start(rxtask, rxtask_main, (uintptr_t)&ctx);
            rtems_task_start(rxtask, rxtask_main, (uintptr_t)&ctx);
        if (txpackets > 0)
        if (txpackets > 0)
            rtems_task_start(txtask, txtask_main, (uintptr_t)&ctx);
            rtems_task_start(txtask, txtask_main, (uintptr_t)&ctx);
 
 
        /* Wait until test complete or test aborted. */
        /* Wait until test complete or test aborted. */
        activethreads = (rxpackets > 0) + (txpackets > 0);
        activethreads = (rxpackets > 0) + (txpackets > 0);
        while (activethreads) {
        while (activethreads) {
            int k;
            int k;
            char c;
            char c;
 
 
            /* Abort test when user hits Enter. */
            /* Abort test when user hits Enter. */
            do {
            do {
                k = read(STDIN_FILENO, &c, 1);
                k = read(STDIN_FILENO, &c, 1);
            } while (k == 1 && c != '\n' && c != '\r');
            } while (k == 1 && c != '\n' && c != '\r');
            if (k == 1 && (c == '\n' || c == '\r')) {
            if (k == 1 && (c == '\n' || c == '\r')) {
                aborted = 1;
                aborted = 1;
                break;
                break;
            }
            }
 
 
            ret = rtems_semaphore_obtain(ctx.semaphore, RTEMS_WAIT,
            ret = rtems_semaphore_obtain(ctx.semaphore, RTEMS_WAIT,
                                         rtems_clock_get_ticks_per_second());
                                         rtems_clock_get_ticks_per_second());
            if (ret == RTEMS_SUCCESSFUL)
            if (ret == RTEMS_SUCCESSFUL)
                activethreads--;
                activethreads--;
        }
        }
 
 
    }
    }
 
 
    /* Stop timer. */
    /* Stop timer. */
    rtems_clock_get_uptime(&tend);
    rtems_clock_get_uptime(&tend);
 
 
    /* Clean up resources. */
    /* Clean up resources. */
    if (!eventloop) {
    if (!eventloop) {
        if (rxpackets > 0)
        if (rxpackets > 0)
            rtems_task_delete(rxtask);
            rtems_task_delete(rxtask);
        if (txpackets > 0)
        if (txpackets > 0)
            rtems_task_delete(txtask);
            rtems_task_delete(txtask);
        rtems_semaphore_delete(ctx.semaphore);
        rtems_semaphore_delete(ctx.semaphore);
    }
    }
 
 
    /* Report result. */
    /* Report result. */
    if (aborted)
    if (aborted)
        printf("  aborted, ");
        printf("  aborted, ");
    else
    else
        printf("  done, ");
        printf("  done, ");
 
 
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
    printf("%3d.%03d seconds elapsed\n", elapsedms / 1000, elapsedms % 1000);
    printf("%3d.%03d seconds elapsed\n", elapsedms / 1000, elapsedms % 1000);
    if (txpackets > 0) {
    if (txpackets > 0) {
        uint64_t rate = (uint64_t)ctx.txdone_packets * (uint64_t)txpacketsize * 1000U / elapsedms;
        uint64_t rate = (uint64_t)ctx.txdone_packets * (uint64_t)txpacketsize * 1000U / elapsedms;
        printf("  sent %u packets (%u bytes/s)\n",
        printf("  sent %u packets (%u bytes/s)\n",
               ctx.txdone_packets, (unsigned int)rate);
               ctx.txdone_packets, (unsigned int)rate);
    }
    }
    if (rxpackets > 0) {
    if (rxpackets > 0) {
        uint64_t rate = (uint64_t)ctx.rxdone_bytes * 1000U / elapsedms;
        uint64_t rate = (uint64_t)ctx.rxdone_bytes * 1000U / elapsedms;
        printf("  received %u packets, %u bytes (%u bytes/s)\n",
        printf("  received %u packets, %u bytes (%u bytes/s)\n",
               ctx.rxdone_packets, ctx.rxdone_bytes, (unsigned int)rate);
               ctx.rxdone_packets, ctx.rxdone_bytes, (unsigned int)rate);
        if (ctx.rxdone_packets > 0)
        if (ctx.rxdone_packets > 0)
            printf("  received min packet size = %u, max packet size = %u\n",
            printf("  received min packet size = %u, max packet size = %u\n",
                   ctx.rxminsize, ctx.rxmaxsize);
                   ctx.rxminsize, ctx.rxmaxsize);
    }
    }
    if (ctx.mismatch)
    if (ctx.mismatch)
        printf("  MISMATCH OR EEP DETECTED IN RECEIVED DATA\n");
        printf("  MISMATCH OR EEP DETECTED IN RECEIVED DATA\n");
 
 
    /* Restore stdin mode. */
    /* Restore stdin mode. */
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
 
 
    return (aborted || ctx.mismatch) ? -1 : 0;
    return (aborted || ctx.mismatch) ? -1 : 0;
}
}
 
 
 
 
/* Run a series of loopback tests. */
/* Run a series of loopback tests. */
int do_autotest(int verify)
int do_autotest(int verify)
{
{
    int queued, eventloop;
    int queued, eventloop;
    unsigned int npackets, packetsize, rxblocksize, txblocksize;
    unsigned int npackets, packetsize, rxblocksize, txblocksize;
    int i, j, ret;
    int i, j, ret;
 
 
    printf("\nStarting automatic test\n");
    printf("\nStarting automatic test\n");
 
 
    for (queued = 0; queued <= 1; queued++) {
    for (queued = 0; queued <= 1; queued++) {
        for(eventloop = 0; eventloop <= 1; eventloop++) {
        for(eventloop = 0; eventloop <= 1; eventloop++) {
            for (i = 0; autotest_packetsize[i] > 0; i++) {
            for (i = 0; autotest_packetsize[i] > 0; i++) {
                for (j = 0; autotest_blocksize[j] > 0; j++) {
                for (j = 0; autotest_blocksize[j] > 0; j++) {
 
 
                    packetsize = autotest_packetsize[i];
                    packetsize = autotest_packetsize[i];
                    txblocksize = autotest_blocksize[j];
                    txblocksize = autotest_blocksize[j];
 
 
                    if (queued && (txblocksize & 3) != 0)
                    if (queued && (txblocksize & 3) != 0)
                        continue;
                        continue;
 
 
                    npackets = 10000000 / packetsize;
                    npackets = 10000000 / packetsize;
                    if (npackets > 100000)
                    if (npackets > 100000)
                        npackets = 100000;
                        npackets = 100000;
                    if (npackets * packetsize / txblocksize > 100000)
                    if (npackets * packetsize / txblocksize > 100000)
                        npackets = 100000 * txblocksize / packetsize;
                        npackets = 100000 * txblocksize / packetsize;
                    if (npackets < 1)
                    if (npackets < 1)
                        continue;
                        continue;
 
 
                    rxblocksize = 4000;
                    rxblocksize = 4000;
                    ret = do_data_test(queued, eventloop,
                    ret = do_data_test(queued, eventloop,
                                       npackets, rxblocksize,
                                       npackets, rxblocksize,
                                       npackets, packetsize, txblocksize,
                                       npackets, packetsize, txblocksize,
                                       verify);
                                       verify);
                    if (ret < 0)
                    if (ret < 0)
                        return ret;
                        return ret;
 
 
                    if (!queued && autotest_blocksize[j] != 4000) {
                    if (!queued && autotest_blocksize[j] != 4000) {
                        txblocksize = 4000;
                        txblocksize = 4000;
                        rxblocksize = autotest_blocksize[j];
                        rxblocksize = autotest_blocksize[j];
                        ret = do_data_test(queued, eventloop,
                        ret = do_data_test(queued, eventloop,
                                           npackets, rxblocksize,
                                           npackets, rxblocksize,
                                           npackets, packetsize, txblocksize,
                                           npackets, packetsize, txblocksize,
                                           verify);
                                           verify);
                        if (ret < 0)
                        if (ret < 0)
                            return ret;
                            return ret;
                    }
                    }
 
 
 
                    if (txblocksize > packetsize && rxblocksize > packetsize)
 
                        break;
                }
                }
            }
            }
        }
        }
    }
    }
 
 
    printf("\nAutomatic test completed\n");
    printf("\nAutomatic test completed\n");
    return 0;
    return 0;
}
}
 
 
 
 
/* Put system in passive loopback mode. */
/* Put system in passive loopback mode. */
void do_passive_loopback(int queued, int blocksize)
void do_passive_loopback(int queued, int blocksize)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    struct termios tcattr;
    struct termios tcattr;
    struct timespec tstart, tend;
    struct timespec tstart, tend;
    unsigned int done_packets = 0, done_bytes = 0;
    unsigned int done_packets = 0, done_bytes = 0;
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
    unsigned int txpos = 0, txbufp = 0, txbufn = 0;
    size_t rxlen = 0;
    size_t rxlen = 0;
    unsigned int rxeop = 0;
    unsigned int rxeop = 0;
    void *rxbufp;
    void *rxbufp;
    unsigned int cond;
    unsigned int cond;
    int k;
    int k;
    char c;
    char c;
    unsigned int elapsedms;
    unsigned int elapsedms;
    uint64_t rate;
    uint64_t rate;
 
 
    printf("\nStarting passive loopback mode:\n");
    printf("\nStarting passive loopback mode:\n");
    printf("  api:       %s\n", queued ? "queue" : "copy");
    printf("  api:       %s\n", queued ? "queue" : "copy");
    if (!queued)
    if (!queued)
        printf("  blocksize: %u\n", blocksize);
        printf("  blocksize: %u\n", blocksize);
 
 
    set_nonblocking(STDIN_FILENO, &tcattr);
    set_nonblocking(STDIN_FILENO, &tcattr);
    printf("  started ... press Enter to stop\n");
    printf("  started ... press Enter to stop\n");
 
 
    /* Flush pending reclaimable buffers from previous test. */
    /* Flush pending reclaimable buffers from previous test. */
    {
    {
        spwl_txbuf_t *tmp;
        spwl_txbuf_t *tmp;
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
        while (spwl_reclaim_txbuf(spwh, &tmp, SPWL_NO_WAIT) == RTEMS_SUCCESSFUL)
            ;
            ;
    }
    }
 
 
    /* Start timer. */
    /* Start timer. */
    rtems_clock_get_uptime(&tstart);
    rtems_clock_get_uptime(&tstart);
 
 
    /* Run in passive loopback. */
    /* Run in passive loopback. */
    while (1) {
    while (1) {
 
 
        /* Check if user pressed Enter. */
        /* Check if user pressed Enter. */
        do {
        do {
            k = read(STDIN_FILENO, &c, 1);
            k = read(STDIN_FILENO, &c, 1);
        } while (k == 1 && c != '\n' && c != '\r');
        } while (k == 1 && c != '\n' && c != '\r');
        if (k == 1 && (c == '\n' || c == '\r'))
        if (k == 1 && (c == '\n' || c == '\r'))
            break;
            break;
 
 
        /* Receive data. */
        /* Receive data. */
        if (rxlen == 0 && rxeop == 0) {
        if (rxlen == 0 && rxeop == 0) {
            if (queued) {
            if (queued) {
                uint16_t rxlen16;
                uint16_t rxlen16;
                ret = spwl_recv_rxbuf(spwh, &rxbufp, &rxlen16, &rxeop, SPWL_NO_WAIT);
                ret = spwl_recv_rxbuf(spwh, &rxbufp, &rxlen16, &rxeop, SPWL_NO_WAIT);
                rxlen = rxlen16;
                rxlen = rxlen16;
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                    fatal_error("spwl_recv_rxbuf", ret);
                    fatal_error("spwl_recv_rxbuf", ret);
            } else {
            } else {
                ret = spwl_recv(spwh, rxbuf, blocksize, &rxlen, &rxeop, SPWL_NO_WAIT);
                ret = spwl_recv(spwh, rxbuf, blocksize, &rxlen, &rxeop, SPWL_NO_WAIT);
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                    fatal_error("spwl_recv", ret);
                    fatal_error("spwl_recv", ret);
            }
            }
            done_bytes += rxlen;
            done_bytes += rxlen;
            if (rxeop)
            if (rxeop)
                done_packets++;
                done_packets++;
        }
        }
 
 
        /* Send data. */
        /* Send data. */
        if ((rxlen > 0 || rxeop != 0) && txbufn < 16) {
        if ((rxlen > 0 || rxeop != 0) && txbufn < 16) {
            if (queued) {
            if (queued) {
                txbuf_desc[txbufp].data = rxbufp;
                txbuf_desc[txbufp].data = rxbufp;
                txbuf_desc[txbufp].nbytes = rxlen;
                txbuf_desc[txbufp].nbytes = rxlen;
                txbuf_desc[txbufp].eop = rxeop;
                txbuf_desc[txbufp].eop = rxeop;
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
                ret = spwl_send_txbuf(spwh, txbuf_desc + txbufp, SPWL_NO_WAIT);
                if (ret == RTEMS_SUCCESSFUL) {
                if (ret == RTEMS_SUCCESSFUL) {
                    ret = spwl_release_rxbuf(spwh, rxbufp);
                    ret = spwl_release_rxbuf(spwh, rxbufp);
                    if (ret != RTEMS_SUCCESSFUL)
                    if (ret != RTEMS_SUCCESSFUL)
                        fatal_error("spwl_release_rxbuf", ret);
                        fatal_error("spwl_release_rxbuf", ret);
                    rxlen = rxeop = 0;
                    rxlen = rxeop = 0;
                    txbufp = (txbufp + 1) & 15;
                    txbufp = (txbufp + 1) & 15;
                    txbufn++;
                    txbufn++;
                }
                }
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                    fatal_error("spwl_send_txbuf", ret);
                    fatal_error("spwl_send_txbuf", ret);
            } else {
            } else {
                size_t ntrans;
                size_t ntrans;
                ret = spwl_send(spwh, rxbuf + txpos, rxlen - txpos, &ntrans, rxeop | SPWL_NO_WAIT);
                ret = spwl_send(spwh, rxbuf + txpos, rxlen - txpos, &ntrans, rxeop | SPWL_NO_WAIT);
                if (ret == RTEMS_SUCCESSFUL) {
                if (ret == RTEMS_SUCCESSFUL) {
                    txpos += ntrans;
                    txpos += ntrans;
                    if (txpos == rxlen)
                    if (txpos == rxlen)
                        rxlen = rxeop = txpos = 0;
                        rxlen = rxeop = txpos = 0;
                }
                }
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                    fatal_error("spwl_send", ret);
                    fatal_error("spwl_send", ret);
            }
            }
        }
        }
 
 
        /* Reclaim buffers. */
        /* Reclaim buffers. */
        if (txbufn > 0) {
        if (txbufn > 0) {
            struct spwl_txbuf *p;
            struct spwl_txbuf *p;
            ret = spwl_reclaim_txbuf(spwh, &p, SPWL_NO_WAIT);
            ret = spwl_reclaim_txbuf(spwh, &p, SPWL_NO_WAIT);
            if (ret == RTEMS_SUCCESSFUL) {
            if (ret == RTEMS_SUCCESSFUL) {
                if (p != txbuf_desc + ((txbufp + 16 - txbufn) & 15))
                if (p != txbuf_desc + ((txbufp + 16 - txbufn) & 15))
                    fatal_error("spwl_reclaim_txbuf returned unexpected buffer", 0);
                    fatal_error("spwl_reclaim_txbuf returned unexpected buffer", 0);
                txbufn--;
                txbufn--;
            }
            }
            if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
            if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_UNSATISFIED)
                fatal_error("spwl_reclaim_txbuf", ret);
                fatal_error("spwl_reclaim_txbuf", ret);
        }
        }
 
 
        /* Wait until ready. */
        /* Wait until ready. */
        cond = 0;
        cond = 0;
        if (rxlen == 0 && rxeop == 0)
        if (rxlen == 0 && rxeop == 0)
            cond |= SPWL_COND_RDYRECV;
            cond |= SPWL_COND_RDYRECV;
        if (!queued && (rxlen > 0 || rxeop != 0))
        if (!queued && (rxlen > 0 || rxeop != 0))
            cond |= SPWL_COND_RDYSEND;
            cond |= SPWL_COND_RDYSEND;
        if (queued && (rxlen > 0 || rxeop != 0) && txbufn < 16)
        if (queued && (rxlen > 0 || rxeop != 0) && txbufn < 16)
            cond |= SPWL_COND_RDYSENDBUF;
            cond |= SPWL_COND_RDYSENDBUF;
        if (txbufn > 0)
        if (txbufn > 0)
            cond |= SPWL_COND_RECLAIM;
            cond |= SPWL_COND_RECLAIM;
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
            fatal_error("spwl_wait", ret);
            fatal_error("spwl_wait", ret);
    }
    }
 
 
    /* Stop timer. */
    /* Stop timer. */
    rtems_clock_get_uptime(&tend);
    rtems_clock_get_uptime(&tend);
 
 
    /* Report result. */
    /* Report result. */
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
    elapsedms = 1 + (tend.tv_sec - tstart.tv_sec) * 1000 +
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
                tend.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
    printf("  done, %3d.%03d seconds elapsed\n",
    printf("  done, %3d.%03d seconds elapsed\n",
           elapsedms / 1000, elapsedms % 1000);
           elapsedms / 1000, elapsedms % 1000);
    rate = (uint64_t)done_bytes * 1000U / elapsedms;
    rate = (uint64_t)done_bytes * 1000U / elapsedms;
    printf("  sent %u packets, %u bytes (%u bytes/s)\n",
    printf("  sent %u packets, %u bytes (%u bytes/s)\n",
           done_packets, done_bytes, (unsigned int)rate);
           done_packets, done_bytes, (unsigned int)rate);
 
 
    /* Restore stdin mode. */
    /* Restore stdin mode. */
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
}
}
 
 
 
 
/* Send time codes. */
/* Send time codes. */
void do_send_timecode(void)
void do_send_timecode(void)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    uint8_t timecode;
    uint8_t timecode;
    int value;
    int value;
 
 
    printf("\n");
    printf("\n");
    value = get_num("Enter timecode value to send (0 .. 63):", 0, 63, -1);
    value = get_num("Enter timecode value to send (0 .. 63):", 0, 63, -1);
    if (value >= 0) {
    if (value >= 0) {
        timecode = spwl_get_timecode(spwh);
        timecode = spwl_get_timecode(spwh);
        printf("Last received timecode value: %u\n", timecode);
        printf("Last received timecode value: %u\n", timecode);
        printf("Sending timecode value %d\n", value);
        printf("Sending timecode value %d\n", value);
        ret = spwl_send_timecode(spwh, value);
        ret = spwl_send_timecode(spwh, value);
        if (ret != RTEMS_SUCCESSFUL)
        if (ret != RTEMS_SUCCESSFUL)
            fatal_error("spwl_send_timecode", ret);
            fatal_error("spwl_send_timecode", ret);
        timecode = spwl_get_timecode(spwh);
        timecode = spwl_get_timecode(spwh);
        printf("Last received timecode value: %u\n", timecode);
        printf("Last received timecode value: %u\n", timecode);
        rtems_task_wake_after(rtems_clock_get_ticks_per_second() / 10);
        rtems_task_wake_after(rtems_clock_get_ticks_per_second() / 10);
        timecode = spwl_get_timecode(spwh);
        timecode = spwl_get_timecode(spwh);
        printf("Last received timecode value (after 0.1s): %u\n", timecode);
        printf("Last received timecode value (after 0.1s): %u\n", timecode);
    }
    }
}
}
 
 
 
 
/* Show time codes and link events. */
/* Show time codes and link events. */
void do_recv_timecode(void)
void do_recv_timecode(void)
{
{
    rtems_status_code ret;
    rtems_status_code ret;
    struct termios tcattr;
    struct termios tcattr;
    struct timespec tstart, ts;
    struct timespec tstart, ts;
    spwl_linkstatus status;
    spwl_linkstatus status;
    int link_is_up;
    int link_is_up;
    unsigned int errors;
    unsigned int errors;
    unsigned int cond;
    unsigned int cond;
    unsigned int millis;
    unsigned int millis;
    uint8_t timecode;
    uint8_t timecode;
    int k;
    int k;
    char c;
    char c;
 
 
    printf("\n---- Show time codes and link events ----\n");
    printf("\n---- Show time codes and link events ----\n");
 
 
    rtems_clock_get_uptime(&tstart);
    rtems_clock_get_uptime(&tstart);
 
 
    spwl_get_linkstatus(spwh, &status, &errors);
    spwl_get_linkstatus(spwh, &status, &errors);
    link_is_up = (status == SPWL_LINK_RUN);
    link_is_up = (status == SPWL_LINK_RUN);
    printf("  link %s, errors = %s%s%s%s%s%s\n",
    printf("  link %s, errors = %s%s%s%s%s%s\n",
           link_is_up ? "up" : "down",
           link_is_up ? "up" : "down",
           (errors == 0) ? "none" : "",
           (errors == 0) ? "none" : "",
           (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
           (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
           (errors & SPWL_ERR_PARITY)     ? "parity " : "",
           (errors & SPWL_ERR_PARITY)     ? "parity " : "",
           (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
           (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
           (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
           (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
           (errors & SPWL_ERR_AHB)        ? "AHB " : "");
           (errors & SPWL_ERR_AHB)        ? "AHB " : "");
 
 
    timecode = spwl_get_timecode(spwh);
    timecode = spwl_get_timecode(spwh);
    printf("  last timecode = %u\n", timecode);
    printf("  last timecode = %u\n", timecode);
 
 
    set_nonblocking(STDIN_FILENO, &tcattr);
    set_nonblocking(STDIN_FILENO, &tcattr);
    printf("  waiting for events ... press Enter to stop\n");
    printf("  waiting for events ... press Enter to stop\n");
 
 
    while (1) {
    while (1) {
 
 
        /* Abort test when user hits Enter. */
        /* Abort test when user hits Enter. */
        do {
        do {
            k = read(STDIN_FILENO, &c, 1);
            k = read(STDIN_FILENO, &c, 1);
        } while (k == 1 && c != '\n' && c != '\r');
        } while (k == 1 && c != '\n' && c != '\r');
        if (k == 1 && (c == '\n' || c == '\r'))
        if (k == 1 && (c == '\n' || c == '\r'))
            break;
            break;
 
 
        /* Wait for event. */
        /* Wait for event. */
        cond = SPWL_COND_TIMECODE;
        cond = SPWL_COND_TIMECODE;
        if (link_is_up)
        if (link_is_up)
            cond |= SPWL_COND_LINKDOWN;
            cond |= SPWL_COND_LINKDOWN;
        else
        else
            cond |= SPWL_COND_LINKUP;
            cond |= SPWL_COND_LINKUP;
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        ret = spwl_wait(spwh, &cond, rtems_clock_get_ticks_per_second());
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
        if (ret != RTEMS_SUCCESSFUL && ret != RTEMS_TIMEOUT)
            fatal_error("spwl_wait", ret);
            fatal_error("spwl_wait", ret);
 
 
        /* Report event. */
        /* Report event. */
        rtems_clock_get_uptime(&ts);
        rtems_clock_get_uptime(&ts);
        millis = (ts.tv_sec - tstart.tv_sec) * 1000 +
        millis = (ts.tv_sec - tstart.tv_sec) * 1000 +
                 ts.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
                 ts.tv_nsec / 1000000 - tstart.tv_nsec / 1000000;
 
 
        if ((cond & SPWL_COND_LINKUP) != 0) {
        if ((cond & SPWL_COND_LINKUP) != 0) {
            printf("  %4u.%03u: link up\n", millis / 1000, millis % 1000);
            printf("  %4u.%03u: link up\n", millis / 1000, millis % 1000);
            link_is_up = 1;
            link_is_up = 1;
        }
        }
 
 
        if ((cond & SPWL_COND_LINKDOWN) != 0) {
        if ((cond & SPWL_COND_LINKDOWN) != 0) {
            spwl_get_linkstatus(spwh, &status, &errors);
            spwl_get_linkstatus(spwh, &status, &errors);
            printf("  %4u.%03u: link down, errors = %s%s%s%s%s%s\n",
            printf("  %4u.%03u: link down, errors = %s%s%s%s%s%s\n",
                   millis / 1000, millis % 1000,
                   millis / 1000, millis % 1000,
                   (errors == 0) ? "none" : "",
                   (errors == 0) ? "none" : "",
                   (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
                   (errors & SPWL_ERR_DISCONNECT) ? "disconnect " : "",
                   (errors & SPWL_ERR_PARITY)     ? "parity " : "",
                   (errors & SPWL_ERR_PARITY)     ? "parity " : "",
                   (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
                   (errors & SPWL_ERR_ESCAPE)     ? "escape " : "",
                   (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
                   (errors & SPWL_ERR_CREDIT)     ? "credit " : "",
                   (errors & SPWL_ERR_AHB)        ? "AHB " : "");
                   (errors & SPWL_ERR_AHB)        ? "AHB " : "");
            link_is_up = 0;
            link_is_up = 0;
        }
        }
 
 
        if ((cond & SPWL_COND_TIMECODE) != 0) {
        if ((cond & SPWL_COND_TIMECODE) != 0) {
            timecode = spwl_get_timecode(spwh);
            timecode = spwl_get_timecode(spwh);
            printf("  %4u.%03u: got tick, timecode = %d\n",
            printf("  %4u.%03u: got tick, timecode = %d\n",
                   millis / 1000, millis % 1000, timecode);
                   millis / 1000, millis % 1000, timecode);
        }
        }
    }
    }
 
 
    /* Restore console mode. */
    /* Restore console mode. */
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
    tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
 
 
    printf("  done\n");
    printf("  done\n");
}
}
 
 
 
 
/* Receive/send menu. */
/* Receive/send menu. */
void menu_recvsend(int send)
void menu_recvsend(int send)
{
{
    int opt;
    int opt;
    int queued, eventloop;
    int queued, eventloop;
    int npacket, packetsize, blocksize;
    int npacket, packetsize, blocksize;
 
 
    do {
    do {
 
 
        printf("\n---- %s packets ----\n", send ? "Send" : "Receive");
        printf("\n---- %s packets ----\n", send ? "Send" : "Receive");
        show_status();
        show_status();
        printf(" 1.  Copy API; blocking calls\n");
        printf(" 1.  Copy API; blocking calls\n");
        printf(" 2.  Copy API; event loop\n");
        printf(" 2.  Copy API; event loop\n");
        printf(" 3.  Queue API; blocking calls\n");
        printf(" 3.  Queue API; blocking calls\n");
        printf(" 4.  Queue API; event loop\n");
        printf(" 4.  Queue API; event loop\n");
        printf(" 0.  Back to main menu\n");
        printf(" 0.  Back to main menu\n");
 
 
        opt = get_opt(4);
        opt = get_opt(4);
        if (opt > 0 && opt <= 4) {
        if (opt > 0 && opt <= 4) {
 
 
            queued    = (opt == 3 || opt == 4);
            queued    = (opt == 3 || opt == 4);
            eventloop = (opt == 2 || opt == 4);
            eventloop = (opt == 2 || opt == 4);
 
 
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
 
 
            if (send)
            if (send)
                packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
                packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
            else
            else
                packetsize = 0;
                packetsize = 0;
 
 
            blocksize = 0;
            blocksize = 0;
            while (send || !queued) {
            while (send || !queued) {
                blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
                blocksize = get_num("Block size in bytes (1 .. 16384) ?", 1, MAX_BLOCK_SIZE, 4096);
                if ((blocksize & 3) == 0 || !queued)
                if ((blocksize & 3) == 0 || !queued)
                    break;
                    break;
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
            }
            }
 
 
            if (npacket > 0) {
            if (npacket > 0) {
                if (send) {
                if (send) {
                    do_data_test(queued, eventloop,
                    do_data_test(queued, eventloop,
                                 0, 0,
                                 0, 0,
                                 npacket, packetsize, blocksize,
                                 npacket, packetsize, blocksize,
                                 0);
                                 0);
                } else {
                } else {
                    do_data_test(queued, eventloop,
                    do_data_test(queued, eventloop,
                                 npacket, blocksize,
                                 npacket, blocksize,
                                 0, 0, 0,
                                 0, 0, 0,
                                 0);
                                 0);
                }
                }
            }
            }
        }
        }
    } while (opt != 0);
    } while (opt != 0);
}
}
 
 
 
 
/* Loopback test menu. */
/* Loopback test menu. */
void menu_loopback(int verify)
void menu_loopback(int verify)
{
{
    int opt;
    int opt;
    int queued, eventloop;
    int queued, eventloop;
    int npacket, packetsize, blocksize;
    int npacket, packetsize, blocksize;
 
 
    do {
    do {
 
 
        printf("\n---- Loopback test %s ----\n",
        printf("\n---- Loopback test %s ----\n",
               verify ? "with data compare" : "(no compare)");
               verify ? "with data compare" : "(no compare)");
        show_status();
        show_status();
        printf(" 1.  Copy API; blocking calls; multi-threaded\n");
        printf(" 1.  Copy API; blocking calls; multi-threaded\n");
        printf(" 2.  Copy API; event loop\n");
        printf(" 2.  Copy API; event loop\n");
        printf(" 3.  Queue API; blocking calls; multi-threaded\n");
        printf(" 3.  Queue API; blocking calls; multi-threaded\n");
        printf(" 4.  Queue API; event loop\n");
        printf(" 4.  Queue API; event loop\n");
        printf(" 5.  Automatic test\n");
        printf(" 5.  Automatic test\n");
        printf(" 0.  Back to main menu\n");
        printf(" 0.  Back to main menu\n");
 
 
        opt = get_opt(5);
        opt = get_opt(5);
        if (opt > 0 && opt <= 4) {
        if (opt > 0 && opt <= 4) {
 
 
            queued    = (opt == 3 || opt == 4);
            queued    = (opt == 3 || opt == 4);
            eventloop = (opt == 2 || opt == 4);
            eventloop = (opt == 2 || opt == 4);
 
 
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
            npacket = get_num("Number of packets ?", 0, 1000000, -1);
            packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
            packetsize = get_num("Packet size in bytes (1 .. 1000000) ?", 1, 1000000, -1);
            while (1) {
            while (1) {
                blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
                blocksize = get_num("Block size in bytes (1 .. 16384) ?", 1, MAX_BLOCK_SIZE, 4096);
                if ((blocksize & 3) == 0 || !queued)
                if ((blocksize & 3) == 0 || !queued)
                    break;
                    break;
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
                printf("INVALID: block size must be a multiple of 4 in queued mode\n");
            }
            }
 
 
            if (npacket > 0) {
            if (npacket > 0) {
                do_data_test(queued, eventloop,
                do_data_test(queued, eventloop,
                             npacket, blocksize,
                             npacket, blocksize,
                             npacket, packetsize, blocksize,
                             npacket, packetsize, blocksize,
                             verify);
                             verify);
            }
            }
 
 
        } else if (opt == 5) {
        } else if (opt == 5) {
 
 
            do_autotest(verify);
            do_autotest(verify);
 
 
        }
        }
 
 
    } while (opt != 0);
    } while (opt != 0);
}
}
 
 
 
 
/* Passive loopback menu. */
/* Passive loopback menu. */
void menu_passiveloop(void)
void menu_passiveloop(void)
{
{
    int opt;
    int opt;
    int queued, blocksize = 0;
    int queued, blocksize = 0;
 
 
    printf("\n---- Passive loopback mode----\n");
    printf("\n---- Passive loopback mode----\n");
    show_status();
    show_status();
    printf(" 1.  Copy API\n");
    printf(" 1.  Copy API\n");
    printf(" 2.  Queue API\n");
    printf(" 2.  Queue API\n");
    printf(" 0.  Back to main menu\n");
    printf(" 0.  Back to main menu\n");
 
 
    opt = get_opt(2);
    opt = get_opt(2);
    if (opt > 0 && opt <= 2) {
    if (opt > 0 && opt <= 2) {
 
 
        queued = (opt == 2);
        queued = (opt == 2);
 
 
        while (!queued) {
        while (!queued) {
            blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
            blocksize = get_num("Block size in bytes (32 .. 16384) ?", 32, MAX_BLOCK_SIZE, 4096);
            if ((blocksize & 3) == 0 || !queued)
            if ((blocksize & 3) == 0 || !queued)
                break;
                break;
            printf("INVALID: block size must be a multiple of 4 in queued mode\n");
            printf("INVALID: block size must be a multiple of 4 in queued mode\n");
        }
        }
 
 
        do_passive_loopback(queued, blocksize);
        do_passive_loopback(queued, blocksize);
    }
    }
}
}
 
 
 
 
/* Main menu. */
/* Main menu. */
void menu_main(void)
void menu_main(void)
{
{
    int opt;
    int opt;
 
 
    do {
    do {
        printf("\n==== SpaceWire Light Test ====\n");
        printf("\n==== SpaceWire Light Test ====\n");
        show_status();
        show_status();
        printf(" 1.  Re-initialize driver\n");
        printf(" 1.  Re-initialize driver\n");
        printf(" 2.  Set link mode\n");
        printf(" 2.  Set link mode\n");
        printf(" 3.  Set link speed\n");
        printf(" 3.  Set link speed\n");
        printf(" 4.  Receive packets\n");
        printf(" 4.  Receive packets\n");
        printf(" 5.  Send packets\n");
        printf(" 5.  Send packets\n");
        printf(" 6.  Loopback test (no compare)\n");
        printf(" 6.  Loopback test (no compare)\n");
        printf(" 7.  Loopback test with data compare\n");
        printf(" 7.  Loopback test with data compare\n");
        printf(" 8.  Passive loopback\n");
        printf(" 8.  Passive loopback\n");
        printf(" 9.  Send time code\n");
        printf(" 9.  Send time code\n");
        printf("10.  Show time codes and link events\n");
        printf("10.  Show time codes and link events\n");
        printf(" 0.  Exit\n");
        printf(" 0.  Exit\n");
 
 
        opt = get_opt(10);
        opt = get_opt(10);
        switch (opt) {
        switch (opt) {
            case 1: do_init_driver(); break;
            case 1: do_init_driver(); break;
            case 2: do_set_link_mode(); break;
            case 2: do_set_link_mode(); break;
            case 3: do_set_link_speed(); break;
            case 3: do_set_link_speed(); break;
            case 4: menu_recvsend(0); break;
            case 4: menu_recvsend(0); break;
            case 5: menu_recvsend(1); break;
            case 5: menu_recvsend(1); break;
            case 6: menu_loopback(0); break;
            case 6: menu_loopback(0); break;
            case 7: menu_loopback(1); break;
            case 7: menu_loopback(1); break;
            case 8: menu_passiveloop(); break;
            case 8: menu_passiveloop(); break;
            case 9: do_send_timecode(); break;
            case 9: do_send_timecode(); break;
            case 10: do_recv_timecode(); break;
            case 10: do_recv_timecode(); break;
        }
        }
 
 
    } while (opt != 0);
    } while (opt != 0);
}
}
 
 
 
 
/* Main program. */
/* Main program. */
void Init(rtems_task_argument arg)
void Init(rtems_task_argument arg)
{
{
    int i;
    int i;
 
 
    printf("\nSpaceWire Light test program for RTEMS\n\n");
    printf("\nSpaceWire Light test program for RTEMS\n\n");
 
 
    /* Put stdin in raw mode. */
    /* Put stdin in raw mode. */
    {
    {
        struct termios tcattr;
        struct termios tcattr;
        tcgetattr(STDIN_FILENO, &tcattr);
        tcgetattr(STDIN_FILENO, &tcattr);
        tcattr.c_iflag &= ~IGNCR;
        tcattr.c_iflag &= ~IGNCR;
        tcattr.c_lflag &= ~(ICANON | ECHO);
        tcattr.c_lflag &= ~(ICANON | ECHO);
        tcattr.c_cc[VMIN] = 1;
        tcattr.c_cc[VMIN] = 1;
        tcattr.c_cc[VTIME] = 0;
        tcattr.c_cc[VTIME] = 0;
        tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
        tcsetattr(STDIN_FILENO, TCSANOW, &tcattr);
    }
    }
 
 
    /* Create TX data pool. */
    /* Create TX data pool. */
    for (i = 0; i < MAX_BLOCK_SIZE; i++) {
    for (i = 0; i < MAX_BLOCK_SIZE; i++) {
        int v = ((i & 1) << 7) | ((i & 2) << 5) |
        int v = ((i & 1) << 7) | ((i & 2) << 5) |
                ((i & 4) << 3) | ((i & 8) << 1) |
                ((i & 4) << 3) | ((i & 8) << 1) |
                ((i & 16) >> 1) | ((i & 32) >> 3) |
                ((i & 16) >> 1) | ((i & 32) >> 3) |
                ((i & 64) >> 5) | ((i & 128) >> 7);
                ((i & 64) >> 5) | ((i & 128) >> 7);
        v += (i >> 8);
        v += (i >> 8);
        txpool[i] = v;
        txpool[i] = v;
    }
    }
    memcpy(txpool + MAX_BLOCK_SIZE, txpool, MAX_BLOCK_SIZE);
    memcpy(txpool + MAX_BLOCK_SIZE, txpool, MAX_BLOCK_SIZE);
 
 
    /* Open SpaceWire core */
    /* Open SpaceWire core */
    spw_index = 0;
    spw_index = 0;
    open_driver();
    open_driver();
 
 
    /* Main menu. */
    /* Main menu. */
    menu_main();
    menu_main();
 
 
    /* Clean up. */
    /* Clean up. */
    spwl_close(spwh);
    spwl_close(spwh);
 
 
    printf("\nExit.\n");
    printf("\nExit.\n");
    rtems_shutdown_executive(0);
    rtems_shutdown_executive(0);
}
}
 
 
/* vim: expandtab softtabstop=4
/* vim: expandtab softtabstop=4
*/
*/
/* end */
/* end */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2020 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.